1*51f48f69SDavid du ColombierTEXT ainc(SB), 1, $-4 /* int ainc(int*); */ 2*51f48f69SDavid du Colombier MOVL arg+0(FP), BX 3*51f48f69SDavid du Colombier MOVL $1, AX 4*51f48f69SDavid du Colombier LOCK; BYTE $0x0f; BYTE $0xc1; BYTE $0x03/* XADDL AX, (BX) */ 5*51f48f69SDavid du Colombier ADDL $1, AX /* overflow if -ve or 0 */ 6*51f48f69SDavid du Colombier RET 7*51f48f69SDavid du Colombier 8*51f48f69SDavid du ColombierTEXT adec(SB), 1, $-4 /* int adec(int*); */ 9*51f48f69SDavid du Colombier MOVL arg+0(FP), BX 10*51f48f69SDavid du Colombier MOVL $-1, AX 11*51f48f69SDavid du Colombier LOCK; BYTE $0x0f; BYTE $0xc1; BYTE $0x03/* XADDL AX, (BX) */ 12*51f48f69SDavid du Colombier SUBL $1, AX /* underflow if -ve */ 13*51f48f69SDavid du Colombier RET 14*51f48f69SDavid du Colombier 15*51f48f69SDavid du Colombier/* 16*51f48f69SDavid du Colombier * int cas32(u32int *p, u32int ov, u32int nv); 17*51f48f69SDavid du Colombier * int cas(uint *p, int ov, int nv); 18*51f48f69SDavid du Colombier * int casp(void **p, void *ov, void *nv); 19*51f48f69SDavid du Colombier * int casl(ulong *p, ulong ov, ulong nv); 20*51f48f69SDavid du Colombier */ 21*51f48f69SDavid du Colombier 22*51f48f69SDavid du Colombier/* 23*51f48f69SDavid du Colombier * CMPXCHG (CX), DX: 0000 1111 1011 000w oorr rmmm, 24*51f48f69SDavid du Colombier * mmm = CX = 001; rrr = DX = 010 25*51f48f69SDavid du Colombier */ 26*51f48f69SDavid du Colombier 27*51f48f69SDavid du Colombier#define CMPXCHG BYTE $0x0F; BYTE $0xB1; BYTE $0x11 28*51f48f69SDavid du Colombier 29*51f48f69SDavid du ColombierTEXT cas32+0(SB),0,$0 30*51f48f69SDavid du ColombierTEXT cas+0(SB),0,$0 31*51f48f69SDavid du ColombierTEXT casp+0(SB),0,$0 32*51f48f69SDavid du ColombierTEXT casl+0(SB),0,$0 33*51f48f69SDavid du Colombier MOVL p+0(FP), CX 34*51f48f69SDavid du Colombier MOVL ov+4(FP), AX 35*51f48f69SDavid du Colombier MOVL nv+8(FP), DX 36*51f48f69SDavid du Colombier LOCK 37*51f48f69SDavid du Colombier CMPXCHG 38*51f48f69SDavid du Colombier JNE fail 39*51f48f69SDavid du Colombier MOVL $1,AX 40*51f48f69SDavid du Colombier RET 41*51f48f69SDavid du Colombierfail: 42*51f48f69SDavid du Colombier MOVL $0,AX 43*51f48f69SDavid du Colombier RET 44*51f48f69SDavid du Colombier 45*51f48f69SDavid du Colombier/* 46*51f48f69SDavid du Colombier * int cas64(u64int *p, u64int ov, u64int nv); 47*51f48f69SDavid du Colombier */ 48*51f48f69SDavid du Colombier 49*51f48f69SDavid du Colombier/* 50*51f48f69SDavid du Colombier * CMPXCHG64 (DI): 0000 1111 1100 0111 0000 1110, 51*51f48f69SDavid du Colombier */ 52*51f48f69SDavid du Colombier 53*51f48f69SDavid du Colombier#define CMPXCHG64 BYTE $0x0F; BYTE $0xC7; BYTE $0x0F 54*51f48f69SDavid du Colombier 55*51f48f69SDavid du ColombierTEXT cas64+0(SB),0,$0 56*51f48f69SDavid du Colombier MOVL p+0(FP), DI 57*51f48f69SDavid du Colombier MOVL ov+0x4(FP), AX 58*51f48f69SDavid du Colombier MOVL ov+0x8(FP), DX 59*51f48f69SDavid du Colombier MOVL nv+0xc(FP), BX 60*51f48f69SDavid du Colombier MOVL nv+0x10(FP), CX 61*51f48f69SDavid du Colombier LOCK 62*51f48f69SDavid du Colombier CMPXCHG64 63*51f48f69SDavid du Colombier JNE fail 64*51f48f69SDavid du Colombier MOVL $1,AX 65*51f48f69SDavid du Colombier RET 66*51f48f69SDavid du Colombier 67*51f48f69SDavid du Colombier/* 68*51f48f69SDavid du Colombier * Versions of compare-and-swap that return the old value 69*51f48f69SDavid du Colombier * (i.e., the value of *p at the time of the operation 70*51f48f69SDavid du Colombier * xcas(p, o, n) == o 71*51f48f69SDavid du Colombier * yields the same value as 72*51f48f69SDavid du Colombier * cas(p, o, n) 73*51f48f69SDavid du Colombier * xcas can be used in constructs like 74*51f48f69SDavid du Colombier * for(o = *p; (oo = xcas(p, o, o+1)) != o; o = oo) 75*51f48f69SDavid du Colombier * ; 76*51f48f69SDavid du Colombier * to avoid the extra dereference of *p (the example is a silly 77*51f48f69SDavid du Colombier * way to increment *p atomically) 78*51f48f69SDavid du Colombier * 79*51f48f69SDavid du Colombier * u32int xcas32(u32int *p, u32int ov, u32int nv); 80*51f48f69SDavid du Colombier * u64int xcas64(u64int *p, u64int ov, u64int nv); 81*51f48f69SDavid du Colombier * int xcas(int *p, int ov, int nv); 82*51f48f69SDavid du Colombier * void* xcasp(void **p, void *ov, void *nv); 83*51f48f69SDavid du Colombier * ulong xcasl(ulong *p, ulong ov, ulong nv); 84*51f48f69SDavid du Colombier */ 85*51f48f69SDavid du Colombier 86*51f48f69SDavid du ColombierTEXT xcas32+0(SB),0,$0 87*51f48f69SDavid du ColombierTEXT xcas+0(SB),0,$0 88*51f48f69SDavid du ColombierTEXT xcasp+0(SB),0,$0 89*51f48f69SDavid du ColombierTEXT xcasl+0(SB),0,$0 90*51f48f69SDavid du Colombier MOVL p+0(FP), CX 91*51f48f69SDavid du Colombier MOVL ov+4(FP), AX /* accumulator */ 92*51f48f69SDavid du Colombier MOVL nv+8(FP), DX 93*51f48f69SDavid du Colombier LOCK 94*51f48f69SDavid du Colombier CMPXCHG 95*51f48f69SDavid du Colombier RET 96*51f48f69SDavid du Colombier 97*51f48f69SDavid du Colombier/* 98*51f48f69SDavid du Colombier * The CMPXCHG8B instruction also requires three operands: 99*51f48f69SDavid du Colombier * a 64-bit value in EDX:EAX, a 64-bit value in ECX:EBX, 100*51f48f69SDavid du Colombier * and a destination operand in memory. The instruction compar 101*51f48f69SDavid du Colombier * es the 64-bit value in the EDX:EAX registers with the 102*51f48f69SDavid du Colombier * destination operand. If they are equal, the 64-bit value 103*51f48f69SDavid du Colombier * in the ECX:EBX register is stored in the destination 104*51f48f69SDavid du Colombier * operand. If the EDX:EAX register and the destination ar 105*51f48f69SDavid du Colombier * e not equal, the destination is loaded in the EDX:EAX 106*51f48f69SDavid du Colombier * register. The CMPXCHG8B instruction can be combined with 107*51f48f69SDavid du Colombier * the LOCK prefix to perform the operation atomically 108*51f48f69SDavid du Colombier */ 109*51f48f69SDavid du Colombier 110*51f48f69SDavid du ColombierTEXT xcas64+0(SB),0,$0 111*51f48f69SDavid du Colombier MOVL p+4(FP), DI 112*51f48f69SDavid du Colombier MOVL ov+0x8(FP), AX 113*51f48f69SDavid du Colombier MOVL ov+0xc(FP), DX 114*51f48f69SDavid du Colombier MOVL nv+0x10(FP), BX 115*51f48f69SDavid du Colombier MOVL nv+0x14(FP), CX 116*51f48f69SDavid du Colombier LOCK 117*51f48f69SDavid du Colombier CMPXCHG64 118*51f48f69SDavid du Colombier MOVL .ret+0x0(FP),CX /* pointer to return value */ 119*51f48f69SDavid du Colombier MOVL AX,0x0(CX) 120*51f48f69SDavid du Colombier MOVL DX,0x4(CX) 121*51f48f69SDavid du Colombier RET 122