Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(574)

Unified Diff: src/mips/simulator-mips.cc

Issue 1310883005: MIPS: Optimize simulator. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Fix nits. Created 5 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « src/mips/simulator-mips.h ('k') | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/mips/simulator-mips.cc
diff --git a/src/mips/simulator-mips.cc b/src/mips/simulator-mips.cc
index 6dea3f09a3969f339af0733c75a5642e5bb4bf3c..4ef61abe3db140721365325748679b91852271fd 100644
--- a/src/mips/simulator-mips.cc
+++ b/src/mips/simulator-mips.cc
@@ -979,10 +979,6 @@ Simulator::Simulator(Isolate* isolate) : isolate_(isolate) {
registers_[pc] = bad_ra;
registers_[ra] = bad_ra;
InitializeCoverage();
- for (int i = 0; i < kNumExceptions; i++) {
- exceptions[i] = 0;
- }
-
last_debugger_input_ = NULL;
}
@@ -1628,7 +1624,8 @@ void Simulator::TraceRegWr(int32_t value) {
// TODO(plind): consider making icount_ printing a flag option.
void Simulator::TraceMemRd(int32_t addr, int32_t value) {
if (::v8::internal::FLAG_trace_sim) {
- SNPrintF(trace_buf_, "%08x <-- [%08x] (%d)", value, addr, icount_);
+ SNPrintF(trace_buf_, "%08x <-- [%08x] (%" PRIu64 ")", value, addr,
+ icount_);
}
}
@@ -2101,7 +2098,8 @@ bool Simulator::IsWatchpoint(uint32_t code) {
void Simulator::PrintWatchpoint(uint32_t code) {
MipsDebugger dbg(this);
++break_count_;
- PrintF("\n---- break %d marker: %3d (instr count: %8d) ----------"
+ PrintF("\n---- break %d marker: %3d (instr count: %" PRIu64
+ ") ----------"
"----------------------------------",
code, break_count_, icount_);
dbg.PrintAllRegs(); // Print registers and continue running.
@@ -2185,362 +2183,26 @@ void Simulator::PrintStopInfo(uint32_t code) {
}
-void Simulator::SignalExceptions() {
- for (int i = 1; i < kNumExceptions; i++) {
- if (exceptions[i] != 0) {
- V8_Fatal(__FILE__, __LINE__, "Error: Exception %i raised.", i);
- }
- }
+void Simulator::SignalException(Exception e) {
+ V8_Fatal(__FILE__, __LINE__, "Error: Exception %i raised.",
+ static_cast<int>(e));
}
-// Handle execution based on instruction types.
-
-void Simulator::ConfigureTypeRegister(Instruction* instr,
- int32_t* alu_out,
- int64_t* i64hilo,
- uint64_t* u64hilo,
- int32_t* next_pc,
- int32_t* return_addr_reg,
- bool* do_interrupt) {
- // Every local variable declared here needs to be const.
- // This is to make sure that changed values are sent back to
- // DecodeTypeRegister correctly.
-
- // Instruction fields.
- const Opcode op = instr->OpcodeFieldRaw();
- const int32_t rs_reg = instr->RsValue();
- const int32_t rs = get_register(rs_reg);
- const uint32_t rs_u = static_cast<uint32_t>(rs);
- const int32_t rt_reg = instr->RtValue();
- const int32_t rt = get_register(rt_reg);
- const uint32_t rt_u = static_cast<uint32_t>(rt);
- const int32_t rd_reg = instr->RdValue();
- const uint32_t sa = instr->SaValue();
- const uint8_t bp = instr->Bp2Value();
-
- const int32_t fs_reg = instr->FsValue();
-
-
- // ---------- Configuration.
- switch (op) {
- case COP1: // Coprocessor instructions.
- switch (instr->RsFieldRaw()) {
- case CFC1:
- // At the moment only FCSR is supported.
- DCHECK(fs_reg == kFCSRRegister);
- *alu_out = FCSR_;
- break;
- case MFC1:
- *alu_out = get_fpu_register_word(fs_reg);
- break;
- case MFHC1:
- *alu_out = get_fpu_register_hi_word(fs_reg);
- break;
- case CTC1:
- case MTC1:
- case MTHC1:
- case S:
- case D:
- case W:
- case L:
- case PS:
- // Do everything in the execution step.
- break;
- default:
- // BC1 BC1EQZ BC1NEZ handled in DecodeTypeImmed, should never come here.
- UNREACHABLE();
- }
- break;
- case COP1X:
- break;
- case SPECIAL:
- switch (instr->FunctionFieldRaw()) {
- case JR:
- case JALR:
- *next_pc = get_register(instr->RsValue());
- *return_addr_reg = instr->RdValue();
- break;
- case SLL:
- *alu_out = rt << sa;
- break;
- case SRL:
- if (rs_reg == 0) {
- // Regular logical right shift of a word by a fixed number of
- // bits instruction. RS field is always equal to 0.
- *alu_out = rt_u >> sa;
- } else {
- // Logical right-rotate of a word by a fixed number of bits. This
- // is special case of SRL instruction, added in MIPS32 Release 2.
- // RS field is equal to 00001.
- *alu_out = base::bits::RotateRight32(rt_u, sa);
- }
- break;
- case SRA:
- *alu_out = rt >> sa;
- break;
- case SLLV:
- *alu_out = rt << rs;
- break;
- case SRLV:
- if (sa == 0) {
- // Regular logical right-shift of a word by a variable number of
- // bits instruction. SA field is always equal to 0.
- *alu_out = rt_u >> rs;
- } else {
- // Logical right-rotate of a word by a variable number of bits.
- // This is special case od SRLV instruction, added in MIPS32
- // Release 2. SA field is equal to 00001.
- *alu_out = base::bits::RotateRight32(rt_u, rs_u);
- }
- break;
- case SRAV:
- *alu_out = rt >> rs;
- break;
- case MFHI: // MFHI == CLZ on R6.
- if (!IsMipsArchVariant(kMips32r6)) {
- DCHECK(instr->SaValue() == 0);
- *alu_out = get_register(HI);
- } else {
- // MIPS spec: If no bits were set in GPR rs, the result written to
- // GPR rd is 32.
- DCHECK(instr->SaValue() == 1);
- *alu_out = base::bits::CountLeadingZeros32(rs_u);
- }
- break;
- case MFLO:
- *alu_out = get_register(LO);
- break;
- case MULT: // MULT == MUL_MUH.
- if (!IsMipsArchVariant(kMips32r6)) {
- *i64hilo = static_cast<int64_t>(rs) * static_cast<int64_t>(rt);
- } else {
- switch (instr->SaValue()) {
- case MUL_OP:
- case MUH_OP:
- *i64hilo = static_cast<int64_t>(rs) * static_cast<int64_t>(rt);
- break;
- default:
- UNIMPLEMENTED_MIPS();
- break;
- }
- }
- break;
- case MULTU: // MULTU == MUL_MUH_U.
- if (!IsMipsArchVariant(kMips32r6)) {
- *u64hilo = static_cast<uint64_t>(rs_u) *
- static_cast<uint64_t>(rt_u);
- } else {
- switch (instr->SaValue()) {
- case MUL_OP:
- case MUH_OP:
- *u64hilo = static_cast<uint64_t>(rs_u) *
- static_cast<uint64_t>(rt_u);
- break;
- default:
- UNIMPLEMENTED_MIPS();
- break;
- }
- }
- break;
- case ADD:
- if (HaveSameSign(rs, rt)) {
- if (rs > 0) {
- exceptions[kIntegerOverflow] = rs > (Registers::kMaxValue - rt);
- } else if (rs < 0) {
- exceptions[kIntegerUnderflow] = rs < (Registers::kMinValue - rt);
- }
- }
- *alu_out = rs + rt;
- break;
- case ADDU:
- *alu_out = rs + rt;
- break;
- case SUB:
- if (!HaveSameSign(rs, rt)) {
- if (rs > 0) {
- exceptions[kIntegerOverflow] = rs > (Registers::kMaxValue + rt);
- } else if (rs < 0) {
- exceptions[kIntegerUnderflow] = rs < (Registers::kMinValue + rt);
- }
- }
- *alu_out = rs - rt;
- break;
- case SUBU:
- *alu_out = rs - rt;
- break;
- case AND:
- *alu_out = rs & rt;
- break;
- case OR:
- *alu_out = rs | rt;
- break;
- case XOR:
- *alu_out = rs ^ rt;
- break;
- case NOR:
- *alu_out = ~(rs | rt);
- break;
- case SLT:
- *alu_out = rs < rt ? 1 : 0;
- break;
- case SLTU:
- *alu_out = rs_u < rt_u ? 1 : 0;
- break;
- // Break and trap instructions.
- case BREAK:
- *do_interrupt = true;
- break;
- case TGE:
- *do_interrupt = rs >= rt;
- break;
- case TGEU:
- *do_interrupt = rs_u >= rt_u;
- break;
- case TLT:
- *do_interrupt = rs < rt;
- break;
- case TLTU:
- *do_interrupt = rs_u < rt_u;
- break;
- case TEQ:
- *do_interrupt = rs == rt;
- break;
- case TNE:
- *do_interrupt = rs != rt;
- break;
- case MOVN:
- case MOVZ:
- case MOVCI:
- // No action taken on decode.
- break;
- case DIV:
- case DIVU:
- // div and divu never raise exceptions.
- case SELEQZ_S:
- case SELNEZ_S:
- break;
- default:
- UNREACHABLE();
- }
- break;
- case SPECIAL2:
- switch (instr->FunctionFieldRaw()) {
- case MUL:
- *alu_out = rs_u * rt_u; // Only the lower 32 bits are kept.
- break;
- case CLZ:
- // MIPS32 spec: If no bits were set in GPR rs, the result written to
- // GPR rd is 32.
- *alu_out = base::bits::CountLeadingZeros32(rs_u);
- break;
- default:
- UNREACHABLE();
- }
- break;
- case SPECIAL3:
- switch (instr->FunctionFieldRaw()) {
- case INS: { // Mips32r2 instruction.
- // Interpret rd field as 5-bit msb of insert.
- uint16_t msb = rd_reg;
- // Interpret sa field as 5-bit lsb of insert.
- uint16_t lsb = sa;
- uint16_t size = msb - lsb + 1;
- uint32_t mask = (1 << size) - 1;
- *alu_out = (rt_u & ~(mask << lsb)) | ((rs_u & mask) << lsb);
- break;
- }
- case EXT: { // Mips32r2 instruction.
- // Interpret rd field as 5-bit msb of extract.
- uint16_t msb = rd_reg;
- // Interpret sa field as 5-bit lsb of extract.
- uint16_t lsb = sa;
- uint16_t size = msb + 1;
- uint32_t mask = (1 << size) - 1;
- *alu_out = (rs_u & (mask << lsb)) >> lsb;
- break;
- }
- case BSHFL: {
- int sa = instr->SaFieldRaw() >> kSaShift;
- switch (sa) {
- case BITSWAP: {
- uint32_t input = static_cast<uint32_t>(rt);
- uint32_t output = 0;
- uint8_t i_byte, o_byte;
-
- // Reverse the bit in byte for each individual byte
- for (int i = 0; i < 4; i++) {
- output = output >> 8;
- i_byte = input & 0xff;
-
- // Fast way to reverse bits in byte
- // Devised by Sean Anderson, July 13, 2001
- o_byte =
- static_cast<uint8_t>(((i_byte * 0x0802LU & 0x22110LU) |
- (i_byte * 0x8020LU & 0x88440LU)) *
- 0x10101LU >>
- 16);
-
- output = output | (static_cast<uint32_t>(o_byte << 24));
- input = input >> 8;
- }
-
- *alu_out = static_cast<int32_t>(output);
- break;
- }
- case SEB:
- case SEH:
- case WSBH:
- UNREACHABLE();
- break;
- default: {
- sa >>= kBp2Bits;
- switch (sa) {
- case ALIGN: {
- if (bp == 0) {
- *alu_out = static_cast<int32_t>(rt);
- } else {
- uint32_t rt_hi = rt << (8 * bp);
- uint32_t rs_lo = rs >> (8 * (4 - bp));
- *alu_out = static_cast<int32_t>(rt_hi | rs_lo);
- }
- break;
- }
- default:
- UNREACHABLE();
- break;
- }
- }
- }
- break;
- }
- default:
- UNREACHABLE();
- }
- break;
- default:
- UNREACHABLE();
- }
-}
-
-
-void Simulator::DecodeTypeRegisterDRsType(Instruction* instr,
- const int32_t& fr_reg,
- const int32_t& fs_reg,
- const int32_t& ft_reg,
- const int32_t& fd_reg) {
+void Simulator::DecodeTypeRegisterDRsType() {
double ft, fs, fd;
uint32_t cc, fcsr_cc;
int64_t i64;
- fs = get_fpu_register_double(fs_reg);
- ft = (instr->FunctionFieldRaw() != MOVF) ? get_fpu_register_double(ft_reg)
- : 0.0;
- fd = get_fpu_register_double(fd_reg);
+ fs = get_fpu_register_double(fs_reg());
+ ft = (get_instr()->FunctionFieldRaw() != MOVF)
+ ? get_fpu_register_double(ft_reg())
+ : 0.0;
+ fd = get_fpu_register_double(fd_reg());
int64_t ft_int = bit_cast<int64_t>(ft);
int64_t fd_int = bit_cast<int64_t>(fd);
- cc = instr->FCccValue();
+ cc = get_instr()->FCccValue();
fcsr_cc = get_fcsr_condition_bit(cc);
- switch (instr->FunctionFieldRaw()) {
+ switch (get_instr()->FunctionFieldRaw()) {
case RINT: {
DCHECK(IsMipsArchVariant(kMips32r6));
double result, temp, temp_result;
@@ -2572,7 +2234,7 @@ void Simulator::DecodeTypeRegisterDRsType(Instruction* instr,
result = lower;
break;
}
- set_fpu_register_double(fd_reg, result);
+ set_fpu_register_double(fd_reg(), result);
if (result != fs) {
set_fcsr_bit(kFCSRInexactFlagBit, true);
}
@@ -2580,69 +2242,67 @@ void Simulator::DecodeTypeRegisterDRsType(Instruction* instr,
}
case SEL:
DCHECK(IsMipsArchVariant(kMips32r6));
- set_fpu_register_double(fd_reg, (fd_int & 0x1) == 0 ? fs : ft);
+ set_fpu_register_double(fd_reg(), (fd_int & 0x1) == 0 ? fs : ft);
break;
case SELEQZ_C:
DCHECK(IsMipsArchVariant(kMips32r6));
- set_fpu_register_double(fd_reg, (ft_int & 0x1) == 0 ? fs : 0.0);
+ set_fpu_register_double(fd_reg(), (ft_int & 0x1) == 0 ? fs : 0.0);
break;
case SELNEZ_C:
DCHECK(IsMipsArchVariant(kMips32r6));
- set_fpu_register_double(fd_reg, (ft_int & 0x1) != 0 ? fs : 0.0);
+ set_fpu_register_double(fd_reg(), (ft_int & 0x1) != 0 ? fs : 0.0);
break;
case MOVZ_C: {
DCHECK(IsMipsArchVariant(kMips32r2));
- int32_t rt_reg = instr->RtValue();
- int32_t rt = get_register(rt_reg);
- if (rt == 0) {
- set_fpu_register_double(fd_reg, fs);
+ if (rt() == 0) {
+ set_fpu_register_double(fd_reg(), fs);
}
break;
}
case MOVN_C: {
DCHECK(IsMipsArchVariant(kMips32r2));
- int32_t rt_reg = instr->RtValue();
+ int32_t rt_reg = get_instr()->RtValue();
int32_t rt = get_register(rt_reg);
if (rt != 0) {
- set_fpu_register_double(fd_reg, fs);
+ set_fpu_register_double(fd_reg(), fs);
}
break;
}
case MOVF: {
// Same function field for MOVT.D and MOVF.D
- uint32_t ft_cc = (ft_reg >> 2) & 0x7;
+ uint32_t ft_cc = (ft_reg() >> 2) & 0x7;
ft_cc = get_fcsr_condition_bit(ft_cc);
- if (instr->Bit(16)) { // Read Tf bit.
+ if (get_instr()->Bit(16)) { // Read Tf bit.
// MOVT.D
- if (test_fcsr_bit(ft_cc)) set_fpu_register_double(fd_reg, fs);
+ if (test_fcsr_bit(ft_cc)) set_fpu_register_double(fd_reg(), fs);
} else {
// MOVF.D
- if (!test_fcsr_bit(ft_cc)) set_fpu_register_double(fd_reg, fs);
+ if (!test_fcsr_bit(ft_cc)) set_fpu_register_double(fd_reg(), fs);
}
break;
}
case MIN:
DCHECK(IsMipsArchVariant(kMips32r6));
- fs = get_fpu_register_double(fs_reg);
+ fs = get_fpu_register_double(fs_reg());
if (std::isnan(fs) && std::isnan(ft)) {
- set_fpu_register_double(fd_reg, fs);
+ set_fpu_register_double(fd_reg(), fs);
} else if (std::isnan(fs) && !std::isnan(ft)) {
- set_fpu_register_double(fd_reg, ft);
+ set_fpu_register_double(fd_reg(), ft);
} else if (!std::isnan(fs) && std::isnan(ft)) {
- set_fpu_register_double(fd_reg, fs);
+ set_fpu_register_double(fd_reg(), fs);
} else {
- set_fpu_register_double(fd_reg, (fs >= ft) ? ft : fs);
+ set_fpu_register_double(fd_reg(), (fs >= ft) ? ft : fs);
}
break;
case MINA:
DCHECK(IsMipsArchVariant(kMips32r6));
- fs = get_fpu_register_double(fs_reg);
+ fs = get_fpu_register_double(fs_reg());
if (std::isnan(fs) && std::isnan(ft)) {
- set_fpu_register_double(fd_reg, fs);
+ set_fpu_register_double(fd_reg(), fs);
} else if (std::isnan(fs) && !std::isnan(ft)) {
- set_fpu_register_double(fd_reg, ft);
+ set_fpu_register_double(fd_reg(), ft);
} else if (!std::isnan(fs) && std::isnan(ft)) {
- set_fpu_register_double(fd_reg, fs);
+ set_fpu_register_double(fd_reg(), fs);
} else {
double result;
if (fabs(fs) > fabs(ft)) {
@@ -2652,18 +2312,18 @@ void Simulator::DecodeTypeRegisterDRsType(Instruction* instr,
} else {
result = (fs > ft ? fs : ft);
}
- set_fpu_register_double(fd_reg, result);
+ set_fpu_register_double(fd_reg(), result);
}
break;
case MAXA:
DCHECK(IsMipsArchVariant(kMips32r6));
- fs = get_fpu_register_double(fs_reg);
+ fs = get_fpu_register_double(fs_reg());
if (std::isnan(fs) && std::isnan(ft)) {
- set_fpu_register_double(fd_reg, fs);
+ set_fpu_register_double(fd_reg(), fs);
} else if (std::isnan(fs) && !std::isnan(ft)) {
- set_fpu_register_double(fd_reg, ft);
+ set_fpu_register_double(fd_reg(), ft);
} else if (!std::isnan(fs) && std::isnan(ft)) {
- set_fpu_register_double(fd_reg, fs);
+ set_fpu_register_double(fd_reg(), fs);
} else {
double result;
if (fabs(fs) < fabs(ft)) {
@@ -2673,57 +2333,57 @@ void Simulator::DecodeTypeRegisterDRsType(Instruction* instr,
} else {
result = (fs > ft ? fs : ft);
}
- set_fpu_register_double(fd_reg, result);
+ set_fpu_register_double(fd_reg(), result);
}
break;
case MAX:
DCHECK(IsMipsArchVariant(kMips32r6));
- fs = get_fpu_register_double(fs_reg);
+ fs = get_fpu_register_double(fs_reg());
if (std::isnan(fs) && std::isnan(ft)) {
- set_fpu_register_double(fd_reg, fs);
+ set_fpu_register_double(fd_reg(), fs);
} else if (std::isnan(fs) && !std::isnan(ft)) {
- set_fpu_register_double(fd_reg, ft);
+ set_fpu_register_double(fd_reg(), ft);
} else if (!std::isnan(fs) && std::isnan(ft)) {
- set_fpu_register_double(fd_reg, fs);
+ set_fpu_register_double(fd_reg(), fs);
} else {
- set_fpu_register_double(fd_reg, (fs <= ft) ? ft : fs);
+ set_fpu_register_double(fd_reg(), (fs <= ft) ? ft : fs);
}
break;
break;
case ADD_D:
- set_fpu_register_double(fd_reg, fs + ft);
+ set_fpu_register_double(fd_reg(), fs + ft);
break;
case SUB_D:
- set_fpu_register_double(fd_reg, fs - ft);
+ set_fpu_register_double(fd_reg(), fs - ft);
break;
case MUL_D:
- set_fpu_register_double(fd_reg, fs * ft);
+ set_fpu_register_double(fd_reg(), fs * ft);
break;
case DIV_D:
- set_fpu_register_double(fd_reg, fs / ft);
+ set_fpu_register_double(fd_reg(), fs / ft);
break;
case ABS_D:
- set_fpu_register_double(fd_reg, fabs(fs));
+ set_fpu_register_double(fd_reg(), fabs(fs));
break;
case MOV_D:
- set_fpu_register_double(fd_reg, fs);
+ set_fpu_register_double(fd_reg(), fs);
break;
case NEG_D:
- set_fpu_register_double(fd_reg, -fs);
+ set_fpu_register_double(fd_reg(), -fs);
break;
case SQRT_D:
- set_fpu_register_double(fd_reg, fast_sqrt(fs));
+ set_fpu_register_double(fd_reg(), fast_sqrt(fs));
break;
case RSQRT_D: {
DCHECK(IsMipsArchVariant(kMips32r2) || IsMipsArchVariant(kMips32r6));
double result = 1.0 / fast_sqrt(fs);
- set_fpu_register_double(fd_reg, result);
+ set_fpu_register_double(fd_reg(), result);
break;
}
case RECIP_D: {
DCHECK(IsMipsArchVariant(kMips32r2) || IsMipsArchVariant(kMips32r6));
double result = 1.0 / fs;
- set_fpu_register_double(fd_reg, result);
+ set_fpu_register_double(fd_reg(), result);
break;
}
case C_UN_D:
@@ -2751,9 +2411,9 @@ void Simulator::DecodeTypeRegisterDRsType(Instruction* instr,
double rounded;
int32_t result;
round_according_to_fcsr(fs, rounded, result, fs);
- set_fpu_register_word(fd_reg, result);
+ set_fpu_register_word(fd_reg(), result);
if (set_fcsr_round_error(fs, rounded)) {
- set_fpu_register_word(fd_reg, kFPUInvalidResult);
+ set_fpu_register_word(fd_reg(), kFPUInvalidResult);
}
} break;
case ROUND_W_D: // Round double to word (round half to even).
@@ -2765,49 +2425,49 @@ void Simulator::DecodeTypeRegisterDRsType(Instruction* instr,
// round to the even one.
result--;
}
- set_fpu_register_word(fd_reg, result);
+ set_fpu_register_word(fd_reg(), result);
if (set_fcsr_round_error(fs, rounded)) {
- set_fpu_register_word(fd_reg, kFPUInvalidResult);
+ set_fpu_register_word(fd_reg(), kFPUInvalidResult);
}
} break;
case TRUNC_W_D: // Truncate double to word (round towards 0).
{
double rounded = trunc(fs);
int32_t result = static_cast<int32_t>(rounded);
- set_fpu_register_word(fd_reg, result);
+ set_fpu_register_word(fd_reg(), result);
if (set_fcsr_round_error(fs, rounded)) {
- set_fpu_register_word(fd_reg, kFPUInvalidResult);
+ set_fpu_register_word(fd_reg(), kFPUInvalidResult);
}
} break;
case FLOOR_W_D: // Round double to word towards negative infinity.
{
double rounded = std::floor(fs);
int32_t result = static_cast<int32_t>(rounded);
- set_fpu_register_word(fd_reg, result);
+ set_fpu_register_word(fd_reg(), result);
if (set_fcsr_round_error(fs, rounded)) {
- set_fpu_register_word(fd_reg, kFPUInvalidResult);
+ set_fpu_register_word(fd_reg(), kFPUInvalidResult);
}
} break;
case CEIL_W_D: // Round double to word towards positive infinity.
{
double rounded = std::ceil(fs);
int32_t result = static_cast<int32_t>(rounded);
- set_fpu_register_word(fd_reg, result);
+ set_fpu_register_word(fd_reg(), result);
if (set_fcsr_round_error(fs, rounded)) {
- set_fpu_register_word(fd_reg, kFPUInvalidResult);
+ set_fpu_register_word(fd_reg(), kFPUInvalidResult);
}
} break;
case CVT_S_D: // Convert double to float (single).
- set_fpu_register_float(fd_reg, static_cast<float>(fs));
+ set_fpu_register_float(fd_reg(), static_cast<float>(fs));
break;
case CVT_L_D: { // Mips32r2: Truncate double to 64-bit long-word.
if (IsFp64Mode()) {
int64_t result;
double rounded;
round64_according_to_fcsr(fs, rounded, result, fs);
- set_fpu_register(fd_reg, result);
+ set_fpu_register(fd_reg(), result);
if (set_fcsr_round64_error(fs, rounded)) {
- set_fpu_register(fd_reg, kFPU64InvalidResult);
+ set_fpu_register(fd_reg(), kFPU64InvalidResult);
}
} else {
UNSUPPORTED();
@@ -2820,9 +2480,9 @@ void Simulator::DecodeTypeRegisterDRsType(Instruction* instr,
double rounded = trunc(fs);
i64 = static_cast<int64_t>(rounded);
if (IsFp64Mode()) {
- set_fpu_register(fd_reg, i64);
+ set_fpu_register(fd_reg(), i64);
if (set_fcsr_round64_error(fs, rounded)) {
- set_fpu_register(fd_reg, kFPU64InvalidResult);
+ set_fpu_register(fd_reg(), kFPU64InvalidResult);
}
} else {
UNSUPPORTED();
@@ -2840,9 +2500,9 @@ void Simulator::DecodeTypeRegisterDRsType(Instruction* instr,
}
int64_t i64 = static_cast<int64_t>(result);
if (IsFp64Mode()) {
- set_fpu_register(fd_reg, i64);
+ set_fpu_register(fd_reg(), i64);
if (set_fcsr_round64_error(fs, rounded)) {
- set_fpu_register(fd_reg, kFPU64InvalidResult);
+ set_fpu_register(fd_reg(), kFPU64InvalidResult);
}
} else {
UNSUPPORTED();
@@ -2854,9 +2514,9 @@ void Simulator::DecodeTypeRegisterDRsType(Instruction* instr,
double rounded = std::floor(fs);
int64_t i64 = static_cast<int64_t>(rounded);
if (IsFp64Mode()) {
- set_fpu_register(fd_reg, i64);
+ set_fpu_register(fd_reg(), i64);
if (set_fcsr_round64_error(fs, rounded)) {
- set_fpu_register(fd_reg, kFPU64InvalidResult);
+ set_fpu_register(fd_reg(), kFPU64InvalidResult);
}
} else {
UNSUPPORTED();
@@ -2868,9 +2528,9 @@ void Simulator::DecodeTypeRegisterDRsType(Instruction* instr,
double rounded = std::ceil(fs);
int64_t i64 = static_cast<int64_t>(rounded);
if (IsFp64Mode()) {
- set_fpu_register(fd_reg, i64);
+ set_fpu_register(fd_reg(), i64);
if (set_fcsr_round64_error(fs, rounded)) {
- set_fpu_register(fd_reg, kFPU64InvalidResult);
+ set_fpu_register(fd_reg(), kFPU64InvalidResult);
}
} else {
UNSUPPORTED();
@@ -2938,7 +2598,7 @@ void Simulator::DecodeTypeRegisterDRsType(Instruction* instr,
DCHECK(result != 0);
dResult = bit_cast<double>(result);
- set_fpu_register_double(fd_reg, dResult);
+ set_fpu_register_double(fd_reg(), dResult);
break;
}
@@ -2952,92 +2612,90 @@ void Simulator::DecodeTypeRegisterDRsType(Instruction* instr,
}
-void Simulator::DecodeTypeRegisterWRsType(Instruction* instr, int32_t& alu_out,
- const int32_t& fd_reg,
- const int32_t& fs_reg,
- const int32_t& ft_reg) {
- float fs = get_fpu_register_float(fs_reg);
- float ft = get_fpu_register_float(ft_reg);
- switch (instr->FunctionFieldRaw()) {
+void Simulator::DecodeTypeRegisterWRsType() {
+ float fs = get_fpu_register_float(fs_reg());
+ float ft = get_fpu_register_float(ft_reg());
+ int32_t alu_out = 0x12345678;
+ switch (get_instr()->FunctionFieldRaw()) {
case CVT_S_W: // Convert word to float (single).
- alu_out = get_fpu_register_signed_word(fs_reg);
- set_fpu_register_float(fd_reg, static_cast<float>(alu_out));
+ alu_out = get_fpu_register_signed_word(fs_reg());
+ set_fpu_register_float(fd_reg(), static_cast<float>(alu_out));
break;
case CVT_D_W: // Convert word to double.
- alu_out = get_fpu_register_signed_word(fs_reg);
- set_fpu_register_double(fd_reg, static_cast<double>(alu_out));
+ alu_out = get_fpu_register_signed_word(fs_reg());
+ set_fpu_register_double(fd_reg(), static_cast<double>(alu_out));
break;
case CMP_AF:
- set_fpu_register_word(fd_reg, 0);
+ set_fpu_register_word(fd_reg(), 0);
break;
case CMP_UN:
if (std::isnan(fs) || std::isnan(ft)) {
- set_fpu_register_word(fd_reg, -1);
+ set_fpu_register_word(fd_reg(), -1);
} else {
- set_fpu_register_word(fd_reg, 0);
+ set_fpu_register_word(fd_reg(), 0);
}
break;
case CMP_EQ:
if (fs == ft) {
- set_fpu_register_word(fd_reg, -1);
+ set_fpu_register_word(fd_reg(), -1);
} else {
- set_fpu_register_word(fd_reg, 0);
+ set_fpu_register_word(fd_reg(), 0);
}
break;
case CMP_UEQ:
if ((fs == ft) || (std::isnan(fs) || std::isnan(ft))) {
- set_fpu_register_word(fd_reg, -1);
+ set_fpu_register_word(fd_reg(), -1);
} else {
- set_fpu_register_word(fd_reg, 0);
+ set_fpu_register_word(fd_reg(), 0);
}
break;
case CMP_LT:
if (fs < ft) {
- set_fpu_register_word(fd_reg, -1);
+ set_fpu_register_word(fd_reg(), -1);
} else {
- set_fpu_register_word(fd_reg, 0);
+ set_fpu_register_word(fd_reg(), 0);
}
break;
case CMP_ULT:
if ((fs < ft) || (std::isnan(fs) || std::isnan(ft))) {
- set_fpu_register_word(fd_reg, -1);
+ set_fpu_register_word(fd_reg(), -1);
} else {
- set_fpu_register_word(fd_reg, 0);
+ set_fpu_register_word(fd_reg(), 0);
}
break;
case CMP_LE:
if (fs <= ft) {
- set_fpu_register_word(fd_reg, -1);
+ set_fpu_register_word(fd_reg(), -1);
} else {
- set_fpu_register_word(fd_reg, 0);
+ set_fpu_register_word(fd_reg(), 0);
}
break;
case CMP_ULE:
if ((fs <= ft) || (std::isnan(fs) || std::isnan(ft))) {
- set_fpu_register_word(fd_reg, -1);
+ set_fpu_register_word(fd_reg(), -1);
} else {
- set_fpu_register_word(fd_reg, 0);
+ set_fpu_register_word(fd_reg(), 0);
}
break;
case CMP_OR:
if (!std::isnan(fs) && !std::isnan(ft)) {
- set_fpu_register_word(fd_reg, -1);
+ set_fpu_register_word(fd_reg(), -1);
} else {
- set_fpu_register_word(fd_reg, 0);
+ set_fpu_register_word(fd_reg(), 0);
}
break;
case CMP_UNE:
if ((fs != ft) || (std::isnan(fs) || std::isnan(ft))) {
- set_fpu_register_word(fd_reg, -1);
+ set_fpu_register_word(fd_reg(), -1);
} else {
- set_fpu_register_word(fd_reg, 0);
+ set_fpu_register_word(fd_reg(), 0);
}
break;
case CMP_NE:
if (fs != ft) {
- set_fpu_register_word(fd_reg, -1);
+ set_fpu_register_word(fd_reg(), -1);
} else {
- set_fpu_register_word(fd_reg, 0);
+ set_fpu_register_word(fd_reg(), 0);
}
break;
default:
@@ -3046,20 +2704,17 @@ void Simulator::DecodeTypeRegisterWRsType(Instruction* instr, int32_t& alu_out,
}
-void Simulator::DecodeTypeRegisterSRsType(Instruction* instr,
- const int32_t& ft_reg,
- const int32_t& fs_reg,
- const int32_t& fd_reg) {
+void Simulator::DecodeTypeRegisterSRsType() {
float fs, ft, fd;
- fs = get_fpu_register_float(fs_reg);
- ft = get_fpu_register_float(ft_reg);
- fd = get_fpu_register_float(fd_reg);
+ fs = get_fpu_register_float(fs_reg());
+ ft = get_fpu_register_float(ft_reg());
+ fd = get_fpu_register_float(fd_reg());
int32_t ft_int = bit_cast<int32_t>(ft);
int32_t fd_int = bit_cast<int32_t>(fd);
uint32_t cc, fcsr_cc;
- cc = instr->FCccValue();
+ cc = get_instr()->FCccValue();
fcsr_cc = get_fcsr_condition_bit(cc);
- switch (instr->FunctionFieldRaw()) {
+ switch (get_instr()->FunctionFieldRaw()) {
case RINT: {
DCHECK(IsMipsArchVariant(kMips32r6));
float result, temp_result;
@@ -3092,46 +2747,46 @@ void Simulator::DecodeTypeRegisterSRsType(Instruction* instr,
result = lower;
break;
}
- set_fpu_register_float(fd_reg, result);
+ set_fpu_register_float(fd_reg(), result);
if (result != fs) {
set_fcsr_bit(kFCSRInexactFlagBit, true);
}
break;
}
case ADD_S:
- set_fpu_register_float(fd_reg, fs + ft);
+ set_fpu_register_float(fd_reg(), fs + ft);
break;
case SUB_S:
- set_fpu_register_float(fd_reg, fs - ft);
+ set_fpu_register_float(fd_reg(), fs - ft);
break;
case MUL_S:
- set_fpu_register_float(fd_reg, fs * ft);
+ set_fpu_register_float(fd_reg(), fs * ft);
break;
case DIV_S:
- set_fpu_register_float(fd_reg, fs / ft);
+ set_fpu_register_float(fd_reg(), fs / ft);
break;
case ABS_S:
- set_fpu_register_float(fd_reg, fabs(fs));
+ set_fpu_register_float(fd_reg(), fabs(fs));
break;
case MOV_S:
- set_fpu_register_float(fd_reg, fs);
+ set_fpu_register_float(fd_reg(), fs);
break;
case NEG_S:
- set_fpu_register_float(fd_reg, -fs);
+ set_fpu_register_float(fd_reg(), -fs);
break;
case SQRT_S:
- set_fpu_register_float(fd_reg, fast_sqrt(fs));
+ set_fpu_register_float(fd_reg(), fast_sqrt(fs));
break;
case RSQRT_S: {
DCHECK(IsMipsArchVariant(kMips32r2) || IsMipsArchVariant(kMips32r6));
float result = 1.0 / fast_sqrt(fs);
- set_fpu_register_float(fd_reg, result);
+ set_fpu_register_float(fd_reg(), result);
break;
}
case RECIP_S: {
DCHECK(IsMipsArchVariant(kMips32r2) || IsMipsArchVariant(kMips32r6));
float result = 1.0 / fs;
- set_fpu_register_float(fd_reg, result);
+ set_fpu_register_float(fd_reg(), result);
break;
}
case C_F_D:
@@ -3159,15 +2814,15 @@ void Simulator::DecodeTypeRegisterSRsType(Instruction* instr,
set_fcsr_bit(fcsr_cc, (fs <= ft) || (std::isnan(fs) || std::isnan(ft)));
break;
case CVT_D_S:
- set_fpu_register_double(fd_reg, static_cast<double>(fs));
+ set_fpu_register_double(fd_reg(), static_cast<double>(fs));
break;
case SEL:
DCHECK(IsMipsArchVariant(kMips32r6));
- set_fpu_register_float(fd_reg, (fd_int & 0x1) == 0 ? fs : ft);
+ set_fpu_register_float(fd_reg(), (fd_int & 0x1) == 0 ? fs : ft);
break;
case CLASS_S: { // Mips32r6 instruction
// Convert float input to uint32_t for easier bit manipulation
- float fs = get_fpu_register_float(fs_reg);
+ float fs = get_fpu_register_float(fs_reg());
uint32_t classed = bit_cast<uint32_t>(fs);
// Extracting sign, exponent and mantissa from the input float
@@ -3227,58 +2882,56 @@ void Simulator::DecodeTypeRegisterSRsType(Instruction* instr,
DCHECK(result != 0);
fResult = bit_cast<float>(result);
- set_fpu_register_float(fd_reg, fResult);
+ set_fpu_register_float(fd_reg(), fResult);
break;
}
case SELEQZ_C:
DCHECK(IsMipsArchVariant(kMips32r6));
- set_fpu_register_float(
- fd_reg, (ft_int & 0x1) == 0 ? get_fpu_register_float(fs_reg) : 0.0);
+ set_fpu_register_float(fd_reg(), (ft_int & 0x1) == 0
+ ? get_fpu_register_float(fs_reg())
+ : 0.0);
break;
case SELNEZ_C:
DCHECK(IsMipsArchVariant(kMips32r6));
- set_fpu_register_float(
- fd_reg, (ft_int & 0x1) != 0 ? get_fpu_register_float(fs_reg) : 0.0);
+ set_fpu_register_float(fd_reg(), (ft_int & 0x1) != 0
+ ? get_fpu_register_float(fs_reg())
+ : 0.0);
break;
case MOVZ_C: {
DCHECK(IsMipsArchVariant(kMips32r2));
- int32_t rt_reg = instr->RtValue();
- int32_t rt = get_register(rt_reg);
- if (rt == 0) {
- set_fpu_register_float(fd_reg, fs);
+ if (rt() == 0) {
+ set_fpu_register_float(fd_reg(), fs);
}
break;
}
case MOVN_C: {
DCHECK(IsMipsArchVariant(kMips32r2));
- int32_t rt_reg = instr->RtValue();
- int32_t rt = get_register(rt_reg);
- if (rt != 0) {
- set_fpu_register_float(fd_reg, fs);
+ if (rt() != 0) {
+ set_fpu_register_float(fd_reg(), fs);
}
break;
}
case MOVF: {
// Same function field for MOVT.D and MOVF.D
- uint32_t ft_cc = (ft_reg >> 2) & 0x7;
+ uint32_t ft_cc = (ft_reg() >> 2) & 0x7;
ft_cc = get_fcsr_condition_bit(ft_cc);
- if (instr->Bit(16)) { // Read Tf bit.
+ if (get_instr()->Bit(16)) { // Read Tf bit.
// MOVT.D
- if (test_fcsr_bit(ft_cc)) set_fpu_register_float(fd_reg, fs);
+ if (test_fcsr_bit(ft_cc)) set_fpu_register_float(fd_reg(), fs);
} else {
// MOVF.D
- if (!test_fcsr_bit(ft_cc)) set_fpu_register_float(fd_reg, fs);
+ if (!test_fcsr_bit(ft_cc)) set_fpu_register_float(fd_reg(), fs);
}
break;
}
case TRUNC_W_S: { // Truncate single to word (round towards 0).
float rounded = trunc(fs);
int32_t result = static_cast<int32_t>(rounded);
- set_fpu_register_word(fd_reg, result);
+ set_fpu_register_word(fd_reg(), result);
if (set_fcsr_round_error(fs, rounded)) {
- set_fpu_register_word(fd_reg, kFPUInvalidResult);
+ set_fpu_register_word(fd_reg(), kFPUInvalidResult);
}
} break;
case TRUNC_L_S: { // Mips32r2 instruction.
@@ -3286,9 +2939,9 @@ void Simulator::DecodeTypeRegisterSRsType(Instruction* instr,
float rounded = trunc(fs);
int64_t i64 = static_cast<int64_t>(rounded);
if (IsFp64Mode()) {
- set_fpu_register(fd_reg, i64);
+ set_fpu_register(fd_reg(), i64);
if (set_fcsr_round64_error(fs, rounded)) {
- set_fpu_register(fd_reg, kFPU64InvalidResult);
+ set_fpu_register(fd_reg(), kFPU64InvalidResult);
}
} else {
UNSUPPORTED();
@@ -3299,9 +2952,9 @@ void Simulator::DecodeTypeRegisterSRsType(Instruction* instr,
{
float rounded = std::floor(fs);
int32_t result = static_cast<int32_t>(rounded);
- set_fpu_register_word(fd_reg, result);
+ set_fpu_register_word(fd_reg(), result);
if (set_fcsr_round_error(fs, rounded)) {
- set_fpu_register_word(fd_reg, kFPUInvalidResult);
+ set_fpu_register_word(fd_reg(), kFPUInvalidResult);
}
} break;
case FLOOR_L_S: { // Mips32r2 instruction.
@@ -3309,9 +2962,9 @@ void Simulator::DecodeTypeRegisterSRsType(Instruction* instr,
float rounded = std::floor(fs);
int64_t i64 = static_cast<int64_t>(rounded);
if (IsFp64Mode()) {
- set_fpu_register(fd_reg, i64);
+ set_fpu_register(fd_reg(), i64);
if (set_fcsr_round64_error(fs, rounded)) {
- set_fpu_register(fd_reg, kFPU64InvalidResult);
+ set_fpu_register(fd_reg(), kFPU64InvalidResult);
}
} else {
UNSUPPORTED();
@@ -3326,9 +2979,9 @@ void Simulator::DecodeTypeRegisterSRsType(Instruction* instr,
// round to the even one.
result--;
}
- set_fpu_register_word(fd_reg, result);
+ set_fpu_register_word(fd_reg(), result);
if (set_fcsr_round_error(fs, rounded)) {
- set_fpu_register_word(fd_reg, kFPUInvalidResult);
+ set_fpu_register_word(fd_reg(), kFPUInvalidResult);
}
break;
}
@@ -3343,9 +2996,9 @@ void Simulator::DecodeTypeRegisterSRsType(Instruction* instr,
}
int64_t i64 = static_cast<int64_t>(result);
if (IsFp64Mode()) {
- set_fpu_register(fd_reg, i64);
+ set_fpu_register(fd_reg(), i64);
if (set_fcsr_round64_error(fs, rounded)) {
- set_fpu_register(fd_reg, kFPU64InvalidResult);
+ set_fpu_register(fd_reg(), kFPU64InvalidResult);
}
} else {
UNSUPPORTED();
@@ -3356,9 +3009,9 @@ void Simulator::DecodeTypeRegisterSRsType(Instruction* instr,
{
float rounded = std::ceil(fs);
int32_t result = static_cast<int32_t>(rounded);
- set_fpu_register_word(fd_reg, result);
+ set_fpu_register_word(fd_reg(), result);
if (set_fcsr_round_error(fs, rounded)) {
- set_fpu_register_word(fd_reg, kFPUInvalidResult);
+ set_fpu_register_word(fd_reg(), kFPUInvalidResult);
}
} break;
case CEIL_L_S: { // Mips32r2 instruction.
@@ -3366,9 +3019,9 @@ void Simulator::DecodeTypeRegisterSRsType(Instruction* instr,
float rounded = std::ceil(fs);
int64_t i64 = static_cast<int64_t>(rounded);
if (IsFp64Mode()) {
- set_fpu_register(fd_reg, i64);
+ set_fpu_register(fd_reg(), i64);
if (set_fcsr_round64_error(fs, rounded)) {
- set_fpu_register(fd_reg, kFPU64InvalidResult);
+ set_fpu_register(fd_reg(), kFPU64InvalidResult);
}
} else {
UNSUPPORTED();
@@ -3377,39 +3030,39 @@ void Simulator::DecodeTypeRegisterSRsType(Instruction* instr,
}
case MIN:
DCHECK(IsMipsArchVariant(kMips32r6));
- fs = get_fpu_register_float(fs_reg);
+ fs = get_fpu_register_float(fs_reg());
if (std::isnan(fs) && std::isnan(ft)) {
- set_fpu_register_float(fd_reg, fs);
+ set_fpu_register_float(fd_reg(), fs);
} else if (std::isnan(fs) && !std::isnan(ft)) {
- set_fpu_register_float(fd_reg, ft);
+ set_fpu_register_float(fd_reg(), ft);
} else if (!std::isnan(fs) && std::isnan(ft)) {
- set_fpu_register_float(fd_reg, fs);
+ set_fpu_register_float(fd_reg(), fs);
} else {
- set_fpu_register_float(fd_reg, (fs >= ft) ? ft : fs);
+ set_fpu_register_float(fd_reg(), (fs >= ft) ? ft : fs);
}
break;
case MAX:
DCHECK(IsMipsArchVariant(kMips32r6));
- fs = get_fpu_register_float(fs_reg);
+ fs = get_fpu_register_float(fs_reg());
if (std::isnan(fs) && std::isnan(ft)) {
- set_fpu_register_float(fd_reg, fs);
+ set_fpu_register_float(fd_reg(), fs);
} else if (std::isnan(fs) && !std::isnan(ft)) {
- set_fpu_register_float(fd_reg, ft);
+ set_fpu_register_float(fd_reg(), ft);
} else if (!std::isnan(fs) && std::isnan(ft)) {
- set_fpu_register_float(fd_reg, fs);
+ set_fpu_register_float(fd_reg(), fs);
} else {
- set_fpu_register_float(fd_reg, (fs <= ft) ? ft : fs);
+ set_fpu_register_float(fd_reg(), (fs <= ft) ? ft : fs);
}
break;
case MINA:
DCHECK(IsMipsArchVariant(kMips32r6));
- fs = get_fpu_register_float(fs_reg);
+ fs = get_fpu_register_float(fs_reg());
if (std::isnan(fs) && std::isnan(ft)) {
- set_fpu_register_float(fd_reg, fs);
+ set_fpu_register_float(fd_reg(), fs);
} else if (std::isnan(fs) && !std::isnan(ft)) {
- set_fpu_register_float(fd_reg, ft);
+ set_fpu_register_float(fd_reg(), ft);
} else if (!std::isnan(fs) && std::isnan(ft)) {
- set_fpu_register_float(fd_reg, fs);
+ set_fpu_register_float(fd_reg(), fs);
} else {
float result;
if (fabs(fs) > fabs(ft)) {
@@ -3419,18 +3072,18 @@ void Simulator::DecodeTypeRegisterSRsType(Instruction* instr,
} else {
result = (fs > ft ? fs : ft);
}
- set_fpu_register_float(fd_reg, result);
+ set_fpu_register_float(fd_reg(), result);
}
break;
case MAXA:
DCHECK(IsMipsArchVariant(kMips32r6));
- fs = get_fpu_register_float(fs_reg);
+ fs = get_fpu_register_float(fs_reg());
if (std::isnan(fs) && std::isnan(ft)) {
- set_fpu_register_float(fd_reg, fs);
+ set_fpu_register_float(fd_reg(), fs);
} else if (std::isnan(fs) && !std::isnan(ft)) {
- set_fpu_register_float(fd_reg, ft);
+ set_fpu_register_float(fd_reg(), ft);
} else if (!std::isnan(fs) && std::isnan(ft)) {
- set_fpu_register_float(fd_reg, fs);
+ set_fpu_register_float(fd_reg(), fs);
} else {
float result;
if (fabs(fs) < fabs(ft)) {
@@ -3440,7 +3093,7 @@ void Simulator::DecodeTypeRegisterSRsType(Instruction* instr,
} else {
result = (fs > ft ? fs : ft);
}
- set_fpu_register_float(fd_reg, result);
+ set_fpu_register_float(fd_reg(), result);
}
break;
case CVT_L_S: {
@@ -3448,9 +3101,9 @@ void Simulator::DecodeTypeRegisterSRsType(Instruction* instr,
int64_t result;
float rounded;
round64_according_to_fcsr(fs, rounded, result, fs);
- set_fpu_register(fd_reg, result);
+ set_fpu_register(fd_reg(), result);
if (set_fcsr_round64_error(fs, rounded)) {
- set_fpu_register(fd_reg, kFPU64InvalidResult);
+ set_fpu_register(fd_reg(), kFPU64InvalidResult);
}
} else {
UNSUPPORTED();
@@ -3461,9 +3114,9 @@ void Simulator::DecodeTypeRegisterSRsType(Instruction* instr,
float rounded;
int32_t result;
round_according_to_fcsr(fs, rounded, result, fs);
- set_fpu_register_word(fd_reg, result);
+ set_fpu_register_word(fd_reg(), result);
if (set_fcsr_round_error(fs, rounded)) {
- set_fpu_register_word(fd_reg, kFPUInvalidResult);
+ set_fpu_register_word(fd_reg(), kFPUInvalidResult);
}
break;
}
@@ -3475,105 +3128,102 @@ void Simulator::DecodeTypeRegisterSRsType(Instruction* instr,
}
-void Simulator::DecodeTypeRegisterLRsType(Instruction* instr,
- const int32_t& ft_reg,
- const int32_t& fs_reg,
- const int32_t& fd_reg) {
- double fs = get_fpu_register_double(fs_reg);
- double ft = get_fpu_register_double(ft_reg);
- switch (instr->FunctionFieldRaw()) {
+void Simulator::DecodeTypeRegisterLRsType() {
+ double fs = get_fpu_register_double(fs_reg());
+ double ft = get_fpu_register_double(ft_reg());
+ switch (get_instr()->FunctionFieldRaw()) {
case CVT_D_L: // Mips32r2 instruction.
// Watch the signs here, we want 2 32-bit vals
// to make a sign-64.
int64_t i64;
if (IsFp64Mode()) {
- i64 = get_fpu_register(fs_reg);
+ i64 = get_fpu_register(fs_reg());
} else {
- i64 = static_cast<uint32_t>(get_fpu_register_word(fs_reg));
- i64 |= static_cast<int64_t>(get_fpu_register_word(fs_reg + 1)) << 32;
+ i64 = static_cast<uint32_t>(get_fpu_register_word(fs_reg()));
+ i64 |= static_cast<int64_t>(get_fpu_register_word(fs_reg() + 1)) << 32;
}
- set_fpu_register_double(fd_reg, static_cast<double>(i64));
+ set_fpu_register_double(fd_reg(), static_cast<double>(i64));
break;
case CVT_S_L:
if (IsFp64Mode()) {
- i64 = get_fpu_register(fs_reg);
+ i64 = get_fpu_register(fs_reg());
} else {
- i64 = static_cast<uint32_t>(get_fpu_register_word(fs_reg));
- i64 |= static_cast<int64_t>(get_fpu_register_word(fs_reg + 1)) << 32;
+ i64 = static_cast<uint32_t>(get_fpu_register_word(fs_reg()));
+ i64 |= static_cast<int64_t>(get_fpu_register_word(fs_reg() + 1)) << 32;
}
- set_fpu_register_float(fd_reg, static_cast<float>(i64));
+ set_fpu_register_float(fd_reg(), static_cast<float>(i64));
break;
case CMP_AF: // Mips64r6 CMP.D instructions.
- set_fpu_register(fd_reg, 0);
+ set_fpu_register(fd_reg(), 0);
break;
case CMP_UN:
if (std::isnan(fs) || std::isnan(ft)) {
- set_fpu_register(fd_reg, -1);
+ set_fpu_register(fd_reg(), -1);
} else {
- set_fpu_register(fd_reg, 0);
+ set_fpu_register(fd_reg(), 0);
}
break;
case CMP_EQ:
if (fs == ft) {
- set_fpu_register(fd_reg, -1);
+ set_fpu_register(fd_reg(), -1);
} else {
- set_fpu_register(fd_reg, 0);
+ set_fpu_register(fd_reg(), 0);
}
break;
case CMP_UEQ:
if ((fs == ft) || (std::isnan(fs) || std::isnan(ft))) {
- set_fpu_register(fd_reg, -1);
+ set_fpu_register(fd_reg(), -1);
} else {
- set_fpu_register(fd_reg, 0);
+ set_fpu_register(fd_reg(), 0);
}
break;
case CMP_LT:
if (fs < ft) {
- set_fpu_register(fd_reg, -1);
+ set_fpu_register(fd_reg(), -1);
} else {
- set_fpu_register(fd_reg, 0);
+ set_fpu_register(fd_reg(), 0);
}
break;
case CMP_ULT:
if ((fs < ft) || (std::isnan(fs) || std::isnan(ft))) {
- set_fpu_register(fd_reg, -1);
+ set_fpu_register(fd_reg(), -1);
} else {
- set_fpu_register(fd_reg, 0);
+ set_fpu_register(fd_reg(), 0);
}
break;
case CMP_LE:
if (fs <= ft) {
- set_fpu_register(fd_reg, -1);
+ set_fpu_register(fd_reg(), -1);
} else {
- set_fpu_register(fd_reg, 0);
+ set_fpu_register(fd_reg(), 0);
}
break;
case CMP_ULE:
if ((fs <= ft) || (std::isnan(fs) || std::isnan(ft))) {
- set_fpu_register(fd_reg, -1);
+ set_fpu_register(fd_reg(), -1);
} else {
- set_fpu_register(fd_reg, 0);
+ set_fpu_register(fd_reg(), 0);
}
break;
case CMP_OR:
if (!std::isnan(fs) && !std::isnan(ft)) {
- set_fpu_register(fd_reg, -1);
+ set_fpu_register(fd_reg(), -1);
} else {
- set_fpu_register(fd_reg, 0);
+ set_fpu_register(fd_reg(), 0);
}
break;
case CMP_UNE:
if ((fs != ft) || (std::isnan(fs) || std::isnan(ft))) {
- set_fpu_register(fd_reg, -1);
+ set_fpu_register(fd_reg(), -1);
} else {
- set_fpu_register(fd_reg, 0);
+ set_fpu_register(fd_reg(), 0);
}
break;
case CMP_NE:
if (fs != ft && (!std::isnan(fs) && !std::isnan(ft))) {
- set_fpu_register(fd_reg, -1);
+ set_fpu_register(fd_reg(), -1);
} else {
- set_fpu_register(fd_reg, 0);
+ set_fpu_register(fd_reg(), 0);
}
break;
default:
@@ -3582,67 +3232,62 @@ void Simulator::DecodeTypeRegisterLRsType(Instruction* instr,
}
-void Simulator::DecodeTypeRegisterCOP1(
- Instruction* instr, const int32_t& rs_reg, const int32_t& rs,
- const uint32_t& rs_u, const int32_t& rt_reg, const int32_t& rt,
- const uint32_t& rt_u, const int32_t& rd_reg, const int32_t& fr_reg,
- const int32_t& fs_reg, const int32_t& ft_reg, const int32_t& fd_reg,
- int64_t& i64hilo, uint64_t& u64hilo, int32_t& alu_out, bool& do_interrupt,
- int32_t& current_pc, int32_t& next_pc, int32_t& return_addr_reg) {
- switch (instr->RsFieldRaw()) {
+void Simulator::DecodeTypeRegisterCOP1() {
+ switch (get_instr()->RsFieldRaw()) {
case CFC1:
- set_register(rt_reg, alu_out);
+ // At the moment only FCSR is supported.
+ DCHECK(fs_reg() == kFCSRRegister);
+ set_register(rt_reg(), FCSR_);
break;
case MFC1:
- set_register(rt_reg, alu_out);
+ set_register(rt_reg(), get_fpu_register_word(fs_reg()));
break;
case MFHC1:
- set_register(rt_reg, alu_out);
+ set_register(rt_reg(), get_fpu_register_hi_word(fs_reg()));
break;
case CTC1:
// At the moment only FCSR is supported.
- DCHECK(fs_reg == kFCSRRegister);
- FCSR_ = registers_[rt_reg];
+ DCHECK(fs_reg() == kFCSRRegister);
+ FCSR_ = registers_[rt_reg()];
break;
case MTC1:
// Hardware writes upper 32-bits to zero on mtc1.
- set_fpu_register_hi_word(fs_reg, 0);
- set_fpu_register_word(fs_reg, registers_[rt_reg]);
+ set_fpu_register_hi_word(fs_reg(), 0);
+ set_fpu_register_word(fs_reg(), registers_[rt_reg()]);
break;
case MTHC1:
- set_fpu_register_hi_word(fs_reg, registers_[rt_reg]);
+ set_fpu_register_hi_word(fs_reg(), registers_[rt_reg()]);
break;
case S: {
- DecodeTypeRegisterSRsType(instr, ft_reg, fs_reg, fd_reg);
+ DecodeTypeRegisterSRsType();
break;
}
case D:
- DecodeTypeRegisterDRsType(instr, fr_reg, fs_reg, ft_reg, fd_reg);
+ DecodeTypeRegisterDRsType();
break;
case W:
- DecodeTypeRegisterWRsType(instr, alu_out, fd_reg, fs_reg, ft_reg);
+ DecodeTypeRegisterWRsType();
break;
case L:
- DecodeTypeRegisterLRsType(instr, ft_reg, fs_reg, fd_reg);
+ DecodeTypeRegisterLRsType();
break;
+ case PS:
+ // Not implemented.
+ UNREACHABLE();
default:
UNREACHABLE();
}
}
-void Simulator::DecodeTypeRegisterCOP1X(Instruction* instr,
- const int32_t& fr_reg,
- const int32_t& fs_reg,
- const int32_t& ft_reg,
- const int32_t& fd_reg) {
- switch (instr->FunctionFieldRaw()) {
+void Simulator::DecodeTypeRegisterCOP1X() {
+ switch (get_instr()->FunctionFieldRaw()) {
case MADD_D:
double fr, ft, fs;
- fr = get_fpu_register_double(fr_reg);
- fs = get_fpu_register_double(fs_reg);
- ft = get_fpu_register_double(ft_reg);
- set_fpu_register_double(fd_reg, fs * ft + fr);
+ fr = get_fpu_register_double(fr_reg());
+ fs = get_fpu_register_double(fs_reg());
+ ft = get_fpu_register_double(ft_reg());
+ set_fpu_register_double(fd_reg(), fs * ft + fr);
break;
default:
UNREACHABLE();
@@ -3650,216 +3295,411 @@ void Simulator::DecodeTypeRegisterCOP1X(Instruction* instr,
}
-void Simulator::DecodeTypeRegisterSPECIAL(
- Instruction* instr, const int32_t& rs_reg, const int32_t& rs,
- const uint32_t& rs_u, const int32_t& rt_reg, const int32_t& rt,
- const uint32_t& rt_u, const int32_t& rd_reg, const int32_t& fr_reg,
- const int32_t& fs_reg, const int32_t& ft_reg, const int32_t& fd_reg,
- int64_t& i64hilo, uint64_t& u64hilo, int32_t& alu_out, bool& do_interrupt,
- int32_t& current_pc, int32_t& next_pc, int32_t& return_addr_reg) {
- switch (instr->FunctionFieldRaw()) {
+void Simulator::DecodeTypeRegisterSPECIAL() {
+ int64_t alu_out = 0x12345678;
+ int64_t i64hilo = 0;
+ uint64_t u64hilo = 0;
+ bool do_interrupt = false;
+
+ switch (get_instr()->FunctionFieldRaw()) {
case SELEQZ_S:
DCHECK(IsMipsArchVariant(kMips32r6));
- set_register(rd_reg, rt == 0 ? rs : 0);
+ set_register(rd_reg(), rt() == 0 ? rs() : 0);
break;
case SELNEZ_S:
DCHECK(IsMipsArchVariant(kMips32r6));
- set_register(rd_reg, rt != 0 ? rs : 0);
- break;
- case JR: {
- Instruction* branch_delay_instr = reinterpret_cast<Instruction*>(
- current_pc+Instruction::kInstrSize);
- BranchDelayInstructionDecode(branch_delay_instr);
- set_pc(next_pc);
- pc_modified_ = true;
- break;
+ set_register(rd_reg(), rt() != 0 ? rs() : 0);
+ break;
+ case JR: {
+ int32_t next_pc = rs();
+ int32_t current_pc = get_pc();
+ Instruction* branch_delay_instr =
+ reinterpret_cast<Instruction*>(current_pc + Instruction::kInstrSize);
+ BranchDelayInstructionDecode(branch_delay_instr);
+ set_pc(next_pc);
+ pc_modified_ = true;
+ break;
+ }
+ case JALR: {
+ int32_t next_pc = rs();
+ int32_t return_addr_reg = rd_reg();
+ int32_t current_pc = get_pc();
+ Instruction* branch_delay_instr =
+ reinterpret_cast<Instruction*>(current_pc + Instruction::kInstrSize);
+ BranchDelayInstructionDecode(branch_delay_instr);
+ set_register(return_addr_reg, current_pc + 2 * Instruction::kInstrSize);
+ set_pc(next_pc);
+ pc_modified_ = true;
+ break;
+ }
+ case SLL:
+ alu_out = rt() << sa();
+ SetResult(rd_reg(), static_cast<int32_t>(alu_out));
+ break;
+ case SRL:
+ if (rs_reg() == 0) {
+ // Regular logical right shift of a word by a fixed number of
+ // bits instruction. RS field is always equal to 0.
+ alu_out = rt_u() >> sa();
+ } else {
+ // Logical right-rotate of a word by a fixed number of bits. This
+ // is special case of SRL instruction, added in MIPS32 Release 2.
+ // RS field is equal to 00001.
+ alu_out = base::bits::RotateRight32(rt_u(), sa());
+ }
+ SetResult(rd_reg(), static_cast<int32_t>(alu_out));
+ break;
+ case SRA:
+ alu_out = rt() >> sa();
+ SetResult(rd_reg(), static_cast<int32_t>(alu_out));
+ break;
+ case SLLV:
+ alu_out = rt() << rs();
+ SetResult(rd_reg(), static_cast<int32_t>(alu_out));
+ break;
+ case SRLV:
+ if (sa() == 0) {
+ // Regular logical right-shift of a word by a variable number of
+ // bits instruction. SA field is always equal to 0.
+ alu_out = rt_u() >> rs();
+ } else {
+ // Logical right-rotate of a word by a variable number of bits.
+ // This is special case od SRLV instruction, added in MIPS32
+ // Release 2. SA field is equal to 00001.
+ alu_out = base::bits::RotateRight32(rt_u(), rs_u());
+ }
+ SetResult(rd_reg(), static_cast<int32_t>(alu_out));
+ break;
+ case SRAV:
+ alu_out = rt() >> rs();
+ SetResult(rd_reg(), static_cast<int32_t>(alu_out));
+ break;
+ case MFHI: // MFHI == CLZ on R6.
+ if (!IsMipsArchVariant(kMips32r6)) {
+ DCHECK(sa() == 0);
+ alu_out = get_register(HI);
+ } else {
+ // MIPS spec: If no bits were set in GPR rs, the result written to
+ // GPR rd is 32.
+ DCHECK(sa() == 1);
+ alu_out = base::bits::CountLeadingZeros32(rs_u());
+ }
+ SetResult(rd_reg(), static_cast<int32_t>(alu_out));
+ break;
+ case MFLO:
+ alu_out = get_register(LO);
+ SetResult(rd_reg(), static_cast<int32_t>(alu_out));
+ break;
+ // Instructions using HI and LO registers.
+ case MULT:
+ i64hilo = static_cast<int64_t>(rs()) * static_cast<int64_t>(rt());
+ if (!IsMipsArchVariant(kMips32r6)) {
+ set_register(LO, static_cast<int32_t>(i64hilo & 0xffffffff));
+ set_register(HI, static_cast<int32_t>(i64hilo >> 32));
+ } else {
+ switch (sa()) {
+ case MUL_OP:
+ set_register(rd_reg(), static_cast<int32_t>(i64hilo & 0xffffffff));
+ break;
+ case MUH_OP:
+ set_register(rd_reg(), static_cast<int32_t>(i64hilo >> 32));
+ break;
+ default:
+ UNIMPLEMENTED_MIPS();
+ break;
}
- case JALR: {
- Instruction* branch_delay_instr = reinterpret_cast<Instruction*>(
- current_pc+Instruction::kInstrSize);
- BranchDelayInstructionDecode(branch_delay_instr);
- set_register(return_addr_reg,
- current_pc + 2 * Instruction::kInstrSize);
- set_pc(next_pc);
- pc_modified_ = true;
- break;
+ }
+ break;
+ case MULTU:
+ u64hilo = static_cast<uint64_t>(rs_u()) * static_cast<uint64_t>(rt_u());
+ if (!IsMipsArchVariant(kMips32r6)) {
+ set_register(LO, static_cast<int32_t>(u64hilo & 0xffffffff));
+ set_register(HI, static_cast<int32_t>(u64hilo >> 32));
+ } else {
+ switch (sa()) {
+ case MUL_OP:
+ set_register(rd_reg(), static_cast<int32_t>(u64hilo & 0xffffffff));
+ break;
+ case MUH_OP:
+ set_register(rd_reg(), static_cast<int32_t>(u64hilo >> 32));
+ break;
+ default:
+ UNIMPLEMENTED_MIPS();
+ break;
}
- // Instructions using HI and LO registers.
- case MULT:
- if (!IsMipsArchVariant(kMips32r6)) {
- set_register(LO, static_cast<int32_t>(i64hilo & 0xffffffff));
- set_register(HI, static_cast<int32_t>(i64hilo >> 32));
- } else {
- switch (instr->SaValue()) {
- case MUL_OP:
- set_register(rd_reg,
- static_cast<int32_t>(i64hilo & 0xffffffff));
- break;
- case MUH_OP:
- set_register(rd_reg, static_cast<int32_t>(i64hilo >> 32));
- break;
- default:
- UNIMPLEMENTED_MIPS();
- break;
- }
- }
- break;
- case MULTU:
- if (!IsMipsArchVariant(kMips32r6)) {
- set_register(LO, static_cast<int32_t>(u64hilo & 0xffffffff));
- set_register(HI, static_cast<int32_t>(u64hilo >> 32));
- } else {
- switch (instr->SaValue()) {
- case MUL_OP:
- set_register(rd_reg,
- static_cast<int32_t>(u64hilo & 0xffffffff));
- break;
- case MUH_OP:
- set_register(rd_reg, static_cast<int32_t>(u64hilo >> 32));
- break;
- default:
- UNIMPLEMENTED_MIPS();
- break;
+ }
+ break;
+ case DIV:
+ if (IsMipsArchVariant(kMips32r6)) {
+ switch (get_instr()->SaValue()) {
+ case DIV_OP:
+ if (rs() == INT_MIN && rt() == -1) {
+ set_register(rd_reg(), INT_MIN);
+ } else if (rt() != 0) {
+ set_register(rd_reg(), rs() / rt());
}
- }
- break;
- case DIV:
- if (IsMipsArchVariant(kMips32r6)) {
- switch (instr->SaValue()) {
- case DIV_OP:
- if (rs == INT_MIN && rt == -1) {
- set_register(rd_reg, INT_MIN);
- } else if (rt != 0) {
- set_register(rd_reg, rs / rt);
- }
- break;
- case MOD_OP:
- if (rs == INT_MIN && rt == -1) {
- set_register(rd_reg, 0);
- } else if (rt != 0) {
- set_register(rd_reg, rs % rt);
- }
- break;
- default:
- UNIMPLEMENTED_MIPS();
- break;
+ break;
+ case MOD_OP:
+ if (rs() == INT_MIN && rt() == -1) {
+ set_register(rd_reg(), 0);
+ } else if (rt() != 0) {
+ set_register(rd_reg(), rs() % rt());
}
- } else {
- // Divide by zero and overflow was not checked in the
- // configuration step - div and divu do not raise exceptions. On
- // division by 0 the result will be UNPREDICTABLE. On overflow
- // (INT_MIN/-1), return INT_MIN which is what the hardware does.
- if (rs == INT_MIN && rt == -1) {
- set_register(LO, INT_MIN);
- set_register(HI, 0);
- } else if (rt != 0) {
- set_register(LO, rs / rt);
- set_register(HI, rs % rt);
+ break;
+ default:
+ UNIMPLEMENTED_MIPS();
+ break;
+ }
+ } else {
+ // Divide by zero and overflow was not checked in the
+ // configuration step - div and divu do not raise exceptions. On
+ // division by 0 the result will be UNPREDICTABLE. On overflow
+ // (INT_MIN/-1), return INT_MIN which is what the hardware does.
+ if (rs() == INT_MIN && rt() == -1) {
+ set_register(LO, INT_MIN);
+ set_register(HI, 0);
+ } else if (rt() != 0) {
+ set_register(LO, rs() / rt());
+ set_register(HI, rs() % rt());
+ }
+ }
+ break;
+ case DIVU:
+ if (IsMipsArchVariant(kMips32r6)) {
+ switch (get_instr()->SaValue()) {
+ case DIV_OP:
+ if (rt_u() != 0) {
+ set_register(rd_reg(), rs_u() / rt_u());
}
- }
- break;
- case DIVU:
- if (IsMipsArchVariant(kMips32r6)) {
- switch (instr->SaValue()) {
- case DIV_OP:
- if (rt_u != 0) {
- set_register(rd_reg, rs_u / rt_u);
- }
- break;
- case MOD_OP:
- if (rt_u != 0) {
- set_register(rd_reg, rs_u % rt_u);
- }
- break;
- default:
- UNIMPLEMENTED_MIPS();
- break;
- }
- } else {
- if (rt_u != 0) {
- set_register(LO, rs_u / rt_u);
- set_register(HI, rs_u % rt_u);
+ break;
+ case MOD_OP:
+ if (rt_u() != 0) {
+ set_register(rd_reg(), rs_u() % rt_u());
}
+ break;
+ default:
+ UNIMPLEMENTED_MIPS();
+ break;
+ }
+ } else {
+ if (rt_u() != 0) {
+ set_register(LO, rs_u() / rt_u());
+ set_register(HI, rs_u() % rt_u());
+ }
+ }
+ break;
+ case ADD:
+ if (HaveSameSign(rs(), rt())) {
+ if (rs() > 0) {
+ if (rs() <= (Registers::kMaxValue - rt())) {
+ SignalException(kIntegerOverflow);
}
- break;
- // Break and trap instructions.
- case BREAK:
- case TGE:
- case TGEU:
- case TLT:
- case TLTU:
- case TEQ:
- case TNE:
- if (do_interrupt) {
- SoftwareInterrupt(instr);
+ } else if (rs() < 0) {
+ if (rs() >= (Registers::kMinValue - rt())) {
+ SignalException(kIntegerUnderflow);
}
- break;
- // Conditional moves.
- case MOVN:
- if (rt) {
- set_register(rd_reg, rs);
- TraceRegWr(rs);
+ }
+ }
+ SetResult(rd_reg(), rs() + rt());
+ break;
+ case ADDU:
+ SetResult(rd_reg(), rs() + rt());
+ break;
+ case SUB:
+ if (!HaveSameSign(rs(), rt())) {
+ if (rs() > 0) {
+ if (rs() <= (Registers::kMaxValue + rt())) {
+ SignalException(kIntegerOverflow);
}
- break;
- case MOVCI: {
- uint32_t cc = instr->FBccValue();
- uint32_t fcsr_cc = get_fcsr_condition_bit(cc);
- if (instr->Bit(16)) { // Read Tf bit.
- if (test_fcsr_bit(fcsr_cc)) set_register(rd_reg, rs);
- } else {
- if (!test_fcsr_bit(fcsr_cc)) set_register(rd_reg, rs);
+ } else if (rs() < 0) {
+ if (rs() >= (Registers::kMinValue + rt())) {
+ SignalException(kIntegerUnderflow);
}
- break;
}
- case MOVZ:
- if (!rt) {
- set_register(rd_reg, rs);
- TraceRegWr(rs);
- }
- break;
- default: // For other special opcodes we do the default operation.
- set_register(rd_reg, alu_out);
- TraceRegWr(alu_out);
}
+ SetResult(rd_reg(), rs() - rt());
+ break;
+ case SUBU:
+ SetResult(rd_reg(), rs() - rt());
+ break;
+ case AND:
+ SetResult(rd_reg(), rs() & rt());
+ break;
+ case OR:
+ SetResult(rd_reg(), rs() | rt());
+ break;
+ case XOR:
+ SetResult(rd_reg(), rs() ^ rt());
+ break;
+ case NOR:
+ SetResult(rd_reg(), ~(rs() | rt()));
+ break;
+ case SLT:
+ SetResult(rd_reg(), rs() < rt() ? 1 : 0);
+ break;
+ case SLTU:
+ SetResult(rd_reg(), rs_u() < rt_u() ? 1 : 0);
+ break;
+ // Break and trap instructions.
+ case BREAK:
+ do_interrupt = true;
+ break;
+ case TGE:
+ do_interrupt = rs() >= rt();
+ break;
+ case TGEU:
+ do_interrupt = rs_u() >= rt_u();
+ break;
+ case TLT:
+ do_interrupt = rs() < rt();
+ break;
+ case TLTU:
+ do_interrupt = rs_u() < rt_u();
+ break;
+ case TEQ:
+ do_interrupt = rs() == rt();
+ break;
+ case TNE:
+ do_interrupt = rs() != rt();
+ break;
+ // Conditional moves.
+ case MOVN:
+ if (rt()) {
+ set_register(rd_reg(), rs());
+ TraceRegWr(rs());
+ }
+ break;
+ case MOVCI: {
+ uint32_t cc = get_instr()->FBccValue();
+ uint32_t fcsr_cc = get_fcsr_condition_bit(cc);
+ if (get_instr()->Bit(16)) { // Read Tf bit.
+ if (test_fcsr_bit(fcsr_cc)) set_register(rd_reg(), rs());
+ } else {
+ if (!test_fcsr_bit(fcsr_cc)) set_register(rd_reg(), rs());
+ }
+ break;
+ }
+ case MOVZ:
+ if (!rt()) {
+ set_register(rd_reg(), rs());
+ TraceRegWr(rs());
+ }
+ break;
+ default:
+ UNREACHABLE();
+ }
+ if (do_interrupt) {
+ SoftwareInterrupt(get_instr());
+ }
}
-void Simulator::DecodeTypeRegisterSPECIAL2(Instruction* instr,
- const int32_t& rd_reg,
- int32_t& alu_out) {
- switch (instr->FunctionFieldRaw()) {
+void Simulator::DecodeTypeRegisterSPECIAL2() {
+ int32_t alu_out;
+ switch (get_instr()->FunctionFieldRaw()) {
case MUL:
- set_register(rd_reg, alu_out);
- TraceRegWr(alu_out);
+ // Only the lower 32 bits are kept.
+ alu_out = rs_u() * rt_u();
// HI and LO are UNPREDICTABLE after the operation.
set_register(LO, Unpredictable);
set_register(HI, Unpredictable);
break;
- default: // For other special2 opcodes we do the default operation.
- set_register(rd_reg, alu_out);
- TraceRegWr(alu_out);
+ case CLZ:
+ // MIPS32 spec: If no bits were set in GPR rs, the result written to
+ // GPR rd is 32.
+ alu_out = base::bits::CountLeadingZeros32(rs_u());
+ break;
+ default:
+ alu_out = 0x12345678;
+ UNREACHABLE();
}
+ SetResult(rd_reg(), alu_out);
}
-void Simulator::DecodeTypeRegisterSPECIAL3(Instruction* instr,
- const int32_t& rt_reg,
- const int32_t& rd_reg,
- int32_t& alu_out) {
- switch (instr->FunctionFieldRaw()) {
- case INS:
+void Simulator::DecodeTypeRegisterSPECIAL3() {
+ int32_t alu_out;
+ switch (get_instr()->FunctionFieldRaw()) {
+ case INS: { // Mips32r2 instruction.
+ // Interpret rd field as 5-bit msb of insert.
+ uint16_t msb = rd_reg();
+ // Interpret sa field as 5-bit lsb of insert.
+ uint16_t lsb = sa();
+ uint16_t size = msb - lsb + 1;
+ uint32_t mask = (1 << size) - 1;
+ alu_out = (rt_u() & ~(mask << lsb)) | ((rs_u() & mask) << lsb);
// Ins instr leaves result in Rt, rather than Rd.
- set_register(rt_reg, alu_out);
- TraceRegWr(alu_out);
+ SetResult(rt_reg(), alu_out);
break;
- case EXT:
- set_register(rt_reg, alu_out);
- TraceRegWr(alu_out);
+ }
+ case EXT: { // Mips32r2 instruction.
+ // Interpret rd field as 5-bit msb of extract.
+ uint16_t msb = rd_reg();
+ // Interpret sa field as 5-bit lsb of extract.
+ uint16_t lsb = sa();
+ uint16_t size = msb + 1;
+ uint32_t mask = (1 << size) - 1;
+ alu_out = (rs_u() & (mask << lsb)) >> lsb;
+ SetResult(rt_reg(), alu_out);
break;
- case BSHFL:
- set_register(rd_reg, alu_out);
- TraceRegWr(alu_out);
+ }
+ case BSHFL: {
+ int sa = get_instr()->SaFieldRaw() >> kSaShift;
+ switch (sa) {
+ case BITSWAP: {
+ uint32_t input = static_cast<uint32_t>(rt());
+ uint32_t output = 0;
+ uint8_t i_byte, o_byte;
+
+ // Reverse the bit in byte for each individual byte
+ for (int i = 0; i < 4; i++) {
+ output = output >> 8;
+ i_byte = input & 0xff;
+
+ // Fast way to reverse bits in byte
+ // Devised by Sean Anderson, July 13, 2001
+ o_byte = static_cast<uint8_t>(((i_byte * 0x0802LU & 0x22110LU) |
+ (i_byte * 0x8020LU & 0x88440LU)) *
+ 0x10101LU >>
+ 16);
+
+ output = output | (static_cast<uint32_t>(o_byte << 24));
+ input = input >> 8;
+ }
+
+ alu_out = static_cast<int32_t>(output);
+ break;
+ }
+ case SEB:
+ case SEH:
+ case WSBH:
+ alu_out = 0x12345678;
+ UNREACHABLE();
+ break;
+ default: {
+ const uint8_t bp = get_instr()->Bp2Value();
+ sa >>= kBp2Bits;
+ switch (sa) {
+ case ALIGN: {
+ if (bp == 0) {
+ alu_out = static_cast<int32_t>(rt());
+ } else {
+ uint32_t rt_hi = rt() << (8 * bp);
+ uint32_t rs_lo = rs() >> (8 * (4 - bp));
+ alu_out = static_cast<int32_t>(rt_hi | rs_lo);
+ }
+ break;
+ }
+ default:
+ alu_out = 0x12345678;
+ UNREACHABLE();
+ break;
+ }
+ }
+ }
+ SetResult(rd_reg(), alu_out);
break;
+ }
default:
UNREACHABLE();
}
@@ -3867,134 +3707,101 @@ void Simulator::DecodeTypeRegisterSPECIAL3(Instruction* instr,
void Simulator::DecodeTypeRegister(Instruction* instr) {
- // Instruction fields.
const Opcode op = instr->OpcodeFieldRaw();
- const int32_t rs_reg = instr->RsValue();
- const int32_t rs = get_register(rs_reg);
- const uint32_t rs_u = static_cast<uint32_t>(rs);
- const int32_t rt_reg = instr->RtValue();
- const int32_t rt = get_register(rt_reg);
- const uint32_t rt_u = static_cast<uint32_t>(rt);
- const int32_t rd_reg = instr->RdValue();
-
- const int32_t fr_reg = instr->FrValue();
- const int32_t fs_reg = instr->FsValue();
- const int32_t ft_reg = instr->FtValue();
- const int32_t fd_reg = instr->FdValue();
- int64_t i64hilo = 0;
- uint64_t u64hilo = 0;
-
- // ALU output.
- // It should not be used as is. Instructions using it should always
- // initialize it first.
- int32_t alu_out = 0x12345678;
-
- // For break and trap instructions.
- bool do_interrupt = false;
-
- // For jr and jalr.
- // Get current pc.
- int32_t current_pc = get_pc();
- // Next pc
- int32_t next_pc = 0;
- int32_t return_addr_reg = 31;
// Set up the variables if needed before executing the instruction.
- ConfigureTypeRegister(instr, &alu_out, &i64hilo, &u64hilo, &next_pc,
- &return_addr_reg, &do_interrupt);
-
- // ---------- Raise exceptions triggered.
- SignalExceptions();
+ // ConfigureTypeRegister(instr);
+ set_instr(instr);
// ---------- Execution.
switch (op) {
case COP1:
- DecodeTypeRegisterCOP1(instr, rs_reg, rs, rs_u, rt_reg, rt, rt_u, rd_reg,
- fr_reg, fs_reg, ft_reg, fd_reg, i64hilo, u64hilo,
- alu_out, do_interrupt, current_pc, next_pc,
- return_addr_reg);
+ DecodeTypeRegisterCOP1();
break;
case COP1X:
- DecodeTypeRegisterCOP1X(instr, fr_reg, fs_reg, ft_reg, fd_reg);
+ DecodeTypeRegisterCOP1X();
break;
case SPECIAL:
- DecodeTypeRegisterSPECIAL(instr, rs_reg, rs, rs_u, rt_reg, rt, rt_u,
- rd_reg, fr_reg, fs_reg, ft_reg, fd_reg, i64hilo,
- u64hilo, alu_out, do_interrupt, current_pc,
- next_pc, return_addr_reg);
+ DecodeTypeRegisterSPECIAL();
break;
case SPECIAL2:
- DecodeTypeRegisterSPECIAL2(instr, rd_reg, alu_out);
+ DecodeTypeRegisterSPECIAL2();
break;
case SPECIAL3:
- DecodeTypeRegisterSPECIAL3(instr, rt_reg, rd_reg, alu_out);
+ DecodeTypeRegisterSPECIAL3();
break;
- // Unimplemented opcodes raised an error in the configuration step before,
- // so we can use the default here to set the destination register in common
- // cases.
default:
- set_register(rd_reg, alu_out);
+ UNREACHABLE();
}
}
+// 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).
void Simulator::DecodeTypeImmediate(Instruction* instr) {
// Instruction fields.
- Opcode op = instr->OpcodeFieldRaw();
+ Opcode op = instr->OpcodeFieldRaw();
int32_t rs_reg = instr->RsValue();
- int32_t rs = get_register(instr->RsValue());
- uint32_t rs_u = static_cast<uint32_t>(rs);
- int32_t rt_reg = instr->RtValue(); // Destination register.
- int32_t rt = get_register(rt_reg);
- int16_t imm16 = instr->Imm16Value();
- int32_t imm19 = instr->Imm19Value();
+ int32_t rs = get_register(instr->RsValue());
+ uint32_t rs_u = static_cast<uint32_t>(rs);
+ 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;
+ int32_t ft_reg = instr->FtValue(); // Destination register.
+ int64_t ft;
// Zero extended immediate.
- uint32_t oe_imm16 = 0xffff & imm16;
+ uint32_t oe_imm16 = 0xffff & imm16;
// Sign extended immediate.
int32_t se_imm16 = imm16;
- int32_t se_imm19 = imm19 | ((imm19 & 0x40000) ? 0xfff80000 : 0);
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;
- // pc increment
- int16_t pc_increment;
// Used for conditional branch instructions.
- bool do_branch = false;
bool execute_branch_delay_instruction = false;
// Used for arithmetic instructions.
int32_t alu_out = 0;
- // Floating point.
- double fp_out = 0.0;
- uint32_t cc, cc_value, fcsr_cc;
// Used for memory instructions.
int32_t addr = 0x0;
- // Value to be written in memory.
- uint32_t mem_value = 0x0;
// ---------- Configuration (and execution for REGIMM).
switch (op) {
// ------------- COP1. Coprocessor instructions.
case COP1:
switch (instr->RsFieldRaw()) {
- case BC1: // Branch on coprocessor condition.
- cc = instr->FBccValue();
- fcsr_cc = get_fcsr_condition_bit(cc);
- cc_value = test_fcsr_bit(fcsr_cc);
- do_branch = (instr->FBtrueValue()) ? cc_value : !cc_value;
+ case BC1: { // Branch on coprocessor condition.
+ // Floating point.
+ uint32_t cc = instr->FBccValue();
+ 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) {
@@ -4003,12 +3810,12 @@ void Simulator::DecodeTypeImmediate(Instruction* instr) {
next_pc = current_pc + kBranchReturnOffset;
}
break;
+ }
case BC1EQZ:
ft = get_fpu_register(ft_reg);
- do_branch = (ft & 0x1) ? false : true;
execute_branch_delay_instruction = true;
// Set next_pc.
- if (do_branch) {
+ if (!(ft & 0x1)) {
next_pc = current_pc + (imm16 << 2) + Instruction::kInstrSize;
} else {
next_pc = current_pc + kBranchReturnOffset;
@@ -4016,10 +3823,9 @@ void Simulator::DecodeTypeImmediate(Instruction* instr) {
break;
case BC1NEZ:
ft = get_fpu_register(ft_reg);
- do_branch = (ft & 0x1) ? true : false;
execute_branch_delay_instruction = true;
// Set next_pc.
- if (do_branch) {
+ if (ft & 0x1) {
next_pc = current_pc + (imm16 << 2) + Instruction::kInstrSize;
} else {
next_pc = current_pc + kBranchReturnOffset;
@@ -4033,54 +3839,35 @@ void Simulator::DecodeTypeImmediate(Instruction* instr) {
case REGIMM:
switch (instr->RtFieldRaw()) {
case BLTZ:
- do_branch = (rs < 0);
- break;
- case BLTZAL:
- do_branch = rs < 0;
+ BranchHelper(rs < 0);
break;
case BGEZ:
- do_branch = rs >= 0;
+ BranchHelper(rs >= 0);
+ break;
+ case BLTZAL:
+ BranchAndLinkHelper(rs < 0);
break;
case BGEZAL:
- do_branch = rs >= 0;
+ BranchAndLinkHelper(rs >= 0);
break;
default:
UNREACHABLE();
}
- switch (instr->RtFieldRaw()) {
- case BLTZ:
- case BLTZAL:
- case BGEZ:
- case BGEZAL:
- // Branch instructions common part.
- execute_branch_delay_instruction = true;
- // Set next_pc.
- if (do_branch) {
- next_pc = current_pc + (imm16 << 2) + Instruction::kInstrSize;
- if (instr->IsLinkingInstruction()) {
- set_register(31, current_pc + kBranchReturnOffset);
- }
- } else {
- next_pc = current_pc + kBranchReturnOffset;
- }
- default:
- break;
- }
- break; // case REGIMM.
+ break; // case REGIMM.
// ------------- Branch instructions.
// When comparing to zero, the encoding of rt field is always 0, so we don't
// need to replace rt with zero.
case BEQ:
- do_branch = (rs == rt);
+ BranchHelper(rs == rt);
break;
case BNE:
- do_branch = rs != rt;
+ BranchHelper(rs != rt);
break;
case BLEZ:
- do_branch = rs <= 0;
+ BranchHelper(rs <= 0);
break;
case BGTZ:
- do_branch = rs > 0;
+ BranchHelper(rs > 0);
break;
case POP66: {
if (rs_reg) { // BEQZC
@@ -4113,43 +3900,44 @@ void Simulator::DecodeTypeImmediate(Instruction* instr) {
case ADDI:
if (HaveSameSign(rs, se_imm16)) {
if (rs > 0) {
- exceptions[kIntegerOverflow] = rs > (Registers::kMaxValue - se_imm16);
+ if (rs <= (Registers::kMaxValue - se_imm16)) {
+ SignalException(kIntegerOverflow);
+ }
} else if (rs < 0) {
- exceptions[kIntegerUnderflow] =
- rs < (Registers::kMinValue - se_imm16);
+ if (rs >= (Registers::kMinValue - se_imm16)) {
+ SignalException(kIntegerUnderflow);
+ }
}
}
- alu_out = rs + se_imm16;
+ SetResult(rt_reg, rs + se_imm16);
break;
case ADDIU:
- alu_out = rs + se_imm16;
+ SetResult(rt_reg, rs + se_imm16);
break;
case SLTI:
- alu_out = (rs < se_imm16) ? 1 : 0;
+ SetResult(rt_reg, rs < se_imm16 ? 1 : 0);
break;
case SLTIU:
- alu_out = (rs_u < static_cast<uint32_t>(se_imm16)) ? 1 : 0;
+ SetResult(rt_reg, rs_u < static_cast<uint32_t>(se_imm16) ? 1 : 0);
break;
case ANDI:
- alu_out = rs & oe_imm16;
+ SetResult(rt_reg, rs & oe_imm16);
break;
case ORI:
- alu_out = rs | oe_imm16;
+ SetResult(rt_reg, rs | oe_imm16);
break;
case XORI:
- alu_out = rs ^ oe_imm16;
+ SetResult(rt_reg, rs ^ oe_imm16);
break;
case LUI:
- alu_out = (oe_imm16 << 16);
+ SetResult(rt_reg, oe_imm16 << 16);
break;
// ------------- Memory instructions.
case LB:
- addr = rs + se_imm16;
- alu_out = ReadB(addr);
+ set_register(rt_reg, ReadB(rs + se_imm16));
break;
case LH:
- addr = rs + se_imm16;
- alu_out = ReadH(addr, instr);
+ set_register(rt_reg, ReadH(rs + se_imm16, instr));
break;
case LWL: {
// al_offset is offset of the effective address within an aligned word.
@@ -4160,19 +3948,17 @@ void Simulator::DecodeTypeImmediate(Instruction* instr) {
alu_out = ReadW(addr, instr);
alu_out <<= byte_shift * 8;
alu_out |= rt & mask;
+ set_register(rt_reg, alu_out);
break;
}
case LW:
- addr = rs + se_imm16;
- alu_out = ReadW(addr, instr);
+ set_register(rt_reg, ReadW(rs + se_imm16, instr));
break;
case LBU:
- addr = rs + se_imm16;
- alu_out = ReadBU(addr);
+ set_register(rt_reg, ReadBU(rs + se_imm16));
break;
case LHU:
- addr = rs + se_imm16;
- alu_out = ReadHU(addr, instr);
+ set_register(rt_reg, ReadHU(rs + se_imm16, instr));
break;
case LWR: {
// al_offset is offset of the effective address within an aligned word.
@@ -4183,58 +3969,64 @@ void Simulator::DecodeTypeImmediate(Instruction* instr) {
alu_out = ReadW(addr, instr);
alu_out = static_cast<uint32_t> (alu_out) >> al_offset * 8;
alu_out |= rt & mask;
+ set_register(rt_reg, alu_out);
break;
}
case SB:
- addr = rs + se_imm16;
+ WriteB(rs + se_imm16, static_cast<int8_t>(rt));
break;
case SH:
- addr = rs + se_imm16;
+ WriteH(rs + se_imm16, static_cast<uint16_t>(rt), instr);
break;
case SWL: {
uint8_t al_offset = (rs + se_imm16) & kPointerAlignmentMask;
uint8_t byte_shift = kPointerAlignmentMask - al_offset;
uint32_t mask = byte_shift ? (~0 << (al_offset + 1) * 8) : 0;
addr = rs + se_imm16 - al_offset;
- mem_value = ReadW(addr, instr) & mask;
+ // Value to be written in memory.
+ uint32_t mem_value = ReadW(addr, instr) & mask;
mem_value |= static_cast<uint32_t>(rt) >> byte_shift * 8;
+ WriteW(addr, mem_value, instr);
break;
}
case SW:
- addr = rs + se_imm16;
+ WriteW(rs + se_imm16, rt, instr);
break;
case SWR: {
uint8_t al_offset = (rs + se_imm16) & kPointerAlignmentMask;
uint32_t mask = (1 << al_offset * 8) - 1;
addr = rs + se_imm16 - al_offset;
- mem_value = ReadW(addr, instr);
+ uint32_t mem_value = ReadW(addr, instr);
mem_value = (rt << al_offset * 8) | (mem_value & mask);
+ WriteW(addr, mem_value, instr);
break;
}
case LWC1:
- addr = rs + se_imm16;
- alu_out = ReadW(addr, instr);
+ set_fpu_register_hi_word(ft_reg, 0);
+ set_fpu_register_word(ft_reg, ReadW(rs + se_imm16, instr));
break;
case LDC1:
- addr = rs + se_imm16;
- fp_out = ReadD(addr, instr);
+ set_fpu_register_double(ft_reg, ReadD(rs + se_imm16, instr));
break;
case SWC1:
+ WriteW(rs + se_imm16, get_fpu_register_word(ft_reg), instr);
+ break;
case SDC1:
- addr = rs + se_imm16;
+ WriteD(rs + se_imm16, get_fpu_register_double(ft_reg), instr);
break;
// ------------- JIALC and BNEZC instructions.
- case POP76:
+ case POP76: {
// Next pc.
next_pc = rt + se_imm16;
// The instruction after the jump is NOT executed.
- pc_increment = Instruction::kInstrSize;
+ 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.
@@ -4248,115 +4040,37 @@ void Simulator::DecodeTypeImmediate(Instruction* instr) {
alu_out = current_pc + (se_imm16 << 16);
break;
default: {
+ int32_t imm19 = instr->Imm19Value();
// rt field: checking the most significant 2-bits.
rt = (imm21 >> kImm19Bits);
switch (rt) {
case LWPC: {
- int32_t offset = imm19;
// Set sign.
- offset <<= (kOpcodeBits + kRsBits + 2);
- offset >>= (kOpcodeBits + kRsBits + 2);
- addr = current_pc + (offset << 2);
+ imm19 <<= (kOpcodeBits + kRsBits + 2);
+ imm19 >>= (kOpcodeBits + kRsBits + 2);
+ addr = current_pc + (imm19 << 2);
uint32_t* ptr = reinterpret_cast<uint32_t*>(addr);
alu_out = *ptr;
break;
}
- case ADDIUPC:
+ case ADDIUPC: {
+ int32_t se_imm19 = imm19 | ((imm19 & 0x40000) ? 0xfff80000 : 0);
alu_out = current_pc + (se_imm19 << 2);
break;
+ }
default:
UNREACHABLE();
break;
}
}
}
+ set_register(rs_reg, alu_out);
break;
}
default:
UNREACHABLE();
}
- // ---------- Raise exceptions triggered.
- SignalExceptions();
-
- // ---------- Execution.
- switch (op) {
- // ------------- Branch instructions.
- case BEQ:
- case BNE:
- case BLEZ:
- case BGTZ:
- // Branch instructions common part.
- execute_branch_delay_instruction = true;
- // Set next_pc.
- if (do_branch) {
- next_pc = current_pc + (imm16 << 2) + Instruction::kInstrSize;
- if (instr->IsLinkingInstruction()) {
- set_register(31, current_pc + 2* Instruction::kInstrSize);
- }
- } else {
- next_pc = current_pc + 2 * Instruction::kInstrSize;
- }
- break;
- // ------------- Arithmetic instructions.
- case ADDI:
- case ADDIU:
- case SLTI:
- case SLTIU:
- case ANDI:
- case ORI:
- case XORI:
- case LUI:
- set_register(rt_reg, alu_out);
- TraceRegWr(alu_out);
- break;
- // ------------- Memory instructions.
- case LB:
- case LH:
- case LWL:
- case LW:
- case LBU:
- case LHU:
- case LWR:
- set_register(rt_reg, alu_out);
- break;
- case SB:
- WriteB(addr, static_cast<int8_t>(rt));
- break;
- case SH:
- WriteH(addr, static_cast<uint16_t>(rt), instr);
- break;
- case SWL:
- WriteW(addr, mem_value, instr);
- break;
- case SW:
- WriteW(addr, rt, instr);
- break;
- case SWR:
- WriteW(addr, mem_value, instr);
- break;
- case LWC1:
- set_fpu_register_hi_word(ft_reg, 0);
- set_fpu_register_word(ft_reg, alu_out);
- break;
- case LDC1:
- set_fpu_register_double(ft_reg, fp_out);
- break;
- case SWC1:
- addr = rs + se_imm16;
- WriteW(addr, get_fpu_register_word(ft_reg), instr);
- break;
- case SDC1:
- addr = rs + se_imm16;
- WriteD(addr, get_fpu_register_double(ft_reg), instr);
- break;
- case PCREL:
- set_register(rs_reg, alu_out);
- default:
- break;
- }
-
-
if (execute_branch_delay_instruction) {
// Execute branch delay slot
// We don't check for end_sim_pc. First it should not be met as the current
@@ -4372,6 +4086,9 @@ 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) {
@@ -4413,7 +4130,7 @@ void Simulator::InstructionDecode(Instruction* instr) {
dasm.InstructionDecode(buffer, reinterpret_cast<byte*>(instr));
}
- switch (instr->InstructionType()) {
+ switch (instr->InstructionType(Instruction::TypeChecks::EXTRA)) {
case Instruction::kRegisterType:
DecodeTypeRegister(instr);
break;
« no previous file with comments | « src/mips/simulator-mips.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698