Am 06.03.2013 um 08:11 schrieb Laurent Desnogues <laurent.desnog...@gmail.com>:
> On Wed, Mar 6, 2013 at 3:01 AM, Alexander Graf <ag...@suse.de> 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 <ag...@suse.de> >> --- >> 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 >> >>