83 lines
2.2 KiB
ArmAsm
83 lines
2.2 KiB
ArmAsm
#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
|