> Subject: [PATCH v2 08/33] target/mips: Add emulation of nanoMIPS FP > instructions > > From: Yongbok Kim <yongbok....@mips.com> > > Add emulation of basic floating point arithmetic for nanoMIPS. > > 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 | 300 > ++++++++++++++++++++++++++++++++++++++++++++++++ > 1 file changed, 300 insertions(+) > > diff --git a/target/mips/translate.c b/target/mips/translate.c
For future cleanups, the code should be organized so that there is one-to-one correspondence between functions (in the code) and instruction pools (as they are defined in the documentation). Also, opcode/register extraction should be consistent, as mentioned in other reviewer comments. That said, for the present development stage: Reviewed-by: Aleksandar Markovic <amarko...@wavecomp.com> > index ae46de2..176d51d 100644 > --- a/target/mips/translate.c > +++ b/target/mips/translate.c > @@ -16447,6 +16447,305 @@ static void gen_pool16c_nanomips_insn(DisasContext > *ctx) > } > } > > +static void gen_pool32f_nanomips_insn(DisasContext *ctx) > +{ > + int rt, rs, rd; > + > + rt = (ctx->opcode >> 21) & 0x1f; > + rs = (ctx->opcode >> 16) & 0x1f; > + rd = (ctx->opcode >> 11) & 0x1f; > + > + if (!(ctx->CP0_Config1 & (1 << CP0C1_FP))) { > + generate_exception_end(ctx, EXCP_RI); > + return; > + } > + check_cp1_enabled(ctx); > + switch (ctx->opcode & 0x07) { > + case NM_POOL32F_0: > + switch ((ctx->opcode >> 3) & 0x7f) { > + case NM_RINT_S: > + gen_farith(ctx, OPC_RINT_S, 0, rt, rs, 0); > + break; > + case NM_RINT_D: > + gen_farith(ctx, OPC_RINT_D, 0, rt, rs, 0); > + break; > + case NM_CLASS_S: > + gen_farith(ctx, OPC_CLASS_S, 0, rt, rs, 0); > + break; > + case NM_CLASS_D: > + gen_farith(ctx, OPC_CLASS_D, 0, rt, rs, 0); > + break; > + case NM_ADD_S: > + gen_farith(ctx, OPC_ADD_S, rt, rs, rd, 0); > + break; > + case NM_ADD_D: > + gen_farith(ctx, OPC_ADD_D, rt, rs, rd, 0); > + break; > + case NM_SUB_S: > + gen_farith(ctx, OPC_SUB_S, rt, rs, rd, 0); > + break; > + case NM_SUB_D: > + gen_farith(ctx, OPC_SUB_D, rt, rs, rd, 0); > + break; > + case NM_MUL_S: > + gen_farith(ctx, OPC_MUL_S, rt, rs, rd, 0); > + break; > + case NM_MUL_D: > + gen_farith(ctx, OPC_MUL_D, rt, rs, rd, 0); > + break; > + case NM_DIV_S: > + gen_farith(ctx, OPC_DIV_S, rt, rs, rd, 0); > + break; > + case NM_DIV_D: > + gen_farith(ctx, OPC_DIV_D, rt, rs, rd, 0); > + break; > + case NM_SELEQZ_S: > + gen_sel_s(ctx, OPC_SELEQZ_S, rd, rt, rs); > + break; > + case NM_SELEQZ_D: > + gen_sel_d(ctx, OPC_SELEQZ_D, rd, rt, rs); > + break; > + case NM_SELNEZ_S: > + gen_sel_s(ctx, OPC_SELNEZ_S, rd, rt, rs); > + break; > + case NM_SELNEZ_D: > + gen_sel_d(ctx, OPC_SELNEZ_D, rd, rt, rs); > + break; > + case NM_SEL_S: > + gen_sel_s(ctx, OPC_SEL_S, rd, rt, rs); > + break; > + case NM_SEL_D: > + gen_sel_d(ctx, OPC_SEL_D, rd, rt, rs); > + break; > + case NM_MADDF_S: > + gen_farith(ctx, OPC_MADDF_S, rt, rs, rd, 0); > + break; > + case NM_MADDF_D: > + gen_farith(ctx, OPC_MADDF_D, rt, rs, rd, 0); > + break; > + case NM_MSUBF_S: > + gen_farith(ctx, OPC_MSUBF_S, rt, rs, rd, 0); > + break; > + case NM_MSUBF_D: > + gen_farith(ctx, OPC_MSUBF_D, rt, rs, rd, 0); > + break; > + default: > + generate_exception_end(ctx, EXCP_RI); > + break; > + } > + break; > + case NM_POOL32F_3: > + switch ((ctx->opcode >> 3) & 0x07) { > + case NM_MIN_FMT: > + switch ((ctx->opcode >> 9) & 1) { > + case FMT_SDPS_S: > + gen_farith(ctx, OPC_MIN_S, rt, rs, rd, 0); > + break; > + case FMT_SDPS_D: > + gen_farith(ctx, OPC_MIN_D, rt, rs, rd, 0); > + break; > + } > + break; > + case NM_MAX_FMT: > + switch ((ctx->opcode >> 9) & 1) { > + case FMT_SDPS_S: > + gen_farith(ctx, OPC_MAX_S, rt, rs, rd, 0); > + break; > + case FMT_SDPS_D: > + gen_farith(ctx, OPC_MAX_D, rt, rs, rd, 0); > + break; > + } > + break; > + case NM_MINA_FMT: > + switch ((ctx->opcode >> 9) & 1) { > + case FMT_SDPS_S: > + gen_farith(ctx, OPC_MINA_S, rt, rs, rd, 0); > + break; > + case FMT_SDPS_D: > + gen_farith(ctx, OPC_MINA_D, rt, rs, rd, 0); > + break; > + } > + break; > + case NM_MAXA_FMT: > + switch ((ctx->opcode >> 9) & 1) { > + case FMT_SDPS_S: > + gen_farith(ctx, OPC_MAXA_S, rt, rs, rd, 0); > + break; > + case FMT_SDPS_D: > + gen_farith(ctx, OPC_MAXA_D, rt, rs, rd, 0); > + break; > + } > + break; > + case NM_POOL32FXF: > + switch ((ctx->opcode >> 6) & 0xff) { > + case NM_CFC1: > + gen_cp1(ctx, OPC_CFC1, rt, rs); > + break; > + case NM_CTC1: > + gen_cp1(ctx, OPC_CTC1, rt, rs); > + break; > + case NM_MFC1: > + gen_cp1(ctx, OPC_MFC1, rt, rs); > + break; > + case NM_MTC1: > + gen_cp1(ctx, OPC_MTC1, rt, rs); > + break; > + case NM_MFHC1: > + gen_cp1(ctx, OPC_MFHC1, rt, rs); > + break; > + case NM_MTHC1: > + gen_cp1(ctx, OPC_MTHC1, rt, rs); > + break; > + case NM_CVT_S_PL: > + gen_farith(ctx, OPC_CVT_S_PL, -1, rs, rt, 0); > + break; > + case NM_CVT_S_PU: > + gen_farith(ctx, OPC_CVT_S_PU, -1, rs, rt, 0); > + break; > + default: > + switch ((ctx->opcode >> 6) & 0x1ff) { > + case NM_CVT_L_S: > + gen_farith(ctx, OPC_CVT_L_S, -1, rs, rt, 0); > + break; > + case NM_CVT_L_D: > + gen_farith(ctx, OPC_CVT_L_D, -1, rs, rt, 0); > + break; > + case NM_CVT_W_S: > + gen_farith(ctx, OPC_CVT_W_S, -1, rs, rt, 0); > + break; > + case NM_CVT_W_D: > + gen_farith(ctx, OPC_CVT_W_D, -1, rs, rt, 0); > + break; > + case NM_RSQRT_S: > + gen_farith(ctx, OPC_RSQRT_S, -1, rs, rt, 0); > + break; > + case NM_RSQRT_D: > + gen_farith(ctx, OPC_RSQRT_D, -1, rs, rt, 0); > + break; > + case NM_SQRT_S: > + gen_farith(ctx, OPC_SQRT_S, -1, rs, rt, 0); > + break; > + case NM_SQRT_D: > + gen_farith(ctx, OPC_SQRT_D, -1, rs, rt, 0); > + break; > + case NM_RECIP_S: > + gen_farith(ctx, OPC_RECIP_S, -1, rs, rt, 0); > + break; > + case NM_RECIP_D: > + gen_farith(ctx, OPC_RECIP_D, -1, rs, rt, 0); > + break; > + case NM_FLOOR_L_S: > + gen_farith(ctx, OPC_FLOOR_L_S, -1, rs, rt, 0); > + break; > + case NM_FLOOR_L_D: > + gen_farith(ctx, OPC_FLOOR_L_D, -1, rs, rt, 0); > + break; > + case NM_FLOOR_W_S: > + gen_farith(ctx, OPC_FLOOR_W_S, -1, rs, rt, 0); > + break; > + case NM_FLOOR_W_D: > + gen_farith(ctx, OPC_FLOOR_W_D, -1, rs, rt, 0); > + break; > + case NM_CEIL_L_S: > + gen_farith(ctx, OPC_CEIL_L_S, -1, rs, rt, 0); > + break; > + case NM_CEIL_L_D: > + gen_farith(ctx, OPC_CEIL_L_D, -1, rs, rt, 0); > + break; > + case NM_CEIL_W_S: > + gen_farith(ctx, OPC_CEIL_W_S, -1, rs, rt, 0); > + break; > + case NM_CEIL_W_D: > + gen_farith(ctx, OPC_CEIL_W_D, -1, rs, rt, 0); > + break; > + case NM_TRUNC_L_S: > + gen_farith(ctx, OPC_TRUNC_L_S, -1, rs, rt, 0); > + break; > + case NM_TRUNC_L_D: > + gen_farith(ctx, OPC_TRUNC_L_D, -1, rs, rt, 0); > + break; > + case NM_TRUNC_W_S: > + gen_farith(ctx, OPC_TRUNC_W_S, -1, rs, rt, 0); > + break; > + case NM_TRUNC_W_D: > + gen_farith(ctx, OPC_TRUNC_W_D, -1, rs, rt, 0); > + break; > + case NM_ROUND_L_S: > + gen_farith(ctx, OPC_ROUND_L_S, -1, rs, rt, 0); > + break; > + case NM_ROUND_L_D: > + gen_farith(ctx, OPC_ROUND_L_D, -1, rs, rt, 0); > + break; > + case NM_ROUND_W_S: > + gen_farith(ctx, OPC_ROUND_W_S, -1, rs, rt, 0); > + break; > + case NM_ROUND_W_D: > + gen_farith(ctx, OPC_ROUND_W_D, -1, rs, rt, 0); > + break; > + case NM_MOV_S: > + gen_farith(ctx, OPC_MOV_S, -1, rs, rt, 0); > + break; > + case NM_MOV_D: > + gen_farith(ctx, OPC_MOV_D, -1, rs, rt, 0); > + break; > + case NM_ABS_S: > + gen_farith(ctx, OPC_ABS_S, -1, rs, rt, 0); > + break; > + case NM_ABS_D: > + gen_farith(ctx, OPC_ABS_D, -1, rs, rt, 0); > + break; > + case NM_NEG_S: > + gen_farith(ctx, OPC_NEG_S, -1, rs, rt, 0); > + break; > + case NM_NEG_D: > + gen_farith(ctx, OPC_NEG_D, -1, rs, rt, 0); > + break; > + case NM_CVT_D_S: > + gen_farith(ctx, OPC_CVT_D_S, -1, rs, rt, 0); > + break; > + case NM_CVT_D_W: > + gen_farith(ctx, OPC_CVT_D_W, -1, rs, rt, 0); > + break; > + case NM_CVT_D_L: > + gen_farith(ctx, OPC_CVT_D_L, -1, rs, rt, 0); > + break; > + case NM_CVT_S_D: > + gen_farith(ctx, OPC_CVT_S_D, -1, rs, rt, 0); > + break; > + case NM_CVT_S_W: > + gen_farith(ctx, OPC_CVT_S_W, -1, rs, rt, 0); > + break; > + case NM_CVT_S_L: > + gen_farith(ctx, OPC_CVT_S_L, -1, rs, rt, 0); > + break; > + default: > + generate_exception_end(ctx, EXCP_RI); > + break; > + } > + break; > + } > + break; > + } > + break; > + case NM_POOL32F_5: > + switch ((ctx->opcode >> 3) & 0x07) { > + case NM_CMP_CONDN_S: > + gen_r6_cmp_s(ctx, (ctx->opcode >> 6) & 0x1f, rt, rs, rd); > + break; > + case NM_CMP_CONDN_D: > + gen_r6_cmp_d(ctx, (ctx->opcode >> 6) & 0x1f, rt, rs, rd); > + break; > + default: > + generate_exception_end(ctx, EXCP_RI); > + break; > + } > + break; > + default: > + generate_exception_end(ctx, EXCP_RI); > + break; > + } > +} > + > static int decode_nanomips_32_48_opc(CPUMIPSState *env, DisasContext *ctx) > { > uint16_t insn; > @@ -16746,6 +17045,7 @@ static int decode_nanomips_32_48_opc(CPUMIPSState > *env, > DisasContext *ctx) > } > break; > case NM_POOL32F: > + gen_pool32f_nanomips_insn(ctx); > break; > case NM_POOL32S: > break; > -- > 2.7.4 > >