aboutsummaryrefslogtreecommitdiff
path: root/target-mips
diff options
context:
space:
mode:
authorths <ths@c046a42c-6fe2-441c-8c8c-71466251a162>2007-04-05 23:20:05 +0000
committerths <ths@c046a42c-6fe2-441c-8c8c-71466251a162>2007-04-05 23:20:05 +0000
commit5a63bcb2d27675a3fc2c5bc8a8c323e5c756e749 (patch)
treef25e4c5339ff58b3b475676dfd1341ed3b2dd7b7 /target-mips
parentacd858d91f73fe310627e2b92a8fdd529ec06ade (diff)
Fix rotr immediate ops, mask shift/rotate arguments to their allowed
size. git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2614 c046a42c-6fe2-441c-8c8c-71466251a162
Diffstat (limited to 'target-mips')
-rw-r--r--target-mips/op.c19
-rw-r--r--target-mips/op_helper.c6
-rw-r--r--target-mips/translate.c126
3 files changed, 103 insertions, 48 deletions
diff --git a/target-mips/op.c b/target-mips/op.c
index d09b8da2df..d440896f32 100644
--- a/target-mips/op.c
+++ b/target-mips/op.c
@@ -493,19 +493,19 @@ void op_xor (void)
void op_sll (void)
{
- T0 = (int32_t)((uint32_t)T0 << (uint32_t)T1);
+ T0 = (int32_t)((uint32_t)T0 << T1);
RETURN();
}
void op_sra (void)
{
- T0 = (int32_t)((int32_t)T0 >> (uint32_t)T1);
+ T0 = (int32_t)((int32_t)T0 >> T1);
RETURN();
}
void op_srl (void)
{
- T0 = (int32_t)((uint32_t)T0 >> (uint32_t)T1);
+ T0 = (int32_t)((uint32_t)T0 >> T1);
RETURN();
}
@@ -514,10 +514,9 @@ void op_rotr (void)
target_ulong tmp;
if (T1) {
- tmp = (int32_t)((uint32_t)T0 << (0x20 - (uint32_t)T1));
- T0 = (int32_t)((uint32_t)T0 >> (uint32_t)T1) | tmp;
- } else
- T0 = T1;
+ tmp = (int32_t)((uint32_t)T0 << (0x20 - T1));
+ T0 = (int32_t)((uint32_t)T0 >> T1) | tmp;
+ }
RETURN();
}
@@ -707,8 +706,7 @@ void op_drotr (void)
if (T1) {
tmp = T0 << (0x40 - T1);
T0 = (T0 >> T1) | tmp;
- } else
- T0 = T1;
+ }
RETURN();
}
@@ -719,8 +717,7 @@ void op_drotr32 (void)
if (T1) {
tmp = T0 << (0x40 - (32 + T1));
T0 = (T0 >> (32 + T1)) | tmp;
- } else
- T0 = T1;
+ }
RETURN();
}
diff --git a/target-mips/op_helper.c b/target-mips/op_helper.c
index 7b6442e8f8..ba02f0d84f 100644
--- a/target-mips/op_helper.c
+++ b/target-mips/op_helper.c
@@ -120,8 +120,7 @@ void do_drotr (void)
if (T1) {
tmp = T0 << (0x40 - T1);
T0 = (T0 >> T1) | tmp;
- } else
- T0 = T1;
+ }
}
void do_drotr32 (void)
@@ -131,8 +130,7 @@ void do_drotr32 (void)
if (T1) {
tmp = T0 << (0x40 - (32 + T1));
T0 = (T0 >> (32 + T1)) | tmp;
- } else
- T0 = T1;
+ }
}
void do_dsllv (void)
diff --git a/target-mips/translate.c b/target-mips/translate.c
index 816b91e1c5..7b7c464fb7 100644
--- a/target-mips/translate.c
+++ b/target-mips/translate.c
@@ -849,18 +849,43 @@ static void gen_arith_imm (DisasContext *ctx, uint32_t opc, int rt,
MIPS_DEBUG("NOP");
return;
}
- if (opc == OPC_ADDI || opc == OPC_ADDIU ||
- opc == OPC_DADDI || opc == OPC_DADDIU ||
- opc == OPC_SLTI || opc == OPC_SLTIU)
+ uimm = (uint16_t)imm;
+ switch (opc) {
+ case OPC_ADDI:
+ case OPC_ADDIU:
+#ifdef TARGET_MIPS64
+ case OPC_DADDI:
+ case OPC_DADDIU:
+#endif
+ case OPC_SLTI:
+ case OPC_SLTIU:
uimm = (int32_t)imm; /* Sign extend to 32 bits */
- else
- uimm = (uint16_t)imm;
- if (opc != OPC_LUI) {
+ /* Fall through. */
+ case OPC_ANDI:
+ case OPC_ORI:
+ case OPC_XORI:
GEN_LOAD_REG_TN(T0, rs);
GEN_LOAD_IMM_TN(T1, uimm);
- } else {
- uimm = uimm << 16;
+ break;
+ case OPC_LUI:
+ uimm <<= 16;
GEN_LOAD_IMM_TN(T0, uimm);
+ break;
+ case OPC_SLL:
+ case OPC_SRA:
+ case OPC_SRL:
+#ifdef TARGET_MIPS64
+ case OPC_DSLL:
+ case OPC_DSRA:
+ case OPC_DSRL:
+ case OPC_DSLL32:
+ case OPC_DSRA32:
+ case OPC_DSRL32:
+#endif
+ uimm &= 0x1f;
+ GEN_LOAD_REG_TN(T0, rs);
+ GEN_LOAD_IMM_TN(T1, uimm);
+ break;
}
switch (opc) {
case OPC_ADDI:
@@ -915,13 +940,20 @@ static void gen_arith_imm (DisasContext *ctx, uint32_t opc, int rt,
opn = "sra";
break;
case OPC_SRL:
- if ((ctx->opcode >> 21) & 1) {
- gen_op_rotr();
- opn = "rotr";
- } else {
+ switch ((ctx->opcode >> 21) & 0x1f) {
+ case 0:
gen_op_srl();
opn = "srl";
- }
+ break;
+ case 1:
+ gen_op_rotr();
+ opn = "rotr";
+ break;
+ default:
+ MIPS_INVAL("invalid srl flag");
+ generate_exception(ctx, EXCP_RI);
+ break;
+ }
break;
#ifdef TARGET_MIPS64
case OPC_DSLL:
@@ -933,13 +965,20 @@ static void gen_arith_imm (DisasContext *ctx, uint32_t opc, int rt,
opn = "dsra";
break;
case OPC_DSRL:
- if ((ctx->opcode >> 21) & 1) {
- gen_op_drotr();
- opn = "drotr";
- } else {
+ switch ((ctx->opcode >> 21) & 0x1f) {
+ case 0:
gen_op_dsrl();
opn = "dsrl";
- }
+ break;
+ case 1:
+ gen_op_drotr();
+ opn = "drotr";
+ break;
+ default:
+ MIPS_INVAL("invalid dsrl flag");
+ generate_exception(ctx, EXCP_RI);
+ break;
+ }
break;
case OPC_DSLL32:
gen_op_dsll32();
@@ -950,13 +989,20 @@ static void gen_arith_imm (DisasContext *ctx, uint32_t opc, int rt,
opn = "dsra32";
break;
case OPC_DSRL32:
- if ((ctx->opcode >> 21) & 1) {
- gen_op_drotr32();
- opn = "drotr32";
- } else {
+ switch ((ctx->opcode >> 21) & 0x1f) {
+ case 0:
gen_op_dsrl32();
opn = "dsrl32";
- }
+ break;
+ case 1:
+ gen_op_drotr32();
+ opn = "drotr32";
+ break;
+ default:
+ MIPS_INVAL("invalid dsrl32 flag");
+ generate_exception(ctx, EXCP_RI);
+ break;
+ }
break;
#endif
default:
@@ -1068,13 +1114,20 @@ static void gen_arith (DisasContext *ctx, uint32_t opc,
opn = "srav";
break;
case OPC_SRLV:
- if ((ctx->opcode >> 6) & 1) {
- gen_op_rotrv();
- opn = "rotrv";
- } else {
+ switch ((ctx->opcode >> 6) & 0x1f) {
+ case 0:
gen_op_srlv();
opn = "srlv";
- }
+ break;
+ case 1:
+ gen_op_rotrv();
+ opn = "rotrv";
+ break;
+ default:
+ MIPS_INVAL("invalid srlv flag");
+ generate_exception(ctx, EXCP_RI);
+ break;
+ }
break;
#ifdef TARGET_MIPS64
case OPC_DSLLV:
@@ -1086,13 +1139,20 @@ static void gen_arith (DisasContext *ctx, uint32_t opc,
opn = "dsrav";
break;
case OPC_DSRLV:
- if ((ctx->opcode >> 6) & 1) {
- gen_op_drotrv();
- opn = "drotrv";
- } else {
+ switch ((ctx->opcode >> 6) & 0x1f) {
+ case 0:
gen_op_dsrlv();
opn = "dsrlv";
- }
+ break;
+ case 1:
+ gen_op_drotrv();
+ opn = "drotrv";
+ break;
+ default:
+ MIPS_INVAL("invalid dsrlv flag");
+ generate_exception(ctx, EXCP_RI);
+ break;
+ }
break;
#endif
default: