aboutsummaryrefslogtreecommitdiffstats
path: root/roms/openbios/arch/sparc64/switch.S
diff options
context:
space:
mode:
Diffstat (limited to 'roms/openbios/arch/sparc64/switch.S')
-rw-r--r--roms/openbios/arch/sparc64/switch.S89
1 files changed, 89 insertions, 0 deletions
diff --git a/roms/openbios/arch/sparc64/switch.S b/roms/openbios/arch/sparc64/switch.S
new file mode 100644
index 000000000..eae4c96a4
--- /dev/null
+++ b/roms/openbios/arch/sparc64/switch.S
@@ -0,0 +1,89 @@
+#include "pstate.h"
+#include <asm/asi.h>
+#include "cpustate.h"
+#define ASI_BP ASI_M_BYPASS
+#define REGWIN_SZ 0x40
+
+ .globl __switch_context, __switch_context_nosave, __exit_context, halt
+
+ .text
+ .align 4
+ .register %g2, #scratch
+ .register %g3, #scratch
+ .register %g6, #scratch
+ .register %g7, #scratch
+
+/*
+ * Switch execution context
+ * This saves registers in the stack, then
+ * switches the stack, and restores everything from the new stack.
+ * This function takes no argument. New stack pointer is
+ * taken from global variable __context, and old stack pointer
+ * is also saved to __context. This way we can just jump to
+ * this routine to get back to the original context.
+ */
+
+__switch_context:
+ /* make sure caller's windows are on caller's stack */
+ flushw;
+
+ /* Save everything in current stack */
+ stx %g1, [%sp + 2047 - 0x500 + 0x30]
+ stx %g2, [%sp + 2047 - 0x500 + 0x38]
+ stx %g3, [%sp + 2047 - 0x500 + 0x40]
+ stx %g4, [%sp + 2047 - 0x500 + 0x48]
+ stx %g5, [%sp + 2047 - 0x500 + 0x50]
+ stx %g6, [%sp + 2047 - 0x500 + 0x58]
+ stx %g7, [%sp + 2047 - 0x500 + 0x60]
+
+ mov %sp, %g1
+ add %g1, 2047 - 0x500, %g1
+
+ /* Return PC value */
+ mov %o7, %g2
+ add %g2, 0x8, %g2
+ stx %g2, [%g1 + 0x4d0]
+
+ SAVE_CPU_STATE(switch)
+
+ /* swap context */
+ setx __context, %g2, %g3
+ ldx [%g3], %g2
+ stx %g1, [%g3]
+ mov %g2, %g1
+
+ ba __set_context
+
+__switch_context_nosave:
+ /* Interrupts are not allowed... */
+ /* make sure caller's windows are on caller's stack */
+ flushw
+ /* Load all registers
+ */
+ setx __context, %g2, %g1
+ ldx [%g1], %g1
+
+__set_context:
+ RESTORE_CPU_STATE(switch)
+
+ /* Restore globals */
+ mov %g1, %g2
+ add %g2, 0x30, %g2
+ stx %g2, [%sp + 2047 - 8]
+
+ ldx [%g1 + 0x38], %g2
+ ldx [%g1 + 0x40], %g3
+ ldx [%g1 + 0x48], %g4
+ ldx [%g1 + 0x50], %g5
+ ldx [%g1 + 0x58], %g6
+ ldx [%g1 + 0x60], %g7
+
+ /* Finally, load new %pc */
+ ldx [%g1 + 0x4d0], %g1
+ jmpl %g1, %o7
+ ldx [%sp + 2047 - 8], %g1
+
+__exit_context:
+ /* Get back to the original context */
+ ba __switch_context
+ nop