diff options
author | ths <ths@c046a42c-6fe2-441c-8c8c-71466251a162> | 2007-04-05 23:20:05 +0000 |
---|---|---|
committer | ths <ths@c046a42c-6fe2-441c-8c8c-71466251a162> | 2007-04-05 23:20:05 +0000 |
commit | 5a63bcb2d27675a3fc2c5bc8a8c323e5c756e749 (patch) | |
tree | f25e4c5339ff58b3b475676dfd1341ed3b2dd7b7 /target-mips | |
parent | acd858d91f73fe310627e2b92a8fdd529ec06ade (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.c | 19 | ||||
-rw-r--r-- | target-mips/op_helper.c | 6 | ||||
-rw-r--r-- | target-mips/translate.c | 126 |
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: |