about summary refs log tree commit diff
path: root/src/rt/arch/mips/morestack.S
diff options
context:
space:
mode:
Diffstat (limited to 'src/rt/arch/mips/morestack.S')
-rw-r--r--src/rt/arch/mips/morestack.S97
1 files changed, 97 insertions, 0 deletions
diff --git a/src/rt/arch/mips/morestack.S b/src/rt/arch/mips/morestack.S
new file mode 100644
index 00000000000..e534ac05913
--- /dev/null
+++ b/src/rt/arch/mips/morestack.S
@@ -0,0 +1,97 @@
+// Mark stack as non-executable
+#if defined(__linux__) && defined(__ELF__)
+.section        .note.GNU-stack, "", @progbits
+#endif
+
+.text
+
+.globl upcall_new_stack
+.globl upcall_del_stack
+.globl __morestack
+
+.hidden __morestack
+
+.cfi_startproc
+.set nomips16
+.ent __morestack
+__morestack:
+        .set noreorder
+        .set nomacro
+
+        addiu $29, $29, -12
+        sw $31, 8($29)
+        sw $30, 4($29)
+        sw $23, 0($29)
+
+        // 24 = 12 (current) + 12 (previous)
+        .cfi_def_cfa_offset 24
+        .cfi_offset 31, -4
+        .cfi_offset 30, -20
+        .cfi_offset 23, -24
+
+        move $23, $28
+        move $30, $29
+        .cfi_def_cfa_register 30
+
+        // Save argument registers of the original function
+        addiu $29, $29, -32
+        sw $4, 16($29)
+        sw $5, 20($29)
+        sw $6, 24($29)
+        sw $7, 28($29)
+
+        move $4, $14     // Size of stack arguments
+        addu $5, $30, 24 // Address of stack arguments
+        move $6, $15     // The amount of stack needed
+
+        move $28, $23
+        lw $25, %call16(upcall_new_stack)($23)
+        jalr $25
+        nop
+
+        // Pop the saved arguments
+        lw $4, 16($29)
+        lw $5, 20($29)
+        lw $6, 24($29)
+        lw $7, 28($29)
+        addiu $29, $29, 32
+
+        lw $24, 8($30)     // Grab the return pointer.
+        addiu $24, $24, 12 // Skip past the `lw`, `jr`, `addiu` in our parent frame
+        move $29, $2       // Switch to the new stack.
+
+        // for PIC
+        lw $2, 12($30)
+        lw $25, 16($30)
+
+        move $28, $23
+        jalr $24           // Reenter the caller function
+        nop
+
+        // Switch back to the rust stack
+        move $29, $30
+
+        // Save the return value
+        addiu $29, $29, -24
+        sw $2, 16($29)
+        sw $3, 20($29)
+
+        move $28, $23
+        lw $25, %call16(upcall_del_stack)($23)
+        jalr $25
+        nop
+
+        // Restore the return value
+        lw $2, 16($29)
+        lw $3, 20($29)
+        addiu $29, $29, 24
+
+        lw $31, 8($29)
+        lw $30, 4($29)
+        lw $23, 0($29)
+        addiu $29, $29, 12
+
+        jr $31
+        nop
+.end __morestack
+.cfi_endproc