From 4a09d0bb34ab030e09e87173b2e3ec0fd7616cff Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Wed, 8 Feb 2017 15:06:54 -0800 Subject: target/openrisc: Rename the cpu from or32 to or1k This is in keeping with the toolchain and or1ksim. Signed-off-by: Richard Henderson --- target/openrisc/cpu.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'target') diff --git a/target/openrisc/cpu.h b/target/openrisc/cpu.h index 508ef56..231c163 100644 --- a/target/openrisc/cpu.h +++ b/target/openrisc/cpu.h @@ -32,7 +32,7 @@ struct OpenRISCCPU; #include "fpu/softfloat.h" #include "qom/cpu.h" -#define TYPE_OPENRISC_CPU "or32-cpu" +#define TYPE_OPENRISC_CPU "or1k-cpu" #define OPENRISC_CPU_CLASS(klass) \ OBJECT_CLASS_CHECK(OpenRISCCPUClass, (klass), TYPE_OPENRISC_CPU) -- cgit v1.1 From c56e3b86701501364a4756201b6a9db9454463ab Mon Sep 17 00:00:00 2001 From: Stafford Horne Date: Sat, 14 Jan 2017 07:00:28 +0900 Subject: target/openrisc: Fix exception handling status registers I am working on testing instruction emulation patches for the linux kernel. During testing I found these 2 issues: - sets DSX (delay slot exception) but never clears it - EEAR for illegal insns should point to the bad exception (as per openrisc spec) but its not This patch fixes these two issues by clearing the DSX flag when not in a delay slot and by setting EEAR to exception PC when handling illegal instruction exceptions. After this patch the openrisc kernel with latest patches boots great on qemu and instruction emulation works. Cc: qemu-trivial@nongnu.org Cc: openrisc@lists.librecores.org Signed-off-by: Stafford Horne Message-Id: <20170113220028.29687-1-shorne@gmail.com> Signed-off-by: Richard Henderson --- target/openrisc/interrupt.c | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'target') diff --git a/target/openrisc/interrupt.c b/target/openrisc/interrupt.c index e43fc84..a243eb2 100644 --- a/target/openrisc/interrupt.c +++ b/target/openrisc/interrupt.c @@ -38,10 +38,17 @@ void openrisc_cpu_do_interrupt(CPUState *cs) env->flags &= ~D_FLAG; env->sr |= SR_DSX; env->epcr -= 4; + } else { + env->sr &= ~SR_DSX; } if (cs->exception_index == EXCP_SYSCALL) { env->epcr += 4; } + /* When we have an illegal instruction the error effective address + shall be set to the illegal instruction address. */ + if (cs->exception_index == EXCP_ILLEGAL) { + env->eear = env->pc; + } /* For machine-state changed between user-mode and supervisor mode, we need flush TLB when we enter&exit EXCP. */ -- cgit v1.1 From 930c3d0074ad0a5e26560f2133f82d803369bec3 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Wed, 18 Feb 2015 22:19:18 -0800 Subject: target/openrisc: Implement lwa, swa Signed-off-by: Richard Henderson --- target/openrisc/cpu.c | 1 + target/openrisc/cpu.h | 3 ++ target/openrisc/interrupt.c | 1 + target/openrisc/interrupt_helper.c | 1 + target/openrisc/machine.c | 24 ++++++++++------ target/openrisc/mmu.c | 1 + target/openrisc/translate.c | 58 ++++++++++++++++++++++++++++++++++++++ 7 files changed, 81 insertions(+), 8 deletions(-) (limited to 'target') diff --git a/target/openrisc/cpu.c b/target/openrisc/cpu.c index 422139d..7fd2b9a 100644 --- a/target/openrisc/cpu.c +++ b/target/openrisc/cpu.c @@ -48,6 +48,7 @@ static void openrisc_cpu_reset(CPUState *s) cpu->env.pc = 0x100; cpu->env.sr = SR_FO | SR_SM; + cpu->env.lock_addr = -1; s->exception_index = -1; cpu->env.upr = UPR_UP | UPR_DMP | UPR_IMP | UPR_PICP | UPR_TTP; diff --git a/target/openrisc/cpu.h b/target/openrisc/cpu.h index 231c163..06d0e89 100644 --- a/target/openrisc/cpu.h +++ b/target/openrisc/cpu.h @@ -296,6 +296,9 @@ typedef struct CPUOpenRISCState { uint32_t fpcsr; /* Float register */ float_status fp_status; + target_ulong lock_addr; + target_ulong lock_value; + uint32_t flags; /* cpu_flags, we only use it for exception in solt so far. */ uint32_t btaken; /* the SR_F bit */ diff --git a/target/openrisc/interrupt.c b/target/openrisc/interrupt.c index a243eb2..a981638 100644 --- a/target/openrisc/interrupt.c +++ b/target/openrisc/interrupt.c @@ -62,6 +62,7 @@ void openrisc_cpu_do_interrupt(CPUState *cs) env->sr &= ~SR_TEE; env->tlb->cpu_openrisc_map_address_data = &cpu_openrisc_get_phys_nommu; env->tlb->cpu_openrisc_map_address_code = &cpu_openrisc_get_phys_nommu; + env->lock_addr = -1; if (cs->exception_index > 0 && cs->exception_index < EXCP_NR) { env->pc = (cs->exception_index << 8); diff --git a/target/openrisc/interrupt_helper.c b/target/openrisc/interrupt_helper.c index 0ed5146..a6d4df3 100644 --- a/target/openrisc/interrupt_helper.c +++ b/target/openrisc/interrupt_helper.c @@ -34,6 +34,7 @@ void HELPER(rfe)(CPUOpenRISCState *env) cpu->env.pc = cpu->env.epcr; cpu->env.npc = cpu->env.epcr; cpu->env.sr = cpu->env.esr; + cpu->env.lock_addr = -1; #ifndef CONFIG_USER_ONLY if (cpu->env.sr & SR_DME) { diff --git a/target/openrisc/machine.c b/target/openrisc/machine.c index 17b0c77..d0b47ef 100644 --- a/target/openrisc/machine.c +++ b/target/openrisc/machine.c @@ -26,18 +26,26 @@ static const VMStateDescription vmstate_env = { .name = "env", - .version_id = 1, - .minimum_version_id = 1, + .version_id = 2, + .minimum_version_id = 2, .fields = (VMStateField[]) { - VMSTATE_UINT32_ARRAY(gpr, CPUOpenRISCState, 32), + VMSTATE_UINTTL_ARRAY(gpr, CPUOpenRISCState, 32), + VMSTATE_UINTTL(pc, CPUOpenRISCState), + VMSTATE_UINTTL(npc, CPUOpenRISCState), + VMSTATE_UINTTL(ppc, CPUOpenRISCState), + VMSTATE_UINTTL(jmp_pc, CPUOpenRISCState), + VMSTATE_UINTTL(lock_addr, CPUOpenRISCState), + VMSTATE_UINTTL(lock_value, CPUOpenRISCState), + VMSTATE_UINTTL(epcr, CPUOpenRISCState), + VMSTATE_UINTTL(eear, CPUOpenRISCState), VMSTATE_UINT32(sr, CPUOpenRISCState), - VMSTATE_UINT32(epcr, CPUOpenRISCState), - VMSTATE_UINT32(eear, CPUOpenRISCState), + VMSTATE_UINT32(vr, CPUOpenRISCState), + VMSTATE_UINT32(upr, CPUOpenRISCState), + VMSTATE_UINT32(cpucfgr, CPUOpenRISCState), + VMSTATE_UINT32(dmmucfgr, CPUOpenRISCState), + VMSTATE_UINT32(immucfgr, CPUOpenRISCState), VMSTATE_UINT32(esr, CPUOpenRISCState), VMSTATE_UINT32(fpcsr, CPUOpenRISCState), - VMSTATE_UINT32(pc, CPUOpenRISCState), - VMSTATE_UINT32(npc, CPUOpenRISCState), - VMSTATE_UINT32(ppc, CPUOpenRISCState), VMSTATE_END_OF_LIST() } }; diff --git a/target/openrisc/mmu.c b/target/openrisc/mmu.c index 505dcdc..56b11d3 100644 --- a/target/openrisc/mmu.c +++ b/target/openrisc/mmu.c @@ -174,6 +174,7 @@ static void cpu_openrisc_raise_mmu_exception(OpenRISCCPU *cpu, cs->exception_index = exception; cpu->env.eear = address; + cpu->env.lock_addr = -1; } #ifndef CONFIG_USER_ONLY diff --git a/target/openrisc/translate.c b/target/openrisc/translate.c index 03fa7db..c207875 100644 --- a/target/openrisc/translate.c +++ b/target/openrisc/translate.c @@ -61,6 +61,8 @@ static TCGv jmp_pc; /* l.jr/l.jalr temp pc */ static TCGv cpu_npc; static TCGv cpu_ppc; static TCGv_i32 env_btaken; /* bf/bnf , F flag taken */ +static TCGv cpu_lock_addr; +static TCGv cpu_lock_value; static TCGv_i32 fpcsr; static TCGv machi, maclo; static TCGv fpmaddhi, fpmaddlo; @@ -95,6 +97,12 @@ void openrisc_translate_init(void) env_btaken = tcg_global_mem_new_i32(cpu_env, offsetof(CPUOpenRISCState, btaken), "btaken"); + cpu_lock_addr = tcg_global_mem_new(cpu_env, + offsetof(CPUOpenRISCState, lock_addr), + "lock_addr"); + cpu_lock_value = tcg_global_mem_new(cpu_env, + offsetof(CPUOpenRISCState, lock_value), + "lock_value"); fpcsr = tcg_global_mem_new_i32(cpu_env, offsetof(CPUOpenRISCState, fpcsr), "fpcsr"); @@ -265,6 +273,46 @@ static void gen_jump(DisasContext *dc, uint32_t imm, uint32_t reg, uint32_t op0) } +static void gen_lwa(DisasContext *dc, TCGv rd, TCGv ra, int32_t ofs) +{ + TCGv ea = tcg_temp_new(); + + tcg_gen_addi_tl(ea, ra, ofs); + tcg_gen_qemu_ld_tl(rd, ea, dc->mem_idx, MO_TEUL); + tcg_gen_mov_tl(cpu_lock_addr, ea); + tcg_gen_mov_tl(cpu_lock_value, rd); + tcg_temp_free(ea); +} + +static void gen_swa(DisasContext *dc, TCGv rb, TCGv ra, int32_t ofs) +{ + TCGv ea, val; + TCGLabel *lab_fail, *lab_done; + + ea = tcg_temp_new(); + tcg_gen_addi_tl(ea, ra, ofs); + + lab_fail = gen_new_label(); + lab_done = gen_new_label(); + tcg_gen_brcond_tl(TCG_COND_NE, ea, cpu_lock_addr, lab_fail); + tcg_temp_free(ea); + + val = tcg_temp_new(); + tcg_gen_atomic_cmpxchg_tl(val, cpu_lock_addr, cpu_lock_value, + rb, dc->mem_idx, MO_TEUL); + tcg_gen_setcond_tl(TCG_COND_EQ, env_btaken, val, cpu_lock_value); + tcg_temp_free(val); + + tcg_gen_br(lab_done); + + gen_set_label(lab_fail); + tcg_gen_movi_tl(env_btaken, 0); + + gen_set_label(lab_done); + tcg_gen_movi_tl(cpu_lock_addr, -1); + wb_SR_F(); +} + static void dec_calc(DisasContext *dc, uint32_t insn) { uint32_t op0, op1, op2; @@ -819,6 +867,11 @@ static void dec_misc(DisasContext *dc, uint32_t insn) } break; + case 0x1b: /* l.lwa */ + LOG_DIS("l.lwa r%d, r%d, %d\n", rd, ra, I16); + gen_lwa(dc, cpu_R[rd], cpu_R[ra], I16); + break; + case 0x1c: /* l.cust1 */ LOG_DIS("l.cust1\n"); break; @@ -1029,6 +1082,11 @@ static void dec_misc(DisasContext *dc, uint32_t insn) } break; + case 0x33: /* l.swa */ + LOG_DIS("l.swa %d, r%d, r%d, %d\n", I5, ra, rb, I11); + gen_swa(dc, cpu_R[rb], cpu_R[ra], sign_extend(tmp, 16)); + break; + /* not used yet, open it when we need or64. */ /*#ifdef TARGET_OPENRISC64 case 0x34: l.sd -- cgit v1.1 From 111ece5133e1f301c43545e9400cbb2f121c0cc3 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Wed, 18 Feb 2015 16:27:45 -0800 Subject: target/openrisc: Tidy insn dumping MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Avoids warnings from unused variables etc. Reviewed-by: Philippe Mathieu-Daudé Reviewed-by: Bastian Koppelmann Signed-off-by: Richard Henderson --- target/openrisc/translate.c | 36 ++++++++++++------------------------ 1 file changed, 12 insertions(+), 24 deletions(-) (limited to 'target') diff --git a/target/openrisc/translate.c b/target/openrisc/translate.c index c207875..ac0c409 100644 --- a/target/openrisc/translate.c +++ b/target/openrisc/translate.c @@ -34,14 +34,8 @@ #include "trace-tcg.h" #include "exec/log.h" - -#define OPENRISC_DISAS - -#ifdef OPENRISC_DISAS -# define LOG_DIS(...) qemu_log_mask(CPU_LOG_TB_IN_ASM, ## __VA_ARGS__) -#else -# define LOG_DIS(...) do { } while (0) -#endif +#define LOG_DIS(str, ...) \ + qemu_log_mask(CPU_LOG_TB_IN_ASM, "%08x: " str, dc->pc, ## __VA_ARGS__) typedef struct DisasContext { TranslationBlock *tb; @@ -766,9 +760,7 @@ static void dec_misc(DisasContext *dc, uint32_t insn) { uint32_t op0, op1; uint32_t ra, rb, rd; -#ifdef OPENRISC_DISAS uint32_t L6, K5; -#endif uint32_t I16, I5, I11, N26, tmp; TCGMemOp mop; @@ -777,10 +769,8 @@ static void dec_misc(DisasContext *dc, uint32_t insn) ra = extract32(insn, 16, 5); rb = extract32(insn, 11, 5); rd = extract32(insn, 21, 5); -#ifdef OPENRISC_DISAS L6 = extract32(insn, 5, 6); K5 = extract32(insn, 0, 5); -#endif I16 = extract32(insn, 0, 16); I5 = extract32(insn, 21, 5); I11 = extract32(insn, 0, 11); @@ -1387,13 +1377,10 @@ static void dec_compi(DisasContext *dc, uint32_t insn) static void dec_sys(DisasContext *dc, uint32_t insn) { uint32_t op0; -#ifdef OPENRISC_DISAS uint32_t K16; -#endif + op0 = extract32(insn, 16, 10); -#ifdef OPENRISC_DISAS K16 = extract32(insn, 0, 16); -#endif switch (op0) { case 0x000: /* l.sys */ @@ -1723,6 +1710,13 @@ void gen_intermediate_code(CPUOpenRISCState *env, struct TranslationBlock *tb) max_insns = TCG_MAX_INSNS; } + if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM) + && qemu_log_in_addr_range(pc_start)) { + qemu_log_lock(); + qemu_log("----------------\n"); + qemu_log("IN: %s\n", lookup_symbol(pc_start)); + } + gen_tb_start(tb); do { @@ -1807,18 +1801,12 @@ void gen_intermediate_code(CPUOpenRISCState *env, struct TranslationBlock *tb) tb->size = dc->pc - pc_start; tb->icount = num_insns; -#ifdef DEBUG_DISAS if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM) && qemu_log_in_addr_range(pc_start)) { - qemu_log_lock(); - qemu_log("----------------\n"); - qemu_log("IN: %s\n", lookup_symbol(pc_start)); - log_target_disas(cs, pc_start, dc->pc - pc_start, 0); - qemu_log("\nisize=%d osize=%d\n", - dc->pc - pc_start, tcg_op_buf_count()); + log_target_disas(cs, pc_start, tb->size, 0); + qemu_log("\n"); qemu_log_unlock(); } -#endif } void openrisc_cpu_dump_state(CPUState *cs, FILE *f, -- cgit v1.1 From 6da544a6c4572ed11931218e940f45d00b1fe3a7 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Thu, 26 Jan 2017 17:35:09 -0800 Subject: target/openrisc: Rationalize immediate extraction The architecture manual is consistent in using "I" for signed fields and "K" for unsigned fields. Mirror that. Reviewed-by: Bastian Koppelmann Signed-off-by: Richard Henderson --- target/openrisc/translate.c | 98 ++++++++++++++++++--------------------------- 1 file changed, 40 insertions(+), 58 deletions(-) (limited to 'target') diff --git a/target/openrisc/translate.c b/target/openrisc/translate.c index ac0c409..d999d2f 100644 --- a/target/openrisc/translate.c +++ b/target/openrisc/translate.c @@ -129,23 +129,6 @@ static inline void wb_SR_F(void) gen_set_label(label); } -static inline int zero_extend(unsigned int val, int width) -{ - return val & ((1 << width) - 1); -} - -static inline int sign_extend(unsigned int val, int width) -{ - int sval; - - /* LSL */ - val <<= TARGET_LONG_BITS - width; - sval = val; - /* ASR. */ - sval >>= TARGET_LONG_BITS - width; - return sval; -} - static inline void gen_sync_flags(DisasContext *dc) { /* Sync the tb dependent flag between translate and runtime. */ @@ -221,11 +204,9 @@ static void gen_goto_tb(DisasContext *dc, int n, target_ulong dest) } } -static void gen_jump(DisasContext *dc, uint32_t imm, uint32_t reg, uint32_t op0) +static void gen_jump(DisasContext *dc, int32_t n26, uint32_t reg, uint32_t op0) { - target_ulong tmp_pc; - /* N26, 26bits imm */ - tmp_pc = sign_extend((imm<<2), 26) + dc->pc; + target_ulong tmp_pc = dc->pc + n26 * 4; switch (op0) { case 0x00: /* l.j */ @@ -760,8 +741,8 @@ static void dec_misc(DisasContext *dc, uint32_t insn) { uint32_t op0, op1; uint32_t ra, rb, rd; - uint32_t L6, K5; - uint32_t I16, I5, I11, N26, tmp; + uint32_t L6, K5, K16, K5_11; + int32_t I16, I5_11, N26; TCGMemOp mop; op0 = extract32(insn, 26, 6); @@ -771,11 +752,11 @@ static void dec_misc(DisasContext *dc, uint32_t insn) rd = extract32(insn, 21, 5); L6 = extract32(insn, 5, 6); K5 = extract32(insn, 0, 5); - I16 = extract32(insn, 0, 16); - I5 = extract32(insn, 21, 5); - I11 = extract32(insn, 0, 11); - N26 = extract32(insn, 0, 26); - tmp = (I5<<11) + I11; + K16 = extract32(insn, 0, 16); + I16 = (int16_t)K16; + N26 = sextract32(insn, 0, 26); + K5_11 = (extract32(insn, 21, 5) << 11) | extract32(insn, 0, 11); + I5_11 = (int16_t)K5_11; switch (op0) { case 0x00: /* l.j */ @@ -821,12 +802,12 @@ static void dec_misc(DisasContext *dc, uint32_t insn) break; case 0x13: /* l.maci */ - LOG_DIS("l.maci %d, r%d, %d\n", I5, ra, I11); + LOG_DIS("l.maci r%d, %d\n", ra, I16); { TCGv_i64 t1 = tcg_temp_new_i64(); TCGv_i64 t2 = tcg_temp_new_i64(); TCGv_i32 dst = tcg_temp_new_i32(); - TCGv ttmp = tcg_const_tl(tmp); + TCGv ttmp = tcg_const_tl(I16); tcg_gen_mul_tl(dst, cpu_R[ra], ttmp); tcg_gen_ext_i32_i64(t1, dst); tcg_gen_concat_i32_i64(t2, maclo, machi); @@ -936,7 +917,7 @@ static void dec_misc(DisasContext *dc, uint32_t insn) do_load: { TCGv t0 = tcg_temp_new(); - tcg_gen_addi_tl(t0, cpu_R[ra], sign_extend(I16, 16)); + tcg_gen_addi_tl(t0, cpu_R[ra], I16); tcg_gen_qemu_ld_tl(cpu_R[rd], t0, dc->mem_idx, mop); tcg_temp_free(t0); } @@ -954,7 +935,7 @@ static void dec_misc(DisasContext *dc, uint32_t insn) TCGv_i32 res = tcg_temp_local_new_i32(); TCGv_i32 sr_ove = tcg_temp_local_new_i32(); tcg_gen_extu_i32_i64(ta, cpu_R[ra]); - tcg_gen_addi_i64(td, ta, sign_extend(I16, 16)); + tcg_gen_addi_i64(td, ta, I16); tcg_gen_extrl_i64_i32(res, td); tcg_gen_shri_i64(td, td, 32); tcg_gen_andi_i64(td, td, 0x3); @@ -989,7 +970,7 @@ static void dec_misc(DisasContext *dc, uint32_t insn) tcg_gen_andi_i32(sr_cy, cpu_sr, SR_CY); tcg_gen_shri_i32(sr_cy, sr_cy, 10); tcg_gen_extu_i32_i64(tcy, sr_cy); - tcg_gen_addi_i64(td, ta, sign_extend(I16, 16)); + tcg_gen_addi_i64(td, ta, I16); tcg_gen_add_i64(td, td, tcy); tcg_gen_extrl_i64_i32(res, td); tcg_gen_shri_i64(td, td, 32); @@ -1013,18 +994,18 @@ static void dec_misc(DisasContext *dc, uint32_t insn) break; case 0x29: /* l.andi */ - LOG_DIS("l.andi r%d, r%d, %d\n", rd, ra, I16); - tcg_gen_andi_tl(cpu_R[rd], cpu_R[ra], zero_extend(I16, 16)); + LOG_DIS("l.andi r%d, r%d, %d\n", rd, ra, K16); + tcg_gen_andi_tl(cpu_R[rd], cpu_R[ra], K16); break; case 0x2a: /* l.ori */ - LOG_DIS("l.ori r%d, r%d, %d\n", rd, ra, I16); - tcg_gen_ori_tl(cpu_R[rd], cpu_R[ra], zero_extend(I16, 16)); + LOG_DIS("l.ori r%d, r%d, %d\n", rd, ra, K16); + tcg_gen_ori_tl(cpu_R[rd], cpu_R[ra], K16); break; case 0x2b: /* l.xori */ LOG_DIS("l.xori r%d, r%d, %d\n", rd, ra, I16); - tcg_gen_xori_tl(cpu_R[rd], cpu_R[ra], sign_extend(I16, 16)); + tcg_gen_xori_tl(cpu_R[rd], cpu_R[ra], I16); break; case 0x2c: /* l.muli */ @@ -1039,12 +1020,12 @@ static void dec_misc(DisasContext *dc, uint32_t insn) break; case 0x2d: /* l.mfspr */ - LOG_DIS("l.mfspr r%d, r%d, %d\n", rd, ra, I16); + LOG_DIS("l.mfspr r%d, r%d, %d\n", rd, ra, K16); { #if defined(CONFIG_USER_ONLY) return; #else - TCGv_i32 ti = tcg_const_i32(I16); + TCGv_i32 ti = tcg_const_i32(K16); if (dc->mem_idx == MMU_USER_IDX) { gen_illegal_exception(dc); return; @@ -1056,12 +1037,12 @@ static void dec_misc(DisasContext *dc, uint32_t insn) break; case 0x30: /* l.mtspr */ - LOG_DIS("l.mtspr %d, r%d, r%d, %d\n", I5, ra, rb, I11); + LOG_DIS("l.mtspr r%d, r%d, %d\n", ra, rb, K5_11); { #if defined(CONFIG_USER_ONLY) return; #else - TCGv_i32 im = tcg_const_i32(tmp); + TCGv_i32 im = tcg_const_i32(K5_11); if (dc->mem_idx == MMU_USER_IDX) { gen_illegal_exception(dc); return; @@ -1073,38 +1054,38 @@ static void dec_misc(DisasContext *dc, uint32_t insn) break; case 0x33: /* l.swa */ - LOG_DIS("l.swa %d, r%d, r%d, %d\n", I5, ra, rb, I11); - gen_swa(dc, cpu_R[rb], cpu_R[ra], sign_extend(tmp, 16)); + LOG_DIS("l.swa r%d, r%d, %d\n", ra, rb, I5_11); + gen_swa(dc, cpu_R[rb], cpu_R[ra], I5_11); break; /* not used yet, open it when we need or64. */ /*#ifdef TARGET_OPENRISC64 case 0x34: l.sd - LOG_DIS("l.sd %d, r%d, r%d, %d\n", I5, ra, rb, I11); + LOG_DIS("l.sd r%d, r%d, %d\n", ra, rb, I5_11); check_ob64s(dc); mop = MO_TEQ; goto do_store; #endif*/ case 0x35: /* l.sw */ - LOG_DIS("l.sw %d, r%d, r%d, %d\n", I5, ra, rb, I11); + LOG_DIS("l.sw r%d, r%d, %d\n", ra, rb, I5_11); mop = MO_TEUL; goto do_store; case 0x36: /* l.sb */ - LOG_DIS("l.sb %d, r%d, r%d, %d\n", I5, ra, rb, I11); + LOG_DIS("l.sb r%d, r%d, %d\n", ra, rb, I5_11); mop = MO_UB; goto do_store; case 0x37: /* l.sh */ - LOG_DIS("l.sh %d, r%d, r%d, %d\n", I5, ra, rb, I11); + LOG_DIS("l.sh r%d, r%d, %d\n", ra, rb, I5_11); mop = MO_TEUW; goto do_store; do_store: { TCGv t0 = tcg_temp_new(); - tcg_gen_addi_tl(t0, cpu_R[ra], sign_extend(tmp, 16)); + tcg_gen_addi_tl(t0, cpu_R[ra], I5_11); tcg_gen_qemu_st_tl(cpu_R[rb], t0, dc->mem_idx, mop); tcg_temp_free(t0); } @@ -1172,30 +1153,32 @@ static void dec_mac(DisasContext *dc, uint32_t insn) static void dec_logic(DisasContext *dc, uint32_t insn) { uint32_t op0; - uint32_t rd, ra, L6; + uint32_t rd, ra, L6, S6; op0 = extract32(insn, 6, 2); rd = extract32(insn, 21, 5); ra = extract32(insn, 16, 5); L6 = extract32(insn, 0, 6); + S6 = L6 & (TARGET_LONG_BITS - 1); switch (op0) { case 0x00: /* l.slli */ LOG_DIS("l.slli r%d, r%d, %d\n", rd, ra, L6); - tcg_gen_shli_tl(cpu_R[rd], cpu_R[ra], (L6 & 0x1f)); + tcg_gen_shli_tl(cpu_R[rd], cpu_R[ra], S6); break; case 0x01: /* l.srli */ LOG_DIS("l.srli r%d, r%d, %d\n", rd, ra, L6); - tcg_gen_shri_tl(cpu_R[rd], cpu_R[ra], (L6 & 0x1f)); + tcg_gen_shri_tl(cpu_R[rd], cpu_R[ra], S6); break; case 0x02: /* l.srai */ LOG_DIS("l.srai r%d, r%d, %d\n", rd, ra, L6); - tcg_gen_sari_tl(cpu_R[rd], cpu_R[ra], (L6 & 0x1f)); break; + tcg_gen_sari_tl(cpu_R[rd], cpu_R[ra], S6); + break; case 0x03: /* l.rori */ LOG_DIS("l.rori r%d, r%d, %d\n", rd, ra, L6); - tcg_gen_rotri_tl(cpu_R[rd], cpu_R[ra], (L6 & 0x1f)); + tcg_gen_rotri_tl(cpu_R[rd], cpu_R[ra], S6); break; default: @@ -1306,15 +1289,14 @@ static void dec_comp(DisasContext *dc, uint32_t insn) static void dec_compi(DisasContext *dc, uint32_t insn) { - uint32_t op0; - uint32_t ra, I16; + uint32_t op0, ra; + int32_t I16; op0 = extract32(insn, 21, 5); ra = extract32(insn, 16, 5); - I16 = extract32(insn, 0, 16); + I16 = sextract32(insn, 0, 16); tcg_gen_movi_i32(env_btaken, 0x0); - I16 = sign_extend(I16, 16); switch (op0) { case 0x0: /* l.sfeqi */ -- cgit v1.1 From 9ecaa27e7123211f45ca723a736ffae14f6c1f42 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Tue, 7 Apr 2015 13:31:50 -0700 Subject: target/openrisc: Streamline arithmetic and OVE Fix incorrect overflow calculation. Move overflow exception check to a helper function, to eliminate inline branches. Remove some incorrect special casing of R0. Implement multiply inline. Reviewed-by: Bastian Koppelmann Signed-off-by: Richard Henderson --- target/openrisc/Makefile.objs | 2 +- target/openrisc/exception_helper.c | 12 ++ target/openrisc/helper.h | 4 +- target/openrisc/int_helper.c | 61 ------ target/openrisc/translate.c | 426 +++++++++++++++---------------------- 5 files changed, 191 insertions(+), 314 deletions(-) delete mode 100644 target/openrisc/int_helper.c (limited to 'target') diff --git a/target/openrisc/Makefile.objs b/target/openrisc/Makefile.objs index 397d016..918b1c6 100644 --- a/target/openrisc/Makefile.objs +++ b/target/openrisc/Makefile.objs @@ -1,5 +1,5 @@ obj-$(CONFIG_SOFTMMU) += machine.o obj-y += cpu.o exception.o interrupt.o mmu.o translate.o -obj-y += exception_helper.o fpu_helper.o int_helper.o \ +obj-y += exception_helper.o fpu_helper.o \ interrupt_helper.o mmu_helper.o sys_helper.o obj-y += gdbstub.o diff --git a/target/openrisc/exception_helper.c b/target/openrisc/exception_helper.c index 329a9e4..7e54c97 100644 --- a/target/openrisc/exception_helper.c +++ b/target/openrisc/exception_helper.c @@ -20,6 +20,7 @@ #include "qemu/osdep.h" #include "cpu.h" #include "exec/helper-proto.h" +#include "exec/exec-all.h" #include "exception.h" void HELPER(exception)(CPUOpenRISCState *env, uint32_t excp) @@ -28,3 +29,14 @@ void HELPER(exception)(CPUOpenRISCState *env, uint32_t excp) raise_exception(cpu, excp); } + +void HELPER(ove)(CPUOpenRISCState *env, target_ulong test) +{ + if (unlikely(test) && (env->sr & SR_OVE)) { + OpenRISCCPU *cpu = openrisc_env_get_cpu(env); + CPUState *cs = CPU(cpu); + + cs->exception_index = EXCP_RANGE; + cpu_loop_exit_restore(cs, GETPC()); + } +} diff --git a/target/openrisc/helper.h b/target/openrisc/helper.h index bcc7245..c2c8098 100644 --- a/target/openrisc/helper.h +++ b/target/openrisc/helper.h @@ -19,6 +19,7 @@ /* exception */ DEF_HELPER_FLAGS_2(exception, 0, void, env, i32) +DEF_HELPER_FLAGS_2(ove, TCG_CALL_NO_WG, void, env, tl) /* float */ DEF_HELPER_FLAGS_2(itofd, 0, i64, env, i64) @@ -53,9 +54,6 @@ FOP_CMP(gt) FOP_CMP(ge) #undef FOP_CMP -/* int */ -DEF_HELPER_FLAGS_3(mul32, 0, i32, env, i32, i32) - /* interrupt */ DEF_HELPER_FLAGS_1(rfe, 0, void, env) diff --git a/target/openrisc/int_helper.c b/target/openrisc/int_helper.c deleted file mode 100644 index ba0fd27..0000000 --- a/target/openrisc/int_helper.c +++ /dev/null @@ -1,61 +0,0 @@ -/* - * OpenRISC int helper routines - * - * Copyright (c) 2011-2012 Jia Liu - * Feng Gao - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, see . - */ - -#include "qemu/osdep.h" -#include "cpu.h" -#include "exec/helper-proto.h" -#include "exception.h" -#include "qemu/host-utils.h" - -uint32_t HELPER(mul32)(CPUOpenRISCState *env, - uint32_t ra, uint32_t rb) -{ - uint64_t result; - uint32_t high, cy; - - OpenRISCCPU *cpu = openrisc_env_get_cpu(env); - - result = (uint64_t)ra * rb; - /* regisiers in or32 is 32bit, so 32 is NOT a magic number. - or64 is not handled in this function, and not implement yet, - TARGET_LONG_BITS for or64 is 64, it will break this function, - so, we didn't use TARGET_LONG_BITS here. */ - high = result >> 32; - cy = result >> (32 - 1); - - if ((cy & 0x1) == 0x0) { - if (high == 0x0) { - return result; - } - } - - if ((cy & 0x1) == 0x1) { - if (high == 0xffffffff) { - return result; - } - } - - cpu->env.sr |= (SR_OV | SR_CY); - if (cpu->env.sr & SR_OVE) { - raise_exception(cpu, EXCP_RANGE); - } - - return result; -} diff --git a/target/openrisc/translate.c b/target/openrisc/translate.c index d999d2f..7c6cd1c 100644 --- a/target/openrisc/translate.c +++ b/target/openrisc/translate.c @@ -247,6 +247,166 @@ static void gen_jump(DisasContext *dc, int32_t n26, uint32_t reg, uint32_t op0) gen_sync_flags(dc); } +static void gen_ove_cy(DisasContext *dc, TCGv cy) +{ + gen_helper_ove(cpu_env, cy); +} + +static void gen_ove_ov(DisasContext *dc, TCGv ov) +{ + gen_helper_ove(cpu_env, ov); +} + +static void gen_ove_cyov(DisasContext *dc, TCGv cy, TCGv ov) +{ + TCGv t0 = tcg_temp_new(); + tcg_gen_or_tl(t0, cy, ov); + gen_helper_ove(cpu_env, t0); + tcg_temp_free(t0); +} + +static void gen_add(DisasContext *dc, TCGv dest, TCGv srca, TCGv srcb) +{ + TCGv t0 = tcg_const_tl(0); + TCGv res = tcg_temp_new(); + TCGv sr_cy = tcg_temp_new(); + TCGv sr_ov = tcg_temp_new(); + + tcg_gen_add2_tl(res, sr_cy, srca, t0, srcb, t0); + tcg_gen_xor_tl(sr_ov, srca, srcb); + tcg_gen_xor_tl(t0, res, srcb); + tcg_gen_andc_tl(sr_ov, t0, sr_ov); + tcg_temp_free(t0); + + tcg_gen_mov_tl(dest, res); + tcg_temp_free(res); + + tcg_gen_shri_tl(sr_ov, sr_ov, TARGET_LONG_BITS - 1); + tcg_gen_deposit_tl(cpu_sr, cpu_sr, sr_cy, ctz32(SR_CY), 1); + tcg_gen_deposit_tl(cpu_sr, cpu_sr, sr_ov, ctz32(SR_OV), 1); + + gen_ove_cyov(dc, sr_ov, sr_cy); + tcg_temp_free(sr_ov); + tcg_temp_free(sr_cy); +} + +static void gen_addc(DisasContext *dc, TCGv dest, TCGv srca, TCGv srcb) +{ + TCGv t0 = tcg_const_tl(0); + TCGv res = tcg_temp_new(); + TCGv sr_cy = tcg_temp_new(); + TCGv sr_ov = tcg_temp_new(); + + tcg_gen_shri_tl(sr_cy, cpu_sr, ctz32(SR_CY)); + tcg_gen_andi_tl(sr_cy, sr_cy, 1); + + tcg_gen_add2_tl(res, sr_cy, srca, t0, sr_cy, t0); + tcg_gen_add2_tl(res, sr_cy, res, sr_cy, srcb, t0); + tcg_gen_xor_tl(sr_ov, srca, srcb); + tcg_gen_xor_tl(t0, res, srcb); + tcg_gen_andc_tl(sr_ov, t0, sr_ov); + tcg_temp_free(t0); + + tcg_gen_mov_tl(dest, res); + tcg_temp_free(res); + + tcg_gen_shri_tl(sr_ov, sr_ov, TARGET_LONG_BITS - 1); + tcg_gen_deposit_tl(cpu_sr, cpu_sr, sr_cy, ctz32(SR_CY), 1); + tcg_gen_deposit_tl(cpu_sr, cpu_sr, sr_ov, ctz32(SR_OV), 1); + + gen_ove_cyov(dc, sr_ov, sr_cy); + tcg_temp_free(sr_ov); + tcg_temp_free(sr_cy); +} + +static void gen_sub(DisasContext *dc, TCGv dest, TCGv srca, TCGv srcb) +{ + TCGv res = tcg_temp_new(); + TCGv sr_cy = tcg_temp_new(); + TCGv sr_ov = tcg_temp_new(); + + tcg_gen_sub_tl(res, srca, srcb); + tcg_gen_xor_tl(sr_cy, srca, srcb); + tcg_gen_xor_tl(sr_ov, res, srcb); + tcg_gen_and_tl(sr_ov, sr_ov, sr_cy); + tcg_gen_setcond_tl(TCG_COND_LTU, sr_cy, srca, srcb); + + tcg_gen_mov_tl(dest, res); + tcg_temp_free(res); + + tcg_gen_shri_tl(sr_ov, sr_ov, TARGET_LONG_BITS - 1); + tcg_gen_deposit_tl(cpu_sr, cpu_sr, sr_cy, ctz32(SR_CY), 1); + tcg_gen_deposit_tl(cpu_sr, cpu_sr, sr_ov, ctz32(SR_OV), 1); + + gen_ove_cyov(dc, sr_ov, sr_cy); + tcg_temp_free(sr_ov); + tcg_temp_free(sr_cy); +} + +static void gen_mul(DisasContext *dc, TCGv dest, TCGv srca, TCGv srcb) +{ + TCGv sr_ov = tcg_temp_new(); + TCGv t0 = tcg_temp_new(); + + tcg_gen_muls2_tl(dest, sr_ov, srca, srcb); + tcg_gen_sari_tl(t0, dest, TARGET_LONG_BITS - 1); + tcg_gen_setcond_tl(TCG_COND_NE, sr_ov, sr_ov, t0); + tcg_temp_free(t0); + + tcg_gen_deposit_tl(cpu_sr, cpu_sr, sr_ov, ctz32(SR_OV), 1); + + gen_ove_ov(dc, sr_ov); + tcg_temp_free(sr_ov); +} + +static void gen_mulu(DisasContext *dc, TCGv dest, TCGv srca, TCGv srcb) +{ + TCGv sr_cy = tcg_temp_new(); + + tcg_gen_muls2_tl(dest, sr_cy, srca, srcb); + tcg_gen_setcondi_tl(TCG_COND_NE, sr_cy, sr_cy, 0); + + tcg_gen_deposit_tl(cpu_sr, cpu_sr, sr_cy, ctz32(SR_CY), 1); + + gen_ove_cy(dc, sr_cy); + tcg_temp_free(sr_cy); +} + +static void gen_div(DisasContext *dc, TCGv dest, TCGv srca, TCGv srcb) +{ + TCGv sr_ov = tcg_temp_new(); + TCGv t0 = tcg_temp_new(); + + tcg_gen_setcondi_tl(TCG_COND_EQ, sr_ov, srcb, 0); + /* The result of divide-by-zero is undefined. + Supress the host-side exception by dividing by 1. */ + tcg_gen_or_tl(t0, srcb, sr_ov); + tcg_gen_div_tl(dest, srca, t0); + tcg_temp_free(t0); + + tcg_gen_deposit_tl(cpu_sr, cpu_sr, sr_ov, ctz32(SR_OV), 1); + + gen_ove_ov(dc, sr_ov); + tcg_temp_free(sr_ov); +} + +static void gen_divu(DisasContext *dc, TCGv dest, TCGv srca, TCGv srcb) +{ + TCGv sr_cy = tcg_temp_new(); + TCGv t0 = tcg_temp_new(); + + tcg_gen_setcondi_tl(TCG_COND_EQ, sr_cy, srcb, 0); + /* The result of divide-by-zero is undefined. + Supress the host-side exception by dividing by 1. */ + tcg_gen_or_tl(t0, srcb, sr_cy); + tcg_gen_divu_tl(dest, srca, t0); + tcg_temp_free(t0); + + tcg_gen_deposit_tl(cpu_sr, cpu_sr, sr_cy, ctz32(SR_CY), 1); + + gen_ove_cy(dc, sr_cy); + tcg_temp_free(sr_cy); +} static void gen_lwa(DisasContext *dc, TCGv rd, TCGv ra, int32_t ofs) { @@ -304,34 +464,7 @@ static void dec_calc(DisasContext *dc, uint32_t insn) switch (op1) { case 0x00: /* l.add */ LOG_DIS("l.add r%d, r%d, r%d\n", rd, ra, rb); - { - TCGLabel *lab = gen_new_label(); - TCGv_i64 ta = tcg_temp_new_i64(); - TCGv_i64 tb = tcg_temp_new_i64(); - TCGv_i64 td = tcg_temp_local_new_i64(); - TCGv_i32 res = tcg_temp_local_new_i32(); - TCGv_i32 sr_ove = tcg_temp_local_new_i32(); - tcg_gen_extu_i32_i64(ta, cpu_R[ra]); - tcg_gen_extu_i32_i64(tb, cpu_R[rb]); - tcg_gen_add_i64(td, ta, tb); - tcg_gen_extrl_i64_i32(res, td); - tcg_gen_shri_i64(td, td, 31); - tcg_gen_andi_i64(td, td, 0x3); - /* Jump to lab when no overflow. */ - tcg_gen_brcondi_i64(TCG_COND_EQ, td, 0x0, lab); - tcg_gen_brcondi_i64(TCG_COND_EQ, td, 0x3, lab); - tcg_gen_ori_i32(cpu_sr, cpu_sr, (SR_OV | SR_CY)); - tcg_gen_andi_i32(sr_ove, cpu_sr, SR_OVE); - tcg_gen_brcondi_i32(TCG_COND_NE, sr_ove, SR_OVE, lab); - gen_exception(dc, EXCP_RANGE); - gen_set_label(lab); - tcg_gen_mov_i32(cpu_R[rd], res); - tcg_temp_free_i64(ta); - tcg_temp_free_i64(tb); - tcg_temp_free_i64(td); - tcg_temp_free_i32(res); - tcg_temp_free_i32(sr_ove); - } + gen_add(dc, cpu_R[rd], cpu_R[ra], cpu_R[rb]); break; default: gen_illegal_exception(dc); @@ -343,42 +476,7 @@ static void dec_calc(DisasContext *dc, uint32_t insn) switch (op1) { case 0x00: LOG_DIS("l.addc r%d, r%d, r%d\n", rd, ra, rb); - { - TCGLabel *lab = gen_new_label(); - TCGv_i64 ta = tcg_temp_new_i64(); - TCGv_i64 tb = tcg_temp_new_i64(); - TCGv_i64 tcy = tcg_temp_local_new_i64(); - TCGv_i64 td = tcg_temp_local_new_i64(); - TCGv_i32 res = tcg_temp_local_new_i32(); - TCGv_i32 sr_cy = tcg_temp_local_new_i32(); - TCGv_i32 sr_ove = tcg_temp_local_new_i32(); - tcg_gen_extu_i32_i64(ta, cpu_R[ra]); - tcg_gen_extu_i32_i64(tb, cpu_R[rb]); - tcg_gen_andi_i32(sr_cy, cpu_sr, SR_CY); - tcg_gen_extu_i32_i64(tcy, sr_cy); - tcg_gen_shri_i64(tcy, tcy, 10); - tcg_gen_add_i64(td, ta, tb); - tcg_gen_add_i64(td, td, tcy); - tcg_gen_extrl_i64_i32(res, td); - tcg_gen_shri_i64(td, td, 32); - tcg_gen_andi_i64(td, td, 0x3); - /* Jump to lab when no overflow. */ - tcg_gen_brcondi_i64(TCG_COND_EQ, td, 0x0, lab); - tcg_gen_brcondi_i64(TCG_COND_EQ, td, 0x3, lab); - tcg_gen_ori_i32(cpu_sr, cpu_sr, (SR_OV | SR_CY)); - tcg_gen_andi_i32(sr_ove, cpu_sr, SR_OVE); - tcg_gen_brcondi_i32(TCG_COND_NE, sr_ove, SR_OVE, lab); - gen_exception(dc, EXCP_RANGE); - gen_set_label(lab); - tcg_gen_mov_i32(cpu_R[rd], res); - tcg_temp_free_i64(ta); - tcg_temp_free_i64(tb); - tcg_temp_free_i64(tcy); - tcg_temp_free_i64(td); - tcg_temp_free_i32(res); - tcg_temp_free_i32(sr_cy); - tcg_temp_free_i32(sr_ove); - } + gen_addc(dc, cpu_R[rd], cpu_R[ra], cpu_R[rb]); break; default: gen_illegal_exception(dc); @@ -390,35 +488,7 @@ static void dec_calc(DisasContext *dc, uint32_t insn) switch (op1) { case 0x00: LOG_DIS("l.sub r%d, r%d, r%d\n", rd, ra, rb); - { - TCGLabel *lab = gen_new_label(); - TCGv_i64 ta = tcg_temp_new_i64(); - TCGv_i64 tb = tcg_temp_new_i64(); - TCGv_i64 td = tcg_temp_local_new_i64(); - TCGv_i32 res = tcg_temp_local_new_i32(); - TCGv_i32 sr_ove = tcg_temp_local_new_i32(); - - tcg_gen_extu_i32_i64(ta, cpu_R[ra]); - tcg_gen_extu_i32_i64(tb, cpu_R[rb]); - tcg_gen_sub_i64(td, ta, tb); - tcg_gen_extrl_i64_i32(res, td); - tcg_gen_shri_i64(td, td, 31); - tcg_gen_andi_i64(td, td, 0x3); - /* Jump to lab when no overflow. */ - tcg_gen_brcondi_i64(TCG_COND_EQ, td, 0x0, lab); - tcg_gen_brcondi_i64(TCG_COND_EQ, td, 0x3, lab); - tcg_gen_ori_i32(cpu_sr, cpu_sr, (SR_OV | SR_CY)); - tcg_gen_andi_i32(sr_ove, cpu_sr, SR_OVE); - tcg_gen_brcondi_i32(TCG_COND_NE, sr_ove, SR_OVE, lab); - gen_exception(dc, EXCP_RANGE); - gen_set_label(lab); - tcg_gen_mov_i32(cpu_R[rd], res); - tcg_temp_free_i64(ta); - tcg_temp_free_i64(tb); - tcg_temp_free_i64(td); - tcg_temp_free_i32(res); - tcg_temp_free_i32(sr_ove); - } + gen_sub(dc, cpu_R[rd], cpu_R[ra], cpu_R[rb]); break; default: gen_illegal_exception(dc); @@ -466,11 +536,7 @@ static void dec_calc(DisasContext *dc, uint32_t insn) switch (op1) { case 0x03: /* l.mul */ LOG_DIS("l.mul r%d, r%d, r%d\n", rd, ra, rb); - if (ra != 0 && rb != 0) { - gen_helper_mul32(cpu_R[rd], cpu_env, cpu_R[ra], cpu_R[rb]); - } else { - tcg_gen_movi_tl(cpu_R[rd], 0x0); - } + gen_mul(dc, cpu_R[rd], cpu_R[ra], cpu_R[rb]); break; default: gen_illegal_exception(dc); @@ -482,36 +548,7 @@ static void dec_calc(DisasContext *dc, uint32_t insn) switch (op1) { case 0x03: /* l.div */ LOG_DIS("l.div r%d, r%d, r%d\n", rd, ra, rb); - { - TCGLabel *lab0 = gen_new_label(); - TCGLabel *lab1 = gen_new_label(); - TCGLabel *lab2 = gen_new_label(); - TCGLabel *lab3 = gen_new_label(); - TCGv_i32 sr_ove = tcg_temp_local_new_i32(); - if (rb == 0) { - tcg_gen_ori_tl(cpu_sr, cpu_sr, (SR_OV | SR_CY)); - tcg_gen_andi_tl(sr_ove, cpu_sr, SR_OVE); - tcg_gen_brcondi_tl(TCG_COND_NE, sr_ove, SR_OVE, lab0); - gen_exception(dc, EXCP_RANGE); - gen_set_label(lab0); - } else { - tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_R[rb], - 0x00000000, lab1); - tcg_gen_brcondi_tl(TCG_COND_NE, cpu_R[ra], - 0x80000000, lab2); - tcg_gen_brcondi_tl(TCG_COND_NE, cpu_R[rb], - 0xffffffff, lab2); - gen_set_label(lab1); - tcg_gen_ori_tl(cpu_sr, cpu_sr, (SR_OV | SR_CY)); - tcg_gen_andi_tl(sr_ove, cpu_sr, SR_OVE); - tcg_gen_brcondi_tl(TCG_COND_NE, sr_ove, SR_OVE, lab3); - gen_exception(dc, EXCP_RANGE); - gen_set_label(lab2); - tcg_gen_div_tl(cpu_R[rd], cpu_R[ra], cpu_R[rb]); - gen_set_label(lab3); - } - tcg_temp_free_i32(sr_ove); - } + gen_div(dc, cpu_R[rd], cpu_R[ra], cpu_R[rb]); break; default: @@ -524,30 +561,7 @@ static void dec_calc(DisasContext *dc, uint32_t insn) switch (op1) { case 0x03: /* l.divu */ LOG_DIS("l.divu r%d, r%d, r%d\n", rd, ra, rb); - { - TCGLabel *lab0 = gen_new_label(); - TCGLabel *lab1 = gen_new_label(); - TCGLabel *lab2 = gen_new_label(); - TCGv_i32 sr_ove = tcg_temp_local_new_i32(); - if (rb == 0) { - tcg_gen_ori_tl(cpu_sr, cpu_sr, (SR_OV | SR_CY)); - tcg_gen_andi_tl(sr_ove, cpu_sr, SR_OVE); - tcg_gen_brcondi_tl(TCG_COND_NE, sr_ove, SR_OVE, lab0); - gen_exception(dc, EXCP_RANGE); - gen_set_label(lab0); - } else { - tcg_gen_brcondi_tl(TCG_COND_NE, cpu_R[rb], - 0x00000000, lab1); - tcg_gen_ori_tl(cpu_sr, cpu_sr, (SR_OV | SR_CY)); - tcg_gen_andi_tl(sr_ove, cpu_sr, SR_OVE); - tcg_gen_brcondi_tl(TCG_COND_NE, sr_ove, SR_OVE, lab2); - gen_exception(dc, EXCP_RANGE); - gen_set_label(lab1); - tcg_gen_divu_tl(cpu_R[rd], cpu_R[ra], cpu_R[rb]); - gen_set_label(lab2); - } - tcg_temp_free_i32(sr_ove); - } + gen_divu(dc, cpu_R[rd], cpu_R[ra], cpu_R[rb]); break; default: @@ -560,34 +574,7 @@ static void dec_calc(DisasContext *dc, uint32_t insn) switch (op1) { case 0x03: /* l.mulu */ LOG_DIS("l.mulu r%d, r%d, r%d\n", rd, ra, rb); - if (rb != 0 && ra != 0) { - TCGv_i64 result = tcg_temp_local_new_i64(); - TCGv_i64 tra = tcg_temp_local_new_i64(); - TCGv_i64 trb = tcg_temp_local_new_i64(); - TCGv_i64 high = tcg_temp_new_i64(); - TCGv_i32 sr_ove = tcg_temp_local_new_i32(); - TCGLabel *lab = gen_new_label(); - /* Calculate each result. */ - tcg_gen_extu_i32_i64(tra, cpu_R[ra]); - tcg_gen_extu_i32_i64(trb, cpu_R[rb]); - tcg_gen_mul_i64(result, tra, trb); - tcg_temp_free_i64(tra); - tcg_temp_free_i64(trb); - tcg_gen_shri_i64(high, result, TARGET_LONG_BITS); - /* Overflow or not. */ - tcg_gen_brcondi_i64(TCG_COND_EQ, high, 0x00000000, lab); - tcg_gen_ori_tl(cpu_sr, cpu_sr, (SR_OV | SR_CY)); - tcg_gen_andi_tl(sr_ove, cpu_sr, SR_OVE); - tcg_gen_brcondi_tl(TCG_COND_NE, sr_ove, SR_OVE, lab); - gen_exception(dc, EXCP_RANGE); - gen_set_label(lab); - tcg_temp_free_i64(high); - tcg_gen_trunc_i64_tl(cpu_R[rd], result); - tcg_temp_free_i64(result); - tcg_temp_free_i32(sr_ove); - } else { - tcg_gen_movi_tl(cpu_R[rd], 0); - } + gen_mulu(dc, cpu_R[rd], cpu_R[ra], cpu_R[rb]); break; default: @@ -744,6 +731,7 @@ static void dec_misc(DisasContext *dc, uint32_t insn) uint32_t L6, K5, K16, K5_11; int32_t I16, I5_11, N26; TCGMemOp mop; + TCGv t0; op0 = extract32(insn, 26, 6); op1 = extract32(insn, 24, 2); @@ -925,72 +913,16 @@ static void dec_misc(DisasContext *dc, uint32_t insn) case 0x27: /* l.addi */ LOG_DIS("l.addi r%d, r%d, %d\n", rd, ra, I16); - { - if (I16 == 0) { - tcg_gen_mov_tl(cpu_R[rd], cpu_R[ra]); - } else { - TCGLabel *lab = gen_new_label(); - TCGv_i64 ta = tcg_temp_new_i64(); - TCGv_i64 td = tcg_temp_local_new_i64(); - TCGv_i32 res = tcg_temp_local_new_i32(); - TCGv_i32 sr_ove = tcg_temp_local_new_i32(); - tcg_gen_extu_i32_i64(ta, cpu_R[ra]); - tcg_gen_addi_i64(td, ta, I16); - tcg_gen_extrl_i64_i32(res, td); - tcg_gen_shri_i64(td, td, 32); - tcg_gen_andi_i64(td, td, 0x3); - /* Jump to lab when no overflow. */ - tcg_gen_brcondi_i64(TCG_COND_EQ, td, 0x0, lab); - tcg_gen_brcondi_i64(TCG_COND_EQ, td, 0x3, lab); - tcg_gen_ori_i32(cpu_sr, cpu_sr, (SR_OV | SR_CY)); - tcg_gen_andi_i32(sr_ove, cpu_sr, SR_OVE); - tcg_gen_brcondi_i32(TCG_COND_NE, sr_ove, SR_OVE, lab); - gen_exception(dc, EXCP_RANGE); - gen_set_label(lab); - tcg_gen_mov_i32(cpu_R[rd], res); - tcg_temp_free_i64(ta); - tcg_temp_free_i64(td); - tcg_temp_free_i32(res); - tcg_temp_free_i32(sr_ove); - } - } + t0 = tcg_const_tl(I16); + gen_add(dc, cpu_R[rd], cpu_R[ra], t0); + tcg_temp_free(t0); break; case 0x28: /* l.addic */ LOG_DIS("l.addic r%d, r%d, %d\n", rd, ra, I16); - { - TCGLabel *lab = gen_new_label(); - TCGv_i64 ta = tcg_temp_new_i64(); - TCGv_i64 td = tcg_temp_local_new_i64(); - TCGv_i64 tcy = tcg_temp_local_new_i64(); - TCGv_i32 res = tcg_temp_local_new_i32(); - TCGv_i32 sr_cy = tcg_temp_local_new_i32(); - TCGv_i32 sr_ove = tcg_temp_local_new_i32(); - tcg_gen_extu_i32_i64(ta, cpu_R[ra]); - tcg_gen_andi_i32(sr_cy, cpu_sr, SR_CY); - tcg_gen_shri_i32(sr_cy, sr_cy, 10); - tcg_gen_extu_i32_i64(tcy, sr_cy); - tcg_gen_addi_i64(td, ta, I16); - tcg_gen_add_i64(td, td, tcy); - tcg_gen_extrl_i64_i32(res, td); - tcg_gen_shri_i64(td, td, 32); - tcg_gen_andi_i64(td, td, 0x3); - /* Jump to lab when no overflow. */ - tcg_gen_brcondi_i64(TCG_COND_EQ, td, 0x0, lab); - tcg_gen_brcondi_i64(TCG_COND_EQ, td, 0x3, lab); - tcg_gen_ori_i32(cpu_sr, cpu_sr, (SR_OV | SR_CY)); - tcg_gen_andi_i32(sr_ove, cpu_sr, SR_OVE); - tcg_gen_brcondi_i32(TCG_COND_NE, sr_ove, SR_OVE, lab); - gen_exception(dc, EXCP_RANGE); - gen_set_label(lab); - tcg_gen_mov_i32(cpu_R[rd], res); - tcg_temp_free_i64(ta); - tcg_temp_free_i64(td); - tcg_temp_free_i64(tcy); - tcg_temp_free_i32(res); - tcg_temp_free_i32(sr_cy); - tcg_temp_free_i32(sr_ove); - } + t0 = tcg_const_tl(I16); + gen_addc(dc, cpu_R[rd], cpu_R[ra], t0); + tcg_temp_free(t0); break; case 0x29: /* l.andi */ @@ -1010,13 +942,9 @@ static void dec_misc(DisasContext *dc, uint32_t insn) case 0x2c: /* l.muli */ LOG_DIS("l.muli r%d, r%d, %d\n", rd, ra, I16); - if (ra != 0 && I16 != 0) { - TCGv_i32 im = tcg_const_i32(I16); - gen_helper_mul32(cpu_R[rd], cpu_env, cpu_R[ra], im); - tcg_temp_free_i32(im); - } else { - tcg_gen_movi_tl(cpu_R[rd], 0x0); - } + t0 = tcg_const_tl(I16); + gen_mul(dc, cpu_R[rd], cpu_R[ra], t0); + tcg_temp_free(t0); break; case 0x2d: /* l.mfspr */ -- cgit v1.1 From 0c53d7342b4e8412f3b81eed67f053304813dc5d Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Wed, 18 Feb 2015 12:34:56 -0800 Subject: target/openrisc: Put SR[OVE] in TB flags Removes a call at execution time for overflow exceptions. Signed-off-by: Richard Henderson --- target/openrisc/cpu.h | 4 ++-- target/openrisc/exception_helper.c | 2 +- target/openrisc/translate.c | 24 +++++++++++++++--------- 3 files changed, 18 insertions(+), 12 deletions(-) (limited to 'target') diff --git a/target/openrisc/cpu.h b/target/openrisc/cpu.h index 06d0e89..ef90e49 100644 --- a/target/openrisc/cpu.h +++ b/target/openrisc/cpu.h @@ -400,8 +400,8 @@ static inline void cpu_get_tb_cpu_state(CPUOpenRISCState *env, { *pc = env->pc; *cs_base = 0; - /* D_FLAG -- branch instruction exception */ - *flags = (env->flags & D_FLAG); + /* D_FLAG -- branch instruction exception, OVE overflow trap enable. */ + *flags = (env->flags & D_FLAG) | (env->sr & SR_OVE); } static inline int cpu_mmu_index(CPUOpenRISCState *env, bool ifetch) diff --git a/target/openrisc/exception_helper.c b/target/openrisc/exception_helper.c index 7e54c97..5147da6 100644 --- a/target/openrisc/exception_helper.c +++ b/target/openrisc/exception_helper.c @@ -32,7 +32,7 @@ void HELPER(exception)(CPUOpenRISCState *env, uint32_t excp) void HELPER(ove)(CPUOpenRISCState *env, target_ulong test) { - if (unlikely(test) && (env->sr & SR_OVE)) { + if (unlikely(test)) { OpenRISCCPU *cpu = openrisc_env_get_cpu(env); CPUState *cs = CPU(cpu); diff --git a/target/openrisc/translate.c b/target/openrisc/translate.c index 7c6cd1c..b8116ba 100644 --- a/target/openrisc/translate.c +++ b/target/openrisc/translate.c @@ -132,8 +132,8 @@ static inline void wb_SR_F(void) static inline void gen_sync_flags(DisasContext *dc) { /* Sync the tb dependent flag between translate and runtime. */ - if (dc->tb_flags != dc->synced_flags) { - tcg_gen_movi_tl(env_flags, dc->tb_flags); + if ((dc->tb_flags ^ dc->synced_flags) & D_FLAG) { + tcg_gen_movi_tl(env_flags, dc->tb_flags & D_FLAG); dc->synced_flags = dc->tb_flags; } } @@ -249,20 +249,26 @@ static void gen_jump(DisasContext *dc, int32_t n26, uint32_t reg, uint32_t op0) static void gen_ove_cy(DisasContext *dc, TCGv cy) { - gen_helper_ove(cpu_env, cy); + if (dc->tb_flags & SR_OVE) { + gen_helper_ove(cpu_env, cy); + } } static void gen_ove_ov(DisasContext *dc, TCGv ov) { - gen_helper_ove(cpu_env, ov); + if (dc->tb_flags & SR_OVE) { + gen_helper_ove(cpu_env, ov); + } } static void gen_ove_cyov(DisasContext *dc, TCGv cy, TCGv ov) { - TCGv t0 = tcg_temp_new(); - tcg_gen_or_tl(t0, cy, ov); - gen_helper_ove(cpu_env, t0); - tcg_temp_free(t0); + if (dc->tb_flags & SR_OVE) { + TCGv t0 = tcg_temp_new(); + tcg_gen_or_tl(t0, cy, ov); + gen_helper_ove(cpu_env, t0); + tcg_temp_free(t0); + } } static void gen_add(DisasContext *dc, TCGv dest, TCGv srca, TCGv srcb) @@ -1606,7 +1612,7 @@ void gen_intermediate_code(CPUOpenRISCState *env, struct TranslationBlock *tb) dc->flags = cpu->env.cpucfgr; dc->mem_idx = cpu_mmu_index(&cpu->env, false); dc->synced_flags = dc->tb_flags = tb->flags; - dc->delayed_branch = !!(dc->tb_flags & D_FLAG); + dc->delayed_branch = (dc->tb_flags & D_FLAG) != 0; dc->singlestep_enabled = cs->singlestep_enabled; next_page_start = (pc_start & TARGET_PAGE_MASK) + TARGET_PAGE_SIZE; -- cgit v1.1 From cf2ae4428f320f3d8027a50c1cd45f4b5a6c93bb Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Wed, 18 Feb 2015 17:41:52 -0800 Subject: target/openrisc: Invert the decoding in dec_calc Decoding the opcodes in the right order reduces by 100+ lines. Also, it happens to put the opcodes in the same order as Chapter 17. Reviewed-by: Bastian Koppelmann Signed-off-by: Richard Henderson --- target/openrisc/translate.c | 302 ++++++++++++++------------------------------ 1 file changed, 95 insertions(+), 207 deletions(-) (limited to 'target') diff --git a/target/openrisc/translate.c b/target/openrisc/translate.c index b8116ba..1f3f22c 100644 --- a/target/openrisc/translate.c +++ b/target/openrisc/translate.c @@ -465,133 +465,95 @@ static void dec_calc(DisasContext *dc, uint32_t insn) rb = extract32(insn, 11, 5); rd = extract32(insn, 21, 5); - switch (op0) { - case 0x0000: - switch (op1) { - case 0x00: /* l.add */ + switch (op1) { + case 0: + switch (op0) { + case 0x0: /* l.add */ LOG_DIS("l.add r%d, r%d, r%d\n", rd, ra, rb); gen_add(dc, cpu_R[rd], cpu_R[ra], cpu_R[rb]); - break; - default: - gen_illegal_exception(dc); - break; - } - break; + return; - case 0x0001: /* l.addc */ - switch (op1) { - case 0x00: + case 0x1: /* l.addc */ LOG_DIS("l.addc r%d, r%d, r%d\n", rd, ra, rb); gen_addc(dc, cpu_R[rd], cpu_R[ra], cpu_R[rb]); - break; - default: - gen_illegal_exception(dc); - break; - } - break; + return; - case 0x0002: /* l.sub */ - switch (op1) { - case 0x00: + case 0x2: /* l.sub */ LOG_DIS("l.sub r%d, r%d, r%d\n", rd, ra, rb); gen_sub(dc, cpu_R[rd], cpu_R[ra], cpu_R[rb]); - break; - default: - gen_illegal_exception(dc); - break; - } - break; + return; - case 0x0003: /* l.and */ - switch (op1) { - case 0x00: + case 0x3: /* l.and */ LOG_DIS("l.and r%d, r%d, r%d\n", rd, ra, rb); tcg_gen_and_tl(cpu_R[rd], cpu_R[ra], cpu_R[rb]); - break; - default: - gen_illegal_exception(dc); - break; - } - break; + return; - case 0x0004: /* l.or */ - switch (op1) { - case 0x00: + case 0x4: /* l.or */ LOG_DIS("l.or r%d, r%d, r%d\n", rd, ra, rb); tcg_gen_or_tl(cpu_R[rd], cpu_R[ra], cpu_R[rb]); - break; - default: - gen_illegal_exception(dc); - break; - } - break; + return; - case 0x0005: - switch (op1) { - case 0x00: /* l.xor */ + case 0x5: /* l.xor */ LOG_DIS("l.xor r%d, r%d, r%d\n", rd, ra, rb); tcg_gen_xor_tl(cpu_R[rd], cpu_R[ra], cpu_R[rb]); - break; - default: - gen_illegal_exception(dc); - break; - } - break; - - case 0x0006: - switch (op1) { - case 0x03: /* l.mul */ - LOG_DIS("l.mul r%d, r%d, r%d\n", rd, ra, rb); - gen_mul(dc, cpu_R[rd], cpu_R[ra], cpu_R[rb]); - break; - default: - gen_illegal_exception(dc); - break; - } - break; - - case 0x0009: - switch (op1) { - case 0x03: /* l.div */ - LOG_DIS("l.div r%d, r%d, r%d\n", rd, ra, rb); - gen_div(dc, cpu_R[rd], cpu_R[ra], cpu_R[rb]); - break; - - default: - gen_illegal_exception(dc); - break; - } - break; - - case 0x000a: - switch (op1) { - case 0x03: /* l.divu */ - LOG_DIS("l.divu r%d, r%d, r%d\n", rd, ra, rb); - gen_divu(dc, cpu_R[rd], cpu_R[ra], cpu_R[rb]); - break; + return; - default: - gen_illegal_exception(dc); + case 0x8: + switch (op2) { + case 0: /* l.sll */ + LOG_DIS("l.sll r%d, r%d, r%d\n", rd, ra, rb); + tcg_gen_shl_tl(cpu_R[rd], cpu_R[ra], cpu_R[rb]); + return; + case 1: /* l.srl */ + LOG_DIS("l.srl r%d, r%d, r%d\n", rd, ra, rb); + tcg_gen_shr_tl(cpu_R[rd], cpu_R[ra], cpu_R[rb]); + return; + case 2: /* l.sra */ + LOG_DIS("l.sra r%d, r%d, r%d\n", rd, ra, rb); + tcg_gen_sar_tl(cpu_R[rd], cpu_R[ra], cpu_R[rb]); + return; + case 3: /* l.ror */ + LOG_DIS("l.ror r%d, r%d, r%d\n", rd, ra, rb); + tcg_gen_rotr_tl(cpu_R[rd], cpu_R[ra], cpu_R[rb]); + return; + } break; - } - break; - case 0x000b: - switch (op1) { - case 0x03: /* l.mulu */ - LOG_DIS("l.mulu r%d, r%d, r%d\n", rd, ra, rb); - gen_mulu(dc, cpu_R[rd], cpu_R[ra], cpu_R[rb]); + case 0xc: + switch (op2) { + case 0: /* l.exths */ + LOG_DIS("l.exths r%d, r%d\n", rd, ra); + tcg_gen_ext16s_tl(cpu_R[rd], cpu_R[ra]); + return; + case 1: /* l.extbs */ + LOG_DIS("l.extbs r%d, r%d\n", rd, ra); + tcg_gen_ext8s_tl(cpu_R[rd], cpu_R[ra]); + return; + case 2: /* l.exthz */ + LOG_DIS("l.exthz r%d, r%d\n", rd, ra); + tcg_gen_ext16u_tl(cpu_R[rd], cpu_R[ra]); + return; + case 3: /* l.extbz */ + LOG_DIS("l.extbz r%d, r%d\n", rd, ra); + tcg_gen_ext8u_tl(cpu_R[rd], cpu_R[ra]); + return; + } break; - default: - gen_illegal_exception(dc); + case 0xd: + switch (op2) { + case 0: /* l.extws */ + LOG_DIS("l.extws r%d, r%d\n", rd, ra); + tcg_gen_ext32s_tl(cpu_R[rd], cpu_R[ra]); + return; + case 1: /* l.extwz */ + LOG_DIS("l.extwz r%d, r%d\n", rd, ra); + tcg_gen_ext32u_tl(cpu_R[rd], cpu_R[ra]); + return; + } break; - } - break; - case 0x000e: - switch (op1) { - case 0x00: /* l.cmov */ + case 0xe: /* l.cmov */ LOG_DIS("l.cmov r%d, r%d, r%d\n", rd, ra, rb); { TCGLabel *lab = gen_new_label(); @@ -606,128 +568,54 @@ static void dec_calc(DisasContext *dc, uint32_t insn) tcg_temp_free(sr_f); tcg_temp_free(res); } - break; - - default: - gen_illegal_exception(dc); - break; - } - break; + return; - case 0x000f: - switch (op1) { - case 0x00: /* l.ff1 */ + case 0xf: /* l.ff1 */ LOG_DIS("l.ff1 r%d, r%d, r%d\n", rd, ra, rb); tcg_gen_ctzi_tl(cpu_R[rd], cpu_R[ra], -1); tcg_gen_addi_tl(cpu_R[rd], cpu_R[rd], 1); - break; - case 0x01: /* l.fl1 */ + return; + } + break; + + case 1: + switch (op0) { + case 0xf: /* l.fl1 */ LOG_DIS("l.fl1 r%d, r%d, r%d\n", rd, ra, rb); tcg_gen_clzi_tl(cpu_R[rd], cpu_R[ra], TARGET_LONG_BITS); tcg_gen_subfi_tl(cpu_R[rd], TARGET_LONG_BITS, cpu_R[rd]); - break; - - default: - gen_illegal_exception(dc); - break; + return; } break; - case 0x0008: - switch (op1) { - case 0x00: - switch (op2) { - case 0x00: /* l.sll */ - LOG_DIS("l.sll r%d, r%d, r%d\n", rd, ra, rb); - tcg_gen_shl_tl(cpu_R[rd], cpu_R[ra], cpu_R[rb]); - break; - case 0x01: /* l.srl */ - LOG_DIS("l.srl r%d, r%d, r%d\n", rd, ra, rb); - tcg_gen_shr_tl(cpu_R[rd], cpu_R[ra], cpu_R[rb]); - break; - case 0x02: /* l.sra */ - LOG_DIS("l.sra r%d, r%d, r%d\n", rd, ra, rb); - tcg_gen_sar_tl(cpu_R[rd], cpu_R[ra], cpu_R[rb]); - break; - case 0x03: /* l.ror */ - LOG_DIS("l.ror r%d, r%d, r%d\n", rd, ra, rb); - tcg_gen_rotr_tl(cpu_R[rd], cpu_R[ra], cpu_R[rb]); - break; - - default: - gen_illegal_exception(dc); - break; - } - break; - - default: - gen_illegal_exception(dc); - break; - } + case 2: break; - case 0x000c: - switch (op1) { - case 0x00: - switch (op2) { - case 0x00: /* l.exths */ - LOG_DIS("l.exths r%d, r%d\n", rd, ra); - tcg_gen_ext16s_tl(cpu_R[rd], cpu_R[ra]); - break; - case 0x01: /* l.extbs */ - LOG_DIS("l.extbs r%d, r%d\n", rd, ra); - tcg_gen_ext8s_tl(cpu_R[rd], cpu_R[ra]); - break; - case 0x02: /* l.exthz */ - LOG_DIS("l.exthz r%d, r%d\n", rd, ra); - tcg_gen_ext16u_tl(cpu_R[rd], cpu_R[ra]); - break; - case 0x03: /* l.extbz */ - LOG_DIS("l.extbz r%d, r%d\n", rd, ra); - tcg_gen_ext8u_tl(cpu_R[rd], cpu_R[ra]); - break; - - default: - gen_illegal_exception(dc); - break; - } - break; - - default: - gen_illegal_exception(dc); - break; - } - break; + case 3: + switch (op0) { + case 0x6: /* l.mul */ + LOG_DIS("l.mul r%d, r%d, r%d\n", rd, ra, rb); + gen_mul(dc, cpu_R[rd], cpu_R[ra], cpu_R[rb]); + return; - case 0x000d: - switch (op1) { - case 0x00: - switch (op2) { - case 0x00: /* l.extws */ - LOG_DIS("l.extws r%d, r%d\n", rd, ra); - tcg_gen_ext32s_tl(cpu_R[rd], cpu_R[ra]); - break; - case 0x01: /* l.extwz */ - LOG_DIS("l.extwz r%d, r%d\n", rd, ra); - tcg_gen_ext32u_tl(cpu_R[rd], cpu_R[ra]); - break; + case 0x9: /* l.div */ + LOG_DIS("l.div r%d, r%d, r%d\n", rd, ra, rb); + gen_div(dc, cpu_R[rd], cpu_R[ra], cpu_R[rb]); + return; - default: - gen_illegal_exception(dc); - break; - } - break; + case 0xa: /* l.divu */ + LOG_DIS("l.divu r%d, r%d, r%d\n", rd, ra, rb); + gen_divu(dc, cpu_R[rd], cpu_R[ra], cpu_R[rb]); + return; - default: - gen_illegal_exception(dc); - break; + case 0xb: /* l.mulu */ + LOG_DIS("l.mulu r%d, r%d, r%d\n", rd, ra, rb); + gen_mulu(dc, cpu_R[rd], cpu_R[ra], cpu_R[rb]); + return; } break; - - default: - gen_illegal_exception(dc); - break; } + gen_illegal_exception(dc); } static void dec_misc(DisasContext *dc, uint32_t insn) -- cgit v1.1 From 84775c43f390d4f5dd9adf8732e7e0b6deed8f61 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Wed, 18 Feb 2015 11:45:54 -0800 Subject: target/openrisc: Keep SR_F in a separate variable This avoids having to keep merging and extracting the flag from SR. Reviewed-by: Bastian Koppelmann Signed-off-by: Richard Henderson --- target/openrisc/cpu.h | 15 +++++- target/openrisc/gdbstub.c | 4 +- target/openrisc/interrupt.c | 2 +- target/openrisc/interrupt_helper.c | 2 +- target/openrisc/machine.c | 38 +++++++++++++- target/openrisc/sys_helper.c | 5 +- target/openrisc/translate.c | 104 ++++++++++++++----------------------- 7 files changed, 96 insertions(+), 74 deletions(-) (limited to 'target') diff --git a/target/openrisc/cpu.h b/target/openrisc/cpu.h index ef90e49..bb5d363 100644 --- a/target/openrisc/cpu.h +++ b/target/openrisc/cpu.h @@ -286,7 +286,8 @@ typedef struct CPUOpenRISCState { target_ulong epcr; /* Exception PC register */ target_ulong eear; /* Exception EA register */ - uint32_t sr; /* Supervisor register */ + target_ulong sr_f; /* the SR_F bit, values 0, 1. */ + uint32_t sr; /* Supervisor register, without SR_F */ uint32_t vr; /* Version register */ uint32_t upr; /* Unit presence register */ uint32_t cpucfgr; /* CPU configure register */ @@ -301,7 +302,6 @@ typedef struct CPUOpenRISCState { uint32_t flags; /* cpu_flags, we only use it for exception in solt so far. */ - uint32_t btaken; /* the SR_F bit */ /* Fields up to this point are cleared by a CPU reset */ struct {} end_reset_fields; @@ -412,6 +412,17 @@ static inline int cpu_mmu_index(CPUOpenRISCState *env, bool ifetch) return (env->sr & SR_SM) == 0 ? MMU_USER_IDX : MMU_SUPERVISOR_IDX; } +static inline uint32_t cpu_get_sr(const CPUOpenRISCState *env) +{ + return env->sr + env->sr_f * SR_F; +} + +static inline void cpu_set_sr(CPUOpenRISCState *env, uint32_t val) +{ + env->sr_f = (val & SR_F) != 0; + env->sr = (val & ~SR_F) | SR_FO; +} + #define CPU_INTERRUPT_TIMER CPU_INTERRUPT_TGT_INT_0 #endif /* OPENRISC_CPU_H */ diff --git a/target/openrisc/gdbstub.c b/target/openrisc/gdbstub.c index cb16e76..31ea013 100644 --- a/target/openrisc/gdbstub.c +++ b/target/openrisc/gdbstub.c @@ -38,7 +38,7 @@ int openrisc_cpu_gdb_read_register(CPUState *cs, uint8_t *mem_buf, int n) return gdb_get_reg32(mem_buf, env->npc); case 34: /* SR */ - return gdb_get_reg32(mem_buf, env->sr); + return gdb_get_reg32(mem_buf, cpu_get_sr(env)); default: break; @@ -73,7 +73,7 @@ int openrisc_cpu_gdb_write_register(CPUState *cs, uint8_t *mem_buf, int n) break; case 34: /* SR */ - env->sr = tmp; + cpu_set_sr(env, tmp); break; default: diff --git a/target/openrisc/interrupt.c b/target/openrisc/interrupt.c index a981638..042506f 100644 --- a/target/openrisc/interrupt.c +++ b/target/openrisc/interrupt.c @@ -54,7 +54,7 @@ void openrisc_cpu_do_interrupt(CPUState *cs) we need flush TLB when we enter&exit EXCP. */ tlb_flush(cs); - env->esr = env->sr; + env->esr = cpu_get_sr(env); env->sr &= ~SR_DME; env->sr &= ~SR_IME; env->sr |= SR_SM; diff --git a/target/openrisc/interrupt_helper.c b/target/openrisc/interrupt_helper.c index a6d4df3..c7fa97a 100644 --- a/target/openrisc/interrupt_helper.c +++ b/target/openrisc/interrupt_helper.c @@ -33,7 +33,7 @@ void HELPER(rfe)(CPUOpenRISCState *env) #endif cpu->env.pc = cpu->env.epcr; cpu->env.npc = cpu->env.epcr; - cpu->env.sr = cpu->env.esr; + cpu_set_sr(&cpu->env, cpu->env.esr); cpu->env.lock_addr = -1; #ifndef CONFIG_USER_ONLY diff --git a/target/openrisc/machine.c b/target/openrisc/machine.c index d0b47ef..b723138 100644 --- a/target/openrisc/machine.c +++ b/target/openrisc/machine.c @@ -24,6 +24,27 @@ #include "hw/boards.h" #include "migration/cpu.h" +static int get_sr(QEMUFile *f, void *opaque, size_t size, VMStateField *field) +{ + CPUOpenRISCState *env = opaque; + cpu_set_sr(env, qemu_get_be32(f)); + return 0; +} + +static int put_sr(QEMUFile *f, void *opaque, size_t size, + VMStateField *field, QJSON *vmdesc) +{ + CPUOpenRISCState *env = opaque; + qemu_put_be32(f, cpu_get_sr(env)); + return 0; +} + +static const VMStateInfo vmstate_sr = { + .name = "sr", + .get = get_sr, + .put = put_sr, +}; + static const VMStateDescription vmstate_env = { .name = "env", .version_id = 2, @@ -38,7 +59,22 @@ static const VMStateDescription vmstate_env = { VMSTATE_UINTTL(lock_value, CPUOpenRISCState), VMSTATE_UINTTL(epcr, CPUOpenRISCState), VMSTATE_UINTTL(eear, CPUOpenRISCState), - VMSTATE_UINT32(sr, CPUOpenRISCState), + + /* Save the architecture value of the SR, not the internally + expanded version. Since this architecture value does not + exist in memory to be stored, this requires a but of hoop + jumping. We want OFFSET=0 so that we effectively pass ENV + to the helper functions, and we need to fill in the name by + hand since there's no field of that name. */ + { + .name = "sr", + .version_id = 0, + .size = sizeof(uint32_t), + .info = &vmstate_sr, + .flags = VMS_SINGLE, + .offset = 0 + }, + VMSTATE_UINT32(vr, CPUOpenRISCState), VMSTATE_UINT32(upr, CPUOpenRISCState), VMSTATE_UINT32(cpucfgr, CPUOpenRISCState), diff --git a/target/openrisc/sys_helper.c b/target/openrisc/sys_helper.c index daea902..4a59728 100644 --- a/target/openrisc/sys_helper.c +++ b/target/openrisc/sys_helper.c @@ -49,8 +49,7 @@ void HELPER(mtspr)(CPUOpenRISCState *env, (rb & (SR_IME | SR_DME | SR_SM))) { tlb_flush(cs); } - env->sr = rb; - env->sr |= SR_FO; /* FO is const equal to 1 */ + cpu_set_sr(env, rb); if (env->sr & SR_DME) { env->tlb->cpu_openrisc_map_address_data = &cpu_openrisc_get_phys_data; @@ -200,7 +199,7 @@ target_ulong HELPER(mfspr)(CPUOpenRISCState *env, return env->npc; case TO_SPR(0, 17): /* SR */ - return env->sr; + return cpu_get_sr(env); case TO_SPR(0, 18): /* PPC */ return env->ppc; diff --git a/target/openrisc/translate.c b/target/openrisc/translate.c index 1f3f22c..405a1a0 100644 --- a/target/openrisc/translate.c +++ b/target/openrisc/translate.c @@ -54,7 +54,7 @@ static TCGv cpu_pc; static TCGv jmp_pc; /* l.jr/l.jalr temp pc */ static TCGv cpu_npc; static TCGv cpu_ppc; -static TCGv_i32 env_btaken; /* bf/bnf , F flag taken */ +static TCGv cpu_sr_f; /* bf/bnf, F flag taken */ static TCGv cpu_lock_addr; static TCGv cpu_lock_value; static TCGv_i32 fpcsr; @@ -88,9 +88,8 @@ void openrisc_translate_init(void) offsetof(CPUOpenRISCState, ppc), "ppc"); jmp_pc = tcg_global_mem_new(cpu_env, offsetof(CPUOpenRISCState, jmp_pc), "jmp_pc"); - env_btaken = tcg_global_mem_new_i32(cpu_env, - offsetof(CPUOpenRISCState, btaken), - "btaken"); + cpu_sr_f = tcg_global_mem_new(cpu_env, + offsetof(CPUOpenRISCState, sr_f), "sr_f"); cpu_lock_addr = tcg_global_mem_new(cpu_env, offsetof(CPUOpenRISCState, lock_addr), "lock_addr"); @@ -119,16 +118,6 @@ void openrisc_translate_init(void) } } -/* Writeback SR_F translation space to execution space. */ -static inline void wb_SR_F(void) -{ - TCGLabel *label = gen_new_label(); - tcg_gen_andi_tl(cpu_sr, cpu_sr, ~SR_F); - tcg_gen_brcondi_tl(TCG_COND_EQ, env_btaken, 0, label); - tcg_gen_ori_tl(cpu_sr, cpu_sr, SR_F); - gen_set_label(label); -} - static inline void gen_sync_flags(DisasContext *dc) { /* Sync the tb dependent flag between translate and runtime. */ @@ -220,14 +209,11 @@ static void gen_jump(DisasContext *dc, int32_t n26, uint32_t reg, uint32_t op0) case 0x04: /* l.bf */ { TCGLabel *lab = gen_new_label(); - TCGv sr_f = tcg_temp_new(); tcg_gen_movi_tl(jmp_pc, dc->pc+8); - tcg_gen_andi_tl(sr_f, cpu_sr, SR_F); - tcg_gen_brcondi_i32(op0 == 0x03 ? TCG_COND_EQ : TCG_COND_NE, - sr_f, SR_F, lab); + tcg_gen_brcondi_tl(op0 == 0x03 ? TCG_COND_NE : TCG_COND_EQ, + cpu_sr_f, 0, lab); tcg_gen_movi_tl(jmp_pc, tmp_pc); gen_set_label(lab); - tcg_temp_free(sr_f); } break; case 0x11: /* l.jr */ @@ -441,17 +427,16 @@ static void gen_swa(DisasContext *dc, TCGv rb, TCGv ra, int32_t ofs) val = tcg_temp_new(); tcg_gen_atomic_cmpxchg_tl(val, cpu_lock_addr, cpu_lock_value, rb, dc->mem_idx, MO_TEUL); - tcg_gen_setcond_tl(TCG_COND_EQ, env_btaken, val, cpu_lock_value); + tcg_gen_setcond_tl(TCG_COND_EQ, cpu_sr_f, val, cpu_lock_value); tcg_temp_free(val); tcg_gen_br(lab_done); gen_set_label(lab_fail); - tcg_gen_movi_tl(env_btaken, 0); + tcg_gen_movi_tl(cpu_sr_f, 0); gen_set_label(lab_done); tcg_gen_movi_tl(cpu_lock_addr, -1); - wb_SR_F(); } static void dec_calc(DisasContext *dc, uint32_t insn) @@ -558,14 +543,11 @@ static void dec_calc(DisasContext *dc, uint32_t insn) { TCGLabel *lab = gen_new_label(); TCGv res = tcg_temp_local_new(); - TCGv sr_f = tcg_temp_new(); - tcg_gen_andi_tl(sr_f, cpu_sr, SR_F); tcg_gen_mov_tl(res, cpu_R[rb]); - tcg_gen_brcondi_tl(TCG_COND_NE, sr_f, SR_F, lab); + tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_sr_f, 0, lab); tcg_gen_mov_tl(res, cpu_R[ra]); gen_set_label(lab); tcg_gen_mov_tl(cpu_R[rd], res); - tcg_temp_free(sr_f); tcg_temp_free(res); } return; @@ -1046,7 +1028,6 @@ static void dec_comp(DisasContext *dc, uint32_t insn) ra = extract32(insn, 16, 5); rb = extract32(insn, 11, 5); - tcg_gen_movi_i32(env_btaken, 0x0); /* unsigned integers */ tcg_gen_ext32u_tl(cpu_R[ra], cpu_R[ra]); tcg_gen_ext32u_tl(cpu_R[rb], cpu_R[rb]); @@ -1054,59 +1035,58 @@ static void dec_comp(DisasContext *dc, uint32_t insn) switch (op0) { case 0x0: /* l.sfeq */ LOG_DIS("l.sfeq r%d, r%d\n", ra, rb); - tcg_gen_setcond_tl(TCG_COND_EQ, env_btaken, cpu_R[ra], cpu_R[rb]); + tcg_gen_setcond_tl(TCG_COND_EQ, cpu_sr_f, cpu_R[ra], cpu_R[rb]); break; case 0x1: /* l.sfne */ LOG_DIS("l.sfne r%d, r%d\n", ra, rb); - tcg_gen_setcond_tl(TCG_COND_NE, env_btaken, cpu_R[ra], cpu_R[rb]); + tcg_gen_setcond_tl(TCG_COND_NE, cpu_sr_f, cpu_R[ra], cpu_R[rb]); break; case 0x2: /* l.sfgtu */ LOG_DIS("l.sfgtu r%d, r%d\n", ra, rb); - tcg_gen_setcond_tl(TCG_COND_GTU, env_btaken, cpu_R[ra], cpu_R[rb]); + tcg_gen_setcond_tl(TCG_COND_GTU, cpu_sr_f, cpu_R[ra], cpu_R[rb]); break; case 0x3: /* l.sfgeu */ LOG_DIS("l.sfgeu r%d, r%d\n", ra, rb); - tcg_gen_setcond_tl(TCG_COND_GEU, env_btaken, cpu_R[ra], cpu_R[rb]); + tcg_gen_setcond_tl(TCG_COND_GEU, cpu_sr_f, cpu_R[ra], cpu_R[rb]); break; case 0x4: /* l.sfltu */ LOG_DIS("l.sfltu r%d, r%d\n", ra, rb); - tcg_gen_setcond_tl(TCG_COND_LTU, env_btaken, cpu_R[ra], cpu_R[rb]); + tcg_gen_setcond_tl(TCG_COND_LTU, cpu_sr_f, cpu_R[ra], cpu_R[rb]); break; case 0x5: /* l.sfleu */ LOG_DIS("l.sfleu r%d, r%d\n", ra, rb); - tcg_gen_setcond_tl(TCG_COND_LEU, env_btaken, cpu_R[ra], cpu_R[rb]); + tcg_gen_setcond_tl(TCG_COND_LEU, cpu_sr_f, cpu_R[ra], cpu_R[rb]); break; case 0xa: /* l.sfgts */ LOG_DIS("l.sfgts r%d, r%d\n", ra, rb); - tcg_gen_setcond_tl(TCG_COND_GT, env_btaken, cpu_R[ra], cpu_R[rb]); + tcg_gen_setcond_tl(TCG_COND_GT, cpu_sr_f, cpu_R[ra], cpu_R[rb]); break; case 0xb: /* l.sfges */ LOG_DIS("l.sfges r%d, r%d\n", ra, rb); - tcg_gen_setcond_tl(TCG_COND_GE, env_btaken, cpu_R[ra], cpu_R[rb]); + tcg_gen_setcond_tl(TCG_COND_GE, cpu_sr_f, cpu_R[ra], cpu_R[rb]); break; case 0xc: /* l.sflts */ LOG_DIS("l.sflts r%d, r%d\n", ra, rb); - tcg_gen_setcond_tl(TCG_COND_LT, env_btaken, cpu_R[ra], cpu_R[rb]); + tcg_gen_setcond_tl(TCG_COND_LT, cpu_sr_f, cpu_R[ra], cpu_R[rb]); break; case 0xd: /* l.sfles */ LOG_DIS("l.sfles r%d, r%d\n", ra, rb); - tcg_gen_setcond_tl(TCG_COND_LE, env_btaken, cpu_R[ra], cpu_R[rb]); + tcg_gen_setcond_tl(TCG_COND_LE, cpu_sr_f, cpu_R[ra], cpu_R[rb]); break; default: gen_illegal_exception(dc); break; } - wb_SR_F(); } static void dec_compi(DisasContext *dc, uint32_t insn) @@ -1118,64 +1098,61 @@ static void dec_compi(DisasContext *dc, uint32_t insn) ra = extract32(insn, 16, 5); I16 = sextract32(insn, 0, 16); - tcg_gen_movi_i32(env_btaken, 0x0); - switch (op0) { case 0x0: /* l.sfeqi */ LOG_DIS("l.sfeqi r%d, %d\n", ra, I16); - tcg_gen_setcondi_tl(TCG_COND_EQ, env_btaken, cpu_R[ra], I16); + tcg_gen_setcondi_tl(TCG_COND_EQ, cpu_sr_f, cpu_R[ra], I16); break; case 0x1: /* l.sfnei */ LOG_DIS("l.sfnei r%d, %d\n", ra, I16); - tcg_gen_setcondi_tl(TCG_COND_NE, env_btaken, cpu_R[ra], I16); + tcg_gen_setcondi_tl(TCG_COND_NE, cpu_sr_f, cpu_R[ra], I16); break; case 0x2: /* l.sfgtui */ LOG_DIS("l.sfgtui r%d, %d\n", ra, I16); - tcg_gen_setcondi_tl(TCG_COND_GTU, env_btaken, cpu_R[ra], I16); + tcg_gen_setcondi_tl(TCG_COND_GTU, cpu_sr_f, cpu_R[ra], I16); break; case 0x3: /* l.sfgeui */ LOG_DIS("l.sfgeui r%d, %d\n", ra, I16); - tcg_gen_setcondi_tl(TCG_COND_GEU, env_btaken, cpu_R[ra], I16); + tcg_gen_setcondi_tl(TCG_COND_GEU, cpu_sr_f, cpu_R[ra], I16); break; case 0x4: /* l.sfltui */ LOG_DIS("l.sfltui r%d, %d\n", ra, I16); - tcg_gen_setcondi_tl(TCG_COND_LTU, env_btaken, cpu_R[ra], I16); + tcg_gen_setcondi_tl(TCG_COND_LTU, cpu_sr_f, cpu_R[ra], I16); break; case 0x5: /* l.sfleui */ LOG_DIS("l.sfleui r%d, %d\n", ra, I16); - tcg_gen_setcondi_tl(TCG_COND_LEU, env_btaken, cpu_R[ra], I16); + tcg_gen_setcondi_tl(TCG_COND_LEU, cpu_sr_f, cpu_R[ra], I16); break; case 0xa: /* l.sfgtsi */ LOG_DIS("l.sfgtsi r%d, %d\n", ra, I16); - tcg_gen_setcondi_tl(TCG_COND_GT, env_btaken, cpu_R[ra], I16); + tcg_gen_setcondi_tl(TCG_COND_GT, cpu_sr_f, cpu_R[ra], I16); break; case 0xb: /* l.sfgesi */ LOG_DIS("l.sfgesi r%d, %d\n", ra, I16); - tcg_gen_setcondi_tl(TCG_COND_GE, env_btaken, cpu_R[ra], I16); + tcg_gen_setcondi_tl(TCG_COND_GE, cpu_sr_f, cpu_R[ra], I16); break; case 0xc: /* l.sfltsi */ LOG_DIS("l.sfltsi r%d, %d\n", ra, I16); - tcg_gen_setcondi_tl(TCG_COND_LT, env_btaken, cpu_R[ra], I16); + tcg_gen_setcondi_tl(TCG_COND_LT, cpu_sr_f, cpu_R[ra], I16); break; case 0xd: /* l.sflesi */ LOG_DIS("l.sflesi r%d, %d\n", ra, I16); - tcg_gen_setcondi_tl(TCG_COND_LE, env_btaken, cpu_R[ra], I16); + tcg_gen_setcondi_tl(TCG_COND_LE, cpu_sr_f, cpu_R[ra], I16); break; default: gen_illegal_exception(dc); break; } - wb_SR_F(); } static void dec_sys(DisasContext *dc, uint32_t insn) @@ -1308,32 +1285,32 @@ static void dec_float(DisasContext *dc, uint32_t insn) case 0x08: /* lf.sfeq.s */ LOG_DIS("lf.sfeq.s r%d, r%d\n", ra, rb); - gen_helper_float_eq_s(env_btaken, cpu_env, cpu_R[ra], cpu_R[rb]); + gen_helper_float_eq_s(cpu_sr_f, cpu_env, cpu_R[ra], cpu_R[rb]); break; case 0x09: /* lf.sfne.s */ LOG_DIS("lf.sfne.s r%d, r%d\n", ra, rb); - gen_helper_float_ne_s(env_btaken, cpu_env, cpu_R[ra], cpu_R[rb]); + gen_helper_float_ne_s(cpu_sr_f, cpu_env, cpu_R[ra], cpu_R[rb]); break; case 0x0a: /* lf.sfgt.s */ LOG_DIS("lf.sfgt.s r%d, r%d\n", ra, rb); - gen_helper_float_gt_s(env_btaken, cpu_env, cpu_R[ra], cpu_R[rb]); + gen_helper_float_gt_s(cpu_sr_f, cpu_env, cpu_R[ra], cpu_R[rb]); break; case 0x0b: /* lf.sfge.s */ LOG_DIS("lf.sfge.s r%d, r%d\n", ra, rb); - gen_helper_float_ge_s(env_btaken, cpu_env, cpu_R[ra], cpu_R[rb]); + gen_helper_float_ge_s(cpu_sr_f, cpu_env, cpu_R[ra], cpu_R[rb]); break; case 0x0c: /* lf.sflt.s */ LOG_DIS("lf.sflt.s r%d, r%d\n", ra, rb); - gen_helper_float_lt_s(env_btaken, cpu_env, cpu_R[ra], cpu_R[rb]); + gen_helper_float_lt_s(cpu_sr_f, cpu_env, cpu_R[ra], cpu_R[rb]); break; case 0x0d: /* lf.sfle.s */ LOG_DIS("lf.sfle.s r%d, r%d\n", ra, rb); - gen_helper_float_le_s(env_btaken, cpu_env, cpu_R[ra], cpu_R[rb]); + gen_helper_float_le_s(cpu_sr_f, cpu_env, cpu_R[ra], cpu_R[rb]); break; /* not used yet, open it when we need or64. */ @@ -1394,37 +1371,37 @@ static void dec_float(DisasContext *dc, uint32_t insn) case 0x18: lf.sfeq.d LOG_DIS("lf.sfeq.d r%d, r%d\n", ra, rb); check_of64s(dc); - gen_helper_float_eq_d(env_btaken, cpu_env, cpu_R[ra], cpu_R[rb]); + gen_helper_float_eq_d(cpu_sr_f, cpu_env, cpu_R[ra], cpu_R[rb]); break; case 0x1a: lf.sfgt.d LOG_DIS("lf.sfgt.d r%d, r%d\n", ra, rb); check_of64s(dc); - gen_helper_float_gt_d(env_btaken, cpu_env, cpu_R[ra], cpu_R[rb]); + gen_helper_float_gt_d(cpu_sr_f, cpu_env, cpu_R[ra], cpu_R[rb]); break; case 0x1b: lf.sfge.d LOG_DIS("lf.sfge.d r%d, r%d\n", ra, rb); check_of64s(dc); - gen_helper_float_ge_d(env_btaken, cpu_env, cpu_R[ra], cpu_R[rb]); + gen_helper_float_ge_d(cpu_sr_f, cpu_env, cpu_R[ra], cpu_R[rb]); break; case 0x19: lf.sfne.d LOG_DIS("lf.sfne.d r%d, r%d\n", ra, rb); check_of64s(dc); - gen_helper_float_ne_d(env_btaken, cpu_env, cpu_R[ra], cpu_R[rb]); + gen_helper_float_ne_d(cpu_sr_f, cpu_env, cpu_R[ra], cpu_R[rb]); break; case 0x1c: lf.sflt.d LOG_DIS("lf.sflt.d r%d, r%d\n", ra, rb); check_of64s(dc); - gen_helper_float_lt_d(env_btaken, cpu_env, cpu_R[ra], cpu_R[rb]); + gen_helper_float_lt_d(cpu_sr_f, cpu_env, cpu_R[ra], cpu_R[rb]); break; case 0x1d: lf.sfle.d LOG_DIS("lf.sfle.d r%d, r%d\n", ra, rb); check_of64s(dc); - gen_helper_float_le_d(env_btaken, cpu_env, cpu_R[ra], cpu_R[rb]); + gen_helper_float_le_d(cpu_sr_f, cpu_env, cpu_R[ra], cpu_R[rb]); break; #endif*/ @@ -1432,7 +1409,6 @@ static void dec_float(DisasContext *dc, uint32_t insn) gen_illegal_exception(dc); break; } - wb_SR_F(); } static void disas_openrisc_insn(DisasContext *dc, OpenRISCCPU *cpu) -- cgit v1.1 From 9745807191a81c45970f780166f44a7f93b18653 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Wed, 18 Feb 2015 13:26:26 -0800 Subject: target/openrisc: Keep SR_CY and SR_OV in a separate variables This significantly streamlines carry and overflow production. Signed-off-by: Richard Henderson --- target/openrisc/cpu.h | 13 +++- target/openrisc/exception_helper.c | 31 ++++++++-- target/openrisc/helper.h | 4 +- target/openrisc/translate.c | 119 +++++++++++++------------------------ 4 files changed, 78 insertions(+), 89 deletions(-) (limited to 'target') diff --git a/target/openrisc/cpu.h b/target/openrisc/cpu.h index bb5d363..e693461 100644 --- a/target/openrisc/cpu.h +++ b/target/openrisc/cpu.h @@ -287,7 +287,9 @@ typedef struct CPUOpenRISCState { target_ulong eear; /* Exception EA register */ target_ulong sr_f; /* the SR_F bit, values 0, 1. */ - uint32_t sr; /* Supervisor register, without SR_F */ + target_ulong sr_cy; /* the SR_CY bit, values 0, 1. */ + target_long sr_ov; /* the SR_OV bit (in the sign bit only) */ + uint32_t sr; /* Supervisor register, without SR_{F,CY,OV} */ uint32_t vr; /* Version register */ uint32_t upr; /* Unit presence register */ uint32_t cpucfgr; /* CPU configure register */ @@ -414,13 +416,18 @@ static inline int cpu_mmu_index(CPUOpenRISCState *env, bool ifetch) static inline uint32_t cpu_get_sr(const CPUOpenRISCState *env) { - return env->sr + env->sr_f * SR_F; + return (env->sr + + env->sr_f * SR_F + + env->sr_cy * SR_CY + + (env->sr_ov < 0) * SR_OV); } static inline void cpu_set_sr(CPUOpenRISCState *env, uint32_t val) { env->sr_f = (val & SR_F) != 0; - env->sr = (val & ~SR_F) | SR_FO; + env->sr_cy = (val & SR_CY) != 0; + env->sr_ov = (val & SR_OV ? -1 : 0); + env->sr = (val & ~(SR_F | SR_CY | SR_OV)) | SR_FO; } #define CPU_INTERRUPT_TIMER CPU_INTERRUPT_TGT_INT_0 diff --git a/target/openrisc/exception_helper.c b/target/openrisc/exception_helper.c index 5147da6..1536053 100644 --- a/target/openrisc/exception_helper.c +++ b/target/openrisc/exception_helper.c @@ -30,13 +30,32 @@ void HELPER(exception)(CPUOpenRISCState *env, uint32_t excp) raise_exception(cpu, excp); } -void HELPER(ove)(CPUOpenRISCState *env, target_ulong test) +static void QEMU_NORETURN do_range(CPUOpenRISCState *env, uintptr_t pc) { - if (unlikely(test)) { - OpenRISCCPU *cpu = openrisc_env_get_cpu(env); - CPUState *cs = CPU(cpu); + OpenRISCCPU *cpu = openrisc_env_get_cpu(env); + CPUState *cs = CPU(cpu); + + cs->exception_index = EXCP_RANGE; + cpu_loop_exit_restore(cs, pc); +} + +void HELPER(ove_cy)(CPUOpenRISCState *env) +{ + if (env->sr_cy) { + do_range(env, GETPC()); + } +} + +void HELPER(ove_ov)(CPUOpenRISCState *env) +{ + if (env->sr_ov < 0) { + do_range(env, GETPC()); + } +} - cs->exception_index = EXCP_RANGE; - cpu_loop_exit_restore(cs, GETPC()); +void HELPER(ove_cyov)(CPUOpenRISCState *env) +{ + if (env->sr_cy || env->sr_ov < 0) { + do_range(env, GETPC()); } } diff --git a/target/openrisc/helper.h b/target/openrisc/helper.h index c2c8098..f4d97a2 100644 --- a/target/openrisc/helper.h +++ b/target/openrisc/helper.h @@ -19,7 +19,9 @@ /* exception */ DEF_HELPER_FLAGS_2(exception, 0, void, env, i32) -DEF_HELPER_FLAGS_2(ove, TCG_CALL_NO_WG, void, env, tl) +DEF_HELPER_FLAGS_1(ove_cy, TCG_CALL_NO_WG, void, env) +DEF_HELPER_FLAGS_1(ove_ov, TCG_CALL_NO_WG, void, env) +DEF_HELPER_FLAGS_1(ove_cyov, TCG_CALL_NO_WG, void, env) /* float */ DEF_HELPER_FLAGS_2(itofd, 0, i64, env, i64) diff --git a/target/openrisc/translate.c b/target/openrisc/translate.c index 405a1a0..6c745d3 100644 --- a/target/openrisc/translate.c +++ b/target/openrisc/translate.c @@ -55,6 +55,8 @@ static TCGv jmp_pc; /* l.jr/l.jalr temp pc */ static TCGv cpu_npc; static TCGv cpu_ppc; static TCGv cpu_sr_f; /* bf/bnf, F flag taken */ +static TCGv cpu_sr_cy; /* carry (unsigned overflow) */ +static TCGv cpu_sr_ov; /* signed overflow */ static TCGv cpu_lock_addr; static TCGv cpu_lock_value; static TCGv_i32 fpcsr; @@ -90,6 +92,10 @@ void openrisc_translate_init(void) offsetof(CPUOpenRISCState, jmp_pc), "jmp_pc"); cpu_sr_f = tcg_global_mem_new(cpu_env, offsetof(CPUOpenRISCState, sr_f), "sr_f"); + cpu_sr_cy = tcg_global_mem_new(cpu_env, + offsetof(CPUOpenRISCState, sr_cy), "sr_cy"); + cpu_sr_ov = tcg_global_mem_new(cpu_env, + offsetof(CPUOpenRISCState, sr_ov), "sr_ov"); cpu_lock_addr = tcg_global_mem_new(cpu_env, offsetof(CPUOpenRISCState, lock_addr), "lock_addr"); @@ -233,27 +239,24 @@ static void gen_jump(DisasContext *dc, int32_t n26, uint32_t reg, uint32_t op0) gen_sync_flags(dc); } -static void gen_ove_cy(DisasContext *dc, TCGv cy) +static void gen_ove_cy(DisasContext *dc) { if (dc->tb_flags & SR_OVE) { - gen_helper_ove(cpu_env, cy); + gen_helper_ove_cy(cpu_env); } } -static void gen_ove_ov(DisasContext *dc, TCGv ov) +static void gen_ove_ov(DisasContext *dc) { if (dc->tb_flags & SR_OVE) { - gen_helper_ove(cpu_env, ov); + gen_helper_ove_ov(cpu_env); } } -static void gen_ove_cyov(DisasContext *dc, TCGv cy, TCGv ov) +static void gen_ove_cyov(DisasContext *dc) { if (dc->tb_flags & SR_OVE) { - TCGv t0 = tcg_temp_new(); - tcg_gen_or_tl(t0, cy, ov); - gen_helper_ove(cpu_env, t0); - tcg_temp_free(t0); + gen_helper_ove_cyov(cpu_env); } } @@ -261,143 +264,101 @@ static void gen_add(DisasContext *dc, TCGv dest, TCGv srca, TCGv srcb) { TCGv t0 = tcg_const_tl(0); TCGv res = tcg_temp_new(); - TCGv sr_cy = tcg_temp_new(); - TCGv sr_ov = tcg_temp_new(); - tcg_gen_add2_tl(res, sr_cy, srca, t0, srcb, t0); - tcg_gen_xor_tl(sr_ov, srca, srcb); + tcg_gen_add2_tl(res, cpu_sr_cy, srca, t0, srcb, t0); + tcg_gen_xor_tl(cpu_sr_ov, srca, srcb); tcg_gen_xor_tl(t0, res, srcb); - tcg_gen_andc_tl(sr_ov, t0, sr_ov); + tcg_gen_andc_tl(cpu_sr_ov, t0, cpu_sr_ov); tcg_temp_free(t0); tcg_gen_mov_tl(dest, res); tcg_temp_free(res); - tcg_gen_shri_tl(sr_ov, sr_ov, TARGET_LONG_BITS - 1); - tcg_gen_deposit_tl(cpu_sr, cpu_sr, sr_cy, ctz32(SR_CY), 1); - tcg_gen_deposit_tl(cpu_sr, cpu_sr, sr_ov, ctz32(SR_OV), 1); - - gen_ove_cyov(dc, sr_ov, sr_cy); - tcg_temp_free(sr_ov); - tcg_temp_free(sr_cy); + gen_ove_cyov(dc); } static void gen_addc(DisasContext *dc, TCGv dest, TCGv srca, TCGv srcb) { TCGv t0 = tcg_const_tl(0); TCGv res = tcg_temp_new(); - TCGv sr_cy = tcg_temp_new(); - TCGv sr_ov = tcg_temp_new(); - - tcg_gen_shri_tl(sr_cy, cpu_sr, ctz32(SR_CY)); - tcg_gen_andi_tl(sr_cy, sr_cy, 1); - tcg_gen_add2_tl(res, sr_cy, srca, t0, sr_cy, t0); - tcg_gen_add2_tl(res, sr_cy, res, sr_cy, srcb, t0); - tcg_gen_xor_tl(sr_ov, srca, srcb); + tcg_gen_add2_tl(res, cpu_sr_cy, srca, t0, cpu_sr_cy, t0); + tcg_gen_add2_tl(res, cpu_sr_cy, res, cpu_sr_cy, srcb, t0); + tcg_gen_xor_tl(cpu_sr_ov, srca, srcb); tcg_gen_xor_tl(t0, res, srcb); - tcg_gen_andc_tl(sr_ov, t0, sr_ov); + tcg_gen_andc_tl(cpu_sr_ov, t0, cpu_sr_ov); tcg_temp_free(t0); tcg_gen_mov_tl(dest, res); tcg_temp_free(res); - tcg_gen_shri_tl(sr_ov, sr_ov, TARGET_LONG_BITS - 1); - tcg_gen_deposit_tl(cpu_sr, cpu_sr, sr_cy, ctz32(SR_CY), 1); - tcg_gen_deposit_tl(cpu_sr, cpu_sr, sr_ov, ctz32(SR_OV), 1); - - gen_ove_cyov(dc, sr_ov, sr_cy); - tcg_temp_free(sr_ov); - tcg_temp_free(sr_cy); + gen_ove_cyov(dc); } static void gen_sub(DisasContext *dc, TCGv dest, TCGv srca, TCGv srcb) { TCGv res = tcg_temp_new(); - TCGv sr_cy = tcg_temp_new(); - TCGv sr_ov = tcg_temp_new(); tcg_gen_sub_tl(res, srca, srcb); - tcg_gen_xor_tl(sr_cy, srca, srcb); - tcg_gen_xor_tl(sr_ov, res, srcb); - tcg_gen_and_tl(sr_ov, sr_ov, sr_cy); - tcg_gen_setcond_tl(TCG_COND_LTU, sr_cy, srca, srcb); + tcg_gen_xor_tl(cpu_sr_cy, srca, srcb); + tcg_gen_xor_tl(cpu_sr_ov, res, srcb); + tcg_gen_and_tl(cpu_sr_ov, cpu_sr_ov, cpu_sr_cy); + tcg_gen_setcond_tl(TCG_COND_LTU, cpu_sr_cy, srca, srcb); tcg_gen_mov_tl(dest, res); tcg_temp_free(res); - tcg_gen_shri_tl(sr_ov, sr_ov, TARGET_LONG_BITS - 1); - tcg_gen_deposit_tl(cpu_sr, cpu_sr, sr_cy, ctz32(SR_CY), 1); - tcg_gen_deposit_tl(cpu_sr, cpu_sr, sr_ov, ctz32(SR_OV), 1); - - gen_ove_cyov(dc, sr_ov, sr_cy); - tcg_temp_free(sr_ov); - tcg_temp_free(sr_cy); + gen_ove_cyov(dc); } static void gen_mul(DisasContext *dc, TCGv dest, TCGv srca, TCGv srcb) { - TCGv sr_ov = tcg_temp_new(); TCGv t0 = tcg_temp_new(); - tcg_gen_muls2_tl(dest, sr_ov, srca, srcb); + tcg_gen_muls2_tl(dest, cpu_sr_ov, srca, srcb); tcg_gen_sari_tl(t0, dest, TARGET_LONG_BITS - 1); - tcg_gen_setcond_tl(TCG_COND_NE, sr_ov, sr_ov, t0); + tcg_gen_setcond_tl(TCG_COND_NE, cpu_sr_ov, cpu_sr_ov, t0); tcg_temp_free(t0); - tcg_gen_deposit_tl(cpu_sr, cpu_sr, sr_ov, ctz32(SR_OV), 1); - - gen_ove_ov(dc, sr_ov); - tcg_temp_free(sr_ov); + tcg_gen_neg_tl(cpu_sr_ov, cpu_sr_ov); + gen_ove_ov(dc); } static void gen_mulu(DisasContext *dc, TCGv dest, TCGv srca, TCGv srcb) { - TCGv sr_cy = tcg_temp_new(); - - tcg_gen_muls2_tl(dest, sr_cy, srca, srcb); - tcg_gen_setcondi_tl(TCG_COND_NE, sr_cy, sr_cy, 0); - - tcg_gen_deposit_tl(cpu_sr, cpu_sr, sr_cy, ctz32(SR_CY), 1); + tcg_gen_muls2_tl(dest, cpu_sr_cy, srca, srcb); + tcg_gen_setcondi_tl(TCG_COND_NE, cpu_sr_cy, cpu_sr_cy, 0); - gen_ove_cy(dc, sr_cy); - tcg_temp_free(sr_cy); + gen_ove_cy(dc); } static void gen_div(DisasContext *dc, TCGv dest, TCGv srca, TCGv srcb) { - TCGv sr_ov = tcg_temp_new(); TCGv t0 = tcg_temp_new(); - tcg_gen_setcondi_tl(TCG_COND_EQ, sr_ov, srcb, 0); + tcg_gen_setcondi_tl(TCG_COND_EQ, cpu_sr_ov, srcb, 0); /* The result of divide-by-zero is undefined. Supress the host-side exception by dividing by 1. */ - tcg_gen_or_tl(t0, srcb, sr_ov); + tcg_gen_or_tl(t0, srcb, cpu_sr_ov); tcg_gen_div_tl(dest, srca, t0); tcg_temp_free(t0); - tcg_gen_deposit_tl(cpu_sr, cpu_sr, sr_ov, ctz32(SR_OV), 1); - - gen_ove_ov(dc, sr_ov); - tcg_temp_free(sr_ov); + tcg_gen_neg_tl(cpu_sr_ov, cpu_sr_ov); + gen_ove_ov(dc); } static void gen_divu(DisasContext *dc, TCGv dest, TCGv srca, TCGv srcb) { - TCGv sr_cy = tcg_temp_new(); TCGv t0 = tcg_temp_new(); - tcg_gen_setcondi_tl(TCG_COND_EQ, sr_cy, srcb, 0); + tcg_gen_setcondi_tl(TCG_COND_EQ, cpu_sr_cy, srcb, 0); /* The result of divide-by-zero is undefined. Supress the host-side exception by dividing by 1. */ - tcg_gen_or_tl(t0, srcb, sr_cy); + tcg_gen_or_tl(t0, srcb, cpu_sr_cy); tcg_gen_divu_tl(dest, srca, t0); tcg_temp_free(t0); - tcg_gen_deposit_tl(cpu_sr, cpu_sr, sr_cy, ctz32(SR_CY), 1); - - gen_ove_cy(dc, sr_cy); - tcg_temp_free(sr_cy); + gen_ove_cy(dc); } static void gen_lwa(DisasContext *dc, TCGv rd, TCGv ra, int32_t ofs) -- cgit v1.1 From 784696d119d2c6709920e8f4c8c9b445a43a8e8c Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Wed, 18 Feb 2015 11:51:10 -0800 Subject: target/openrisc: Use movcond where appropriate Reviewed-by: Bastian Koppelmann Signed-off-by: Richard Henderson --- target/openrisc/translate.c | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) (limited to 'target') diff --git a/target/openrisc/translate.c b/target/openrisc/translate.c index 6c745d3..f91ab6a 100644 --- a/target/openrisc/translate.c +++ b/target/openrisc/translate.c @@ -214,12 +214,16 @@ static void gen_jump(DisasContext *dc, int32_t n26, uint32_t reg, uint32_t op0) case 0x03: /* l.bnf */ case 0x04: /* l.bf */ { - TCGLabel *lab = gen_new_label(); - tcg_gen_movi_tl(jmp_pc, dc->pc+8); - tcg_gen_brcondi_tl(op0 == 0x03 ? TCG_COND_NE : TCG_COND_EQ, - cpu_sr_f, 0, lab); - tcg_gen_movi_tl(jmp_pc, tmp_pc); - gen_set_label(lab); + TCGv t_next = tcg_const_tl(dc->pc + 8); + TCGv t_true = tcg_const_tl(tmp_pc); + TCGv t_zero = tcg_const_tl(0); + + tcg_gen_movcond_tl(op0 == 0x03 ? TCG_COND_EQ : TCG_COND_NE, + jmp_pc, cpu_sr_f, t_zero, t_true, t_next); + + tcg_temp_free(t_next); + tcg_temp_free(t_true); + tcg_temp_free(t_zero); } break; case 0x11: /* l.jr */ @@ -502,14 +506,10 @@ static void dec_calc(DisasContext *dc, uint32_t insn) case 0xe: /* l.cmov */ LOG_DIS("l.cmov r%d, r%d, r%d\n", rd, ra, rb); { - TCGLabel *lab = gen_new_label(); - TCGv res = tcg_temp_local_new(); - tcg_gen_mov_tl(res, cpu_R[rb]); - tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_sr_f, 0, lab); - tcg_gen_mov_tl(res, cpu_R[ra]); - gen_set_label(lab); - tcg_gen_mov_tl(cpu_R[rd], res); - tcg_temp_free(res); + TCGv zero = tcg_const_tl(0); + tcg_gen_movcond_tl(TCG_COND_NE, cpu_R[rd], cpu_sr_f, zero, + cpu_R[ra], cpu_R[rb]); + tcg_temp_free(zero); } return; -- cgit v1.1 From 9fba702bd4be03f1df156d4d60178c4badc8ff2d Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Wed, 18 Feb 2015 13:38:33 -0800 Subject: target/openrisc: Set flags on helpers MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Reviewed-by: Philippe Mathieu-Daudé Reviewed-by: Bastian Koppelmann Signed-off-by: Richard Henderson --- target/openrisc/helper.h | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) (limited to 'target') diff --git a/target/openrisc/helper.h b/target/openrisc/helper.h index f4d97a2..78a123d 100644 --- a/target/openrisc/helper.h +++ b/target/openrisc/helper.h @@ -18,26 +18,26 @@ */ /* exception */ -DEF_HELPER_FLAGS_2(exception, 0, void, env, i32) +DEF_HELPER_FLAGS_2(exception, TCG_CALL_NO_WG, void, env, i32) DEF_HELPER_FLAGS_1(ove_cy, TCG_CALL_NO_WG, void, env) DEF_HELPER_FLAGS_1(ove_ov, TCG_CALL_NO_WG, void, env) DEF_HELPER_FLAGS_1(ove_cyov, TCG_CALL_NO_WG, void, env) /* float */ -DEF_HELPER_FLAGS_2(itofd, 0, i64, env, i64) -DEF_HELPER_FLAGS_2(itofs, 0, i32, env, i32) -DEF_HELPER_FLAGS_2(ftoid, 0, i64, env, i64) -DEF_HELPER_FLAGS_2(ftois, 0, i32, env, i32) +DEF_HELPER_FLAGS_2(itofd, TCG_CALL_NO_WG, i64, env, i64) +DEF_HELPER_FLAGS_2(itofs, TCG_CALL_NO_WG, i32, env, i32) +DEF_HELPER_FLAGS_2(ftoid, TCG_CALL_NO_WG, i64, env, i64) +DEF_HELPER_FLAGS_2(ftois, TCG_CALL_NO_WG, i32, env, i32) #define FOP_MADD(op) \ -DEF_HELPER_FLAGS_3(float_ ## op ## _s, 0, i32, env, i32, i32) \ -DEF_HELPER_FLAGS_3(float_ ## op ## _d, 0, i64, env, i64, i64) +DEF_HELPER_FLAGS_3(float_ ## op ## _s, TCG_CALL_NO_WG, i32, env, i32, i32) \ +DEF_HELPER_FLAGS_3(float_ ## op ## _d, TCG_CALL_NO_WG, i64, env, i64, i64) FOP_MADD(muladd) #undef FOP_MADD #define FOP_CALC(op) \ -DEF_HELPER_FLAGS_3(float_ ## op ## _s, 0, i32, env, i32, i32) \ -DEF_HELPER_FLAGS_3(float_ ## op ## _d, 0, i64, env, i64, i64) +DEF_HELPER_FLAGS_3(float_ ## op ## _s, TCG_CALL_NO_WG, i32, env, i32, i32) \ +DEF_HELPER_FLAGS_3(float_ ## op ## _d, TCG_CALL_NO_WG, i64, env, i64, i64) FOP_CALC(add) FOP_CALC(sub) FOP_CALC(mul) @@ -46,8 +46,8 @@ FOP_CALC(rem) #undef FOP_CALC #define FOP_CMP(op) \ -DEF_HELPER_FLAGS_3(float_ ## op ## _s, 0, i32, env, i32, i32) \ -DEF_HELPER_FLAGS_3(float_ ## op ## _d, 0, i64, env, i64, i64) +DEF_HELPER_FLAGS_3(float_ ## op ## _s, TCG_CALL_NO_WG, i32, env, i32, i32) \ +DEF_HELPER_FLAGS_3(float_ ## op ## _d, TCG_CALL_NO_WG, i64, env, i64, i64) FOP_CMP(eq) FOP_CMP(lt) FOP_CMP(le) @@ -61,4 +61,4 @@ DEF_HELPER_FLAGS_1(rfe, 0, void, env) /* sys */ DEF_HELPER_FLAGS_4(mtspr, 0, void, env, tl, tl, tl) -DEF_HELPER_FLAGS_4(mfspr, 0, tl, env, tl, tl, tl) +DEF_HELPER_FLAGS_4(mfspr, TCG_CALL_NO_WG, tl, env, tl, tl, tl) -- cgit v1.1 From 20dc52a37c81b672a5239b20527335508bcea02e Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Wed, 18 Feb 2015 16:26:01 -0800 Subject: target/openrisc: Enable trap, csync, msync, psync for user mode MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Not documented as disabled for user mode. Reviewed-by: Philippe Mathieu-Daudé Reviewed-by: Bastian Koppelmann Signed-off-by: Richard Henderson --- target/openrisc/translate.c | 32 -------------------------------- 1 file changed, 32 deletions(-) (limited to 'target') diff --git a/target/openrisc/translate.c b/target/openrisc/translate.c index f91ab6a..6c8f05c 100644 --- a/target/openrisc/translate.c +++ b/target/openrisc/translate.c @@ -1134,52 +1134,20 @@ static void dec_sys(DisasContext *dc, uint32_t insn) case 0x100: /* l.trap */ LOG_DIS("l.trap %d\n", K16); -#if defined(CONFIG_USER_ONLY) - return; -#else - if (dc->mem_idx == MMU_USER_IDX) { - gen_illegal_exception(dc); - return; - } tcg_gen_movi_tl(cpu_pc, dc->pc); gen_exception(dc, EXCP_TRAP); -#endif break; case 0x300: /* l.csync */ LOG_DIS("l.csync\n"); -#if defined(CONFIG_USER_ONLY) - return; -#else - if (dc->mem_idx == MMU_USER_IDX) { - gen_illegal_exception(dc); - return; - } -#endif break; case 0x200: /* l.msync */ LOG_DIS("l.msync\n"); -#if defined(CONFIG_USER_ONLY) - return; -#else - if (dc->mem_idx == MMU_USER_IDX) { - gen_illegal_exception(dc); - return; - } -#endif break; case 0x270: /* l.psync */ LOG_DIS("l.psync\n"); -#if defined(CONFIG_USER_ONLY) - return; -#else - if (dc->mem_idx == MMU_USER_IDX) { - gen_illegal_exception(dc); - return; - } -#endif break; default: -- cgit v1.1 From 24fc5c0feb0d8ed3367c6628c14ac3ba6ebcbb89 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Mon, 23 Jan 2017 19:07:40 -0800 Subject: target/openrisc: Implement msync Signed-off-by: Richard Henderson --- target/openrisc/translate.c | 1 + 1 file changed, 1 insertion(+) (limited to 'target') diff --git a/target/openrisc/translate.c b/target/openrisc/translate.c index 6c8f05c..dd4ba8c 100644 --- a/target/openrisc/translate.c +++ b/target/openrisc/translate.c @@ -1144,6 +1144,7 @@ static void dec_sys(DisasContext *dc, uint32_t insn) case 0x200: /* l.msync */ LOG_DIS("l.msync\n"); + tcg_gen_mb(TCG_MO_ALL); break; case 0x270: /* l.psync */ -- cgit v1.1 From 6f7332ba713bc4d36f1078990c5a48618933d6c3 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Wed, 18 Feb 2015 15:05:05 -0800 Subject: target/openrisc: Represent MACHI:MACLO as a single unit Significantly simplifies the implementation of the use of MAC. Reviewed-by: Bastian Koppelmann Signed-off-by: Richard Henderson --- target/openrisc/cpu.h | 3 +- target/openrisc/machine.c | 5 +- target/openrisc/sys_helper.c | 13 +++++ target/openrisc/translate.c | 120 +++++++++++++++++++++++-------------------- 4 files changed, 80 insertions(+), 61 deletions(-) (limited to 'target') diff --git a/target/openrisc/cpu.h b/target/openrisc/cpu.h index e693461..9528277 100644 --- a/target/openrisc/cpu.h +++ b/target/openrisc/cpu.h @@ -277,8 +277,7 @@ typedef struct CPUOpenRISCState { target_ulong ppc; /* Prev PC */ target_ulong jmp_pc; /* Jump PC */ - target_ulong machi; /* Multiply register MACHI */ - target_ulong maclo; /* Multiply register MACLO */ + uint64_t mac; /* Multiply registers MACHI:MACLO */ target_ulong fpmaddhi; /* Multiply and add float register FPMADDHI */ target_ulong fpmaddlo; /* Multiply and add float register FPMADDLO */ diff --git a/target/openrisc/machine.c b/target/openrisc/machine.c index b723138..4100957 100644 --- a/target/openrisc/machine.c +++ b/target/openrisc/machine.c @@ -47,8 +47,8 @@ static const VMStateInfo vmstate_sr = { static const VMStateDescription vmstate_env = { .name = "env", - .version_id = 2, - .minimum_version_id = 2, + .version_id = 3, + .minimum_version_id = 3, .fields = (VMStateField[]) { VMSTATE_UINTTL_ARRAY(gpr, CPUOpenRISCState, 32), VMSTATE_UINTTL(pc, CPUOpenRISCState), @@ -82,6 +82,7 @@ static const VMStateDescription vmstate_env = { VMSTATE_UINT32(immucfgr, CPUOpenRISCState), VMSTATE_UINT32(esr, CPUOpenRISCState), VMSTATE_UINT32(fpcsr, CPUOpenRISCState), + VMSTATE_UINT64(mac, CPUOpenRISCState), VMSTATE_END_OF_LIST() } }; diff --git a/target/openrisc/sys_helper.c b/target/openrisc/sys_helper.c index 4a59728..9841a5b 100644 --- a/target/openrisc/sys_helper.c +++ b/target/openrisc/sys_helper.c @@ -120,6 +120,12 @@ void HELPER(mtspr)(CPUOpenRISCState *env, case TO_SPR(2, 1280) ... TO_SPR(2, 1407): /* ITLBW3MR 0-127 */ case TO_SPR(2, 1408) ... TO_SPR(2, 1535): /* ITLBW3TR 0-127 */ break; + case TO_SPR(5, 1): /* MACLO */ + env->mac = deposit64(env->mac, 0, 32, rb); + break; + case TO_SPR(5, 2): /* MACHI */ + env->mac = deposit64(env->mac, 32, 32, rb); + break; case TO_SPR(9, 0): /* PICMR */ env->picmr |= rb; break; @@ -245,6 +251,13 @@ target_ulong HELPER(mfspr)(CPUOpenRISCState *env, case TO_SPR(2, 1408) ... TO_SPR(2, 1535): /* ITLBW3TR 0-127 */ break; + case TO_SPR(5, 1): /* MACLO */ + return (uint32_t)env->mac; + break; + case TO_SPR(5, 2): /* MACHI */ + return env->mac >> 32; + break; + case TO_SPR(9, 0): /* PICMR */ return env->picmr; diff --git a/target/openrisc/translate.c b/target/openrisc/translate.c index dd4ba8c..82b8bec 100644 --- a/target/openrisc/translate.c +++ b/target/openrisc/translate.c @@ -60,7 +60,7 @@ static TCGv cpu_sr_ov; /* signed overflow */ static TCGv cpu_lock_addr; static TCGv cpu_lock_value; static TCGv_i32 fpcsr; -static TCGv machi, maclo; +static TCGv_i64 cpu_mac; /* MACHI:MACLO */ static TCGv fpmaddhi, fpmaddlo; static TCGv_i32 env_flags; #include "exec/gen-icount.h" @@ -105,12 +105,9 @@ void openrisc_translate_init(void) fpcsr = tcg_global_mem_new_i32(cpu_env, offsetof(CPUOpenRISCState, fpcsr), "fpcsr"); - machi = tcg_global_mem_new(cpu_env, - offsetof(CPUOpenRISCState, machi), - "machi"); - maclo = tcg_global_mem_new(cpu_env, - offsetof(CPUOpenRISCState, maclo), - "maclo"); + cpu_mac = tcg_global_mem_new_i64(cpu_env, + offsetof(CPUOpenRISCState, mac), + "mac"); fpmaddhi = tcg_global_mem_new(cpu_env, offsetof(CPUOpenRISCState, fpmaddhi), "fpmaddhi"); @@ -365,6 +362,58 @@ static void gen_divu(DisasContext *dc, TCGv dest, TCGv srca, TCGv srcb) gen_ove_cy(dc); } +static void gen_mac(DisasContext *dc, TCGv srca, TCGv srcb) +{ + TCGv_i64 t1 = tcg_temp_new_i64(); + TCGv_i64 t2 = tcg_temp_new_i64(); + + tcg_gen_ext_tl_i64(t1, srca); + tcg_gen_ext_tl_i64(t2, srcb); + tcg_gen_mul_i64(t1, t1, t2); + + /* Note that overflow is only computed during addition stage. */ + tcg_gen_xor_i64(t2, cpu_mac, t1); + tcg_gen_add_i64(cpu_mac, cpu_mac, t1); + tcg_gen_xor_i64(t1, t1, cpu_mac); + tcg_gen_andc_i64(t1, t1, t2); + tcg_temp_free_i64(t2); + +#if TARGET_LONG_BITS == 32 + tcg_gen_extrh_i64_i32(cpu_sr_ov, t1); +#else + tcg_gen_mov_i64(cpu_sr_ov, t1); +#endif + tcg_temp_free_i64(t1); + + gen_ove_ov(dc); +} + +static void gen_msb(DisasContext *dc, TCGv srca, TCGv srcb) +{ + TCGv_i64 t1 = tcg_temp_new_i64(); + TCGv_i64 t2 = tcg_temp_new_i64(); + + tcg_gen_ext_tl_i64(t1, srca); + tcg_gen_ext_tl_i64(t2, srcb); + tcg_gen_mul_i64(t1, t1, t2); + + /* Note that overflow is only computed during subtraction stage. */ + tcg_gen_xor_i64(t2, cpu_mac, t1); + tcg_gen_sub_i64(cpu_mac, cpu_mac, t1); + tcg_gen_xor_i64(t1, t1, cpu_mac); + tcg_gen_and_i64(t1, t1, t2); + tcg_temp_free_i64(t2); + +#if TARGET_LONG_BITS == 32 + tcg_gen_extrh_i64_i32(cpu_sr_ov, t1); +#else + tcg_gen_mov_i64(cpu_sr_ov, t1); +#endif + tcg_temp_free_i64(t1); + + gen_ove_ov(dc); +} + static void gen_lwa(DisasContext *dc, TCGv rd, TCGv ra, int32_t ofs) { TCGv ea = tcg_temp_new(); @@ -628,23 +677,9 @@ static void dec_misc(DisasContext *dc, uint32_t insn) case 0x13: /* l.maci */ LOG_DIS("l.maci r%d, %d\n", ra, I16); - { - TCGv_i64 t1 = tcg_temp_new_i64(); - TCGv_i64 t2 = tcg_temp_new_i64(); - TCGv_i32 dst = tcg_temp_new_i32(); - TCGv ttmp = tcg_const_tl(I16); - tcg_gen_mul_tl(dst, cpu_R[ra], ttmp); - tcg_gen_ext_i32_i64(t1, dst); - tcg_gen_concat_i32_i64(t2, maclo, machi); - tcg_gen_add_i64(t2, t2, t1); - tcg_gen_extrl_i64_i32(maclo, t2); - tcg_gen_shri_i64(t2, t2, 32); - tcg_gen_extrl_i64_i32(machi, t2); - tcg_temp_free_i32(dst); - tcg_temp_free(ttmp); - tcg_temp_free_i64(t1); - tcg_temp_free_i64(t2); - } + t0 = tcg_const_tl(I16); + gen_mac(dc, cpu_R[ra], t0); + tcg_temp_free(t0); break; case 0x09: /* l.rfe */ @@ -873,40 +908,12 @@ static void dec_mac(DisasContext *dc, uint32_t insn) switch (op0) { case 0x0001: /* l.mac */ LOG_DIS("l.mac r%d, r%d\n", ra, rb); - { - TCGv_i32 t0 = tcg_temp_new_i32(); - TCGv_i64 t1 = tcg_temp_new_i64(); - TCGv_i64 t2 = tcg_temp_new_i64(); - tcg_gen_mul_tl(t0, cpu_R[ra], cpu_R[rb]); - tcg_gen_ext_i32_i64(t1, t0); - tcg_gen_concat_i32_i64(t2, maclo, machi); - tcg_gen_add_i64(t2, t2, t1); - tcg_gen_extrl_i64_i32(maclo, t2); - tcg_gen_shri_i64(t2, t2, 32); - tcg_gen_extrl_i64_i32(machi, t2); - tcg_temp_free_i32(t0); - tcg_temp_free_i64(t1); - tcg_temp_free_i64(t2); - } + gen_mac(dc, cpu_R[ra], cpu_R[rb]); break; case 0x0002: /* l.msb */ LOG_DIS("l.msb r%d, r%d\n", ra, rb); - { - TCGv_i32 t0 = tcg_temp_new_i32(); - TCGv_i64 t1 = tcg_temp_new_i64(); - TCGv_i64 t2 = tcg_temp_new_i64(); - tcg_gen_mul_tl(t0, cpu_R[ra], cpu_R[rb]); - tcg_gen_ext_i32_i64(t1, t0); - tcg_gen_concat_i32_i64(t2, maclo, machi); - tcg_gen_sub_i64(t2, t2, t1); - tcg_gen_extrl_i64_i32(maclo, t2); - tcg_gen_shri_i64(t2, t2, 32); - tcg_gen_extrl_i64_i32(machi, t2); - tcg_temp_free_i32(t0); - tcg_temp_free_i64(t1); - tcg_temp_free_i64(t2); - } + gen_msb(dc, cpu_R[ra], cpu_R[rb]); break; default: @@ -969,9 +976,8 @@ static void dec_M(DisasContext *dc, uint32_t insn) case 0x1: /* l.macrc */ LOG_DIS("l.macrc r%d\n", rd); - tcg_gen_mov_tl(cpu_R[rd], maclo); - tcg_gen_movi_tl(maclo, 0x0); - tcg_gen_movi_tl(machi, 0x0); + tcg_gen_trunc_i64_tl(cpu_R[rd], cpu_mac); + tcg_gen_movi_i64(cpu_mac, 0); break; default: -- cgit v1.1 From cc5de49ebe5b2881b88b22c13410f13657b472e0 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Wed, 18 Feb 2015 17:03:40 -0800 Subject: target/openrisc: Implement muld, muldu, macu, msbu Reviewed-by: Bastian Koppelmann Signed-off-by: Richard Henderson --- target/openrisc/translate.c | 108 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 108 insertions(+) (limited to 'target') diff --git a/target/openrisc/translate.c b/target/openrisc/translate.c index 82b8bec..ce9672e 100644 --- a/target/openrisc/translate.c +++ b/target/openrisc/translate.c @@ -362,6 +362,56 @@ static void gen_divu(DisasContext *dc, TCGv dest, TCGv srca, TCGv srcb) gen_ove_cy(dc); } +static void gen_muld(DisasContext *dc, TCGv srca, TCGv srcb) +{ + TCGv_i64 t1 = tcg_temp_new_i64(); + TCGv_i64 t2 = tcg_temp_new_i64(); + + tcg_gen_ext_tl_i64(t1, srca); + tcg_gen_ext_tl_i64(t2, srcb); + if (TARGET_LONG_BITS == 32) { + tcg_gen_mul_i64(cpu_mac, t1, t2); + tcg_gen_movi_tl(cpu_sr_ov, 0); + } else { + TCGv_i64 high = tcg_temp_new_i64(); + + tcg_gen_muls2_i64(cpu_mac, high, t1, t2); + tcg_gen_sari_i64(t1, cpu_mac, 63); + tcg_gen_setcond_i64(TCG_COND_NE, t1, t1, high); + tcg_temp_free_i64(high); + tcg_gen_trunc_i64_tl(cpu_sr_ov, t1); + tcg_gen_neg_tl(cpu_sr_ov, cpu_sr_ov); + + gen_ove_ov(dc); + } + tcg_temp_free_i64(t1); + tcg_temp_free_i64(t2); +} + +static void gen_muldu(DisasContext *dc, TCGv srca, TCGv srcb) +{ + TCGv_i64 t1 = tcg_temp_new_i64(); + TCGv_i64 t2 = tcg_temp_new_i64(); + + tcg_gen_extu_tl_i64(t1, srca); + tcg_gen_extu_tl_i64(t2, srcb); + if (TARGET_LONG_BITS == 32) { + tcg_gen_mul_i64(cpu_mac, t1, t2); + tcg_gen_movi_tl(cpu_sr_cy, 0); + } else { + TCGv_i64 high = tcg_temp_new_i64(); + + tcg_gen_mulu2_i64(cpu_mac, high, t1, t2); + tcg_gen_setcondi_i64(TCG_COND_NE, high, high, 0); + tcg_gen_trunc_i64_tl(cpu_sr_cy, high); + tcg_temp_free_i64(high); + + gen_ove_cy(dc); + } + tcg_temp_free_i64(t1); + tcg_temp_free_i64(t2); +} + static void gen_mac(DisasContext *dc, TCGv srca, TCGv srcb) { TCGv_i64 t1 = tcg_temp_new_i64(); @@ -388,6 +438,25 @@ static void gen_mac(DisasContext *dc, TCGv srca, TCGv srcb) gen_ove_ov(dc); } +static void gen_macu(DisasContext *dc, TCGv srca, TCGv srcb) +{ + TCGv_i64 t1 = tcg_temp_new_i64(); + TCGv_i64 t2 = tcg_temp_new_i64(); + + tcg_gen_extu_tl_i64(t1, srca); + tcg_gen_extu_tl_i64(t2, srcb); + tcg_gen_mul_i64(t1, t1, t2); + tcg_temp_free_i64(t2); + + /* Note that overflow is only computed during addition stage. */ + tcg_gen_add_i64(cpu_mac, cpu_mac, t1); + tcg_gen_setcond_i64(TCG_COND_LTU, t1, cpu_mac, t1); + tcg_gen_trunc_i64_tl(cpu_sr_cy, t1); + tcg_temp_free_i64(t1); + + gen_ove_cy(dc); +} + static void gen_msb(DisasContext *dc, TCGv srca, TCGv srcb) { TCGv_i64 t1 = tcg_temp_new_i64(); @@ -414,6 +483,25 @@ static void gen_msb(DisasContext *dc, TCGv srca, TCGv srcb) gen_ove_ov(dc); } +static void gen_msbu(DisasContext *dc, TCGv srca, TCGv srcb) +{ + TCGv_i64 t1 = tcg_temp_new_i64(); + TCGv_i64 t2 = tcg_temp_new_i64(); + + tcg_gen_extu_tl_i64(t1, srca); + tcg_gen_extu_tl_i64(t2, srcb); + tcg_gen_mul_i64(t1, t1, t2); + + /* Note that overflow is only computed during subtraction stage. */ + tcg_gen_setcond_i64(TCG_COND_LTU, t2, cpu_mac, t1); + tcg_gen_sub_i64(cpu_mac, cpu_mac, t1); + tcg_gen_trunc_i64_tl(cpu_sr_cy, t2); + tcg_temp_free_i64(t2); + tcg_temp_free_i64(t1); + + gen_ove_cy(dc); +} + static void gen_lwa(DisasContext *dc, TCGv rd, TCGv ra, int32_t ofs) { TCGv ea = tcg_temp_new(); @@ -590,6 +678,11 @@ static void dec_calc(DisasContext *dc, uint32_t insn) gen_mul(dc, cpu_R[rd], cpu_R[ra], cpu_R[rb]); return; + case 0x7: /* l.muld */ + LOG_DIS("l.muld r%d, r%d\n", ra, rb); + gen_muld(dc, cpu_R[ra], cpu_R[rb]); + break; + case 0x9: /* l.div */ LOG_DIS("l.div r%d, r%d, r%d\n", rd, ra, rb); gen_div(dc, cpu_R[rd], cpu_R[ra], cpu_R[rb]); @@ -604,6 +697,11 @@ static void dec_calc(DisasContext *dc, uint32_t insn) LOG_DIS("l.mulu r%d, r%d, r%d\n", rd, ra, rb); gen_mulu(dc, cpu_R[rd], cpu_R[ra], cpu_R[rb]); return; + + case 0xc: /* l.muldu */ + LOG_DIS("l.muldu r%d, r%d\n", ra, rb); + gen_muldu(dc, cpu_R[ra], cpu_R[rb]); + return; } break; } @@ -916,6 +1014,16 @@ static void dec_mac(DisasContext *dc, uint32_t insn) gen_msb(dc, cpu_R[ra], cpu_R[rb]); break; + case 0x0003: /* l.macu */ + LOG_DIS("l.macu r%d, r%d\n", ra, rb); + gen_macu(dc, cpu_R[ra], cpu_R[rb]); + break; + + case 0x0004: /* l.msbu */ + LOG_DIS("l.msbu r%d, r%d\n", ra, rb); + gen_msbu(dc, cpu_R[ra], cpu_R[rb]); + break; + default: gen_illegal_exception(dc); break; -- cgit v1.1 From 762e22edcd021035e1dbcf0dbc31b4794c5c1027 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Wed, 18 Feb 2015 18:47:35 -0800 Subject: target/openrisc: Fix madd Note that the specification for lf.madd.s is confused. It's the only mention of supposed FPMADDHI/FPMADDLO special registers. On the other hand, or1ksim implements a somewhat normal non-fused multiply and add. Mirror that. Reviewed-by: Bastian Koppelmann Signed-off-by: Richard Henderson --- target/openrisc/cpu.h | 3 -- target/openrisc/fpu_helper.c | 68 ++++++++++++++++---------------------------- target/openrisc/helper.h | 7 ++--- target/openrisc/translate.c | 13 +++------ 4 files changed, 30 insertions(+), 61 deletions(-) (limited to 'target') diff --git a/target/openrisc/cpu.h b/target/openrisc/cpu.h index 9528277..0694038 100644 --- a/target/openrisc/cpu.h +++ b/target/openrisc/cpu.h @@ -279,9 +279,6 @@ typedef struct CPUOpenRISCState { uint64_t mac; /* Multiply registers MACHI:MACLO */ - target_ulong fpmaddhi; /* Multiply and add float register FPMADDHI */ - target_ulong fpmaddlo; /* Multiply and add float register FPMADDLO */ - target_ulong epcr; /* Exception PC register */ target_ulong eear; /* Exception EA register */ diff --git a/target/openrisc/fpu_helper.c b/target/openrisc/fpu_helper.c index c54404b..1375cea 100644 --- a/target/openrisc/fpu_helper.c +++ b/target/openrisc/fpu_helper.c @@ -146,52 +146,32 @@ FLOAT_CALC(div) FLOAT_CALC(rem) #undef FLOAT_CALC -#define FLOAT_TERNOP(name1, name2) \ -uint64_t helper_float_ ## name1 ## name2 ## _d(CPUOpenRISCState *env, \ - uint64_t fdt0, \ - uint64_t fdt1) \ -{ \ - uint64_t result, temp, hi, lo; \ - uint32_t val1, val2; \ - OpenRISCCPU *cpu = openrisc_env_get_cpu(env); \ - hi = env->fpmaddhi; \ - lo = env->fpmaddlo; \ - set_float_exception_flags(0, &cpu->env.fp_status); \ - result = float64_ ## name1(fdt0, fdt1, &cpu->env.fp_status); \ - lo &= 0xffffffff; \ - hi &= 0xffffffff; \ - temp = (hi << 32) | lo; \ - result = float64_ ## name2(result, temp, &cpu->env.fp_status); \ - val1 = result >> 32; \ - val2 = (uint32_t) (result & 0xffffffff); \ - update_fpcsr(cpu); \ - cpu->env.fpmaddlo = val2; \ - cpu->env.fpmaddhi = val1; \ - return 0; \ -} \ - \ -uint32_t helper_float_ ## name1 ## name2 ## _s(CPUOpenRISCState *env, \ - uint32_t fdt0, uint32_t fdt1) \ -{ \ - uint64_t result, temp, hi, lo; \ - uint32_t val1, val2; \ - OpenRISCCPU *cpu = openrisc_env_get_cpu(env); \ - hi = cpu->env.fpmaddhi; \ - lo = cpu->env.fpmaddlo; \ - set_float_exception_flags(0, &cpu->env.fp_status); \ - result = float64_ ## name1(fdt0, fdt1, &cpu->env.fp_status); \ - temp = (hi << 32) | lo; \ - result = float64_ ## name2(result, temp, &cpu->env.fp_status); \ - val1 = result >> 32; \ - val2 = (uint32_t) (result & 0xffffffff); \ - update_fpcsr(cpu); \ - cpu->env.fpmaddlo = val2; \ - cpu->env.fpmaddhi = val1; \ - return 0; \ + +uint64_t helper_float_madd_d(CPUOpenRISCState *env, uint64_t a, + uint64_t b, uint64_t c) +{ + OpenRISCCPU *cpu = openrisc_env_get_cpu(env); + uint64_t result; + set_float_exception_flags(0, &cpu->env.fp_status); + /* Note that or1ksim doesn't use merged operation. */ + result = float64_mul(b, c, &cpu->env.fp_status); + result = float64_add(result, a, &cpu->env.fp_status); + update_fpcsr(cpu); + return result; } -FLOAT_TERNOP(mul, add) -#undef FLOAT_TERNOP +uint32_t helper_float_madd_s(CPUOpenRISCState *env, uint32_t a, + uint32_t b, uint32_t c) +{ + OpenRISCCPU *cpu = openrisc_env_get_cpu(env); + uint32_t result; + set_float_exception_flags(0, &cpu->env.fp_status); + /* Note that or1ksim doesn't use merged operation. */ + result = float32_mul(b, c, &cpu->env.fp_status); + result = float32_add(result, a, &cpu->env.fp_status); + update_fpcsr(cpu); + return result; +} #define FLOAT_CMP(name) \ diff --git a/target/openrisc/helper.h b/target/openrisc/helper.h index 78a123d..4fd1a6b 100644 --- a/target/openrisc/helper.h +++ b/target/openrisc/helper.h @@ -29,11 +29,8 @@ DEF_HELPER_FLAGS_2(itofs, TCG_CALL_NO_WG, i32, env, i32) DEF_HELPER_FLAGS_2(ftoid, TCG_CALL_NO_WG, i64, env, i64) DEF_HELPER_FLAGS_2(ftois, TCG_CALL_NO_WG, i32, env, i32) -#define FOP_MADD(op) \ -DEF_HELPER_FLAGS_3(float_ ## op ## _s, TCG_CALL_NO_WG, i32, env, i32, i32) \ -DEF_HELPER_FLAGS_3(float_ ## op ## _d, TCG_CALL_NO_WG, i64, env, i64, i64) -FOP_MADD(muladd) -#undef FOP_MADD +DEF_HELPER_FLAGS_4(float_madd_s, TCG_CALL_NO_WG, i32, env, i32, i32, i32) +DEF_HELPER_FLAGS_4(float_madd_d, TCG_CALL_NO_WG, i64, env, i64, i64, i64) #define FOP_CALC(op) \ DEF_HELPER_FLAGS_3(float_ ## op ## _s, TCG_CALL_NO_WG, i32, env, i32, i32) \ diff --git a/target/openrisc/translate.c b/target/openrisc/translate.c index ce9672e..66064e1 100644 --- a/target/openrisc/translate.c +++ b/target/openrisc/translate.c @@ -61,7 +61,6 @@ static TCGv cpu_lock_addr; static TCGv cpu_lock_value; static TCGv_i32 fpcsr; static TCGv_i64 cpu_mac; /* MACHI:MACLO */ -static TCGv fpmaddhi, fpmaddlo; static TCGv_i32 env_flags; #include "exec/gen-icount.h" @@ -108,12 +107,6 @@ void openrisc_translate_init(void) cpu_mac = tcg_global_mem_new_i64(cpu_env, offsetof(CPUOpenRISCState, mac), "mac"); - fpmaddhi = tcg_global_mem_new(cpu_env, - offsetof(CPUOpenRISCState, fpmaddhi), - "fpmaddhi"); - fpmaddlo = tcg_global_mem_new(cpu_env, - offsetof(CPUOpenRISCState, fpmaddlo), - "fpmaddlo"); for (i = 0; i < 32; i++) { cpu_R[i] = tcg_global_mem_new(cpu_env, offsetof(CPUOpenRISCState, gpr[i]), @@ -1324,7 +1317,8 @@ static void dec_float(DisasContext *dc, uint32_t insn) case 0x07: /* lf.madd.s */ LOG_DIS("lf.madd.s r%d, r%d, r%d\n", rd, ra, rb); - gen_helper_float_muladd_s(cpu_R[rd], cpu_env, cpu_R[ra], cpu_R[rb]); + gen_helper_float_madd_s(cpu_R[rd], cpu_env, cpu_R[rd], + cpu_R[ra], cpu_R[rb]); break; case 0x08: /* lf.sfeq.s */ @@ -1409,7 +1403,8 @@ static void dec_float(DisasContext *dc, uint32_t insn) case 0x17: lf.madd.d LOG_DIS("lf.madd.d r%d, r%d, r%d\n", rd, ra, rb); check_of64s(dc); - gen_helper_float_muladd_d(cpu_R[rd], cpu_env, cpu_R[ra], cpu_R[rb]); + gen_helper_float_madd_d(cpu_R[rd], cpu_env, cpu_R[rd], + cpu_R[ra], cpu_R[rb]); break; case 0x18: lf.sfeq.d -- cgit v1.1 From a8000cb480c8cfb612b039bf0382c41b9d6c7d45 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Tue, 5 Apr 2016 11:50:16 -0700 Subject: target/openrisc: Optimize l.jal to next MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This allows the tcg optimizer to see, and fold, all of the constants involved in a GOT base register load sequence. Reviewed-by: Philippe Mathieu-Daudé Signed-off-by: Richard Henderson --- target/openrisc/translate.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'target') diff --git a/target/openrisc/translate.c b/target/openrisc/translate.c index 66064e1..cda84b6 100644 --- a/target/openrisc/translate.c +++ b/target/openrisc/translate.c @@ -198,7 +198,11 @@ static void gen_jump(DisasContext *dc, int32_t n26, uint32_t reg, uint32_t op0) tcg_gen_movi_tl(jmp_pc, tmp_pc); break; case 0x01: /* l.jal */ - tcg_gen_movi_tl(cpu_R[9], (dc->pc + 8)); + tcg_gen_movi_tl(cpu_R[9], dc->pc + 8); + /* Optimize jal being used to load the PC for PIC. */ + if (tmp_pc == dc->pc + 8) { + return; + } tcg_gen_movi_tl(jmp_pc, tmp_pc); break; case 0x03: /* l.bnf */ -- cgit v1.1 From 24c328521b19aff2559118809ddf0522d6dfaaea Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Tue, 5 Apr 2016 11:41:48 -0700 Subject: target/openrisc: Tidy ppc/npc implementation The NPC SPR is really only supposed to be used for FPGA debugging. It contains the same contents as PC, unless one plays games. Follow the or1ksim implementation in flushing delayed branch state when it is changed. The PPC SPR need not be updated every instruction, merely when we exit the TB or attempt to read its contents. Signed-off-by: Richard Henderson --- target/openrisc/cpu.h | 2 +- target/openrisc/gdbstub.c | 13 +++++++---- target/openrisc/interrupt_helper.c | 1 - target/openrisc/machine.c | 5 ++--- target/openrisc/sys_helper.c | 44 ++++++++++++++------------------------ target/openrisc/translate.c | 29 ++++++++++--------------- 6 files changed, 39 insertions(+), 55 deletions(-) (limited to 'target') diff --git a/target/openrisc/cpu.h b/target/openrisc/cpu.h index 0694038..8294636 100644 --- a/target/openrisc/cpu.h +++ b/target/openrisc/cpu.h @@ -58,6 +58,7 @@ typedef struct OpenRISCCPUClass { } OpenRISCCPUClass; #define NB_MMU_MODES 3 +#define TARGET_INSN_START_EXTRA_WORDS 1 enum { MMU_NOMMU_IDX = 0, @@ -273,7 +274,6 @@ typedef struct CPUOpenRISCTLBContext { typedef struct CPUOpenRISCState { target_ulong gpr[32]; /* General registers */ target_ulong pc; /* Program counter */ - target_ulong npc; /* Next PC */ target_ulong ppc; /* Prev PC */ target_ulong jmp_pc; /* Jump PC */ diff --git a/target/openrisc/gdbstub.c b/target/openrisc/gdbstub.c index 31ea013..2a4821f 100644 --- a/target/openrisc/gdbstub.c +++ b/target/openrisc/gdbstub.c @@ -34,8 +34,8 @@ int openrisc_cpu_gdb_read_register(CPUState *cs, uint8_t *mem_buf, int n) case 32: /* PPC */ return gdb_get_reg32(mem_buf, env->ppc); - case 33: /* NPC */ - return gdb_get_reg32(mem_buf, env->npc); + case 33: /* NPC (equals PC) */ + return gdb_get_reg32(mem_buf, env->pc); case 34: /* SR */ return gdb_get_reg32(mem_buf, cpu_get_sr(env)); @@ -68,8 +68,13 @@ int openrisc_cpu_gdb_write_register(CPUState *cs, uint8_t *mem_buf, int n) env->ppc = tmp; break; - case 33: /* NPC */ - env->npc = tmp; + case 33: /* NPC (equals PC) */ + /* If setting PC to something different, + also clear delayed branch status. */ + if (env->pc != tmp) { + env->pc = tmp; + env->flags = 0; + } break; case 34: /* SR */ diff --git a/target/openrisc/interrupt_helper.c b/target/openrisc/interrupt_helper.c index c7fa97a..56620e0 100644 --- a/target/openrisc/interrupt_helper.c +++ b/target/openrisc/interrupt_helper.c @@ -32,7 +32,6 @@ void HELPER(rfe)(CPUOpenRISCState *env) (cpu->env.esr & (SR_SM | SR_IME | SR_DME)); #endif cpu->env.pc = cpu->env.epcr; - cpu->env.npc = cpu->env.epcr; cpu_set_sr(&cpu->env, cpu->env.esr); cpu->env.lock_addr = -1; diff --git a/target/openrisc/machine.c b/target/openrisc/machine.c index 4100957..686eaa3 100644 --- a/target/openrisc/machine.c +++ b/target/openrisc/machine.c @@ -47,12 +47,11 @@ static const VMStateInfo vmstate_sr = { static const VMStateDescription vmstate_env = { .name = "env", - .version_id = 3, - .minimum_version_id = 3, + .version_id = 4, + .minimum_version_id = 4, .fields = (VMStateField[]) { VMSTATE_UINTTL_ARRAY(gpr, CPUOpenRISCState, 32), VMSTATE_UINTTL(pc, CPUOpenRISCState), - VMSTATE_UINTTL(npc, CPUOpenRISCState), VMSTATE_UINTTL(ppc, CPUOpenRISCState), VMSTATE_UINTTL(jmp_pc, CPUOpenRISCState), VMSTATE_UINTTL(lock_addr, CPUOpenRISCState), diff --git a/target/openrisc/sys_helper.c b/target/openrisc/sys_helper.c index 9841a5b..0968901 100644 --- a/target/openrisc/sys_helper.c +++ b/target/openrisc/sys_helper.c @@ -29,11 +29,10 @@ void HELPER(mtspr)(CPUOpenRISCState *env, target_ulong ra, target_ulong rb, target_ulong offset) { #ifndef CONFIG_USER_ONLY - int spr = (ra | offset); - int idx; - OpenRISCCPU *cpu = openrisc_env_get_cpu(env); CPUState *cs = CPU(cpu); + int spr = (ra | offset); + int idx; switch (spr) { case TO_SPR(0, 0): /* VR */ @@ -41,7 +40,14 @@ void HELPER(mtspr)(CPUOpenRISCState *env, break; case TO_SPR(0, 16): /* NPC */ - env->npc = rb; + cpu_restore_state(cs, GETPC()); + /* ??? Mirror or1ksim in not trashing delayed branch state + when "jumping" to the current instruction. */ + if (env->pc != rb) { + env->pc = rb; + env->flags = 0; + cpu_loop_exit(cs); + } break; case TO_SPR(0, 17): /* SR */ @@ -170,7 +176,6 @@ void HELPER(mtspr)(CPUOpenRISCState *env, cpu_openrisc_timer_update(cpu); break; default: - break; } #endif @@ -180,11 +185,11 @@ target_ulong HELPER(mfspr)(CPUOpenRISCState *env, target_ulong rd, target_ulong ra, uint32_t offset) { #ifndef CONFIG_USER_ONLY + OpenRISCCPU *cpu = openrisc_env_get_cpu(env); + CPUState *cs = CPU(cpu); int spr = (ra | offset); int idx; - OpenRISCCPU *cpu = openrisc_env_get_cpu(env); - switch (spr) { case TO_SPR(0, 0): /* VR */ return env->vr & SPR_VR; @@ -201,13 +206,15 @@ target_ulong HELPER(mfspr)(CPUOpenRISCState *env, case TO_SPR(0, 4): /* IMMUCFGR */ return env->immucfgr; - case TO_SPR(0, 16): /* NPC */ - return env->npc; + case TO_SPR(0, 16): /* NPC (equals PC) */ + cpu_restore_state(cs, GETPC()); + return env->pc; case TO_SPR(0, 17): /* SR */ return cpu_get_sr(env); case TO_SPR(0, 18): /* PPC */ + cpu_restore_state(cs, GETPC()); return env->ppc; case TO_SPR(0, 32): /* EPCR */ @@ -276,25 +283,6 @@ target_ulong HELPER(mfspr)(CPUOpenRISCState *env, } #endif -/*If we later need to add tracepoints (or debug printfs) for the return -value, it may be useful to structure the code like this: - -target_ulong ret = 0; - -switch() { -case x: - ret = y; - break; -case z: - ret = 42; - break; -... -} - -later something like trace_spr_read(ret); - -return ret;*/ - /* for rd is passed in, if rd unchanged, just keep it back. */ return rd; } diff --git a/target/openrisc/translate.c b/target/openrisc/translate.c index cda84b6..10f0633 100644 --- a/target/openrisc/translate.c +++ b/target/openrisc/translate.c @@ -39,7 +39,7 @@ typedef struct DisasContext { TranslationBlock *tb; - target_ulong pc, ppc, npc; + target_ulong pc; uint32_t tb_flags, synced_flags, flags; uint32_t is_jmp; uint32_t mem_idx; @@ -52,7 +52,6 @@ static TCGv cpu_sr; static TCGv cpu_R[32]; static TCGv cpu_pc; static TCGv jmp_pc; /* l.jr/l.jalr temp pc */ -static TCGv cpu_npc; static TCGv cpu_ppc; static TCGv cpu_sr_f; /* bf/bnf, F flag taken */ static TCGv cpu_sr_cy; /* carry (unsigned overflow) */ @@ -83,8 +82,6 @@ void openrisc_translate_init(void) "flags"); cpu_pc = tcg_global_mem_new(cpu_env, offsetof(CPUOpenRISCState, pc), "pc"); - cpu_npc = tcg_global_mem_new(cpu_env, - offsetof(CPUOpenRISCState, npc), "npc"); cpu_ppc = tcg_global_mem_new(cpu_env, offsetof(CPUOpenRISCState, ppc), "ppc"); jmp_pc = tcg_global_mem_new(cpu_env, @@ -1514,7 +1511,6 @@ void gen_intermediate_code(CPUOpenRISCState *env, struct TranslationBlock *tb) dc->tb = tb; dc->is_jmp = DISAS_NEXT; - dc->ppc = pc_start; dc->pc = pc_start; dc->flags = cpu->env.cpucfgr; dc->mem_idx = cpu_mmu_index(&cpu->env, false); @@ -1543,7 +1539,7 @@ void gen_intermediate_code(CPUOpenRISCState *env, struct TranslationBlock *tb) gen_tb_start(tb); do { - tcg_gen_insn_start(dc->pc); + tcg_gen_insn_start(dc->pc, num_insns != 0); num_insns++; if (unlikely(cpu_breakpoint_test(cs, dc->pc, BP_ANY))) { @@ -1561,12 +1557,9 @@ void gen_intermediate_code(CPUOpenRISCState *env, struct TranslationBlock *tb) if (num_insns == max_insns && (tb->cflags & CF_LAST_IO)) { gen_io_start(); } - dc->ppc = dc->pc - 4; - dc->npc = dc->pc + 4; - tcg_gen_movi_tl(cpu_ppc, dc->ppc); - tcg_gen_movi_tl(cpu_npc, dc->npc); disas_openrisc_insn(dc, cpu); - dc->pc = dc->npc; + dc->pc = dc->pc + 4; + /* delay slot */ if (dc->delayed_branch) { dc->delayed_branch--; @@ -1574,10 +1567,8 @@ void gen_intermediate_code(CPUOpenRISCState *env, struct TranslationBlock *tb) dc->tb_flags &= ~D_FLAG; gen_sync_flags(dc); tcg_gen_mov_tl(cpu_pc, jmp_pc); - tcg_gen_mov_tl(cpu_npc, jmp_pc); - tcg_gen_movi_tl(jmp_pc, 0); - tcg_gen_exit_tb(0); - dc->is_jmp = DISAS_JUMP; + tcg_gen_discard_tl(jmp_pc); + dc->is_jmp = DISAS_UPDATE; break; } } @@ -1591,14 +1582,13 @@ void gen_intermediate_code(CPUOpenRISCState *env, struct TranslationBlock *tb) if (tb->cflags & CF_LAST_IO) { gen_io_end(); } + + tcg_gen_movi_tl(cpu_ppc, dc->pc - 4); if (dc->is_jmp == DISAS_NEXT) { dc->is_jmp = DISAS_UPDATE; tcg_gen_movi_tl(cpu_pc, dc->pc); } if (unlikely(cs->singlestep_enabled)) { - if (dc->is_jmp == DISAS_NEXT) { - tcg_gen_movi_tl(cpu_pc, dc->pc); - } gen_exception(dc, EXCP_DEBUG); } else { switch (dc->is_jmp) { @@ -1651,4 +1641,7 @@ void restore_state_to_opc(CPUOpenRISCState *env, TranslationBlock *tb, target_ulong *data) { env->pc = data[0]; + if (data[1]) { + env->ppc = env->pc - 4; + } } -- cgit v1.1 From a01deb36a685365b4a3117112da3cc4f0f79e955 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Tue, 5 Apr 2016 18:00:33 -0700 Subject: target/openrisc: Tidy handling of delayed branches Signed-off-by: Richard Henderson --- target/openrisc/cpu.h | 12 +++++------- target/openrisc/gdbstub.c | 2 +- target/openrisc/interrupt.c | 4 ++-- target/openrisc/sys_helper.c | 2 +- target/openrisc/translate.c | 40 ++++++++++++++++------------------------ 5 files changed, 25 insertions(+), 35 deletions(-) (limited to 'target') diff --git a/target/openrisc/cpu.h b/target/openrisc/cpu.h index 8294636..50a36ba 100644 --- a/target/openrisc/cpu.h +++ b/target/openrisc/cpu.h @@ -83,9 +83,6 @@ enum { /* Version Register */ #define SPR_VR 0xFFFF003F -/* Internal flags, delay slot flag */ -#define D_FLAG 1 - /* Interrupt */ #define NR_IRQS 32 @@ -298,8 +295,7 @@ typedef struct CPUOpenRISCState { target_ulong lock_addr; target_ulong lock_value; - uint32_t flags; /* cpu_flags, we only use it for exception - in solt so far. */ + uint32_t dflag; /* In delay slot (boolean) */ /* Fields up to this point are cleared by a CPU reset */ struct {} end_reset_fields; @@ -392,14 +388,16 @@ int cpu_openrisc_get_phys_data(OpenRISCCPU *cpu, #include "exec/cpu-all.h" +#define TB_FLAGS_DFLAG 1 +#define TB_FLAGS_OVE SR_OVE + static inline void cpu_get_tb_cpu_state(CPUOpenRISCState *env, target_ulong *pc, target_ulong *cs_base, uint32_t *flags) { *pc = env->pc; *cs_base = 0; - /* D_FLAG -- branch instruction exception, OVE overflow trap enable. */ - *flags = (env->flags & D_FLAG) | (env->sr & SR_OVE); + *flags = env->dflag | (env->sr & SR_OVE); } static inline int cpu_mmu_index(CPUOpenRISCState *env, bool ifetch) diff --git a/target/openrisc/gdbstub.c b/target/openrisc/gdbstub.c index 2a4821f..b18c7e9 100644 --- a/target/openrisc/gdbstub.c +++ b/target/openrisc/gdbstub.c @@ -73,7 +73,7 @@ int openrisc_cpu_gdb_write_register(CPUState *cs, uint8_t *mem_buf, int n) also clear delayed branch status. */ if (env->pc != tmp) { env->pc = tmp; - env->flags = 0; + env->dflag = 0; } break; diff --git a/target/openrisc/interrupt.c b/target/openrisc/interrupt.c index 042506f..a2eec6f 100644 --- a/target/openrisc/interrupt.c +++ b/target/openrisc/interrupt.c @@ -34,8 +34,8 @@ void openrisc_cpu_do_interrupt(CPUState *cs) CPUOpenRISCState *env = &cpu->env; env->epcr = env->pc; - if (env->flags & D_FLAG) { - env->flags &= ~D_FLAG; + if (env->dflag) { + env->dflag = 0; env->sr |= SR_DSX; env->epcr -= 4; } else { diff --git a/target/openrisc/sys_helper.c b/target/openrisc/sys_helper.c index 0968901..60c3193 100644 --- a/target/openrisc/sys_helper.c +++ b/target/openrisc/sys_helper.c @@ -45,7 +45,7 @@ void HELPER(mtspr)(CPUOpenRISCState *env, when "jumping" to the current instruction. */ if (env->pc != rb) { env->pc = rb; - env->flags = 0; + env->dflag = 0; cpu_loop_exit(cs); } break; diff --git a/target/openrisc/translate.c b/target/openrisc/translate.c index 10f0633..313dae2 100644 --- a/target/openrisc/translate.c +++ b/target/openrisc/translate.c @@ -40,11 +40,11 @@ typedef struct DisasContext { TranslationBlock *tb; target_ulong pc; - uint32_t tb_flags, synced_flags, flags; uint32_t is_jmp; uint32_t mem_idx; - int singlestep_enabled; + uint32_t tb_flags; uint32_t delayed_branch; + bool singlestep_enabled; } DisasContext; static TCGv_env cpu_env; @@ -60,7 +60,7 @@ static TCGv cpu_lock_addr; static TCGv cpu_lock_value; static TCGv_i32 fpcsr; static TCGv_i64 cpu_mac; /* MACHI:MACLO */ -static TCGv_i32 env_flags; +static TCGv_i32 cpu_dflag; #include "exec/gen-icount.h" void openrisc_translate_init(void) @@ -77,9 +77,9 @@ void openrisc_translate_init(void) tcg_ctx.tcg_env = cpu_env; cpu_sr = tcg_global_mem_new(cpu_env, offsetof(CPUOpenRISCState, sr), "sr"); - env_flags = tcg_global_mem_new_i32(cpu_env, - offsetof(CPUOpenRISCState, flags), - "flags"); + cpu_dflag = tcg_global_mem_new_i32(cpu_env, + offsetof(CPUOpenRISCState, dflag), + "dflag"); cpu_pc = tcg_global_mem_new(cpu_env, offsetof(CPUOpenRISCState, pc), "pc"); cpu_ppc = tcg_global_mem_new(cpu_env, @@ -111,15 +111,6 @@ void openrisc_translate_init(void) } } -static inline void gen_sync_flags(DisasContext *dc) -{ - /* Sync the tb dependent flag between translate and runtime. */ - if ((dc->tb_flags ^ dc->synced_flags) & D_FLAG) { - tcg_gen_movi_tl(env_flags, dc->tb_flags & D_FLAG); - dc->synced_flags = dc->tb_flags; - } -} - static void gen_exception(DisasContext *dc, unsigned int excp) { TCGv_i32 tmp = tcg_const_i32(excp); @@ -230,8 +221,6 @@ static void gen_jump(DisasContext *dc, int32_t n26, uint32_t reg, uint32_t op0) } dc->delayed_branch = 2; - dc->tb_flags |= D_FLAG; - gen_sync_flags(dc); } static void gen_ove_cy(DisasContext *dc) @@ -1512,10 +1501,9 @@ void gen_intermediate_code(CPUOpenRISCState *env, struct TranslationBlock *tb) dc->is_jmp = DISAS_NEXT; dc->pc = pc_start; - dc->flags = cpu->env.cpucfgr; dc->mem_idx = cpu_mmu_index(&cpu->env, false); - dc->synced_flags = dc->tb_flags = tb->flags; - dc->delayed_branch = (dc->tb_flags & D_FLAG) != 0; + dc->tb_flags = tb->flags; + dc->delayed_branch = (dc->tb_flags & TB_FLAGS_DFLAG) != 0; dc->singlestep_enabled = cs->singlestep_enabled; next_page_start = (pc_start & TARGET_PAGE_MASK) + TARGET_PAGE_SIZE; @@ -1539,7 +1527,8 @@ void gen_intermediate_code(CPUOpenRISCState *env, struct TranslationBlock *tb) gen_tb_start(tb); do { - tcg_gen_insn_start(dc->pc, num_insns != 0); + tcg_gen_insn_start(dc->pc, (dc->delayed_branch ? 1 : 0) + | (num_insns ? 2 : 0)); num_insns++; if (unlikely(cpu_breakpoint_test(cs, dc->pc, BP_ANY))) { @@ -1564,8 +1553,6 @@ void gen_intermediate_code(CPUOpenRISCState *env, struct TranslationBlock *tb) if (dc->delayed_branch) { dc->delayed_branch--; if (!dc->delayed_branch) { - dc->tb_flags &= ~D_FLAG; - gen_sync_flags(dc); tcg_gen_mov_tl(cpu_pc, jmp_pc); tcg_gen_discard_tl(jmp_pc); dc->is_jmp = DISAS_UPDATE; @@ -1583,6 +1570,10 @@ void gen_intermediate_code(CPUOpenRISCState *env, struct TranslationBlock *tb) gen_io_end(); } + if ((dc->tb_flags & TB_FLAGS_DFLAG ? 1 : 0) != (dc->delayed_branch != 0)) { + tcg_gen_movi_i32(cpu_dflag, dc->delayed_branch != 0); + } + tcg_gen_movi_tl(cpu_ppc, dc->pc - 4); if (dc->is_jmp == DISAS_NEXT) { dc->is_jmp = DISAS_UPDATE; @@ -1641,7 +1632,8 @@ void restore_state_to_opc(CPUOpenRISCState *env, TranslationBlock *tb, target_ulong *data) { env->pc = data[0]; - if (data[1]) { + env->dflag = data[1] & 1; + if (data[1] & 2) { env->ppc = env->pc - 4; } } -- cgit v1.1 From 6597c28d618a3d16d468770b7c30a0237a8c8ea9 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Tue, 5 Apr 2016 19:43:40 -0700 Subject: target/openrisc: Optimize for r0 being zero The HW does not special-case r0, but the ABI specifies that r0 should contain 0. If we expose this fact to the optimizer, we can simplify a lot of the generated code. We must of course verify that r0==0, but that is trivial to do with a TB flag. Signed-off-by: Richard Henderson --- target/openrisc/cpu.h | 5 ++- target/openrisc/exception_helper.c | 1 + target/openrisc/translate.c | 83 ++++++++++++++++++++++++++++---------- 3 files changed, 66 insertions(+), 23 deletions(-) (limited to 'target') diff --git a/target/openrisc/cpu.h b/target/openrisc/cpu.h index 50a36ba..418a0e6 100644 --- a/target/openrisc/cpu.h +++ b/target/openrisc/cpu.h @@ -389,6 +389,7 @@ int cpu_openrisc_get_phys_data(OpenRISCCPU *cpu, #include "exec/cpu-all.h" #define TB_FLAGS_DFLAG 1 +#define TB_FLAGS_R0_0 2 #define TB_FLAGS_OVE SR_OVE static inline void cpu_get_tb_cpu_state(CPUOpenRISCState *env, @@ -397,7 +398,9 @@ static inline void cpu_get_tb_cpu_state(CPUOpenRISCState *env, { *pc = env->pc; *cs_base = 0; - *flags = env->dflag | (env->sr & SR_OVE); + *flags = (env->dflag + | (env->gpr[0] == 0 ? TB_FLAGS_R0_0 : 0) + | (env->sr & SR_OVE)); } static inline int cpu_mmu_index(CPUOpenRISCState *env, bool ifetch) diff --git a/target/openrisc/exception_helper.c b/target/openrisc/exception_helper.c index 1536053..a8a5f69 100644 --- a/target/openrisc/exception_helper.c +++ b/target/openrisc/exception_helper.c @@ -19,6 +19,7 @@ #include "qemu/osdep.h" #include "cpu.h" +#include "exec/exec-all.h" #include "exec/helper-proto.h" #include "exec/exec-all.h" #include "exception.h" diff --git a/target/openrisc/translate.c b/target/openrisc/translate.c index 313dae2..7c4cbf2 100644 --- a/target/openrisc/translate.c +++ b/target/openrisc/translate.c @@ -50,6 +50,7 @@ typedef struct DisasContext { static TCGv_env cpu_env; static TCGv cpu_sr; static TCGv cpu_R[32]; +static TCGv cpu_R0; static TCGv cpu_pc; static TCGv jmp_pc; /* l.jr/l.jalr temp pc */ static TCGv cpu_ppc; @@ -109,6 +110,7 @@ void openrisc_translate_init(void) offsetof(CPUOpenRISCState, gpr[i]), regnames[i]); } + cpu_R0 = cpu_R[0]; } static void gen_exception(DisasContext *dc, unsigned int excp) @@ -149,6 +151,15 @@ static void check_ov64s(DisasContext *dc) } #endif*/ +/* We're about to write to REG. On the off-chance that the user is + writing to R0, re-instate the architectural register. */ +#define check_r0_write(reg) \ + do { \ + if (unlikely(reg == 0)) { \ + cpu_R[0] = cpu_R0; \ + } \ + } while (0) + static inline bool use_goto_tb(DisasContext *dc, target_ulong dest) { if (unlikely(dc->singlestep_enabled)) { @@ -496,7 +507,7 @@ static void gen_lwa(DisasContext *dc, TCGv rd, TCGv ra, int32_t ofs) tcg_temp_free(ea); } -static void gen_swa(DisasContext *dc, TCGv rb, TCGv ra, int32_t ofs) +static void gen_swa(DisasContext *dc, int b, TCGv ra, int32_t ofs) { TCGv ea, val; TCGLabel *lab_fail, *lab_done; @@ -504,6 +515,12 @@ static void gen_swa(DisasContext *dc, TCGv rb, TCGv ra, int32_t ofs) ea = tcg_temp_new(); tcg_gen_addi_tl(ea, ra, ofs); + /* For TB_FLAGS_R0_0, the branch below invalidates the temporary assigned + to cpu_R[0]. Since l.swa is quite often immediately followed by a + branch, don't bother reallocating; finish the TB using the "real" R0. + This also takes care of RB input across the branch. */ + cpu_R[0] = cpu_R0; + lab_fail = gen_new_label(); lab_done = gen_new_label(); tcg_gen_brcond_tl(TCG_COND_NE, ea, cpu_lock_addr, lab_fail); @@ -511,7 +528,7 @@ static void gen_swa(DisasContext *dc, TCGv rb, TCGv ra, int32_t ofs) val = tcg_temp_new(); tcg_gen_atomic_cmpxchg_tl(val, cpu_lock_addr, cpu_lock_value, - rb, dc->mem_idx, MO_TEUL); + cpu_R[b], dc->mem_idx, MO_TEUL); tcg_gen_setcond_tl(TCG_COND_EQ, cpu_sr_f, val, cpu_lock_value); tcg_temp_free(val); @@ -781,6 +798,7 @@ static void dec_misc(DisasContext *dc, uint32_t insn) case 0x1b: /* l.lwa */ LOG_DIS("l.lwa r%d, r%d, %d\n", rd, ra, I16); + check_r0_write(rd); gen_lwa(dc, cpu_R[rd], cpu_R[ra], I16); break; @@ -856,16 +874,16 @@ static void dec_misc(DisasContext *dc, uint32_t insn) goto do_load; do_load: - { - TCGv t0 = tcg_temp_new(); - tcg_gen_addi_tl(t0, cpu_R[ra], I16); - tcg_gen_qemu_ld_tl(cpu_R[rd], t0, dc->mem_idx, mop); - tcg_temp_free(t0); - } + check_r0_write(rd); + t0 = tcg_temp_new(); + tcg_gen_addi_tl(t0, cpu_R[ra], I16); + tcg_gen_qemu_ld_tl(cpu_R[rd], t0, dc->mem_idx, mop); + tcg_temp_free(t0); break; case 0x27: /* l.addi */ LOG_DIS("l.addi r%d, r%d, %d\n", rd, ra, I16); + check_r0_write(rd); t0 = tcg_const_tl(I16); gen_add(dc, cpu_R[rd], cpu_R[ra], t0); tcg_temp_free(t0); @@ -873,6 +891,7 @@ static void dec_misc(DisasContext *dc, uint32_t insn) case 0x28: /* l.addic */ LOG_DIS("l.addic r%d, r%d, %d\n", rd, ra, I16); + check_r0_write(rd); t0 = tcg_const_tl(I16); gen_addc(dc, cpu_R[rd], cpu_R[ra], t0); tcg_temp_free(t0); @@ -880,21 +899,25 @@ static void dec_misc(DisasContext *dc, uint32_t insn) case 0x29: /* l.andi */ LOG_DIS("l.andi r%d, r%d, %d\n", rd, ra, K16); + check_r0_write(rd); tcg_gen_andi_tl(cpu_R[rd], cpu_R[ra], K16); break; case 0x2a: /* l.ori */ LOG_DIS("l.ori r%d, r%d, %d\n", rd, ra, K16); + check_r0_write(rd); tcg_gen_ori_tl(cpu_R[rd], cpu_R[ra], K16); break; case 0x2b: /* l.xori */ LOG_DIS("l.xori r%d, r%d, %d\n", rd, ra, I16); + check_r0_write(rd); tcg_gen_xori_tl(cpu_R[rd], cpu_R[ra], I16); break; case 0x2c: /* l.muli */ LOG_DIS("l.muli r%d, r%d, %d\n", rd, ra, I16); + check_r0_write(rd); t0 = tcg_const_tl(I16); gen_mul(dc, cpu_R[rd], cpu_R[ra], t0); tcg_temp_free(t0); @@ -902,6 +925,7 @@ static void dec_misc(DisasContext *dc, uint32_t insn) case 0x2d: /* l.mfspr */ LOG_DIS("l.mfspr r%d, r%d, %d\n", rd, ra, K16); + check_r0_write(rd); { #if defined(CONFIG_USER_ONLY) return; @@ -936,7 +960,7 @@ static void dec_misc(DisasContext *dc, uint32_t insn) case 0x33: /* l.swa */ LOG_DIS("l.swa r%d, r%d, %d\n", ra, rb, I5_11); - gen_swa(dc, cpu_R[rb], cpu_R[ra], I5_11); + gen_swa(dc, rb, cpu_R[ra], I5_11); break; /* not used yet, open it when we need or64. */ @@ -1023,6 +1047,7 @@ static void dec_logic(DisasContext *dc, uint32_t insn) L6 = extract32(insn, 0, 6); S6 = L6 & (TARGET_LONG_BITS - 1); + check_r0_write(rd); switch (op0) { case 0x00: /* l.slli */ LOG_DIS("l.slli r%d, r%d, %d\n", rd, ra, L6); @@ -1059,6 +1084,7 @@ static void dec_M(DisasContext *dc, uint32_t insn) rd = extract32(insn, 21, 5); K16 = extract32(insn, 0, 16); + check_r0_write(rd); switch (op0) { case 0x0: /* l.movhi */ LOG_DIS("l.movhi r%d, %d\n", rd, K16); @@ -1266,47 +1292,49 @@ static void dec_float(DisasContext *dc, uint32_t insn) switch (op0) { case 0x00: /* lf.add.s */ LOG_DIS("lf.add.s r%d, r%d, r%d\n", rd, ra, rb); + check_r0_write(rd); gen_helper_float_add_s(cpu_R[rd], cpu_env, cpu_R[ra], cpu_R[rb]); break; case 0x01: /* lf.sub.s */ LOG_DIS("lf.sub.s r%d, r%d, r%d\n", rd, ra, rb); + check_r0_write(rd); gen_helper_float_sub_s(cpu_R[rd], cpu_env, cpu_R[ra], cpu_R[rb]); break; - case 0x02: /* lf.mul.s */ LOG_DIS("lf.mul.s r%d, r%d, r%d\n", rd, ra, rb); - if (ra != 0 && rb != 0) { - gen_helper_float_mul_s(cpu_R[rd], cpu_env, cpu_R[ra], cpu_R[rb]); - } else { - tcg_gen_ori_tl(fpcsr, fpcsr, FPCSR_ZF); - tcg_gen_movi_i32(cpu_R[rd], 0x0); - } + check_r0_write(rd); + gen_helper_float_mul_s(cpu_R[rd], cpu_env, cpu_R[ra], cpu_R[rb]); break; case 0x03: /* lf.div.s */ LOG_DIS("lf.div.s r%d, r%d, r%d\n", rd, ra, rb); + check_r0_write(rd); gen_helper_float_div_s(cpu_R[rd], cpu_env, cpu_R[ra], cpu_R[rb]); break; case 0x04: /* lf.itof.s */ LOG_DIS("lf.itof r%d, r%d\n", rd, ra); + check_r0_write(rd); gen_helper_itofs(cpu_R[rd], cpu_env, cpu_R[ra]); break; case 0x05: /* lf.ftoi.s */ LOG_DIS("lf.ftoi r%d, r%d\n", rd, ra); + check_r0_write(rd); gen_helper_ftois(cpu_R[rd], cpu_env, cpu_R[ra]); break; case 0x06: /* lf.rem.s */ LOG_DIS("lf.rem.s r%d, r%d, r%d\n", rd, ra, rb); + check_r0_write(rd); gen_helper_float_rem_s(cpu_R[rd], cpu_env, cpu_R[ra], cpu_R[rb]); break; case 0x07: /* lf.madd.s */ LOG_DIS("lf.madd.s r%d, r%d, r%d\n", rd, ra, rb); + check_r0_write(rd); gen_helper_float_madd_s(cpu_R[rd], cpu_env, cpu_R[rd], cpu_R[ra], cpu_R[rb]); break; @@ -1346,53 +1374,56 @@ static void dec_float(DisasContext *dc, uint32_t insn) case 0x10: lf.add.d LOG_DIS("lf.add.d r%d, r%d, r%d\n", rd, ra, rb); check_of64s(dc); + check_r0_write(rd); gen_helper_float_add_d(cpu_R[rd], cpu_env, cpu_R[ra], cpu_R[rb]); break; case 0x11: lf.sub.d LOG_DIS("lf.sub.d r%d, r%d, r%d\n", rd, ra, rb); check_of64s(dc); + check_r0_write(rd); gen_helper_float_sub_d(cpu_R[rd], cpu_env, cpu_R[ra], cpu_R[rb]); break; case 0x12: lf.mul.d LOG_DIS("lf.mul.d r%d, r%d, r%d\n", rd, ra, rb); check_of64s(dc); - if (ra != 0 && rb != 0) { - gen_helper_float_mul_d(cpu_R[rd], cpu_env, cpu_R[ra], cpu_R[rb]); - } else { - tcg_gen_ori_tl(fpcsr, fpcsr, FPCSR_ZF); - tcg_gen_movi_i64(cpu_R[rd], 0x0); - } + check_r0_write(rd); + gen_helper_float_mul_d(cpu_R[rd], cpu_env, cpu_R[ra], cpu_R[rb]); break; case 0x13: lf.div.d LOG_DIS("lf.div.d r%d, r%d, r%d\n", rd, ra, rb); check_of64s(dc); + check_r0_write(rd); gen_helper_float_div_d(cpu_R[rd], cpu_env, cpu_R[ra], cpu_R[rb]); break; case 0x14: lf.itof.d LOG_DIS("lf.itof r%d, r%d\n", rd, ra); check_of64s(dc); + check_r0_write(rd); gen_helper_itofd(cpu_R[rd], cpu_env, cpu_R[ra]); break; case 0x15: lf.ftoi.d LOG_DIS("lf.ftoi r%d, r%d\n", rd, ra); check_of64s(dc); + check_r0_write(rd); gen_helper_ftoid(cpu_R[rd], cpu_env, cpu_R[ra]); break; case 0x16: lf.rem.d LOG_DIS("lf.rem.d r%d, r%d, r%d\n", rd, ra, rb); check_of64s(dc); + check_r0_write(rd); gen_helper_float_rem_d(cpu_R[rd], cpu_env, cpu_R[ra], cpu_R[rb]); break; case 0x17: lf.madd.d LOG_DIS("lf.madd.d r%d, r%d, r%d\n", rd, ra, rb); check_of64s(dc); + check_r0_write(rd); gen_helper_float_madd_d(cpu_R[rd], cpu_env, cpu_R[rd], cpu_R[ra], cpu_R[rb]); break; @@ -1526,6 +1557,14 @@ void gen_intermediate_code(CPUOpenRISCState *env, struct TranslationBlock *tb) gen_tb_start(tb); + /* Allow the TCG optimizer to see that R0 == 0, + when it's true, which is the common case. */ + if (dc->tb_flags & TB_FLAGS_R0_0) { + cpu_R[0] = tcg_const_tl(0); + } else { + cpu_R[0] = cpu_R0; + } + do { tcg_gen_insn_start(dc->pc, (dc->delayed_branch ? 1 : 0) | (num_insns ? 2 : 0)); -- cgit v1.1