aboutsummaryrefslogtreecommitdiffstats
path: root/roms/openbios/arch/sparc64/call-client.S
diff options
context:
space:
mode:
Diffstat (limited to 'roms/openbios/arch/sparc64/call-client.S')
-rw-r--r--roms/openbios/arch/sparc64/call-client.S142
1 files changed, 142 insertions, 0 deletions
diff --git a/roms/openbios/arch/sparc64/call-client.S b/roms/openbios/arch/sparc64/call-client.S
new file mode 100644
index 000000000..4129505f0
--- /dev/null
+++ b/roms/openbios/arch/sparc64/call-client.S
@@ -0,0 +1,142 @@
+#include "cpustate.h"
+
+ .globl sparc64_of_client_interface, client_tba
+
+
+/*
+ * SAVE_WINDOW_STATE and RESTORE_WINDOW_STATE are used to ensure
+ * that the CPU window state is preserved across CIF calls. This is
+ * to workaround a *BSD restriction that window fill/spill traps must
+ * be minimised during trap table takeover, and likely emulates the
+ * behaviour of OBP.
+ */
+
+ .data
+ .align 8
+
+client_context:
+ .xword 0
+client_stack:
+ .xword 0
+client_window:
+ .skip 2048
+
+
+ .text
+ .align 4
+ .register %g2, #scratch
+ .register %g3, #scratch
+ .register %g6, #scratch
+ .register %g7, #scratch
+/*
+ make some more space on stack since linux kernel only provides 128 bytes
+ without memory to spill registers (used by gcc in -O0 mode)
+*/
+
+sparc64_of_client_interface:
+
+ /* Save globals on callers stack */
+ stx %g1, [%sp + 2047 - 248 + 192]
+ stx %g2, [%sp + 2047 - 248 + 200]
+ stx %g3, [%sp + 2047 - 248 + 208]
+ stx %g4, [%sp + 2047 - 248 + 216]
+ stx %g5, [%sp + 2047 - 248 + 224]
+ stx %g6, [%sp + 2047 - 248 + 232]
+ stx %g7, [%sp + 2047 - 248 + 240]
+
+ /* Save existing stack */
+ setx client_stack, %g6, %g7
+ stx %sp, [%g7]
+
+ /* Save windows */
+ setx _fcstack_ptr, %g6, %g7
+ ldx [%g7], %g1
+ add %g1, -CONTEXT_STATE_SIZE, %g1
+ stx %g1, [%g7]
+
+ /* Save globals */
+ ldx [%sp + 2047 - 248 + 192], %g7
+ stx %g7, [%g1 + 0x30]
+ ldx [%sp + 2047 - 248 + 200], %g7
+ stx %g7, [%g1 + 0x38]
+ ldx [%sp + 2047 - 248 + 208], %g7
+ stx %g7, [%g1 + 0x40]
+ ldx [%sp + 2047 - 248 + 216], %g7
+ stx %g7, [%g1 + 0x48]
+ ldx [%sp + 2047 - 248 + 224], %g7
+ stx %g7, [%g1 + 0x50]
+ ldx [%sp + 2047 - 248 + 232], %g7
+ stx %g7, [%g1 + 0x58]
+ ldx [%sp + 2047 - 248 + 240], %g7
+ stx %g7, [%g1 + 0x60]
+
+ /* Save %pc */
+ mov %o7, %g7
+ add %g7, 8, %g7
+ stx %g7, [%g1 + 0x4d0]
+
+ SAVE_CPU_STATE(cif)
+
+ RESET_CPU_WINDOW_STATE(cif)
+
+ /* Update __context to point to saved area */
+ setx __context, %g6, %g7
+ ldx [%g7], %g3
+ setx client_context, %g4, %g5
+ stx %g3, [%g5]
+ stx %g1, [%g7]
+
+ /* Move to OpenBIOS context stack */
+ setx _fcstack_ptr, %g6, %g7
+ ldx [%g7], %g6
+ setx CONTEXT_STACK_SIZE, %g4, %g5
+ sub %g6, %g5, %g6
+ stx %g6, [%g7]
+
+ setx - 2047 - 192, %g6, %g7
+ add %g1, %g7, %g7
+ mov %g7, %sp
+
+ /* Call client inteface */
+ call of_client_interface
+ ldx [%g1 + 0x70], %o0
+
+ /* Restore windows */
+ setx _fcstack_ptr, %g6, %g7
+ ldx [%g7], %g1
+ setx CONTEXT_STACK_SIZE, %g4, %g5
+ add %g1, %g5, %g1
+ stx %g1, [%g7]
+
+ /* Return value */
+ stx %o0, [%g1 + 0x70]
+
+ /* Restore __context */
+ setx client_context, %g4, %g5
+ ldx [%g5], %g3
+ setx __context, %g6, %g7
+ stx %g3, [%g7]
+
+ RESTORE_CPU_STATE(cif)
+
+ add %g1, CONTEXT_STATE_SIZE, %g5
+ setx _fcstack_ptr, %g6, %g7
+ stx %g5, [%g7]
+
+ /* Restore stack */
+ setx client_stack, %g6, %g7
+ ldx [%g7], %sp
+
+ /* Restore %pc */
+ ldx [%g1 + 0x4d0], %o7
+
+ /* Restore globals */
+ ldx [%g1 + 0x38], %g2
+ ldx [%g1 + 0x40], %g3
+ ldx [%g1 + 0x48], %g4
+ ldx [%g1 + 0x50], %g5
+ ldx [%g1 + 0x58], %g6
+ ldx [%g1 + 0x60], %g7
+
+ jmp %o7
+ ldx [%g1 + 0x30], %g1