qemu-devel
[Top][All Lists]
Advanced

[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
>> 
>> 



reply via email to

[Prev in Thread] Current Thread [Next in Thread]