> Subject: [PATCH v2 14/33] target/mips: Add emulation of nanoMIPS 32-bit load > and store > instructions > > From: Yongbok Kim <yongbok....@mips.com> > > Add emulation of various nanoMIPS load and store instructions. > > Signed-off-by: Yongbok Kim <yongbok....@mips.com> > Signed-off-by: Aleksandar Markovic <amarko...@wavecomp.com> > Signed-off-by: Stefan Markovic <smarko...@wavecomp.com> > --- > target/mips/translate.c | 271 > ++++++++++++++++++++++++++++++++++++++++++++++++ > 1 file changed, 271 insertions(+) >
Switch-case alignment in this parch doesn't look good. If this is fixed: Reviewed-by: Aleksandar Markovic <amarko...@wavecomp.com> > diff --git a/target/mips/translate.c b/target/mips/translate.c > index 3160a3f..d48a0cf 100644 > --- a/target/mips/translate.c > +++ b/target/mips/translate.c > @@ -17527,10 +17527,281 @@ static int decode_nanomips_32_48_opc(CPUMIPSState > *env, > DisasContext *ctx) > } > break; > case NM_P_GP_BH: > + { > + uint32_t u = extract32(ctx->opcode, 0, 18); > + switch ((ctx->opcode >> 18) & 0x7) { > + case NM_LBGP: > + gen_ld(ctx, OPC_LB, rt, 28, u); > + break; > + case NM_SBGP: > + gen_st(ctx, OPC_SB, rt, 28, u); > + break; > + case NM_LBUGP: > + gen_ld(ctx, OPC_LBU, rt, 28, u); > + break; > + case NM_ADDIUGP_B: > + gen_arith_imm(ctx, OPC_ADDIU, rt, 28, u); > + break; > + case NM_P_GP_LH: > + u &= ~1; > + switch (ctx->opcode & 1) { > + case NM_LHGP: > + gen_ld(ctx, OPC_LH, rt, 28, u); > + break; > + case NM_LHUGP: > + gen_ld(ctx, OPC_LHU, rt, 28, u); > + break; > + } > + break; > + case NM_P_GP_SH: > + u &= ~1; > + switch (ctx->opcode & 1) { > + case NM_SHGP: > + gen_st(ctx, OPC_SH, rt, 28, u); > + break; > + default: > + generate_exception_end(ctx, EXCP_RI); > + break; > + } > + break; > + case NM_P_GP_CP1: > + u &= ~0x3; > + switch ((ctx->opcode & 0x3)) { > + case NM_LWC1GP: > + gen_cop1_ldst(ctx, OPC_LWC1, rt, 28, u); > + break; > + case NM_LDC1GP: > + gen_cop1_ldst(ctx, OPC_LDC1, rt, 28, u); > + break; > + case NM_SWC1GP: > + gen_cop1_ldst(ctx, OPC_SWC1, rt, 28, u); > + break; > + case NM_SDC1GP: > + gen_cop1_ldst(ctx, OPC_SDC1, rt, 28, u); > + break; > + } > + break; > + default: > + generate_exception_end(ctx, EXCP_RI); > + break; > + } > + } > break; > case NM_P_LS_U12: > + { > + uint32_t u = extract32(ctx->opcode, 0, 12); > + switch ((ctx->opcode >> 12) & 0x0f) { > + case NM_P_PREFU12: > + if (rt == 31) { > + /* SYNCI */ > + /* Break the TB to be able to sync copied instructions > + immediately */ > + ctx->base.is_jmp = DISAS_STOP; > + } else { > + /* PREF */ > + /* Treat as NOP. */ > + } > + break; > + case NM_LB: > + gen_ld(ctx, OPC_LB, rt, rs, u); > + break; > + case NM_LH: > + gen_ld(ctx, OPC_LH, rt, rs, u); > + break; > + case NM_LW: > + gen_ld(ctx, OPC_LW, rt, rs, u); > + break; > + case NM_LBU: > + gen_ld(ctx, OPC_LBU, rt, rs, u); > + break; > + case NM_LHU: > + gen_ld(ctx, OPC_LHU, rt, rs, u); > + break; > + case NM_SB: > + gen_st(ctx, OPC_SB, rt, rs, u); > + break; > + case NM_SH: > + gen_st(ctx, OPC_SH, rt, rs, u); > + break; > + case NM_SW: > + gen_st(ctx, OPC_SW, rt, rs, u); > + break; > + case NM_LWC1: > + gen_cop1_ldst(ctx, OPC_LWC1, rt, rs, u); > + break; > + case NM_LDC1: > + gen_cop1_ldst(ctx, OPC_LDC1, rt, rs, u); > + break; > + case NM_SWC1: > + gen_cop1_ldst(ctx, OPC_SWC1, rt, rs, u); > + break; > + case NM_SDC1: > + gen_cop1_ldst(ctx, OPC_SDC1, rt, rs, u); > + break; > + default: > + generate_exception_end(ctx, EXCP_RI); > + break; > + } > + } > break; > case NM_P_LS_S9: > + { > + int32_t s = (sextract32(ctx->opcode, 15, 1) << 8) | > + extract32(ctx->opcode, 0, 8); > + switch ((ctx->opcode >> 8) & 0x07) { > + case NM_P_LS_S0: > + switch ((ctx->opcode >> 11) & 0x0f) { > + case NM_LBS9: > + gen_ld(ctx, OPC_LB, rt, rs, s); > + break; > + case NM_LHS9: > + gen_ld(ctx, OPC_LH, rt, rs, s); > + break; > + case NM_LWS9: > + gen_ld(ctx, OPC_LW, rt, rs, s); > + break; > + case NM_LBUS9: > + gen_ld(ctx, OPC_LBU, rt, rs, s); > + break; > + case NM_LHUS9: > + gen_ld(ctx, OPC_LHU, rt, rs, s); > + break; > + case NM_SBS9: > + gen_st(ctx, OPC_SB, rt, rs, s); > + break; > + case NM_SHS9: > + gen_st(ctx, OPC_SH, rt, rs, s); > + break; > + case NM_SWS9: > + gen_st(ctx, OPC_SW, rt, rs, s); > + break; > + case NM_LWC1S9: > + gen_cop1_ldst(ctx, OPC_LWC1, rt, rs, s); > + break; > + case NM_LDC1S9: > + gen_cop1_ldst(ctx, OPC_LDC1, rt, rs, s); > + break; > + case NM_SWC1S9: > + gen_cop1_ldst(ctx, OPC_SWC1, rt, rs, s); > + break; > + case NM_SDC1S9: > + gen_cop1_ldst(ctx, OPC_SDC1, rt, rs, s); > + break; > + case NM_P_PREFS9: > + if (rt == 31) { > + /* SYNCI */ > + /* Break the TB to be able to sync copied instructions > + immediately */ > + ctx->base.is_jmp = DISAS_STOP; > + } else { > + /* PREF */ > + /* Treat as NOP. */ > + } > + break; > + default: > + generate_exception_end(ctx, EXCP_RI); > + break; > + } > + break; > + case NM_P_LS_S1: > + switch ((ctx->opcode >> 11) & 0x0f) { > + case NM_UALH: > + case NM_UASH: > + { > + TCGv t0 = tcg_temp_new(); > + TCGv t1 = tcg_temp_new(); > + > + gen_base_offset_addr(ctx, t0, rs, s); > + > + switch ((ctx->opcode >> 11) & 0x0f) { > + case NM_UALH: > + tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESW | > + MO_UNALN); > + gen_store_gpr(t0, rt); > + break; > + case NM_UASH: > + gen_load_gpr(t1, rt); > + tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUW | > + MO_UNALN); > + break; > + } > + tcg_temp_free(t0); > + tcg_temp_free(t1); > + } > + break; > + case NM_P_LL: > + switch (ctx->opcode & 0x03) { > + case NM_LL: > + gen_ld(ctx, OPC_LL, rt, rs, s); > + break; > + case NM_LLWP: > + break; > + } > + break; > + case NM_P_SC: > + switch (ctx->opcode & 0x03) { > + case NM_SC: > + gen_st_cond(ctx, OPC_SC, rt, rs, s); > + break; > + case NM_SCWP: > + break; > + } > + break; > + case NM_CACHE: > + check_cp0_enabled(ctx); > + if (ctx->hflags & MIPS_HFLAG_ITC_CACHE) { > + gen_cache_operation(ctx, rt, rs, s); > + } > + break; > + } > + break; > + case NM_P_LS_WM: > + case NM_P_LS_UAWM: > + { > + int32_t offset = sextract32(ctx->opcode, 15, 1) << 8 | > + extract32(ctx->opcode, 0, 8); > + int count = extract32(ctx->opcode, 12, 3); > + int counter = 0; > + TCGv va = tcg_temp_new(); > + TCGv t1 = tcg_temp_new(); > + TCGMemOp memop = ((ctx->opcode >> 8) & 0x07) == NM_P_LS_UAWM ? > + MO_UNALN : 0; > + > + count = (count == 0) ? 8 : count; > + while (counter != count) { > + int this_rt = ((rt + counter) & 0x1f) | (rt & 0x10); > + int32_t this_offset = offset + (counter << 2); > + > + gen_base_offset_addr(ctx, va, rs, this_offset); > + > + switch (extract32(ctx->opcode, 11, 1)) { > + case NM_LWM: > + tcg_gen_qemu_ld_tl(t1, va, ctx->mem_idx, > + memop | MO_TESL); > + gen_store_gpr(t1, this_rt); > + if ((this_rt == rs) && > + (counter != (count - 1))) { > + /* UNPREDICTABLE */ > + } > + break; > + case NM_SWM: > + this_rt = (rt == 0) ? 0 : this_rt; > + gen_load_gpr(t1, this_rt); > + tcg_gen_qemu_st_tl(t1, va, ctx->mem_idx, > + memop | MO_TEUL); > + break; > + } > + counter++; > + } > + tcg_temp_free(va); > + tcg_temp_free(t1); > + } > + break; > + default: > + generate_exception_end(ctx, EXCP_RI); > + break; > + } > + } > break; > case NM_MOVE_BALC: > break; > -- > 2.7.4 > >