Message ID | 1339396324-21368-9-git-send-email-proljc@gmail.com |
---|---|
State | New |
Headers | show |
On Mon, Jun 11, 2012 at 6:31 AM, Jia Liu <proljc@gmail.com> wrote: > Add OpenRISC translation routines. > > Signed-off-by: Jia Liu <proljc@gmail.com> > --- > target-openrisc/translate.c | 1523 +++++++++++++++++++++++++++++++++++++++++++ > 1 file changed, 1523 insertions(+) > > diff --git a/target-openrisc/translate.c b/target-openrisc/translate.c > index 1d87d76..ec004be 100644 > --- a/target-openrisc/translate.c > +++ b/target-openrisc/translate.c > @@ -26,6 +26,10 @@ > #include "qemu-log.h" > #include "config.h" > > +#include "helper.h" > +#define GEN_HELPER 1 > +#include "helper.h" > + > #define OPENRISC_DISAS > > #ifdef OPENRISC_DISAS > @@ -34,14 +38,1533 @@ > # define LOG_DIS(...) do { } while (0) > #endif > > +typedef struct DisasContext { > + CPUOpenRISCState *env; > + TranslationBlock *tb; > + target_ulong pc, ppc, npc; > + uint32_t tb_flags, synced_flags, flags; > + uint32_t is_jmp; > + uint32_t mem_idx; > + int singlestep_enabled; > + uint32_t delayed_branch; > +} DisasContext; > + > +static TCGv_ptr cpu_env; > +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_i32 env_btaken; /* bf/bnf , F flag taken */ > +static TCGv_i32 fpcsr; > +static TCGv machi, maclo; > +static TCGv fpmaddhi, fpmaddlo; > +static TCGv_i32 env_flags; > +#include "gen-icount.h" > + > void openrisc_translate_init(void) > { > + static const char * const regnames[] = { > + "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", > + "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", > + "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23", > + "r24", "r25", "r26", "r27", "r28", "r29", "r30", "r31", > + }; > + int i; > + > + cpu_env = tcg_global_reg_new_ptr(TCG_AREG0, "env"); > + cpu_sr = tcg_global_mem_new(TCG_AREG0, > + offsetof(CPUOpenRISCState, sr), "sr"); > + env_flags = tcg_global_mem_new_i32(TCG_AREG0, > + offsetof(CPUOpenRISCState, flags), > + "flags"); > + cpu_pc = tcg_global_mem_new(TCG_AREG0, > + offsetof(CPUOpenRISCState, pc), "pc"); > + cpu_npc = tcg_global_mem_new(TCG_AREG0, > + offsetof(CPUOpenRISCState, npc), "npc"); > + cpu_ppc = tcg_global_mem_new(TCG_AREG0, > + offsetof(CPUOpenRISCState, ppc), "ppc"); > + jmp_pc = tcg_global_mem_new(TCG_AREG0, > + offsetof(CPUOpenRISCState, jmp_pc), "jmp_pc"); > + env_btaken = tcg_global_mem_new_i32(TCG_AREG0, > + offsetof(CPUOpenRISCState, btaken), > + "btaken"); > + fpcsr = tcg_global_mem_new_i32(TCG_AREG0, > + offsetof(CPUOpenRISCState, fpcsr), > + "fpcsr"); > + machi = tcg_global_mem_new(TCG_AREG0, > + offsetof(CPUOpenRISCState, machi), > + "machi"); > + maclo = tcg_global_mem_new(TCG_AREG0, > + offsetof(CPUOpenRISCState, maclo), > + "maclo"); > + fpmaddhi = tcg_global_mem_new(TCG_AREG0, > + offsetof(CPUOpenRISCState, fpmaddhi), > + "fpmaddhi"); > + fpmaddlo = tcg_global_mem_new(TCG_AREG0, > + offsetof(CPUOpenRISCState, fpmaddlo), > + "fpmaddlo"); > + for (i = 0; i < 32; i++) { > + cpu_R[i] = tcg_global_mem_new(TCG_AREG0, > + offsetof(CPUOpenRISCState, gpr[i]), > + regnames[i]); > + } > +#define GEN_HELPER 2 > +#include "helper.h" > +} > + > +/* Writeback SR_F transaltion-space to execution-space. */ > +static inline void wb_SR_F(void) > +{ > + int label; > + > + 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 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. */ > + if (dc->tb_flags != dc->synced_flags) { > + tcg_gen_movi_tl(env_flags, dc->tb_flags); > + dc->synced_flags = dc->tb_flags; > + } > +} > + > +static void gen_exception(DisasContext *dc, unsigned int excp) > +{ > + TCGv_i32 tmp = tcg_const_i32(excp); > + gen_helper_exception(cpu_env, tmp); > + tcg_temp_free(tmp); > +} > + > +static void gen_illegal_exception(DisasContext *dc) > +{ > + tcg_gen_movi_tl(cpu_pc, dc->pc); > + gen_exception(dc, EXCP_ILLEGAL); > + dc->is_jmp = DISAS_UPDATE; > +} > + > +static void check_ob64s(DisasContext *dc) > +{ > + if (!(dc->flags & CPUCFGR_OB64S)) { > + gen_illegal_exception(dc); > + } > +} > + > +static void check_of64s(DisasContext *dc) > +{ > + if (!(dc->flags & CPUCFGR_OF64S)) { > + gen_illegal_exception(dc); > + } > +} > + > +/* not used yet, open it when we need or64. */ > +/*static void check_ov64s(DisasContext *dc) > +{ > + if (!(dc->flags & CPUCFGR_OV64S)) { > + gen_illegal_exception(dc); > + } > +}*/ > + > +static void gen_goto_tb(DisasContext *dc, int n, target_ulong dest) > +{ > + TranslationBlock *tb; > + tb = dc->tb; > + if ((tb->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK) && > + likely(!dc->singlestep_enabled)) { > + tcg_gen_movi_tl(cpu_pc, dest); > + tcg_gen_goto_tb(n); > + tcg_gen_exit_tb((tcg_target_long)tb + n); > + } else { > + tcg_gen_movi_tl(cpu_pc, dest); > + if (dc->singlestep_enabled) { > + gen_exception(dc, EXCP_DEBUG); > + } > + tcg_gen_exit_tb(0); > + } > +} > + > +static void gen_jump(DisasContext *dc, uint32_t imm, uint32_t reg, uint32_t op0) > +{ > + target_ulong tmp_pc; > + int lab = gen_new_label(); > + TCGv sr_f = tcg_temp_new(); > + /* N26, 26bits imm */ > + tmp_pc = sign_extend((imm<<2), 26) + dc->pc; > + tcg_gen_andi_tl(sr_f, cpu_sr, SR_F); > + > + if (op0 == 0x00) { /*l.j*/ > + tcg_gen_movi_tl(jmp_pc, tmp_pc); > + } else if (op0 == 0x01) { /*l.jal*/ > + tcg_gen_movi_tl(cpu_R[9], (dc->pc + 8)); > + tcg_gen_movi_tl(jmp_pc, tmp_pc); > + } else if (op0 == 0x03) { /*l.bnf*/ > + tcg_gen_movi_tl(jmp_pc, dc->pc+8); > + tcg_gen_brcondi_i32(TCG_COND_EQ, sr_f, SR_F, lab); > + tcg_gen_movi_tl(jmp_pc, tmp_pc); > + gen_set_label(lab); > + } else if (op0 == 0x04) { /*l.bf*/ > + tcg_gen_movi_tl(jmp_pc, dc->pc+8); > + tcg_gen_brcondi_i32(TCG_COND_NE, sr_f, SR_F, lab); > + tcg_gen_movi_tl(jmp_pc, tmp_pc); > + gen_set_label(lab); > + } else if (op0 == 0x11) { /*l.jr*/ > + tcg_gen_mov_tl(jmp_pc, cpu_R[reg]); > + } else if (op0 == 0x12) { /*l.jalr*/ > + tcg_gen_movi_tl(cpu_R[9], (dc->pc + 8)); > + tcg_gen_mov_tl(jmp_pc, cpu_R[reg]); > + } else { > + gen_illegal_exception(dc); > + } > + > + tcg_temp_free(sr_f); > + dc->delayed_branch = 2; > + dc->tb_flags |= D_FLAG; > + gen_sync_flags(dc); > +} > + > +static inline uint32_t field(uint32_t val, int start, int length) > +{ > + val >>= start; > + val &= ~(~0 << length); > + return val; > +} > + > +static void dec_calc(DisasContext *dc, CPUOpenRISCState *env, uint32_t insn) > +{ > + uint32_t op0, op1, op2; > + uint32_t ra, rb, rd; > + op0 = field(insn, 0, 4); > + op1 = field(insn, 8, 2); > + op2 = field(insn, 6, 2); > + ra = field(insn, 16, 5); > + rb = field(insn, 11, 5); > + rd = field(insn, 21, 5); > + > + switch (op0) { > + case 0x0000: > + switch (op1) { > + case 0x00: /*l.add*/ > + LOG_DIS("l.add r%d, r%d, r%d\n", rd, ra, rb); > + gen_helper_add(cpu_R[rd], cpu_env, cpu_R[ra], cpu_R[rb]); > + break; > + default: > + gen_illegal_exception(dc); > + break; > + } > + break; > + > + case 0x0001: /*l.addc*/ > + switch (op1) { > + case 0x00: > + LOG_DIS("l.addc r%d, r%d, r%d\n", rd, ra, rb); > + gen_helper_addc(cpu_R[rd], cpu_env, cpu_R[ra], cpu_R[rb]); > + break; > + default: > + gen_illegal_exception(dc); > + break; > + } > + break; > + > + case 0x0002: /*l.sub*/ > + switch (op1) { > + case 0x00: > + LOG_DIS("l.sub r%d, r%d, r%d\n", rd, ra, rb); > + gen_helper_sub(cpu_R[rd], cpu_env, cpu_R[ra], cpu_R[rb]); > + break; > + default: > + gen_illegal_exception(dc); > + break; > + } > + break; > + > + case 0x0003: /*l.and*/ > + switch (op1) { > + case 0x00: > + 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; > + > + case 0x0004: /*l.or*/ > + switch (op1) { > + case 0x00: > + 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; > + > + case 0x0005: > + switch (op1) { > + case 0x00: /*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); > + if (ra != 0 && rb != 0) { > + gen_helper_mul(cpu_R[rd], cpu_env, cpu_R[ra], cpu_R[rb]); > + } else { > + tcg_gen_movi_tl(cpu_R[rd], 0x0); > + } > + 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); > + { > + int lab0 = gen_new_label(); > + int lab1 = gen_new_label(); > + int lab2 = gen_new_label(); > + TCGv_i32 sr_ove = tcg_temp_local_new_i32(); > + tcg_gen_andi_tl(sr_ove, cpu_sr, SR_OVE); > + if (rb == 0) { > + tcg_gen_ori_tl(cpu_sr, cpu_sr, SR_OV | SR_CY); > + 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], > + 0xffffffff, lab2); > + tcg_gen_brcondi_tl(TCG_COND_NE, cpu_R[rb], > + 0x80000000, lab2); > + gen_set_label(lab1); > + tcg_gen_ori_tl(cpu_sr, cpu_sr, SR_OV | SR_CY); > + tcg_gen_brcondi_tl(TCG_COND_NE, sr_ove, SR_OVE, lab2); > + gen_exception(dc, EXCP_RANGE); > + gen_set_label(lab2); > + tcg_gen_div_tl(cpu_R[rd], cpu_R[ra], cpu_R[rb]); > + } > + tcg_temp_free_i32(sr_ove); > + } > + 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); > + { > + int lab0 = gen_new_label(); > + int lab1 = gen_new_label(); > + TCGv_i32 sr_ove = tcg_temp_local_new_i32(); > + tcg_gen_andi_tl(sr_ove, cpu_sr, SR_OVE); > + if (rb == 0) { > + tcg_gen_ori_tl(cpu_sr, cpu_sr, SR_OV | SR_CY); > + 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_brcondi_tl(TCG_COND_NE, sr_ove, SR_OVE, lab1); > + gen_exception(dc, EXCP_RANGE); > + gen_set_label(lab1); > + tcg_gen_divu_tl(cpu_R[rd], cpu_R[ra], cpu_R[rb]); > + } > + tcg_temp_free_i32(sr_ove); > + } > + break; > + > + default: > + gen_illegal_exception(dc); > + break; > + } > + break; > + > + case 0x000b: > + 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_new_i64(); > + TCGv_i64 tra = tcg_temp_new_i64(); > + TCGv_i64 trb = tcg_temp_new_i64(); > + TCGv high = tcg_temp_new(); > + TCGv_i32 sr_ove = tcg_temp_new(); > + int lab = gen_new_label(); > + 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(tra); > + tcg_temp_free(trb); > + tcg_gen_shri_i64(high, result, TARGET_LONG_BITS); Here type i64 for 'high' does not match 'tl' for brcondi_tl below, so please use brcondi_i64. > + tcg_gen_brcondi_tl(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(high); > + tcg_gen_trunc_i64_tl(cpu_R[rd], result); > + tcg_temp_free(result); > + tcg_temp_free(sr_ove); > + } else { > + tcg_gen_movi_tl(cpu_R[rd], 0); > + } > + break; > + > + default: > + gen_illegal_exception(dc); > + break; > + } > + break; > + > + case 0x000e: > + switch (op1) { > + case 0x00: /*l.cmov*/ > + LOG_DIS("l.cmov r%d, r%d, r%d\n", rd, ra, rb); > + { > + int lab = gen_new_label(); > + TCGv res = tcg_temp_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_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); > + } > + break; > + > + default: > + gen_illegal_exception(dc); > + break; > + } > + break; > + > + case 0x000f: > + switch (op1) { > + case 0x00: /*l.ff1*/ > + LOG_DIS("l.ff1 r%d, r%d, r%d\n", rd, ra, rb); > + gen_helper_ff1(cpu_R[rd], cpu_R[ra]); > + break; > + case 0x01: /*l.fl1*/ > + LOG_DIS("l.fl1 r%d, r%d, r%d\n", rd, ra, rb); > + gen_helper_fl1(cpu_R[rd], cpu_R[ra]); > + break; > + > + default: > + gen_illegal_exception(dc); > + break; > + } > + 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; > + } > + 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 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; > + > + default: > + gen_illegal_exception(dc); > + break; > + } > + break; > + > + default: > + gen_illegal_exception(dc); > + break; > + } > + break; > + > + default: > + gen_illegal_exception(dc); > + break; > + } > +} > + > +static void dec_misc(DisasContext *dc, CPUOpenRISCState *env, uint32_t insn) > +{ > + uint32_t op0, op1; > + uint32_t ra, rb, rd; > + uint32_t /*L6, K5, */I16, I5, I11, N26, tmp; > + op0 = field(insn, 26, 6); > + op1 = field(insn, 24, 2); > + ra = field(insn, 16, 5); > + rb = field(insn, 11, 5); > + rd = field(insn, 21, 5); > + /*L6 = field(insn, 5, 6); > + K5 = field(insn, 0, 5);*/ > + I16 = field(insn, 0, 16); > + I5 = field(insn, 21, 5); > + I11 = field(insn, 0, 11); > + N26 = field(insn, 0, 26); > + tmp = (I5<<11) + I11; > + > + switch (op0) { > + case 0x00: /*l.j*/ > + LOG_DIS("l.j %d\n", N26); > + case 0x01: /*l.jal*/ > + LOG_DIS("l.jal %d\n", N26); > + case 0x03: /*l.bnf*/ > + LOG_DIS("l.bnf %d\n", N26); > + case 0x04: /*l.bf*/ > + LOG_DIS("l.bf %d\n", N26); > + > + gen_jump(dc, N26, 0, op0); > + break; > + > + case 0x05: > + switch (op1) { > + case 0x01: /*l.nop*/ > + LOG_DIS("l.nop %d\n", I16); > + break; > + > + default: > + gen_illegal_exception(dc); > + break; > + } > + break; > + > + case 0x11: /*l.jr*/ > + LOG_DIS("l.jr r%d\n", rb); > + case 0x12: /*l.jalr*/ > + LOG_DIS("l.jalr r%d\n", rb); > + > + gen_jump(dc, 0, rb, op0); > + break; > + > + case 0x13: /*l.maci*/ > + LOG_DIS("l.maci %d, r%d, %d\n", I5, ra, I11); > + { > + TCGv t1 = tcg_temp_new(); > + TCGv t2 = tcg_temp_new(); > + TCGv ttmp = tcg_const_tl(tmp); /* store machi maclo*/ > + tcg_gen_mul_tl(ttmp, cpu_R[ra], ttmp); I'm not sure if it's valid to use ttmp created with tcg_const_tl() as destination. > + tcg_gen_ext_i32_i64(t1, ttmp); ext_i32_i64() needs an i32 argument. > + tcg_gen_concat_i32_i64(t2, maclo, machi); Here the types don't match what concat_i32_i64 expects, also other lines below have wrong types. Please check if configuring with '--enable-debug-tcg' helps. > + tcg_gen_add_i64(t2, t2, t1); > + tcg_gen_trunc_i64_i32(maclo, t2); > + tcg_gen_shri_i64(t2, t2, 32); > + tcg_gen_trunc_i64_i32(machi, t2); > + tcg_temp_free(ttmp); > + tcg_temp_free(t1); > + tcg_temp_free(t2); > + } > + break; > + > + case 0x09: /*l.rfe*/ > + LOG_DIS("l.rfe\n"); > + { > + gen_helper_rfe(cpu_env); > + dc->is_jmp = DISAS_UPDATE; > + } > + break; > + > + case 0x1c: /*l.cust1*/ > + LOG_DIS("l.cust1\n"); > + break; > + > + case 0x1d: /*l.cust2*/ > + LOG_DIS("l.cust2\n"); > + break; > + > + case 0x1e: /*l.cust3*/ > + LOG_DIS("l.cust3\n"); > + break; > + > + case 0x1f: /*l.cust4*/ > + LOG_DIS("l.cust4\n"); > + break; > + > + case 0x3c: /*l.cust5*/ > + /*LOG_DIS("l.cust5 r%d, r%d, r%d, %d, %d\n", rd, ra, rb, L6, K5);*/ > + break; > + > + case 0x3d: /*l.cust6*/ > + LOG_DIS("l.cust6\n"); > + break; > + > + case 0x3e: /*l.cust7*/ > + LOG_DIS("l.cust7\n"); > + break; > + > + case 0x3f: /*l.cust8*/ > + LOG_DIS("l.cust8\n"); > + break; > + > + case 0x20: /*l.ld*/ > + LOG_DIS("l.ld r%d, r%d, %d\n", rd, ra, I16); > + { > + check_ob64s(dc); > + TCGv_i64 t0 = tcg_temp_new_i64(); > + tcg_gen_addi_i64(t0, cpu_R[ra], sign_extend(I16, 16)); > + tcg_gen_qemu_ld64(cpu_R[rd], t0, dc->mem_idx); > + tcg_temp_free_i64(t0); > + } > + break; > + > + case 0x21: /*l.lwz*/ > + LOG_DIS("l.lwz r%d, r%d, %d\n", rd, ra, I16); > + { > + TCGv t0 = tcg_temp_new(); > + tcg_gen_addi_tl(t0, cpu_R[ra], sign_extend(I16, 16)); > + tcg_gen_qemu_ld32u(cpu_R[rd], t0, dc->mem_idx); > + tcg_temp_free(t0); > + } > + break; > + > + case 0x22: /*l.lws*/ > + LOG_DIS("l.lws r%d, r%d, %d\n", rd, ra, I16); > + { > + TCGv t0 = tcg_temp_new(); > + tcg_gen_addi_tl(t0, cpu_R[ra], sign_extend(I16, 16)); > + tcg_gen_qemu_ld32s(cpu_R[rd], t0, dc->mem_idx); > + tcg_temp_free(t0); > + } > + break; > + > + case 0x23: /*l.lbz*/ > + LOG_DIS("l.lbz r%d, r%d, %d\n", rd, ra, I16); > + { > + TCGv t0 = tcg_temp_new(); > + tcg_gen_addi_tl(t0, cpu_R[ra], sign_extend(I16, 16)); > + tcg_gen_qemu_ld8u(cpu_R[rd], t0, dc->mem_idx); > + tcg_temp_free(t0); > + } > + break; > + > + case 0x24: /*l.lbs*/ > + LOG_DIS("l.lbs r%d, r%d, %d\n", rd, ra, I16); > + { > + TCGv t0 = tcg_temp_new(); > + tcg_gen_addi_tl(t0, cpu_R[ra], sign_extend(I16, 16)); > + tcg_gen_qemu_ld8s(cpu_R[rd], t0, dc->mem_idx); > + tcg_temp_free(t0); > + } > + break; > + > + case 0x25: /*l.lhz*/ > + LOG_DIS("l.lhz r%d, r%d, %d\n", rd, ra, I16); > + { > + TCGv t0 = tcg_temp_new(); > + tcg_gen_addi_tl(t0, cpu_R[ra], sign_extend(I16, 16)); > + tcg_gen_qemu_ld16u(cpu_R[rd], t0, dc->mem_idx); > + tcg_temp_free(t0); > + } > + break; > + > + case 0x26: /*l.lhs*/ > + LOG_DIS("l.lhs r%d, r%d, %d\n", rd, ra, I16); > + { > + TCGv t0 = tcg_temp_new(); > + tcg_gen_addi_tl(t0, cpu_R[ra], sign_extend(I16, 16)); > + tcg_gen_qemu_ld16s(cpu_R[rd], t0, dc->mem_idx); > + tcg_temp_free(t0); > + } > + break; > + > + case 0x27: /*l.addi*/ > + LOG_DIS("l.addi r%d, r%d, %d\n", rd, ra, I16); > + { > + TCGv t0 = tcg_const_tl(sign_extend(I16, 16)); > + gen_helper_add(cpu_R[rd], cpu_env, 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); > + { > + TCGv t0 = tcg_const_tl(sign_extend(I16, 16)); > + gen_helper_addc(cpu_R[rd], cpu_env, cpu_R[ra], t0); > + tcg_temp_free(t0); > + } > + 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)); > + 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)); > + 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)); > + break; > + > + case 0x2c: /*l.muli*/ > + LOG_DIS("l.muli r%d, r%d, %d\n", rd, ra, I16); > + if (ra != 0 && I16 != 0) { > + TCGv i16 = tcg_const_tl(I16); > + gen_helper_mul(cpu_R[rd], cpu_env, cpu_R[ra], i16); This should be 'muli', not 'mul' and there's no need for the temp. > + tcg_temp_free(i16); > + } else { > + tcg_gen_movi_tl(cpu_R[rd], 0x0); > + } > + break; > + > + case 0x2d: /*l.mfspr*/ > + LOG_DIS("l.mfspr r%d, r%d, %d\n", rd, ra, I16); > + break; > + > + case 0x30: /*l.mtspr*/ > + LOG_DIS("l.mtspr %d, r%d, r%d, %d\n", I5, ra, rb, I11); > + break; > + > + case 0x34: /*l.sd*/ > + LOG_DIS("l.sd %d, r%d, r%d, %d\n", I5, ra, rb, I11); > + { > + check_ob64s(dc); > + TCGv_i64 t0 = tcg_temp_new_i64(); > + tcg_gen_addi_tl(t0, cpu_R[ra], sign_extend(tmp, 16)); > + tcg_gen_qemu_st64(cpu_R[rb], t0, dc->mem_idx); > + tcg_temp_free_i64(t0); > + } > + break; > + > + case 0x35: /*l.sw*/ > + LOG_DIS("l.sw %d, r%d, r%d, %d\n", I5, ra, rb, I11); > + { > + TCGv t0 = tcg_temp_new(); > + tcg_gen_addi_tl(t0, cpu_R[ra], sign_extend(tmp, 16)); > + tcg_gen_qemu_st32(cpu_R[rb], t0, dc->mem_idx); > + tcg_temp_free(t0); > + } > + break; > + > + case 0x36: /*l.sb*/ > + LOG_DIS("l.sb %d, r%d, r%d, %d\n", I5, ra, rb, I11); > + { > + TCGv t0 = tcg_temp_new(); > + tcg_gen_addi_tl(t0, cpu_R[ra], sign_extend(tmp, 16)); > + tcg_gen_qemu_st8(cpu_R[rb], t0, dc->mem_idx); > + tcg_temp_free(t0); > + } > + break; > + > + case 0x37: /*l.sh*/ > + LOG_DIS("l.sh %d, r%d, r%d, %d\n", I5, ra, rb, I11); > + { > + TCGv t0 = tcg_temp_new(); > + tcg_gen_addi_tl(t0, cpu_R[ra], sign_extend(tmp, 16)); > + tcg_gen_qemu_st16(cpu_R[rb], t0, dc->mem_idx); > + tcg_temp_free(t0); > + } > + break; > + > + default: > + gen_illegal_exception(dc); > + break; > + } > +} > + > +static void dec_mac(DisasContext *dc, CPUOpenRISCState *env, uint32_t insn) > +{ > + uint32_t op0; > + uint32_t ra, rb; > + op0 = field(insn, 0, 4); > + ra = field(insn, 16, 5); > + rb = field(insn, 11, 5); > + > + switch (op0) { > + case 0x0001: /*l.mac*/ > + LOG_DIS("l.mac r%d, r%d\n", ra, rb); > + { > + TCGv t0 = tcg_temp_new(); > + TCGv_i64 t1 = tcg_temp_new(); > + TCGv_i64 t2 = tcg_temp_new(); > + 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_trunc_i64_i32(maclo, t2); > + tcg_gen_shri_i64(t2, t2, 32); > + tcg_gen_trunc_i64_i32(machi, t2); > + tcg_temp_free(t0); > + tcg_temp_free(t1); > + tcg_temp_free(t2); > + } > + break; > + > + case 0x0002: /*l.msb*/ > + LOG_DIS("l.msb r%d, r%d\n", ra, rb); > + { > + TCGv_i64 t0 = tcg_temp_new(); > + TCGv_i64 t1 = tcg_temp_new(); > + TCGv_i64 t2 = tcg_temp_new(); > + 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_trunc_i64_i32(maclo, t2); > + tcg_gen_shri_i64(t2, t2, 32); > + tcg_gen_trunc_i64_i32(machi, t2); > + tcg_temp_free(t0); > + tcg_temp_free(t1); > + tcg_temp_free(t2); > + } > + break; > + > + default: > + gen_illegal_exception(dc); > + break; > + } > +} > + > +static void dec_logic(DisasContext *dc, CPUOpenRISCState *env, uint32_t insn) > +{ > + uint32_t op0; > + uint32_t rd, ra, L6; > + op0 = field(insn, 6, 2); > + rd = field(insn, 21, 5); > + ra = field(insn, 16, 5); > + L6 = field(insn, 0, 6); > + > + 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)); > + 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)); > + 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; > + > + 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)); > + break; > + > + default: > + gen_illegal_exception(dc); > + break; > + } > +} > + > +static void dec_M(DisasContext *dc, CPUOpenRISCState *env, uint32_t insn) > +{ > + uint32_t op0; > + uint32_t rd; > + uint32_t K16; > + op0 = field(insn, 16, 1); > + rd = field(insn, 21, 5); > + K16 = field(insn, 0, 16); > + > + switch (op0) { > + case 0x0: /*l.movhi*/ > + LOG_DIS("l.movhi r%d, %d\n", rd, K16); > + tcg_gen_movi_tl(cpu_R[rd], (K16 << 16)); > + break; > + > + 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); > + break; > + > + default: > + gen_illegal_exception(dc); > + break; > + } > +} > + > +static void dec_comp(DisasContext *dc, CPUOpenRISCState *env, uint32_t insn) > +{ > + uint32_t op0; > + uint32_t ra, rb; > + > + op0 = field(insn, 21, 5); > + ra = field(insn, 16, 5); > + rb = field(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]); > + > + 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]); > + 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]); > + 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]); > + 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]); > + 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]); > + 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]); > + 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]); > + 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]); > + 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]); > + 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]); > + break; > + > + default: > + gen_illegal_exception(dc); > + break; > + } > + wb_SR_F(); > +} > + > +static void dec_compi(DisasContext *dc, CPUOpenRISCState *env, uint32_t insn) > +{ > + uint32_t op0; > + uint32_t ra, I16; > + > + op0 = field(insn, 21, 5); > + ra = field(insn, 16, 5); > + I16 = field(insn, 0, 16); > + > + tcg_gen_movi_i32(env_btaken, 0x0); > + I16 = sign_extend(I16, 16); > + > + 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); > + 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); > + 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); > + 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); > + 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); > + 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); > + 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); > + 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); > + 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); > + 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); > + break; > + > + default: > + gen_illegal_exception(dc); > + break; > + } > + wb_SR_F(); > +} > + > +static void dec_sys(DisasContext *dc, CPUOpenRISCState *env, uint32_t insn) > +{ > + uint32_t op0; > + /*uint32_t K16;*/ > + op0 = field(insn, 16, 8); > + /*K16 = field(insn, 0, 16);*/ > + > + switch (op0) { > + case 0x000: /*l.sys*/ > + /*LOG_DIS("l.sys %d\n", K16);*/ > + tcg_gen_movi_tl(cpu_pc, dc->pc); > + gen_exception(dc, EXCP_SYSCALL); > + dc->is_jmp = DISAS_UPDATE; > + break; > + > + case 0x100: /*l.trap*/ > + /*LOG_DIS("l.trap %d\n", K16);*/ > + tcg_gen_movi_tl(cpu_pc, dc->pc); > + gen_exception(dc, EXCP_TRAP); > + break; > + > + case 0x300: /*l.csync*/ > + LOG_DIS("l.csync\n"); > + break; > + > + case 0x200: /*l.msync*/ > + LOG_DIS("l.msync\n"); > + break; > + > + case 0x270: /*l.psync*/ > + LOG_DIS("l.psync\n"); > + break; > + > + default: > + gen_illegal_exception(dc); > + break; > + } > +} > + > +static void dec_float(DisasContext *dc, CPUOpenRISCState *env, uint32_t insn) > +{ > + uint32_t op0; > + uint32_t ra, rb, rd; > + op0 = field(insn, 0, 8); > + ra = field(insn, 16, 5); > + rb = field(insn, 11, 5); > + rd = field(insn, 21, 5); > + > + switch (op0) { > + case 0x10: /*lf.add.d*/ > + LOG_DIS("lf.add.d r%d, r%d, r%d\n", rd, ra, rb); > + check_of64s(dc); > + gen_helper_float_add_d(cpu_R[rd], cpu_env, cpu_R[ra], cpu_R[rb]); > + break; > + > + case 0x00: /*lf.add.s*/ > + LOG_DIS("lf.add.s r%d, r%d, r%d\n", rd, ra, rb); > + gen_helper_float_add_s(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); > + gen_helper_float_sub_d(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); > + gen_helper_float_sub_s(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); > + } > + 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); > + } > + break; > + > + case 0x13: /*lf.div.d*/ > + LOG_DIS("lf.div.d r%d, r%d, r%d\n", rd, ra, rb); > + check_of64s(dc); > + gen_helper_float_div_d(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); > + gen_helper_float_div_s(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); > + gen_helper_itofd(cpu_R[rd], cpu_env, cpu_R[ra]); > + break; > + > + case 0x04: /*lf.itof.s*/ > + LOG_DIS("lf.itof r%d, r%d\n", rd, ra); > + gen_helper_itofs(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); > + gen_helper_ftoid(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); > + gen_helper_ftois(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); > + gen_helper_float_rem_d(cpu_R[rd], cpu_env, cpu_R[ra], cpu_R[rb]); > + break; > + > + case 0x06: /*lf.rem.s*/ > + LOG_DIS("lf.rem.s r%d, r%d, r%d\n", rd, ra, rb); > + gen_helper_float_rem_s(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); > + gen_helper_float_muladd_d(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); > + gen_helper_float_muladd_s(cpu_R[rd], cpu_env, cpu_R[ra], cpu_R[rb]); > + break; > + > + 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]); > + break; > + > + 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]); > + 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]); > + 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]); > + 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]); > + 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]); > + 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]); > + 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]); > + 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]); > + 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]); > + 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]); > + 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]); > + break; > + > + default: > + gen_illegal_exception(dc); > + break; > + } > + wb_SR_F(); > +} > + > +static void disas_openrisc_insn(DisasContext *dc, CPUOpenRISCState *env) > +{ > + uint32_t op0; > + uint32_t insn; > + insn = cpu_ldl_code(env, dc->pc); > + op0 = field(insn, 26, 6); > + > + switch (op0) { > + case 0x06: > + dec_M(dc, env, insn); > + break; > + > + case 0x08: > + dec_sys(dc, env, insn); > + break; > + > + case 0x2e: > + dec_logic(dc, env, insn); > + break; > + > + case 0x2f: > + dec_compi(dc, env, insn); > + break; > + > + case 0x31: > + dec_mac(dc, env, insn); > + break; > + > + case 0x32: > + dec_float(dc, env, insn); > + break; > + > + case 0x38: > + dec_calc(dc, env, insn); > + break; > + > + case 0x39: > + dec_comp(dc, env, insn); > + break; > + > + default: > + dec_misc(dc, env, insn); > + break; > + } > +} > + > +static void check_breakpoint(CPUOpenRISCState *env, DisasContext *dc) > +{ > + CPUBreakpoint *bp; > + > + if (unlikely(!QTAILQ_EMPTY(&env->breakpoints))) { > + QTAILQ_FOREACH(bp, &env->breakpoints, entry) { > + if (bp->pc == dc->pc) { > + tcg_gen_movi_tl(cpu_pc, dc->pc); > + gen_exception(dc, EXCP_DEBUG); > + dc->is_jmp = DISAS_UPDATE; > + } > + } > + } > } > > static inline void gen_intermediate_code_internal(CPUOpenRISCState *env, > TranslationBlock *tb, > int search_pc) > { > + struct DisasContext ctx, *dc = &ctx; > + uint16_t *gen_opc_end; > + uint32_t pc_start; > + int j, k; > + uint32_t next_page_start; > + int num_insns; > + int max_insns; > + > + qemu_log_try_set_file(stderr); > + > + pc_start = tb->pc; > + dc->env = env; > + dc->tb = tb; > + > + gen_opc_end = gen_opc_buf + OPC_MAX_SIZE; > + dc->is_jmp = DISAS_NEXT; > + dc->ppc = pc_start; > + dc->pc = pc_start; > + dc->flags = env->cpucfgr; > + dc->mem_idx = cpu_mmu_index(env); > + dc->synced_flags = dc->tb_flags = tb->flags; > + dc->delayed_branch = !!(dc->tb_flags & D_FLAG); > + dc->singlestep_enabled = env->singlestep_enabled; > + if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)) { > + qemu_log("-----------------------------------------\n"); > + log_cpu_state(env, 0); > + } > + > + next_page_start = (pc_start & TARGET_PAGE_MASK) + TARGET_PAGE_SIZE; > + k = -1; > + num_insns = 0; > + max_insns = tb->cflags & CF_COUNT_MASK; > + > + if (max_insns == 0) { > + max_insns = CF_COUNT_MASK; > + } > + > + gen_icount_start(); > + > + do { > + check_breakpoint(env, dc); > + if (search_pc) { > + j = gen_opc_ptr - gen_opc_buf; > + if (k < j) { > + k++; > + while (k < j) { > + gen_opc_instr_start[k++] = 0; > + } > + } > + gen_opc_pc[k] = dc->pc; > + gen_opc_instr_start[k] = 1; > + gen_opc_icount[k] = num_insns; > + } > + > + if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP))) { > + tcg_gen_debug_insn_start(dc->pc); > + } > + > + if (num_insns + 1 == 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, env); > + dc->pc = dc->npc; > + num_insns++; > + /* delay slot */ > + 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_mov_tl(cpu_npc, jmp_pc); > + tcg_gen_movi_tl(jmp_pc, 0); > + tcg_gen_exit_tb(0); > + dc->is_jmp = DISAS_JUMP; > + break; > + } > + } > + } while (!dc->is_jmp > + && gen_opc_ptr < gen_opc_end > + && !env->singlestep_enabled > + && !singlestep > + && (dc->pc < next_page_start) > + && num_insns < max_insns); > + > + if (tb->cflags & CF_LAST_IO) { > + gen_io_end(); > + } > + if (dc->is_jmp == DISAS_NEXT) { > + dc->is_jmp = DISAS_UPDATE; > + tcg_gen_movi_tl(cpu_pc, dc->pc); > + } > + if (unlikely(env->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) { > + case DISAS_NEXT: > + gen_goto_tb(dc, 0, dc->pc); > + break; > + default: > + case DISAS_JUMP: > + break; > + case DISAS_UPDATE: > + /* indicate that the hash table must be used > + to find the next TB */ > + tcg_gen_exit_tb(0); > + break; > + case DISAS_TB_JUMP: > + /* nothing more to generate */ > + break; > + } > + } > + > + gen_icount_end(tb, num_insns); > + *gen_opc_ptr = INDEX_op_end; > + if (search_pc) { > + j = gen_opc_ptr - gen_opc_buf; > + k++; > + while (k <= j) { > + gen_opc_instr_start[k++] = 0; > + } > + } else { > + tb->size = dc->pc - pc_start; > + tb->icount = num_insns; > + } > + > +#ifdef DEBUG_DISAS > + if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)) { > + qemu_log("\n"); > + log_target_disas(pc_start, dc->pc - pc_start, 0); > + qemu_log("\nisize=%d osize=%td\n", > + dc->pc - pc_start, gen_opc_ptr - gen_opc_buf); > + } > +#endif > } > > void gen_intermediate_code(CPUOpenRISCState *env, struct TranslationBlock *tb) > -- > 1.7.9.5 > >
Hi Blue, Thank you for '--enable-debug-tcg' :-) All fixed. On Thu, Jun 14, 2012 at 2:59 AM, Blue Swirl <blauwirbel@gmail.com> wrote: > On Mon, Jun 11, 2012 at 6:31 AM, Jia Liu <proljc@gmail.com> wrote: >> Add OpenRISC translation routines. >> >> Signed-off-by: Jia Liu <proljc@gmail.com> >> --- >> target-openrisc/translate.c | 1523 +++++++++++++++++++++++++++++++++++++++++++ >> 1 file changed, 1523 insertions(+) >> >> diff --git a/target-openrisc/translate.c b/target-openrisc/translate.c >> index 1d87d76..ec004be 100644 >> --- a/target-openrisc/translate.c >> +++ b/target-openrisc/translate.c >> @@ -26,6 +26,10 @@ >> #include "qemu-log.h" >> #include "config.h" >> >> +#include "helper.h" >> +#define GEN_HELPER 1 >> +#include "helper.h" >> + >> #define OPENRISC_DISAS >> >> #ifdef OPENRISC_DISAS >> @@ -34,14 +38,1533 @@ >> # define LOG_DIS(...) do { } while (0) >> #endif >> >> +typedef struct DisasContext { >> + CPUOpenRISCState *env; >> + TranslationBlock *tb; >> + target_ulong pc, ppc, npc; >> + uint32_t tb_flags, synced_flags, flags; >> + uint32_t is_jmp; >> + uint32_t mem_idx; >> + int singlestep_enabled; >> + uint32_t delayed_branch; >> +} DisasContext; >> + >> +static TCGv_ptr cpu_env; >> +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_i32 env_btaken; /* bf/bnf , F flag taken */ >> +static TCGv_i32 fpcsr; >> +static TCGv machi, maclo; >> +static TCGv fpmaddhi, fpmaddlo; >> +static TCGv_i32 env_flags; >> +#include "gen-icount.h" >> + >> void openrisc_translate_init(void) >> { >> + static const char * const regnames[] = { >> + "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", >> + "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", >> + "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23", >> + "r24", "r25", "r26", "r27", "r28", "r29", "r30", "r31", >> + }; >> + int i; >> + >> + cpu_env = tcg_global_reg_new_ptr(TCG_AREG0, "env"); >> + cpu_sr = tcg_global_mem_new(TCG_AREG0, >> + offsetof(CPUOpenRISCState, sr), "sr"); >> + env_flags = tcg_global_mem_new_i32(TCG_AREG0, >> + offsetof(CPUOpenRISCState, flags), >> + "flags"); >> + cpu_pc = tcg_global_mem_new(TCG_AREG0, >> + offsetof(CPUOpenRISCState, pc), "pc"); >> + cpu_npc = tcg_global_mem_new(TCG_AREG0, >> + offsetof(CPUOpenRISCState, npc), "npc"); >> + cpu_ppc = tcg_global_mem_new(TCG_AREG0, >> + offsetof(CPUOpenRISCState, ppc), "ppc"); >> + jmp_pc = tcg_global_mem_new(TCG_AREG0, >> + offsetof(CPUOpenRISCState, jmp_pc), "jmp_pc"); >> + env_btaken = tcg_global_mem_new_i32(TCG_AREG0, >> + offsetof(CPUOpenRISCState, btaken), >> + "btaken"); >> + fpcsr = tcg_global_mem_new_i32(TCG_AREG0, >> + offsetof(CPUOpenRISCState, fpcsr), >> + "fpcsr"); >> + machi = tcg_global_mem_new(TCG_AREG0, >> + offsetof(CPUOpenRISCState, machi), >> + "machi"); >> + maclo = tcg_global_mem_new(TCG_AREG0, >> + offsetof(CPUOpenRISCState, maclo), >> + "maclo"); >> + fpmaddhi = tcg_global_mem_new(TCG_AREG0, >> + offsetof(CPUOpenRISCState, fpmaddhi), >> + "fpmaddhi"); >> + fpmaddlo = tcg_global_mem_new(TCG_AREG0, >> + offsetof(CPUOpenRISCState, fpmaddlo), >> + "fpmaddlo"); >> + for (i = 0; i < 32; i++) { >> + cpu_R[i] = tcg_global_mem_new(TCG_AREG0, >> + offsetof(CPUOpenRISCState, gpr[i]), >> + regnames[i]); >> + } >> +#define GEN_HELPER 2 >> +#include "helper.h" >> +} >> + >> +/* Writeback SR_F transaltion-space to execution-space. */ >> +static inline void wb_SR_F(void) >> +{ >> + int label; >> + >> + 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 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. */ >> + if (dc->tb_flags != dc->synced_flags) { >> + tcg_gen_movi_tl(env_flags, dc->tb_flags); >> + dc->synced_flags = dc->tb_flags; >> + } >> +} >> + >> +static void gen_exception(DisasContext *dc, unsigned int excp) >> +{ >> + TCGv_i32 tmp = tcg_const_i32(excp); >> + gen_helper_exception(cpu_env, tmp); >> + tcg_temp_free(tmp); >> +} >> + >> +static void gen_illegal_exception(DisasContext *dc) >> +{ >> + tcg_gen_movi_tl(cpu_pc, dc->pc); >> + gen_exception(dc, EXCP_ILLEGAL); >> + dc->is_jmp = DISAS_UPDATE; >> +} >> + >> +static void check_ob64s(DisasContext *dc) >> +{ >> + if (!(dc->flags & CPUCFGR_OB64S)) { >> + gen_illegal_exception(dc); >> + } >> +} >> + >> +static void check_of64s(DisasContext *dc) >> +{ >> + if (!(dc->flags & CPUCFGR_OF64S)) { >> + gen_illegal_exception(dc); >> + } >> +} >> + >> +/* not used yet, open it when we need or64. */ >> +/*static void check_ov64s(DisasContext *dc) >> +{ >> + if (!(dc->flags & CPUCFGR_OV64S)) { >> + gen_illegal_exception(dc); >> + } >> +}*/ >> + >> +static void gen_goto_tb(DisasContext *dc, int n, target_ulong dest) >> +{ >> + TranslationBlock *tb; >> + tb = dc->tb; >> + if ((tb->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK) && >> + likely(!dc->singlestep_enabled)) { >> + tcg_gen_movi_tl(cpu_pc, dest); >> + tcg_gen_goto_tb(n); >> + tcg_gen_exit_tb((tcg_target_long)tb + n); >> + } else { >> + tcg_gen_movi_tl(cpu_pc, dest); >> + if (dc->singlestep_enabled) { >> + gen_exception(dc, EXCP_DEBUG); >> + } >> + tcg_gen_exit_tb(0); >> + } >> +} >> + >> +static void gen_jump(DisasContext *dc, uint32_t imm, uint32_t reg, uint32_t op0) >> +{ >> + target_ulong tmp_pc; >> + int lab = gen_new_label(); >> + TCGv sr_f = tcg_temp_new(); >> + /* N26, 26bits imm */ >> + tmp_pc = sign_extend((imm<<2), 26) + dc->pc; >> + tcg_gen_andi_tl(sr_f, cpu_sr, SR_F); >> + >> + if (op0 == 0x00) { /*l.j*/ >> + tcg_gen_movi_tl(jmp_pc, tmp_pc); >> + } else if (op0 == 0x01) { /*l.jal*/ >> + tcg_gen_movi_tl(cpu_R[9], (dc->pc + 8)); >> + tcg_gen_movi_tl(jmp_pc, tmp_pc); >> + } else if (op0 == 0x03) { /*l.bnf*/ >> + tcg_gen_movi_tl(jmp_pc, dc->pc+8); >> + tcg_gen_brcondi_i32(TCG_COND_EQ, sr_f, SR_F, lab); >> + tcg_gen_movi_tl(jmp_pc, tmp_pc); >> + gen_set_label(lab); >> + } else if (op0 == 0x04) { /*l.bf*/ >> + tcg_gen_movi_tl(jmp_pc, dc->pc+8); >> + tcg_gen_brcondi_i32(TCG_COND_NE, sr_f, SR_F, lab); >> + tcg_gen_movi_tl(jmp_pc, tmp_pc); >> + gen_set_label(lab); >> + } else if (op0 == 0x11) { /*l.jr*/ >> + tcg_gen_mov_tl(jmp_pc, cpu_R[reg]); >> + } else if (op0 == 0x12) { /*l.jalr*/ >> + tcg_gen_movi_tl(cpu_R[9], (dc->pc + 8)); >> + tcg_gen_mov_tl(jmp_pc, cpu_R[reg]); >> + } else { >> + gen_illegal_exception(dc); >> + } >> + >> + tcg_temp_free(sr_f); >> + dc->delayed_branch = 2; >> + dc->tb_flags |= D_FLAG; >> + gen_sync_flags(dc); >> +} >> + >> +static inline uint32_t field(uint32_t val, int start, int length) >> +{ >> + val >>= start; >> + val &= ~(~0 << length); >> + return val; >> +} >> + >> +static void dec_calc(DisasContext *dc, CPUOpenRISCState *env, uint32_t insn) >> +{ >> + uint32_t op0, op1, op2; >> + uint32_t ra, rb, rd; >> + op0 = field(insn, 0, 4); >> + op1 = field(insn, 8, 2); >> + op2 = field(insn, 6, 2); >> + ra = field(insn, 16, 5); >> + rb = field(insn, 11, 5); >> + rd = field(insn, 21, 5); >> + >> + switch (op0) { >> + case 0x0000: >> + switch (op1) { >> + case 0x00: /*l.add*/ >> + LOG_DIS("l.add r%d, r%d, r%d\n", rd, ra, rb); >> + gen_helper_add(cpu_R[rd], cpu_env, cpu_R[ra], cpu_R[rb]); >> + break; >> + default: >> + gen_illegal_exception(dc); >> + break; >> + } >> + break; >> + >> + case 0x0001: /*l.addc*/ >> + switch (op1) { >> + case 0x00: >> + LOG_DIS("l.addc r%d, r%d, r%d\n", rd, ra, rb); >> + gen_helper_addc(cpu_R[rd], cpu_env, cpu_R[ra], cpu_R[rb]); >> + break; >> + default: >> + gen_illegal_exception(dc); >> + break; >> + } >> + break; >> + >> + case 0x0002: /*l.sub*/ >> + switch (op1) { >> + case 0x00: >> + LOG_DIS("l.sub r%d, r%d, r%d\n", rd, ra, rb); >> + gen_helper_sub(cpu_R[rd], cpu_env, cpu_R[ra], cpu_R[rb]); >> + break; >> + default: >> + gen_illegal_exception(dc); >> + break; >> + } >> + break; >> + >> + case 0x0003: /*l.and*/ >> + switch (op1) { >> + case 0x00: >> + 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; >> + >> + case 0x0004: /*l.or*/ >> + switch (op1) { >> + case 0x00: >> + 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; >> + >> + case 0x0005: >> + switch (op1) { >> + case 0x00: /*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); >> + if (ra != 0 && rb != 0) { >> + gen_helper_mul(cpu_R[rd], cpu_env, cpu_R[ra], cpu_R[rb]); >> + } else { >> + tcg_gen_movi_tl(cpu_R[rd], 0x0); >> + } >> + 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); >> + { >> + int lab0 = gen_new_label(); >> + int lab1 = gen_new_label(); >> + int lab2 = gen_new_label(); >> + TCGv_i32 sr_ove = tcg_temp_local_new_i32(); >> + tcg_gen_andi_tl(sr_ove, cpu_sr, SR_OVE); >> + if (rb == 0) { >> + tcg_gen_ori_tl(cpu_sr, cpu_sr, SR_OV | SR_CY); >> + 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], >> + 0xffffffff, lab2); >> + tcg_gen_brcondi_tl(TCG_COND_NE, cpu_R[rb], >> + 0x80000000, lab2); >> + gen_set_label(lab1); >> + tcg_gen_ori_tl(cpu_sr, cpu_sr, SR_OV | SR_CY); >> + tcg_gen_brcondi_tl(TCG_COND_NE, sr_ove, SR_OVE, lab2); >> + gen_exception(dc, EXCP_RANGE); >> + gen_set_label(lab2); >> + tcg_gen_div_tl(cpu_R[rd], cpu_R[ra], cpu_R[rb]); >> + } >> + tcg_temp_free_i32(sr_ove); >> + } >> + 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); >> + { >> + int lab0 = gen_new_label(); >> + int lab1 = gen_new_label(); >> + TCGv_i32 sr_ove = tcg_temp_local_new_i32(); >> + tcg_gen_andi_tl(sr_ove, cpu_sr, SR_OVE); >> + if (rb == 0) { >> + tcg_gen_ori_tl(cpu_sr, cpu_sr, SR_OV | SR_CY); >> + 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_brcondi_tl(TCG_COND_NE, sr_ove, SR_OVE, lab1); >> + gen_exception(dc, EXCP_RANGE); >> + gen_set_label(lab1); >> + tcg_gen_divu_tl(cpu_R[rd], cpu_R[ra], cpu_R[rb]); >> + } >> + tcg_temp_free_i32(sr_ove); >> + } >> + break; >> + >> + default: >> + gen_illegal_exception(dc); >> + break; >> + } >> + break; >> + >> + case 0x000b: >> + 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_new_i64(); >> + TCGv_i64 tra = tcg_temp_new_i64(); >> + TCGv_i64 trb = tcg_temp_new_i64(); >> + TCGv high = tcg_temp_new(); >> + TCGv_i32 sr_ove = tcg_temp_new(); >> + int lab = gen_new_label(); >> + 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(tra); >> + tcg_temp_free(trb); >> + tcg_gen_shri_i64(high, result, TARGET_LONG_BITS); > > Here type i64 for 'high' does not match 'tl' for brcondi_tl below, so > please use brcondi_i64. > >> + tcg_gen_brcondi_tl(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(high); >> + tcg_gen_trunc_i64_tl(cpu_R[rd], result); >> + tcg_temp_free(result); >> + tcg_temp_free(sr_ove); >> + } else { >> + tcg_gen_movi_tl(cpu_R[rd], 0); >> + } >> + break; >> + >> + default: >> + gen_illegal_exception(dc); >> + break; >> + } >> + break; >> + >> + case 0x000e: >> + switch (op1) { >> + case 0x00: /*l.cmov*/ >> + LOG_DIS("l.cmov r%d, r%d, r%d\n", rd, ra, rb); >> + { >> + int lab = gen_new_label(); >> + TCGv res = tcg_temp_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_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); >> + } >> + break; >> + >> + default: >> + gen_illegal_exception(dc); >> + break; >> + } >> + break; >> + >> + case 0x000f: >> + switch (op1) { >> + case 0x00: /*l.ff1*/ >> + LOG_DIS("l.ff1 r%d, r%d, r%d\n", rd, ra, rb); >> + gen_helper_ff1(cpu_R[rd], cpu_R[ra]); >> + break; >> + case 0x01: /*l.fl1*/ >> + LOG_DIS("l.fl1 r%d, r%d, r%d\n", rd, ra, rb); >> + gen_helper_fl1(cpu_R[rd], cpu_R[ra]); >> + break; >> + >> + default: >> + gen_illegal_exception(dc); >> + break; >> + } >> + 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; >> + } >> + 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 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; >> + >> + default: >> + gen_illegal_exception(dc); >> + break; >> + } >> + break; >> + >> + default: >> + gen_illegal_exception(dc); >> + break; >> + } >> + break; >> + >> + default: >> + gen_illegal_exception(dc); >> + break; >> + } >> +} >> + >> +static void dec_misc(DisasContext *dc, CPUOpenRISCState *env, uint32_t insn) >> +{ >> + uint32_t op0, op1; >> + uint32_t ra, rb, rd; >> + uint32_t /*L6, K5, */I16, I5, I11, N26, tmp; >> + op0 = field(insn, 26, 6); >> + op1 = field(insn, 24, 2); >> + ra = field(insn, 16, 5); >> + rb = field(insn, 11, 5); >> + rd = field(insn, 21, 5); >> + /*L6 = field(insn, 5, 6); >> + K5 = field(insn, 0, 5);*/ >> + I16 = field(insn, 0, 16); >> + I5 = field(insn, 21, 5); >> + I11 = field(insn, 0, 11); >> + N26 = field(insn, 0, 26); >> + tmp = (I5<<11) + I11; >> + >> + switch (op0) { >> + case 0x00: /*l.j*/ >> + LOG_DIS("l.j %d\n", N26); >> + case 0x01: /*l.jal*/ >> + LOG_DIS("l.jal %d\n", N26); >> + case 0x03: /*l.bnf*/ >> + LOG_DIS("l.bnf %d\n", N26); >> + case 0x04: /*l.bf*/ >> + LOG_DIS("l.bf %d\n", N26); >> + >> + gen_jump(dc, N26, 0, op0); >> + break; >> + >> + case 0x05: >> + switch (op1) { >> + case 0x01: /*l.nop*/ >> + LOG_DIS("l.nop %d\n", I16); >> + break; >> + >> + default: >> + gen_illegal_exception(dc); >> + break; >> + } >> + break; >> + >> + case 0x11: /*l.jr*/ >> + LOG_DIS("l.jr r%d\n", rb); >> + case 0x12: /*l.jalr*/ >> + LOG_DIS("l.jalr r%d\n", rb); >> + >> + gen_jump(dc, 0, rb, op0); >> + break; >> + >> + case 0x13: /*l.maci*/ >> + LOG_DIS("l.maci %d, r%d, %d\n", I5, ra, I11); >> + { >> + TCGv t1 = tcg_temp_new(); >> + TCGv t2 = tcg_temp_new(); >> + TCGv ttmp = tcg_const_tl(tmp); /* store machi maclo*/ >> + tcg_gen_mul_tl(ttmp, cpu_R[ra], ttmp); > > I'm not sure if it's valid to use ttmp created with tcg_const_tl() as > destination. > >> + tcg_gen_ext_i32_i64(t1, ttmp); > > ext_i32_i64() needs an i32 argument. > >> + tcg_gen_concat_i32_i64(t2, maclo, machi); > > Here the types don't match what concat_i32_i64 expects, also other > lines below have wrong types. Please check if configuring with > '--enable-debug-tcg' helps. > >> + tcg_gen_add_i64(t2, t2, t1); >> + tcg_gen_trunc_i64_i32(maclo, t2); >> + tcg_gen_shri_i64(t2, t2, 32); >> + tcg_gen_trunc_i64_i32(machi, t2); >> + tcg_temp_free(ttmp); >> + tcg_temp_free(t1); >> + tcg_temp_free(t2); >> + } >> + break; >> + >> + case 0x09: /*l.rfe*/ >> + LOG_DIS("l.rfe\n"); >> + { >> + gen_helper_rfe(cpu_env); >> + dc->is_jmp = DISAS_UPDATE; >> + } >> + break; >> + >> + case 0x1c: /*l.cust1*/ >> + LOG_DIS("l.cust1\n"); >> + break; >> + >> + case 0x1d: /*l.cust2*/ >> + LOG_DIS("l.cust2\n"); >> + break; >> + >> + case 0x1e: /*l.cust3*/ >> + LOG_DIS("l.cust3\n"); >> + break; >> + >> + case 0x1f: /*l.cust4*/ >> + LOG_DIS("l.cust4\n"); >> + break; >> + >> + case 0x3c: /*l.cust5*/ >> + /*LOG_DIS("l.cust5 r%d, r%d, r%d, %d, %d\n", rd, ra, rb, L6, K5);*/ >> + break; >> + >> + case 0x3d: /*l.cust6*/ >> + LOG_DIS("l.cust6\n"); >> + break; >> + >> + case 0x3e: /*l.cust7*/ >> + LOG_DIS("l.cust7\n"); >> + break; >> + >> + case 0x3f: /*l.cust8*/ >> + LOG_DIS("l.cust8\n"); >> + break; >> + >> + case 0x20: /*l.ld*/ >> + LOG_DIS("l.ld r%d, r%d, %d\n", rd, ra, I16); >> + { >> + check_ob64s(dc); >> + TCGv_i64 t0 = tcg_temp_new_i64(); >> + tcg_gen_addi_i64(t0, cpu_R[ra], sign_extend(I16, 16)); >> + tcg_gen_qemu_ld64(cpu_R[rd], t0, dc->mem_idx); >> + tcg_temp_free_i64(t0); >> + } >> + break; >> + >> + case 0x21: /*l.lwz*/ >> + LOG_DIS("l.lwz r%d, r%d, %d\n", rd, ra, I16); >> + { >> + TCGv t0 = tcg_temp_new(); >> + tcg_gen_addi_tl(t0, cpu_R[ra], sign_extend(I16, 16)); >> + tcg_gen_qemu_ld32u(cpu_R[rd], t0, dc->mem_idx); >> + tcg_temp_free(t0); >> + } >> + break; >> + >> + case 0x22: /*l.lws*/ >> + LOG_DIS("l.lws r%d, r%d, %d\n", rd, ra, I16); >> + { >> + TCGv t0 = tcg_temp_new(); >> + tcg_gen_addi_tl(t0, cpu_R[ra], sign_extend(I16, 16)); >> + tcg_gen_qemu_ld32s(cpu_R[rd], t0, dc->mem_idx); >> + tcg_temp_free(t0); >> + } >> + break; >> + >> + case 0x23: /*l.lbz*/ >> + LOG_DIS("l.lbz r%d, r%d, %d\n", rd, ra, I16); >> + { >> + TCGv t0 = tcg_temp_new(); >> + tcg_gen_addi_tl(t0, cpu_R[ra], sign_extend(I16, 16)); >> + tcg_gen_qemu_ld8u(cpu_R[rd], t0, dc->mem_idx); >> + tcg_temp_free(t0); >> + } >> + break; >> + >> + case 0x24: /*l.lbs*/ >> + LOG_DIS("l.lbs r%d, r%d, %d\n", rd, ra, I16); >> + { >> + TCGv t0 = tcg_temp_new(); >> + tcg_gen_addi_tl(t0, cpu_R[ra], sign_extend(I16, 16)); >> + tcg_gen_qemu_ld8s(cpu_R[rd], t0, dc->mem_idx); >> + tcg_temp_free(t0); >> + } >> + break; >> + >> + case 0x25: /*l.lhz*/ >> + LOG_DIS("l.lhz r%d, r%d, %d\n", rd, ra, I16); >> + { >> + TCGv t0 = tcg_temp_new(); >> + tcg_gen_addi_tl(t0, cpu_R[ra], sign_extend(I16, 16)); >> + tcg_gen_qemu_ld16u(cpu_R[rd], t0, dc->mem_idx); >> + tcg_temp_free(t0); >> + } >> + break; >> + >> + case 0x26: /*l.lhs*/ >> + LOG_DIS("l.lhs r%d, r%d, %d\n", rd, ra, I16); >> + { >> + TCGv t0 = tcg_temp_new(); >> + tcg_gen_addi_tl(t0, cpu_R[ra], sign_extend(I16, 16)); >> + tcg_gen_qemu_ld16s(cpu_R[rd], t0, dc->mem_idx); >> + tcg_temp_free(t0); >> + } >> + break; >> + >> + case 0x27: /*l.addi*/ >> + LOG_DIS("l.addi r%d, r%d, %d\n", rd, ra, I16); >> + { >> + TCGv t0 = tcg_const_tl(sign_extend(I16, 16)); >> + gen_helper_add(cpu_R[rd], cpu_env, 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); >> + { >> + TCGv t0 = tcg_const_tl(sign_extend(I16, 16)); >> + gen_helper_addc(cpu_R[rd], cpu_env, cpu_R[ra], t0); >> + tcg_temp_free(t0); >> + } >> + 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)); >> + 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)); >> + 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)); >> + break; >> + >> + case 0x2c: /*l.muli*/ >> + LOG_DIS("l.muli r%d, r%d, %d\n", rd, ra, I16); >> + if (ra != 0 && I16 != 0) { >> + TCGv i16 = tcg_const_tl(I16); >> + gen_helper_mul(cpu_R[rd], cpu_env, cpu_R[ra], i16); > > This should be 'muli', not 'mul' and there's no need for the temp. > >> + tcg_temp_free(i16); >> + } else { >> + tcg_gen_movi_tl(cpu_R[rd], 0x0); >> + } >> + break; >> + >> + case 0x2d: /*l.mfspr*/ >> + LOG_DIS("l.mfspr r%d, r%d, %d\n", rd, ra, I16); >> + break; >> + >> + case 0x30: /*l.mtspr*/ >> + LOG_DIS("l.mtspr %d, r%d, r%d, %d\n", I5, ra, rb, I11); >> + break; >> + >> + case 0x34: /*l.sd*/ >> + LOG_DIS("l.sd %d, r%d, r%d, %d\n", I5, ra, rb, I11); >> + { >> + check_ob64s(dc); >> + TCGv_i64 t0 = tcg_temp_new_i64(); >> + tcg_gen_addi_tl(t0, cpu_R[ra], sign_extend(tmp, 16)); >> + tcg_gen_qemu_st64(cpu_R[rb], t0, dc->mem_idx); >> + tcg_temp_free_i64(t0); >> + } >> + break; >> + >> + case 0x35: /*l.sw*/ >> + LOG_DIS("l.sw %d, r%d, r%d, %d\n", I5, ra, rb, I11); >> + { >> + TCGv t0 = tcg_temp_new(); >> + tcg_gen_addi_tl(t0, cpu_R[ra], sign_extend(tmp, 16)); >> + tcg_gen_qemu_st32(cpu_R[rb], t0, dc->mem_idx); >> + tcg_temp_free(t0); >> + } >> + break; >> + >> + case 0x36: /*l.sb*/ >> + LOG_DIS("l.sb %d, r%d, r%d, %d\n", I5, ra, rb, I11); >> + { >> + TCGv t0 = tcg_temp_new(); >> + tcg_gen_addi_tl(t0, cpu_R[ra], sign_extend(tmp, 16)); >> + tcg_gen_qemu_st8(cpu_R[rb], t0, dc->mem_idx); >> + tcg_temp_free(t0); >> + } >> + break; >> + >> + case 0x37: /*l.sh*/ >> + LOG_DIS("l.sh %d, r%d, r%d, %d\n", I5, ra, rb, I11); >> + { >> + TCGv t0 = tcg_temp_new(); >> + tcg_gen_addi_tl(t0, cpu_R[ra], sign_extend(tmp, 16)); >> + tcg_gen_qemu_st16(cpu_R[rb], t0, dc->mem_idx); >> + tcg_temp_free(t0); >> + } >> + break; >> + >> + default: >> + gen_illegal_exception(dc); >> + break; >> + } >> +} >> + >> +static void dec_mac(DisasContext *dc, CPUOpenRISCState *env, uint32_t insn) >> +{ >> + uint32_t op0; >> + uint32_t ra, rb; >> + op0 = field(insn, 0, 4); >> + ra = field(insn, 16, 5); >> + rb = field(insn, 11, 5); >> + >> + switch (op0) { >> + case 0x0001: /*l.mac*/ >> + LOG_DIS("l.mac r%d, r%d\n", ra, rb); >> + { >> + TCGv t0 = tcg_temp_new(); >> + TCGv_i64 t1 = tcg_temp_new(); >> + TCGv_i64 t2 = tcg_temp_new(); >> + 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_trunc_i64_i32(maclo, t2); >> + tcg_gen_shri_i64(t2, t2, 32); >> + tcg_gen_trunc_i64_i32(machi, t2); >> + tcg_temp_free(t0); >> + tcg_temp_free(t1); >> + tcg_temp_free(t2); >> + } >> + break; >> + >> + case 0x0002: /*l.msb*/ >> + LOG_DIS("l.msb r%d, r%d\n", ra, rb); >> + { >> + TCGv_i64 t0 = tcg_temp_new(); >> + TCGv_i64 t1 = tcg_temp_new(); >> + TCGv_i64 t2 = tcg_temp_new(); >> + 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_trunc_i64_i32(maclo, t2); >> + tcg_gen_shri_i64(t2, t2, 32); >> + tcg_gen_trunc_i64_i32(machi, t2); >> + tcg_temp_free(t0); >> + tcg_temp_free(t1); >> + tcg_temp_free(t2); >> + } >> + break; >> + >> + default: >> + gen_illegal_exception(dc); >> + break; >> + } >> +} >> + >> +static void dec_logic(DisasContext *dc, CPUOpenRISCState *env, uint32_t insn) >> +{ >> + uint32_t op0; >> + uint32_t rd, ra, L6; >> + op0 = field(insn, 6, 2); >> + rd = field(insn, 21, 5); >> + ra = field(insn, 16, 5); >> + L6 = field(insn, 0, 6); >> + >> + 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)); >> + 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)); >> + 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; >> + >> + 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)); >> + break; >> + >> + default: >> + gen_illegal_exception(dc); >> + break; >> + } >> +} >> + >> +static void dec_M(DisasContext *dc, CPUOpenRISCState *env, uint32_t insn) >> +{ >> + uint32_t op0; >> + uint32_t rd; >> + uint32_t K16; >> + op0 = field(insn, 16, 1); >> + rd = field(insn, 21, 5); >> + K16 = field(insn, 0, 16); >> + >> + switch (op0) { >> + case 0x0: /*l.movhi*/ >> + LOG_DIS("l.movhi r%d, %d\n", rd, K16); >> + tcg_gen_movi_tl(cpu_R[rd], (K16 << 16)); >> + break; >> + >> + 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); >> + break; >> + >> + default: >> + gen_illegal_exception(dc); >> + break; >> + } >> +} >> + >> +static void dec_comp(DisasContext *dc, CPUOpenRISCState *env, uint32_t insn) >> +{ >> + uint32_t op0; >> + uint32_t ra, rb; >> + >> + op0 = field(insn, 21, 5); >> + ra = field(insn, 16, 5); >> + rb = field(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]); >> + >> + 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]); >> + 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]); >> + 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]); >> + 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]); >> + 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]); >> + 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]); >> + 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]); >> + 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]); >> + 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]); >> + 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]); >> + break; >> + >> + default: >> + gen_illegal_exception(dc); >> + break; >> + } >> + wb_SR_F(); >> +} >> + >> +static void dec_compi(DisasContext *dc, CPUOpenRISCState *env, uint32_t insn) >> +{ >> + uint32_t op0; >> + uint32_t ra, I16; >> + >> + op0 = field(insn, 21, 5); >> + ra = field(insn, 16, 5); >> + I16 = field(insn, 0, 16); >> + >> + tcg_gen_movi_i32(env_btaken, 0x0); >> + I16 = sign_extend(I16, 16); >> + >> + 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); >> + 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); >> + 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); >> + 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); >> + 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); >> + 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); >> + 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); >> + 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); >> + 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); >> + 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); >> + break; >> + >> + default: >> + gen_illegal_exception(dc); >> + break; >> + } >> + wb_SR_F(); >> +} >> + >> +static void dec_sys(DisasContext *dc, CPUOpenRISCState *env, uint32_t insn) >> +{ >> + uint32_t op0; >> + /*uint32_t K16;*/ >> + op0 = field(insn, 16, 8); >> + /*K16 = field(insn, 0, 16);*/ >> + >> + switch (op0) { >> + case 0x000: /*l.sys*/ >> + /*LOG_DIS("l.sys %d\n", K16);*/ >> + tcg_gen_movi_tl(cpu_pc, dc->pc); >> + gen_exception(dc, EXCP_SYSCALL); >> + dc->is_jmp = DISAS_UPDATE; >> + break; >> + >> + case 0x100: /*l.trap*/ >> + /*LOG_DIS("l.trap %d\n", K16);*/ >> + tcg_gen_movi_tl(cpu_pc, dc->pc); >> + gen_exception(dc, EXCP_TRAP); >> + break; >> + >> + case 0x300: /*l.csync*/ >> + LOG_DIS("l.csync\n"); >> + break; >> + >> + case 0x200: /*l.msync*/ >> + LOG_DIS("l.msync\n"); >> + break; >> + >> + case 0x270: /*l.psync*/ >> + LOG_DIS("l.psync\n"); >> + break; >> + >> + default: >> + gen_illegal_exception(dc); >> + break; >> + } >> +} >> + >> +static void dec_float(DisasContext *dc, CPUOpenRISCState *env, uint32_t insn) >> +{ >> + uint32_t op0; >> + uint32_t ra, rb, rd; >> + op0 = field(insn, 0, 8); >> + ra = field(insn, 16, 5); >> + rb = field(insn, 11, 5); >> + rd = field(insn, 21, 5); >> + >> + switch (op0) { >> + case 0x10: /*lf.add.d*/ >> + LOG_DIS("lf.add.d r%d, r%d, r%d\n", rd, ra, rb); >> + check_of64s(dc); >> + gen_helper_float_add_d(cpu_R[rd], cpu_env, cpu_R[ra], cpu_R[rb]); >> + break; >> + >> + case 0x00: /*lf.add.s*/ >> + LOG_DIS("lf.add.s r%d, r%d, r%d\n", rd, ra, rb); >> + gen_helper_float_add_s(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); >> + gen_helper_float_sub_d(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); >> + gen_helper_float_sub_s(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); >> + } >> + 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); >> + } >> + break; >> + >> + case 0x13: /*lf.div.d*/ >> + LOG_DIS("lf.div.d r%d, r%d, r%d\n", rd, ra, rb); >> + check_of64s(dc); >> + gen_helper_float_div_d(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); >> + gen_helper_float_div_s(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); >> + gen_helper_itofd(cpu_R[rd], cpu_env, cpu_R[ra]); >> + break; >> + >> + case 0x04: /*lf.itof.s*/ >> + LOG_DIS("lf.itof r%d, r%d\n", rd, ra); >> + gen_helper_itofs(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); >> + gen_helper_ftoid(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); >> + gen_helper_ftois(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); >> + gen_helper_float_rem_d(cpu_R[rd], cpu_env, cpu_R[ra], cpu_R[rb]); >> + break; >> + >> + case 0x06: /*lf.rem.s*/ >> + LOG_DIS("lf.rem.s r%d, r%d, r%d\n", rd, ra, rb); >> + gen_helper_float_rem_s(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); >> + gen_helper_float_muladd_d(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); >> + gen_helper_float_muladd_s(cpu_R[rd], cpu_env, cpu_R[ra], cpu_R[rb]); >> + break; >> + >> + 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]); >> + break; >> + >> + 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]); >> + 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]); >> + 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]); >> + 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]); >> + 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]); >> + 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]); >> + 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]); >> + 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]); >> + 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]); >> + 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]); >> + 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]); >> + break; >> + >> + default: >> + gen_illegal_exception(dc); >> + break; >> + } >> + wb_SR_F(); >> +} >> + >> +static void disas_openrisc_insn(DisasContext *dc, CPUOpenRISCState *env) >> +{ >> + uint32_t op0; >> + uint32_t insn; >> + insn = cpu_ldl_code(env, dc->pc); >> + op0 = field(insn, 26, 6); >> + >> + switch (op0) { >> + case 0x06: >> + dec_M(dc, env, insn); >> + break; >> + >> + case 0x08: >> + dec_sys(dc, env, insn); >> + break; >> + >> + case 0x2e: >> + dec_logic(dc, env, insn); >> + break; >> + >> + case 0x2f: >> + dec_compi(dc, env, insn); >> + break; >> + >> + case 0x31: >> + dec_mac(dc, env, insn); >> + break; >> + >> + case 0x32: >> + dec_float(dc, env, insn); >> + break; >> + >> + case 0x38: >> + dec_calc(dc, env, insn); >> + break; >> + >> + case 0x39: >> + dec_comp(dc, env, insn); >> + break; >> + >> + default: >> + dec_misc(dc, env, insn); >> + break; >> + } >> +} >> + >> +static void check_breakpoint(CPUOpenRISCState *env, DisasContext *dc) >> +{ >> + CPUBreakpoint *bp; >> + >> + if (unlikely(!QTAILQ_EMPTY(&env->breakpoints))) { >> + QTAILQ_FOREACH(bp, &env->breakpoints, entry) { >> + if (bp->pc == dc->pc) { >> + tcg_gen_movi_tl(cpu_pc, dc->pc); >> + gen_exception(dc, EXCP_DEBUG); >> + dc->is_jmp = DISAS_UPDATE; >> + } >> + } >> + } >> } >> >> static inline void gen_intermediate_code_internal(CPUOpenRISCState *env, >> TranslationBlock *tb, >> int search_pc) >> { >> + struct DisasContext ctx, *dc = &ctx; >> + uint16_t *gen_opc_end; >> + uint32_t pc_start; >> + int j, k; >> + uint32_t next_page_start; >> + int num_insns; >> + int max_insns; >> + >> + qemu_log_try_set_file(stderr); >> + >> + pc_start = tb->pc; >> + dc->env = env; >> + dc->tb = tb; >> + >> + gen_opc_end = gen_opc_buf + OPC_MAX_SIZE; >> + dc->is_jmp = DISAS_NEXT; >> + dc->ppc = pc_start; >> + dc->pc = pc_start; >> + dc->flags = env->cpucfgr; >> + dc->mem_idx = cpu_mmu_index(env); >> + dc->synced_flags = dc->tb_flags = tb->flags; >> + dc->delayed_branch = !!(dc->tb_flags & D_FLAG); >> + dc->singlestep_enabled = env->singlestep_enabled; >> + if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)) { >> + qemu_log("-----------------------------------------\n"); >> + log_cpu_state(env, 0); >> + } >> + >> + next_page_start = (pc_start & TARGET_PAGE_MASK) + TARGET_PAGE_SIZE; >> + k = -1; >> + num_insns = 0; >> + max_insns = tb->cflags & CF_COUNT_MASK; >> + >> + if (max_insns == 0) { >> + max_insns = CF_COUNT_MASK; >> + } >> + >> + gen_icount_start(); >> + >> + do { >> + check_breakpoint(env, dc); >> + if (search_pc) { >> + j = gen_opc_ptr - gen_opc_buf; >> + if (k < j) { >> + k++; >> + while (k < j) { >> + gen_opc_instr_start[k++] = 0; >> + } >> + } >> + gen_opc_pc[k] = dc->pc; >> + gen_opc_instr_start[k] = 1; >> + gen_opc_icount[k] = num_insns; >> + } >> + >> + if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP))) { >> + tcg_gen_debug_insn_start(dc->pc); >> + } >> + >> + if (num_insns + 1 == 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, env); >> + dc->pc = dc->npc; >> + num_insns++; >> + /* delay slot */ >> + 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_mov_tl(cpu_npc, jmp_pc); >> + tcg_gen_movi_tl(jmp_pc, 0); >> + tcg_gen_exit_tb(0); >> + dc->is_jmp = DISAS_JUMP; >> + break; >> + } >> + } >> + } while (!dc->is_jmp >> + && gen_opc_ptr < gen_opc_end >> + && !env->singlestep_enabled >> + && !singlestep >> + && (dc->pc < next_page_start) >> + && num_insns < max_insns); >> + >> + if (tb->cflags & CF_LAST_IO) { >> + gen_io_end(); >> + } >> + if (dc->is_jmp == DISAS_NEXT) { >> + dc->is_jmp = DISAS_UPDATE; >> + tcg_gen_movi_tl(cpu_pc, dc->pc); >> + } >> + if (unlikely(env->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) { >> + case DISAS_NEXT: >> + gen_goto_tb(dc, 0, dc->pc); >> + break; >> + default: >> + case DISAS_JUMP: >> + break; >> + case DISAS_UPDATE: >> + /* indicate that the hash table must be used >> + to find the next TB */ >> + tcg_gen_exit_tb(0); >> + break; >> + case DISAS_TB_JUMP: >> + /* nothing more to generate */ >> + break; >> + } >> + } >> + >> + gen_icount_end(tb, num_insns); >> + *gen_opc_ptr = INDEX_op_end; >> + if (search_pc) { >> + j = gen_opc_ptr - gen_opc_buf; >> + k++; >> + while (k <= j) { >> + gen_opc_instr_start[k++] = 0; >> + } >> + } else { >> + tb->size = dc->pc - pc_start; >> + tb->icount = num_insns; >> + } >> + >> +#ifdef DEBUG_DISAS >> + if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)) { >> + qemu_log("\n"); >> + log_target_disas(pc_start, dc->pc - pc_start, 0); >> + qemu_log("\nisize=%d osize=%td\n", >> + dc->pc - pc_start, gen_opc_ptr - gen_opc_buf); >> + } >> +#endif >> } >> >> void gen_intermediate_code(CPUOpenRISCState *env, struct TranslationBlock *tb) >> -- >> 1.7.9.5 >> >> Regards, Jia.
diff --git a/target-openrisc/translate.c b/target-openrisc/translate.c index 1d87d76..ec004be 100644 --- a/target-openrisc/translate.c +++ b/target-openrisc/translate.c @@ -26,6 +26,10 @@ #include "qemu-log.h" #include "config.h" +#include "helper.h" +#define GEN_HELPER 1 +#include "helper.h" + #define OPENRISC_DISAS #ifdef OPENRISC_DISAS @@ -34,14 +38,1533 @@ # define LOG_DIS(...) do { } while (0) #endif +typedef struct DisasContext { + CPUOpenRISCState *env; + TranslationBlock *tb; + target_ulong pc, ppc, npc; + uint32_t tb_flags, synced_flags, flags; + uint32_t is_jmp; + uint32_t mem_idx; + int singlestep_enabled; + uint32_t delayed_branch; +} DisasContext; + +static TCGv_ptr cpu_env; +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_i32 env_btaken; /* bf/bnf , F flag taken */ +static TCGv_i32 fpcsr; +static TCGv machi, maclo; +static TCGv fpmaddhi, fpmaddlo; +static TCGv_i32 env_flags; +#include "gen-icount.h" + void openrisc_translate_init(void) { + static const char * const regnames[] = { + "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", + "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", + "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23", + "r24", "r25", "r26", "r27", "r28", "r29", "r30", "r31", + }; + int i; + + cpu_env = tcg_global_reg_new_ptr(TCG_AREG0, "env"); + cpu_sr = tcg_global_mem_new(TCG_AREG0, + offsetof(CPUOpenRISCState, sr), "sr"); + env_flags = tcg_global_mem_new_i32(TCG_AREG0, + offsetof(CPUOpenRISCState, flags), + "flags"); + cpu_pc = tcg_global_mem_new(TCG_AREG0, + offsetof(CPUOpenRISCState, pc), "pc"); + cpu_npc = tcg_global_mem_new(TCG_AREG0, + offsetof(CPUOpenRISCState, npc), "npc"); + cpu_ppc = tcg_global_mem_new(TCG_AREG0, + offsetof(CPUOpenRISCState, ppc), "ppc"); + jmp_pc = tcg_global_mem_new(TCG_AREG0, + offsetof(CPUOpenRISCState, jmp_pc), "jmp_pc"); + env_btaken = tcg_global_mem_new_i32(TCG_AREG0, + offsetof(CPUOpenRISCState, btaken), + "btaken"); + fpcsr = tcg_global_mem_new_i32(TCG_AREG0, + offsetof(CPUOpenRISCState, fpcsr), + "fpcsr"); + machi = tcg_global_mem_new(TCG_AREG0, + offsetof(CPUOpenRISCState, machi), + "machi"); + maclo = tcg_global_mem_new(TCG_AREG0, + offsetof(CPUOpenRISCState, maclo), + "maclo"); + fpmaddhi = tcg_global_mem_new(TCG_AREG0, + offsetof(CPUOpenRISCState, fpmaddhi), + "fpmaddhi"); + fpmaddlo = tcg_global_mem_new(TCG_AREG0, + offsetof(CPUOpenRISCState, fpmaddlo), + "fpmaddlo"); + for (i = 0; i < 32; i++) { + cpu_R[i] = tcg_global_mem_new(TCG_AREG0, + offsetof(CPUOpenRISCState, gpr[i]), + regnames[i]); + } +#define GEN_HELPER 2 +#include "helper.h" +} + +/* Writeback SR_F transaltion-space to execution-space. */ +static inline void wb_SR_F(void) +{ + int label; + + 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 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. */ + if (dc->tb_flags != dc->synced_flags) { + tcg_gen_movi_tl(env_flags, dc->tb_flags); + dc->synced_flags = dc->tb_flags; + } +} + +static void gen_exception(DisasContext *dc, unsigned int excp) +{ + TCGv_i32 tmp = tcg_const_i32(excp); + gen_helper_exception(cpu_env, tmp); + tcg_temp_free(tmp); +} + +static void gen_illegal_exception(DisasContext *dc) +{ + tcg_gen_movi_tl(cpu_pc, dc->pc); + gen_exception(dc, EXCP_ILLEGAL); + dc->is_jmp = DISAS_UPDATE; +} + +static void check_ob64s(DisasContext *dc) +{ + if (!(dc->flags & CPUCFGR_OB64S)) { + gen_illegal_exception(dc); + } +} + +static void check_of64s(DisasContext *dc) +{ + if (!(dc->flags & CPUCFGR_OF64S)) { + gen_illegal_exception(dc); + } +} + +/* not used yet, open it when we need or64. */ +/*static void check_ov64s(DisasContext *dc) +{ + if (!(dc->flags & CPUCFGR_OV64S)) { + gen_illegal_exception(dc); + } +}*/ + +static void gen_goto_tb(DisasContext *dc, int n, target_ulong dest) +{ + TranslationBlock *tb; + tb = dc->tb; + if ((tb->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK) && + likely(!dc->singlestep_enabled)) { + tcg_gen_movi_tl(cpu_pc, dest); + tcg_gen_goto_tb(n); + tcg_gen_exit_tb((tcg_target_long)tb + n); + } else { + tcg_gen_movi_tl(cpu_pc, dest); + if (dc->singlestep_enabled) { + gen_exception(dc, EXCP_DEBUG); + } + tcg_gen_exit_tb(0); + } +} + +static void gen_jump(DisasContext *dc, uint32_t imm, uint32_t reg, uint32_t op0) +{ + target_ulong tmp_pc; + int lab = gen_new_label(); + TCGv sr_f = tcg_temp_new(); + /* N26, 26bits imm */ + tmp_pc = sign_extend((imm<<2), 26) + dc->pc; + tcg_gen_andi_tl(sr_f, cpu_sr, SR_F); + + if (op0 == 0x00) { /*l.j*/ + tcg_gen_movi_tl(jmp_pc, tmp_pc); + } else if (op0 == 0x01) { /*l.jal*/ + tcg_gen_movi_tl(cpu_R[9], (dc->pc + 8)); + tcg_gen_movi_tl(jmp_pc, tmp_pc); + } else if (op0 == 0x03) { /*l.bnf*/ + tcg_gen_movi_tl(jmp_pc, dc->pc+8); + tcg_gen_brcondi_i32(TCG_COND_EQ, sr_f, SR_F, lab); + tcg_gen_movi_tl(jmp_pc, tmp_pc); + gen_set_label(lab); + } else if (op0 == 0x04) { /*l.bf*/ + tcg_gen_movi_tl(jmp_pc, dc->pc+8); + tcg_gen_brcondi_i32(TCG_COND_NE, sr_f, SR_F, lab); + tcg_gen_movi_tl(jmp_pc, tmp_pc); + gen_set_label(lab); + } else if (op0 == 0x11) { /*l.jr*/ + tcg_gen_mov_tl(jmp_pc, cpu_R[reg]); + } else if (op0 == 0x12) { /*l.jalr*/ + tcg_gen_movi_tl(cpu_R[9], (dc->pc + 8)); + tcg_gen_mov_tl(jmp_pc, cpu_R[reg]); + } else { + gen_illegal_exception(dc); + } + + tcg_temp_free(sr_f); + dc->delayed_branch = 2; + dc->tb_flags |= D_FLAG; + gen_sync_flags(dc); +} + +static inline uint32_t field(uint32_t val, int start, int length) +{ + val >>= start; + val &= ~(~0 << length); + return val; +} + +static void dec_calc(DisasContext *dc, CPUOpenRISCState *env, uint32_t insn) +{ + uint32_t op0, op1, op2; + uint32_t ra, rb, rd; + op0 = field(insn, 0, 4); + op1 = field(insn, 8, 2); + op2 = field(insn, 6, 2); + ra = field(insn, 16, 5); + rb = field(insn, 11, 5); + rd = field(insn, 21, 5); + + switch (op0) { + case 0x0000: + switch (op1) { + case 0x00: /*l.add*/ + LOG_DIS("l.add r%d, r%d, r%d\n", rd, ra, rb); + gen_helper_add(cpu_R[rd], cpu_env, cpu_R[ra], cpu_R[rb]); + break; + default: + gen_illegal_exception(dc); + break; + } + break; + + case 0x0001: /*l.addc*/ + switch (op1) { + case 0x00: + LOG_DIS("l.addc r%d, r%d, r%d\n", rd, ra, rb); + gen_helper_addc(cpu_R[rd], cpu_env, cpu_R[ra], cpu_R[rb]); + break; + default: + gen_illegal_exception(dc); + break; + } + break; + + case 0x0002: /*l.sub*/ + switch (op1) { + case 0x00: + LOG_DIS("l.sub r%d, r%d, r%d\n", rd, ra, rb); + gen_helper_sub(cpu_R[rd], cpu_env, cpu_R[ra], cpu_R[rb]); + break; + default: + gen_illegal_exception(dc); + break; + } + break; + + case 0x0003: /*l.and*/ + switch (op1) { + case 0x00: + 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; + + case 0x0004: /*l.or*/ + switch (op1) { + case 0x00: + 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; + + case 0x0005: + switch (op1) { + case 0x00: /*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); + if (ra != 0 && rb != 0) { + gen_helper_mul(cpu_R[rd], cpu_env, cpu_R[ra], cpu_R[rb]); + } else { + tcg_gen_movi_tl(cpu_R[rd], 0x0); + } + 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); + { + int lab0 = gen_new_label(); + int lab1 = gen_new_label(); + int lab2 = gen_new_label(); + TCGv_i32 sr_ove = tcg_temp_local_new_i32(); + tcg_gen_andi_tl(sr_ove, cpu_sr, SR_OVE); + if (rb == 0) { + tcg_gen_ori_tl(cpu_sr, cpu_sr, SR_OV | SR_CY); + 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], + 0xffffffff, lab2); + tcg_gen_brcondi_tl(TCG_COND_NE, cpu_R[rb], + 0x80000000, lab2); + gen_set_label(lab1); + tcg_gen_ori_tl(cpu_sr, cpu_sr, SR_OV | SR_CY); + tcg_gen_brcondi_tl(TCG_COND_NE, sr_ove, SR_OVE, lab2); + gen_exception(dc, EXCP_RANGE); + gen_set_label(lab2); + tcg_gen_div_tl(cpu_R[rd], cpu_R[ra], cpu_R[rb]); + } + tcg_temp_free_i32(sr_ove); + } + 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); + { + int lab0 = gen_new_label(); + int lab1 = gen_new_label(); + TCGv_i32 sr_ove = tcg_temp_local_new_i32(); + tcg_gen_andi_tl(sr_ove, cpu_sr, SR_OVE); + if (rb == 0) { + tcg_gen_ori_tl(cpu_sr, cpu_sr, SR_OV | SR_CY); + 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_brcondi_tl(TCG_COND_NE, sr_ove, SR_OVE, lab1); + gen_exception(dc, EXCP_RANGE); + gen_set_label(lab1); + tcg_gen_divu_tl(cpu_R[rd], cpu_R[ra], cpu_R[rb]); + } + tcg_temp_free_i32(sr_ove); + } + break; + + default: + gen_illegal_exception(dc); + break; + } + break; + + case 0x000b: + 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_new_i64(); + TCGv_i64 tra = tcg_temp_new_i64(); + TCGv_i64 trb = tcg_temp_new_i64(); + TCGv high = tcg_temp_new(); + TCGv_i32 sr_ove = tcg_temp_new(); + int lab = gen_new_label(); + 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(tra); + tcg_temp_free(trb); + tcg_gen_shri_i64(high, result, TARGET_LONG_BITS); + tcg_gen_brcondi_tl(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(high); + tcg_gen_trunc_i64_tl(cpu_R[rd], result); + tcg_temp_free(result); + tcg_temp_free(sr_ove); + } else { + tcg_gen_movi_tl(cpu_R[rd], 0); + } + break; + + default: + gen_illegal_exception(dc); + break; + } + break; + + case 0x000e: + switch (op1) { + case 0x00: /*l.cmov*/ + LOG_DIS("l.cmov r%d, r%d, r%d\n", rd, ra, rb); + { + int lab = gen_new_label(); + TCGv res = tcg_temp_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_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); + } + break; + + default: + gen_illegal_exception(dc); + break; + } + break; + + case 0x000f: + switch (op1) { + case 0x00: /*l.ff1*/ + LOG_DIS("l.ff1 r%d, r%d, r%d\n", rd, ra, rb); + gen_helper_ff1(cpu_R[rd], cpu_R[ra]); + break; + case 0x01: /*l.fl1*/ + LOG_DIS("l.fl1 r%d, r%d, r%d\n", rd, ra, rb); + gen_helper_fl1(cpu_R[rd], cpu_R[ra]); + break; + + default: + gen_illegal_exception(dc); + break; + } + 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; + } + 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 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; + + default: + gen_illegal_exception(dc); + break; + } + break; + + default: + gen_illegal_exception(dc); + break; + } + break; + + default: + gen_illegal_exception(dc); + break; + } +} + +static void dec_misc(DisasContext *dc, CPUOpenRISCState *env, uint32_t insn) +{ + uint32_t op0, op1; + uint32_t ra, rb, rd; + uint32_t /*L6, K5, */I16, I5, I11, N26, tmp; + op0 = field(insn, 26, 6); + op1 = field(insn, 24, 2); + ra = field(insn, 16, 5); + rb = field(insn, 11, 5); + rd = field(insn, 21, 5); + /*L6 = field(insn, 5, 6); + K5 = field(insn, 0, 5);*/ + I16 = field(insn, 0, 16); + I5 = field(insn, 21, 5); + I11 = field(insn, 0, 11); + N26 = field(insn, 0, 26); + tmp = (I5<<11) + I11; + + switch (op0) { + case 0x00: /*l.j*/ + LOG_DIS("l.j %d\n", N26); + case 0x01: /*l.jal*/ + LOG_DIS("l.jal %d\n", N26); + case 0x03: /*l.bnf*/ + LOG_DIS("l.bnf %d\n", N26); + case 0x04: /*l.bf*/ + LOG_DIS("l.bf %d\n", N26); + + gen_jump(dc, N26, 0, op0); + break; + + case 0x05: + switch (op1) { + case 0x01: /*l.nop*/ + LOG_DIS("l.nop %d\n", I16); + break; + + default: + gen_illegal_exception(dc); + break; + } + break; + + case 0x11: /*l.jr*/ + LOG_DIS("l.jr r%d\n", rb); + case 0x12: /*l.jalr*/ + LOG_DIS("l.jalr r%d\n", rb); + + gen_jump(dc, 0, rb, op0); + break; + + case 0x13: /*l.maci*/ + LOG_DIS("l.maci %d, r%d, %d\n", I5, ra, I11); + { + TCGv t1 = tcg_temp_new(); + TCGv t2 = tcg_temp_new(); + TCGv ttmp = tcg_const_tl(tmp); /* store machi maclo*/ + tcg_gen_mul_tl(ttmp, cpu_R[ra], ttmp); + tcg_gen_ext_i32_i64(t1, ttmp); + tcg_gen_concat_i32_i64(t2, maclo, machi); + tcg_gen_add_i64(t2, t2, t1); + tcg_gen_trunc_i64_i32(maclo, t2); + tcg_gen_shri_i64(t2, t2, 32); + tcg_gen_trunc_i64_i32(machi, t2); + tcg_temp_free(ttmp); + tcg_temp_free(t1); + tcg_temp_free(t2); + } + break; + + case 0x09: /*l.rfe*/ + LOG_DIS("l.rfe\n"); + { + gen_helper_rfe(cpu_env); + dc->is_jmp = DISAS_UPDATE; + } + break; + + case 0x1c: /*l.cust1*/ + LOG_DIS("l.cust1\n"); + break; + + case 0x1d: /*l.cust2*/ + LOG_DIS("l.cust2\n"); + break; + + case 0x1e: /*l.cust3*/ + LOG_DIS("l.cust3\n"); + break; + + case 0x1f: /*l.cust4*/ + LOG_DIS("l.cust4\n"); + break; + + case 0x3c: /*l.cust5*/ + /*LOG_DIS("l.cust5 r%d, r%d, r%d, %d, %d\n", rd, ra, rb, L6, K5);*/ + break; + + case 0x3d: /*l.cust6*/ + LOG_DIS("l.cust6\n"); + break; + + case 0x3e: /*l.cust7*/ + LOG_DIS("l.cust7\n"); + break; + + case 0x3f: /*l.cust8*/ + LOG_DIS("l.cust8\n"); + break; + + case 0x20: /*l.ld*/ + LOG_DIS("l.ld r%d, r%d, %d\n", rd, ra, I16); + { + check_ob64s(dc); + TCGv_i64 t0 = tcg_temp_new_i64(); + tcg_gen_addi_i64(t0, cpu_R[ra], sign_extend(I16, 16)); + tcg_gen_qemu_ld64(cpu_R[rd], t0, dc->mem_idx); + tcg_temp_free_i64(t0); + } + break; + + case 0x21: /*l.lwz*/ + LOG_DIS("l.lwz r%d, r%d, %d\n", rd, ra, I16); + { + TCGv t0 = tcg_temp_new(); + tcg_gen_addi_tl(t0, cpu_R[ra], sign_extend(I16, 16)); + tcg_gen_qemu_ld32u(cpu_R[rd], t0, dc->mem_idx); + tcg_temp_free(t0); + } + break; + + case 0x22: /*l.lws*/ + LOG_DIS("l.lws r%d, r%d, %d\n", rd, ra, I16); + { + TCGv t0 = tcg_temp_new(); + tcg_gen_addi_tl(t0, cpu_R[ra], sign_extend(I16, 16)); + tcg_gen_qemu_ld32s(cpu_R[rd], t0, dc->mem_idx); + tcg_temp_free(t0); + } + break; + + case 0x23: /*l.lbz*/ + LOG_DIS("l.lbz r%d, r%d, %d\n", rd, ra, I16); + { + TCGv t0 = tcg_temp_new(); + tcg_gen_addi_tl(t0, cpu_R[ra], sign_extend(I16, 16)); + tcg_gen_qemu_ld8u(cpu_R[rd], t0, dc->mem_idx); + tcg_temp_free(t0); + } + break; + + case 0x24: /*l.lbs*/ + LOG_DIS("l.lbs r%d, r%d, %d\n", rd, ra, I16); + { + TCGv t0 = tcg_temp_new(); + tcg_gen_addi_tl(t0, cpu_R[ra], sign_extend(I16, 16)); + tcg_gen_qemu_ld8s(cpu_R[rd], t0, dc->mem_idx); + tcg_temp_free(t0); + } + break; + + case 0x25: /*l.lhz*/ + LOG_DIS("l.lhz r%d, r%d, %d\n", rd, ra, I16); + { + TCGv t0 = tcg_temp_new(); + tcg_gen_addi_tl(t0, cpu_R[ra], sign_extend(I16, 16)); + tcg_gen_qemu_ld16u(cpu_R[rd], t0, dc->mem_idx); + tcg_temp_free(t0); + } + break; + + case 0x26: /*l.lhs*/ + LOG_DIS("l.lhs r%d, r%d, %d\n", rd, ra, I16); + { + TCGv t0 = tcg_temp_new(); + tcg_gen_addi_tl(t0, cpu_R[ra], sign_extend(I16, 16)); + tcg_gen_qemu_ld16s(cpu_R[rd], t0, dc->mem_idx); + tcg_temp_free(t0); + } + break; + + case 0x27: /*l.addi*/ + LOG_DIS("l.addi r%d, r%d, %d\n", rd, ra, I16); + { + TCGv t0 = tcg_const_tl(sign_extend(I16, 16)); + gen_helper_add(cpu_R[rd], cpu_env, 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); + { + TCGv t0 = tcg_const_tl(sign_extend(I16, 16)); + gen_helper_addc(cpu_R[rd], cpu_env, cpu_R[ra], t0); + tcg_temp_free(t0); + } + 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)); + 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)); + 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)); + break; + + case 0x2c: /*l.muli*/ + LOG_DIS("l.muli r%d, r%d, %d\n", rd, ra, I16); + if (ra != 0 && I16 != 0) { + TCGv i16 = tcg_const_tl(I16); + gen_helper_mul(cpu_R[rd], cpu_env, cpu_R[ra], i16); + tcg_temp_free(i16); + } else { + tcg_gen_movi_tl(cpu_R[rd], 0x0); + } + break; + + case 0x2d: /*l.mfspr*/ + LOG_DIS("l.mfspr r%d, r%d, %d\n", rd, ra, I16); + break; + + case 0x30: /*l.mtspr*/ + LOG_DIS("l.mtspr %d, r%d, r%d, %d\n", I5, ra, rb, I11); + break; + + case 0x34: /*l.sd*/ + LOG_DIS("l.sd %d, r%d, r%d, %d\n", I5, ra, rb, I11); + { + check_ob64s(dc); + TCGv_i64 t0 = tcg_temp_new_i64(); + tcg_gen_addi_tl(t0, cpu_R[ra], sign_extend(tmp, 16)); + tcg_gen_qemu_st64(cpu_R[rb], t0, dc->mem_idx); + tcg_temp_free_i64(t0); + } + break; + + case 0x35: /*l.sw*/ + LOG_DIS("l.sw %d, r%d, r%d, %d\n", I5, ra, rb, I11); + { + TCGv t0 = tcg_temp_new(); + tcg_gen_addi_tl(t0, cpu_R[ra], sign_extend(tmp, 16)); + tcg_gen_qemu_st32(cpu_R[rb], t0, dc->mem_idx); + tcg_temp_free(t0); + } + break; + + case 0x36: /*l.sb*/ + LOG_DIS("l.sb %d, r%d, r%d, %d\n", I5, ra, rb, I11); + { + TCGv t0 = tcg_temp_new(); + tcg_gen_addi_tl(t0, cpu_R[ra], sign_extend(tmp, 16)); + tcg_gen_qemu_st8(cpu_R[rb], t0, dc->mem_idx); + tcg_temp_free(t0); + } + break; + + case 0x37: /*l.sh*/ + LOG_DIS("l.sh %d, r%d, r%d, %d\n", I5, ra, rb, I11); + { + TCGv t0 = tcg_temp_new(); + tcg_gen_addi_tl(t0, cpu_R[ra], sign_extend(tmp, 16)); + tcg_gen_qemu_st16(cpu_R[rb], t0, dc->mem_idx); + tcg_temp_free(t0); + } + break; + + default: + gen_illegal_exception(dc); + break; + } +} + +static void dec_mac(DisasContext *dc, CPUOpenRISCState *env, uint32_t insn) +{ + uint32_t op0; + uint32_t ra, rb; + op0 = field(insn, 0, 4); + ra = field(insn, 16, 5); + rb = field(insn, 11, 5); + + switch (op0) { + case 0x0001: /*l.mac*/ + LOG_DIS("l.mac r%d, r%d\n", ra, rb); + { + TCGv t0 = tcg_temp_new(); + TCGv_i64 t1 = tcg_temp_new(); + TCGv_i64 t2 = tcg_temp_new(); + 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_trunc_i64_i32(maclo, t2); + tcg_gen_shri_i64(t2, t2, 32); + tcg_gen_trunc_i64_i32(machi, t2); + tcg_temp_free(t0); + tcg_temp_free(t1); + tcg_temp_free(t2); + } + break; + + case 0x0002: /*l.msb*/ + LOG_DIS("l.msb r%d, r%d\n", ra, rb); + { + TCGv_i64 t0 = tcg_temp_new(); + TCGv_i64 t1 = tcg_temp_new(); + TCGv_i64 t2 = tcg_temp_new(); + 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_trunc_i64_i32(maclo, t2); + tcg_gen_shri_i64(t2, t2, 32); + tcg_gen_trunc_i64_i32(machi, t2); + tcg_temp_free(t0); + tcg_temp_free(t1); + tcg_temp_free(t2); + } + break; + + default: + gen_illegal_exception(dc); + break; + } +} + +static void dec_logic(DisasContext *dc, CPUOpenRISCState *env, uint32_t insn) +{ + uint32_t op0; + uint32_t rd, ra, L6; + op0 = field(insn, 6, 2); + rd = field(insn, 21, 5); + ra = field(insn, 16, 5); + L6 = field(insn, 0, 6); + + 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)); + 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)); + 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; + + 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)); + break; + + default: + gen_illegal_exception(dc); + break; + } +} + +static void dec_M(DisasContext *dc, CPUOpenRISCState *env, uint32_t insn) +{ + uint32_t op0; + uint32_t rd; + uint32_t K16; + op0 = field(insn, 16, 1); + rd = field(insn, 21, 5); + K16 = field(insn, 0, 16); + + switch (op0) { + case 0x0: /*l.movhi*/ + LOG_DIS("l.movhi r%d, %d\n", rd, K16); + tcg_gen_movi_tl(cpu_R[rd], (K16 << 16)); + break; + + 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); + break; + + default: + gen_illegal_exception(dc); + break; + } +} + +static void dec_comp(DisasContext *dc, CPUOpenRISCState *env, uint32_t insn) +{ + uint32_t op0; + uint32_t ra, rb; + + op0 = field(insn, 21, 5); + ra = field(insn, 16, 5); + rb = field(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]); + + 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]); + 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]); + 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]); + 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]); + 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]); + 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]); + 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]); + 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]); + 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]); + 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]); + break; + + default: + gen_illegal_exception(dc); + break; + } + wb_SR_F(); +} + +static void dec_compi(DisasContext *dc, CPUOpenRISCState *env, uint32_t insn) +{ + uint32_t op0; + uint32_t ra, I16; + + op0 = field(insn, 21, 5); + ra = field(insn, 16, 5); + I16 = field(insn, 0, 16); + + tcg_gen_movi_i32(env_btaken, 0x0); + I16 = sign_extend(I16, 16); + + 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); + 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); + 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); + 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); + 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); + 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); + 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); + 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); + 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); + 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); + break; + + default: + gen_illegal_exception(dc); + break; + } + wb_SR_F(); +} + +static void dec_sys(DisasContext *dc, CPUOpenRISCState *env, uint32_t insn) +{ + uint32_t op0; + /*uint32_t K16;*/ + op0 = field(insn, 16, 8); + /*K16 = field(insn, 0, 16);*/ + + switch (op0) { + case 0x000: /*l.sys*/ + /*LOG_DIS("l.sys %d\n", K16);*/ + tcg_gen_movi_tl(cpu_pc, dc->pc); + gen_exception(dc, EXCP_SYSCALL); + dc->is_jmp = DISAS_UPDATE; + break; + + case 0x100: /*l.trap*/ + /*LOG_DIS("l.trap %d\n", K16);*/ + tcg_gen_movi_tl(cpu_pc, dc->pc); + gen_exception(dc, EXCP_TRAP); + break; + + case 0x300: /*l.csync*/ + LOG_DIS("l.csync\n"); + break; + + case 0x200: /*l.msync*/ + LOG_DIS("l.msync\n"); + break; + + case 0x270: /*l.psync*/ + LOG_DIS("l.psync\n"); + break; + + default: + gen_illegal_exception(dc); + break; + } +} + +static void dec_float(DisasContext *dc, CPUOpenRISCState *env, uint32_t insn) +{ + uint32_t op0; + uint32_t ra, rb, rd; + op0 = field(insn, 0, 8); + ra = field(insn, 16, 5); + rb = field(insn, 11, 5); + rd = field(insn, 21, 5); + + switch (op0) { + case 0x10: /*lf.add.d*/ + LOG_DIS("lf.add.d r%d, r%d, r%d\n", rd, ra, rb); + check_of64s(dc); + gen_helper_float_add_d(cpu_R[rd], cpu_env, cpu_R[ra], cpu_R[rb]); + break; + + case 0x00: /*lf.add.s*/ + LOG_DIS("lf.add.s r%d, r%d, r%d\n", rd, ra, rb); + gen_helper_float_add_s(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); + gen_helper_float_sub_d(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); + gen_helper_float_sub_s(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); + } + 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); + } + break; + + case 0x13: /*lf.div.d*/ + LOG_DIS("lf.div.d r%d, r%d, r%d\n", rd, ra, rb); + check_of64s(dc); + gen_helper_float_div_d(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); + gen_helper_float_div_s(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); + gen_helper_itofd(cpu_R[rd], cpu_env, cpu_R[ra]); + break; + + case 0x04: /*lf.itof.s*/ + LOG_DIS("lf.itof r%d, r%d\n", rd, ra); + gen_helper_itofs(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); + gen_helper_ftoid(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); + gen_helper_ftois(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); + gen_helper_float_rem_d(cpu_R[rd], cpu_env, cpu_R[ra], cpu_R[rb]); + break; + + case 0x06: /*lf.rem.s*/ + LOG_DIS("lf.rem.s r%d, r%d, r%d\n", rd, ra, rb); + gen_helper_float_rem_s(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); + gen_helper_float_muladd_d(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); + gen_helper_float_muladd_s(cpu_R[rd], cpu_env, cpu_R[ra], cpu_R[rb]); + break; + + 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]); + break; + + 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]); + 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]); + 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]); + 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]); + 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]); + 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]); + 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]); + 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]); + 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]); + 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]); + 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]); + break; + + default: + gen_illegal_exception(dc); + break; + } + wb_SR_F(); +} + +static void disas_openrisc_insn(DisasContext *dc, CPUOpenRISCState *env) +{ + uint32_t op0; + uint32_t insn; + insn = cpu_ldl_code(env, dc->pc); + op0 = field(insn, 26, 6); + + switch (op0) { + case 0x06: + dec_M(dc, env, insn); + break; + + case 0x08: + dec_sys(dc, env, insn); + break; + + case 0x2e: + dec_logic(dc, env, insn); + break; + + case 0x2f: + dec_compi(dc, env, insn); + break; + + case 0x31: + dec_mac(dc, env, insn); + break; + + case 0x32: + dec_float(dc, env, insn); + break; + + case 0x38: + dec_calc(dc, env, insn); + break; + + case 0x39: + dec_comp(dc, env, insn); + break; + + default: + dec_misc(dc, env, insn); + break; + } +} + +static void check_breakpoint(CPUOpenRISCState *env, DisasContext *dc) +{ + CPUBreakpoint *bp; + + if (unlikely(!QTAILQ_EMPTY(&env->breakpoints))) { + QTAILQ_FOREACH(bp, &env->breakpoints, entry) { + if (bp->pc == dc->pc) { + tcg_gen_movi_tl(cpu_pc, dc->pc); + gen_exception(dc, EXCP_DEBUG); + dc->is_jmp = DISAS_UPDATE; + } + } + } } static inline void gen_intermediate_code_internal(CPUOpenRISCState *env, TranslationBlock *tb, int search_pc) { + struct DisasContext ctx, *dc = &ctx; + uint16_t *gen_opc_end; + uint32_t pc_start; + int j, k; + uint32_t next_page_start; + int num_insns; + int max_insns; + + qemu_log_try_set_file(stderr); + + pc_start = tb->pc; + dc->env = env; + dc->tb = tb; + + gen_opc_end = gen_opc_buf + OPC_MAX_SIZE; + dc->is_jmp = DISAS_NEXT; + dc->ppc = pc_start; + dc->pc = pc_start; + dc->flags = env->cpucfgr; + dc->mem_idx = cpu_mmu_index(env); + dc->synced_flags = dc->tb_flags = tb->flags; + dc->delayed_branch = !!(dc->tb_flags & D_FLAG); + dc->singlestep_enabled = env->singlestep_enabled; + if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)) { + qemu_log("-----------------------------------------\n"); + log_cpu_state(env, 0); + } + + next_page_start = (pc_start & TARGET_PAGE_MASK) + TARGET_PAGE_SIZE; + k = -1; + num_insns = 0; + max_insns = tb->cflags & CF_COUNT_MASK; + + if (max_insns == 0) { + max_insns = CF_COUNT_MASK; + } + + gen_icount_start(); + + do { + check_breakpoint(env, dc); + if (search_pc) { + j = gen_opc_ptr - gen_opc_buf; + if (k < j) { + k++; + while (k < j) { + gen_opc_instr_start[k++] = 0; + } + } + gen_opc_pc[k] = dc->pc; + gen_opc_instr_start[k] = 1; + gen_opc_icount[k] = num_insns; + } + + if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP))) { + tcg_gen_debug_insn_start(dc->pc); + } + + if (num_insns + 1 == 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, env); + dc->pc = dc->npc; + num_insns++; + /* delay slot */ + 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_mov_tl(cpu_npc, jmp_pc); + tcg_gen_movi_tl(jmp_pc, 0); + tcg_gen_exit_tb(0); + dc->is_jmp = DISAS_JUMP; + break; + } + } + } while (!dc->is_jmp + && gen_opc_ptr < gen_opc_end + && !env->singlestep_enabled + && !singlestep + && (dc->pc < next_page_start) + && num_insns < max_insns); + + if (tb->cflags & CF_LAST_IO) { + gen_io_end(); + } + if (dc->is_jmp == DISAS_NEXT) { + dc->is_jmp = DISAS_UPDATE; + tcg_gen_movi_tl(cpu_pc, dc->pc); + } + if (unlikely(env->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) { + case DISAS_NEXT: + gen_goto_tb(dc, 0, dc->pc); + break; + default: + case DISAS_JUMP: + break; + case DISAS_UPDATE: + /* indicate that the hash table must be used + to find the next TB */ + tcg_gen_exit_tb(0); + break; + case DISAS_TB_JUMP: + /* nothing more to generate */ + break; + } + } + + gen_icount_end(tb, num_insns); + *gen_opc_ptr = INDEX_op_end; + if (search_pc) { + j = gen_opc_ptr - gen_opc_buf; + k++; + while (k <= j) { + gen_opc_instr_start[k++] = 0; + } + } else { + tb->size = dc->pc - pc_start; + tb->icount = num_insns; + } + +#ifdef DEBUG_DISAS + if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)) { + qemu_log("\n"); + log_target_disas(pc_start, dc->pc - pc_start, 0); + qemu_log("\nisize=%d osize=%td\n", + dc->pc - pc_start, gen_opc_ptr - gen_opc_buf); + } +#endif } void gen_intermediate_code(CPUOpenRISCState *env, struct TranslationBlock *tb)
Add OpenRISC translation routines. Signed-off-by: Jia Liu <proljc@gmail.com> --- target-openrisc/translate.c | 1523 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 1523 insertions(+)