1/* 2** Copyright 2003, Axel Dörfler, axeld@pinc-software.de. All rights reserved. 3** Distributed under the terms of the OpenBeOS License. 4*/ 5 6/* 7 * gcc/config/m68k/m68k.h:CALL_USED_REGISTERS: 8 * d0,d1,a0,a1 are scratch regs, not to be saved. 9 */ 10 11/* 12 * see http://mail-index.netbsd.org/amiga/1995/06/ 13 * for concerns about TAS, CAS and Amiga. 14 * I suppose as long as we don't use it on a variable in 15 * chip ram it shouldn't be a problem, and since we don't 16 * have any SMP Amiga anyway it should be ok. 17 */ 18 19#define FUNCTION(x) .global x; .type x,@function; x 20 21.text 22 23/* int atomic_add(int *value, int increment) 24 */ 25FUNCTION(atomic_add): 26 move.l (4,%a7),%a0 27 move.l (%a0),%d0 28miss1: move.l %d0,%d1 29 add.l (8,%a7),%d1 30 cas.l %d0,%d1,(%a0) 31 bne miss1 32 // d0 = old value 33 rts 34 35/* int atomic_and(int *value, int andValue) 36 */ 37FUNCTION(atomic_and): 38 move.l (4,%a7),%a0 39 move.l (%a0),%d0 40miss2: move.l %d0,%d1 41 and.l (8,%a7),%d1 42 cas.l %d0,%d1,(%a0) 43 bne miss2 44 // d0 = old value 45 rts 46 47/* int atomic_or(int *value, int orValue) 48 */ 49FUNCTION(atomic_or): 50 move.l (4,%a7),%a0 51 move.l (%a0),%d0 52miss3: move.l %d0,%d1 53 or.l (8,%a7),%d1 54 cas.l %d0,%d1,(%a0) 55 bne miss3 56 rts 57 58/* int atomic_set(int *value, int setTo) 59 */ 60FUNCTION(atomic_set): 61 move.l (4,%a7),%a0 62 move.l (%a0),%d0 63 move.l (8,%a7),%d1 64miss4: cas.l %d0,%d1,(%a0) 65 bne miss4 66 rts 67 68/* int atomic_test_and_set(int *value, int setTo, int testValue) 69 */ 70FUNCTION(atomic_test_and_set): 71 move.l (4,%a7),%a0 72 move.l (8,%a7),%d1 73 move.l (12,%a7),%d0 74 cas.l %d0,%d1,(%a0) 75 rts 76 77/* int atomic_get(int *value) 78 */ 79FUNCTION(atomic_get): 80 move.l (4,%a7),%a0 81 move.l (%a0),%d0 82 move.l %d0,%d1 83 cas.l %d0,%d1,(%a0) 84 // we must use cas... so we change to the same value if matching, 85 // else we get the correct one anyway 86 rts 87 88/* m68k elf convention is to return structs in (a0) 89 * but use d0/d1 for int64 and small structs. 90 * d0 MSB, d1 LSB 91 */ 92#warning M68K: 68060 doesn't have CAS2: use spinlock ?? 93/* see http://retropc.net/x68000/software/develop/as/has060/m68k.htm */ 94 95/* int64 atomic_add64(vint64 *value, int64 addValue) */ 96FUNCTION(atomic_add64): 97 movem.l %d2-%d3/%a2,-(%a7) 98 move.l (4,%a7),%a2 99 lea.l (4,%a2),%a1 100 // addValue 101 move.l (12,%a7),%d3 /*LSB*/ 102 move.l (8,%a7),%d2 /*MSB*/ 103miss5: // old value 104 move.l (%a1),%d1 /*LSB*/ 105 move.l (%a2),%d0 /*MSB*/ 106 add.l %d1,%d3 107 addx.l %d0,%d2 108 cas2.l %d0:%d1,%d2:%d3,(%a2):(%a1) 109 bne miss5 110 // return value d0:d1 111 movem.l (%a7)+,%d2-%d3/%a2 112 rts 113 114/* int64 atomic_and64(vint64 *value, int64 andValue) */ 115FUNCTION(atomic_and64): 116 movem.l %d2-%d3/%a2,-(%a7) 117 move.l (4,%a7),%a2 118 lea.l (4,%a2),%a1 119 // addValue 120 move.l (12,%a7),%d3 /*LSB*/ 121 move.l (8,%a7),%d2 /*MSB*/ 122miss6: // old value 123 move.l (%a1),%d1 /*LSB*/ 124 move.l (%a2),%d0 /*MSB*/ 125 and.l %d1,%d3 126 and.l %d0,%d2 127 cas2.l %d0:%d1,%d2:%d3,(%a2):(%a1) 128 bne miss6 129 // return value d0:d1 130 movem.l (%a7)+,%d2-%d3/%a2 131 rts 132 133/* int64 atomic_or64(vint64 *value, int64 orValue) */ 134FUNCTION(atomic_or64): 135 movem.l %d2-%d3/%a2,-(%a7) 136 move.l (4,%a7),%a2 137 lea.l (4,%a2),%a1 138 // addValue 139 move.l (12,%a7),%d3 /*LSB*/ 140 move.l (8,%a7),%d2 /*MSB*/ 141miss7: // old value 142 move.l (%a1),%d1 /*LSB*/ 143 move.l (%a2),%d0 /*MSB*/ 144 or.l %d1,%d3 145 or.l %d0,%d2 146 cas2.l %d0:%d1,%d2:%d3,(%a2):(%a1) 147 bne miss7 148 // return value d0:d1 149 movem.l (%a7)+,%d2-%d3/%a2 150 rts 151 152/* int64 atomic_set64(vint64 *value, int64 newValue) */ 153FUNCTION(atomic_set64): 154 movem.l %d2-%d3/%a2,-(%a7) 155 move.l (4,%a7),%a2 156 lea.l (4,%a2),%a1 157 // new value 158 move.l (12,%a7),%d3 /*LSB*/ 159 move.l (8,%a7),%d2 /*MSB*/ 160 // old value 161 move.l (%a1),%d1 /*LSB*/ 162 move.l (%a2),%d0 /*MSB*/ 163miss8: cas2.l %d0:%d1,%d2:%d3,(%a2):(%a1) 164 bne miss8 165 // return value d0:d1 166 movem.l (%a7)+,%d2-%d3/%a2 167 rts 168 169/* int64 atomic_test_and_set64(vint64 *value, int64 newValue, int64 testAgainst) */ 170FUNCTION(atomic_test_and_set64): 171 movem.l %d2-%d3/%a2,-(%a7) 172 move.l (4,%a7),%a2 173 lea.l (4,%a2),%a1 174 // new value 175 move.l (12,%a7),%d3 /*LSB*/ 176 move.l (8,%a7),%d2 /*MSB*/ 177 // test against value 178 move.l (20,%a7),%d1 /*LSB*/ 179 move.l (16,%a7),%d0 /*MSB*/ 180 cas2.l %d0:%d1,%d2:%d3,(%a2):(%a1) 181 // return value d0:d1 182 movem.l (%a7)+,%d2-%d3/%a2 183 rts 184 185/* int64 atomic_get64(vint64 *value) */ 186FUNCTION(atomic_get64): 187 movem.l %d2-%d3/%a2,-(%a7) 188 move.l (4,%a7),%a2 189 lea.l (4,%a2),%a1 190 move.l (%a1),%d1 /*LSB*/ 191 move.l (%a2),%d0 /*MSB*/ 192 move.l %d1,%d3 193 move.l %d0,%d2 194 // we must use cas... so we change to the same value if matching, 195 // else we get the correct one anyway 196 cas2.l %d0:%d1,%d2:%d3,(%a2):(%a1) 197 // return value 198 movem.l (%a7)+,%d2-%d3/%a2 199 rts 200 201