From 343ed32dacd866e393a8fa4825c53bcd610330f5 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Mon, 29 Jan 2024 08:47:40 +1000 Subject: [PATCH 01/58] include/hw/core: Add mmu_index to CPUClass MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit To be used after all targets have populated the hook. Reviewed-by: Philippe Mathieu-Daudé Signed-off-by: Richard Henderson --- include/hw/core/cpu.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/include/hw/core/cpu.h b/include/hw/core/cpu.h index 2c284d6397..4385ce54c9 100644 --- a/include/hw/core/cpu.h +++ b/include/hw/core/cpu.h @@ -103,6 +103,8 @@ struct SysemuCPUOps; * @parse_features: Callback to parse command line arguments. * @reset_dump_flags: #CPUDumpFlags to use for reset logging. * @has_work: Callback for checking if there is work to do. + * @mmu_index: Callback for choosing softmmu mmu index; + * may be used internally by memory_rw_debug without TCG. * @memory_rw_debug: Callback for GDB memory access. * @dump_state: Callback for dumping state. * @query_cpu_fast: @@ -150,6 +152,7 @@ struct CPUClass { void (*parse_features)(const char *typename, char *str, Error **errp); bool (*has_work)(CPUState *cpu); + int (*mmu_index)(CPUState *cpu, bool ifetch); int (*memory_rw_debug)(CPUState *cpu, vaddr addr, uint8_t *buf, int len, bool is_write); void (*dump_state)(CPUState *cpu, FILE *, int flags); From 32a8ea12fab6b8f2959090819aa589c24b33715e Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Sun, 28 Jan 2024 14:47:19 +1000 Subject: [PATCH 02/58] target/alpha: Split out alpha_env_mmu_index MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Reviewed-by: Philippe Mathieu-Daudé Signed-off-by: Richard Henderson --- target/alpha/cpu.h | 7 ++++++- target/alpha/translate.c | 2 +- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/target/alpha/cpu.h b/target/alpha/cpu.h index ce806587ca..3beff2738a 100644 --- a/target/alpha/cpu.h +++ b/target/alpha/cpu.h @@ -389,7 +389,7 @@ enum { #define TB_FLAG_UNALIGN (1u << 1) -static inline int cpu_mmu_index(CPUAlphaState *env, bool ifetch) +static inline int alpha_env_mmu_index(CPUAlphaState *env) { int ret = env->flags & ENV_FLAG_PS_USER ? MMU_USER_IDX : MMU_KERNEL_IDX; if (env->flags & ENV_FLAG_PAL_MODE) { @@ -398,6 +398,11 @@ static inline int cpu_mmu_index(CPUAlphaState *env, bool ifetch) return ret; } +static inline int cpu_mmu_index(CPUAlphaState *env, bool ifetch) +{ + return alpha_env_mmu_index(env); +} + enum { IR_V0 = 0, IR_T0 = 1, diff --git a/target/alpha/translate.c b/target/alpha/translate.c index 134eb7225b..4b464f8651 100644 --- a/target/alpha/translate.c +++ b/target/alpha/translate.c @@ -2875,7 +2875,7 @@ static void alpha_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cpu) int64_t bound; ctx->tbflags = ctx->base.tb->flags; - ctx->mem_idx = cpu_mmu_index(env, false); + ctx->mem_idx = alpha_env_mmu_index(env); ctx->implver = env->implver; ctx->amask = env->amask; From 9d6847904b83df2cb0d1a1b8e72d141331094054 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Mon, 29 Jan 2024 08:53:49 +1000 Subject: [PATCH 03/58] target/alpha: Populate CPUClass.mmu_index MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Reviewed-by: Philippe Mathieu-Daudé Signed-off-by: Richard Henderson --- target/alpha/cpu.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/target/alpha/cpu.c b/target/alpha/cpu.c index de705c3703..bf70173a25 100644 --- a/target/alpha/cpu.c +++ b/target/alpha/cpu.c @@ -64,6 +64,11 @@ static bool alpha_cpu_has_work(CPUState *cs) | CPU_INTERRUPT_MCHK); } +static int alpha_cpu_mmu_index(CPUState *cs, bool ifetch) +{ + return alpha_env_mmu_index(cpu_env(cs)); +} + static void alpha_cpu_disas_set_info(CPUState *cpu, disassemble_info *info) { info->mach = bfd_mach_alpha_ev6; @@ -230,6 +235,7 @@ static void alpha_cpu_class_init(ObjectClass *oc, void *data) cc->class_by_name = alpha_cpu_class_by_name; cc->has_work = alpha_cpu_has_work; + cc->mmu_index = alpha_cpu_mmu_index; cc->dump_state = alpha_cpu_dump_state; cc->set_pc = alpha_cpu_set_pc; cc->get_pc = alpha_cpu_get_pc; From b7770d72f51505e7fbc4683b4c72085e40dcec51 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Sun, 28 Jan 2024 14:56:54 +1000 Subject: [PATCH 04/58] target/arm: Split out arm_env_mmu_index MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Reviewed-by: Philippe Mathieu-Daudé Signed-off-by: Richard Henderson --- target/arm/helper.c | 2 +- target/arm/internals.h | 5 +++++ target/arm/tcg/helper-a64.c | 4 ++-- target/arm/tcg/mte_helper.c | 18 +++++++++--------- target/arm/tcg/sve_helper.c | 8 ++++---- target/arm/tcg/tlb_helper.c | 2 +- 6 files changed, 22 insertions(+), 17 deletions(-) diff --git a/target/arm/helper.c b/target/arm/helper.c index 945d8571a6..b0488caf40 100644 --- a/target/arm/helper.c +++ b/target/arm/helper.c @@ -7841,7 +7841,7 @@ static void dccvap_writefn(CPUARMState *env, const ARMCPRegInfo *opaque, uint64_t vaddr_in = (uint64_t) value; uint64_t vaddr = vaddr_in & ~(dline_size - 1); void *haddr; - int mem_idx = cpu_mmu_index(env, false); + int mem_idx = arm_env_mmu_index(env); /* This won't be crossing page boundaries */ haddr = probe_read(env, vaddr, dline_size, mem_idx, GETPC()); diff --git a/target/arm/internals.h b/target/arm/internals.h index 71d6c70bf3..fc337fe40e 100644 --- a/target/arm/internals.h +++ b/target/arm/internals.h @@ -40,6 +40,11 @@ #define BANK_HYP 6 #define BANK_MON 7 +static inline int arm_env_mmu_index(CPUARMState *env) +{ + return EX_TBFLAG_ANY(env->hflags, MMUIDX); +} + static inline bool excp_is_internal(int excp) { /* Return true if this exception number represents a QEMU-internal diff --git a/target/arm/tcg/helper-a64.c b/target/arm/tcg/helper-a64.c index 198b975f20..ebaa7f00df 100644 --- a/target/arm/tcg/helper-a64.c +++ b/target/arm/tcg/helper-a64.c @@ -856,7 +856,7 @@ void HELPER(exception_return)(CPUARMState *env, uint64_t new_pc) tbii = EX_TBFLAG_A64(env->hflags, TBII); if ((tbii >> extract64(new_pc, 55, 1)) & 1) { /* TBI is enabled. */ - int core_mmu_idx = cpu_mmu_index(env, false); + int core_mmu_idx = arm_env_mmu_index(env); if (regime_has_2_ranges(core_to_aa64_mmu_idx(core_mmu_idx))) { new_pc = sextract64(new_pc, 0, 56); } else { @@ -925,7 +925,7 @@ void HELPER(dc_zva)(CPUARMState *env, uint64_t vaddr_in) */ int blocklen = 4 << env_archcpu(env)->dcz_blocksize; uint64_t vaddr = vaddr_in & ~(blocklen - 1); - int mmu_idx = cpu_mmu_index(env, false); + int mmu_idx = arm_env_mmu_index(env); void *mem; /* diff --git a/target/arm/tcg/mte_helper.c b/target/arm/tcg/mte_helper.c index ffb8ea1c34..d971b81370 100644 --- a/target/arm/tcg/mte_helper.c +++ b/target/arm/tcg/mte_helper.c @@ -291,7 +291,7 @@ static int load_tag1(uint64_t ptr, uint8_t *mem) uint64_t HELPER(ldg)(CPUARMState *env, uint64_t ptr, uint64_t xt) { - int mmu_idx = cpu_mmu_index(env, false); + int mmu_idx = arm_env_mmu_index(env); uint8_t *mem; int rtag = 0; @@ -311,7 +311,7 @@ static void check_tag_aligned(CPUARMState *env, uint64_t ptr, uintptr_t ra) { if (unlikely(!QEMU_IS_ALIGNED(ptr, TAG_GRANULE))) { arm_cpu_do_unaligned_access(env_cpu(env), ptr, MMU_DATA_STORE, - cpu_mmu_index(env, false), ra); + arm_env_mmu_index(env), ra); g_assert_not_reached(); } } @@ -344,7 +344,7 @@ typedef void stg_store1(uint64_t, uint8_t *, int); static inline void do_stg(CPUARMState *env, uint64_t ptr, uint64_t xt, uintptr_t ra, stg_store1 store1) { - int mmu_idx = cpu_mmu_index(env, false); + int mmu_idx = arm_env_mmu_index(env); uint8_t *mem; check_tag_aligned(env, ptr, ra); @@ -371,7 +371,7 @@ void HELPER(stg_parallel)(CPUARMState *env, uint64_t ptr, uint64_t xt) void HELPER(stg_stub)(CPUARMState *env, uint64_t ptr) { - int mmu_idx = cpu_mmu_index(env, false); + int mmu_idx = arm_env_mmu_index(env); uintptr_t ra = GETPC(); check_tag_aligned(env, ptr, ra); @@ -381,7 +381,7 @@ void HELPER(stg_stub)(CPUARMState *env, uint64_t ptr) static inline void do_st2g(CPUARMState *env, uint64_t ptr, uint64_t xt, uintptr_t ra, stg_store1 store1) { - int mmu_idx = cpu_mmu_index(env, false); + int mmu_idx = arm_env_mmu_index(env); int tag = allocation_tag_from_addr(xt); uint8_t *mem1, *mem2; @@ -429,7 +429,7 @@ void HELPER(st2g_parallel)(CPUARMState *env, uint64_t ptr, uint64_t xt) void HELPER(st2g_stub)(CPUARMState *env, uint64_t ptr) { - int mmu_idx = cpu_mmu_index(env, false); + int mmu_idx = arm_env_mmu_index(env); uintptr_t ra = GETPC(); int in_page = -(ptr | TARGET_PAGE_MASK); @@ -445,7 +445,7 @@ void HELPER(st2g_stub)(CPUARMState *env, uint64_t ptr) uint64_t HELPER(ldgm)(CPUARMState *env, uint64_t ptr) { - int mmu_idx = cpu_mmu_index(env, false); + int mmu_idx = arm_env_mmu_index(env); uintptr_t ra = GETPC(); int gm_bs = env_archcpu(env)->gm_blocksize; int gm_bs_bytes = 4 << gm_bs; @@ -505,7 +505,7 @@ uint64_t HELPER(ldgm)(CPUARMState *env, uint64_t ptr) void HELPER(stgm)(CPUARMState *env, uint64_t ptr, uint64_t val) { - int mmu_idx = cpu_mmu_index(env, false); + int mmu_idx = arm_env_mmu_index(env); uintptr_t ra = GETPC(); int gm_bs = env_archcpu(env)->gm_blocksize; int gm_bs_bytes = 4 << gm_bs; @@ -555,7 +555,7 @@ void HELPER(stgm)(CPUARMState *env, uint64_t ptr, uint64_t val) void HELPER(stzgm_tags)(CPUARMState *env, uint64_t ptr, uint64_t val) { uintptr_t ra = GETPC(); - int mmu_idx = cpu_mmu_index(env, false); + int mmu_idx = arm_env_mmu_index(env); int log2_dcz_bytes, log2_tag_bytes; intptr_t dcz_bytes, tag_bytes; uint8_t *mem; diff --git a/target/arm/tcg/sve_helper.c b/target/arm/tcg/sve_helper.c index f006d152cc..bce4295d28 100644 --- a/target/arm/tcg/sve_helper.c +++ b/target/arm/tcg/sve_helper.c @@ -5481,7 +5481,7 @@ bool sve_cont_ldst_pages(SVEContLdSt *info, SVEContFault fault, CPUARMState *env, target_ulong addr, MMUAccessType access_type, uintptr_t retaddr) { - int mmu_idx = cpu_mmu_index(env, false); + int mmu_idx = arm_env_mmu_index(env); int mem_off = info->mem_off_first[0]; bool nofault = fault == FAULT_NO; bool have_work = true; @@ -6529,7 +6529,7 @@ void sve_ld1_z(CPUARMState *env, void *vd, uint64_t *vg, void *vm, sve_ldst1_host_fn *host_fn, sve_ldst1_tlb_fn *tlb_fn) { - const int mmu_idx = cpu_mmu_index(env, false); + const int mmu_idx = arm_env_mmu_index(env); const intptr_t reg_max = simd_oprsz(desc); const int scale = simd_data(desc); ARMVectorReg scratch; @@ -6715,7 +6715,7 @@ void sve_ldff1_z(CPUARMState *env, void *vd, uint64_t *vg, void *vm, sve_ldst1_host_fn *host_fn, sve_ldst1_tlb_fn *tlb_fn) { - const int mmu_idx = cpu_mmu_index(env, false); + const int mmu_idx = arm_env_mmu_index(env); const intptr_t reg_max = simd_oprsz(desc); const int scale = simd_data(desc); const int esize = 1 << esz; @@ -6920,7 +6920,7 @@ void sve_st1_z(CPUARMState *env, void *vd, uint64_t *vg, void *vm, sve_ldst1_host_fn *host_fn, sve_ldst1_tlb_fn *tlb_fn) { - const int mmu_idx = cpu_mmu_index(env, false); + const int mmu_idx = arm_env_mmu_index(env); const intptr_t reg_max = simd_oprsz(desc); const int scale = simd_data(desc); void *host[ARM_MAX_VQ * 4]; diff --git a/target/arm/tcg/tlb_helper.c b/target/arm/tcg/tlb_helper.c index 5477c7fb7d..885bf4ec14 100644 --- a/target/arm/tcg/tlb_helper.c +++ b/target/arm/tcg/tlb_helper.c @@ -281,7 +281,7 @@ void helper_exception_pc_alignment(CPUARMState *env, target_ulong pc) { ARMMMUFaultInfo fi = { .type = ARMFault_Alignment }; int target_el = exception_target_el(env); - int mmu_idx = cpu_mmu_index(env, true); + int mmu_idx = arm_env_mmu_index(env); uint32_t fsc; env->exception.vaddress = pc; From 628421c74a64bcc7b4eda1218a66b77e89e02d4f Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Mon, 29 Jan 2024 09:08:57 +1000 Subject: [PATCH 05/58] target/arm: Populate CPUClass.mmu_index MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Reviewed-by: Philippe Mathieu-Daudé Signed-off-by: Richard Henderson --- target/arm/cpu.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/target/arm/cpu.c b/target/arm/cpu.c index 6a96b245f2..1f9ea622bd 100644 --- a/target/arm/cpu.c +++ b/target/arm/cpu.c @@ -133,6 +133,11 @@ static bool arm_cpu_has_work(CPUState *cs) | CPU_INTERRUPT_EXITTB); } +static int arm_cpu_mmu_index(CPUState *cs, bool ifetch) +{ + return arm_env_mmu_index(cpu_env(cs)); +} + void arm_register_pre_el_change_hook(ARMCPU *cpu, ARMELChangeHookFn *hook, void *opaque) { @@ -2497,6 +2502,7 @@ static void arm_cpu_class_init(ObjectClass *oc, void *data) cc->class_by_name = arm_cpu_class_by_name; cc->has_work = arm_cpu_has_work; + cc->mmu_index = arm_cpu_mmu_index; cc->dump_state = arm_cpu_dump_state; cc->set_pc = arm_cpu_set_pc; cc->get_pc = arm_cpu_get_pc; From b9e877f20f22b308ef2c2fd5e3e7c3b6295db994 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Mon, 29 Jan 2024 09:12:17 +1000 Subject: [PATCH 06/58] target/avr: Populate CPUClass.mmu_index MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Reviewed-by: Philippe Mathieu-Daudé Signed-off-by: Richard Henderson --- target/avr/cpu.c | 6 ++++++ target/avr/cpu.h | 4 +--- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/target/avr/cpu.c b/target/avr/cpu.c index 1c68748b24..a40f445af2 100644 --- a/target/avr/cpu.c +++ b/target/avr/cpu.c @@ -50,6 +50,11 @@ static bool avr_cpu_has_work(CPUState *cs) && cpu_interrupts_enabled(env); } +static int avr_cpu_mmu_index(CPUState *cs, bool ifetch) +{ + return ifetch ? MMU_CODE_IDX : MMU_DATA_IDX; +} + static void avr_cpu_synchronize_from_tb(CPUState *cs, const TranslationBlock *tb) { @@ -236,6 +241,7 @@ static void avr_cpu_class_init(ObjectClass *oc, void *data) cc->class_by_name = avr_cpu_class_by_name; cc->has_work = avr_cpu_has_work; + cc->mmu_index = avr_cpu_mmu_index; cc->dump_state = avr_cpu_dump_state; cc->set_pc = avr_cpu_set_pc; cc->get_pc = avr_cpu_get_pc; diff --git a/target/avr/cpu.h b/target/avr/cpu.h index 7d5dd42575..4595c6bb18 100644 --- a/target/avr/cpu.h +++ b/target/avr/cpu.h @@ -184,9 +184,7 @@ static inline void set_avr_feature(CPUAVRState *env, int feature) env->features |= (1U << feature); } -#define cpu_mmu_index avr_cpu_mmu_index - -static inline int avr_cpu_mmu_index(CPUAVRState *env, bool ifetch) +static inline int cpu_mmu_index(CPUAVRState *env, bool ifetch) { return ifetch ? MMU_CODE_IDX : MMU_DATA_IDX; } From 97fc0c210bf522d319f2c55c03c7f977f3f9b46c Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Sun, 28 Jan 2024 15:05:06 +1000 Subject: [PATCH 07/58] target/cris: Cache mem_index in DisasContext MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Compute this value once for each translation. Reviewed-by: Philippe Mathieu-Daudé Signed-off-by: Richard Henderson --- target/cris/translate.c | 14 +++++--------- target/cris/translate_v10.c.inc | 6 ++---- 2 files changed, 7 insertions(+), 13 deletions(-) diff --git a/target/cris/translate.c b/target/cris/translate.c index ee1402a9a3..7acea29a01 100644 --- a/target/cris/translate.c +++ b/target/cris/translate.c @@ -94,6 +94,7 @@ typedef struct DisasContext { CRISCPU *cpu; target_ulong pc, ppc; + int mem_index; /* Decoder. */ unsigned int (*decoder)(CPUCRISState *env, struct DisasContext *dc); @@ -1008,37 +1009,31 @@ static inline void cris_prepare_jmp (DisasContext *dc, unsigned int type) static void gen_load64(DisasContext *dc, TCGv_i64 dst, TCGv addr) { - int mem_index = cpu_mmu_index(&dc->cpu->env, false); - /* If we get a fault on a delayslot we must keep the jmp state in the cpu-state to be able to re-execute the jmp. */ if (dc->delayed_branch == 1) { cris_store_direct_jmp(dc); } - tcg_gen_qemu_ld_i64(dst, addr, mem_index, MO_TEUQ); + tcg_gen_qemu_ld_i64(dst, addr, dc->mem_index, MO_TEUQ); } static void gen_load(DisasContext *dc, TCGv dst, TCGv addr, unsigned int size, int sign) { - int mem_index = cpu_mmu_index(&dc->cpu->env, false); - /* If we get a fault on a delayslot we must keep the jmp state in the cpu-state to be able to re-execute the jmp. */ if (dc->delayed_branch == 1) { cris_store_direct_jmp(dc); } - tcg_gen_qemu_ld_tl(dst, addr, mem_index, + tcg_gen_qemu_ld_tl(dst, addr, dc->mem_index, MO_TE + ctz32(size) + (sign ? MO_SIGN : 0)); } static void gen_store (DisasContext *dc, TCGv addr, TCGv val, unsigned int size) { - int mem_index = cpu_mmu_index(&dc->cpu->env, false); - /* If we get a fault on a delayslot we must keep the jmp state in the cpu-state to be able to re-execute the jmp. */ if (dc->delayed_branch == 1) { @@ -1055,7 +1050,7 @@ static void gen_store (DisasContext *dc, TCGv addr, TCGv val, return; } - tcg_gen_qemu_st_tl(val, addr, mem_index, MO_TE + ctz32(size)); + tcg_gen_qemu_st_tl(val, addr, dc->mem_index, MO_TE + ctz32(size)); if (dc->flags_x) { cris_evaluate_flags(dc); @@ -2971,6 +2966,7 @@ static void cris_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cs) dc->cpu = env_archcpu(env); dc->ppc = pc_start; dc->pc = pc_start; + dc->mem_index = cpu_mmu_index(env, false); dc->flags_uptodate = 1; dc->flags_x = tb_flags & X_FLAG; dc->cc_x_uptodate = 0; diff --git a/target/cris/translate_v10.c.inc b/target/cris/translate_v10.c.inc index 6df599fdce..73fc27c15d 100644 --- a/target/cris/translate_v10.c.inc +++ b/target/cris/translate_v10.c.inc @@ -91,8 +91,6 @@ static void gen_store_v10_conditional(DisasContext *dc, TCGv addr, TCGv val, static void gen_store_v10(DisasContext *dc, TCGv addr, TCGv val, unsigned int size) { - int mem_index = cpu_mmu_index(&dc->cpu->env, false); - /* If we get a fault on a delayslot we must keep the jmp state in the cpu-state to be able to re-execute the jmp. */ if (dc->delayed_branch == 1) { @@ -101,11 +99,11 @@ static void gen_store_v10(DisasContext *dc, TCGv addr, TCGv val, /* Conditional writes. */ if (dc->flags_x) { - gen_store_v10_conditional(dc, addr, val, size, mem_index); + gen_store_v10_conditional(dc, addr, val, size, dc->mem_index); return; } - tcg_gen_qemu_st_tl(val, addr, mem_index, ctz32(size) | MO_TE); + tcg_gen_qemu_st_tl(val, addr, dc->mem_index, ctz32(size) | MO_TE); } From 3f605a15a7ec14885ba34d15758ccaeceeee9f49 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Mon, 29 Jan 2024 09:17:09 +1000 Subject: [PATCH 08/58] target/cris: Populate CPUClass.mmu_index MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Reviewed-by: Philippe Mathieu-Daudé Signed-off-by: Richard Henderson --- target/cris/cpu.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/target/cris/cpu.c b/target/cris/cpu.c index 6349148b65..163fb05d58 100644 --- a/target/cris/cpu.c +++ b/target/cris/cpu.c @@ -56,6 +56,11 @@ static bool cris_cpu_has_work(CPUState *cs) return cs->interrupt_request & (CPU_INTERRUPT_HARD | CPU_INTERRUPT_NMI); } +static int cris_cpu_mmu_index(CPUState *cs, bool ifetch) +{ + return !!(cpu_env(cs)->pregs[PR_CCS] & U_FLAG); +} + static void cris_cpu_reset_hold(Object *obj) { CPUState *s = CPU(obj); @@ -274,6 +279,7 @@ static void cris_cpu_class_init(ObjectClass *oc, void *data) cc->class_by_name = cris_cpu_class_by_name; cc->has_work = cris_cpu_has_work; + cc->mmu_index = cris_cpu_mmu_index; cc->dump_state = cris_cpu_dump_state; cc->set_pc = cris_cpu_set_pc; cc->get_pc = cris_cpu_get_pc; From 8f39cb77643828e08fe3320a0080dd0e27dd8e3b Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Mon, 29 Jan 2024 09:22:51 +1000 Subject: [PATCH 09/58] target/hppa: Populate CPUClass.mmu_index MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Reviewed-by: Helge Deller Reviewed-by: Philippe Mathieu-Daudé Signed-off-by: Richard Henderson --- target/hppa/cpu.c | 12 ++++++++++++ target/hppa/cpu.h | 7 ++----- 2 files changed, 14 insertions(+), 5 deletions(-) diff --git a/target/hppa/cpu.c b/target/hppa/cpu.c index 3c019855b4..fbb37e541e 100644 --- a/target/hppa/cpu.c +++ b/target/hppa/cpu.c @@ -94,6 +94,17 @@ static bool hppa_cpu_has_work(CPUState *cs) return cs->interrupt_request & (CPU_INTERRUPT_HARD | CPU_INTERRUPT_NMI); } +int hppa_cpu_mmu_index(CPUState *cs, bool ifetch) +{ + CPUHPPAState *env = cpu_env(cs); + + if (env->psw & (ifetch ? PSW_C : PSW_D)) { + return PRIV_P_TO_MMU_IDX(env->iaoq_f & 3, env->psw & PSW_P); + } + /* mmu disabled */ + return env->psw & PSW_W ? MMU_ABS_W_IDX : MMU_ABS_IDX; +} + static void hppa_cpu_disas_set_info(CPUState *cs, disassemble_info *info) { info->mach = bfd_mach_hppa20; @@ -194,6 +205,7 @@ static void hppa_cpu_class_init(ObjectClass *oc, void *data) cc->class_by_name = hppa_cpu_class_by_name; cc->has_work = hppa_cpu_has_work; + cc->mmu_index = hppa_cpu_mmu_index; cc->dump_state = hppa_cpu_dump_state; cc->set_pc = hppa_cpu_set_pc; cc->get_pc = hppa_cpu_get_pc; diff --git a/target/hppa/cpu.h b/target/hppa/cpu.h index 6a153405d2..04439f247d 100644 --- a/target/hppa/cpu.h +++ b/target/hppa/cpu.h @@ -281,16 +281,13 @@ static inline int HPPA_BTLB_ENTRIES(CPUHPPAState *env) return hppa_is_pa20(env) ? 0 : PA10_BTLB_FIXED + PA10_BTLB_VARIABLE; } +int hppa_cpu_mmu_index(CPUState *cs, bool ifetch); static inline int cpu_mmu_index(CPUHPPAState *env, bool ifetch) { #ifdef CONFIG_USER_ONLY return MMU_USER_IDX; #else - if (env->psw & (ifetch ? PSW_C : PSW_D)) { - return PRIV_P_TO_MMU_IDX(env->iaoq_f & 3, env->psw & PSW_P); - } - /* mmu disabled */ - return env->psw & PSW_W ? MMU_ABS_W_IDX : MMU_ABS_IDX; + return hppa_cpu_mmu_index(env_cpu(env), ifetch); #endif } From ace0c5fe595047d720c685478b22a5e4c572ac42 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Mon, 29 Jan 2024 09:31:15 +1000 Subject: [PATCH 10/58] target/i386: Populate CPUClass.mmu_index MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Reviewed-by: Philippe Mathieu-Daudé Signed-off-by: Richard Henderson --- target/i386/cpu.c | 10 ++++++++++ target/i386/cpu.h | 13 ++++++------- 2 files changed, 16 insertions(+), 7 deletions(-) diff --git a/target/i386/cpu.c b/target/i386/cpu.c index 03822d9ba8..280bcb7d00 100644 --- a/target/i386/cpu.c +++ b/target/i386/cpu.c @@ -7720,6 +7720,15 @@ static bool x86_cpu_has_work(CPUState *cs) return x86_cpu_pending_interrupt(cs, cs->interrupt_request) != 0; } +int x86_cpu_mmu_index(CPUState *cs, bool ifetch) +{ + CPUX86State *env = cpu_env(cs); + + return (env->hflags & HF_CPL_MASK) == 3 ? MMU_USER_IDX : + (!(env->hflags & HF_SMAP_MASK) || (env->eflags & AC_MASK)) + ? MMU_KNOSMAP_IDX : MMU_KSMAP_IDX; +} + static void x86_disas_set_info(CPUState *cs, disassemble_info *info) { X86CPU *cpu = X86_CPU(cs); @@ -7954,6 +7963,7 @@ static void x86_cpu_common_class_init(ObjectClass *oc, void *data) cc->class_by_name = x86_cpu_class_by_name; cc->parse_features = x86_cpu_parse_featurestr; cc->has_work = x86_cpu_has_work; + cc->mmu_index = x86_cpu_mmu_index; cc->dump_state = x86_cpu_dump_state; cc->set_pc = x86_cpu_set_pc; cc->get_pc = x86_cpu_get_pc; diff --git a/target/i386/cpu.h b/target/i386/cpu.h index 7f0786e8b9..62bdb02378 100644 --- a/target/i386/cpu.h +++ b/target/i386/cpu.h @@ -2296,13 +2296,6 @@ uint64_t cpu_get_tsc(CPUX86State *env); #define MMU_NESTED_IDX 3 #define MMU_PHYS_IDX 4 -static inline int cpu_mmu_index(CPUX86State *env, bool ifetch) -{ - return (env->hflags & HF_CPL_MASK) == 3 ? MMU_USER_IDX : - (!(env->hflags & HF_SMAP_MASK) || (env->eflags & AC_MASK)) - ? MMU_KNOSMAP_IDX : MMU_KSMAP_IDX; -} - static inline int cpu_mmu_index_kernel(CPUX86State *env) { return !(env->hflags & HF_SMAP_MASK) ? MMU_KNOSMAP_IDX : @@ -2322,6 +2315,12 @@ static inline int cpu_mmu_index_kernel(CPUX86State *env) #include "hw/i386/apic.h" #endif +int x86_cpu_mmu_index(CPUState *cs, bool ifetch); +static inline int cpu_mmu_index(CPUX86State *env, bool ifetch) +{ + return x86_cpu_mmu_index(env_cpu(env), ifetch); +} + static inline void cpu_get_tb_cpu_state(CPUX86State *env, vaddr *pc, uint64_t *cs_base, uint32_t *flags) { From a72a1b105d22eaf9a095143a317e738a3ef12019 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Fri, 2 Feb 2024 15:49:50 +1000 Subject: [PATCH 11/58] target/loongarch: Populate CPUClass.mmu_index MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Reviewed-by: Philippe Mathieu-Daudé Signed-off-by: Richard Henderson --- target/loongarch/cpu.c | 11 +++++++++++ target/loongarch/cpu.h | 6 ++---- 2 files changed, 13 insertions(+), 4 deletions(-) diff --git a/target/loongarch/cpu.c b/target/loongarch/cpu.c index 76eb4961d5..e96159943a 100644 --- a/target/loongarch/cpu.c +++ b/target/loongarch/cpu.c @@ -375,6 +375,16 @@ static bool loongarch_cpu_has_work(CPUState *cs) #endif } +int loongarch_cpu_mmu_index(CPUState *cs, bool ifetch) +{ + CPULoongArchState *env = cpu_env(cs); + + if (FIELD_EX64(env->CSR_CRMD, CSR_CRMD, PG)) { + return FIELD_EX64(env->CSR_CRMD, CSR_CRMD, PLV); + } + return MMU_IDX_DA; +} + static void loongarch_la464_initfn(Object *obj) { LoongArchCPU *cpu = LOONGARCH_CPU(obj); @@ -777,6 +787,7 @@ static void loongarch_cpu_class_init(ObjectClass *c, void *data) cc->class_by_name = loongarch_cpu_class_by_name; cc->has_work = loongarch_cpu_has_work; + cc->mmu_index = loongarch_cpu_mmu_index; cc->dump_state = loongarch_cpu_dump_state; cc->set_pc = loongarch_cpu_set_pc; cc->get_pc = loongarch_cpu_get_pc; diff --git a/target/loongarch/cpu.h b/target/loongarch/cpu.h index 0fa5e0ca93..5dfcfeb3a4 100644 --- a/target/loongarch/cpu.h +++ b/target/loongarch/cpu.h @@ -408,15 +408,13 @@ struct LoongArchCPUClass { #define MMU_IDX_USER MMU_PLV_USER #define MMU_IDX_DA 4 +int loongarch_cpu_mmu_index(CPUState *cs, bool ifetch); static inline int cpu_mmu_index(CPULoongArchState *env, bool ifetch) { #ifdef CONFIG_USER_ONLY return MMU_IDX_USER; #else - if (FIELD_EX64(env->CSR_CRMD, CSR_CRMD, PG)) { - return FIELD_EX64(env->CSR_CRMD, CSR_CRMD, PLV); - } - return MMU_IDX_DA; + return loongarch_cpu_mmu_index(env_cpu(env), ifetch); #endif } From 3f262d256802b72a2b819de260c5e57effbc53f7 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Fri, 2 Feb 2024 15:49:51 +1000 Subject: [PATCH 12/58] target/loongarch: Rename MMU_IDX_* MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The expected form is MMU_FOO_IDX, not MMU_IDX_FOO. Rename to match generic code. Reviewed-by: Philippe Mathieu-Daudé Signed-off-by: Richard Henderson --- target/loongarch/cpu.c | 2 +- target/loongarch/cpu.h | 8 ++++---- target/loongarch/cpu_helper.c | 4 ++-- target/loongarch/tcg/insn_trans/trans_privileged.c.inc | 2 +- target/loongarch/tcg/translate.c | 2 +- 5 files changed, 9 insertions(+), 9 deletions(-) diff --git a/target/loongarch/cpu.c b/target/loongarch/cpu.c index e96159943a..49ced9888e 100644 --- a/target/loongarch/cpu.c +++ b/target/loongarch/cpu.c @@ -382,7 +382,7 @@ int loongarch_cpu_mmu_index(CPUState *cs, bool ifetch) if (FIELD_EX64(env->CSR_CRMD, CSR_CRMD, PG)) { return FIELD_EX64(env->CSR_CRMD, CSR_CRMD, PLV); } - return MMU_IDX_DA; + return MMU_DA_IDX; } static void loongarch_la464_initfn(Object *obj) diff --git a/target/loongarch/cpu.h b/target/loongarch/cpu.h index 5dfcfeb3a4..47fd110e81 100644 --- a/target/loongarch/cpu.h +++ b/target/loongarch/cpu.h @@ -404,15 +404,15 @@ struct LoongArchCPUClass { */ #define MMU_PLV_KERNEL 0 #define MMU_PLV_USER 3 -#define MMU_IDX_KERNEL MMU_PLV_KERNEL -#define MMU_IDX_USER MMU_PLV_USER -#define MMU_IDX_DA 4 +#define MMU_KERNEL_IDX MMU_PLV_KERNEL +#define MMU_USER_IDX MMU_PLV_USER +#define MMU_DA_IDX 4 int loongarch_cpu_mmu_index(CPUState *cs, bool ifetch); static inline int cpu_mmu_index(CPULoongArchState *env, bool ifetch) { #ifdef CONFIG_USER_ONLY - return MMU_IDX_USER; + return MMU_USER_IDX; #else return loongarch_cpu_mmu_index(env_cpu(env), ifetch); #endif diff --git a/target/loongarch/cpu_helper.c b/target/loongarch/cpu_helper.c index f68d63f466..b0658773b0 100644 --- a/target/loongarch/cpu_helper.c +++ b/target/loongarch/cpu_helper.c @@ -171,8 +171,8 @@ int get_physical_address(CPULoongArchState *env, hwaddr *physical, int *prot, target_ulong address, MMUAccessType access_type, int mmu_idx) { - int user_mode = mmu_idx == MMU_IDX_USER; - int kernel_mode = mmu_idx == MMU_IDX_KERNEL; + int user_mode = mmu_idx == MMU_USER_IDX; + int kernel_mode = mmu_idx == MMU_KERNEL_IDX; uint32_t plv, base_c, base_v; int64_t addr_high; uint8_t da = FIELD_EX64(env->CSR_CRMD, CSR_CRMD, DA); diff --git a/target/loongarch/tcg/insn_trans/trans_privileged.c.inc b/target/loongarch/tcg/insn_trans/trans_privileged.c.inc index 01d457212b..7e4ec93edb 100644 --- a/target/loongarch/tcg/insn_trans/trans_privileged.c.inc +++ b/target/loongarch/tcg/insn_trans/trans_privileged.c.inc @@ -323,7 +323,7 @@ TRANS(iocsrwr_d, IOCSR, gen_iocsrwr, gen_helper_iocsrwr_d) static void check_mmu_idx(DisasContext *ctx) { - if (ctx->mem_idx != MMU_IDX_DA) { + if (ctx->mem_idx != MMU_DA_IDX) { tcg_gen_movi_tl(cpu_pc, ctx->base.pc_next + 4); ctx->base.is_jmp = DISAS_EXIT; } diff --git a/target/loongarch/tcg/translate.c b/target/loongarch/tcg/translate.c index 235515c629..58674cb268 100644 --- a/target/loongarch/tcg/translate.c +++ b/target/loongarch/tcg/translate.c @@ -125,7 +125,7 @@ static void loongarch_tr_init_disas_context(DisasContextBase *dcbase, if (ctx->base.tb->flags & HW_FLAGS_CRMD_PG) { ctx->mem_idx = ctx->plv; } else { - ctx->mem_idx = MMU_IDX_DA; + ctx->mem_idx = MMU_DA_IDX; } /* Bound the number of insns to execute to those left on the page. */ From a5a2d7f64f0d71278fb338a25fb9a05f926b6845 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Mon, 29 Jan 2024 09:38:31 +1000 Subject: [PATCH 13/58] target/m68k: Populate CPUClass.mmu_index MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Reviewed-by: Philippe Mathieu-Daudé Signed-off-by: Richard Henderson --- target/m68k/cpu.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/target/m68k/cpu.c b/target/m68k/cpu.c index 44000f5869..8a8392e694 100644 --- a/target/m68k/cpu.c +++ b/target/m68k/cpu.c @@ -56,6 +56,11 @@ static bool m68k_cpu_has_work(CPUState *cs) return cs->interrupt_request & CPU_INTERRUPT_HARD; } +static int m68k_cpu_mmu_index(CPUState *cs, bool ifetch) +{ + return cpu_env(cs)->sr & SR_S ? MMU_KERNEL_IDX : MMU_USER_IDX; +} + static void m68k_set_feature(CPUM68KState *env, int feature) { env->features |= BIT_ULL(feature); @@ -551,6 +556,7 @@ static void m68k_cpu_class_init(ObjectClass *c, void *data) cc->class_by_name = m68k_cpu_class_by_name; cc->has_work = m68k_cpu_has_work; + cc->mmu_index = m68k_cpu_mmu_index; cc->dump_state = m68k_cpu_dump_state; cc->set_pc = m68k_cpu_set_pc; cc->get_pc = m68k_cpu_get_pc; From 167d6cd0e855eb64d51707fea194833695bac2c4 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Mon, 29 Jan 2024 09:44:10 +1000 Subject: [PATCH 14/58] target/microblaze: Populate CPUClass.mmu_index MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Reviewed-by: Philippe Mathieu-Daudé Signed-off-by: Richard Henderson --- target/microblaze/cpu.c | 18 +++++++++++++++++- target/microblaze/cpu.h | 13 ++----------- 2 files changed, 19 insertions(+), 12 deletions(-) diff --git a/target/microblaze/cpu.c b/target/microblaze/cpu.c index 2318ad7013..6dad11905b 100644 --- a/target/microblaze/cpu.c +++ b/target/microblaze/cpu.c @@ -118,6 +118,22 @@ static bool mb_cpu_has_work(CPUState *cs) return cs->interrupt_request & (CPU_INTERRUPT_HARD | CPU_INTERRUPT_NMI); } +int mb_cpu_mmu_index(CPUState *cs, bool ifetch) +{ + CPUMBState *env = cpu_env(cs); + MicroBlazeCPU *cpu = env_archcpu(env); + + /* Are we in nommu mode?. */ + if (!(env->msr & MSR_VM) || !cpu->cfg.use_mmu) { + return MMU_NOMMU_IDX; + } + + if (env->msr & MSR_UM) { + return MMU_USER_IDX; + } + return MMU_KERNEL_IDX; +} + #ifndef CONFIG_USER_ONLY static void mb_cpu_ns_axi_dp(void *opaque, int irq, int level) { @@ -415,7 +431,7 @@ static void mb_cpu_class_init(ObjectClass *oc, void *data) cc->class_by_name = mb_cpu_class_by_name; cc->has_work = mb_cpu_has_work; - + cc->mmu_index = mb_cpu_mmu_index; cc->dump_state = mb_cpu_dump_state; cc->set_pc = mb_cpu_set_pc; cc->get_pc = mb_cpu_get_pc; diff --git a/target/microblaze/cpu.h b/target/microblaze/cpu.h index b5374365f5..90ab796de9 100644 --- a/target/microblaze/cpu.h +++ b/target/microblaze/cpu.h @@ -434,19 +434,10 @@ void mb_cpu_transaction_failed(CPUState *cs, hwaddr physaddr, vaddr addr, MemTxResult response, uintptr_t retaddr); #endif +int mb_cpu_mmu_index(CPUState *cs, bool ifetch); static inline int cpu_mmu_index(CPUMBState *env, bool ifetch) { - MicroBlazeCPU *cpu = env_archcpu(env); - - /* Are we in nommu mode?. */ - if (!(env->msr & MSR_VM) || !cpu->cfg.use_mmu) { - return MMU_NOMMU_IDX; - } - - if (env->msr & MSR_UM) { - return MMU_USER_IDX; - } - return MMU_KERNEL_IDX; + return mb_cpu_mmu_index(env_cpu(env), ifetch); } #ifndef CONFIG_USER_ONLY From 4e999bf4197ae3dc58b7092260f98146920a7469 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Sun, 28 Jan 2024 15:58:52 +1000 Subject: [PATCH 15/58] target/mips: Pass ptw_mmu_idx down from mips_cpu_tlb_fill MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Rather than adjust env->hflags so that the value computed by cpu_mmu_index() changes, compute the mmu_idx that we want directly and pass it down. Introduce symbolic constants for MMU_{KERNEL,ERL}_IDX. Reviewed-by: Philippe Mathieu-Daudé Signed-off-by: Richard Henderson --- target/mips/cpu.h | 4 +++- target/mips/tcg/sysemu/tlb_helper.c | 32 ++++++++++++----------------- 2 files changed, 16 insertions(+), 20 deletions(-) diff --git a/target/mips/cpu.h b/target/mips/cpu.h index 1163a71f3c..3ba8dccd2d 100644 --- a/target/mips/cpu.h +++ b/target/mips/cpu.h @@ -1242,12 +1242,14 @@ uint32_t cpu_rddsp(uint32_t mask_num, CPUMIPSState *env); * MMU modes definitions. We carefully match the indices with our * hflags layout. */ +#define MMU_KERNEL_IDX 0 #define MMU_USER_IDX 2 +#define MMU_ERL_IDX 3 static inline int hflags_mmu_index(uint32_t hflags) { if (hflags & MIPS_HFLAG_ERL) { - return 3; /* ERL */ + return MMU_ERL_IDX; } else { return hflags & MIPS_HFLAG_KSU; } diff --git a/target/mips/tcg/sysemu/tlb_helper.c b/target/mips/tcg/sysemu/tlb_helper.c index 4ede904800..b715449114 100644 --- a/target/mips/tcg/sysemu/tlb_helper.c +++ b/target/mips/tcg/sysemu/tlb_helper.c @@ -623,7 +623,7 @@ static uint64_t get_tlb_entry_layout(CPUMIPSState *env, uint64_t entry, static int walk_directory(CPUMIPSState *env, uint64_t *vaddr, int directory_index, bool *huge_page, bool *hgpg_directory_hit, uint64_t *pw_entrylo0, uint64_t *pw_entrylo1, - unsigned directory_shift, unsigned leaf_shift) + unsigned directory_shift, unsigned leaf_shift, int ptw_mmu_idx) { int dph = (env->CP0_PWCtl >> CP0PC_DPH) & 0x1; int psn = (env->CP0_PWCtl >> CP0PC_PSN) & 0x3F; @@ -638,8 +638,7 @@ static int walk_directory(CPUMIPSState *env, uint64_t *vaddr, uint64_t w = 0; if (get_physical_address(env, &paddr, &prot, *vaddr, MMU_DATA_LOAD, - cpu_mmu_index(env, false)) != - TLBRET_MATCH) { + ptw_mmu_idx) != TLBRET_MATCH) { /* wrong base address */ return 0; } @@ -666,8 +665,7 @@ static int walk_directory(CPUMIPSState *env, uint64_t *vaddr, *pw_entrylo0 = entry; } if (get_physical_address(env, &paddr, &prot, vaddr2, MMU_DATA_LOAD, - cpu_mmu_index(env, false)) != - TLBRET_MATCH) { + ptw_mmu_idx) != TLBRET_MATCH) { return 0; } if (!get_pte(env, vaddr2, leafentry_size, &entry)) { @@ -690,7 +688,7 @@ static int walk_directory(CPUMIPSState *env, uint64_t *vaddr, } static bool page_table_walk_refill(CPUMIPSState *env, vaddr address, - int mmu_idx) + int ptw_mmu_idx) { int gdw = (env->CP0_PWSize >> CP0PS_GDW) & 0x3F; int udw = (env->CP0_PWSize >> CP0PS_UDW) & 0x3F; @@ -776,7 +774,7 @@ static bool page_table_walk_refill(CPUMIPSState *env, vaddr address, vaddr |= goffset; switch (walk_directory(env, &vaddr, pf_gdw, &huge_page, &hgpg_gdhit, &pw_entrylo0, &pw_entrylo1, - directory_shift, leaf_shift)) + directory_shift, leaf_shift, ptw_mmu_idx)) { case 0: return false; @@ -793,7 +791,7 @@ static bool page_table_walk_refill(CPUMIPSState *env, vaddr address, vaddr |= uoffset; switch (walk_directory(env, &vaddr, pf_udw, &huge_page, &hgpg_udhit, &pw_entrylo0, &pw_entrylo1, - directory_shift, leaf_shift)) + directory_shift, leaf_shift, ptw_mmu_idx)) { case 0: return false; @@ -810,7 +808,7 @@ static bool page_table_walk_refill(CPUMIPSState *env, vaddr address, vaddr |= moffset; switch (walk_directory(env, &vaddr, pf_mdw, &huge_page, &hgpg_mdhit, &pw_entrylo0, &pw_entrylo1, - directory_shift, leaf_shift)) + directory_shift, leaf_shift, ptw_mmu_idx)) { case 0: return false; @@ -825,8 +823,7 @@ static bool page_table_walk_refill(CPUMIPSState *env, vaddr address, /* Leaf Level Page Table - First half of PTE pair */ vaddr |= ptoffset0; if (get_physical_address(env, &paddr, &prot, vaddr, MMU_DATA_LOAD, - cpu_mmu_index(env, false)) != - TLBRET_MATCH) { + ptw_mmu_idx) != TLBRET_MATCH) { return false; } if (!get_pte(env, vaddr, leafentry_size, &dir_entry)) { @@ -838,8 +835,7 @@ static bool page_table_walk_refill(CPUMIPSState *env, vaddr address, /* Leaf Level Page Table - Second half of PTE pair */ vaddr |= ptoffset1; if (get_physical_address(env, &paddr, &prot, vaddr, MMU_DATA_LOAD, - cpu_mmu_index(env, false)) != - TLBRET_MATCH) { + ptw_mmu_idx) != TLBRET_MATCH) { return false; } if (!get_pte(env, vaddr, leafentry_size, &dir_entry)) { @@ -944,12 +940,10 @@ bool mips_cpu_tlb_fill(CPUState *cs, vaddr address, int size, * Memory reads during hardware page table walking are performed * as if they were kernel-mode load instructions. */ - int mode = (env->hflags & MIPS_HFLAG_KSU); - bool ret_walker; - env->hflags &= ~MIPS_HFLAG_KSU; - ret_walker = page_table_walk_refill(env, address, mmu_idx); - env->hflags |= mode; - if (ret_walker) { + int ptw_mmu_idx = (env->hflags & MIPS_HFLAG_ERL ? + MMU_ERL_IDX : MMU_KERNEL_IDX); + + if (page_table_walk_refill(env, address, ptw_mmu_idx)) { ret = get_physical_address(env, &physical, &prot, address, access_type, mmu_idx); if (ret == TLBRET_MATCH) { From 6ebf33c5dccf71ca7bbb0d3d799af82f79d6445b Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Sun, 28 Jan 2024 16:00:39 +1000 Subject: [PATCH 16/58] target/mips: Split out mips_env_mmu_index MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Reviewed-by: Philippe Mathieu-Daudé Signed-off-by: Richard Henderson --- target/mips/cpu.h | 7 ++++++- target/mips/sysemu/physaddr.c | 2 +- target/mips/tcg/msa_helper.c | 10 +++++----- target/mips/tcg/sysemu/cp0_helper.c | 2 +- target/mips/tcg/sysemu/special_helper.c | 2 +- target/mips/tcg/sysemu/tlb_helper.c | 2 +- 6 files changed, 15 insertions(+), 10 deletions(-) diff --git a/target/mips/cpu.h b/target/mips/cpu.h index 3ba8dccd2d..4c15e76781 100644 --- a/target/mips/cpu.h +++ b/target/mips/cpu.h @@ -1255,11 +1255,16 @@ static inline int hflags_mmu_index(uint32_t hflags) } } -static inline int cpu_mmu_index(CPUMIPSState *env, bool ifetch) +static inline int mips_env_mmu_index(CPUMIPSState *env) { return hflags_mmu_index(env->hflags); } +static inline int cpu_mmu_index(CPUMIPSState *env, bool ifetch) +{ + return mips_env_mmu_index(env); +} + #include "exec/cpu-all.h" /* Exceptions */ diff --git a/target/mips/sysemu/physaddr.c b/target/mips/sysemu/physaddr.c index 05990aa5bb..13c8bc8f47 100644 --- a/target/mips/sysemu/physaddr.c +++ b/target/mips/sysemu/physaddr.c @@ -236,7 +236,7 @@ hwaddr mips_cpu_get_phys_page_debug(CPUState *cs, vaddr addr) int prot; if (get_physical_address(env, &phys_addr, &prot, addr, MMU_DATA_LOAD, - cpu_mmu_index(env, false)) != 0) { + mips_env_mmu_index(env)) != 0) { return -1; } return phys_addr; diff --git a/target/mips/tcg/msa_helper.c b/target/mips/tcg/msa_helper.c index 7a8dbada5d..d2181763e7 100644 --- a/target/mips/tcg/msa_helper.c +++ b/target/mips/tcg/msa_helper.c @@ -8214,7 +8214,7 @@ void helper_msa_ffint_u_df(CPUMIPSState *env, uint32_t df, uint32_t wd, #if !defined(CONFIG_USER_ONLY) #define MEMOP_IDX(DF) \ MemOpIdx oi = make_memop_idx(MO_TE | DF | MO_UNALN, \ - cpu_mmu_index(env, false)); + mips_env_mmu_index(env)); #else #define MEMOP_IDX(DF) #endif @@ -8323,7 +8323,7 @@ void helper_msa_st_b(CPUMIPSState *env, uint32_t wd, target_ulong addr) { wr_t *pwd = &(env->active_fpu.fpr[wd].wr); - int mmu_idx = cpu_mmu_index(env, false); + int mmu_idx = mips_env_mmu_index(env); uintptr_t ra = GETPC(); ensure_writable_pages(env, addr, mmu_idx, ra); @@ -8337,7 +8337,7 @@ void helper_msa_st_h(CPUMIPSState *env, uint32_t wd, target_ulong addr) { wr_t *pwd = &(env->active_fpu.fpr[wd].wr); - int mmu_idx = cpu_mmu_index(env, false); + int mmu_idx = mips_env_mmu_index(env); uintptr_t ra = GETPC(); uint64_t d0, d1; @@ -8358,7 +8358,7 @@ void helper_msa_st_w(CPUMIPSState *env, uint32_t wd, target_ulong addr) { wr_t *pwd = &(env->active_fpu.fpr[wd].wr); - int mmu_idx = cpu_mmu_index(env, false); + int mmu_idx = mips_env_mmu_index(env); uintptr_t ra = GETPC(); uint64_t d0, d1; @@ -8379,7 +8379,7 @@ void helper_msa_st_d(CPUMIPSState *env, uint32_t wd, target_ulong addr) { wr_t *pwd = &(env->active_fpu.fpr[wd].wr); - int mmu_idx = cpu_mmu_index(env, false); + int mmu_idx = mips_env_mmu_index(env); uintptr_t ra = GETPC(); ensure_writable_pages(env, addr, mmu_idx, GETPC()); diff --git a/target/mips/tcg/sysemu/cp0_helper.c b/target/mips/tcg/sysemu/cp0_helper.c index cc545aed9c..62f6fb4bf6 100644 --- a/target/mips/tcg/sysemu/cp0_helper.c +++ b/target/mips/tcg/sysemu/cp0_helper.c @@ -1202,7 +1202,7 @@ void helper_mtc0_status(CPUMIPSState *env, target_ulong arg1) old, old & env->CP0_Cause & CP0Ca_IP_mask, val, val & env->CP0_Cause & CP0Ca_IP_mask, env->CP0_Cause); - switch (cpu_mmu_index(env, false)) { + switch (mips_env_mmu_index(env)) { case 3: qemu_log(", ERL\n"); break; diff --git a/target/mips/tcg/sysemu/special_helper.c b/target/mips/tcg/sysemu/special_helper.c index 93276f789d..518d3fbc34 100644 --- a/target/mips/tcg/sysemu/special_helper.c +++ b/target/mips/tcg/sysemu/special_helper.c @@ -68,7 +68,7 @@ static void debug_post_eret(CPUMIPSState *env) if (env->hflags & MIPS_HFLAG_DM) { qemu_log(" DEPC " TARGET_FMT_lx, env->CP0_DEPC); } - switch (cpu_mmu_index(env, false)) { + switch (mips_env_mmu_index(env)) { case 3: qemu_log(", ERL\n"); break; diff --git a/target/mips/tcg/sysemu/tlb_helper.c b/target/mips/tcg/sysemu/tlb_helper.c index b715449114..cdae42ffdd 100644 --- a/target/mips/tcg/sysemu/tlb_helper.c +++ b/target/mips/tcg/sysemu/tlb_helper.c @@ -973,7 +973,7 @@ hwaddr cpu_mips_translate_address(CPUMIPSState *env, target_ulong address, /* data access */ ret = get_physical_address(env, &physical, &prot, address, access_type, - cpu_mmu_index(env, false)); + mips_env_mmu_index(env)); if (ret == TLBRET_MATCH) { return physical; } From 0efa3dc2757635e5a0dba745058e8eb2a126ffe5 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Mon, 29 Jan 2024 09:46:54 +1000 Subject: [PATCH 17/58] target/mips: Populate CPUClass.mmu_index MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Reviewed-by: Philippe Mathieu-Daudé Signed-off-by: Richard Henderson --- target/mips/cpu.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/target/mips/cpu.c b/target/mips/cpu.c index df544ab39b..d644adbc77 100644 --- a/target/mips/cpu.c +++ b/target/mips/cpu.c @@ -182,6 +182,11 @@ static bool mips_cpu_has_work(CPUState *cs) return has_work; } +static int mips_cpu_mmu_index(CPUState *cs, bool ifunc) +{ + return mips_env_mmu_index(cpu_env(cs)); +} + #include "cpu-defs.c.inc" static void mips_cpu_reset_hold(Object *obj) @@ -579,6 +584,7 @@ static void mips_cpu_class_init(ObjectClass *c, void *data) cc->class_by_name = mips_cpu_class_by_name; cc->has_work = mips_cpu_has_work; + cc->mmu_index = mips_cpu_mmu_index; cc->dump_state = mips_cpu_dump_state; cc->set_pc = mips_cpu_set_pc; cc->get_pc = mips_cpu_get_pc; From 498c7d78d3ef0346d3885842c505eb8d0ffb940e Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Mon, 29 Jan 2024 09:50:52 +1000 Subject: [PATCH 18/58] target/nios2: Populate CPUClass.mmu_index MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Reviewed-by: Philippe Mathieu-Daudé Signed-off-by: Richard Henderson --- target/nios2/cpu.c | 7 +++++++ target/nios2/cpu.h | 12 ++++++------ 2 files changed, 13 insertions(+), 6 deletions(-) diff --git a/target/nios2/cpu.c b/target/nios2/cpu.c index 596c0c5617..e42885997e 100644 --- a/target/nios2/cpu.c +++ b/target/nios2/cpu.c @@ -57,6 +57,12 @@ static bool nios2_cpu_has_work(CPUState *cs) return cs->interrupt_request & CPU_INTERRUPT_HARD; } +int nios2_cpu_mmu_index(CPUState *cs, bool ifetch) +{ + return (cpu_env(cs)->ctrl[CR_STATUS] & CR_STATUS_U + ? MMU_USER_IDX : MMU_SUPERVISOR_IDX); +} + static void nios2_cpu_reset_hold(Object *obj) { CPUState *cs = CPU(obj); @@ -381,6 +387,7 @@ static void nios2_cpu_class_init(ObjectClass *oc, void *data) cc->class_by_name = nios2_cpu_class_by_name; cc->has_work = nios2_cpu_has_work; + cc->mmu_index = nios2_cpu_mmu_index; cc->dump_state = nios2_cpu_dump_state; cc->set_pc = nios2_cpu_set_pc; cc->get_pc = nios2_cpu_get_pc; diff --git a/target/nios2/cpu.h b/target/nios2/cpu.h index 2d79b5b298..9965ff74c1 100644 --- a/target/nios2/cpu.h +++ b/target/nios2/cpu.h @@ -270,12 +270,6 @@ void do_nios2_semihosting(CPUNios2State *env); #define MMU_SUPERVISOR_IDX 0 #define MMU_USER_IDX 1 -static inline int cpu_mmu_index(CPUNios2State *env, bool ifetch) -{ - return (env->ctrl[CR_STATUS] & CR_STATUS_U) ? MMU_USER_IDX : - MMU_SUPERVISOR_IDX; -} - #ifndef CONFIG_USER_ONLY hwaddr nios2_cpu_get_phys_page_debug(CPUState *cpu, vaddr addr); bool nios2_cpu_tlb_fill(CPUState *cs, vaddr address, int size, @@ -292,6 +286,12 @@ FIELD(TBFLAGS, CRS0, 0, 1) /* Set if CRS == 0. */ FIELD(TBFLAGS, U, 1, 1) /* Overlaps CR_STATUS_U */ FIELD(TBFLAGS, R0_0, 2, 1) /* Set if R0 == 0. */ +int nios2_cpu_mmu_index(CPUState *cs, bool ifetch); +static inline int cpu_mmu_index(CPUNios2State *env, bool ifetch) +{ + return nios2_cpu_mmu_index(env_cpu(env), ifetch); +} + static inline void cpu_get_tb_cpu_state(CPUNios2State *env, vaddr *pc, uint64_t *cs_base, uint32_t *flags) { From db8b41941aabdfdc505b372ae8b8445581e96840 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Mon, 29 Jan 2024 10:13:23 +1000 Subject: [PATCH 19/58] target/openrisc: Populate CPUClass.mmu_index MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Reviewed-by: Philippe Mathieu-Daudé Signed-off-by: Richard Henderson --- target/openrisc/cpu.c | 13 +++++++++++++ target/openrisc/cpu.h | 10 ++-------- 2 files changed, 15 insertions(+), 8 deletions(-) diff --git a/target/openrisc/cpu.c b/target/openrisc/cpu.c index 477d49d4bc..8670152c84 100644 --- a/target/openrisc/cpu.c +++ b/target/openrisc/cpu.c @@ -68,6 +68,18 @@ static bool openrisc_cpu_has_work(CPUState *cs) CPU_INTERRUPT_TIMER); } +int openrisc_cpu_mmu_index(CPUState *cs, bool ifetch) +{ + CPUOpenRISCState *env = cpu_env(cs); + + if (env->sr & (ifetch ? SR_IME : SR_DME)) { + /* The mmu is enabled; test supervisor state. */ + return env->sr & SR_SM ? MMU_SUPERVISOR_IDX : MMU_USER_IDX; + } + + return MMU_NOMMU_IDX; /* mmu is disabled */ +} + static void openrisc_disas_set_info(CPUState *cpu, disassemble_info *info) { info->print_insn = print_insn_or1k; @@ -239,6 +251,7 @@ static void openrisc_cpu_class_init(ObjectClass *oc, void *data) cc->class_by_name = openrisc_cpu_class_by_name; cc->has_work = openrisc_cpu_has_work; + cc->mmu_index = openrisc_cpu_mmu_index; cc->dump_state = openrisc_cpu_dump_state; cc->set_pc = openrisc_cpu_set_pc; cc->get_pc = openrisc_cpu_get_pc; diff --git a/target/openrisc/cpu.h b/target/openrisc/cpu.h index b454014ddd..7dbed8d8be 100644 --- a/target/openrisc/cpu.h +++ b/target/openrisc/cpu.h @@ -361,16 +361,10 @@ static inline void cpu_get_tb_cpu_state(CPUOpenRISCState *env, vaddr *pc, | (env->sr & (SR_SM | SR_DME | SR_IME | SR_OVE)); } +int openrisc_cpu_mmu_index(CPUState *cs, bool ifetch); static inline int cpu_mmu_index(CPUOpenRISCState *env, bool ifetch) { - int ret = MMU_NOMMU_IDX; /* mmu is disabled */ - - if (env->sr & (ifetch ? SR_IME : SR_DME)) { - /* The mmu is enabled; test supervisor state. */ - ret = env->sr & SR_SM ? MMU_SUPERVISOR_IDX : MMU_USER_IDX; - } - - return ret; + return openrisc_cpu_mmu_index(env_cpu(env), ifetch); } static inline uint32_t cpu_get_sr(const CPUOpenRISCState *env) From fb00f730c5eb05b3c54da8b1f805008ca38672ea Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Mon, 29 Jan 2024 10:18:33 +1000 Subject: [PATCH 20/58] target/ppc: Split out ppc_env_mmu_index MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Reviewed-by: Philippe Mathieu-Daudé Signed-off-by: Richard Henderson --- target/ppc/cpu.h | 7 ++++++- target/ppc/cpu_init.c | 2 +- target/ppc/mem_helper.c | 10 +++++----- target/ppc/mmu_common.c | 4 ++-- 4 files changed, 14 insertions(+), 9 deletions(-) diff --git a/target/ppc/cpu.h b/target/ppc/cpu.h index f8101ffa29..5f4f52aec5 100644 --- a/target/ppc/cpu.h +++ b/target/ppc/cpu.h @@ -1624,7 +1624,7 @@ int ppc_dcr_write(ppc_dcr_t *dcr_env, int dcrn, uint32_t val); /* MMU modes definitions */ #define MMU_USER_IDX 0 -static inline int cpu_mmu_index(CPUPPCState *env, bool ifetch) +static inline int ppc_env_mmu_index(CPUPPCState *env, bool ifetch) { #ifdef CONFIG_USER_ONLY return MMU_USER_IDX; @@ -1633,6 +1633,11 @@ static inline int cpu_mmu_index(CPUPPCState *env, bool ifetch) #endif } +static inline int cpu_mmu_index(CPUPPCState *env, bool ifetch) +{ + return ppc_env_mmu_index(env, ifetch); +} + /* Compatibility modes */ #if defined(TARGET_PPC64) bool ppc_check_compat(PowerPCCPU *cpu, uint32_t compat_pvr, diff --git a/target/ppc/cpu_init.c b/target/ppc/cpu_init.c index 23eb5522b6..86c8031765 100644 --- a/target/ppc/cpu_init.c +++ b/target/ppc/cpu_init.c @@ -7457,7 +7457,7 @@ void ppc_cpu_dump_state(CPUState *cs, FILE *f, int flags) qemu_fprintf(f, "MSR " TARGET_FMT_lx " HID0 " TARGET_FMT_lx " HF " "%08x iidx %d didx %d\n", env->msr, env->spr[SPR_HID0], env->hflags, - cpu_mmu_index(env, true), cpu_mmu_index(env, false)); + ppc_env_mmu_index(env, true), ppc_env_mmu_index(env, false)); #if !defined(CONFIG_USER_ONLY) if (env->tb_env) { qemu_fprintf(f, "TB %08" PRIu32 " %08" PRIu64 diff --git a/target/ppc/mem_helper.c b/target/ppc/mem_helper.c index c7535481d6..ea7e8443a8 100644 --- a/target/ppc/mem_helper.c +++ b/target/ppc/mem_helper.c @@ -83,7 +83,7 @@ static void *probe_contiguous(CPUPPCState *env, target_ulong addr, uint32_t nb, void helper_lmw(CPUPPCState *env, target_ulong addr, uint32_t reg) { uintptr_t raddr = GETPC(); - int mmu_idx = cpu_mmu_index(env, false); + int mmu_idx = ppc_env_mmu_index(env, false); void *host = probe_contiguous(env, addr, (32 - reg) * 4, MMU_DATA_LOAD, mmu_idx, raddr); @@ -105,7 +105,7 @@ void helper_lmw(CPUPPCState *env, target_ulong addr, uint32_t reg) void helper_stmw(CPUPPCState *env, target_ulong addr, uint32_t reg) { uintptr_t raddr = GETPC(); - int mmu_idx = cpu_mmu_index(env, false); + int mmu_idx = ppc_env_mmu_index(env, false); void *host = probe_contiguous(env, addr, (32 - reg) * 4, MMU_DATA_STORE, mmu_idx, raddr); @@ -135,7 +135,7 @@ static void do_lsw(CPUPPCState *env, target_ulong addr, uint32_t nb, return; } - mmu_idx = cpu_mmu_index(env, false); + mmu_idx = ppc_env_mmu_index(env, false); host = probe_contiguous(env, addr, nb, MMU_DATA_LOAD, mmu_idx, raddr); if (likely(host)) { @@ -224,7 +224,7 @@ void helper_stsw(CPUPPCState *env, target_ulong addr, uint32_t nb, return; } - mmu_idx = cpu_mmu_index(env, false); + mmu_idx = ppc_env_mmu_index(env, false); host = probe_contiguous(env, addr, nb, MMU_DATA_STORE, mmu_idx, raddr); if (likely(host)) { @@ -276,7 +276,7 @@ static void dcbz_common(CPUPPCState *env, target_ulong addr, target_ulong mask, dcbz_size = env->dcache_line_size; uint32_t i; void *haddr; - int mmu_idx = epid ? PPC_TLB_EPID_STORE : cpu_mmu_index(env, false); + int mmu_idx = epid ? PPC_TLB_EPID_STORE : ppc_env_mmu_index(env, false); #if defined(TARGET_PPC64) /* Check for dcbz vs dcbzl on 970 */ diff --git a/target/ppc/mmu_common.c b/target/ppc/mmu_common.c index 6ca5d12207..751403f1c8 100644 --- a/target/ppc/mmu_common.c +++ b/target/ppc/mmu_common.c @@ -1561,9 +1561,9 @@ hwaddr ppc_cpu_get_phys_page_debug(CPUState *cs, vaddr addr) * mapped by code TLBs, so we also try a MMU_INST_FETCH. */ if (ppc_xlate(cpu, addr, MMU_DATA_LOAD, &raddr, &s, &p, - cpu_mmu_index(&cpu->env, false), false) || + ppc_env_mmu_index(&cpu->env, false), false) || ppc_xlate(cpu, addr, MMU_INST_FETCH, &raddr, &s, &p, - cpu_mmu_index(&cpu->env, true), false)) { + ppc_env_mmu_index(&cpu->env, true), false)) { return raddr & TARGET_PAGE_MASK; } return -1; From f331e82c3d60ede1cf9482a31ba5fdb0a292b274 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Mon, 29 Jan 2024 10:20:52 +1000 Subject: [PATCH 21/58] target/ppc: Populate CPUClass.mmu_index MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Reviewed-by: Philippe Mathieu-Daudé Signed-off-by: Richard Henderson --- target/ppc/cpu_init.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/target/ppc/cpu_init.c b/target/ppc/cpu_init.c index 86c8031765..9931372a08 100644 --- a/target/ppc/cpu_init.c +++ b/target/ppc/cpu_init.c @@ -7105,6 +7105,11 @@ static bool ppc_cpu_has_work(CPUState *cs) return cs->interrupt_request & CPU_INTERRUPT_HARD; } +static int ppc_cpu_mmu_index(CPUState *cs, bool ifetch) +{ + return ppc_env_mmu_index(cpu_env(cs), ifetch); +} + static void ppc_cpu_reset_hold(Object *obj) { CPUState *s = CPU(obj); @@ -7372,6 +7377,7 @@ static void ppc_cpu_class_init(ObjectClass *oc, void *data) cc->class_by_name = ppc_cpu_class_by_name; cc->has_work = ppc_cpu_has_work; + cc->mmu_index = ppc_cpu_mmu_index; cc->dump_state = ppc_cpu_dump_state; cc->set_pc = ppc_cpu_set_pc; cc->get_pc = ppc_cpu_get_pc; From 7f6f2ebbaa37d1c1db0e264d52d32893873aa635 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Mon, 29 Jan 2024 10:28:02 +1000 Subject: [PATCH 22/58] target/riscv: Rename riscv_cpu_mmu_index to riscv_env_mmu_index MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Free up the riscv_cpu_mmu_index name for other usage; emphasize that the argument is 'env'. Reviewed-by: Alistair Francis Reviewed-by: Philippe Mathieu-Daudé Signed-off-by: Richard Henderson --- target/riscv/cpu.h | 4 ++-- target/riscv/cpu_helper.c | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h index 5f3955c38d..9c825c7b51 100644 --- a/target/riscv/cpu.h +++ b/target/riscv/cpu.h @@ -498,7 +498,7 @@ target_ulong riscv_cpu_get_geilen(CPURISCVState *env); void riscv_cpu_set_geilen(CPURISCVState *env, target_ulong geilen); bool riscv_cpu_vector_enabled(CPURISCVState *env); void riscv_cpu_set_virt_enabled(CPURISCVState *env, bool enable); -int riscv_cpu_mmu_index(CPURISCVState *env, bool ifetch); +int riscv_env_mmu_index(CPURISCVState *env, bool ifetch); G_NORETURN void riscv_cpu_do_unaligned_access(CPUState *cs, vaddr addr, MMUAccessType access_type, int mmu_idx, uintptr_t retaddr); @@ -507,7 +507,7 @@ bool riscv_cpu_tlb_fill(CPUState *cs, vaddr address, int size, bool probe, uintptr_t retaddr); char *riscv_isa_string(RISCVCPU *cpu); -#define cpu_mmu_index riscv_cpu_mmu_index +#define cpu_mmu_index riscv_env_mmu_index #ifndef CONFIG_USER_ONLY void riscv_cpu_do_transaction_failed(CPUState *cs, hwaddr physaddr, diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c index c7cc7eb423..15f87ecdb0 100644 --- a/target/riscv/cpu_helper.c +++ b/target/riscv/cpu_helper.c @@ -33,7 +33,7 @@ #include "debug.h" #include "tcg/oversized-guest.h" -int riscv_cpu_mmu_index(CPURISCVState *env, bool ifetch) +int riscv_env_mmu_index(CPURISCVState *env, bool ifetch) { #ifdef CONFIG_USER_ONLY return 0; From d9996d0904398c236212e1d7678fd1b7f3554057 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Mon, 29 Jan 2024 10:28:52 +1000 Subject: [PATCH 23/58] target/riscv: Replace cpu_mmu_index with riscv_env_mmu_index MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Use the target-specific function name in preference to the generic name. Reviewed-by: Alistair Francis Reviewed-by: Philippe Mathieu-Daudé Signed-off-by: Richard Henderson --- target/riscv/cpu_helper.c | 4 ++-- target/riscv/op_helper.c | 4 ++-- target/riscv/vector_helper.c | 9 +++++---- 3 files changed, 9 insertions(+), 8 deletions(-) diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c index 15f87ecdb0..b6b23b7d03 100644 --- a/target/riscv/cpu_helper.c +++ b/target/riscv/cpu_helper.c @@ -106,7 +106,7 @@ void cpu_get_tb_cpu_state(CPURISCVState *env, vaddr *pc, #else flags = FIELD_DP32(flags, TB_FLAGS, PRIV, env->priv); - flags |= cpu_mmu_index(env, 0); + flags |= riscv_env_mmu_index(env, 0); fs = get_field(env->mstatus, MSTATUS_FS); vs = get_field(env->mstatus, MSTATUS_VS); @@ -1200,7 +1200,7 @@ hwaddr riscv_cpu_get_phys_page_debug(CPUState *cs, vaddr addr) CPURISCVState *env = &cpu->env; hwaddr phys_addr; int prot; - int mmu_idx = cpu_mmu_index(&cpu->env, false); + int mmu_idx = riscv_env_mmu_index(&cpu->env, false); if (get_physical_address(env, &phys_addr, &prot, addr, NULL, 0, mmu_idx, true, env->virt_enabled, true)) { diff --git a/target/riscv/op_helper.c b/target/riscv/op_helper.c index 5355225d56..f414aaebdb 100644 --- a/target/riscv/op_helper.c +++ b/target/riscv/op_helper.c @@ -157,7 +157,7 @@ void helper_cbo_zero(CPURISCVState *env, target_ulong address) { RISCVCPU *cpu = env_archcpu(env); uint16_t cbozlen = cpu->cfg.cboz_blocksize; - int mmu_idx = cpu_mmu_index(env, false); + int mmu_idx = riscv_env_mmu_index(env, false); uintptr_t ra = GETPC(); void *mem; @@ -205,7 +205,7 @@ static void check_zicbom_access(CPURISCVState *env, uintptr_t ra) { RISCVCPU *cpu = env_archcpu(env); - int mmu_idx = cpu_mmu_index(env, false); + int mmu_idx = riscv_env_mmu_index(env, false); uint16_t cbomlen = cpu->cfg.cbom_blocksize; void *phost; int ret; diff --git a/target/riscv/vector_helper.c b/target/riscv/vector_helper.c index c1c3a4d1ea..fe0d5d053c 100644 --- a/target/riscv/vector_helper.c +++ b/target/riscv/vector_helper.c @@ -113,14 +113,15 @@ static void probe_pages(CPURISCVState *env, target_ulong addr, { target_ulong pagelen = -(addr | TARGET_PAGE_MASK); target_ulong curlen = MIN(pagelen, len); + int mmu_index = riscv_env_mmu_index(env, false); probe_access(env, adjust_addr(env, addr), curlen, access_type, - cpu_mmu_index(env, false), ra); + mmu_index, ra); if (len > curlen) { addr += curlen; curlen = len - curlen; probe_access(env, adjust_addr(env, addr), curlen, access_type, - cpu_mmu_index(env, false), ra); + mmu_index, ra); } } @@ -464,6 +465,7 @@ vext_ldff(void *vd, void *v0, target_ulong base, uint32_t esz = 1 << log2_esz; uint32_t vma = vext_vma(desc); target_ulong addr, offset, remain; + int mmu_index = riscv_env_mmu_index(env, false); /* probe every access */ for (i = env->vstart; i < env->vl; i++) { @@ -478,8 +480,7 @@ vext_ldff(void *vd, void *v0, target_ulong base, remain = nf << log2_esz; while (remain > 0) { offset = -(addr | TARGET_PAGE_MASK); - host = tlb_vaddr_to_host(env, addr, MMU_DATA_LOAD, - cpu_mmu_index(env, false)); + host = tlb_vaddr_to_host(env, addr, MMU_DATA_LOAD, mmu_index); if (host) { #ifdef CONFIG_USER_ONLY if (!page_check_range(addr, offset, PAGE_READ)) { From a5c7797496a276b695189015afcce31829b8705e Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Mon, 29 Jan 2024 10:34:43 +1000 Subject: [PATCH 24/58] target/riscv: Populate CPUClass.mmu_index MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Reviewed-by: Alistair Francis Reviewed-by: Philippe Mathieu-Daudé Signed-off-by: Richard Henderson --- target/riscv/cpu.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c index 8cbfc7e781..be21fa09c6 100644 --- a/target/riscv/cpu.c +++ b/target/riscv/cpu.c @@ -867,6 +867,11 @@ static bool riscv_cpu_has_work(CPUState *cs) #endif } +static int riscv_cpu_mmu_index(CPUState *cs, bool ifetch) +{ + return riscv_env_mmu_index(cpu_env(cs), ifetch); +} + static void riscv_cpu_reset_hold(Object *obj) { #ifndef CONFIG_USER_ONLY @@ -1810,6 +1815,7 @@ static void riscv_cpu_class_init(ObjectClass *c, void *data) cc->class_by_name = riscv_cpu_class_by_name; cc->has_work = riscv_cpu_has_work; + cc->mmu_index = riscv_cpu_mmu_index; cc->dump_state = riscv_cpu_dump_state; cc->set_pc = riscv_cpu_set_pc; cc->get_pc = riscv_cpu_get_pc; From ef5cc166da1934c3f9d430b82e7ce89c65f8b6aa Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Mon, 29 Jan 2024 10:36:27 +1000 Subject: [PATCH 25/58] target/rx: Populate CPUClass.mmu_index MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Reviewed-by: Philippe Mathieu-Daudé Signed-off-by: Richard Henderson --- target/rx/cpu.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/target/rx/cpu.c b/target/rx/cpu.c index 353132dac2..5205167da1 100644 --- a/target/rx/cpu.c +++ b/target/rx/cpu.c @@ -64,6 +64,11 @@ static bool rx_cpu_has_work(CPUState *cs) (CPU_INTERRUPT_HARD | CPU_INTERRUPT_FIR); } +static int riscv_cpu_mmu_index(CPUState *cs, bool ifunc) +{ + return 0; +} + static void rx_cpu_reset_hold(Object *obj) { RXCPU *cpu = RX_CPU(obj); @@ -204,6 +209,7 @@ static void rx_cpu_class_init(ObjectClass *klass, void *data) cc->class_by_name = rx_cpu_class_by_name; cc->has_work = rx_cpu_has_work; + cc->mmu_index = riscv_cpu_mmu_index; cc->dump_state = rx_cpu_dump_state; cc->set_pc = rx_cpu_set_pc; cc->get_pc = rx_cpu_get_pc; From 90b7022e698d0d80e133957bb7baece66311247d Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Mon, 29 Jan 2024 10:42:41 +1000 Subject: [PATCH 26/58] target/s390x: Split out s390x_env_mmu_index MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Reviewed-by: Philippe Mathieu-Daudé Signed-off-by: Richard Henderson --- target/s390x/cpu.h | 4 +++- target/s390x/tcg/mem_helper.c | 34 ++++++++++++++++++---------------- 2 files changed, 21 insertions(+), 17 deletions(-) diff --git a/target/s390x/cpu.h b/target/s390x/cpu.h index fa3aac4f97..f0fed5d6ad 100644 --- a/target/s390x/cpu.h +++ b/target/s390x/cpu.h @@ -381,7 +381,7 @@ extern const VMStateDescription vmstate_s390_cpu; #define MMU_HOME_IDX 2 #define MMU_REAL_IDX 3 -static inline int cpu_mmu_index(CPUS390XState *env, bool ifetch) +static inline int s390x_env_mmu_index(CPUS390XState *env, bool ifetch) { #ifdef CONFIG_USER_ONLY return MMU_USER_IDX; @@ -412,6 +412,8 @@ static inline int cpu_mmu_index(CPUS390XState *env, bool ifetch) #endif } +#define cpu_mmu_index s390x_env_mmu_index + #ifdef CONFIG_TCG #include "tcg/tcg_s390x.h" diff --git a/target/s390x/tcg/mem_helper.c b/target/s390x/tcg/mem_helper.c index 84103251b9..557831def4 100644 --- a/target/s390x/tcg/mem_helper.c +++ b/target/s390x/tcg/mem_helper.c @@ -358,7 +358,7 @@ static int mmu_idx_from_as(uint8_t as) static uint32_t do_helper_nc(CPUS390XState *env, uint32_t l, uint64_t dest, uint64_t src, uintptr_t ra) { - const int mmu_idx = cpu_mmu_index(env, false); + const int mmu_idx = s390x_env_mmu_index(env, false); S390Access srca1, srca2, desta; uint32_t i; uint8_t c = 0; @@ -392,7 +392,7 @@ uint32_t HELPER(nc)(CPUS390XState *env, uint32_t l, uint64_t dest, static uint32_t do_helper_xc(CPUS390XState *env, uint32_t l, uint64_t dest, uint64_t src, uintptr_t ra) { - const int mmu_idx = cpu_mmu_index(env, false); + const int mmu_idx = s390x_env_mmu_index(env, false); S390Access srca1, srca2, desta; uint32_t i; uint8_t c = 0; @@ -433,7 +433,7 @@ uint32_t HELPER(xc)(CPUS390XState *env, uint32_t l, uint64_t dest, static uint32_t do_helper_oc(CPUS390XState *env, uint32_t l, uint64_t dest, uint64_t src, uintptr_t ra) { - const int mmu_idx = cpu_mmu_index(env, false); + const int mmu_idx = s390x_env_mmu_index(env, false); S390Access srca1, srca2, desta; uint32_t i; uint8_t c = 0; @@ -467,7 +467,7 @@ uint32_t HELPER(oc)(CPUS390XState *env, uint32_t l, uint64_t dest, static uint32_t do_helper_mvc(CPUS390XState *env, uint32_t l, uint64_t dest, uint64_t src, uintptr_t ra) { - const int mmu_idx = cpu_mmu_index(env, false); + const int mmu_idx = s390x_env_mmu_index(env, false); S390Access srca, desta; uint32_t i; @@ -508,7 +508,7 @@ void HELPER(mvc)(CPUS390XState *env, uint32_t l, uint64_t dest, uint64_t src) /* move right to left */ void HELPER(mvcrl)(CPUS390XState *env, uint64_t l, uint64_t dest, uint64_t src) { - const int mmu_idx = cpu_mmu_index(env, false); + const int mmu_idx = s390x_env_mmu_index(env, false); const uint64_t ra = GETPC(); S390Access srca, desta; int32_t i; @@ -529,7 +529,7 @@ void HELPER(mvcrl)(CPUS390XState *env, uint64_t l, uint64_t dest, uint64_t src) /* move inverse */ void HELPER(mvcin)(CPUS390XState *env, uint32_t l, uint64_t dest, uint64_t src) { - const int mmu_idx = cpu_mmu_index(env, false); + const int mmu_idx = s390x_env_mmu_index(env, false); S390Access srca, desta; uintptr_t ra = GETPC(); int i; @@ -550,7 +550,7 @@ void HELPER(mvcin)(CPUS390XState *env, uint32_t l, uint64_t dest, uint64_t src) /* move numerics */ void HELPER(mvn)(CPUS390XState *env, uint32_t l, uint64_t dest, uint64_t src) { - const int mmu_idx = cpu_mmu_index(env, false); + const int mmu_idx = s390x_env_mmu_index(env, false); S390Access srca1, srca2, desta; uintptr_t ra = GETPC(); int i; @@ -572,7 +572,7 @@ void HELPER(mvn)(CPUS390XState *env, uint32_t l, uint64_t dest, uint64_t src) /* move with offset */ void HELPER(mvo)(CPUS390XState *env, uint32_t l, uint64_t dest, uint64_t src) { - const int mmu_idx = cpu_mmu_index(env, false); + const int mmu_idx = s390x_env_mmu_index(env, false); /* MVO always processes one more byte than specified - maximum is 16 */ const int len_dest = (l >> 4) + 1; const int len_src = (l & 0xf) + 1; @@ -606,7 +606,7 @@ void HELPER(mvo)(CPUS390XState *env, uint32_t l, uint64_t dest, uint64_t src) /* move zones */ void HELPER(mvz)(CPUS390XState *env, uint32_t l, uint64_t dest, uint64_t src) { - const int mmu_idx = cpu_mmu_index(env, false); + const int mmu_idx = s390x_env_mmu_index(env, false); S390Access srca1, srca2, desta; uintptr_t ra = GETPC(); int i; @@ -669,7 +669,7 @@ uint32_t HELPER(clm)(CPUS390XState *env, uint32_t r1, uint32_t mask, if (!mask) { /* Recognize access exceptions for the first byte */ - probe_read(env, addr, 1, cpu_mmu_index(env, false), ra); + probe_read(env, addr, 1, s390x_env_mmu_index(env, false), ra); } while (mask) { @@ -893,7 +893,7 @@ uint32_t HELPER(mvpg)(CPUS390XState *env, uint64_t r0, uint32_t r1, uint32_t r2) { const uint64_t src = get_address(env, r2) & TARGET_PAGE_MASK; const uint64_t dst = get_address(env, r1) & TARGET_PAGE_MASK; - const int mmu_idx = cpu_mmu_index(env, false); + const int mmu_idx = s390x_env_mmu_index(env, false); const bool f = extract64(r0, 11, 1); const bool s = extract64(r0, 10, 1); const bool cco = extract64(r0, 8, 1); @@ -946,7 +946,7 @@ inject_exc: /* string copy */ uint32_t HELPER(mvst)(CPUS390XState *env, uint32_t r1, uint32_t r2) { - const int mmu_idx = cpu_mmu_index(env, false); + const int mmu_idx = s390x_env_mmu_index(env, false); const uint64_t d = get_address(env, r1); const uint64_t s = get_address(env, r2); const uint8_t c = env->regs[0]; @@ -1027,7 +1027,7 @@ static inline uint32_t do_mvcl(CPUS390XState *env, uint64_t *src, uint64_t *srclen, uint16_t pad, int wordsize, uintptr_t ra) { - const int mmu_idx = cpu_mmu_index(env, false); + const int mmu_idx = s390x_env_mmu_index(env, false); int len = MIN(*destlen, -(*dest | TARGET_PAGE_MASK)); S390Access srca, desta; int i, cc; @@ -1084,7 +1084,7 @@ static inline uint32_t do_mvcl(CPUS390XState *env, /* move long */ uint32_t HELPER(mvcl)(CPUS390XState *env, uint32_t r1, uint32_t r2) { - const int mmu_idx = cpu_mmu_index(env, false); + const int mmu_idx = s390x_env_mmu_index(env, false); uintptr_t ra = GETPC(); uint64_t destlen = env->regs[r1 + 1] & 0xffffff; uint64_t dest = get_address(env, r1); @@ -1742,7 +1742,7 @@ uint32_t HELPER(trXX)(CPUS390XState *env, uint32_t r1, uint32_t r2, static uint32_t do_csst(CPUS390XState *env, uint32_t r3, uint64_t a1, uint64_t a2, bool parallel) { - uint32_t mem_idx = cpu_mmu_index(env, false); + uint32_t mem_idx = s390x_env_mmu_index(env, false); MemOpIdx oi16 = make_memop_idx(MO_TE | MO_128, mem_idx); MemOpIdx oi8 = make_memop_idx(MO_TE | MO_64, mem_idx); MemOpIdx oi4 = make_memop_idx(MO_TE | MO_32, mem_idx); @@ -2867,12 +2867,14 @@ uint32_t HELPER(cu42)(CPUS390XState *env, uint32_t r1, uint32_t r2, uint32_t m3) void probe_write_access(CPUS390XState *env, uint64_t addr, uint64_t len, uintptr_t ra) { + const int mmu_idx = s390x_env_mmu_index(env, false); + /* test the actual access, not just any access to the page due to LAP */ while (len) { const uint64_t pagelen = -(addr | TARGET_PAGE_MASK); const uint64_t curlen = MIN(pagelen, len); - probe_write(env, addr, curlen, cpu_mmu_index(env, false), ra); + probe_write(env, addr, curlen, mmu_idx, ra); addr = wrap_address(env, addr + curlen); len -= curlen; } From 4ef80b271fd59db418e43d8d37219b351f11a567 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Mon, 29 Jan 2024 10:49:39 +1000 Subject: [PATCH 27/58] target/s390x: Populate CPUClass.mmu_index MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Reviewed-by: Philippe Mathieu-Daudé Signed-off-by: Richard Henderson --- target/s390x/cpu.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/target/s390x/cpu.c b/target/s390x/cpu.c index 7f123863dc..49a2341acc 100644 --- a/target/s390x/cpu.c +++ b/target/s390x/cpu.c @@ -142,6 +142,11 @@ static bool s390_cpu_has_work(CPUState *cs) return s390_cpu_has_int(cpu); } +static int s390x_cpu_mmu_index(CPUState *cs, bool ifetch) +{ + return s390x_env_mmu_index(cpu_env(cs), ifetch); +} + static void s390_query_cpu_fast(CPUState *cpu, CpuInfoFast *value) { S390CPU *s390_cpu = S390_CPU(cpu); @@ -352,6 +357,7 @@ static void s390_cpu_class_init(ObjectClass *oc, void *data) scc->reset = s390_cpu_reset; cc->class_by_name = s390_cpu_class_by_name, cc->has_work = s390_cpu_has_work; + cc->mmu_index = s390x_cpu_mmu_index; cc->dump_state = s390_cpu_dump_state; cc->query_cpu_fast = s390_query_cpu_fast; cc->set_pc = s390_cpu_set_pc; From 9ba49d722284b63ee9ccf20e27b1b31ad4a26c6c Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Mon, 29 Jan 2024 10:55:40 +1000 Subject: [PATCH 28/58] target/sh4: Populate CPUClass.mmu_index MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Reviewed-by: Philippe Mathieu-Daudé Signed-off-by: Richard Henderson --- target/sh4/cpu.c | 16 ++++++++++++++++ target/sh4/cpu.h | 16 ++++++---------- 2 files changed, 22 insertions(+), 10 deletions(-) diff --git a/target/sh4/cpu.c b/target/sh4/cpu.c index 39772955b5..6fead5655f 100644 --- a/target/sh4/cpu.c +++ b/target/sh4/cpu.c @@ -89,6 +89,21 @@ static bool superh_cpu_has_work(CPUState *cs) return cs->interrupt_request & CPU_INTERRUPT_HARD; } +int sh4_cpu_mmu_index(CPUState *cs, bool ifetch) +{ + CPUSH4State *env = cpu_env(cs); + + /* + * The instruction in a RTE delay slot is fetched in privileged mode, + * but executed in user mode. + */ + if (ifetch && (env->flags & TB_FLAG_DELAY_SLOT_RTE)) { + return 0; + } else { + return (env->sr & (1u << SR_MD)) == 0 ? 1 : 0; + } +} + static void superh_cpu_reset_hold(Object *obj) { CPUState *s = CPU(obj); @@ -266,6 +281,7 @@ static void superh_cpu_class_init(ObjectClass *oc, void *data) cc->class_by_name = superh_cpu_class_by_name; cc->has_work = superh_cpu_has_work; + cc->mmu_index = sh4_cpu_mmu_index; cc->dump_state = superh_cpu_dump_state; cc->set_pc = superh_cpu_set_pc; cc->get_pc = superh_cpu_get_pc; diff --git a/target/sh4/cpu.h b/target/sh4/cpu.h index 0e6fa65bae..9c5e2b349e 100644 --- a/target/sh4/cpu.h +++ b/target/sh4/cpu.h @@ -273,16 +273,6 @@ void cpu_load_tlb(CPUSH4State * env); /* MMU modes definitions */ #define MMU_USER_IDX 1 -static inline int cpu_mmu_index (CPUSH4State *env, bool ifetch) -{ - /* The instruction in a RTE delay slot is fetched in privileged - mode, but executed in user mode. */ - if (ifetch && (env->flags & TB_FLAG_DELAY_SLOT_RTE)) { - return 0; - } else { - return (env->sr & (1u << SR_MD)) == 0 ? 1 : 0; - } -} #include "exec/cpu-all.h" @@ -380,6 +370,12 @@ static inline void cpu_write_sr(CPUSH4State *env, target_ulong sr) env->sr = sr & ~((1u << SR_M) | (1u << SR_Q) | (1u << SR_T)); } +int sh4_cpu_mmu_index(CPUState *cs, bool ifetch); +static inline int cpu_mmu_index(CPUSH4State *env, bool ifetch) +{ + return sh4_cpu_mmu_index(env_cpu(env), ifetch); +} + static inline void cpu_get_tb_cpu_state(CPUSH4State *env, vaddr *pc, uint64_t *cs_base, uint32_t *flags) { From e3547a7d0770ad3f8049d8f991abcf7756c0c96d Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Mon, 29 Jan 2024 11:01:52 +1000 Subject: [PATCH 29/58] target/sparc: Populate CPUClass.mmu_index MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Reviewed-by: Philippe Mathieu-Daudé Signed-off-by: Richard Henderson --- target/sparc/cpu.c | 29 +++++++++++++++++++++++++++++ target/sparc/cpu.h | 34 ++++++---------------------------- 2 files changed, 35 insertions(+), 28 deletions(-) diff --git a/target/sparc/cpu.c b/target/sparc/cpu.c index 7d0d629a3d..7a3b815737 100644 --- a/target/sparc/cpu.c +++ b/target/sparc/cpu.c @@ -718,6 +718,34 @@ static bool sparc_cpu_has_work(CPUState *cs) cpu_interrupts_enabled(env); } +int sparc_cpu_mmu_index(CPUState *cs, bool ifetch) +{ + CPUSPARCState *env = cpu_env(cs); + +#ifndef TARGET_SPARC64 + if ((env->mmuregs[0] & MMU_E) == 0) { /* MMU disabled */ + return MMU_PHYS_IDX; + } else { + return env->psrs; + } +#else + /* IMMU or DMMU disabled. */ + if (ifetch + ? (env->lsu & IMMU_E) == 0 || (env->pstate & PS_RED) != 0 + : (env->lsu & DMMU_E) == 0) { + return MMU_PHYS_IDX; + } else if (cpu_hypervisor_mode(env)) { + return MMU_PHYS_IDX; + } else if (env->tl > 0) { + return MMU_NUCLEUS_IDX; + } else if (cpu_supervisor_mode(env)) { + return MMU_KERNEL_IDX; + } else { + return MMU_USER_IDX; + } +#endif +} + static char *sparc_cpu_type_name(const char *cpu_model) { char *name = g_strdup_printf(SPARC_CPU_TYPE_NAME("%s"), cpu_model); @@ -906,6 +934,7 @@ static void sparc_cpu_class_init(ObjectClass *oc, void *data) cc->class_by_name = sparc_cpu_class_by_name; cc->parse_features = sparc_cpu_parse_features; cc->has_work = sparc_cpu_has_work; + cc->mmu_index = sparc_cpu_mmu_index; cc->dump_state = sparc_cpu_dump_state; #if !defined(TARGET_SPARC64) && !defined(CONFIG_USER_ONLY) cc->memory_rw_debug = sparc_cpu_memory_rw_debug; diff --git a/target/sparc/cpu.h b/target/sparc/cpu.h index 12a11ecb26..92c58c92c1 100644 --- a/target/sparc/cpu.h +++ b/target/sparc/cpu.h @@ -708,34 +708,6 @@ static inline int cpu_supervisor_mode(CPUSPARCState *env1) } #endif -static inline int cpu_mmu_index(CPUSPARCState *env, bool ifetch) -{ -#if defined(CONFIG_USER_ONLY) - return MMU_USER_IDX; -#elif !defined(TARGET_SPARC64) - if ((env->mmuregs[0] & MMU_E) == 0) { /* MMU disabled */ - return MMU_PHYS_IDX; - } else { - return env->psrs; - } -#else - /* IMMU or DMMU disabled. */ - if (ifetch - ? (env->lsu & IMMU_E) == 0 || (env->pstate & PS_RED) != 0 - : (env->lsu & DMMU_E) == 0) { - return MMU_PHYS_IDX; - } else if (cpu_hypervisor_mode(env)) { - return MMU_PHYS_IDX; - } else if (env->tl > 0) { - return MMU_NUCLEUS_IDX; - } else if (cpu_supervisor_mode(env)) { - return MMU_KERNEL_IDX; - } else { - return MMU_USER_IDX; - } -#endif -} - static inline int cpu_interrupts_enabled(CPUSPARCState *env1) { #if !defined (TARGET_SPARC64) @@ -777,6 +749,12 @@ trap_state* cpu_tsptr(CPUSPARCState* env); #define TB_FLAG_HYPER (1 << 7) #define TB_FLAG_ASI_SHIFT 24 +int sparc_cpu_mmu_index(CPUState *cs, bool ifetch); +static inline int cpu_mmu_index(CPUSPARCState *env, bool ifetch) +{ + return sparc_cpu_mmu_index(env_cpu(env), ifetch); +} + static inline void cpu_get_tb_cpu_state(CPUSPARCState *env, vaddr *pc, uint64_t *cs_base, uint32_t *pflags) { From eafa0f68c3924df193b64c121657bbffe3248076 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Mon, 29 Jan 2024 11:05:54 +1000 Subject: [PATCH 30/58] target/tricore: Populate CPUClass.mmu_index MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Reviewed-by: Philippe Mathieu-Daudé Signed-off-by: Richard Henderson --- target/tricore/cpu.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/target/tricore/cpu.c b/target/tricore/cpu.c index e6d91c74b5..74e8a22b86 100644 --- a/target/tricore/cpu.c +++ b/target/tricore/cpu.c @@ -89,6 +89,11 @@ static bool tricore_cpu_has_work(CPUState *cs) return true; } +static int tricore_cpu_mmu_index(CPUState *cs, bool ifetch) +{ + return 0; +} + static void tricore_cpu_realizefn(DeviceState *dev, Error **errp) { CPUState *cs = CPU(dev); @@ -194,6 +199,7 @@ static void tricore_cpu_class_init(ObjectClass *c, void *data) &mcc->parent_phases); cc->class_by_name = tricore_cpu_class_by_name; cc->has_work = tricore_cpu_has_work; + cc->mmu_index = tricore_cpu_mmu_index; cc->gdb_read_register = tricore_cpu_gdb_read_register; cc->gdb_write_register = tricore_cpu_gdb_write_register; From 68283ff4b48344fb996384f0481b3d8d72c830fe Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Mon, 29 Jan 2024 11:07:43 +1000 Subject: [PATCH 31/58] target/xtensa: Populate CPUClass.mmu_index MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Reviewed-by: Philippe Mathieu-Daudé Signed-off-by: Richard Henderson --- target/xtensa/cpu.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/target/xtensa/cpu.c b/target/xtensa/cpu.c index 62020b1f33..79f91819df 100644 --- a/target/xtensa/cpu.c +++ b/target/xtensa/cpu.c @@ -74,6 +74,11 @@ static bool xtensa_cpu_has_work(CPUState *cs) #endif } +static int xtensa_cpu_mmu_index(CPUState *cs, bool ifetch) +{ + return xtensa_get_cring(cpu_env(cs)); +} + #ifdef CONFIG_USER_ONLY static bool abi_call0; @@ -252,6 +257,7 @@ static void xtensa_cpu_class_init(ObjectClass *oc, void *data) cc->class_by_name = xtensa_cpu_class_by_name; cc->has_work = xtensa_cpu_has_work; + cc->mmu_index = xtensa_cpu_mmu_index; cc->dump_state = xtensa_cpu_dump_state; cc->set_pc = xtensa_cpu_set_pc; cc->get_pc = xtensa_cpu_get_pc; From a120d32097910edfc1612c604836582c3a4b83c6 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Mon, 29 Jan 2024 11:37:54 +1000 Subject: [PATCH 32/58] include/exec: Implement cpu_mmu_index generically MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit For user-only mode, use MMU_USER_IDX. For system mode, use CPUClass.mmu_index. Reviewed-by: Philippe Mathieu-Daudé Signed-off-by: Richard Henderson --- include/exec/cpu-all.h | 4 ++++ include/exec/cpu-common.h | 22 ++++++++++++++++++++++ target/alpha/cpu.h | 5 ----- target/arm/cpu.h | 13 ------------- target/avr/cpu.h | 5 ----- target/cris/cpu.h | 4 ---- target/hexagon/cpu.h | 9 --------- target/hppa/cpu.c | 2 +- target/hppa/cpu.h | 10 ---------- target/i386/cpu.c | 2 +- target/i386/cpu.h | 6 ------ target/loongarch/cpu.c | 2 +- target/loongarch/cpu.h | 10 ---------- target/m68k/cpu.h | 4 ---- target/microblaze/cpu.c | 2 +- target/microblaze/cpu.h | 6 ------ target/mips/cpu.h | 5 ----- target/nios2/cpu.c | 2 +- target/nios2/cpu.h | 6 ------ target/openrisc/cpu.c | 2 +- target/openrisc/cpu.h | 6 ------ target/ppc/cpu.h | 5 ----- target/riscv/cpu.h | 2 -- target/rx/cpu.h | 5 ----- target/s390x/cpu.h | 2 -- target/sh4/cpu.c | 2 +- target/sh4/cpu.h | 6 ------ target/sparc/cpu.c | 2 +- target/sparc/cpu.h | 6 ------ target/tricore/cpu.h | 5 ----- target/xtensa/cpu.h | 5 ----- 31 files changed, 34 insertions(+), 133 deletions(-) diff --git a/include/exec/cpu-all.h b/include/exec/cpu-all.h index 8501a33dbf..80c0d0699b 100644 --- a/include/exec/cpu-all.h +++ b/include/exec/cpu-all.h @@ -311,6 +311,10 @@ CPUArchState *cpu_copy(CPUArchState *env); #define TLB_MMIO (1 << (TARGET_PAGE_BITS_MIN - 2)) #define TLB_WATCHPOINT 0 +static inline int cpu_mmu_index(CPUArchState *env, bool ifetch) +{ + return MMU_USER_IDX; +} #else /* diff --git a/include/exec/cpu-common.h b/include/exec/cpu-common.h index dcbd5f5783..cdfbe994fd 100644 --- a/include/exec/cpu-common.h +++ b/include/exec/cpu-common.h @@ -8,6 +8,7 @@ #include "exec/hwaddr.h" #endif #include "hw/core/cpu.h" +#include "tcg/debug-assert.h" #define EXCP_INTERRUPT 0x10000 /* async interruption */ #define EXCP_HLT 0x10001 /* hlt instruction reached */ @@ -262,4 +263,25 @@ static inline CPUState *env_cpu(CPUArchState *env) return (void *)env - sizeof(CPUState); } +#ifndef CONFIG_USER_ONLY +/** + * cpu_mmu_index: + * @env: The cpu environment + * @ifetch: True for code access, false for data access. + * + * Return the core mmu index for the current translation regime. + * This function is used by generic TCG code paths. + * + * The user-only version of this function is inline in cpu-all.h, + * where it always returns MMU_USER_IDX. + */ +static inline int cpu_mmu_index(CPUArchState *env, bool ifetch) +{ + CPUState *cs = env_cpu(env); + int ret = cs->cc->mmu_index(cs, ifetch); + tcg_debug_assert(ret >= 0 && ret < NB_MMU_MODES); + return ret; +} +#endif /* !CONFIG_USER_ONLY */ + #endif /* CPU_COMMON_H */ diff --git a/target/alpha/cpu.h b/target/alpha/cpu.h index 3beff2738a..7188a409a0 100644 --- a/target/alpha/cpu.h +++ b/target/alpha/cpu.h @@ -398,11 +398,6 @@ static inline int alpha_env_mmu_index(CPUAlphaState *env) return ret; } -static inline int cpu_mmu_index(CPUAlphaState *env, bool ifetch) -{ - return alpha_env_mmu_index(env); -} - enum { IR_V0 = 0, IR_T0 = 1, diff --git a/target/arm/cpu.h b/target/arm/cpu.h index d3477b1601..63f31e0d98 100644 --- a/target/arm/cpu.h +++ b/target/arm/cpu.h @@ -3240,19 +3240,6 @@ FIELD(TBFLAG_A64, NV2_MEM_BE, 36, 1) #define EX_TBFLAG_M32(IN, WHICH) FIELD_EX32(IN.flags2, TBFLAG_M32, WHICH) #define EX_TBFLAG_AM32(IN, WHICH) FIELD_EX32(IN.flags2, TBFLAG_AM32, WHICH) -/** - * cpu_mmu_index: - * @env: The cpu environment - * @ifetch: True for code access, false for data access. - * - * Return the core mmu index for the current translation regime. - * This function is used by generic TCG code paths. - */ -static inline int cpu_mmu_index(CPUARMState *env, bool ifetch) -{ - return EX_TBFLAG_ANY(env->hflags, MMUIDX); -} - /** * sve_vq * @env: the cpu context diff --git a/target/avr/cpu.h b/target/avr/cpu.h index 4595c6bb18..d185d20dcb 100644 --- a/target/avr/cpu.h +++ b/target/avr/cpu.h @@ -184,11 +184,6 @@ static inline void set_avr_feature(CPUAVRState *env, int feature) env->features |= (1U << feature); } -static inline int cpu_mmu_index(CPUAVRState *env, bool ifetch) -{ - return ifetch ? MMU_CODE_IDX : MMU_DATA_IDX; -} - void avr_cpu_tcg_init(void); int cpu_avr_exec(CPUState *cpu); diff --git a/target/cris/cpu.h b/target/cris/cpu.h index d830dcac5b..3904e5448c 100644 --- a/target/cris/cpu.h +++ b/target/cris/cpu.h @@ -260,10 +260,6 @@ enum { /* MMU modes definitions */ #define MMU_USER_IDX 1 -static inline int cpu_mmu_index (CPUCRISState *env, bool ifetch) -{ - return !!(env->pregs[PR_CCS] & U_FLAG); -} /* Support function regs. */ #define SFR_RW_GC_CFG 0][0 diff --git a/target/hexagon/cpu.h b/target/hexagon/cpu.h index 5c11ae3445..3eef58fe8f 100644 --- a/target/hexagon/cpu.h +++ b/target/hexagon/cpu.h @@ -146,15 +146,6 @@ static inline void cpu_get_tb_cpu_state(CPUHexagonState *env, vaddr *pc, *flags = hex_flags; } -static inline int cpu_mmu_index(CPUHexagonState *env, bool ifetch) -{ -#ifdef CONFIG_USER_ONLY - return MMU_USER_IDX; -#else -#error System mode not supported on Hexagon yet -#endif -} - typedef HexagonCPU ArchCPU; void hexagon_translate_init(void); diff --git a/target/hppa/cpu.c b/target/hppa/cpu.c index fbb37e541e..5f87c1b12a 100644 --- a/target/hppa/cpu.c +++ b/target/hppa/cpu.c @@ -94,7 +94,7 @@ static bool hppa_cpu_has_work(CPUState *cs) return cs->interrupt_request & (CPU_INTERRUPT_HARD | CPU_INTERRUPT_NMI); } -int hppa_cpu_mmu_index(CPUState *cs, bool ifetch) +static int hppa_cpu_mmu_index(CPUState *cs, bool ifetch) { CPUHPPAState *env = cpu_env(cs); diff --git a/target/hppa/cpu.h b/target/hppa/cpu.h index 04439f247d..7a181e8f33 100644 --- a/target/hppa/cpu.h +++ b/target/hppa/cpu.h @@ -281,16 +281,6 @@ static inline int HPPA_BTLB_ENTRIES(CPUHPPAState *env) return hppa_is_pa20(env) ? 0 : PA10_BTLB_FIXED + PA10_BTLB_VARIABLE; } -int hppa_cpu_mmu_index(CPUState *cs, bool ifetch); -static inline int cpu_mmu_index(CPUHPPAState *env, bool ifetch) -{ -#ifdef CONFIG_USER_ONLY - return MMU_USER_IDX; -#else - return hppa_cpu_mmu_index(env_cpu(env), ifetch); -#endif -} - void hppa_translate_init(void); #define CPU_RESOLVING_TYPE TYPE_HPPA_CPU diff --git a/target/i386/cpu.c b/target/i386/cpu.c index 280bcb7d00..ef46755a50 100644 --- a/target/i386/cpu.c +++ b/target/i386/cpu.c @@ -7720,7 +7720,7 @@ static bool x86_cpu_has_work(CPUState *cs) return x86_cpu_pending_interrupt(cs, cs->interrupt_request) != 0; } -int x86_cpu_mmu_index(CPUState *cs, bool ifetch) +static int x86_cpu_mmu_index(CPUState *cs, bool ifetch) { CPUX86State *env = cpu_env(cs); diff --git a/target/i386/cpu.h b/target/i386/cpu.h index 62bdb02378..6a5b180ccb 100644 --- a/target/i386/cpu.h +++ b/target/i386/cpu.h @@ -2315,12 +2315,6 @@ static inline int cpu_mmu_index_kernel(CPUX86State *env) #include "hw/i386/apic.h" #endif -int x86_cpu_mmu_index(CPUState *cs, bool ifetch); -static inline int cpu_mmu_index(CPUX86State *env, bool ifetch) -{ - return x86_cpu_mmu_index(env_cpu(env), ifetch); -} - static inline void cpu_get_tb_cpu_state(CPUX86State *env, vaddr *pc, uint64_t *cs_base, uint32_t *flags) { diff --git a/target/loongarch/cpu.c b/target/loongarch/cpu.c index 49ced9888e..7dc50bf35f 100644 --- a/target/loongarch/cpu.c +++ b/target/loongarch/cpu.c @@ -375,7 +375,7 @@ static bool loongarch_cpu_has_work(CPUState *cs) #endif } -int loongarch_cpu_mmu_index(CPUState *cs, bool ifetch) +static int loongarch_cpu_mmu_index(CPUState *cs, bool ifetch) { CPULoongArchState *env = cpu_env(cs); diff --git a/target/loongarch/cpu.h b/target/loongarch/cpu.h index 47fd110e81..ec37579fd6 100644 --- a/target/loongarch/cpu.h +++ b/target/loongarch/cpu.h @@ -408,16 +408,6 @@ struct LoongArchCPUClass { #define MMU_USER_IDX MMU_PLV_USER #define MMU_DA_IDX 4 -int loongarch_cpu_mmu_index(CPUState *cs, bool ifetch); -static inline int cpu_mmu_index(CPULoongArchState *env, bool ifetch) -{ -#ifdef CONFIG_USER_ONLY - return MMU_USER_IDX; -#else - return loongarch_cpu_mmu_index(env_cpu(env), ifetch); -#endif -} - static inline bool is_la64(CPULoongArchState *env) { return FIELD_EX32(env->cpucfg[1], CPUCFG1, ARCH) == CPUCFG1_ARCH_LA64; diff --git a/target/m68k/cpu.h b/target/m68k/cpu.h index d13427b0fe..aca4aa610b 100644 --- a/target/m68k/cpu.h +++ b/target/m68k/cpu.h @@ -577,10 +577,6 @@ enum { /* MMU modes definitions */ #define MMU_KERNEL_IDX 0 #define MMU_USER_IDX 1 -static inline int cpu_mmu_index (CPUM68KState *env, bool ifetch) -{ - return (env->sr & SR_S) == 0 ? 1 : 0; -} bool m68k_cpu_tlb_fill(CPUState *cs, vaddr address, int size, MMUAccessType access_type, int mmu_idx, diff --git a/target/microblaze/cpu.c b/target/microblaze/cpu.c index 6dad11905b..2002231a6b 100644 --- a/target/microblaze/cpu.c +++ b/target/microblaze/cpu.c @@ -118,7 +118,7 @@ static bool mb_cpu_has_work(CPUState *cs) return cs->interrupt_request & (CPU_INTERRUPT_HARD | CPU_INTERRUPT_NMI); } -int mb_cpu_mmu_index(CPUState *cs, bool ifetch) +static int mb_cpu_mmu_index(CPUState *cs, bool ifetch) { CPUMBState *env = cpu_env(cs); MicroBlazeCPU *cpu = env_archcpu(env); diff --git a/target/microblaze/cpu.h b/target/microblaze/cpu.h index 90ab796de9..446af5dd4c 100644 --- a/target/microblaze/cpu.h +++ b/target/microblaze/cpu.h @@ -434,12 +434,6 @@ void mb_cpu_transaction_failed(CPUState *cs, hwaddr physaddr, vaddr addr, MemTxResult response, uintptr_t retaddr); #endif -int mb_cpu_mmu_index(CPUState *cs, bool ifetch); -static inline int cpu_mmu_index(CPUMBState *env, bool ifetch) -{ - return mb_cpu_mmu_index(env_cpu(env), ifetch); -} - #ifndef CONFIG_USER_ONLY extern const VMStateDescription vmstate_mb_cpu; #endif diff --git a/target/mips/cpu.h b/target/mips/cpu.h index 4c15e76781..ef26fe03c7 100644 --- a/target/mips/cpu.h +++ b/target/mips/cpu.h @@ -1260,11 +1260,6 @@ static inline int mips_env_mmu_index(CPUMIPSState *env) return hflags_mmu_index(env->hflags); } -static inline int cpu_mmu_index(CPUMIPSState *env, bool ifetch) -{ - return mips_env_mmu_index(env); -} - #include "exec/cpu-all.h" /* Exceptions */ diff --git a/target/nios2/cpu.c b/target/nios2/cpu.c index e42885997e..0760bf6b38 100644 --- a/target/nios2/cpu.c +++ b/target/nios2/cpu.c @@ -57,7 +57,7 @@ static bool nios2_cpu_has_work(CPUState *cs) return cs->interrupt_request & CPU_INTERRUPT_HARD; } -int nios2_cpu_mmu_index(CPUState *cs, bool ifetch) +static int nios2_cpu_mmu_index(CPUState *cs, bool ifetch) { return (cpu_env(cs)->ctrl[CR_STATUS] & CR_STATUS_U ? MMU_USER_IDX : MMU_SUPERVISOR_IDX); diff --git a/target/nios2/cpu.h b/target/nios2/cpu.h index 9965ff74c1..4164a3432e 100644 --- a/target/nios2/cpu.h +++ b/target/nios2/cpu.h @@ -286,12 +286,6 @@ FIELD(TBFLAGS, CRS0, 0, 1) /* Set if CRS == 0. */ FIELD(TBFLAGS, U, 1, 1) /* Overlaps CR_STATUS_U */ FIELD(TBFLAGS, R0_0, 2, 1) /* Set if R0 == 0. */ -int nios2_cpu_mmu_index(CPUState *cs, bool ifetch); -static inline int cpu_mmu_index(CPUNios2State *env, bool ifetch) -{ - return nios2_cpu_mmu_index(env_cpu(env), ifetch); -} - static inline void cpu_get_tb_cpu_state(CPUNios2State *env, vaddr *pc, uint64_t *cs_base, uint32_t *flags) { diff --git a/target/openrisc/cpu.c b/target/openrisc/cpu.c index 8670152c84..a3cb80ca34 100644 --- a/target/openrisc/cpu.c +++ b/target/openrisc/cpu.c @@ -68,7 +68,7 @@ static bool openrisc_cpu_has_work(CPUState *cs) CPU_INTERRUPT_TIMER); } -int openrisc_cpu_mmu_index(CPUState *cs, bool ifetch) +static int openrisc_cpu_mmu_index(CPUState *cs, bool ifetch) { CPUOpenRISCState *env = cpu_env(cs); diff --git a/target/openrisc/cpu.h b/target/openrisc/cpu.h index 7dbed8d8be..b1b7db5cbd 100644 --- a/target/openrisc/cpu.h +++ b/target/openrisc/cpu.h @@ -361,12 +361,6 @@ static inline void cpu_get_tb_cpu_state(CPUOpenRISCState *env, vaddr *pc, | (env->sr & (SR_SM | SR_DME | SR_IME | SR_OVE)); } -int openrisc_cpu_mmu_index(CPUState *cs, bool ifetch); -static inline int cpu_mmu_index(CPUOpenRISCState *env, bool ifetch) -{ - return openrisc_cpu_mmu_index(env_cpu(env), ifetch); -} - static inline uint32_t cpu_get_sr(const CPUOpenRISCState *env) { return (env->sr diff --git a/target/ppc/cpu.h b/target/ppc/cpu.h index 5f4f52aec5..a44de22ca4 100644 --- a/target/ppc/cpu.h +++ b/target/ppc/cpu.h @@ -1633,11 +1633,6 @@ static inline int ppc_env_mmu_index(CPUPPCState *env, bool ifetch) #endif } -static inline int cpu_mmu_index(CPUPPCState *env, bool ifetch) -{ - return ppc_env_mmu_index(env, ifetch); -} - /* Compatibility modes */ #if defined(TARGET_PPC64) bool ppc_check_compat(PowerPCCPU *cpu, uint32_t compat_pvr, diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h index 9c825c7b51..f63ee9cc58 100644 --- a/target/riscv/cpu.h +++ b/target/riscv/cpu.h @@ -507,8 +507,6 @@ bool riscv_cpu_tlb_fill(CPUState *cs, vaddr address, int size, bool probe, uintptr_t retaddr); char *riscv_isa_string(RISCVCPU *cpu); -#define cpu_mmu_index riscv_env_mmu_index - #ifndef CONFIG_USER_ONLY void riscv_cpu_do_transaction_failed(CPUState *cs, hwaddr physaddr, vaddr addr, unsigned size, diff --git a/target/rx/cpu.h b/target/rx/cpu.h index 65f9cd2d0a..c53593d7aa 100644 --- a/target/rx/cpu.h +++ b/target/rx/cpu.h @@ -158,11 +158,6 @@ static inline void cpu_get_tb_cpu_state(CPURXState *env, vaddr *pc, *flags = FIELD_DP32(*flags, PSW, U, env->psw_u); } -static inline int cpu_mmu_index(CPURXState *env, bool ifetch) -{ - return 0; -} - static inline uint32_t rx_cpu_pack_psw(CPURXState *env) { uint32_t psw = 0; diff --git a/target/s390x/cpu.h b/target/s390x/cpu.h index f0fed5d6ad..d37a49b4d9 100644 --- a/target/s390x/cpu.h +++ b/target/s390x/cpu.h @@ -412,8 +412,6 @@ static inline int s390x_env_mmu_index(CPUS390XState *env, bool ifetch) #endif } -#define cpu_mmu_index s390x_env_mmu_index - #ifdef CONFIG_TCG #include "tcg/tcg_s390x.h" diff --git a/target/sh4/cpu.c b/target/sh4/cpu.c index 6fead5655f..2031168dc6 100644 --- a/target/sh4/cpu.c +++ b/target/sh4/cpu.c @@ -89,7 +89,7 @@ static bool superh_cpu_has_work(CPUState *cs) return cs->interrupt_request & CPU_INTERRUPT_HARD; } -int sh4_cpu_mmu_index(CPUState *cs, bool ifetch) +static int sh4_cpu_mmu_index(CPUState *cs, bool ifetch) { CPUSH4State *env = cpu_env(cs); diff --git a/target/sh4/cpu.h b/target/sh4/cpu.h index 9c5e2b349e..9211da6bde 100644 --- a/target/sh4/cpu.h +++ b/target/sh4/cpu.h @@ -370,12 +370,6 @@ static inline void cpu_write_sr(CPUSH4State *env, target_ulong sr) env->sr = sr & ~((1u << SR_M) | (1u << SR_Q) | (1u << SR_T)); } -int sh4_cpu_mmu_index(CPUState *cs, bool ifetch); -static inline int cpu_mmu_index(CPUSH4State *env, bool ifetch) -{ - return sh4_cpu_mmu_index(env_cpu(env), ifetch); -} - static inline void cpu_get_tb_cpu_state(CPUSH4State *env, vaddr *pc, uint64_t *cs_base, uint32_t *flags) { diff --git a/target/sparc/cpu.c b/target/sparc/cpu.c index 7a3b815737..afa62723fe 100644 --- a/target/sparc/cpu.c +++ b/target/sparc/cpu.c @@ -718,7 +718,7 @@ static bool sparc_cpu_has_work(CPUState *cs) cpu_interrupts_enabled(env); } -int sparc_cpu_mmu_index(CPUState *cs, bool ifetch) +static int sparc_cpu_mmu_index(CPUState *cs, bool ifetch) { CPUSPARCState *env = cpu_env(cs); diff --git a/target/sparc/cpu.h b/target/sparc/cpu.h index 92c58c92c1..51856152fa 100644 --- a/target/sparc/cpu.h +++ b/target/sparc/cpu.h @@ -749,12 +749,6 @@ trap_state* cpu_tsptr(CPUSPARCState* env); #define TB_FLAG_HYPER (1 << 7) #define TB_FLAG_ASI_SHIFT 24 -int sparc_cpu_mmu_index(CPUState *cs, bool ifetch); -static inline int cpu_mmu_index(CPUSPARCState *env, bool ifetch) -{ - return sparc_cpu_mmu_index(env_cpu(env), ifetch); -} - static inline void cpu_get_tb_cpu_state(CPUSPARCState *env, vaddr *pc, uint64_t *cs_base, uint32_t *pflags) { diff --git a/target/tricore/cpu.h b/target/tricore/cpu.h index 2d4446cea5..220af69fc2 100644 --- a/target/tricore/cpu.h +++ b/target/tricore/cpu.h @@ -246,11 +246,6 @@ void fpu_set_state(CPUTriCoreState *env); #define MMU_USER_IDX 2 -static inline int cpu_mmu_index(CPUTriCoreState *env, bool ifetch) -{ - return 0; -} - #include "exec/cpu-all.h" FIELD(TB_FLAGS, PRIV, 0, 2) diff --git a/target/xtensa/cpu.h b/target/xtensa/cpu.h index 4b033ee924..6b8d0636d2 100644 --- a/target/xtensa/cpu.h +++ b/target/xtensa/cpu.h @@ -713,11 +713,6 @@ static inline uint32_t xtensa_replicate_windowstart(CPUXtensaState *env) /* MMU modes definitions */ #define MMU_USER_IDX 3 -static inline int cpu_mmu_index(CPUXtensaState *env, bool ifetch) -{ - return xtensa_get_cring(env); -} - #define XTENSA_TBFLAG_RING_MASK 0x3 #define XTENSA_TBFLAG_EXCM 0x4 #define XTENSA_TBFLAG_LITBASE 0x8 From 3b916140043e2757dd8d51ec641a6885e960e6ca Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Mon, 29 Jan 2024 20:35:06 +1000 Subject: [PATCH 33/58] include/exec: Change cpu_mmu_index argument to CPUState MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Reviewed-by: Philippe Mathieu-Daudé Signed-off-by: Richard Henderson --- accel/tcg/cputlb.c | 22 +++++++++------- accel/tcg/ldst_common.c.inc | 42 ++++++++++++++++++++----------- include/exec/cpu-all.h | 2 +- include/exec/cpu-common.h | 3 +-- semihosting/uaccess.c | 2 +- target/cris/translate.c | 2 +- target/hppa/mem_helper.c | 2 +- target/hppa/op_helper.c | 8 +++--- target/i386/tcg/translate.c | 2 +- target/loongarch/cpu_helper.c | 2 +- target/loongarch/tcg/tlb_helper.c | 2 +- target/m68k/op_helper.c | 2 +- target/microblaze/helper.c | 3 +-- target/microblaze/mmu.c | 2 +- target/microblaze/translate.c | 2 +- target/nios2/translate.c | 2 +- target/openrisc/translate.c | 2 +- target/sparc/cpu.h | 2 +- target/sparc/ldst_helper.c | 2 +- target/sparc/mmu_helper.c | 2 +- target/tricore/helper.c | 2 +- target/tricore/translate.c | 2 +- target/xtensa/mmu_helper.c | 2 +- 23 files changed, 65 insertions(+), 49 deletions(-) diff --git a/accel/tcg/cputlb.c b/accel/tcg/cputlb.c index 3facfcbb24..047cd2cc0a 100644 --- a/accel/tcg/cputlb.c +++ b/accel/tcg/cputlb.c @@ -1601,7 +1601,7 @@ tb_page_addr_t get_page_addr_code_hostp(CPUArchState *env, vaddr addr, void *p; (void)probe_access_internal(env_cpu(env), addr, 1, MMU_INST_FETCH, - cpu_mmu_index(env, true), false, + cpu_mmu_index(env_cpu(env), true), false, &p, &full, 0, false); if (p == NULL) { return -1; @@ -2959,26 +2959,30 @@ static void do_st16_mmu(CPUState *cpu, vaddr addr, Int128 val, uint32_t cpu_ldub_code(CPUArchState *env, abi_ptr addr) { - MemOpIdx oi = make_memop_idx(MO_UB, cpu_mmu_index(env, true)); - return do_ld1_mmu(env_cpu(env), addr, oi, 0, MMU_INST_FETCH); + CPUState *cs = env_cpu(env); + MemOpIdx oi = make_memop_idx(MO_UB, cpu_mmu_index(cs, true)); + return do_ld1_mmu(cs, addr, oi, 0, MMU_INST_FETCH); } uint32_t cpu_lduw_code(CPUArchState *env, abi_ptr addr) { - MemOpIdx oi = make_memop_idx(MO_TEUW, cpu_mmu_index(env, true)); - return do_ld2_mmu(env_cpu(env), addr, oi, 0, MMU_INST_FETCH); + CPUState *cs = env_cpu(env); + MemOpIdx oi = make_memop_idx(MO_TEUW, cpu_mmu_index(cs, true)); + return do_ld2_mmu(cs, addr, oi, 0, MMU_INST_FETCH); } uint32_t cpu_ldl_code(CPUArchState *env, abi_ptr addr) { - MemOpIdx oi = make_memop_idx(MO_TEUL, cpu_mmu_index(env, true)); - return do_ld4_mmu(env_cpu(env), addr, oi, 0, MMU_INST_FETCH); + CPUState *cs = env_cpu(env); + MemOpIdx oi = make_memop_idx(MO_TEUL, cpu_mmu_index(cs, true)); + return do_ld4_mmu(cs, addr, oi, 0, MMU_INST_FETCH); } uint64_t cpu_ldq_code(CPUArchState *env, abi_ptr addr) { - MemOpIdx oi = make_memop_idx(MO_TEUQ, cpu_mmu_index(env, true)); - return do_ld8_mmu(env_cpu(env), addr, oi, 0, MMU_INST_FETCH); + CPUState *cs = env_cpu(env); + MemOpIdx oi = make_memop_idx(MO_TEUQ, cpu_mmu_index(cs, true)); + return do_ld8_mmu(cs, addr, oi, 0, MMU_INST_FETCH); } uint8_t cpu_ldb_code_mmu(CPUArchState *env, abi_ptr addr, diff --git a/accel/tcg/ldst_common.c.inc b/accel/tcg/ldst_common.c.inc index 44833513fb..c82048e377 100644 --- a/accel/tcg/ldst_common.c.inc +++ b/accel/tcg/ldst_common.c.inc @@ -354,7 +354,8 @@ void cpu_stq_le_mmuidx_ra(CPUArchState *env, abi_ptr addr, uint64_t val, uint32_t cpu_ldub_data_ra(CPUArchState *env, abi_ptr addr, uintptr_t ra) { - return cpu_ldub_mmuidx_ra(env, addr, cpu_mmu_index(env, false), ra); + int mmu_index = cpu_mmu_index(env_cpu(env), false); + return cpu_ldub_mmuidx_ra(env, addr, mmu_index, ra); } int cpu_ldsb_data_ra(CPUArchState *env, abi_ptr addr, uintptr_t ra) @@ -364,7 +365,8 @@ int cpu_ldsb_data_ra(CPUArchState *env, abi_ptr addr, uintptr_t ra) uint32_t cpu_lduw_be_data_ra(CPUArchState *env, abi_ptr addr, uintptr_t ra) { - return cpu_lduw_be_mmuidx_ra(env, addr, cpu_mmu_index(env, false), ra); + int mmu_index = cpu_mmu_index(env_cpu(env), false); + return cpu_lduw_be_mmuidx_ra(env, addr, mmu_index, ra); } int cpu_ldsw_be_data_ra(CPUArchState *env, abi_ptr addr, uintptr_t ra) @@ -374,17 +376,20 @@ int cpu_ldsw_be_data_ra(CPUArchState *env, abi_ptr addr, uintptr_t ra) uint32_t cpu_ldl_be_data_ra(CPUArchState *env, abi_ptr addr, uintptr_t ra) { - return cpu_ldl_be_mmuidx_ra(env, addr, cpu_mmu_index(env, false), ra); + int mmu_index = cpu_mmu_index(env_cpu(env), false); + return cpu_ldl_be_mmuidx_ra(env, addr, mmu_index, ra); } uint64_t cpu_ldq_be_data_ra(CPUArchState *env, abi_ptr addr, uintptr_t ra) { - return cpu_ldq_be_mmuidx_ra(env, addr, cpu_mmu_index(env, false), ra); + int mmu_index = cpu_mmu_index(env_cpu(env), false); + return cpu_ldq_be_mmuidx_ra(env, addr, mmu_index, ra); } uint32_t cpu_lduw_le_data_ra(CPUArchState *env, abi_ptr addr, uintptr_t ra) { - return cpu_lduw_le_mmuidx_ra(env, addr, cpu_mmu_index(env, false), ra); + int mmu_index = cpu_mmu_index(env_cpu(env), false); + return cpu_lduw_le_mmuidx_ra(env, addr, mmu_index, ra); } int cpu_ldsw_le_data_ra(CPUArchState *env, abi_ptr addr, uintptr_t ra) @@ -394,54 +399,63 @@ int cpu_ldsw_le_data_ra(CPUArchState *env, abi_ptr addr, uintptr_t ra) uint32_t cpu_ldl_le_data_ra(CPUArchState *env, abi_ptr addr, uintptr_t ra) { - return cpu_ldl_le_mmuidx_ra(env, addr, cpu_mmu_index(env, false), ra); + int mmu_index = cpu_mmu_index(env_cpu(env), false); + return cpu_ldl_le_mmuidx_ra(env, addr, mmu_index, ra); } uint64_t cpu_ldq_le_data_ra(CPUArchState *env, abi_ptr addr, uintptr_t ra) { - return cpu_ldq_le_mmuidx_ra(env, addr, cpu_mmu_index(env, false), ra); + int mmu_index = cpu_mmu_index(env_cpu(env), false); + return cpu_ldq_le_mmuidx_ra(env, addr, mmu_index, ra); } void cpu_stb_data_ra(CPUArchState *env, abi_ptr addr, uint32_t val, uintptr_t ra) { - cpu_stb_mmuidx_ra(env, addr, val, cpu_mmu_index(env, false), ra); + int mmu_index = cpu_mmu_index(env_cpu(env), false); + cpu_stb_mmuidx_ra(env, addr, val, mmu_index, ra); } void cpu_stw_be_data_ra(CPUArchState *env, abi_ptr addr, uint32_t val, uintptr_t ra) { - cpu_stw_be_mmuidx_ra(env, addr, val, cpu_mmu_index(env, false), ra); + int mmu_index = cpu_mmu_index(env_cpu(env), false); + cpu_stw_be_mmuidx_ra(env, addr, val, mmu_index, ra); } void cpu_stl_be_data_ra(CPUArchState *env, abi_ptr addr, uint32_t val, uintptr_t ra) { - cpu_stl_be_mmuidx_ra(env, addr, val, cpu_mmu_index(env, false), ra); + int mmu_index = cpu_mmu_index(env_cpu(env), false); + cpu_stl_be_mmuidx_ra(env, addr, val, mmu_index, ra); } void cpu_stq_be_data_ra(CPUArchState *env, abi_ptr addr, uint64_t val, uintptr_t ra) { - cpu_stq_be_mmuidx_ra(env, addr, val, cpu_mmu_index(env, false), ra); + int mmu_index = cpu_mmu_index(env_cpu(env), false); + cpu_stq_be_mmuidx_ra(env, addr, val, mmu_index, ra); } void cpu_stw_le_data_ra(CPUArchState *env, abi_ptr addr, uint32_t val, uintptr_t ra) { - cpu_stw_le_mmuidx_ra(env, addr, val, cpu_mmu_index(env, false), ra); + int mmu_index = cpu_mmu_index(env_cpu(env), false); + cpu_stw_le_mmuidx_ra(env, addr, val, mmu_index, ra); } void cpu_stl_le_data_ra(CPUArchState *env, abi_ptr addr, uint32_t val, uintptr_t ra) { - cpu_stl_le_mmuidx_ra(env, addr, val, cpu_mmu_index(env, false), ra); + int mmu_index = cpu_mmu_index(env_cpu(env), false); + cpu_stl_le_mmuidx_ra(env, addr, val, mmu_index, ra); } void cpu_stq_le_data_ra(CPUArchState *env, abi_ptr addr, uint64_t val, uintptr_t ra) { - cpu_stq_le_mmuidx_ra(env, addr, val, cpu_mmu_index(env, false), ra); + int mmu_index = cpu_mmu_index(env_cpu(env), false); + cpu_stq_le_mmuidx_ra(env, addr, val, mmu_index, ra); } /*--------------------------*/ diff --git a/include/exec/cpu-all.h b/include/exec/cpu-all.h index 80c0d0699b..bc05dce7ab 100644 --- a/include/exec/cpu-all.h +++ b/include/exec/cpu-all.h @@ -311,7 +311,7 @@ CPUArchState *cpu_copy(CPUArchState *env); #define TLB_MMIO (1 << (TARGET_PAGE_BITS_MIN - 2)) #define TLB_WATCHPOINT 0 -static inline int cpu_mmu_index(CPUArchState *env, bool ifetch) +static inline int cpu_mmu_index(CPUState *cs, bool ifetch) { return MMU_USER_IDX; } diff --git a/include/exec/cpu-common.h b/include/exec/cpu-common.h index cdfbe994fd..9ead1be100 100644 --- a/include/exec/cpu-common.h +++ b/include/exec/cpu-common.h @@ -275,9 +275,8 @@ static inline CPUState *env_cpu(CPUArchState *env) * The user-only version of this function is inline in cpu-all.h, * where it always returns MMU_USER_IDX. */ -static inline int cpu_mmu_index(CPUArchState *env, bool ifetch) +static inline int cpu_mmu_index(CPUState *cs, bool ifetch) { - CPUState *cs = env_cpu(env); int ret = cs->cc->mmu_index(cs, ifetch); tcg_debug_assert(ret >= 0 && ret < NB_MMU_MODES); return ret; diff --git a/semihosting/uaccess.c b/semihosting/uaccess.c index 5d889f9263..dc587d73bc 100644 --- a/semihosting/uaccess.c +++ b/semihosting/uaccess.c @@ -26,7 +26,7 @@ void *uaccess_lock_user(CPUArchState *env, target_ulong addr, ssize_t uaccess_strlen_user(CPUArchState *env, target_ulong addr) { - int mmu_idx = cpu_mmu_index(env, false); + int mmu_idx = cpu_mmu_index(env_cpu(env), false); size_t len = 0; while (1) { diff --git a/target/cris/translate.c b/target/cris/translate.c index 7acea29a01..8f74b6c53f 100644 --- a/target/cris/translate.c +++ b/target/cris/translate.c @@ -2966,7 +2966,7 @@ static void cris_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cs) dc->cpu = env_archcpu(env); dc->ppc = pc_start; dc->pc = pc_start; - dc->mem_index = cpu_mmu_index(env, false); + dc->mem_index = cpu_mmu_index(cs, false); dc->flags_uptodate = 1; dc->flags_x = tb_flags & X_FLAG; dc->cc_x_uptodate = 0; diff --git a/target/hppa/mem_helper.c b/target/hppa/mem_helper.c index 4fcc612754..629a9d90ef 100644 --- a/target/hppa/mem_helper.c +++ b/target/hppa/mem_helper.c @@ -646,7 +646,7 @@ int hppa_artype_for_page(CPUHPPAState *env, target_ulong vaddr) void HELPER(diag_btlb)(CPUHPPAState *env) { unsigned int phys_page, len, slot; - int mmu_idx = cpu_mmu_index(env, 0); + int mmu_idx = cpu_mmu_index(env_cpu(env), 0); uintptr_t ra = GETPC(); HPPATLBEntry *btlb; uint64_t virt_page; diff --git a/target/hppa/op_helper.c b/target/hppa/op_helper.c index ce15469465..b1f24a5aad 100644 --- a/target/hppa/op_helper.c +++ b/target/hppa/op_helper.c @@ -59,7 +59,7 @@ void HELPER(tcond)(CPUHPPAState *env, target_ulong cond) static void atomic_store_mask32(CPUHPPAState *env, target_ulong addr, uint32_t val, uint32_t mask, uintptr_t ra) { - int mmu_idx = cpu_mmu_index(env, 0); + int mmu_idx = cpu_mmu_index(env_cpu(env), 0); uint32_t old, new, cmp, *haddr; void *vaddr; @@ -86,7 +86,7 @@ static void atomic_store_mask64(CPUHPPAState *env, target_ulong addr, int size, uintptr_t ra) { #ifdef CONFIG_ATOMIC64 - int mmu_idx = cpu_mmu_index(env, 0); + int mmu_idx = cpu_mmu_index(env_cpu(env), 0); uint64_t old, new, cmp, *haddr; void *vaddr; @@ -235,7 +235,7 @@ static void do_stby_e(CPUHPPAState *env, target_ulong addr, target_ulong val, default: /* Nothing is stored, but protection is checked and the cacheline is marked dirty. */ - probe_write(env, addr, 0, cpu_mmu_index(env, 0), ra); + probe_write(env, addr, 0, cpu_mmu_index(env_cpu(env), 0), ra); break; } } @@ -296,7 +296,7 @@ static void do_stdby_e(CPUHPPAState *env, target_ulong addr, uint64_t val, default: /* Nothing is stored, but protection is checked and the cacheline is marked dirty. */ - probe_write(env, addr, 0, cpu_mmu_index(env, 0), ra); + probe_write(env, addr, 0, cpu_mmu_index(env_cpu(env), 0), ra); break; } } diff --git a/target/i386/tcg/translate.c b/target/i386/tcg/translate.c index 2808903661..10cba16256 100644 --- a/target/i386/tcg/translate.c +++ b/target/i386/tcg/translate.c @@ -6955,7 +6955,7 @@ static void i386_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cpu) dc->cc_op_dirty = false; dc->popl_esp_hack = 0; /* select memory access functions */ - dc->mem_index = cpu_mmu_index(env, false); + dc->mem_index = cpu_mmu_index(cpu, false); dc->cpuid_features = env->features[FEAT_1_EDX]; dc->cpuid_ext_features = env->features[FEAT_1_ECX]; dc->cpuid_ext2_features = env->features[FEAT_8000_0001_EDX]; diff --git a/target/loongarch/cpu_helper.c b/target/loongarch/cpu_helper.c index b0658773b0..45f821d086 100644 --- a/target/loongarch/cpu_helper.c +++ b/target/loongarch/cpu_helper.c @@ -224,7 +224,7 @@ hwaddr loongarch_cpu_get_phys_page_debug(CPUState *cs, vaddr addr) int prot; if (get_physical_address(env, &phys_addr, &prot, addr, MMU_DATA_LOAD, - cpu_mmu_index(env, false)) != 0) { + cpu_mmu_index(cs, false)) != 0) { return -1; } return phys_addr; diff --git a/target/loongarch/tcg/tlb_helper.c b/target/loongarch/tcg/tlb_helper.c index 804ab7a263..a08c08b05a 100644 --- a/target/loongarch/tcg/tlb_helper.c +++ b/target/loongarch/tcg/tlb_helper.c @@ -90,7 +90,7 @@ static void invalidate_tlb_entry(CPULoongArchState *env, int index) uint8_t tlb_ps; LoongArchTLB *tlb = &env->tlb[index]; - int mmu_idx = cpu_mmu_index(env, false); + int mmu_idx = cpu_mmu_index(env_cpu(env), false); uint8_t tlb_v0 = FIELD_EX64(tlb->tlb_entry0, TLBENTRY, V); uint8_t tlb_v1 = FIELD_EX64(tlb->tlb_entry1, TLBENTRY, V); uint64_t tlb_vppn = FIELD_EX64(tlb->tlb_misc, TLB_MISC, VPPN); diff --git a/target/m68k/op_helper.c b/target/m68k/op_helper.c index 1ce850bbc5..47b4173bb9 100644 --- a/target/m68k/op_helper.c +++ b/target/m68k/op_helper.c @@ -811,7 +811,7 @@ static void do_cas2l(CPUM68KState *env, uint32_t regs, uint32_t a1, uint32_t a2, uint32_t l1, l2; uintptr_t ra = GETPC(); #if defined(CONFIG_ATOMIC64) - int mmu_idx = cpu_mmu_index(env, 0); + int mmu_idx = cpu_mmu_index(env_cpu(env), 0); MemOpIdx oi = make_memop_idx(MO_BEUQ, mmu_idx); #endif diff --git a/target/microblaze/helper.c b/target/microblaze/helper.c index 98bdb82de8..460eee0cf5 100644 --- a/target/microblaze/helper.c +++ b/target/microblaze/helper.c @@ -228,10 +228,9 @@ hwaddr mb_cpu_get_phys_page_attrs_debug(CPUState *cs, vaddr addr, MemTxAttrs *attrs) { MicroBlazeCPU *cpu = MICROBLAZE_CPU(cs); - CPUMBState *env = &cpu->env; target_ulong vaddr, paddr = 0; MicroBlazeMMULookup lu; - int mmu_idx = cpu_mmu_index(env, false); + int mmu_idx = cpu_mmu_index(cs, false); unsigned int hit; /* Caller doesn't initialize */ diff --git a/target/microblaze/mmu.c b/target/microblaze/mmu.c index 75651979a9..234006634e 100644 --- a/target/microblaze/mmu.c +++ b/target/microblaze/mmu.c @@ -305,7 +305,7 @@ void mmu_write(CPUMBState *env, bool ext, uint32_t rn, uint32_t v) } hit = mmu_translate(cpu, &lu, v & TLB_EPN_MASK, - 0, cpu_mmu_index(env, false)); + 0, cpu_mmu_index(env_cpu(env), false)); if (hit) { env->mmu.regs[MMU_R_TLBX] = lu.idx; } else { diff --git a/target/microblaze/translate.c b/target/microblaze/translate.c index 2e628647d1..a465c2d245 100644 --- a/target/microblaze/translate.c +++ b/target/microblaze/translate.c @@ -1607,7 +1607,7 @@ static void mb_tr_init_disas_context(DisasContextBase *dcb, CPUState *cs) dc->ext_imm = dc->base.tb->cs_base; dc->r0 = NULL; dc->r0_set = false; - dc->mem_index = cpu_mmu_index(&cpu->env, false); + dc->mem_index = cpu_mmu_index(cs, false); dc->jmp_cond = dc->tb_flags & D_FLAG ? TCG_COND_ALWAYS : TCG_COND_NEVER; dc->jmp_dest = -1; diff --git a/target/nios2/translate.c b/target/nios2/translate.c index 3078372b36..612556b297 100644 --- a/target/nios2/translate.c +++ b/target/nios2/translate.c @@ -948,7 +948,7 @@ static void nios2_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cs) Nios2CPU *cpu = env_archcpu(env); int page_insns; - dc->mem_idx = cpu_mmu_index(env, false); + dc->mem_idx = cpu_mmu_index(cs, false); dc->cr_state = cpu->cr_state; dc->tb_flags = dc->base.tb->flags; dc->eic_present = cpu->eic_present; diff --git a/target/openrisc/translate.c b/target/openrisc/translate.c index d4cbc5eaea..785bcb6552 100644 --- a/target/openrisc/translate.c +++ b/target/openrisc/translate.c @@ -1528,7 +1528,7 @@ static void openrisc_tr_init_disas_context(DisasContextBase *dcb, CPUState *cs) CPUOpenRISCState *env = cpu_env(cs); int bound; - dc->mem_idx = cpu_mmu_index(env, false); + dc->mem_idx = cpu_mmu_index(cs, false); dc->tb_flags = dc->base.tb->flags; dc->delayed_branch = (dc->tb_flags & TB_FLAGS_DFLAG) != 0; dc->cpucfgr = env->cpucfgr; diff --git a/target/sparc/cpu.h b/target/sparc/cpu.h index 51856152fa..1e076f6355 100644 --- a/target/sparc/cpu.h +++ b/target/sparc/cpu.h @@ -755,7 +755,7 @@ static inline void cpu_get_tb_cpu_state(CPUSPARCState *env, vaddr *pc, uint32_t flags; *pc = env->pc; *cs_base = env->npc; - flags = cpu_mmu_index(env, false); + flags = cpu_mmu_index(env_cpu(env), false); #ifndef CONFIG_USER_ONLY if (cpu_supervisor_mode(env)) { flags |= TB_FLAG_SUPER; diff --git a/target/sparc/ldst_helper.c b/target/sparc/ldst_helper.c index 09066d5487..52aa6c631b 100644 --- a/target/sparc/ldst_helper.c +++ b/target/sparc/ldst_helper.c @@ -690,7 +690,7 @@ uint64_t helper_ld_asi(CPUSPARCState *env, target_ulong addr, case ASI_M_IODIAG: /* Turbosparc IOTLB Diagnostic */ break; case ASI_KERNELTXT: /* Supervisor code access */ - oi = make_memop_idx(memop, cpu_mmu_index(env, true)); + oi = make_memop_idx(memop, cpu_mmu_index(env_cpu(env), true)); switch (size) { case 1: ret = cpu_ldb_code_mmu(env, addr, oi, GETPC()); diff --git a/target/sparc/mmu_helper.c b/target/sparc/mmu_helper.c index 453498c670..5170a668bb 100644 --- a/target/sparc/mmu_helper.c +++ b/target/sparc/mmu_helper.c @@ -901,7 +901,7 @@ hwaddr sparc_cpu_get_phys_page_debug(CPUState *cs, vaddr addr) SPARCCPU *cpu = SPARC_CPU(cs); CPUSPARCState *env = &cpu->env; hwaddr phys_addr; - int mmu_idx = cpu_mmu_index(env, false); + int mmu_idx = cpu_mmu_index(cs, false); if (cpu_sparc_get_phys_page(env, &phys_addr, addr, 2, mmu_idx) != 0) { if (cpu_sparc_get_phys_page(env, &phys_addr, addr, 0, mmu_idx) != 0) { diff --git a/target/tricore/helper.c b/target/tricore/helper.c index 174f666e1e..649373a9cb 100644 --- a/target/tricore/helper.c +++ b/target/tricore/helper.c @@ -48,7 +48,7 @@ hwaddr tricore_cpu_get_phys_page_debug(CPUState *cs, vaddr addr) TriCoreCPU *cpu = TRICORE_CPU(cs); hwaddr phys_addr; int prot; - int mmu_idx = cpu_mmu_index(&cpu->env, false); + int mmu_idx = cpu_mmu_index(cs, false); if (get_physical_address(&cpu->env, &phys_addr, &prot, addr, MMU_DATA_LOAD, mmu_idx)) { diff --git a/target/tricore/translate.c b/target/tricore/translate.c index f1156c39e7..278c514ab0 100644 --- a/target/tricore/translate.c +++ b/target/tricore/translate.c @@ -8355,7 +8355,7 @@ static void tricore_tr_init_disas_context(DisasContextBase *dcbase, { DisasContext *ctx = container_of(dcbase, DisasContext, base); CPUTriCoreState *env = cpu_env(cs); - ctx->mem_idx = cpu_mmu_index(env, false); + ctx->mem_idx = cpu_mmu_index(cs, false); uint32_t tb_flags = (uint32_t)ctx->base.tb->flags; ctx->priv = FIELD_EX32(tb_flags, TB_FLAGS, PRIV); diff --git a/target/xtensa/mmu_helper.c b/target/xtensa/mmu_helper.c index 2fda4e887c..47063b0a57 100644 --- a/target/xtensa/mmu_helper.c +++ b/target/xtensa/mmu_helper.c @@ -66,7 +66,7 @@ void HELPER(itlb_hit_test)(CPUXtensaState *env, uint32_t vaddr) * only the side-effects (ie any MMU or other exception) */ probe_access(env, vaddr, 1, MMU_INST_FETCH, - cpu_mmu_index(env, true), GETPC()); + cpu_mmu_index(env_cpu(env), true), GETPC()); } void HELPER(wsr_rasid)(CPUXtensaState *env, uint32_t v) From da4038d2da6d3a3d5f86665bd51b2ba49df5d652 Mon Sep 17 00:00:00 2001 From: Ilya Leoshkevich Date: Wed, 31 Jan 2024 23:02:18 +0100 Subject: [PATCH 34/58] tests/tcg: Fix the /proc/self/mem probing in the PROT_NONE gdbstub test The `if not probe_proc_self_mem` check never passes, because probe_proc_self_mem is a function object, which is a truthy value. Add parentheses in order to perform a function call. Fixes: dc84d50a7f9b ("tests/tcg: Add the PROT_NONE gdbstub test") Signed-off-by: Ilya Leoshkevich Message-Id: <20240131220245.235993-1-iii@linux.ibm.com> Signed-off-by: Richard Henderson --- tests/tcg/multiarch/gdbstub/prot-none.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/tcg/multiarch/gdbstub/prot-none.py b/tests/tcg/multiarch/gdbstub/prot-none.py index e829d3ebc5..7e264589cb 100644 --- a/tests/tcg/multiarch/gdbstub/prot-none.py +++ b/tests/tcg/multiarch/gdbstub/prot-none.py @@ -20,7 +20,7 @@ def probe_proc_self_mem(): def run_test(): """Run through the tests one by one""" - if not probe_proc_self_mem: + if not probe_proc_self_mem(): print("SKIP: /proc/self/mem is not usable") exit(0) gdb.Breakpoint("break_here") From 45bf0e7aa648369cf8ab2333bd20144806fc1be3 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Fri, 2 Feb 2024 09:34:14 +1000 Subject: [PATCH 35/58] tcg/loongarch64: Set vector registers call clobbered Because there are more call clobbered registers than call saved registers, we begin with all registers as call clobbered and then reset those that are saved. This was missed when we introduced the LSX support. Cc: qemu-stable@nongnu.org Fixes: 16288ded944 ("tcg/loongarch64: Lower basic tcg vec ops to LSX") Resolves: https://gitlab.com/qemu-project/qemu/-/issues/2136 Signed-off-by: Richard Henderson Reviewed-by: Song Gao Message-Id: <20240201233414.500588-1-richard.henderson@linaro.org> --- tcg/loongarch64/tcg-target.c.inc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tcg/loongarch64/tcg-target.c.inc b/tcg/loongarch64/tcg-target.c.inc index bab0a173a3..dcf0205458 100644 --- a/tcg/loongarch64/tcg-target.c.inc +++ b/tcg/loongarch64/tcg-target.c.inc @@ -2327,7 +2327,7 @@ static void tcg_target_init(TCGContext *s) tcg_target_available_regs[TCG_TYPE_I32] = ALL_GENERAL_REGS; tcg_target_available_regs[TCG_TYPE_I64] = ALL_GENERAL_REGS; - tcg_target_call_clobber_regs = ALL_GENERAL_REGS; + tcg_target_call_clobber_regs = ALL_GENERAL_REGS | ALL_VECTOR_REGS; tcg_regset_reset_reg(tcg_target_call_clobber_regs, TCG_REG_S0); tcg_regset_reset_reg(tcg_target_call_clobber_regs, TCG_REG_S1); tcg_regset_reset_reg(tcg_target_call_clobber_regs, TCG_REG_S2); From 98271007379bae8ca4300ae5d8cdc37ec662ee73 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Fri, 3 Nov 2023 10:38:20 -0700 Subject: [PATCH 36/58] target/sparc: Use tcg_gen_qemu_{ld, st}_i128 for ASI_M_BCOPY Align the operation to the 32-byte cacheline. Use 2 pair of i128 instead of 8 pair of i32. Signed-off-by: Richard Henderson Tested-by: Mark Cave-Ayland Acked-by: Mark Cave-Ayland Message-Id: <20231103173841.33651-2-richard.henderson@linaro.org> --- target/sparc/translate.c | 43 +++++++++++++++++++++++----------------- 1 file changed, 25 insertions(+), 18 deletions(-) diff --git a/target/sparc/translate.c b/target/sparc/translate.c index 97184fa403..1082aabc14 100644 --- a/target/sparc/translate.c +++ b/target/sparc/translate.c @@ -1727,28 +1727,35 @@ static void gen_st_asi(DisasContext *dc, DisasASI *da, TCGv src, TCGv addr) case GET_ASI_BCOPY: assert(TARGET_LONG_BITS == 32); - /* Copy 32 bytes from the address in SRC to ADDR. */ - /* ??? The original qemu code suggests 4-byte alignment, dropping - the low bits, but the only place I can see this used is in the - Linux kernel with 32 byte alignment, which would make more sense - as a cacheline-style operation. */ + /* + * Copy 32 bytes from the address in SRC to ADDR. + * + * From Ross RT625 hyperSPARC manual, section 4.6: + * "Block Copy and Block Fill will work only on cache line boundaries." + * + * It does not specify if an unaliged address is truncated or trapped. + * Previous qemu behaviour was to truncate to 4 byte alignment, which + * is obviously wrong. The only place I can see this used is in the + * Linux kernel which begins with page alignment, advancing by 32, + * so is always aligned. Assume truncation as the simpler option. + * + * Since the loads and stores are paired, allow the copy to happen + * in the host endianness. The copy need not be atomic. + */ { + MemOp mop = MO_128 | MO_ATOM_IFALIGN_PAIR; TCGv saddr = tcg_temp_new(); TCGv daddr = tcg_temp_new(); - TCGv four = tcg_constant_tl(4); - TCGv_i32 tmp = tcg_temp_new_i32(); - int i; + TCGv_i128 tmp = tcg_temp_new_i128(); - tcg_gen_andi_tl(saddr, src, -4); - tcg_gen_andi_tl(daddr, addr, -4); - for (i = 0; i < 32; i += 4) { - /* Since the loads and stores are paired, allow the - copy to happen in the host endianness. */ - tcg_gen_qemu_ld_i32(tmp, saddr, da->mem_idx, MO_UL); - tcg_gen_qemu_st_i32(tmp, daddr, da->mem_idx, MO_UL); - tcg_gen_add_tl(saddr, saddr, four); - tcg_gen_add_tl(daddr, daddr, four); - } + tcg_gen_andi_tl(saddr, src, -32); + tcg_gen_andi_tl(daddr, addr, -32); + tcg_gen_qemu_ld_i128(tmp, saddr, da->mem_idx, mop); + tcg_gen_qemu_st_i128(tmp, daddr, da->mem_idx, mop); + tcg_gen_addi_tl(saddr, saddr, 16); + tcg_gen_addi_tl(daddr, daddr, 16); + tcg_gen_qemu_ld_i128(tmp, saddr, da->mem_idx, mop); + tcg_gen_qemu_st_i128(tmp, daddr, da->mem_idx, mop); } break; From 54c3e9534f81a733806ac823185918dfe88687a5 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Fri, 3 Nov 2023 10:38:21 -0700 Subject: [PATCH 37/58] target/sparc: Use tcg_gen_qemu_{ld, st}_i128 for ASI_M_BFILL Align the operation to the 32-byte cacheline. Use 2 i128 instead of 4 i64. Signed-off-by: Richard Henderson Tested-by: Mark Cave-Ayland Acked-by: Mark Cave-Ayland Message-Id: <20231103173841.33651-3-richard.henderson@linaro.org> --- target/sparc/translate.c | 29 ++++++++++++++--------------- 1 file changed, 14 insertions(+), 15 deletions(-) diff --git a/target/sparc/translate.c b/target/sparc/translate.c index 1082aabc14..3a59262c9a 100644 --- a/target/sparc/translate.c +++ b/target/sparc/translate.c @@ -2172,23 +2172,22 @@ static void gen_stda_asi(DisasContext *dc, DisasASI *da, TCGv addr, int rd) case GET_ASI_BFILL: assert(TARGET_LONG_BITS == 32); - /* Store 32 bytes of T64 to ADDR. */ - /* ??? The original qemu code suggests 8-byte alignment, dropping - the low bits, but the only place I can see this used is in the - Linux kernel with 32 byte alignment, which would make more sense - as a cacheline-style operation. */ + /* + * Store 32 bytes of [rd:rd+1] to ADDR. + * See comments for GET_ASI_COPY above. + */ { - TCGv_i64 t64 = tcg_temp_new_i64(); - TCGv d_addr = tcg_temp_new(); - TCGv eight = tcg_constant_tl(8); - int i; + MemOp mop = MO_TE | MO_128 | MO_ATOM_IFALIGN_PAIR; + TCGv_i64 t8 = tcg_temp_new_i64(); + TCGv_i128 t16 = tcg_temp_new_i128(); + TCGv daddr = tcg_temp_new(); - tcg_gen_concat_tl_i64(t64, lo, hi); - tcg_gen_andi_tl(d_addr, addr, -8); - for (i = 0; i < 32; i += 8) { - tcg_gen_qemu_st_i64(t64, d_addr, da->mem_idx, da->memop); - tcg_gen_add_tl(d_addr, d_addr, eight); - } + tcg_gen_concat_tl_i64(t8, lo, hi); + tcg_gen_concat_i64_i128(t16, t8, t8); + tcg_gen_andi_tl(daddr, addr, -32); + tcg_gen_qemu_st_i128(t16, daddr, da->mem_idx, mop); + tcg_gen_addi_tl(daddr, daddr, 16); + tcg_gen_qemu_st_i128(t16, daddr, da->mem_idx, mop); } break; From 388a6465957edea5759e727d5d54898fb4feba91 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Fri, 3 Nov 2023 10:38:22 -0700 Subject: [PATCH 38/58] target/sparc: Remove gen_dest_fpr_F MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Replace with tcg_temp_new_i32. Signed-off-by: Richard Henderson Reviewed-by: Philippe Mathieu-Daudé Tested-by: Mark Cave-Ayland Acked-by: Mark Cave-Ayland Message-Id: <20231103173841.33651-4-richard.henderson@linaro.org> --- target/sparc/translate.c | 17 ++++++----------- 1 file changed, 6 insertions(+), 11 deletions(-) diff --git a/target/sparc/translate.c b/target/sparc/translate.c index 3a59262c9a..6824b5d835 100644 --- a/target/sparc/translate.c +++ b/target/sparc/translate.c @@ -246,11 +246,6 @@ static void gen_store_fpr_F(DisasContext *dc, unsigned int dst, TCGv_i32 v) gen_update_fprs_dirty(dc, dst); } -static TCGv_i32 gen_dest_fpr_F(DisasContext *dc) -{ - return tcg_temp_new_i32(); -} - static TCGv_i64 gen_load_fpr_D(DisasContext *dc, unsigned int src) { src = DFPREG(src); @@ -1873,7 +1868,7 @@ static void gen_ldf_asi(DisasContext *dc, DisasASI *da, MemOp orig_size, memop |= MO_ALIGN_4; switch (size) { case MO_32: - d32 = gen_dest_fpr_F(dc); + d32 = tcg_temp_new_i32(); tcg_gen_qemu_ld_i32(d32, addr, da->mem_idx, memop); gen_store_fpr_F(dc, rd, d32); break; @@ -1938,7 +1933,7 @@ static void gen_ldf_asi(DisasContext *dc, DisasASI *da, MemOp orig_size, case MO_32: d64 = tcg_temp_new_i64(); gen_helper_ld_asi(d64, tcg_env, addr, r_asi, r_mop); - d32 = gen_dest_fpr_F(dc); + d32 = tcg_temp_new_i32(); tcg_gen_extrl_i64_i32(d32, d64); gen_store_fpr_F(dc, rd, d32); break; @@ -2228,7 +2223,7 @@ static void gen_fmovs(DisasContext *dc, DisasCompare *cmp, int rd, int rs) s1 = gen_load_fpr_F(dc, rs); s2 = gen_load_fpr_F(dc, rd); - dst = gen_dest_fpr_F(dc); + dst = tcg_temp_new_i32(); zero = tcg_constant_i32(0); tcg_gen_movcond_i32(TCG_COND_NE, dst, c32, zero, s1, s2); @@ -4497,7 +4492,7 @@ static bool do_fd(DisasContext *dc, arg_r_r *a, return true; } - dst = gen_dest_fpr_F(dc); + dst = tcg_temp_new_i32(); src = gen_load_fpr_D(dc, a->rs); func(dst, src); gen_store_fpr_F(dc, a->rd, dst); @@ -4539,7 +4534,7 @@ static bool do_env_fd(DisasContext *dc, arg_r_r *a, } gen_op_clear_ieee_excp_and_FTT(); - dst = gen_dest_fpr_F(dc); + dst = tcg_temp_new_i32(); src = gen_load_fpr_D(dc, a->rs); func(dst, tcg_env, src); gen_helper_check_ieee_exceptions(cpu_fsr, tcg_env); @@ -4697,7 +4692,7 @@ static bool do_env_fq(DisasContext *dc, arg_r_r *a, gen_op_clear_ieee_excp_and_FTT(); gen_op_load_fpr_QT1(QFPREG(a->rs)); - dst = gen_dest_fpr_F(dc); + dst = tcg_temp_new_i32(); func(dst, tcg_env); gen_helper_check_ieee_exceptions(cpu_fsr, tcg_env); gen_store_fpr_F(dc, a->rd, dst); From 33ec424535e2e8e5fa1fd78f691eb9c3c68fd449 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Fri, 3 Nov 2023 10:38:23 -0700 Subject: [PATCH 39/58] target/sparc: Introduce gen_{load,store}_fpr_Q MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Use them for trans_FMOVq. Signed-off-by: Richard Henderson Reviewed-by: Philippe Mathieu-Daudé Tested-by: Mark Cave-Ayland Acked-by: Mark Cave-Ayland Message-Id: <20231103173841.33651-5-richard.henderson@linaro.org> --- target/sparc/translate.c | 25 +++++++++++++++++++------ 1 file changed, 19 insertions(+), 6 deletions(-) diff --git a/target/sparc/translate.c b/target/sparc/translate.c index 6824b5d835..c68f6ca94e 100644 --- a/target/sparc/translate.c +++ b/target/sparc/translate.c @@ -264,6 +264,22 @@ static TCGv_i64 gen_dest_fpr_D(DisasContext *dc, unsigned int dst) return cpu_fpr[DFPREG(dst) / 2]; } +static TCGv_i128 gen_load_fpr_Q(DisasContext *dc, unsigned int src) +{ + TCGv_i128 ret = tcg_temp_new_i128(); + + src = QFPREG(src); + tcg_gen_concat_i64_i128(ret, cpu_fpr[src / 2 + 1], cpu_fpr[src / 2]); + return ret; +} + +static void gen_store_fpr_Q(DisasContext *dc, unsigned int dst, TCGv_i128 v) +{ + dst = DFPREG(dst); + tcg_gen_extr_i128_i64(cpu_fpr[dst / 2 + 1], cpu_fpr[dst / 2], v); + gen_update_fprs_dirty(dc, dst); +} + static void gen_op_load_fpr_QT0(unsigned int src) { tcg_gen_st_i64(cpu_fpr[src / 2], tcg_env, offsetof(CPUSPARCState, qt0) + @@ -4615,7 +4631,7 @@ TRANS(FsTOx, 64, do_env_df, a, gen_helper_fstox) static bool trans_FMOVq(DisasContext *dc, arg_FMOVq *a) { - int rd, rs; + TCGv_i128 t; if (!avail_64(dc)) { return false; @@ -4628,11 +4644,8 @@ static bool trans_FMOVq(DisasContext *dc, arg_FMOVq *a) } gen_op_clear_ieee_excp_and_FTT(); - rd = QFPREG(a->rd); - rs = QFPREG(a->rs); - tcg_gen_mov_i64(cpu_fpr[rd / 2], cpu_fpr[rs / 2]); - tcg_gen_mov_i64(cpu_fpr[rd / 2 + 1], cpu_fpr[rs / 2 + 1]); - gen_update_fprs_dirty(dc, rd); + t = gen_load_fpr_Q(dc, a->rs); + gen_store_fpr_Q(dc, a->rd, t); return advance_pc(dc); } From daf457d40f92dd5f957b206cc86d95d9c42350c6 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Fri, 3 Nov 2023 10:38:24 -0700 Subject: [PATCH 40/58] target/sparc: Inline FNEG, FABS MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit These are simple bit manipulation insns. Begin using i128 for float128. Implement FMOVq with do_qq. Signed-off-by: Richard Henderson Reviewed-by: Philippe Mathieu-Daudé Tested-by: Mark Cave-Ayland Acked-by: Mark Cave-Ayland Message-Id: <20231103173841.33651-6-richard.henderson@linaro.org> --- target/sparc/fop_helper.c | 34 --------------------- target/sparc/helper.h | 6 ---- target/sparc/translate.c | 62 +++++++++++++++++++-------------------- 3 files changed, 30 insertions(+), 72 deletions(-) diff --git a/target/sparc/fop_helper.c b/target/sparc/fop_helper.c index 0f8aa3abcd..d6fb769769 100644 --- a/target/sparc/fop_helper.c +++ b/target/sparc/fop_helper.c @@ -114,23 +114,6 @@ void helper_fdmulq(CPUSPARCState *env, float64 src1, float64 src2) &env->fp_status); } -float32 helper_fnegs(float32 src) -{ - return float32_chs(src); -} - -#ifdef TARGET_SPARC64 -float64 helper_fnegd(float64 src) -{ - return float64_chs(src); -} - -F_HELPER(neg, q) -{ - QT0 = float128_chs(QT1); -} -#endif - /* Integer to float conversion. */ float32 helper_fitos(CPUSPARCState *env, int32_t src) { @@ -229,23 +212,6 @@ int64_t helper_fqtox(CPUSPARCState *env) } #endif -float32 helper_fabss(float32 src) -{ - return float32_abs(src); -} - -#ifdef TARGET_SPARC64 -float64 helper_fabsd(float64 src) -{ - return float64_abs(src); -} - -void helper_fabsq(CPUSPARCState *env) -{ - QT0 = float128_abs(QT1); -} -#endif - float32 helper_fsqrts(CPUSPARCState *env, float32 src) { return float32_sqrt(src, &env->fp_status); diff --git a/target/sparc/helper.h b/target/sparc/helper.h index 55eff66283..74a1575d21 100644 --- a/target/sparc/helper.h +++ b/target/sparc/helper.h @@ -37,7 +37,6 @@ DEF_HELPER_FLAGS_5(st_asi, TCG_CALL_NO_WG, void, env, tl, i64, int, i32) #endif DEF_HELPER_FLAGS_1(check_ieee_exceptions, TCG_CALL_NO_WG, tl, env) DEF_HELPER_FLAGS_2(set_fsr, TCG_CALL_NO_RWG, void, env, tl) -DEF_HELPER_FLAGS_1(fabss, TCG_CALL_NO_RWG_SE, f32, f32) DEF_HELPER_FLAGS_2(fsqrts, TCG_CALL_NO_RWG, f32, env, f32) DEF_HELPER_FLAGS_2(fsqrtd, TCG_CALL_NO_RWG, f64, env, f64) DEF_HELPER_FLAGS_3(fcmps, TCG_CALL_NO_WG, tl, env, f32, f32) @@ -48,7 +47,6 @@ DEF_HELPER_FLAGS_1(fsqrtq, TCG_CALL_NO_RWG, void, env) DEF_HELPER_FLAGS_1(fcmpq, TCG_CALL_NO_WG, tl, env) DEF_HELPER_FLAGS_1(fcmpeq, TCG_CALL_NO_WG, tl, env) #ifdef TARGET_SPARC64 -DEF_HELPER_FLAGS_1(fabsd, TCG_CALL_NO_RWG_SE, f64, f64) DEF_HELPER_FLAGS_3(fcmps_fcc1, TCG_CALL_NO_WG, tl, env, f32, f32) DEF_HELPER_FLAGS_3(fcmps_fcc2, TCG_CALL_NO_WG, tl, env, f32, f32) DEF_HELPER_FLAGS_3(fcmps_fcc3, TCG_CALL_NO_WG, tl, env, f32, f32) @@ -61,7 +59,6 @@ DEF_HELPER_FLAGS_3(fcmpes_fcc3, TCG_CALL_NO_WG, tl, env, f32, f32) DEF_HELPER_FLAGS_3(fcmped_fcc1, TCG_CALL_NO_WG, tl, env, f64, f64) DEF_HELPER_FLAGS_3(fcmped_fcc2, TCG_CALL_NO_WG, tl, env, f64, f64) DEF_HELPER_FLAGS_3(fcmped_fcc3, TCG_CALL_NO_WG, tl, env, f64, f64) -DEF_HELPER_FLAGS_1(fabsq, TCG_CALL_NO_RWG, void, env) DEF_HELPER_FLAGS_1(fcmpq_fcc1, TCG_CALL_NO_WG, tl, env) DEF_HELPER_FLAGS_1(fcmpq_fcc2, TCG_CALL_NO_WG, tl, env) DEF_HELPER_FLAGS_1(fcmpq_fcc3, TCG_CALL_NO_WG, tl, env) @@ -90,15 +87,12 @@ DEF_HELPER_FLAGS_3(fdivs, TCG_CALL_NO_RWG, f32, env, f32, f32) DEF_HELPER_FLAGS_3(fsmuld, TCG_CALL_NO_RWG, f64, env, f32, f32) DEF_HELPER_FLAGS_3(fdmulq, TCG_CALL_NO_RWG, void, env, f64, f64) -DEF_HELPER_FLAGS_1(fnegs, TCG_CALL_NO_RWG_SE, f32, f32) DEF_HELPER_FLAGS_2(fitod, TCG_CALL_NO_RWG_SE, f64, env, s32) DEF_HELPER_FLAGS_2(fitoq, TCG_CALL_NO_RWG, void, env, s32) DEF_HELPER_FLAGS_2(fitos, TCG_CALL_NO_RWG, f32, env, s32) #ifdef TARGET_SPARC64 -DEF_HELPER_FLAGS_1(fnegd, TCG_CALL_NO_RWG_SE, f64, f64) -DEF_HELPER_FLAGS_1(fnegq, TCG_CALL_NO_RWG, void, env) DEF_HELPER_FLAGS_2(fxtos, TCG_CALL_NO_RWG, f32, env, s64) DEF_HELPER_FLAGS_2(fxtod, TCG_CALL_NO_RWG, f64, env, s64) DEF_HELPER_FLAGS_2(fxtoq, TCG_CALL_NO_RWG, void, env, s64) diff --git a/target/sparc/translate.c b/target/sparc/translate.c index c68f6ca94e..41952281dc 100644 --- a/target/sparc/translate.c +++ b/target/sparc/translate.c @@ -43,9 +43,7 @@ #else # define gen_helper_clear_softint(E, S) qemu_build_not_reached() # define gen_helper_done(E) qemu_build_not_reached() -# define gen_helper_fabsd(D, S) qemu_build_not_reached() # define gen_helper_flushw(E) qemu_build_not_reached() -# define gen_helper_fnegd(D, S) qemu_build_not_reached() # define gen_helper_rdccr(D, E) qemu_build_not_reached() # define gen_helper_rdcwp(D, E) qemu_build_not_reached() # define gen_helper_restored(E) qemu_build_not_reached() @@ -61,7 +59,6 @@ # define gen_helper_write_softint(E, S) qemu_build_not_reached() # define gen_helper_wrpil(E, S) qemu_build_not_reached() # define gen_helper_wrpstate(E, S) qemu_build_not_reached() -# define gen_helper_fabsq ({ qemu_build_not_reached(); NULL; }) # define gen_helper_fcmpeq16 ({ qemu_build_not_reached(); NULL; }) # define gen_helper_fcmpeq32 ({ qemu_build_not_reached(); NULL; }) # define gen_helper_fcmpgt16 ({ qemu_build_not_reached(); NULL; }) @@ -79,7 +76,6 @@ # define gen_helper_fmul8x16 ({ qemu_build_not_reached(); NULL; }) # define gen_helper_fmuld8sux16 ({ qemu_build_not_reached(); NULL; }) # define gen_helper_fmuld8ulx16 ({ qemu_build_not_reached(); NULL; }) -# define gen_helper_fnegq ({ qemu_build_not_reached(); NULL; }) # define gen_helper_fpmerge ({ qemu_build_not_reached(); NULL; }) # define gen_helper_fqtox ({ qemu_build_not_reached(); NULL; }) # define gen_helper_fstox ({ qemu_build_not_reached(); NULL; }) @@ -1239,13 +1235,13 @@ static void gen_op_fmovs(TCGv_i32 dst, TCGv_i32 src) static void gen_op_fnegs(TCGv_i32 dst, TCGv_i32 src) { gen_op_clear_ieee_excp_and_FTT(); - gen_helper_fnegs(dst, src); + tcg_gen_xori_i32(dst, src, 1u << 31); } static void gen_op_fabss(TCGv_i32 dst, TCGv_i32 src) { gen_op_clear_ieee_excp_and_FTT(); - gen_helper_fabss(dst, src); + tcg_gen_andi_i32(dst, src, ~(1u << 31)); } static void gen_op_fmovd(TCGv_i64 dst, TCGv_i64 src) @@ -1257,13 +1253,33 @@ static void gen_op_fmovd(TCGv_i64 dst, TCGv_i64 src) static void gen_op_fnegd(TCGv_i64 dst, TCGv_i64 src) { gen_op_clear_ieee_excp_and_FTT(); - gen_helper_fnegd(dst, src); + tcg_gen_xori_i64(dst, src, 1ull << 63); } static void gen_op_fabsd(TCGv_i64 dst, TCGv_i64 src) { gen_op_clear_ieee_excp_and_FTT(); - gen_helper_fabsd(dst, src); + tcg_gen_andi_i64(dst, src, ~(1ull << 63)); +} + +static void gen_op_fnegq(TCGv_i128 dst, TCGv_i128 src) +{ + TCGv_i64 l = tcg_temp_new_i64(); + TCGv_i64 h = tcg_temp_new_i64(); + + tcg_gen_extr_i128_i64(l, h, src); + tcg_gen_xori_i64(h, h, 1ull << 63); + tcg_gen_concat_i64_i128(dst, l, h); +} + +static void gen_op_fabsq(TCGv_i128 dst, TCGv_i128 src) +{ + TCGv_i64 l = tcg_temp_new_i64(); + TCGv_i64 h = tcg_temp_new_i64(); + + tcg_gen_extr_i128_i64(l, h, src); + tcg_gen_andi_i64(h, h, ~(1ull << 63)); + tcg_gen_concat_i64_i128(dst, l, h); } #ifdef TARGET_SPARC64 @@ -4629,13 +4645,11 @@ TRANS(FiTOd, ALL, do_env_df, a, gen_helper_fitod) TRANS(FsTOd, ALL, do_env_df, a, gen_helper_fstod) TRANS(FsTOx, 64, do_env_df, a, gen_helper_fstox) -static bool trans_FMOVq(DisasContext *dc, arg_FMOVq *a) +static bool do_qq(DisasContext *dc, arg_r_r *a, + void (*func)(TCGv_i128, TCGv_i128)) { TCGv_i128 t; - if (!avail_64(dc)) { - return false; - } if (gen_trap_ifnofpu(dc)) { return true; } @@ -4645,30 +4659,14 @@ static bool trans_FMOVq(DisasContext *dc, arg_FMOVq *a) gen_op_clear_ieee_excp_and_FTT(); t = gen_load_fpr_Q(dc, a->rs); + func(t, t); gen_store_fpr_Q(dc, a->rd, t); return advance_pc(dc); } -static bool do_qq(DisasContext *dc, arg_r_r *a, - void (*func)(TCGv_env)) -{ - if (gen_trap_ifnofpu(dc)) { - return true; - } - if (gen_trap_float128(dc)) { - return true; - } - - gen_op_clear_ieee_excp_and_FTT(); - gen_op_load_fpr_QT1(QFPREG(a->rs)); - func(tcg_env); - gen_op_store_QT0_fpr(QFPREG(a->rd)); - gen_update_fprs_dirty(dc, QFPREG(a->rd)); - return advance_pc(dc); -} - -TRANS(FNEGq, 64, do_qq, a, gen_helper_fnegq) -TRANS(FABSq, 64, do_qq, a, gen_helper_fabsq) +TRANS(FMOVq, 64, do_qq, a, tcg_gen_mov_i128) +TRANS(FNEGq, 64, do_qq, a, gen_op_fnegq) +TRANS(FABSq, 64, do_qq, a, gen_op_fabsq) static bool do_env_qq(DisasContext *dc, arg_r_r *a, void (*func)(TCGv_env)) From e41716be4db43446f7dd1688f66e9c27d2dace31 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Fri, 3 Nov 2023 10:38:25 -0700 Subject: [PATCH 41/58] target/sparc: Use i128 for FSQRTq Signed-off-by: Richard Henderson Tested-by: Mark Cave-Ayland Acked-by: Mark Cave-Ayland Message-Id: <20231103173841.33651-7-richard.henderson@linaro.org> --- target/sparc/fop_helper.c | 26 ++++++++++++++++++++++++-- target/sparc/helper.h | 2 +- target/sparc/translate.c | 12 +++++++----- 3 files changed, 32 insertions(+), 8 deletions(-) diff --git a/target/sparc/fop_helper.c b/target/sparc/fop_helper.c index d6fb769769..d639e50965 100644 --- a/target/sparc/fop_helper.c +++ b/target/sparc/fop_helper.c @@ -26,6 +26,28 @@ #define QT0 (env->qt0) #define QT1 (env->qt1) +static inline float128 f128_in(Int128 i) +{ + union { + Int128 i; + float128 f; + } u; + + u.i = i; + return u.f; +} + +static inline Int128 f128_ret(float128 f) +{ + union { + Int128 i; + float128 f; + } u; + + u.f = f; + return u.i; +} + static target_ulong do_check_ieee_exceptions(CPUSPARCState *env, uintptr_t ra) { target_ulong status = get_float_exception_flags(&env->fp_status); @@ -222,9 +244,9 @@ float64 helper_fsqrtd(CPUSPARCState *env, float64 src) return float64_sqrt(src, &env->fp_status); } -void helper_fsqrtq(CPUSPARCState *env) +Int128 helper_fsqrtq(CPUSPARCState *env, Int128 src) { - QT0 = float128_sqrt(QT1, &env->fp_status); + return f128_ret(float128_sqrt(f128_in(src), &env->fp_status)); } #define GEN_FCMP(name, size, reg1, reg2, FS, E) \ diff --git a/target/sparc/helper.h b/target/sparc/helper.h index 74a1575d21..eea2fa570c 100644 --- a/target/sparc/helper.h +++ b/target/sparc/helper.h @@ -43,7 +43,7 @@ DEF_HELPER_FLAGS_3(fcmps, TCG_CALL_NO_WG, tl, env, f32, f32) DEF_HELPER_FLAGS_3(fcmpd, TCG_CALL_NO_WG, tl, env, f64, f64) DEF_HELPER_FLAGS_3(fcmpes, TCG_CALL_NO_WG, tl, env, f32, f32) DEF_HELPER_FLAGS_3(fcmped, TCG_CALL_NO_WG, tl, env, f64, f64) -DEF_HELPER_FLAGS_1(fsqrtq, TCG_CALL_NO_RWG, void, env) +DEF_HELPER_FLAGS_2(fsqrtq, TCG_CALL_NO_RWG, i128, env, i128) DEF_HELPER_FLAGS_1(fcmpq, TCG_CALL_NO_WG, tl, env) DEF_HELPER_FLAGS_1(fcmpeq, TCG_CALL_NO_WG, tl, env) #ifdef TARGET_SPARC64 diff --git a/target/sparc/translate.c b/target/sparc/translate.c index 41952281dc..ca98565c16 100644 --- a/target/sparc/translate.c +++ b/target/sparc/translate.c @@ -4669,8 +4669,10 @@ TRANS(FNEGq, 64, do_qq, a, gen_op_fnegq) TRANS(FABSq, 64, do_qq, a, gen_op_fabsq) static bool do_env_qq(DisasContext *dc, arg_r_r *a, - void (*func)(TCGv_env)) + void (*func)(TCGv_i128, TCGv_env, TCGv_i128)) { + TCGv_i128 t; + if (gen_trap_ifnofpu(dc)) { return true; } @@ -4679,11 +4681,11 @@ static bool do_env_qq(DisasContext *dc, arg_r_r *a, } gen_op_clear_ieee_excp_and_FTT(); - gen_op_load_fpr_QT1(QFPREG(a->rs)); - func(tcg_env); + + t = gen_load_fpr_Q(dc, a->rs); + func(t, tcg_env, t); gen_helper_check_ieee_exceptions(cpu_fsr, tcg_env); - gen_op_store_QT0_fpr(QFPREG(a->rd)); - gen_update_fprs_dirty(dc, QFPREG(a->rd)); + gen_store_fpr_Q(dc, a->rd, t); return advance_pc(dc); } From 16bedf89c1d5511e883a4b7ba41fc327ce1ccadb Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Fri, 3 Nov 2023 10:38:26 -0700 Subject: [PATCH 42/58] target/sparc: Use i128 for FADDq, FSUBq, FMULq, FDIVq Signed-off-by: Richard Henderson Tested-by: Mark Cave-Ayland Acked-by: Mark Cave-Ayland Message-Id: <20231103173841.33651-8-richard.henderson@linaro.org> --- target/sparc/fop_helper.c | 29 ++++++++++++++--------------- target/sparc/helper.h | 12 +++++------- target/sparc/translate.c | 13 +++++++------ 3 files changed, 26 insertions(+), 28 deletions(-) diff --git a/target/sparc/fop_helper.c b/target/sparc/fop_helper.c index d639e50965..ceb64d802f 100644 --- a/target/sparc/fop_helper.c +++ b/target/sparc/fop_helper.c @@ -98,22 +98,22 @@ target_ulong helper_check_ieee_exceptions(CPUSPARCState *env) return do_check_ieee_exceptions(env, GETPC()); } -#define F_HELPER(name, p) void helper_f##name##p(CPUSPARCState *env) - -#define F_BINOP(name) \ +#define F_BINOP(name) \ float32 helper_f ## name ## s (CPUSPARCState *env, float32 src1, \ - float32 src2) \ - { \ - return float32_ ## name (src1, src2, &env->fp_status); \ - } \ + float32 src2) \ + { \ + return float32_ ## name (src1, src2, &env->fp_status); \ + } \ float64 helper_f ## name ## d (CPUSPARCState * env, float64 src1,\ - float64 src2) \ - { \ - return float64_ ## name (src1, src2, &env->fp_status); \ - } \ - F_HELPER(name, q) \ - { \ - QT0 = float128_ ## name (QT0, QT1, &env->fp_status); \ + float64 src2) \ + { \ + return float64_ ## name (src1, src2, &env->fp_status); \ + } \ + Int128 helper_f ## name ## q(CPUSPARCState * env, Int128 src1, \ + Int128 src2) \ + { \ + return f128_ret(float128_ ## name (f128_in(src1), f128_in(src2), \ + &env->fp_status)); \ } F_BINOP(add); @@ -168,7 +168,6 @@ void helper_fxtoq(CPUSPARCState *env, int64_t src) QT0 = int64_to_float128(src, &env->fp_status); } #endif -#undef F_HELPER /* floating point conversion */ float32 helper_fdtos(CPUSPARCState *env, float64 src) diff --git a/target/sparc/helper.h b/target/sparc/helper.h index eea2fa570c..0a030fc908 100644 --- a/target/sparc/helper.h +++ b/target/sparc/helper.h @@ -67,17 +67,16 @@ DEF_HELPER_FLAGS_1(fcmpeq_fcc2, TCG_CALL_NO_WG, tl, env) DEF_HELPER_FLAGS_1(fcmpeq_fcc3, TCG_CALL_NO_WG, tl, env) #endif DEF_HELPER_2(raise_exception, noreturn, env, int) -#define F_HELPER_0_1(name) \ - DEF_HELPER_FLAGS_1(f ## name, TCG_CALL_NO_RWG, void, env) DEF_HELPER_FLAGS_3(faddd, TCG_CALL_NO_RWG, f64, env, f64, f64) DEF_HELPER_FLAGS_3(fsubd, TCG_CALL_NO_RWG, f64, env, f64, f64) DEF_HELPER_FLAGS_3(fmuld, TCG_CALL_NO_RWG, f64, env, f64, f64) DEF_HELPER_FLAGS_3(fdivd, TCG_CALL_NO_RWG, f64, env, f64, f64) -F_HELPER_0_1(addq) -F_HELPER_0_1(subq) -F_HELPER_0_1(mulq) -F_HELPER_0_1(divq) + +DEF_HELPER_FLAGS_3(faddq, TCG_CALL_NO_RWG, i128, env, i128, i128) +DEF_HELPER_FLAGS_3(fsubq, TCG_CALL_NO_RWG, i128, env, i128, i128) +DEF_HELPER_FLAGS_3(fmulq, TCG_CALL_NO_RWG, i128, env, i128, i128) +DEF_HELPER_FLAGS_3(fdivq, TCG_CALL_NO_RWG, i128, env, i128, i128) DEF_HELPER_FLAGS_3(fadds, TCG_CALL_NO_RWG, f32, env, f32, f32) DEF_HELPER_FLAGS_3(fsubs, TCG_CALL_NO_RWG, f32, env, f32, f32) @@ -135,6 +134,5 @@ VIS_CMPHELPER(cmpeq) VIS_CMPHELPER(cmple) VIS_CMPHELPER(cmpne) #endif -#undef F_HELPER_0_1 #undef VIS_HELPER #undef VIS_CMPHELPER diff --git a/target/sparc/translate.c b/target/sparc/translate.c index ca98565c16..96aa7ed235 100644 --- a/target/sparc/translate.c +++ b/target/sparc/translate.c @@ -4976,8 +4976,10 @@ static bool do_dddd(DisasContext *dc, arg_r_r_r *a, TRANS(PDIST, VIS1, do_dddd, a, gen_helper_pdist) static bool do_env_qqq(DisasContext *dc, arg_r_r_r *a, - void (*func)(TCGv_env)) + void (*func)(TCGv_i128, TCGv_env, TCGv_i128, TCGv_i128)) { + TCGv_i128 src1, src2; + if (gen_trap_ifnofpu(dc)) { return true; } @@ -4986,12 +4988,11 @@ static bool do_env_qqq(DisasContext *dc, arg_r_r_r *a, } gen_op_clear_ieee_excp_and_FTT(); - gen_op_load_fpr_QT0(QFPREG(a->rs1)); - gen_op_load_fpr_QT1(QFPREG(a->rs2)); - func(tcg_env); + src1 = gen_load_fpr_Q(dc, a->rs1); + src2 = gen_load_fpr_Q(dc, a->rs2); + func(src1, tcg_env, src1, src2); gen_helper_check_ieee_exceptions(cpu_fsr, tcg_env); - gen_op_store_QT0_fpr(QFPREG(a->rd)); - gen_update_fprs_dirty(dc, QFPREG(a->rd)); + gen_store_fpr_Q(dc, a->rd, src1); return advance_pc(dc); } From d81e3efed9c9c487c86bb834ab74302c643a703b Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Fri, 3 Nov 2023 10:38:27 -0700 Subject: [PATCH 43/58] target/sparc: Use i128 for FqTOs, FqTOi Signed-off-by: Richard Henderson Tested-by: Mark Cave-Ayland Acked-by: Mark Cave-Ayland Message-Id: <20231103173841.33651-9-richard.henderson@linaro.org> --- target/sparc/fop_helper.c | 8 ++++---- target/sparc/helper.h | 4 ++-- target/sparc/translate.c | 7 ++++--- 3 files changed, 10 insertions(+), 9 deletions(-) diff --git a/target/sparc/fop_helper.c b/target/sparc/fop_helper.c index ceb64d802f..657a14575d 100644 --- a/target/sparc/fop_helper.c +++ b/target/sparc/fop_helper.c @@ -180,9 +180,9 @@ float64 helper_fstod(CPUSPARCState *env, float32 src) return float32_to_float64(src, &env->fp_status); } -float32 helper_fqtos(CPUSPARCState *env) +float32 helper_fqtos(CPUSPARCState *env, Int128 src) { - return float128_to_float32(QT1, &env->fp_status); + return float128_to_float32(f128_in(src), &env->fp_status); } void helper_fstoq(CPUSPARCState *env, float32 src) @@ -211,9 +211,9 @@ int32_t helper_fdtoi(CPUSPARCState *env, float64 src) return float64_to_int32_round_to_zero(src, &env->fp_status); } -int32_t helper_fqtoi(CPUSPARCState *env) +int32_t helper_fqtoi(CPUSPARCState *env, Int128 src) { - return float128_to_int32_round_to_zero(QT1, &env->fp_status); + return float128_to_int32_round_to_zero(f128_in(src), &env->fp_status); } #ifdef TARGET_SPARC64 diff --git a/target/sparc/helper.h b/target/sparc/helper.h index 0a030fc908..e770107eb0 100644 --- a/target/sparc/helper.h +++ b/target/sparc/helper.h @@ -98,13 +98,13 @@ DEF_HELPER_FLAGS_2(fxtoq, TCG_CALL_NO_RWG, void, env, s64) #endif DEF_HELPER_FLAGS_2(fdtos, TCG_CALL_NO_RWG, f32, env, f64) DEF_HELPER_FLAGS_2(fstod, TCG_CALL_NO_RWG, f64, env, f32) -DEF_HELPER_FLAGS_1(fqtos, TCG_CALL_NO_RWG, f32, env) +DEF_HELPER_FLAGS_2(fqtos, TCG_CALL_NO_RWG, f32, env, i128) DEF_HELPER_FLAGS_2(fstoq, TCG_CALL_NO_RWG, void, env, f32) DEF_HELPER_FLAGS_1(fqtod, TCG_CALL_NO_RWG, f64, env) DEF_HELPER_FLAGS_2(fdtoq, TCG_CALL_NO_RWG, void, env, f64) DEF_HELPER_FLAGS_2(fstoi, TCG_CALL_NO_RWG, s32, env, f32) DEF_HELPER_FLAGS_2(fdtoi, TCG_CALL_NO_RWG, s32, env, f64) -DEF_HELPER_FLAGS_1(fqtoi, TCG_CALL_NO_RWG, s32, env) +DEF_HELPER_FLAGS_2(fqtoi, TCG_CALL_NO_RWG, s32, env, i128) #ifdef TARGET_SPARC64 DEF_HELPER_FLAGS_2(fstox, TCG_CALL_NO_RWG, s64, env, f32) DEF_HELPER_FLAGS_2(fdtox, TCG_CALL_NO_RWG, s64, env, f64) diff --git a/target/sparc/translate.c b/target/sparc/translate.c index 96aa7ed235..f70efb29a1 100644 --- a/target/sparc/translate.c +++ b/target/sparc/translate.c @@ -4692,8 +4692,9 @@ static bool do_env_qq(DisasContext *dc, arg_r_r *a, TRANS(FSQRTq, ALL, do_env_qq, a, gen_helper_fsqrtq) static bool do_env_fq(DisasContext *dc, arg_r_r *a, - void (*func)(TCGv_i32, TCGv_env)) + void (*func)(TCGv_i32, TCGv_env, TCGv_i128)) { + TCGv_i128 src; TCGv_i32 dst; if (gen_trap_ifnofpu(dc)) { @@ -4704,9 +4705,9 @@ static bool do_env_fq(DisasContext *dc, arg_r_r *a, } gen_op_clear_ieee_excp_and_FTT(); - gen_op_load_fpr_QT1(QFPREG(a->rs)); + src = gen_load_fpr_Q(dc, a->rs); dst = tcg_temp_new_i32(); - func(dst, tcg_env); + func(dst, tcg_env, src); gen_helper_check_ieee_exceptions(cpu_fsr, tcg_env); gen_store_fpr_F(dc, a->rd, dst); return advance_pc(dc); From 25a5769e3b0da1c1f69e93af1ace8f7b5d0cd238 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Fri, 3 Nov 2023 10:38:28 -0700 Subject: [PATCH 44/58] target/sparc: Use i128 for FqTOd, FqTOx Signed-off-by: Richard Henderson Tested-by: Mark Cave-Ayland Acked-by: Mark Cave-Ayland Message-Id: <20231103173841.33651-10-richard.henderson@linaro.org> --- target/sparc/fop_helper.c | 8 ++++---- target/sparc/helper.h | 4 ++-- target/sparc/translate.c | 7 ++++--- 3 files changed, 10 insertions(+), 9 deletions(-) diff --git a/target/sparc/fop_helper.c b/target/sparc/fop_helper.c index 657a14575d..9f39b933e8 100644 --- a/target/sparc/fop_helper.c +++ b/target/sparc/fop_helper.c @@ -190,9 +190,9 @@ void helper_fstoq(CPUSPARCState *env, float32 src) QT0 = float32_to_float128(src, &env->fp_status); } -float64 helper_fqtod(CPUSPARCState *env) +float64 helper_fqtod(CPUSPARCState *env, Int128 src) { - return float128_to_float64(QT1, &env->fp_status); + return float128_to_float64(f128_in(src), &env->fp_status); } void helper_fdtoq(CPUSPARCState *env, float64 src) @@ -227,9 +227,9 @@ int64_t helper_fdtox(CPUSPARCState *env, float64 src) return float64_to_int64_round_to_zero(src, &env->fp_status); } -int64_t helper_fqtox(CPUSPARCState *env) +int64_t helper_fqtox(CPUSPARCState *env, Int128 src) { - return float128_to_int64_round_to_zero(QT1, &env->fp_status); + return float128_to_int64_round_to_zero(f128_in(src), &env->fp_status); } #endif diff --git a/target/sparc/helper.h b/target/sparc/helper.h index e770107eb0..4cb3451878 100644 --- a/target/sparc/helper.h +++ b/target/sparc/helper.h @@ -100,7 +100,7 @@ DEF_HELPER_FLAGS_2(fdtos, TCG_CALL_NO_RWG, f32, env, f64) DEF_HELPER_FLAGS_2(fstod, TCG_CALL_NO_RWG, f64, env, f32) DEF_HELPER_FLAGS_2(fqtos, TCG_CALL_NO_RWG, f32, env, i128) DEF_HELPER_FLAGS_2(fstoq, TCG_CALL_NO_RWG, void, env, f32) -DEF_HELPER_FLAGS_1(fqtod, TCG_CALL_NO_RWG, f64, env) +DEF_HELPER_FLAGS_2(fqtod, TCG_CALL_NO_RWG, f64, env, i128) DEF_HELPER_FLAGS_2(fdtoq, TCG_CALL_NO_RWG, void, env, f64) DEF_HELPER_FLAGS_2(fstoi, TCG_CALL_NO_RWG, s32, env, f32) DEF_HELPER_FLAGS_2(fdtoi, TCG_CALL_NO_RWG, s32, env, f64) @@ -108,7 +108,7 @@ DEF_HELPER_FLAGS_2(fqtoi, TCG_CALL_NO_RWG, s32, env, i128) #ifdef TARGET_SPARC64 DEF_HELPER_FLAGS_2(fstox, TCG_CALL_NO_RWG, s64, env, f32) DEF_HELPER_FLAGS_2(fdtox, TCG_CALL_NO_RWG, s64, env, f64) -DEF_HELPER_FLAGS_1(fqtox, TCG_CALL_NO_RWG, s64, env) +DEF_HELPER_FLAGS_2(fqtox, TCG_CALL_NO_RWG, s64, env, i128) DEF_HELPER_FLAGS_2(fpmerge, TCG_CALL_NO_RWG_SE, i64, i64, i64) DEF_HELPER_FLAGS_2(fmul8x16, TCG_CALL_NO_RWG_SE, i64, i64, i64) diff --git a/target/sparc/translate.c b/target/sparc/translate.c index f70efb29a1..6f75f4d5d6 100644 --- a/target/sparc/translate.c +++ b/target/sparc/translate.c @@ -4717,8 +4717,9 @@ TRANS(FqTOs, ALL, do_env_fq, a, gen_helper_fqtos) TRANS(FqTOi, ALL, do_env_fq, a, gen_helper_fqtoi) static bool do_env_dq(DisasContext *dc, arg_r_r *a, - void (*func)(TCGv_i64, TCGv_env)) + void (*func)(TCGv_i64, TCGv_env, TCGv_i128)) { + TCGv_i128 src; TCGv_i64 dst; if (gen_trap_ifnofpu(dc)) { @@ -4729,9 +4730,9 @@ static bool do_env_dq(DisasContext *dc, arg_r_r *a, } gen_op_clear_ieee_excp_and_FTT(); - gen_op_load_fpr_QT1(QFPREG(a->rs)); + src = gen_load_fpr_Q(dc, a->rs); dst = gen_dest_fpr_D(dc, a->rd); - func(dst, tcg_env); + func(dst, tcg_env, src); gen_helper_check_ieee_exceptions(cpu_fsr, tcg_env); gen_store_fpr_D(dc, a->rd, dst); return advance_pc(dc); From f3ceafad5e30891207282f18ad6c4e22d8902e6f Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Fri, 3 Nov 2023 10:38:29 -0700 Subject: [PATCH 45/58] target/sparc: Use i128 for FCMPq, FCMPEq Signed-off-by: Richard Henderson Tested-by: Mark Cave-Ayland Acked-by: Mark Cave-Ayland Message-Id: <20231103173841.33651-11-richard.henderson@linaro.org> --- target/sparc/fop_helper.c | 23 +++++++++-------- target/sparc/helper.h | 16 ++++++------ target/sparc/translate.c | 54 +++++++++++++++------------------------ 3 files changed, 41 insertions(+), 52 deletions(-) diff --git a/target/sparc/fop_helper.c b/target/sparc/fop_helper.c index 9f39b933e8..faf75e651f 100644 --- a/target/sparc/fop_helper.c +++ b/target/sparc/fop_helper.c @@ -248,9 +248,12 @@ Int128 helper_fsqrtq(CPUSPARCState *env, Int128 src) return f128_ret(float128_sqrt(f128_in(src), &env->fp_status)); } -#define GEN_FCMP(name, size, reg1, reg2, FS, E) \ - target_ulong glue(helper_, name) (CPUSPARCState *env) \ +#define GEN_FCMP(name, size, FS, E) \ + target_ulong glue(helper_, name) (CPUSPARCState *env, \ + Int128 src1, Int128 src2) \ { \ + float128 reg1 = f128_in(src1); \ + float128 reg2 = f128_in(src2); \ FloatRelation ret; \ target_ulong fsr; \ if (E) { \ @@ -316,33 +319,33 @@ GEN_FCMP_T(fcmpd, float64, 0, 0); GEN_FCMP_T(fcmpes, float32, 0, 1); GEN_FCMP_T(fcmped, float64, 0, 1); -GEN_FCMP(fcmpq, float128, QT0, QT1, 0, 0); -GEN_FCMP(fcmpeq, float128, QT0, QT1, 0, 1); +GEN_FCMP(fcmpq, float128, 0, 0); +GEN_FCMP(fcmpeq, float128, 0, 1); #ifdef TARGET_SPARC64 GEN_FCMP_T(fcmps_fcc1, float32, 22, 0); GEN_FCMP_T(fcmpd_fcc1, float64, 22, 0); -GEN_FCMP(fcmpq_fcc1, float128, QT0, QT1, 22, 0); +GEN_FCMP(fcmpq_fcc1, float128, 22, 0); GEN_FCMP_T(fcmps_fcc2, float32, 24, 0); GEN_FCMP_T(fcmpd_fcc2, float64, 24, 0); -GEN_FCMP(fcmpq_fcc2, float128, QT0, QT1, 24, 0); +GEN_FCMP(fcmpq_fcc2, float128, 24, 0); GEN_FCMP_T(fcmps_fcc3, float32, 26, 0); GEN_FCMP_T(fcmpd_fcc3, float64, 26, 0); -GEN_FCMP(fcmpq_fcc3, float128, QT0, QT1, 26, 0); +GEN_FCMP(fcmpq_fcc3, float128, 26, 0); GEN_FCMP_T(fcmpes_fcc1, float32, 22, 1); GEN_FCMP_T(fcmped_fcc1, float64, 22, 1); -GEN_FCMP(fcmpeq_fcc1, float128, QT0, QT1, 22, 1); +GEN_FCMP(fcmpeq_fcc1, float128, 22, 1); GEN_FCMP_T(fcmpes_fcc2, float32, 24, 1); GEN_FCMP_T(fcmped_fcc2, float64, 24, 1); -GEN_FCMP(fcmpeq_fcc2, float128, QT0, QT1, 24, 1); +GEN_FCMP(fcmpeq_fcc2, float128, 24, 1); GEN_FCMP_T(fcmpes_fcc3, float32, 26, 1); GEN_FCMP_T(fcmped_fcc3, float64, 26, 1); -GEN_FCMP(fcmpeq_fcc3, float128, QT0, QT1, 26, 1); +GEN_FCMP(fcmpeq_fcc3, float128, 26, 1); #endif #undef GEN_FCMP_T #undef GEN_FCMP diff --git a/target/sparc/helper.h b/target/sparc/helper.h index 4cb3451878..7caae9a441 100644 --- a/target/sparc/helper.h +++ b/target/sparc/helper.h @@ -44,8 +44,8 @@ DEF_HELPER_FLAGS_3(fcmpd, TCG_CALL_NO_WG, tl, env, f64, f64) DEF_HELPER_FLAGS_3(fcmpes, TCG_CALL_NO_WG, tl, env, f32, f32) DEF_HELPER_FLAGS_3(fcmped, TCG_CALL_NO_WG, tl, env, f64, f64) DEF_HELPER_FLAGS_2(fsqrtq, TCG_CALL_NO_RWG, i128, env, i128) -DEF_HELPER_FLAGS_1(fcmpq, TCG_CALL_NO_WG, tl, env) -DEF_HELPER_FLAGS_1(fcmpeq, TCG_CALL_NO_WG, tl, env) +DEF_HELPER_FLAGS_3(fcmpq, TCG_CALL_NO_WG, tl, env, i128, i128) +DEF_HELPER_FLAGS_3(fcmpeq, TCG_CALL_NO_WG, tl, env, i128, i128) #ifdef TARGET_SPARC64 DEF_HELPER_FLAGS_3(fcmps_fcc1, TCG_CALL_NO_WG, tl, env, f32, f32) DEF_HELPER_FLAGS_3(fcmps_fcc2, TCG_CALL_NO_WG, tl, env, f32, f32) @@ -59,12 +59,12 @@ DEF_HELPER_FLAGS_3(fcmpes_fcc3, TCG_CALL_NO_WG, tl, env, f32, f32) DEF_HELPER_FLAGS_3(fcmped_fcc1, TCG_CALL_NO_WG, tl, env, f64, f64) DEF_HELPER_FLAGS_3(fcmped_fcc2, TCG_CALL_NO_WG, tl, env, f64, f64) DEF_HELPER_FLAGS_3(fcmped_fcc3, TCG_CALL_NO_WG, tl, env, f64, f64) -DEF_HELPER_FLAGS_1(fcmpq_fcc1, TCG_CALL_NO_WG, tl, env) -DEF_HELPER_FLAGS_1(fcmpq_fcc2, TCG_CALL_NO_WG, tl, env) -DEF_HELPER_FLAGS_1(fcmpq_fcc3, TCG_CALL_NO_WG, tl, env) -DEF_HELPER_FLAGS_1(fcmpeq_fcc1, TCG_CALL_NO_WG, tl, env) -DEF_HELPER_FLAGS_1(fcmpeq_fcc2, TCG_CALL_NO_WG, tl, env) -DEF_HELPER_FLAGS_1(fcmpeq_fcc3, TCG_CALL_NO_WG, tl, env) +DEF_HELPER_FLAGS_3(fcmpq_fcc1, TCG_CALL_NO_WG, tl, env, i128, i128) +DEF_HELPER_FLAGS_3(fcmpq_fcc2, TCG_CALL_NO_WG, tl, env, i128, i128) +DEF_HELPER_FLAGS_3(fcmpq_fcc3, TCG_CALL_NO_WG, tl, env, i128, i128) +DEF_HELPER_FLAGS_3(fcmpeq_fcc1, TCG_CALL_NO_WG, tl, env, i128, i128) +DEF_HELPER_FLAGS_3(fcmpeq_fcc2, TCG_CALL_NO_WG, tl, env, i128, i128) +DEF_HELPER_FLAGS_3(fcmpeq_fcc3, TCG_CALL_NO_WG, tl, env, i128, i128) #endif DEF_HELPER_2(raise_exception, noreturn, env, int) diff --git a/target/sparc/translate.c b/target/sparc/translate.c index 6f75f4d5d6..6c003eed7c 100644 --- a/target/sparc/translate.c +++ b/target/sparc/translate.c @@ -276,22 +276,6 @@ static void gen_store_fpr_Q(DisasContext *dc, unsigned int dst, TCGv_i128 v) gen_update_fprs_dirty(dc, dst); } -static void gen_op_load_fpr_QT0(unsigned int src) -{ - tcg_gen_st_i64(cpu_fpr[src / 2], tcg_env, offsetof(CPUSPARCState, qt0) + - offsetof(CPU_QuadU, ll.upper)); - tcg_gen_st_i64(cpu_fpr[src/2 + 1], tcg_env, offsetof(CPUSPARCState, qt0) + - offsetof(CPU_QuadU, ll.lower)); -} - -static void gen_op_load_fpr_QT1(unsigned int src) -{ - tcg_gen_st_i64(cpu_fpr[src / 2], tcg_env, offsetof(CPUSPARCState, qt1) + - offsetof(CPU_QuadU, ll.upper)); - tcg_gen_st_i64(cpu_fpr[src/2 + 1], tcg_env, offsetof(CPUSPARCState, qt1) + - offsetof(CPU_QuadU, ll.lower)); -} - static void gen_op_store_QT0_fpr(unsigned int dst) { tcg_gen_ld_i64(cpu_fpr[dst / 2], tcg_env, offsetof(CPUSPARCState, qt0) + @@ -1319,20 +1303,20 @@ static void gen_op_fcmpd(int fccno, TCGv_i64 r_rs1, TCGv_i64 r_rs2) } } -static void gen_op_fcmpq(int fccno) +static void gen_op_fcmpq(int fccno, TCGv_i128 r_rs1, TCGv_i128 r_rs2) { switch (fccno) { case 0: - gen_helper_fcmpq(cpu_fsr, tcg_env); + gen_helper_fcmpq(cpu_fsr, tcg_env, r_rs1, r_rs2); break; case 1: - gen_helper_fcmpq_fcc1(cpu_fsr, tcg_env); + gen_helper_fcmpq_fcc1(cpu_fsr, tcg_env, r_rs1, r_rs2); break; case 2: - gen_helper_fcmpq_fcc2(cpu_fsr, tcg_env); + gen_helper_fcmpq_fcc2(cpu_fsr, tcg_env, r_rs1, r_rs2); break; case 3: - gen_helper_fcmpq_fcc3(cpu_fsr, tcg_env); + gen_helper_fcmpq_fcc3(cpu_fsr, tcg_env, r_rs1, r_rs2); break; } } @@ -1373,20 +1357,20 @@ static void gen_op_fcmped(int fccno, TCGv_i64 r_rs1, TCGv_i64 r_rs2) } } -static void gen_op_fcmpeq(int fccno) +static void gen_op_fcmpeq(int fccno, TCGv_i128 r_rs1, TCGv_i128 r_rs2) { switch (fccno) { case 0: - gen_helper_fcmpeq(cpu_fsr, tcg_env); + gen_helper_fcmpeq(cpu_fsr, tcg_env, r_rs1, r_rs2); break; case 1: - gen_helper_fcmpeq_fcc1(cpu_fsr, tcg_env); + gen_helper_fcmpeq_fcc1(cpu_fsr, tcg_env, r_rs1, r_rs2); break; case 2: - gen_helper_fcmpeq_fcc2(cpu_fsr, tcg_env); + gen_helper_fcmpeq_fcc2(cpu_fsr, tcg_env, r_rs1, r_rs2); break; case 3: - gen_helper_fcmpeq_fcc3(cpu_fsr, tcg_env); + gen_helper_fcmpeq_fcc3(cpu_fsr, tcg_env, r_rs1, r_rs2); break; } } @@ -1403,9 +1387,9 @@ static void gen_op_fcmpd(int fccno, TCGv_i64 r_rs1, TCGv_i64 r_rs2) gen_helper_fcmpd(cpu_fsr, tcg_env, r_rs1, r_rs2); } -static void gen_op_fcmpq(int fccno) +static void gen_op_fcmpq(int fccno, TCGv_i128 r_rs1, TCGv_i128 r_rs2) { - gen_helper_fcmpq(cpu_fsr, tcg_env); + gen_helper_fcmpq(cpu_fsr, tcg_env, r_rs1, r_rs2); } static void gen_op_fcmpes(int fccno, TCGv r_rs1, TCGv r_rs2) @@ -1418,9 +1402,9 @@ static void gen_op_fcmped(int fccno, TCGv_i64 r_rs1, TCGv_i64 r_rs2) gen_helper_fcmped(cpu_fsr, tcg_env, r_rs1, r_rs2); } -static void gen_op_fcmpeq(int fccno) +static void gen_op_fcmpeq(int fccno, TCGv_i128 r_rs1, TCGv_i128 r_rs2) { - gen_helper_fcmpeq(cpu_fsr, tcg_env); + gen_helper_fcmpeq(cpu_fsr, tcg_env, r_rs1, r_rs2); } #endif @@ -5144,6 +5128,8 @@ TRANS(FCMPEd, ALL, do_fcmpd, a, true) static bool do_fcmpq(DisasContext *dc, arg_FCMPq *a, bool e) { + TCGv_i128 src1, src2; + if (avail_32(dc) && a->cc != 0) { return false; } @@ -5155,12 +5141,12 @@ static bool do_fcmpq(DisasContext *dc, arg_FCMPq *a, bool e) } gen_op_clear_ieee_excp_and_FTT(); - gen_op_load_fpr_QT0(QFPREG(a->rs1)); - gen_op_load_fpr_QT1(QFPREG(a->rs2)); + src1 = gen_load_fpr_Q(dc, a->rs1); + src2 = gen_load_fpr_Q(dc, a->rs2); if (e) { - gen_op_fcmpeq(a->cc); + gen_op_fcmpeq(a->cc, src1, src2); } else { - gen_op_fcmpq(a->cc); + gen_op_fcmpq(a->cc, src1, src2); } return advance_pc(dc); } From 0b2a61cc26caa8e3ba6425f7c4159aa75fe520b9 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Fri, 3 Nov 2023 10:38:30 -0700 Subject: [PATCH 46/58] target/sparc: Use i128 for FsTOq, FiTOq Signed-off-by: Richard Henderson Tested-by: Mark Cave-Ayland Acked-by: Mark Cave-Ayland Message-Id: <20231103173841.33651-12-richard.henderson@linaro.org> --- target/sparc/fop_helper.c | 8 ++++---- target/sparc/helper.h | 4 ++-- target/sparc/translate.c | 9 +++++---- 3 files changed, 11 insertions(+), 10 deletions(-) diff --git a/target/sparc/fop_helper.c b/target/sparc/fop_helper.c index faf75e651f..c7dc835d28 100644 --- a/target/sparc/fop_helper.c +++ b/target/sparc/fop_helper.c @@ -147,9 +147,9 @@ float64 helper_fitod(CPUSPARCState *env, int32_t src) return int32_to_float64(src, &env->fp_status); } -void helper_fitoq(CPUSPARCState *env, int32_t src) +Int128 helper_fitoq(CPUSPARCState *env, int32_t src) { - QT0 = int32_to_float128(src, &env->fp_status); + return f128_ret(int32_to_float128(src, &env->fp_status)); } #ifdef TARGET_SPARC64 @@ -185,9 +185,9 @@ float32 helper_fqtos(CPUSPARCState *env, Int128 src) return float128_to_float32(f128_in(src), &env->fp_status); } -void helper_fstoq(CPUSPARCState *env, float32 src) +Int128 helper_fstoq(CPUSPARCState *env, float32 src) { - QT0 = float32_to_float128(src, &env->fp_status); + return f128_ret(float32_to_float128(src, &env->fp_status)); } float64 helper_fqtod(CPUSPARCState *env, Int128 src) diff --git a/target/sparc/helper.h b/target/sparc/helper.h index 7caae9a441..5e93342583 100644 --- a/target/sparc/helper.h +++ b/target/sparc/helper.h @@ -87,7 +87,7 @@ DEF_HELPER_FLAGS_3(fsmuld, TCG_CALL_NO_RWG, f64, env, f32, f32) DEF_HELPER_FLAGS_3(fdmulq, TCG_CALL_NO_RWG, void, env, f64, f64) DEF_HELPER_FLAGS_2(fitod, TCG_CALL_NO_RWG_SE, f64, env, s32) -DEF_HELPER_FLAGS_2(fitoq, TCG_CALL_NO_RWG, void, env, s32) +DEF_HELPER_FLAGS_2(fitoq, TCG_CALL_NO_RWG, i128, env, s32) DEF_HELPER_FLAGS_2(fitos, TCG_CALL_NO_RWG, f32, env, s32) @@ -99,7 +99,7 @@ DEF_HELPER_FLAGS_2(fxtoq, TCG_CALL_NO_RWG, void, env, s64) DEF_HELPER_FLAGS_2(fdtos, TCG_CALL_NO_RWG, f32, env, f64) DEF_HELPER_FLAGS_2(fstod, TCG_CALL_NO_RWG, f64, env, f32) DEF_HELPER_FLAGS_2(fqtos, TCG_CALL_NO_RWG, f32, env, i128) -DEF_HELPER_FLAGS_2(fstoq, TCG_CALL_NO_RWG, void, env, f32) +DEF_HELPER_FLAGS_2(fstoq, TCG_CALL_NO_RWG, i128, env, f32) DEF_HELPER_FLAGS_2(fqtod, TCG_CALL_NO_RWG, f64, env, i128) DEF_HELPER_FLAGS_2(fdtoq, TCG_CALL_NO_RWG, void, env, f64) DEF_HELPER_FLAGS_2(fstoi, TCG_CALL_NO_RWG, s32, env, f32) diff --git a/target/sparc/translate.c b/target/sparc/translate.c index 6c003eed7c..6522a9b0c8 100644 --- a/target/sparc/translate.c +++ b/target/sparc/translate.c @@ -4726,9 +4726,10 @@ TRANS(FqTOd, ALL, do_env_dq, a, gen_helper_fqtod) TRANS(FqTOx, 64, do_env_dq, a, gen_helper_fqtox) static bool do_env_qf(DisasContext *dc, arg_r_r *a, - void (*func)(TCGv_env, TCGv_i32)) + void (*func)(TCGv_i128, TCGv_env, TCGv_i32)) { TCGv_i32 src; + TCGv_i128 dst; if (gen_trap_ifnofpu(dc)) { return true; @@ -4739,9 +4740,9 @@ static bool do_env_qf(DisasContext *dc, arg_r_r *a, gen_op_clear_ieee_excp_and_FTT(); src = gen_load_fpr_F(dc, a->rs); - func(tcg_env, src); - gen_op_store_QT0_fpr(QFPREG(a->rd)); - gen_update_fprs_dirty(dc, QFPREG(a->rd)); + dst = tcg_temp_new_i128(); + func(dst, tcg_env, src); + gen_store_fpr_Q(dc, a->rd, dst); return advance_pc(dc); } From fdc50716a0c9e522ea91a7e909a624f2a1c65e59 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Fri, 3 Nov 2023 10:38:31 -0700 Subject: [PATCH 47/58] target/sparc: Use i128 for FdTOq, FxTOq Signed-off-by: Richard Henderson Tested-by: Mark Cave-Ayland Acked-by: Mark Cave-Ayland Message-Id: <20231103173841.33651-13-richard.henderson@linaro.org> --- target/sparc/fop_helper.c | 8 ++++---- target/sparc/helper.h | 4 ++-- target/sparc/translate.c | 9 +++++---- 3 files changed, 11 insertions(+), 10 deletions(-) diff --git a/target/sparc/fop_helper.c b/target/sparc/fop_helper.c index c7dc835d28..9a0110e201 100644 --- a/target/sparc/fop_helper.c +++ b/target/sparc/fop_helper.c @@ -163,9 +163,9 @@ float64 helper_fxtod(CPUSPARCState *env, int64_t src) return int64_to_float64(src, &env->fp_status); } -void helper_fxtoq(CPUSPARCState *env, int64_t src) +Int128 helper_fxtoq(CPUSPARCState *env, int64_t src) { - QT0 = int64_to_float128(src, &env->fp_status); + return f128_ret(int64_to_float128(src, &env->fp_status)); } #endif @@ -195,9 +195,9 @@ float64 helper_fqtod(CPUSPARCState *env, Int128 src) return float128_to_float64(f128_in(src), &env->fp_status); } -void helper_fdtoq(CPUSPARCState *env, float64 src) +Int128 helper_fdtoq(CPUSPARCState *env, float64 src) { - QT0 = float64_to_float128(src, &env->fp_status); + return f128_ret(float64_to_float128(src, &env->fp_status)); } /* Float to integer conversion. */ diff --git a/target/sparc/helper.h b/target/sparc/helper.h index 5e93342583..20f67f89b0 100644 --- a/target/sparc/helper.h +++ b/target/sparc/helper.h @@ -94,14 +94,14 @@ DEF_HELPER_FLAGS_2(fitos, TCG_CALL_NO_RWG, f32, env, s32) #ifdef TARGET_SPARC64 DEF_HELPER_FLAGS_2(fxtos, TCG_CALL_NO_RWG, f32, env, s64) DEF_HELPER_FLAGS_2(fxtod, TCG_CALL_NO_RWG, f64, env, s64) -DEF_HELPER_FLAGS_2(fxtoq, TCG_CALL_NO_RWG, void, env, s64) +DEF_HELPER_FLAGS_2(fxtoq, TCG_CALL_NO_RWG, i128, env, s64) #endif DEF_HELPER_FLAGS_2(fdtos, TCG_CALL_NO_RWG, f32, env, f64) DEF_HELPER_FLAGS_2(fstod, TCG_CALL_NO_RWG, f64, env, f32) DEF_HELPER_FLAGS_2(fqtos, TCG_CALL_NO_RWG, f32, env, i128) DEF_HELPER_FLAGS_2(fstoq, TCG_CALL_NO_RWG, i128, env, f32) DEF_HELPER_FLAGS_2(fqtod, TCG_CALL_NO_RWG, f64, env, i128) -DEF_HELPER_FLAGS_2(fdtoq, TCG_CALL_NO_RWG, void, env, f64) +DEF_HELPER_FLAGS_2(fdtoq, TCG_CALL_NO_RWG, i128, env, f64) DEF_HELPER_FLAGS_2(fstoi, TCG_CALL_NO_RWG, s32, env, f32) DEF_HELPER_FLAGS_2(fdtoi, TCG_CALL_NO_RWG, s32, env, f64) DEF_HELPER_FLAGS_2(fqtoi, TCG_CALL_NO_RWG, s32, env, i128) diff --git a/target/sparc/translate.c b/target/sparc/translate.c index 6522a9b0c8..d478a2fcd0 100644 --- a/target/sparc/translate.c +++ b/target/sparc/translate.c @@ -4750,9 +4750,10 @@ TRANS(FiTOq, ALL, do_env_qf, a, gen_helper_fitoq) TRANS(FsTOq, ALL, do_env_qf, a, gen_helper_fstoq) static bool do_env_qd(DisasContext *dc, arg_r_r *a, - void (*func)(TCGv_env, TCGv_i64)) + void (*func)(TCGv_i128, TCGv_env, TCGv_i64)) { TCGv_i64 src; + TCGv_i128 dst; if (gen_trap_ifnofpu(dc)) { return true; @@ -4763,9 +4764,9 @@ static bool do_env_qd(DisasContext *dc, arg_r_r *a, gen_op_clear_ieee_excp_and_FTT(); src = gen_load_fpr_D(dc, a->rs); - func(tcg_env, src); - gen_op_store_QT0_fpr(QFPREG(a->rd)); - gen_update_fprs_dirty(dc, QFPREG(a->rd)); + dst = tcg_temp_new_i128(); + func(dst, tcg_env, src); + gen_store_fpr_Q(dc, a->rd, dst); return advance_pc(dc); } From ba21dc991be87ee8e15d124a80b27ce626a77b14 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Fri, 3 Nov 2023 10:38:32 -0700 Subject: [PATCH 48/58] target/sparc: Use i128 for Fdmulq Signed-off-by: Richard Henderson Tested-by: Mark Cave-Ayland Acked-by: Mark Cave-Ayland Message-Id: <20231103173841.33651-14-richard.henderson@linaro.org> --- target/sparc/fop_helper.c | 8 ++++---- target/sparc/helper.h | 2 +- target/sparc/translate.c | 15 ++++----------- 3 files changed, 9 insertions(+), 16 deletions(-) diff --git a/target/sparc/fop_helper.c b/target/sparc/fop_helper.c index 9a0110e201..cd9b212597 100644 --- a/target/sparc/fop_helper.c +++ b/target/sparc/fop_helper.c @@ -129,11 +129,11 @@ float64 helper_fsmuld(CPUSPARCState *env, float32 src1, float32 src2) &env->fp_status); } -void helper_fdmulq(CPUSPARCState *env, float64 src1, float64 src2) +Int128 helper_fdmulq(CPUSPARCState *env, float64 src1, float64 src2) { - QT0 = float128_mul(float64_to_float128(src1, &env->fp_status), - float64_to_float128(src2, &env->fp_status), - &env->fp_status); + return f128_ret(float128_mul(float64_to_float128(src1, &env->fp_status), + float64_to_float128(src2, &env->fp_status), + &env->fp_status)); } /* Integer to float conversion. */ diff --git a/target/sparc/helper.h b/target/sparc/helper.h index 20f67f89b0..f7aeb31169 100644 --- a/target/sparc/helper.h +++ b/target/sparc/helper.h @@ -84,7 +84,7 @@ DEF_HELPER_FLAGS_3(fmuls, TCG_CALL_NO_RWG, f32, env, f32, f32) DEF_HELPER_FLAGS_3(fdivs, TCG_CALL_NO_RWG, f32, env, f32, f32) DEF_HELPER_FLAGS_3(fsmuld, TCG_CALL_NO_RWG, f64, env, f32, f32) -DEF_HELPER_FLAGS_3(fdmulq, TCG_CALL_NO_RWG, void, env, f64, f64) +DEF_HELPER_FLAGS_3(fdmulq, TCG_CALL_NO_RWG, i128, env, f64, f64) DEF_HELPER_FLAGS_2(fitod, TCG_CALL_NO_RWG_SE, f64, env, s32) DEF_HELPER_FLAGS_2(fitoq, TCG_CALL_NO_RWG, i128, env, s32) diff --git a/target/sparc/translate.c b/target/sparc/translate.c index d478a2fcd0..d12de5ae5c 100644 --- a/target/sparc/translate.c +++ b/target/sparc/translate.c @@ -276,14 +276,6 @@ static void gen_store_fpr_Q(DisasContext *dc, unsigned int dst, TCGv_i128 v) gen_update_fprs_dirty(dc, dst); } -static void gen_op_store_QT0_fpr(unsigned int dst) -{ - tcg_gen_ld_i64(cpu_fpr[dst / 2], tcg_env, offsetof(CPUSPARCState, qt0) + - offsetof(CPU_QuadU, ll.upper)); - tcg_gen_ld_i64(cpu_fpr[dst/2 + 1], tcg_env, offsetof(CPUSPARCState, qt0) + - offsetof(CPU_QuadU, ll.lower)); -} - /* moves */ #ifdef CONFIG_USER_ONLY #define supervisor(dc) 0 @@ -4992,6 +4984,7 @@ TRANS(FDIVq, ALL, do_env_qqq, a, gen_helper_fdivq) static bool trans_FdMULq(DisasContext *dc, arg_r_r_r *a) { TCGv_i64 src1, src2; + TCGv_i128 dst; if (gen_trap_ifnofpu(dc)) { return true; @@ -5003,10 +4996,10 @@ static bool trans_FdMULq(DisasContext *dc, arg_r_r_r *a) gen_op_clear_ieee_excp_and_FTT(); src1 = gen_load_fpr_D(dc, a->rs1); src2 = gen_load_fpr_D(dc, a->rs2); - gen_helper_fdmulq(tcg_env, src1, src2); + dst = tcg_temp_new_i128(); + gen_helper_fdmulq(dst, tcg_env, src1, src2); gen_helper_check_ieee_exceptions(cpu_fsr, tcg_env); - gen_op_store_QT0_fpr(QFPREG(a->rd)); - gen_update_fprs_dirty(dc, QFPREG(a->rd)); + gen_store_fpr_Q(dc, a->rd, dst); return advance_pc(dc); } From 41535ca6f4d708cf376d731930fd89f44c84c98a Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Fri, 3 Nov 2023 10:38:33 -0700 Subject: [PATCH 49/58] target/sparc: Remove qt0, qt1 temporaries These are no longer used for passing data to/from helpers. Signed-off-by: Richard Henderson Tested-by: Mark Cave-Ayland Acked-by: Mark Cave-Ayland Message-Id: <20231103173841.33651-15-richard.henderson@linaro.org> --- target/sparc/cpu.h | 2 -- target/sparc/fop_helper.c | 3 --- target/sparc/ldst_helper.c | 3 --- 3 files changed, 8 deletions(-) diff --git a/target/sparc/cpu.h b/target/sparc/cpu.h index 1e076f6355..75c46e2736 100644 --- a/target/sparc/cpu.h +++ b/target/sparc/cpu.h @@ -509,8 +509,6 @@ struct CPUArchState { uint64_t mmubpregs[4]; uint64_t prom_addr; #endif - /* temporary float registers */ - float128 qt0, qt1; float_status fp_status; #if defined(TARGET_SPARC64) #define MAXTL_MAX 8 diff --git a/target/sparc/fop_helper.c b/target/sparc/fop_helper.c index cd9b212597..7353a61237 100644 --- a/target/sparc/fop_helper.c +++ b/target/sparc/fop_helper.c @@ -23,9 +23,6 @@ #include "exec/helper-proto.h" #include "fpu/softfloat.h" -#define QT0 (env->qt0) -#define QT1 (env->qt1) - static inline float128 f128_in(Int128 i) { union { diff --git a/target/sparc/ldst_helper.c b/target/sparc/ldst_helper.c index 52aa6c631b..1ecd58e8ff 100644 --- a/target/sparc/ldst_helper.c +++ b/target/sparc/ldst_helper.c @@ -66,9 +66,6 @@ #endif #endif -#define QT0 (env->qt0) -#define QT1 (env->qt1) - #if defined(TARGET_SPARC64) && !defined(CONFIG_USER_ONLY) /* Calculates TSB pointer value for fault page size * UltraSPARC IIi has fixed sizes (8k or 64k) for the page pointers From 1ccd6e13ccc0913bd3750f47c697c3d7c31cd418 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Fri, 3 Nov 2023 10:38:34 -0700 Subject: [PATCH 50/58] target/sparc: Introduce cpu_get_fsr, cpu_put_fsr MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Richard Henderson Reviewed-by: Philippe Mathieu-Daudé Tested-by: Mark Cave-Ayland Acked-by: Mark Cave-Ayland Message-Id: <20231103173841.33651-16-richard.henderson@linaro.org> --- linux-user/sparc/cpu_loop.c | 2 +- linux-user/sparc/signal.c | 14 +++++++++----- target/sparc/cpu.c | 5 +++-- target/sparc/cpu.h | 4 +++- target/sparc/fop_helper.c | 21 +++++++++++++++++++-- target/sparc/gdbstub.c | 8 ++++---- target/sparc/helper.h | 1 + target/sparc/machine.c | 36 ++++++++++++++++++++++++++++++++++-- target/sparc/translate.c | 7 ++++++- 9 files changed, 80 insertions(+), 18 deletions(-) diff --git a/linux-user/sparc/cpu_loop.c b/linux-user/sparc/cpu_loop.c index 3c1bde00dd..50424a54df 100644 --- a/linux-user/sparc/cpu_loop.c +++ b/linux-user/sparc/cpu_loop.c @@ -293,7 +293,7 @@ void cpu_loop (CPUSPARCState *env) case TT_FP_EXCP: { int code = TARGET_FPE_FLTUNK; - target_ulong fsr = env->fsr; + target_ulong fsr = cpu_get_fsr(env); if ((fsr & FSR_FTT_MASK) == FSR_FTT_IEEE_EXCP) { if (fsr & FSR_NVC) { diff --git a/linux-user/sparc/signal.c b/linux-user/sparc/signal.c index dfcae707e0..c2dc1000e2 100644 --- a/linux-user/sparc/signal.c +++ b/linux-user/sparc/signal.c @@ -199,20 +199,21 @@ static void save_fpu(struct target_siginfo_fpu *fpu, CPUSPARCState *env) for (i = 0; i < 32; ++i) { __put_user(env->fpr[i].ll, &fpu->si_double_regs[i]); } - __put_user(env->fsr, &fpu->si_fsr); + __put_user(cpu_get_fsr(env), &fpu->si_fsr); __put_user(env->gsr, &fpu->si_gsr); __put_user(env->fprs, &fpu->si_fprs); #else for (i = 0; i < 16; ++i) { __put_user(env->fpr[i].ll, &fpu->si_double_regs[i]); } - __put_user(env->fsr, &fpu->si_fsr); + __put_user(cpu_get_fsr(env), &fpu->si_fsr); __put_user(0, &fpu->si_fpqdepth); #endif } static void restore_fpu(struct target_siginfo_fpu *fpu, CPUSPARCState *env) { + target_ulong fsr; int i; #ifdef TARGET_SPARC64 @@ -230,15 +231,16 @@ static void restore_fpu(struct target_siginfo_fpu *fpu, CPUSPARCState *env) __get_user(env->fpr[i].ll, &fpu->si_double_regs[i]); } } - __get_user(env->fsr, &fpu->si_fsr); __get_user(env->gsr, &fpu->si_gsr); env->fprs |= fprs; #else for (i = 0; i < 16; ++i) { __get_user(env->fpr[i].ll, &fpu->si_double_regs[i]); } - __get_user(env->fsr, &fpu->si_fsr); #endif + + __get_user(fsr, &fpu->si_fsr); + cpu_put_fsr(env, fsr); } #ifdef TARGET_ARCH_HAS_SETUP_FRAME @@ -662,6 +664,7 @@ void sparc64_set_context(CPUSPARCState *env) __get_user(fenab, &(fpup->mcfpu_enab)); if (fenab) { abi_ulong fprs; + abi_ulong fsr; /* * We use the FPRS from the guest only in deciding whether @@ -690,7 +693,8 @@ void sparc64_set_context(CPUSPARCState *env) __get_user(env->fpr[i].ll, &(fpup->mcfpu_fregs.dregs[i])); } } - __get_user(env->fsr, &(fpup->mcfpu_fsr)); + __get_user(fsr, &(fpup->mcfpu_fsr)); + cpu_put_fsr(env, fsr); __get_user(env->gsr, &(fpup->mcfpu_gsr)); } unlock_user_struct(ucp, ucp_addr, 0); diff --git a/target/sparc/cpu.c b/target/sparc/cpu.c index afa62723fe..1897ab230d 100644 --- a/target/sparc/cpu.c +++ b/target/sparc/cpu.c @@ -670,7 +670,7 @@ static void sparc_cpu_dump_state(CPUState *cs, FILE *f, int flags) env->cansave, env->canrestore, env->otherwin, env->wstate, env->cleanwin, env->nwindows - 1 - env->cwp); qemu_fprintf(f, "fsr: " TARGET_FMT_lx " y: " TARGET_FMT_lx " fprs: %016x\n", - env->fsr, env->y, env->fprs); + cpu_get_fsr(env), env->y, env->fprs); #else qemu_fprintf(f, "psr: %08x (icc: ", cpu_get_psr(env)); @@ -679,7 +679,7 @@ static void sparc_cpu_dump_state(CPUState *cs, FILE *f, int flags) env->psrps ? 'P' : '-', env->psret ? 'E' : '-', env->wim); qemu_fprintf(f, "fsr: " TARGET_FMT_lx " y: " TARGET_FMT_lx "\n", - env->fsr, env->y); + cpu_get_fsr(env), env->y); #endif qemu_fprintf(f, "\n"); } @@ -798,6 +798,7 @@ static void sparc_cpu_realizefn(DeviceState *dev, Error **errp) env->version |= env->def.maxtl << 8; env->version |= env->def.nwindows - 1; #endif + cpu_put_fsr(env, 0); cpu_exec_realizefn(cs, &local_err); if (local_err != NULL) { diff --git a/target/sparc/cpu.h b/target/sparc/cpu.h index 75c46e2736..3cf8cc2d0b 100644 --- a/target/sparc/cpu.h +++ b/target/sparc/cpu.h @@ -617,7 +617,9 @@ void sparc_restore_state_to_opc(CPUState *cs, const TranslationBlock *tb, const uint64_t *data); -/* cpu-exec.c */ +/* fop_helper.c */ +target_ulong cpu_get_fsr(CPUSPARCState *); +void cpu_put_fsr(CPUSPARCState *, target_ulong); /* win_helper.c */ target_ulong cpu_get_psr(CPUSPARCState *env1); diff --git a/target/sparc/fop_helper.c b/target/sparc/fop_helper.c index 7353a61237..70b38011d2 100644 --- a/target/sparc/fop_helper.c +++ b/target/sparc/fop_helper.c @@ -347,10 +347,22 @@ GEN_FCMP(fcmpeq_fcc3, float128, 26, 1); #undef GEN_FCMP_T #undef GEN_FCMP -static void set_fsr(CPUSPARCState *env, target_ulong fsr) +target_ulong cpu_get_fsr(CPUSPARCState *env) +{ + return env->fsr; +} + +target_ulong helper_get_fsr(CPUSPARCState *env) +{ + return cpu_get_fsr(env); +} + +static void set_fsr_nonsplit(CPUSPARCState *env, target_ulong fsr) { int rnd_mode; + env->fsr = fsr; + switch (fsr & FSR_RD_MASK) { case FSR_RD_NEAREST: rnd_mode = float_round_nearest_even; @@ -369,7 +381,12 @@ static void set_fsr(CPUSPARCState *env, target_ulong fsr) set_float_rounding_mode(rnd_mode, &env->fp_status); } +void cpu_put_fsr(CPUSPARCState *env, target_ulong fsr) +{ + set_fsr_nonsplit(env, fsr); +} + void helper_set_fsr(CPUSPARCState *env, target_ulong fsr) { - set_fsr(env, fsr); + set_fsr_nonsplit(env, fsr); } diff --git a/target/sparc/gdbstub.c b/target/sparc/gdbstub.c index a1c8fdc4d5..d1586b2392 100644 --- a/target/sparc/gdbstub.c +++ b/target/sparc/gdbstub.c @@ -64,7 +64,7 @@ int sparc_cpu_gdb_read_register(CPUState *cs, GByteArray *mem_buf, int n) case 69: return gdb_get_rega(mem_buf, env->npc); case 70: - return gdb_get_rega(mem_buf, env->fsr); + return gdb_get_rega(mem_buf, cpu_get_fsr(env)); case 71: return gdb_get_rega(mem_buf, 0); /* csr */ default: @@ -94,7 +94,7 @@ int sparc_cpu_gdb_read_register(CPUState *cs, GByteArray *mem_buf, int n) ((env->pstate & 0xfff) << 8) | cpu_get_cwp64(env)); case 83: - return gdb_get_regl(mem_buf, env->fsr); + return gdb_get_regl(mem_buf, cpu_get_fsr(env)); case 84: return gdb_get_regl(mem_buf, env->fprs); case 85: @@ -156,7 +156,7 @@ int sparc_cpu_gdb_write_register(CPUState *cs, uint8_t *mem_buf, int n) env->npc = tmp; break; case 70: - env->fsr = tmp; + cpu_put_fsr(env, tmp); break; default: return 0; @@ -191,7 +191,7 @@ int sparc_cpu_gdb_write_register(CPUState *cs, uint8_t *mem_buf, int n) cpu_put_cwp64(env, tmp & 0xff); break; case 83: - env->fsr = tmp; + cpu_put_fsr(env, tmp); break; case 84: env->fprs = tmp; diff --git a/target/sparc/helper.h b/target/sparc/helper.h index f7aeb31169..cc8db50d75 100644 --- a/target/sparc/helper.h +++ b/target/sparc/helper.h @@ -36,6 +36,7 @@ DEF_HELPER_FLAGS_4(ld_asi, TCG_CALL_NO_WG, i64, env, tl, int, i32) DEF_HELPER_FLAGS_5(st_asi, TCG_CALL_NO_WG, void, env, tl, i64, int, i32) #endif DEF_HELPER_FLAGS_1(check_ieee_exceptions, TCG_CALL_NO_WG, tl, env) +DEF_HELPER_FLAGS_1(get_fsr, TCG_CALL_NO_WG_SE, tl, env) DEF_HELPER_FLAGS_2(set_fsr, TCG_CALL_NO_RWG, void, env, tl) DEF_HELPER_FLAGS_2(fsqrts, TCG_CALL_NO_RWG, f32, env, f32) DEF_HELPER_FLAGS_2(fsqrtd, TCG_CALL_NO_RWG, f64, env, f64) diff --git a/target/sparc/machine.c b/target/sparc/machine.c index 2b5686c330..48e0cf22f3 100644 --- a/target/sparc/machine.c +++ b/target/sparc/machine.c @@ -83,6 +83,32 @@ static const VMStateInfo vmstate_psr = { .put = put_psr, }; +static int get_fsr(QEMUFile *f, void *opaque, size_t size, + const VMStateField *field) +{ + SPARCCPU *cpu = opaque; + target_ulong val = qemu_get_betl(f); + + cpu_put_fsr(&cpu->env, val); + return 0; +} + +static int put_fsr(QEMUFile *f, void *opaque, size_t size, + const VMStateField *field, JSONWriter *vmdesc) +{ + SPARCCPU *cpu = opaque; + target_ulong val = cpu_get_fsr(&cpu->env); + + qemu_put_betl(f, val); + return 0; +} + +static const VMStateInfo vmstate_fsr = { + .name = "fsr", + .get = get_fsr, + .put = put_fsr, +}; + #ifdef TARGET_SPARC64 static int get_xcc(QEMUFile *f, void *opaque, size_t size, const VMStateField *field) @@ -157,7 +183,6 @@ const VMStateDescription vmstate_sparc_cpu = { VMSTATE_UINTTL(env.npc, SPARCCPU), VMSTATE_UINTTL(env.y, SPARCCPU), { - .name = "psr", .version_id = 0, .size = sizeof(uint32_t), @@ -165,7 +190,14 @@ const VMStateDescription vmstate_sparc_cpu = { .flags = VMS_SINGLE, .offset = 0, }, - VMSTATE_UINTTL(env.fsr, SPARCCPU), + { + .name = "fsr", + .version_id = 0, + .size = sizeof(target_ulong), + .info = &vmstate_fsr, + .flags = VMS_SINGLE, + .offset = 0, + }, VMSTATE_UINTTL(env.tbr, SPARCCPU), VMSTATE_INT32(env.interrupt_index, SPARCCPU), VMSTATE_UINT32(env.pil_in, SPARCCPU), diff --git a/target/sparc/translate.c b/target/sparc/translate.c index d12de5ae5c..da4f167fa6 100644 --- a/target/sparc/translate.c +++ b/target/sparc/translate.c @@ -4417,13 +4417,18 @@ TRANS(LDXFSR, 64, do_ldfsr, a, MO_TEUQ, FSR_LDXFSR_MASK, FSR_LDXFSR_OLDMASK) static bool do_stfsr(DisasContext *dc, arg_r_r_ri *a, MemOp mop) { TCGv addr = gen_ldst_addr(dc, a->rs1, a->imm, a->rs2_or_imm); + TCGv fsr; + if (addr == NULL) { return false; } if (gen_trap_ifnofpu(dc)) { return true; } - tcg_gen_qemu_st_tl(cpu_fsr, addr, dc->mem_idx, mop | MO_ALIGN); + + fsr = tcg_temp_new(); + gen_helper_get_fsr(fsr, tcg_env); + tcg_gen_qemu_st_tl(fsr, addr, dc->mem_idx, mop | MO_ALIGN); return advance_pc(dc); } From 49bb972513ced00ac772c282246f3b46e3cd75c3 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Fri, 3 Nov 2023 10:38:35 -0700 Subject: [PATCH 51/58] target/sparc: Split ver from env->fsr MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This field is read-only. It is easier to store it separately and merge it only upon read. While we're at it, use FSR_VER_SHIFT to initialize fpu_version. Signed-off-by: Richard Henderson Reviewed-by: Philippe Mathieu-Daudé Tested-by: Mark Cave-Ayland Acked-by: Mark Cave-Ayland Message-Id: <20231103173841.33651-17-richard.henderson@linaro.org> --- target/sparc/cpu.c | 27 +++++++++++++-------------- target/sparc/cpu.h | 3 +++ target/sparc/fop_helper.c | 9 +++++++-- 3 files changed, 23 insertions(+), 16 deletions(-) diff --git a/target/sparc/cpu.c b/target/sparc/cpu.c index 1897ab230d..313ebc4c11 100644 --- a/target/sparc/cpu.c +++ b/target/sparc/cpu.c @@ -368,7 +368,7 @@ static const sparc_def_t sparc_defs[] = { { .name = "Fujitsu MB86904", .iu_version = 0x04 << 24, /* Impl 0, ver 4 */ - .fpu_version = 4 << 17, /* FPU version 4 (Meiko) */ + .fpu_version = 4 << FSR_VER_SHIFT, /* FPU version 4 (Meiko) */ .mmu_version = 0x04 << 24, /* Impl 0, ver 4 */ .mmu_bm = 0x00004000, .mmu_ctpr_mask = 0x00ffffc0, @@ -381,7 +381,7 @@ static const sparc_def_t sparc_defs[] = { { .name = "Fujitsu MB86907", .iu_version = 0x05 << 24, /* Impl 0, ver 5 */ - .fpu_version = 4 << 17, /* FPU version 4 (Meiko) */ + .fpu_version = 4 << FSR_VER_SHIFT, /* FPU version 4 (Meiko) */ .mmu_version = 0x05 << 24, /* Impl 0, ver 5 */ .mmu_bm = 0x00004000, .mmu_ctpr_mask = 0xffffffc0, @@ -394,7 +394,7 @@ static const sparc_def_t sparc_defs[] = { { .name = "TI MicroSparc I", .iu_version = 0x41000000, - .fpu_version = 4 << 17, + .fpu_version = 4 << FSR_VER_SHIFT, .mmu_version = 0x41000000, .mmu_bm = 0x00004000, .mmu_ctpr_mask = 0x007ffff0, @@ -407,7 +407,7 @@ static const sparc_def_t sparc_defs[] = { { .name = "TI MicroSparc II", .iu_version = 0x42000000, - .fpu_version = 4 << 17, + .fpu_version = 4 << FSR_VER_SHIFT, .mmu_version = 0x02000000, .mmu_bm = 0x00004000, .mmu_ctpr_mask = 0x00ffffc0, @@ -420,7 +420,7 @@ static const sparc_def_t sparc_defs[] = { { .name = "TI MicroSparc IIep", .iu_version = 0x42000000, - .fpu_version = 4 << 17, + .fpu_version = 4 << FSR_VER_SHIFT, .mmu_version = 0x04000000, .mmu_bm = 0x00004000, .mmu_ctpr_mask = 0x00ffffc0, @@ -433,7 +433,7 @@ static const sparc_def_t sparc_defs[] = { { .name = "TI SuperSparc 40", /* STP1020NPGA */ .iu_version = 0x41000000, /* SuperSPARC 2.x */ - .fpu_version = 0 << 17, + .fpu_version = 0 << FSR_VER_SHIFT, .mmu_version = 0x00000800, /* SuperSPARC 2.x, no MXCC */ .mmu_bm = 0x00002000, .mmu_ctpr_mask = 0xffffffc0, @@ -446,7 +446,7 @@ static const sparc_def_t sparc_defs[] = { { .name = "TI SuperSparc 50", /* STP1020PGA */ .iu_version = 0x40000000, /* SuperSPARC 3.x */ - .fpu_version = 0 << 17, + .fpu_version = 0 << FSR_VER_SHIFT, .mmu_version = 0x01000800, /* SuperSPARC 3.x, no MXCC */ .mmu_bm = 0x00002000, .mmu_ctpr_mask = 0xffffffc0, @@ -459,7 +459,7 @@ static const sparc_def_t sparc_defs[] = { { .name = "TI SuperSparc 51", .iu_version = 0x40000000, /* SuperSPARC 3.x */ - .fpu_version = 0 << 17, + .fpu_version = 0 << FSR_VER_SHIFT, .mmu_version = 0x01000000, /* SuperSPARC 3.x, MXCC */ .mmu_bm = 0x00002000, .mmu_ctpr_mask = 0xffffffc0, @@ -473,7 +473,7 @@ static const sparc_def_t sparc_defs[] = { { .name = "TI SuperSparc 60", /* STP1020APGA */ .iu_version = 0x40000000, /* SuperSPARC 3.x */ - .fpu_version = 0 << 17, + .fpu_version = 0 << FSR_VER_SHIFT, .mmu_version = 0x01000800, /* SuperSPARC 3.x, no MXCC */ .mmu_bm = 0x00002000, .mmu_ctpr_mask = 0xffffffc0, @@ -486,7 +486,7 @@ static const sparc_def_t sparc_defs[] = { { .name = "TI SuperSparc 61", .iu_version = 0x44000000, /* SuperSPARC 3.x */ - .fpu_version = 0 << 17, + .fpu_version = 0 << FSR_VER_SHIFT, .mmu_version = 0x01000000, /* SuperSPARC 3.x, MXCC */ .mmu_bm = 0x00002000, .mmu_ctpr_mask = 0xffffffc0, @@ -500,7 +500,7 @@ static const sparc_def_t sparc_defs[] = { { .name = "TI SuperSparc II", .iu_version = 0x40000000, /* SuperSPARC II 1.x */ - .fpu_version = 0 << 17, + .fpu_version = 0 << FSR_VER_SHIFT, .mmu_version = 0x08000000, /* SuperSPARC II 1.x, MXCC */ .mmu_bm = 0x00002000, .mmu_ctpr_mask = 0xffffffc0, @@ -514,7 +514,7 @@ static const sparc_def_t sparc_defs[] = { { .name = "LEON2", .iu_version = 0xf2000000, - .fpu_version = 4 << 17, /* FPU version 4 (Meiko) */ + .fpu_version = 4 << FSR_VER_SHIFT, /* FPU version 4 (Meiko) */ .mmu_version = 0xf2000000, .mmu_bm = 0x00004000, .mmu_ctpr_mask = 0x007ffff0, @@ -527,7 +527,7 @@ static const sparc_def_t sparc_defs[] = { { .name = "LEON3", .iu_version = 0xf3000000, - .fpu_version = 4 << 17, /* FPU version 4 (Meiko) */ + .fpu_version = 4 << FSR_VER_SHIFT, /* FPU version 4 (Meiko) */ .mmu_version = 0xf3000000, .mmu_bm = 0x00000000, .mmu_ctpr_mask = 0xfffffffc, @@ -786,7 +786,6 @@ static void sparc_cpu_realizefn(DeviceState *dev, Error **errp) #endif env->version = env->def.iu_version; - env->fsr = env->def.fpu_version; env->nwindows = env->def.nwindows; #if !defined(TARGET_SPARC64) env->mmuregs[0] |= env->def.mmu_version; diff --git a/target/sparc/cpu.h b/target/sparc/cpu.h index 3cf8cc2d0b..216155d231 100644 --- a/target/sparc/cpu.h +++ b/target/sparc/cpu.h @@ -191,6 +191,9 @@ enum { #define FSR_NXC (1ULL << 0) #define FSR_CEXC_MASK (FSR_NVC | FSR_OFC | FSR_UFC | FSR_DZC | FSR_NXC) +#define FSR_VER_SHIFT 17 +#define FSR_VER_MASK (7 << FSR_VER_SHIFT) + #define FSR_FTT2 (1ULL << 16) #define FSR_FTT1 (1ULL << 15) #define FSR_FTT0 (1ULL << 14) diff --git a/target/sparc/fop_helper.c b/target/sparc/fop_helper.c index 70b38011d2..22b412adb5 100644 --- a/target/sparc/fop_helper.c +++ b/target/sparc/fop_helper.c @@ -349,7 +349,12 @@ GEN_FCMP(fcmpeq_fcc3, float128, 26, 1); target_ulong cpu_get_fsr(CPUSPARCState *env) { - return env->fsr; + target_ulong fsr = env->fsr; + + /* VER is kept completely separate until re-assembly. */ + fsr |= env->def.fpu_version; + + return fsr; } target_ulong helper_get_fsr(CPUSPARCState *env) @@ -361,7 +366,7 @@ static void set_fsr_nonsplit(CPUSPARCState *env, target_ulong fsr) { int rnd_mode; - env->fsr = fsr; + env->fsr = fsr & ~FSR_VER_MASK; switch (fsr & FSR_RD_MASK) { case FSR_RD_NEAREST: From efeb8b07502570aa133a87f7430dd919a9f5c37a Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Fri, 3 Nov 2023 10:38:36 -0700 Subject: [PATCH 52/58] target/sparc: Clear cexc and ftt in do_check_ieee_exceptions Don't do the clearing explicitly before each FPop, rather do it as part of the rest of exception handling. Signed-off-by: Richard Henderson Tested-by: Mark Cave-Ayland Acked-by: Mark Cave-Ayland Message-Id: <20231103173841.33651-18-richard.henderson@linaro.org> --- target/sparc/fop_helper.c | 2 ++ target/sparc/translate.c | 16 ---------------- 2 files changed, 2 insertions(+), 16 deletions(-) diff --git a/target/sparc/fop_helper.c b/target/sparc/fop_helper.c index 22b412adb5..64f20e78f1 100644 --- a/target/sparc/fop_helper.c +++ b/target/sparc/fop_helper.c @@ -50,6 +50,8 @@ static target_ulong do_check_ieee_exceptions(CPUSPARCState *env, uintptr_t ra) target_ulong status = get_float_exception_flags(&env->fp_status); target_ulong fsr = env->fsr; + fsr &= FSR_FTT_CEXC_NMASK; + if (unlikely(status)) { /* Keep exception flags clear for next time. */ set_float_exception_flags(0, &env->fp_status); diff --git a/target/sparc/translate.c b/target/sparc/translate.c index da4f167fa6..67bac6f65f 100644 --- a/target/sparc/translate.c +++ b/target/sparc/translate.c @@ -4524,7 +4524,6 @@ static bool do_env_ff(DisasContext *dc, arg_r_r *a, return true; } - gen_op_clear_ieee_excp_and_FTT(); tmp = gen_load_fpr_F(dc, a->rs); func(tmp, tcg_env, tmp); gen_helper_check_ieee_exceptions(cpu_fsr, tcg_env); @@ -4546,7 +4545,6 @@ static bool do_env_fd(DisasContext *dc, arg_r_r *a, return true; } - gen_op_clear_ieee_excp_and_FTT(); dst = tcg_temp_new_i32(); src = gen_load_fpr_D(dc, a->rs); func(dst, tcg_env, src); @@ -4590,7 +4588,6 @@ static bool do_env_dd(DisasContext *dc, arg_r_r *a, return true; } - gen_op_clear_ieee_excp_and_FTT(); dst = gen_dest_fpr_D(dc, a->rd); src = gen_load_fpr_D(dc, a->rs); func(dst, tcg_env, src); @@ -4613,7 +4610,6 @@ static bool do_env_df(DisasContext *dc, arg_r_r *a, return true; } - gen_op_clear_ieee_excp_and_FTT(); dst = gen_dest_fpr_D(dc, a->rd); src = gen_load_fpr_F(dc, a->rs); func(dst, tcg_env, src); @@ -4661,8 +4657,6 @@ static bool do_env_qq(DisasContext *dc, arg_r_r *a, return true; } - gen_op_clear_ieee_excp_and_FTT(); - t = gen_load_fpr_Q(dc, a->rs); func(t, tcg_env, t); gen_helper_check_ieee_exceptions(cpu_fsr, tcg_env); @@ -4685,7 +4679,6 @@ static bool do_env_fq(DisasContext *dc, arg_r_r *a, return true; } - gen_op_clear_ieee_excp_and_FTT(); src = gen_load_fpr_Q(dc, a->rs); dst = tcg_temp_new_i32(); func(dst, tcg_env, src); @@ -4710,7 +4703,6 @@ static bool do_env_dq(DisasContext *dc, arg_r_r *a, return true; } - gen_op_clear_ieee_excp_and_FTT(); src = gen_load_fpr_Q(dc, a->rs); dst = gen_dest_fpr_D(dc, a->rd); func(dst, tcg_env, src); @@ -4808,7 +4800,6 @@ static bool do_env_fff(DisasContext *dc, arg_r_r_r *a, return true; } - gen_op_clear_ieee_excp_and_FTT(); src1 = gen_load_fpr_F(dc, a->rs1); src2 = gen_load_fpr_F(dc, a->rs2); func(src1, tcg_env, src1, src2); @@ -4903,7 +4894,6 @@ static bool do_env_ddd(DisasContext *dc, arg_r_r_r *a, return true; } - gen_op_clear_ieee_excp_and_FTT(); dst = gen_dest_fpr_D(dc, a->rd); src1 = gen_load_fpr_D(dc, a->rs1); src2 = gen_load_fpr_D(dc, a->rs2); @@ -4930,7 +4920,6 @@ static bool trans_FsMULd(DisasContext *dc, arg_r_r_r *a) return raise_unimpfpop(dc); } - gen_op_clear_ieee_excp_and_FTT(); dst = gen_dest_fpr_D(dc, a->rd); src1 = gen_load_fpr_F(dc, a->rs1); src2 = gen_load_fpr_F(dc, a->rs2); @@ -4972,7 +4961,6 @@ static bool do_env_qqq(DisasContext *dc, arg_r_r_r *a, return true; } - gen_op_clear_ieee_excp_and_FTT(); src1 = gen_load_fpr_Q(dc, a->rs1); src2 = gen_load_fpr_Q(dc, a->rs2); func(src1, tcg_env, src1, src2); @@ -4998,7 +4986,6 @@ static bool trans_FdMULq(DisasContext *dc, arg_r_r_r *a) return true; } - gen_op_clear_ieee_excp_and_FTT(); src1 = gen_load_fpr_D(dc, a->rs1); src2 = gen_load_fpr_D(dc, a->rs2); dst = tcg_temp_new_i128(); @@ -5087,7 +5074,6 @@ static bool do_fcmps(DisasContext *dc, arg_FCMPs *a, bool e) return true; } - gen_op_clear_ieee_excp_and_FTT(); src1 = gen_load_fpr_F(dc, a->rs1); src2 = gen_load_fpr_F(dc, a->rs2); if (e) { @@ -5112,7 +5098,6 @@ static bool do_fcmpd(DisasContext *dc, arg_FCMPd *a, bool e) return true; } - gen_op_clear_ieee_excp_and_FTT(); src1 = gen_load_fpr_D(dc, a->rs1); src2 = gen_load_fpr_D(dc, a->rs2); if (e) { @@ -5140,7 +5125,6 @@ static bool do_fcmpq(DisasContext *dc, arg_FCMPq *a, bool e) return true; } - gen_op_clear_ieee_excp_and_FTT(); src1 = gen_load_fpr_Q(dc, a->rs1); src2 = gen_load_fpr_Q(dc, a->rs2); if (e) { From db71391123dccccc2c8632a6f5ad451369a35391 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Fri, 3 Nov 2023 10:38:37 -0700 Subject: [PATCH 53/58] target/sparc: Merge check_ieee_exceptions with FPop helpers If an exception is to be raised, the destination fp register should be unmodified. The current implementation is incorrect, in that double results will be written back before calling gen_helper_check_ieee_exceptions, despite the placement of gen_store_fpr_D, since gen_dest_fpr_D returns cpu_fpr[]. We can simplify the entire implementation by having each FPOp helper call check_ieee_exceptions. For the moment this requires that all FPop helpers write to the TCG global cpu_fsr, so remove TCG_CALL_NO_WG from the DEF_HELPER_FLAGS_*. Signed-off-by: Richard Henderson Tested-by: Mark Cave-Ayland Acked-by: Mark Cave-Ayland Message-Id: <20231103173841.33651-19-richard.henderson@linaro.org> --- target/sparc/fop_helper.c | 215 ++++++++++++++++++++++++++++---------- target/sparc/helper.h | 119 +++++++++++---------- target/sparc/translate.c | 14 --- 3 files changed, 219 insertions(+), 129 deletions(-) diff --git a/target/sparc/fop_helper.c b/target/sparc/fop_helper.c index 64f20e78f1..755117ea08 100644 --- a/target/sparc/fop_helper.c +++ b/target/sparc/fop_helper.c @@ -45,7 +45,7 @@ static inline Int128 f128_ret(float128 f) return u.i; } -static target_ulong do_check_ieee_exceptions(CPUSPARCState *env, uintptr_t ra) +static void check_ieee_exceptions(CPUSPARCState *env, uintptr_t ra) { target_ulong status = get_float_exception_flags(&env->fp_status); target_ulong fsr = env->fsr; @@ -89,162 +89,265 @@ static target_ulong do_check_ieee_exceptions(CPUSPARCState *env, uintptr_t ra) } } - return fsr; + env->fsr = fsr; } -target_ulong helper_check_ieee_exceptions(CPUSPARCState *env) +float32 helper_fadds(CPUSPARCState *env, float32 src1, float32 src2) { - return do_check_ieee_exceptions(env, GETPC()); + float32 ret = float32_add(src1, src2, &env->fp_status); + check_ieee_exceptions(env, GETPC()); + return ret; } -#define F_BINOP(name) \ - float32 helper_f ## name ## s (CPUSPARCState *env, float32 src1, \ - float32 src2) \ - { \ - return float32_ ## name (src1, src2, &env->fp_status); \ - } \ - float64 helper_f ## name ## d (CPUSPARCState * env, float64 src1,\ - float64 src2) \ - { \ - return float64_ ## name (src1, src2, &env->fp_status); \ - } \ - Int128 helper_f ## name ## q(CPUSPARCState * env, Int128 src1, \ - Int128 src2) \ - { \ - return f128_ret(float128_ ## name (f128_in(src1), f128_in(src2), \ - &env->fp_status)); \ - } +float32 helper_fsubs(CPUSPARCState *env, float32 src1, float32 src2) +{ + float32 ret = float32_sub(src1, src2, &env->fp_status); + check_ieee_exceptions(env, GETPC()); + return ret; +} -F_BINOP(add); -F_BINOP(sub); -F_BINOP(mul); -F_BINOP(div); -#undef F_BINOP +float32 helper_fmuls(CPUSPARCState *env, float32 src1, float32 src2) +{ + float32 ret = float32_mul(src1, src2, &env->fp_status); + check_ieee_exceptions(env, GETPC()); + return ret; +} + +float32 helper_fdivs(CPUSPARCState *env, float32 src1, float32 src2) +{ + float32 ret = float32_div(src1, src2, &env->fp_status); + check_ieee_exceptions(env, GETPC()); + return ret; +} + +float64 helper_faddd(CPUSPARCState *env, float64 src1, float64 src2) +{ + float64 ret = float64_add(src1, src2, &env->fp_status); + check_ieee_exceptions(env, GETPC()); + return ret; +} + +float64 helper_fsubd(CPUSPARCState *env, float64 src1, float64 src2) +{ + float64 ret = float64_sub(src1, src2, &env->fp_status); + check_ieee_exceptions(env, GETPC()); + return ret; +} + +float64 helper_fmuld(CPUSPARCState *env, float64 src1, float64 src2) +{ + float64 ret = float64_mul(src1, src2, &env->fp_status); + check_ieee_exceptions(env, GETPC()); + return ret; +} + +float64 helper_fdivd(CPUSPARCState *env, float64 src1, float64 src2) +{ + float64 ret = float64_div(src1, src2, &env->fp_status); + check_ieee_exceptions(env, GETPC()); + return ret; +} + +Int128 helper_faddq(CPUSPARCState *env, Int128 src1, Int128 src2) +{ + float128 ret = float128_add(f128_in(src1), f128_in(src2), &env->fp_status); + check_ieee_exceptions(env, GETPC()); + return f128_ret(ret); +} + +Int128 helper_fsubq(CPUSPARCState *env, Int128 src1, Int128 src2) +{ + float128 ret = float128_sub(f128_in(src1), f128_in(src2), &env->fp_status); + check_ieee_exceptions(env, GETPC()); + return f128_ret(ret); +} + +Int128 helper_fmulq(CPUSPARCState *env, Int128 src1, Int128 src2) +{ + float128 ret = float128_mul(f128_in(src1), f128_in(src2), &env->fp_status); + check_ieee_exceptions(env, GETPC()); + return f128_ret(ret); +} + +Int128 helper_fdivq(CPUSPARCState *env, Int128 src1, Int128 src2) +{ + float128 ret = float128_div(f128_in(src1), f128_in(src2), &env->fp_status); + check_ieee_exceptions(env, GETPC()); + return f128_ret(ret); +} float64 helper_fsmuld(CPUSPARCState *env, float32 src1, float32 src2) { - return float64_mul(float32_to_float64(src1, &env->fp_status), - float32_to_float64(src2, &env->fp_status), - &env->fp_status); + float64 ret = float64_mul(float32_to_float64(src1, &env->fp_status), + float32_to_float64(src2, &env->fp_status), + &env->fp_status); + check_ieee_exceptions(env, GETPC()); + return ret; } Int128 helper_fdmulq(CPUSPARCState *env, float64 src1, float64 src2) { - return f128_ret(float128_mul(float64_to_float128(src1, &env->fp_status), - float64_to_float128(src2, &env->fp_status), - &env->fp_status)); + float128 ret = float128_mul(float64_to_float128(src1, &env->fp_status), + float64_to_float128(src2, &env->fp_status), + &env->fp_status); + check_ieee_exceptions(env, GETPC()); + return f128_ret(ret); } /* Integer to float conversion. */ float32 helper_fitos(CPUSPARCState *env, int32_t src) { - return int32_to_float32(src, &env->fp_status); + float32 ret = int32_to_float32(src, &env->fp_status); + check_ieee_exceptions(env, GETPC()); + return ret; } float64 helper_fitod(CPUSPARCState *env, int32_t src) { - return int32_to_float64(src, &env->fp_status); + float64 ret = int32_to_float64(src, &env->fp_status); + check_ieee_exceptions(env, GETPC()); + return ret; } Int128 helper_fitoq(CPUSPARCState *env, int32_t src) { - return f128_ret(int32_to_float128(src, &env->fp_status)); + float128 ret = int32_to_float128(src, &env->fp_status); + check_ieee_exceptions(env, GETPC()); + return f128_ret(ret); } #ifdef TARGET_SPARC64 float32 helper_fxtos(CPUSPARCState *env, int64_t src) { - return int64_to_float32(src, &env->fp_status); + float32 ret = int64_to_float32(src, &env->fp_status); + check_ieee_exceptions(env, GETPC()); + return ret; } float64 helper_fxtod(CPUSPARCState *env, int64_t src) { - return int64_to_float64(src, &env->fp_status); + float64 ret = int64_to_float64(src, &env->fp_status); + check_ieee_exceptions(env, GETPC()); + return ret; } Int128 helper_fxtoq(CPUSPARCState *env, int64_t src) { - return f128_ret(int64_to_float128(src, &env->fp_status)); + float128 ret = int64_to_float128(src, &env->fp_status); + check_ieee_exceptions(env, GETPC()); + return f128_ret(ret); } #endif /* floating point conversion */ float32 helper_fdtos(CPUSPARCState *env, float64 src) { - return float64_to_float32(src, &env->fp_status); + float32 ret = float64_to_float32(src, &env->fp_status); + check_ieee_exceptions(env, GETPC()); + return ret; } float64 helper_fstod(CPUSPARCState *env, float32 src) { - return float32_to_float64(src, &env->fp_status); + float64 ret = float32_to_float64(src, &env->fp_status); + check_ieee_exceptions(env, GETPC()); + return ret; } float32 helper_fqtos(CPUSPARCState *env, Int128 src) { - return float128_to_float32(f128_in(src), &env->fp_status); + float32 ret = float128_to_float32(f128_in(src), &env->fp_status); + check_ieee_exceptions(env, GETPC()); + return ret; } Int128 helper_fstoq(CPUSPARCState *env, float32 src) { - return f128_ret(float32_to_float128(src, &env->fp_status)); + float128 ret = float32_to_float128(src, &env->fp_status); + check_ieee_exceptions(env, GETPC()); + return f128_ret(ret); } float64 helper_fqtod(CPUSPARCState *env, Int128 src) { - return float128_to_float64(f128_in(src), &env->fp_status); + float64 ret = float128_to_float64(f128_in(src), &env->fp_status); + check_ieee_exceptions(env, GETPC()); + return ret; } Int128 helper_fdtoq(CPUSPARCState *env, float64 src) { - return f128_ret(float64_to_float128(src, &env->fp_status)); + float128 ret = float64_to_float128(src, &env->fp_status); + check_ieee_exceptions(env, GETPC()); + return f128_ret(ret); } /* Float to integer conversion. */ int32_t helper_fstoi(CPUSPARCState *env, float32 src) { - return float32_to_int32_round_to_zero(src, &env->fp_status); + int32_t ret = float32_to_int32_round_to_zero(src, &env->fp_status); + check_ieee_exceptions(env, GETPC()); + return ret; } int32_t helper_fdtoi(CPUSPARCState *env, float64 src) { - return float64_to_int32_round_to_zero(src, &env->fp_status); + int32_t ret = float64_to_int32_round_to_zero(src, &env->fp_status); + check_ieee_exceptions(env, GETPC()); + return ret; } int32_t helper_fqtoi(CPUSPARCState *env, Int128 src) { - return float128_to_int32_round_to_zero(f128_in(src), &env->fp_status); + int32_t ret = float128_to_int32_round_to_zero(f128_in(src), + &env->fp_status); + check_ieee_exceptions(env, GETPC()); + return ret; } #ifdef TARGET_SPARC64 int64_t helper_fstox(CPUSPARCState *env, float32 src) { - return float32_to_int64_round_to_zero(src, &env->fp_status); + int64_t ret = float32_to_int64_round_to_zero(src, &env->fp_status); + check_ieee_exceptions(env, GETPC()); + return ret; } int64_t helper_fdtox(CPUSPARCState *env, float64 src) { - return float64_to_int64_round_to_zero(src, &env->fp_status); + int64_t ret = float64_to_int64_round_to_zero(src, &env->fp_status); + check_ieee_exceptions(env, GETPC()); + return ret; } int64_t helper_fqtox(CPUSPARCState *env, Int128 src) { - return float128_to_int64_round_to_zero(f128_in(src), &env->fp_status); + int64_t ret = float128_to_int64_round_to_zero(f128_in(src), + &env->fp_status); + check_ieee_exceptions(env, GETPC()); + return ret; } #endif float32 helper_fsqrts(CPUSPARCState *env, float32 src) { - return float32_sqrt(src, &env->fp_status); + float32 ret = float32_sqrt(src, &env->fp_status); + check_ieee_exceptions(env, GETPC()); + return ret; } float64 helper_fsqrtd(CPUSPARCState *env, float64 src) { - return float64_sqrt(src, &env->fp_status); + float64 ret = float64_sqrt(src, &env->fp_status); + check_ieee_exceptions(env, GETPC()); + return ret; } Int128 helper_fsqrtq(CPUSPARCState *env, Int128 src) { - return f128_ret(float128_sqrt(f128_in(src), &env->fp_status)); + float128 ret = float128_sqrt(f128_in(src), &env->fp_status); + check_ieee_exceptions(env, GETPC()); + return f128_ret(ret); } #define GEN_FCMP(name, size, FS, E) \ @@ -261,7 +364,8 @@ Int128 helper_fsqrtq(CPUSPARCState *env, Int128 src) ret = glue(size, _compare_quiet)(reg1, reg2, \ &env->fp_status); \ } \ - fsr = do_check_ieee_exceptions(env, GETPC()); \ + check_ieee_exceptions(env, GETPC()); \ + fsr = env->fsr; \ switch (ret) { \ case float_relation_unordered: \ fsr |= (FSR_FCC1 | FSR_FCC0) << FS; \ @@ -292,7 +396,8 @@ Int128 helper_fsqrtq(CPUSPARCState *env, Int128 src) ret = glue(size, _compare_quiet)(src1, src2, \ &env->fp_status); \ } \ - fsr = do_check_ieee_exceptions(env, GETPC()); \ + check_ieee_exceptions(env, GETPC()); \ + fsr = env->fsr; \ switch (ret) { \ case float_relation_unordered: \ fsr |= (FSR_FCC1 | FSR_FCC0) << FS; \ diff --git a/target/sparc/helper.h b/target/sparc/helper.h index cc8db50d75..7c688edd62 100644 --- a/target/sparc/helper.h +++ b/target/sparc/helper.h @@ -35,81 +35,80 @@ DEF_HELPER_3(tsubcctv, tl, env, tl, tl) DEF_HELPER_FLAGS_4(ld_asi, TCG_CALL_NO_WG, i64, env, tl, int, i32) DEF_HELPER_FLAGS_5(st_asi, TCG_CALL_NO_WG, void, env, tl, i64, int, i32) #endif -DEF_HELPER_FLAGS_1(check_ieee_exceptions, TCG_CALL_NO_WG, tl, env) DEF_HELPER_FLAGS_1(get_fsr, TCG_CALL_NO_WG_SE, tl, env) DEF_HELPER_FLAGS_2(set_fsr, TCG_CALL_NO_RWG, void, env, tl) -DEF_HELPER_FLAGS_2(fsqrts, TCG_CALL_NO_RWG, f32, env, f32) -DEF_HELPER_FLAGS_2(fsqrtd, TCG_CALL_NO_RWG, f64, env, f64) -DEF_HELPER_FLAGS_3(fcmps, TCG_CALL_NO_WG, tl, env, f32, f32) -DEF_HELPER_FLAGS_3(fcmpd, TCG_CALL_NO_WG, tl, env, f64, f64) -DEF_HELPER_FLAGS_3(fcmpes, TCG_CALL_NO_WG, tl, env, f32, f32) -DEF_HELPER_FLAGS_3(fcmped, TCG_CALL_NO_WG, tl, env, f64, f64) -DEF_HELPER_FLAGS_2(fsqrtq, TCG_CALL_NO_RWG, i128, env, i128) -DEF_HELPER_FLAGS_3(fcmpq, TCG_CALL_NO_WG, tl, env, i128, i128) -DEF_HELPER_FLAGS_3(fcmpeq, TCG_CALL_NO_WG, tl, env, i128, i128) +DEF_HELPER_FLAGS_2(fsqrts, 0, f32, env, f32) +DEF_HELPER_FLAGS_2(fsqrtd, 0, f64, env, f64) +DEF_HELPER_FLAGS_2(fsqrtq, 0, i128, env, i128) +DEF_HELPER_FLAGS_3(fcmps, 0, tl, env, f32, f32) +DEF_HELPER_FLAGS_3(fcmpd, 0, tl, env, f64, f64) +DEF_HELPER_FLAGS_3(fcmpes, 0, tl, env, f32, f32) +DEF_HELPER_FLAGS_3(fcmped, 0, tl, env, f64, f64) +DEF_HELPER_FLAGS_3(fcmpq, 0, tl, env, i128, i128) +DEF_HELPER_FLAGS_3(fcmpeq, 0, tl, env, i128, i128) #ifdef TARGET_SPARC64 -DEF_HELPER_FLAGS_3(fcmps_fcc1, TCG_CALL_NO_WG, tl, env, f32, f32) -DEF_HELPER_FLAGS_3(fcmps_fcc2, TCG_CALL_NO_WG, tl, env, f32, f32) -DEF_HELPER_FLAGS_3(fcmps_fcc3, TCG_CALL_NO_WG, tl, env, f32, f32) -DEF_HELPER_FLAGS_3(fcmpd_fcc1, TCG_CALL_NO_WG, tl, env, f64, f64) -DEF_HELPER_FLAGS_3(fcmpd_fcc2, TCG_CALL_NO_WG, tl, env, f64, f64) -DEF_HELPER_FLAGS_3(fcmpd_fcc3, TCG_CALL_NO_WG, tl, env, f64, f64) -DEF_HELPER_FLAGS_3(fcmpes_fcc1, TCG_CALL_NO_WG, tl, env, f32, f32) -DEF_HELPER_FLAGS_3(fcmpes_fcc2, TCG_CALL_NO_WG, tl, env, f32, f32) -DEF_HELPER_FLAGS_3(fcmpes_fcc3, TCG_CALL_NO_WG, tl, env, f32, f32) -DEF_HELPER_FLAGS_3(fcmped_fcc1, TCG_CALL_NO_WG, tl, env, f64, f64) -DEF_HELPER_FLAGS_3(fcmped_fcc2, TCG_CALL_NO_WG, tl, env, f64, f64) -DEF_HELPER_FLAGS_3(fcmped_fcc3, TCG_CALL_NO_WG, tl, env, f64, f64) -DEF_HELPER_FLAGS_3(fcmpq_fcc1, TCG_CALL_NO_WG, tl, env, i128, i128) -DEF_HELPER_FLAGS_3(fcmpq_fcc2, TCG_CALL_NO_WG, tl, env, i128, i128) -DEF_HELPER_FLAGS_3(fcmpq_fcc3, TCG_CALL_NO_WG, tl, env, i128, i128) -DEF_HELPER_FLAGS_3(fcmpeq_fcc1, TCG_CALL_NO_WG, tl, env, i128, i128) -DEF_HELPER_FLAGS_3(fcmpeq_fcc2, TCG_CALL_NO_WG, tl, env, i128, i128) -DEF_HELPER_FLAGS_3(fcmpeq_fcc3, TCG_CALL_NO_WG, tl, env, i128, i128) +DEF_HELPER_FLAGS_3(fcmps_fcc1, 0, tl, env, f32, f32) +DEF_HELPER_FLAGS_3(fcmps_fcc2, 0, tl, env, f32, f32) +DEF_HELPER_FLAGS_3(fcmps_fcc3, 0, tl, env, f32, f32) +DEF_HELPER_FLAGS_3(fcmpd_fcc1, 0, tl, env, f64, f64) +DEF_HELPER_FLAGS_3(fcmpd_fcc2, 0, tl, env, f64, f64) +DEF_HELPER_FLAGS_3(fcmpd_fcc3, 0, tl, env, f64, f64) +DEF_HELPER_FLAGS_3(fcmpes_fcc1, 0, tl, env, f32, f32) +DEF_HELPER_FLAGS_3(fcmpes_fcc2, 0, tl, env, f32, f32) +DEF_HELPER_FLAGS_3(fcmpes_fcc3, 0, tl, env, f32, f32) +DEF_HELPER_FLAGS_3(fcmped_fcc1, 0, tl, env, f64, f64) +DEF_HELPER_FLAGS_3(fcmped_fcc2, 0, tl, env, f64, f64) +DEF_HELPER_FLAGS_3(fcmped_fcc3, 0, tl, env, f64, f64) +DEF_HELPER_FLAGS_3(fcmpq_fcc1, 0, tl, env, i128, i128) +DEF_HELPER_FLAGS_3(fcmpq_fcc2, 0, tl, env, i128, i128) +DEF_HELPER_FLAGS_3(fcmpq_fcc3, 0, tl, env, i128, i128) +DEF_HELPER_FLAGS_3(fcmpeq_fcc1, 0, tl, env, i128, i128) +DEF_HELPER_FLAGS_3(fcmpeq_fcc2, 0, tl, env, i128, i128) +DEF_HELPER_FLAGS_3(fcmpeq_fcc3, 0, tl, env, i128, i128) #endif DEF_HELPER_2(raise_exception, noreturn, env, int) -DEF_HELPER_FLAGS_3(faddd, TCG_CALL_NO_RWG, f64, env, f64, f64) -DEF_HELPER_FLAGS_3(fsubd, TCG_CALL_NO_RWG, f64, env, f64, f64) -DEF_HELPER_FLAGS_3(fmuld, TCG_CALL_NO_RWG, f64, env, f64, f64) -DEF_HELPER_FLAGS_3(fdivd, TCG_CALL_NO_RWG, f64, env, f64, f64) +DEF_HELPER_FLAGS_3(faddd, 0, f64, env, f64, f64) +DEF_HELPER_FLAGS_3(fsubd, 0, f64, env, f64, f64) +DEF_HELPER_FLAGS_3(fmuld, 0, f64, env, f64, f64) +DEF_HELPER_FLAGS_3(fdivd, 0, f64, env, f64, f64) -DEF_HELPER_FLAGS_3(faddq, TCG_CALL_NO_RWG, i128, env, i128, i128) -DEF_HELPER_FLAGS_3(fsubq, TCG_CALL_NO_RWG, i128, env, i128, i128) -DEF_HELPER_FLAGS_3(fmulq, TCG_CALL_NO_RWG, i128, env, i128, i128) -DEF_HELPER_FLAGS_3(fdivq, TCG_CALL_NO_RWG, i128, env, i128, i128) +DEF_HELPER_FLAGS_3(faddq, 0, i128, env, i128, i128) +DEF_HELPER_FLAGS_3(fsubq, 0, i128, env, i128, i128) +DEF_HELPER_FLAGS_3(fmulq, 0, i128, env, i128, i128) +DEF_HELPER_FLAGS_3(fdivq, 0, i128, env, i128, i128) -DEF_HELPER_FLAGS_3(fadds, TCG_CALL_NO_RWG, f32, env, f32, f32) -DEF_HELPER_FLAGS_3(fsubs, TCG_CALL_NO_RWG, f32, env, f32, f32) -DEF_HELPER_FLAGS_3(fmuls, TCG_CALL_NO_RWG, f32, env, f32, f32) -DEF_HELPER_FLAGS_3(fdivs, TCG_CALL_NO_RWG, f32, env, f32, f32) +DEF_HELPER_FLAGS_3(fadds, 0, f32, env, f32, f32) +DEF_HELPER_FLAGS_3(fsubs, 0, f32, env, f32, f32) +DEF_HELPER_FLAGS_3(fmuls, 0, f32, env, f32, f32) +DEF_HELPER_FLAGS_3(fdivs, 0, f32, env, f32, f32) -DEF_HELPER_FLAGS_3(fsmuld, TCG_CALL_NO_RWG, f64, env, f32, f32) -DEF_HELPER_FLAGS_3(fdmulq, TCG_CALL_NO_RWG, i128, env, f64, f64) +DEF_HELPER_FLAGS_3(fsmuld, 0, f64, env, f32, f32) +DEF_HELPER_FLAGS_3(fdmulq, 0, i128, env, f64, f64) -DEF_HELPER_FLAGS_2(fitod, TCG_CALL_NO_RWG_SE, f64, env, s32) -DEF_HELPER_FLAGS_2(fitoq, TCG_CALL_NO_RWG, i128, env, s32) +DEF_HELPER_FLAGS_2(fitod, 0, f64, env, s32) +DEF_HELPER_FLAGS_2(fitoq, 0, i128, env, s32) -DEF_HELPER_FLAGS_2(fitos, TCG_CALL_NO_RWG, f32, env, s32) +DEF_HELPER_FLAGS_2(fitos, 0, f32, env, s32) #ifdef TARGET_SPARC64 -DEF_HELPER_FLAGS_2(fxtos, TCG_CALL_NO_RWG, f32, env, s64) -DEF_HELPER_FLAGS_2(fxtod, TCG_CALL_NO_RWG, f64, env, s64) -DEF_HELPER_FLAGS_2(fxtoq, TCG_CALL_NO_RWG, i128, env, s64) +DEF_HELPER_FLAGS_2(fxtos, 0, f32, env, s64) +DEF_HELPER_FLAGS_2(fxtod, 0, f64, env, s64) +DEF_HELPER_FLAGS_2(fxtoq, 0, i128, env, s64) #endif -DEF_HELPER_FLAGS_2(fdtos, TCG_CALL_NO_RWG, f32, env, f64) -DEF_HELPER_FLAGS_2(fstod, TCG_CALL_NO_RWG, f64, env, f32) -DEF_HELPER_FLAGS_2(fqtos, TCG_CALL_NO_RWG, f32, env, i128) -DEF_HELPER_FLAGS_2(fstoq, TCG_CALL_NO_RWG, i128, env, f32) -DEF_HELPER_FLAGS_2(fqtod, TCG_CALL_NO_RWG, f64, env, i128) -DEF_HELPER_FLAGS_2(fdtoq, TCG_CALL_NO_RWG, i128, env, f64) -DEF_HELPER_FLAGS_2(fstoi, TCG_CALL_NO_RWG, s32, env, f32) -DEF_HELPER_FLAGS_2(fdtoi, TCG_CALL_NO_RWG, s32, env, f64) -DEF_HELPER_FLAGS_2(fqtoi, TCG_CALL_NO_RWG, s32, env, i128) +DEF_HELPER_FLAGS_2(fdtos, 0, f32, env, f64) +DEF_HELPER_FLAGS_2(fstod, 0, f64, env, f32) +DEF_HELPER_FLAGS_2(fqtos, 0, f32, env, i128) +DEF_HELPER_FLAGS_2(fstoq, 0, i128, env, f32) +DEF_HELPER_FLAGS_2(fqtod, 0, f64, env, i128) +DEF_HELPER_FLAGS_2(fdtoq, 0, i128, env, f64) +DEF_HELPER_FLAGS_2(fstoi, 0, s32, env, f32) +DEF_HELPER_FLAGS_2(fdtoi, 0, s32, env, f64) +DEF_HELPER_FLAGS_2(fqtoi, 0, s32, env, i128) #ifdef TARGET_SPARC64 -DEF_HELPER_FLAGS_2(fstox, TCG_CALL_NO_RWG, s64, env, f32) -DEF_HELPER_FLAGS_2(fdtox, TCG_CALL_NO_RWG, s64, env, f64) -DEF_HELPER_FLAGS_2(fqtox, TCG_CALL_NO_RWG, s64, env, i128) +DEF_HELPER_FLAGS_2(fstox, 0, s64, env, f32) +DEF_HELPER_FLAGS_2(fdtox, 0, s64, env, f64) +DEF_HELPER_FLAGS_2(fqtox, 0, s64, env, i128) DEF_HELPER_FLAGS_2(fpmerge, TCG_CALL_NO_RWG_SE, i64, i64, i64) DEF_HELPER_FLAGS_2(fmul8x16, TCG_CALL_NO_RWG_SE, i64, i64, i64) diff --git a/target/sparc/translate.c b/target/sparc/translate.c index 67bac6f65f..25f93ec44a 100644 --- a/target/sparc/translate.c +++ b/target/sparc/translate.c @@ -4526,7 +4526,6 @@ static bool do_env_ff(DisasContext *dc, arg_r_r *a, tmp = gen_load_fpr_F(dc, a->rs); func(tmp, tcg_env, tmp); - gen_helper_check_ieee_exceptions(cpu_fsr, tcg_env); gen_store_fpr_F(dc, a->rd, tmp); return advance_pc(dc); } @@ -4548,7 +4547,6 @@ static bool do_env_fd(DisasContext *dc, arg_r_r *a, dst = tcg_temp_new_i32(); src = gen_load_fpr_D(dc, a->rs); func(dst, tcg_env, src); - gen_helper_check_ieee_exceptions(cpu_fsr, tcg_env); gen_store_fpr_F(dc, a->rd, dst); return advance_pc(dc); } @@ -4591,7 +4589,6 @@ static bool do_env_dd(DisasContext *dc, arg_r_r *a, dst = gen_dest_fpr_D(dc, a->rd); src = gen_load_fpr_D(dc, a->rs); func(dst, tcg_env, src); - gen_helper_check_ieee_exceptions(cpu_fsr, tcg_env); gen_store_fpr_D(dc, a->rd, dst); return advance_pc(dc); } @@ -4613,7 +4610,6 @@ static bool do_env_df(DisasContext *dc, arg_r_r *a, dst = gen_dest_fpr_D(dc, a->rd); src = gen_load_fpr_F(dc, a->rs); func(dst, tcg_env, src); - gen_helper_check_ieee_exceptions(cpu_fsr, tcg_env); gen_store_fpr_D(dc, a->rd, dst); return advance_pc(dc); } @@ -4659,7 +4655,6 @@ static bool do_env_qq(DisasContext *dc, arg_r_r *a, t = gen_load_fpr_Q(dc, a->rs); func(t, tcg_env, t); - gen_helper_check_ieee_exceptions(cpu_fsr, tcg_env); gen_store_fpr_Q(dc, a->rd, t); return advance_pc(dc); } @@ -4682,7 +4677,6 @@ static bool do_env_fq(DisasContext *dc, arg_r_r *a, src = gen_load_fpr_Q(dc, a->rs); dst = tcg_temp_new_i32(); func(dst, tcg_env, src); - gen_helper_check_ieee_exceptions(cpu_fsr, tcg_env); gen_store_fpr_F(dc, a->rd, dst); return advance_pc(dc); } @@ -4706,7 +4700,6 @@ static bool do_env_dq(DisasContext *dc, arg_r_r *a, src = gen_load_fpr_Q(dc, a->rs); dst = gen_dest_fpr_D(dc, a->rd); func(dst, tcg_env, src); - gen_helper_check_ieee_exceptions(cpu_fsr, tcg_env); gen_store_fpr_D(dc, a->rd, dst); return advance_pc(dc); } @@ -4727,7 +4720,6 @@ static bool do_env_qf(DisasContext *dc, arg_r_r *a, return true; } - gen_op_clear_ieee_excp_and_FTT(); src = gen_load_fpr_F(dc, a->rs); dst = tcg_temp_new_i128(); func(dst, tcg_env, src); @@ -4751,7 +4743,6 @@ static bool do_env_qd(DisasContext *dc, arg_r_r *a, return true; } - gen_op_clear_ieee_excp_and_FTT(); src = gen_load_fpr_D(dc, a->rs); dst = tcg_temp_new_i128(); func(dst, tcg_env, src); @@ -4803,7 +4794,6 @@ static bool do_env_fff(DisasContext *dc, arg_r_r_r *a, src1 = gen_load_fpr_F(dc, a->rs1); src2 = gen_load_fpr_F(dc, a->rs2); func(src1, tcg_env, src1, src2); - gen_helper_check_ieee_exceptions(cpu_fsr, tcg_env); gen_store_fpr_F(dc, a->rd, src1); return advance_pc(dc); } @@ -4898,7 +4888,6 @@ static bool do_env_ddd(DisasContext *dc, arg_r_r_r *a, src1 = gen_load_fpr_D(dc, a->rs1); src2 = gen_load_fpr_D(dc, a->rs2); func(dst, tcg_env, src1, src2); - gen_helper_check_ieee_exceptions(cpu_fsr, tcg_env); gen_store_fpr_D(dc, a->rd, dst); return advance_pc(dc); } @@ -4924,7 +4913,6 @@ static bool trans_FsMULd(DisasContext *dc, arg_r_r_r *a) src1 = gen_load_fpr_F(dc, a->rs1); src2 = gen_load_fpr_F(dc, a->rs2); gen_helper_fsmuld(dst, tcg_env, src1, src2); - gen_helper_check_ieee_exceptions(cpu_fsr, tcg_env); gen_store_fpr_D(dc, a->rd, dst); return advance_pc(dc); } @@ -4964,7 +4952,6 @@ static bool do_env_qqq(DisasContext *dc, arg_r_r_r *a, src1 = gen_load_fpr_Q(dc, a->rs1); src2 = gen_load_fpr_Q(dc, a->rs2); func(src1, tcg_env, src1, src2); - gen_helper_check_ieee_exceptions(cpu_fsr, tcg_env); gen_store_fpr_Q(dc, a->rd, src1); return advance_pc(dc); } @@ -4990,7 +4977,6 @@ static bool trans_FdMULq(DisasContext *dc, arg_r_r_r *a) src2 = gen_load_fpr_D(dc, a->rs2); dst = tcg_temp_new_i128(); gen_helper_fdmulq(dst, tcg_env, src1, src2); - gen_helper_check_ieee_exceptions(cpu_fsr, tcg_env); gen_store_fpr_Q(dc, a->rd, dst); return advance_pc(dc); } From 3590f01ed288c23594ba4a1c54a9c3b68081526f Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Fri, 3 Nov 2023 10:38:38 -0700 Subject: [PATCH 54/58] target/sparc: Split cexc and ftt from env->fsr These two fields are adjusted by all FPop insns. Having them separate makes it easier to set without masking. Signed-off-by: Richard Henderson Tested-by: Mark Cave-Ayland Acked-by: Mark Cave-Ayland Message-Id: <20231103173841.33651-20-richard.henderson@linaro.org> --- target/sparc/cpu.h | 7 +++++- target/sparc/fop_helper.c | 46 ++++++++++++++++++--------------------- target/sparc/helper.h | 2 +- target/sparc/translate.c | 31 ++++++++++++++++---------- 4 files changed, 48 insertions(+), 38 deletions(-) diff --git a/target/sparc/cpu.h b/target/sparc/cpu.h index 216155d231..c5be9e37de 100644 --- a/target/sparc/cpu.h +++ b/target/sparc/cpu.h @@ -176,6 +176,7 @@ enum { #define FSR_DZM (1ULL << 24) #define FSR_NXM (1ULL << 23) #define FSR_TEM_MASK (FSR_NVM | FSR_OFM | FSR_UFM | FSR_DZM | FSR_NXM) +#define FSR_TEM_SHIFT 23 #define FSR_NVA (1ULL << 9) #define FSR_OFA (1ULL << 8) @@ -183,6 +184,7 @@ enum { #define FSR_DZA (1ULL << 6) #define FSR_NXA (1ULL << 5) #define FSR_AEXC_MASK (FSR_NVA | FSR_OFA | FSR_UFA | FSR_DZA | FSR_NXA) +#define FSR_AEXC_SHIFT 5 #define FSR_NVC (1ULL << 4) #define FSR_OFC (1ULL << 3) @@ -464,7 +466,10 @@ struct CPUArchState { target_ulong cond; /* conditional branch result (XXX: save it in a temporary register when possible) */ - target_ulong fsr; /* FPU state register */ + /* FPU State Register, in parts */ + target_ulong fsr; /* rm, tem, aexc, fcc* */ + uint32_t fsr_cexc_ftt; /* cexc, ftt */ + CPU_DoubleU fpr[TARGET_DPREGS]; /* floating point registers */ uint32_t cwp; /* index of current register window (extracted from PSR) */ diff --git a/target/sparc/fop_helper.c b/target/sparc/fop_helper.c index 755117ea08..ac30f88810 100644 --- a/target/sparc/fop_helper.c +++ b/target/sparc/fop_helper.c @@ -48,9 +48,7 @@ static inline Int128 f128_ret(float128 f) static void check_ieee_exceptions(CPUSPARCState *env, uintptr_t ra) { target_ulong status = get_float_exception_flags(&env->fp_status); - target_ulong fsr = env->fsr; - - fsr &= FSR_FTT_CEXC_NMASK; + uint32_t cexc = 0; if (unlikely(status)) { /* Keep exception flags clear for next time. */ @@ -58,38 +56,33 @@ static void check_ieee_exceptions(CPUSPARCState *env, uintptr_t ra) /* Copy IEEE 754 flags into FSR */ if (status & float_flag_invalid) { - fsr |= FSR_NVC; + cexc |= FSR_NVC; } if (status & float_flag_overflow) { - fsr |= FSR_OFC; + cexc |= FSR_OFC; } if (status & float_flag_underflow) { - fsr |= FSR_UFC; + cexc |= FSR_UFC; } if (status & float_flag_divbyzero) { - fsr |= FSR_DZC; + cexc |= FSR_DZC; } if (status & float_flag_inexact) { - fsr |= FSR_NXC; + cexc |= FSR_NXC; } - if ((fsr & FSR_CEXC_MASK) & ((fsr & FSR_TEM_MASK) >> 23)) { - CPUState *cs = env_cpu(env); - - /* Unmasked exception, generate a trap. Note that while - the helper is marked as NO_WG, we can get away with - writing to cpu state along the exception path, since - TCG generated code will never see the write. */ - env->fsr = fsr | FSR_FTT_IEEE_EXCP; - cs->exception_index = TT_FP_EXCP; - cpu_loop_exit_restore(cs, ra); - } else { - /* Accumulate exceptions */ - fsr |= (fsr & FSR_CEXC_MASK) << 5; + if (cexc & (env->fsr >> FSR_TEM_SHIFT)) { + /* Unmasked exception, generate an IEEE trap. */ + env->fsr_cexc_ftt = cexc | FSR_FTT_IEEE_EXCP; + cpu_raise_exception_ra(env, TT_FP_EXCP, ra); } + + /* Accumulate exceptions */ + env->fsr |= cexc << FSR_AEXC_SHIFT; } - env->fsr = fsr; + /* No trap, so FTT is cleared. */ + env->fsr_cexc_ftt = cexc; } float32 helper_fadds(CPUSPARCState *env, float32 src1, float32 src2) @@ -456,7 +449,7 @@ GEN_FCMP(fcmpeq_fcc3, float128, 26, 1); target_ulong cpu_get_fsr(CPUSPARCState *env) { - target_ulong fsr = env->fsr; + target_ulong fsr = env->fsr | env->fsr_cexc_ftt; /* VER is kept completely separate until re-assembly. */ fsr |= env->def.fpu_version; @@ -473,7 +466,7 @@ static void set_fsr_nonsplit(CPUSPARCState *env, target_ulong fsr) { int rnd_mode; - env->fsr = fsr & ~FSR_VER_MASK; + env->fsr = fsr & ~(FSR_VER_MASK | FSR_CEXC_MASK | FSR_FTT_MASK); switch (fsr & FSR_RD_MASK) { case FSR_RD_NEAREST: @@ -495,10 +488,13 @@ static void set_fsr_nonsplit(CPUSPARCState *env, target_ulong fsr) void cpu_put_fsr(CPUSPARCState *env, target_ulong fsr) { + env->fsr_cexc_ftt = fsr & (FSR_CEXC_MASK | FSR_FTT_MASK); set_fsr_nonsplit(env, fsr); } -void helper_set_fsr(CPUSPARCState *env, target_ulong fsr) +void helper_set_fsr_noftt(CPUSPARCState *env, target_ulong fsr) { + env->fsr_cexc_ftt &= FSR_FTT_MASK; + env->fsr_cexc_ftt |= fsr & FSR_CEXC_MASK; set_fsr_nonsplit(env, fsr); } diff --git a/target/sparc/helper.h b/target/sparc/helper.h index 7c688edd62..7466164468 100644 --- a/target/sparc/helper.h +++ b/target/sparc/helper.h @@ -36,7 +36,7 @@ DEF_HELPER_FLAGS_4(ld_asi, TCG_CALL_NO_WG, i64, env, tl, int, i32) DEF_HELPER_FLAGS_5(st_asi, TCG_CALL_NO_WG, void, env, tl, i64, int, i32) #endif DEF_HELPER_FLAGS_1(get_fsr, TCG_CALL_NO_WG_SE, tl, env) -DEF_HELPER_FLAGS_2(set_fsr, TCG_CALL_NO_RWG, void, env, tl) +DEF_HELPER_FLAGS_2(set_fsr_noftt, 0, void, env, tl) DEF_HELPER_FLAGS_2(fsqrts, 0, f32, env, f32) DEF_HELPER_FLAGS_2(fsqrtd, 0, f64, env, f64) DEF_HELPER_FLAGS_2(fsqrtq, 0, i128, env, i128) diff --git a/target/sparc/translate.c b/target/sparc/translate.c index 25f93ec44a..5b9bbeb8ff 100644 --- a/target/sparc/translate.c +++ b/target/sparc/translate.c @@ -1199,7 +1199,8 @@ static bool gen_compare_reg(DisasCompare *cmp, int cond, TCGv r_src) static void gen_op_clear_ieee_excp_and_FTT(void) { - tcg_gen_andi_tl(cpu_fsr, cpu_fsr, FSR_FTT_CEXC_NMASK); + tcg_gen_st_i32(tcg_constant_i32(0), tcg_env, + offsetof(CPUSPARCState, fsr_cexc_ftt)); } static void gen_op_fmovs(TCGv_i32 dst, TCGv_i32 src) @@ -1400,10 +1401,15 @@ static void gen_op_fcmpeq(int fccno, TCGv_i128 r_rs1, TCGv_i128 r_rs2) } #endif -static void gen_op_fpexception_im(DisasContext *dc, int fsr_flags) +static void gen_op_fpexception_im(DisasContext *dc, int ftt) { - tcg_gen_andi_tl(cpu_fsr, cpu_fsr, FSR_FTT_NMASK); - tcg_gen_ori_tl(cpu_fsr, cpu_fsr, fsr_flags); + /* + * CEXC is only set when succesfully completing an FPop, + * or when raising FSR_FTT_IEEE_EXCP, i.e. check_ieee_exception. + * Thus we can simply store FTT into this field. + */ + tcg_gen_st_i32(tcg_constant_i32(ftt), tcg_env, + offsetof(CPUSPARCState, fsr_cexc_ftt)); gen_exception(dc, TT_FP_EXCP); } @@ -4395,19 +4401,22 @@ static bool trans_STDFQ(DisasContext *dc, arg_STDFQ *a) static bool do_ldfsr(DisasContext *dc, arg_r_r_ri *a, MemOp mop, target_ulong new_mask, target_ulong old_mask) { - TCGv tmp, addr = gen_ldst_addr(dc, a->rs1, a->imm, a->rs2_or_imm); + TCGv addr = gen_ldst_addr(dc, a->rs1, a->imm, a->rs2_or_imm); + TCGv tnew, told; + if (addr == NULL) { return false; } if (gen_trap_ifnofpu(dc)) { return true; } - tmp = tcg_temp_new(); - tcg_gen_qemu_ld_tl(tmp, addr, dc->mem_idx, mop | MO_ALIGN); - tcg_gen_andi_tl(tmp, tmp, new_mask); - tcg_gen_andi_tl(cpu_fsr, cpu_fsr, old_mask); - tcg_gen_or_tl(cpu_fsr, cpu_fsr, tmp); - gen_helper_set_fsr(tcg_env, cpu_fsr); + tnew = tcg_temp_new(); + told = tcg_temp_new(); + tcg_gen_qemu_ld_tl(tnew, addr, dc->mem_idx, mop | MO_ALIGN); + tcg_gen_andi_tl(tnew, tnew, new_mask); + tcg_gen_andi_tl(told, cpu_fsr, old_mask); + tcg_gen_or_tl(tnew, tnew, told); + gen_helper_set_fsr_noftt(tcg_env, tnew); return advance_pc(dc); } From c9fa8e586b2235cd173fdd8d4acaf2d84ed30009 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Fri, 3 Nov 2023 10:38:39 -0700 Subject: [PATCH 55/58] target/sparc: Remove cpu_fsr Drop this field as a tcg global, loading it explicitly in the few places required. This means that all FPop helpers may once again be TCG_CALL_NO_WG. Signed-off-by: Richard Henderson Tested-by: Mark Cave-Ayland Acked-by: Mark Cave-Ayland Message-Id: <20231103173841.33651-21-richard.henderson@linaro.org> --- target/sparc/fop_helper.c | 9 ++- target/sparc/helper.h | 120 +++++++++++++++++++------------------- target/sparc/translate.c | 98 ++++++++++++++++--------------- 3 files changed, 114 insertions(+), 113 deletions(-) diff --git a/target/sparc/fop_helper.c b/target/sparc/fop_helper.c index ac30f88810..796f448bfd 100644 --- a/target/sparc/fop_helper.c +++ b/target/sparc/fop_helper.c @@ -344,8 +344,7 @@ Int128 helper_fsqrtq(CPUSPARCState *env, Int128 src) } #define GEN_FCMP(name, size, FS, E) \ - target_ulong glue(helper_, name) (CPUSPARCState *env, \ - Int128 src1, Int128 src2) \ + void glue(helper_, name)(CPUSPARCState *env, Int128 src1, Int128 src2) \ { \ float128 reg1 = f128_in(src1); \ float128 reg2 = f128_in(src2); \ @@ -376,10 +375,10 @@ Int128 helper_fsqrtq(CPUSPARCState *env, Int128 src) fsr &= ~((FSR_FCC1 | FSR_FCC0) << FS); \ break; \ } \ - return fsr; \ + env->fsr = fsr; \ } #define GEN_FCMP_T(name, size, FS, E) \ - target_ulong glue(helper_, name)(CPUSPARCState *env, size src1, size src2)\ + void glue(helper_, name)(CPUSPARCState *env, size src1, size src2) \ { \ FloatRelation ret; \ target_ulong fsr; \ @@ -407,7 +406,7 @@ Int128 helper_fsqrtq(CPUSPARCState *env, Int128 src) fsr &= ~((FSR_FCC1 | FSR_FCC0) << FS); \ break; \ } \ - return fsr; \ + env->fsr = fsr; \ } GEN_FCMP_T(fcmps, float32, 0, 0); diff --git a/target/sparc/helper.h b/target/sparc/helper.h index 7466164468..c8e14fe371 100644 --- a/target/sparc/helper.h +++ b/target/sparc/helper.h @@ -36,79 +36,79 @@ DEF_HELPER_FLAGS_4(ld_asi, TCG_CALL_NO_WG, i64, env, tl, int, i32) DEF_HELPER_FLAGS_5(st_asi, TCG_CALL_NO_WG, void, env, tl, i64, int, i32) #endif DEF_HELPER_FLAGS_1(get_fsr, TCG_CALL_NO_WG_SE, tl, env) -DEF_HELPER_FLAGS_2(set_fsr_noftt, 0, void, env, tl) -DEF_HELPER_FLAGS_2(fsqrts, 0, f32, env, f32) -DEF_HELPER_FLAGS_2(fsqrtd, 0, f64, env, f64) -DEF_HELPER_FLAGS_2(fsqrtq, 0, i128, env, i128) -DEF_HELPER_FLAGS_3(fcmps, 0, tl, env, f32, f32) -DEF_HELPER_FLAGS_3(fcmpd, 0, tl, env, f64, f64) -DEF_HELPER_FLAGS_3(fcmpes, 0, tl, env, f32, f32) -DEF_HELPER_FLAGS_3(fcmped, 0, tl, env, f64, f64) -DEF_HELPER_FLAGS_3(fcmpq, 0, tl, env, i128, i128) -DEF_HELPER_FLAGS_3(fcmpeq, 0, tl, env, i128, i128) +DEF_HELPER_FLAGS_2(set_fsr_noftt, TCG_CALL_NO_RWG, void, env, tl) +DEF_HELPER_FLAGS_2(fsqrts, TCG_CALL_NO_WG, f32, env, f32) +DEF_HELPER_FLAGS_2(fsqrtd, TCG_CALL_NO_WG, f64, env, f64) +DEF_HELPER_FLAGS_2(fsqrtq, TCG_CALL_NO_WG, i128, env, i128) +DEF_HELPER_FLAGS_3(fcmps, TCG_CALL_NO_WG, void, env, f32, f32) +DEF_HELPER_FLAGS_3(fcmpd, TCG_CALL_NO_WG, void, env, f64, f64) +DEF_HELPER_FLAGS_3(fcmpes, TCG_CALL_NO_WG, void, env, f32, f32) +DEF_HELPER_FLAGS_3(fcmped, TCG_CALL_NO_WG, void, env, f64, f64) +DEF_HELPER_FLAGS_3(fcmpq, TCG_CALL_NO_WG, void, env, i128, i128) +DEF_HELPER_FLAGS_3(fcmpeq, TCG_CALL_NO_WG, void, env, i128, i128) #ifdef TARGET_SPARC64 -DEF_HELPER_FLAGS_3(fcmps_fcc1, 0, tl, env, f32, f32) -DEF_HELPER_FLAGS_3(fcmps_fcc2, 0, tl, env, f32, f32) -DEF_HELPER_FLAGS_3(fcmps_fcc3, 0, tl, env, f32, f32) -DEF_HELPER_FLAGS_3(fcmpd_fcc1, 0, tl, env, f64, f64) -DEF_HELPER_FLAGS_3(fcmpd_fcc2, 0, tl, env, f64, f64) -DEF_HELPER_FLAGS_3(fcmpd_fcc3, 0, tl, env, f64, f64) -DEF_HELPER_FLAGS_3(fcmpes_fcc1, 0, tl, env, f32, f32) -DEF_HELPER_FLAGS_3(fcmpes_fcc2, 0, tl, env, f32, f32) -DEF_HELPER_FLAGS_3(fcmpes_fcc3, 0, tl, env, f32, f32) -DEF_HELPER_FLAGS_3(fcmped_fcc1, 0, tl, env, f64, f64) -DEF_HELPER_FLAGS_3(fcmped_fcc2, 0, tl, env, f64, f64) -DEF_HELPER_FLAGS_3(fcmped_fcc3, 0, tl, env, f64, f64) -DEF_HELPER_FLAGS_3(fcmpq_fcc1, 0, tl, env, i128, i128) -DEF_HELPER_FLAGS_3(fcmpq_fcc2, 0, tl, env, i128, i128) -DEF_HELPER_FLAGS_3(fcmpq_fcc3, 0, tl, env, i128, i128) -DEF_HELPER_FLAGS_3(fcmpeq_fcc1, 0, tl, env, i128, i128) -DEF_HELPER_FLAGS_3(fcmpeq_fcc2, 0, tl, env, i128, i128) -DEF_HELPER_FLAGS_3(fcmpeq_fcc3, 0, tl, env, i128, i128) +DEF_HELPER_FLAGS_3(fcmps_fcc1, TCG_CALL_NO_WG, void, env, f32, f32) +DEF_HELPER_FLAGS_3(fcmps_fcc2, TCG_CALL_NO_WG, void, env, f32, f32) +DEF_HELPER_FLAGS_3(fcmps_fcc3, TCG_CALL_NO_WG, void, env, f32, f32) +DEF_HELPER_FLAGS_3(fcmpd_fcc1, TCG_CALL_NO_WG, void, env, f64, f64) +DEF_HELPER_FLAGS_3(fcmpd_fcc2, TCG_CALL_NO_WG, void, env, f64, f64) +DEF_HELPER_FLAGS_3(fcmpd_fcc3, TCG_CALL_NO_WG, void, env, f64, f64) +DEF_HELPER_FLAGS_3(fcmpes_fcc1, TCG_CALL_NO_WG, void, env, f32, f32) +DEF_HELPER_FLAGS_3(fcmpes_fcc2, TCG_CALL_NO_WG, void, env, f32, f32) +DEF_HELPER_FLAGS_3(fcmpes_fcc3, TCG_CALL_NO_WG, void, env, f32, f32) +DEF_HELPER_FLAGS_3(fcmped_fcc1, TCG_CALL_NO_WG, void, env, f64, f64) +DEF_HELPER_FLAGS_3(fcmped_fcc2, TCG_CALL_NO_WG, void, env, f64, f64) +DEF_HELPER_FLAGS_3(fcmped_fcc3, TCG_CALL_NO_WG, void, env, f64, f64) +DEF_HELPER_FLAGS_3(fcmpq_fcc1, TCG_CALL_NO_WG, void, env, i128, i128) +DEF_HELPER_FLAGS_3(fcmpq_fcc2, TCG_CALL_NO_WG, void, env, i128, i128) +DEF_HELPER_FLAGS_3(fcmpq_fcc3, TCG_CALL_NO_WG, void, env, i128, i128) +DEF_HELPER_FLAGS_3(fcmpeq_fcc1, TCG_CALL_NO_WG, void, env, i128, i128) +DEF_HELPER_FLAGS_3(fcmpeq_fcc2, TCG_CALL_NO_WG, void, env, i128, i128) +DEF_HELPER_FLAGS_3(fcmpeq_fcc3, TCG_CALL_NO_WG, void, env, i128, i128) #endif DEF_HELPER_2(raise_exception, noreturn, env, int) -DEF_HELPER_FLAGS_3(faddd, 0, f64, env, f64, f64) -DEF_HELPER_FLAGS_3(fsubd, 0, f64, env, f64, f64) -DEF_HELPER_FLAGS_3(fmuld, 0, f64, env, f64, f64) -DEF_HELPER_FLAGS_3(fdivd, 0, f64, env, f64, f64) +DEF_HELPER_FLAGS_3(faddd, TCG_CALL_NO_WG, f64, env, f64, f64) +DEF_HELPER_FLAGS_3(fsubd, TCG_CALL_NO_WG, f64, env, f64, f64) +DEF_HELPER_FLAGS_3(fmuld, TCG_CALL_NO_WG, f64, env, f64, f64) +DEF_HELPER_FLAGS_3(fdivd, TCG_CALL_NO_WG, f64, env, f64, f64) -DEF_HELPER_FLAGS_3(faddq, 0, i128, env, i128, i128) -DEF_HELPER_FLAGS_3(fsubq, 0, i128, env, i128, i128) -DEF_HELPER_FLAGS_3(fmulq, 0, i128, env, i128, i128) -DEF_HELPER_FLAGS_3(fdivq, 0, i128, env, i128, i128) +DEF_HELPER_FLAGS_3(faddq, TCG_CALL_NO_WG, i128, env, i128, i128) +DEF_HELPER_FLAGS_3(fsubq, TCG_CALL_NO_WG, i128, env, i128, i128) +DEF_HELPER_FLAGS_3(fmulq, TCG_CALL_NO_WG, i128, env, i128, i128) +DEF_HELPER_FLAGS_3(fdivq, TCG_CALL_NO_WG, i128, env, i128, i128) -DEF_HELPER_FLAGS_3(fadds, 0, f32, env, f32, f32) -DEF_HELPER_FLAGS_3(fsubs, 0, f32, env, f32, f32) -DEF_HELPER_FLAGS_3(fmuls, 0, f32, env, f32, f32) -DEF_HELPER_FLAGS_3(fdivs, 0, f32, env, f32, f32) +DEF_HELPER_FLAGS_3(fadds, TCG_CALL_NO_WG, f32, env, f32, f32) +DEF_HELPER_FLAGS_3(fsubs, TCG_CALL_NO_WG, f32, env, f32, f32) +DEF_HELPER_FLAGS_3(fmuls, TCG_CALL_NO_WG, f32, env, f32, f32) +DEF_HELPER_FLAGS_3(fdivs, TCG_CALL_NO_WG, f32, env, f32, f32) -DEF_HELPER_FLAGS_3(fsmuld, 0, f64, env, f32, f32) -DEF_HELPER_FLAGS_3(fdmulq, 0, i128, env, f64, f64) +DEF_HELPER_FLAGS_3(fsmuld, TCG_CALL_NO_WG, f64, env, f32, f32) +DEF_HELPER_FLAGS_3(fdmulq, TCG_CALL_NO_WG, i128, env, f64, f64) -DEF_HELPER_FLAGS_2(fitod, 0, f64, env, s32) -DEF_HELPER_FLAGS_2(fitoq, 0, i128, env, s32) +DEF_HELPER_FLAGS_2(fitod, TCG_CALL_NO_WG, f64, env, s32) +DEF_HELPER_FLAGS_2(fitoq, TCG_CALL_NO_WG, i128, env, s32) -DEF_HELPER_FLAGS_2(fitos, 0, f32, env, s32) +DEF_HELPER_FLAGS_2(fitos, TCG_CALL_NO_WG, f32, env, s32) #ifdef TARGET_SPARC64 -DEF_HELPER_FLAGS_2(fxtos, 0, f32, env, s64) -DEF_HELPER_FLAGS_2(fxtod, 0, f64, env, s64) -DEF_HELPER_FLAGS_2(fxtoq, 0, i128, env, s64) +DEF_HELPER_FLAGS_2(fxtos, TCG_CALL_NO_WG, f32, env, s64) +DEF_HELPER_FLAGS_2(fxtod, TCG_CALL_NO_WG, f64, env, s64) +DEF_HELPER_FLAGS_2(fxtoq, TCG_CALL_NO_WG, i128, env, s64) #endif -DEF_HELPER_FLAGS_2(fdtos, 0, f32, env, f64) -DEF_HELPER_FLAGS_2(fstod, 0, f64, env, f32) -DEF_HELPER_FLAGS_2(fqtos, 0, f32, env, i128) -DEF_HELPER_FLAGS_2(fstoq, 0, i128, env, f32) -DEF_HELPER_FLAGS_2(fqtod, 0, f64, env, i128) -DEF_HELPER_FLAGS_2(fdtoq, 0, i128, env, f64) -DEF_HELPER_FLAGS_2(fstoi, 0, s32, env, f32) -DEF_HELPER_FLAGS_2(fdtoi, 0, s32, env, f64) -DEF_HELPER_FLAGS_2(fqtoi, 0, s32, env, i128) +DEF_HELPER_FLAGS_2(fdtos, TCG_CALL_NO_WG, f32, env, f64) +DEF_HELPER_FLAGS_2(fstod, TCG_CALL_NO_WG, f64, env, f32) +DEF_HELPER_FLAGS_2(fqtos, TCG_CALL_NO_WG, f32, env, i128) +DEF_HELPER_FLAGS_2(fstoq, TCG_CALL_NO_WG, i128, env, f32) +DEF_HELPER_FLAGS_2(fqtod, TCG_CALL_NO_WG, f64, env, i128) +DEF_HELPER_FLAGS_2(fdtoq, TCG_CALL_NO_WG, i128, env, f64) +DEF_HELPER_FLAGS_2(fstoi, TCG_CALL_NO_WG, s32, env, f32) +DEF_HELPER_FLAGS_2(fdtoi, TCG_CALL_NO_WG, s32, env, f64) +DEF_HELPER_FLAGS_2(fqtoi, TCG_CALL_NO_WG, s32, env, i128) #ifdef TARGET_SPARC64 -DEF_HELPER_FLAGS_2(fstox, 0, s64, env, f32) -DEF_HELPER_FLAGS_2(fdtox, 0, s64, env, f64) -DEF_HELPER_FLAGS_2(fqtox, 0, s64, env, i128) +DEF_HELPER_FLAGS_2(fstox, TCG_CALL_NO_WG, s64, env, f32) +DEF_HELPER_FLAGS_2(fdtox, TCG_CALL_NO_WG, s64, env, f64) +DEF_HELPER_FLAGS_2(fqtox, TCG_CALL_NO_WG, s64, env, i128) DEF_HELPER_FLAGS_2(fpmerge, TCG_CALL_NO_RWG_SE, i64, i64, i64) DEF_HELPER_FLAGS_2(fmul8x16, TCG_CALL_NO_RWG_SE, i64, i64, i64) diff --git a/target/sparc/translate.c b/target/sparc/translate.c index 5b9bbeb8ff..cf8cfe5cc4 100644 --- a/target/sparc/translate.c +++ b/target/sparc/translate.c @@ -99,7 +99,7 @@ /* global register indexes */ static TCGv_ptr cpu_regwptr; -static TCGv cpu_fsr, cpu_pc, cpu_npc; +static TCGv cpu_pc, cpu_npc; static TCGv cpu_regs[32]; static TCGv cpu_y; static TCGv cpu_tbr; @@ -1097,7 +1097,7 @@ static void gen_compare(DisasCompare *cmp, bool xcc, unsigned int cond, static void gen_fcompare(DisasCompare *cmp, unsigned int cc, unsigned int cond) { unsigned int offset; - TCGv r_dst; + TCGv r_dst, fsr; /* For now we still generate a straight boolean result. */ cmp->cond = TCG_COND_NE; @@ -1120,54 +1120,56 @@ static void gen_fcompare(DisasCompare *cmp, unsigned int cc, unsigned int cond) break; } + fsr = tcg_temp_new(); + tcg_gen_ld_tl(fsr, tcg_env, offsetof(CPUSPARCState, fsr)); switch (cond) { case 0x0: gen_op_eval_bn(r_dst); break; case 0x1: - gen_op_eval_fbne(r_dst, cpu_fsr, offset); + gen_op_eval_fbne(r_dst, fsr, offset); break; case 0x2: - gen_op_eval_fblg(r_dst, cpu_fsr, offset); + gen_op_eval_fblg(r_dst, fsr, offset); break; case 0x3: - gen_op_eval_fbul(r_dst, cpu_fsr, offset); + gen_op_eval_fbul(r_dst, fsr, offset); break; case 0x4: - gen_op_eval_fbl(r_dst, cpu_fsr, offset); + gen_op_eval_fbl(r_dst, fsr, offset); break; case 0x5: - gen_op_eval_fbug(r_dst, cpu_fsr, offset); + gen_op_eval_fbug(r_dst, fsr, offset); break; case 0x6: - gen_op_eval_fbg(r_dst, cpu_fsr, offset); + gen_op_eval_fbg(r_dst, fsr, offset); break; case 0x7: - gen_op_eval_fbu(r_dst, cpu_fsr, offset); + gen_op_eval_fbu(r_dst, fsr, offset); break; case 0x8: gen_op_eval_ba(r_dst); break; case 0x9: - gen_op_eval_fbe(r_dst, cpu_fsr, offset); + gen_op_eval_fbe(r_dst, fsr, offset); break; case 0xa: - gen_op_eval_fbue(r_dst, cpu_fsr, offset); + gen_op_eval_fbue(r_dst, fsr, offset); break; case 0xb: - gen_op_eval_fbge(r_dst, cpu_fsr, offset); + gen_op_eval_fbge(r_dst, fsr, offset); break; case 0xc: - gen_op_eval_fbuge(r_dst, cpu_fsr, offset); + gen_op_eval_fbuge(r_dst, fsr, offset); break; case 0xd: - gen_op_eval_fble(r_dst, cpu_fsr, offset); + gen_op_eval_fble(r_dst, fsr, offset); break; case 0xe: - gen_op_eval_fbule(r_dst, cpu_fsr, offset); + gen_op_eval_fbule(r_dst, fsr, offset); break; case 0xf: - gen_op_eval_fbo(r_dst, cpu_fsr, offset); + gen_op_eval_fbo(r_dst, fsr, offset); break; } } @@ -1264,16 +1266,16 @@ static void gen_op_fcmps(int fccno, TCGv_i32 r_rs1, TCGv_i32 r_rs2) { switch (fccno) { case 0: - gen_helper_fcmps(cpu_fsr, tcg_env, r_rs1, r_rs2); + gen_helper_fcmps(tcg_env, r_rs1, r_rs2); break; case 1: - gen_helper_fcmps_fcc1(cpu_fsr, tcg_env, r_rs1, r_rs2); + gen_helper_fcmps_fcc1(tcg_env, r_rs1, r_rs2); break; case 2: - gen_helper_fcmps_fcc2(cpu_fsr, tcg_env, r_rs1, r_rs2); + gen_helper_fcmps_fcc2(tcg_env, r_rs1, r_rs2); break; case 3: - gen_helper_fcmps_fcc3(cpu_fsr, tcg_env, r_rs1, r_rs2); + gen_helper_fcmps_fcc3(tcg_env, r_rs1, r_rs2); break; } } @@ -1282,16 +1284,16 @@ static void gen_op_fcmpd(int fccno, TCGv_i64 r_rs1, TCGv_i64 r_rs2) { switch (fccno) { case 0: - gen_helper_fcmpd(cpu_fsr, tcg_env, r_rs1, r_rs2); + gen_helper_fcmpd(tcg_env, r_rs1, r_rs2); break; case 1: - gen_helper_fcmpd_fcc1(cpu_fsr, tcg_env, r_rs1, r_rs2); + gen_helper_fcmpd_fcc1(tcg_env, r_rs1, r_rs2); break; case 2: - gen_helper_fcmpd_fcc2(cpu_fsr, tcg_env, r_rs1, r_rs2); + gen_helper_fcmpd_fcc2(tcg_env, r_rs1, r_rs2); break; case 3: - gen_helper_fcmpd_fcc3(cpu_fsr, tcg_env, r_rs1, r_rs2); + gen_helper_fcmpd_fcc3(tcg_env, r_rs1, r_rs2); break; } } @@ -1300,16 +1302,16 @@ static void gen_op_fcmpq(int fccno, TCGv_i128 r_rs1, TCGv_i128 r_rs2) { switch (fccno) { case 0: - gen_helper_fcmpq(cpu_fsr, tcg_env, r_rs1, r_rs2); + gen_helper_fcmpq(tcg_env, r_rs1, r_rs2); break; case 1: - gen_helper_fcmpq_fcc1(cpu_fsr, tcg_env, r_rs1, r_rs2); + gen_helper_fcmpq_fcc1(tcg_env, r_rs1, r_rs2); break; case 2: - gen_helper_fcmpq_fcc2(cpu_fsr, tcg_env, r_rs1, r_rs2); + gen_helper_fcmpq_fcc2(tcg_env, r_rs1, r_rs2); break; case 3: - gen_helper_fcmpq_fcc3(cpu_fsr, tcg_env, r_rs1, r_rs2); + gen_helper_fcmpq_fcc3(tcg_env, r_rs1, r_rs2); break; } } @@ -1318,16 +1320,16 @@ static void gen_op_fcmpes(int fccno, TCGv_i32 r_rs1, TCGv_i32 r_rs2) { switch (fccno) { case 0: - gen_helper_fcmpes(cpu_fsr, tcg_env, r_rs1, r_rs2); + gen_helper_fcmpes(tcg_env, r_rs1, r_rs2); break; case 1: - gen_helper_fcmpes_fcc1(cpu_fsr, tcg_env, r_rs1, r_rs2); + gen_helper_fcmpes_fcc1(tcg_env, r_rs1, r_rs2); break; case 2: - gen_helper_fcmpes_fcc2(cpu_fsr, tcg_env, r_rs1, r_rs2); + gen_helper_fcmpes_fcc2(tcg_env, r_rs1, r_rs2); break; case 3: - gen_helper_fcmpes_fcc3(cpu_fsr, tcg_env, r_rs1, r_rs2); + gen_helper_fcmpes_fcc3(tcg_env, r_rs1, r_rs2); break; } } @@ -1336,16 +1338,16 @@ static void gen_op_fcmped(int fccno, TCGv_i64 r_rs1, TCGv_i64 r_rs2) { switch (fccno) { case 0: - gen_helper_fcmped(cpu_fsr, tcg_env, r_rs1, r_rs2); + gen_helper_fcmped(tcg_env, r_rs1, r_rs2); break; case 1: - gen_helper_fcmped_fcc1(cpu_fsr, tcg_env, r_rs1, r_rs2); + gen_helper_fcmped_fcc1(tcg_env, r_rs1, r_rs2); break; case 2: - gen_helper_fcmped_fcc2(cpu_fsr, tcg_env, r_rs1, r_rs2); + gen_helper_fcmped_fcc2(tcg_env, r_rs1, r_rs2); break; case 3: - gen_helper_fcmped_fcc3(cpu_fsr, tcg_env, r_rs1, r_rs2); + gen_helper_fcmped_fcc3(tcg_env, r_rs1, r_rs2); break; } } @@ -1354,16 +1356,16 @@ static void gen_op_fcmpeq(int fccno, TCGv_i128 r_rs1, TCGv_i128 r_rs2) { switch (fccno) { case 0: - gen_helper_fcmpeq(cpu_fsr, tcg_env, r_rs1, r_rs2); + gen_helper_fcmpeq(tcg_env, r_rs1, r_rs2); break; case 1: - gen_helper_fcmpeq_fcc1(cpu_fsr, tcg_env, r_rs1, r_rs2); + gen_helper_fcmpeq_fcc1(tcg_env, r_rs1, r_rs2); break; case 2: - gen_helper_fcmpeq_fcc2(cpu_fsr, tcg_env, r_rs1, r_rs2); + gen_helper_fcmpeq_fcc2(tcg_env, r_rs1, r_rs2); break; case 3: - gen_helper_fcmpeq_fcc3(cpu_fsr, tcg_env, r_rs1, r_rs2); + gen_helper_fcmpeq_fcc3(tcg_env, r_rs1, r_rs2); break; } } @@ -1372,32 +1374,32 @@ static void gen_op_fcmpeq(int fccno, TCGv_i128 r_rs1, TCGv_i128 r_rs2) static void gen_op_fcmps(int fccno, TCGv r_rs1, TCGv r_rs2) { - gen_helper_fcmps(cpu_fsr, tcg_env, r_rs1, r_rs2); + gen_helper_fcmps(tcg_env, r_rs1, r_rs2); } static void gen_op_fcmpd(int fccno, TCGv_i64 r_rs1, TCGv_i64 r_rs2) { - gen_helper_fcmpd(cpu_fsr, tcg_env, r_rs1, r_rs2); + gen_helper_fcmpd(tcg_env, r_rs1, r_rs2); } static void gen_op_fcmpq(int fccno, TCGv_i128 r_rs1, TCGv_i128 r_rs2) { - gen_helper_fcmpq(cpu_fsr, tcg_env, r_rs1, r_rs2); + gen_helper_fcmpq(tcg_env, r_rs1, r_rs2); } static void gen_op_fcmpes(int fccno, TCGv r_rs1, TCGv r_rs2) { - gen_helper_fcmpes(cpu_fsr, tcg_env, r_rs1, r_rs2); + gen_helper_fcmpes(tcg_env, r_rs1, r_rs2); } static void gen_op_fcmped(int fccno, TCGv_i64 r_rs1, TCGv_i64 r_rs2) { - gen_helper_fcmped(cpu_fsr, tcg_env, r_rs1, r_rs2); + gen_helper_fcmped(tcg_env, r_rs1, r_rs2); } static void gen_op_fcmpeq(int fccno, TCGv_i128 r_rs1, TCGv_i128 r_rs2) { - gen_helper_fcmpeq(cpu_fsr, tcg_env, r_rs1, r_rs2); + gen_helper_fcmpeq(tcg_env, r_rs1, r_rs2); } #endif @@ -4413,8 +4415,9 @@ static bool do_ldfsr(DisasContext *dc, arg_r_r_ri *a, MemOp mop, tnew = tcg_temp_new(); told = tcg_temp_new(); tcg_gen_qemu_ld_tl(tnew, addr, dc->mem_idx, mop | MO_ALIGN); + tcg_gen_ld_tl(told, tcg_env, offsetof(CPUSPARCState, fsr)); tcg_gen_andi_tl(tnew, tnew, new_mask); - tcg_gen_andi_tl(told, cpu_fsr, old_mask); + tcg_gen_andi_tl(told, told, old_mask); tcg_gen_or_tl(tnew, tnew, told); gen_helper_set_fsr_noftt(tcg_env, tnew); return advance_pc(dc); @@ -5342,7 +5345,6 @@ void sparc_tcg_init(void) { &cpu_icc_Z, offsetof(CPUSPARCState, icc_Z), "icc_Z" }, { &cpu_icc_C, offsetof(CPUSPARCState, icc_C), "icc_C" }, { &cpu_cond, offsetof(CPUSPARCState, cond), "cond" }, - { &cpu_fsr, offsetof(CPUSPARCState, fsr), "fsr" }, { &cpu_pc, offsetof(CPUSPARCState, pc), "pc" }, { &cpu_npc, offsetof(CPUSPARCState, npc), "npc" }, { &cpu_y, offsetof(CPUSPARCState, y), "y" }, From d8c5b92f3f5982b16cf2058395d584d38b9143f7 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Fri, 3 Nov 2023 10:38:40 -0700 Subject: [PATCH 56/58] target/sparc: Split fcc out of env->fsr Represent each fcc field separately from the rest of fsr. This vastly simplifies floating-point comparisons. Signed-off-by: Richard Henderson Tested-by: Mark Cave-Ayland Acked-by: Mark Cave-Ayland Message-Id: <20231103173841.33651-22-richard.henderson@linaro.org> --- target/sparc/cpu.h | 20 +- target/sparc/fop_helper.c | 169 ++++++------- target/sparc/helper.h | 34 +-- target/sparc/translate.c | 503 +++++++++----------------------------- 4 files changed, 201 insertions(+), 525 deletions(-) diff --git a/target/sparc/cpu.h b/target/sparc/cpu.h index c5be9e37de..986c7217ed 100644 --- a/target/sparc/cpu.h +++ b/target/sparc/cpu.h @@ -31,8 +31,10 @@ #if !defined(TARGET_SPARC64) #define TARGET_DPREGS 16 +#define TARGET_FCCREGS 1 #else #define TARGET_DPREGS 32 +#define TARGET_FCCREGS 4 #endif /*#define EXCP_INTERRUPT 0x100*/ @@ -203,24 +205,19 @@ enum { #ifdef TARGET_SPARC64 #define FSR_FTT_NMASK 0xfffffffffffe3fffULL #define FSR_FTT_CEXC_NMASK 0xfffffffffffe3fe0ULL -#define FSR_LDFSR_OLDMASK 0x0000003f000fc000ULL -#define FSR_LDXFSR_MASK 0x0000003fcfc00fffULL -#define FSR_LDXFSR_OLDMASK 0x00000000000fc000ULL #else #define FSR_FTT_NMASK 0xfffe3fffULL #define FSR_FTT_CEXC_NMASK 0xfffe3fe0ULL -#define FSR_LDFSR_OLDMASK 0x000fc000ULL #endif -#define FSR_LDFSR_MASK 0xcfc00fffULL #define FSR_FTT_IEEE_EXCP (1ULL << 14) #define FSR_FTT_UNIMPFPOP (3ULL << 14) #define FSR_FTT_SEQ_ERROR (4ULL << 14) #define FSR_FTT_INVAL_FPR (6ULL << 14) -#define FSR_FCC1_SHIFT 11 -#define FSR_FCC1 (1ULL << FSR_FCC1_SHIFT) -#define FSR_FCC0_SHIFT 10 -#define FSR_FCC0 (1ULL << FSR_FCC0_SHIFT) +#define FSR_FCC0_SHIFT 10 +#define FSR_FCC1_SHIFT 32 +#define FSR_FCC2_SHIFT 34 +#define FSR_FCC3_SHIFT 36 /* MMU */ #define MMU_E (1<<0) @@ -467,8 +464,9 @@ struct CPUArchState { temporary register when possible) */ /* FPU State Register, in parts */ - target_ulong fsr; /* rm, tem, aexc, fcc* */ - uint32_t fsr_cexc_ftt; /* cexc, ftt */ + uint32_t fsr; /* rm, tem, aexc */ + uint32_t fsr_cexc_ftt; /* cexc, ftt */ + uint32_t fcc[TARGET_FCCREGS]; /* fcc* */ CPU_DoubleU fpr[TARGET_DPREGS]; /* floating point registers */ uint32_t cwp; /* index of current register window (extracted diff --git a/target/sparc/fop_helper.c b/target/sparc/fop_helper.c index 796f448bfd..1205a599ef 100644 --- a/target/sparc/fop_helper.c +++ b/target/sparc/fop_helper.c @@ -343,113 +343,80 @@ Int128 helper_fsqrtq(CPUSPARCState *env, Int128 src) return f128_ret(ret); } -#define GEN_FCMP(name, size, FS, E) \ - void glue(helper_, name)(CPUSPARCState *env, Int128 src1, Int128 src2) \ - { \ - float128 reg1 = f128_in(src1); \ - float128 reg2 = f128_in(src2); \ - FloatRelation ret; \ - target_ulong fsr; \ - if (E) { \ - ret = glue(size, _compare)(reg1, reg2, &env->fp_status); \ - } else { \ - ret = glue(size, _compare_quiet)(reg1, reg2, \ - &env->fp_status); \ - } \ - check_ieee_exceptions(env, GETPC()); \ - fsr = env->fsr; \ - switch (ret) { \ - case float_relation_unordered: \ - fsr |= (FSR_FCC1 | FSR_FCC0) << FS; \ - fsr |= FSR_NVA; \ - break; \ - case float_relation_less: \ - fsr &= ~(FSR_FCC1) << FS; \ - fsr |= FSR_FCC0 << FS; \ - break; \ - case float_relation_greater: \ - fsr &= ~(FSR_FCC0) << FS; \ - fsr |= FSR_FCC1 << FS; \ - break; \ - default: \ - fsr &= ~((FSR_FCC1 | FSR_FCC0) << FS); \ - break; \ - } \ - env->fsr = fsr; \ - } -#define GEN_FCMP_T(name, size, FS, E) \ - void glue(helper_, name)(CPUSPARCState *env, size src1, size src2) \ - { \ - FloatRelation ret; \ - target_ulong fsr; \ - if (E) { \ - ret = glue(size, _compare)(src1, src2, &env->fp_status); \ - } else { \ - ret = glue(size, _compare_quiet)(src1, src2, \ - &env->fp_status); \ - } \ - check_ieee_exceptions(env, GETPC()); \ - fsr = env->fsr; \ - switch (ret) { \ - case float_relation_unordered: \ - fsr |= (FSR_FCC1 | FSR_FCC0) << FS; \ - break; \ - case float_relation_less: \ - fsr &= ~(FSR_FCC1 << FS); \ - fsr |= FSR_FCC0 << FS; \ - break; \ - case float_relation_greater: \ - fsr &= ~(FSR_FCC0 << FS); \ - fsr |= FSR_FCC1 << FS; \ - break; \ - default: \ - fsr &= ~((FSR_FCC1 | FSR_FCC0) << FS); \ - break; \ - } \ - env->fsr = fsr; \ +static uint32_t finish_fcmp(CPUSPARCState *env, FloatRelation r, uintptr_t ra) +{ + check_ieee_exceptions(env, ra); + + /* + * FCC values: + * 0 = + * 1 < + * 2 > + * 3 unordered + */ + switch (r) { + case float_relation_equal: + return 0; + case float_relation_less: + return 1; + case float_relation_greater: + return 2; + case float_relation_unordered: + env->fsr |= FSR_NVA; + return 3; } + g_assert_not_reached(); +} -GEN_FCMP_T(fcmps, float32, 0, 0); -GEN_FCMP_T(fcmpd, float64, 0, 0); +uint32_t helper_fcmps(CPUSPARCState *env, float32 src1, float32 src2) +{ + FloatRelation r = float32_compare_quiet(src1, src2, &env->fp_status); + return finish_fcmp(env, r, GETPC()); +} -GEN_FCMP_T(fcmpes, float32, 0, 1); -GEN_FCMP_T(fcmped, float64, 0, 1); +uint32_t helper_fcmpes(CPUSPARCState *env, float32 src1, float32 src2) +{ + FloatRelation r = float32_compare(src1, src2, &env->fp_status); + return finish_fcmp(env, r, GETPC()); +} -GEN_FCMP(fcmpq, float128, 0, 0); -GEN_FCMP(fcmpeq, float128, 0, 1); +uint32_t helper_fcmpd(CPUSPARCState *env, float64 src1, float64 src2) +{ + FloatRelation r = float64_compare_quiet(src1, src2, &env->fp_status); + return finish_fcmp(env, r, GETPC()); +} -#ifdef TARGET_SPARC64 -GEN_FCMP_T(fcmps_fcc1, float32, 22, 0); -GEN_FCMP_T(fcmpd_fcc1, float64, 22, 0); -GEN_FCMP(fcmpq_fcc1, float128, 22, 0); +uint32_t helper_fcmped(CPUSPARCState *env, float64 src1, float64 src2) +{ + FloatRelation r = float64_compare(src1, src2, &env->fp_status); + return finish_fcmp(env, r, GETPC()); +} -GEN_FCMP_T(fcmps_fcc2, float32, 24, 0); -GEN_FCMP_T(fcmpd_fcc2, float64, 24, 0); -GEN_FCMP(fcmpq_fcc2, float128, 24, 0); +uint32_t helper_fcmpq(CPUSPARCState *env, Int128 src1, Int128 src2) +{ + FloatRelation r = float128_compare_quiet(f128_in(src1), f128_in(src2), + &env->fp_status); + return finish_fcmp(env, r, GETPC()); +} -GEN_FCMP_T(fcmps_fcc3, float32, 26, 0); -GEN_FCMP_T(fcmpd_fcc3, float64, 26, 0); -GEN_FCMP(fcmpq_fcc3, float128, 26, 0); - -GEN_FCMP_T(fcmpes_fcc1, float32, 22, 1); -GEN_FCMP_T(fcmped_fcc1, float64, 22, 1); -GEN_FCMP(fcmpeq_fcc1, float128, 22, 1); - -GEN_FCMP_T(fcmpes_fcc2, float32, 24, 1); -GEN_FCMP_T(fcmped_fcc2, float64, 24, 1); -GEN_FCMP(fcmpeq_fcc2, float128, 24, 1); - -GEN_FCMP_T(fcmpes_fcc3, float32, 26, 1); -GEN_FCMP_T(fcmped_fcc3, float64, 26, 1); -GEN_FCMP(fcmpeq_fcc3, float128, 26, 1); -#endif -#undef GEN_FCMP_T -#undef GEN_FCMP +uint32_t helper_fcmpeq(CPUSPARCState *env, Int128 src1, Int128 src2) +{ + FloatRelation r = float128_compare(f128_in(src1), f128_in(src2), + &env->fp_status); + return finish_fcmp(env, r, GETPC()); +} target_ulong cpu_get_fsr(CPUSPARCState *env) { target_ulong fsr = env->fsr | env->fsr_cexc_ftt; + fsr |= env->fcc[0] << FSR_FCC0_SHIFT; +#ifdef TARGET_SPARC64 + fsr |= (uint64_t)env->fcc[1] << FSR_FCC1_SHIFT; + fsr |= (uint64_t)env->fcc[2] << FSR_FCC2_SHIFT; + fsr |= (uint64_t)env->fcc[3] << FSR_FCC3_SHIFT; +#endif + /* VER is kept completely separate until re-assembly. */ fsr |= env->def.fpu_version; @@ -465,7 +432,7 @@ static void set_fsr_nonsplit(CPUSPARCState *env, target_ulong fsr) { int rnd_mode; - env->fsr = fsr & ~(FSR_VER_MASK | FSR_CEXC_MASK | FSR_FTT_MASK); + env->fsr = fsr & (FSR_RD_MASK | FSR_TEM_MASK | FSR_AEXC_MASK); switch (fsr & FSR_RD_MASK) { case FSR_RD_NEAREST: @@ -488,10 +455,18 @@ static void set_fsr_nonsplit(CPUSPARCState *env, target_ulong fsr) void cpu_put_fsr(CPUSPARCState *env, target_ulong fsr) { env->fsr_cexc_ftt = fsr & (FSR_CEXC_MASK | FSR_FTT_MASK); + + env->fcc[0] = extract32(fsr, FSR_FCC0_SHIFT, 2); +#ifdef TARGET_SPARC64 + env->fcc[1] = extract64(fsr, FSR_FCC1_SHIFT, 2); + env->fcc[2] = extract64(fsr, FSR_FCC2_SHIFT, 2); + env->fcc[3] = extract64(fsr, FSR_FCC3_SHIFT, 2); +#endif + set_fsr_nonsplit(env, fsr); } -void helper_set_fsr_noftt(CPUSPARCState *env, target_ulong fsr) +void helper_set_fsr_nofcc_noftt(CPUSPARCState *env, uint32_t fsr) { env->fsr_cexc_ftt &= FSR_FTT_MASK; env->fsr_cexc_ftt |= fsr & FSR_CEXC_MASK; diff --git a/target/sparc/helper.h b/target/sparc/helper.h index c8e14fe371..6a42ba4e9e 100644 --- a/target/sparc/helper.h +++ b/target/sparc/helper.h @@ -36,36 +36,16 @@ DEF_HELPER_FLAGS_4(ld_asi, TCG_CALL_NO_WG, i64, env, tl, int, i32) DEF_HELPER_FLAGS_5(st_asi, TCG_CALL_NO_WG, void, env, tl, i64, int, i32) #endif DEF_HELPER_FLAGS_1(get_fsr, TCG_CALL_NO_WG_SE, tl, env) -DEF_HELPER_FLAGS_2(set_fsr_noftt, TCG_CALL_NO_RWG, void, env, tl) +DEF_HELPER_FLAGS_2(set_fsr_nofcc_noftt, TCG_CALL_NO_RWG, void, env, i32) DEF_HELPER_FLAGS_2(fsqrts, TCG_CALL_NO_WG, f32, env, f32) DEF_HELPER_FLAGS_2(fsqrtd, TCG_CALL_NO_WG, f64, env, f64) DEF_HELPER_FLAGS_2(fsqrtq, TCG_CALL_NO_WG, i128, env, i128) -DEF_HELPER_FLAGS_3(fcmps, TCG_CALL_NO_WG, void, env, f32, f32) -DEF_HELPER_FLAGS_3(fcmpd, TCG_CALL_NO_WG, void, env, f64, f64) -DEF_HELPER_FLAGS_3(fcmpes, TCG_CALL_NO_WG, void, env, f32, f32) -DEF_HELPER_FLAGS_3(fcmped, TCG_CALL_NO_WG, void, env, f64, f64) -DEF_HELPER_FLAGS_3(fcmpq, TCG_CALL_NO_WG, void, env, i128, i128) -DEF_HELPER_FLAGS_3(fcmpeq, TCG_CALL_NO_WG, void, env, i128, i128) -#ifdef TARGET_SPARC64 -DEF_HELPER_FLAGS_3(fcmps_fcc1, TCG_CALL_NO_WG, void, env, f32, f32) -DEF_HELPER_FLAGS_3(fcmps_fcc2, TCG_CALL_NO_WG, void, env, f32, f32) -DEF_HELPER_FLAGS_3(fcmps_fcc3, TCG_CALL_NO_WG, void, env, f32, f32) -DEF_HELPER_FLAGS_3(fcmpd_fcc1, TCG_CALL_NO_WG, void, env, f64, f64) -DEF_HELPER_FLAGS_3(fcmpd_fcc2, TCG_CALL_NO_WG, void, env, f64, f64) -DEF_HELPER_FLAGS_3(fcmpd_fcc3, TCG_CALL_NO_WG, void, env, f64, f64) -DEF_HELPER_FLAGS_3(fcmpes_fcc1, TCG_CALL_NO_WG, void, env, f32, f32) -DEF_HELPER_FLAGS_3(fcmpes_fcc2, TCG_CALL_NO_WG, void, env, f32, f32) -DEF_HELPER_FLAGS_3(fcmpes_fcc3, TCG_CALL_NO_WG, void, env, f32, f32) -DEF_HELPER_FLAGS_3(fcmped_fcc1, TCG_CALL_NO_WG, void, env, f64, f64) -DEF_HELPER_FLAGS_3(fcmped_fcc2, TCG_CALL_NO_WG, void, env, f64, f64) -DEF_HELPER_FLAGS_3(fcmped_fcc3, TCG_CALL_NO_WG, void, env, f64, f64) -DEF_HELPER_FLAGS_3(fcmpq_fcc1, TCG_CALL_NO_WG, void, env, i128, i128) -DEF_HELPER_FLAGS_3(fcmpq_fcc2, TCG_CALL_NO_WG, void, env, i128, i128) -DEF_HELPER_FLAGS_3(fcmpq_fcc3, TCG_CALL_NO_WG, void, env, i128, i128) -DEF_HELPER_FLAGS_3(fcmpeq_fcc1, TCG_CALL_NO_WG, void, env, i128, i128) -DEF_HELPER_FLAGS_3(fcmpeq_fcc2, TCG_CALL_NO_WG, void, env, i128, i128) -DEF_HELPER_FLAGS_3(fcmpeq_fcc3, TCG_CALL_NO_WG, void, env, i128, i128) -#endif +DEF_HELPER_FLAGS_3(fcmps, TCG_CALL_NO_WG, i32, env, f32, f32) +DEF_HELPER_FLAGS_3(fcmpes, TCG_CALL_NO_WG, i32, env, f32, f32) +DEF_HELPER_FLAGS_3(fcmpd, TCG_CALL_NO_WG, i32, env, f64, f64) +DEF_HELPER_FLAGS_3(fcmped, TCG_CALL_NO_WG, i32, env, f64, f64) +DEF_HELPER_FLAGS_3(fcmpq, TCG_CALL_NO_WG, i32, env, i128, i128) +DEF_HELPER_FLAGS_3(fcmpeq, TCG_CALL_NO_WG, i32, env, i128, i128) DEF_HELPER_2(raise_exception, noreturn, env, int) DEF_HELPER_FLAGS_3(faddd, TCG_CALL_NO_WG, f64, env, f64, f64) diff --git a/target/sparc/translate.c b/target/sparc/translate.c index cf8cfe5cc4..7df6f83b13 100644 --- a/target/sparc/translate.c +++ b/target/sparc/translate.c @@ -83,8 +83,6 @@ # define gen_helper_fxtoq ({ qemu_build_not_reached(); NULL; }) # define gen_helper_fxtos ({ qemu_build_not_reached(); NULL; }) # define gen_helper_pdist ({ qemu_build_not_reached(); NULL; }) -# define FSR_LDXFSR_MASK 0 -# define FSR_LDXFSR_OLDMASK 0 # define MAXTL_MASK 0 #endif @@ -130,6 +128,7 @@ static TCGv cpu_gsr; /* Floating point registers */ static TCGv_i64 cpu_fpr[TARGET_DPREGS]; +static TCGv_i32 cpu_fcc[TARGET_FCCREGS]; #define env_field_offsetof(X) offsetof(CPUSPARCState, X) #ifdef TARGET_SPARC64 @@ -719,159 +718,6 @@ static void gen_op_bshuffle(TCGv_i64 dst, TCGv_i64 src1, TCGv_i64 src2) #endif } -// 1 -static void gen_op_eval_ba(TCGv dst) -{ - tcg_gen_movi_tl(dst, 1); -} - -// 0 -static void gen_op_eval_bn(TCGv dst) -{ - tcg_gen_movi_tl(dst, 0); -} - -/* - FPSR bit field FCC1 | FCC0: - 0 = - 1 < - 2 > - 3 unordered -*/ -static void gen_mov_reg_FCC0(TCGv reg, TCGv src, - unsigned int fcc_offset) -{ - tcg_gen_shri_tl(reg, src, FSR_FCC0_SHIFT + fcc_offset); - tcg_gen_andi_tl(reg, reg, 0x1); -} - -static void gen_mov_reg_FCC1(TCGv reg, TCGv src, unsigned int fcc_offset) -{ - tcg_gen_shri_tl(reg, src, FSR_FCC1_SHIFT + fcc_offset); - tcg_gen_andi_tl(reg, reg, 0x1); -} - -// !0: FCC0 | FCC1 -static void gen_op_eval_fbne(TCGv dst, TCGv src, unsigned int fcc_offset) -{ - TCGv t0 = tcg_temp_new(); - gen_mov_reg_FCC0(dst, src, fcc_offset); - gen_mov_reg_FCC1(t0, src, fcc_offset); - tcg_gen_or_tl(dst, dst, t0); -} - -// 1 or 2: FCC0 ^ FCC1 -static void gen_op_eval_fblg(TCGv dst, TCGv src, unsigned int fcc_offset) -{ - TCGv t0 = tcg_temp_new(); - gen_mov_reg_FCC0(dst, src, fcc_offset); - gen_mov_reg_FCC1(t0, src, fcc_offset); - tcg_gen_xor_tl(dst, dst, t0); -} - -// 1 or 3: FCC0 -static void gen_op_eval_fbul(TCGv dst, TCGv src, unsigned int fcc_offset) -{ - gen_mov_reg_FCC0(dst, src, fcc_offset); -} - -// 1: FCC0 & !FCC1 -static void gen_op_eval_fbl(TCGv dst, TCGv src, unsigned int fcc_offset) -{ - TCGv t0 = tcg_temp_new(); - gen_mov_reg_FCC0(dst, src, fcc_offset); - gen_mov_reg_FCC1(t0, src, fcc_offset); - tcg_gen_andc_tl(dst, dst, t0); -} - -// 2 or 3: FCC1 -static void gen_op_eval_fbug(TCGv dst, TCGv src, unsigned int fcc_offset) -{ - gen_mov_reg_FCC1(dst, src, fcc_offset); -} - -// 2: !FCC0 & FCC1 -static void gen_op_eval_fbg(TCGv dst, TCGv src, unsigned int fcc_offset) -{ - TCGv t0 = tcg_temp_new(); - gen_mov_reg_FCC0(dst, src, fcc_offset); - gen_mov_reg_FCC1(t0, src, fcc_offset); - tcg_gen_andc_tl(dst, t0, dst); -} - -// 3: FCC0 & FCC1 -static void gen_op_eval_fbu(TCGv dst, TCGv src, unsigned int fcc_offset) -{ - TCGv t0 = tcg_temp_new(); - gen_mov_reg_FCC0(dst, src, fcc_offset); - gen_mov_reg_FCC1(t0, src, fcc_offset); - tcg_gen_and_tl(dst, dst, t0); -} - -// 0: !(FCC0 | FCC1) -static void gen_op_eval_fbe(TCGv dst, TCGv src, unsigned int fcc_offset) -{ - TCGv t0 = tcg_temp_new(); - gen_mov_reg_FCC0(dst, src, fcc_offset); - gen_mov_reg_FCC1(t0, src, fcc_offset); - tcg_gen_or_tl(dst, dst, t0); - tcg_gen_xori_tl(dst, dst, 0x1); -} - -// 0 or 3: !(FCC0 ^ FCC1) -static void gen_op_eval_fbue(TCGv dst, TCGv src, unsigned int fcc_offset) -{ - TCGv t0 = tcg_temp_new(); - gen_mov_reg_FCC0(dst, src, fcc_offset); - gen_mov_reg_FCC1(t0, src, fcc_offset); - tcg_gen_xor_tl(dst, dst, t0); - tcg_gen_xori_tl(dst, dst, 0x1); -} - -// 0 or 2: !FCC0 -static void gen_op_eval_fbge(TCGv dst, TCGv src, unsigned int fcc_offset) -{ - gen_mov_reg_FCC0(dst, src, fcc_offset); - tcg_gen_xori_tl(dst, dst, 0x1); -} - -// !1: !(FCC0 & !FCC1) -static void gen_op_eval_fbuge(TCGv dst, TCGv src, unsigned int fcc_offset) -{ - TCGv t0 = tcg_temp_new(); - gen_mov_reg_FCC0(dst, src, fcc_offset); - gen_mov_reg_FCC1(t0, src, fcc_offset); - tcg_gen_andc_tl(dst, dst, t0); - tcg_gen_xori_tl(dst, dst, 0x1); -} - -// 0 or 1: !FCC1 -static void gen_op_eval_fble(TCGv dst, TCGv src, unsigned int fcc_offset) -{ - gen_mov_reg_FCC1(dst, src, fcc_offset); - tcg_gen_xori_tl(dst, dst, 0x1); -} - -// !2: !(!FCC0 & FCC1) -static void gen_op_eval_fbule(TCGv dst, TCGv src, unsigned int fcc_offset) -{ - TCGv t0 = tcg_temp_new(); - gen_mov_reg_FCC0(dst, src, fcc_offset); - gen_mov_reg_FCC1(t0, src, fcc_offset); - tcg_gen_andc_tl(dst, t0, dst); - tcg_gen_xori_tl(dst, dst, 0x1); -} - -// !3: !(FCC0 & FCC1) -static void gen_op_eval_fbo(TCGv dst, TCGv src, unsigned int fcc_offset) -{ - TCGv t0 = tcg_temp_new(); - gen_mov_reg_FCC0(dst, src, fcc_offset); - gen_mov_reg_FCC1(t0, src, fcc_offset); - tcg_gen_and_tl(dst, dst, t0); - tcg_gen_xori_tl(dst, dst, 0x1); -} - static void finishing_insn(DisasContext *dc) { /* @@ -1096,82 +942,62 @@ static void gen_compare(DisasCompare *cmp, bool xcc, unsigned int cond, static void gen_fcompare(DisasCompare *cmp, unsigned int cc, unsigned int cond) { - unsigned int offset; - TCGv r_dst, fsr; + TCGv_i32 fcc = cpu_fcc[cc]; + TCGv_i32 c1 = fcc; + int c2 = 0; + TCGCond tcond; - /* For now we still generate a straight boolean result. */ - cmp->cond = TCG_COND_NE; - cmp->c1 = r_dst = tcg_temp_new(); - cmp->c2 = 0; - - switch (cc) { - default: - case 0x0: - offset = 0; + /* + * FCC values: + * 0 = + * 1 < + * 2 > + * 3 unordered + */ + switch (cond & 7) { + case 0x0: /* fbn */ + tcond = TCG_COND_NEVER; break; - case 0x1: - offset = 32 - 10; + case 0x1: /* fbne : !0 */ + tcond = TCG_COND_NE; break; - case 0x2: - offset = 34 - 10; + case 0x2: /* fblg : 1 or 2 */ + /* fcc in {1,2} - 1 -> fcc in {0,1} */ + c1 = tcg_temp_new_i32(); + tcg_gen_addi_i32(c1, fcc, -1); + c2 = 1; + tcond = TCG_COND_LEU; break; - case 0x3: - offset = 36 - 10; + case 0x3: /* fbul : 1 or 3 */ + c1 = tcg_temp_new_i32(); + tcg_gen_andi_i32(c1, fcc, 1); + tcond = TCG_COND_NE; + break; + case 0x4: /* fbl : 1 */ + c2 = 1; + tcond = TCG_COND_EQ; + break; + case 0x5: /* fbug : 2 or 3 */ + c2 = 2; + tcond = TCG_COND_GEU; + break; + case 0x6: /* fbg : 2 */ + c2 = 2; + tcond = TCG_COND_EQ; + break; + case 0x7: /* fbu : 3 */ + c2 = 3; + tcond = TCG_COND_EQ; break; } - - fsr = tcg_temp_new(); - tcg_gen_ld_tl(fsr, tcg_env, offsetof(CPUSPARCState, fsr)); - switch (cond) { - case 0x0: - gen_op_eval_bn(r_dst); - break; - case 0x1: - gen_op_eval_fbne(r_dst, fsr, offset); - break; - case 0x2: - gen_op_eval_fblg(r_dst, fsr, offset); - break; - case 0x3: - gen_op_eval_fbul(r_dst, fsr, offset); - break; - case 0x4: - gen_op_eval_fbl(r_dst, fsr, offset); - break; - case 0x5: - gen_op_eval_fbug(r_dst, fsr, offset); - break; - case 0x6: - gen_op_eval_fbg(r_dst, fsr, offset); - break; - case 0x7: - gen_op_eval_fbu(r_dst, fsr, offset); - break; - case 0x8: - gen_op_eval_ba(r_dst); - break; - case 0x9: - gen_op_eval_fbe(r_dst, fsr, offset); - break; - case 0xa: - gen_op_eval_fbue(r_dst, fsr, offset); - break; - case 0xb: - gen_op_eval_fbge(r_dst, fsr, offset); - break; - case 0xc: - gen_op_eval_fbuge(r_dst, fsr, offset); - break; - case 0xd: - gen_op_eval_fble(r_dst, fsr, offset); - break; - case 0xe: - gen_op_eval_fbule(r_dst, fsr, offset); - break; - case 0xf: - gen_op_eval_fbo(r_dst, fsr, offset); - break; + if (cond & 8) { + tcond = tcg_invert_cond(tcond); } + + cmp->cond = tcond; + cmp->c2 = c2; + cmp->c1 = tcg_temp_new(); + tcg_gen_extu_i32_tl(cmp->c1, c1); } static bool gen_compare_reg(DisasCompare *cmp, int cond, TCGv r_src) @@ -1261,148 +1087,6 @@ static void gen_op_fabsq(TCGv_i128 dst, TCGv_i128 src) tcg_gen_concat_i64_i128(dst, l, h); } -#ifdef TARGET_SPARC64 -static void gen_op_fcmps(int fccno, TCGv_i32 r_rs1, TCGv_i32 r_rs2) -{ - switch (fccno) { - case 0: - gen_helper_fcmps(tcg_env, r_rs1, r_rs2); - break; - case 1: - gen_helper_fcmps_fcc1(tcg_env, r_rs1, r_rs2); - break; - case 2: - gen_helper_fcmps_fcc2(tcg_env, r_rs1, r_rs2); - break; - case 3: - gen_helper_fcmps_fcc3(tcg_env, r_rs1, r_rs2); - break; - } -} - -static void gen_op_fcmpd(int fccno, TCGv_i64 r_rs1, TCGv_i64 r_rs2) -{ - switch (fccno) { - case 0: - gen_helper_fcmpd(tcg_env, r_rs1, r_rs2); - break; - case 1: - gen_helper_fcmpd_fcc1(tcg_env, r_rs1, r_rs2); - break; - case 2: - gen_helper_fcmpd_fcc2(tcg_env, r_rs1, r_rs2); - break; - case 3: - gen_helper_fcmpd_fcc3(tcg_env, r_rs1, r_rs2); - break; - } -} - -static void gen_op_fcmpq(int fccno, TCGv_i128 r_rs1, TCGv_i128 r_rs2) -{ - switch (fccno) { - case 0: - gen_helper_fcmpq(tcg_env, r_rs1, r_rs2); - break; - case 1: - gen_helper_fcmpq_fcc1(tcg_env, r_rs1, r_rs2); - break; - case 2: - gen_helper_fcmpq_fcc2(tcg_env, r_rs1, r_rs2); - break; - case 3: - gen_helper_fcmpq_fcc3(tcg_env, r_rs1, r_rs2); - break; - } -} - -static void gen_op_fcmpes(int fccno, TCGv_i32 r_rs1, TCGv_i32 r_rs2) -{ - switch (fccno) { - case 0: - gen_helper_fcmpes(tcg_env, r_rs1, r_rs2); - break; - case 1: - gen_helper_fcmpes_fcc1(tcg_env, r_rs1, r_rs2); - break; - case 2: - gen_helper_fcmpes_fcc2(tcg_env, r_rs1, r_rs2); - break; - case 3: - gen_helper_fcmpes_fcc3(tcg_env, r_rs1, r_rs2); - break; - } -} - -static void gen_op_fcmped(int fccno, TCGv_i64 r_rs1, TCGv_i64 r_rs2) -{ - switch (fccno) { - case 0: - gen_helper_fcmped(tcg_env, r_rs1, r_rs2); - break; - case 1: - gen_helper_fcmped_fcc1(tcg_env, r_rs1, r_rs2); - break; - case 2: - gen_helper_fcmped_fcc2(tcg_env, r_rs1, r_rs2); - break; - case 3: - gen_helper_fcmped_fcc3(tcg_env, r_rs1, r_rs2); - break; - } -} - -static void gen_op_fcmpeq(int fccno, TCGv_i128 r_rs1, TCGv_i128 r_rs2) -{ - switch (fccno) { - case 0: - gen_helper_fcmpeq(tcg_env, r_rs1, r_rs2); - break; - case 1: - gen_helper_fcmpeq_fcc1(tcg_env, r_rs1, r_rs2); - break; - case 2: - gen_helper_fcmpeq_fcc2(tcg_env, r_rs1, r_rs2); - break; - case 3: - gen_helper_fcmpeq_fcc3(tcg_env, r_rs1, r_rs2); - break; - } -} - -#else - -static void gen_op_fcmps(int fccno, TCGv r_rs1, TCGv r_rs2) -{ - gen_helper_fcmps(tcg_env, r_rs1, r_rs2); -} - -static void gen_op_fcmpd(int fccno, TCGv_i64 r_rs1, TCGv_i64 r_rs2) -{ - gen_helper_fcmpd(tcg_env, r_rs1, r_rs2); -} - -static void gen_op_fcmpq(int fccno, TCGv_i128 r_rs1, TCGv_i128 r_rs2) -{ - gen_helper_fcmpq(tcg_env, r_rs1, r_rs2); -} - -static void gen_op_fcmpes(int fccno, TCGv r_rs1, TCGv r_rs2) -{ - gen_helper_fcmpes(tcg_env, r_rs1, r_rs2); -} - -static void gen_op_fcmped(int fccno, TCGv_i64 r_rs1, TCGv_i64 r_rs2) -{ - gen_helper_fcmped(tcg_env, r_rs1, r_rs2); -} - -static void gen_op_fcmpeq(int fccno, TCGv_i128 r_rs1, TCGv_i128 r_rs2) -{ - gen_helper_fcmpeq(tcg_env, r_rs1, r_rs2); -} -#endif - static void gen_op_fpexception_im(DisasContext *dc, int ftt) { /* @@ -4400,11 +4084,10 @@ static bool trans_STDFQ(DisasContext *dc, arg_STDFQ *a) return true; } -static bool do_ldfsr(DisasContext *dc, arg_r_r_ri *a, MemOp mop, - target_ulong new_mask, target_ulong old_mask) +static bool trans_LDFSR(DisasContext *dc, arg_r_r_ri *a) { TCGv addr = gen_ldst_addr(dc, a->rs1, a->imm, a->rs2_or_imm); - TCGv tnew, told; + TCGv_i32 tmp; if (addr == NULL) { return false; @@ -4412,19 +4095,48 @@ static bool do_ldfsr(DisasContext *dc, arg_r_r_ri *a, MemOp mop, if (gen_trap_ifnofpu(dc)) { return true; } - tnew = tcg_temp_new(); - told = tcg_temp_new(); - tcg_gen_qemu_ld_tl(tnew, addr, dc->mem_idx, mop | MO_ALIGN); - tcg_gen_ld_tl(told, tcg_env, offsetof(CPUSPARCState, fsr)); - tcg_gen_andi_tl(tnew, tnew, new_mask); - tcg_gen_andi_tl(told, told, old_mask); - tcg_gen_or_tl(tnew, tnew, told); - gen_helper_set_fsr_noftt(tcg_env, tnew); + + tmp = tcg_temp_new_i32(); + tcg_gen_qemu_ld_i32(tmp, addr, dc->mem_idx, MO_TEUL | MO_ALIGN); + + tcg_gen_extract_i32(cpu_fcc[0], tmp, FSR_FCC0_SHIFT, 2); + /* LDFSR does not change FCC[1-3]. */ + + gen_helper_set_fsr_nofcc_noftt(tcg_env, tmp); return advance_pc(dc); } -TRANS(LDFSR, ALL, do_ldfsr, a, MO_TEUL, FSR_LDFSR_MASK, FSR_LDFSR_OLDMASK) -TRANS(LDXFSR, 64, do_ldfsr, a, MO_TEUQ, FSR_LDXFSR_MASK, FSR_LDXFSR_OLDMASK) +static bool trans_LDXFSR(DisasContext *dc, arg_r_r_ri *a) +{ +#ifdef TARGET_SPARC64 + TCGv addr = gen_ldst_addr(dc, a->rs1, a->imm, a->rs2_or_imm); + TCGv_i64 t64; + TCGv_i32 lo, hi; + + if (addr == NULL) { + return false; + } + if (gen_trap_ifnofpu(dc)) { + return true; + } + + t64 = tcg_temp_new_i64(); + tcg_gen_qemu_ld_i64(t64, addr, dc->mem_idx, MO_TEUQ | MO_ALIGN); + + lo = tcg_temp_new_i32(); + hi = cpu_fcc[3]; + tcg_gen_extr_i64_i32(lo, hi, t64); + tcg_gen_extract_i32(cpu_fcc[0], lo, FSR_FCC0_SHIFT, 2); + tcg_gen_extract_i32(cpu_fcc[1], hi, FSR_FCC1_SHIFT - 32, 2); + tcg_gen_extract_i32(cpu_fcc[2], hi, FSR_FCC2_SHIFT - 32, 2); + tcg_gen_extract_i32(cpu_fcc[3], hi, FSR_FCC3_SHIFT - 32, 2); + + gen_helper_set_fsr_nofcc_noftt(tcg_env, lo); + return advance_pc(dc); +#else + return false; +#endif +} static bool do_stfsr(DisasContext *dc, arg_r_r_ri *a, MemOp mop) { @@ -5075,9 +4787,9 @@ static bool do_fcmps(DisasContext *dc, arg_FCMPs *a, bool e) src1 = gen_load_fpr_F(dc, a->rs1); src2 = gen_load_fpr_F(dc, a->rs2); if (e) { - gen_op_fcmpes(a->cc, src1, src2); + gen_helper_fcmpes(cpu_fcc[a->cc], tcg_env, src1, src2); } else { - gen_op_fcmps(a->cc, src1, src2); + gen_helper_fcmps(cpu_fcc[a->cc], tcg_env, src1, src2); } return advance_pc(dc); } @@ -5099,9 +4811,9 @@ static bool do_fcmpd(DisasContext *dc, arg_FCMPd *a, bool e) src1 = gen_load_fpr_D(dc, a->rs1); src2 = gen_load_fpr_D(dc, a->rs2); if (e) { - gen_op_fcmped(a->cc, src1, src2); + gen_helper_fcmped(cpu_fcc[a->cc], tcg_env, src1, src2); } else { - gen_op_fcmpd(a->cc, src1, src2); + gen_helper_fcmpd(cpu_fcc[a->cc], tcg_env, src1, src2); } return advance_pc(dc); } @@ -5126,9 +4838,9 @@ static bool do_fcmpq(DisasContext *dc, arg_FCMPq *a, bool e) src1 = gen_load_fpr_Q(dc, a->rs1); src2 = gen_load_fpr_Q(dc, a->rs2); if (e) { - gen_op_fcmpeq(a->cc, src1, src2); + gen_helper_fcmpeq(cpu_fcc[a->cc], tcg_env, src1, src2); } else { - gen_op_fcmpq(a->cc, src1, src2); + gen_helper_fcmpq(cpu_fcc[a->cc], tcg_env, src1, src2); } return advance_pc(dc); } @@ -5334,6 +5046,18 @@ void sparc_tcg_init(void) "f48", "f50", "f52", "f54", "f56", "f58", "f60", "f62", }; + static const struct { TCGv_i32 *ptr; int off; const char *name; } r32[] = { +#ifdef TARGET_SPARC64 + { &cpu_fprs, offsetof(CPUSPARCState, fprs), "fprs" }, + { &cpu_fcc[0], offsetof(CPUSPARCState, fcc[0]), "fcc0" }, + { &cpu_fcc[1], offsetof(CPUSPARCState, fcc[1]), "fcc1" }, + { &cpu_fcc[2], offsetof(CPUSPARCState, fcc[2]), "fcc2" }, + { &cpu_fcc[3], offsetof(CPUSPARCState, fcc[3]), "fcc3" }, +#else + { &cpu_fcc[0], offsetof(CPUSPARCState, fcc[0]), "fcc" }, +#endif + }; + static const struct { TCGv *ptr; int off; const char *name; } rtl[] = { #ifdef TARGET_SPARC64 { &cpu_gsr, offsetof(CPUSPARCState, gsr), "gsr" }, @@ -5357,6 +5081,10 @@ void sparc_tcg_init(void) offsetof(CPUSPARCState, regwptr), "regwptr"); + for (i = 0; i < ARRAY_SIZE(r32); ++i) { + *r32[i].ptr = tcg_global_mem_new_i32(tcg_env, r32[i].off, r32[i].name); + } + for (i = 0; i < ARRAY_SIZE(rtl); ++i) { *rtl[i].ptr = tcg_global_mem_new(tcg_env, rtl[i].off, rtl[i].name); } @@ -5379,11 +5107,6 @@ void sparc_tcg_init(void) offsetof(CPUSPARCState, fpr[i]), fregnames[i]); } - -#ifdef TARGET_SPARC64 - cpu_fprs = tcg_global_mem_new_i32(tcg_env, - offsetof(CPUSPARCState, fprs), "fprs"); -#endif } void sparc_restore_state_to_opc(CPUState *cs, From 240f46b9f26f5aaa0495d30a6d49f94861d04014 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Fri, 3 Nov 2023 10:38:41 -0700 Subject: [PATCH 57/58] target/sparc: Remove FSR_FTT_NMASK, FSR_FTT_CEXC_NMASK These macros are no longer used. Signed-off-by: Richard Henderson Tested-by: Mark Cave-Ayland Acked-by: Mark Cave-Ayland Message-Id: <20231103173841.33651-23-richard.henderson@linaro.org> --- target/sparc/cpu.h | 7 ------- 1 file changed, 7 deletions(-) diff --git a/target/sparc/cpu.h b/target/sparc/cpu.h index 986c7217ed..edf46b387e 100644 --- a/target/sparc/cpu.h +++ b/target/sparc/cpu.h @@ -202,13 +202,6 @@ enum { #define FSR_FTT1 (1ULL << 15) #define FSR_FTT0 (1ULL << 14) #define FSR_FTT_MASK (FSR_FTT2 | FSR_FTT1 | FSR_FTT0) -#ifdef TARGET_SPARC64 -#define FSR_FTT_NMASK 0xfffffffffffe3fffULL -#define FSR_FTT_CEXC_NMASK 0xfffffffffffe3fe0ULL -#else -#define FSR_FTT_NMASK 0xfffe3fffULL -#define FSR_FTT_CEXC_NMASK 0xfffe3fe0ULL -#endif #define FSR_FTT_IEEE_EXCP (1ULL << 14) #define FSR_FTT_UNIMPFPOP (3ULL << 14) #define FSR_FTT_SEQ_ERROR (4ULL << 14) From 6400be014f80e4c2c246eb8be709ea3a96428233 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Fri, 2 Feb 2024 13:44:27 +1000 Subject: [PATCH 58/58] linux-user/aarch64: Add padding before __kernel_rt_sigreturn MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Without this padding, an unwind through the signal handler will pick up the unwind info for the preceding syscall. This fixes gcc's 30_threads/thread/native_handle/cancel.cc. Cc: qemu-stable@nongnu.org Fixes: ee95fae075c6 ("linux-user/aarch64: Add vdso") Resolves: https://linaro.atlassian.net/browse/GNU-974 Signed-off-by: Richard Henderson Reviewed-by: Alex Bennée Message-Id: <20240202034427.504686-1-richard.henderson@linaro.org> --- linux-user/aarch64/vdso-be.so | Bin 3216 -> 3224 bytes linux-user/aarch64/vdso-le.so | Bin 3216 -> 3224 bytes linux-user/aarch64/vdso.S | 4 ++++ 3 files changed, 4 insertions(+) diff --git a/linux-user/aarch64/vdso-be.so b/linux-user/aarch64/vdso-be.so index 6084f3d1a701316004894fcdd739c4e1e0463b68..808206ade824b09d786f6cc34f7cddf80b63130e 100755 GIT binary patch delta 121 zcmbOrIYV-SKI4pu2Kk&{7{Gw#%fuBAMC1c?^>~k}v|avdxNjSSLfftVb3bgJ!|2S& z_-6A1CJrVZc?IUH8G;R$7#SF@Om<{a*v!K!&BXX-vIe^~TWO|cva$K*Om;sOMw`hy ZxXl@VO#Z-a&zLdUfXALuXmSCM0s#EKC)of1 delta 116 zcmbOsIYDxQKI4Rm2Kk&H7{Gw#!^9O2L>8U?-5V_M@!kH(Sx4vJn|*ujLPgija~Pc& z8DDIEz{J5c`3;N8W)W6tCdL<&4cM*OEF8_CVnO!c?IUH8G;R$7#SF@Om<{a*v!K!!o>JyvLd?^n`3BUW_royOm=q`Mw`hS dxy>1WOn%92&zLb;lgFM@hy!9z%j7~Xc>tTxDQW-! delta 108 zcmbOsIYDxQ2IGW@n)#d`SQx