newlib-cygwin/libgloss/or1k/sync-asm.S

136 lines
2.9 KiB
ArmAsm

#include "include/or1k-asm.h"
#include "include/or1k-sprs.h"
.section .text
.global or1k_has_multicore_support
.type or1k_has_multicore_support,@function
or1k_has_multicore_support:
#ifdef __OR1K_MULTICORE__
// Return 1
OR1K_DELAYED(
OR1K_INST(l.ori r11,r0,1),
OR1K_INST(l.jr r9)
)
#else
// Return 0
OR1K_DELAYED(
OR1K_INST(l.or r11,r0,r0),
OR1K_INST(l.jr r9)
)
#endif
.global or1k_coreid
.type or1k_coreid,@function
or1k_coreid:
#ifdef __OR1K_MULTICORE__
// Return SPR with core identifier
OR1K_DELAYED(
OR1K_INST(l.mfspr r11,r0,OR1K_SPR_SYS_COREID_ADDR),
OR1K_INST(l.jr r9)
)
#else
// Return 0
OR1K_DELAYED(
OR1K_INST(l.or r11,r0,r0),
OR1K_INST(l.jr r9)
)
#endif
.global or1k_numcores
.type or1k_numcores,@function
or1k_numcores:
#ifdef __OR1K_MULTICORE__
// Return SPR with number of cores
OR1K_DELAYED(
OR1K_INST(l.mfspr r11,r0,OR1K_SPR_SYS_NUMCORES_ADDR),
OR1K_INST(l.jr r9)
)
#else
// Return 1
OR1K_DELAYED(
OR1K_INST(l.ori r11,r0,1),
OR1K_INST(l.jr r9)
)
#endif
.global or1k_sync_ll
.type or1k_sync_ll,@function
or1k_sync_ll:
#ifdef __OR1K_MULTICORE__
// Load word atomic
OR1K_DELAYED(
OR1K_INST(l.lwa r11, 0(r3)),
OR1K_INST(l.jr r9)
)
#else
// Simply load word, TODO: throw exception? which?
OR1K_DELAYED(
OR1K_INST(l.lwz r11, 0(r3)),
OR1K_INST(l.jr r9)
)
#endif
.global or1k_sync_sc
.type or1k_sync_sc,@function
or1k_sync_sc:
#ifdef __OR1K_MULTICORE__
// swa sets the flag if it was succesfull
// Store the value to address and set flag
l.swa 0(r3),r4
OR1K_DELAYED(
// Set return to success speculatively (may go to delay slot)
OR1K_INST(l.ori r11,r0,1),
// If the swa was successfull, jump to end
OR1K_INST(l.bf .or1k_sync_sc_done)
)
// If the swa was not successfull, set
l.or r11,r0,r0
.or1k_sync_sc_done:
OR1K_DELAYED_NOP(OR1K_INST(l.jr r9))
#else
// Simply store word, TODO: throw exception? which?
OR1K_DELAYED(
OR1K_INST(l.sw 0(r3),r4),
OR1K_INST(l.jr r9)
)
#endif
.global or1k_sync_cas
.type or1k_sync_sc,@function
or1k_sync_cas:
#ifdef __OR1K_MULTICORE__
/* Load linked address value to return register */
l.lwa r11,0(r3)
/* Compare value to parameter */
l.sfeq r11,r4
/* If not equal: abort and return the read value */
OR1K_DELAYED_NOP(OR1K_INST(l.bnf .or1k_sync_cas_done))
/* If compare was successfull: try writing */
l.swa 0(r3),r5
/* If writing was not successful: restart */
OR1K_DELAYED_NOP(OR1K_INST(l.bnf or1k_sync_cas))
.or1k_sync_cas_done:
/* Return value is the original read value */
OR1K_DELAYED_NOP(OR1K_INST(l.jr r9))
#else
// Non-atomic CAS, TODO: throw exception? which?
l.lwz r11,0(r3)
l.sfeq r11,r4
OR1K_DELAYED_NOP(OR1K_INST(l.bnf .or1k_sync_cas_done))
l.sw 0(r3),r5
.or1k_sync_cas_done:
OR1K_DELAYED_NOP(OR1K_INST(l.jr r9))
#endif
.global or1k_sync_tsl
.type or1k_sync_tsl,@function
or1k_sync_tsl:
l.or r4,r0,r0
OR1K_DELAYED(
OR1K_INST(l.addi r5,r0,1),
OR1K_INST(l.j or1k_sync_cas)
)