aboutsummaryrefslogtreecommitdiffstats
path: root/roms/openbios/arch/sparc32/switch.S
diff options
context:
space:
mode:
Diffstat (limited to 'roms/openbios/arch/sparc32/switch.S')
-rw-r--r--roms/openbios/arch/sparc32/switch.S83
1 files changed, 83 insertions, 0 deletions
diff --git a/roms/openbios/arch/sparc32/switch.S b/roms/openbios/arch/sparc32/switch.S
new file mode 100644
index 000000000..e4dbc9afb
--- /dev/null
+++ b/roms/openbios/arch/sparc32/switch.S
@@ -0,0 +1,83 @@
+#define __ASSEMBLY
+#include "psr.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
+
+/*
+ * 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:
+ FLUSH_ALL_KERNEL_WINDOWS
+
+ /* Save everything in stack */
+ st %g1, [%sp - 0x260 + 0x14]
+ st %g2, [%sp - 0x260 + 0x18]
+ st %g3, [%sp - 0x260 + 0x1c]
+ st %g4, [%sp - 0x260 + 0x20]
+ st %g5, [%sp - 0x260 + 0x24]
+ st %g6, [%sp - 0x260 + 0x28]
+ st %g7, [%sp - 0x260 + 0x2c]
+
+ mov %sp, %g1
+ add %g1, -0x260, %g1
+
+ SAVE_CPU_STATE(switch)
+
+ /* Return PC value */
+ mov %o7, %g2
+ add %g2, 4, %g2
+ st %g2, [%sp - 0x260 + 0x250]
+
+ /* swap context */
+ set __context, %g3
+ ld [%g3], %g2
+ st %g1, [%g3]
+ mov %g2, %g1
+
+ ba __set_context
+ nop
+
+__switch_context_nosave:
+ FLUSH_ALL_KERNEL_WINDOWS
+
+ set __context, %g1
+ ld [%g1], %g1
+
+__set_context:
+ RESTORE_CPU_STATE(switch)
+
+ /* Restore globals */
+ mov %g1, %g2
+ add %g2, 0x14, %g2
+ st %g2, [%sp - 96]
+
+ ld [%g1 + 0x18], %g2
+ ld [%g1 + 0x1c], %g3
+ ld [%g1 + 0x20], %g4
+ ld [%g1 + 0x24], %g5
+ ld [%g1 + 0x28], %g6
+ ld [%g1 + 0x2c], %g7
+
+ /* Finally, load new %pc */
+ ld [%g1 + 0x250], %g1
+ jmpl %g1, %o7
+ ld [%sp - 96], %g1
+
+__exit_context:
+ /* Get back to the original context */
+ ba __switch_context
+ nop