/* ** Copyright 2003, Axel Dörfler, axeld@pinc-software.de. All rights reserved. ** Distributed under the terms of the OpenBeOS License. */ /* * gcc/config/m68k/m68k.h:CALL_USED_REGISTERS: * d0,d1,a0,a1 are scratch regs, not to be saved. */ /* * see http://mail-index.netbsd.org/amiga/1995/06/ * for concerns about TAS, CAS and Amiga. * I suppose as long as we don't use it on a variable in * chip ram it shouldn't be a problem, and since we don't * have any SMP Amiga anyway it should be ok. */ #define FUNCTION(x) .global x; .type x,@function; x .text /* int atomic_add(int *value, int increment) */ FUNCTION(atomic_add): move.l (4,%a7),%a0 move.l (%a0),%d0 miss1: move.l %d0,%d1 add.l (8,%a7),%d1 cas.l %d0,%d1,(%a0) bne miss1 // d0 = old value rts /* int atomic_and(int *value, int andValue) */ FUNCTION(atomic_and): move.l (4,%a7),%a0 move.l (%a0),%d0 miss2: move.l %d0,%d1 and.l (8,%a7),%d1 cas.l %d0,%d1,(%a0) bne miss2 // d0 = old value rts /* int atomic_or(int *value, int orValue) */ FUNCTION(atomic_or): move.l (4,%a7),%a0 move.l (%a0),%d0 miss3: move.l %d0,%d1 or.l (8,%a7),%d1 cas.l %d0,%d1,(%a0) bne miss3 rts /* int atomic_set(int *value, int setTo) */ FUNCTION(atomic_set): move.l (4,%a7),%a0 move.l (%a0),%d0 move.l (8,%a7),%d1 miss4: cas.l %d0,%d1,(%a0) bne miss4 rts /* int atomic_test_and_set(int *value, int setTo, int testValue) */ FUNCTION(atomic_test_and_set): move.l (4,%a7),%a0 move.l (8,%a7),%d1 move.l (12,%a7),%d0 cas.l %d0,%d1,(%a0) rts /* int atomic_get(int *value) */ FUNCTION(atomic_get): move.l (4,%a7),%a0 move.l (%a0),%d0 move.l %d0,%d1 cas.l %d0,%d1,(%a0) // we must use cas... so we change to the same value if matching, // else we get the correct one anyway rts /* m68k elf convention is to return structs in (a0) */ /* other conventions use d0/d1 but which is MSB ?? */ #warning M68K: 68060 doesn't have CAS2: use spinlock ?? /* see http://retropc.net/x68000/software/develop/as/has060/m68k.htm */ /* int64 atomic_add64(vint64 *value, int64 addValue) */ FUNCTION(atomic_add64): move.l %d2,-(%a7) move.l %d3,-(%a7) move.l %a2,-(%a7) move.l (4,%a7),%a1 lea.l (4,%a1),%a2 // addValue move.l (12,%a7),%d2 /*LSB*/ move.l (8,%a7),%d3 /*MSB*/ miss5: // old value move.l (4,%a1),%d0 /*LSB*/ move.l (%a1),%d1 /*MSB*/ add.l %d0,%d2 addx.l %d1,%d3 cas2.l %d0:%d1,%d2:%d3,(%a2):(%a1) bne miss5 // return value move.l %d0,(4,%a0) move.l %d1,(%a0) move.l (%a7)+,%a2 move.l (%a7)+,%d3 move.l (%a7)+,%d2 rts /* int64 atomic_and64(vint64 *value, int64 andValue) */ FUNCTION(atomic_and64): move.l %d2,-(%a7) move.l %d3,-(%a7) move.l %a2,-(%a7) move.l (4,%a7),%a1 lea.l (4,%a1),%a2 // addValue move.l (12,%a7),%d2 /*LSB*/ move.l (8,%a7),%d3 /*MSB*/ miss6: // old value move.l (4,%a1),%d0 /*LSB*/ move.l (%a1),%d1 /*MSB*/ and.l %d0,%d2 and.l %d1,%d3 cas2.l %d0:%d1,%d2:%d3,(%a2):(%a1) bne miss6 // return value move.l %d0,(4,%a0) move.l %d1,(%a0) move.l (%a7)+,%a2 move.l (%a7)+,%d3 move.l (%a7)+,%d2 rts /* int64 atomic_or64(vint64 *value, int64 orValue) */ FUNCTION(atomic_or64): move.l %d2,-(%a7) move.l %d3,-(%a7) move.l %a2,-(%a7) move.l (4,%a7),%a1 lea.l (4,%a1),%a2 // addValue move.l (12,%a7),%d2 /*LSB*/ move.l (8,%a7),%d3 /*MSB*/ miss7: // old value move.l (4,%a1),%d0 /*LSB*/ move.l (%a1),%d1 /*MSB*/ or.l %d0,%d2 or.l %d1,%d3 cas2.l %d0:%d1,%d2:%d3,(%a2):(%a1) bne miss7 // return value move.l %d0,(4,%a0) move.l %d1,(%a0) move.l (%a7)+,%a2 move.l (%a7)+,%d3 move.l (%a7)+,%d2 rts /* int64 atomic_set64(vint64 *value, int64 newValue) */ FUNCTION(atomic_set64): move.l %d2,-(%a7) move.l %d3,-(%a7) move.l %a2,-(%a7) move.l (4,%a7),%a1 lea.l (4,%a1),%a2 // new value move.l (12,%a7),%d2 /*LSB*/ move.l (8,%a7),%d3 /*MSB*/ // old value move.l (4,%a1),%d0 /*LSB*/ move.l (%a1),%d1 /*MSB*/ miss8: cas2.l %d0:%d1,%d2:%d3,(%a2):(%a1) bne miss8 // return value move.l %d0,(4,%a0) move.l %d1,(%a0) move.l (%a7)+,%a2 move.l (%a7)+,%d3 move.l (%a7)+,%d2 rts /* int64 atomic_test_and_set64(vint64 *value, int64 newValue, int64 testAgainst) */ FUNCTION(atomic_test_and_set64): move.l %d2,-(%a7) move.l %d3,-(%a7) move.l %a2,-(%a7) move.l (4,%a7),%a1 lea.l (4,%a1),%a2 // new value move.l (12,%a7),%d2 /*LSB*/ move.l (8,%a7),%d3 /*MSB*/ // test against value move.l (20,%a7),%d0 /*LSB*/ move.l (16,%a7),%d1 /*MSB*/ cas2.l %d0:%d1,%d2:%d3,(%a2):(%a1) // return value move.l %d0,(4,%a0) move.l %d1,(%a0) move.l (%a7)+,%a2 move.l (%a7)+,%d3 move.l (%a7)+,%d2 rts /* int64 atomic_get64(vint64 *value) */ FUNCTION(atomic_get64): move.l %d2,-(%a7) move.l %d3,-(%a7) move.l %a2,-(%a7) move.l (4,%a7),%a1 lea.l (4,%a1),%a2 move.l (4,%a1),%d0 /*LSB*/ move.l (%a1),%d1 /*MSB*/ move.l %d0,%d2 move.l %d1,%d3 // we must use cas... so we change to the same value if matching, // else we get the correct one anyway cas2.l %d0:%d1,%d2:%d3,(%a2):(%a1) // return value move.l %d0,(4,%a0) move.l %d1,(%a0) move.l (%a7)+,%a2 move.l (%a7)+,%d3 move.l (%a7)+,%d2 rts