aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRichard Henderson <rth@twiddle.net>2014-03-19 14:46:36 -0700
committerRichard Henderson <rth@twiddle.net>2014-04-17 11:47:40 -0700
commit64f45e49911abb1b40095fc4cbf1e42172d267e7 (patch)
tree046689150d44ea0edb8e6ac29acf35816825349a
parent5238c88657d751e3acf3e953a9b11f5f24262f75 (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>
-rw-r--r--target-alpha/translate.c70
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) {