Move all knowledge about coprocessor-checking and register numbering into the gen_cmp* helper functions.
Signed-off-by: Nathan Froyd <froy...@codesourcery.com> --- target-mips/translate.c | 232 ++++++++++++++++++++++++++++++----------------- 1 files changed, 149 insertions(+), 83 deletions(-) diff --git a/target-mips/translate.c b/target-mips/translate.c index 2568e16..8a7f3e9 100644 --- a/target-mips/translate.c +++ b/target-mips/translate.c @@ -354,6 +354,18 @@ enum { /* Coprocessor 1 (rs field) */ #define MASK_CP1(op) MASK_OP_MAJOR(op) | (op & (0x1F << 21)) +/* Values for the fmt field in FP instructions */ +enum { + /* 0 - 15 are reserved */ + FMT_S = 16, + FMT_D = 17, + /* 18 - 19 are reserved */ + FMT_W = 20, + FMT_L = 21, + FMT_PS = 22, + /* 23 - 31 are reserved */ +}; + enum { OPC_MFC1 = (0x00 << 21) | OPC_CP1, OPC_DMFC1 = (0x01 << 21) | OPC_CP1, @@ -663,39 +675,6 @@ static inline int get_fp_bit (int cc) return 23; } -#define FOP_CONDS(type, fmt, bits) \ -static inline void gen_cmp ## type ## _ ## fmt(int n, TCGv_i##bits a, \ - TCGv_i##bits b, int cc) \ -{ \ - switch (n) { \ - case 0: gen_helper_2i(cmp ## type ## _ ## fmt ## _f, a, b, cc); break;\ - case 1: gen_helper_2i(cmp ## type ## _ ## fmt ## _un, a, b, cc); break;\ - case 2: gen_helper_2i(cmp ## type ## _ ## fmt ## _eq, a, b, cc); break;\ - case 3: gen_helper_2i(cmp ## type ## _ ## fmt ## _ueq, a, b, cc); break;\ - case 4: gen_helper_2i(cmp ## type ## _ ## fmt ## _olt, a, b, cc); break;\ - case 5: gen_helper_2i(cmp ## type ## _ ## fmt ## _ult, a, b, cc); break;\ - case 6: gen_helper_2i(cmp ## type ## _ ## fmt ## _ole, a, b, cc); break;\ - case 7: gen_helper_2i(cmp ## type ## _ ## fmt ## _ule, a, b, cc); break;\ - case 8: gen_helper_2i(cmp ## type ## _ ## fmt ## _sf, a, b, cc); break;\ - case 9: gen_helper_2i(cmp ## type ## _ ## fmt ## _ngle, a, b, cc); break;\ - case 10: gen_helper_2i(cmp ## type ## _ ## fmt ## _seq, a, b, cc); break;\ - case 11: gen_helper_2i(cmp ## type ## _ ## fmt ## _ngl, a, b, cc); break;\ - case 12: gen_helper_2i(cmp ## type ## _ ## fmt ## _lt, a, b, cc); break;\ - case 13: gen_helper_2i(cmp ## type ## _ ## fmt ## _nge, a, b, cc); break;\ - case 14: gen_helper_2i(cmp ## type ## _ ## fmt ## _le, a, b, cc); break;\ - case 15: gen_helper_2i(cmp ## type ## _ ## fmt ## _ngt, a, b, cc); break;\ - default: abort(); \ - } \ -} - -FOP_CONDS(, d, 64) -FOP_CONDS(abs, d, 64) -FOP_CONDS(, s, 32) -FOP_CONDS(abs, s, 32) -FOP_CONDS(, ps, 64) -FOP_CONDS(abs, ps, 64) -#undef FOP_CONDS - /* Tests */ static inline void gen_save_pc(target_ulong pc) { @@ -836,6 +815,125 @@ static inline void check_mips_64(DisasContext *ctx) generate_exception(ctx, EXCP_RI); } +/* Define small wrappers for gen_load_fpr* so that we have a uniform + calling interface for 32 and 64-bit FPRs. No sense in changing + all callers for gen_load_fpr32 when we need the CTX parameter for + this one use. */ +#define gen_ldcmp_fpr32(ctx, x, y) gen_load_fpr32(x, y) +#define gen_ldcmp_fpr64(ctx, x, y) gen_load_fpr64(ctx, x, y) +#define FOP_CONDS(type, abs, fmt, ifmt, bits) \ +static inline void gen_cmp ## type ## _ ## fmt(DisasContext *ctx, int n, \ + int ft, int fs, int cc) \ +{ \ + TCGv_i##bits fp0 = tcg_temp_new_i##bits (); \ + TCGv_i##bits fp1 = tcg_temp_new_i##bits (); \ + switch (ifmt) { \ + case FMT_PS: \ + check_cp1_64bitmode(ctx); \ + break; \ + case FMT_D: \ + if (abs) \ + check_cop1x(ctx); \ + check_cp1_registers(ctx, fs | ft); \ + break; \ + case FMT_S: \ + if (abs) \ + check_cop1x(ctx); \ + break; \ + } \ + gen_ldcmp_fpr##bits (ctx, fp0, fs); \ + gen_ldcmp_fpr##bits (ctx, fp1, ft); \ + switch (n) { \ + case 0: gen_helper_2i(cmp ## type ## _ ## fmt ## _f, fp0, fp1, cc); break;\ + case 1: gen_helper_2i(cmp ## type ## _ ## fmt ## _un, fp0, fp1, cc); break;\ + case 2: gen_helper_2i(cmp ## type ## _ ## fmt ## _eq, fp0, fp1, cc); break;\ + case 3: gen_helper_2i(cmp ## type ## _ ## fmt ## _ueq, fp0, fp1, cc); break;\ + case 4: gen_helper_2i(cmp ## type ## _ ## fmt ## _olt, fp0, fp1, cc); break;\ + case 5: gen_helper_2i(cmp ## type ## _ ## fmt ## _ult, fp0, fp1, cc); break;\ + case 6: gen_helper_2i(cmp ## type ## _ ## fmt ## _ole, fp0, fp1, cc); break;\ + case 7: gen_helper_2i(cmp ## type ## _ ## fmt ## _ule, fp0, fp1, cc); break;\ + case 8: gen_helper_2i(cmp ## type ## _ ## fmt ## _sf, fp0, fp1, cc); break;\ + case 9: gen_helper_2i(cmp ## type ## _ ## fmt ## _ngle, fp0, fp1, cc); break;\ + case 10: gen_helper_2i(cmp ## type ## _ ## fmt ## _seq, fp0, fp1, cc); break;\ + case 11: gen_helper_2i(cmp ## type ## _ ## fmt ## _ngl, fp0, fp1, cc); break;\ + case 12: gen_helper_2i(cmp ## type ## _ ## fmt ## _lt, fp0, fp1, cc); break;\ + case 13: gen_helper_2i(cmp ## type ## _ ## fmt ## _nge, fp0, fp1, cc); break;\ + case 14: gen_helper_2i(cmp ## type ## _ ## fmt ## _le, fp0, fp1, cc); break;\ + case 15: gen_helper_2i(cmp ## type ## _ ## fmt ## _ngt, fp0, fp1, cc); break;\ + default: abort(); \ + } \ + tcg_temp_free_i##bits (fp0); \ + tcg_temp_free_i##bits (fp1); \ +} + +FOP_CONDS(, 0, d, FMT_D, 64) +FOP_CONDS(abs, 1, d, FMT_D, 64) +FOP_CONDS(, 0, s, FMT_S, 32) +FOP_CONDS(abs, 1, s, FMT_S, 32) +FOP_CONDS(, 0, ps, FMT_PS, 64) +FOP_CONDS(abs, 1, ps, FMT_PS, 64) +#undef FOP_CONDS +#undef gen_ldcmp_fpr32 +#undef gen_ldcmp_fpr64 + +/* Tests */ +#define OP_COND(name, cond) \ +static inline void glue(gen_op_, name) (TCGv ret, TCGv t0, TCGv t1) \ +{ \ + int l1 = gen_new_label(); \ + int l2 = gen_new_label(); \ + \ + tcg_gen_brcond_tl(cond, t0, t1, l1); \ + tcg_gen_movi_tl(ret, 0); \ + tcg_gen_br(l2); \ + gen_set_label(l1); \ + tcg_gen_movi_tl(ret, 1); \ + gen_set_label(l2); \ +} +OP_COND(eq, TCG_COND_EQ); +OP_COND(ne, TCG_COND_NE); +OP_COND(ge, TCG_COND_GE); +OP_COND(geu, TCG_COND_GEU); +OP_COND(lt, TCG_COND_LT); +OP_COND(ltu, TCG_COND_LTU); +#undef OP_COND + +#define OP_CONDI(name, cond) \ +static inline void glue(gen_op_, name) (TCGv ret, TCGv t0, target_ulong val) \ +{ \ + int l1 = gen_new_label(); \ + int l2 = gen_new_label(); \ + \ + tcg_gen_brcondi_tl(cond, t0, val, l1); \ + tcg_gen_movi_tl(ret, 0); \ + tcg_gen_br(l2); \ + gen_set_label(l1); \ + tcg_gen_movi_tl(ret, 1); \ + gen_set_label(l2); \ +} +OP_CONDI(lti, TCG_COND_LT); +OP_CONDI(ltiu, TCG_COND_LTU); +#undef OP_CONDI + +#define OP_CONDZ(name, cond) \ +static inline void glue(gen_op_, name) (TCGv ret, TCGv t0) \ +{ \ + int l1 = gen_new_label(); \ + int l2 = gen_new_label(); \ + \ + tcg_gen_brcondi_tl(cond, t0, 0, l1); \ + tcg_gen_movi_tl(ret, 0); \ + tcg_gen_br(l2); \ + gen_set_label(l1); \ + tcg_gen_movi_tl(ret, 1); \ + gen_set_label(l2); \ +} +OP_CONDZ(gez, TCG_COND_GE); +OP_CONDZ(gtz, TCG_COND_GT); +OP_CONDZ(lez, TCG_COND_LE); +OP_CONDZ(ltz, TCG_COND_LT); +#undef OP_CONDZ + /* load/store instructions. */ #define OP_LD(insn,fname) \ static inline void op_ldst_##insn(TCGv ret, TCGv arg1, DisasContext *ctx) \ @@ -6421,22 +6519,12 @@ static void gen_farith (DisasContext *ctx, uint32_t op1, case FOP(61, 16): case FOP(62, 16): case FOP(63, 16): - { - TCGv_i32 fp0 = tcg_temp_new_i32(); - TCGv_i32 fp1 = tcg_temp_new_i32(); - - gen_load_fpr32(fp0, fs); - gen_load_fpr32(fp1, ft); - if (ctx->opcode & (1 << 6)) { - check_cop1x(ctx); - gen_cmpabs_s(func-48, fp0, fp1, cc); - opn = condnames_abs[func-48]; - } else { - gen_cmp_s(func-48, fp0, fp1, cc); - opn = condnames[func-48]; - } - tcg_temp_free_i32(fp0); - tcg_temp_free_i32(fp1); + if (ctx->opcode & (1 << 6)) { + gen_cmpabs_s(ctx, func-48, ft, fs, cc); + opn = condnames_abs[func-48]; + } else { + gen_cmp_s(ctx, func-48, ft, fs, cc); + opn = condnames[func-48]; } break; case OPC_ADD_D: @@ -6784,24 +6872,12 @@ static void gen_farith (DisasContext *ctx, uint32_t op1, case FOP(61, 17): case FOP(62, 17): case FOP(63, 17): - { - TCGv_i64 fp0 = tcg_temp_new_i64(); - TCGv_i64 fp1 = tcg_temp_new_i64(); - - gen_load_fpr64(ctx, fp0, fs); - gen_load_fpr64(ctx, fp1, ft); - if (ctx->opcode & (1 << 6)) { - check_cop1x(ctx); - check_cp1_registers(ctx, fs | ft); - gen_cmpabs_d(func-48, fp0, fp1, cc); - opn = condnames_abs[func-48]; - } else { - check_cp1_registers(ctx, fs | ft); - gen_cmp_d(func-48, fp0, fp1, cc); - opn = condnames[func-48]; - } - tcg_temp_free_i64(fp0); - tcg_temp_free_i64(fp1); + if (ctx->opcode & (1 << 6)) { + gen_cmpabs_d(ctx, func-48, ft, fs, cc); + opn = condnames_abs[func-48]; + } else { + gen_cmp_d(ctx, func-48, ft, fs, cc); + opn = condnames[func-48]; } break; case OPC_CVT_S_D: @@ -7221,22 +7297,12 @@ static void gen_farith (DisasContext *ctx, uint32_t op1, case FOP(61, 22): case FOP(62, 22): case FOP(63, 22): - check_cp1_64bitmode(ctx); - { - TCGv_i64 fp0 = tcg_temp_new_i64(); - TCGv_i64 fp1 = tcg_temp_new_i64(); - - gen_load_fpr64(ctx, fp0, fs); - gen_load_fpr64(ctx, fp1, ft); - if (ctx->opcode & (1 << 6)) { - gen_cmpabs_ps(func-48, fp0, fp1, cc); - opn = condnames_abs[func-48]; - } else { - gen_cmp_ps(func-48, fp0, fp1, cc); - opn = condnames[func-48]; - } - tcg_temp_free_i64(fp0); - tcg_temp_free_i64(fp1); + if (ctx->opcode & (1 << 6)) { + gen_cmpabs_ps(ctx, func-48, ft, fs, cc); + opn = condnames_abs[func-48]; + } else { + gen_cmp_ps(ctx, func-48, ft, fs, cc); + opn = condnames[func-48]; } break; default: -- 1.6.3.2