On 30.04.2013, at 08:36, John Rigby wrote: > From: Alexander Graf <ag...@suse.de> > > 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. > > Add new ARM_TBFLAG_AARCH64_STATE flag that indicates an ARMv8 cpu > running in aarch64 mode vs aarch32 mode. > > Signed-off-by: Alexander Graf <ag...@suse.de> > Signed-off-by: John Rigby <john.ri...@linaro.org> > --- > Changes in v2: > - remove many uses of is_a64 as that is a indicator the target arch is > aarch64 not what mode it is running in.
It indicates what mode the CPU is running on. The only reason it was defined statically so far, was that linux-user was the only target I implemented. And that one can't switch during runtime. Alex > - add ARM_TBFLAG_AARCH64_STATE and aarch64_state > > include/elf.h | 2 + > target-arm/cpu.h | 138 ++++++++++++++++++++++++++++++++++-------------- > target-arm/translate.c | 14 +++-- > 3 files changed, 108 insertions(+), 46 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 5438444..3a79dfa 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_AARCH64) > + /* 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,14 @@ struct arm_boot_info; > typedef struct CPUARMState { > /* Regs for current mode. */ > uint32_t regs[16]; > + > + /* Regs for A64 mode. */ > + uint64_t xregs[31]; > + uint64_t pc; > + uint64_t sp; > + uint32_t pstate; > + uint32_t aarch64_state; /* 1 if CPU is in aarch64 state */ > + > /* 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 +168,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 +189,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. */ > @@ -240,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_AARCH64 > + 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. */ > @@ -623,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_AARCH64) > +# 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) > { > @@ -661,21 +703,23 @@ static inline void cpu_clone_regs(CPUARMState *env, > target_ulong newsp) > #include "exec/cpu-all.h" > > /* Bit usage in the TB flags field: */ > -#define ARM_TBFLAG_THUMB_SHIFT 0 > -#define ARM_TBFLAG_THUMB_MASK (1 << ARM_TBFLAG_THUMB_SHIFT) > -#define ARM_TBFLAG_VECLEN_SHIFT 1 > -#define ARM_TBFLAG_VECLEN_MASK (0x7 << ARM_TBFLAG_VECLEN_SHIFT) > -#define ARM_TBFLAG_VECSTRIDE_SHIFT 4 > -#define ARM_TBFLAG_VECSTRIDE_MASK (0x3 << ARM_TBFLAG_VECSTRIDE_SHIFT) > -#define ARM_TBFLAG_PRIV_SHIFT 6 > -#define ARM_TBFLAG_PRIV_MASK (1 << ARM_TBFLAG_PRIV_SHIFT) > -#define ARM_TBFLAG_VFPEN_SHIFT 7 > -#define ARM_TBFLAG_VFPEN_MASK (1 << ARM_TBFLAG_VFPEN_SHIFT) > -#define ARM_TBFLAG_CONDEXEC_SHIFT 8 > -#define ARM_TBFLAG_CONDEXEC_MASK (0xff << ARM_TBFLAG_CONDEXEC_SHIFT) > -#define ARM_TBFLAG_BSWAP_CODE_SHIFT 16 > -#define ARM_TBFLAG_BSWAP_CODE_MASK (1 << ARM_TBFLAG_BSWAP_CODE_SHIFT) > -/* Bits 31..17 are currently unused. */ > +#define ARM_TBFLAG_THUMB_SHIFT 0 > +#define ARM_TBFLAG_THUMB_MASK (1 << ARM_TBFLAG_THUMB_SHIFT) > +#define ARM_TBFLAG_VECLEN_SHIFT 1 > +#define ARM_TBFLAG_VECLEN_MASK (0x7 << ARM_TBFLAG_VECLEN_SHIFT) > +#define ARM_TBFLAG_VECSTRIDE_SHIFT 4 > +#define ARM_TBFLAG_VECSTRIDE_MASK (0x3 << ARM_TBFLAG_VECSTRIDE_SHIFT) > +#define ARM_TBFLAG_PRIV_SHIFT 6 > +#define ARM_TBFLAG_PRIV_MASK (1 << ARM_TBFLAG_PRIV_SHIFT) > +#define ARM_TBFLAG_VFPEN_SHIFT 7 > +#define ARM_TBFLAG_VFPEN_MASK (1 << ARM_TBFLAG_VFPEN_SHIFT) > +#define ARM_TBFLAG_CONDEXEC_SHIFT 8 > +#define ARM_TBFLAG_CONDEXEC_MASK (0xff << ARM_TBFLAG_CONDEXEC_SHIFT) > +#define ARM_TBFLAG_BSWAP_CODE_SHIFT 16 > +#define ARM_TBFLAG_BSWAP_CODE_MASK (1 << ARM_TBFLAG_BSWAP_CODE_SHIFT) > +#define ARM_TBFLAG_AARCH64_STATE_SHIFT 17 > +#define ARM_TBFLAG_AARCH64_STATE_MASK (1 << ARM_TBFLAG_AARCH64_STATE_SHIFT) > +/* Bits 31..18 are currently unused. */ > > /* some convenience accessor macros */ > #define ARM_TBFLAG_THUMB(F) \ > @@ -692,29 +736,37 @@ static inline void cpu_clone_regs(CPUARMState *env, > target_ulong newsp) > (((F) & ARM_TBFLAG_CONDEXEC_MASK) >> ARM_TBFLAG_CONDEXEC_SHIFT) > #define ARM_TBFLAG_BSWAP_CODE(F) \ > (((F) & ARM_TBFLAG_BSWAP_CODE_MASK) >> ARM_TBFLAG_BSWAP_CODE_SHIFT) > +#define ARM_TBFLAG_AARCH64_STATE(F) \ > + (((F) & ARM_TBFLAG_AARCH64_STATE_MASK) >> ARM_TBFLAG_AARCH64_STATE_SHIFT) > > 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 = env->aarch64_state << ARM_TBFLAG_AARCH64_STATE_SHIFT; > } 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) > @@ -727,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 (ARM_TBFLAG_AARCH64_STATE(tb->flags)) { > + 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); > @@ -742,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 36537bd..a4b6d8a 100644 > --- a/target-arm/translate.c > +++ b/target-arm/translate.c > @@ -9750,7 +9750,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; > > @@ -9838,7 +9838,7 @@ static inline void > gen_intermediate_code_internal(CPUARMState *env, > /* 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. */ > + conditional execution block. */ > gen_exception(EXCP_KERNEL_TRAP); > dc->is_jmp = DISAS_UPDATE; > break; > @@ -9846,7 +9846,7 @@ static inline void > gen_intermediate_code_internal(CPUARMState *env, > #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. */ > + conditional execution block. */ > gen_exception(EXCP_EXCEPTION_EXIT); > dc->is_jmp = DISAS_UPDATE; > break; > @@ -9905,7 +9905,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. > @@ -10075,6 +10075,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.7.9.5 >