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