summaryrefslogtreecommitdiffstats
path: root/qemu/roms/openbios/arch/sparc64/switch.S
diff options
context:
space:
mode:
Diffstat (limited to 'qemu/roms/openbios/arch/sparc64/switch.S')
-rw-r--r--qemu/roms/openbios/arch/sparc64/switch.S124
1 files changed, 124 insertions, 0 deletions
diff --git a/qemu/roms/openbios/arch/sparc64/switch.S b/qemu/roms/openbios/arch/sparc64/switch.S
new file mode 100644
index 000000000..d2cc7bedb
--- /dev/null
+++ b/qemu/roms/openbios/arch/sparc64/switch.S
@@ -0,0 +1,124 @@
+#include "pstate.h"
+#include <asm/asi.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.
+ */
+
+/* XXX: totally bogus for sparc, need to save and restore all windows */
+__switch_context:
+
+ /* make sure caller's windows are on caller's stack */
+ flushw;
+
+ /* Save everything in current stack */
+
+ setx __context, %g2, %g1
+ stx %g3, [%g1 + 24]
+ stx %g4, [%g1 + 32]
+ stx %g5, [%g1 + 40]
+ stx %g6, [%g1 + 48]
+ stx %g7, [%g1 + 56]
+
+ stx %o0, [%g1 + 64]
+ stx %o1, [%g1 + 72]
+ stx %o2, [%g1 + 80]
+ stx %o3, [%g1 + 88]
+ stx %o4, [%g1 + 96]
+ stx %o5, [%g1 + 104]
+ stx %o6, [%g1 + 112]
+ stx %o7, [%g1 + 120]
+
+ stx %l0, [%g1 + 128]
+ stx %l1, [%g1 + 136]
+ stx %l2, [%g1 + 144]
+ stx %l3, [%g1 + 152]
+ stx %l4, [%g1 + 160]
+ stx %l5, [%g1 + 168]
+ stx %l6, [%g1 + 176]
+ stx %l7, [%g1 + 184]
+
+ stx %i0, [%g1 + 192]
+ stx %i1, [%g1 + 200]
+ stx %i2, [%g1 + 208]
+ stx %i3, [%g1 + 216]
+ stx %i4, [%g1 + 224]
+ stx %i5, [%g1 + 232]
+ stx %i6, [%g1 + 240]
+ stx %i7, [%g1 + 248]
+
+__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
+ ldx [%g1 + 16], %g2
+ ldx [%g1 + 24], %g3
+ ldx [%g1 + 32], %g4
+ ldx [%g1 + 40], %g5
+ ldx [%g1 + 48], %g6
+ ldx [%g1 + 56], %g7
+
+ ldx [%g1 + 64], %o0
+ ldx [%g1 + 72], %o1
+ ldx [%g1 + 80], %o2
+ ldx [%g1 + 88], %o3
+ ldx [%g1 + 96], %o4
+ ldx [%g1 + 104], %o5
+ ldx [%g1 + 112], %o6
+ ldx [%g1 + 120], %o7
+
+ ldx [%g1 + 128], %l0
+ ldx [%g1 + 136], %l1
+ ldx [%g1 + 144], %l2
+ ldx [%g1 + 152], %l3
+ ldx [%g1 + 160], %l4
+ ldx [%g1 + 168], %l5
+ ldx [%g1 + 176], %l6
+ ldx [%g1 + 184], %l7
+
+ ldx [%g1 + 192], %i0
+ ldx [%g1 + 200], %i1
+ ldx [%g1 + 208], %i2
+ ldx [%g1 + 216], %i3
+ ldx [%g1 + 224], %i4
+ ldx [%g1 + 232], %i5
+ ldx [%g1 + 240], %i6
+ ldx [%g1 + 248], %i7
+
+ ldx [%g1 + 256], %g1
+ /* Finally, load new %pc */
+ jmp %g1
+ clr %g1
+
+__exit_context:
+ /* Get back to the original context */
+ call __switch_context
+ nop
+
+ /* We get here if the other context attempt to switch to this
+ * dead context. This should not happen. */
+
+halt:
+ b halt
+ nop