| 1 | #include "../mips/elfload.c" |
| 2 | |
| 3 | /* |
| 4 | * mips/elfload.c defines elf_core_copy_regs guarded by #ifndef TARGET_MIPS64. |
| 5 | * |
| 6 | * We must provide the mips64 version here. We cannot use r->pt.regs[] because |
| 7 | * when mips/elfload.c is #include'd above its "#include "target_elf.h"" resolves |
| 8 | * to mips/target_elf.h (compiler searches the including file's directory first), |
| 9 | * which pulls in mips/target_ptrace.h. That struct has pad0[6] before regs[], |
| 10 | * so r->pt.regs[i] writes to reserved[6+i] — offset by 6 from what the kernel |
| 11 | * and glibc expect for the N64 ABI (EPC at reserved[34], not reserved[40]). |
| 12 | * |
| 13 | * Write directly to reserved[] using the mips64 N64 index layout: |
| 14 | * R0-R31 at reserved[0..31], LO at [32], HI at [33], EPC at [34]. |
| 15 | */ |
| 16 | void elf_core_copy_regs(target_elf_gregset_t *r, const CPUMIPSState *env) |
| 17 | { |
| 18 | /* |
| 19 | * linux-user/elfload.c allocates target_elf_prstatus using the |
| 20 | * definition from mips64/target_elf.h, where target_elf_gregset_t |
| 21 | * has target_ulong reserved[45] (8 bytes each = 360 bytes total). |
| 22 | * |
| 23 | * But in this compilation unit, "#include target_elf.h" resolved to |
| 24 | * mips/target_elf.h (wrong directory), so our local target_elf_gregset_t |
| 25 | * has abi_ulong reserved[45] which is only 4 bytes each for mipsn32. |
| 26 | * Using r->reserved[i] would write to the wrong offsets for mipsn32. |
| 27 | * |
| 28 | * Cast to target_ulong * to always write 8-byte entries at the correct |
| 29 | * positions, matching the layout that elfload.c allocated. |
| 30 | */ |
| 31 | target_ulong *regs = (target_ulong *)r; |
| 32 | |
| 33 | /* R0 is always 0; buffer is zero-initialised by the caller */ |
| 34 | for (int i = 1; i < 32; i++) { |
| 35 | regs[i] = tswap64(env->active_tc.gpr[i]); |
| 36 | } |
| 37 | regs[26] = 0; /* k0 */ |
| 38 | regs[27] = 0; /* k1 */ |
| 39 | regs[32] = tswap64(env->active_tc.LO[0]); |
| 40 | regs[33] = tswap64(env->active_tc.HI[0]); |
| 41 | regs[34] = tswap64(env->active_tc.PC); |
| 42 | regs[35] = tswap64(env->CP0_BadVAddr); |
| 43 | regs[36] = tswap64(env->CP0_Status); |
| 44 | regs[37] = tswap64(env->CP0_Cause); |
| 45 | } |