summaryrefslogtreecommitdiffstats
path: root/libgloss/or1k/sync-asm.S
diff options
context:
space:
mode:
Diffstat (limited to 'libgloss/or1k/sync-asm.S')
-rw-r--r--libgloss/or1k/sync-asm.S135
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)
+ )