diff options
Diffstat (limited to 'libgloss/or1k/sync-asm.S')
-rw-r--r-- | libgloss/or1k/sync-asm.S | 135 |
1 files changed, 135 insertions, 0 deletions
diff --git a/libgloss/or1k/sync-asm.S b/libgloss/or1k/sync-asm.S new file mode 100644 index 000000000..911e2552f --- /dev/null +++ b/libgloss/or1k/sync-asm.S @@ -0,0 +1,135 @@ +#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) + ) |