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#include <asm_defs.h> 7 8/* 9 * gcc/config/m68k/m68k.h:CALL_USED_REGISTERS: 10 * d0,d1,a0,a1 are scratch regs, not to be saved. 11 */ 12 13/* 14 * see http://mail-index.netbsd.org/amiga/1995/06/ 15 * for concerns about TAS, CAS and Amiga. 16 * I suppose as long as we don't use it on a variable in 17 * chip ram it shouldn't be a problem, and since we don't 18 * have any SMP Amiga anyway it should be ok. 19 */ 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 34FUNCTION_END(atomic_add) 35 36/* int atomic_and(int *value, int andValue) 37 */ 38FUNCTION(atomic_and): 39 move.l (4,%a7),%a0 40 move.l (%a0),%d0 41miss2: move.l %d0,%d1 42 and.l (8,%a7),%d1 43 cas.l %d0,%d1,(%a0) 44 bne miss2 45 // d0 = old value 46 rts 47FUNCTION_END(atomic_and) 48 49/* int atomic_or(int *value, int orValue) 50 */ 51FUNCTION(atomic_or): 52 move.l (4,%a7),%a0 53 move.l (%a0),%d0 54miss3: move.l %d0,%d1 55 or.l (8,%a7),%d1 56 cas.l %d0,%d1,(%a0) 57 bne miss3 58 rts 59FUNCTION_END(atomic_or) 60 61/* int atomic_set(int *value, int setTo) 62 */ 63FUNCTION(atomic_set): 64 move.l (4,%a7),%a0 65 move.l (%a0),%d0 66 move.l (8,%a7),%d1 67miss4: cas.l %d0,%d1,(%a0) 68 bne miss4 69 rts 70FUNCTION_END(atomic_set) 71 72/* int atomic_test_and_set(int *value, int setTo, int testValue) 73 */ 74FUNCTION(atomic_test_and_set): 75 move.l (4,%a7),%a0 76 move.l (8,%a7),%d1 77 move.l (12,%a7),%d0 78 cas.l %d0,%d1,(%a0) 79 rts 80FUNCTION_END(atomic_test_and_set) 81 82/* int atomic_get(int *value) 83 */ 84FUNCTION(atomic_get): 85 move.l (4,%a7),%a0 86 move.l (%a0),%d0 87 move.l %d0,%d1 88 cas.l %d0,%d1,(%a0) 89 // we must use cas... so we change to the same value if matching, 90 // else we get the correct one anyway 91 rts 92FUNCTION_END(atomic_get) 93 94/* m68k elf convention is to return structs in (a0) 95 * but use d0/d1 for int64 and small structs. 96 * d0 MSB, d1 LSB 97 */ 98#warning M68K: 68060 doesn't have CAS2: use spinlock ?? 99/* see http://retropc.net/x68000/software/develop/as/has060/m68k.htm */ 100 101/* int64 atomic_add64(vint64 *value, int64 addValue) */ 102FUNCTION(atomic_add64): 103 movem.l %d2-%d3/%a2,-(%a7) 104 move.l (4,%a7),%a2 105 lea.l (4,%a2),%a1 106 // addValue 107 move.l (12,%a7),%d3 /*LSB*/ 108 move.l (8,%a7),%d2 /*MSB*/ 109miss5: // old value 110 move.l (%a1),%d1 /*LSB*/ 111 move.l (%a2),%d0 /*MSB*/ 112 add.l %d1,%d3 113 addx.l %d0,%d2 114 cas2.l %d0:%d1,%d2:%d3,(%a2):(%a1) 115 bne miss5 116 // return value d0:d1 117 movem.l (%a7)+,%d2-%d3/%a2 118 rts 119FUNCTION_END(atomic_add64) 120 121/* int64 atomic_and64(vint64 *value, int64 andValue) */ 122FUNCTION(atomic_and64): 123 movem.l %d2-%d3/%a2,-(%a7) 124 move.l (4,%a7),%a2 125 lea.l (4,%a2),%a1 126 // addValue 127 move.l (12,%a7),%d3 /*LSB*/ 128 move.l (8,%a7),%d2 /*MSB*/ 129miss6: // old value 130 move.l (%a1),%d1 /*LSB*/ 131 move.l (%a2),%d0 /*MSB*/ 132 and.l %d1,%d3 133 and.l %d0,%d2 134 cas2.l %d0:%d1,%d2:%d3,(%a2):(%a1) 135 bne miss6 136 // return value d0:d1 137 movem.l (%a7)+,%d2-%d3/%a2 138 rts 139FUNCTION_END(atomic_and64) 140 141/* int64 atomic_or64(vint64 *value, int64 orValue) */ 142FUNCTION(atomic_or64): 143 movem.l %d2-%d3/%a2,-(%a7) 144 move.l (4,%a7),%a2 145 lea.l (4,%a2),%a1 146 // addValue 147 move.l (12,%a7),%d3 /*LSB*/ 148 move.l (8,%a7),%d2 /*MSB*/ 149miss7: // old value 150 move.l (%a1),%d1 /*LSB*/ 151 move.l (%a2),%d0 /*MSB*/ 152 or.l %d1,%d3 153 or.l %d0,%d2 154 cas2.l %d0:%d1,%d2:%d3,(%a2):(%a1) 155 bne miss7 156 // return value d0:d1 157 movem.l (%a7)+,%d2-%d3/%a2 158 rts 159FUNCTION_END(atomic_or64) 160 161/* int64 atomic_set64(vint64 *value, int64 newValue) */ 162FUNCTION(atomic_set64): 163 movem.l %d2-%d3/%a2,-(%a7) 164 move.l (4,%a7),%a2 165 lea.l (4,%a2),%a1 166 // new value 167 move.l (12,%a7),%d3 /*LSB*/ 168 move.l (8,%a7),%d2 /*MSB*/ 169 // old value 170 move.l (%a1),%d1 /*LSB*/ 171 move.l (%a2),%d0 /*MSB*/ 172miss8: cas2.l %d0:%d1,%d2:%d3,(%a2):(%a1) 173 bne miss8 174 // return value d0:d1 175 movem.l (%a7)+,%d2-%d3/%a2 176 rts 177FUNCTION_END(atomic_set64) 178 179/* int64 atomic_test_and_set64(vint64 *value, int64 newValue, int64 testAgainst) */ 180FUNCTION(atomic_test_and_set64): 181 movem.l %d2-%d3/%a2,-(%a7) 182 move.l (4,%a7),%a2 183 lea.l (4,%a2),%a1 184 // new value 185 move.l (12,%a7),%d3 /*LSB*/ 186 move.l (8,%a7),%d2 /*MSB*/ 187 // test against value 188 move.l (20,%a7),%d1 /*LSB*/ 189 move.l (16,%a7),%d0 /*MSB*/ 190 cas2.l %d0:%d1,%d2:%d3,(%a2):(%a1) 191 // return value d0:d1 192 movem.l (%a7)+,%d2-%d3/%a2 193 rts 194FUNCTION_END(atomic_test_and_set64) 195 196/* int64 atomic_get64(vint64 *value) */ 197FUNCTION(atomic_get64): 198 movem.l %d2-%d3/%a2,-(%a7) 199 move.l (4,%a7),%a2 200 lea.l (4,%a2),%a1 201 move.l (%a1),%d1 /*LSB*/ 202 move.l (%a2),%d0 /*MSB*/ 203 move.l %d1,%d3 204 move.l %d0,%d2 205 // we must use cas... so we change to the same value if matching, 206 // else we get the correct one anyway 207 cas2.l %d0:%d1,%d2:%d3,(%a2):(%a1) 208 // return value 209 movem.l (%a7)+,%d2-%d3/%a2 210 rts 211FUNCTION_END(atomic_get64) 212.text 213 214#warning IMPLEMENT GCC 64-bit ATOMICS ON m68k! 215 216/* These are to fill in 64-bit atomic calls emitted by 217 * by GCC when 64-bit atomics are unavailable. 218 */ 219 220FUNCTION(__atomic_fetch_add_8): 221 nop 222 rts 223FUNCTION_END(__atomic_fetch_add_8) 224 225FUNCTION(__atomic_store_8): 226 nop 227 rts 228FUNCTION_END(__atomic_store_8) 229 230FUNCTION(__atomic_load_8): 231 nop 232 rts 233FUNCTION_END(__atomic_load_8) 234 235