xref: /plan9/sys/src/cmd/unix/drawterm/posix-power/tas.c (revision 8ccd4a6360d974db7bd7bbd4f37e7018419ea908)
1 #include "u.h"
2 #include "libc.h"
3 
4 /*
5  * first argument (l) is in r3 at entry.
6  * r3 contains return value upon return.
7  */
8 int
tas(long * x)9 tas(long *x)
10 {
11 	int     v;
12 	/*
13 	 * this __asm__ works with gcc 2.95.2 (mac os x 10.1).
14 	 * this assembly language destroys r0 (0), some other register (v),
15 	 * r4 (x) and r5 (temp).
16 	 */
17 	__asm__("\n	sync\n"
18 	"	li	r0,0\n"
19 	"	mr	r4,%1		/* &l->val */\n"
20 	"	lis	r5,0xdead	/* assemble constant 0xdeaddead */\n"
21 	"	ori	r5,r5,0xdead	/* \" */\n"
22 	"tas1:\n"
23 	"	dcbf	r4,r0	/* cache flush; \"fix for 603x bug\" */\n"
24 	"	lwarx	%0,r4,r0	/* v = l->val with reservation */\n"
25 	"	cmp	cr0,0,%0,r0	/* v == 0 */\n"
26 	"	bne	tas0\n"
27 	"	stwcx.	r5,r4,r0   /* if (l->val same) l->val = 0xdeaddead */\n"
28 	"	bne	tas1\n"
29 	"tas0:\n"
30 	"	sync\n"
31 	"	isync\n"
32 	: "=r" (v)
33 	: "r"  (x)
34 	: "cc", "memory", "r0", "r4", "r5"
35 	);
36 	switch(v) {
37 	case 0:		return 0;
38 	case 0xdeaddead: return 1;
39 	default:	print("tas: corrupted 0x%lux\n", v);
40 	}
41 	return 0;
42 }
43