Skip to content

Conversation

@walruscraft
Copy link

@walruscraft walruscraft commented Jan 13, 2026

This adds startup code for powerpc64le (ELF v2 ABI) and mipsel (O32 ABI).

Two new arch modules: powerpc64.rs and mips32.rs. Each one has the usual set: entry point, trap(), dynamic_table_addr(), relocation helpers, thread support, etc.

The tricky part on PowerPC64 is r2 (TOC pointer) setup. On ELF v2, r12 contains the entry point address at program start, and we need to compute r2 from it before touching any global/static data:

addis 2, 12, .TOC. - _start@ha
addi 2, 2, .TOC. - _start@l

Without this, any access to static data gives EFAULT because r2 is garbage. Syscalls use the sc instruction with error indicated by the cr0.SO flag (not negative return like x86).

MIPS uses __start as entry point (MIPS convention). The O32 ABI requires a 16-byte argument save area on the stack, and indirect jumps should go through $t9 for PIC compatibility. Thread pointer is accessed via the userlocal register: rdhwr $3, $29.

I tested with a minimal no_std binary that reads a static variable and exits with code 42. Both architectures work under QEMU user-mode.

I also tested with a larger application (kv) that does file I/O and string formatting. MIPS works fully including argument parsing. PowerPC64 works the same way except for an argv issue - as far as I can tell from various workarounds and debugging, it's the same correct behavior, but there's a QEMU user-mode bug that corrupts the argv array for non-glibc PPC64LE binaries. The argument strings are placed correctly in memory, but the pointer array has NULLs interleaved. This only affects QEMU emulation, not the origin code itself.

Add startup code for powerpc64le (ELFv2 ABI) and mipsel (O32 ABI) targets,
enabling no_std programs to run on these architectures.

PowerPC64 (powerpc64.rs):
- _start sets up r2 (TOC pointer) using r12 before calling entry
- trap() uses the `trap` instruction
- Full thread support scaffolding (clone, thread pointer, TLS)
- Relocation support for PIC binaries

MIPS32 (mips32.rs):
- __start entry point (MIPS convention, not _start)
- 8-byte stack alignment with 16-byte O32 save area
- trap() uses the `break` instruction
- Thread support using rdhwr for thread pointer
- Syscall convention: $v0=syscall#, $a0-$a3=args, $a3=error flag

Both architectures:
- Implement origin-start feature for program startup
- Support optimize_for_size feature
- Follow existing origin patterns from other architectures

Tested with QEMU user-mode emulation (qemu-ppc64le-static, qemu-mipsel-static).
Note: QEMU ppc64le has a bug with argv setup for non-glibc binaries, but
the startup code itself is correct and works on real hardware.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant