| Index: src/mips/simulator-mips.cc
|
| diff --git a/src/mips/simulator-mips.cc b/src/mips/simulator-mips.cc
|
| index e945b0ca5fa1741c58368a348e90f25ad81c899d..e9dd0d32dca5c69b0d8ae19419a580f14a9ec33f 100644
|
| --- a/src/mips/simulator-mips.cc
|
| +++ b/src/mips/simulator-mips.cc
|
| @@ -129,7 +129,7 @@ void MipsDebugger::Stop(Instruction* instr) {
|
|
|
| #else // GENERATED_CODE_COVERAGE
|
|
|
| -#define UNSUPPORTED() printf("Unsupported instruction.\n");
|
| +#define UNSUPPORTED() printf("Sim: Unsupported instruction.\n");
|
|
|
| static void InitializeCoverage() {}
|
|
|
| @@ -3736,26 +3736,7 @@ void Simulator::DecodeTypeRegister(Instruction* instr) {
|
| }
|
|
|
|
|
| -// Branch instructions common part.
|
| -#define BranchAndLinkHelper(do_branch) \
|
| - execute_branch_delay_instruction = true; \
|
| - if (do_branch) { \
|
| - next_pc = current_pc + (imm16 << 2) + Instruction::kInstrSize; \
|
| - set_register(31, current_pc + 2 * Instruction::kInstrSize); \
|
| - } else { \
|
| - next_pc = current_pc + 2 * Instruction::kInstrSize; \
|
| - }
|
| -
|
| -#define BranchHelper(do_branch) \
|
| - execute_branch_delay_instruction = true; \
|
| - if (do_branch) { \
|
| - next_pc = current_pc + (imm16 << 2) + Instruction::kInstrSize; \
|
| - } else { \
|
| - next_pc = current_pc + 2 * Instruction::kInstrSize; \
|
| - }
|
| -
|
| -
|
| -// Type 2: instructions using a 16 bytes immediate. (e.g. addi, beq).
|
| +// Type 2: instructions using a 16, 21 or 26 bits immediate. (e.g. beq, beqc).
|
| void Simulator::DecodeTypeImmediate(Instruction* instr) {
|
| // Instruction fields.
|
| Opcode op = instr->OpcodeFieldRaw();
|
| @@ -3765,20 +3746,14 @@ void Simulator::DecodeTypeImmediate(Instruction* instr) {
|
| int32_t rt_reg = instr->RtValue(); // Destination register.
|
| int32_t rt = get_register(rt_reg);
|
| int16_t imm16 = instr->Imm16Value();
|
| - int32_t imm21 = instr->Imm21Value();
|
| - int32_t imm26 = instr->Imm26Value();
|
|
|
| int32_t ft_reg = instr->FtValue(); // Destination register.
|
| - int64_t ft;
|
|
|
| // Zero extended immediate.
|
| uint32_t oe_imm16 = 0xffff & imm16;
|
| // Sign extended immediate.
|
| int32_t se_imm16 = imm16;
|
| - int32_t se_imm26 = imm26 | ((imm26 & 0x2000000) ? 0xfc000000 : 0);
|
|
|
| - // Get current pc.
|
| - int32_t current_pc = get_pc();
|
| // Next pc.
|
| int32_t next_pc = bad_ra;
|
|
|
| @@ -3791,7 +3766,58 @@ void Simulator::DecodeTypeImmediate(Instruction* instr) {
|
| // Used for memory instructions.
|
| int32_t addr = 0x0;
|
|
|
| - // ---------- Configuration (and execution for REGIMM).
|
| + // Branch instructions common part.
|
| + auto BranchAndLinkHelper = [this, instr, &next_pc,
|
| + &execute_branch_delay_instruction](
|
| + bool do_branch) {
|
| + execute_branch_delay_instruction = true;
|
| + int32_t current_pc = get_pc();
|
| + if (do_branch) {
|
| + int16_t imm16 = instr->Imm16Value();
|
| + next_pc = current_pc + (imm16 << 2) + Instruction::kInstrSize;
|
| + set_register(31, current_pc + 2 * Instruction::kInstrSize);
|
| + } else {
|
| + next_pc = current_pc + 2 * Instruction::kInstrSize;
|
| + }
|
| + };
|
| +
|
| + auto BranchHelper = [this, instr, &next_pc,
|
| + &execute_branch_delay_instruction](bool do_branch) {
|
| + execute_branch_delay_instruction = true;
|
| + int32_t current_pc = get_pc();
|
| + if (do_branch) {
|
| + int16_t imm16 = instr->Imm16Value();
|
| + next_pc = current_pc + (imm16 << 2) + Instruction::kInstrSize;
|
| + } else {
|
| + next_pc = current_pc + 2 * Instruction::kInstrSize;
|
| + }
|
| + };
|
| +
|
| + auto BranchAndLinkCompactHelper = [this, instr, &next_pc](bool do_branch,
|
| + int bits) {
|
| + int32_t current_pc = get_pc();
|
| + CheckForbiddenSlot(current_pc);
|
| + if (do_branch) {
|
| + int32_t imm = instr->ImmValue(bits);
|
| + imm <<= 32 - bits;
|
| + imm >>= 32 - bits;
|
| + next_pc = current_pc + (imm << 2) + Instruction::kInstrSize;
|
| + set_register(31, current_pc + Instruction::kInstrSize);
|
| + }
|
| + };
|
| +
|
| + auto BranchCompactHelper = [&next_pc, this, instr](bool do_branch, int bits) {
|
| + int32_t current_pc = get_pc();
|
| + CheckForbiddenSlot(current_pc);
|
| + if (do_branch) {
|
| + int32_t imm = instr->ImmValue(bits);
|
| + imm <<= 32 - bits;
|
| + imm >>= 32 - bits;
|
| + next_pc = get_pc() + (imm << 2) + Instruction::kInstrSize;
|
| + }
|
| + };
|
| +
|
| +
|
| switch (op) {
|
| // ------------- COP1. Coprocessor instructions.
|
| case COP1:
|
| @@ -3802,34 +3828,14 @@ void Simulator::DecodeTypeImmediate(Instruction* instr) {
|
| uint32_t fcsr_cc = get_fcsr_condition_bit(cc);
|
| uint32_t cc_value = test_fcsr_bit(fcsr_cc);
|
| bool do_branch = (instr->FBtrueValue()) ? cc_value : !cc_value;
|
| - execute_branch_delay_instruction = true;
|
| - // Set next_pc.
|
| - if (do_branch) {
|
| - next_pc = current_pc + (imm16 << 2) + Instruction::kInstrSize;
|
| - } else {
|
| - next_pc = current_pc + kBranchReturnOffset;
|
| - }
|
| + BranchHelper(do_branch);
|
| break;
|
| }
|
| case BC1EQZ:
|
| - ft = get_fpu_register(ft_reg);
|
| - execute_branch_delay_instruction = true;
|
| - // Set next_pc.
|
| - if (!(ft & 0x1)) {
|
| - next_pc = current_pc + (imm16 << 2) + Instruction::kInstrSize;
|
| - } else {
|
| - next_pc = current_pc + kBranchReturnOffset;
|
| - }
|
| + BranchHelper(!(get_fpu_register(ft_reg) & 0x1));
|
| break;
|
| case BC1NEZ:
|
| - ft = get_fpu_register(ft_reg);
|
| - execute_branch_delay_instruction = true;
|
| - // Set next_pc.
|
| - if (ft & 0x1) {
|
| - next_pc = current_pc + (imm16 << 2) + Instruction::kInstrSize;
|
| - } else {
|
| - next_pc = current_pc + kBranchReturnOffset;
|
| - }
|
| + BranchHelper(get_fpu_register(ft_reg) & 0x1);
|
| break;
|
| default:
|
| UNREACHABLE();
|
| @@ -3863,54 +3869,158 @@ void Simulator::DecodeTypeImmediate(Instruction* instr) {
|
| case BNE:
|
| BranchHelper(rs != rt);
|
| break;
|
| - case BLEZ:
|
| - BranchHelper(rs <= 0);
|
| - break;
|
| - case BGTZ:
|
| - BranchHelper(rs > 0);
|
| - break;
|
| - case POP66: {
|
| - if (rs_reg) { // BEQZC
|
| - int32_t se_imm21 =
|
| - static_cast<int32_t>(imm21 << (kOpcodeBits + kRsBits));
|
| - se_imm21 = se_imm21 >> (kOpcodeBits + kRsBits);
|
| - if (rs == 0)
|
| - next_pc = current_pc + 4 + (se_imm21 << 2);
|
| - else
|
| - next_pc = current_pc + 4;
|
| + case POP06: // BLEZALC, BGEZALC, BGEUC, BLEZ (pre-r6)
|
| + if (IsMipsArchVariant(kMips32r6)) {
|
| + if (rt_reg != 0) {
|
| + if (rs_reg == 0) { // BLEZALC
|
| + BranchAndLinkCompactHelper(rt <= 0, 16);
|
| + } else {
|
| + if (rs_reg == rt_reg) { // BGEZALC
|
| + BranchAndLinkCompactHelper(rt >= 0, 16);
|
| + } else { // BGEUC
|
| + BranchCompactHelper(
|
| + static_cast<uint32_t>(rs) >= static_cast<uint32_t>(rt), 16);
|
| + }
|
| + }
|
| + } else { // BLEZ
|
| + BranchHelper(rs <= 0);
|
| + }
|
| + } else { // BLEZ
|
| + BranchHelper(rs <= 0);
|
| + }
|
| + break;
|
| + case POP07: // BGTZALC, BLTZALC, BLTUC, BGTZ (pre-r6)
|
| + if (IsMipsArchVariant(kMips32r6)) {
|
| + if (rt_reg != 0) {
|
| + if (rs_reg == 0) { // BGTZALC
|
| + BranchAndLinkCompactHelper(rt > 0, 16);
|
| + } else {
|
| + if (rt_reg == rs_reg) { // BLTZALC
|
| + BranchAndLinkCompactHelper(rt < 0, 16);
|
| + } else { // BLTUC
|
| + BranchCompactHelper(
|
| + static_cast<uint32_t>(rs) < static_cast<uint32_t>(rt), 16);
|
| + }
|
| + }
|
| + } else { // BGTZ
|
| + BranchHelper(rs > 0);
|
| + }
|
| + } else { // BGTZ
|
| + BranchHelper(rs > 0);
|
| + }
|
| + break;
|
| + case POP26: // BLEZC, BGEZC, BGEC/BLEC / BLEZL (pre-r6)
|
| + if (IsMipsArchVariant(kMips32r6)) {
|
| + if (rt_reg != 0) {
|
| + if (rs_reg == 0) { // BLEZC
|
| + BranchCompactHelper(rt <= 0, 16);
|
| + } else {
|
| + if (rs_reg == rt_reg) { // BGEZC
|
| + BranchCompactHelper(rt >= 0, 16);
|
| + } else { // BGEC/BLEC
|
| + BranchCompactHelper(rs >= rt, 16);
|
| + }
|
| + }
|
| + }
|
| + } else { // BLEZL
|
| + BranchAndLinkHelper(rs <= 0);
|
| + }
|
| + break;
|
| + case POP27: // BGTZC, BLTZC, BLTC/BGTC / BGTZL (pre-r6)
|
| + if (IsMipsArchVariant(kMips32r6)) {
|
| + if (rt_reg != 0) {
|
| + if (rs_reg == 0) { // BGTZC
|
| + BranchCompactHelper(rt > 0, 16);
|
| + } else {
|
| + if (rs_reg == rt_reg) { // BLTZC
|
| + BranchCompactHelper(rt < 0, 16);
|
| + } else { // BLTC/BGTC
|
| + BranchCompactHelper(rs < rt, 16);
|
| + }
|
| + }
|
| + }
|
| + } else { // BGTZL
|
| + BranchAndLinkHelper(rs > 0);
|
| + }
|
| + break;
|
| + case POP66: // BEQZC, JIC
|
| + if (rs_reg != 0) { // BEQZC
|
| + BranchCompactHelper(rs == 0, 21);
|
| } else { // JIC
|
| + CheckForbiddenSlot(get_pc());
|
| next_pc = rt + imm16;
|
| }
|
| break;
|
| - }
|
| - case BC: {
|
| - next_pc = current_pc + 4 + (se_imm26 << 2);
|
| - set_pc(next_pc);
|
| - pc_modified_ = true;
|
| + case POP76: // BNEZC, JIALC
|
| + if (rs_reg != 0) { // BNEZC
|
| + BranchCompactHelper(rs != 0, 21);
|
| + } else { // JIALC
|
| + int32_t current_pc = get_pc();
|
| + CheckForbiddenSlot(current_pc);
|
| + set_register(31, current_pc + Instruction::kInstrSize);
|
| + next_pc = rt + imm16;
|
| + }
|
| break;
|
| - }
|
| - case BALC: {
|
| - set_register(31, current_pc + 4);
|
| - next_pc = current_pc + 4 + (se_imm26 << 2);
|
| - set_pc(next_pc);
|
| - pc_modified_ = true;
|
| + case BC:
|
| + BranchCompactHelper(true, 26);
|
| break;
|
| - }
|
| - // ------------- Arithmetic instructions.
|
| - case ADDI:
|
| - if (HaveSameSign(rs, se_imm16)) {
|
| - if (rs > 0) {
|
| - if (rs <= (Registers::kMaxValue - se_imm16)) {
|
| - SignalException(kIntegerOverflow);
|
| + case BALC:
|
| + BranchAndLinkCompactHelper(true, 26);
|
| + break;
|
| + case POP10: // BOVC, BEQZALC, BEQC / ADDI (pre-r6)
|
| + if (IsMipsArchVariant(kMips32r6)) {
|
| + if (rs_reg >= rt_reg) { // BOVC
|
| + if (HaveSameSign(rs, rt)) {
|
| + if (rs > 0) {
|
| + BranchCompactHelper(rs > Registers::kMaxValue - rt, 16);
|
| + } else if (rs < 0) {
|
| + BranchCompactHelper(rs < Registers::kMinValue - rt, 16);
|
| + }
|
| }
|
| - } else if (rs < 0) {
|
| - if (rs >= (Registers::kMinValue - se_imm16)) {
|
| - SignalException(kIntegerUnderflow);
|
| + } else {
|
| + if (rs_reg == 0) { // BEQZALC
|
| + BranchAndLinkCompactHelper(rt == 0, 16);
|
| + } else { // BEQC
|
| + BranchCompactHelper(rt == rs, 16);
|
| }
|
| }
|
| + } else { // ADDI
|
| + if (HaveSameSign(rs, se_imm16)) {
|
| + if (rs > 0) {
|
| + if (rs <= Registers::kMaxValue - se_imm16) {
|
| + SignalException(kIntegerOverflow);
|
| + }
|
| + } else if (rs < 0) {
|
| + if (rs >= Registers::kMinValue - se_imm16) {
|
| + SignalException(kIntegerUnderflow);
|
| + }
|
| + }
|
| + }
|
| + SetResult(rt_reg, rs + se_imm16);
|
| }
|
| - SetResult(rt_reg, rs + se_imm16);
|
| break;
|
| + case POP30: // BNVC, BNEZALC, BNEC / DADDI (pre-r6)
|
| + if (IsMipsArchVariant(kMips32r6)) {
|
| + if (rs_reg >= rt_reg) { // BNVC
|
| + if (!HaveSameSign(rs, rt) || rs == 0 || rt == 0) {
|
| + BranchCompactHelper(true, 16);
|
| + } else {
|
| + if (rs > 0) {
|
| + BranchCompactHelper(rs <= Registers::kMaxValue - rt, 16);
|
| + } else if (rs < 0) {
|
| + BranchCompactHelper(rs >= Registers::kMinValue - rt, 16);
|
| + }
|
| + }
|
| + } else {
|
| + if (rs_reg == 0) { // BNEZALC
|
| + BranchAndLinkCompactHelper(rt != 0, 16);
|
| + } else { // BNEC
|
| + BranchCompactHelper(rt != rs, 16);
|
| + }
|
| + }
|
| + }
|
| + break;
|
| + // ------------- Arithmetic instructions.
|
| case ADDIU:
|
| SetResult(rt_reg, rs + se_imm16);
|
| break;
|
| @@ -4014,22 +4124,11 @@ void Simulator::DecodeTypeImmediate(Instruction* instr) {
|
| case SDC1:
|
| WriteD(rs + se_imm16, get_fpu_register_double(ft_reg), instr);
|
| break;
|
| - // ------------- JIALC and BNEZC instructions.
|
| - case POP76: {
|
| - // Next pc.
|
| - next_pc = rt + se_imm16;
|
| - // The instruction after the jump is NOT executed.
|
| - int16_t pc_increment = Instruction::kInstrSize;
|
| - if (instr->IsLinkingInstruction()) {
|
| - set_register(31, current_pc + pc_increment);
|
| - }
|
| - set_pc(next_pc);
|
| - pc_modified_ = true;
|
| - break;
|
| - }
|
| // ------------- PC-Relative instructions.
|
| case PCREL: {
|
| // rt field: checking 5-bits.
|
| + int32_t imm21 = instr->Imm21Value();
|
| + int32_t current_pc = get_pc();
|
| uint8_t rt = (imm21 >> kImm16Bits);
|
| switch (rt) {
|
| case ALUIPC:
|
| @@ -4076,7 +4175,7 @@ void Simulator::DecodeTypeImmediate(Instruction* instr) {
|
| // We don't check for end_sim_pc. First it should not be met as the current
|
| // pc is valid. Secondly a jump should always execute its branch delay slot.
|
| Instruction* branch_delay_instr =
|
| - reinterpret_cast<Instruction*>(current_pc+Instruction::kInstrSize);
|
| + reinterpret_cast<Instruction*>(get_pc() + Instruction::kInstrSize);
|
| BranchDelayInstructionDecode(branch_delay_instr);
|
| }
|
|
|
| @@ -4086,9 +4185,6 @@ void Simulator::DecodeTypeImmediate(Instruction* instr) {
|
| }
|
| }
|
|
|
| -#undef BranchHelper
|
| -#undef BranchAndLinkHelper
|
| -
|
|
|
| // Type 3: instructions using a 26 bytes immediate. (e.g. j, jal).
|
| void Simulator::DecodeTypeJump(Instruction* instr) {
|
| @@ -4174,7 +4270,7 @@ void Simulator::Execute() {
|
| while (program_counter != end_sim_pc) {
|
| Instruction* instr = reinterpret_cast<Instruction*>(program_counter);
|
| icount_++;
|
| - if (icount_ == ::v8::internal::FLAG_stop_sim_at) {
|
| + if (icount_ == static_cast<uint64_t>(::v8::internal::FLAG_stop_sim_at)) {
|
| MipsDebugger dbg(this);
|
| dbg.Debug();
|
| } else {
|
|
|