Upstream: https://gitlab.com/qemu-project/qemu.git Upstream-Commit: d2e570cc0f97b936902a5b1b86b73c0f5998b475
97 lines
2.8 KiB
C
97 lines
2.8 KiB
C
/* SPDX-License-Identifier: GPL-2.0-or-later */
|
|
|
|
#include "qemu/osdep.h"
|
|
#include "qemu.h"
|
|
#include "loader.h"
|
|
#include "elf.h"
|
|
#include "target_elf.h"
|
|
|
|
|
|
void elf_core_copy_regs(target_elf_gregset_t *r, const CPUArchState *env)
|
|
{
|
|
CPUSPARCState *e = (CPUSPARCState *)env;
|
|
int i;
|
|
|
|
memset(r, 0, sizeof(*r));
|
|
|
|
#if defined(TARGET_SPARC64) && !defined(TARGET_ABI32)
|
|
/* Linux kernel layout for sparc64 (arch/sparc/include/asm/elf_64.h):
|
|
* [0..7] G0-G7
|
|
* [8..15] O0-O7
|
|
* [16..23] L0-L7
|
|
* [24..31] I0-I7
|
|
* [32] TSTATE
|
|
* [33] TPC
|
|
* [34] TNPC
|
|
* [35] Y
|
|
*/
|
|
for (i = 0; i < 8; i++) {
|
|
r->regs[i] = tswap64(env->gregs[i]);
|
|
r->regs[8 + i] = tswap64(env->regwptr[WREG_O0 + i]);
|
|
r->regs[16 + i] = tswap64(env->regwptr[WREG_L0 + i]);
|
|
r->regs[24 + i] = tswap64(env->regwptr[WREG_I0 + i]);
|
|
}
|
|
r->regs[32] = tswap64(sparc64_tstate(e));
|
|
r->regs[33] = tswap64(env->pc);
|
|
r->regs[34] = tswap64(env->npc);
|
|
r->regs[35] = tswap64(env->y);
|
|
#else
|
|
/* Linux kernel layout for sparc32 (arch/sparc/include/asm/elf_32.h):
|
|
* [0] PSR
|
|
* [1] PC
|
|
* [2] NPC
|
|
* [3] Y
|
|
* [4..11] G0-G7
|
|
* [12..19] O0-O7
|
|
* [20..27] L0-L7
|
|
* [28..35] I0-I7
|
|
* [36..37] reserved (stack_check)
|
|
*/
|
|
r->regs[0] = tswap32(cpu_get_psr(e));
|
|
r->regs[1] = tswap32(env->pc);
|
|
r->regs[2] = tswap32(env->npc);
|
|
r->regs[3] = tswap32(env->y);
|
|
for (i = 0; i < 8; i++) {
|
|
r->regs[4 + i] = tswap32(env->gregs[i]);
|
|
r->regs[12 + i] = tswap32(env->regwptr[WREG_O0 + i]);
|
|
r->regs[20 + i] = tswap32(env->regwptr[WREG_L0 + i]);
|
|
r->regs[28 + i] = tswap32(env->regwptr[WREG_I0 + i]);
|
|
}
|
|
#endif
|
|
}
|
|
|
|
const char *get_elf_cpu_model(uint32_t eflags)
|
|
{
|
|
#ifdef TARGET_SPARC64
|
|
return "TI UltraSparc II";
|
|
#else
|
|
return "Fujitsu MB86904";
|
|
#endif
|
|
}
|
|
|
|
abi_ulong get_elf_hwcap(CPUState *cs)
|
|
{
|
|
/* There are not many sparc32 hwcap bits -- we have all of them. */
|
|
uint32_t r = HWCAP_SPARC_FLUSH | HWCAP_SPARC_STBAR |
|
|
HWCAP_SPARC_SWAP | HWCAP_SPARC_MULDIV;
|
|
|
|
#ifdef TARGET_SPARC64
|
|
CPUSPARCState *env = cpu_env(cs);
|
|
uint32_t features = env->def.features;
|
|
|
|
r |= HWCAP_SPARC_V9 | HWCAP_SPARC_V8PLUS;
|
|
/* 32x32 multiply and divide are efficient. */
|
|
r |= HWCAP_SPARC_MUL32 | HWCAP_SPARC_DIV32;
|
|
/* We don't have an internal feature bit for this. */
|
|
r |= HWCAP_SPARC_POPC;
|
|
r |= features & CPU_FEATURE_FSMULD ? HWCAP_SPARC_FSMULD : 0;
|
|
r |= features & CPU_FEATURE_VIS1 ? HWCAP_SPARC_VIS : 0;
|
|
r |= features & CPU_FEATURE_VIS2 ? HWCAP_SPARC_VIS2 : 0;
|
|
r |= features & CPU_FEATURE_FMAF ? HWCAP_SPARC_FMAF : 0;
|
|
r |= features & CPU_FEATURE_VIS3 ? HWCAP_SPARC_VIS3 : 0;
|
|
r |= features & CPU_FEATURE_IMA ? HWCAP_SPARC_IMA : 0;
|
|
#endif
|
|
|
|
return r;
|
|
}
|