Subversion Repositories planix.SVN

Rev

Rev 2 | Blame | Compare with Previous | Last modification | View Log | RSS feed

TEXT ainc(SB), 1, $-4                           /* int ainc(int*); */
        MOVL    arg+0(FP), BX
        MOVL    $1, AX
        LOCK; BYTE $0x0f; BYTE $0xc1; BYTE $0x03/* XADDL AX, (BX) */
        ADDL    $1, AX                          /* overflow if -ve or 0 */
        RET

TEXT adec(SB), 1, $-4                           /* int adec(int*); */
        MOVL    arg+0(FP), BX
        MOVL    $-1, AX
        LOCK; BYTE $0x0f; BYTE $0xc1; BYTE $0x03/* XADDL AX, (BX) */
        SUBL    $1, AX                          /* underflow if -ve */
        RET

/*
 * int cas32(u32int *p, u32int ov, u32int nv);
 * int cas(uint *p, int ov, int nv);
 * int casp(void **p, void *ov, void *nv);
 * int casl(ulong *p, ulong ov, ulong nv);
 */

/*
 * CMPXCHG (CX), DX: 0000 1111 1011 000w oorr rmmm,
 * mmm = CX = 001; rrr = DX = 010
 */

#define CMPXCHG         BYTE $0x0F; BYTE $0xB1; BYTE $0x11

TEXT    cas32+0(SB),0,$0
TEXT    cas+0(SB),0,$0
TEXT    casp+0(SB),0,$0
TEXT    casl+0(SB),0,$0
        MOVL    p+0(FP), CX
        MOVL    ov+4(FP), AX
        MOVL    nv+8(FP), DX
        LOCK
        CMPXCHG
        JNE     fail
        MOVL    $1,AX
        RET
fail:
        MOVL    $0,AX
        RET

/*
 * int cas64(u64int *p, u64int ov, u64int nv);
 */

/*
 * CMPXCHG64 (DI): 0000 1111 1100 0111 0000 1110,
 */

#define CMPXCHG64               BYTE $0x0F; BYTE $0xC7; BYTE $0x0F

TEXT    cas64+0(SB),0,$0
        MOVL    p+0(FP), DI
        MOVL    ov+0x4(FP), AX
        MOVL    ov+0x8(FP), DX
        MOVL    nv+0xc(FP), BX
        MOVL    nv+0x10(FP), CX
        LOCK
        CMPXCHG64
        JNE     fail
        MOVL    $1,AX
        RET

/*
 * Versions of compare-and-swap that return the old value
 * (i.e., the value of *p at the time of the operation
 *      xcas(p, o, n) == o
 * yields the same value as
 *      cas(p, o, n)
 * xcas can be used in constructs like
 *      for(o = *p; (oo = xcas(p, o, o+1)) != o; o = oo)
 *              ;
 * to avoid the extra dereference of *p (the example is a silly
 * way to increment *p atomically)
 *
 * u32int       xcas32(u32int *p, u32int ov, u32int nv);
 * u64int       xcas64(u64int *p, u64int ov, u64int nv);
 * int          xcas(int *p, int ov, int nv);
 * void*        xcasp(void **p, void *ov, void *nv);
 * ulong        xcasl(ulong *p, ulong ov, ulong nv);
 */

TEXT    xcas32+0(SB),0,$0
TEXT    xcas+0(SB),0,$0
TEXT    xcasp+0(SB),0,$0
TEXT    xcasl+0(SB),0,$0
        MOVL    p+0(FP), CX
        MOVL    ov+4(FP), AX    /* accumulator */
        MOVL    nv+8(FP), DX
        LOCK
        CMPXCHG
        RET
        
/*
 * The CMPXCHG8B instruction also requires three operands:
 * a 64-bit value in EDX:EAX, a 64-bit value in ECX:EBX,
 * and a destination operand in memory. The instruction compar
 * es the 64-bit value in the EDX:EAX registers with the
 * destination operand. If they are equal, the 64-bit value
 * in the ECX:EBX register is stored in the destination
 * operand. If the EDX:EAX register and the destination ar
 * e not equal, the destination is loaded in the EDX:EAX
 * register. The CMPXCHG8B instruction can be combined with
 * the LOCK prefix to perform the operation atomically
 */

TEXT    xcas64+0(SB),0,$0
        MOVL    p+4(FP), DI
        MOVL    ov+0x8(FP), AX
        MOVL    ov+0xc(FP), DX
        MOVL    nv+0x10(FP), BX
        MOVL    nv+0x14(FP), CX
        LOCK
        CMPXCHG64
        MOVL    .ret+0x0(FP),CX /* pointer to return value */
        MOVL    AX,0x0(CX)
        MOVL    DX,0x4(CX)
        RET

Generated by GNU Enscript 1.6.6.