[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: [Qemu-devel] [PATCH 03/12] ARM: Prepare translation for AArch64 code
From: |
Alexander Graf |
Subject: |
Re: [Qemu-devel] [PATCH 03/12] ARM: Prepare translation for AArch64 code |
Date: |
Wed, 6 Mar 2013 10:36:50 +0100 |
Am 06.03.2013 um 08:11 schrieb Laurent Desnogues <address@hidden>:
> On Wed, Mar 6, 2013 at 3:01 AM, Alexander Graf <address@hidden> wrote:
>> This patch adds all the prerequisites for AArch64 support that didn't
>> fit into split up patches. It extends important bits in the core cpu
>> headers to also take AArch64 mode into account.
>>
>> Signed-off-by: Alexander Graf <address@hidden>
>> ---
>> include/elf.h | 2 +
>> target-arm/cpu.h | 103
>> ++++++++++++++++++++++++++++++++++++------------
>> target-arm/translate.c | 42 +++++++++++--------
>> 3 files changed, 103 insertions(+), 44 deletions(-)
>>
>> diff --git a/include/elf.h b/include/elf.h
>> index a21ea53..0ff0ea6 100644
>> --- a/include/elf.h
>> +++ b/include/elf.h
>> @@ -109,6 +109,8 @@ typedef int64_t Elf64_Sxword;
>> #define EM_OPENRISC 92 /* OpenCores OpenRISC */
>>
>> #define EM_UNICORE32 110 /* UniCore32 */
>> +#define EM_AARCH64 183 /* ARM 64-bit architecture */
>> +
>>
>> /*
>> * This is an interim value that we will use until the committee comes
>> diff --git a/target-arm/cpu.h b/target-arm/cpu.h
>> index c28a0d9..ec292c9 100644
>> --- a/target-arm/cpu.h
>> +++ b/target-arm/cpu.h
>> @@ -19,13 +19,19 @@
>> #ifndef CPU_ARM_H
>> #define CPU_ARM_H
>>
>> -#define TARGET_LONG_BITS 32
>> +#include "config.h"
>>
>> -#define ELF_MACHINE EM_ARM
>> +#if defined (TARGET_ARM64)
>> + /* AArch64 definitions */
>> +# define TARGET_LONG_BITS 64
>> +# define ELF_MACHINE EM_AARCH64
>> +#else
>> +# define TARGET_LONG_BITS 32
>> +# define ELF_MACHINE EM_ARM
>> +#endif
>>
>> #define CPUArchState struct CPUARMState
>>
>> -#include "config.h"
>> #include "qemu-common.h"
>> #include "exec/cpu-defs.h"
>>
>> @@ -79,6 +85,13 @@ struct arm_boot_info;
>> typedef struct CPUARMState {
>> /* Regs for current mode. */
>> uint32_t regs[16];
>> +
>> + /* Regs for A64 mode. */
>> + uint64_t xregs[32];
>
> I'm not sure it makes sense to allocate space for xregs[31].
> If it is the zero register then you would anyway have special
> cases in translation code to discard writes to reg 31 and so
> it could be argued you could also special case reads from
> reg 31 (and you should so that the optimizer knows it's zero).
>
> Perhaps you could use xregs[31] as SP, which after all is
> a more "regular" register than xzr.
Sp is a separate env field in my patch set. So yeah, I should just drop
xregs[31] and always special case it I suppose. That's the best way to avoid
accidents I hope :)
Alex
>
>
> Laurent
>
>> + uint64_t pc;
>> + uint64_t sp;
>> + uint32_t pstate;
>> +
>> /* Frequently accessed CPSR bits are stored separately for efficiency.
>> This contains all the other bits. Use cpsr_{read,write} to access
>> the whole CPSR. */
>> @@ -154,6 +167,11 @@ typedef struct CPUARMState {
>> uint32_t c15_power_control; /* power control */
>> } cp15;
>>
>> + /* System registers (AArch64) */
>> + struct {
>> + uint64_t tpidr_el0;
>> + } sr;
>> +
>> struct {
>> uint32_t other_sp;
>> uint32_t vecbase;
>> @@ -170,7 +188,7 @@ typedef struct CPUARMState {
>>
>> /* VFP coprocessor state. */
>> struct {
>> - float64 regs[32];
>> + float64 regs[64];
>>
>> uint32_t xregs[16];
>> /* We store these fpcsr fields separately for convenience. */
>> @@ -241,6 +259,24 @@ int bank_number(int mode);
>> void switch_mode(CPUARMState *, int);
>> uint32_t do_arm_semihosting(CPUARMState *env);
>>
>> +static inline bool is_a64(CPUARMState *env)
>> +{
>> +#ifdef TARGET_ARM64
>> + return true;
>> +#else
>> + return false;
>> +#endif
>> +}
>> +
>> +#define PSTATE_N_SHIFT 3
>> +#define PSTATE_N (1 << PSTATE_N_SHIFT)
>> +#define PSTATE_Z_SHIFT 2
>> +#define PSTATE_Z (1 << PSTATE_Z_SHIFT)
>> +#define PSTATE_C_SHIFT 1
>> +#define PSTATE_C (1 << PSTATE_C_SHIFT)
>> +#define PSTATE_V_SHIFT 0
>> +#define PSTATE_V (1 << PSTATE_V_SHIFT)
>> +
>> /* you can call this signal handler from your SIGBUS and SIGSEGV
>> signal handlers to inform the virtual CPU of exceptions. non zero
>> is returned if the signal was handled by the virtual CPU. */
>> @@ -624,8 +660,13 @@ static inline bool cp_access_ok(CPUARMState *env,
>> #define TARGET_PAGE_BITS 10
>> #endif
>>
>> -#define TARGET_PHYS_ADDR_SPACE_BITS 40
>> -#define TARGET_VIRT_ADDR_SPACE_BITS 32
>> +#if defined (TARGET_ARM64)
>> +# define TARGET_PHYS_ADDR_SPACE_BITS 64
>> +# define TARGET_VIRT_ADDR_SPACE_BITS 64
>> +#else
>> +# define TARGET_PHYS_ADDR_SPACE_BITS 40
>> +# define TARGET_VIRT_ADDR_SPACE_BITS 32
>> +#endif
>>
>> static inline CPUARMState *cpu_init(const char *cpu_model)
>> {
>> @@ -699,25 +740,31 @@ static inline void cpu_clone_regs(CPUARMState *env,
>> target_ulong newsp)
>> static inline void cpu_get_tb_cpu_state(CPUARMState *env, target_ulong *pc,
>> target_ulong *cs_base, int *flags)
>> {
>> - int privmode;
>> - *pc = env->regs[15];
>> - *cs_base = 0;
>> - *flags = (env->thumb << ARM_TBFLAG_THUMB_SHIFT)
>> - | (env->vfp.vec_len << ARM_TBFLAG_VECLEN_SHIFT)
>> - | (env->vfp.vec_stride << ARM_TBFLAG_VECSTRIDE_SHIFT)
>> - | (env->condexec_bits << ARM_TBFLAG_CONDEXEC_SHIFT)
>> - | (env->bswap_code << ARM_TBFLAG_BSWAP_CODE_SHIFT);
>> - if (arm_feature(env, ARM_FEATURE_M)) {
>> - privmode = !((env->v7m.exception == 0) && (env->v7m.control & 1));
>> + if (is_a64(env)) {
>> + *pc = env->pc;
>> + *flags = 0;
>> } else {
>> - privmode = (env->uncached_cpsr & CPSR_M) != ARM_CPU_MODE_USR;
>> - }
>> - if (privmode) {
>> - *flags |= ARM_TBFLAG_PRIV_MASK;
>> - }
>> - if (env->vfp.xregs[ARM_VFP_FPEXC] & (1 << 30)) {
>> - *flags |= ARM_TBFLAG_VFPEN_MASK;
>> + int privmode;
>> + *pc = env->regs[15];
>> + *flags = (env->thumb << ARM_TBFLAG_THUMB_SHIFT)
>> + | (env->vfp.vec_len << ARM_TBFLAG_VECLEN_SHIFT)
>> + | (env->vfp.vec_stride << ARM_TBFLAG_VECSTRIDE_SHIFT)
>> + | (env->condexec_bits << ARM_TBFLAG_CONDEXEC_SHIFT)
>> + | (env->bswap_code << ARM_TBFLAG_BSWAP_CODE_SHIFT);
>> + if (arm_feature(env, ARM_FEATURE_M)) {
>> + privmode = !((env->v7m.exception == 0) && (env->v7m.control &
>> 1));
>> + } else {
>> + privmode = (env->uncached_cpsr & CPSR_M) != ARM_CPU_MODE_USR;
>> + }
>> + if (privmode) {
>> + *flags |= ARM_TBFLAG_PRIV_MASK;
>> + }
>> + if (env->vfp.xregs[ARM_VFP_FPEXC] & (1 << 30)) {
>> + *flags |= ARM_TBFLAG_VFPEN_MASK;
>> + }
>> }
>> +
>> + *cs_base = 0;
>> }
>>
>> static inline bool cpu_has_work(CPUState *cpu)
>> @@ -732,11 +779,15 @@ static inline bool cpu_has_work(CPUState *cpu)
>>
>> static inline void cpu_pc_from_tb(CPUARMState *env, TranslationBlock *tb)
>> {
>> - env->regs[15] = tb->pc;
>> + if (is_a64(env)) {
>> + env->pc = tb->pc;
>> + } else {
>> + env->regs[15] = tb->pc;
>> + }
>> }
>>
>> /* Load an instruction and return it in the standard little-endian order */
>> -static inline uint32_t arm_ldl_code(CPUARMState *env, uint32_t addr,
>> +static inline uint32_t arm_ldl_code(CPUARMState *env, target_ulong addr,
>> bool do_swap)
>> {
>> uint32_t insn = cpu_ldl_code(env, addr);
>> @@ -747,7 +798,7 @@ static inline uint32_t arm_ldl_code(CPUARMState *env,
>> uint32_t addr,
>> }
>>
>> /* Ditto, for a halfword (Thumb) instruction */
>> -static inline uint16_t arm_lduw_code(CPUARMState *env, uint32_t addr,
>> +static inline uint16_t arm_lduw_code(CPUARMState *env, target_ulong addr,
>> bool do_swap)
>> {
>> uint16_t insn = cpu_lduw_code(env, addr);
>> diff --git a/target-arm/translate.c b/target-arm/translate.c
>> index f8838f3..de04a0c 100644
>> --- a/target-arm/translate.c
>> +++ b/target-arm/translate.c
>> @@ -9749,7 +9749,7 @@ static inline void
>> gen_intermediate_code_internal(CPUARMState *env,
>> uint16_t *gen_opc_end;
>> int j, lj;
>> target_ulong pc_start;
>> - uint32_t next_page_start;
>> + target_ulong next_page_start;
>> int num_insns;
>> int max_insns;
>>
>> @@ -9833,24 +9833,26 @@ static inline void
>> gen_intermediate_code_internal(CPUARMState *env,
>> store_cpu_field(tmp, condexec_bits);
>> }
>> do {
>> + if (!is_a64(env)) {
>> #ifdef CONFIG_USER_ONLY
>> - /* Intercept jump to the magic kernel page. */
>> - if (dc->pc >= 0xffff0000) {
>> - /* We always get here via a jump, so know we are not in a
>> - conditional execution block. */
>> - gen_exception(EXCP_KERNEL_TRAP);
>> - dc->is_jmp = DISAS_UPDATE;
>> - break;
>> - }
>> + /* Intercept jump to the magic kernel page. */
>> + if (dc->pc >= 0xffff0000) {
>> + /* We always get here via a jump, so know we are not in a
>> + conditional execution block. */
>> + gen_exception(EXCP_KERNEL_TRAP);
>> + dc->is_jmp = DISAS_UPDATE;
>> + break;
>> + }
>> #else
>> - if (dc->pc >= 0xfffffff0 && IS_M(env)) {
>> - /* We always get here via a jump, so know we are not in a
>> - conditional execution block. */
>> - gen_exception(EXCP_EXCEPTION_EXIT);
>> - dc->is_jmp = DISAS_UPDATE;
>> - break;
>> - }
>> + if (dc->pc >= 0xfffffff0 && IS_M(env)) {
>> + /* We always get here via a jump, so know we are not in a
>> + conditional execution block. */
>> + gen_exception(EXCP_EXCEPTION_EXIT);
>> + dc->is_jmp = DISAS_UPDATE;
>> + break;
>> + }
>> #endif
>> + }
>>
>> if (unlikely(!QTAILQ_EMPTY(&env->breakpoints))) {
>> QTAILQ_FOREACH(bp, &env->breakpoints, entry) {
>> @@ -9904,7 +9906,7 @@ static inline void
>> gen_intermediate_code_internal(CPUARMState *env,
>> }
>>
>> if (tcg_check_temp_count()) {
>> - fprintf(stderr, "TCG temporary leak before %08x\n", dc->pc);
>> + fprintf(stderr, "TCG temporary leak before "TARGET_FMT_lx"\n",
>> dc->pc);
>> }
>>
>> /* Translation stops when a conditional branch is encountered.
>> @@ -10074,6 +10076,10 @@ void cpu_dump_state(CPUARMState *env, FILE *f,
>> fprintf_function cpu_fprintf,
>>
>> void restore_state_to_opc(CPUARMState *env, TranslationBlock *tb, int pc_pos)
>> {
>> - env->regs[15] = tcg_ctx.gen_opc_pc[pc_pos];
>> + if (is_a64(env)) {
>> + env->pc = tcg_ctx.gen_opc_pc[pc_pos];
>> + } else {
>> + env->regs[15] = tcg_ctx.gen_opc_pc[pc_pos];
>> + }
>> env->condexec_bits = gen_opc_condexec_bits[pc_pos];
>> }
>> --
>> 1.6.0.2
>>
>>
- [Qemu-devel] [PATCH 00/12] AArch64 preparation patch set, Alexander Graf, 2013/03/05
- [Qemu-devel] [PATCH 12/12] ARM: Add arm64 target to configure, Alexander Graf, 2013/03/05
- [Qemu-devel] [PATCH 02/12] ARM: Export cpu_env, Alexander Graf, 2013/03/05
- [Qemu-devel] [PATCH 09/12] linux-user: Fix up AArch64 syscall handlers, Alexander Graf, 2013/03/05
- [Qemu-devel] [PATCH 03/12] ARM: Prepare translation for AArch64 code, Alexander Graf, 2013/03/05
- Re: [Qemu-devel] [PATCH 03/12] ARM: Prepare translation for AArch64 code, Peter Maydell, 2013/03/07
- [Qemu-devel] [PATCH 05/12] AArch64: Add gdb stub, Alexander Graf, 2013/03/05
- [Qemu-devel] [PATCH 07/12] linux-user: AArch64 requires at least 3.8.0, Alexander Graf, 2013/03/05
- [Qemu-devel] [PATCH 11/12] linux-user: Add AArch64 support, Alexander Graf, 2013/03/05
- [Qemu-devel] [PATCH 01/12] ARM: Extract the disas struct to a header file, Alexander Graf, 2013/03/05
- [Qemu-devel] [PATCH 06/12] linux-user: Don't treat aarch64 cpu names specially, Alexander Graf, 2013/03/05
- [Qemu-devel] [PATCH 08/12] linux-user: Add syscall handling for AArch64, Alexander Graf, 2013/03/05
- [Qemu-devel] [PATCH 10/12] linux-user: Add signal handling for AArch64, Alexander Graf, 2013/03/05