| 1 | /* SPDX-License-Identifier: GPL-2.0-or-later */ |
| 2 | |
| 3 | #include "qemu/osdep.h" |
| 4 | #include "qemu.h" |
| 5 | #include "loader.h" |
| 6 | #include "elf.h" |
| 7 | #include "target_elf.h" |
| 8 | |
| 9 | |
| 10 | void elf_core_copy_regs(target_elf_gregset_t *r, const CPUArchState *env) |
| 11 | { |
| 12 | CPUSPARCState *e = (CPUSPARCState *)env; |
| 13 | int i; |
| 14 | |
| 15 | memset(r, 0, sizeof(*r)); |
| 16 | |
| 17 | #if defined(TARGET_SPARC64) && !defined(TARGET_ABI32) |
| 18 | /* Linux kernel layout for sparc64 (arch/sparc/include/asm/elf_64.h): |
| 19 | * [0..7] G0-G7 |
| 20 | * [8..15] O0-O7 |
| 21 | * [16..23] L0-L7 |
| 22 | * [24..31] I0-I7 |
| 23 | * [32] TSTATE |
| 24 | * [33] TPC |
| 25 | * [34] TNPC |
| 26 | * [35] Y |
| 27 | */ |
| 28 | for (i = 0; i < 8; i++) { |
| 29 | r->regs[i] = tswap64(env->gregs[i]); |
| 30 | r->regs[8 + i] = tswap64(env->regwptr[WREG_O0 + i]); |
| 31 | r->regs[16 + i] = tswap64(env->regwptr[WREG_L0 + i]); |
| 32 | r->regs[24 + i] = tswap64(env->regwptr[WREG_I0 + i]); |
| 33 | } |
| 34 | r->regs[32] = tswap64(sparc64_tstate(e)); |
| 35 | r->regs[33] = tswap64(env->pc); |
| 36 | r->regs[34] = tswap64(env->npc); |
| 37 | r->regs[35] = tswap64(env->y); |
| 38 | #else |
| 39 | /* Linux kernel layout for sparc32 (arch/sparc/include/asm/elf_32.h): |
| 40 | * [0] PSR |
| 41 | * [1] PC |
| 42 | * [2] NPC |
| 43 | * [3] Y |
| 44 | * [4..11] G0-G7 |
| 45 | * [12..19] O0-O7 |
| 46 | * [20..27] L0-L7 |
| 47 | * [28..35] I0-I7 |
| 48 | * [36..37] reserved (stack_check) |
| 49 | */ |
| 50 | r->regs[0] = tswap32(cpu_get_psr(e)); |
| 51 | r->regs[1] = tswap32(env->pc); |
| 52 | r->regs[2] = tswap32(env->npc); |
| 53 | r->regs[3] = tswap32(env->y); |
| 54 | for (i = 0; i < 8; i++) { |
| 55 | r->regs[4 + i] = tswap32(env->gregs[i]); |
| 56 | r->regs[12 + i] = tswap32(env->regwptr[WREG_O0 + i]); |
| 57 | r->regs[20 + i] = tswap32(env->regwptr[WREG_L0 + i]); |
| 58 | r->regs[28 + i] = tswap32(env->regwptr[WREG_I0 + i]); |
| 59 | } |
| 60 | #endif |
| 61 | } |
| 62 | |
| 63 | const char *get_elf_cpu_model(uint32_t eflags) |
| 64 | { |
| 65 | #ifdef TARGET_SPARC64 |
| 66 | return "TI UltraSparc II"; |
| 67 | #else |
| 68 | return "Fujitsu MB86904"; |
| 69 | #endif |
| 70 | } |
| 71 | |
| 72 | abi_ulong get_elf_hwcap(CPUState *cs) |
| 73 | { |
| 74 | /* There are not many sparc32 hwcap bits -- we have all of them. */ |
| 75 | uint32_t r = HWCAP_SPARC_FLUSH | HWCAP_SPARC_STBAR | |
| 76 | HWCAP_SPARC_SWAP | HWCAP_SPARC_MULDIV; |
| 77 | |
| 78 | #ifdef TARGET_SPARC64 |
| 79 | CPUSPARCState *env = cpu_env(cs); |
| 80 | uint32_t features = env->def.features; |
| 81 | |
| 82 | r |= HWCAP_SPARC_V9 | HWCAP_SPARC_V8PLUS; |
| 83 | /* 32x32 multiply and divide are efficient. */ |
| 84 | r |= HWCAP_SPARC_MUL32 | HWCAP_SPARC_DIV32; |
| 85 | /* We don't have an internal feature bit for this. */ |
| 86 | r |= HWCAP_SPARC_POPC; |
| 87 | r |= features & CPU_FEATURE_FSMULD ? HWCAP_SPARC_FSMULD : 0; |
| 88 | r |= features & CPU_FEATURE_VIS1 ? HWCAP_SPARC_VIS : 0; |
| 89 | r |= features & CPU_FEATURE_VIS2 ? HWCAP_SPARC_VIS2 : 0; |
| 90 | r |= features & CPU_FEATURE_FMAF ? HWCAP_SPARC_FMAF : 0; |
| 91 | r |= features & CPU_FEATURE_VIS3 ? HWCAP_SPARC_VIS3 : 0; |
| 92 | r |= features & CPU_FEATURE_IMA ? HWCAP_SPARC_IMA : 0; |
| 93 | #endif |
| 94 | |
| 95 | return r; |
| 96 | } |