summaryrefslogtreecommitdiff
path: root/deps/v8/src/mips/simulator-mips.cc
diff options
context:
space:
mode:
Diffstat (limited to 'deps/v8/src/mips/simulator-mips.cc')
-rw-r--r--deps/v8/src/mips/simulator-mips.cc401
1 files changed, 257 insertions, 144 deletions
diff --git a/deps/v8/src/mips/simulator-mips.cc b/deps/v8/src/mips/simulator-mips.cc
index 59dc300f68..bd423996d8 100644
--- a/deps/v8/src/mips/simulator-mips.cc
+++ b/deps/v8/src/mips/simulator-mips.cc
@@ -808,8 +808,8 @@ void Simulator::set_last_debugger_input(char* input) {
last_debugger_input_ = input;
}
-void Simulator::FlushICache(base::HashMap* i_cache, void* start_addr,
- size_t size) {
+void Simulator::FlushICache(base::CustomMatcherHashMap* i_cache,
+ void* start_addr, size_t size) {
intptr_t start = reinterpret_cast<intptr_t>(start_addr);
int intra_line = (start & CachePage::kLineMask);
start -= intra_line;
@@ -829,8 +829,10 @@ void Simulator::FlushICache(base::HashMap* i_cache, void* start_addr,
}
}
-CachePage* Simulator::GetCachePage(base::HashMap* i_cache, void* page) {
- base::HashMap::Entry* entry = i_cache->LookupOrInsert(page, ICacheHash(page));
+CachePage* Simulator::GetCachePage(base::CustomMatcherHashMap* i_cache,
+ void* page) {
+ base::CustomMatcherHashMap::Entry* entry =
+ i_cache->LookupOrInsert(page, ICacheHash(page));
if (entry->value == NULL) {
CachePage* new_page = new CachePage();
entry->value = new_page;
@@ -840,7 +842,8 @@ CachePage* Simulator::GetCachePage(base::HashMap* i_cache, void* page) {
// Flush from start up to and not including start + size.
-void Simulator::FlushOnePage(base::HashMap* i_cache, intptr_t start, int size) {
+void Simulator::FlushOnePage(base::CustomMatcherHashMap* i_cache,
+ intptr_t start, int size) {
DCHECK(size <= CachePage::kPageSize);
DCHECK(AllOnOnePage(start, size - 1));
DCHECK((start & CachePage::kLineMask) == 0);
@@ -852,7 +855,8 @@ void Simulator::FlushOnePage(base::HashMap* i_cache, intptr_t start, int size) {
memset(valid_bytemap, CachePage::LINE_INVALID, size >> CachePage::kLineShift);
}
-void Simulator::CheckICache(base::HashMap* i_cache, Instruction* instr) {
+void Simulator::CheckICache(base::CustomMatcherHashMap* i_cache,
+ Instruction* instr) {
intptr_t address = reinterpret_cast<intptr_t>(instr);
void* page = reinterpret_cast<void*>(address & (~CachePage::kPageMask));
void* line = reinterpret_cast<void*>(address & (~CachePage::kLineMask));
@@ -885,7 +889,7 @@ void Simulator::Initialize(Isolate* isolate) {
Simulator::Simulator(Isolate* isolate) : isolate_(isolate) {
i_cache_ = isolate_->simulator_i_cache();
if (i_cache_ == NULL) {
- i_cache_ = new base::HashMap(&ICacheMatch);
+ i_cache_ = new base::CustomMatcherHashMap(&ICacheMatch);
isolate_->set_simulator_i_cache(i_cache_);
}
Initialize(isolate);
@@ -997,11 +1001,12 @@ class Redirection {
// static
-void Simulator::TearDown(base::HashMap* i_cache, Redirection* first) {
+void Simulator::TearDown(base::CustomMatcherHashMap* i_cache,
+ Redirection* first) {
Redirection::DeleteChain(first);
if (i_cache != nullptr) {
- for (base::HashMap::Entry* entry = i_cache->Start(); entry != nullptr;
- entry = i_cache->Next(entry)) {
+ for (base::CustomMatcherHashMap::Entry* entry = i_cache->Start();
+ entry != nullptr; entry = i_cache->Next(entry)) {
delete static_cast<CachePage*>(entry->value);
}
delete i_cache;
@@ -1929,16 +1934,16 @@ typedef void (*SimulatorRuntimeProfilingGetterCall)(
// Software interrupt instructions are used by the simulator to call into the
// C-based V8 runtime. They are also used for debugging with simulator.
-void Simulator::SoftwareInterrupt(Instruction* instr) {
+void Simulator::SoftwareInterrupt() {
// There are several instructions that could get us here,
// the break_ instruction, or several variants of traps. All
// Are "SPECIAL" class opcode, and are distinuished by function.
- int32_t func = instr->FunctionFieldRaw();
- uint32_t code = (func == BREAK) ? instr->Bits(25, 6) : -1;
+ int32_t func = instr_.FunctionFieldRaw();
+ uint32_t code = (func == BREAK) ? instr_.Bits(25, 6) : -1;
// We first check if we met a call_rt_redirected.
- if (instr->InstructionBits() == rtCallRedirInstr) {
- Redirection* redirection = Redirection::FromSwiInstruction(instr);
+ if (instr_.InstructionBits() == rtCallRedirInstr) {
+ Redirection* redirection = Redirection::FromSwiInstruction(instr_.instr());
int32_t arg0 = get_register(a0);
int32_t arg1 = get_register(a1);
int32_t arg2 = get_register(a2);
@@ -2173,7 +2178,7 @@ void Simulator::SoftwareInterrupt(Instruction* instr) {
PrintWatchpoint(code);
} else {
IncreaseStopCounter(code);
- HandleStop(code, instr);
+ HandleStop(code, instr_.instr());
}
} else {
// All remaining break_ codes, and all traps are handled here.
@@ -2366,6 +2371,49 @@ static T FPUMaxA(T a, T b) {
return result;
}
+enum class KeepSign : bool { no = false, yes };
+
+template <typename T, typename std::enable_if<std::is_floating_point<T>::value,
+ int>::type = 0>
+T FPUCanonalizeNaNArg(T result, T arg, KeepSign keepSign = KeepSign::no) {
+ DCHECK(std::isnan(arg));
+ T qNaN = std::numeric_limits<T>::quiet_NaN();
+ if (keepSign == KeepSign::yes) {
+ return std::copysign(qNaN, result);
+ }
+ return qNaN;
+}
+
+template <typename T>
+T FPUCanonalizeNaNArgs(T result, KeepSign keepSign, T first) {
+ if (std::isnan(first)) {
+ return FPUCanonalizeNaNArg(result, first, keepSign);
+ }
+ return result;
+}
+
+template <typename T, typename... Args>
+T FPUCanonalizeNaNArgs(T result, KeepSign keepSign, T first, Args... args) {
+ if (std::isnan(first)) {
+ return FPUCanonalizeNaNArg(result, first, keepSign);
+ }
+ return FPUCanonalizeNaNArgs(result, keepSign, args...);
+}
+
+template <typename Func, typename T, typename... Args>
+T FPUCanonalizeOperation(Func f, T first, Args... args) {
+ return FPUCanonalizeOperation(f, KeepSign::no, first, args...);
+}
+
+template <typename Func, typename T, typename... Args>
+T FPUCanonalizeOperation(Func f, KeepSign keepSign, T first, Args... args) {
+ T result = f(first, args...);
+ if (std::isnan(result)) {
+ result = FPUCanonalizeNaNArgs(result, keepSign, first, args...);
+ }
+ return result;
+}
+
// Handle execution based on instruction types.
void Simulator::DecodeTypeRegisterDRsType() {
@@ -2373,15 +2421,14 @@ void Simulator::DecodeTypeRegisterDRsType() {
uint32_t cc, fcsr_cc;
int64_t i64;
fs = get_fpu_register_double(fs_reg());
- ft = (get_instr()->FunctionFieldRaw() != MOVF)
- ? get_fpu_register_double(ft_reg())
- : 0.0;
+ ft = (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 = get_instr()->FCccValue();
+ cc = instr_.FCccValue();
fcsr_cc = get_fcsr_condition_bit(cc);
- switch (get_instr()->FunctionFieldRaw()) {
+ switch (instr_.FunctionFieldRaw()) {
case RINT: {
DCHECK(IsMipsArchVariant(kMips32r6));
double result, temp, temp_result;
@@ -2440,7 +2487,7 @@ void Simulator::DecodeTypeRegisterDRsType() {
}
case MOVN_C: {
DCHECK(IsMipsArchVariant(kMips32r2));
- int32_t rt_reg = get_instr()->RtValue();
+ int32_t rt_reg = instr_.RtValue();
int32_t rt = get_register(rt_reg);
if (rt != 0) {
set_fpu_register_double(fd_reg(), fs);
@@ -2451,7 +2498,7 @@ void Simulator::DecodeTypeRegisterDRsType() {
// Same function field for MOVT.D and MOVF.D
uint32_t ft_cc = (ft_reg() >> 2) & 0x7;
ft_cc = get_fcsr_condition_bit(ft_cc);
- if (get_instr()->Bit(16)) { // Read Tf bit.
+ if (instr_.Bit(16)) { // Read Tf bit.
// MOVT.D
if (test_fcsr_bit(ft_cc)) set_fpu_register_double(fd_reg(), fs);
} else {
@@ -2477,43 +2524,65 @@ void Simulator::DecodeTypeRegisterDRsType() {
set_fpu_register_double(fd_reg(), FPUMaxA(ft, fs));
break;
case ADD_D:
- set_fpu_register_double(fd_reg(), fs + ft);
+ set_fpu_register_double(
+ fd_reg(),
+ FPUCanonalizeOperation(
+ [](double lhs, double rhs) { return lhs + rhs; }, fs, ft));
break;
case SUB_D:
- set_fpu_register_double(fd_reg(), fs - ft);
+ set_fpu_register_double(
+ fd_reg(),
+ FPUCanonalizeOperation(
+ [](double lhs, double rhs) { return lhs - rhs; }, fs, ft));
+ break;
+ case MADDF_D:
+ DCHECK(IsMipsArchVariant(kMips32r6));
+ set_fpu_register_double(fd_reg(), fd + (fs * ft));
+ break;
+ case MSUBF_D:
+ DCHECK(IsMipsArchVariant(kMips32r6));
+ set_fpu_register_double(fd_reg(), fd - (fs * ft));
break;
case MUL_D:
- set_fpu_register_double(fd_reg(), fs * ft);
+ set_fpu_register_double(
+ fd_reg(),
+ FPUCanonalizeOperation(
+ [](double lhs, double rhs) { return lhs * rhs; }, fs, ft));
break;
case DIV_D:
- set_fpu_register_double(fd_reg(), fs / ft);
+ set_fpu_register_double(
+ fd_reg(),
+ FPUCanonalizeOperation(
+ [](double lhs, double rhs) { return lhs / rhs; }, fs, ft));
break;
case ABS_D:
- set_fpu_register_double(fd_reg(), fabs(fs));
+ set_fpu_register_double(
+ fd_reg(),
+ FPUCanonalizeOperation([](double fs) { return FPAbs(fs); }, fs));
break;
case MOV_D:
set_fpu_register_double(fd_reg(), fs);
break;
case NEG_D:
- set_fpu_register_double(fd_reg(), -fs);
+ set_fpu_register_double(
+ fd_reg(), FPUCanonalizeOperation([](double src) { return -src; },
+ KeepSign::yes, fs));
break;
case SQRT_D:
- lazily_initialize_fast_sqrt(isolate_);
- set_fpu_register_double(fd_reg(), fast_sqrt(fs, isolate_));
+ set_fpu_register_double(
+ fd_reg(),
+ FPUCanonalizeOperation([](double fs) { return std::sqrt(fs); }, fs));
break;
- case RSQRT_D: {
- DCHECK(IsMipsArchVariant(kMips32r2) || IsMipsArchVariant(kMips32r6));
- lazily_initialize_fast_sqrt(isolate_);
- double result = 1.0 / fast_sqrt(fs, isolate_);
- set_fpu_register_double(fd_reg(), result);
+ case RSQRT_D:
+ set_fpu_register_double(
+ fd_reg(), FPUCanonalizeOperation(
+ [](double fs) { return 1.0 / std::sqrt(fs); }, fs));
break;
- }
- case RECIP_D: {
- DCHECK(IsMipsArchVariant(kMips32r2) || IsMipsArchVariant(kMips32r6));
- double result = 1.0 / fs;
- set_fpu_register_double(fd_reg(), result);
+ case RECIP_D:
+ set_fpu_register_double(
+ fd_reg(),
+ FPUCanonalizeOperation([](double fs) { return 1.0 / fs; }, fs));
break;
- }
case C_UN_D:
set_fcsr_bit(fcsr_cc, std::isnan(fs) || std::isnan(ft));
break;
@@ -2744,7 +2813,7 @@ 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()) {
+ switch (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));
@@ -2840,9 +2909,9 @@ void Simulator::DecodeTypeRegisterSRsType() {
int32_t ft_int = bit_cast<int32_t>(ft);
int32_t fd_int = bit_cast<int32_t>(fd);
uint32_t cc, fcsr_cc;
- cc = get_instr()->FCccValue();
+ cc = instr_.FCccValue();
fcsr_cc = get_fcsr_condition_bit(cc);
- switch (get_instr()->FunctionFieldRaw()) {
+ switch (instr_.FunctionFieldRaw()) {
case RINT: {
DCHECK(IsMipsArchVariant(kMips32r6));
float result, temp_result;
@@ -2882,43 +2951,65 @@ void Simulator::DecodeTypeRegisterSRsType() {
break;
}
case ADD_S:
- set_fpu_register_float(fd_reg(), fs + ft);
+ set_fpu_register_float(
+ fd_reg(),
+ FPUCanonalizeOperation([](float lhs, float rhs) { return lhs + rhs; },
+ fs, ft));
break;
case SUB_S:
- set_fpu_register_float(fd_reg(), fs - ft);
+ set_fpu_register_float(
+ fd_reg(),
+ FPUCanonalizeOperation([](float lhs, float rhs) { return lhs - rhs; },
+ fs, ft));
+ break;
+ case MADDF_S:
+ DCHECK(IsMipsArchVariant(kMips32r6));
+ set_fpu_register_float(fd_reg(), fd + (fs * ft));
+ break;
+ case MSUBF_S:
+ DCHECK(IsMipsArchVariant(kMips32r6));
+ set_fpu_register_float(fd_reg(), fd - (fs * ft));
break;
case MUL_S:
- set_fpu_register_float(fd_reg(), fs * ft);
+ set_fpu_register_float(
+ fd_reg(),
+ FPUCanonalizeOperation([](float lhs, float rhs) { return lhs * rhs; },
+ fs, ft));
break;
case DIV_S:
- set_fpu_register_float(fd_reg(), fs / ft);
+ set_fpu_register_float(
+ fd_reg(),
+ FPUCanonalizeOperation([](float lhs, float rhs) { return lhs / rhs; },
+ fs, ft));
break;
case ABS_S:
- set_fpu_register_float(fd_reg(), fabs(fs));
+ set_fpu_register_float(
+ fd_reg(),
+ FPUCanonalizeOperation([](float fs) { return FPAbs(fs); }, fs));
break;
case MOV_S:
set_fpu_register_float(fd_reg(), fs);
break;
case NEG_S:
- set_fpu_register_float(fd_reg(), -fs);
+ set_fpu_register_float(
+ fd_reg(), FPUCanonalizeOperation([](float src) { return -src; },
+ KeepSign::yes, fs));
break;
case SQRT_S:
- lazily_initialize_fast_sqrt(isolate_);
- set_fpu_register_float(fd_reg(), fast_sqrt(fs, isolate_));
+ set_fpu_register_float(
+ fd_reg(),
+ FPUCanonalizeOperation([](float src) { return std::sqrt(src); }, fs));
break;
- case RSQRT_S: {
- DCHECK(IsMipsArchVariant(kMips32r2) || IsMipsArchVariant(kMips32r6));
- lazily_initialize_fast_sqrt(isolate_);
- float result = 1.0 / fast_sqrt(fs, isolate_);
- set_fpu_register_float(fd_reg(), result);
+ case RSQRT_S:
+ set_fpu_register_float(
+ fd_reg(), FPUCanonalizeOperation(
+ [](float src) { return 1.0 / std::sqrt(src); }, fs));
break;
- }
- case RECIP_S: {
- DCHECK(IsMipsArchVariant(kMips32r2) || IsMipsArchVariant(kMips32r6));
- float result = 1.0 / fs;
- set_fpu_register_float(fd_reg(), result);
+ case RECIP_S:
+ set_fpu_register_float(
+ fd_reg(),
+ FPUCanonalizeOperation([](float src) { return 1.0 / src; }, fs));
break;
- }
case C_F_D:
set_fcsr_bit(fcsr_cc, false);
break;
@@ -3047,7 +3138,7 @@ void Simulator::DecodeTypeRegisterSRsType() {
uint32_t ft_cc = (ft_reg() >> 2) & 0x7;
ft_cc = get_fcsr_condition_bit(ft_cc);
- if (get_instr()->Bit(16)) { // Read Tf bit.
+ if (instr_.Bit(16)) { // Read Tf bit.
// MOVT.D
if (test_fcsr_bit(ft_cc)) set_fpu_register_float(fd_reg(), fs);
} else {
@@ -3209,7 +3300,7 @@ void Simulator::DecodeTypeRegisterSRsType() {
void Simulator::DecodeTypeRegisterLRsType() {
double fs = get_fpu_register_double(fs_reg());
double ft = get_fpu_register_double(ft_reg());
- switch (get_instr()->FunctionFieldRaw()) {
+ switch (instr_.FunctionFieldRaw()) {
case CVT_D_L: // Mips32r2 instruction.
// Watch the signs here, we want 2 32-bit vals
// to make a sign-64.
@@ -3311,7 +3402,7 @@ void Simulator::DecodeTypeRegisterLRsType() {
void Simulator::DecodeTypeRegisterCOP1() {
- switch (get_instr()->RsFieldRaw()) {
+ switch (instr_.RsFieldRaw()) {
case CFC1:
// At the moment only FCSR is supported.
DCHECK(fs_reg() == kFCSRRegister);
@@ -3374,14 +3465,43 @@ void Simulator::DecodeTypeRegisterCOP1() {
void Simulator::DecodeTypeRegisterCOP1X() {
- switch (get_instr()->FunctionFieldRaw()) {
- case MADD_D:
+ switch (instr_.FunctionFieldRaw()) {
+ case MADD_S: {
+ DCHECK(IsMipsArchVariant(kMips32r2));
+ float fr, ft, fs;
+ fr = get_fpu_register_float(fr_reg());
+ fs = get_fpu_register_float(fs_reg());
+ ft = get_fpu_register_float(ft_reg());
+ set_fpu_register_float(fd_reg(), fs * ft + fr);
+ break;
+ }
+ case MSUB_S: {
+ DCHECK(IsMipsArchVariant(kMips32r2));
+ float fr, ft, fs;
+ fr = get_fpu_register_float(fr_reg());
+ fs = get_fpu_register_float(fs_reg());
+ ft = get_fpu_register_float(ft_reg());
+ set_fpu_register_float(fd_reg(), fs * ft - fr);
+ break;
+ }
+ case MADD_D: {
+ DCHECK(IsMipsArchVariant(kMips32r2));
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);
break;
+ }
+ case MSUB_D: {
+ DCHECK(IsMipsArchVariant(kMips32r2));
+ 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);
+ break;
+ }
default:
UNREACHABLE();
}
@@ -3394,7 +3514,7 @@ void Simulator::DecodeTypeRegisterSPECIAL() {
uint64_t u64hilo = 0;
bool do_interrupt = false;
- switch (get_instr()->FunctionFieldRaw()) {
+ switch (instr_.FunctionFieldRaw()) {
case SELEQZ_S:
DCHECK(IsMipsArchVariant(kMips32r6));
set_register(rd_reg(), rt() == 0 ? rs() : 0);
@@ -3534,7 +3654,7 @@ void Simulator::DecodeTypeRegisterSPECIAL() {
break;
case DIV:
if (IsMipsArchVariant(kMips32r6)) {
- switch (get_instr()->SaValue()) {
+ switch (sa()) {
case DIV_OP:
if (rs() == INT_MIN && rt() == -1) {
set_register(rd_reg(), INT_MIN);
@@ -3569,7 +3689,7 @@ void Simulator::DecodeTypeRegisterSPECIAL() {
break;
case DIVU:
if (IsMipsArchVariant(kMips32r6)) {
- switch (get_instr()->SaValue()) {
+ switch (sa()) {
case DIV_OP:
if (rt_u() != 0) {
set_register(rd_reg(), rs_u() / rt_u());
@@ -3676,9 +3796,9 @@ void Simulator::DecodeTypeRegisterSPECIAL() {
}
break;
case MOVCI: {
- uint32_t cc = get_instr()->FBccValue();
+ uint32_t cc = instr_.FBccValue();
uint32_t fcsr_cc = get_fcsr_condition_bit(cc);
- if (get_instr()->Bit(16)) { // Read Tf bit.
+ 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());
@@ -3695,14 +3815,14 @@ void Simulator::DecodeTypeRegisterSPECIAL() {
UNREACHABLE();
}
if (do_interrupt) {
- SoftwareInterrupt(get_instr());
+ SoftwareInterrupt();
}
}
void Simulator::DecodeTypeRegisterSPECIAL2() {
int32_t alu_out;
- switch (get_instr()->FunctionFieldRaw()) {
+ switch (instr_.FunctionFieldRaw()) {
case MUL:
// Only the lower 32 bits are kept.
alu_out = rs_u() * rt_u();
@@ -3725,7 +3845,7 @@ void Simulator::DecodeTypeRegisterSPECIAL2() {
void Simulator::DecodeTypeRegisterSPECIAL3() {
int32_t alu_out;
- switch (get_instr()->FunctionFieldRaw()) {
+ switch (instr_.FunctionFieldRaw()) {
case INS: { // Mips32r2 instruction.
// Interpret rd field as 5-bit msb of insert.
uint16_t msb = rd_reg();
@@ -3750,7 +3870,7 @@ void Simulator::DecodeTypeRegisterSPECIAL3() {
break;
}
case BSHFL: {
- int sa = get_instr()->SaFieldRaw() >> kSaShift;
+ int sa = instr_.SaFieldRaw() >> kSaShift;
switch (sa) {
case BITSWAP: {
uint32_t input = static_cast<uint32_t>(rt());
@@ -3822,7 +3942,7 @@ void Simulator::DecodeTypeRegisterSPECIAL3() {
break;
}
default: {
- const uint8_t bp = get_instr()->Bp2Value();
+ const uint8_t bp = instr_.Bp2Value();
sa >>= kBp2Bits;
switch (sa) {
case ALIGN: {
@@ -3850,16 +3970,9 @@ void Simulator::DecodeTypeRegisterSPECIAL3() {
}
}
-
-void Simulator::DecodeTypeRegister(Instruction* instr) {
- const Opcode op = instr->OpcodeFieldRaw();
-
- // Set up the variables if needed before executing the instruction.
- // ConfigureTypeRegister(instr);
- set_instr(instr);
-
+void Simulator::DecodeTypeRegister() {
// ---------- Execution.
- switch (op) {
+ switch (instr_.OpcodeFieldRaw()) {
case COP1:
DecodeTypeRegisterCOP1();
break;
@@ -3882,17 +3995,17 @@ void Simulator::DecodeTypeRegister(Instruction* instr) {
// Type 2: instructions using a 16, 21 or 26 bits immediate. (e.g. beq, beqc).
-void Simulator::DecodeTypeImmediate(Instruction* instr) {
+void Simulator::DecodeTypeImmediate() {
// Instruction fields.
- Opcode op = instr->OpcodeFieldRaw();
- int32_t rs_reg = instr->RsValue();
- int32_t rs = get_register(instr->RsValue());
+ 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_reg = instr_.RtValue(); // Destination register.
int32_t rt = get_register(rt_reg);
- int16_t imm16 = instr->Imm16Value();
+ int16_t imm16 = instr_.Imm16Value();
- int32_t ft_reg = instr->FtValue(); // Destination register.
+ int32_t ft_reg = instr_.FtValue(); // Destination register.
// Zero extended immediate.
uint32_t oe_imm16 = 0xffff & imm16;
@@ -3912,38 +4025,36 @@ void Simulator::DecodeTypeImmediate(Instruction* instr) {
int32_t addr = 0x0;
// 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 BranchAndLinkHelper =
+ [this, &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 = this->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,
+ auto BranchHelper = [this, &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();
+ int16_t imm16 = this->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) {
+ auto BranchAndLinkCompactHelper = [this, &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);
+ int32_t imm = this->instr_.ImmValue(bits);
imm <<= 32 - bits;
imm >>= 32 - bits;
next_pc = current_pc + (imm << 2) + Instruction::kInstrSize;
@@ -3951,28 +4062,27 @@ void Simulator::DecodeTypeImmediate(Instruction* instr) {
}
};
- auto BranchCompactHelper = [&next_pc, this, instr](bool do_branch, int bits) {
+ auto BranchCompactHelper = [this, &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);
+ int32_t imm = this->instr_.ImmValue(bits);
imm <<= 32 - bits;
imm >>= 32 - bits;
next_pc = get_pc() + (imm << 2) + Instruction::kInstrSize;
}
};
-
switch (op) {
// ------------- COP1. Coprocessor instructions.
case COP1:
- switch (instr->RsFieldRaw()) {
+ switch (instr_.RsFieldRaw()) {
case BC1: { // Branch on coprocessor condition.
// Floating point.
- uint32_t cc = instr->FBccValue();
+ 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;
+ bool do_branch = (instr_.FBtrueValue()) ? cc_value : !cc_value;
BranchHelper(do_branch);
break;
}
@@ -3988,7 +4098,7 @@ void Simulator::DecodeTypeImmediate(Instruction* instr) {
break;
// ------------- REGIMM class.
case REGIMM:
- switch (instr->RtFieldRaw()) {
+ switch (instr_.RtFieldRaw()) {
case BLTZ:
BranchHelper(rs < 0);
break;
@@ -4196,7 +4306,7 @@ void Simulator::DecodeTypeImmediate(Instruction* instr) {
set_register(rt_reg, ReadB(rs + se_imm16));
break;
case LH:
- set_register(rt_reg, ReadH(rs + se_imm16, instr));
+ set_register(rt_reg, ReadH(rs + se_imm16, instr_.instr()));
break;
case LWL: {
// al_offset is offset of the effective address within an aligned word.
@@ -4204,20 +4314,20 @@ void Simulator::DecodeTypeImmediate(Instruction* instr) {
uint8_t byte_shift = kPointerAlignmentMask - al_offset;
uint32_t mask = (1 << byte_shift * 8) - 1;
addr = rs + se_imm16 - al_offset;
- alu_out = ReadW(addr, instr);
+ alu_out = ReadW(addr, instr_.instr());
alu_out <<= byte_shift * 8;
alu_out |= rt & mask;
set_register(rt_reg, alu_out);
break;
}
case LW:
- set_register(rt_reg, ReadW(rs + se_imm16, instr));
+ set_register(rt_reg, ReadW(rs + se_imm16, instr_.instr()));
break;
case LBU:
set_register(rt_reg, ReadBU(rs + se_imm16));
break;
case LHU:
- set_register(rt_reg, ReadHU(rs + se_imm16, instr));
+ set_register(rt_reg, ReadHU(rs + se_imm16, instr_.instr()));
break;
case LWR: {
// al_offset is offset of the effective address within an aligned word.
@@ -4225,7 +4335,7 @@ void Simulator::DecodeTypeImmediate(Instruction* instr) {
uint8_t byte_shift = kPointerAlignmentMask - al_offset;
uint32_t mask = al_offset ? (~0 << (byte_shift + 1) * 8) : 0;
addr = rs + se_imm16 - al_offset;
- alu_out = ReadW(addr, instr);
+ alu_out = ReadW(addr, instr_.instr());
alu_out = static_cast<uint32_t> (alu_out) >> al_offset * 8;
alu_out |= rt & mask;
set_register(rt_reg, alu_out);
@@ -4235,7 +4345,7 @@ void Simulator::DecodeTypeImmediate(Instruction* instr) {
WriteB(rs + se_imm16, static_cast<int8_t>(rt));
break;
case SH:
- WriteH(rs + se_imm16, static_cast<uint16_t>(rt), instr);
+ WriteH(rs + se_imm16, static_cast<uint16_t>(rt), instr_.instr());
break;
case SWL: {
uint8_t al_offset = (rs + se_imm16) & kPointerAlignmentMask;
@@ -4243,40 +4353,40 @@ void Simulator::DecodeTypeImmediate(Instruction* instr) {
uint32_t mask = byte_shift ? (~0 << (al_offset + 1) * 8) : 0;
addr = rs + se_imm16 - al_offset;
// Value to be written in memory.
- uint32_t mem_value = ReadW(addr, instr) & mask;
+ uint32_t mem_value = ReadW(addr, instr_.instr()) & mask;
mem_value |= static_cast<uint32_t>(rt) >> byte_shift * 8;
- WriteW(addr, mem_value, instr);
+ WriteW(addr, mem_value, instr_.instr());
break;
}
case SW:
- WriteW(rs + se_imm16, rt, instr);
+ WriteW(rs + se_imm16, rt, instr_.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;
- uint32_t mem_value = ReadW(addr, instr);
+ uint32_t mem_value = ReadW(addr, instr_.instr());
mem_value = (rt << al_offset * 8) | (mem_value & mask);
- WriteW(addr, mem_value, instr);
+ WriteW(addr, mem_value, instr_.instr());
break;
}
case LWC1:
set_fpu_register_hi_word(ft_reg, 0);
- set_fpu_register_word(ft_reg, ReadW(rs + se_imm16, instr));
+ set_fpu_register_word(ft_reg, ReadW(rs + se_imm16, instr_.instr()));
break;
case LDC1:
- set_fpu_register_double(ft_reg, ReadD(rs + se_imm16, instr));
+ set_fpu_register_double(ft_reg, ReadD(rs + se_imm16, instr_.instr()));
break;
case SWC1:
- WriteW(rs + se_imm16, get_fpu_register_word(ft_reg), instr);
+ WriteW(rs + se_imm16, get_fpu_register_word(ft_reg), instr_.instr());
break;
case SDC1:
- WriteD(rs + se_imm16, get_fpu_register_double(ft_reg), instr);
+ WriteD(rs + se_imm16, get_fpu_register_double(ft_reg), instr_.instr());
break;
// ------------- PC-Relative instructions.
case PCREL: {
// rt field: checking 5-bits.
- int32_t imm21 = instr->Imm21Value();
+ int32_t imm21 = instr_.Imm21Value();
int32_t current_pc = get_pc();
uint8_t rt = (imm21 >> kImm16Bits);
switch (rt) {
@@ -4288,7 +4398,7 @@ void Simulator::DecodeTypeImmediate(Instruction* instr) {
alu_out = current_pc + (se_imm16 << 16);
break;
default: {
- int32_t imm19 = instr->Imm19Value();
+ int32_t imm19 = instr_.Imm19Value();
// rt field: checking the most significant 2-bits.
rt = (imm21 >> kImm19Bits);
switch (rt) {
@@ -4336,13 +4446,15 @@ void Simulator::DecodeTypeImmediate(Instruction* instr) {
// Type 3: instructions using a 26 bytes immediate. (e.g. j, jal).
-void Simulator::DecodeTypeJump(Instruction* instr) {
+void Simulator::DecodeTypeJump() {
+ SimInstruction simInstr = instr_;
// Get current pc.
int32_t current_pc = get_pc();
// Get unchanged bits of pc.
int32_t pc_high_bits = current_pc & 0xf0000000;
// Next pc.
- int32_t next_pc = pc_high_bits | (instr->Imm26Value() << 2);
+
+ int32_t next_pc = pc_high_bits | (simInstr.Imm26Value() << 2);
// Execute branch delay slot.
// We don't check for end_sim_pc. First it should not be met as the current pc
@@ -4353,7 +4465,7 @@ void Simulator::DecodeTypeJump(Instruction* instr) {
// Update pc and ra if necessary.
// Do this after the branch delay execution.
- if (instr->IsLinkingInstruction()) {
+ if (simInstr.IsLinkingInstruction()) {
set_register(31, current_pc + 2 * Instruction::kInstrSize);
}
set_pc(next_pc);
@@ -4375,15 +4487,16 @@ void Simulator::InstructionDecode(Instruction* instr) {
dasm.InstructionDecode(buffer, reinterpret_cast<byte*>(instr));
}
- switch (instr->InstructionType(Instruction::TypeChecks::EXTRA)) {
+ instr_ = instr;
+ switch (instr_.InstructionType()) {
case Instruction::kRegisterType:
- DecodeTypeRegister(instr);
+ DecodeTypeRegister();
break;
case Instruction::kImmediateType:
- DecodeTypeImmediate(instr);
+ DecodeTypeImmediate();
break;
case Instruction::kJumpType:
- DecodeTypeJump(instr);
+ DecodeTypeJump();
break;
default:
UNSUPPORTED();