xref: /plan9/sys/src/ape/lib/ap/386/atom.s (revision 51f48f69b4c3e5c9d9f7955d28612ef2d4048ccc)
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