| ... | @@ -272,6 +272,12 @@ fn _start() callconv(.Naked) noreturn { | ... | @@ -272,6 +272,12 @@ fn _start() callconv(.Naked) noreturn { |
| 272 | : [tos] "={rax}" (-> *std.os.plan9.Tos), | 272 | : [tos] "={rax}" (-> *std.os.plan9.Tos), |
| 273 | ); | 273 | ); |
| 274 | } | 274 | } |
| | 275 | |
| | 276 | // Note that we maintain a very low level of trust with regards to ABI guarantees at this point. |
| | 277 | // We will redundantly align the stack, clear the link register, etc. While e.g. the Linux |
| | 278 | // kernel is usually good about upholding the ABI guarantees, the same cannot be said of dynamic |
| | 279 | // linkers; musl's ldso, for example, opts to not align the stack when invoking the dynamic |
| | 280 | // linker explicitly. |
| 275 | asm volatile (switch (native_arch) { | 281 | asm volatile (switch (native_arch) { |
| 276 | .x86_64 => | 282 | .x86_64 => |
| 277 | \\ xorl %%ebp, %%ebp | 283 | \\ xorl %%ebp, %%ebp |
| ... | @@ -291,6 +297,7 @@ fn _start() callconv(.Naked) noreturn { | ... | @@ -291,6 +297,7 @@ fn _start() callconv(.Naked) noreturn { |
| 291 | \\ mov fp, #0 | 297 | \\ mov fp, #0 |
| 292 | \\ mov lr, #0 | 298 | \\ mov lr, #0 |
| 293 | \\ mov x0, sp | 299 | \\ mov x0, sp |
| | 300 | \\ and sp, x0, #-16 |
| 294 | \\ b %[posixCallMainAndExit] | 301 | \\ b %[posixCallMainAndExit] |
| 295 | , | 302 | , |
| 296 | .arm, .armeb, .thumb, .thumbeb => | 303 | .arm, .armeb, .thumb, .thumbeb => |
| ... | @@ -322,30 +329,23 @@ fn _start() callconv(.Naked) noreturn { | ... | @@ -322,30 +329,23 @@ fn _start() callconv(.Naked) noreturn { |
| 322 | \\ jsr (%%pc, %%a0) | 329 | \\ jsr (%%pc, %%a0) |
| 323 | , | 330 | , |
| 324 | .mips, .mipsel => | 331 | .mips, .mipsel => |
| 325 | // The lr is already zeroed on entry, as specified by the ABI. | 332 | \\ move $fp, $0 |
| 326 | \\ addiu $fp, $zero, 0 | 333 | \\ move $ra, $0 |
| 327 | \\ move $a0, $sp | 334 | \\ move $a0, $sp |
| 328 | \\ .set push | 335 | \\ and $sp, -8 |
| 329 | \\ .set noat | | |
| 330 | \\ addiu $1, $zero, -16 | | |
| 331 | \\ and $sp, $sp, $1 | | |
| 332 | \\ .set pop | | |
| 333 | \\ j %[posixCallMainAndExit] | 336 | \\ j %[posixCallMainAndExit] |
| 334 | , | 337 | , |
| 335 | .mips64, .mips64el => | 338 | .mips64, .mips64el => |
| 336 | // The lr is already zeroed on entry, as specified by the ABI. | 339 | \\ move $fp, $0 |
| 337 | \\ addiu $fp, $zero, 0 | 340 | \\ move $ra, $0 |
| 338 | \\ move $a0, $sp | 341 | \\ move $a0, $sp |
| 339 | \\ .set push | 342 | \\ and $sp, -16 |
| 340 | \\ .set noat | | |
| 341 | \\ daddiu $1, $zero, -16 | | |
| 342 | \\ and $sp, $sp, $1 | | |
| 343 | \\ .set pop | | |
| 344 | \\ j %[posixCallMainAndExit] | 343 | \\ j %[posixCallMainAndExit] |
| 345 | , | 344 | , |
| 346 | .powerpc, .powerpcle => | 345 | .powerpc, .powerpcle => |
| 347 | // Setup the initial stack frame and clear the back chain pointer. | 346 | // Set up the initial stack frame, and clear the back chain pointer. |
| 348 | \\ mr 3, 1 | 347 | \\ mr 3, 1 |
| | 348 | \\ clrrwi 1, 1, 4 |
| 349 | \\ li 0, 0 | 349 | \\ li 0, 0 |
| 350 | \\ stwu 1, -16(1) | 350 | \\ stwu 1, -16(1) |
| 351 | \\ stw 0, 0(1) | 351 | \\ stw 0, 0(1) |
| ... | @@ -353,7 +353,7 @@ fn _start() callconv(.Naked) noreturn { | ... | @@ -353,7 +353,7 @@ fn _start() callconv(.Naked) noreturn { |
| 353 | \\ b %[posixCallMainAndExit] | 353 | \\ b %[posixCallMainAndExit] |
| 354 | , | 354 | , |
| 355 | .powerpc64, .powerpc64le => | 355 | .powerpc64, .powerpc64le => |
| 356 | // Setup the initial stack frame and clear the back chain pointer. | 356 | // Set up the ToC and initial stack frame, and clear the back chain pointer. |
| 357 | \\ addis 2, 12, .TOC. - %[_start]@ha | 357 | \\ addis 2, 12, .TOC. - %[_start]@ha |
| 358 | \\ addi 2, 2, .TOC. - %[_start]@l | 358 | \\ addi 2, 2, .TOC. - %[_start]@l |
| 359 | \\ mr 3, 1 | 359 | \\ mr 3, 1 |
| ... | @@ -365,18 +365,22 @@ fn _start() callconv(.Naked) noreturn { | ... | @@ -365,18 +365,22 @@ fn _start() callconv(.Naked) noreturn { |
| 365 | , | 365 | , |
| 366 | .s390x => | 366 | .s390x => |
| 367 | // Set up the stack frame (register save area and cleared back-chain slot). | 367 | // Set up the stack frame (register save area and cleared back-chain slot). |
| 368 | // Note: Stack pointer is guaranteed by ABI to be 8-byte aligned as required. | 368 | \\ lgr %%r2, %%r15 |
| 369 | \\ lgr %r2, %r15 | 369 | \\ lghi %%r0, -16 |
| 370 | \\ aghi %r15, -160 | 370 | \\ ngr %%r15, %%r0 |
| 371 | \\ lghi %r0, 0 | 371 | \\ aghi %%r15, -160 |
| 372 | \\ stg %r0, 0(%r15) | 372 | \\ lghi %%r0, 0 |
| | 373 | \\ stg %%r0, 0(%%r15) |
| 373 | \\ jg %[posixCallMainAndExit] | 374 | \\ jg %[posixCallMainAndExit] |
| 374 | , | 375 | , |
| 375 | .sparc64 => | 376 | .sparc64 => |
| 376 | // argc is stored after a register window (16 registers) plus stack bias | 377 | // argc is stored after a register window (16 registers * 8 bytes) plus the stack bias |
| 377 | \\ mov %%g0, %%i6 | 378 | // (2047 bytes). |
| 378 | \\ add %%o6, 2175, %%l0 | 379 | \\ mov %%g0, %%fp |
| 379 | \\ mov %%l0, %%o0 | 380 | \\ add %%sp, 2175, %%o0 |
| | 381 | \\ add %%sp, 2047, %%sp |
| | 382 | \\ and %%sp, -16, %%sp |
| | 383 | \\ sub %%sp, 2047, %%sp |
| 380 | \\ ba,a %[posixCallMainAndExit] | 384 | \\ ba,a %[posixCallMainAndExit] |
| 381 | , | 385 | , |
| 382 | else => @compileError("unsupported arch"), | 386 | else => @compileError("unsupported arch"), |