* Re: [Qemu-devel] [PATCH v8 08/16] target-or32: Add instruction translation [not found] ` <1341110730-444-9-git-send-email-proljc@gmail.com> @ 2012-07-03 18:48 ` Blue Swirl 2012-07-04 2:23 ` Jia Liu 0 siblings, 1 reply; 9+ messages in thread From: Blue Swirl @ 2012-07-03 18:48 UTC (permalink / raw) To: Jia Liu; +Cc: qemu-devel On Sun, Jul 1, 2012 at 2:45 AM, Jia Liu <proljc@gmail.com> wrote: > Add OpenRISC instruction tanslation routines. > > Signed-off-by: Jia Liu <proljc@gmail.com> > --- > target-openrisc/translate.c | 1678 +++++++++++++++++++++++++++++++++++++++++++ > 1 file changed, 1678 insertions(+) > > diff --git a/target-openrisc/translate.c b/target-openrisc/translate.c > index 4d4aa23..b69722c 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,1688 @@ > # define LOG_DIS(...) do { } while (0) > #endif > > +typedef struct DisasContext { > + 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_i32(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; > +} > + > +#ifdef TARGET_OPENRISC64 > +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); > + } > +}*/ > +#endif > + > +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, 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); > + { > + int lab = gen_new_label(); > + TCGv_i64 ta = tcg_temp_new_i64(); > + TCGv_i64 tb = tcg_temp_new_i64(); > + TCGv_i64 td = tcg_temp_local_new_i64(); > + TCGv_i32 res = tcg_temp_local_new_i32(); > + TCGv_i32 sr_ove = tcg_temp_local_new_i32(); > + tcg_gen_extu_i32_i64(ta, cpu_R[ra]); > + tcg_gen_extu_i32_i64(tb, cpu_R[rb]); > + tcg_gen_add_i64(td, ta, tb); > + tcg_gen_trunc_i64_i32(res, td); > + tcg_gen_shri_i64(td, td, 31); > + tcg_gen_andi_i64(td, td, 0x3); > + /* Jump to lab when no overflow. */ > + tcg_gen_brcondi_i64(TCG_COND_EQ, td, 0x0, lab); > + tcg_gen_brcondi_i64(TCG_COND_EQ, td, 0x3, lab); > + tcg_gen_ori_i32(cpu_sr, cpu_sr, (SR_OV | SR_CY)); > + tcg_gen_andi_i32(sr_ove, cpu_sr, SR_OVE); > + tcg_gen_brcondi_i32(TCG_COND_NE, sr_ove, SR_OVE, lab); > + gen_exception(dc, EXCP_RANGE); > + gen_set_label(lab); > + tcg_gen_mov_i32(cpu_R[rd], res); > + tcg_temp_free_i64(ta); > + tcg_temp_free_i64(tb); > + tcg_temp_free_i64(td); > + tcg_temp_free_i32(res); > + tcg_temp_free_i32(sr_ove); > + } > + 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); > + { > + int lab = gen_new_label(); > + TCGv_i64 ta = tcg_temp_new_i64(); > + TCGv_i64 tb = tcg_temp_new_i64(); > + TCGv_i64 tcy = tcg_temp_local_new_i64(); > + TCGv_i64 td = tcg_temp_local_new_i64(); > + TCGv_i32 res = tcg_temp_local_new_i32(); > + TCGv_i32 sr_cy = tcg_temp_local_new_i32(); > + TCGv_i32 sr_ove = tcg_temp_local_new_i32(); > + tcg_gen_extu_i32_i64(ta, cpu_R[ra]); > + tcg_gen_extu_i32_i64(tb, cpu_R[rb]); > + tcg_gen_andi_i32(sr_cy, cpu_sr, SR_CY); > + tcg_gen_extu_i32_i64(tcy, sr_cy); > + tcg_gen_shri_i64(tcy, tcy, 10); > + tcg_gen_add_i64(td, ta, tb); > + tcg_gen_add_i64(td, td, tcy); > + tcg_gen_trunc_i64_i32(res, td); > + tcg_gen_shri_i64(td, td, 32); > + tcg_gen_andi_i64(td, td, 0x3); > + /* Jump to lab when no overflow. */ > + tcg_gen_brcondi_i64(TCG_COND_EQ, td, 0x0, lab); > + tcg_gen_brcondi_i64(TCG_COND_EQ, td, 0x3, lab); > + tcg_gen_ori_i32(cpu_sr, cpu_sr, (SR_OV | SR_CY)); > + tcg_gen_andi_i32(sr_ove, cpu_sr, SR_OVE); > + tcg_gen_brcondi_i32(TCG_COND_NE, sr_ove, SR_OVE, lab); > + gen_exception(dc, EXCP_RANGE); > + gen_set_label(lab); > + tcg_gen_mov_i32(cpu_R[rd], res); > + tcg_temp_free_i64(ta); > + tcg_temp_free_i64(tb); > + tcg_temp_free_i64(tcy); > + tcg_temp_free_i64(td); > + tcg_temp_free_i32(res); > + tcg_temp_free_i32(sr_cy); > + tcg_temp_free_i32(sr_ove); > + } > + 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); > + { > + int lab = gen_new_label(); > + TCGv_i64 ta = tcg_temp_new_i64(); > + TCGv_i64 tb = tcg_temp_new_i64(); > + TCGv_i64 td = tcg_temp_local_new_i64(); > + TCGv_i32 res = tcg_temp_local_new_i32(); > + TCGv_i32 sr_ove = tcg_temp_local_new_i32(); > + > + tcg_gen_extu_i32_i64(ta, cpu_R[ra]); > + tcg_gen_extu_i32_i64(tb, cpu_R[rb]); > + tcg_gen_sub_i64(td, ta, tb); > + tcg_gen_trunc_i64_i32(res, td); > + tcg_gen_shri_i64(td, td, 31); > + tcg_gen_andi_i64(td, td, 0x3); > + /* Jump to lab when no overflow. */ > + tcg_gen_brcondi_i64(TCG_COND_EQ, td, 0x0, lab); > + tcg_gen_brcondi_i64(TCG_COND_EQ, td, 0x3, lab); > + tcg_gen_ori_i32(cpu_sr, cpu_sr, (SR_OV | SR_CY)); > + tcg_gen_andi_i32(sr_ove, cpu_sr, SR_OVE); > + tcg_gen_brcondi_i32(TCG_COND_NE, sr_ove, SR_OVE, lab); > + gen_exception(dc, EXCP_RANGE); > + gen_set_label(lab); > + tcg_gen_mov_i32(cpu_R[rd], res); > + tcg_temp_free_i64(ta); > + tcg_temp_free_i64(tb); > + tcg_temp_free_i64(td); > + tcg_temp_free_i32(res); > + tcg_temp_free_i32(sr_ove); > + } > + 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_mul32(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(); > + int lab3 = gen_new_label(); > + TCGv_i32 sr_ove = tcg_temp_local_new_i32(); > + if (rb == 0) { > + tcg_gen_ori_tl(cpu_sr, cpu_sr, (SR_OV | SR_CY)); > + tcg_gen_andi_tl(sr_ove, cpu_sr, SR_OVE); > + tcg_gen_brcondi_tl(TCG_COND_NE, sr_ove, SR_OVE, lab0); > + gen_exception(dc, EXCP_RANGE); > + gen_set_label(lab0); > + } else { > + tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_R[rb], > + 0x00000000, lab1); > + tcg_gen_brcondi_tl(TCG_COND_NE, cpu_R[ra], > + 0x80000000, lab2); > + tcg_gen_brcondi_tl(TCG_COND_NE, cpu_R[rb], > + 0xffffffff, lab2); > + gen_set_label(lab1); > + tcg_gen_ori_tl(cpu_sr, cpu_sr, (SR_OV | SR_CY)); > + tcg_gen_andi_tl(sr_ove, cpu_sr, SR_OVE); > + tcg_gen_brcondi_tl(TCG_COND_NE, sr_ove, SR_OVE, lab3); > + gen_exception(dc, EXCP_RANGE); > + gen_set_label(lab2); > + tcg_gen_div_tl(cpu_R[rd], cpu_R[ra], cpu_R[rb]); > + gen_set_label(lab3); > + } > + tcg_temp_free_i32(sr_ove); > + } > + 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(); > + int lab2 = gen_new_label(); > + TCGv_i32 sr_ove = tcg_temp_local_new_i32(); > + if (rb == 0) { > + tcg_gen_ori_tl(cpu_sr, cpu_sr, (SR_OV | SR_CY)); > + tcg_gen_andi_tl(sr_ove, cpu_sr, SR_OVE); > + tcg_gen_brcondi_tl(TCG_COND_NE, sr_ove, SR_OVE, lab0); > + gen_exception(dc, EXCP_RANGE); > + gen_set_label(lab0); > + } else { > + tcg_gen_brcondi_tl(TCG_COND_NE, cpu_R[rb], > + 0x00000000, lab1); > + tcg_gen_ori_tl(cpu_sr, cpu_sr, (SR_OV | SR_CY)); > + tcg_gen_andi_tl(sr_ove, cpu_sr, SR_OVE); > + tcg_gen_brcondi_tl(TCG_COND_NE, sr_ove, SR_OVE, lab2); > + gen_exception(dc, EXCP_RANGE); > + gen_set_label(lab1); > + tcg_gen_divu_tl(cpu_R[rd], cpu_R[ra], cpu_R[rb]); > + gen_set_label(lab2); > + } > + tcg_temp_free_i32(sr_ove); > + } > + 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_local_new_i64(); > + TCGv_i64 tra = tcg_temp_local_new_i64(); > + TCGv_i64 trb = tcg_temp_local_new_i64(); > + TCGv_i64 high = tcg_temp_new_i64(); > + TCGv_i32 sr_ove = tcg_temp_local_new_i32(); > + int lab = gen_new_label(); > + /* Calculate the each result. */ > + tcg_gen_extu_i32_i64(tra, cpu_R[ra]); > + tcg_gen_extu_i32_i64(trb, cpu_R[rb]); > + tcg_gen_mul_i64(result, tra, trb); > + tcg_temp_free_i64(tra); > + tcg_temp_free_i64(trb); > + tcg_gen_shri_i64(high, result, TARGET_LONG_BITS); > + /* Overflow or not. */ > + tcg_gen_brcondi_i64(TCG_COND_EQ, high, 0x00000000, lab); > + tcg_gen_ori_tl(cpu_sr, cpu_sr, (SR_OV | SR_CY)); > + tcg_gen_andi_tl(sr_ove, cpu_sr, SR_OVE); > + tcg_gen_brcondi_tl(TCG_COND_NE, sr_ove, SR_OVE, lab); > + gen_exception(dc, EXCP_RANGE); > + gen_set_label(lab); > + tcg_temp_free_i64(high); > + tcg_gen_trunc_i64_tl(cpu_R[rd], result); > + tcg_temp_free_i64(result); > + tcg_temp_free_i32(sr_ove); > + } else { > + tcg_gen_movi_tl(cpu_R[rd], 0); > + } > + 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_local_new(); > + TCGv sr_f = tcg_temp_new(); > + tcg_gen_andi_tl(sr_f, cpu_sr, SR_F); > + tcg_gen_mov_tl(res, cpu_R[rb]); > + tcg_gen_brcondi_tl(TCG_COND_NE, sr_f, SR_F, lab); > + tcg_gen_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, 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); The cases 0x00 to 0x03 will fall through to this case, calling LOG_DIS one to four times. > + 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); Also here. > + break; > + > + case 0x13: /* l.maci */ > + LOG_DIS("l.maci %d, r%d, %d\n", I5, ra, I11); > + { > + TCGv_i64 t1 = tcg_temp_new_i64(); > + TCGv_i64 t2 = tcg_temp_new_i64(); > + TCGv_i32 dst = tcg_temp_new_i32(); > + TCGv ttmp = tcg_const_tl(tmp); > + tcg_gen_mul_tl(dst, cpu_R[ra], ttmp); > + tcg_gen_ext_i32_i64(t1, dst); > + tcg_gen_concat_i32_i64(t2, maclo, machi); > + tcg_gen_add_i64(t2, t2, t1); > + tcg_gen_trunc_i64_i32(maclo, t2); > + tcg_gen_shri_i64(t2, t2, 32); > + tcg_gen_trunc_i64_i32(machi, t2); > + tcg_temp_free_i32(dst); > + tcg_temp_free(ttmp); > + tcg_temp_free_i64(t1); > + tcg_temp_free_i64(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); > + { > +#ifdef TARGET_OPENRISC64 > + 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); > +#endif > + } > + 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); > + { > + int lab = gen_new_label(); > + TCGv_i64 ta = tcg_temp_new_i64(); > + TCGv_i64 td = tcg_temp_local_new_i64(); > + TCGv_i32 res = tcg_temp_local_new_i32(); > + TCGv_i32 sr_ove = tcg_temp_local_new_i32(); > + tcg_gen_extu_i32_i64(ta, cpu_R[ra]); > + tcg_gen_addi_i64(td, ta, sign_extend(I16, 16)); > + tcg_gen_trunc_i64_i32(res, td); > + tcg_gen_shri_i64(td, td, 32); > + tcg_gen_andi_i64(td, td, 0x3); > + /* Jump to lab when no overflow. */ > + tcg_gen_brcondi_i64(TCG_COND_EQ, td, 0x0, lab); > + tcg_gen_brcondi_i64(TCG_COND_EQ, td, 0x3, lab); > + tcg_gen_ori_i32(cpu_sr, cpu_sr, (SR_OV | SR_CY)); > + tcg_gen_andi_i32(sr_ove, cpu_sr, SR_OVE); > + tcg_gen_brcondi_i32(TCG_COND_NE, sr_ove, SR_OVE, lab); > + gen_exception(dc, EXCP_RANGE); > + gen_set_label(lab); > + tcg_gen_mov_i32(cpu_R[rd], res); > + tcg_temp_free_i64(ta); > + tcg_temp_free_i64(td); > + tcg_temp_free_i32(res); > + tcg_temp_free_i32(sr_ove); > + } > + break; > + > + case 0x28: /* l.addic */ > + LOG_DIS("l.addic r%d, r%d, %d\n", rd, ra, I16); > + { > + int lab = gen_new_label(); > + TCGv_i64 ta = tcg_temp_new_i64(); > + TCGv_i64 td = tcg_temp_local_new_i64(); > + TCGv_i64 tcy = tcg_temp_local_new_i64(); > + TCGv_i32 res = tcg_temp_local_new_i32(); > + TCGv_i32 sr_cy = tcg_temp_local_new_i32(); > + TCGv_i32 sr_ove = tcg_temp_local_new_i32(); > + tcg_gen_extu_i32_i64(ta, cpu_R[ra]); > + tcg_gen_andi_i32(sr_cy, cpu_sr, SR_CY); > + tcg_gen_shri_i32(sr_cy, sr_cy, 10); > + tcg_gen_extu_i32_i64(tcy, sr_cy); > + tcg_gen_addi_i64(td, ta, sign_extend(I16, 16)); > + tcg_gen_add_i64(td, td, tcy); > + tcg_gen_trunc_i64_i32(res, td); > + tcg_gen_shri_i64(td, td, 32); > + tcg_gen_andi_i64(td, td, 0x3); > + /* Jump to lab when no overflow. */ > + tcg_gen_brcondi_i64(TCG_COND_EQ, td, 0x0, lab); > + tcg_gen_brcondi_i64(TCG_COND_EQ, td, 0x3, lab); > + tcg_gen_ori_i32(cpu_sr, cpu_sr, (SR_OV | SR_CY)); > + tcg_gen_andi_i32(sr_ove, cpu_sr, SR_OVE); > + tcg_gen_brcondi_i32(TCG_COND_NE, sr_ove, SR_OVE, lab); > + gen_exception(dc, EXCP_RANGE); > + gen_set_label(lab); > + tcg_gen_mov_i32(cpu_R[rd], res); > + tcg_temp_free_i64(ta); > + tcg_temp_free_i64(td); > + tcg_temp_free_i64(tcy); > + tcg_temp_free_i32(res); > + tcg_temp_free_i32(sr_cy); > + tcg_temp_free_i32(sr_ove); > + } > + 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_i32 im = tcg_const_i32(I16); > + gen_helper_mul32(cpu_R[rd], cpu_env, cpu_R[ra], im); > + tcg_temp_free_i32(im); > + } else { > + tcg_gen_movi_tl(cpu_R[rd], 0x0); > + } > + 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); > + { > +#ifdef TARGET_OPENRISC64 > + 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); > +#endif > + } > + 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, 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_i32 t0 = tcg_temp_new_i32(); > + TCGv_i64 t1 = tcg_temp_new_i64(); > + TCGv_i64 t2 = tcg_temp_new_i64(); > + tcg_gen_mul_tl(t0, cpu_R[ra], cpu_R[rb]); > + tcg_gen_ext_i32_i64(t1, t0); > + tcg_gen_concat_i32_i64(t2, maclo, machi); > + tcg_gen_add_i64(t2, t2, t1); > + tcg_gen_trunc_i64_i32(maclo, t2); > + tcg_gen_shri_i64(t2, t2, 32); > + tcg_gen_trunc_i64_i32(machi, t2); > + tcg_temp_free_i32(t0); > + tcg_temp_free_i64(t1); > + tcg_temp_free_i64(t2); > + } > + break; > + > + case 0x0002: /* l.msb */ > + LOG_DIS("l.msb r%d, r%d\n", ra, rb); > + { > + TCGv_i32 t0 = tcg_temp_new_i32(); > + TCGv_i64 t1 = tcg_temp_new_i64(); > + TCGv_i64 t2 = tcg_temp_new_i64(); > + tcg_gen_mul_tl(t0, cpu_R[ra], cpu_R[rb]); > + tcg_gen_ext_i32_i64(t1, t0); > + tcg_gen_concat_i32_i64(t2, maclo, machi); > + tcg_gen_sub_i64(t2, t2, t1); > + tcg_gen_trunc_i64_i32(maclo, t2); > + tcg_gen_shri_i64(t2, t2, 32); > + tcg_gen_trunc_i64_i32(machi, t2); > + tcg_temp_free_i32(t0); > + tcg_temp_free_i64(t1); > + tcg_temp_free_i64(t2); > + } > + break; > + > + default: > + gen_illegal_exception(dc); > + break; > + } > +} > + > +static void dec_logic(DisasContext *dc, 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, 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, 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, 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, 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);*/ Why commented out? > + 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);*/ Ditto > + 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, 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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; > + > +#ifdef TARGET_OPENRISC64 > + 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 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 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 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 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 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 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 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 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 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 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 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 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 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; > +#endif > + > + default: > + gen_illegal_exception(dc); > + break; > + } > + wb_SR_F(); > +} > + > +static void disas_openrisc_insn(DisasContext *dc, OpenRISCCPU *cpu) > +{ > + uint32_t op0; > + uint32_t insn; > + insn = cpu_ldl_code(&cpu->env, dc->pc); > + op0 = field(insn, 26, 6); > + > + switch (op0) { > + case 0x06: > + dec_M(dc, insn); > + break; > + > + case 0x08: > + dec_sys(dc, insn); > + break; > + > + case 0x2e: > + dec_logic(dc, insn); > + break; > + > + case 0x2f: > + dec_compi(dc, insn); > + break; > + > + case 0x31: > + dec_mac(dc, insn); > + break; > + > + case 0x32: > + dec_float(dc, insn); > + break; > + > + case 0x38: > + dec_calc(dc, insn); > + break; > + > + case 0x39: > + dec_comp(dc, insn); > + break; > + > + default: > + dec_misc(dc, insn); > + break; > + } > +} > + > +static void check_breakpoint(OpenRISCCPU *cpu, DisasContext *dc) > +{ > + CPUBreakpoint *bp; > + > + if (unlikely(!QTAILQ_EMPTY(&cpu->env.breakpoints))) { > + QTAILQ_FOREACH(bp, &cpu->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(OpenRISCCPU *cpu, > 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->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 = cpu->env.cpucfgr; > + dc->mem_idx = cpu_mmu_index(&cpu->env); > + dc->synced_flags = dc->tb_flags = tb->flags; > + dc->delayed_branch = !!(dc->tb_flags & D_FLAG); > + dc->singlestep_enabled = cpu->env.singlestep_enabled; > + if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)) { > + qemu_log("-----------------------------------------\n"); > + log_cpu_state(&cpu->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(cpu, 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, cpu); > + 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 > + && !cpu->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(cpu->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 > > ^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [Qemu-devel] [PATCH v8 08/16] target-or32: Add instruction translation 2012-07-03 18:48 ` [Qemu-devel] [PATCH v8 08/16] target-or32: Add instruction translation Blue Swirl @ 2012-07-04 2:23 ` Jia Liu 2012-07-04 23:59 ` Jia Liu 0 siblings, 1 reply; 9+ messages in thread From: Jia Liu @ 2012-07-04 2:23 UTC (permalink / raw) To: Blue Swirl; +Cc: qemu-devel Hi Blue, On Wed, Jul 4, 2012 at 2:48 AM, Blue Swirl <blauwirbel@gmail.com> wrote: > On Sun, Jul 1, 2012 at 2:45 AM, Jia Liu <proljc@gmail.com> wrote: >> Add OpenRISC instruction tanslation routines. >> >> Signed-off-by: Jia Liu <proljc@gmail.com> >> --- >> target-openrisc/translate.c | 1678 +++++++++++++++++++++++++++++++++++++++++++ >> 1 file changed, 1678 insertions(+) >> >> diff --git a/target-openrisc/translate.c b/target-openrisc/translate.c >> index 4d4aa23..b69722c 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,1688 @@ >> # define LOG_DIS(...) do { } while (0) >> #endif >> >> +typedef struct DisasContext { >> + 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_i32(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; >> +} >> + >> +#ifdef TARGET_OPENRISC64 >> +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); >> + } >> +}*/ >> +#endif >> + >> +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, 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); >> + { >> + int lab = gen_new_label(); >> + TCGv_i64 ta = tcg_temp_new_i64(); >> + TCGv_i64 tb = tcg_temp_new_i64(); >> + TCGv_i64 td = tcg_temp_local_new_i64(); >> + TCGv_i32 res = tcg_temp_local_new_i32(); >> + TCGv_i32 sr_ove = tcg_temp_local_new_i32(); >> + tcg_gen_extu_i32_i64(ta, cpu_R[ra]); >> + tcg_gen_extu_i32_i64(tb, cpu_R[rb]); >> + tcg_gen_add_i64(td, ta, tb); >> + tcg_gen_trunc_i64_i32(res, td); >> + tcg_gen_shri_i64(td, td, 31); >> + tcg_gen_andi_i64(td, td, 0x3); >> + /* Jump to lab when no overflow. */ >> + tcg_gen_brcondi_i64(TCG_COND_EQ, td, 0x0, lab); >> + tcg_gen_brcondi_i64(TCG_COND_EQ, td, 0x3, lab); >> + tcg_gen_ori_i32(cpu_sr, cpu_sr, (SR_OV | SR_CY)); >> + tcg_gen_andi_i32(sr_ove, cpu_sr, SR_OVE); >> + tcg_gen_brcondi_i32(TCG_COND_NE, sr_ove, SR_OVE, lab); >> + gen_exception(dc, EXCP_RANGE); >> + gen_set_label(lab); >> + tcg_gen_mov_i32(cpu_R[rd], res); >> + tcg_temp_free_i64(ta); >> + tcg_temp_free_i64(tb); >> + tcg_temp_free_i64(td); >> + tcg_temp_free_i32(res); >> + tcg_temp_free_i32(sr_ove); >> + } >> + 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); >> + { >> + int lab = gen_new_label(); >> + TCGv_i64 ta = tcg_temp_new_i64(); >> + TCGv_i64 tb = tcg_temp_new_i64(); >> + TCGv_i64 tcy = tcg_temp_local_new_i64(); >> + TCGv_i64 td = tcg_temp_local_new_i64(); >> + TCGv_i32 res = tcg_temp_local_new_i32(); >> + TCGv_i32 sr_cy = tcg_temp_local_new_i32(); >> + TCGv_i32 sr_ove = tcg_temp_local_new_i32(); >> + tcg_gen_extu_i32_i64(ta, cpu_R[ra]); >> + tcg_gen_extu_i32_i64(tb, cpu_R[rb]); >> + tcg_gen_andi_i32(sr_cy, cpu_sr, SR_CY); >> + tcg_gen_extu_i32_i64(tcy, sr_cy); >> + tcg_gen_shri_i64(tcy, tcy, 10); >> + tcg_gen_add_i64(td, ta, tb); >> + tcg_gen_add_i64(td, td, tcy); >> + tcg_gen_trunc_i64_i32(res, td); >> + tcg_gen_shri_i64(td, td, 32); >> + tcg_gen_andi_i64(td, td, 0x3); >> + /* Jump to lab when no overflow. */ >> + tcg_gen_brcondi_i64(TCG_COND_EQ, td, 0x0, lab); >> + tcg_gen_brcondi_i64(TCG_COND_EQ, td, 0x3, lab); >> + tcg_gen_ori_i32(cpu_sr, cpu_sr, (SR_OV | SR_CY)); >> + tcg_gen_andi_i32(sr_ove, cpu_sr, SR_OVE); >> + tcg_gen_brcondi_i32(TCG_COND_NE, sr_ove, SR_OVE, lab); >> + gen_exception(dc, EXCP_RANGE); >> + gen_set_label(lab); >> + tcg_gen_mov_i32(cpu_R[rd], res); >> + tcg_temp_free_i64(ta); >> + tcg_temp_free_i64(tb); >> + tcg_temp_free_i64(tcy); >> + tcg_temp_free_i64(td); >> + tcg_temp_free_i32(res); >> + tcg_temp_free_i32(sr_cy); >> + tcg_temp_free_i32(sr_ove); >> + } >> + 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); >> + { >> + int lab = gen_new_label(); >> + TCGv_i64 ta = tcg_temp_new_i64(); >> + TCGv_i64 tb = tcg_temp_new_i64(); >> + TCGv_i64 td = tcg_temp_local_new_i64(); >> + TCGv_i32 res = tcg_temp_local_new_i32(); >> + TCGv_i32 sr_ove = tcg_temp_local_new_i32(); >> + >> + tcg_gen_extu_i32_i64(ta, cpu_R[ra]); >> + tcg_gen_extu_i32_i64(tb, cpu_R[rb]); >> + tcg_gen_sub_i64(td, ta, tb); >> + tcg_gen_trunc_i64_i32(res, td); >> + tcg_gen_shri_i64(td, td, 31); >> + tcg_gen_andi_i64(td, td, 0x3); >> + /* Jump to lab when no overflow. */ >> + tcg_gen_brcondi_i64(TCG_COND_EQ, td, 0x0, lab); >> + tcg_gen_brcondi_i64(TCG_COND_EQ, td, 0x3, lab); >> + tcg_gen_ori_i32(cpu_sr, cpu_sr, (SR_OV | SR_CY)); >> + tcg_gen_andi_i32(sr_ove, cpu_sr, SR_OVE); >> + tcg_gen_brcondi_i32(TCG_COND_NE, sr_ove, SR_OVE, lab); >> + gen_exception(dc, EXCP_RANGE); >> + gen_set_label(lab); >> + tcg_gen_mov_i32(cpu_R[rd], res); >> + tcg_temp_free_i64(ta); >> + tcg_temp_free_i64(tb); >> + tcg_temp_free_i64(td); >> + tcg_temp_free_i32(res); >> + tcg_temp_free_i32(sr_ove); >> + } >> + 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_mul32(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(); >> + int lab3 = gen_new_label(); >> + TCGv_i32 sr_ove = tcg_temp_local_new_i32(); >> + if (rb == 0) { >> + tcg_gen_ori_tl(cpu_sr, cpu_sr, (SR_OV | SR_CY)); >> + tcg_gen_andi_tl(sr_ove, cpu_sr, SR_OVE); >> + tcg_gen_brcondi_tl(TCG_COND_NE, sr_ove, SR_OVE, lab0); >> + gen_exception(dc, EXCP_RANGE); >> + gen_set_label(lab0); >> + } else { >> + tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_R[rb], >> + 0x00000000, lab1); >> + tcg_gen_brcondi_tl(TCG_COND_NE, cpu_R[ra], >> + 0x80000000, lab2); >> + tcg_gen_brcondi_tl(TCG_COND_NE, cpu_R[rb], >> + 0xffffffff, lab2); >> + gen_set_label(lab1); >> + tcg_gen_ori_tl(cpu_sr, cpu_sr, (SR_OV | SR_CY)); >> + tcg_gen_andi_tl(sr_ove, cpu_sr, SR_OVE); >> + tcg_gen_brcondi_tl(TCG_COND_NE, sr_ove, SR_OVE, lab3); >> + gen_exception(dc, EXCP_RANGE); >> + gen_set_label(lab2); >> + tcg_gen_div_tl(cpu_R[rd], cpu_R[ra], cpu_R[rb]); >> + gen_set_label(lab3); >> + } >> + tcg_temp_free_i32(sr_ove); >> + } >> + 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(); >> + int lab2 = gen_new_label(); >> + TCGv_i32 sr_ove = tcg_temp_local_new_i32(); >> + if (rb == 0) { >> + tcg_gen_ori_tl(cpu_sr, cpu_sr, (SR_OV | SR_CY)); >> + tcg_gen_andi_tl(sr_ove, cpu_sr, SR_OVE); >> + tcg_gen_brcondi_tl(TCG_COND_NE, sr_ove, SR_OVE, lab0); >> + gen_exception(dc, EXCP_RANGE); >> + gen_set_label(lab0); >> + } else { >> + tcg_gen_brcondi_tl(TCG_COND_NE, cpu_R[rb], >> + 0x00000000, lab1); >> + tcg_gen_ori_tl(cpu_sr, cpu_sr, (SR_OV | SR_CY)); >> + tcg_gen_andi_tl(sr_ove, cpu_sr, SR_OVE); >> + tcg_gen_brcondi_tl(TCG_COND_NE, sr_ove, SR_OVE, lab2); >> + gen_exception(dc, EXCP_RANGE); >> + gen_set_label(lab1); >> + tcg_gen_divu_tl(cpu_R[rd], cpu_R[ra], cpu_R[rb]); >> + gen_set_label(lab2); >> + } >> + tcg_temp_free_i32(sr_ove); >> + } >> + 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_local_new_i64(); >> + TCGv_i64 tra = tcg_temp_local_new_i64(); >> + TCGv_i64 trb = tcg_temp_local_new_i64(); >> + TCGv_i64 high = tcg_temp_new_i64(); >> + TCGv_i32 sr_ove = tcg_temp_local_new_i32(); >> + int lab = gen_new_label(); >> + /* Calculate the each result. */ >> + tcg_gen_extu_i32_i64(tra, cpu_R[ra]); >> + tcg_gen_extu_i32_i64(trb, cpu_R[rb]); >> + tcg_gen_mul_i64(result, tra, trb); >> + tcg_temp_free_i64(tra); >> + tcg_temp_free_i64(trb); >> + tcg_gen_shri_i64(high, result, TARGET_LONG_BITS); >> + /* Overflow or not. */ >> + tcg_gen_brcondi_i64(TCG_COND_EQ, high, 0x00000000, lab); >> + tcg_gen_ori_tl(cpu_sr, cpu_sr, (SR_OV | SR_CY)); >> + tcg_gen_andi_tl(sr_ove, cpu_sr, SR_OVE); >> + tcg_gen_brcondi_tl(TCG_COND_NE, sr_ove, SR_OVE, lab); >> + gen_exception(dc, EXCP_RANGE); >> + gen_set_label(lab); >> + tcg_temp_free_i64(high); >> + tcg_gen_trunc_i64_tl(cpu_R[rd], result); >> + tcg_temp_free_i64(result); >> + tcg_temp_free_i32(sr_ove); >> + } else { >> + tcg_gen_movi_tl(cpu_R[rd], 0); >> + } >> + 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_local_new(); >> + TCGv sr_f = tcg_temp_new(); >> + tcg_gen_andi_tl(sr_f, cpu_sr, SR_F); >> + tcg_gen_mov_tl(res, cpu_R[rb]); >> + tcg_gen_brcondi_tl(TCG_COND_NE, sr_f, SR_F, lab); >> + tcg_gen_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, 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); > > The cases 0x00 to 0x03 will fall through to this case, calling LOG_DIS > one to four times. Sorry, I can't find a better path. Is this code OK? switch (op0) { case 0x00: /* l.j */ case 0x01: /* l.jal */ case 0x03: /* l.bnf */ case 0x04: /* l.bf */ LOG_DIS("l.j/l.jal/l.bnf/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); > > Also here. > And, this? case 0x11: /* l.jr */ case 0x12: /* l.jalr */ LOG_DIS("l.jr/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_i64 t1 = tcg_temp_new_i64(); >> + TCGv_i64 t2 = tcg_temp_new_i64(); >> + TCGv_i32 dst = tcg_temp_new_i32(); >> + TCGv ttmp = tcg_const_tl(tmp); >> + tcg_gen_mul_tl(dst, cpu_R[ra], ttmp); >> + tcg_gen_ext_i32_i64(t1, dst); >> + tcg_gen_concat_i32_i64(t2, maclo, machi); >> + tcg_gen_add_i64(t2, t2, t1); >> + tcg_gen_trunc_i64_i32(maclo, t2); >> + tcg_gen_shri_i64(t2, t2, 32); >> + tcg_gen_trunc_i64_i32(machi, t2); >> + tcg_temp_free_i32(dst); >> + tcg_temp_free(ttmp); >> + tcg_temp_free_i64(t1); >> + tcg_temp_free_i64(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); >> + { >> +#ifdef TARGET_OPENRISC64 >> + 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); >> +#endif >> + } >> + 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); >> + { >> + int lab = gen_new_label(); >> + TCGv_i64 ta = tcg_temp_new_i64(); >> + TCGv_i64 td = tcg_temp_local_new_i64(); >> + TCGv_i32 res = tcg_temp_local_new_i32(); >> + TCGv_i32 sr_ove = tcg_temp_local_new_i32(); >> + tcg_gen_extu_i32_i64(ta, cpu_R[ra]); >> + tcg_gen_addi_i64(td, ta, sign_extend(I16, 16)); >> + tcg_gen_trunc_i64_i32(res, td); >> + tcg_gen_shri_i64(td, td, 32); >> + tcg_gen_andi_i64(td, td, 0x3); >> + /* Jump to lab when no overflow. */ >> + tcg_gen_brcondi_i64(TCG_COND_EQ, td, 0x0, lab); >> + tcg_gen_brcondi_i64(TCG_COND_EQ, td, 0x3, lab); >> + tcg_gen_ori_i32(cpu_sr, cpu_sr, (SR_OV | SR_CY)); >> + tcg_gen_andi_i32(sr_ove, cpu_sr, SR_OVE); >> + tcg_gen_brcondi_i32(TCG_COND_NE, sr_ove, SR_OVE, lab); >> + gen_exception(dc, EXCP_RANGE); >> + gen_set_label(lab); >> + tcg_gen_mov_i32(cpu_R[rd], res); >> + tcg_temp_free_i64(ta); >> + tcg_temp_free_i64(td); >> + tcg_temp_free_i32(res); >> + tcg_temp_free_i32(sr_ove); >> + } >> + break; >> + >> + case 0x28: /* l.addic */ >> + LOG_DIS("l.addic r%d, r%d, %d\n", rd, ra, I16); >> + { >> + int lab = gen_new_label(); >> + TCGv_i64 ta = tcg_temp_new_i64(); >> + TCGv_i64 td = tcg_temp_local_new_i64(); >> + TCGv_i64 tcy = tcg_temp_local_new_i64(); >> + TCGv_i32 res = tcg_temp_local_new_i32(); >> + TCGv_i32 sr_cy = tcg_temp_local_new_i32(); >> + TCGv_i32 sr_ove = tcg_temp_local_new_i32(); >> + tcg_gen_extu_i32_i64(ta, cpu_R[ra]); >> + tcg_gen_andi_i32(sr_cy, cpu_sr, SR_CY); >> + tcg_gen_shri_i32(sr_cy, sr_cy, 10); >> + tcg_gen_extu_i32_i64(tcy, sr_cy); >> + tcg_gen_addi_i64(td, ta, sign_extend(I16, 16)); >> + tcg_gen_add_i64(td, td, tcy); >> + tcg_gen_trunc_i64_i32(res, td); >> + tcg_gen_shri_i64(td, td, 32); >> + tcg_gen_andi_i64(td, td, 0x3); >> + /* Jump to lab when no overflow. */ >> + tcg_gen_brcondi_i64(TCG_COND_EQ, td, 0x0, lab); >> + tcg_gen_brcondi_i64(TCG_COND_EQ, td, 0x3, lab); >> + tcg_gen_ori_i32(cpu_sr, cpu_sr, (SR_OV | SR_CY)); >> + tcg_gen_andi_i32(sr_ove, cpu_sr, SR_OVE); >> + tcg_gen_brcondi_i32(TCG_COND_NE, sr_ove, SR_OVE, lab); >> + gen_exception(dc, EXCP_RANGE); >> + gen_set_label(lab); >> + tcg_gen_mov_i32(cpu_R[rd], res); >> + tcg_temp_free_i64(ta); >> + tcg_temp_free_i64(td); >> + tcg_temp_free_i64(tcy); >> + tcg_temp_free_i32(res); >> + tcg_temp_free_i32(sr_cy); >> + tcg_temp_free_i32(sr_ove); >> + } >> + 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_i32 im = tcg_const_i32(I16); >> + gen_helper_mul32(cpu_R[rd], cpu_env, cpu_R[ra], im); >> + tcg_temp_free_i32(im); >> + } else { >> + tcg_gen_movi_tl(cpu_R[rd], 0x0); >> + } >> + 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); >> + { >> +#ifdef TARGET_OPENRISC64 >> + 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); >> +#endif >> + } >> + 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, 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_i32 t0 = tcg_temp_new_i32(); >> + TCGv_i64 t1 = tcg_temp_new_i64(); >> + TCGv_i64 t2 = tcg_temp_new_i64(); >> + tcg_gen_mul_tl(t0, cpu_R[ra], cpu_R[rb]); >> + tcg_gen_ext_i32_i64(t1, t0); >> + tcg_gen_concat_i32_i64(t2, maclo, machi); >> + tcg_gen_add_i64(t2, t2, t1); >> + tcg_gen_trunc_i64_i32(maclo, t2); >> + tcg_gen_shri_i64(t2, t2, 32); >> + tcg_gen_trunc_i64_i32(machi, t2); >> + tcg_temp_free_i32(t0); >> + tcg_temp_free_i64(t1); >> + tcg_temp_free_i64(t2); >> + } >> + break; >> + >> + case 0x0002: /* l.msb */ >> + LOG_DIS("l.msb r%d, r%d\n", ra, rb); >> + { >> + TCGv_i32 t0 = tcg_temp_new_i32(); >> + TCGv_i64 t1 = tcg_temp_new_i64(); >> + TCGv_i64 t2 = tcg_temp_new_i64(); >> + tcg_gen_mul_tl(t0, cpu_R[ra], cpu_R[rb]); >> + tcg_gen_ext_i32_i64(t1, t0); >> + tcg_gen_concat_i32_i64(t2, maclo, machi); >> + tcg_gen_sub_i64(t2, t2, t1); >> + tcg_gen_trunc_i64_i32(maclo, t2); >> + tcg_gen_shri_i64(t2, t2, 32); >> + tcg_gen_trunc_i64_i32(machi, t2); >> + tcg_temp_free_i32(t0); >> + tcg_temp_free_i64(t1); >> + tcg_temp_free_i64(t2); >> + } >> + break; >> + >> + default: >> + gen_illegal_exception(dc); >> + break; >> + } >> +} >> + >> +static void dec_logic(DisasContext *dc, 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, 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, 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, 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, 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);*/ > > Why commented out? When I build QEMU, I got a error msg like "unused var K16, treat warnings as errors". I didn't find a better way to handle it, so, commented it. > >> + 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);*/ > > Ditto > And, commented it here. >> + 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, 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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; >> + >> +#ifdef TARGET_OPENRISC64 >> + 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 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 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 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 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 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 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 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 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 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 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 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 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 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; >> +#endif >> + >> + default: >> + gen_illegal_exception(dc); >> + break; >> + } >> + wb_SR_F(); >> +} >> + >> +static void disas_openrisc_insn(DisasContext *dc, OpenRISCCPU *cpu) >> +{ >> + uint32_t op0; >> + uint32_t insn; >> + insn = cpu_ldl_code(&cpu->env, dc->pc); >> + op0 = field(insn, 26, 6); >> + >> + switch (op0) { >> + case 0x06: >> + dec_M(dc, insn); >> + break; >> + >> + case 0x08: >> + dec_sys(dc, insn); >> + break; >> + >> + case 0x2e: >> + dec_logic(dc, insn); >> + break; >> + >> + case 0x2f: >> + dec_compi(dc, insn); >> + break; >> + >> + case 0x31: >> + dec_mac(dc, insn); >> + break; >> + >> + case 0x32: >> + dec_float(dc, insn); >> + break; >> + >> + case 0x38: >> + dec_calc(dc, insn); >> + break; >> + >> + case 0x39: >> + dec_comp(dc, insn); >> + break; >> + >> + default: >> + dec_misc(dc, insn); >> + break; >> + } >> +} >> + >> +static void check_breakpoint(OpenRISCCPU *cpu, DisasContext *dc) >> +{ >> + CPUBreakpoint *bp; >> + >> + if (unlikely(!QTAILQ_EMPTY(&cpu->env.breakpoints))) { >> + QTAILQ_FOREACH(bp, &cpu->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(OpenRISCCPU *cpu, >> 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->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 = cpu->env.cpucfgr; >> + dc->mem_idx = cpu_mmu_index(&cpu->env); >> + dc->synced_flags = dc->tb_flags = tb->flags; >> + dc->delayed_branch = !!(dc->tb_flags & D_FLAG); >> + dc->singlestep_enabled = cpu->env.singlestep_enabled; >> + if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)) { >> + qemu_log("-----------------------------------------\n"); >> + log_cpu_state(&cpu->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(cpu, 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, cpu); >> + 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 >> + && !cpu->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(cpu->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. ^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [Qemu-devel] [PATCH v8 08/16] target-or32: Add instruction translation 2012-07-04 2:23 ` Jia Liu @ 2012-07-04 23:59 ` Jia Liu 2012-07-05 18:45 ` Blue Swirl 0 siblings, 1 reply; 9+ messages in thread From: Jia Liu @ 2012-07-04 23:59 UTC (permalink / raw) To: Blue Swirl; +Cc: qemu-devel On Wed, Jul 4, 2012 at 10:23 AM, Jia Liu <proljc@gmail.com> wrote: > Hi Blue, > > On Wed, Jul 4, 2012 at 2:48 AM, Blue Swirl <blauwirbel@gmail.com> wrote: >> On Sun, Jul 1, 2012 at 2:45 AM, Jia Liu <proljc@gmail.com> wrote: >>> + 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); >> >> The cases 0x00 to 0x03 will fall through to this case, calling LOG_DIS >> one to four times. > > Sorry, I can't find a better path. Is this code OK? > > switch (op0) { > case 0x00: /* l.j */ > case 0x01: /* l.jal */ > case 0x03: /* l.bnf */ > case 0x04: /* l.bf */ > LOG_DIS("l.j/l.jal/l.bnf/l.bf %d\n", N26); > > gen_jump(dc, N26, 0, op0); > or is this code OK? switch (op0) { case 0x00: /* l.j */ LOG_DIS("l.j %d\n", N26); gen_jump(dc, N26, 0, op0); break; case 0x01: /* l.jal */ LOG_DIS("l.jal %d\n", N26); gen_jump(dc, N26, 0, op0); break; case 0x03: /* l.bnf */ LOG_DIS("l.bnf %d\n", N26); gen_jump(dc, N26, 0, op0); break; case 0x04: /* l.bf */ LOG_DIS("l.bf %d\n", N26); gen_jump(dc, N26, 0, op0); 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); >> >> Also here. >> > > And, this? > case 0x11: /* l.jr */ gen_jump(dc, 0, rb, op0); break; case 0x12: /* l.jalr */ LOG_DIS("l.jr r%d\n", rb); gen_jump(dc, 0, rb, op0); break; >>> +static void dec_sys(DisasContext *dc, 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);*/ >> >> Why commented out? > > When I build QEMU, I got a error msg like "unused var K16, treat > warnings as errors". > I didn't find a better way to handle it, so, commented it. > >> >>> + 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);*/ >> >> Ditto >> > > And, commented it here. > >>> + tcg_gen_movi_tl(cpu_pc, dc->pc); >>> + gen_exception(dc, EXCP_TRAP); >>> + break; >>> + > > Regards, > Jia. Regards, Jia. ^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [Qemu-devel] [PATCH v8 08/16] target-or32: Add instruction translation 2012-07-04 23:59 ` Jia Liu @ 2012-07-05 18:45 ` Blue Swirl 2012-07-06 0:23 ` Jia Liu 0 siblings, 1 reply; 9+ messages in thread From: Blue Swirl @ 2012-07-05 18:45 UTC (permalink / raw) To: Jia Liu; +Cc: qemu-devel On Wed, Jul 4, 2012 at 11:59 PM, Jia Liu <proljc@gmail.com> wrote: > On Wed, Jul 4, 2012 at 10:23 AM, Jia Liu <proljc@gmail.com> wrote: >> Hi Blue, >> >> On Wed, Jul 4, 2012 at 2:48 AM, Blue Swirl <blauwirbel@gmail.com> wrote: >>> On Sun, Jul 1, 2012 at 2:45 AM, Jia Liu <proljc@gmail.com> wrote: >>>> + 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); >>> >>> The cases 0x00 to 0x03 will fall through to this case, calling LOG_DIS >>> one to four times. >> >> Sorry, I can't find a better path. Is this code OK? >> >> switch (op0) { >> case 0x00: /* l.j */ >> case 0x01: /* l.jal */ >> case 0x03: /* l.bnf */ >> case 0x04: /* l.bf */ >> LOG_DIS("l.j/l.jal/l.bnf/l.bf %d\n", N26); >> >> gen_jump(dc, N26, 0, op0); >> > > or is this code OK? > > switch (op0) { > case 0x00: /* l.j */ > LOG_DIS("l.j %d\n", N26); > gen_jump(dc, N26, 0, op0); > break; > case 0x01: /* l.jal */ > LOG_DIS("l.jal %d\n", N26); > gen_jump(dc, N26, 0, op0); > break; > case 0x03: /* l.bnf */ > LOG_DIS("l.bnf %d\n", N26); > gen_jump(dc, N26, 0, op0); > break; > case 0x04: /* l.bf */ > LOG_DIS("l.bf %d\n", N26); > gen_jump(dc, N26, 0, op0); > break; Yes, with N26 defined only when LOG_DIS does something (see below). > > >>>> + >>>> + 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); >>> >>> Also here. >>> >> >> And, this? >> > case 0x11: /* l.jr */ Now there's no LOG_DIS() line. > gen_jump(dc, 0, rb, op0); > break; > case 0x12: /* l.jalr */ > LOG_DIS("l.jr r%d\n", rb); > gen_jump(dc, 0, rb, op0); > break; > >>>> +static void dec_sys(DisasContext *dc, 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);*/ >>> >>> Why commented out? >> >> When I build QEMU, I got a error msg like "unused var K16, treat >> warnings as errors". >> I didn't find a better way to handle it, so, commented it. This can be avoided by adjusting those variable definitions which are only used by LOG_DIS() so that they are only defined when LOG_DIS needs them: #ifdef OPENRISC_DISAS int K16, N26; #endif >> >>> >>>> + 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);*/ >>> >>> Ditto >>> >> >> And, commented it here. >> >>>> + tcg_gen_movi_tl(cpu_pc, dc->pc); >>>> + gen_exception(dc, EXCP_TRAP); >>>> + break; >>>> + >> >> Regards, >> Jia. > > > Regards, > Jia. ^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [Qemu-devel] [PATCH v8 08/16] target-or32: Add instruction translation 2012-07-05 18:45 ` Blue Swirl @ 2012-07-06 0:23 ` Jia Liu 0 siblings, 0 replies; 9+ messages in thread From: Jia Liu @ 2012-07-06 0:23 UTC (permalink / raw) To: Blue Swirl; +Cc: qemu-devel Hi Blue, On Fri, Jul 6, 2012 at 2:45 AM, Blue Swirl <blauwirbel@gmail.com> wrote: > On Wed, Jul 4, 2012 at 11:59 PM, Jia Liu <proljc@gmail.com> wrote: >> On Wed, Jul 4, 2012 at 10:23 AM, Jia Liu <proljc@gmail.com> wrote: >>> Hi Blue, >>> >>> On Wed, Jul 4, 2012 at 2:48 AM, Blue Swirl <blauwirbel@gmail.com> wrote: >>>> On Sun, Jul 1, 2012 at 2:45 AM, Jia Liu <proljc@gmail.com> wrote: >>>>> + 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); >>>> >>>> The cases 0x00 to 0x03 will fall through to this case, calling LOG_DIS >>>> one to four times. >>> >>> Sorry, I can't find a better path. Is this code OK? >>> >>> switch (op0) { >>> case 0x00: /* l.j */ >>> case 0x01: /* l.jal */ >>> case 0x03: /* l.bnf */ >>> case 0x04: /* l.bf */ >>> LOG_DIS("l.j/l.jal/l.bnf/l.bf %d\n", N26); >>> >>> gen_jump(dc, N26, 0, op0); >>> >> >> or is this code OK? >> >> switch (op0) { >> case 0x00: /* l.j */ >> LOG_DIS("l.j %d\n", N26); >> gen_jump(dc, N26, 0, op0); >> break; >> case 0x01: /* l.jal */ >> LOG_DIS("l.jal %d\n", N26); >> gen_jump(dc, N26, 0, op0); >> break; >> case 0x03: /* l.bnf */ >> LOG_DIS("l.bnf %d\n", N26); >> gen_jump(dc, N26, 0, op0); >> break; >> case 0x04: /* l.bf */ >> LOG_DIS("l.bf %d\n", N26); >> gen_jump(dc, N26, 0, op0); >> break; > > Yes, with N26 defined only when LOG_DIS does something (see below). > >> >> >>>>> + >>>>> + 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); >>>> >>>> Also here. >>>> >>> >>> And, this? >>> >> case 0x11: /* l.jr */ > > Now there's no LOG_DIS() line. Oh! I was too careless! It shouldn't a LOG_DIS() here! Thank you very much! > >> gen_jump(dc, 0, rb, op0); >> break; >> case 0x12: /* l.jalr */ >> LOG_DIS("l.jr r%d\n", rb); >> gen_jump(dc, 0, rb, op0); >> break; >> >>>>> +static void dec_sys(DisasContext *dc, 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);*/ >>>> >>>> Why commented out? >>> >>> When I build QEMU, I got a error msg like "unused var K16, treat >>> warnings as errors". >>> I didn't find a better way to handle it, so, commented it. > > This can be avoided by adjusting those variable definitions which are > only used by LOG_DIS() so that they are only defined when LOG_DIS > needs them: > #ifdef OPENRISC_DISAS > int K16, N26; > #endif > Thank you very much! This is a very nice way. >>> >>>> >>>>> + 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);*/ >>>> >>>> Ditto >>>> >>> >>> And, commented it here. >>> >>>>> + tcg_gen_movi_tl(cpu_pc, dc->pc); >>>>> + gen_exception(dc, EXCP_TRAP); >>>>> + break; >>>>> + >>> >>> Regards, >>> Jia. >> >> >> Regards, >> Jia. Regards, Jia. ^ permalink raw reply [flat|nested] 9+ messages in thread
[parent not found: <1341110730-444-2-git-send-email-proljc@gmail.com>]
* Re: [Qemu-devel] [PATCH v8 01/16] target-or32: Add target stubs and QOM cpu [not found] ` <1341110730-444-2-git-send-email-proljc@gmail.com> @ 2012-07-05 13:22 ` Andreas Färber 2012-07-05 13:31 ` Paolo Bonzini 2012-07-09 7:08 ` Jia Liu 0 siblings, 2 replies; 9+ messages in thread From: Andreas Färber @ 2012-07-05 13:22 UTC (permalink / raw) To: Jia Liu; +Cc: Paolo Bonzini, qemu-devel, Juan Quintela Am 01.07.2012 04:45, schrieb Jia Liu: > Add OpenRISC target stubs and cpu support. > > Signed-off-by: Jia Liu <proljc@gmail.com> > --- > arch_init.c | 2 + > arch_init.h | 1 + > configure | 14 +- > cpu-exec.c | 2 + > default-configs/or32-softmmu.mak | 4 + > elf.h | 2 + > hw/openrisc/Makefile.objs | 1 + > poison.h | 1 + > target-openrisc/Makefile.objs | 3 + > target-openrisc/cpu.c | 236 +++++++++++++++++++++++++++++++ > target-openrisc/cpu.h | 286 ++++++++++++++++++++++++++++++++++++++ > target-openrisc/intrpt.c | 30 ++++ > target-openrisc/machine.c | 30 ++++ > target-openrisc/mmu.c | 39 ++++++ > target-openrisc/mmu_helper.c | 43 ++++++ > target-openrisc/translate.c | 75 ++++++++++ > 16 files changed, 767 insertions(+), 2 deletions(-) > create mode 100644 default-configs/or32-softmmu.mak > create mode 100644 hw/openrisc/Makefile.objs > create mode 100644 target-openrisc/Makefile.objs > create mode 100644 target-openrisc/cpu.c > create mode 100644 target-openrisc/cpu.h > create mode 100644 target-openrisc/intrpt.c > create mode 100644 target-openrisc/machine.c > create mode 100644 target-openrisc/mmu.c > create mode 100644 target-openrisc/mmu_helper.c > create mode 100644 target-openrisc/translate.c > diff --git a/target-openrisc/Makefile.objs b/target-openrisc/Makefile.objs > new file mode 100644 > index 0000000..21b76b2 > --- /dev/null > +++ b/target-openrisc/Makefile.objs > @@ -0,0 +1,3 @@ > +obj-$(CONFIG_SOFTMMU) += machine.o > +obj-y += cpu.o intrpt.o mmu.o translate.o intrpt.o? Any chance of a better to read/remember file name? > +obj-y += mmu_helper.o > diff --git a/target-openrisc/cpu.c b/target-openrisc/cpu.c > new file mode 100644 > index 0000000..64ddc98 > --- /dev/null > +++ b/target-openrisc/cpu.c > @@ -0,0 +1,236 @@ > +/* > + * QEMU OpenRISC CPU > + * > + * Copyright (c) 2012 Jia Liu <proljc@gmail.com> Two-space indentation? (also in other files) > + * > + * This library is free software; you can redistribute it and/or > + * modify it under the terms of the GNU Lesser General Public > + * License as published by the Free Software Foundation; either > + * version 2 of the License, or (at your option) any later version. > + * > + * This library is distributed in the hope that it will be useful, > + * but WITHOUT ANY WARRANTY; without even the implied warranty of > + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU > + * Lesser General Public License for more details. > + * > + * You should have received a copy of the GNU Lesser General Public > + * License along with this library; if not, see <http://www.gnu.org/licenses/>. > + */ > + > +#include "cpu.h" > +#include "qemu-common.h" > +#ifndef CONFIG_USER_ONLY > +#include "hw/loader.h" > +#endif Not yet needed in this patch? > + > +/* CPUClass::reset() */ > +static void openrisc_cpu_reset(CPUState *s) > +{ > + OpenRISCCPU *cpu = OPENRISC_CPU(s); > + OpenRISCCPUClass *occ = OPENRISC_CPU_GET_CLASS(cpu); > + > + if (qemu_loglevel_mask(CPU_LOG_RESET)) { > + qemu_log("CPU Reset (CPU %d)\n", cpu->env.cpu_index); > + log_cpu_state(&cpu->env, 0); > + } > + > + occ->parent_reset(s); > + > + memset(&cpu->env, 0, offsetof(CPUOpenRISCState, breakpoints)); Note, if you wanted, you could've declared a CPUOpenRISCState *env to avoid re-typing "cpu->env." or "&cpu->env". > + > + tlb_flush(&cpu->env, 1); > + /*tb_flush(&cpu->env); FIXME: Do we need it? */ > + > + cpu->env.pc = 0x100; > + cpu->env.sr = SR_FO | SR_SM; > + cpu->env.exception_index = -1; > + > + cpu->env.upr = UPR_UP | UPR_DMP | UPR_IMP | UPR_PICP | UPR_TTP; > + cpu->env.cpucfgr = CPUCFGR_OB32S | CPUCFGR_OF32S; > + cpu->env.dmmucfgr = (DMMUCFGR_NTW & (0 << 2)) | (DMMUCFGR_NTS & (6 << 2)); > + cpu->env.immucfgr = (IMMUCFGR_NTW & (0 << 2)) | (IMMUCFGR_NTS & (6 << 2)); > + > +#ifndef CONFIG_USER_ONLY > + cpu->env.picmr = 0x00000000; > + cpu->env.picsr = 0x00000000; > + > + cpu->env.ttmr = 0x00000000; > + cpu->env.ttcr = 0x00000000; > +#endif > +} > + > +static inline int openrisc_feature(OpenRISCCPU *cpu, int feature) This could return bool. > +{ > + return (cpu->env.feature & (1u << feature)) != 0; > +} > + > +static inline void set_feature(OpenRISCCPU *cpu, int feature) > +{ > + cpu->env.feature |= 1u << feature; > +} > + > +void openrisc_cpu_realize(Object *obj, Error **errp) > +{ > + OpenRISCCPU *cpu = OPENRISC_CPU(obj); > + if (openrisc_feature(cpu, OPENRISC_FEATURE_OR1200)) { > + set_feature(cpu, OPENRISC_FEATURE_OB32S); > + set_feature(cpu, OPENRISC_FEATURE_OF32S); > + } > + > + qemu_init_vcpu(&cpu->env); > +} > + > +static void openrisc_cpu_initfn(Object *obj) > +{ > + OpenRISCCPU *cpu = OPENRISC_CPU(obj); > + cpu_exec_init(&cpu->env); > +} > + > +/* CPU models */ > +static void or1200_initfn(Object *obj) > +{ > + OpenRISCCPU *cpu = OPENRISC_CPU(obj); > + > + set_feature(cpu, OPENRISC_FEATURE_OR1200); > + > + cpu_reset(CPU(cpu)); > +} > + > +static void openrisc_any_initfn(Object *obj) > +{ > + OpenRISCCPU *cpu = OPENRISC_CPU(obj); > + > + set_feature(cpu, OPENRISC_FEATURE_OB32S); > + set_feature(cpu, OPENRISC_FEATURE_OF32S); > + > + cpu_reset(CPU(cpu)); > +} Paolo, could class_base_init or something help with this pattern of needing to do something in every derived initfn? On the other hand I think we should move cpu_reset() into the realizefn instead, that would avoid this issue here. > + > +typedef struct OpenRISCCPUInfo { > + const char *name; > + void (*initfn)(Object *obj); > +} OpenRISCCPUInfo; > + > +static const OpenRISCCPUInfo openrisc_cpus[] = { > + { .name = "or1200", .initfn = or1200_initfn }, > + { .name = "any", .initfn = openrisc_any_initfn }, > +}; > + > +static void openrisc_cpu_class_init(ObjectClass *oc, void *data) > +{ > + OpenRISCCPUClass *occ = OPENRISC_CPU_CLASS(oc); > + CPUClass *cc = CPU_CLASS(occ); > + > + occ->parent_reset = cc->reset; > + cc->reset = openrisc_cpu_reset; > +} > + > +static void cpu_register(const OpenRISCCPUInfo *info) > +{ > + TypeInfo type_info = { > + .name = info->name, > + .parent = TYPE_OPENRISC_CPU, > + .instance_size = sizeof(OpenRISCCPU), > + .instance_init = info->initfn, > + .class_size = sizeof(OpenRISCCPUClass), > + }; > + > + type_register_static(&type_info); > +} > + > +static const TypeInfo openrisc_cpu_type_info = { > + .name = TYPE_OPENRISC_CPU, > + .parent = TYPE_CPU, > + .instance_size = sizeof(OpenRISCCPU), > + .instance_init = openrisc_cpu_initfn, > + .abstract = false, > + .class_size = sizeof(OpenRISCCPUClass), > + .class_init = openrisc_cpu_class_init, > +}; > + > +static void openrisc_cpu_register_types(void) > +{ > + int i; > + > + type_register_static(&openrisc_cpu_type_info); > + for (i = 0; i < ARRAY_SIZE(openrisc_cpus); i++) { > + cpu_register(&openrisc_cpus[i]); > + } > +} > + > +OpenRISCCPU *cpu_openrisc_init(const char *cpu_model) > +{ > + OpenRISCCPU *cpu; > + static int inited; > + inited = 0; > + > + if (!object_class_by_name(cpu_model)) { > + return NULL; > + } > + cpu = OPENRISC_CPU(object_new(cpu_model)); This currently does a reset in initfn. > + cpu->env.cpu_model_str = cpu_model; > + > + openrisc_cpu_realize(OBJECT(cpu), NULL); > + > +#ifndef CONFIG_USER_ONLY > + cpu_openrisc_mmu_init(cpu); > +#endif > + > + if (tcg_enabled() && !inited) { > + inited = 1; > + openrisc_translate_init(); > + } Could you move this into the initfn please like Igor has done for x86? > + > + cpu_reset(CPU(cpu)); It is then reset again here, which is why I think doing it once in the realizefn would be sufficient. > + > + return cpu; > +} > + > +typedef struct OpenRISCCPUList { > + fprintf_function cpu_fprintf; > + FILE *file; > +} OpenRISCCPUList; > + > +/* Sort alphabetically by type name, except for "any". */ > +static gint openrisc_cpu_list_compare(gconstpointer a, gconstpointer b) > +{ > + ObjectClass *class_a = (ObjectClass *)a; > + ObjectClass *class_b = (ObjectClass *)b; > + const char *name_a, *name_b; > + > + name_a = object_class_get_name(class_a); > + name_b = object_class_get_name(class_b); > + if (strcmp(name_a, "any") == 0) { > + return 1; > + } else if (strcmp(name_b, "any") == 0) { > + return -1; > + } else { > + return strcmp(name_a, name_b); > + } > +} > + > +static void openrisc_cpu_list_entry(gpointer data, gpointer user_data) > +{ > + ObjectClass *oc = data; > + OpenRISCCPUList *s = user_data; > + > + (*s->cpu_fprintf)(s->file, " %s\n", > + object_class_get_name(oc)); > +} > + > +void cpu_openrisc_list(FILE *f, fprintf_function cpu_fprintf) > +{ > + OpenRISCCPUList s = { > + .file = f, > + .cpu_fprintf = cpu_fprintf, > + }; > + GSList *list; > + > + list = object_class_get_list(TYPE_OPENRISC_CPU, false); > + list = g_slist_sort(list, openrisc_cpu_list_compare); > + (*cpu_fprintf)(f, "Available CPUs:\n"); > + g_slist_foreach(list, openrisc_cpu_list_entry, &s); > + g_slist_free(list); > +} > + > +type_init(openrisc_cpu_register_types) > diff --git a/target-openrisc/cpu.h b/target-openrisc/cpu.h > new file mode 100644 > index 0000000..728e4b3 > --- /dev/null > +++ b/target-openrisc/cpu.h > @@ -0,0 +1,286 @@ > +/* > + * OpenRISC virtual CPU header. > + * > + * Copyright (c) 2011-2012 Jia Liu <proljc@gmail.com> > + * > + * This library is free software; you can redistribute it and/or > + * modify it under the terms of the GNU Lesser General Public > + * License as published by the Free Software Foundation; either > + * version 2 of the License, or (at your option) any later version. > + * > + * This library is distributed in the hope that it will be useful, > + * but WITHOUT ANY WARRANTY; without even the implied warranty of > + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU > + * Lesser General Public License for more details. > + * > + * You should have received a copy of the GNU Lesser General Public > + * License along with this library; if not, see <http://www.gnu.org/licenses/>. > + */ > + > +#ifndef CPU_OPENRISC_H > +#define CPU_OPENRISC_H > + > +#if defined(TARGET_OPENRISC64) > +#define TARGET_LONG_BITS 64 > +#define ELF_MACHINE EM_NONE I don't see any provisions in configure for openrisc64? > +#else > +#define TARGET_LONG_BITS 32 > +#define ELF_MACHINE EM_OPENRISC > +#endif > + > +#define CPUArchState struct CPUOpenRISCState > + > +#include "config.h" > +#include "qemu-common.h" > +#include "cpu-defs.h" > +#include "softfloat.h" > +#include "qemu/cpu.h" > +#include "error.h" > + > +#define TYPE_OPENRISC_CPU "or32-cpu" "openrisc-cpu"? Also for or64 it should be adjusted. > + > +#define OPENRISC_CPU_CLASS(klass) \ > + OBJECT_CLASS_CHECK(OpenRISCCPUClass, (klass), TYPE_OPENRISC_CPU) > +#define OPENRISC_CPU(obj) \ > + OBJECT_CHECK(OpenRISCCPU, (obj), TYPE_OPENRISC_CPU) > +#define OPENRISC_CPU_GET_CLASS(obj) \ > + OBJECT_GET_CLASS(OpenRISCCPUClass, (obj), TYPE_OPENRISC_CPU) > + > +/** > + * OpenRISCCPUClass: > + * @parent_reset: The parent class' reset handler. > + * > + * A OpenRISC CPU model. > + */ > +typedef struct OpenRISCCPUClass { > + /*< private >*/ > + CPUClass parent_class; > + /*< public >*/ > + > + void (*parent_reset)(CPUState *cpu); > +} OpenRISCCPUClass; > + > +#define NB_MMU_MODES 3 > + > +#define TARGET_PAGE_BITS 13 > + > +#define TARGET_PHYS_ADDR_SPACE_BITS 32 > +#define TARGET_VIRT_ADDR_SPACE_BITS 32 > + > +/* Internal flags, delay slot flag */ > +#define D_FLAG 1 > + > +/* Registers */ > +enum { > + R0 = 0, 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 > +}; > + > +/* Register aliases */ > +enum { > + R_ZERO = R0, > + R_SP = R1, > + R_FP = R2, > + R_LR = R9, > + R_RV = R11, > + R_RVH = R12 > +}; > + > +/* Unit presece register */ > +enum { > + UPR_UP = (1 << 0), > + UPR_DCP = (1 << 1), > + UPR_ICP = (1 << 2), > + UPR_DMP = (1 << 3), > + UPR_IMP = (1 << 4), > + UPR_MP = (1 << 5), > + UPR_DUP = (1 << 6), > + UPR_PCUR = (1 << 7), > + UPR_PMP = (1 << 8), > + UPR_PICP = (1 << 9), > + UPR_TTP = (1 << 10), > + UPR_CUP = (255 << 24), > +}; > + > +/* CPU configure register */ > +enum { > + CPUCFGR_NSGF = (15 << 0), > + CPUCFGR_CGF = (1 << 4), > + CPUCFGR_OB32S = (1 << 5), > + CPUCFGR_OB64S = (1 << 6), > + CPUCFGR_OF32S = (1 << 7), > + CPUCFGR_OF64S = (1 << 8), > + CPUCFGR_OV64S = (1 << 9), > +}; > + > +/* DMMU configure register */ > +enum { > + DMMUCFGR_NTW = (3 << 0), > + DMMUCFGR_NTS = (7 << 2), > + DMMUCFGR_NAE = (7 << 5), > + DMMUCFGR_CRI = (1 << 8), > + DMMUCFGR_PRI = (1 << 9), > + DMMUCFGR_TEIRI = (1 << 10), > + DMMUCFGR_HTR = (1 << 11), > +}; > + > +/* IMMU configure register */ > +enum { > + IMMUCFGR_NTW = (3 << 0), > + IMMUCFGR_NTS = (7 << 2), > + IMMUCFGR_NAE = (7 << 5), > + IMMUCFGR_CRI = (1 << 8), > + IMMUCFGR_PRI = (1 << 9), > + IMMUCFGR_TEIRI = (1 << 10), > + IMMUCFGR_HTR = (1 << 11), > +}; > + > +/* Supervisor register */ > +enum { > + SR_SM = (1 << 0), > + SR_TEE = (1 << 1), > + SR_IEE = (1 << 2), > + SR_DCE = (1 << 3), > + SR_ICE = (1 << 4), > + SR_DME = (1 << 5), > + SR_IME = (1 << 6), > + SR_LEE = (1 << 7), > + SR_CE = (1 << 8), > + SR_F = (1 << 9), > + SR_CY = (1 << 10), > + SR_OV = (1 << 11), > + SR_OVE = (1 << 12), > + SR_DSX = (1 << 13), > + SR_EPH = (1 << 14), > + SR_FO = (1 << 15), > + SR_SUMRA = (1 << 16), > + SR_SCE = (1 << 17), > +}; > + > +/* OpenRISC Hardware Capabilities */ > +enum { > + OPENRISC_FEATURE_NSGF, > + OPENRISC_FEATURE_CGF, > + OPENRISC_FEATURE_OB32S, > + OPENRISC_FEATURE_OB64S, > + OPENRISC_FEATURE_OF32S, > + OPENRISC_FEATURE_OF64S, > + OPENRISC_FEATURE_OV64S, > + OPENRISC_FEATURE_OR1200, > +}; > + > +typedef struct CPUOpenRISCState { > + target_ulong gpr[32]; /* General registers */ > + target_ulong pc; /* Program counter */ > + target_ulong npc; /* Next PC */ > + target_ulong ppc; /* Prev PC */ > + target_ulong jmp_pc; /* Jump PC */ > + > + uint32_t sr; /* Supervisor register */ > + uint32_t vr; /* Version register */ > + uint32_t upr; /* Unit presence register */ > + uint32_t cpucfgr; /* CPU configure register */ > + uint32_t dmmucfgr; /* DMMU configure register */ > + uint32_t immucfgr; /* IMMU configure register */ > + > + uint32_t flags; /* cpu_flags, we only use it for exception > + in solt so far. */ > + uint32_t btaken; /* the SR_F bit */ > + > + CPU_COMMON > + > +#ifndef CONFIG_USER_ONLY > + struct QEMUTimer *timer; > + uint32_t ttmr; /* Timer tick mode register */ > + uint32_t ttcr; /* Timer tick count register */ > + > + uint32_t picmr; /* Interrupt mask register */ > + uint32_t picsr; /* Interrupt contrl register*/ > +#endif > + uint32_t feature; /* CPU Capabilities */ Could the feature(s) field be moved into OpenRISCCPU after env? > +} CPUOpenRISCState; > + > +/** > + * OpenRISCCPU: > + * @env: #CPUOpenRISCState > + * > + * A OpenRISC CPU. > + */ > +typedef struct OpenRISCCPU { > + /*< private >*/ > + CPUState parent_obj; > + /*< public >*/ > + > + CPUOpenRISCState env; > +} OpenRISCCPU; > + > +static inline OpenRISCCPU *openrisc_env_get_cpu(CPUOpenRISCState *env) > +{ > + return OPENRISC_CPU(container_of(env, OpenRISCCPU, env)); > +} > + > +#define ENV_GET_CPU(e) CPU(openrisc_env_get_cpu(e)) > + > +OpenRISCCPU *cpu_openrisc_init(const char *cpu_model); > +void openrisc_cpu_realize(Object *obj, Error **errp); > + > +void cpu_openrisc_list(FILE *f, fprintf_function cpu_fprintf); > +int cpu_openrisc_exec(CPUOpenRISCState *s); > +void do_interrupt(CPUOpenRISCState *env); > +void openrisc_translate_init(void); > + > +#define cpu_list cpu_openrisc_list > +#define cpu_exec cpu_openrisc_exec > +#define cpu_gen_code cpu_openrisc_gen_code > + > +#define CPU_SAVE_VERSION 1 Is this still needed? > + > +#ifndef CONFIG_USER_ONLY > +void cpu_openrisc_mmu_init(OpenRISCCPU *cpu); > +#endif > + > +static inline CPUOpenRISCState *cpu_init(const char *cpu_model) > +{ > + OpenRISCCPU *cpu = cpu_openrisc_init(cpu_model); > + if (cpu) { > + return &cpu->env; > + } > + return NULL; > +} > + > +#include "cpu-all.h" > + > +static inline void cpu_get_tb_cpu_state(CPUOpenRISCState *env, > + target_ulong *pc, > + target_ulong *cs_base, int *flags) > +{ > + *pc = env->pc; > + *cs_base = 0; > + *flags = 0; > +} > + > +static inline int cpu_mmu_index(CPUOpenRISCState *env) > +{ > + return 0; > +} > + > +static inline bool cpu_has_work(CPUOpenRISCState *env) > +{ > + return true; > +} > + > +#include "exec-all.h" > + > +static inline target_ulong cpu_get_pc(CPUOpenRISCState *env) > +{ > + return env->pc; > +} > + > +static inline void cpu_pc_from_tb(CPUOpenRISCState *env, TranslationBlock *tb) > +{ > + env->pc = tb->pc; > +} > + > +#endif /* CPU_OPENRISC_H */ > diff --git a/target-openrisc/intrpt.c b/target-openrisc/intrpt.c > new file mode 100644 > index 0000000..a3bb7f8 > --- /dev/null > +++ b/target-openrisc/intrpt.c > @@ -0,0 +1,30 @@ > +/* > + * OpenRISC interrupt. > + * > + * Copyright (c) 2011-2012 Jia Liu <proljc@gmail.com> > + * > + * This library is free software; you can redistribute it and/or > + * modify it under the terms of the GNU Lesser General Public > + * License as published by the Free Software Foundation; either > + * version 2 of the License, or (at your option) any later version. > + * > + * This library is distributed in the hope that it will be useful, > + * but WITHOUT ANY WARRANTY; without even the implied warranty of > + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU > + * Lesser General Public License for more details. > + * > + * You should have received a copy of the GNU Lesser General Public > + * License along with this library; if not, see <http://www.gnu.org/licenses/>. > + */ > + > +#include "cpu.h" > +#include "qemu-common.h" > +#include "gdbstub.h" > +#include "host-utils.h" > +#ifndef CONFIG_USER_ONLY > +#include "hw/loader.h" > +#endif > + > +void do_interrupt(CPUOpenRISCState *env) > +{ > +} > diff --git a/target-openrisc/machine.c b/target-openrisc/machine.c > new file mode 100644 > index 0000000..11bf275 > --- /dev/null > +++ b/target-openrisc/machine.c > @@ -0,0 +1,30 @@ > +/* > + * OpenRISC Machine > + * > + * Copyright (c) 2011-2012 Jia Liu <proljc@gmail.com> > + * > + * This library is free software; you can redistribute it and/or > + * modify it under the terms of the GNU Lesser General Public > + * License as published by the Free Software Foundation; either > + * version 2 of the License, or (at your option) any later version. > + * > + * This library is distributed in the hope that it will be useful, > + * but WITHOUT ANY WARRANTY; without even the implied warranty of > + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU > + * Lesser General Public License for more details. > + * > + * You should have received a copy of the GNU Lesser General Public > + * License along with this library; if not, see <http://www.gnu.org/licenses/>. > + */ > + > +#include "hw/hw.h" > +#include "hw/boards.h" > + > +void cpu_save(QEMUFile *f, void *opaque) > +{ > +} > + > +int cpu_load(QEMUFile *f, void *opaque, int version_id) > +{ > + return 0; > +} [snip] Shouldn't this be using VMState? Was there any problem converting? Andreas -- SUSE LINUX Products GmbH, Maxfeldstr. 5, 90409 Nürnberg, Germany GF: Jeff Hawn, Jennifer Guild, Felix Imendörffer; HRB 16746 AG Nürnberg ^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [Qemu-devel] [PATCH v8 01/16] target-or32: Add target stubs and QOM cpu 2012-07-05 13:22 ` [Qemu-devel] [PATCH v8 01/16] target-or32: Add target stubs and QOM cpu Andreas Färber @ 2012-07-05 13:31 ` Paolo Bonzini 2012-07-05 15:31 ` Andreas Färber 2012-07-09 7:08 ` Jia Liu 1 sibling, 1 reply; 9+ messages in thread From: Paolo Bonzini @ 2012-07-05 13:31 UTC (permalink / raw) To: Andreas Färber; +Cc: Juan Quintela, Jia Liu, qemu-devel Il 05/07/2012 15:22, Andreas Färber ha scritto: >> > +static void openrisc_any_initfn(Object *obj) >> > +{ >> > + OpenRISCCPU *cpu = OPENRISC_CPU(obj); >> > + >> > + set_feature(cpu, OPENRISC_FEATURE_OB32S); >> > + set_feature(cpu, OPENRISC_FEATURE_OF32S); >> > + >> > + cpu_reset(CPU(cpu)); >> > +} > Paolo, could class_base_init or something help with this pattern of > needing to do something in every derived initfn? I guess what you're looking for is some instance_post_init that is called at init time after instance_init? > On the other hand I think we should move cpu_reset() into the realizefn > instead, that would avoid this issue here. Yep. Paolo ^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [Qemu-devel] [PATCH v8 01/16] target-or32: Add target stubs and QOM cpu 2012-07-05 13:31 ` Paolo Bonzini @ 2012-07-05 15:31 ` Andreas Färber 0 siblings, 0 replies; 9+ messages in thread From: Andreas Färber @ 2012-07-05 15:31 UTC (permalink / raw) To: Paolo Bonzini; +Cc: Jia Liu, qemu-devel Am 05.07.2012 15:31, schrieb Paolo Bonzini: > Il 05/07/2012 15:22, Andreas Färber ha scritto: >>>> +static void openrisc_any_initfn(Object *obj) >>>> +{ >>>> + OpenRISCCPU *cpu = OPENRISC_CPU(obj); >>>> + >>>> + set_feature(cpu, OPENRISC_FEATURE_OB32S); >>>> + set_feature(cpu, OPENRISC_FEATURE_OF32S); >>>> + >>>> + cpu_reset(CPU(cpu)); >>>> +} >> Paolo, could class_base_init or something help with this pattern of >> needing to do something in every derived initfn? > > I guess what you're looking for is some instance_post_init that is > called at init time after instance_init? Sort of. The pattern I was seeing is parent initializes something, child modifies it, some action is performed on it. Here we can get away by deferring the common action to realize stage, just like we did for arm. My reasoning was that it's better to reset in realizefn for reproducible behavior over system_reset. Not sure if we can always escape to such a late stage, but we can worry about that when we have a concrete use case. :) Andreas >> On the other hand I think we should move cpu_reset() into the realizefn >> instead, that would avoid this issue here. > > Yep. > > Paolo -- SUSE LINUX Products GmbH, Maxfeldstr. 5, 90409 Nürnberg, Germany GF: Jeff Hawn, Jennifer Guild, Felix Imendörffer; HRB 16746 AG Nürnberg ^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [Qemu-devel] [PATCH v8 01/16] target-or32: Add target stubs and QOM cpu 2012-07-05 13:22 ` [Qemu-devel] [PATCH v8 01/16] target-or32: Add target stubs and QOM cpu Andreas Färber 2012-07-05 13:31 ` Paolo Bonzini @ 2012-07-09 7:08 ` Jia Liu 1 sibling, 0 replies; 9+ messages in thread From: Jia Liu @ 2012-07-09 7:08 UTC (permalink / raw) To: Andreas Färber; +Cc: Paolo Bonzini, qemu-devel, Juan Quintela Hi Andreas, Thank you for comment. I've tried fix them, but I'm afraid I didn't fully understand what you mean. Please read the new code and give me some comment, please. On Thu, Jul 5, 2012 at 9:22 PM, Andreas Färber <afaerber@suse.de> wrote: > Am 01.07.2012 04:45, schrieb Jia Liu: >> Add OpenRISC target stubs and cpu support. >> >> Signed-off-by: Jia Liu <proljc@gmail.com> >> --- >> arch_init.c | 2 + >> arch_init.h | 1 + >> configure | 14 +- >> cpu-exec.c | 2 + >> default-configs/or32-softmmu.mak | 4 + >> elf.h | 2 + >> hw/openrisc/Makefile.objs | 1 + >> poison.h | 1 + >> target-openrisc/Makefile.objs | 3 + >> target-openrisc/cpu.c | 236 +++++++++++++++++++++++++++++++ >> target-openrisc/cpu.h | 286 ++++++++++++++++++++++++++++++++++++++ >> target-openrisc/intrpt.c | 30 ++++ >> target-openrisc/machine.c | 30 ++++ >> target-openrisc/mmu.c | 39 ++++++ >> target-openrisc/mmu_helper.c | 43 ++++++ >> target-openrisc/translate.c | 75 ++++++++++ >> 16 files changed, 767 insertions(+), 2 deletions(-) >> create mode 100644 default-configs/or32-softmmu.mak >> create mode 100644 hw/openrisc/Makefile.objs >> create mode 100644 target-openrisc/Makefile.objs >> create mode 100644 target-openrisc/cpu.c >> create mode 100644 target-openrisc/cpu.h >> create mode 100644 target-openrisc/intrpt.c >> create mode 100644 target-openrisc/machine.c >> create mode 100644 target-openrisc/mmu.c >> create mode 100644 target-openrisc/mmu_helper.c >> create mode 100644 target-openrisc/translate.c > >> diff --git a/target-openrisc/Makefile.objs b/target-openrisc/Makefile.objs >> new file mode 100644 >> index 0000000..21b76b2 >> --- /dev/null >> +++ b/target-openrisc/Makefile.objs >> @@ -0,0 +1,3 @@ >> +obj-$(CONFIG_SOFTMMU) += machine.o >> +obj-y += cpu.o intrpt.o mmu.o translate.o > > intrpt.o? Any chance of a better to read/remember file name? Is interrupt.o OK? > >> +obj-y += mmu_helper.o >> diff --git a/target-openrisc/cpu.c b/target-openrisc/cpu.c >> new file mode 100644 >> index 0000000..64ddc98 >> --- /dev/null >> +++ b/target-openrisc/cpu.c >> @@ -0,0 +1,236 @@ >> +/* >> + * QEMU OpenRISC CPU >> + * >> + * Copyright (c) 2012 Jia Liu <proljc@gmail.com> > > Two-space indentation? (also in other files) I'll change all of them into one-space indentation. > >> + * >> + * This library is free software; you can redistribute it and/or >> + * modify it under the terms of the GNU Lesser General Public >> + * License as published by the Free Software Foundation; either >> + * version 2 of the License, or (at your option) any later version. >> + * >> + * This library is distributed in the hope that it will be useful, >> + * but WITHOUT ANY WARRANTY; without even the implied warranty of >> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU >> + * Lesser General Public License for more details. >> + * >> + * You should have received a copy of the GNU Lesser General Public >> + * License along with this library; if not, see <http://www.gnu.org/licenses/>. >> + */ >> + >> +#include "cpu.h" >> +#include "qemu-common.h" > >> +#ifndef CONFIG_USER_ONLY >> +#include "hw/loader.h" >> +#endif > > Not yet needed in this patch? Thanks, I've deleted them. > >> + >> +/* CPUClass::reset() */ >> +static void openrisc_cpu_reset(CPUState *s) >> +{ >> + OpenRISCCPU *cpu = OPENRISC_CPU(s); >> + OpenRISCCPUClass *occ = OPENRISC_CPU_GET_CLASS(cpu); >> + >> + if (qemu_loglevel_mask(CPU_LOG_RESET)) { >> + qemu_log("CPU Reset (CPU %d)\n", cpu->env.cpu_index); >> + log_cpu_state(&cpu->env, 0); >> + } >> + >> + occ->parent_reset(s); >> + >> + memset(&cpu->env, 0, offsetof(CPUOpenRISCState, breakpoints)); > > Note, if you wanted, you could've declared a CPUOpenRISCState *env to > avoid re-typing "cpu->env." or "&cpu->env". Thank you for notice me. > >> + >> + tlb_flush(&cpu->env, 1); >> + /*tb_flush(&cpu->env); FIXME: Do we need it? */ >> + >> + cpu->env.pc = 0x100; >> + cpu->env.sr = SR_FO | SR_SM; >> + cpu->env.exception_index = -1; >> + >> + cpu->env.upr = UPR_UP | UPR_DMP | UPR_IMP | UPR_PICP | UPR_TTP; >> + cpu->env.cpucfgr = CPUCFGR_OB32S | CPUCFGR_OF32S; >> + cpu->env.dmmucfgr = (DMMUCFGR_NTW & (0 << 2)) | (DMMUCFGR_NTS & (6 << 2)); >> + cpu->env.immucfgr = (IMMUCFGR_NTW & (0 << 2)) | (IMMUCFGR_NTS & (6 << 2)); >> + >> +#ifndef CONFIG_USER_ONLY >> + cpu->env.picmr = 0x00000000; >> + cpu->env.picsr = 0x00000000; >> + >> + cpu->env.ttmr = 0x00000000; >> + cpu->env.ttcr = 0x00000000; >> +#endif >> +} >> + >> +static inline int openrisc_feature(OpenRISCCPU *cpu, int feature) > > This could return bool. Thank you for point this! > >> +{ >> + return (cpu->env.feature & (1u << feature)) != 0; >> +} >> + >> +static inline void set_feature(OpenRISCCPU *cpu, int feature) >> +{ >> + cpu->env.feature |= 1u << feature; >> +} >> + >> +void openrisc_cpu_realize(Object *obj, Error **errp) >> +{ >> + OpenRISCCPU *cpu = OPENRISC_CPU(obj); >> + if (openrisc_feature(cpu, OPENRISC_FEATURE_OR1200)) { >> + set_feature(cpu, OPENRISC_FEATURE_OB32S); >> + set_feature(cpu, OPENRISC_FEATURE_OF32S); >> + } >> + >> + qemu_init_vcpu(&cpu->env); >> +} >> + >> +static void openrisc_cpu_initfn(Object *obj) >> +{ >> + OpenRISCCPU *cpu = OPENRISC_CPU(obj); >> + cpu_exec_init(&cpu->env); >> +} >> + >> +/* CPU models */ >> +static void or1200_initfn(Object *obj) >> +{ >> + OpenRISCCPU *cpu = OPENRISC_CPU(obj); >> + >> + set_feature(cpu, OPENRISC_FEATURE_OR1200); >> + >> + cpu_reset(CPU(cpu)); >> +} >> + >> +static void openrisc_any_initfn(Object *obj) >> +{ >> + OpenRISCCPU *cpu = OPENRISC_CPU(obj); >> + >> + set_feature(cpu, OPENRISC_FEATURE_OB32S); >> + set_feature(cpu, OPENRISC_FEATURE_OF32S); >> + >> + cpu_reset(CPU(cpu)); >> +} > > Paolo, could class_base_init or something help with this pattern of > needing to do something in every derived initfn? > > On the other hand I think we should move cpu_reset() into the realizefn > instead, that would avoid this issue here. > Sorry, I'm not true about this. May take a look at the new code? /* CPU models */ static void or1200_initfn(Object *obj) { OpenRISCCPU *cpu = OPENRISC_CPU(obj); set_feature(cpu, OPENRISC_FEATURE_OB32S); set_feature(cpu, OPENRISC_FEATURE_OF32S); } static void openrisc_any_initfn(Object *obj) { OpenRISCCPU *cpu = OPENRISC_CPU(obj); set_feature(cpu, OPENRISC_FEATURE_OB32S); } >> + >> +typedef struct OpenRISCCPUInfo { >> + const char *name; >> + void (*initfn)(Object *obj); >> +} OpenRISCCPUInfo; >> + >> +static const OpenRISCCPUInfo openrisc_cpus[] = { >> + { .name = "or1200", .initfn = or1200_initfn }, >> + { .name = "any", .initfn = openrisc_any_initfn }, >> +}; >> + >> +static void openrisc_cpu_class_init(ObjectClass *oc, void *data) >> +{ >> + OpenRISCCPUClass *occ = OPENRISC_CPU_CLASS(oc); >> + CPUClass *cc = CPU_CLASS(occ); >> + >> + occ->parent_reset = cc->reset; >> + cc->reset = openrisc_cpu_reset; >> +} >> + >> +static void cpu_register(const OpenRISCCPUInfo *info) >> +{ >> + TypeInfo type_info = { >> + .name = info->name, >> + .parent = TYPE_OPENRISC_CPU, >> + .instance_size = sizeof(OpenRISCCPU), >> + .instance_init = info->initfn, >> + .class_size = sizeof(OpenRISCCPUClass), >> + }; >> + >> + type_register_static(&type_info); >> +} >> + >> +static const TypeInfo openrisc_cpu_type_info = { >> + .name = TYPE_OPENRISC_CPU, >> + .parent = TYPE_CPU, >> + .instance_size = sizeof(OpenRISCCPU), >> + .instance_init = openrisc_cpu_initfn, >> + .abstract = false, >> + .class_size = sizeof(OpenRISCCPUClass), >> + .class_init = openrisc_cpu_class_init, >> +}; >> + >> +static void openrisc_cpu_register_types(void) >> +{ >> + int i; >> + >> + type_register_static(&openrisc_cpu_type_info); >> + for (i = 0; i < ARRAY_SIZE(openrisc_cpus); i++) { >> + cpu_register(&openrisc_cpus[i]); >> + } >> +} >> + >> +OpenRISCCPU *cpu_openrisc_init(const char *cpu_model) >> +{ >> + OpenRISCCPU *cpu; >> + static int inited; >> + inited = 0; >> + >> + if (!object_class_by_name(cpu_model)) { >> + return NULL; >> + } >> + cpu = OPENRISC_CPU(object_new(cpu_model)); > > This currently does a reset in initfn. > >> + cpu->env.cpu_model_str = cpu_model; >> + >> + openrisc_cpu_realize(OBJECT(cpu), NULL); >> + >> +#ifndef CONFIG_USER_ONLY >> + cpu_openrisc_mmu_init(cpu); >> +#endif >> + >> + if (tcg_enabled() && !inited) { >> + inited = 1; >> + openrisc_translate_init(); >> + } > > Could you move this into the initfn please like Igor has done for x86? > >> + >> + cpu_reset(CPU(cpu)); > > It is then reset again here, which is why I think doing it once in the > realizefn would be sufficient. > Sorry, I didn't fully understand it. May you take a look at the new code? OpenRISCCPU *cpu_openrisc_init(const char *cpu_model) { OpenRISCCPU *cpu; static int inited; inited = 0; if (!object_class_by_name(cpu_model)) { return NULL; } cpu = OPENRISC_CPU(object_new(cpu_model)); cpu->env.cpu_model_str = cpu_model; openrisc_cpu_realize(OBJECT(cpu), NULL); #ifndef CONFIG_USER_ONLY cpu_openrisc_mmu_init(cpu); #endif if (tcg_enabled() && !inited) { inited = 1; openrisc_translate_init(); } return cpu; } >> + >> + return cpu; >> +} >> + >> +typedef struct OpenRISCCPUList { >> + fprintf_function cpu_fprintf; >> + FILE *file; >> +} OpenRISCCPUList; >> + >> +/* Sort alphabetically by type name, except for "any". */ >> +static gint openrisc_cpu_list_compare(gconstpointer a, gconstpointer b) >> +{ >> + ObjectClass *class_a = (ObjectClass *)a; >> + ObjectClass *class_b = (ObjectClass *)b; >> + const char *name_a, *name_b; >> + >> + name_a = object_class_get_name(class_a); >> + name_b = object_class_get_name(class_b); >> + if (strcmp(name_a, "any") == 0) { >> + return 1; >> + } else if (strcmp(name_b, "any") == 0) { >> + return -1; >> + } else { >> + return strcmp(name_a, name_b); >> + } >> +} >> + >> +static void openrisc_cpu_list_entry(gpointer data, gpointer user_data) >> +{ >> + ObjectClass *oc = data; >> + OpenRISCCPUList *s = user_data; >> + >> + (*s->cpu_fprintf)(s->file, " %s\n", >> + object_class_get_name(oc)); >> +} >> + >> +void cpu_openrisc_list(FILE *f, fprintf_function cpu_fprintf) >> +{ >> + OpenRISCCPUList s = { >> + .file = f, >> + .cpu_fprintf = cpu_fprintf, >> + }; >> + GSList *list; >> + >> + list = object_class_get_list(TYPE_OPENRISC_CPU, false); >> + list = g_slist_sort(list, openrisc_cpu_list_compare); >> + (*cpu_fprintf)(f, "Available CPUs:\n"); >> + g_slist_foreach(list, openrisc_cpu_list_entry, &s); >> + g_slist_free(list); >> +} >> + >> +type_init(openrisc_cpu_register_types) >> diff --git a/target-openrisc/cpu.h b/target-openrisc/cpu.h >> new file mode 100644 >> index 0000000..728e4b3 >> --- /dev/null >> +++ b/target-openrisc/cpu.h >> @@ -0,0 +1,286 @@ >> +/* >> + * OpenRISC virtual CPU header. >> + * >> + * Copyright (c) 2011-2012 Jia Liu <proljc@gmail.com> >> + * >> + * This library is free software; you can redistribute it and/or >> + * modify it under the terms of the GNU Lesser General Public >> + * License as published by the Free Software Foundation; either >> + * version 2 of the License, or (at your option) any later version. >> + * >> + * This library is distributed in the hope that it will be useful, >> + * but WITHOUT ANY WARRANTY; without even the implied warranty of >> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU >> + * Lesser General Public License for more details. >> + * >> + * You should have received a copy of the GNU Lesser General Public >> + * License along with this library; if not, see <http://www.gnu.org/licenses/>. >> + */ >> + >> +#ifndef CPU_OPENRISC_H >> +#define CPU_OPENRISC_H >> + >> +#if defined(TARGET_OPENRISC64) >> +#define TARGET_LONG_BITS 64 >> +#define ELF_MACHINE EM_NONE > > I don't see any provisions in configure for openrisc64? or64 is not implemented, I'll delete/commented all of them. > >> +#else >> +#define TARGET_LONG_BITS 32 >> +#define ELF_MACHINE EM_OPENRISC >> +#endif >> + >> +#define CPUArchState struct CPUOpenRISCState >> + >> +#include "config.h" >> +#include "qemu-common.h" >> +#include "cpu-defs.h" >> +#include "softfloat.h" >> +#include "qemu/cpu.h" >> +#include "error.h" >> + >> +#define TYPE_OPENRISC_CPU "or32-cpu" > > "openrisc-cpu"? Also for or64 it should be adjusted. > or64 is not implemented, I'll delete/comment all of them. >> + >> +#define OPENRISC_CPU_CLASS(klass) \ >> + OBJECT_CLASS_CHECK(OpenRISCCPUClass, (klass), TYPE_OPENRISC_CPU) >> +#define OPENRISC_CPU(obj) \ >> + OBJECT_CHECK(OpenRISCCPU, (obj), TYPE_OPENRISC_CPU) >> +#define OPENRISC_CPU_GET_CLASS(obj) \ >> + OBJECT_GET_CLASS(OpenRISCCPUClass, (obj), TYPE_OPENRISC_CPU) >> + >> +/** >> + * OpenRISCCPUClass: >> + * @parent_reset: The parent class' reset handler. >> + * >> + * A OpenRISC CPU model. >> + */ >> +typedef struct OpenRISCCPUClass { >> + /*< private >*/ >> + CPUClass parent_class; >> + /*< public >*/ >> + >> + void (*parent_reset)(CPUState *cpu); >> +} OpenRISCCPUClass; >> + >> +#define NB_MMU_MODES 3 >> + >> +#define TARGET_PAGE_BITS 13 >> + >> +#define TARGET_PHYS_ADDR_SPACE_BITS 32 >> +#define TARGET_VIRT_ADDR_SPACE_BITS 32 >> + >> +/* Internal flags, delay slot flag */ >> +#define D_FLAG 1 >> + >> +/* Registers */ >> +enum { >> + R0 = 0, 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 >> +}; >> + >> +/* Register aliases */ >> +enum { >> + R_ZERO = R0, >> + R_SP = R1, >> + R_FP = R2, >> + R_LR = R9, >> + R_RV = R11, >> + R_RVH = R12 >> +}; >> + >> +/* Unit presece register */ >> +enum { >> + UPR_UP = (1 << 0), >> + UPR_DCP = (1 << 1), >> + UPR_ICP = (1 << 2), >> + UPR_DMP = (1 << 3), >> + UPR_IMP = (1 << 4), >> + UPR_MP = (1 << 5), >> + UPR_DUP = (1 << 6), >> + UPR_PCUR = (1 << 7), >> + UPR_PMP = (1 << 8), >> + UPR_PICP = (1 << 9), >> + UPR_TTP = (1 << 10), >> + UPR_CUP = (255 << 24), >> +}; >> + >> +/* CPU configure register */ >> +enum { >> + CPUCFGR_NSGF = (15 << 0), >> + CPUCFGR_CGF = (1 << 4), >> + CPUCFGR_OB32S = (1 << 5), >> + CPUCFGR_OB64S = (1 << 6), >> + CPUCFGR_OF32S = (1 << 7), >> + CPUCFGR_OF64S = (1 << 8), >> + CPUCFGR_OV64S = (1 << 9), >> +}; >> + >> +/* DMMU configure register */ >> +enum { >> + DMMUCFGR_NTW = (3 << 0), >> + DMMUCFGR_NTS = (7 << 2), >> + DMMUCFGR_NAE = (7 << 5), >> + DMMUCFGR_CRI = (1 << 8), >> + DMMUCFGR_PRI = (1 << 9), >> + DMMUCFGR_TEIRI = (1 << 10), >> + DMMUCFGR_HTR = (1 << 11), >> +}; >> + >> +/* IMMU configure register */ >> +enum { >> + IMMUCFGR_NTW = (3 << 0), >> + IMMUCFGR_NTS = (7 << 2), >> + IMMUCFGR_NAE = (7 << 5), >> + IMMUCFGR_CRI = (1 << 8), >> + IMMUCFGR_PRI = (1 << 9), >> + IMMUCFGR_TEIRI = (1 << 10), >> + IMMUCFGR_HTR = (1 << 11), >> +}; >> + >> +/* Supervisor register */ >> +enum { >> + SR_SM = (1 << 0), >> + SR_TEE = (1 << 1), >> + SR_IEE = (1 << 2), >> + SR_DCE = (1 << 3), >> + SR_ICE = (1 << 4), >> + SR_DME = (1 << 5), >> + SR_IME = (1 << 6), >> + SR_LEE = (1 << 7), >> + SR_CE = (1 << 8), >> + SR_F = (1 << 9), >> + SR_CY = (1 << 10), >> + SR_OV = (1 << 11), >> + SR_OVE = (1 << 12), >> + SR_DSX = (1 << 13), >> + SR_EPH = (1 << 14), >> + SR_FO = (1 << 15), >> + SR_SUMRA = (1 << 16), >> + SR_SCE = (1 << 17), >> +}; >> + >> +/* OpenRISC Hardware Capabilities */ >> +enum { >> + OPENRISC_FEATURE_NSGF, >> + OPENRISC_FEATURE_CGF, >> + OPENRISC_FEATURE_OB32S, >> + OPENRISC_FEATURE_OB64S, >> + OPENRISC_FEATURE_OF32S, >> + OPENRISC_FEATURE_OF64S, >> + OPENRISC_FEATURE_OV64S, >> + OPENRISC_FEATURE_OR1200, >> +}; >> + >> +typedef struct CPUOpenRISCState { >> + target_ulong gpr[32]; /* General registers */ >> + target_ulong pc; /* Program counter */ >> + target_ulong npc; /* Next PC */ >> + target_ulong ppc; /* Prev PC */ >> + target_ulong jmp_pc; /* Jump PC */ >> + >> + uint32_t sr; /* Supervisor register */ >> + uint32_t vr; /* Version register */ >> + uint32_t upr; /* Unit presence register */ >> + uint32_t cpucfgr; /* CPU configure register */ >> + uint32_t dmmucfgr; /* DMMU configure register */ >> + uint32_t immucfgr; /* IMMU configure register */ >> + >> + uint32_t flags; /* cpu_flags, we only use it for exception >> + in solt so far. */ >> + uint32_t btaken; /* the SR_F bit */ >> + >> + CPU_COMMON >> + >> +#ifndef CONFIG_USER_ONLY >> + struct QEMUTimer *timer; >> + uint32_t ttmr; /* Timer tick mode register */ >> + uint32_t ttcr; /* Timer tick count register */ >> + >> + uint32_t picmr; /* Interrupt mask register */ >> + uint32_t picsr; /* Interrupt contrl register*/ >> +#endif >> + uint32_t feature; /* CPU Capabilities */ > > Could the feature(s) field be moved into OpenRISCCPU after env? Thank you, done. > >> +} CPUOpenRISCState; >> + >> +/** >> + * OpenRISCCPU: >> + * @env: #CPUOpenRISCState >> + * >> + * A OpenRISC CPU. >> + */ >> +typedef struct OpenRISCCPU { >> + /*< private >*/ >> + CPUState parent_obj; >> + /*< public >*/ >> + >> + CPUOpenRISCState env; >> +} OpenRISCCPU; >> + >> +static inline OpenRISCCPU *openrisc_env_get_cpu(CPUOpenRISCState *env) >> +{ >> + return OPENRISC_CPU(container_of(env, OpenRISCCPU, env)); >> +} >> + >> +#define ENV_GET_CPU(e) CPU(openrisc_env_get_cpu(e)) >> + >> +OpenRISCCPU *cpu_openrisc_init(const char *cpu_model); >> +void openrisc_cpu_realize(Object *obj, Error **errp); >> + >> +void cpu_openrisc_list(FILE *f, fprintf_function cpu_fprintf); >> +int cpu_openrisc_exec(CPUOpenRISCState *s); >> +void do_interrupt(CPUOpenRISCState *env); >> +void openrisc_translate_init(void); >> + >> +#define cpu_list cpu_openrisc_list >> +#define cpu_exec cpu_openrisc_exec >> +#define cpu_gen_code cpu_openrisc_gen_code >> + >> +#define CPU_SAVE_VERSION 1 > > Is this still needed? Thanks, I'll delete it. > >> + >> +#ifndef CONFIG_USER_ONLY >> +void cpu_openrisc_mmu_init(OpenRISCCPU *cpu); >> +#endif >> + >> +static inline CPUOpenRISCState *cpu_init(const char *cpu_model) >> +{ >> + OpenRISCCPU *cpu = cpu_openrisc_init(cpu_model); >> + if (cpu) { >> + return &cpu->env; >> + } >> + return NULL; >> +} >> + >> +#include "cpu-all.h" >> + >> +static inline void cpu_get_tb_cpu_state(CPUOpenRISCState *env, >> + target_ulong *pc, >> + target_ulong *cs_base, int *flags) >> +{ >> + *pc = env->pc; >> + *cs_base = 0; >> + *flags = 0; >> +} >> + >> +static inline int cpu_mmu_index(CPUOpenRISCState *env) >> +{ >> + return 0; >> +} >> + >> +static inline bool cpu_has_work(CPUOpenRISCState *env) >> +{ >> + return true; >> +} >> + >> +#include "exec-all.h" >> + >> +static inline target_ulong cpu_get_pc(CPUOpenRISCState *env) >> +{ >> + return env->pc; >> +} >> + >> +static inline void cpu_pc_from_tb(CPUOpenRISCState *env, TranslationBlock *tb) >> +{ >> + env->pc = tb->pc; >> +} >> + >> +#endif /* CPU_OPENRISC_H */ >> diff --git a/target-openrisc/intrpt.c b/target-openrisc/intrpt.c >> new file mode 100644 >> index 0000000..a3bb7f8 >> --- /dev/null >> +++ b/target-openrisc/intrpt.c >> @@ -0,0 +1,30 @@ >> +/* >> + * OpenRISC interrupt. >> + * >> + * Copyright (c) 2011-2012 Jia Liu <proljc@gmail.com> >> + * >> + * This library is free software; you can redistribute it and/or >> + * modify it under the terms of the GNU Lesser General Public >> + * License as published by the Free Software Foundation; either >> + * version 2 of the License, or (at your option) any later version. >> + * >> + * This library is distributed in the hope that it will be useful, >> + * but WITHOUT ANY WARRANTY; without even the implied warranty of >> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU >> + * Lesser General Public License for more details. >> + * >> + * You should have received a copy of the GNU Lesser General Public >> + * License along with this library; if not, see <http://www.gnu.org/licenses/>. >> + */ >> + >> +#include "cpu.h" >> +#include "qemu-common.h" >> +#include "gdbstub.h" >> +#include "host-utils.h" >> +#ifndef CONFIG_USER_ONLY >> +#include "hw/loader.h" >> +#endif >> + >> +void do_interrupt(CPUOpenRISCState *env) >> +{ >> +} >> diff --git a/target-openrisc/machine.c b/target-openrisc/machine.c >> new file mode 100644 >> index 0000000..11bf275 >> --- /dev/null >> +++ b/target-openrisc/machine.c >> @@ -0,0 +1,30 @@ >> +/* >> + * OpenRISC Machine >> + * >> + * Copyright (c) 2011-2012 Jia Liu <proljc@gmail.com> >> + * >> + * This library is free software; you can redistribute it and/or >> + * modify it under the terms of the GNU Lesser General Public >> + * License as published by the Free Software Foundation; either >> + * version 2 of the License, or (at your option) any later version. >> + * >> + * This library is distributed in the hope that it will be useful, >> + * but WITHOUT ANY WARRANTY; without even the implied warranty of >> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU >> + * Lesser General Public License for more details. >> + * >> + * You should have received a copy of the GNU Lesser General Public >> + * License along with this library; if not, see <http://www.gnu.org/licenses/>. >> + */ >> + >> +#include "hw/hw.h" >> +#include "hw/boards.h" >> + >> +void cpu_save(QEMUFile *f, void *opaque) >> +{ >> +} >> + >> +int cpu_load(QEMUFile *f, void *opaque, int version_id) >> +{ >> + return 0; >> +} > [snip] > > Shouldn't this be using VMState? Was there any problem converting? > Sorry, I'm not very sure. Is this code OK? static const VMStateDescription vmstate_cpu = { .name = "cpu", .fields = (VMStateField[]) { VMSTATE_UINT32_ARRAY(gpr, CPUOpenRISCState, 32), VMSTATE_UINT32(sr, CPUOpenRISCState), VMSTATE_UINT32(epcr, CPUOpenRISCState), VMSTATE_UINT32(eear, CPUOpenRISCState), VMSTATE_UINT32(esr, CPUOpenRISCState), VMSTATE_UINT32(fpcsr, CPUOpenRISCState), VMSTATE_UINT32(pc, CPUOpenRISCState), VMSTATE_UINT32(npc, CPUOpenRISCState), VMSTATE_UINT32(ppc, CPUOpenRISCState), VMSTATE_END_OF_LIST() } }; void cpu_save(QEMUFile *f, void *opaque) { vmstate_save_state(f, &vmstate_cpu, opaque); } int cpu_load(QEMUFile *f, void *opaque, int version_id) { return vmstate_load_state(f, &vmstate_cpu, opaque, version_id); } > Andreas > > -- > SUSE LINUX Products GmbH, Maxfeldstr. 5, 90409 Nürnberg, Germany > GF: Jeff Hawn, Jennifer Guild, Felix Imendörffer; HRB 16746 AG Nürnberg > > Regards, JIa. ^ permalink raw reply [flat|nested] 9+ messages in thread
end of thread, other threads:[~2012-07-09 7:08 UTC | newest] Thread overview: 9+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- [not found] <1341110730-444-1-git-send-email-proljc@gmail.com> [not found] ` <1341110730-444-9-git-send-email-proljc@gmail.com> 2012-07-03 18:48 ` [Qemu-devel] [PATCH v8 08/16] target-or32: Add instruction translation Blue Swirl 2012-07-04 2:23 ` Jia Liu 2012-07-04 23:59 ` Jia Liu 2012-07-05 18:45 ` Blue Swirl 2012-07-06 0:23 ` Jia Liu [not found] ` <1341110730-444-2-git-send-email-proljc@gmail.com> 2012-07-05 13:22 ` [Qemu-devel] [PATCH v8 01/16] target-or32: Add target stubs and QOM cpu Andreas Färber 2012-07-05 13:31 ` Paolo Bonzini 2012-07-05 15:31 ` Andreas Färber 2012-07-09 7:08 ` Jia Liu
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for NNTP newsgroup(s).