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/* other conventions use d0/d1 but which is MSB ?? */ 90#warning M68K: 68060 doesn't have CAS2: use spinlock ?? 91/* see http://retropc.net/x68000/software/develop/as/has060/m68k.htm */ 92 93/* int64 atomic_add64(vint64 *value, int64 addValue) */ 94FUNCTION(atomic_add64): 95 move.l %d2,-(%a7) 96 move.l %d3,-(%a7) 97 move.l %a2,-(%a7) 98 move.l (4,%a7),%a1 99 lea.l (4,%a1),%a2 100 // addValue 101 move.l (12,%a7),%d2 /*LSB*/ 102 move.l (8,%a7),%d3 /*MSB*/ 103miss5: // old value 104 move.l (4,%a1),%d0 /*LSB*/ 105 move.l (%a1),%d1 /*MSB*/ 106 add.l %d0,%d2 107 addx.l %d1,%d3 108 cas2.l %d0:%d1,%d2:%d3,(%a2):(%a1) 109 bne miss5 110 // return value 111 move.l %d0,(4,%a0) 112 move.l %d1,(%a0) 113 move.l (%a7)+,%a2 114 move.l (%a7)+,%d3 115 move.l (%a7)+,%d2 116 rts 117 118/* int64 atomic_and64(vint64 *value, int64 andValue) */ 119FUNCTION(atomic_and64): 120 move.l %d2,-(%a7) 121 move.l %d3,-(%a7) 122 move.l %a2,-(%a7) 123 move.l (4,%a7),%a1 124 lea.l (4,%a1),%a2 125 // addValue 126 move.l (12,%a7),%d2 /*LSB*/ 127 move.l (8,%a7),%d3 /*MSB*/ 128miss6: // old value 129 move.l (4,%a1),%d0 /*LSB*/ 130 move.l (%a1),%d1 /*MSB*/ 131 and.l %d0,%d2 132 and.l %d1,%d3 133 cas2.l %d0:%d1,%d2:%d3,(%a2):(%a1) 134 bne miss6 135 // return value 136 move.l %d0,(4,%a0) 137 move.l %d1,(%a0) 138 move.l (%a7)+,%a2 139 move.l (%a7)+,%d3 140 move.l (%a7)+,%d2 141 rts 142 143/* int64 atomic_or64(vint64 *value, int64 orValue) */ 144FUNCTION(atomic_or64): 145 move.l %d2,-(%a7) 146 move.l %d3,-(%a7) 147 move.l %a2,-(%a7) 148 move.l (4,%a7),%a1 149 lea.l (4,%a1),%a2 150 // addValue 151 move.l (12,%a7),%d2 /*LSB*/ 152 move.l (8,%a7),%d3 /*MSB*/ 153miss7: // old value 154 move.l (4,%a1),%d0 /*LSB*/ 155 move.l (%a1),%d1 /*MSB*/ 156 or.l %d0,%d2 157 or.l %d1,%d3 158 cas2.l %d0:%d1,%d2:%d3,(%a2):(%a1) 159 bne miss7 160 // return value 161 move.l %d0,(4,%a0) 162 move.l %d1,(%a0) 163 move.l (%a7)+,%a2 164 move.l (%a7)+,%d3 165 move.l (%a7)+,%d2 166 rts 167 168/* int64 atomic_set64(vint64 *value, int64 newValue) */ 169FUNCTION(atomic_set64): 170 move.l %d2,-(%a7) 171 move.l %d3,-(%a7) 172 move.l %a2,-(%a7) 173 move.l (4,%a7),%a1 174 lea.l (4,%a1),%a2 175 // new value 176 move.l (12,%a7),%d2 /*LSB*/ 177 move.l (8,%a7),%d3 /*MSB*/ 178 // old value 179 move.l (4,%a1),%d0 /*LSB*/ 180 move.l (%a1),%d1 /*MSB*/ 181miss8: cas2.l %d0:%d1,%d2:%d3,(%a2):(%a1) 182 bne miss8 183 // return value 184 move.l %d0,(4,%a0) 185 move.l %d1,(%a0) 186 move.l (%a7)+,%a2 187 move.l (%a7)+,%d3 188 move.l (%a7)+,%d2 189 rts 190 191/* int64 atomic_test_and_set64(vint64 *value, int64 newValue, int64 testAgainst) */ 192FUNCTION(atomic_test_and_set64): 193 move.l %d2,-(%a7) 194 move.l %d3,-(%a7) 195 move.l %a2,-(%a7) 196 move.l (4,%a7),%a1 197 lea.l (4,%a1),%a2 198 // new value 199 move.l (12,%a7),%d2 /*LSB*/ 200 move.l (8,%a7),%d3 /*MSB*/ 201 // test against value 202 move.l (20,%a7),%d0 /*LSB*/ 203 move.l (16,%a7),%d1 /*MSB*/ 204 cas2.l %d0:%d1,%d2:%d3,(%a2):(%a1) 205 // return value 206 move.l %d0,(4,%a0) 207 move.l %d1,(%a0) 208 move.l (%a7)+,%a2 209 move.l (%a7)+,%d3 210 move.l (%a7)+,%d2 211 rts 212 213/* int64 atomic_get64(vint64 *value) */ 214FUNCTION(atomic_get64): 215 move.l %d2,-(%a7) 216 move.l %d3,-(%a7) 217 move.l %a2,-(%a7) 218 move.l (4,%a7),%a1 219 lea.l (4,%a1),%a2 220 move.l (4,%a1),%d0 /*LSB*/ 221 move.l (%a1),%d1 /*MSB*/ 222 move.l %d0,%d2 223 move.l %d1,%d3 224 // we must use cas... so we change to the same value if matching, 225 // else we get the correct one anyway 226 cas2.l %d0:%d1,%d2:%d3,(%a2):(%a1) 227 // return value 228 move.l %d0,(4,%a0) 229 move.l %d1,(%a0) 230 move.l (%a7)+,%a2 231 move.l (%a7)+,%d3 232 move.l (%a7)+,%d2 233 rts 234 235