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