diff options
Diffstat (limited to 'target-mips/translate.c')
-rw-r--r-- | target-mips/translate.c | 126 |
1 files changed, 93 insertions, 33 deletions
diff --git a/target-mips/translate.c b/target-mips/translate.c index 816b91e..7b7c464 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: |