diff options
Diffstat (limited to 'roms/openbios/arch/sparc64/switch.S')
-rw-r--r-- | roms/openbios/arch/sparc64/switch.S | 89 |
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 |