aboutsummaryrefslogtreecommitdiff
path: root/lib/std/start.zig
diff options
context:
space:
mode:
authorAlex Rønne Petersen <alex@alexrp.com>2025-10-18 01:56:20 +0200
committerAlex Rønne Petersen <alex@alexrp.com>2025-10-18 11:16:31 +0200
commitb8d776928a0b0092830ee632b1c57c8bcf9391ea (patch)
tree5f30b527977d152cad713f19018c69c7a71124c5 /lib/std/start.zig
parentf3da54f53c1db1484b00657de18e3677358549cd (diff)
downloadzig-b8d776928a0b0092830ee632b1c57c8bcf9391ea.tar.gz
zig-b8d776928a0b0092830ee632b1c57c8bcf9391ea.zip
std: make all MIPS inline asm safe for MIPS I
MIPS I has load hazards so we need to insert nops in a few places. This is not a problem for MIPS II and later. While doing this, I also touched up all the inline asm to use ABI register aliases and a consistent formatting convention. Also fixed a few places that didn't properly check if the syscall return value should be negated.
Diffstat (limited to 'lib/std/start.zig')
-rw-r--r--lib/std/start.zig26
1 files changed, 14 insertions, 12 deletions
diff --git a/lib/std/start.zig b/lib/std/start.zig
index 60ddae43ac..da880e7803 100644
--- a/lib/std/start.zig
+++ b/lib/std/start.zig
@@ -325,24 +325,26 @@ fn _start() callconv(.naked) noreturn {
\\ jsr (%%pc, %%a0)
,
.mips, .mipsel =>
- \\ move $fp, $0
+ \\ move $fp, $zero
\\ bal 1f
\\ .gpword .
\\ .gpword %[posixCallMainAndExit]
- \\ 1:
+ \\1:
// The `gp` register on MIPS serves a similar purpose to `r2` (ToC pointer) on PPC64.
\\ lw $gp, 0($ra)
+ \\ nop
\\ subu $gp, $ra, $gp
- \\ lw $25, 4($ra)
- \\ addu $25, $25, $gp
- \\ move $ra, $0
+ \\ lw $t9, 4($ra)
+ \\ nop
+ \\ addu $t9, $t9, $gp
+ \\ move $ra, $zero
\\ move $a0, $sp
\\ and $sp, -8
\\ subu $sp, $sp, 16
- \\ jalr $25
+ \\ jalr $t9
,
.mips64, .mips64el =>
- \\ move $fp, $0
+ \\ move $fp, $zero
// This is needed because early MIPS versions don't support misaligned loads. Without
// this directive, the hidden `nop` inserted to fill the delay slot after `bal` would
// cause the two doublewords to be aligned to 4 bytes instead of 8.
@@ -350,17 +352,17 @@ fn _start() callconv(.naked) noreturn {
\\ bal 1f
\\ .gpdword .
\\ .gpdword %[posixCallMainAndExit]
- \\ 1:
+ \\1:
// The `gp` register on MIPS serves a similar purpose to `r2` (ToC pointer) on PPC64.
\\ ld $gp, 0($ra)
\\ dsubu $gp, $ra, $gp
- \\ ld $25, 8($ra)
- \\ daddu $25, $25, $gp
- \\ move $ra, $0
+ \\ ld $t9, 8($ra)
+ \\ daddu $t9, $t9, $gp
+ \\ move $ra, $zero
\\ move $a0, $sp
\\ and $sp, -16
\\ dsubu $sp, $sp, 16
- \\ jalr $25
+ \\ jalr $t9
,
.powerpc, .powerpcle =>
// Set up the initial stack frame, and clear the back chain pointer.