Index: runtime/vm/simulator_mips.cc |
=================================================================== |
--- runtime/vm/simulator_mips.cc (revision 20399) |
+++ runtime/vm/simulator_mips.cc (working copy) |
@@ -990,6 +990,65 @@ |
} |
+void Simulator::DoBranch(Instr* instr, bool taken, bool likely) { |
+ ASSERT(!delay_slot_); |
+ int32_t imm_val = instr->SImmField() << 2; |
+ |
+ uword next_pc; |
+ if (taken) { |
+ // imm_val is added to the address of the instruction following the branch. |
+ next_pc = pc_ + imm_val + Instr::kInstrSize; |
+ if (likely) { |
+ ExecuteDelaySlot(); |
+ } |
+ } else { |
+ next_pc = pc_ + (2 * Instr::kInstrSize); // Next after delay slot. |
+ } |
+ if (!likely) { |
+ ExecuteDelaySlot(); |
+ } |
+ pc_ = next_pc - Instr::kInstrSize; |
+ |
+ return; |
+} |
+ |
+ |
+void Simulator::DecodeRegImm(Instr* instr) { |
+ ASSERT(instr->OpcodeField() == REGIMM); |
+ switch (instr->RegImmFnField()) { |
+ case BGEZ: { |
+ // Format(instr, "bgez 'rs, 'dest"); |
+ int32_t rs_val = get_register(instr->RsField()); |
+ DoBranch(instr, rs_val >= 0, false); |
+ break; |
+ } |
+ case BGEZL: { |
+ // Format(instr, "bgezl 'rs, 'dest"); |
+ int32_t rs_val = get_register(instr->RsField()); |
+ DoBranch(instr, rs_val >= 0, true); |
+ break; |
+ } |
+ case BLTZ: { |
+ // Format(instr, "bltz 'rs, 'dest"); |
+ int32_t rs_val = get_register(instr->RsField()); |
+ DoBranch(instr, rs_val < 0, false); |
+ break; |
+ } |
+ case BLTZL: { |
+ // Format(instr, "bltzl 'rs, 'dest"); |
+ int32_t rs_val = get_register(instr->RsField()); |
+ DoBranch(instr, rs_val < 0, true); |
+ break; |
+ } |
+ default: { |
+ OS::PrintErr("DecodeRegImm: 0x%x\n", instr->InstructionBits()); |
+ UnimplementedInstruction(instr); |
+ break; |
+ } |
+ } |
+} |
+ |
+ |
void Simulator::InstructionDecode(Instr* instr) { |
switch (instr->OpcodeField()) { |
case SPECIAL: { |
@@ -1000,6 +1059,10 @@ |
DecodeSpecial2(instr); |
break; |
} |
+ case REGIMM: { |
+ DecodeRegImm(instr); |
+ break; |
+ } |
case ADDIU: { |
// Format(instr, "addiu 'rt, 'rs, 'imms"); |
int32_t rs_val = get_register(instr->RsField()); |
@@ -1015,6 +1078,62 @@ |
set_register(instr->RtField(), rs_val & instr->UImmField()); |
break; |
} |
+ case BEQ: { |
+ // Format(instr, "beq 'rs, 'rt, 'dest"); |
+ int32_t rs_val = get_register(instr->RsField()); |
+ int32_t rt_val = get_register(instr->RtField()); |
+ DoBranch(instr, rs_val == rt_val, false); |
+ break; |
+ } |
+ case BEQL: { |
+ // Format(instr, "beql 'rs, 'rt, 'dest"); |
+ int32_t rs_val = get_register(instr->RsField()); |
+ int32_t rt_val = get_register(instr->RtField()); |
+ DoBranch(instr, rs_val == rt_val, true); |
+ break; |
+ } |
+ case BGTZ: { |
+ ASSERT(instr->RtField() == R0); |
+ // Format(instr, "bgtz 'rs, 'dest"); |
+ int32_t rs_val = get_register(instr->RsField()); |
+ DoBranch(instr, rs_val > 0, false); |
+ break; |
+ } |
+ case BGTZL: { |
+ ASSERT(instr->RtField() == R0); |
+ // Format(instr, "bgtzl 'rs, 'dest"); |
+ int32_t rs_val = get_register(instr->RsField()); |
+ DoBranch(instr, rs_val > 0, true); |
+ break; |
+ } |
+ case BLEZ: { |
+ ASSERT(instr->RtField() == R0); |
+ // Format(instr, "blez 'rs, 'dest"); |
+ int32_t rs_val = get_register(instr->RsField()); |
+ DoBranch(instr, rs_val <= 0, false); |
+ break; |
+ } |
+ case BLEZL: { |
+ ASSERT(instr->RtField() == R0); |
+ // Format(instr, "blezl 'rs, 'dest"); |
+ int32_t rs_val = get_register(instr->RsField()); |
+ DoBranch(instr, rs_val <= 0, true); |
+ break; |
+ } |
+ case BNE: { |
+ // Format(instr, "bne 'rs, 'rt, 'dest"); |
+ int32_t rs_val = get_register(instr->RsField()); |
+ int32_t rt_val = get_register(instr->RtField()); |
+ DoBranch(instr, rs_val != rt_val, false); |
+ break; |
+ } |
+ case BNEL: { |
+ // Format(instr, "bnel 'rs, 'rt, 'dest"); |
+ int32_t rs_val = get_register(instr->RsField()); |
+ int32_t rt_val = get_register(instr->RtField()); |
+ DoBranch(instr, rs_val != rt_val, true); |
+ break; |
+ } |
case LB: { |
// Format(instr, "lb 'rt, 'imms('rs)"); |
int32_t base_val = get_register(instr->RsField()); |