diff options
author | Richard Henderson <rth@twiddle.net> | 2014-03-19 14:46:36 -0700 |
---|---|---|
committer | Richard Henderson <rth@twiddle.net> | 2014-04-17 11:47:40 -0700 |
commit | 64f45e49911abb1b40095fc4cbf1e42172d267e7 (patch) | |
tree | 046689150d44ea0edb8e6ac29acf35816825349a /target-alpha | |
parent | 5238c88657d751e3acf3e953a9b11f5f24262f75 (diff) |
target-alpha: Introduce REQUIRE_REG_31
We were missing quite a few checks for Ra or Rb required to be 31.
Further, the one place we did check we also checked for no literal
operand and the Handbook says nothing about that.
Signed-off-by: Richard Henderson <rth@twiddle.net>
Diffstat (limited to 'target-alpha')
-rw-r--r-- | target-alpha/translate.c | 70 |
1 files changed, 44 insertions, 26 deletions
diff --git a/target-alpha/translate.c b/target-alpha/translate.c index 6ce4207adb..5c62244818 100644 --- a/target-alpha/translate.c +++ b/target-alpha/translate.c @@ -1772,6 +1772,13 @@ static ExitStatus gen_mtpr(DisasContext *ctx, int rb, int regno) } \ } while (0) +#define REQUIRE_REG_31(WHICH) \ + do { \ + if (WHICH != 31) { \ + goto invalid_opc; \ + } \ + } while (0) + static ExitStatus translate_one(DisasContext *ctx, uint32_t insn) { uint32_t palcode; @@ -1780,7 +1787,7 @@ static ExitStatus translate_one(DisasContext *ctx, uint32_t insn) int32_t disp12; #endif uint16_t fn11; - uint8_t opc, ra, rb, rc, fpfn, fn7, islit, real_islit; + uint8_t opc, ra, rb, rc, fpfn, fn7, islit; uint8_t lit; ExitStatus ret; @@ -1789,7 +1796,7 @@ static ExitStatus translate_one(DisasContext *ctx, uint32_t insn) ra = (insn >> 21) & 0x1F; rb = (insn >> 16) & 0x1F; rc = insn & 0x1F; - real_islit = islit = (insn >> 12) & 1; + islit = (insn >> 12) & 1; if (rb == 31 && !islit) { islit = 1; lit = 0; @@ -2303,6 +2310,7 @@ static ExitStatus translate_one(DisasContext *ctx, uint32_t insn) break; case 0x61: /* AMASK */ + REQUIRE_REG_31(ra); if (likely(rc != 31)) { uint64_t amask = ctx->tb->flags >> TB_FLAGS_AMASK_SHIFT; @@ -2323,6 +2331,7 @@ static ExitStatus translate_one(DisasContext *ctx, uint32_t insn) break; case 0x6C: /* IMPLVER */ + REQUIRE_REG_31(ra); if (rc != 31) { tcg_gen_movi_i64(cpu_ir[rc], ctx->implver); } @@ -2544,6 +2553,7 @@ static ExitStatus translate_one(DisasContext *ctx, uint32_t insn) switch (fpfn) { /* fn11 & 0x3F */ case 0x04: /* ITOFS */ + REQUIRE_REG_31(rb); if (likely(rc != 31)) { if (ra != 31) { TCGv_i32 tmp = tcg_temp_new_i32(); @@ -2556,14 +2566,17 @@ static ExitStatus translate_one(DisasContext *ctx, uint32_t insn) break; case 0x0A: /* SQRTF */ + REQUIRE_REG_31(ra); gen_fsqrtf(rb, rc); break; case 0x0B: /* SQRTS */ + REQUIRE_REG_31(ra); gen_fsqrts(ctx, rb, rc, fn11); break; case 0x14: /* ITOFF */ + REQUIRE_REG_31(rb); if (likely(rc != 31)) { if (ra != 31) { TCGv_i32 tmp = tcg_temp_new_i32(); @@ -2576,6 +2589,7 @@ static ExitStatus translate_one(DisasContext *ctx, uint32_t insn) break; case 0x24: /* ITOFT */ + REQUIRE_REG_31(rb); if (likely(rc != 31)) { if (ra != 31) { tcg_gen_mov_i64(cpu_fir[rc], cpu_ir[ra]); @@ -2586,10 +2600,12 @@ static ExitStatus translate_one(DisasContext *ctx, uint32_t insn) break; case 0x2A: /* SQRTG */ + REQUIRE_REG_31(ra); gen_fsqrtg(rb, rc); break; case 0x02B: /* SQRTT */ + REQUIRE_REG_31(ra); gen_fsqrtt(ctx, rb, rc, fn11); break; default: @@ -2617,13 +2633,9 @@ static ExitStatus translate_one(DisasContext *ctx, uint32_t insn) gen_fdivf(ra, rb, rc); break; case 0x1E: - /* CVTDG */ -#if 0 // TODO - gen_fcvtdg(rb, rc); -#else + /* CVTDG -- TODO */ + REQUIRE_REG_31(ra); goto invalid_opc; -#endif - break; case 0x20: /* ADDG */ gen_faddg(ra, rb, rc); @@ -2654,26 +2666,26 @@ static ExitStatus translate_one(DisasContext *ctx, uint32_t insn) break; case 0x2C: /* CVTGF */ + REQUIRE_REG_31(ra); gen_fcvtgf(rb, rc); break; case 0x2D: - /* CVTGD */ -#if 0 // TODO - gen_fcvtgd(rb, rc); -#else + /* CVTGD -- TODO */ + REQUIRE_REG_31(ra); goto invalid_opc; -#endif - break; case 0x2F: /* CVTGQ */ + REQUIRE_REG_31(ra); gen_fcvtgq(rb, rc); break; case 0x3C: /* CVTQF */ + REQUIRE_REG_31(ra); gen_fcvtqf(rb, rc); break; case 0x3E: /* CVTQG */ + REQUIRE_REG_31(ra); gen_fcvtqg(rb, rc); break; default: @@ -2732,6 +2744,7 @@ static ExitStatus translate_one(DisasContext *ctx, uint32_t insn) gen_fcmptle(ctx, ra, rb, rc, fn11); break; case 0x2C: + REQUIRE_REG_31(ra); if (fn11 == 0x2AC || fn11 == 0x6AC) { /* CVTST */ gen_fcvtst(ctx, rb, rc, fn11); @@ -2742,14 +2755,17 @@ static ExitStatus translate_one(DisasContext *ctx, uint32_t insn) break; case 0x2F: /* CVTTQ */ + REQUIRE_REG_31(ra); gen_fcvttq(ctx, rb, rc, fn11); break; case 0x3C: /* CVTQS */ + REQUIRE_REG_31(ra); gen_fcvtqs(ctx, rb, rc, fn11); break; case 0x3E: /* CVTQT */ + REQUIRE_REG_31(ra); gen_fcvtqt(ctx, rb, rc, fn11); break; default: @@ -2760,6 +2776,7 @@ static ExitStatus translate_one(DisasContext *ctx, uint32_t insn) switch (fn11) { case 0x010: /* CVTLQ */ + REQUIRE_REG_31(ra); gen_fcvtlq(rb, rc); break; case 0x020: @@ -2827,12 +2844,14 @@ static ExitStatus translate_one(DisasContext *ctx, uint32_t insn) break; case 0x030: /* CVTQL */ + REQUIRE_REG_31(ra); gen_fcvtql(rb, rc); break; case 0x130: /* CVTQL/V */ case 0x530: /* CVTQL/SV */ + REQUIRE_REG_31(ra); /* ??? I'm pretty sure there's nothing that /sv needs to do that /v doesn't do. The only thing I can think is that /sv is a valid instruction merely for completeness in the ISA. */ @@ -3010,6 +3029,7 @@ static ExitStatus translate_one(DisasContext *ctx, uint32_t insn) case 0x00: /* SEXTB */ REQUIRE_TB_FLAG(TB_FLAGS_AMASK_BWX); + REQUIRE_REG_31(ra); if (likely(rc != 31)) { if (islit) { tcg_gen_movi_i64(cpu_ir[rc], (int64_t)((int8_t)lit)); @@ -3021,6 +3041,7 @@ static ExitStatus translate_one(DisasContext *ctx, uint32_t insn) case 0x01: /* SEXTW */ REQUIRE_TB_FLAG(TB_FLAGS_AMASK_BWX); + REQUIRE_REG_31(ra); if (likely(rc != 31)) { if (islit) { tcg_gen_movi_i64(cpu_ir[rc], (int64_t)((int16_t)lit)); @@ -3032,6 +3053,7 @@ static ExitStatus translate_one(DisasContext *ctx, uint32_t insn) case 0x30: /* CTPOP */ REQUIRE_TB_FLAG(TB_FLAGS_AMASK_CIX); + REQUIRE_REG_31(ra); if (likely(rc != 31)) { if (islit) { tcg_gen_movi_i64(cpu_ir[rc], ctpop64(lit)); @@ -3048,6 +3070,7 @@ static ExitStatus translate_one(DisasContext *ctx, uint32_t insn) case 0x32: /* CTLZ */ REQUIRE_TB_FLAG(TB_FLAGS_AMASK_CIX); + REQUIRE_REG_31(ra); if (likely(rc != 31)) { if (islit) { tcg_gen_movi_i64(cpu_ir[rc], clz64(lit)); @@ -3059,6 +3082,7 @@ static ExitStatus translate_one(DisasContext *ctx, uint32_t insn) case 0x33: /* CTTZ */ REQUIRE_TB_FLAG(TB_FLAGS_AMASK_CIX); + REQUIRE_REG_31(ra); if (likely(rc != 31)) { if (islit) { tcg_gen_movi_i64(cpu_ir[rc], ctz64(lit)); @@ -3070,33 +3094,25 @@ static ExitStatus translate_one(DisasContext *ctx, uint32_t insn) case 0x34: /* UNPKBW */ REQUIRE_TB_FLAG(TB_FLAGS_AMASK_MVI); - if (real_islit || ra != 31) { - goto invalid_opc; - } + REQUIRE_REG_31(ra); gen_unpkbw(rb, rc); break; case 0x35: /* UNPKBL */ REQUIRE_TB_FLAG(TB_FLAGS_AMASK_MVI); - if (real_islit || ra != 31) { - goto invalid_opc; - } + REQUIRE_REG_31(ra); gen_unpkbl(rb, rc); break; case 0x36: /* PKWB */ REQUIRE_TB_FLAG(TB_FLAGS_AMASK_MVI); - if (real_islit || ra != 31) { - goto invalid_opc; - } + REQUIRE_REG_31(ra); gen_pkwb(rb, rc); break; case 0x37: /* PKLB */ REQUIRE_TB_FLAG(TB_FLAGS_AMASK_MVI); - if (real_islit || ra != 31) { - goto invalid_opc; - } + REQUIRE_REG_31(ra); gen_pklb(rb, rc); break; case 0x38: @@ -3142,6 +3158,7 @@ static ExitStatus translate_one(DisasContext *ctx, uint32_t insn) case 0x70: /* FTOIT */ REQUIRE_TB_FLAG(TB_FLAGS_AMASK_FIX); + REQUIRE_REG_31(rb); if (likely(rc != 31)) { if (ra != 31) { tcg_gen_mov_i64(cpu_ir[rc], cpu_fir[ra]); @@ -3153,6 +3170,7 @@ static ExitStatus translate_one(DisasContext *ctx, uint32_t insn) case 0x78: /* FTOIS */ REQUIRE_TB_FLAG(TB_FLAGS_AMASK_FIX); + REQUIRE_REG_31(rb); if (rc != 31) { TCGv_i32 tmp1 = tcg_temp_new_i32(); if (ra != 31) { |