diff options
Diffstat (limited to 'target')
70 files changed, 1533 insertions, 515 deletions
diff --git a/target/alpha/cpu.h b/target/alpha/cpu.h index 994a018b91..d0abc949a8 100644 --- a/target/alpha/cpu.h +++ b/target/alpha/cpu.h @@ -434,8 +434,8 @@ void alpha_translate_init(void); #define CPU_RESOLVING_TYPE TYPE_ALPHA_CPU void alpha_cpu_list(void); -void QEMU_NORETURN dynamic_excp(CPUAlphaState *, uintptr_t, int, int); -void QEMU_NORETURN arith_excp(CPUAlphaState *, uintptr_t, int, uint64_t); +G_NORETURN void dynamic_excp(CPUAlphaState *, uintptr_t, int, int); +G_NORETURN void arith_excp(CPUAlphaState *, uintptr_t, int, uint64_t); uint64_t cpu_alpha_load_fpcr (CPUAlphaState *env); void cpu_alpha_store_fpcr (CPUAlphaState *env, uint64_t val); @@ -452,9 +452,9 @@ void alpha_cpu_record_sigbus(CPUState *cs, vaddr address, bool alpha_cpu_tlb_fill(CPUState *cs, vaddr address, int size, MMUAccessType access_type, int mmu_idx, bool probe, uintptr_t retaddr); -void alpha_cpu_do_unaligned_access(CPUState *cpu, vaddr addr, - MMUAccessType access_type, int mmu_idx, - uintptr_t retaddr) QEMU_NORETURN; +G_NORETURN void alpha_cpu_do_unaligned_access(CPUState *cpu, vaddr addr, + MMUAccessType access_type, int mmu_idx, + uintptr_t retaddr); void alpha_cpu_do_transaction_failed(CPUState *cs, hwaddr physaddr, vaddr addr, unsigned size, MMUAccessType access_type, diff --git a/target/alpha/helper.c b/target/alpha/helper.c index dcaa2d03ad..a5a389b5a3 100644 --- a/target/alpha/helper.c +++ b/target/alpha/helper.c @@ -514,7 +514,7 @@ void alpha_cpu_dump_state(CPUState *cs, FILE *f, int flags) /* This should only be called from translate, via gen_excp. We expect that ENV->PC has already been updated. */ -void QEMU_NORETURN helper_excp(CPUAlphaState *env, int excp, int error) +G_NORETURN void helper_excp(CPUAlphaState *env, int excp, int error) { CPUState *cs = env_cpu(env); @@ -524,8 +524,8 @@ void QEMU_NORETURN helper_excp(CPUAlphaState *env, int excp, int error) } /* This may be called from any of the helpers to set up EXCEPTION_INDEX. */ -void QEMU_NORETURN dynamic_excp(CPUAlphaState *env, uintptr_t retaddr, - int excp, int error) +G_NORETURN void dynamic_excp(CPUAlphaState *env, uintptr_t retaddr, + int excp, int error) { CPUState *cs = env_cpu(env); @@ -539,8 +539,8 @@ void QEMU_NORETURN dynamic_excp(CPUAlphaState *env, uintptr_t retaddr, cpu_loop_exit(cs); } -void QEMU_NORETURN arith_excp(CPUAlphaState *env, uintptr_t retaddr, - int exc, uint64_t mask) +G_NORETURN void arith_excp(CPUAlphaState *env, uintptr_t retaddr, + int exc, uint64_t mask) { env->trap_arg0 = exc; env->trap_arg1 = mask; diff --git a/target/arm/cpu.c b/target/arm/cpu.c index 3609de0888..e3f8215203 100644 --- a/target/arm/cpu.c +++ b/target/arm/cpu.c @@ -51,7 +51,7 @@ static void arm_cpu_set_pc(CPUState *cs, vaddr value) if (is_a64(env)) { env->pc = value; - env->thumb = 0; + env->thumb = false; } else { env->regs[15] = value & ~1; env->thumb = value & 1; @@ -189,7 +189,7 @@ static void arm_cpu_reset(DeviceState *dev) if (arm_feature(env, ARM_FEATURE_AARCH64)) { /* 64 bit CPUs always start in 64 bit mode */ - env->aarch64 = 1; + env->aarch64 = true; #if defined(CONFIG_USER_ONLY) env->pstate = PSTATE_MODE_EL0t; /* Userspace expects access to DC ZVA, CTL_EL0 and the cache ops */ @@ -694,6 +694,16 @@ static void arm_cpu_set_irq(void *opaque, int irq, int level) [ARM_CPU_VFIQ] = CPU_INTERRUPT_VFIQ }; + if (!arm_feature(env, ARM_FEATURE_EL2) && + (irq == ARM_CPU_VIRQ || irq == ARM_CPU_VFIQ)) { + /* + * The GIC might tell us about VIRQ and VFIQ state, but if we don't + * have EL2 support we don't care. (Unless the guest is doing something + * silly this will only be calls saying "level is still 0".) + */ + return; + } + if (level) { env->irq_line_state |= mask[irq]; } else { @@ -702,11 +712,9 @@ static void arm_cpu_set_irq(void *opaque, int irq, int level) switch (irq) { case ARM_CPU_VIRQ: - assert(arm_feature(env, ARM_FEATURE_EL2)); arm_cpu_update_virq(cpu); break; case ARM_CPU_VFIQ: - assert(arm_feature(env, ARM_FEATURE_EL2)); arm_cpu_update_vfiq(cpu); break; case ARM_CPU_IRQ: diff --git a/target/arm/cpu.h b/target/arm/cpu.h index cb5359a747..db8ff04449 100644 --- a/target/arm/cpu.h +++ b/target/arm/cpu.h @@ -259,7 +259,8 @@ typedef struct CPUArchState { * all other bits are stored in their correct places in env->pstate */ uint32_t pstate; - uint32_t aarch64; /* 1 if CPU is in aarch64 state; inverse of PSTATE.nRW */ + bool aarch64; /* True if CPU is in aarch64 state; inverse of PSTATE.nRW */ + bool thumb; /* True if CPU is in thumb mode; cpsr[5] */ /* Cached TBFLAGS state. See below for which bits are included. */ CPUARMTBFlags hflags; @@ -286,7 +287,6 @@ typedef struct CPUArchState { uint32_t ZF; /* Z set if zero. */ uint32_t QF; /* 0 or 1 */ uint32_t GE; /* cpsr[19:16] */ - uint32_t thumb; /* cpsr[5]. 0 = arm mode, 1 = thumb mode. */ uint32_t condexec_bits; /* IT bits. cpsr[15:10,26:25]. */ uint32_t btype; /* BTI branch type. spsr[11:10]. */ uint64_t daif; /* exception masks, in the bits they are in PSTATE */ @@ -1233,6 +1233,20 @@ void pmu_init(ARMCPU *cpu); #define SCTLR_ATA0 (1ULL << 42) /* v8.5-MemTag */ #define SCTLR_ATA (1ULL << 43) /* v8.5-MemTag */ #define SCTLR_DSSBS_64 (1ULL << 44) /* v8.5, AArch64 only */ +#define SCTLR_TWEDEn (1ULL << 45) /* FEAT_TWED */ +#define SCTLR_TWEDEL MAKE_64_MASK(46, 4) /* FEAT_TWED */ +#define SCTLR_TMT0 (1ULL << 50) /* FEAT_TME */ +#define SCTLR_TMT (1ULL << 51) /* FEAT_TME */ +#define SCTLR_TME0 (1ULL << 52) /* FEAT_TME */ +#define SCTLR_TME (1ULL << 53) /* FEAT_TME */ +#define SCTLR_EnASR (1ULL << 54) /* FEAT_LS64_V */ +#define SCTLR_EnAS0 (1ULL << 55) /* FEAT_LS64_ACCDATA */ +#define SCTLR_EnALS (1ULL << 56) /* FEAT_LS64 */ +#define SCTLR_EPAN (1ULL << 57) /* FEAT_PAN3 */ +#define SCTLR_EnTP2 (1ULL << 60) /* FEAT_SME */ +#define SCTLR_NMI (1ULL << 61) /* FEAT_NMI */ +#define SCTLR_SPINTMASK (1ULL << 62) /* FEAT_NMI */ +#define SCTLR_TIDCP (1ULL << 63) /* FEAT_TIDCP1 */ #define CPTR_TCPAC (1U << 31) #define CPTR_TTA (1U << 20) @@ -1545,6 +1559,18 @@ static inline void xpsr_write(CPUARMState *env, uint32_t val, uint32_t mask) #define SCR_FIEN (1U << 21) #define SCR_ENSCXT (1U << 25) #define SCR_ATA (1U << 26) +#define SCR_FGTEN (1U << 27) +#define SCR_ECVEN (1U << 28) +#define SCR_TWEDEN (1U << 29) +#define SCR_TWEDEL MAKE_64BIT_MASK(30, 4) +#define SCR_TME (1ULL << 34) +#define SCR_AMVOFFEN (1ULL << 35) +#define SCR_ENAS0 (1ULL << 36) +#define SCR_ADEN (1ULL << 37) +#define SCR_HXEN (1ULL << 38) +#define SCR_TRNDR (1ULL << 40) +#define SCR_ENTP2 (1ULL << 41) +#define SCR_GPF (1ULL << 48) #define HSTR_TTEE (1 << 16) #define HSTR_TJDBX (1 << 17) @@ -1934,6 +1960,7 @@ FIELD(ID_MMFR4, CCIDX, 24, 4) FIELD(ID_MMFR4, EVT, 28, 4) FIELD(ID_MMFR5, ETS, 0, 4) +FIELD(ID_MMFR5, NTLBPA, 4, 4) FIELD(ID_PFR0, STATE0, 0, 4) FIELD(ID_PFR0, STATE1, 4, 4) @@ -1986,6 +2013,16 @@ FIELD(ID_AA64ISAR1, SPECRES, 40, 4) FIELD(ID_AA64ISAR1, BF16, 44, 4) FIELD(ID_AA64ISAR1, DGH, 48, 4) FIELD(ID_AA64ISAR1, I8MM, 52, 4) +FIELD(ID_AA64ISAR1, XS, 56, 4) +FIELD(ID_AA64ISAR1, LS64, 60, 4) + +FIELD(ID_AA64ISAR2, WFXT, 0, 4) +FIELD(ID_AA64ISAR2, RPRES, 4, 4) +FIELD(ID_AA64ISAR2, GPA3, 8, 4) +FIELD(ID_AA64ISAR2, APA3, 12, 4) +FIELD(ID_AA64ISAR2, MOPS, 16, 4) +FIELD(ID_AA64ISAR2, BC, 20, 4) +FIELD(ID_AA64ISAR2, PAC_FRAC, 24, 4) FIELD(ID_AA64PFR0, EL0, 0, 4) FIELD(ID_AA64PFR0, EL1, 4, 4) @@ -2008,6 +2045,10 @@ FIELD(ID_AA64PFR1, SSBS, 4, 4) FIELD(ID_AA64PFR1, MTE, 8, 4) FIELD(ID_AA64PFR1, RAS_FRAC, 12, 4) FIELD(ID_AA64PFR1, MPAM_FRAC, 16, 4) +FIELD(ID_AA64PFR1, SME, 24, 4) +FIELD(ID_AA64PFR1, RNDR_TRAP, 28, 4) +FIELD(ID_AA64PFR1, CSV2_FRAC, 32, 4) +FIELD(ID_AA64PFR1, NMI, 36, 4) FIELD(ID_AA64MMFR0, PARANGE, 0, 4) FIELD(ID_AA64MMFR0, ASIDBITS, 4, 4) @@ -2034,6 +2075,11 @@ FIELD(ID_AA64MMFR1, SPECSEI, 24, 4) FIELD(ID_AA64MMFR1, XNX, 28, 4) FIELD(ID_AA64MMFR1, TWED, 32, 4) FIELD(ID_AA64MMFR1, ETS, 36, 4) +FIELD(ID_AA64MMFR1, HCX, 40, 4) +FIELD(ID_AA64MMFR1, AFP, 44, 4) +FIELD(ID_AA64MMFR1, NTLBPA, 48, 4) +FIELD(ID_AA64MMFR1, TIDCP1, 52, 4) +FIELD(ID_AA64MMFR1, CMOW, 56, 4) FIELD(ID_AA64MMFR2, CNP, 0, 4) FIELD(ID_AA64MMFR2, UAO, 4, 4) @@ -2060,7 +2106,10 @@ FIELD(ID_AA64DFR0, CTX_CMPS, 28, 4) FIELD(ID_AA64DFR0, PMSVER, 32, 4) FIELD(ID_AA64DFR0, DOUBLELOCK, 36, 4) FIELD(ID_AA64DFR0, TRACEFILT, 40, 4) +FIELD(ID_AA64DFR0, TRACEBUFFER, 44, 4) FIELD(ID_AA64DFR0, MTPMU, 48, 4) +FIELD(ID_AA64DFR0, BRBE, 52, 4) +FIELD(ID_AA64DFR0, HPMN0, 60, 4) FIELD(ID_AA64ZFR0, SVEVER, 0, 4) FIELD(ID_AA64ZFR0, AES, 4, 4) @@ -2082,6 +2131,7 @@ FIELD(ID_DFR0, PERFMON, 24, 4) FIELD(ID_DFR0, TRACEFILT, 28, 4) FIELD(ID_DFR1, MTPMU, 0, 4) +FIELD(ID_DFR1, HPMN0, 4, 4) FIELD(DBGDIDR, SE_IMP, 12, 1) FIELD(DBGDIDR, NSUHD_IMP, 14, 1) @@ -2757,11 +2807,6 @@ typedef enum CPAccessResult { /* As CP_ACCESS_UNCATEGORIZED, but for traps directly to EL2 or EL3 */ CP_ACCESS_TRAP_UNCATEGORIZED_EL2 = 5, CP_ACCESS_TRAP_UNCATEGORIZED_EL3 = 6, - /* Access fails and results in an exception syndrome for an FP access, - * trapped directly to EL2 or EL3 - */ - CP_ACCESS_TRAP_FP_EL2 = 7, - CP_ACCESS_TRAP_FP_EL3 = 8, } CPAccessResult; /* Access functions for coprocessor registers. These cannot fail and diff --git a/target/arm/helper-a64.c b/target/arm/helper-a64.c index 7cf953b1e6..77a8502b6b 100644 --- a/target/arm/helper-a64.c +++ b/target/arm/helper-a64.c @@ -952,7 +952,7 @@ void HELPER(exception_return)(CPUARMState *env, uint64_t new_pc) qemu_mutex_unlock_iothread(); if (!return_to_aa64) { - env->aarch64 = 0; + env->aarch64 = false; /* We do a raw CPSR write because aarch64_sync_64_to_32() * will sort the register banks out for us, and we've already * caught all the bad-mode cases in el_from_spsr(). @@ -975,7 +975,7 @@ void HELPER(exception_return)(CPUARMState *env, uint64_t new_pc) } else { int tbii; - env->aarch64 = 1; + env->aarch64 = true; spsr &= aarch64_pstate_valid_mask(&env_archcpu(env)->isar); pstate_write(env, spsr); if (!arm_singlestep_active(env)) { diff --git a/target/arm/helper.c b/target/arm/helper.c index d7715c911a..63397bbac1 100644 --- a/target/arm/helper.c +++ b/target/arm/helper.c @@ -4784,18 +4784,6 @@ static void sctlr_write(CPUARMState *env, const ARMCPRegInfo *ri, } } -static CPAccessResult fpexc32_access(CPUARMState *env, const ARMCPRegInfo *ri, - bool isread) -{ - if ((env->cp15.cptr_el[2] & CPTR_TFP) && arm_current_el(env) == 2) { - return CP_ACCESS_TRAP_FP_EL2; - } - if (env->cp15.cptr_el[3] & CPTR_TFP) { - return CP_ACCESS_TRAP_FP_EL3; - } - return CP_ACCESS_OK; -} - static void sdcr_write(CPUARMState *env, const ARMCPRegInfo *ri, uint64_t value) { @@ -5097,9 +5085,8 @@ static const ARMCPRegInfo v8_cp_reginfo[] = { .access = PL1_RW, .readfn = spsel_read, .writefn = spsel_write }, { .name = "FPEXC32_EL2", .state = ARM_CP_STATE_AA64, .opc0 = 3, .opc1 = 4, .crn = 5, .crm = 3, .opc2 = 0, - .type = ARM_CP_ALIAS, - .fieldoffset = offsetof(CPUARMState, vfp.xregs[ARM_VFP_FPEXC]), - .access = PL2_RW, .accessfn = fpexc32_access }, + .access = PL2_RW, .type = ARM_CP_ALIAS | ARM_CP_FPU, + .fieldoffset = offsetof(CPUARMState, vfp.xregs[ARM_VFP_FPEXC]) }, { .name = "DACR32_EL2", .state = ARM_CP_STATE_AA64, .opc0 = 3, .opc1 = 4, .crn = 3, .crm = 0, .opc2 = 0, .access = PL2_RW, .resetvalue = 0, @@ -10181,7 +10168,7 @@ static void arm_cpu_do_interrupt_aarch64(CPUState *cs) } pstate_write(env, PSTATE_DAIF | new_mode); - env->aarch64 = 1; + env->aarch64 = true; aarch64_restore_sp(env, new_el); helper_rebuild_hflags_a64(env, new_el); diff --git a/target/arm/hvf/hvf.c b/target/arm/hvf/hvf.c index 567e296b21..b11a8b9a18 100644 --- a/target/arm/hvf/hvf.c +++ b/target/arm/hvf/hvf.c @@ -564,7 +564,7 @@ int hvf_arch_init_vcpu(CPUState *cpu) hv_return_t ret; int i; - env->aarch64 = 1; + env->aarch64 = true; asm volatile("mrs %0, cntfrq_el0" : "=r"(arm_cpu->gt_cntfrq_hz)); /* Allocate enough space for our sysreg sync */ diff --git a/target/arm/internals.h b/target/arm/internals.h index 7f696cd36a..9556e3b29e 100644 --- a/target/arm/internals.h +++ b/target/arm/internals.h @@ -102,13 +102,13 @@ FIELD(V7M_EXCRET, RES1, 7, 25) /* including the must-be-1 prefix */ * and target exception level. This should be called from helper functions, * and never returns because we will longjump back up to the CPU main loop. */ -void QEMU_NORETURN raise_exception(CPUARMState *env, uint32_t excp, - uint32_t syndrome, uint32_t target_el); +G_NORETURN void raise_exception(CPUARMState *env, uint32_t excp, + uint32_t syndrome, uint32_t target_el); /* * Similarly, but also use unwinding to restore cpu state. */ -void QEMU_NORETURN raise_exception_ra(CPUARMState *env, uint32_t excp, +G_NORETURN void raise_exception_ra(CPUARMState *env, uint32_t excp, uint32_t syndrome, uint32_t target_el, uintptr_t ra); @@ -606,9 +606,9 @@ ARMMMUIdx arm_v7m_mmu_idx_for_secstate(CPUARMState *env, bool secstate); bool arm_s1_regime_using_lpae_format(CPUARMState *env, ARMMMUIdx mmu_idx); /* Raise a data fault alignment exception for the specified virtual address */ -void arm_cpu_do_unaligned_access(CPUState *cs, vaddr vaddr, - MMUAccessType access_type, - int mmu_idx, uintptr_t retaddr) QEMU_NORETURN; +G_NORETURN void arm_cpu_do_unaligned_access(CPUState *cs, vaddr vaddr, + MMUAccessType access_type, + int mmu_idx, uintptr_t retaddr); /* arm_cpu_do_transaction_failed: handle a memory system error response * (eg "no device/memory present at address") by raising an external abort diff --git a/target/arm/m_helper.c b/target/arm/m_helper.c index b7a0fe0114..a740c3e160 100644 --- a/target/arm/m_helper.c +++ b/target/arm/m_helper.c @@ -564,7 +564,7 @@ void HELPER(v7m_bxns)(CPUARMState *env, uint32_t dest) env->v7m.control[M_REG_S] &= ~R_V7M_CONTROL_SFPA_MASK; } switch_v7m_security_state(env, dest & 1); - env->thumb = 1; + env->thumb = true; env->regs[15] = dest & ~1; arm_rebuild_hflags(env); } @@ -590,7 +590,7 @@ void HELPER(v7m_blxns)(CPUARMState *env, uint32_t dest) * except that the low bit doesn't indicate Thumb/not. */ env->regs[14] = nextinst; - env->thumb = 1; + env->thumb = true; env->regs[15] = dest & ~1; return; } @@ -626,7 +626,7 @@ void HELPER(v7m_blxns)(CPUARMState *env, uint32_t dest) } env->v7m.control[M_REG_S] &= ~R_V7M_CONTROL_SFPA_MASK; switch_v7m_security_state(env, 0); - env->thumb = 1; + env->thumb = true; env->regs[15] = dest; arm_rebuild_hflags(env); } diff --git a/target/arm/op_helper.c b/target/arm/op_helper.c index 70b42b55fd..2b87e8808b 100644 --- a/target/arm/op_helper.c +++ b/target/arm/op_helper.c @@ -691,19 +691,6 @@ void HELPER(access_check_cp_reg)(CPUARMState *env, void *rip, uint32_t syndrome, target_el = 3; syndrome = syn_uncategorized(); break; - case CP_ACCESS_TRAP_FP_EL2: - target_el = 2; - /* Since we are an implementation that takes exceptions on a trapped - * conditional insn only if the insn has passed its condition code - * check, we take the IMPDEF choice to always report CV=1 COND=0xe - * (which is also the required value for AArch64 traps). - */ - syndrome = syn_fp_access_trap(1, 0xe, false); - break; - case CP_ACCESS_TRAP_FP_EL3: - target_el = 3; - syndrome = syn_fp_access_trap(1, 0xe, false); - break; default: g_assert_not_reached(); } diff --git a/target/arm/pauth_helper.c b/target/arm/pauth_helper.c index 739aa520dd..d0483bf051 100644 --- a/target/arm/pauth_helper.c +++ b/target/arm/pauth_helper.c @@ -382,8 +382,8 @@ static uint64_t pauth_strip(CPUARMState *env, uint64_t ptr, bool data) return pauth_original_ptr(ptr, param); } -static void QEMU_NORETURN pauth_trap(CPUARMState *env, int target_el, - uintptr_t ra) +static G_NORETURN +void pauth_trap(CPUARMState *env, int target_el, uintptr_t ra) { raise_exception_ra(env, EXCP_UDEF, syn_pactrap(), target_el, ra); } diff --git a/target/arm/tlb_helper.c b/target/arm/tlb_helper.c index b79004e0cc..6421e16202 100644 --- a/target/arm/tlb_helper.c +++ b/target/arm/tlb_helper.c @@ -79,9 +79,10 @@ static uint32_t compute_fsr_fsc(CPUARMState *env, ARMMMUFaultInfo *fi, return fsr; } -static void QEMU_NORETURN arm_deliver_fault(ARMCPU *cpu, vaddr addr, - MMUAccessType access_type, - int mmu_idx, ARMMMUFaultInfo *fi) +static G_NORETURN +void arm_deliver_fault(ARMCPU *cpu, vaddr addr, + MMUAccessType access_type, + int mmu_idx, ARMMMUFaultInfo *fi) { CPUARMState *env = &cpu->env; int target_el; diff --git a/target/arm/translate-a32.h b/target/arm/translate-a32.h index 5be4b9b834..09010ad2da 100644 --- a/target/arm/translate-a32.h +++ b/target/arm/translate-a32.h @@ -61,17 +61,14 @@ static inline TCGv_i32 load_cpu_offset(int offset) #define load_cpu_field(name) load_cpu_offset(offsetof(CPUARMState, name)) -static inline void store_cpu_offset(TCGv_i32 var, int offset) -{ - tcg_gen_st_i32(var, cpu_env, offset); - tcg_temp_free_i32(var); -} +void store_cpu_offset(TCGv_i32 var, int offset, int size); -#define store_cpu_field(var, name) \ - store_cpu_offset(var, offsetof(CPUARMState, name)) +#define store_cpu_field(var, name) \ + store_cpu_offset(var, offsetof(CPUARMState, name), \ + sizeof_field(CPUARMState, name)) #define store_cpu_field_constant(val, name) \ - tcg_gen_st_i32(tcg_constant_i32(val), cpu_env, offsetof(CPUARMState, name)) + store_cpu_field(tcg_constant_i32(val), name) /* Create a new temporary and set it to the value of a CPU register. */ static inline TCGv_i32 load_reg(DisasContext *s, int reg) diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c index 19c09c3b53..adbcd99941 100644 --- a/target/arm/translate-a64.c +++ b/target/arm/translate-a64.c @@ -128,29 +128,28 @@ static int get_a64_user_mem_index(DisasContext *s) return arm_to_core_mmu_idx(useridx); } -static void reset_btype(DisasContext *s) +static void set_btype_raw(int val) { - if (s->btype != 0) { - TCGv_i32 zero = tcg_const_i32(0); - tcg_gen_st_i32(zero, cpu_env, offsetof(CPUARMState, btype)); - tcg_temp_free_i32(zero); - s->btype = 0; - } + tcg_gen_st_i32(tcg_constant_i32(val), cpu_env, + offsetof(CPUARMState, btype)); } static void set_btype(DisasContext *s, int val) { - TCGv_i32 tcg_val; - /* BTYPE is a 2-bit field, and 0 should be done with reset_btype. */ tcg_debug_assert(val >= 1 && val <= 3); - - tcg_val = tcg_const_i32(val); - tcg_gen_st_i32(tcg_val, cpu_env, offsetof(CPUARMState, btype)); - tcg_temp_free_i32(tcg_val); + set_btype_raw(val); s->btype = -1; } +static void reset_btype(DisasContext *s) +{ + if (s->btype != 0) { + set_btype_raw(0); + s->btype = 0; + } +} + void gen_a64_set_pc_im(uint64_t val) { tcg_gen_movi_i64(cpu_pc, val); @@ -342,6 +341,11 @@ static void a64_free_cc(DisasCompare64 *c64) tcg_temp_free_i64(c64->value); } +static void gen_rebuild_hflags(DisasContext *s) +{ + gen_helper_rebuild_hflags_a64(cpu_env, tcg_constant_i32(s->current_el)); +} + static void gen_exception_internal(int excp) { TCGv_i32 tcg_excp = tcg_const_i32(excp); @@ -1668,9 +1672,7 @@ static void handle_msr_i(DisasContext *s, uint32_t insn, } else { clear_pstate_bits(PSTATE_UAO); } - t1 = tcg_const_i32(s->current_el); - gen_helper_rebuild_hflags_a64(cpu_env, t1); - tcg_temp_free_i32(t1); + gen_rebuild_hflags(s); break; case 0x04: /* PAN */ @@ -1682,9 +1684,7 @@ static void handle_msr_i(DisasContext *s, uint32_t insn, } else { clear_pstate_bits(PSTATE_PAN); } - t1 = tcg_const_i32(s->current_el); - gen_helper_rebuild_hflags_a64(cpu_env, t1); - tcg_temp_free_i32(t1); + gen_rebuild_hflags(s); break; case 0x05: /* SPSel */ @@ -1742,9 +1742,7 @@ static void handle_msr_i(DisasContext *s, uint32_t insn, } else { clear_pstate_bits(PSTATE_TCO); } - t1 = tcg_const_i32(s->current_el); - gen_helper_rebuild_hflags_a64(cpu_env, t1); - tcg_temp_free_i32(t1); + gen_rebuild_hflags(s); /* Many factors, including TCO, go into MTE_ACTIVE. */ s->base.is_jmp = DISAS_UPDATE_NOCHAIN; } else if (dc_isar_feature(aa64_mte_insn_reg, s)) { @@ -1991,9 +1989,7 @@ static void handle_sys(DisasContext *s, uint32_t insn, bool isread, * A write to any coprocessor regiser that ends a TB * must rebuild the hflags for the next TB. */ - TCGv_i32 tcg_el = tcg_const_i32(s->current_el); - gen_helper_rebuild_hflags_a64(cpu_env, tcg_el); - tcg_temp_free_i32(tcg_el); + gen_rebuild_hflags(s); /* * We default to ending the TB on a coprocessor register write, * but allow this to be suppressed by the register definition @@ -14664,13 +14660,13 @@ static void aarch64_tr_init_disas_context(DisasContextBase *dcbase, dc->isar = &arm_cpu->isar; dc->condjmp = 0; - dc->aarch64 = 1; + dc->aarch64 = true; /* If we are coming from secure EL0 in a system with a 32-bit EL3, then * there is no secure EL1, so we route exceptions to EL3. */ dc->secure_routed_to_el3 = arm_feature(env, ARM_FEATURE_EL3) && !arm_el_is_aa64(env, 3); - dc->thumb = 0; + dc->thumb = false; dc->sctlr_b = 0; dc->be_data = EX_TBFLAG_ANY(tb_flags, BE_DATA) ? MO_BE : MO_LE; dc->condexec_mask = 0; diff --git a/target/arm/translate-m-nocp.c b/target/arm/translate-m-nocp.c index d9e144e8eb..27363a7b4e 100644 --- a/target/arm/translate-m-nocp.c +++ b/target/arm/translate-m-nocp.c @@ -173,7 +173,7 @@ static bool trans_VSCCLRM(DisasContext *s, arg_VSCCLRM *a) } /* Zero the Sregs from btmreg to topreg inclusive. */ - zero = tcg_const_i64(0); + zero = tcg_constant_i64(0); if (btmreg & 1) { write_neon_element64(zero, btmreg >> 1, 1, MO_32); btmreg++; @@ -187,8 +187,7 @@ static bool trans_VSCCLRM(DisasContext *s, arg_VSCCLRM *a) } assert(btmreg == topreg + 1); if (dc_isar_feature(aa32_mve, s)) { - TCGv_i32 z32 = tcg_const_i32(0); - store_cpu_field(z32, v7m.vpr); + store_cpu_field(tcg_constant_i32(0), v7m.vpr); } clear_eci_state(s); @@ -512,7 +511,7 @@ static bool gen_M_fp_sysreg_read(DisasContext *s, int regno, } case ARM_VFP_FPCXT_NS: { - TCGv_i32 control, sfpa, fpscr, fpdscr, zero; + TCGv_i32 control, sfpa, fpscr, fpdscr; TCGLabel *lab_active = gen_new_label(); lookup_tb = true; @@ -552,10 +551,9 @@ static bool gen_M_fp_sysreg_read(DisasContext *s, int regno, storefn(s, opaque, tmp, true); /* If SFPA is zero then set FPSCR from FPDSCR_NS */ fpdscr = load_cpu_field(v7m.fpdscr[M_REG_NS]); - zero = tcg_const_i32(0); - tcg_gen_movcond_i32(TCG_COND_EQ, fpscr, sfpa, zero, fpdscr, fpscr); + tcg_gen_movcond_i32(TCG_COND_EQ, fpscr, sfpa, tcg_constant_i32(0), + fpdscr, fpscr); gen_helper_vfp_set_fpscr(cpu_env, fpscr); - tcg_temp_free_i32(zero); tcg_temp_free_i32(sfpa); tcg_temp_free_i32(fpdscr); tcg_temp_free_i32(fpscr); diff --git a/target/arm/translate-neon.c b/target/arm/translate-neon.c index 384604c009..2e4d1ec87d 100644 --- a/target/arm/translate-neon.c +++ b/target/arm/translate-neon.c @@ -447,7 +447,7 @@ static bool trans_VLDST_multiple(DisasContext *s, arg_VLDST_multiple *a) int mmu_idx = get_mem_index(s); int size = a->size; TCGv_i64 tmp64; - TCGv_i32 addr, tmp; + TCGv_i32 addr; if (!arm_dc_feature(s, ARM_FEATURE_NEON)) { return false; @@ -513,7 +513,6 @@ static bool trans_VLDST_multiple(DisasContext *s, arg_VLDST_multiple *a) tmp64 = tcg_temp_new_i64(); addr = tcg_temp_new_i32(); - tmp = tcg_const_i32(1 << size); load_reg_var(s, addr, a->rn); mop = endian | size | align; @@ -530,7 +529,7 @@ static bool trans_VLDST_multiple(DisasContext *s, arg_VLDST_multiple *a) neon_load_element64(tmp64, tt, n, size); gen_aa32_st_internal_i64(s, tmp64, addr, mmu_idx, mop); } - tcg_gen_add_i32(addr, addr, tmp); + tcg_gen_addi_i32(addr, addr, 1 << size); /* Subsequent memory operations inherit alignment */ mop &= ~MO_AMASK; @@ -538,7 +537,6 @@ static bool trans_VLDST_multiple(DisasContext *s, arg_VLDST_multiple *a) } } tcg_temp_free_i32(addr); - tcg_temp_free_i32(tmp); tcg_temp_free_i64(tmp64); gen_neon_ldst_base_update(s, a->rm, a->rn, nregs * interleave * 8); @@ -1348,7 +1346,7 @@ static bool do_2shift_env_64(DisasContext *s, arg_2reg_shift *a, * To avoid excessive duplication of ops we implement shift * by immediate using the variable shift operations. */ - constimm = tcg_const_i64(dup_const(a->size, a->shift)); + constimm = tcg_constant_i64(dup_const(a->size, a->shift)); for (pass = 0; pass < a->q + 1; pass++) { TCGv_i64 tmp = tcg_temp_new_i64(); @@ -1358,7 +1356,6 @@ static bool do_2shift_env_64(DisasContext *s, arg_2reg_shift *a, write_neon_element64(tmp, a->vd, pass, MO_64); tcg_temp_free_i64(tmp); } - tcg_temp_free_i64(constimm); return true; } @@ -1394,7 +1391,7 @@ static bool do_2shift_env_32(DisasContext *s, arg_2reg_shift *a, * To avoid excessive duplication of ops we implement shift * by immediate using the variable shift operations. */ - constimm = tcg_const_i32(dup_const(a->size, a->shift)); + constimm = tcg_constant_i32(dup_const(a->size, a->shift)); tmp = tcg_temp_new_i32(); for (pass = 0; pass < (a->q ? 4 : 2); pass++) { @@ -1403,7 +1400,6 @@ static bool do_2shift_env_32(DisasContext *s, arg_2reg_shift *a, write_neon_element32(tmp, a->vd, pass, MO_32); } tcg_temp_free_i32(tmp); - tcg_temp_free_i32(constimm); return true; } @@ -1457,7 +1453,7 @@ static bool do_2shift_narrow_64(DisasContext *s, arg_2reg_shift *a, * This is always a right shift, and the shiftfn is always a * left-shift helper, which thus needs the negated shift count. */ - constimm = tcg_const_i64(-a->shift); + constimm = tcg_constant_i64(-a->shift); rm1 = tcg_temp_new_i64(); rm2 = tcg_temp_new_i64(); rd = tcg_temp_new_i32(); @@ -1477,7 +1473,6 @@ static bool do_2shift_narrow_64(DisasContext *s, arg_2reg_shift *a, tcg_temp_free_i32(rd); tcg_temp_free_i64(rm1); tcg_temp_free_i64(rm2); - tcg_temp_free_i64(constimm); return true; } @@ -1521,7 +1516,7 @@ static bool do_2shift_narrow_32(DisasContext *s, arg_2reg_shift *a, /* size == 2 */ imm = -a->shift; } - constimm = tcg_const_i32(imm); + constimm = tcg_constant_i32(imm); /* Load all inputs first to avoid potential overwrite */ rm1 = tcg_temp_new_i32(); @@ -1546,7 +1541,6 @@ static bool do_2shift_narrow_32(DisasContext *s, arg_2reg_shift *a, shiftfn(rm3, rm3, constimm); shiftfn(rm4, rm4, constimm); - tcg_temp_free_i32(constimm); tcg_gen_concat_i32_i64(rtmp, rm3, rm4); tcg_temp_free_i32(rm4); @@ -2911,7 +2905,7 @@ static bool trans_VTBL(DisasContext *s, arg_VTBL *a) return true; } - desc = tcg_const_i32((a->vn << 2) | a->len); + desc = tcg_constant_i32((a->vn << 2) | a->len); def = tcg_temp_new_i64(); if (a->op) { read_neon_element64(def, a->vd, 0, MO_64); @@ -2926,7 +2920,6 @@ static bool trans_VTBL(DisasContext *s, arg_VTBL *a) tcg_temp_free_i64(def); tcg_temp_free_i64(val); - tcg_temp_free_i32(desc); return true; } diff --git a/target/arm/translate-sve.c b/target/arm/translate-sve.c index 180e14d9f8..726cf88d7c 100644 --- a/target/arm/translate-sve.c +++ b/target/arm/translate-sve.c @@ -1916,8 +1916,6 @@ static bool trans_PNEXT(DisasContext *s, arg_rr_esz *a) static void do_sat_addsub_32(TCGv_i64 reg, TCGv_i64 val, bool u, bool d) { int64_t ibound; - TCGv_i64 bound; - TCGCond cond; /* Use normal 64-bit arithmetic to detect 32-bit overflow. */ if (u) { @@ -1928,15 +1926,12 @@ static void do_sat_addsub_32(TCGv_i64 reg, TCGv_i64 val, bool u, bool d) if (d) { tcg_gen_sub_i64(reg, reg, val); ibound = (u ? 0 : INT32_MIN); - cond = TCG_COND_LT; + tcg_gen_smax_i64(reg, reg, tcg_constant_i64(ibound)); } else { tcg_gen_add_i64(reg, reg, val); ibound = (u ? UINT32_MAX : INT32_MAX); - cond = TCG_COND_GT; + tcg_gen_smin_i64(reg, reg, tcg_constant_i64(ibound)); } - bound = tcg_const_i64(ibound); - tcg_gen_movcond_i64(cond, reg, reg, bound, bound, reg); - tcg_temp_free_i64(bound); } /* Similarly with 64-bit values. */ diff --git a/target/arm/translate-vfp.c b/target/arm/translate-vfp.c index 6a95a67a69..40a513b822 100644 --- a/target/arm/translate-vfp.c +++ b/target/arm/translate-vfp.c @@ -180,8 +180,7 @@ static void gen_update_fp_context(DisasContext *s) gen_helper_vfp_set_fpscr(cpu_env, fpscr); tcg_temp_free_i32(fpscr); if (dc_isar_feature(aa32_mve, s)) { - TCGv_i32 z32 = tcg_const_i32(0); - store_cpu_field(z32, v7m.vpr); + store_cpu_field(tcg_constant_i32(0), v7m.vpr); } /* * We just updated the FPSCR and VPR. Some of this state is cached @@ -317,7 +316,7 @@ static bool trans_VSEL(DisasContext *s, arg_VSEL *a) TCGv_i64 frn, frm, dest; TCGv_i64 tmp, zero, zf, nf, vf; - zero = tcg_const_i64(0); + zero = tcg_constant_i64(0); frn = tcg_temp_new_i64(); frm = tcg_temp_new_i64(); @@ -335,27 +334,22 @@ static bool trans_VSEL(DisasContext *s, arg_VSEL *a) vfp_load_reg64(frm, rm); switch (a->cc) { case 0: /* eq: Z */ - tcg_gen_movcond_i64(TCG_COND_EQ, dest, zf, zero, - frn, frm); + tcg_gen_movcond_i64(TCG_COND_EQ, dest, zf, zero, frn, frm); break; case 1: /* vs: V */ - tcg_gen_movcond_i64(TCG_COND_LT, dest, vf, zero, - frn, frm); + tcg_gen_movcond_i64(TCG_COND_LT, dest, vf, zero, frn, frm); break; case 2: /* ge: N == V -> N ^ V == 0 */ tmp = tcg_temp_new_i64(); tcg_gen_xor_i64(tmp, vf, nf); - tcg_gen_movcond_i64(TCG_COND_GE, dest, tmp, zero, - frn, frm); + tcg_gen_movcond_i64(TCG_COND_GE, dest, tmp, zero, frn, frm); tcg_temp_free_i64(tmp); break; case 3: /* gt: !Z && N == V */ - tcg_gen_movcond_i64(TCG_COND_NE, dest, zf, zero, - frn, frm); + tcg_gen_movcond_i64(TCG_COND_NE, dest, zf, zero, frn, frm); tmp = tcg_temp_new_i64(); tcg_gen_xor_i64(tmp, vf, nf); - tcg_gen_movcond_i64(TCG_COND_GE, dest, tmp, zero, - dest, frm); + tcg_gen_movcond_i64(TCG_COND_GE, dest, tmp, zero, dest, frm); tcg_temp_free_i64(tmp); break; } @@ -367,13 +361,11 @@ static bool trans_VSEL(DisasContext *s, arg_VSEL *a) tcg_temp_free_i64(zf); tcg_temp_free_i64(nf); tcg_temp_free_i64(vf); - - tcg_temp_free_i64(zero); } else { TCGv_i32 frn, frm, dest; TCGv_i32 tmp, zero; - zero = tcg_const_i32(0); + zero = tcg_constant_i32(0); frn = tcg_temp_new_i32(); frm = tcg_temp_new_i32(); @@ -382,27 +374,22 @@ static bool trans_VSEL(DisasContext *s, arg_VSEL *a) vfp_load_reg32(frm, rm); switch (a->cc) { case 0: /* eq: Z */ - tcg_gen_movcond_i32(TCG_COND_EQ, dest, cpu_ZF, zero, - frn, frm); + tcg_gen_movcond_i32(TCG_COND_EQ, dest, cpu_ZF, zero, frn, frm); break; case 1: /* vs: V */ - tcg_gen_movcond_i32(TCG_COND_LT, dest, cpu_VF, zero, - frn, frm); + tcg_gen_movcond_i32(TCG_COND_LT, dest, cpu_VF, zero, frn, frm); break; case 2: /* ge: N == V -> N ^ V == 0 */ tmp = tcg_temp_new_i32(); tcg_gen_xor_i32(tmp, cpu_VF, cpu_NF); - tcg_gen_movcond_i32(TCG_COND_GE, dest, tmp, zero, - frn, frm); + tcg_gen_movcond_i32(TCG_COND_GE, dest, tmp, zero, frn, frm); tcg_temp_free_i32(tmp); break; case 3: /* gt: !Z && N == V */ - tcg_gen_movcond_i32(TCG_COND_NE, dest, cpu_ZF, zero, - frn, frm); + tcg_gen_movcond_i32(TCG_COND_NE, dest, cpu_ZF, zero, frn, frm); tmp = tcg_temp_new_i32(); tcg_gen_xor_i32(tmp, cpu_VF, cpu_NF); - tcg_gen_movcond_i32(TCG_COND_GE, dest, tmp, zero, - dest, frm); + tcg_gen_movcond_i32(TCG_COND_GE, dest, tmp, zero, dest, frm); tcg_temp_free_i32(tmp); break; } @@ -414,8 +401,6 @@ static bool trans_VSEL(DisasContext *s, arg_VSEL *a) tcg_temp_free_i32(frn); tcg_temp_free_i32(frm); tcg_temp_free_i32(dest); - - tcg_temp_free_i32(zero); } return true; @@ -547,7 +532,7 @@ static bool trans_VCVT(DisasContext *s, arg_VCVT *a) fpst = fpstatus_ptr(FPST_FPCR); } - tcg_shift = tcg_const_i32(0); + tcg_shift = tcg_constant_i32(0); tcg_rmode = tcg_const_i32(arm_rmode_to_sf(rounding)); gen_helper_set_rmode(tcg_rmode, tcg_rmode, fpst); @@ -595,8 +580,6 @@ static bool trans_VCVT(DisasContext *s, arg_VCVT *a) gen_helper_set_rmode(tcg_rmode, tcg_rmode, fpst); tcg_temp_free_i32(tcg_rmode); - tcg_temp_free_i32(tcg_shift); - tcg_temp_free_ptr(fpst); return true; @@ -850,15 +833,11 @@ static bool trans_VMSR_VMRS(DisasContext *s, arg_VMSR_VMRS *a) case ARM_VFP_MVFR2: case ARM_VFP_FPSID: if (s->current_el == 1) { - TCGv_i32 tcg_reg, tcg_rt; - gen_set_condexec(s); gen_set_pc_im(s, s->pc_curr); - tcg_reg = tcg_const_i32(a->reg); - tcg_rt = tcg_const_i32(a->rt); - gen_helper_check_hcr_el2_trap(cpu_env, tcg_rt, tcg_reg); - tcg_temp_free_i32(tcg_reg); - tcg_temp_free_i32(tcg_rt); + gen_helper_check_hcr_el2_trap(cpu_env, + tcg_constant_i32(a->rt), + tcg_constant_i32(a->reg)); } /* fall through */ case ARM_VFP_FPEXC: @@ -2388,8 +2367,6 @@ MAKE_VFM_TRANS_FNS(dp) static bool trans_VMOV_imm_hp(DisasContext *s, arg_VMOV_imm_sp *a) { - TCGv_i32 fd; - if (!dc_isar_feature(aa32_fp16_arith, s)) { return false; } @@ -2402,9 +2379,7 @@ static bool trans_VMOV_imm_hp(DisasContext *s, arg_VMOV_imm_sp *a) return true; } - fd = tcg_const_i32(vfp_expand_imm(MO_16, a->imm)); - vfp_store_reg32(fd, a->vd); - tcg_temp_free_i32(fd); + vfp_store_reg32(tcg_constant_i32(vfp_expand_imm(MO_16, a->imm)), a->vd); return true; } @@ -2440,7 +2415,7 @@ static bool trans_VMOV_imm_sp(DisasContext *s, arg_VMOV_imm_sp *a) } } - fd = tcg_const_i32(vfp_expand_imm(MO_32, a->imm)); + fd = tcg_constant_i32(vfp_expand_imm(MO_32, a->imm)); for (;;) { vfp_store_reg32(fd, vd); @@ -2454,7 +2429,6 @@ static bool trans_VMOV_imm_sp(DisasContext *s, arg_VMOV_imm_sp *a) vd = vfp_advance_sreg(vd, delta_d); } - tcg_temp_free_i32(fd); return true; } @@ -2495,7 +2469,7 @@ static bool trans_VMOV_imm_dp(DisasContext *s, arg_VMOV_imm_dp *a) } } - fd = tcg_const_i64(vfp_expand_imm(MO_64, a->imm)); + fd = tcg_constant_i64(vfp_expand_imm(MO_64, a->imm)); for (;;) { vfp_store_reg64(fd, vd); @@ -2509,7 +2483,6 @@ static bool trans_VMOV_imm_dp(DisasContext *s, arg_VMOV_imm_dp *a) vd = vfp_advance_dreg(vd, delta_d); } - tcg_temp_free_i64(fd); return true; } @@ -3294,7 +3267,7 @@ static bool trans_VCVT_fix_hp(DisasContext *s, arg_VCVT_fix_sp *a) vfp_load_reg32(vd, a->vd); fpst = fpstatus_ptr(FPST_FPCR_F16); - shift = tcg_const_i32(frac_bits); + shift = tcg_constant_i32(frac_bits); /* Switch on op:U:sx bits */ switch (a->opc) { @@ -3328,7 +3301,6 @@ static bool trans_VCVT_fix_hp(DisasContext *s, arg_VCVT_fix_sp *a) vfp_store_reg32(vd, a->vd); tcg_temp_free_i32(vd); - tcg_temp_free_i32(shift); tcg_temp_free_ptr(fpst); return true; } @@ -3353,7 +3325,7 @@ static bool trans_VCVT_fix_sp(DisasContext *s, arg_VCVT_fix_sp *a) vfp_load_reg32(vd, a->vd); fpst = fpstatus_ptr(FPST_FPCR); - shift = tcg_const_i32(frac_bits); + shift = tcg_constant_i32(frac_bits); /* Switch on op:U:sx bits */ switch (a->opc) { @@ -3387,7 +3359,6 @@ static bool trans_VCVT_fix_sp(DisasContext *s, arg_VCVT_fix_sp *a) vfp_store_reg32(vd, a->vd); tcg_temp_free_i32(vd); - tcg_temp_free_i32(shift); tcg_temp_free_ptr(fpst); return true; } @@ -3418,7 +3389,7 @@ static bool trans_VCVT_fix_dp(DisasContext *s, arg_VCVT_fix_dp *a) vfp_load_reg64(vd, a->vd); fpst = fpstatus_ptr(FPST_FPCR); - shift = tcg_const_i32(frac_bits); + shift = tcg_constant_i32(frac_bits); /* Switch on op:U:sx bits */ switch (a->opc) { @@ -3452,7 +3423,6 @@ static bool trans_VCVT_fix_dp(DisasContext *s, arg_VCVT_fix_dp *a) vfp_store_reg64(vd, a->vd); tcg_temp_free_i64(vd); - tcg_temp_free_i32(shift); tcg_temp_free_ptr(fpst); return true; } diff --git a/target/arm/translate.c b/target/arm/translate.c index 38e7a38f28..d09692c125 100644 --- a/target/arm/translate.c +++ b/target/arm/translate.c @@ -180,6 +180,25 @@ typedef enum ISSInfo { ISSIs16Bit = (1 << 8), } ISSInfo; +/* + * Store var into env + offset to a member with size bytes. + * Free var after use. + */ +void store_cpu_offset(TCGv_i32 var, int offset, int size) +{ + switch (size) { + case 1: + tcg_gen_st8_i32(var, cpu_env, offset); + break; + case 4: + tcg_gen_st_i32(var, cpu_env, offset); + break; + default: + g_assert_not_reached(); + } + tcg_temp_free_i32(var); +} + /* Save the syndrome information for a Data Abort */ static void disas_set_da_iss(DisasContext *s, MemOp memop, ISSInfo issinfo) { @@ -332,6 +351,26 @@ void gen_set_cpsr(TCGv_i32 var, uint32_t mask) tcg_temp_free_i32(tmp_mask); } +static void gen_rebuild_hflags(DisasContext *s, bool new_el) +{ + bool m_profile = arm_dc_feature(s, ARM_FEATURE_M); + + if (new_el) { + if (m_profile) { + gen_helper_rebuild_hflags_m32_newel(cpu_env); + } else { + gen_helper_rebuild_hflags_a32_newel(cpu_env); + } + } else { + TCGv_i32 tcg_el = tcg_constant_i32(s->current_el); + if (m_profile) { + gen_helper_rebuild_hflags_m32(cpu_env, tcg_el); + } else { + gen_helper_rebuild_hflags_a32(cpu_env, tcg_el); + } + } +} + static void gen_exception_internal(int excp) { TCGv_i32 tcg_excp = tcg_const_i32(excp); @@ -513,16 +552,14 @@ static void gen_sbc_CC(TCGv_i32 dest, TCGv_i32 t0, TCGv_i32 t1) #define GEN_SHIFT(name) \ static void gen_##name(TCGv_i32 dest, TCGv_i32 t0, TCGv_i32 t1) \ { \ - TCGv_i32 tmp1, tmp2, tmp3; \ - tmp1 = tcg_temp_new_i32(); \ - tcg_gen_andi_i32(tmp1, t1, 0xff); \ - tmp2 = tcg_const_i32(0); \ - tmp3 = tcg_const_i32(0x1f); \ - tcg_gen_movcond_i32(TCG_COND_GTU, tmp2, tmp1, tmp3, tmp2, t0); \ - tcg_temp_free_i32(tmp3); \ - tcg_gen_andi_i32(tmp1, tmp1, 0x1f); \ - tcg_gen_##name##_i32(dest, tmp2, tmp1); \ - tcg_temp_free_i32(tmp2); \ + TCGv_i32 tmpd = tcg_temp_new_i32(); \ + TCGv_i32 tmp1 = tcg_temp_new_i32(); \ + TCGv_i32 zero = tcg_constant_i32(0); \ + tcg_gen_andi_i32(tmp1, t1, 0x1f); \ + tcg_gen_##name##_i32(tmpd, t0, tmp1); \ + tcg_gen_andi_i32(tmp1, t1, 0xe0); \ + tcg_gen_movcond_i32(TCG_COND_NE, dest, tmp1, zero, zero, tmpd); \ + tcg_temp_free_i32(tmpd); \ tcg_temp_free_i32(tmp1); \ } GEN_SHIFT(shl) @@ -531,12 +568,10 @@ GEN_SHIFT(shr) static void gen_sar(TCGv_i32 dest, TCGv_i32 t0, TCGv_i32 t1) { - TCGv_i32 tmp1, tmp2; - tmp1 = tcg_temp_new_i32(); + TCGv_i32 tmp1 = tcg_temp_new_i32(); + tcg_gen_andi_i32(tmp1, t1, 0xff); - tmp2 = tcg_const_i32(0x1f); - tcg_gen_movcond_i32(TCG_COND_GTU, tmp1, tmp1, tmp2, tmp2, tmp1); - tcg_temp_free_i32(tmp2); + tcg_gen_umin_i32(tmp1, tmp1, tcg_constant_i32(31)); tcg_gen_sar_i32(dest, t0, tmp1); tcg_temp_free_i32(tmp1); } @@ -4852,7 +4887,7 @@ static void do_coproc_insn(DisasContext *s, int cpnum, int is64, tcg_temp_free_i32(tmp); } else { TCGv_i32 tmp = load_reg(s, rt); - store_cpu_offset(tmp, ri->fieldoffset); + store_cpu_offset(tmp, ri->fieldoffset, 4); } } } @@ -4866,17 +4901,7 @@ static void do_coproc_insn(DisasContext *s, int cpnum, int is64, * A write to any coprocessor register that ends a TB * must rebuild the hflags for the next TB. */ - TCGv_i32 tcg_el = tcg_const_i32(s->current_el); - if (arm_dc_feature(s, ARM_FEATURE_M)) { - gen_helper_rebuild_hflags_m32(cpu_env, tcg_el); - } else { - if (ri->type & ARM_CP_NEWEL) { - gen_helper_rebuild_hflags_a32_newel(cpu_env); - } else { - gen_helper_rebuild_hflags_a32(cpu_env, tcg_el); - } - } - tcg_temp_free_i32(tcg_el); + gen_rebuild_hflags(s, ri->type & ARM_CP_NEWEL); /* * We default to ending the TB on a coprocessor register write, * but allow this to be suppressed by the register definition @@ -6426,7 +6451,7 @@ static bool trans_MSR_v7m(DisasContext *s, arg_MSR_v7m *a) tcg_temp_free_i32(addr); tcg_temp_free_i32(reg); /* If we wrote to CONTROL, the EL might have changed */ - gen_helper_rebuild_hflags_m32_newel(cpu_env); + gen_rebuild_hflags(s, true); gen_lookup_tb(s); return true; } @@ -8878,7 +8903,7 @@ static bool trans_CPS(DisasContext *s, arg_CPS *a) static bool trans_CPS_v7m(DisasContext *s, arg_CPS_v7m *a) { - TCGv_i32 tmp, addr, el; + TCGv_i32 tmp, addr; if (!arm_dc_feature(s, ARM_FEATURE_M)) { return false; @@ -8901,9 +8926,7 @@ static bool trans_CPS_v7m(DisasContext *s, arg_CPS_v7m *a) gen_helper_v7m_msr(cpu_env, addr, tmp); tcg_temp_free_i32(addr); } - el = tcg_const_i32(s->current_el); - gen_helper_rebuild_hflags_m32(cpu_env, el); - tcg_temp_free_i32(el); + gen_rebuild_hflags(s, false); tcg_temp_free_i32(tmp); gen_lookup_tb(s); return true; @@ -9334,7 +9357,7 @@ static void arm_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cs) dc->isar = &cpu->isar; dc->condjmp = 0; - dc->aarch64 = 0; + dc->aarch64 = false; /* If we are coming from secure EL0 in a system with a 32-bit EL3, then * there is no secure EL1, so we route exceptions to EL3. */ @@ -9847,18 +9870,14 @@ static void arm_tr_tb_stop(DisasContextBase *dcbase, CPUState *cpu) /* nothing more to generate */ break; case DISAS_WFI: - { - TCGv_i32 tmp = tcg_const_i32((dc->thumb && - !(dc->insn & (1U << 31))) ? 2 : 4); - - gen_helper_wfi(cpu_env, tmp); - tcg_temp_free_i32(tmp); - /* The helper doesn't necessarily throw an exception, but we + gen_helper_wfi(cpu_env, + tcg_constant_i32(dc->base.pc_next - dc->pc_curr)); + /* + * The helper doesn't necessarily throw an exception, but we * must go back to the main loop to check for interrupts anyway. */ tcg_gen_exit_tb(NULL, 0); break; - } case DISAS_WFE: gen_helper_wfe(cpu_env); break; diff --git a/target/arm/translate.h b/target/arm/translate.h index 3a0db801d3..6f0ebdc88e 100644 --- a/target/arm/translate.h +++ b/target/arm/translate.h @@ -30,7 +30,6 @@ typedef struct DisasContext { bool eci_handled; /* TCG op to rewind to if this turns out to be an invalid ECI state */ TCGOp *insn_eci_rewind; - int thumb; int sctlr_b; MemOp be_data; #if !defined(CONFIG_USER_ONLY) @@ -59,12 +58,13 @@ typedef struct DisasContext { * so that top level loop can generate correct syndrome information. */ uint32_t svc_imm; - int aarch64; int current_el; /* Debug target exception level for single-step exceptions */ int debug_target_el; GHashTable *cp_regs; uint64_t features; /* CPU features bits */ + bool aarch64; + bool thumb; /* Because unallocated encodings generate different exception syndrome * information from traps due to FP being disabled, we can't do a single * "is fp access disabled" check at a high level in the decode tree. @@ -332,16 +332,9 @@ static inline void gen_ss_advance(DisasContext *s) static inline void gen_exception(int excp, uint32_t syndrome, uint32_t target_el) { - TCGv_i32 tcg_excp = tcg_const_i32(excp); - TCGv_i32 tcg_syn = tcg_const_i32(syndrome); - TCGv_i32 tcg_el = tcg_const_i32(target_el); - - gen_helper_exception_with_syndrome(cpu_env, tcg_excp, - tcg_syn, tcg_el); - - tcg_temp_free_i32(tcg_el); - tcg_temp_free_i32(tcg_syn); - tcg_temp_free_i32(tcg_excp); + gen_helper_exception_with_syndrome(cpu_env, tcg_constant_i32(excp), + tcg_constant_i32(syndrome), + tcg_constant_i32(target_el)); } /* Generate an architectural singlestep exception */ diff --git a/target/hexagon/op_helper.c b/target/hexagon/op_helper.c index 63e5ad5d68..a5ed819c04 100644 --- a/target/hexagon/op_helper.c +++ b/target/hexagon/op_helper.c @@ -34,9 +34,10 @@ #define SF_MANTBITS 23 /* Exceptions processing helpers */ -static void QEMU_NORETURN do_raise_exception_err(CPUHexagonState *env, - uint32_t exception, - uintptr_t pc) +static G_NORETURN +void do_raise_exception_err(CPUHexagonState *env, + uint32_t exception, + uintptr_t pc) { CPUState *cs = env_cpu(env); qemu_log_mask(CPU_LOG_INT, "%s: %d\n", __func__, exception); @@ -44,7 +45,7 @@ static void QEMU_NORETURN do_raise_exception_err(CPUHexagonState *env, cpu_loop_exit_restore(cs, pc); } -void QEMU_NORETURN HELPER(raise_exception)(CPUHexagonState *env, uint32_t excp) +G_NORETURN void HELPER(raise_exception)(CPUHexagonState *env, uint32_t excp) { do_raise_exception_err(env, excp, 0); } diff --git a/target/hppa/cpu.c b/target/hppa/cpu.c index 5f46ba801e..a6f52caf14 100644 --- a/target/hppa/cpu.c +++ b/target/hppa/cpu.c @@ -73,10 +73,10 @@ static void hppa_cpu_disas_set_info(CPUState *cs, disassemble_info *info) } #ifndef CONFIG_USER_ONLY -static void QEMU_NORETURN -hppa_cpu_do_unaligned_access(CPUState *cs, vaddr addr, - MMUAccessType access_type, int mmu_idx, - uintptr_t retaddr) +static G_NORETURN +void hppa_cpu_do_unaligned_access(CPUState *cs, vaddr addr, + MMUAccessType access_type, int mmu_idx, + uintptr_t retaddr) { HPPACPU *cpu = HPPA_CPU(cs); CPUHPPAState *env = &cpu->env; diff --git a/target/hppa/cpu.h b/target/hppa/cpu.h index c43b93a68f..6f3b6beecf 100644 --- a/target/hppa/cpu.h +++ b/target/hppa/cpu.h @@ -339,6 +339,6 @@ extern const VMStateDescription vmstate_hppa_cpu; void hppa_cpu_alarm_timer(void *); int hppa_artype_for_page(CPUHPPAState *env, target_ulong vaddr); #endif -void QEMU_NORETURN hppa_dynamic_excp(CPUHPPAState *env, int excp, uintptr_t ra); +G_NORETURN void hppa_dynamic_excp(CPUHPPAState *env, int excp, uintptr_t ra); #endif /* HPPA_CPU_H */ diff --git a/target/hppa/op_helper.c b/target/hppa/op_helper.c index 2810361be0..cd304f051e 100644 --- a/target/hppa/op_helper.c +++ b/target/hppa/op_helper.c @@ -28,7 +28,7 @@ #include "fpu/softfloat.h" #include "trace.h" -void QEMU_NORETURN HELPER(excp)(CPUHPPAState *env, int excp) +G_NORETURN void HELPER(excp)(CPUHPPAState *env, int excp) { CPUState *cs = env_cpu(env); @@ -36,7 +36,7 @@ void QEMU_NORETURN HELPER(excp)(CPUHPPAState *env, int excp) cpu_loop_exit(cs); } -void QEMU_NORETURN hppa_dynamic_excp(CPUHPPAState *env, int excp, uintptr_t ra) +G_NORETURN void hppa_dynamic_excp(CPUHPPAState *env, int excp, uintptr_t ra) { CPUState *cs = env_cpu(env); diff --git a/target/i386/tcg/bpt_helper.c b/target/i386/tcg/bpt_helper.c index b6c1fff16e..bc34ac27fe 100644 --- a/target/i386/tcg/bpt_helper.c +++ b/target/i386/tcg/bpt_helper.c @@ -22,7 +22,7 @@ #include "exec/helper-proto.h" #include "helper-tcg.h" -void QEMU_NORETURN helper_single_step(CPUX86State *env) +G_NORETURN void helper_single_step(CPUX86State *env) { #ifndef CONFIG_USER_ONLY check_hw_breakpoints(env, true); diff --git a/target/i386/tcg/excp_helper.c b/target/i386/tcg/excp_helper.c index bdae887d0a..c1ffa1c0ef 100644 --- a/target/i386/tcg/excp_helper.c +++ b/target/i386/tcg/excp_helper.c @@ -25,13 +25,13 @@ #include "exec/helper-proto.h" #include "helper-tcg.h" -void QEMU_NORETURN helper_raise_interrupt(CPUX86State *env, int intno, +G_NORETURN void helper_raise_interrupt(CPUX86State *env, int intno, int next_eip_addend) { raise_interrupt(env, intno, 1, 0, next_eip_addend); } -void QEMU_NORETURN helper_raise_exception(CPUX86State *env, int exception_index) +G_NORETURN void helper_raise_exception(CPUX86State *env, int exception_index) { raise_exception(env, exception_index); } @@ -87,10 +87,11 @@ static int check_exception(CPUX86State *env, int intno, int *error_code, * env->eip value AFTER the interrupt instruction. It is only relevant if * is_int is TRUE. */ -static void QEMU_NORETURN raise_interrupt2(CPUX86State *env, int intno, - int is_int, int error_code, - int next_eip_addend, - uintptr_t retaddr) +static G_NORETURN +void raise_interrupt2(CPUX86State *env, int intno, + int is_int, int error_code, + int next_eip_addend, + uintptr_t retaddr) { CPUState *cs = env_cpu(env); @@ -111,31 +112,31 @@ static void QEMU_NORETURN raise_interrupt2(CPUX86State *env, int intno, /* shortcuts to generate exceptions */ -void QEMU_NORETURN raise_interrupt(CPUX86State *env, int intno, int is_int, - int error_code, int next_eip_addend) +G_NORETURN void raise_interrupt(CPUX86State *env, int intno, int is_int, + int error_code, int next_eip_addend) { raise_interrupt2(env, intno, is_int, error_code, next_eip_addend, 0); } -void QEMU_NORETURN raise_exception_err(CPUX86State *env, int exception_index, - int error_code) +G_NORETURN void raise_exception_err(CPUX86State *env, int exception_index, + int error_code) { raise_interrupt2(env, exception_index, 0, error_code, 0, 0); } -void QEMU_NORETURN raise_exception_err_ra(CPUX86State *env, int exception_index, - int error_code, uintptr_t retaddr) +G_NORETURN void raise_exception_err_ra(CPUX86State *env, int exception_index, + int error_code, uintptr_t retaddr) { raise_interrupt2(env, exception_index, 0, error_code, 0, retaddr); } -void QEMU_NORETURN raise_exception(CPUX86State *env, int exception_index) +G_NORETURN void raise_exception(CPUX86State *env, int exception_index) { raise_interrupt2(env, exception_index, 0, 0, 0, 0); } -void QEMU_NORETURN raise_exception_ra(CPUX86State *env, int exception_index, - uintptr_t retaddr) +G_NORETURN void raise_exception_ra(CPUX86State *env, int exception_index, + uintptr_t retaddr) { raise_interrupt2(env, exception_index, 0, 0, 0, retaddr); } diff --git a/target/i386/tcg/helper-tcg.h b/target/i386/tcg/helper-tcg.h index 0a4401e917..34167e2e29 100644 --- a/target/i386/tcg/helper-tcg.h +++ b/target/i386/tcg/helper-tcg.h @@ -69,27 +69,27 @@ static inline target_long lshift(target_long x, int n) void tcg_x86_init(void); /* excp_helper.c */ -void QEMU_NORETURN raise_exception(CPUX86State *env, int exception_index); -void QEMU_NORETURN raise_exception_ra(CPUX86State *env, int exception_index, - uintptr_t retaddr); -void QEMU_NORETURN raise_exception_err(CPUX86State *env, int exception_index, - int error_code); -void QEMU_NORETURN raise_exception_err_ra(CPUX86State *env, int exception_index, - int error_code, uintptr_t retaddr); -void QEMU_NORETURN raise_interrupt(CPUX86State *nenv, int intno, int is_int, - int error_code, int next_eip_addend); +G_NORETURN void raise_exception(CPUX86State *env, int exception_index); +G_NORETURN void raise_exception_ra(CPUX86State *env, int exception_index, + uintptr_t retaddr); +G_NORETURN void raise_exception_err(CPUX86State *env, int exception_index, + int error_code); +G_NORETURN void raise_exception_err_ra(CPUX86State *env, int exception_index, + int error_code, uintptr_t retaddr); +G_NORETURN void raise_interrupt(CPUX86State *nenv, int intno, int is_int, + int error_code, int next_eip_addend); /* cc_helper.c */ extern const uint8_t parity_table[256]; /* misc_helper.c */ void cpu_load_eflags(CPUX86State *env, int eflags, int update_mask); -void do_pause(CPUX86State *env) QEMU_NORETURN; +G_NORETURN void do_pause(CPUX86State *env); /* sysemu/svm_helper.c */ #ifndef CONFIG_USER_ONLY -void QEMU_NORETURN cpu_vmexit(CPUX86State *nenv, uint32_t exit_code, - uint64_t exit_info_1, uintptr_t retaddr); +G_NORETURN void cpu_vmexit(CPUX86State *nenv, uint32_t exit_code, + uint64_t exit_info_1, uintptr_t retaddr); void do_vmexit(CPUX86State *env); #endif diff --git a/target/i386/tcg/misc_helper.c b/target/i386/tcg/misc_helper.c index 24a0eaa3d5..5f7a3061ca 100644 --- a/target/i386/tcg/misc_helper.c +++ b/target/i386/tcg/misc_helper.c @@ -81,7 +81,7 @@ void helper_rdtscp(CPUX86State *env) env->regs[R_ECX] = (uint32_t)(env->tsc_aux); } -void QEMU_NORETURN helper_rdpmc(CPUX86State *env) +G_NORETURN void helper_rdpmc(CPUX86State *env) { if (((env->cr[4] & CR4_PCE_MASK) == 0 ) && ((env->hflags & HF_CPL_MASK) != 0)) { @@ -94,7 +94,7 @@ void QEMU_NORETURN helper_rdpmc(CPUX86State *env) raise_exception_err(env, EXCP06_ILLOP, 0); } -void QEMU_NORETURN do_pause(CPUX86State *env) +G_NORETURN void do_pause(CPUX86State *env) { CPUState *cs = env_cpu(env); @@ -103,7 +103,7 @@ void QEMU_NORETURN do_pause(CPUX86State *env) cpu_loop_exit(cs); } -void QEMU_NORETURN helper_pause(CPUX86State *env, int next_eip_addend) +G_NORETURN void helper_pause(CPUX86State *env, int next_eip_addend) { cpu_svm_check_intercept_param(env, SVM_EXIT_PAUSE, 0, GETPC()); env->eip += next_eip_addend; diff --git a/target/i386/tcg/sysemu/misc_helper.c b/target/i386/tcg/sysemu/misc_helper.c index 3715c1e262..1328aa656f 100644 --- a/target/i386/tcg/sysemu/misc_helper.c +++ b/target/i386/tcg/sysemu/misc_helper.c @@ -471,7 +471,8 @@ void helper_flush_page(CPUX86State *env, target_ulong addr) tlb_flush_page(env_cpu(env), addr); } -static void QEMU_NORETURN do_hlt(CPUX86State *env) +static G_NORETURN +void do_hlt(CPUX86State *env) { CPUState *cs = env_cpu(env); @@ -481,7 +482,7 @@ static void QEMU_NORETURN do_hlt(CPUX86State *env) cpu_loop_exit(cs); } -void QEMU_NORETURN helper_hlt(CPUX86State *env, int next_eip_addend) +G_NORETURN void helper_hlt(CPUX86State *env, int next_eip_addend) { cpu_svm_check_intercept_param(env, SVM_EXIT_HLT, 0, GETPC()); env->eip += next_eip_addend; @@ -498,7 +499,7 @@ void helper_monitor(CPUX86State *env, target_ulong ptr) cpu_svm_check_intercept_param(env, SVM_EXIT_MONITOR, 0, GETPC()); } -void QEMU_NORETURN helper_mwait(CPUX86State *env, int next_eip_addend) +G_NORETURN void helper_mwait(CPUX86State *env, int next_eip_addend) { CPUState *cs = env_cpu(env); diff --git a/target/microblaze/cpu.h b/target/microblaze/cpu.h index 67aa88b8db..1e84dd8f47 100644 --- a/target/microblaze/cpu.h +++ b/target/microblaze/cpu.h @@ -359,9 +359,9 @@ struct ArchCPU { void mb_cpu_do_interrupt(CPUState *cs); bool mb_cpu_exec_interrupt(CPUState *cs, int int_req); #endif /* !CONFIG_USER_ONLY */ -void mb_cpu_do_unaligned_access(CPUState *cs, vaddr vaddr, - MMUAccessType access_type, - int mmu_idx, uintptr_t retaddr) QEMU_NORETURN; +G_NORETURN void mb_cpu_do_unaligned_access(CPUState *cs, vaddr vaddr, + MMUAccessType access_type, + int mmu_idx, uintptr_t retaddr); void mb_cpu_dump_state(CPUState *cpu, FILE *f, int flags); hwaddr mb_cpu_get_phys_page_attrs_debug(CPUState *cpu, vaddr addr, MemTxAttrs *attrs); diff --git a/target/mips/tcg/tcg-internal.h b/target/mips/tcg/tcg-internal.h index 466768aec4..993720b00c 100644 --- a/target/mips/tcg/tcg-internal.h +++ b/target/mips/tcg/tcg-internal.h @@ -18,18 +18,19 @@ void mips_tcg_init(void); void mips_cpu_synchronize_from_tb(CPUState *cs, const TranslationBlock *tb); -void mips_cpu_do_unaligned_access(CPUState *cpu, vaddr addr, - MMUAccessType access_type, int mmu_idx, - uintptr_t retaddr) QEMU_NORETURN; +G_NORETURN void mips_cpu_do_unaligned_access(CPUState *cpu, vaddr addr, + MMUAccessType access_type, int mmu_idx, + uintptr_t retaddr); const char *mips_exception_name(int32_t exception); -void QEMU_NORETURN do_raise_exception_err(CPUMIPSState *env, uint32_t exception, - int error_code, uintptr_t pc); +G_NORETURN void do_raise_exception_err(CPUMIPSState *env, uint32_t exception, + int error_code, uintptr_t pc); -static inline void QEMU_NORETURN do_raise_exception(CPUMIPSState *env, - uint32_t exception, - uintptr_t pc) +static inline G_NORETURN +void do_raise_exception(CPUMIPSState *env, + uint32_t exception, + uintptr_t pc) { do_raise_exception_err(env, exception, 0, pc); } diff --git a/target/nios2/cpu.h b/target/nios2/cpu.h index ca0f3420cd..1bab805bb0 100644 --- a/target/nios2/cpu.h +++ b/target/nios2/cpu.h @@ -194,9 +194,9 @@ void nios2_cpu_do_interrupt(CPUState *cs); void dump_mmu(CPUNios2State *env); void nios2_cpu_dump_state(CPUState *cpu, FILE *f, int flags); hwaddr nios2_cpu_get_phys_page_debug(CPUState *cpu, vaddr addr); -void nios2_cpu_do_unaligned_access(CPUState *cpu, vaddr addr, - MMUAccessType access_type, int mmu_idx, - uintptr_t retaddr) QEMU_NORETURN; +G_NORETURN void nios2_cpu_do_unaligned_access(CPUState *cpu, vaddr addr, + MMUAccessType access_type, int mmu_idx, + uintptr_t retaddr); void do_nios2_semihosting(CPUNios2State *env); diff --git a/target/openrisc/exception.c b/target/openrisc/exception.c index 28c1fce523..8699c3dcea 100644 --- a/target/openrisc/exception.c +++ b/target/openrisc/exception.c @@ -22,7 +22,7 @@ #include "exec/exec-all.h" #include "exception.h" -void QEMU_NORETURN raise_exception(OpenRISCCPU *cpu, uint32_t excp) +G_NORETURN void raise_exception(OpenRISCCPU *cpu, uint32_t excp) { CPUState *cs = CPU(cpu); diff --git a/target/openrisc/exception.h b/target/openrisc/exception.h index 333bf84638..f62fc314c1 100644 --- a/target/openrisc/exception.h +++ b/target/openrisc/exception.h @@ -22,6 +22,6 @@ #include "cpu.h" -void QEMU_NORETURN raise_exception(OpenRISCCPU *cpu, uint32_t excp); +G_NORETURN void raise_exception(OpenRISCCPU *cpu, uint32_t excp); #endif /* TARGET_OPENRISC_EXCEPTION_H */ diff --git a/target/openrisc/exception_helper.c b/target/openrisc/exception_helper.c index d02a1cf0aa..1f5be4bed9 100644 --- a/target/openrisc/exception_helper.c +++ b/target/openrisc/exception_helper.c @@ -30,7 +30,8 @@ void HELPER(exception)(CPUOpenRISCState *env, uint32_t excp) raise_exception(cpu, excp); } -static void QEMU_NORETURN do_range(CPUOpenRISCState *env, uintptr_t pc) +static G_NORETURN +void do_range(CPUOpenRISCState *env, uintptr_t pc) { CPUState *cs = env_cpu(env); diff --git a/target/ppc/cpu.h b/target/ppc/cpu.h index 473436a49e..c2b6c987c0 100644 --- a/target/ppc/cpu.h +++ b/target/ppc/cpu.h @@ -2492,13 +2492,13 @@ static inline void cpu_get_tb_cpu_state(CPUPPCState *env, target_ulong *pc, } #endif -void QEMU_NORETURN raise_exception(CPUPPCState *env, uint32_t exception); -void QEMU_NORETURN raise_exception_ra(CPUPPCState *env, uint32_t exception, - uintptr_t raddr); -void QEMU_NORETURN raise_exception_err(CPUPPCState *env, uint32_t exception, - uint32_t error_code); -void QEMU_NORETURN raise_exception_err_ra(CPUPPCState *env, uint32_t exception, - uint32_t error_code, uintptr_t raddr); +G_NORETURN void raise_exception(CPUPPCState *env, uint32_t exception); +G_NORETURN void raise_exception_ra(CPUPPCState *env, uint32_t exception, + uintptr_t raddr); +G_NORETURN void raise_exception_err(CPUPPCState *env, uint32_t exception, + uint32_t error_code); +G_NORETURN void raise_exception_err_ra(CPUPPCState *env, uint32_t exception, + uint32_t error_code, uintptr_t raddr); /* PERFM EBB helper*/ #if defined(TARGET_PPC64) && !defined(CONFIG_USER_ONLY) diff --git a/target/ppc/cpu_init.c b/target/ppc/cpu_init.c index 5062d0e478..d42e2ba8e0 100644 --- a/target/ppc/cpu_init.c +++ b/target/ppc/cpu_init.c @@ -6457,6 +6457,7 @@ static void init_proc_POWER10(CPUPPCState *env) register_power5p_common_sprs(env); register_power5p_lpar_sprs(env); register_power5p_ear_sprs(env); + register_power5p_tb_sprs(env); register_power6_common_sprs(env); register_power6_dbg_sprs(env); register_power8_tce_address_control_sprs(env); @@ -6467,6 +6468,7 @@ static void init_proc_POWER10(CPUPPCState *env) register_power8_pmu_user_sprs(env); register_power8_tm_sprs(env); register_power8_pspb_sprs(env); + register_power8_dpdes_sprs(env); register_vtb_sprs(env); register_power8_ic_sprs(env); register_power8_book4_sprs(env); diff --git a/target/ppc/fpu_helper.c b/target/ppc/fpu_helper.c index 7e8be99cc0..99281cc37a 100644 --- a/target/ppc/fpu_helper.c +++ b/target/ppc/fpu_helper.c @@ -2925,6 +2925,27 @@ VSX_CVT_FP_TO_INT(xvcvspsxws, 4, float32, int32, VsrW(i), VsrW(i), 0x80000000U) VSX_CVT_FP_TO_INT(xvcvspuxds, 2, float32, uint64, VsrW(2 * i), VsrD(i), 0ULL) VSX_CVT_FP_TO_INT(xvcvspuxws, 4, float32, uint32, VsrW(i), VsrW(i), 0U) +#define VSX_CVT_FP_TO_INT128(op, tp, rnan) \ +void helper_##op(CPUPPCState *env, ppc_vsr_t *xt, ppc_vsr_t *xb) \ +{ \ + ppc_vsr_t t; \ + int flags; \ + \ + helper_reset_fpstatus(env); \ + t.s128 = float128_to_##tp##_round_to_zero(xb->f128, &env->fp_status); \ + flags = get_float_exception_flags(&env->fp_status); \ + if (unlikely(flags & float_flag_invalid)) { \ + t.VsrD(0) = float_invalid_cvt(env, flags, t.VsrD(0), rnan, 0, GETPC());\ + t.VsrD(1) = -(t.VsrD(0) & 1); \ + } \ + \ + *xt = t; \ + do_float_check_status(env, GETPC()); \ +} + +VSX_CVT_FP_TO_INT128(XSCVQPUQZ, uint128, 0) +VSX_CVT_FP_TO_INT128(XSCVQPSQZ, int128, 0x8000000000000000ULL); + /* * Likewise, except that the result is duplicated into both subwords. * Power ISA v3.1 has Programming Notes for these insns: @@ -3058,6 +3079,18 @@ void helper_##op(CPUPPCState *env, ppc_vsr_t *xt, ppc_vsr_t *xb) \ VSX_CVT_INT_TO_FP2(xvcvsxdsp, int64, float32) VSX_CVT_INT_TO_FP2(xvcvuxdsp, uint64, float32) +#define VSX_CVT_INT128_TO_FP(op, tp) \ +void helper_##op(CPUPPCState *env, ppc_vsr_t *xt, ppc_vsr_t *xb)\ +{ \ + helper_reset_fpstatus(env); \ + xt->f128 = tp##_to_float128(xb->s128, &env->fp_status); \ + helper_compute_fprf_float128(env, xt->f128); \ + do_float_check_status(env, GETPC()); \ +} + +VSX_CVT_INT128_TO_FP(XSCVUQQP, uint128); +VSX_CVT_INT128_TO_FP(XSCVSQQP, int128); + /* * VSX_CVT_INT_TO_FP_VECTOR - VSX integer to floating point conversion * op - instruction mnemonic diff --git a/target/ppc/helper.h b/target/ppc/helper.h index 57da11c77e..aa6773c4a5 100644 --- a/target/ppc/helper.h +++ b/target/ppc/helper.h @@ -388,6 +388,10 @@ DEF_HELPER_4(xscvqpsdz, void, env, i32, vsr, vsr) DEF_HELPER_4(xscvqpswz, void, env, i32, vsr, vsr) DEF_HELPER_4(xscvqpudz, void, env, i32, vsr, vsr) DEF_HELPER_4(xscvqpuwz, void, env, i32, vsr, vsr) +DEF_HELPER_3(XSCVQPUQZ, void, env, vsr, vsr) +DEF_HELPER_3(XSCVQPSQZ, void, env, vsr, vsr) +DEF_HELPER_3(XSCVUQQP, void, env, vsr, vsr) +DEF_HELPER_3(XSCVSQQP, void, env, vsr, vsr) DEF_HELPER_3(xscvhpdp, void, env, vsr, vsr) DEF_HELPER_4(xscvsdqp, void, env, i32, vsr, vsr) DEF_HELPER_3(xscvspdp, void, env, vsr, vsr) diff --git a/target/ppc/insn32.decode b/target/ppc/insn32.decode index ac2d3da9a7..39372fe673 100644 --- a/target/ppc/insn32.decode +++ b/target/ppc/insn32.decode @@ -91,6 +91,9 @@ @X_tp_a_bp_rc ...... ....0 ra:5 ....0 .......... rc:1 &X_rc rt=%x_frtp rb=%x_frbp +&X_tb rt rb +@X_tb ...... rt:5 ..... rb:5 .......... . &X_tb + &X_tb_rc rt rb rc:bool @X_tb_rc ...... rt:5 ..... rb:5 .......... rc:1 &X_tb_rc @@ -692,6 +695,10 @@ XSCMPGTQP 111111 ..... ..... ..... 0011100100 - @X ## VSX Binary Floating-Point Convert Instructions XSCVQPDP 111111 ..... 10100 ..... 1101000100 . @X_tb_rc +XSCVQPUQZ 111111 ..... 00000 ..... 1101000100 - @X_tb +XSCVQPSQZ 111111 ..... 01000 ..... 1101000100 - @X_tb +XSCVUQQP 111111 ..... 00011 ..... 1101000100 - @X_tb +XSCVSQQP 111111 ..... 01011 ..... 1101000100 - @X_tb XVCVBF16SPN 111100 ..... 10000 ..... 111011011 .. @XX2 XVCVSPBF16 111100 ..... 10001 ..... 111011011 .. @XX2 diff --git a/target/ppc/internal.h b/target/ppc/internal.h index 6aa9484f34..8094e0b033 100644 --- a/target/ppc/internal.h +++ b/target/ppc/internal.h @@ -286,9 +286,9 @@ void ppc_cpu_record_sigsegv(CPUState *cs, vaddr addr, bool ppc_cpu_tlb_fill(CPUState *cs, vaddr address, int size, MMUAccessType access_type, int mmu_idx, bool probe, uintptr_t retaddr); -void ppc_cpu_do_unaligned_access(CPUState *cs, vaddr addr, - MMUAccessType access_type, int mmu_idx, - uintptr_t retaddr) QEMU_NORETURN; +G_NORETURN void ppc_cpu_do_unaligned_access(CPUState *cs, vaddr addr, + MMUAccessType access_type, int mmu_idx, + uintptr_t retaddr); #endif #endif /* PPC_INTERNAL_H */ diff --git a/target/ppc/kvm.c b/target/ppc/kvm.c index f905a2af17..a3c31b4e48 100644 --- a/target/ppc/kvm.c +++ b/target/ppc/kvm.c @@ -1680,7 +1680,7 @@ int kvm_arch_handle_exit(CPUState *cs, struct kvm_run *run) break; #if defined(TARGET_PPC64) case KVM_EXIT_PAPR_HCALL: - trace_kvm_handle_papr_hcall(); + trace_kvm_handle_papr_hcall(run->papr_hcall.nr); run->papr_hcall.ret = spapr_hypercall(cpu, run->papr_hcall.nr, run->papr_hcall.args); diff --git a/target/ppc/trace-events b/target/ppc/trace-events index 53b107f56e..a79f1b4370 100644 --- a/target/ppc/trace-events +++ b/target/ppc/trace-events @@ -23,7 +23,7 @@ kvm_failed_get_vpa(void) "Warning: Unable to get VPA information from KVM" kvm_handle_dcr_write(void) "handle dcr write" kvm_handle_dcr_read(void) "handle dcr read" kvm_handle_halt(void) "handle halt" -kvm_handle_papr_hcall(void) "handle PAPR hypercall" +kvm_handle_papr_hcall(uint64_t hcall) "0x%" PRIx64 kvm_handle_epr(void) "handle epr" kvm_handle_watchdog_expiry(void) "handle watchdog expiry" kvm_handle_debug_exception(void) "handle debug exception" diff --git a/target/ppc/translate/vsx-impl.c.inc b/target/ppc/translate/vsx-impl.c.inc index 7181a672d8..3692740736 100644 --- a/target/ppc/translate/vsx-impl.c.inc +++ b/target/ppc/translate/vsx-impl.c.inc @@ -838,6 +838,28 @@ static bool trans_XSCVQPDP(DisasContext *ctx, arg_X_tb_rc *a) return true; } +static bool do_helper_env_X_tb(DisasContext *ctx, arg_X_tb *a, + void (*gen_helper)(TCGv_ptr, TCGv_ptr, TCGv_ptr)) +{ + TCGv_ptr xt, xb; + + REQUIRE_INSNS_FLAGS2(ctx, ISA310); + REQUIRE_VSX(ctx); + + xt = gen_avr_ptr(a->rt); + xb = gen_avr_ptr(a->rb); + gen_helper(cpu_env, xt, xb); + tcg_temp_free_ptr(xt); + tcg_temp_free_ptr(xb); + + return true; +} + +TRANS(XSCVUQQP, do_helper_env_X_tb, gen_helper_XSCVUQQP) +TRANS(XSCVSQQP, do_helper_env_X_tb, gen_helper_XSCVSQQP) +TRANS(XSCVQPUQZ, do_helper_env_X_tb, gen_helper_XSCVQPUQZ) +TRANS(XSCVQPSQZ, do_helper_env_X_tb, gen_helper_XSCVQPSQZ) + #define GEN_VSX_HELPER_2(name, op1, op2, inval, type) \ static void gen_##name(DisasContext *ctx) \ { \ diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c index ddda4906ff..0c774056c5 100644 --- a/target/riscv/cpu.c +++ b/target/riscv/cpu.c @@ -34,7 +34,12 @@ /* RISC-V CPU definitions */ -static const char riscv_exts[26] = "IEMAFDQCLBJTPVNSUHKORWXYZG"; +static const char riscv_single_letter_exts[] = "IEMAFDQCPVH"; + +struct isa_ext_data { + const char *name; + bool enabled; +}; const char * const riscv_int_regnames[] = { "x0/zero", "x1/ra", "x2/sp", "x3/gp", "x4/tp", "x5/t0", "x6/t1", @@ -150,7 +155,7 @@ static void riscv_any_cpu_init(Object *obj) #elif defined(TARGET_RISCV64) set_misa(env, MXL_RV64, RVI | RVM | RVA | RVF | RVD | RVC | RVU); #endif - set_priv_version(env, PRIV_VERSION_1_11_0); + set_priv_version(env, PRIV_VERSION_1_12_0); } #if defined(TARGET_RISCV64) @@ -461,6 +466,10 @@ static void riscv_cpu_reset(DeviceState *dev) set_default_nan_mode(1, &env->fp_status); #ifndef CONFIG_USER_ONLY + if (riscv_feature(env, RISCV_FEATURE_DEBUG)) { + riscv_trigger_init(env); + } + if (kvm_enabled()) { kvm_riscv_reset_vcpu(cpu); } @@ -503,7 +512,9 @@ static void riscv_cpu_realize(DeviceState *dev, Error **errp) } if (cpu->cfg.priv_spec) { - if (!g_strcmp0(cpu->cfg.priv_spec, "v1.11.0")) { + if (!g_strcmp0(cpu->cfg.priv_spec, "v1.12.0")) { + priv_version = PRIV_VERSION_1_12_0; + } else if (!g_strcmp0(cpu->cfg.priv_spec, "v1.11.0")) { priv_version = PRIV_VERSION_1_11_0; } else if (!g_strcmp0(cpu->cfg.priv_spec, "v1.10.0")) { priv_version = PRIV_VERSION_1_10_0; @@ -518,7 +529,7 @@ static void riscv_cpu_realize(DeviceState *dev, Error **errp) if (priv_version) { set_priv_version(env, priv_version); } else if (!env->priv_ver) { - set_priv_version(env, PRIV_VERSION_1_11_0); + set_priv_version(env, PRIV_VERSION_1_12_0); } if (cpu->cfg.mmu) { @@ -541,6 +552,10 @@ static void riscv_cpu_realize(DeviceState *dev, Error **errp) riscv_set_feature(env, RISCV_FEATURE_AIA); } + if (cpu->cfg.debug) { + riscv_set_feature(env, RISCV_FEATURE_DEBUG); + } + set_resetvec(env, cpu->cfg.resetvec); /* Validate that MISA_MXL is set properly. */ @@ -567,18 +582,18 @@ static void riscv_cpu_realize(DeviceState *dev, Error **errp) if (cpu->cfg.ext_i && cpu->cfg.ext_e) { error_setg(errp, "I and E extensions are incompatible"); - return; - } + return; + } if (!cpu->cfg.ext_i && !cpu->cfg.ext_e) { error_setg(errp, "Either I or E extension must be set"); - return; - } + return; + } - if (cpu->cfg.ext_g && !(cpu->cfg.ext_i & cpu->cfg.ext_m & - cpu->cfg.ext_a & cpu->cfg.ext_f & - cpu->cfg.ext_d)) { + if (cpu->cfg.ext_g && !(cpu->cfg.ext_i & cpu->cfg.ext_m & + cpu->cfg.ext_a & cpu->cfg.ext_f & + cpu->cfg.ext_d)) { warn_report("Setting G will also set IMAFD"); cpu->cfg.ext_i = true; cpu->cfg.ext_m = true; @@ -706,15 +721,23 @@ static void riscv_cpu_set_irq(void *opaque, int irq, int level) case IRQ_VS_TIMER: case IRQ_M_TIMER: case IRQ_U_EXT: - case IRQ_S_EXT: case IRQ_VS_EXT: case IRQ_M_EXT: - if (kvm_enabled()) { + if (kvm_enabled()) { kvm_riscv_set_irq(cpu, irq, level); - } else { + } else { riscv_cpu_update_mip(cpu, 1 << irq, BOOL_TO_MASK(level)); - } + } break; + case IRQ_S_EXT: + if (kvm_enabled()) { + kvm_riscv_set_irq(cpu, irq, level); + } else { + env->external_seip = level; + riscv_cpu_update_mip(cpu, 1 << irq, + BOOL_TO_MASK(level | env->software_seip)); + } + break; default: g_assert_not_reached(); } @@ -780,6 +803,7 @@ static Property riscv_cpu_properties[] = { DEFINE_PROP_BOOL("Zve64f", RISCVCPU, cfg.ext_zve64f, false), DEFINE_PROP_BOOL("mmu", RISCVCPU, cfg.mmu, true), DEFINE_PROP_BOOL("pmp", RISCVCPU, cfg.pmp, true), + DEFINE_PROP_BOOL("debug", RISCVCPU, cfg.debug, true), DEFINE_PROP_STRING("priv_spec", RISCVCPU, cfg.priv_spec), DEFINE_PROP_STRING("vext_spec", RISCVCPU, cfg.vext_spec), @@ -865,6 +889,9 @@ static const struct TCGCPUOps riscv_tcg_ops = { .do_interrupt = riscv_cpu_do_interrupt, .do_transaction_failed = riscv_cpu_do_transaction_failed, .do_unaligned_access = riscv_cpu_do_unaligned_access, + .debug_excp_handler = riscv_cpu_debug_excp_handler, + .debug_check_breakpoint = riscv_cpu_debug_check_breakpoint, + .debug_check_watchpoint = riscv_cpu_debug_check_watchpoint, #endif /* !CONFIG_USER_ONLY */ }; @@ -898,18 +925,73 @@ static void riscv_cpu_class_init(ObjectClass *c, void *data) device_class_set_props(dc, riscv_cpu_properties); } +#define ISA_EDATA_ENTRY(name, prop) {#name, cpu->cfg.prop} + +static void riscv_isa_string_ext(RISCVCPU *cpu, char **isa_str, int max_str_len) +{ + char *old = *isa_str; + char *new = *isa_str; + int i; + + /** + * Here are the ordering rules of extension naming defined by RISC-V + * specification : + * 1. All extensions should be separated from other multi-letter extensions + * by an underscore. + * 2. The first letter following the 'Z' conventionally indicates the most + * closely related alphabetical extension category, IMAFDQLCBKJTPVH. + * If multiple 'Z' extensions are named, they should be ordered first + * by category, then alphabetically within a category. + * 3. Standard supervisor-level extensions (starts with 'S') should be + * listed after standard unprivileged extensions. If multiple + * supervisor-level extensions are listed, they should be ordered + * alphabetically. + * 4. Non-standard extensions (starts with 'X') must be listed after all + * standard extensions. They must be separated from other multi-letter + * extensions by an underscore. + */ + struct isa_ext_data isa_edata_arr[] = { + ISA_EDATA_ENTRY(zfh, ext_zfh), + ISA_EDATA_ENTRY(zfhmin, ext_zfhmin), + ISA_EDATA_ENTRY(zfinx, ext_zfinx), + ISA_EDATA_ENTRY(zhinx, ext_zhinx), + ISA_EDATA_ENTRY(zhinxmin, ext_zhinxmin), + ISA_EDATA_ENTRY(zdinx, ext_zdinx), + ISA_EDATA_ENTRY(zba, ext_zba), + ISA_EDATA_ENTRY(zbb, ext_zbb), + ISA_EDATA_ENTRY(zbc, ext_zbc), + ISA_EDATA_ENTRY(zbs, ext_zbs), + ISA_EDATA_ENTRY(zve32f, ext_zve32f), + ISA_EDATA_ENTRY(zve64f, ext_zve64f), + ISA_EDATA_ENTRY(svinval, ext_svinval), + ISA_EDATA_ENTRY(svnapot, ext_svnapot), + ISA_EDATA_ENTRY(svpbmt, ext_svpbmt), + }; + + for (i = 0; i < ARRAY_SIZE(isa_edata_arr); i++) { + if (isa_edata_arr[i].enabled) { + new = g_strconcat(old, "_", isa_edata_arr[i].name, NULL); + g_free(old); + old = new; + } + } + + *isa_str = new; +} + char *riscv_isa_string(RISCVCPU *cpu) { int i; - const size_t maxlen = sizeof("rv128") + sizeof(riscv_exts) + 1; + const size_t maxlen = sizeof("rv128") + sizeof(riscv_single_letter_exts); char *isa_str = g_new(char, maxlen); char *p = isa_str + snprintf(isa_str, maxlen, "rv%d", TARGET_LONG_BITS); - for (i = 0; i < sizeof(riscv_exts); i++) { - if (cpu->env.misa_ext & RV(riscv_exts[i])) { - *p++ = qemu_tolower(riscv_exts[i]); + for (i = 0; i < sizeof(riscv_single_letter_exts) - 1; i++) { + if (cpu->env.misa_ext & RV(riscv_single_letter_exts[i])) { + *p++ = qemu_tolower(riscv_single_letter_exts[i]); } } *p = '\0'; + riscv_isa_string_ext(cpu, &isa_str, maxlen); return isa_str; } diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h index e1d976bdef..34c22d5d3b 100644 --- a/target/riscv/cpu.h +++ b/target/riscv/cpu.h @@ -79,11 +79,16 @@ enum { RISCV_FEATURE_PMP, RISCV_FEATURE_EPMP, RISCV_FEATURE_MISA, - RISCV_FEATURE_AIA + RISCV_FEATURE_AIA, + RISCV_FEATURE_DEBUG }; -#define PRIV_VERSION_1_10_0 0x00011000 -#define PRIV_VERSION_1_11_0 0x00011100 +/* Privileged specification version */ +enum { + PRIV_VERSION_1_10_0 = 0, + PRIV_VERSION_1_11_0, + PRIV_VERSION_1_12_0, +}; #define VEXT_VERSION_1_00_0 0x00010000 @@ -102,6 +107,7 @@ typedef struct CPUArchState CPURISCVState; #if !defined(CONFIG_USER_ONLY) #include "pmp.h" +#include "debug.h" #endif #define RV_VLEN_MAX 1024 @@ -173,6 +179,14 @@ struct CPUArchState { uint64_t mstatus; uint64_t mip; + /* + * MIP contains the software writable version of SEIP ORed with the + * external interrupt value. The MIP register is always up-to-date. + * To keep track of the current source, we also save booleans of the values + * here. + */ + bool external_seip; + bool software_seip; uint64_t miclaim; @@ -267,9 +281,13 @@ struct CPUArchState { pmp_table_t pmp_state; target_ulong mseccfg; + /* trigger module */ + target_ulong trigger_cur; + type2_trigger_t type2_trig[TRIGGER_TYPE2_NUM]; + /* machine specific rdtime callback */ - uint64_t (*rdtime_fn)(uint32_t); - uint32_t rdtime_fn_arg; + uint64_t (*rdtime_fn)(void *); + void *rdtime_fn_arg; /* machine specific AIA ireg read-modify-write callback */ #define AIA_MAKE_IREG(__isel, __priv, __virt, __vgein, __xlen) \ @@ -300,6 +318,11 @@ struct CPUArchState { target_ulong spmbase; target_ulong upmmask; target_ulong upmbase; + + /* CSRs for execution enviornment configuration */ + uint64_t menvcfg; + target_ulong senvcfg; + uint64_t henvcfg; #endif target_ulong cur_pmmask; target_ulong cur_pmbase; @@ -383,6 +406,7 @@ struct RISCVCPUConfig { bool pmp; bool epmp; bool aia; + bool debug; uint64_t resetvec; }; @@ -451,9 +475,9 @@ void riscv_cpu_set_virt_enabled(CPURISCVState *env, bool enable); bool riscv_cpu_two_stage_lookup(int mmu_idx); int riscv_cpu_mmu_index(CPURISCVState *env, bool ifetch); hwaddr riscv_cpu_get_phys_page_debug(CPUState *cpu, vaddr addr); -void riscv_cpu_do_unaligned_access(CPUState *cs, vaddr addr, - MMUAccessType access_type, int mmu_idx, - uintptr_t retaddr) QEMU_NORETURN; +G_NORETURN void riscv_cpu_do_unaligned_access(CPUState *cs, vaddr addr, + MMUAccessType access_type, int mmu_idx, + uintptr_t retaddr); bool riscv_cpu_tlb_fill(CPUState *cs, vaddr address, int size, MMUAccessType access_type, int mmu_idx, bool probe, uintptr_t retaddr); @@ -474,8 +498,8 @@ void riscv_cpu_swap_hypervisor_regs(CPURISCVState *env); int riscv_cpu_claim_interrupts(RISCVCPU *cpu, uint64_t interrupts); uint64_t riscv_cpu_update_mip(RISCVCPU *cpu, uint64_t mask, uint64_t value); #define BOOL_TO_MASK(x) (-!!(x)) /* helper for riscv_cpu_update_mip value */ -void riscv_cpu_set_rdtime_fn(CPURISCVState *env, uint64_t (*fn)(uint32_t), - uint32_t arg); +void riscv_cpu_set_rdtime_fn(CPURISCVState *env, uint64_t (*fn)(void *), + void *arg); void riscv_cpu_set_aia_ireg_rmw_fn(CPURISCVState *env, uint32_t priv, int (*rmw_fn)(void *arg, target_ulong reg, @@ -487,8 +511,8 @@ void riscv_cpu_set_aia_ireg_rmw_fn(CPURISCVState *env, uint32_t priv, void riscv_cpu_set_mode(CPURISCVState *env, target_ulong newpriv); void riscv_translate_init(void); -void QEMU_NORETURN riscv_raise_exception(CPURISCVState *env, - uint32_t exception, uintptr_t pc); +G_NORETURN void riscv_raise_exception(CPURISCVState *env, + uint32_t exception, uintptr_t pc); target_ulong riscv_cpu_get_fflags(CPURISCVState *env); void riscv_cpu_set_fflags(CPURISCVState *env, target_ulong); @@ -654,6 +678,8 @@ typedef struct { riscv_csr_op_fn op; riscv_csr_read128_fn read128; riscv_csr_write128_fn write128; + /* The default priv spec version should be PRIV_VERSION_1_10_0 (i.e 0) */ + uint32_t min_priv_ver; } riscv_csr_operations; /* CSR function table constants */ diff --git a/target/riscv/cpu_bits.h b/target/riscv/cpu_bits.h index 0fe01d7da5..4a9e4f7d09 100644 --- a/target/riscv/cpu_bits.h +++ b/target/riscv/cpu_bits.h @@ -148,6 +148,7 @@ #define CSR_MARCHID 0xf12 #define CSR_MIMPID 0xf13 #define CSR_MHARTID 0xf14 +#define CSR_MCONFIGPTR 0xf15 /* Machine Trap Setup */ #define CSR_MSTATUS 0x300 @@ -201,6 +202,9 @@ #define CSR_STVEC 0x105 #define CSR_SCOUNTEREN 0x106 +/* Supervisor Configuration CSRs */ +#define CSR_SENVCFG 0x10A + /* Supervisor Trap Handling */ #define CSR_SSCRATCH 0x140 #define CSR_SEPC 0x141 @@ -246,6 +250,10 @@ #define CSR_HTIMEDELTA 0x605 #define CSR_HTIMEDELTAH 0x615 +/* Hypervisor Configuration CSRs */ +#define CSR_HENVCFG 0x60A +#define CSR_HENVCFGH 0x61A + /* Virtual CSRs */ #define CSR_VSSTATUS 0x200 #define CSR_VSIE 0x204 @@ -289,6 +297,10 @@ #define CSR_VSIEH 0x214 #define CSR_VSIPH 0x254 +/* Machine Configuration CSRs */ +#define CSR_MENVCFG 0x30A +#define CSR_MENVCFGH 0x31A + /* Enhanced Physical Memory Protection (ePMP) */ #define CSR_MSECCFG 0x747 #define CSR_MSECCFGH 0x757 @@ -662,6 +674,34 @@ typedef enum RISCVException { #define PM_EXT_CLEAN 0x00000002ULL #define PM_EXT_DIRTY 0x00000003ULL +/* Execution enviornment configuration bits */ +#define MENVCFG_FIOM BIT(0) +#define MENVCFG_CBIE (3UL << 4) +#define MENVCFG_CBCFE BIT(6) +#define MENVCFG_CBZE BIT(7) +#define MENVCFG_PBMTE (1ULL << 62) +#define MENVCFG_STCE (1ULL << 63) + +/* For RV32 */ +#define MENVCFGH_PBMTE BIT(30) +#define MENVCFGH_STCE BIT(31) + +#define SENVCFG_FIOM MENVCFG_FIOM +#define SENVCFG_CBIE MENVCFG_CBIE +#define SENVCFG_CBCFE MENVCFG_CBCFE +#define SENVCFG_CBZE MENVCFG_CBZE + +#define HENVCFG_FIOM MENVCFG_FIOM +#define HENVCFG_CBIE MENVCFG_CBIE +#define HENVCFG_CBCFE MENVCFG_CBCFE +#define HENVCFG_CBZE MENVCFG_CBZE +#define HENVCFG_PBMTE MENVCFG_PBMTE +#define HENVCFG_STCE MENVCFG_STCE + +/* For RV32 */ +#define HENVCFGH_PBMTE MENVCFGH_PBMTE +#define HENVCFGH_STCE MENVCFGH_STCE + /* Offsets for every pair of control bits per each priv level */ #define XS_OFFSET 0ULL #define U_OFFSET 2ULL diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c index 1c60fb2e80..e1aa4f2097 100644 --- a/target/riscv/cpu_helper.c +++ b/target/riscv/cpu_helper.c @@ -632,8 +632,8 @@ uint64_t riscv_cpu_update_mip(RISCVCPU *cpu, uint64_t mask, uint64_t value) return old; } -void riscv_cpu_set_rdtime_fn(CPURISCVState *env, uint64_t (*fn)(uint32_t), - uint32_t arg) +void riscv_cpu_set_rdtime_fn(CPURISCVState *env, uint64_t (*fn)(void *), + void *arg) { env->rdtime_fn = fn; env->rdtime_fn_arg = arg; @@ -1150,7 +1150,7 @@ void riscv_cpu_do_transaction_failed(CPUState *cs, hwaddr physaddr, env->badaddr = addr; env->two_stage_lookup = riscv_cpu_virt_enabled(env) || riscv_cpu_two_stage_lookup(mmu_idx); - riscv_raise_exception(&cpu->env, cs->exception_index, retaddr); + cpu_loop_exit_restore(cs, retaddr); } void riscv_cpu_do_unaligned_access(CPUState *cs, vaddr addr, @@ -1175,7 +1175,7 @@ void riscv_cpu_do_unaligned_access(CPUState *cs, vaddr addr, env->badaddr = addr; env->two_stage_lookup = riscv_cpu_virt_enabled(env) || riscv_cpu_two_stage_lookup(mmu_idx); - riscv_raise_exception(env, cs->exception_index, retaddr); + cpu_loop_exit_restore(cs, retaddr); } bool riscv_cpu_tlb_fill(CPUState *cs, vaddr address, int size, @@ -1311,7 +1311,7 @@ bool riscv_cpu_tlb_fill(CPUState *cs, vaddr address, int size, first_stage_error, riscv_cpu_virt_enabled(env) || riscv_cpu_two_stage_lookup(mmu_idx)); - riscv_raise_exception(env, cs->exception_index, retaddr); + cpu_loop_exit_restore(cs, retaddr); } return true; diff --git a/target/riscv/csr.c b/target/riscv/csr.c index 341c2e6f23..6ba85e7b5d 100644 --- a/target/riscv/csr.c +++ b/target/riscv/csr.c @@ -290,6 +290,15 @@ static RISCVException epmp(CPURISCVState *env, int csrno) return RISCV_EXCP_ILLEGAL_INST; } + +static RISCVException debug(CPURISCVState *env, int csrno) +{ + if (riscv_feature(env, RISCV_FEATURE_DEBUG)) { + return RISCV_EXCP_NONE; + } + + return RISCV_EXCP_ILLEGAL_INST; +} #endif /* User Floating-Point CSRs */ @@ -1398,15 +1407,114 @@ static RISCVException write_mtval(CPURISCVState *env, int csrno, return RISCV_EXCP_NONE; } +/* Execution environment configuration setup */ +static RISCVException read_menvcfg(CPURISCVState *env, int csrno, + target_ulong *val) +{ + *val = env->menvcfg; + return RISCV_EXCP_NONE; +} + +static RISCVException write_menvcfg(CPURISCVState *env, int csrno, + target_ulong val) +{ + uint64_t mask = MENVCFG_FIOM | MENVCFG_CBIE | MENVCFG_CBCFE | MENVCFG_CBZE; + + if (riscv_cpu_mxl(env) == MXL_RV64) { + mask |= MENVCFG_PBMTE | MENVCFG_STCE; + } + env->menvcfg = (env->menvcfg & ~mask) | (val & mask); + + return RISCV_EXCP_NONE; +} + +static RISCVException read_menvcfgh(CPURISCVState *env, int csrno, + target_ulong *val) +{ + *val = env->menvcfg >> 32; + return RISCV_EXCP_NONE; +} + +static RISCVException write_menvcfgh(CPURISCVState *env, int csrno, + target_ulong val) +{ + uint64_t mask = MENVCFG_PBMTE | MENVCFG_STCE; + uint64_t valh = (uint64_t)val << 32; + + env->menvcfg = (env->menvcfg & ~mask) | (valh & mask); + + return RISCV_EXCP_NONE; +} + +static RISCVException read_senvcfg(CPURISCVState *env, int csrno, + target_ulong *val) +{ + *val = env->senvcfg; + return RISCV_EXCP_NONE; +} + +static RISCVException write_senvcfg(CPURISCVState *env, int csrno, + target_ulong val) +{ + uint64_t mask = SENVCFG_FIOM | SENVCFG_CBIE | SENVCFG_CBCFE | SENVCFG_CBZE; + + env->senvcfg = (env->senvcfg & ~mask) | (val & mask); + + return RISCV_EXCP_NONE; +} + +static RISCVException read_henvcfg(CPURISCVState *env, int csrno, + target_ulong *val) +{ + *val = env->henvcfg; + return RISCV_EXCP_NONE; +} + +static RISCVException write_henvcfg(CPURISCVState *env, int csrno, + target_ulong val) +{ + uint64_t mask = HENVCFG_FIOM | HENVCFG_CBIE | HENVCFG_CBCFE | HENVCFG_CBZE; + + if (riscv_cpu_mxl(env) == MXL_RV64) { + mask |= HENVCFG_PBMTE | HENVCFG_STCE; + } + + env->henvcfg = (env->henvcfg & ~mask) | (val & mask); + + return RISCV_EXCP_NONE; +} + +static RISCVException read_henvcfgh(CPURISCVState *env, int csrno, + target_ulong *val) +{ + *val = env->henvcfg >> 32; + return RISCV_EXCP_NONE; +} + +static RISCVException write_henvcfgh(CPURISCVState *env, int csrno, + target_ulong val) +{ + uint64_t mask = HENVCFG_PBMTE | HENVCFG_STCE; + uint64_t valh = (uint64_t)val << 32; + + env->henvcfg = (env->henvcfg & ~mask) | (valh & mask); + + return RISCV_EXCP_NONE; +} + static RISCVException rmw_mip64(CPURISCVState *env, int csrno, uint64_t *ret_val, uint64_t new_val, uint64_t wr_mask) { RISCVCPU *cpu = env_archcpu(env); - /* Allow software control of delegable interrupts not claimed by hardware */ - uint64_t old_mip, mask = wr_mask & delegable_ints & ~env->miclaim; + uint64_t old_mip, mask = wr_mask & delegable_ints; uint32_t gin; + if (mask & MIP_SEIP) { + env->software_seip = new_val & MIP_SEIP; + new_val |= env->external_seip * MIP_SEIP; + } + if (mask) { old_mip = riscv_cpu_update_mip(cpu, mask, (new_val & mask)); } else { @@ -2578,6 +2686,48 @@ static RISCVException write_pmpaddr(CPURISCVState *env, int csrno, return RISCV_EXCP_NONE; } +static RISCVException read_tselect(CPURISCVState *env, int csrno, + target_ulong *val) +{ + *val = tselect_csr_read(env); + return RISCV_EXCP_NONE; +} + +static RISCVException write_tselect(CPURISCVState *env, int csrno, + target_ulong val) +{ + tselect_csr_write(env, val); + return RISCV_EXCP_NONE; +} + +static RISCVException read_tdata(CPURISCVState *env, int csrno, + target_ulong *val) +{ + /* return 0 in tdata1 to end the trigger enumeration */ + if (env->trigger_cur >= TRIGGER_NUM && csrno == CSR_TDATA1) { + *val = 0; + return RISCV_EXCP_NONE; + } + + if (!tdata_available(env, csrno - CSR_TDATA1)) { + return RISCV_EXCP_ILLEGAL_INST; + } + + *val = tdata_csr_read(env, csrno - CSR_TDATA1); + return RISCV_EXCP_NONE; +} + +static RISCVException write_tdata(CPURISCVState *env, int csrno, + target_ulong val) +{ + if (!tdata_available(env, csrno - CSR_TDATA1)) { + return RISCV_EXCP_ILLEGAL_INST; + } + + tdata_csr_write(env, csrno - CSR_TDATA1, val); + return RISCV_EXCP_NONE; +} + /* * Functions to access Pointer Masking feature registers * We have to check if current priv lvl could modify @@ -2880,6 +3030,7 @@ static inline RISCVException riscv_csrrw_check(CPURISCVState *env, { /* check privileges and return RISCV_EXCP_ILLEGAL_INST if check fails */ int read_only = get_field(csrno, 0xC00) == 3; + int csr_min_priv = csr_ops[csrno].min_priv_ver; #if !defined(CONFIG_USER_ONLY) int effective_priv = env->priv; @@ -2912,6 +3063,10 @@ static inline RISCVException riscv_csrrw_check(CPURISCVState *env, return RISCV_EXCP_ILLEGAL_INST; } + if (env->priv_ver < csr_min_priv) { + return RISCV_EXCP_ILLEGAL_INST; + } + return csr_ops[csrno].predicate(env, csrno); } @@ -3070,13 +3225,20 @@ riscv_csr_operations csr_ops[CSR_TABLE_SIZE] = { [CSR_FRM] = { "frm", fs, read_frm, write_frm }, [CSR_FCSR] = { "fcsr", fs, read_fcsr, write_fcsr }, /* Vector CSRs */ - [CSR_VSTART] = { "vstart", vs, read_vstart, write_vstart }, - [CSR_VXSAT] = { "vxsat", vs, read_vxsat, write_vxsat }, - [CSR_VXRM] = { "vxrm", vs, read_vxrm, write_vxrm }, - [CSR_VCSR] = { "vcsr", vs, read_vcsr, write_vcsr }, - [CSR_VL] = { "vl", vs, read_vl }, - [CSR_VTYPE] = { "vtype", vs, read_vtype }, - [CSR_VLENB] = { "vlenb", vs, read_vlenb }, + [CSR_VSTART] = { "vstart", vs, read_vstart, write_vstart, + .min_priv_ver = PRIV_VERSION_1_12_0 }, + [CSR_VXSAT] = { "vxsat", vs, read_vxsat, write_vxsat, + .min_priv_ver = PRIV_VERSION_1_12_0 }, + [CSR_VXRM] = { "vxrm", vs, read_vxrm, write_vxrm, + .min_priv_ver = PRIV_VERSION_1_12_0 }, + [CSR_VCSR] = { "vcsr", vs, read_vcsr, write_vcsr, + .min_priv_ver = PRIV_VERSION_1_12_0 }, + [CSR_VL] = { "vl", vs, read_vl, + .min_priv_ver = PRIV_VERSION_1_12_0 }, + [CSR_VTYPE] = { "vtype", vs, read_vtype, + .min_priv_ver = PRIV_VERSION_1_12_0 }, + [CSR_VLENB] = { "vlenb", vs, read_vlenb, + .min_priv_ver = PRIV_VERSION_1_12_0 }, /* User Timers and Counters */ [CSR_CYCLE] = { "cycle", ctr, read_instret }, [CSR_INSTRET] = { "instret", ctr, read_instret }, @@ -3103,6 +3265,8 @@ riscv_csr_operations csr_ops[CSR_TABLE_SIZE] = { [CSR_MIMPID] = { "mimpid", any, read_zero }, [CSR_MHARTID] = { "mhartid", any, read_mhartid }, + [CSR_MCONFIGPTR] = { "mconfigptr", any, read_zero, + .min_priv_ver = PRIV_VERSION_1_12_0 }, /* Machine Trap Setup */ [CSR_MSTATUS] = { "mstatus", any, read_mstatus, write_mstatus, NULL, read_mstatus_i128 }, @@ -3149,6 +3313,18 @@ riscv_csr_operations csr_ops[CSR_TABLE_SIZE] = { [CSR_MVIPH] = { "mviph", aia_any32, read_zero, write_ignore }, [CSR_MIPH] = { "miph", aia_any32, NULL, NULL, rmw_miph }, + /* Execution environment configuration */ + [CSR_MENVCFG] = { "menvcfg", any, read_menvcfg, write_menvcfg, + .min_priv_ver = PRIV_VERSION_1_12_0 }, + [CSR_MENVCFGH] = { "menvcfgh", any32, read_menvcfgh, write_menvcfgh, + .min_priv_ver = PRIV_VERSION_1_12_0 }, + [CSR_SENVCFG] = { "senvcfg", smode, read_senvcfg, write_senvcfg, + .min_priv_ver = PRIV_VERSION_1_12_0 }, + [CSR_HENVCFG] = { "henvcfg", hmode, read_henvcfg, write_henvcfg, + .min_priv_ver = PRIV_VERSION_1_12_0 }, + [CSR_HENVCFGH] = { "henvcfgh", hmode32, read_henvcfgh, write_henvcfgh, + .min_priv_ver = PRIV_VERSION_1_12_0 }, + /* Supervisor Trap Setup */ [CSR_SSTATUS] = { "sstatus", smode, read_sstatus, write_sstatus, NULL, read_sstatus_i128 }, @@ -3185,33 +3361,58 @@ riscv_csr_operations csr_ops[CSR_TABLE_SIZE] = { [CSR_SIEH] = { "sieh", aia_smode32, NULL, NULL, rmw_sieh }, [CSR_SIPH] = { "siph", aia_smode32, NULL, NULL, rmw_siph }, - [CSR_HSTATUS] = { "hstatus", hmode, read_hstatus, write_hstatus }, - [CSR_HEDELEG] = { "hedeleg", hmode, read_hedeleg, write_hedeleg }, - [CSR_HIDELEG] = { "hideleg", hmode, NULL, NULL, rmw_hideleg }, - [CSR_HVIP] = { "hvip", hmode, NULL, NULL, rmw_hvip }, - [CSR_HIP] = { "hip", hmode, NULL, NULL, rmw_hip }, - [CSR_HIE] = { "hie", hmode, NULL, NULL, rmw_hie }, - [CSR_HCOUNTEREN] = { "hcounteren", hmode, read_hcounteren, write_hcounteren }, - [CSR_HGEIE] = { "hgeie", hmode, read_hgeie, write_hgeie }, - [CSR_HTVAL] = { "htval", hmode, read_htval, write_htval }, - [CSR_HTINST] = { "htinst", hmode, read_htinst, write_htinst }, - [CSR_HGEIP] = { "hgeip", hmode, read_hgeip, NULL }, - [CSR_HGATP] = { "hgatp", hmode, read_hgatp, write_hgatp }, - [CSR_HTIMEDELTA] = { "htimedelta", hmode, read_htimedelta, write_htimedelta }, - [CSR_HTIMEDELTAH] = { "htimedeltah", hmode32, read_htimedeltah, write_htimedeltah }, - - [CSR_VSSTATUS] = { "vsstatus", hmode, read_vsstatus, write_vsstatus }, - [CSR_VSIP] = { "vsip", hmode, NULL, NULL, rmw_vsip }, - [CSR_VSIE] = { "vsie", hmode, NULL, NULL, rmw_vsie }, - [CSR_VSTVEC] = { "vstvec", hmode, read_vstvec, write_vstvec }, - [CSR_VSSCRATCH] = { "vsscratch", hmode, read_vsscratch, write_vsscratch }, - [CSR_VSEPC] = { "vsepc", hmode, read_vsepc, write_vsepc }, - [CSR_VSCAUSE] = { "vscause", hmode, read_vscause, write_vscause }, - [CSR_VSTVAL] = { "vstval", hmode, read_vstval, write_vstval }, - [CSR_VSATP] = { "vsatp", hmode, read_vsatp, write_vsatp }, - - [CSR_MTVAL2] = { "mtval2", hmode, read_mtval2, write_mtval2 }, - [CSR_MTINST] = { "mtinst", hmode, read_mtinst, write_mtinst }, + [CSR_HSTATUS] = { "hstatus", hmode, read_hstatus, write_hstatus, + .min_priv_ver = PRIV_VERSION_1_12_0 }, + [CSR_HEDELEG] = { "hedeleg", hmode, read_hedeleg, write_hedeleg, + .min_priv_ver = PRIV_VERSION_1_12_0 }, + [CSR_HIDELEG] = { "hideleg", hmode, NULL, NULL, rmw_hideleg, + .min_priv_ver = PRIV_VERSION_1_12_0 }, + [CSR_HVIP] = { "hvip", hmode, NULL, NULL, rmw_hvip, + .min_priv_ver = PRIV_VERSION_1_12_0 }, + [CSR_HIP] = { "hip", hmode, NULL, NULL, rmw_hip, + .min_priv_ver = PRIV_VERSION_1_12_0 }, + [CSR_HIE] = { "hie", hmode, NULL, NULL, rmw_hie, + .min_priv_ver = PRIV_VERSION_1_12_0 }, + [CSR_HCOUNTEREN] = { "hcounteren", hmode, read_hcounteren, write_hcounteren, + .min_priv_ver = PRIV_VERSION_1_12_0 }, + [CSR_HGEIE] = { "hgeie", hmode, read_hgeie, write_hgeie, + .min_priv_ver = PRIV_VERSION_1_12_0 }, + [CSR_HTVAL] = { "htval", hmode, read_htval, write_htval, + .min_priv_ver = PRIV_VERSION_1_12_0 }, + [CSR_HTINST] = { "htinst", hmode, read_htinst, write_htinst, + .min_priv_ver = PRIV_VERSION_1_12_0 }, + [CSR_HGEIP] = { "hgeip", hmode, read_hgeip, + .min_priv_ver = PRIV_VERSION_1_12_0 }, + [CSR_HGATP] = { "hgatp", hmode, read_hgatp, write_hgatp, + .min_priv_ver = PRIV_VERSION_1_12_0 }, + [CSR_HTIMEDELTA] = { "htimedelta", hmode, read_htimedelta, write_htimedelta, + .min_priv_ver = PRIV_VERSION_1_12_0 }, + [CSR_HTIMEDELTAH] = { "htimedeltah", hmode32, read_htimedeltah, write_htimedeltah, + .min_priv_ver = PRIV_VERSION_1_12_0 }, + + [CSR_VSSTATUS] = { "vsstatus", hmode, read_vsstatus, write_vsstatus, + .min_priv_ver = PRIV_VERSION_1_12_0 }, + [CSR_VSIP] = { "vsip", hmode, NULL, NULL, rmw_vsip, + .min_priv_ver = PRIV_VERSION_1_12_0 }, + [CSR_VSIE] = { "vsie", hmode, NULL, NULL, rmw_vsie , + .min_priv_ver = PRIV_VERSION_1_12_0 }, + [CSR_VSTVEC] = { "vstvec", hmode, read_vstvec, write_vstvec, + .min_priv_ver = PRIV_VERSION_1_12_0 }, + [CSR_VSSCRATCH] = { "vsscratch", hmode, read_vsscratch, write_vsscratch, + .min_priv_ver = PRIV_VERSION_1_12_0 }, + [CSR_VSEPC] = { "vsepc", hmode, read_vsepc, write_vsepc, + .min_priv_ver = PRIV_VERSION_1_12_0 }, + [CSR_VSCAUSE] = { "vscause", hmode, read_vscause, write_vscause, + .min_priv_ver = PRIV_VERSION_1_12_0 }, + [CSR_VSTVAL] = { "vstval", hmode, read_vstval, write_vstval, + .min_priv_ver = PRIV_VERSION_1_12_0 }, + [CSR_VSATP] = { "vsatp", hmode, read_vsatp, write_vsatp, + .min_priv_ver = PRIV_VERSION_1_12_0 }, + + [CSR_MTVAL2] = { "mtval2", hmode, read_mtval2, write_mtval2, + .min_priv_ver = PRIV_VERSION_1_12_0 }, + [CSR_MTINST] = { "mtinst", hmode, read_mtinst, write_mtinst, + .min_priv_ver = PRIV_VERSION_1_12_0 }, /* Virtual Interrupts and Interrupt Priorities (H-extension with AIA) */ [CSR_HVIEN] = { "hvien", aia_hmode, read_zero, write_ignore }, @@ -3245,7 +3446,8 @@ riscv_csr_operations csr_ops[CSR_TABLE_SIZE] = { [CSR_VSIPH] = { "vsiph", aia_hmode32, NULL, NULL, rmw_vsiph }, /* Physical Memory Protection */ - [CSR_MSECCFG] = { "mseccfg", epmp, read_mseccfg, write_mseccfg }, + [CSR_MSECCFG] = { "mseccfg", epmp, read_mseccfg, write_mseccfg, + .min_priv_ver = PRIV_VERSION_1_12_0 }, [CSR_PMPCFG0] = { "pmpcfg0", pmp, read_pmpcfg, write_pmpcfg }, [CSR_PMPCFG1] = { "pmpcfg1", pmp, read_pmpcfg, write_pmpcfg }, [CSR_PMPCFG2] = { "pmpcfg2", pmp, read_pmpcfg, write_pmpcfg }, @@ -3267,6 +3469,12 @@ riscv_csr_operations csr_ops[CSR_TABLE_SIZE] = { [CSR_PMPADDR14] = { "pmpaddr14", pmp, read_pmpaddr, write_pmpaddr }, [CSR_PMPADDR15] = { "pmpaddr15", pmp, read_pmpaddr, write_pmpaddr }, + /* Debug CSRs */ + [CSR_TSELECT] = { "tselect", debug, read_tselect, write_tselect }, + [CSR_TDATA1] = { "tdata1", debug, read_tdata, write_tdata }, + [CSR_TDATA2] = { "tdata2", debug, read_tdata, write_tdata }, + [CSR_TDATA3] = { "tdata3", debug, read_tdata, write_tdata }, + /* User Pointer Masking */ [CSR_UMTE] = { "umte", pointer_masking, read_umte, write_umte }, [CSR_UPMMASK] = { "upmmask", pointer_masking, read_upmmask, write_upmmask }, diff --git a/target/riscv/debug.c b/target/riscv/debug.c new file mode 100644 index 0000000000..2f2a51c732 --- /dev/null +++ b/target/riscv/debug.c @@ -0,0 +1,441 @@ +/* + * QEMU RISC-V Native Debug Support + * + * Copyright (c) 2022 Wind River Systems, Inc. + * + * Author: + * Bin Meng <bin.meng@windriver.com> + * + * This provides the native debug support via the Trigger Module, as defined + * in the RISC-V Debug Specification: + * https://github.com/riscv/riscv-debug-spec/raw/master/riscv-debug-stable.pdf + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2 or later, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include "qemu/osdep.h" +#include "qemu/log.h" +#include "qapi/error.h" +#include "cpu.h" +#include "trace.h" +#include "exec/exec-all.h" + +/* + * The following M-mode trigger CSRs are implemented: + * + * - tselect + * - tdata1 + * - tdata2 + * - tdata3 + * + * We don't support writable 'type' field in the tdata1 register, so there is + * no need to implement the "tinfo" CSR. + * + * The following triggers are implemented: + * + * Index | Type | tdata mapping | Description + * ------+------+------------------------+------------ + * 0 | 2 | tdata1, tdata2 | Address / Data Match + * 1 | 2 | tdata1, tdata2 | Address / Data Match + */ + +/* tdata availability of a trigger */ +typedef bool tdata_avail[TDATA_NUM]; + +static tdata_avail tdata_mapping[TRIGGER_NUM] = { + [TRIGGER_TYPE2_IDX_0 ... TRIGGER_TYPE2_IDX_1] = { true, true, false }, +}; + +/* only breakpoint size 1/2/4/8 supported */ +static int access_size[SIZE_NUM] = { + [SIZE_ANY] = 0, + [SIZE_1B] = 1, + [SIZE_2B] = 2, + [SIZE_4B] = 4, + [SIZE_6B] = -1, + [SIZE_8B] = 8, + [6 ... 15] = -1, +}; + +static inline target_ulong trigger_type(CPURISCVState *env, + trigger_type_t type) +{ + target_ulong tdata1; + + switch (riscv_cpu_mxl(env)) { + case MXL_RV32: + tdata1 = RV32_TYPE(type); + break; + case MXL_RV64: + tdata1 = RV64_TYPE(type); + break; + default: + g_assert_not_reached(); + } + + return tdata1; +} + +bool tdata_available(CPURISCVState *env, int tdata_index) +{ + if (unlikely(tdata_index >= TDATA_NUM)) { + return false; + } + + if (unlikely(env->trigger_cur >= TRIGGER_NUM)) { + return false; + } + + return tdata_mapping[env->trigger_cur][tdata_index]; +} + +target_ulong tselect_csr_read(CPURISCVState *env) +{ + return env->trigger_cur; +} + +void tselect_csr_write(CPURISCVState *env, target_ulong val) +{ + /* all target_ulong bits of tselect are implemented */ + env->trigger_cur = val; +} + +static target_ulong tdata1_validate(CPURISCVState *env, target_ulong val, + trigger_type_t t) +{ + uint32_t type, dmode; + target_ulong tdata1; + + switch (riscv_cpu_mxl(env)) { + case MXL_RV32: + type = extract32(val, 28, 4); + dmode = extract32(val, 27, 1); + tdata1 = RV32_TYPE(t); + break; + case MXL_RV64: + type = extract64(val, 60, 4); + dmode = extract64(val, 59, 1); + tdata1 = RV64_TYPE(t); + break; + default: + g_assert_not_reached(); + } + + if (type != t) { + qemu_log_mask(LOG_GUEST_ERROR, + "ignoring type write to tdata1 register\n"); + } + if (dmode != 0) { + qemu_log_mask(LOG_UNIMP, "debug mode is not supported\n"); + } + + return tdata1; +} + +static inline void warn_always_zero_bit(target_ulong val, target_ulong mask, + const char *msg) +{ + if (val & mask) { + qemu_log_mask(LOG_UNIMP, "%s bit is always zero\n", msg); + } +} + +static uint32_t type2_breakpoint_size(CPURISCVState *env, target_ulong ctrl) +{ + uint32_t size, sizelo, sizehi = 0; + + if (riscv_cpu_mxl(env) == MXL_RV64) { + sizehi = extract32(ctrl, 21, 2); + } + sizelo = extract32(ctrl, 16, 2); + size = (sizehi << 2) | sizelo; + + return size; +} + +static inline bool type2_breakpoint_enabled(target_ulong ctrl) +{ + bool mode = !!(ctrl & (TYPE2_U | TYPE2_S | TYPE2_M)); + bool rwx = !!(ctrl & (TYPE2_LOAD | TYPE2_STORE | TYPE2_EXEC)); + + return mode && rwx; +} + +static target_ulong type2_mcontrol_validate(CPURISCVState *env, + target_ulong ctrl) +{ + target_ulong val; + uint32_t size; + + /* validate the generic part first */ + val = tdata1_validate(env, ctrl, TRIGGER_TYPE_AD_MATCH); + + /* validate unimplemented (always zero) bits */ + warn_always_zero_bit(ctrl, TYPE2_MATCH, "match"); + warn_always_zero_bit(ctrl, TYPE2_CHAIN, "chain"); + warn_always_zero_bit(ctrl, TYPE2_ACTION, "action"); + warn_always_zero_bit(ctrl, TYPE2_TIMING, "timing"); + warn_always_zero_bit(ctrl, TYPE2_SELECT, "select"); + warn_always_zero_bit(ctrl, TYPE2_HIT, "hit"); + + /* validate size encoding */ + size = type2_breakpoint_size(env, ctrl); + if (access_size[size] == -1) { + qemu_log_mask(LOG_UNIMP, "access size %d is not supported, using SIZE_ANY\n", + size); + } else { + val |= (ctrl & TYPE2_SIZELO); + if (riscv_cpu_mxl(env) == MXL_RV64) { + val |= (ctrl & TYPE2_SIZEHI); + } + } + + /* keep the mode and attribute bits */ + val |= (ctrl & (TYPE2_U | TYPE2_S | TYPE2_M | + TYPE2_LOAD | TYPE2_STORE | TYPE2_EXEC)); + + return val; +} + +static void type2_breakpoint_insert(CPURISCVState *env, target_ulong index) +{ + target_ulong ctrl = env->type2_trig[index].mcontrol; + target_ulong addr = env->type2_trig[index].maddress; + bool enabled = type2_breakpoint_enabled(ctrl); + CPUState *cs = env_cpu(env); + int flags = BP_CPU | BP_STOP_BEFORE_ACCESS; + uint32_t size; + + if (!enabled) { + return; + } + + if (ctrl & TYPE2_EXEC) { + cpu_breakpoint_insert(cs, addr, flags, &env->type2_trig[index].bp); + } + + if (ctrl & TYPE2_LOAD) { + flags |= BP_MEM_READ; + } + if (ctrl & TYPE2_STORE) { + flags |= BP_MEM_WRITE; + } + + if (flags & BP_MEM_ACCESS) { + size = type2_breakpoint_size(env, ctrl); + if (size != 0) { + cpu_watchpoint_insert(cs, addr, size, flags, + &env->type2_trig[index].wp); + } else { + cpu_watchpoint_insert(cs, addr, 8, flags, + &env->type2_trig[index].wp); + } + } +} + +static void type2_breakpoint_remove(CPURISCVState *env, target_ulong index) +{ + CPUState *cs = env_cpu(env); + + if (env->type2_trig[index].bp) { + cpu_breakpoint_remove_by_ref(cs, env->type2_trig[index].bp); + env->type2_trig[index].bp = NULL; + } + + if (env->type2_trig[index].wp) { + cpu_watchpoint_remove_by_ref(cs, env->type2_trig[index].wp); + env->type2_trig[index].wp = NULL; + } +} + +static target_ulong type2_reg_read(CPURISCVState *env, + target_ulong trigger_index, int tdata_index) +{ + uint32_t index = trigger_index - TRIGGER_TYPE2_IDX_0; + target_ulong tdata; + + switch (tdata_index) { + case TDATA1: + tdata = env->type2_trig[index].mcontrol; + break; + case TDATA2: + tdata = env->type2_trig[index].maddress; + break; + default: + g_assert_not_reached(); + } + + return tdata; +} + +static void type2_reg_write(CPURISCVState *env, target_ulong trigger_index, + int tdata_index, target_ulong val) +{ + uint32_t index = trigger_index - TRIGGER_TYPE2_IDX_0; + target_ulong new_val; + + switch (tdata_index) { + case TDATA1: + new_val = type2_mcontrol_validate(env, val); + if (new_val != env->type2_trig[index].mcontrol) { + env->type2_trig[index].mcontrol = new_val; + type2_breakpoint_remove(env, index); + type2_breakpoint_insert(env, index); + } + break; + case TDATA2: + if (val != env->type2_trig[index].maddress) { + env->type2_trig[index].maddress = val; + type2_breakpoint_remove(env, index); + type2_breakpoint_insert(env, index); + } + break; + default: + g_assert_not_reached(); + } + + return; +} + +typedef target_ulong (*tdata_read_func)(CPURISCVState *env, + target_ulong trigger_index, + int tdata_index); + +static tdata_read_func trigger_read_funcs[TRIGGER_NUM] = { + [TRIGGER_TYPE2_IDX_0 ... TRIGGER_TYPE2_IDX_1] = type2_reg_read, +}; + +typedef void (*tdata_write_func)(CPURISCVState *env, + target_ulong trigger_index, + int tdata_index, + target_ulong val); + +static tdata_write_func trigger_write_funcs[TRIGGER_NUM] = { + [TRIGGER_TYPE2_IDX_0 ... TRIGGER_TYPE2_IDX_1] = type2_reg_write, +}; + +target_ulong tdata_csr_read(CPURISCVState *env, int tdata_index) +{ + tdata_read_func read_func = trigger_read_funcs[env->trigger_cur]; + + return read_func(env, env->trigger_cur, tdata_index); +} + +void tdata_csr_write(CPURISCVState *env, int tdata_index, target_ulong val) +{ + tdata_write_func write_func = trigger_write_funcs[env->trigger_cur]; + + return write_func(env, env->trigger_cur, tdata_index, val); +} + +void riscv_cpu_debug_excp_handler(CPUState *cs) +{ + RISCVCPU *cpu = RISCV_CPU(cs); + CPURISCVState *env = &cpu->env; + + if (cs->watchpoint_hit) { + if (cs->watchpoint_hit->flags & BP_CPU) { + cs->watchpoint_hit = NULL; + riscv_raise_exception(env, RISCV_EXCP_BREAKPOINT, 0); + } + } else { + if (cpu_breakpoint_test(cs, env->pc, BP_CPU)) { + riscv_raise_exception(env, RISCV_EXCP_BREAKPOINT, 0); + } + } +} + +bool riscv_cpu_debug_check_breakpoint(CPUState *cs) +{ + RISCVCPU *cpu = RISCV_CPU(cs); + CPURISCVState *env = &cpu->env; + CPUBreakpoint *bp; + target_ulong ctrl; + target_ulong pc; + int i; + + QTAILQ_FOREACH(bp, &cs->breakpoints, entry) { + for (i = 0; i < TRIGGER_TYPE2_NUM; i++) { + ctrl = env->type2_trig[i].mcontrol; + pc = env->type2_trig[i].maddress; + + if ((ctrl & TYPE2_EXEC) && (bp->pc == pc)) { + /* check U/S/M bit against current privilege level */ + if ((ctrl >> 3) & BIT(env->priv)) { + return true; + } + } + } + } + + return false; +} + +bool riscv_cpu_debug_check_watchpoint(CPUState *cs, CPUWatchpoint *wp) +{ + RISCVCPU *cpu = RISCV_CPU(cs); + CPURISCVState *env = &cpu->env; + target_ulong ctrl; + target_ulong addr; + int flags; + int i; + + for (i = 0; i < TRIGGER_TYPE2_NUM; i++) { + ctrl = env->type2_trig[i].mcontrol; + addr = env->type2_trig[i].maddress; + flags = 0; + + if (ctrl & TYPE2_LOAD) { + flags |= BP_MEM_READ; + } + if (ctrl & TYPE2_STORE) { + flags |= BP_MEM_WRITE; + } + + if ((wp->flags & flags) && (wp->vaddr == addr)) { + /* check U/S/M bit against current privilege level */ + if ((ctrl >> 3) & BIT(env->priv)) { + return true; + } + } + } + + return false; +} + +void riscv_trigger_init(CPURISCVState *env) +{ + target_ulong type2 = trigger_type(env, TRIGGER_TYPE_AD_MATCH); + int i; + + /* type 2 triggers */ + for (i = 0; i < TRIGGER_TYPE2_NUM; i++) { + /* + * type = TRIGGER_TYPE_AD_MATCH + * dmode = 0 (both debug and M-mode can write tdata) + * maskmax = 0 (unimplemented, always 0) + * sizehi = 0 (match against any size, RV64 only) + * hit = 0 (unimplemented, always 0) + * select = 0 (always 0, perform match on address) + * timing = 0 (always 0, trigger before instruction) + * sizelo = 0 (match against any size) + * action = 0 (always 0, raise a breakpoint exception) + * chain = 0 (unimplemented, always 0) + * match = 0 (always 0, when any compare value equals tdata2) + */ + env->type2_trig[i].mcontrol = type2; + env->type2_trig[i].maddress = 0; + env->type2_trig[i].bp = NULL; + env->type2_trig[i].wp = NULL; + } +} diff --git a/target/riscv/debug.h b/target/riscv/debug.h new file mode 100644 index 0000000000..27b9cac6b4 --- /dev/null +++ b/target/riscv/debug.h @@ -0,0 +1,114 @@ +/* + * QEMU RISC-V Native Debug Support + * + * Copyright (c) 2022 Wind River Systems, Inc. + * + * Author: + * Bin Meng <bin.meng@windriver.com> + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2 or later, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef RISCV_DEBUG_H +#define RISCV_DEBUG_H + +/* trigger indexes implemented */ +enum { + TRIGGER_TYPE2_IDX_0 = 0, + TRIGGER_TYPE2_IDX_1, + TRIGGER_TYPE2_NUM, + TRIGGER_NUM = TRIGGER_TYPE2_NUM +}; + +/* register index of tdata CSRs */ +enum { + TDATA1 = 0, + TDATA2, + TDATA3, + TDATA_NUM +}; + +typedef enum { + TRIGGER_TYPE_NO_EXIST = 0, /* trigger does not exist */ + TRIGGER_TYPE_AD_MATCH = 2, /* address/data match trigger */ + TRIGGER_TYPE_INST_CNT = 3, /* instruction count trigger */ + TRIGGER_TYPE_INT = 4, /* interrupt trigger */ + TRIGGER_TYPE_EXCP = 5, /* exception trigger */ + TRIGGER_TYPE_AD_MATCH6 = 6, /* new address/data match trigger */ + TRIGGER_TYPE_EXT_SRC = 7, /* external source trigger */ + TRIGGER_TYPE_UNAVAIL = 15 /* trigger exists, but unavailable */ +} trigger_type_t; + +typedef struct { + target_ulong mcontrol; + target_ulong maddress; + struct CPUBreakpoint *bp; + struct CPUWatchpoint *wp; +} type2_trigger_t; + +/* tdata field masks */ + +#define RV32_TYPE(t) ((uint32_t)(t) << 28) +#define RV32_TYPE_MASK (0xf << 28) +#define RV32_DMODE BIT(27) +#define RV64_TYPE(t) ((uint64_t)(t) << 60) +#define RV64_TYPE_MASK (0xfULL << 60) +#define RV64_DMODE BIT_ULL(59) + +/* mcontrol field masks */ + +#define TYPE2_LOAD BIT(0) +#define TYPE2_STORE BIT(1) +#define TYPE2_EXEC BIT(2) +#define TYPE2_U BIT(3) +#define TYPE2_S BIT(4) +#define TYPE2_M BIT(6) +#define TYPE2_MATCH (0xf << 7) +#define TYPE2_CHAIN BIT(11) +#define TYPE2_ACTION (0xf << 12) +#define TYPE2_SIZELO (0x3 << 16) +#define TYPE2_TIMING BIT(18) +#define TYPE2_SELECT BIT(19) +#define TYPE2_HIT BIT(20) +#define TYPE2_SIZEHI (0x3 << 21) /* RV64 only */ + +/* access size */ +enum { + SIZE_ANY = 0, + SIZE_1B, + SIZE_2B, + SIZE_4B, + SIZE_6B, + SIZE_8B, + SIZE_10B, + SIZE_12B, + SIZE_14B, + SIZE_16B, + SIZE_NUM = 16 +}; + +bool tdata_available(CPURISCVState *env, int tdata_index); + +target_ulong tselect_csr_read(CPURISCVState *env); +void tselect_csr_write(CPURISCVState *env, target_ulong val); + +target_ulong tdata_csr_read(CPURISCVState *env, int tdata_index); +void tdata_csr_write(CPURISCVState *env, int tdata_index, target_ulong val); + +void riscv_cpu_debug_excp_handler(CPUState *cs); +bool riscv_cpu_debug_check_breakpoint(CPUState *cs); +bool riscv_cpu_debug_check_watchpoint(CPUState *cs, CPUWatchpoint *wp); + +void riscv_trigger_init(CPURISCVState *env); + +#endif /* RISCV_DEBUG_H */ diff --git a/target/riscv/helper.h b/target/riscv/helper.h index 26bbab2fab..a669d0187b 100644 --- a/target/riscv/helper.h +++ b/target/riscv/helper.h @@ -1086,10 +1086,7 @@ DEF_HELPER_6(vcompress_vm_h, void, ptr, ptr, ptr, ptr, env, i32) DEF_HELPER_6(vcompress_vm_w, void, ptr, ptr, ptr, ptr, env, i32) DEF_HELPER_6(vcompress_vm_d, void, ptr, ptr, ptr, ptr, env, i32) -DEF_HELPER_4(vmv1r_v, void, ptr, ptr, env, i32) -DEF_HELPER_4(vmv2r_v, void, ptr, ptr, env, i32) -DEF_HELPER_4(vmv4r_v, void, ptr, ptr, env, i32) -DEF_HELPER_4(vmv8r_v, void, ptr, ptr, env, i32) +DEF_HELPER_4(vmvr_v, void, ptr, ptr, env, i32) DEF_HELPER_5(vzext_vf2_h, void, ptr, ptr, ptr, env, i32) DEF_HELPER_5(vzext_vf2_w, void, ptr, ptr, ptr, env, i32) diff --git a/target/riscv/insn_trans/trans_rvv.c.inc b/target/riscv/insn_trans/trans_rvv.c.inc index 8d675db9a2..90327509f7 100644 --- a/target/riscv/insn_trans/trans_rvv.c.inc +++ b/target/riscv/insn_trans/trans_rvv.c.inc @@ -1198,7 +1198,7 @@ GEN_LDST_WHOLE_TRANS(vs8r_v, 8, true) static inline uint32_t MAXSZ(DisasContext *s) { int scale = s->lmul - 3; - return scale < 0 ? s->cfg_ptr->vlen >> -scale : s->cfg_ptr->vlen << scale; + return s->cfg_ptr->vlen >> -scale; } static bool opivv_check(DisasContext *s, arg_rmrr *a) @@ -3597,8 +3597,7 @@ static bool trans_vrgather_vx(DisasContext *s, arg_rmrr *a) if (a->vm && s->vl_eq_vlmax) { int scale = s->lmul - (s->sew + 3); - int vlmax = scale < 0 ? - s->cfg_ptr->vlen >> -scale : s->cfg_ptr->vlen << scale; + int vlmax = s->cfg_ptr->vlen >> -scale; TCGv_i64 dest = tcg_temp_new_i64(); if (a->rs1 == 0) { @@ -3630,8 +3629,7 @@ static bool trans_vrgather_vi(DisasContext *s, arg_rmrr *a) if (a->vm && s->vl_eq_vlmax) { int scale = s->lmul - (s->sew + 3); - int vlmax = scale < 0 ? - s->cfg_ptr->vlen >> -scale : s->cfg_ptr->vlen << scale; + int vlmax = s->cfg_ptr->vlen >> -scale; if (a->rs1 >= vlmax) { tcg_gen_gvec_dup_imm(MO_64, vreg_ofs(s, a->rd), MAXSZ(s), MAXSZ(s), 0); @@ -3697,7 +3695,7 @@ static bool trans_vcompress_vm(DisasContext *s, arg_r *a) * Whole Vector Register Move Instructions ignore vtype and vl setting. * Thus, we don't need to check vill bit. (Section 16.6) */ -#define GEN_VMV_WHOLE_TRANS(NAME, LEN, SEQ) \ +#define GEN_VMV_WHOLE_TRANS(NAME, LEN) \ static bool trans_##NAME(DisasContext *s, arg_##NAME * a) \ { \ if (require_rvv(s) && \ @@ -3712,13 +3710,8 @@ static bool trans_##NAME(DisasContext *s, arg_##NAME * a) \ } else { \ TCGLabel *over = gen_new_label(); \ tcg_gen_brcondi_tl(TCG_COND_GEU, cpu_vstart, maxsz, over); \ - \ - static gen_helper_gvec_2_ptr * const fns[4] = { \ - gen_helper_vmv1r_v, gen_helper_vmv2r_v, \ - gen_helper_vmv4r_v, gen_helper_vmv8r_v, \ - }; \ tcg_gen_gvec_2_ptr(vreg_ofs(s, a->rd), vreg_ofs(s, a->rs2), \ - cpu_env, maxsz, maxsz, 0, fns[SEQ]); \ + cpu_env, maxsz, maxsz, 0, gen_helper_vmvr_v); \ mark_vs_dirty(s); \ gen_set_label(over); \ } \ @@ -3727,10 +3720,10 @@ static bool trans_##NAME(DisasContext *s, arg_##NAME * a) \ return false; \ } -GEN_VMV_WHOLE_TRANS(vmv1r_v, 1, 0) -GEN_VMV_WHOLE_TRANS(vmv2r_v, 2, 1) -GEN_VMV_WHOLE_TRANS(vmv4r_v, 4, 2) -GEN_VMV_WHOLE_TRANS(vmv8r_v, 8, 3) +GEN_VMV_WHOLE_TRANS(vmv1r_v, 1) +GEN_VMV_WHOLE_TRANS(vmv2r_v, 2) +GEN_VMV_WHOLE_TRANS(vmv4r_v, 4) +GEN_VMV_WHOLE_TRANS(vmv8r_v, 8) static bool int_ext_check(DisasContext *s, arg_rmr *a, uint8_t div) { diff --git a/target/riscv/machine.c b/target/riscv/machine.c index 5178b3fec9..2a437b29a1 100644 --- a/target/riscv/machine.c +++ b/target/riscv/machine.c @@ -216,7 +216,38 @@ static const VMStateDescription vmstate_kvmtimer = { VMSTATE_UINT64(env.kvm_timer_time, RISCVCPU), VMSTATE_UINT64(env.kvm_timer_compare, RISCVCPU), VMSTATE_UINT64(env.kvm_timer_state, RISCVCPU), + VMSTATE_END_OF_LIST() + } +}; + +static bool debug_needed(void *opaque) +{ + RISCVCPU *cpu = opaque; + CPURISCVState *env = &cpu->env; + + return riscv_feature(env, RISCV_FEATURE_DEBUG); +} + +static const VMStateDescription vmstate_debug_type2 = { + .name = "cpu/debug/type2", + .version_id = 1, + .minimum_version_id = 1, + .fields = (VMStateField[]) { + VMSTATE_UINTTL(mcontrol, type2_trigger_t), + VMSTATE_UINTTL(maddress, type2_trigger_t), + VMSTATE_END_OF_LIST() + } +}; +static const VMStateDescription vmstate_debug = { + .name = "cpu/debug", + .version_id = 1, + .minimum_version_id = 1, + .needed = debug_needed, + .fields = (VMStateField[]) { + VMSTATE_UINTTL(env.trigger_cur, RISCVCPU), + VMSTATE_STRUCT_ARRAY(env.type2_trig, RISCVCPU, TRIGGER_TYPE2_NUM, + 0, vmstate_debug_type2, type2_trigger_t), VMSTATE_END_OF_LIST() } }; @@ -231,6 +262,28 @@ static int riscv_cpu_post_load(void *opaque, int version_id) return 0; } +static bool envcfg_needed(void *opaque) +{ + RISCVCPU *cpu = opaque; + CPURISCVState *env = &cpu->env; + + return (env->priv_ver >= PRIV_VERSION_1_12_0 ? 1 : 0); +} + +static const VMStateDescription vmstate_envcfg = { + .name = "cpu/envcfg", + .version_id = 1, + .minimum_version_id = 1, + .needed = envcfg_needed, + .fields = (VMStateField[]) { + VMSTATE_UINT64(env.menvcfg, RISCVCPU), + VMSTATE_UINTTL(env.senvcfg, RISCVCPU), + VMSTATE_UINT64(env.henvcfg, RISCVCPU), + + VMSTATE_END_OF_LIST() + } +}; + const VMStateDescription vmstate_riscv_cpu = { .name = "cpu", .version_id = 3, @@ -292,6 +345,8 @@ const VMStateDescription vmstate_riscv_cpu = { &vmstate_pointermasking, &vmstate_rv128, &vmstate_kvmtimer, + &vmstate_envcfg, + &vmstate_debug, NULL } }; diff --git a/target/riscv/meson.build b/target/riscv/meson.build index 91f0ac32ff..2c20f3dd8e 100644 --- a/target/riscv/meson.build +++ b/target/riscv/meson.build @@ -27,6 +27,7 @@ riscv_softmmu_ss = ss.source_set() riscv_softmmu_ss.add(files( 'arch_dump.c', 'pmp.c', + 'debug.c', 'monitor.c', 'machine.c' )) diff --git a/target/riscv/op_helper.c b/target/riscv/op_helper.c index 1a75ba11e6..df35736883 100644 --- a/target/riscv/op_helper.c +++ b/target/riscv/op_helper.c @@ -24,8 +24,8 @@ #include "exec/helper-proto.h" /* Exceptions processing helpers */ -void QEMU_NORETURN riscv_raise_exception(CPURISCVState *env, - uint32_t exception, uintptr_t pc) +G_NORETURN void riscv_raise_exception(CPURISCVState *env, + uint32_t exception, uintptr_t pc) { CPUState *cs = env_cpu(env); cs->exception_index = exception; diff --git a/target/riscv/pmp.c b/target/riscv/pmp.c index 81b61bb65c..151da3fa08 100644 --- a/target/riscv/pmp.c +++ b/target/riscv/pmp.c @@ -141,17 +141,9 @@ static void pmp_decode_napot(target_ulong a, target_ulong *sa, target_ulong *ea) 0111...1111 2^(XLEN+2)-byte NAPOT range 1111...1111 Reserved */ - if (a == -1) { - *sa = 0u; - *ea = -1; - return; - } else { - target_ulong t1 = ctz64(~a); - target_ulong base = (a & ~(((target_ulong)1 << t1) - 1)) << 2; - target_ulong range = ((target_ulong)1 << (t1 + 3)) - 1; - *sa = base; - *ea = base + range; - } + a = (a << 2) | 0x3; + *sa = a & (a + 1); + *ea = a | (a + 1); } void pmp_update_rule_addr(CPURISCVState *env, uint32_t pmp_index) diff --git a/target/riscv/vector_helper.c b/target/riscv/vector_helper.c index 7a6ce0a3bc..576b14e5a3 100644 --- a/target/riscv/vector_helper.c +++ b/target/riscv/vector_helper.c @@ -4888,25 +4888,20 @@ GEN_VEXT_VCOMPRESS_VM(vcompress_vm_w, uint32_t, H4) GEN_VEXT_VCOMPRESS_VM(vcompress_vm_d, uint64_t, H8) /* Vector Whole Register Move */ -#define GEN_VEXT_VMV_WHOLE(NAME, LEN) \ -void HELPER(NAME)(void *vd, void *vs2, CPURISCVState *env, \ - uint32_t desc) \ -{ \ - /* EEW = 8 */ \ - uint32_t maxsz = simd_maxsz(desc); \ - uint32_t i = env->vstart; \ - \ - memcpy((uint8_t *)vd + H1(i), \ - (uint8_t *)vs2 + H1(i), \ - maxsz - env->vstart); \ - \ - env->vstart = 0; \ -} +void HELPER(vmvr_v)(void *vd, void *vs2, CPURISCVState *env, uint32_t desc) +{ + /* EEW = SEW */ + uint32_t maxsz = simd_maxsz(desc); + uint32_t sewb = 1 << FIELD_EX64(env->vtype, VTYPE, VSEW); + uint32_t startb = env->vstart * sewb; + uint32_t i = startb; + + memcpy((uint8_t *)vd + H1(i), + (uint8_t *)vs2 + H1(i), + maxsz - startb); -GEN_VEXT_VMV_WHOLE(vmv1r_v, 1) -GEN_VEXT_VMV_WHOLE(vmv2r_v, 2) -GEN_VEXT_VMV_WHOLE(vmv4r_v, 4) -GEN_VEXT_VMV_WHOLE(vmv8r_v, 8) + env->vstart = 0; +} /* Vector Integer Extension */ #define GEN_VEXT_INT_EXT(NAME, ETYPE, DTYPE, HD, HS1) \ diff --git a/target/rx/cpu.h b/target/rx/cpu.h index 1c267f83bf..5655dffeff 100644 --- a/target/rx/cpu.h +++ b/target/rx/cpu.h @@ -149,6 +149,7 @@ static inline void cpu_get_tb_cpu_state(CPURXState *env, target_ulong *pc, *pc = env->pc; *cs_base = 0; *flags = FIELD_DP32(0, PSW, PM, env->psw_pm); + *flags = FIELD_DP32(*flags, PSW, U, env->psw_u); } static inline int cpu_mmu_index(CPURXState *env, bool ifetch) diff --git a/target/rx/op_helper.c b/target/rx/op_helper.c index 11f952d340..9ca32dcc82 100644 --- a/target/rx/op_helper.c +++ b/target/rx/op_helper.c @@ -24,8 +24,9 @@ #include "exec/cpu_ldst.h" #include "fpu/softfloat.h" -static inline void QEMU_NORETURN raise_exception(CPURXState *env, int index, - uintptr_t retaddr); +static inline G_NORETURN +void raise_exception(CPURXState *env, int index, + uintptr_t retaddr); static void _set_psw(CPURXState *env, uint32_t psw, uint32_t rte) { @@ -418,8 +419,9 @@ uint32_t helper_divu(CPURXState *env, uint32_t num, uint32_t den) } /* exception */ -static inline void QEMU_NORETURN raise_exception(CPURXState *env, int index, - uintptr_t retaddr) +static inline G_NORETURN +void raise_exception(CPURXState *env, int index, + uintptr_t retaddr) { CPUState *cs = env_cpu(env); @@ -427,36 +429,37 @@ static inline void QEMU_NORETURN raise_exception(CPURXState *env, int index, cpu_loop_exit_restore(cs, retaddr); } -void QEMU_NORETURN helper_raise_privilege_violation(CPURXState *env) +G_NORETURN void helper_raise_privilege_violation(CPURXState *env) { raise_exception(env, 20, GETPC()); } -void QEMU_NORETURN helper_raise_access_fault(CPURXState *env) +G_NORETURN void helper_raise_access_fault(CPURXState *env) { raise_exception(env, 21, GETPC()); } -void QEMU_NORETURN helper_raise_illegal_instruction(CPURXState *env) +G_NORETURN void helper_raise_illegal_instruction(CPURXState *env) { raise_exception(env, 23, GETPC()); } -void QEMU_NORETURN helper_wait(CPURXState *env) +G_NORETURN void helper_wait(CPURXState *env) { CPUState *cs = env_cpu(env); cs->halted = 1; env->in_sleep = 1; + env->psw_i = 1; raise_exception(env, EXCP_HLT, 0); } -void QEMU_NORETURN helper_rxint(CPURXState *env, uint32_t vec) +G_NORETURN void helper_rxint(CPURXState *env, uint32_t vec) { raise_exception(env, 0x100 + vec, 0); } -void QEMU_NORETURN helper_rxbrk(CPURXState *env) +G_NORETURN void helper_rxbrk(CPURXState *env) { raise_exception(env, 0x100, 0); } diff --git a/target/rx/translate.c b/target/rx/translate.c index c8a8991a63..62aee66937 100644 --- a/target/rx/translate.c +++ b/target/rx/translate.c @@ -32,6 +32,7 @@ typedef struct DisasContext { DisasContextBase base; CPURXState *env; uint32_t pc; + uint32_t tb_flags; } DisasContext; typedef struct DisasCompare { @@ -231,7 +232,7 @@ static inline TCGv rx_load_source(DisasContext *ctx, TCGv mem, /* Processor mode check */ static int is_privileged(DisasContext *ctx, int is_exception) { - if (FIELD_EX32(ctx->base.tb->flags, PSW, PM)) { + if (FIELD_EX32(ctx->tb_flags, PSW, PM)) { if (is_exception) { gen_helper_raise_privilege_violation(cpu_env); } @@ -310,9 +311,8 @@ static void psw_cond(DisasCompare *dc, uint32_t cond) } } -static void move_from_cr(TCGv ret, int cr, uint32_t pc) +static void move_from_cr(DisasContext *ctx, TCGv ret, int cr, uint32_t pc) { - TCGv z = tcg_const_i32(0); switch (cr) { case 0: /* PSW */ gen_helper_pack_psw(ret, cpu_env); @@ -321,8 +321,11 @@ static void move_from_cr(TCGv ret, int cr, uint32_t pc) tcg_gen_movi_i32(ret, pc); break; case 2: /* USP */ - tcg_gen_movcond_i32(TCG_COND_NE, ret, - cpu_psw_u, z, cpu_sp, cpu_usp); + if (FIELD_EX32(ctx->tb_flags, PSW, U)) { + tcg_gen_mov_i32(ret, cpu_sp); + } else { + tcg_gen_mov_i32(ret, cpu_usp); + } break; case 3: /* FPSW */ tcg_gen_mov_i32(ret, cpu_fpsw); @@ -334,8 +337,11 @@ static void move_from_cr(TCGv ret, int cr, uint32_t pc) tcg_gen_mov_i32(ret, cpu_bpc); break; case 10: /* ISP */ - tcg_gen_movcond_i32(TCG_COND_EQ, ret, - cpu_psw_u, z, cpu_sp, cpu_isp); + if (FIELD_EX32(ctx->tb_flags, PSW, U)) { + tcg_gen_mov_i32(ret, cpu_isp); + } else { + tcg_gen_mov_i32(ret, cpu_sp); + } break; case 11: /* FINTV */ tcg_gen_mov_i32(ret, cpu_fintv); @@ -349,28 +355,31 @@ static void move_from_cr(TCGv ret, int cr, uint32_t pc) tcg_gen_movi_i32(ret, 0); break; } - tcg_temp_free(z); } static void move_to_cr(DisasContext *ctx, TCGv val, int cr) { - TCGv z; if (cr >= 8 && !is_privileged(ctx, 0)) { /* Some control registers can only be written in privileged mode. */ qemu_log_mask(LOG_GUEST_ERROR, "disallow control register write %s", rx_crname(cr)); return; } - z = tcg_const_i32(0); switch (cr) { case 0: /* PSW */ gen_helper_set_psw(cpu_env, val); + if (is_privileged(ctx, 0)) { + /* PSW.{I,U} may be updated here. exit TB. */ + ctx->base.is_jmp = DISAS_UPDATE; + } break; /* case 1: to PC not supported */ case 2: /* USP */ - tcg_gen_mov_i32(cpu_usp, val); - tcg_gen_movcond_i32(TCG_COND_NE, cpu_sp, - cpu_psw_u, z, cpu_usp, cpu_sp); + if (FIELD_EX32(ctx->tb_flags, PSW, U)) { + tcg_gen_mov_i32(cpu_sp, val); + } else { + tcg_gen_mov_i32(cpu_usp, val); + } break; case 3: /* FPSW */ gen_helper_set_fpsw(cpu_env, val); @@ -382,10 +391,11 @@ static void move_to_cr(DisasContext *ctx, TCGv val, int cr) tcg_gen_mov_i32(cpu_bpc, val); break; case 10: /* ISP */ - tcg_gen_mov_i32(cpu_isp, val); - /* if PSW.U is 0, copy isp to r0 */ - tcg_gen_movcond_i32(TCG_COND_EQ, cpu_sp, - cpu_psw_u, z, cpu_isp, cpu_sp); + if (FIELD_EX32(ctx->tb_flags, PSW, U)) { + tcg_gen_mov_i32(cpu_isp, val); + } else { + tcg_gen_mov_i32(cpu_sp, val); + } break; case 11: /* FINTV */ tcg_gen_mov_i32(cpu_fintv, val); @@ -398,7 +408,6 @@ static void move_to_cr(DisasContext *ctx, TCGv val, int cr) "Unimplement control register %d", cr); break; } - tcg_temp_free(z); } static void push(TCGv val) @@ -626,10 +635,6 @@ static bool trans_POPC(DisasContext *ctx, arg_POPC *a) val = tcg_temp_new(); pop(val); move_to_cr(ctx, val, a->cr); - if (a->cr == 0 && is_privileged(ctx, 0)) { - /* PSW.I may be updated here. exit TB. */ - ctx->base.is_jmp = DISAS_UPDATE; - } tcg_temp_free(val); return true; } @@ -682,7 +687,7 @@ static bool trans_PUSHC(DisasContext *ctx, arg_PUSHC *a) { TCGv val; val = tcg_temp_new(); - move_from_cr(val, a->cr, ctx->pc); + move_from_cr(ctx, val, a->cr, ctx->pc); push(val); tcg_temp_free(val); return true; @@ -2160,7 +2165,12 @@ static inline void clrsetpsw(DisasContext *ctx, int cb, int val) ctx->base.is_jmp = DISAS_UPDATE; break; case PSW_U: - tcg_gen_movi_i32(cpu_psw_u, val); + if (FIELD_EX32(ctx->tb_flags, PSW, U) != val) { + ctx->tb_flags = FIELD_DP32(ctx->tb_flags, PSW, U, val); + tcg_gen_movi_i32(cpu_psw_u, val); + tcg_gen_mov_i32(val ? cpu_isp : cpu_usp, cpu_sp); + tcg_gen_mov_i32(cpu_sp, val ? cpu_usp : cpu_isp); + } break; default: qemu_log_mask(LOG_GUEST_ERROR, "Invalid distination %d", cb); @@ -2200,9 +2210,6 @@ static bool trans_MVTC_i(DisasContext *ctx, arg_MVTC_i *a) imm = tcg_const_i32(a->imm); move_to_cr(ctx, imm, a->cr); - if (a->cr == 0 && is_privileged(ctx, 0)) { - ctx->base.is_jmp = DISAS_UPDATE; - } tcg_temp_free(imm); return true; } @@ -2211,16 +2218,13 @@ static bool trans_MVTC_i(DisasContext *ctx, arg_MVTC_i *a) static bool trans_MVTC_r(DisasContext *ctx, arg_MVTC_r *a) { move_to_cr(ctx, cpu_regs[a->rs], a->cr); - if (a->cr == 0 && is_privileged(ctx, 0)) { - ctx->base.is_jmp = DISAS_UPDATE; - } return true; } /* mvfc rs, rd */ static bool trans_MVFC(DisasContext *ctx, arg_MVFC *a) { - move_from_cr(cpu_regs[a->rd], a->cr, ctx->pc); + move_from_cr(ctx, cpu_regs[a->rd], a->cr, ctx->pc); return true; } @@ -2281,7 +2285,7 @@ static bool trans_INT(DisasContext *ctx, arg_INT *a) static bool trans_WAIT(DisasContext *ctx, arg_WAIT *a) { if (is_privileged(ctx, 1)) { - tcg_gen_addi_i32(cpu_pc, cpu_pc, 2); + tcg_gen_movi_i32(cpu_pc, ctx->base.pc_next); gen_helper_wait(cpu_env); } return true; @@ -2292,6 +2296,7 @@ static void rx_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cs) CPURXState *env = cs->env_ptr; DisasContext *ctx = container_of(dcbase, DisasContext, base); ctx->env = env; + ctx->tb_flags = ctx->base.tb->flags; } static void rx_tr_tb_start(DisasContextBase *dcbase, CPUState *cs) diff --git a/target/s390x/s390x-internal.h b/target/s390x/s390x-internal.h index 6fc8cad2d5..6aba7fd0ca 100644 --- a/target/s390x/s390x-internal.h +++ b/target/s390x/s390x-internal.h @@ -280,9 +280,9 @@ void s390_cpu_record_sigbus(CPUState *cs, vaddr address, bool s390_cpu_tlb_fill(CPUState *cs, vaddr address, int size, MMUAccessType access_type, int mmu_idx, bool probe, uintptr_t retaddr); -void s390x_cpu_do_unaligned_access(CPUState *cs, vaddr addr, - MMUAccessType access_type, int mmu_idx, - uintptr_t retaddr) QEMU_NORETURN; +G_NORETURN void s390x_cpu_do_unaligned_access(CPUState *cs, vaddr addr, + MMUAccessType access_type, int mmu_idx, + uintptr_t retaddr); #endif diff --git a/target/s390x/tcg/excp_helper.c b/target/s390x/tcg/excp_helper.c index be6c966cfa..29ccf70df1 100644 --- a/target/s390x/tcg/excp_helper.c +++ b/target/s390x/tcg/excp_helper.c @@ -34,8 +34,8 @@ #include "hw/boards.h" #endif -void QEMU_NORETURN tcg_s390_program_interrupt(CPUS390XState *env, - uint32_t code, uintptr_t ra) +G_NORETURN void tcg_s390_program_interrupt(CPUS390XState *env, + uint32_t code, uintptr_t ra) { CPUState *cs = env_cpu(env); @@ -46,8 +46,8 @@ void QEMU_NORETURN tcg_s390_program_interrupt(CPUS390XState *env, cpu_loop_exit(cs); } -void QEMU_NORETURN tcg_s390_data_exception(CPUS390XState *env, uint32_t dxc, - uintptr_t ra) +G_NORETURN void tcg_s390_data_exception(CPUS390XState *env, uint32_t dxc, + uintptr_t ra) { g_assert(dxc <= 0xff); #if !defined(CONFIG_USER_ONLY) @@ -63,8 +63,8 @@ void QEMU_NORETURN tcg_s390_data_exception(CPUS390XState *env, uint32_t dxc, tcg_s390_program_interrupt(env, PGM_DATA, ra); } -void QEMU_NORETURN tcg_s390_vector_exception(CPUS390XState *env, uint32_t vxc, - uintptr_t ra) +G_NORETURN void tcg_s390_vector_exception(CPUS390XState *env, uint32_t vxc, + uintptr_t ra) { g_assert(vxc <= 0xff); #if !defined(CONFIG_USER_ONLY) @@ -88,7 +88,8 @@ void HELPER(data_exception)(CPUS390XState *env, uint32_t dxc) * this is only for the atomic operations, for which we want to raise a * specification exception. */ -static void QEMU_NORETURN do_unaligned_access(CPUState *cs, uintptr_t retaddr) +static G_NORETURN +void do_unaligned_access(CPUState *cs, uintptr_t retaddr) { S390CPU *cpu = S390_CPU(cs); CPUS390XState *env = &cpu->env; @@ -620,9 +621,10 @@ void s390x_cpu_do_unaligned_access(CPUState *cs, vaddr addr, do_unaligned_access(cs, retaddr); } -static void QEMU_NORETURN monitor_event(CPUS390XState *env, - uint64_t monitor_code, - uint8_t monitor_class, uintptr_t ra) +static G_NORETURN +void monitor_event(CPUS390XState *env, + uint64_t monitor_code, + uint8_t monitor_class, uintptr_t ra) { /* Store the Monitor Code and the Monitor Class Number into the lowcore */ stq_phys(env_cpu(env)->as, diff --git a/target/s390x/tcg/tcg_s390x.h b/target/s390x/tcg/tcg_s390x.h index 2f54ccb027..78558912f9 100644 --- a/target/s390x/tcg/tcg_s390x.h +++ b/target/s390x/tcg/tcg_s390x.h @@ -14,11 +14,11 @@ #define TCG_S390X_H void tcg_s390_tod_updated(CPUState *cs, run_on_cpu_data opaque); -void QEMU_NORETURN tcg_s390_program_interrupt(CPUS390XState *env, - uint32_t code, uintptr_t ra); -void QEMU_NORETURN tcg_s390_data_exception(CPUS390XState *env, uint32_t dxc, - uintptr_t ra); -void QEMU_NORETURN tcg_s390_vector_exception(CPUS390XState *env, uint32_t vxc, - uintptr_t ra); +G_NORETURN void tcg_s390_program_interrupt(CPUS390XState *env, + uint32_t code, uintptr_t ra); +G_NORETURN void tcg_s390_data_exception(CPUS390XState *env, uint32_t dxc, + uintptr_t ra); +G_NORETURN void tcg_s390_vector_exception(CPUS390XState *env, uint32_t vxc, + uintptr_t ra); #endif /* TCG_S390X_H */ diff --git a/target/sh4/cpu.h b/target/sh4/cpu.h index 14d490ac47..9f15ef913c 100644 --- a/target/sh4/cpu.h +++ b/target/sh4/cpu.h @@ -210,9 +210,9 @@ void superh_cpu_dump_state(CPUState *cpu, FILE *f, int flags); hwaddr superh_cpu_get_phys_page_debug(CPUState *cpu, vaddr addr); int superh_cpu_gdb_read_register(CPUState *cpu, GByteArray *buf, int reg); int superh_cpu_gdb_write_register(CPUState *cpu, uint8_t *buf, int reg); -void superh_cpu_do_unaligned_access(CPUState *cpu, vaddr addr, - MMUAccessType access_type, int mmu_idx, - uintptr_t retaddr) QEMU_NORETURN; +G_NORETURN void superh_cpu_do_unaligned_access(CPUState *cpu, vaddr addr, + MMUAccessType access_type, int mmu_idx, + uintptr_t retaddr); void sh4_translate_init(void); void sh4_cpu_list(void); diff --git a/target/sh4/op_helper.c b/target/sh4/op_helper.c index 752669825f..a663335c39 100644 --- a/target/sh4/op_helper.c +++ b/target/sh4/op_helper.c @@ -57,8 +57,9 @@ void helper_ldtlb(CPUSH4State *env) #endif } -static inline void QEMU_NORETURN raise_exception(CPUSH4State *env, int index, - uintptr_t retaddr) +static inline G_NORETURN +void raise_exception(CPUSH4State *env, int index, + uintptr_t retaddr) { CPUState *cs = env_cpu(env); diff --git a/target/sparc/cpu.h b/target/sparc/cpu.h index dd9e2f5cdb..f80ea2e8cf 100644 --- a/target/sparc/cpu.h +++ b/target/sparc/cpu.h @@ -575,11 +575,11 @@ void sparc_cpu_do_interrupt(CPUState *cpu); hwaddr sparc_cpu_get_phys_page_debug(CPUState *cpu, vaddr addr); int sparc_cpu_gdb_read_register(CPUState *cpu, GByteArray *buf, int reg); int sparc_cpu_gdb_write_register(CPUState *cpu, uint8_t *buf, int reg); -void QEMU_NORETURN sparc_cpu_do_unaligned_access(CPUState *cpu, vaddr addr, - MMUAccessType access_type, - int mmu_idx, - uintptr_t retaddr); -void cpu_raise_exception_ra(CPUSPARCState *, int, uintptr_t) QEMU_NORETURN; +G_NORETURN void sparc_cpu_do_unaligned_access(CPUState *cpu, vaddr addr, + MMUAccessType access_type, + int mmu_idx, + uintptr_t retaddr); +G_NORETURN void cpu_raise_exception_ra(CPUSPARCState *, int, uintptr_t); #ifndef NO_CPU_IO_DEFS /* cpu_init.c */ diff --git a/target/sparc/mmu_helper.c b/target/sparc/mmu_helper.c index 346a6dfa35..919448a494 100644 --- a/target/sparc/mmu_helper.c +++ b/target/sparc/mmu_helper.c @@ -925,10 +925,10 @@ hwaddr sparc_cpu_get_phys_page_debug(CPUState *cs, vaddr addr) } #ifndef CONFIG_USER_ONLY -void QEMU_NORETURN sparc_cpu_do_unaligned_access(CPUState *cs, vaddr addr, - MMUAccessType access_type, - int mmu_idx, - uintptr_t retaddr) +G_NORETURN void sparc_cpu_do_unaligned_access(CPUState *cs, vaddr addr, + MMUAccessType access_type, + int mmu_idx, + uintptr_t retaddr) { SPARCCPU *cpu = SPARC_CPU(cs); CPUSPARCState *env = &cpu->env; diff --git a/target/tricore/op_helper.c b/target/tricore/op_helper.c index 9476d10d00..a79c838a92 100644 --- a/target/tricore/op_helper.c +++ b/target/tricore/op_helper.c @@ -25,9 +25,9 @@ /* Exception helpers */ -static void QEMU_NORETURN -raise_exception_sync_internal(CPUTriCoreState *env, uint32_t class, int tin, - uintptr_t pc, uint32_t fcd_pc) +static G_NORETURN +void raise_exception_sync_internal(CPUTriCoreState *env, uint32_t class, int tin, + uintptr_t pc, uint32_t fcd_pc) { CPUState *cs = env_cpu(env); /* in case we come from a helper-call we need to restore the PC */ diff --git a/target/xtensa/cpu.h b/target/xtensa/cpu.h index 71142ea8f4..d4b8268146 100644 --- a/target/xtensa/cpu.h +++ b/target/xtensa/cpu.h @@ -581,9 +581,9 @@ void xtensa_count_regs(const XtensaConfig *config, unsigned *n_regs, unsigned *n_core_regs); int xtensa_cpu_gdb_read_register(CPUState *cpu, GByteArray *buf, int reg); int xtensa_cpu_gdb_write_register(CPUState *cpu, uint8_t *buf, int reg); -void xtensa_cpu_do_unaligned_access(CPUState *cpu, vaddr addr, - MMUAccessType access_type, int mmu_idx, - uintptr_t retaddr) QEMU_NORETURN; +G_NORETURN void xtensa_cpu_do_unaligned_access(CPUState *cpu, vaddr addr, + MMUAccessType access_type, int mmu_idx, + uintptr_t retaddr); #define cpu_list xtensa_cpu_list |