| OLD | NEW |
| 1 // Copyright 2010 the V8 project authors. All rights reserved. | 1 // Copyright 2010 the V8 project authors. All rights reserved. |
| 2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
| 3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
| 4 // met: | 4 // met: |
| 5 // | 5 // |
| 6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
| 7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
| 8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
| 9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
| 10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
| (...skipping 22 matching lines...) Expand all Loading... |
| 33 #if defined(V8_TARGET_ARCH_ARM) | 33 #if defined(V8_TARGET_ARCH_ARM) |
| 34 | 34 |
| 35 #include "disasm.h" | 35 #include "disasm.h" |
| 36 #include "assembler.h" | 36 #include "assembler.h" |
| 37 #include "arm/constants-arm.h" | 37 #include "arm/constants-arm.h" |
| 38 #include "arm/simulator-arm.h" | 38 #include "arm/simulator-arm.h" |
| 39 | 39 |
| 40 #if defined(USE_SIMULATOR) | 40 #if defined(USE_SIMULATOR) |
| 41 | 41 |
| 42 // Only build the simulator if not compiling for real ARM hardware. | 42 // Only build the simulator if not compiling for real ARM hardware. |
| 43 namespace assembler { | 43 namespace v8 { |
| 44 namespace arm { | 44 namespace internal { |
| 45 | |
| 46 using ::v8::internal::Object; | |
| 47 using ::v8::internal::PrintF; | |
| 48 using ::v8::internal::OS; | |
| 49 using ::v8::internal::ReadLine; | |
| 50 using ::v8::internal::DeleteArray; | |
| 51 | 45 |
| 52 // This macro provides a platform independent use of sscanf. The reason for | 46 // This macro provides a platform independent use of sscanf. The reason for |
| 53 // SScanF not being implemented in a platform independent way through | 47 // SScanF not being implemented in a platform independent way through |
| 54 // ::v8::internal::OS in the same way as SNPrintF is that the | 48 // ::v8::internal::OS in the same way as SNPrintF is that the |
| 55 // Windows C Run-Time Library does not provide vsscanf. | 49 // Windows C Run-Time Library does not provide vsscanf. |
| 56 #define SScanF sscanf // NOLINT | 50 #define SScanF sscanf // NOLINT |
| 57 | 51 |
| 58 // The Debugger class is used by the simulator while debugging simulated ARM | 52 // The Debugger class is used by the simulator while debugging simulated ARM |
| 59 // code. | 53 // code. |
| 60 class Debugger { | 54 class Debugger { |
| 61 public: | 55 public: |
| 62 explicit Debugger(Simulator* sim); | 56 explicit Debugger(Simulator* sim); |
| 63 ~Debugger(); | 57 ~Debugger(); |
| 64 | 58 |
| 65 void Stop(Instr* instr); | 59 void Stop(Instruction* instr); |
| 66 void Debug(); | 60 void Debug(); |
| 67 | 61 |
| 68 private: | 62 private: |
| 69 static const instr_t kBreakpointInstr = | 63 static const Instr kBreakpointInstr = |
| 70 ((AL << 28) | (7 << 25) | (1 << 24) | break_point); | 64 (al | (7*B25) | (1*B24) | kBreakpoint); |
| 71 static const instr_t kNopInstr = | 65 static const Instr kNopInstr = (al | (13*B21)); |
| 72 ((AL << 28) | (13 << 21)); | |
| 73 | 66 |
| 74 Simulator* sim_; | 67 Simulator* sim_; |
| 75 | 68 |
| 76 int32_t GetRegisterValue(int regnum); | 69 int32_t GetRegisterValue(int regnum); |
| 77 double GetVFPDoubleRegisterValue(int regnum); | 70 double GetVFPDoubleRegisterValue(int regnum); |
| 78 bool GetValue(const char* desc, int32_t* value); | 71 bool GetValue(const char* desc, int32_t* value); |
| 79 bool GetVFPSingleValue(const char* desc, float* value); | 72 bool GetVFPSingleValue(const char* desc, float* value); |
| 80 bool GetVFPDoubleValue(const char* desc, double* value); | 73 bool GetVFPDoubleValue(const char* desc, double* value); |
| 81 | 74 |
| 82 // Set or delete a breakpoint. Returns true if successful. | 75 // Set or delete a breakpoint. Returns true if successful. |
| 83 bool SetBreakpoint(Instr* breakpc); | 76 bool SetBreakpoint(Instruction* breakpc); |
| 84 bool DeleteBreakpoint(Instr* breakpc); | 77 bool DeleteBreakpoint(Instruction* breakpc); |
| 85 | 78 |
| 86 // Undo and redo all breakpoints. This is needed to bracket disassembly and | 79 // Undo and redo all breakpoints. This is needed to bracket disassembly and |
| 87 // execution to skip past breakpoints when run from the debugger. | 80 // execution to skip past breakpoints when run from the debugger. |
| 88 void UndoBreakpoints(); | 81 void UndoBreakpoints(); |
| 89 void RedoBreakpoints(); | 82 void RedoBreakpoints(); |
| 90 }; | 83 }; |
| 91 | 84 |
| 92 | 85 |
| 93 Debugger::Debugger(Simulator* sim) { | 86 Debugger::Debugger(Simulator* sim) { |
| 94 sim_ = sim; | 87 sim_ = sim; |
| (...skipping 10 matching lines...) Expand all Loading... |
| 105 | 98 |
| 106 | 99 |
| 107 static void InitializeCoverage() { | 100 static void InitializeCoverage() { |
| 108 char* file_name = getenv("V8_GENERATED_CODE_COVERAGE_LOG"); | 101 char* file_name = getenv("V8_GENERATED_CODE_COVERAGE_LOG"); |
| 109 if (file_name != NULL) { | 102 if (file_name != NULL) { |
| 110 coverage_log = fopen(file_name, "aw+"); | 103 coverage_log = fopen(file_name, "aw+"); |
| 111 } | 104 } |
| 112 } | 105 } |
| 113 | 106 |
| 114 | 107 |
| 115 void Debugger::Stop(Instr* instr) { | 108 void Debugger::Stop(Instruction* instr) { |
| 116 // Get the stop code. | 109 // Get the stop code. |
| 117 uint32_t code = instr->SvcField() & kStopCodeMask; | 110 uint32_t code = instr->SvcValue() & kStopCodeMask; |
| 118 // Retrieve the encoded address, which comes just after this stop. | 111 // Retrieve the encoded address, which comes just after this stop. |
| 119 char** msg_address = | 112 char** msg_address = |
| 120 reinterpret_cast<char**>(sim_->get_pc() + Instr::kInstrSize); | 113 reinterpret_cast<char**>(sim_->get_pc() + Instruction::kInstrSize); |
| 121 char* msg = *msg_address; | 114 char* msg = *msg_address; |
| 122 ASSERT(msg != NULL); | 115 ASSERT(msg != NULL); |
| 123 | 116 |
| 124 // Update this stop description. | 117 // Update this stop description. |
| 125 if (isWatchedStop(code) && !watched_stops[code].desc) { | 118 if (isWatchedStop(code) && !watched_stops[code].desc) { |
| 126 watched_stops[code].desc = msg; | 119 watched_stops[code].desc = msg; |
| 127 } | 120 } |
| 128 | 121 |
| 129 if (strlen(msg) > 0) { | 122 if (strlen(msg) > 0) { |
| 130 if (coverage_log != NULL) { | 123 if (coverage_log != NULL) { |
| 131 fprintf(coverage_log, "%s\n", msg); | 124 fprintf(coverage_log, "%s\n", msg); |
| 132 fflush(coverage_log); | 125 fflush(coverage_log); |
| 133 } | 126 } |
| 134 // Overwrite the instruction and address with nops. | 127 // Overwrite the instruction and address with nops. |
| 135 instr->SetInstructionBits(kNopInstr); | 128 instr->SetInstructionBits(kNopInstr); |
| 136 reinterpret_cast<Instr*>(msg_address)->SetInstructionBits(kNopInstr); | 129 reinterpret_cast<Instruction*>(msg_address)->SetInstructionBits(kNopInstr); |
| 137 } | 130 } |
| 138 sim_->set_pc(sim_->get_pc() + 2 * Instr::kInstrSize); | 131 sim_->set_pc(sim_->get_pc() + 2 * Instruction::kInstrSize); |
| 139 } | 132 } |
| 140 | 133 |
| 141 #else // ndef GENERATED_CODE_COVERAGE | 134 #else // ndef GENERATED_CODE_COVERAGE |
| 142 | 135 |
| 143 static void InitializeCoverage() { | 136 static void InitializeCoverage() { |
| 144 } | 137 } |
| 145 | 138 |
| 146 | 139 |
| 147 void Debugger::Stop(Instr* instr) { | 140 void Debugger::Stop(Instruction* instr) { |
| 148 // Get the stop code. | 141 // Get the stop code. |
| 149 uint32_t code = instr->SvcField() & kStopCodeMask; | 142 uint32_t code = instr->SvcValue() & kStopCodeMask; |
| 150 // Retrieve the encoded address, which comes just after this stop. | 143 // Retrieve the encoded address, which comes just after this stop. |
| 151 char* msg = *reinterpret_cast<char**>(sim_->get_pc() + Instr::kInstrSize); | 144 char* msg = *reinterpret_cast<char**>(sim_->get_pc() |
| 145 + Instruction::kInstrSize); |
| 152 // Update this stop description. | 146 // Update this stop description. |
| 153 if (sim_->isWatchedStop(code) && !sim_->watched_stops[code].desc) { | 147 if (sim_->isWatchedStop(code) && !sim_->watched_stops[code].desc) { |
| 154 sim_->watched_stops[code].desc = msg; | 148 sim_->watched_stops[code].desc = msg; |
| 155 } | 149 } |
| 156 PrintF("Simulator hit %s\n", msg); | 150 // Print the stop message and code if it is not the default code. |
| 157 sim_->set_pc(sim_->get_pc() + 2 * Instr::kInstrSize); | 151 if (code != kMaxStopCode) { |
| 152 PrintF("Simulator hit stop %u: %s\n", code, msg); |
| 153 } else { |
| 154 PrintF("Simulator hit %s\n", msg); |
| 155 } |
| 156 sim_->set_pc(sim_->get_pc() + 2 * Instruction::kInstrSize); |
| 158 Debug(); | 157 Debug(); |
| 159 } | 158 } |
| 160 #endif | 159 #endif |
| 161 | 160 |
| 162 | 161 |
| 163 int32_t Debugger::GetRegisterValue(int regnum) { | 162 int32_t Debugger::GetRegisterValue(int regnum) { |
| 164 if (regnum == kPCRegister) { | 163 if (regnum == kPCRegister) { |
| 165 return sim_->get_pc(); | 164 return sim_->get_pc(); |
| 166 } else { | 165 } else { |
| 167 return sim_->get_register(regnum); | 166 return sim_->get_register(regnum); |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 205 bool is_double; | 204 bool is_double; |
| 206 int regnum = VFPRegisters::Number(desc, &is_double); | 205 int regnum = VFPRegisters::Number(desc, &is_double); |
| 207 if (regnum != kNoRegister && is_double) { | 206 if (regnum != kNoRegister && is_double) { |
| 208 *value = sim_->get_double_from_d_register(regnum); | 207 *value = sim_->get_double_from_d_register(regnum); |
| 209 return true; | 208 return true; |
| 210 } | 209 } |
| 211 return false; | 210 return false; |
| 212 } | 211 } |
| 213 | 212 |
| 214 | 213 |
| 215 bool Debugger::SetBreakpoint(Instr* breakpc) { | 214 bool Debugger::SetBreakpoint(Instruction* breakpc) { |
| 216 // Check if a breakpoint can be set. If not return without any side-effects. | 215 // Check if a breakpoint can be set. If not return without any side-effects. |
| 217 if (sim_->break_pc_ != NULL) { | 216 if (sim_->break_pc_ != NULL) { |
| 218 return false; | 217 return false; |
| 219 } | 218 } |
| 220 | 219 |
| 221 // Set the breakpoint. | 220 // Set the breakpoint. |
| 222 sim_->break_pc_ = breakpc; | 221 sim_->break_pc_ = breakpc; |
| 223 sim_->break_instr_ = breakpc->InstructionBits(); | 222 sim_->break_instr_ = breakpc->InstructionBits(); |
| 224 // Not setting the breakpoint instruction in the code itself. It will be set | 223 // Not setting the breakpoint instruction in the code itself. It will be set |
| 225 // when the debugger shell continues. | 224 // when the debugger shell continues. |
| 226 return true; | 225 return true; |
| 227 } | 226 } |
| 228 | 227 |
| 229 | 228 |
| 230 bool Debugger::DeleteBreakpoint(Instr* breakpc) { | 229 bool Debugger::DeleteBreakpoint(Instruction* breakpc) { |
| 231 if (sim_->break_pc_ != NULL) { | 230 if (sim_->break_pc_ != NULL) { |
| 232 sim_->break_pc_->SetInstructionBits(sim_->break_instr_); | 231 sim_->break_pc_->SetInstructionBits(sim_->break_instr_); |
| 233 } | 232 } |
| 234 | 233 |
| 235 sim_->break_pc_ = NULL; | 234 sim_->break_pc_ = NULL; |
| 236 sim_->break_instr_ = 0; | 235 sim_->break_instr_ = 0; |
| 237 return true; | 236 return true; |
| 238 } | 237 } |
| 239 | 238 |
| 240 | 239 |
| (...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 292 break; | 291 break; |
| 293 } else { | 292 } else { |
| 294 // Use sscanf to parse the individual parts of the command line. At the | 293 // Use sscanf to parse the individual parts of the command line. At the |
| 295 // moment no command expects more than two parameters. | 294 // moment no command expects more than two parameters. |
| 296 int argc = SScanF(line, | 295 int argc = SScanF(line, |
| 297 "%" XSTR(COMMAND_SIZE) "s " | 296 "%" XSTR(COMMAND_SIZE) "s " |
| 298 "%" XSTR(ARG_SIZE) "s " | 297 "%" XSTR(ARG_SIZE) "s " |
| 299 "%" XSTR(ARG_SIZE) "s", | 298 "%" XSTR(ARG_SIZE) "s", |
| 300 cmd, arg1, arg2); | 299 cmd, arg1, arg2); |
| 301 if ((strcmp(cmd, "si") == 0) || (strcmp(cmd, "stepi") == 0)) { | 300 if ((strcmp(cmd, "si") == 0) || (strcmp(cmd, "stepi") == 0)) { |
| 302 sim_->InstructionDecode(reinterpret_cast<Instr*>(sim_->get_pc())); | 301 sim_->InstructionDecode(reinterpret_cast<Instruction*>(sim_->get_pc())); |
| 303 } else if ((strcmp(cmd, "c") == 0) || (strcmp(cmd, "cont") == 0)) { | 302 } else if ((strcmp(cmd, "c") == 0) || (strcmp(cmd, "cont") == 0)) { |
| 304 // Execute the one instruction we broke at with breakpoints disabled. | 303 // Execute the one instruction we broke at with breakpoints disabled. |
| 305 sim_->InstructionDecode(reinterpret_cast<Instr*>(sim_->get_pc())); | 304 sim_->InstructionDecode(reinterpret_cast<Instruction*>(sim_->get_pc())); |
| 306 // Leave the debugger shell. | 305 // Leave the debugger shell. |
| 307 done = true; | 306 done = true; |
| 308 } else if ((strcmp(cmd, "p") == 0) || (strcmp(cmd, "print") == 0)) { | 307 } else if ((strcmp(cmd, "p") == 0) || (strcmp(cmd, "print") == 0)) { |
| 309 if (argc == 2) { | 308 if (argc == 2) { |
| 310 int32_t value; | 309 int32_t value; |
| 311 float svalue; | 310 float svalue; |
| 312 double dvalue; | 311 double dvalue; |
| 313 if (strcmp(arg1, "all") == 0) { | 312 if (strcmp(arg1, "all") == 0) { |
| 314 for (int i = 0; i < kNumRegisters; i++) { | 313 for (int i = 0; i < kNumRegisters; i++) { |
| 315 value = GetRegisterValue(i); | 314 value = GetRegisterValue(i); |
| (...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 390 disasm::Disassembler dasm(converter); | 389 disasm::Disassembler dasm(converter); |
| 391 // use a reasonably large buffer | 390 // use a reasonably large buffer |
| 392 v8::internal::EmbeddedVector<char, 256> buffer; | 391 v8::internal::EmbeddedVector<char, 256> buffer; |
| 393 | 392 |
| 394 byte* prev = NULL; | 393 byte* prev = NULL; |
| 395 byte* cur = NULL; | 394 byte* cur = NULL; |
| 396 byte* end = NULL; | 395 byte* end = NULL; |
| 397 | 396 |
| 398 if (argc == 1) { | 397 if (argc == 1) { |
| 399 cur = reinterpret_cast<byte*>(sim_->get_pc()); | 398 cur = reinterpret_cast<byte*>(sim_->get_pc()); |
| 400 end = cur + (10 * Instr::kInstrSize); | 399 end = cur + (10 * Instruction::kInstrSize); |
| 401 } else if (argc == 2) { | 400 } else if (argc == 2) { |
| 402 int32_t value; | 401 int32_t value; |
| 403 if (GetValue(arg1, &value)) { | 402 if (GetValue(arg1, &value)) { |
| 404 cur = reinterpret_cast<byte*>(sim_->get_pc()); | 403 cur = reinterpret_cast<byte*>(sim_->get_pc()); |
| 405 // Disassemble <arg1> instructions. | 404 // Disassemble <arg1> instructions. |
| 406 end = cur + (value * Instr::kInstrSize); | 405 end = cur + (value * Instruction::kInstrSize); |
| 407 } | 406 } |
| 408 } else { | 407 } else { |
| 409 int32_t value1; | 408 int32_t value1; |
| 410 int32_t value2; | 409 int32_t value2; |
| 411 if (GetValue(arg1, &value1) && GetValue(arg2, &value2)) { | 410 if (GetValue(arg1, &value1) && GetValue(arg2, &value2)) { |
| 412 cur = reinterpret_cast<byte*>(value1); | 411 cur = reinterpret_cast<byte*>(value1); |
| 413 end = cur + (value2 * Instr::kInstrSize); | 412 end = cur + (value2 * Instruction::kInstrSize); |
| 414 } | 413 } |
| 415 } | 414 } |
| 416 | 415 |
| 417 while (cur < end) { | 416 while (cur < end) { |
| 418 prev = cur; | 417 prev = cur; |
| 419 cur += dasm.InstructionDecode(buffer, cur); | 418 cur += dasm.InstructionDecode(buffer, cur); |
| 420 PrintF(" 0x%08x %s\n", | 419 PrintF(" 0x%08x %s\n", |
| 421 reinterpret_cast<intptr_t>(prev), buffer.start()); | 420 reinterpret_cast<intptr_t>(prev), buffer.start()); |
| 422 } | 421 } |
| 423 } else if (strcmp(cmd, "gdb") == 0) { | 422 } else if (strcmp(cmd, "gdb") == 0) { |
| 424 PrintF("relinquishing control to gdb\n"); | 423 PrintF("relinquishing control to gdb\n"); |
| 425 v8::internal::OS::DebugBreak(); | 424 v8::internal::OS::DebugBreak(); |
| 426 PrintF("regaining control from gdb\n"); | 425 PrintF("regaining control from gdb\n"); |
| 427 } else if (strcmp(cmd, "break") == 0) { | 426 } else if (strcmp(cmd, "break") == 0) { |
| 428 if (argc == 2) { | 427 if (argc == 2) { |
| 429 int32_t value; | 428 int32_t value; |
| 430 if (GetValue(arg1, &value)) { | 429 if (GetValue(arg1, &value)) { |
| 431 if (!SetBreakpoint(reinterpret_cast<Instr*>(value))) { | 430 if (!SetBreakpoint(reinterpret_cast<Instruction*>(value))) { |
| 432 PrintF("setting breakpoint failed\n"); | 431 PrintF("setting breakpoint failed\n"); |
| 433 } | 432 } |
| 434 } else { | 433 } else { |
| 435 PrintF("%s unrecognized\n", arg1); | 434 PrintF("%s unrecognized\n", arg1); |
| 436 } | 435 } |
| 437 } else { | 436 } else { |
| 438 PrintF("break <address>\n"); | 437 PrintF("break <address>\n"); |
| 439 } | 438 } |
| 440 } else if (strcmp(cmd, "del") == 0) { | 439 } else if (strcmp(cmd, "del") == 0) { |
| 441 if (!DeleteBreakpoint(NULL)) { | 440 if (!DeleteBreakpoint(NULL)) { |
| 442 PrintF("deleting breakpoint failed\n"); | 441 PrintF("deleting breakpoint failed\n"); |
| 443 } | 442 } |
| 444 } else if (strcmp(cmd, "flags") == 0) { | 443 } else if (strcmp(cmd, "flags") == 0) { |
| 445 PrintF("N flag: %d; ", sim_->n_flag_); | 444 PrintF("N flag: %d; ", sim_->n_flag_); |
| 446 PrintF("Z flag: %d; ", sim_->z_flag_); | 445 PrintF("Z flag: %d; ", sim_->z_flag_); |
| 447 PrintF("C flag: %d; ", sim_->c_flag_); | 446 PrintF("C flag: %d; ", sim_->c_flag_); |
| 448 PrintF("V flag: %d\n", sim_->v_flag_); | 447 PrintF("V flag: %d\n", sim_->v_flag_); |
| 449 PrintF("INVALID OP flag: %d; ", sim_->inv_op_vfp_flag_); | 448 PrintF("INVALID OP flag: %d; ", sim_->inv_op_vfp_flag_); |
| 450 PrintF("DIV BY ZERO flag: %d; ", sim_->div_zero_vfp_flag_); | 449 PrintF("DIV BY ZERO flag: %d; ", sim_->div_zero_vfp_flag_); |
| 451 PrintF("OVERFLOW flag: %d; ", sim_->overflow_vfp_flag_); | 450 PrintF("OVERFLOW flag: %d; ", sim_->overflow_vfp_flag_); |
| 452 PrintF("UNDERFLOW flag: %d; ", sim_->underflow_vfp_flag_); | 451 PrintF("UNDERFLOW flag: %d; ", sim_->underflow_vfp_flag_); |
| 453 PrintF("INEXACT flag: %d; ", sim_->inexact_vfp_flag_); | 452 PrintF("INEXACT flag: %d;\n", sim_->inexact_vfp_flag_); |
| 454 } else if (strcmp(cmd, "stop") == 0) { | 453 } else if (strcmp(cmd, "stop") == 0) { |
| 455 int32_t value; | 454 int32_t value; |
| 456 intptr_t stop_pc = sim_->get_pc() - 2 * Instr::kInstrSize; | 455 intptr_t stop_pc = sim_->get_pc() - 2 * Instruction::kInstrSize; |
| 457 Instr* stop_instr = reinterpret_cast<Instr*>(stop_pc); | 456 Instruction* stop_instr = reinterpret_cast<Instruction*>(stop_pc); |
| 458 Instr* msg_address = | 457 Instruction* msg_address = |
| 459 reinterpret_cast<Instr*>(stop_pc + Instr::kInstrSize); | 458 reinterpret_cast<Instruction*>(stop_pc + Instruction::kInstrSize); |
| 460 if ((argc == 2) && (strcmp(arg1, "unstop") == 0)) { | 459 if ((argc == 2) && (strcmp(arg1, "unstop") == 0)) { |
| 461 // Remove the current stop. | 460 // Remove the current stop. |
| 462 if (sim_->isStopInstruction(stop_instr)) { | 461 if (sim_->isStopInstruction(stop_instr)) { |
| 463 stop_instr->SetInstructionBits(kNopInstr); | 462 stop_instr->SetInstructionBits(kNopInstr); |
| 464 msg_address->SetInstructionBits(kNopInstr); | 463 msg_address->SetInstructionBits(kNopInstr); |
| 465 } else { | 464 } else { |
| 466 PrintF("Not at debugger stop.\n"); | 465 PrintF("Not at debugger stop.\n"); |
| 467 } | 466 } |
| 468 } else if (argc == 3) { | 467 } else if (argc == 3) { |
| 469 // Print information about all/the specified breakpoint(s). | 468 // Print information about all/the specified breakpoint(s). |
| (...skipping 164 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 634 ASSERT((start & CachePage::kLineMask) == 0); | 633 ASSERT((start & CachePage::kLineMask) == 0); |
| 635 ASSERT((size & CachePage::kLineMask) == 0); | 634 ASSERT((size & CachePage::kLineMask) == 0); |
| 636 void* page = reinterpret_cast<void*>(start & (~CachePage::kPageMask)); | 635 void* page = reinterpret_cast<void*>(start & (~CachePage::kPageMask)); |
| 637 int offset = (start & CachePage::kPageMask); | 636 int offset = (start & CachePage::kPageMask); |
| 638 CachePage* cache_page = GetCachePage(page); | 637 CachePage* cache_page = GetCachePage(page); |
| 639 char* valid_bytemap = cache_page->ValidityByte(offset); | 638 char* valid_bytemap = cache_page->ValidityByte(offset); |
| 640 memset(valid_bytemap, CachePage::LINE_INVALID, size >> CachePage::kLineShift); | 639 memset(valid_bytemap, CachePage::LINE_INVALID, size >> CachePage::kLineShift); |
| 641 } | 640 } |
| 642 | 641 |
| 643 | 642 |
| 644 void Simulator::CheckICache(Instr* instr) { | 643 void Simulator::CheckICache(Instruction* instr) { |
| 645 intptr_t address = reinterpret_cast<intptr_t>(instr); | 644 intptr_t address = reinterpret_cast<intptr_t>(instr); |
| 646 void* page = reinterpret_cast<void*>(address & (~CachePage::kPageMask)); | 645 void* page = reinterpret_cast<void*>(address & (~CachePage::kPageMask)); |
| 647 void* line = reinterpret_cast<void*>(address & (~CachePage::kLineMask)); | 646 void* line = reinterpret_cast<void*>(address & (~CachePage::kLineMask)); |
| 648 int offset = (address & CachePage::kPageMask); | 647 int offset = (address & CachePage::kPageMask); |
| 649 CachePage* cache_page = GetCachePage(page); | 648 CachePage* cache_page = GetCachePage(page); |
| 650 char* cache_valid_byte = cache_page->ValidityByte(offset); | 649 char* cache_valid_byte = cache_page->ValidityByte(offset); |
| 651 bool cache_hit = (*cache_valid_byte == CachePage::LINE_VALID); | 650 bool cache_hit = (*cache_valid_byte == CachePage::LINE_VALID); |
| 652 char* cached_line = cache_page->CachedData(offset & ~CachePage::kLineMask); | 651 char* cached_line = cache_page->CachedData(offset & ~CachePage::kLineMask); |
| 653 if (cache_hit) { | 652 if (cache_hit) { |
| 654 // Check that the data in memory matches the contents of the I-cache. | 653 // Check that the data in memory matches the contents of the I-cache. |
| 655 CHECK(memcmp(reinterpret_cast<void*>(instr), | 654 CHECK(memcmp(reinterpret_cast<void*>(instr), |
| 656 cache_page->CachedData(offset), | 655 cache_page->CachedData(offset), |
| 657 Instr::kInstrSize) == 0); | 656 Instruction::kInstrSize) == 0); |
| 658 } else { | 657 } else { |
| 659 // Cache miss. Load memory into the cache. | 658 // Cache miss. Load memory into the cache. |
| 660 memcpy(cached_line, line, CachePage::kLineLength); | 659 memcpy(cached_line, line, CachePage::kLineLength); |
| 661 *cache_valid_byte = CachePage::LINE_VALID; | 660 *cache_valid_byte = CachePage::LINE_VALID; |
| 662 } | 661 } |
| 663 } | 662 } |
| 664 | 663 |
| 665 | 664 |
| 666 // Create one simulator per thread and keep it in thread local storage. | 665 // Create one simulator per thread and keep it in thread local storage. |
| 667 static v8::internal::Thread::LocalStorageKey simulator_key; | 666 static v8::internal::Thread::LocalStorageKey simulator_key; |
| (...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 738 | 737 |
| 739 // When the generated code calls an external reference we need to catch that in | 738 // When the generated code calls an external reference we need to catch that in |
| 740 // the simulator. The external reference will be a function compiled for the | 739 // the simulator. The external reference will be a function compiled for the |
| 741 // host architecture. We need to call that function instead of trying to | 740 // host architecture. We need to call that function instead of trying to |
| 742 // execute it with the simulator. We do that by redirecting the external | 741 // execute it with the simulator. We do that by redirecting the external |
| 743 // reference to a svc (Supervisor Call) instruction that is handled by | 742 // reference to a svc (Supervisor Call) instruction that is handled by |
| 744 // the simulator. We write the original destination of the jump just at a known | 743 // the simulator. We write the original destination of the jump just at a known |
| 745 // offset from the svc instruction so the simulator knows what to call. | 744 // offset from the svc instruction so the simulator knows what to call. |
| 746 class Redirection { | 745 class Redirection { |
| 747 public: | 746 public: |
| 748 Redirection(void* external_function, bool fp_return) | 747 Redirection(void* external_function, ExternalReference::Type type) |
| 749 : external_function_(external_function), | 748 : external_function_(external_function), |
| 750 swi_instruction_((AL << 28) | (0xf << 24) | call_rt_redirected), | 749 swi_instruction_(al | (0xf*B24) | kCallRtRedirected), |
| 751 fp_return_(fp_return), | 750 type_(type), |
| 752 next_(list_) { | 751 next_(list_) { |
| 753 Simulator::current()-> | 752 Simulator::current()-> |
| 754 FlushICache(reinterpret_cast<void*>(&swi_instruction_), | 753 FlushICache(reinterpret_cast<void*>(&swi_instruction_), |
| 755 Instr::kInstrSize); | 754 Instruction::kInstrSize); |
| 756 list_ = this; | 755 list_ = this; |
| 757 } | 756 } |
| 758 | 757 |
| 759 void* address_of_swi_instruction() { | 758 void* address_of_swi_instruction() { |
| 760 return reinterpret_cast<void*>(&swi_instruction_); | 759 return reinterpret_cast<void*>(&swi_instruction_); |
| 761 } | 760 } |
| 762 | 761 |
| 763 void* external_function() { return external_function_; } | 762 void* external_function() { return external_function_; } |
| 764 bool fp_return() { return fp_return_; } | 763 ExternalReference::Type type() { return type_; } |
| 765 | 764 |
| 766 static Redirection* Get(void* external_function, bool fp_return) { | 765 static Redirection* Get(void* external_function, |
| 766 ExternalReference::Type type) { |
| 767 Redirection* current; | 767 Redirection* current; |
| 768 for (current = list_; current != NULL; current = current->next_) { | 768 for (current = list_; current != NULL; current = current->next_) { |
| 769 if (current->external_function_ == external_function) return current; | 769 if (current->external_function_ == external_function) return current; |
| 770 } | 770 } |
| 771 return new Redirection(external_function, fp_return); | 771 return new Redirection(external_function, type); |
| 772 } | 772 } |
| 773 | 773 |
| 774 static Redirection* FromSwiInstruction(Instr* swi_instruction) { | 774 static Redirection* FromSwiInstruction(Instruction* swi_instruction) { |
| 775 char* addr_of_swi = reinterpret_cast<char*>(swi_instruction); | 775 char* addr_of_swi = reinterpret_cast<char*>(swi_instruction); |
| 776 char* addr_of_redirection = | 776 char* addr_of_redirection = |
| 777 addr_of_swi - OFFSET_OF(Redirection, swi_instruction_); | 777 addr_of_swi - OFFSET_OF(Redirection, swi_instruction_); |
| 778 return reinterpret_cast<Redirection*>(addr_of_redirection); | 778 return reinterpret_cast<Redirection*>(addr_of_redirection); |
| 779 } | 779 } |
| 780 | 780 |
| 781 private: | 781 private: |
| 782 void* external_function_; | 782 void* external_function_; |
| 783 uint32_t swi_instruction_; | 783 uint32_t swi_instruction_; |
| 784 bool fp_return_; | 784 ExternalReference::Type type_; |
| 785 Redirection* next_; | 785 Redirection* next_; |
| 786 static Redirection* list_; | 786 static Redirection* list_; |
| 787 }; | 787 }; |
| 788 | 788 |
| 789 | 789 |
| 790 Redirection* Redirection::list_ = NULL; | 790 Redirection* Redirection::list_ = NULL; |
| 791 | 791 |
| 792 | 792 |
| 793 void* Simulator::RedirectExternalReference(void* external_function, | 793 void* Simulator::RedirectExternalReference(void* external_function, |
| 794 bool fp_return) { | 794 ExternalReference::Type type) { |
| 795 Redirection* redirection = Redirection::Get(external_function, fp_return); | 795 Redirection* redirection = Redirection::Get(external_function, type); |
| 796 return redirection->address_of_swi_instruction(); | 796 return redirection->address_of_swi_instruction(); |
| 797 } | 797 } |
| 798 | 798 |
| 799 | 799 |
| 800 // Get the active Simulator for the current thread. | 800 // Get the active Simulator for the current thread. |
| 801 Simulator* Simulator::current() { | 801 Simulator* Simulator::current() { |
| 802 Initialize(); | 802 Initialize(); |
| 803 Simulator* sim = reinterpret_cast<Simulator*>( | 803 Simulator* sim = reinterpret_cast<Simulator*>( |
| 804 v8::internal::Thread::GetThreadLocal(simulator_key)); | 804 v8::internal::Thread::GetThreadLocal(simulator_key)); |
| 805 if (sim == NULL) { | 805 if (sim == NULL) { |
| (...skipping 17 matching lines...) Expand all Loading... |
| 823 | 823 |
| 824 | 824 |
| 825 // Get the register from the architecture state. This function does handle | 825 // Get the register from the architecture state. This function does handle |
| 826 // the special case of accessing the PC register. | 826 // the special case of accessing the PC register. |
| 827 int32_t Simulator::get_register(int reg) const { | 827 int32_t Simulator::get_register(int reg) const { |
| 828 ASSERT((reg >= 0) && (reg < num_registers)); | 828 ASSERT((reg >= 0) && (reg < num_registers)); |
| 829 // Stupid code added to avoid bug in GCC. | 829 // Stupid code added to avoid bug in GCC. |
| 830 // See: http://gcc.gnu.org/bugzilla/show_bug.cgi?id=43949 | 830 // See: http://gcc.gnu.org/bugzilla/show_bug.cgi?id=43949 |
| 831 if (reg >= num_registers) return 0; | 831 if (reg >= num_registers) return 0; |
| 832 // End stupid code. | 832 // End stupid code. |
| 833 return registers_[reg] + ((reg == pc) ? Instr::kPCReadOffset : 0); | 833 return registers_[reg] + ((reg == pc) ? Instruction::kPCReadOffset : 0); |
| 834 } | 834 } |
| 835 | 835 |
| 836 | 836 |
| 837 void Simulator::set_dw_register(int dreg, const int* dbl) { | 837 void Simulator::set_dw_register(int dreg, const int* dbl) { |
| 838 ASSERT((dreg >= 0) && (dreg < num_d_registers)); | 838 ASSERT((dreg >= 0) && (dreg < num_d_registers)); |
| 839 registers_[dreg] = dbl[0]; | 839 registers_[dreg] = dbl[0]; |
| 840 registers_[dreg + 1] = dbl[1]; | 840 registers_[dreg + 1] = dbl[1]; |
| 841 } | 841 } |
| 842 | 842 |
| 843 | 843 |
| (...skipping 145 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 989 // that don't support unaligned access. | 989 // that don't support unaligned access. |
| 990 // Some ARM platforms raise an interrupt on detecting unaligned access. | 990 // Some ARM platforms raise an interrupt on detecting unaligned access. |
| 991 // On others it does a funky rotation thing. For now we | 991 // On others it does a funky rotation thing. For now we |
| 992 // simply disallow unaligned reads. Note that simulator runs have the runtime | 992 // simply disallow unaligned reads. Note that simulator runs have the runtime |
| 993 // system running directly on the host system and only generated code is | 993 // system running directly on the host system and only generated code is |
| 994 // executed in the simulator. Since the host is typically IA32 we will not | 994 // executed in the simulator. Since the host is typically IA32 we will not |
| 995 // get the correct ARM-like behaviour on unaligned accesses for those ARM | 995 // get the correct ARM-like behaviour on unaligned accesses for those ARM |
| 996 // targets that don't support unaligned loads and stores. | 996 // targets that don't support unaligned loads and stores. |
| 997 | 997 |
| 998 | 998 |
| 999 int Simulator::ReadW(int32_t addr, Instr* instr) { | 999 int Simulator::ReadW(int32_t addr, Instruction* instr) { |
| 1000 #if V8_TARGET_CAN_READ_UNALIGNED | 1000 #if V8_TARGET_CAN_READ_UNALIGNED |
| 1001 intptr_t* ptr = reinterpret_cast<intptr_t*>(addr); | 1001 intptr_t* ptr = reinterpret_cast<intptr_t*>(addr); |
| 1002 return *ptr; | 1002 return *ptr; |
| 1003 #else | 1003 #else |
| 1004 if ((addr & 3) == 0) { | 1004 if ((addr & 3) == 0) { |
| 1005 intptr_t* ptr = reinterpret_cast<intptr_t*>(addr); | 1005 intptr_t* ptr = reinterpret_cast<intptr_t*>(addr); |
| 1006 return *ptr; | 1006 return *ptr; |
| 1007 } | 1007 } |
| 1008 PrintF("Unaligned read at 0x%08x, pc=%p\n", addr, instr); | 1008 PrintF("Unaligned read at 0x%08x, pc=%p\n", addr, instr); |
| 1009 UNIMPLEMENTED(); | 1009 UNIMPLEMENTED(); |
| 1010 return 0; | 1010 return 0; |
| 1011 #endif | 1011 #endif |
| 1012 } | 1012 } |
| 1013 | 1013 |
| 1014 | 1014 |
| 1015 void Simulator::WriteW(int32_t addr, int value, Instr* instr) { | 1015 void Simulator::WriteW(int32_t addr, int value, Instruction* instr) { |
| 1016 #if V8_TARGET_CAN_READ_UNALIGNED | 1016 #if V8_TARGET_CAN_READ_UNALIGNED |
| 1017 intptr_t* ptr = reinterpret_cast<intptr_t*>(addr); | 1017 intptr_t* ptr = reinterpret_cast<intptr_t*>(addr); |
| 1018 *ptr = value; | 1018 *ptr = value; |
| 1019 return; | 1019 return; |
| 1020 #else | 1020 #else |
| 1021 if ((addr & 3) == 0) { | 1021 if ((addr & 3) == 0) { |
| 1022 intptr_t* ptr = reinterpret_cast<intptr_t*>(addr); | 1022 intptr_t* ptr = reinterpret_cast<intptr_t*>(addr); |
| 1023 *ptr = value; | 1023 *ptr = value; |
| 1024 return; | 1024 return; |
| 1025 } | 1025 } |
| 1026 PrintF("Unaligned write at 0x%08x, pc=%p\n", addr, instr); | 1026 PrintF("Unaligned write at 0x%08x, pc=%p\n", addr, instr); |
| 1027 UNIMPLEMENTED(); | 1027 UNIMPLEMENTED(); |
| 1028 #endif | 1028 #endif |
| 1029 } | 1029 } |
| 1030 | 1030 |
| 1031 | 1031 |
| 1032 uint16_t Simulator::ReadHU(int32_t addr, Instr* instr) { | 1032 uint16_t Simulator::ReadHU(int32_t addr, Instruction* instr) { |
| 1033 #if V8_TARGET_CAN_READ_UNALIGNED | 1033 #if V8_TARGET_CAN_READ_UNALIGNED |
| 1034 uint16_t* ptr = reinterpret_cast<uint16_t*>(addr); | 1034 uint16_t* ptr = reinterpret_cast<uint16_t*>(addr); |
| 1035 return *ptr; | 1035 return *ptr; |
| 1036 #else | 1036 #else |
| 1037 if ((addr & 1) == 0) { | 1037 if ((addr & 1) == 0) { |
| 1038 uint16_t* ptr = reinterpret_cast<uint16_t*>(addr); | 1038 uint16_t* ptr = reinterpret_cast<uint16_t*>(addr); |
| 1039 return *ptr; | 1039 return *ptr; |
| 1040 } | 1040 } |
| 1041 PrintF("Unaligned unsigned halfword read at 0x%08x, pc=%p\n", addr, instr); | 1041 PrintF("Unaligned unsigned halfword read at 0x%08x, pc=%p\n", addr, instr); |
| 1042 UNIMPLEMENTED(); | 1042 UNIMPLEMENTED(); |
| 1043 return 0; | 1043 return 0; |
| 1044 #endif | 1044 #endif |
| 1045 } | 1045 } |
| 1046 | 1046 |
| 1047 | 1047 |
| 1048 int16_t Simulator::ReadH(int32_t addr, Instr* instr) { | 1048 int16_t Simulator::ReadH(int32_t addr, Instruction* instr) { |
| 1049 #if V8_TARGET_CAN_READ_UNALIGNED | 1049 #if V8_TARGET_CAN_READ_UNALIGNED |
| 1050 int16_t* ptr = reinterpret_cast<int16_t*>(addr); | 1050 int16_t* ptr = reinterpret_cast<int16_t*>(addr); |
| 1051 return *ptr; | 1051 return *ptr; |
| 1052 #else | 1052 #else |
| 1053 if ((addr & 1) == 0) { | 1053 if ((addr & 1) == 0) { |
| 1054 int16_t* ptr = reinterpret_cast<int16_t*>(addr); | 1054 int16_t* ptr = reinterpret_cast<int16_t*>(addr); |
| 1055 return *ptr; | 1055 return *ptr; |
| 1056 } | 1056 } |
| 1057 PrintF("Unaligned signed halfword read at 0x%08x\n", addr); | 1057 PrintF("Unaligned signed halfword read at 0x%08x\n", addr); |
| 1058 UNIMPLEMENTED(); | 1058 UNIMPLEMENTED(); |
| 1059 return 0; | 1059 return 0; |
| 1060 #endif | 1060 #endif |
| 1061 } | 1061 } |
| 1062 | 1062 |
| 1063 | 1063 |
| 1064 void Simulator::WriteH(int32_t addr, uint16_t value, Instr* instr) { | 1064 void Simulator::WriteH(int32_t addr, uint16_t value, Instruction* instr) { |
| 1065 #if V8_TARGET_CAN_READ_UNALIGNED | 1065 #if V8_TARGET_CAN_READ_UNALIGNED |
| 1066 uint16_t* ptr = reinterpret_cast<uint16_t*>(addr); | 1066 uint16_t* ptr = reinterpret_cast<uint16_t*>(addr); |
| 1067 *ptr = value; | 1067 *ptr = value; |
| 1068 return; | 1068 return; |
| 1069 #else | 1069 #else |
| 1070 if ((addr & 1) == 0) { | 1070 if ((addr & 1) == 0) { |
| 1071 uint16_t* ptr = reinterpret_cast<uint16_t*>(addr); | 1071 uint16_t* ptr = reinterpret_cast<uint16_t*>(addr); |
| 1072 *ptr = value; | 1072 *ptr = value; |
| 1073 return; | 1073 return; |
| 1074 } | 1074 } |
| 1075 PrintF("Unaligned unsigned halfword write at 0x%08x, pc=%p\n", addr, instr); | 1075 PrintF("Unaligned unsigned halfword write at 0x%08x, pc=%p\n", addr, instr); |
| 1076 UNIMPLEMENTED(); | 1076 UNIMPLEMENTED(); |
| 1077 #endif | 1077 #endif |
| 1078 } | 1078 } |
| 1079 | 1079 |
| 1080 | 1080 |
| 1081 void Simulator::WriteH(int32_t addr, int16_t value, Instr* instr) { | 1081 void Simulator::WriteH(int32_t addr, int16_t value, Instruction* instr) { |
| 1082 #if V8_TARGET_CAN_READ_UNALIGNED | 1082 #if V8_TARGET_CAN_READ_UNALIGNED |
| 1083 int16_t* ptr = reinterpret_cast<int16_t*>(addr); | 1083 int16_t* ptr = reinterpret_cast<int16_t*>(addr); |
| 1084 *ptr = value; | 1084 *ptr = value; |
| 1085 return; | 1085 return; |
| 1086 #else | 1086 #else |
| 1087 if ((addr & 1) == 0) { | 1087 if ((addr & 1) == 0) { |
| 1088 int16_t* ptr = reinterpret_cast<int16_t*>(addr); | 1088 int16_t* ptr = reinterpret_cast<int16_t*>(addr); |
| 1089 *ptr = value; | 1089 *ptr = value; |
| 1090 return; | 1090 return; |
| 1091 } | 1091 } |
| (...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1156 | 1156 |
| 1157 // Returns the limit of the stack area to enable checking for stack overflows. | 1157 // Returns the limit of the stack area to enable checking for stack overflows. |
| 1158 uintptr_t Simulator::StackLimit() const { | 1158 uintptr_t Simulator::StackLimit() const { |
| 1159 // Leave a safety margin of 256 bytes to prevent overrunning the stack when | 1159 // Leave a safety margin of 256 bytes to prevent overrunning the stack when |
| 1160 // pushing values. | 1160 // pushing values. |
| 1161 return reinterpret_cast<uintptr_t>(stack_) + 256; | 1161 return reinterpret_cast<uintptr_t>(stack_) + 256; |
| 1162 } | 1162 } |
| 1163 | 1163 |
| 1164 | 1164 |
| 1165 // Unsupported instructions use Format to print an error and stop execution. | 1165 // Unsupported instructions use Format to print an error and stop execution. |
| 1166 void Simulator::Format(Instr* instr, const char* format) { | 1166 void Simulator::Format(Instruction* instr, const char* format) { |
| 1167 PrintF("Simulator found unsupported instruction:\n 0x%08x: %s\n", | 1167 PrintF("Simulator found unsupported instruction:\n 0x%08x: %s\n", |
| 1168 reinterpret_cast<intptr_t>(instr), format); | 1168 reinterpret_cast<intptr_t>(instr), format); |
| 1169 UNIMPLEMENTED(); | 1169 UNIMPLEMENTED(); |
| 1170 } | 1170 } |
| 1171 | 1171 |
| 1172 | 1172 |
| 1173 // Checks if the current instruction should be executed based on its | 1173 // Checks if the current instruction should be executed based on its |
| 1174 // condition bits. | 1174 // condition bits. |
| 1175 bool Simulator::ConditionallyExecute(Instr* instr) { | 1175 bool Simulator::ConditionallyExecute(Instruction* instr) { |
| 1176 switch (instr->ConditionField()) { | 1176 switch (instr->ConditionField()) { |
| 1177 case EQ: return z_flag_; | 1177 case eq: return z_flag_; |
| 1178 case NE: return !z_flag_; | 1178 case ne: return !z_flag_; |
| 1179 case CS: return c_flag_; | 1179 case cs: return c_flag_; |
| 1180 case CC: return !c_flag_; | 1180 case cc: return !c_flag_; |
| 1181 case MI: return n_flag_; | 1181 case mi: return n_flag_; |
| 1182 case PL: return !n_flag_; | 1182 case pl: return !n_flag_; |
| 1183 case VS: return v_flag_; | 1183 case vs: return v_flag_; |
| 1184 case VC: return !v_flag_; | 1184 case vc: return !v_flag_; |
| 1185 case HI: return c_flag_ && !z_flag_; | 1185 case hi: return c_flag_ && !z_flag_; |
| 1186 case LS: return !c_flag_ || z_flag_; | 1186 case ls: return !c_flag_ || z_flag_; |
| 1187 case GE: return n_flag_ == v_flag_; | 1187 case ge: return n_flag_ == v_flag_; |
| 1188 case LT: return n_flag_ != v_flag_; | 1188 case lt: return n_flag_ != v_flag_; |
| 1189 case GT: return !z_flag_ && (n_flag_ == v_flag_); | 1189 case gt: return !z_flag_ && (n_flag_ == v_flag_); |
| 1190 case LE: return z_flag_ || (n_flag_ != v_flag_); | 1190 case le: return z_flag_ || (n_flag_ != v_flag_); |
| 1191 case AL: return true; | 1191 case al: return true; |
| 1192 default: UNREACHABLE(); | 1192 default: UNREACHABLE(); |
| 1193 } | 1193 } |
| 1194 return false; | 1194 return false; |
| 1195 } | 1195 } |
| 1196 | 1196 |
| 1197 | 1197 |
| 1198 // Calculate and set the Negative and Zero flags. | 1198 // Calculate and set the Negative and Zero flags. |
| 1199 void Simulator::SetNZFlags(int32_t val) { | 1199 void Simulator::SetNZFlags(int32_t val) { |
| 1200 n_flag_ = (val < 0); | 1200 n_flag_ = (val < 0); |
| 1201 z_flag_ = (val == 0); | 1201 z_flag_ = (val == 0); |
| (...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1283 void Simulator::Copy_FPSCR_to_APSR() { | 1283 void Simulator::Copy_FPSCR_to_APSR() { |
| 1284 n_flag_ = n_flag_FPSCR_; | 1284 n_flag_ = n_flag_FPSCR_; |
| 1285 z_flag_ = z_flag_FPSCR_; | 1285 z_flag_ = z_flag_FPSCR_; |
| 1286 c_flag_ = c_flag_FPSCR_; | 1286 c_flag_ = c_flag_FPSCR_; |
| 1287 v_flag_ = v_flag_FPSCR_; | 1287 v_flag_ = v_flag_FPSCR_; |
| 1288 } | 1288 } |
| 1289 | 1289 |
| 1290 | 1290 |
| 1291 // Addressing Mode 1 - Data-processing operands: | 1291 // Addressing Mode 1 - Data-processing operands: |
| 1292 // Get the value based on the shifter_operand with register. | 1292 // Get the value based on the shifter_operand with register. |
| 1293 int32_t Simulator::GetShiftRm(Instr* instr, bool* carry_out) { | 1293 int32_t Simulator::GetShiftRm(Instruction* instr, bool* carry_out) { |
| 1294 Shift shift = instr->ShiftField(); | 1294 ShiftOp shift = instr->ShiftField(); |
| 1295 int shift_amount = instr->ShiftAmountField(); | 1295 int shift_amount = instr->ShiftAmountValue(); |
| 1296 int32_t result = get_register(instr->RmField()); | 1296 int32_t result = get_register(instr->RmValue()); |
| 1297 if (instr->Bit(4) == 0) { | 1297 if (instr->Bit(4) == 0) { |
| 1298 // by immediate | 1298 // by immediate |
| 1299 if ((shift == ROR) && (shift_amount == 0)) { | 1299 if ((shift == ROR) && (shift_amount == 0)) { |
| 1300 UNIMPLEMENTED(); | 1300 UNIMPLEMENTED(); |
| 1301 return result; | 1301 return result; |
| 1302 } else if (((shift == LSR) || (shift == ASR)) && (shift_amount == 0)) { | 1302 } else if (((shift == LSR) || (shift == ASR)) && (shift_amount == 0)) { |
| 1303 shift_amount = 32; | 1303 shift_amount = 32; |
| 1304 } | 1304 } |
| 1305 switch (shift) { | 1305 switch (shift) { |
| 1306 case ASR: { | 1306 case ASR: { |
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1350 break; | 1350 break; |
| 1351 } | 1351 } |
| 1352 | 1352 |
| 1353 default: { | 1353 default: { |
| 1354 UNREACHABLE(); | 1354 UNREACHABLE(); |
| 1355 break; | 1355 break; |
| 1356 } | 1356 } |
| 1357 } | 1357 } |
| 1358 } else { | 1358 } else { |
| 1359 // by register | 1359 // by register |
| 1360 int rs = instr->RsField(); | 1360 int rs = instr->RsValue(); |
| 1361 shift_amount = get_register(rs) &0xff; | 1361 shift_amount = get_register(rs) &0xff; |
| 1362 switch (shift) { | 1362 switch (shift) { |
| 1363 case ASR: { | 1363 case ASR: { |
| 1364 if (shift_amount == 0) { | 1364 if (shift_amount == 0) { |
| 1365 *carry_out = c_flag_; | 1365 *carry_out = c_flag_; |
| 1366 } else if (shift_amount < 32) { | 1366 } else if (shift_amount < 32) { |
| 1367 result >>= (shift_amount - 1); | 1367 result >>= (shift_amount - 1); |
| 1368 *carry_out = (result & 1) == 1; | 1368 *carry_out = (result & 1) == 1; |
| 1369 result >>= 1; | 1369 result >>= 1; |
| 1370 } else { | 1370 } else { |
| (...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1427 break; | 1427 break; |
| 1428 } | 1428 } |
| 1429 } | 1429 } |
| 1430 } | 1430 } |
| 1431 return result; | 1431 return result; |
| 1432 } | 1432 } |
| 1433 | 1433 |
| 1434 | 1434 |
| 1435 // Addressing Mode 1 - Data-processing operands: | 1435 // Addressing Mode 1 - Data-processing operands: |
| 1436 // Get the value based on the shifter_operand with immediate. | 1436 // Get the value based on the shifter_operand with immediate. |
| 1437 int32_t Simulator::GetImm(Instr* instr, bool* carry_out) { | 1437 int32_t Simulator::GetImm(Instruction* instr, bool* carry_out) { |
| 1438 int rotate = instr->RotateField() * 2; | 1438 int rotate = instr->RotateValue() * 2; |
| 1439 int immed8 = instr->Immed8Field(); | 1439 int immed8 = instr->Immed8Value(); |
| 1440 int imm = (immed8 >> rotate) | (immed8 << (32 - rotate)); | 1440 int imm = (immed8 >> rotate) | (immed8 << (32 - rotate)); |
| 1441 *carry_out = (rotate == 0) ? c_flag_ : (imm < 0); | 1441 *carry_out = (rotate == 0) ? c_flag_ : (imm < 0); |
| 1442 return imm; | 1442 return imm; |
| 1443 } | 1443 } |
| 1444 | 1444 |
| 1445 | 1445 |
| 1446 static int count_bits(int bit_vector) { | 1446 static int count_bits(int bit_vector) { |
| 1447 int count = 0; | 1447 int count = 0; |
| 1448 while (bit_vector != 0) { | 1448 while (bit_vector != 0) { |
| 1449 if ((bit_vector & 1) != 0) { | 1449 if ((bit_vector & 1) != 0) { |
| 1450 count++; | 1450 count++; |
| 1451 } | 1451 } |
| 1452 bit_vector >>= 1; | 1452 bit_vector >>= 1; |
| 1453 } | 1453 } |
| 1454 return count; | 1454 return count; |
| 1455 } | 1455 } |
| 1456 | 1456 |
| 1457 | 1457 |
| 1458 // Addressing Mode 4 - Load and Store Multiple | 1458 // Addressing Mode 4 - Load and Store Multiple |
| 1459 void Simulator::HandleRList(Instr* instr, bool load) { | 1459 void Simulator::HandleRList(Instruction* instr, bool load) { |
| 1460 int rn = instr->RnField(); | 1460 int rn = instr->RnValue(); |
| 1461 int32_t rn_val = get_register(rn); | 1461 int32_t rn_val = get_register(rn); |
| 1462 int rlist = instr->RlistField(); | 1462 int rlist = instr->RlistValue(); |
| 1463 int num_regs = count_bits(rlist); | 1463 int num_regs = count_bits(rlist); |
| 1464 | 1464 |
| 1465 intptr_t start_address = 0; | 1465 intptr_t start_address = 0; |
| 1466 intptr_t end_address = 0; | 1466 intptr_t end_address = 0; |
| 1467 switch (instr->PUField()) { | 1467 switch (instr->PUField()) { |
| 1468 case 0: { | 1468 case da_x: { |
| 1469 // Print("da"); | |
| 1470 UNIMPLEMENTED(); | 1469 UNIMPLEMENTED(); |
| 1471 break; | 1470 break; |
| 1472 } | 1471 } |
| 1473 case 1: { | 1472 case ia_x: { |
| 1474 // Print("ia"); | |
| 1475 start_address = rn_val; | 1473 start_address = rn_val; |
| 1476 end_address = rn_val + (num_regs * 4) - 4; | 1474 end_address = rn_val + (num_regs * 4) - 4; |
| 1477 rn_val = rn_val + (num_regs * 4); | 1475 rn_val = rn_val + (num_regs * 4); |
| 1478 break; | 1476 break; |
| 1479 } | 1477 } |
| 1480 case 2: { | 1478 case db_x: { |
| 1481 // Print("db"); | |
| 1482 start_address = rn_val - (num_regs * 4); | 1479 start_address = rn_val - (num_regs * 4); |
| 1483 end_address = rn_val - 4; | 1480 end_address = rn_val - 4; |
| 1484 rn_val = start_address; | 1481 rn_val = start_address; |
| 1485 break; | 1482 break; |
| 1486 } | 1483 } |
| 1487 case 3: { | 1484 case ib_x: { |
| 1488 // Print("ib"); | |
| 1489 start_address = rn_val + 4; | 1485 start_address = rn_val + 4; |
| 1490 end_address = rn_val + (num_regs * 4); | 1486 end_address = rn_val + (num_regs * 4); |
| 1491 rn_val = end_address; | 1487 rn_val = end_address; |
| 1492 break; | 1488 break; |
| 1493 } | 1489 } |
| 1494 default: { | 1490 default: { |
| 1495 UNREACHABLE(); | 1491 UNREACHABLE(); |
| 1496 break; | 1492 break; |
| 1497 } | 1493 } |
| 1498 } | 1494 } |
| (...skipping 27 matching lines...) Expand all Loading... |
| 1526 typedef int64_t (*SimulatorRuntimeCall)(int32_t arg0, | 1522 typedef int64_t (*SimulatorRuntimeCall)(int32_t arg0, |
| 1527 int32_t arg1, | 1523 int32_t arg1, |
| 1528 int32_t arg2, | 1524 int32_t arg2, |
| 1529 int32_t arg3, | 1525 int32_t arg3, |
| 1530 int32_t arg4); | 1526 int32_t arg4); |
| 1531 typedef double (*SimulatorRuntimeFPCall)(int32_t arg0, | 1527 typedef double (*SimulatorRuntimeFPCall)(int32_t arg0, |
| 1532 int32_t arg1, | 1528 int32_t arg1, |
| 1533 int32_t arg2, | 1529 int32_t arg2, |
| 1534 int32_t arg3); | 1530 int32_t arg3); |
| 1535 | 1531 |
| 1532 // This signature supports direct call in to API function native callback |
| 1533 // (refer to InvocationCallback in v8.h). |
| 1534 typedef v8::Handle<v8::Value> (*SimulatorRuntimeApiCall)(int32_t arg0); |
| 1536 | 1535 |
| 1537 // Software interrupt instructions are used by the simulator to call into the | 1536 // Software interrupt instructions are used by the simulator to call into the |
| 1538 // C-based V8 runtime. | 1537 // C-based V8 runtime. |
| 1539 void Simulator::SoftwareInterrupt(Instr* instr) { | 1538 void Simulator::SoftwareInterrupt(Instruction* instr) { |
| 1540 int svc = instr->SvcField(); | 1539 int svc = instr->SvcValue(); |
| 1541 switch (svc) { | 1540 switch (svc) { |
| 1542 case call_rt_redirected: { | 1541 case kCallRtRedirected: { |
| 1543 // Check if stack is aligned. Error if not aligned is reported below to | 1542 // Check if stack is aligned. Error if not aligned is reported below to |
| 1544 // include information on the function called. | 1543 // include information on the function called. |
| 1545 bool stack_aligned = | 1544 bool stack_aligned = |
| 1546 (get_register(sp) | 1545 (get_register(sp) |
| 1547 & (::v8::internal::FLAG_sim_stack_alignment - 1)) == 0; | 1546 & (::v8::internal::FLAG_sim_stack_alignment - 1)) == 0; |
| 1548 Redirection* redirection = Redirection::FromSwiInstruction(instr); | 1547 Redirection* redirection = Redirection::FromSwiInstruction(instr); |
| 1549 int32_t arg0 = get_register(r0); | 1548 int32_t arg0 = get_register(r0); |
| 1550 int32_t arg1 = get_register(r1); | 1549 int32_t arg1 = get_register(r1); |
| 1551 int32_t arg2 = get_register(r2); | 1550 int32_t arg2 = get_register(r2); |
| 1552 int32_t arg3 = get_register(r3); | 1551 int32_t arg3 = get_register(r3); |
| 1553 int32_t* stack_pointer = reinterpret_cast<int32_t*>(get_register(sp)); | 1552 int32_t* stack_pointer = reinterpret_cast<int32_t*>(get_register(sp)); |
| 1554 int32_t arg4 = *stack_pointer; | 1553 int32_t arg4 = *stack_pointer; |
| 1555 // This is dodgy but it works because the C entry stubs are never moved. | 1554 // This is dodgy but it works because the C entry stubs are never moved. |
| 1556 // See comment in codegen-arm.cc and bug 1242173. | 1555 // See comment in codegen-arm.cc and bug 1242173. |
| 1557 int32_t saved_lr = get_register(lr); | 1556 int32_t saved_lr = get_register(lr); |
| 1558 if (redirection->fp_return()) { | 1557 intptr_t external = |
| 1559 intptr_t external = | 1558 reinterpret_cast<intptr_t>(redirection->external_function()); |
| 1560 reinterpret_cast<intptr_t>(redirection->external_function()); | 1559 if (redirection->type() == ExternalReference::FP_RETURN_CALL) { |
| 1561 SimulatorRuntimeFPCall target = | 1560 SimulatorRuntimeFPCall target = |
| 1562 reinterpret_cast<SimulatorRuntimeFPCall>(external); | 1561 reinterpret_cast<SimulatorRuntimeFPCall>(external); |
| 1563 if (::v8::internal::FLAG_trace_sim || !stack_aligned) { | 1562 if (::v8::internal::FLAG_trace_sim || !stack_aligned) { |
| 1564 double x, y; | 1563 double x, y; |
| 1565 GetFpArgs(&x, &y); | 1564 GetFpArgs(&x, &y); |
| 1566 PrintF("Call to host function at %p with args %f, %f", | 1565 PrintF("Call to host function at %p with args %f, %f", |
| 1567 FUNCTION_ADDR(target), x, y); | 1566 FUNCTION_ADDR(target), x, y); |
| 1568 if (!stack_aligned) { | 1567 if (!stack_aligned) { |
| 1569 PrintF(" with unaligned stack %08x\n", get_register(sp)); | 1568 PrintF(" with unaligned stack %08x\n", get_register(sp)); |
| 1570 } | 1569 } |
| 1571 PrintF("\n"); | 1570 PrintF("\n"); |
| 1572 } | 1571 } |
| 1573 CHECK(stack_aligned); | 1572 CHECK(stack_aligned); |
| 1574 double result = target(arg0, arg1, arg2, arg3); | 1573 double result = target(arg0, arg1, arg2, arg3); |
| 1575 SetFpResult(result); | 1574 SetFpResult(result); |
| 1575 } else if (redirection->type() == ExternalReference::DIRECT_CALL) { |
| 1576 SimulatorRuntimeApiCall target = |
| 1577 reinterpret_cast<SimulatorRuntimeApiCall>(external); |
| 1578 if (::v8::internal::FLAG_trace_sim || !stack_aligned) { |
| 1579 PrintF( |
| 1580 "Call to host function at %p args %08x", |
| 1581 FUNCTION_ADDR(target), |
| 1582 arg0); |
| 1583 if (!stack_aligned) { |
| 1584 PrintF(" with unaligned stack %08x\n", get_register(sp)); |
| 1585 } |
| 1586 PrintF("\n"); |
| 1587 } |
| 1588 CHECK(stack_aligned); |
| 1589 v8::Handle<v8::Value> result = target(arg0); |
| 1590 if (::v8::internal::FLAG_trace_sim) { |
| 1591 PrintF("Returned %p\n", reinterpret_cast<void *>(*result)); |
| 1592 } |
| 1593 set_register(r0, (int32_t) *result); |
| 1576 } else { | 1594 } else { |
| 1577 intptr_t external = | 1595 // builtin call. |
| 1578 reinterpret_cast<int32_t>(redirection->external_function()); | 1596 ASSERT(redirection->type() == ExternalReference::BUILTIN_CALL); |
| 1579 SimulatorRuntimeCall target = | 1597 SimulatorRuntimeCall target = |
| 1580 reinterpret_cast<SimulatorRuntimeCall>(external); | 1598 reinterpret_cast<SimulatorRuntimeCall>(external); |
| 1581 if (::v8::internal::FLAG_trace_sim || !stack_aligned) { | 1599 if (::v8::internal::FLAG_trace_sim || !stack_aligned) { |
| 1582 PrintF( | 1600 PrintF( |
| 1583 "Call to host function at %p args %08x, %08x, %08x, %08x, %0xc", | 1601 "Call to host function at %p args %08x, %08x, %08x, %08x, %0xc", |
| 1584 FUNCTION_ADDR(target), | 1602 FUNCTION_ADDR(target), |
| 1585 arg0, | 1603 arg0, |
| 1586 arg1, | 1604 arg1, |
| 1587 arg2, | 1605 arg2, |
| 1588 arg3, | 1606 arg3, |
| (...skipping 10 matching lines...) Expand all Loading... |
| 1599 if (::v8::internal::FLAG_trace_sim) { | 1617 if (::v8::internal::FLAG_trace_sim) { |
| 1600 PrintF("Returned %08x\n", lo_res); | 1618 PrintF("Returned %08x\n", lo_res); |
| 1601 } | 1619 } |
| 1602 set_register(r0, lo_res); | 1620 set_register(r0, lo_res); |
| 1603 set_register(r1, hi_res); | 1621 set_register(r1, hi_res); |
| 1604 } | 1622 } |
| 1605 set_register(lr, saved_lr); | 1623 set_register(lr, saved_lr); |
| 1606 set_pc(get_register(lr)); | 1624 set_pc(get_register(lr)); |
| 1607 break; | 1625 break; |
| 1608 } | 1626 } |
| 1609 case break_point: { | 1627 case kBreakpoint: { |
| 1610 Debugger dbg(this); | 1628 Debugger dbg(this); |
| 1611 dbg.Debug(); | 1629 dbg.Debug(); |
| 1612 break; | 1630 break; |
| 1613 } | 1631 } |
| 1614 // stop uses all codes greater than 1 << 23. | 1632 // stop uses all codes greater than 1 << 23. |
| 1615 default: { | 1633 default: { |
| 1616 if (svc >= (1 << 23)) { | 1634 if (svc >= (1 << 23)) { |
| 1617 uint32_t code = svc & kStopCodeMask; | 1635 uint32_t code = svc & kStopCodeMask; |
| 1618 if (isWatchedStop(code)) { | 1636 if (isWatchedStop(code)) { |
| 1619 IncreaseStopCounter(code); | 1637 IncreaseStopCounter(code); |
| 1620 } | 1638 } |
| 1621 // Stop if it is enabled, otherwise go on jumping over the stop | 1639 // Stop if it is enabled, otherwise go on jumping over the stop |
| 1622 // and the message address. | 1640 // and the message address. |
| 1623 if (isEnabledStop(code)) { | 1641 if (isEnabledStop(code)) { |
| 1624 Debugger dbg(this); | 1642 Debugger dbg(this); |
| 1625 dbg.Stop(instr); | 1643 dbg.Stop(instr); |
| 1626 } else { | 1644 } else { |
| 1627 set_pc(get_pc() + 2 * Instr::kInstrSize); | 1645 set_pc(get_pc() + 2 * Instruction::kInstrSize); |
| 1628 } | 1646 } |
| 1629 } else { | 1647 } else { |
| 1630 // This is not a valid svc code. | 1648 // This is not a valid svc code. |
| 1631 UNREACHABLE(); | 1649 UNREACHABLE(); |
| 1632 break; | 1650 break; |
| 1633 } | 1651 } |
| 1634 } | 1652 } |
| 1635 } | 1653 } |
| 1636 } | 1654 } |
| 1637 | 1655 |
| 1638 | 1656 |
| 1639 // Stop helper functions. | 1657 // Stop helper functions. |
| 1640 bool Simulator::isStopInstruction(Instr* instr) { | 1658 bool Simulator::isStopInstruction(Instruction* instr) { |
| 1641 return (instr->Bits(27, 24) == 0xF) && (instr->SvcField() >= stop); | 1659 return (instr->Bits(27, 24) == 0xF) && (instr->SvcValue() >= kStopCode); |
| 1642 } | 1660 } |
| 1643 | 1661 |
| 1644 | 1662 |
| 1645 bool Simulator::isWatchedStop(uint32_t code) { | 1663 bool Simulator::isWatchedStop(uint32_t code) { |
| 1646 ASSERT(code <= kMaxStopCode); | 1664 ASSERT(code <= kMaxStopCode); |
| 1647 return code < kNumOfWatchedStops; | 1665 return code < kNumOfWatchedStops; |
| 1648 } | 1666 } |
| 1649 | 1667 |
| 1650 | 1668 |
| 1651 bool Simulator::isEnabledStop(uint32_t code) { | 1669 bool Simulator::isEnabledStop(uint32_t code) { |
| (...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1705 } | 1723 } |
| 1706 } | 1724 } |
| 1707 } | 1725 } |
| 1708 } | 1726 } |
| 1709 | 1727 |
| 1710 | 1728 |
| 1711 // Handle execution based on instruction types. | 1729 // Handle execution based on instruction types. |
| 1712 | 1730 |
| 1713 // Instruction types 0 and 1 are both rolled into one function because they | 1731 // Instruction types 0 and 1 are both rolled into one function because they |
| 1714 // only differ in the handling of the shifter_operand. | 1732 // only differ in the handling of the shifter_operand. |
| 1715 void Simulator::DecodeType01(Instr* instr) { | 1733 void Simulator::DecodeType01(Instruction* instr) { |
| 1716 int type = instr->TypeField(); | 1734 int type = instr->TypeValue(); |
| 1717 if ((type == 0) && instr->IsSpecialType0()) { | 1735 if ((type == 0) && instr->IsSpecialType0()) { |
| 1718 // multiply instruction or extra loads and stores | 1736 // multiply instruction or extra loads and stores |
| 1719 if (instr->Bits(7, 4) == 9) { | 1737 if (instr->Bits(7, 4) == 9) { |
| 1720 if (instr->Bit(24) == 0) { | 1738 if (instr->Bit(24) == 0) { |
| 1721 // Raw field decoding here. Multiply instructions have their Rd in | 1739 // Raw field decoding here. Multiply instructions have their Rd in |
| 1722 // funny places. | 1740 // funny places. |
| 1723 int rn = instr->RnField(); | 1741 int rn = instr->RnValue(); |
| 1724 int rm = instr->RmField(); | 1742 int rm = instr->RmValue(); |
| 1725 int rs = instr->RsField(); | 1743 int rs = instr->RsValue(); |
| 1726 int32_t rs_val = get_register(rs); | 1744 int32_t rs_val = get_register(rs); |
| 1727 int32_t rm_val = get_register(rm); | 1745 int32_t rm_val = get_register(rm); |
| 1728 if (instr->Bit(23) == 0) { | 1746 if (instr->Bit(23) == 0) { |
| 1729 if (instr->Bit(21) == 0) { | 1747 if (instr->Bit(21) == 0) { |
| 1730 // The MUL instruction description (A 4.1.33) refers to Rd as being | 1748 // The MUL instruction description (A 4.1.33) refers to Rd as being |
| 1731 // the destination for the operation, but it confusingly uses the | 1749 // the destination for the operation, but it confusingly uses the |
| 1732 // Rn field to encode it. | 1750 // Rn field to encode it. |
| 1733 // Format(instr, "mul'cond's 'rn, 'rm, 'rs"); | 1751 // Format(instr, "mul'cond's 'rn, 'rm, 'rs"); |
| 1734 int rd = rn; // Remap the rn field to the Rd register. | 1752 int rd = rn; // Remap the rn field to the Rd register. |
| 1735 int32_t alu_out = rm_val * rs_val; | 1753 int32_t alu_out = rm_val * rs_val; |
| (...skipping 13 matching lines...) Expand all Loading... |
| 1749 // when referring to the target registers. They are mapped to the Rn | 1767 // when referring to the target registers. They are mapped to the Rn |
| 1750 // and Rd fields as follows: | 1768 // and Rd fields as follows: |
| 1751 // RdLo == Rd | 1769 // RdLo == Rd |
| 1752 // RdHi == Rn (This is confusingly stored in variable rd here | 1770 // RdHi == Rn (This is confusingly stored in variable rd here |
| 1753 // because the mul instruction from above uses the | 1771 // because the mul instruction from above uses the |
| 1754 // Rn field to encode the Rd register. Good luck figuring | 1772 // Rn field to encode the Rd register. Good luck figuring |
| 1755 // this out without reading the ARM instruction manual | 1773 // this out without reading the ARM instruction manual |
| 1756 // at a very detailed level.) | 1774 // at a very detailed level.) |
| 1757 // Format(instr, "'um'al'cond's 'rd, 'rn, 'rs, 'rm"); | 1775 // Format(instr, "'um'al'cond's 'rd, 'rn, 'rs, 'rm"); |
| 1758 int rd_hi = rn; // Remap the rn field to the RdHi register. | 1776 int rd_hi = rn; // Remap the rn field to the RdHi register. |
| 1759 int rd_lo = instr->RdField(); | 1777 int rd_lo = instr->RdValue(); |
| 1760 int32_t hi_res = 0; | 1778 int32_t hi_res = 0; |
| 1761 int32_t lo_res = 0; | 1779 int32_t lo_res = 0; |
| 1762 if (instr->Bit(22) == 1) { | 1780 if (instr->Bit(22) == 1) { |
| 1763 int64_t left_op = static_cast<int32_t>(rm_val); | 1781 int64_t left_op = static_cast<int32_t>(rm_val); |
| 1764 int64_t right_op = static_cast<int32_t>(rs_val); | 1782 int64_t right_op = static_cast<int32_t>(rs_val); |
| 1765 uint64_t result = left_op * right_op; | 1783 uint64_t result = left_op * right_op; |
| 1766 hi_res = static_cast<int32_t>(result >> 32); | 1784 hi_res = static_cast<int32_t>(result >> 32); |
| 1767 lo_res = static_cast<int32_t>(result & 0xffffffff); | 1785 lo_res = static_cast<int32_t>(result & 0xffffffff); |
| 1768 } else { | 1786 } else { |
| 1769 // unsigned multiply | 1787 // unsigned multiply |
| 1770 uint64_t left_op = static_cast<uint32_t>(rm_val); | 1788 uint64_t left_op = static_cast<uint32_t>(rm_val); |
| 1771 uint64_t right_op = static_cast<uint32_t>(rs_val); | 1789 uint64_t right_op = static_cast<uint32_t>(rs_val); |
| 1772 uint64_t result = left_op * right_op; | 1790 uint64_t result = left_op * right_op; |
| 1773 hi_res = static_cast<int32_t>(result >> 32); | 1791 hi_res = static_cast<int32_t>(result >> 32); |
| 1774 lo_res = static_cast<int32_t>(result & 0xffffffff); | 1792 lo_res = static_cast<int32_t>(result & 0xffffffff); |
| 1775 } | 1793 } |
| 1776 set_register(rd_lo, lo_res); | 1794 set_register(rd_lo, lo_res); |
| 1777 set_register(rd_hi, hi_res); | 1795 set_register(rd_hi, hi_res); |
| 1778 if (instr->HasS()) { | 1796 if (instr->HasS()) { |
| 1779 UNIMPLEMENTED(); | 1797 UNIMPLEMENTED(); |
| 1780 } | 1798 } |
| 1781 } | 1799 } |
| 1782 } else { | 1800 } else { |
| 1783 UNIMPLEMENTED(); // Not used by V8. | 1801 UNIMPLEMENTED(); // Not used by V8. |
| 1784 } | 1802 } |
| 1785 } else { | 1803 } else { |
| 1786 // extra load/store instructions | 1804 // extra load/store instructions |
| 1787 int rd = instr->RdField(); | 1805 int rd = instr->RdValue(); |
| 1788 int rn = instr->RnField(); | 1806 int rn = instr->RnValue(); |
| 1789 int32_t rn_val = get_register(rn); | 1807 int32_t rn_val = get_register(rn); |
| 1790 int32_t addr = 0; | 1808 int32_t addr = 0; |
| 1791 if (instr->Bit(22) == 0) { | 1809 if (instr->Bit(22) == 0) { |
| 1792 int rm = instr->RmField(); | 1810 int rm = instr->RmValue(); |
| 1793 int32_t rm_val = get_register(rm); | 1811 int32_t rm_val = get_register(rm); |
| 1794 switch (instr->PUField()) { | 1812 switch (instr->PUField()) { |
| 1795 case 0: { | 1813 case da_x: { |
| 1796 // Format(instr, "'memop'cond'sign'h 'rd, ['rn], -'rm"); | 1814 // Format(instr, "'memop'cond'sign'h 'rd, ['rn], -'rm"); |
| 1797 ASSERT(!instr->HasW()); | 1815 ASSERT(!instr->HasW()); |
| 1798 addr = rn_val; | 1816 addr = rn_val; |
| 1799 rn_val -= rm_val; | 1817 rn_val -= rm_val; |
| 1800 set_register(rn, rn_val); | 1818 set_register(rn, rn_val); |
| 1801 break; | 1819 break; |
| 1802 } | 1820 } |
| 1803 case 1: { | 1821 case ia_x: { |
| 1804 // Format(instr, "'memop'cond'sign'h 'rd, ['rn], +'rm"); | 1822 // Format(instr, "'memop'cond'sign'h 'rd, ['rn], +'rm"); |
| 1805 ASSERT(!instr->HasW()); | 1823 ASSERT(!instr->HasW()); |
| 1806 addr = rn_val; | 1824 addr = rn_val; |
| 1807 rn_val += rm_val; | 1825 rn_val += rm_val; |
| 1808 set_register(rn, rn_val); | 1826 set_register(rn, rn_val); |
| 1809 break; | 1827 break; |
| 1810 } | 1828 } |
| 1811 case 2: { | 1829 case db_x: { |
| 1812 // Format(instr, "'memop'cond'sign'h 'rd, ['rn, -'rm]'w"); | 1830 // Format(instr, "'memop'cond'sign'h 'rd, ['rn, -'rm]'w"); |
| 1813 rn_val -= rm_val; | 1831 rn_val -= rm_val; |
| 1814 addr = rn_val; | 1832 addr = rn_val; |
| 1815 if (instr->HasW()) { | 1833 if (instr->HasW()) { |
| 1816 set_register(rn, rn_val); | 1834 set_register(rn, rn_val); |
| 1817 } | 1835 } |
| 1818 break; | 1836 break; |
| 1819 } | 1837 } |
| 1820 case 3: { | 1838 case ib_x: { |
| 1821 // Format(instr, "'memop'cond'sign'h 'rd, ['rn, +'rm]'w"); | 1839 // Format(instr, "'memop'cond'sign'h 'rd, ['rn, +'rm]'w"); |
| 1822 rn_val += rm_val; | 1840 rn_val += rm_val; |
| 1823 addr = rn_val; | 1841 addr = rn_val; |
| 1824 if (instr->HasW()) { | 1842 if (instr->HasW()) { |
| 1825 set_register(rn, rn_val); | 1843 set_register(rn, rn_val); |
| 1826 } | 1844 } |
| 1827 break; | 1845 break; |
| 1828 } | 1846 } |
| 1829 default: { | 1847 default: { |
| 1830 // The PU field is a 2-bit field. | 1848 // The PU field is a 2-bit field. |
| 1831 UNREACHABLE(); | 1849 UNREACHABLE(); |
| 1832 break; | 1850 break; |
| 1833 } | 1851 } |
| 1834 } | 1852 } |
| 1835 } else { | 1853 } else { |
| 1836 int32_t imm_val = (instr->ImmedHField() << 4) | instr->ImmedLField(); | 1854 int32_t imm_val = (instr->ImmedHValue() << 4) | instr->ImmedLValue(); |
| 1837 switch (instr->PUField()) { | 1855 switch (instr->PUField()) { |
| 1838 case 0: { | 1856 case da_x: { |
| 1839 // Format(instr, "'memop'cond'sign'h 'rd, ['rn], #-'off8"); | 1857 // Format(instr, "'memop'cond'sign'h 'rd, ['rn], #-'off8"); |
| 1840 ASSERT(!instr->HasW()); | 1858 ASSERT(!instr->HasW()); |
| 1841 addr = rn_val; | 1859 addr = rn_val; |
| 1842 rn_val -= imm_val; | 1860 rn_val -= imm_val; |
| 1843 set_register(rn, rn_val); | 1861 set_register(rn, rn_val); |
| 1844 break; | 1862 break; |
| 1845 } | 1863 } |
| 1846 case 1: { | 1864 case ia_x: { |
| 1847 // Format(instr, "'memop'cond'sign'h 'rd, ['rn], #+'off8"); | 1865 // Format(instr, "'memop'cond'sign'h 'rd, ['rn], #+'off8"); |
| 1848 ASSERT(!instr->HasW()); | 1866 ASSERT(!instr->HasW()); |
| 1849 addr = rn_val; | 1867 addr = rn_val; |
| 1850 rn_val += imm_val; | 1868 rn_val += imm_val; |
| 1851 set_register(rn, rn_val); | 1869 set_register(rn, rn_val); |
| 1852 break; | 1870 break; |
| 1853 } | 1871 } |
| 1854 case 2: { | 1872 case db_x: { |
| 1855 // Format(instr, "'memop'cond'sign'h 'rd, ['rn, #-'off8]'w"); | 1873 // Format(instr, "'memop'cond'sign'h 'rd, ['rn, #-'off8]'w"); |
| 1856 rn_val -= imm_val; | 1874 rn_val -= imm_val; |
| 1857 addr = rn_val; | 1875 addr = rn_val; |
| 1858 if (instr->HasW()) { | 1876 if (instr->HasW()) { |
| 1859 set_register(rn, rn_val); | 1877 set_register(rn, rn_val); |
| 1860 } | 1878 } |
| 1861 break; | 1879 break; |
| 1862 } | 1880 } |
| 1863 case 3: { | 1881 case ib_x: { |
| 1864 // Format(instr, "'memop'cond'sign'h 'rd, ['rn, #+'off8]'w"); | 1882 // Format(instr, "'memop'cond'sign'h 'rd, ['rn, #+'off8]'w"); |
| 1865 rn_val += imm_val; | 1883 rn_val += imm_val; |
| 1866 addr = rn_val; | 1884 addr = rn_val; |
| 1867 if (instr->HasW()) { | 1885 if (instr->HasW()) { |
| 1868 set_register(rn, rn_val); | 1886 set_register(rn, rn_val); |
| 1869 } | 1887 } |
| 1870 break; | 1888 break; |
| 1871 } | 1889 } |
| 1872 default: { | 1890 default: { |
| 1873 // The PU field is a 2-bit field. | 1891 // The PU field is a 2-bit field. |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1910 // signed byte loads | 1928 // signed byte loads |
| 1911 ASSERT(instr->HasSign()); | 1929 ASSERT(instr->HasSign()); |
| 1912 ASSERT(instr->HasL()); | 1930 ASSERT(instr->HasL()); |
| 1913 int8_t val = ReadB(addr); | 1931 int8_t val = ReadB(addr); |
| 1914 set_register(rd, val); | 1932 set_register(rd, val); |
| 1915 } | 1933 } |
| 1916 return; | 1934 return; |
| 1917 } | 1935 } |
| 1918 } else if ((type == 0) && instr->IsMiscType0()) { | 1936 } else if ((type == 0) && instr->IsMiscType0()) { |
| 1919 if (instr->Bits(22, 21) == 1) { | 1937 if (instr->Bits(22, 21) == 1) { |
| 1920 int rm = instr->RmField(); | 1938 int rm = instr->RmValue(); |
| 1921 switch (instr->Bits(7, 4)) { | 1939 switch (instr->BitField(7, 4)) { |
| 1922 case BX: | 1940 case BX: |
| 1923 set_pc(get_register(rm)); | 1941 set_pc(get_register(rm)); |
| 1924 break; | 1942 break; |
| 1925 case BLX: { | 1943 case BLX: { |
| 1926 uint32_t old_pc = get_pc(); | 1944 uint32_t old_pc = get_pc(); |
| 1927 set_pc(get_register(rm)); | 1945 set_pc(get_register(rm)); |
| 1928 set_register(lr, old_pc + Instr::kInstrSize); | 1946 set_register(lr, old_pc + Instruction::kInstrSize); |
| 1929 break; | 1947 break; |
| 1930 } | 1948 } |
| 1931 case BKPT: { | 1949 case BKPT: { |
| 1932 Debugger dbg(this); | 1950 Debugger dbg(this); |
| 1933 PrintF("Simulator hit BKPT.\n"); | 1951 PrintF("Simulator hit BKPT.\n"); |
| 1934 dbg.Debug(); | 1952 dbg.Debug(); |
| 1935 break; | 1953 break; |
| 1936 } | 1954 } |
| 1937 default: | 1955 default: |
| 1938 UNIMPLEMENTED(); | 1956 UNIMPLEMENTED(); |
| 1939 } | 1957 } |
| 1940 } else if (instr->Bits(22, 21) == 3) { | 1958 } else if (instr->Bits(22, 21) == 3) { |
| 1941 int rm = instr->RmField(); | 1959 int rm = instr->RmValue(); |
| 1942 int rd = instr->RdField(); | 1960 int rd = instr->RdValue(); |
| 1943 switch (instr->Bits(7, 4)) { | 1961 switch (instr->BitField(7, 4)) { |
| 1944 case CLZ: { | 1962 case CLZ: { |
| 1945 uint32_t bits = get_register(rm); | 1963 uint32_t bits = get_register(rm); |
| 1946 int leading_zeros = 0; | 1964 int leading_zeros = 0; |
| 1947 if (bits == 0) { | 1965 if (bits == 0) { |
| 1948 leading_zeros = 32; | 1966 leading_zeros = 32; |
| 1949 } else { | 1967 } else { |
| 1950 while ((bits & 0x80000000u) == 0) { | 1968 while ((bits & 0x80000000u) == 0) { |
| 1951 bits <<= 1; | 1969 bits <<= 1; |
| 1952 leading_zeros++; | 1970 leading_zeros++; |
| 1953 } | 1971 } |
| 1954 } | 1972 } |
| 1955 set_register(rd, leading_zeros); | 1973 set_register(rd, leading_zeros); |
| 1956 break; | 1974 break; |
| 1957 } | 1975 } |
| 1958 default: | 1976 default: |
| 1959 UNIMPLEMENTED(); | 1977 UNIMPLEMENTED(); |
| 1960 } | 1978 } |
| 1961 } else { | 1979 } else { |
| 1962 PrintF("%08x\n", instr->InstructionBits()); | 1980 PrintF("%08x\n", instr->InstructionBits()); |
| 1963 UNIMPLEMENTED(); | 1981 UNIMPLEMENTED(); |
| 1964 } | 1982 } |
| 1965 } else { | 1983 } else { |
| 1966 int rd = instr->RdField(); | 1984 int rd = instr->RdValue(); |
| 1967 int rn = instr->RnField(); | 1985 int rn = instr->RnValue(); |
| 1968 int32_t rn_val = get_register(rn); | 1986 int32_t rn_val = get_register(rn); |
| 1969 int32_t shifter_operand = 0; | 1987 int32_t shifter_operand = 0; |
| 1970 bool shifter_carry_out = 0; | 1988 bool shifter_carry_out = 0; |
| 1971 if (type == 0) { | 1989 if (type == 0) { |
| 1972 shifter_operand = GetShiftRm(instr, &shifter_carry_out); | 1990 shifter_operand = GetShiftRm(instr, &shifter_carry_out); |
| 1973 } else { | 1991 } else { |
| 1974 ASSERT(instr->TypeField() == 1); | 1992 ASSERT(instr->TypeValue() == 1); |
| 1975 shifter_operand = GetImm(instr, &shifter_carry_out); | 1993 shifter_operand = GetImm(instr, &shifter_carry_out); |
| 1976 } | 1994 } |
| 1977 int32_t alu_out; | 1995 int32_t alu_out; |
| 1978 | 1996 |
| 1979 switch (instr->OpcodeField()) { | 1997 switch (instr->OpcodeField()) { |
| 1980 case AND: { | 1998 case AND: { |
| 1981 // Format(instr, "and'cond's 'rd, 'rn, 'shift_rm"); | 1999 // Format(instr, "and'cond's 'rd, 'rn, 'shift_rm"); |
| 1982 // Format(instr, "and'cond's 'rd, 'rn, 'imm"); | 2000 // Format(instr, "and'cond's 'rd, 'rn, 'imm"); |
| 1983 alu_out = rn_val & shifter_operand; | 2001 alu_out = rn_val & shifter_operand; |
| 1984 set_register(rd, alu_out); | 2002 set_register(rd, alu_out); |
| (...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2060 | 2078 |
| 2061 case TST: { | 2079 case TST: { |
| 2062 if (instr->HasS()) { | 2080 if (instr->HasS()) { |
| 2063 // Format(instr, "tst'cond 'rn, 'shift_rm"); | 2081 // Format(instr, "tst'cond 'rn, 'shift_rm"); |
| 2064 // Format(instr, "tst'cond 'rn, 'imm"); | 2082 // Format(instr, "tst'cond 'rn, 'imm"); |
| 2065 alu_out = rn_val & shifter_operand; | 2083 alu_out = rn_val & shifter_operand; |
| 2066 SetNZFlags(alu_out); | 2084 SetNZFlags(alu_out); |
| 2067 SetCFlag(shifter_carry_out); | 2085 SetCFlag(shifter_carry_out); |
| 2068 } else { | 2086 } else { |
| 2069 // Format(instr, "movw'cond 'rd, 'imm"). | 2087 // Format(instr, "movw'cond 'rd, 'imm"). |
| 2070 alu_out = instr->ImmedMovwMovtField(); | 2088 alu_out = instr->ImmedMovwMovtValue(); |
| 2071 set_register(rd, alu_out); | 2089 set_register(rd, alu_out); |
| 2072 } | 2090 } |
| 2073 break; | 2091 break; |
| 2074 } | 2092 } |
| 2075 | 2093 |
| 2076 case TEQ: { | 2094 case TEQ: { |
| 2077 if (instr->HasS()) { | 2095 if (instr->HasS()) { |
| 2078 // Format(instr, "teq'cond 'rn, 'shift_rm"); | 2096 // Format(instr, "teq'cond 'rn, 'shift_rm"); |
| 2079 // Format(instr, "teq'cond 'rn, 'imm"); | 2097 // Format(instr, "teq'cond 'rn, 'imm"); |
| 2080 alu_out = rn_val ^ shifter_operand; | 2098 alu_out = rn_val ^ shifter_operand; |
| (...skipping 11 matching lines...) Expand all Loading... |
| 2092 if (instr->HasS()) { | 2110 if (instr->HasS()) { |
| 2093 // Format(instr, "cmp'cond 'rn, 'shift_rm"); | 2111 // Format(instr, "cmp'cond 'rn, 'shift_rm"); |
| 2094 // Format(instr, "cmp'cond 'rn, 'imm"); | 2112 // Format(instr, "cmp'cond 'rn, 'imm"); |
| 2095 alu_out = rn_val - shifter_operand; | 2113 alu_out = rn_val - shifter_operand; |
| 2096 SetNZFlags(alu_out); | 2114 SetNZFlags(alu_out); |
| 2097 SetCFlag(!BorrowFrom(rn_val, shifter_operand)); | 2115 SetCFlag(!BorrowFrom(rn_val, shifter_operand)); |
| 2098 SetVFlag(OverflowFrom(alu_out, rn_val, shifter_operand, false)); | 2116 SetVFlag(OverflowFrom(alu_out, rn_val, shifter_operand, false)); |
| 2099 } else { | 2117 } else { |
| 2100 // Format(instr, "movt'cond 'rd, 'imm"). | 2118 // Format(instr, "movt'cond 'rd, 'imm"). |
| 2101 alu_out = (get_register(rd) & 0xffff) | | 2119 alu_out = (get_register(rd) & 0xffff) | |
| 2102 (instr->ImmedMovwMovtField() << 16); | 2120 (instr->ImmedMovwMovtValue() << 16); |
| 2103 set_register(rd, alu_out); | 2121 set_register(rd, alu_out); |
| 2104 } | 2122 } |
| 2105 break; | 2123 break; |
| 2106 } | 2124 } |
| 2107 | 2125 |
| 2108 case CMN: { | 2126 case CMN: { |
| 2109 if (instr->HasS()) { | 2127 if (instr->HasS()) { |
| 2110 // Format(instr, "cmn'cond 'rn, 'shift_rm"); | 2128 // Format(instr, "cmn'cond 'rn, 'shift_rm"); |
| 2111 // Format(instr, "cmn'cond 'rn, 'imm"); | 2129 // Format(instr, "cmn'cond 'rn, 'imm"); |
| 2112 alu_out = rn_val + shifter_operand; | 2130 alu_out = rn_val + shifter_operand; |
| (...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2171 | 2189 |
| 2172 default: { | 2190 default: { |
| 2173 UNREACHABLE(); | 2191 UNREACHABLE(); |
| 2174 break; | 2192 break; |
| 2175 } | 2193 } |
| 2176 } | 2194 } |
| 2177 } | 2195 } |
| 2178 } | 2196 } |
| 2179 | 2197 |
| 2180 | 2198 |
| 2181 void Simulator::DecodeType2(Instr* instr) { | 2199 void Simulator::DecodeType2(Instruction* instr) { |
| 2182 int rd = instr->RdField(); | 2200 int rd = instr->RdValue(); |
| 2183 int rn = instr->RnField(); | 2201 int rn = instr->RnValue(); |
| 2184 int32_t rn_val = get_register(rn); | 2202 int32_t rn_val = get_register(rn); |
| 2185 int32_t im_val = instr->Offset12Field(); | 2203 int32_t im_val = instr->Offset12Value(); |
| 2186 int32_t addr = 0; | 2204 int32_t addr = 0; |
| 2187 switch (instr->PUField()) { | 2205 switch (instr->PUField()) { |
| 2188 case 0: { | 2206 case da_x: { |
| 2189 // Format(instr, "'memop'cond'b 'rd, ['rn], #-'off12"); | 2207 // Format(instr, "'memop'cond'b 'rd, ['rn], #-'off12"); |
| 2190 ASSERT(!instr->HasW()); | 2208 ASSERT(!instr->HasW()); |
| 2191 addr = rn_val; | 2209 addr = rn_val; |
| 2192 rn_val -= im_val; | 2210 rn_val -= im_val; |
| 2193 set_register(rn, rn_val); | 2211 set_register(rn, rn_val); |
| 2194 break; | 2212 break; |
| 2195 } | 2213 } |
| 2196 case 1: { | 2214 case ia_x: { |
| 2197 // Format(instr, "'memop'cond'b 'rd, ['rn], #+'off12"); | 2215 // Format(instr, "'memop'cond'b 'rd, ['rn], #+'off12"); |
| 2198 ASSERT(!instr->HasW()); | 2216 ASSERT(!instr->HasW()); |
| 2199 addr = rn_val; | 2217 addr = rn_val; |
| 2200 rn_val += im_val; | 2218 rn_val += im_val; |
| 2201 set_register(rn, rn_val); | 2219 set_register(rn, rn_val); |
| 2202 break; | 2220 break; |
| 2203 } | 2221 } |
| 2204 case 2: { | 2222 case db_x: { |
| 2205 // Format(instr, "'memop'cond'b 'rd, ['rn, #-'off12]'w"); | 2223 // Format(instr, "'memop'cond'b 'rd, ['rn, #-'off12]'w"); |
| 2206 rn_val -= im_val; | 2224 rn_val -= im_val; |
| 2207 addr = rn_val; | 2225 addr = rn_val; |
| 2208 if (instr->HasW()) { | 2226 if (instr->HasW()) { |
| 2209 set_register(rn, rn_val); | 2227 set_register(rn, rn_val); |
| 2210 } | 2228 } |
| 2211 break; | 2229 break; |
| 2212 } | 2230 } |
| 2213 case 3: { | 2231 case ib_x: { |
| 2214 // Format(instr, "'memop'cond'b 'rd, ['rn, #+'off12]'w"); | 2232 // Format(instr, "'memop'cond'b 'rd, ['rn, #+'off12]'w"); |
| 2215 rn_val += im_val; | 2233 rn_val += im_val; |
| 2216 addr = rn_val; | 2234 addr = rn_val; |
| 2217 if (instr->HasW()) { | 2235 if (instr->HasW()) { |
| 2218 set_register(rn, rn_val); | 2236 set_register(rn, rn_val); |
| 2219 } | 2237 } |
| 2220 break; | 2238 break; |
| 2221 } | 2239 } |
| 2222 default: { | 2240 default: { |
| 2223 UNREACHABLE(); | 2241 UNREACHABLE(); |
| (...skipping 11 matching lines...) Expand all Loading... |
| 2235 } else { | 2253 } else { |
| 2236 if (instr->HasL()) { | 2254 if (instr->HasL()) { |
| 2237 set_register(rd, ReadW(addr, instr)); | 2255 set_register(rd, ReadW(addr, instr)); |
| 2238 } else { | 2256 } else { |
| 2239 WriteW(addr, get_register(rd), instr); | 2257 WriteW(addr, get_register(rd), instr); |
| 2240 } | 2258 } |
| 2241 } | 2259 } |
| 2242 } | 2260 } |
| 2243 | 2261 |
| 2244 | 2262 |
| 2245 void Simulator::DecodeType3(Instr* instr) { | 2263 void Simulator::DecodeType3(Instruction* instr) { |
| 2246 int rd = instr->RdField(); | 2264 int rd = instr->RdValue(); |
| 2247 int rn = instr->RnField(); | 2265 int rn = instr->RnValue(); |
| 2248 int32_t rn_val = get_register(rn); | 2266 int32_t rn_val = get_register(rn); |
| 2249 bool shifter_carry_out = 0; | 2267 bool shifter_carry_out = 0; |
| 2250 int32_t shifter_operand = GetShiftRm(instr, &shifter_carry_out); | 2268 int32_t shifter_operand = GetShiftRm(instr, &shifter_carry_out); |
| 2251 int32_t addr = 0; | 2269 int32_t addr = 0; |
| 2252 switch (instr->PUField()) { | 2270 switch (instr->PUField()) { |
| 2253 case 0: { | 2271 case da_x: { |
| 2254 ASSERT(!instr->HasW()); | 2272 ASSERT(!instr->HasW()); |
| 2255 Format(instr, "'memop'cond'b 'rd, ['rn], -'shift_rm"); | 2273 Format(instr, "'memop'cond'b 'rd, ['rn], -'shift_rm"); |
| 2256 UNIMPLEMENTED(); | 2274 UNIMPLEMENTED(); |
| 2257 break; | 2275 break; |
| 2258 } | 2276 } |
| 2259 case 1: { | 2277 case ia_x: { |
| 2260 if (instr->HasW()) { | 2278 if (instr->HasW()) { |
| 2261 ASSERT(instr->Bits(5, 4) == 0x1); | 2279 ASSERT(instr->Bits(5, 4) == 0x1); |
| 2262 | 2280 |
| 2263 if (instr->Bit(22) == 0x1) { // USAT. | 2281 if (instr->Bit(22) == 0x1) { // USAT. |
| 2264 int32_t sat_pos = instr->Bits(20, 16); | 2282 int32_t sat_pos = instr->Bits(20, 16); |
| 2265 int32_t sat_val = (1 << sat_pos) - 1; | 2283 int32_t sat_val = (1 << sat_pos) - 1; |
| 2266 int32_t shift = instr->Bits(11, 7); | 2284 int32_t shift = instr->Bits(11, 7); |
| 2267 int32_t shift_type = instr->Bit(6); | 2285 int32_t shift_type = instr->Bit(6); |
| 2268 int32_t rm_val = get_register(instr->RmField()); | 2286 int32_t rm_val = get_register(instr->RmValue()); |
| 2269 if (shift_type == 0) { // LSL | 2287 if (shift_type == 0) { // LSL |
| 2270 rm_val <<= shift; | 2288 rm_val <<= shift; |
| 2271 } else { // ASR | 2289 } else { // ASR |
| 2272 rm_val >>= shift; | 2290 rm_val >>= shift; |
| 2273 } | 2291 } |
| 2274 // If saturation occurs, the Q flag should be set in the CPSR. | 2292 // If saturation occurs, the Q flag should be set in the CPSR. |
| 2275 // There is no Q flag yet, and no instruction (MRS) to read the | 2293 // There is no Q flag yet, and no instruction (MRS) to read the |
| 2276 // CPSR directly. | 2294 // CPSR directly. |
| 2277 if (rm_val > sat_val) { | 2295 if (rm_val > sat_val) { |
| 2278 rm_val = sat_val; | 2296 rm_val = sat_val; |
| 2279 } else if (rm_val < 0) { | 2297 } else if (rm_val < 0) { |
| 2280 rm_val = 0; | 2298 rm_val = 0; |
| 2281 } | 2299 } |
| 2282 set_register(rd, rm_val); | 2300 set_register(rd, rm_val); |
| 2283 } else { // SSAT. | 2301 } else { // SSAT. |
| 2284 UNIMPLEMENTED(); | 2302 UNIMPLEMENTED(); |
| 2285 } | 2303 } |
| 2286 return; | 2304 return; |
| 2287 } else { | 2305 } else { |
| 2288 Format(instr, "'memop'cond'b 'rd, ['rn], +'shift_rm"); | 2306 Format(instr, "'memop'cond'b 'rd, ['rn], +'shift_rm"); |
| 2289 UNIMPLEMENTED(); | 2307 UNIMPLEMENTED(); |
| 2290 } | 2308 } |
| 2291 break; | 2309 break; |
| 2292 } | 2310 } |
| 2293 case 2: { | 2311 case db_x: { |
| 2294 // Format(instr, "'memop'cond'b 'rd, ['rn, -'shift_rm]'w"); | 2312 // Format(instr, "'memop'cond'b 'rd, ['rn, -'shift_rm]'w"); |
| 2295 addr = rn_val - shifter_operand; | 2313 addr = rn_val - shifter_operand; |
| 2296 if (instr->HasW()) { | 2314 if (instr->HasW()) { |
| 2297 set_register(rn, addr); | 2315 set_register(rn, addr); |
| 2298 } | 2316 } |
| 2299 break; | 2317 break; |
| 2300 } | 2318 } |
| 2301 case 3: { | 2319 case ib_x: { |
| 2302 if (instr->HasW() && (instr->Bits(6, 4) == 0x5)) { | 2320 if (instr->HasW() && (instr->Bits(6, 4) == 0x5)) { |
| 2303 uint32_t widthminus1 = static_cast<uint32_t>(instr->Bits(20, 16)); | 2321 uint32_t widthminus1 = static_cast<uint32_t>(instr->Bits(20, 16)); |
| 2304 uint32_t lsbit = static_cast<uint32_t>(instr->Bits(11, 7)); | 2322 uint32_t lsbit = static_cast<uint32_t>(instr->Bits(11, 7)); |
| 2305 uint32_t msbit = widthminus1 + lsbit; | 2323 uint32_t msbit = widthminus1 + lsbit; |
| 2306 if (msbit <= 31) { | 2324 if (msbit <= 31) { |
| 2307 if (instr->Bit(22)) { | 2325 if (instr->Bit(22)) { |
| 2308 // ubfx - unsigned bitfield extract. | 2326 // ubfx - unsigned bitfield extract. |
| 2309 uint32_t rm_val = | 2327 uint32_t rm_val = |
| 2310 static_cast<uint32_t>(get_register(instr->RmField())); | 2328 static_cast<uint32_t>(get_register(instr->RmValue())); |
| 2311 uint32_t extr_val = rm_val << (31 - msbit); | 2329 uint32_t extr_val = rm_val << (31 - msbit); |
| 2312 extr_val = extr_val >> (31 - widthminus1); | 2330 extr_val = extr_val >> (31 - widthminus1); |
| 2313 set_register(instr->RdField(), extr_val); | 2331 set_register(instr->RdValue(), extr_val); |
| 2314 } else { | 2332 } else { |
| 2315 // sbfx - signed bitfield extract. | 2333 // sbfx - signed bitfield extract. |
| 2316 int32_t rm_val = get_register(instr->RmField()); | 2334 int32_t rm_val = get_register(instr->RmValue()); |
| 2317 int32_t extr_val = rm_val << (31 - msbit); | 2335 int32_t extr_val = rm_val << (31 - msbit); |
| 2318 extr_val = extr_val >> (31 - widthminus1); | 2336 extr_val = extr_val >> (31 - widthminus1); |
| 2319 set_register(instr->RdField(), extr_val); | 2337 set_register(instr->RdValue(), extr_val); |
| 2320 } | 2338 } |
| 2321 } else { | 2339 } else { |
| 2322 UNREACHABLE(); | 2340 UNREACHABLE(); |
| 2323 } | 2341 } |
| 2324 return; | 2342 return; |
| 2325 } else if (!instr->HasW() && (instr->Bits(6, 4) == 0x1)) { | 2343 } else if (!instr->HasW() && (instr->Bits(6, 4) == 0x1)) { |
| 2326 uint32_t lsbit = static_cast<uint32_t>(instr->Bits(11, 7)); | 2344 uint32_t lsbit = static_cast<uint32_t>(instr->Bits(11, 7)); |
| 2327 uint32_t msbit = static_cast<uint32_t>(instr->Bits(20, 16)); | 2345 uint32_t msbit = static_cast<uint32_t>(instr->Bits(20, 16)); |
| 2328 if (msbit >= lsbit) { | 2346 if (msbit >= lsbit) { |
| 2329 // bfc or bfi - bitfield clear/insert. | 2347 // bfc or bfi - bitfield clear/insert. |
| 2330 uint32_t rd_val = | 2348 uint32_t rd_val = |
| 2331 static_cast<uint32_t>(get_register(instr->RdField())); | 2349 static_cast<uint32_t>(get_register(instr->RdValue())); |
| 2332 uint32_t bitcount = msbit - lsbit + 1; | 2350 uint32_t bitcount = msbit - lsbit + 1; |
| 2333 uint32_t mask = (1 << bitcount) - 1; | 2351 uint32_t mask = (1 << bitcount) - 1; |
| 2334 rd_val &= ~(mask << lsbit); | 2352 rd_val &= ~(mask << lsbit); |
| 2335 if (instr->RmField() != 15) { | 2353 if (instr->RmValue() != 15) { |
| 2336 // bfi - bitfield insert. | 2354 // bfi - bitfield insert. |
| 2337 uint32_t rm_val = | 2355 uint32_t rm_val = |
| 2338 static_cast<uint32_t>(get_register(instr->RmField())); | 2356 static_cast<uint32_t>(get_register(instr->RmValue())); |
| 2339 rm_val &= mask; | 2357 rm_val &= mask; |
| 2340 rd_val |= rm_val << lsbit; | 2358 rd_val |= rm_val << lsbit; |
| 2341 } | 2359 } |
| 2342 set_register(instr->RdField(), rd_val); | 2360 set_register(instr->RdValue(), rd_val); |
| 2343 } else { | 2361 } else { |
| 2344 UNREACHABLE(); | 2362 UNREACHABLE(); |
| 2345 } | 2363 } |
| 2346 return; | 2364 return; |
| 2347 } else { | 2365 } else { |
| 2348 // Format(instr, "'memop'cond'b 'rd, ['rn, +'shift_rm]'w"); | 2366 // Format(instr, "'memop'cond'b 'rd, ['rn, +'shift_rm]'w"); |
| 2349 addr = rn_val + shifter_operand; | 2367 addr = rn_val + shifter_operand; |
| 2350 if (instr->HasW()) { | 2368 if (instr->HasW()) { |
| 2351 set_register(rn, addr); | 2369 set_register(rn, addr); |
| 2352 } | 2370 } |
| (...skipping 16 matching lines...) Expand all Loading... |
| 2369 } else { | 2387 } else { |
| 2370 if (instr->HasL()) { | 2388 if (instr->HasL()) { |
| 2371 set_register(rd, ReadW(addr, instr)); | 2389 set_register(rd, ReadW(addr, instr)); |
| 2372 } else { | 2390 } else { |
| 2373 WriteW(addr, get_register(rd), instr); | 2391 WriteW(addr, get_register(rd), instr); |
| 2374 } | 2392 } |
| 2375 } | 2393 } |
| 2376 } | 2394 } |
| 2377 | 2395 |
| 2378 | 2396 |
| 2379 void Simulator::DecodeType4(Instr* instr) { | 2397 void Simulator::DecodeType4(Instruction* instr) { |
| 2380 ASSERT(instr->Bit(22) == 0); // only allowed to be set in privileged mode | 2398 ASSERT(instr->Bit(22) == 0); // only allowed to be set in privileged mode |
| 2381 if (instr->HasL()) { | 2399 if (instr->HasL()) { |
| 2382 // Format(instr, "ldm'cond'pu 'rn'w, 'rlist"); | 2400 // Format(instr, "ldm'cond'pu 'rn'w, 'rlist"); |
| 2383 HandleRList(instr, true); | 2401 HandleRList(instr, true); |
| 2384 } else { | 2402 } else { |
| 2385 // Format(instr, "stm'cond'pu 'rn'w, 'rlist"); | 2403 // Format(instr, "stm'cond'pu 'rn'w, 'rlist"); |
| 2386 HandleRList(instr, false); | 2404 HandleRList(instr, false); |
| 2387 } | 2405 } |
| 2388 } | 2406 } |
| 2389 | 2407 |
| 2390 | 2408 |
| 2391 void Simulator::DecodeType5(Instr* instr) { | 2409 void Simulator::DecodeType5(Instruction* instr) { |
| 2392 // Format(instr, "b'l'cond 'target"); | 2410 // Format(instr, "b'l'cond 'target"); |
| 2393 int off = (instr->SImmed24Field() << 2); | 2411 int off = (instr->SImmed24Value() << 2); |
| 2394 intptr_t pc_address = get_pc(); | 2412 intptr_t pc_address = get_pc(); |
| 2395 if (instr->HasLink()) { | 2413 if (instr->HasLink()) { |
| 2396 set_register(lr, pc_address + Instr::kInstrSize); | 2414 set_register(lr, pc_address + Instruction::kInstrSize); |
| 2397 } | 2415 } |
| 2398 int pc_reg = get_register(pc); | 2416 int pc_reg = get_register(pc); |
| 2399 set_pc(pc_reg + off); | 2417 set_pc(pc_reg + off); |
| 2400 } | 2418 } |
| 2401 | 2419 |
| 2402 | 2420 |
| 2403 void Simulator::DecodeType6(Instr* instr) { | 2421 void Simulator::DecodeType6(Instruction* instr) { |
| 2404 DecodeType6CoprocessorIns(instr); | 2422 DecodeType6CoprocessorIns(instr); |
| 2405 } | 2423 } |
| 2406 | 2424 |
| 2407 | 2425 |
| 2408 void Simulator::DecodeType7(Instr* instr) { | 2426 void Simulator::DecodeType7(Instruction* instr) { |
| 2409 if (instr->Bit(24) == 1) { | 2427 if (instr->Bit(24) == 1) { |
| 2410 SoftwareInterrupt(instr); | 2428 SoftwareInterrupt(instr); |
| 2411 } else { | 2429 } else { |
| 2412 DecodeTypeVFP(instr); | 2430 DecodeTypeVFP(instr); |
| 2413 } | 2431 } |
| 2414 } | 2432 } |
| 2415 | 2433 |
| 2416 | 2434 |
| 2417 // void Simulator::DecodeTypeVFP(Instr* instr) | 2435 // void Simulator::DecodeTypeVFP(Instruction* instr) |
| 2418 // The Following ARMv7 VFPv instructions are currently supported. | 2436 // The Following ARMv7 VFPv instructions are currently supported. |
| 2419 // vmov :Sn = Rt | 2437 // vmov :Sn = Rt |
| 2420 // vmov :Rt = Sn | 2438 // vmov :Rt = Sn |
| 2421 // vcvt: Dd = Sm | 2439 // vcvt: Dd = Sm |
| 2422 // vcvt: Sd = Dm | 2440 // vcvt: Sd = Dm |
| 2423 // Dd = vadd(Dn, Dm) | 2441 // Dd = vadd(Dn, Dm) |
| 2424 // Dd = vsub(Dn, Dm) | 2442 // Dd = vsub(Dn, Dm) |
| 2425 // Dd = vmul(Dn, Dm) | 2443 // Dd = vmul(Dn, Dm) |
| 2426 // Dd = vdiv(Dn, Dm) | 2444 // Dd = vdiv(Dn, Dm) |
| 2427 // vcmp(Dd, Dm) | 2445 // vcmp(Dd, Dm) |
| 2428 // vmrs | 2446 // vmrs |
| 2429 // Dd = vsqrt(Dm) | 2447 // Dd = vsqrt(Dm) |
| 2430 void Simulator::DecodeTypeVFP(Instr* instr) { | 2448 void Simulator::DecodeTypeVFP(Instruction* instr) { |
| 2431 ASSERT((instr->TypeField() == 7) && (instr->Bit(24) == 0x0) ); | 2449 ASSERT((instr->TypeValue() == 7) && (instr->Bit(24) == 0x0) ); |
| 2432 ASSERT(instr->Bits(11, 9) == 0x5); | 2450 ASSERT(instr->Bits(11, 9) == 0x5); |
| 2433 | 2451 |
| 2434 // Obtain double precision register codes. | 2452 // Obtain double precision register codes. |
| 2435 int vm = instr->VFPMRegCode(kDoublePrecision); | 2453 int vm = instr->VFPMRegValue(kDoublePrecision); |
| 2436 int vd = instr->VFPDRegCode(kDoublePrecision); | 2454 int vd = instr->VFPDRegValue(kDoublePrecision); |
| 2437 int vn = instr->VFPNRegCode(kDoublePrecision); | 2455 int vn = instr->VFPNRegValue(kDoublePrecision); |
| 2438 | 2456 |
| 2439 if (instr->Bit(4) == 0) { | 2457 if (instr->Bit(4) == 0) { |
| 2440 if (instr->Opc1Field() == 0x7) { | 2458 if (instr->Opc1Value() == 0x7) { |
| 2441 // Other data processing instructions | 2459 // Other data processing instructions |
| 2442 if ((instr->Opc2Field() == 0x0) && (instr->Opc3Field() == 0x1)) { | 2460 if ((instr->Opc2Value() == 0x0) && (instr->Opc3Value() == 0x1)) { |
| 2443 // vmov register to register. | 2461 // vmov register to register. |
| 2444 if (instr->SzField() == 0x1) { | 2462 if (instr->SzValue() == 0x1) { |
| 2445 int m = instr->VFPMRegCode(kDoublePrecision); | 2463 int m = instr->VFPMRegValue(kDoublePrecision); |
| 2446 int d = instr->VFPDRegCode(kDoublePrecision); | 2464 int d = instr->VFPDRegValue(kDoublePrecision); |
| 2447 set_d_register_from_double(d, get_double_from_d_register(m)); | 2465 set_d_register_from_double(d, get_double_from_d_register(m)); |
| 2448 } else { | 2466 } else { |
| 2449 int m = instr->VFPMRegCode(kSinglePrecision); | 2467 int m = instr->VFPMRegValue(kSinglePrecision); |
| 2450 int d = instr->VFPDRegCode(kSinglePrecision); | 2468 int d = instr->VFPDRegValue(kSinglePrecision); |
| 2451 set_s_register_from_float(d, get_float_from_s_register(m)); | 2469 set_s_register_from_float(d, get_float_from_s_register(m)); |
| 2452 } | 2470 } |
| 2453 } else if ((instr->Opc2Field() == 0x7) && (instr->Opc3Field() == 0x3)) { | 2471 } else if ((instr->Opc2Value() == 0x0) && (instr->Opc3Value() == 0x3)) { |
| 2472 // vabs |
| 2473 double dm_value = get_double_from_d_register(vm); |
| 2474 double dd_value = fabs(dm_value); |
| 2475 set_d_register_from_double(vd, dd_value); |
| 2476 } else if ((instr->Opc2Value() == 0x7) && (instr->Opc3Value() == 0x3)) { |
| 2454 DecodeVCVTBetweenDoubleAndSingle(instr); | 2477 DecodeVCVTBetweenDoubleAndSingle(instr); |
| 2455 } else if ((instr->Opc2Field() == 0x8) && (instr->Opc3Field() & 0x1)) { | 2478 } else if ((instr->Opc2Value() == 0x8) && (instr->Opc3Value() & 0x1)) { |
| 2456 DecodeVCVTBetweenFloatingPointAndInteger(instr); | 2479 DecodeVCVTBetweenFloatingPointAndInteger(instr); |
| 2457 } else if (((instr->Opc2Field() >> 1) == 0x6) && | 2480 } else if (((instr->Opc2Value() >> 1) == 0x6) && |
| 2458 (instr->Opc3Field() & 0x1)) { | 2481 (instr->Opc3Value() & 0x1)) { |
| 2459 DecodeVCVTBetweenFloatingPointAndInteger(instr); | 2482 DecodeVCVTBetweenFloatingPointAndInteger(instr); |
| 2460 } else if (((instr->Opc2Field() == 0x4) || (instr->Opc2Field() == 0x5)) && | 2483 } else if (((instr->Opc2Value() == 0x4) || (instr->Opc2Value() == 0x5)) && |
| 2461 (instr->Opc3Field() & 0x1)) { | 2484 (instr->Opc3Value() & 0x1)) { |
| 2462 DecodeVCMP(instr); | 2485 DecodeVCMP(instr); |
| 2463 } else if (((instr->Opc2Field() == 0x1)) && (instr->Opc3Field() == 0x3)) { | 2486 } else if (((instr->Opc2Value() == 0x1)) && (instr->Opc3Value() == 0x3)) { |
| 2464 // vsqrt | 2487 // vsqrt |
| 2465 double dm_value = get_double_from_d_register(vm); | 2488 double dm_value = get_double_from_d_register(vm); |
| 2466 double dd_value = sqrt(dm_value); | 2489 double dd_value = sqrt(dm_value); |
| 2467 set_d_register_from_double(vd, dd_value); | 2490 set_d_register_from_double(vd, dd_value); |
| 2468 } else if (instr->Opc3Field() == 0x0) { | 2491 } else if (instr->Opc3Value() == 0x0) { |
| 2469 // vmov immediate. | 2492 // vmov immediate. |
| 2470 if (instr->SzField() == 0x1) { | 2493 if (instr->SzValue() == 0x1) { |
| 2471 set_d_register_from_double(vd, instr->DoubleImmedVmov()); | 2494 set_d_register_from_double(vd, instr->DoubleImmedVmov()); |
| 2472 } else { | 2495 } else { |
| 2473 UNREACHABLE(); // Not used by v8. | 2496 UNREACHABLE(); // Not used by v8. |
| 2474 } | 2497 } |
| 2475 } else { | 2498 } else { |
| 2476 UNREACHABLE(); // Not used by V8. | 2499 UNREACHABLE(); // Not used by V8. |
| 2477 } | 2500 } |
| 2478 } else if (instr->Opc1Field() == 0x3) { | 2501 } else if (instr->Opc1Value() == 0x3) { |
| 2479 if (instr->SzField() != 0x1) { | 2502 if (instr->SzValue() != 0x1) { |
| 2480 UNREACHABLE(); // Not used by V8. | 2503 UNREACHABLE(); // Not used by V8. |
| 2481 } | 2504 } |
| 2482 | 2505 |
| 2483 if (instr->Opc3Field() & 0x1) { | 2506 if (instr->Opc3Value() & 0x1) { |
| 2484 // vsub | 2507 // vsub |
| 2485 double dn_value = get_double_from_d_register(vn); | 2508 double dn_value = get_double_from_d_register(vn); |
| 2486 double dm_value = get_double_from_d_register(vm); | 2509 double dm_value = get_double_from_d_register(vm); |
| 2487 double dd_value = dn_value - dm_value; | 2510 double dd_value = dn_value - dm_value; |
| 2488 set_d_register_from_double(vd, dd_value); | 2511 set_d_register_from_double(vd, dd_value); |
| 2489 } else { | 2512 } else { |
| 2490 // vadd | 2513 // vadd |
| 2491 double dn_value = get_double_from_d_register(vn); | 2514 double dn_value = get_double_from_d_register(vn); |
| 2492 double dm_value = get_double_from_d_register(vm); | 2515 double dm_value = get_double_from_d_register(vm); |
| 2493 double dd_value = dn_value + dm_value; | 2516 double dd_value = dn_value + dm_value; |
| 2494 set_d_register_from_double(vd, dd_value); | 2517 set_d_register_from_double(vd, dd_value); |
| 2495 } | 2518 } |
| 2496 } else if ((instr->Opc1Field() == 0x2) && !(instr->Opc3Field() & 0x1)) { | 2519 } else if ((instr->Opc1Value() == 0x2) && !(instr->Opc3Value() & 0x1)) { |
| 2497 // vmul | 2520 // vmul |
| 2498 if (instr->SzField() != 0x1) { | 2521 if (instr->SzValue() != 0x1) { |
| 2499 UNREACHABLE(); // Not used by V8. | 2522 UNREACHABLE(); // Not used by V8. |
| 2500 } | 2523 } |
| 2501 | 2524 |
| 2502 double dn_value = get_double_from_d_register(vn); | 2525 double dn_value = get_double_from_d_register(vn); |
| 2503 double dm_value = get_double_from_d_register(vm); | 2526 double dm_value = get_double_from_d_register(vm); |
| 2504 double dd_value = dn_value * dm_value; | 2527 double dd_value = dn_value * dm_value; |
| 2505 set_d_register_from_double(vd, dd_value); | 2528 set_d_register_from_double(vd, dd_value); |
| 2506 } else if ((instr->Opc1Field() == 0x4) && !(instr->Opc3Field() & 0x1)) { | 2529 } else if ((instr->Opc1Value() == 0x4) && !(instr->Opc3Value() & 0x1)) { |
| 2507 // vdiv | 2530 // vdiv |
| 2508 if (instr->SzField() != 0x1) { | 2531 if (instr->SzValue() != 0x1) { |
| 2509 UNREACHABLE(); // Not used by V8. | 2532 UNREACHABLE(); // Not used by V8. |
| 2510 } | 2533 } |
| 2511 | 2534 |
| 2512 double dn_value = get_double_from_d_register(vn); | 2535 double dn_value = get_double_from_d_register(vn); |
| 2513 double dm_value = get_double_from_d_register(vm); | 2536 double dm_value = get_double_from_d_register(vm); |
| 2514 double dd_value = dn_value / dm_value; | 2537 double dd_value = dn_value / dm_value; |
| 2515 set_d_register_from_double(vd, dd_value); | 2538 set_d_register_from_double(vd, dd_value); |
| 2516 } else { | 2539 } else { |
| 2517 UNIMPLEMENTED(); // Not used by V8. | 2540 UNIMPLEMENTED(); // Not used by V8. |
| 2518 } | 2541 } |
| 2519 } else { | 2542 } else { |
| 2520 if ((instr->VCField() == 0x0) && | 2543 if ((instr->VCValue() == 0x0) && |
| 2521 (instr->VAField() == 0x0)) { | 2544 (instr->VAValue() == 0x0)) { |
| 2522 DecodeVMOVBetweenCoreAndSinglePrecisionRegisters(instr); | 2545 DecodeVMOVBetweenCoreAndSinglePrecisionRegisters(instr); |
| 2523 } else if ((instr->VLField() == 0x1) && | 2546 } else if ((instr->VLValue() == 0x1) && |
| 2524 (instr->VCField() == 0x0) && | 2547 (instr->VCValue() == 0x0) && |
| 2525 (instr->VAField() == 0x7) && | 2548 (instr->VAValue() == 0x7) && |
| 2526 (instr->Bits(19, 16) == 0x1)) { | 2549 (instr->Bits(19, 16) == 0x1)) { |
| 2527 // vmrs | 2550 // vmrs |
| 2528 uint32_t rt = instr->RtField(); | 2551 uint32_t rt = instr->RtValue(); |
| 2529 if (rt == 0xF) { | 2552 if (rt == 0xF) { |
| 2530 Copy_FPSCR_to_APSR(); | 2553 Copy_FPSCR_to_APSR(); |
| 2531 } else { | 2554 } else { |
| 2532 // Emulate FPSCR from the Simulator flags. | 2555 // Emulate FPSCR from the Simulator flags. |
| 2533 uint32_t fpscr = (n_flag_FPSCR_ << 31) | | 2556 uint32_t fpscr = (n_flag_FPSCR_ << 31) | |
| 2534 (z_flag_FPSCR_ << 30) | | 2557 (z_flag_FPSCR_ << 30) | |
| 2535 (c_flag_FPSCR_ << 29) | | 2558 (c_flag_FPSCR_ << 29) | |
| 2536 (v_flag_FPSCR_ << 28) | | 2559 (v_flag_FPSCR_ << 28) | |
| 2537 (inexact_vfp_flag_ << 4) | | 2560 (inexact_vfp_flag_ << 4) | |
| 2538 (underflow_vfp_flag_ << 3) | | 2561 (underflow_vfp_flag_ << 3) | |
| 2539 (overflow_vfp_flag_ << 2) | | 2562 (overflow_vfp_flag_ << 2) | |
| 2540 (div_zero_vfp_flag_ << 1) | | 2563 (div_zero_vfp_flag_ << 1) | |
| 2541 (inv_op_vfp_flag_ << 0) | | 2564 (inv_op_vfp_flag_ << 0) | |
| 2542 (FPSCR_rounding_mode_ << 22); | 2565 (FPSCR_rounding_mode_); |
| 2543 set_register(rt, fpscr); | 2566 set_register(rt, fpscr); |
| 2544 } | 2567 } |
| 2545 } else if ((instr->VLField() == 0x0) && | 2568 } else if ((instr->VLValue() == 0x0) && |
| 2546 (instr->VCField() == 0x0) && | 2569 (instr->VCValue() == 0x0) && |
| 2547 (instr->VAField() == 0x7) && | 2570 (instr->VAValue() == 0x7) && |
| 2548 (instr->Bits(19, 16) == 0x1)) { | 2571 (instr->Bits(19, 16) == 0x1)) { |
| 2549 // vmsr | 2572 // vmsr |
| 2550 uint32_t rt = instr->RtField(); | 2573 uint32_t rt = instr->RtValue(); |
| 2551 if (rt == pc) { | 2574 if (rt == pc) { |
| 2552 UNREACHABLE(); | 2575 UNREACHABLE(); |
| 2553 } else { | 2576 } else { |
| 2554 uint32_t rt_value = get_register(rt); | 2577 uint32_t rt_value = get_register(rt); |
| 2555 n_flag_FPSCR_ = (rt_value >> 31) & 1; | 2578 n_flag_FPSCR_ = (rt_value >> 31) & 1; |
| 2556 z_flag_FPSCR_ = (rt_value >> 30) & 1; | 2579 z_flag_FPSCR_ = (rt_value >> 30) & 1; |
| 2557 c_flag_FPSCR_ = (rt_value >> 29) & 1; | 2580 c_flag_FPSCR_ = (rt_value >> 29) & 1; |
| 2558 v_flag_FPSCR_ = (rt_value >> 28) & 1; | 2581 v_flag_FPSCR_ = (rt_value >> 28) & 1; |
| 2559 inexact_vfp_flag_ = (rt_value >> 4) & 1; | 2582 inexact_vfp_flag_ = (rt_value >> 4) & 1; |
| 2560 underflow_vfp_flag_ = (rt_value >> 3) & 1; | 2583 underflow_vfp_flag_ = (rt_value >> 3) & 1; |
| 2561 overflow_vfp_flag_ = (rt_value >> 2) & 1; | 2584 overflow_vfp_flag_ = (rt_value >> 2) & 1; |
| 2562 div_zero_vfp_flag_ = (rt_value >> 1) & 1; | 2585 div_zero_vfp_flag_ = (rt_value >> 1) & 1; |
| 2563 inv_op_vfp_flag_ = (rt_value >> 0) & 1; | 2586 inv_op_vfp_flag_ = (rt_value >> 0) & 1; |
| 2564 FPSCR_rounding_mode_ = | 2587 FPSCR_rounding_mode_ = |
| 2565 static_cast<FPSCRRoundingModes>((rt_value >> 22) & 3); | 2588 static_cast<VFPRoundingMode>((rt_value) & kVFPRoundingModeMask); |
| 2566 } | 2589 } |
| 2567 } else { | 2590 } else { |
| 2568 UNIMPLEMENTED(); // Not used by V8. | 2591 UNIMPLEMENTED(); // Not used by V8. |
| 2569 } | 2592 } |
| 2570 } | 2593 } |
| 2571 } | 2594 } |
| 2572 | 2595 |
| 2573 | 2596 |
| 2574 void Simulator::DecodeVMOVBetweenCoreAndSinglePrecisionRegisters(Instr* instr) { | 2597 void Simulator::DecodeVMOVBetweenCoreAndSinglePrecisionRegisters( |
| 2575 ASSERT((instr->Bit(4) == 1) && (instr->VCField() == 0x0) && | 2598 Instruction* instr) { |
| 2576 (instr->VAField() == 0x0)); | 2599 ASSERT((instr->Bit(4) == 1) && (instr->VCValue() == 0x0) && |
| 2600 (instr->VAValue() == 0x0)); |
| 2577 | 2601 |
| 2578 int t = instr->RtField(); | 2602 int t = instr->RtValue(); |
| 2579 int n = instr->VFPNRegCode(kSinglePrecision); | 2603 int n = instr->VFPNRegValue(kSinglePrecision); |
| 2580 bool to_arm_register = (instr->VLField() == 0x1); | 2604 bool to_arm_register = (instr->VLValue() == 0x1); |
| 2581 | 2605 |
| 2582 if (to_arm_register) { | 2606 if (to_arm_register) { |
| 2583 int32_t int_value = get_sinteger_from_s_register(n); | 2607 int32_t int_value = get_sinteger_from_s_register(n); |
| 2584 set_register(t, int_value); | 2608 set_register(t, int_value); |
| 2585 } else { | 2609 } else { |
| 2586 int32_t rs_val = get_register(t); | 2610 int32_t rs_val = get_register(t); |
| 2587 set_s_register_from_sinteger(n, rs_val); | 2611 set_s_register_from_sinteger(n, rs_val); |
| 2588 } | 2612 } |
| 2589 } | 2613 } |
| 2590 | 2614 |
| 2591 | 2615 |
| 2592 void Simulator::DecodeVCMP(Instr* instr) { | 2616 void Simulator::DecodeVCMP(Instruction* instr) { |
| 2593 ASSERT((instr->Bit(4) == 0) && (instr->Opc1Field() == 0x7)); | 2617 ASSERT((instr->Bit(4) == 0) && (instr->Opc1Value() == 0x7)); |
| 2594 ASSERT(((instr->Opc2Field() == 0x4) || (instr->Opc2Field() == 0x5)) && | 2618 ASSERT(((instr->Opc2Value() == 0x4) || (instr->Opc2Value() == 0x5)) && |
| 2595 (instr->Opc3Field() & 0x1)); | 2619 (instr->Opc3Value() & 0x1)); |
| 2596 // Comparison. | 2620 // Comparison. |
| 2597 | 2621 |
| 2598 VFPRegPrecision precision = kSinglePrecision; | 2622 VFPRegPrecision precision = kSinglePrecision; |
| 2599 if (instr->SzField() == 1) { | 2623 if (instr->SzValue() == 1) { |
| 2600 precision = kDoublePrecision; | 2624 precision = kDoublePrecision; |
| 2601 } | 2625 } |
| 2602 | 2626 |
| 2603 if (instr->Bit(7) != 0) { | 2627 int d = instr->VFPDRegValue(precision); |
| 2604 // Raising exceptions for quiet NaNs are not supported. | |
| 2605 UNIMPLEMENTED(); // Not used by V8. | |
| 2606 } | |
| 2607 | |
| 2608 int d = instr->VFPDRegCode(precision); | |
| 2609 int m = 0; | 2628 int m = 0; |
| 2610 if (instr->Opc2Field() == 0x4) { | 2629 if (instr->Opc2Value() == 0x4) { |
| 2611 m = instr->VFPMRegCode(precision); | 2630 m = instr->VFPMRegValue(precision); |
| 2612 } | 2631 } |
| 2613 | 2632 |
| 2614 if (precision == kDoublePrecision) { | 2633 if (precision == kDoublePrecision) { |
| 2615 double dd_value = get_double_from_d_register(d); | 2634 double dd_value = get_double_from_d_register(d); |
| 2616 double dm_value = 0.0; | 2635 double dm_value = 0.0; |
| 2617 if (instr->Opc2Field() == 0x4) { | 2636 if (instr->Opc2Value() == 0x4) { |
| 2618 dm_value = get_double_from_d_register(m); | 2637 dm_value = get_double_from_d_register(m); |
| 2619 } | 2638 } |
| 2620 | 2639 |
| 2640 // Raise exceptions for quiet NaNs if necessary. |
| 2641 if (instr->Bit(7) == 1) { |
| 2642 if (isnan(dd_value)) { |
| 2643 inv_op_vfp_flag_ = true; |
| 2644 } |
| 2645 } |
| 2646 |
| 2621 Compute_FPSCR_Flags(dd_value, dm_value); | 2647 Compute_FPSCR_Flags(dd_value, dm_value); |
| 2622 } else { | 2648 } else { |
| 2623 UNIMPLEMENTED(); // Not used by V8. | 2649 UNIMPLEMENTED(); // Not used by V8. |
| 2624 } | 2650 } |
| 2625 } | 2651 } |
| 2626 | 2652 |
| 2627 | 2653 |
| 2628 void Simulator::DecodeVCVTBetweenDoubleAndSingle(Instr* instr) { | 2654 void Simulator::DecodeVCVTBetweenDoubleAndSingle(Instruction* instr) { |
| 2629 ASSERT((instr->Bit(4) == 0) && (instr->Opc1Field() == 0x7)); | 2655 ASSERT((instr->Bit(4) == 0) && (instr->Opc1Value() == 0x7)); |
| 2630 ASSERT((instr->Opc2Field() == 0x7) && (instr->Opc3Field() == 0x3)); | 2656 ASSERT((instr->Opc2Value() == 0x7) && (instr->Opc3Value() == 0x3)); |
| 2631 | 2657 |
| 2632 VFPRegPrecision dst_precision = kDoublePrecision; | 2658 VFPRegPrecision dst_precision = kDoublePrecision; |
| 2633 VFPRegPrecision src_precision = kSinglePrecision; | 2659 VFPRegPrecision src_precision = kSinglePrecision; |
| 2634 if (instr->SzField() == 1) { | 2660 if (instr->SzValue() == 1) { |
| 2635 dst_precision = kSinglePrecision; | 2661 dst_precision = kSinglePrecision; |
| 2636 src_precision = kDoublePrecision; | 2662 src_precision = kDoublePrecision; |
| 2637 } | 2663 } |
| 2638 | 2664 |
| 2639 int dst = instr->VFPDRegCode(dst_precision); | 2665 int dst = instr->VFPDRegValue(dst_precision); |
| 2640 int src = instr->VFPMRegCode(src_precision); | 2666 int src = instr->VFPMRegValue(src_precision); |
| 2641 | 2667 |
| 2642 if (dst_precision == kSinglePrecision) { | 2668 if (dst_precision == kSinglePrecision) { |
| 2643 double val = get_double_from_d_register(src); | 2669 double val = get_double_from_d_register(src); |
| 2644 set_s_register_from_float(dst, static_cast<float>(val)); | 2670 set_s_register_from_float(dst, static_cast<float>(val)); |
| 2645 } else { | 2671 } else { |
| 2646 float val = get_float_from_s_register(src); | 2672 float val = get_float_from_s_register(src); |
| 2647 set_d_register_from_double(dst, static_cast<double>(val)); | 2673 set_d_register_from_double(dst, static_cast<double>(val)); |
| 2648 } | 2674 } |
| 2649 } | 2675 } |
| 2650 | 2676 |
| 2677 bool get_inv_op_vfp_flag(VFPRoundingMode mode, |
| 2678 double val, |
| 2679 bool unsigned_) { |
| 2680 ASSERT((mode == RN) || (mode == RM) || (mode == RZ)); |
| 2681 double max_uint = static_cast<double>(0xffffffffu); |
| 2682 double max_int = static_cast<double>(kMaxInt); |
| 2683 double min_int = static_cast<double>(kMinInt); |
| 2684 |
| 2685 // Check for NaN. |
| 2686 if (val != val) { |
| 2687 return true; |
| 2688 } |
| 2689 |
| 2690 // Check for overflow. This code works because 32bit integers can be |
| 2691 // exactly represented by ieee-754 64bit floating-point values. |
| 2692 switch (mode) { |
| 2693 case RN: |
| 2694 return unsigned_ ? (val >= (max_uint + 0.5)) || |
| 2695 (val < -0.5) |
| 2696 : (val >= (max_int + 0.5)) || |
| 2697 (val < (min_int - 0.5)); |
| 2698 |
| 2699 case RM: |
| 2700 return unsigned_ ? (val >= (max_uint + 1.0)) || |
| 2701 (val < 0) |
| 2702 : (val >= (max_int + 1.0)) || |
| 2703 (val < min_int); |
| 2704 |
| 2705 case RZ: |
| 2706 return unsigned_ ? (val >= (max_uint + 1.0)) || |
| 2707 (val <= -1) |
| 2708 : (val >= (max_int + 1.0)) || |
| 2709 (val <= (min_int - 1.0)); |
| 2710 default: |
| 2711 UNREACHABLE(); |
| 2712 return true; |
| 2713 } |
| 2714 } |
| 2715 |
| 2651 | 2716 |
| 2652 void Simulator::DecodeVCVTBetweenFloatingPointAndInteger(Instr* instr) { | 2717 // We call this function only if we had a vfp invalid exception. |
| 2653 ASSERT((instr->Bit(4) == 0) && (instr->Opc1Field() == 0x7)); | 2718 // It returns the correct saturated value. |
| 2654 ASSERT(((instr->Opc2Field() == 0x8) && (instr->Opc3Field() & 0x1)) || | 2719 int VFPConversionSaturate(double val, bool unsigned_res) { |
| 2655 (((instr->Opc2Field() >> 1) == 0x6) && (instr->Opc3Field() & 0x1))); | 2720 if (val != val) { |
| 2721 return 0; |
| 2722 } else { |
| 2723 if (unsigned_res) { |
| 2724 return (val < 0) ? 0 : 0xffffffffu; |
| 2725 } else { |
| 2726 return (val < 0) ? kMinInt : kMaxInt; |
| 2727 } |
| 2728 } |
| 2729 } |
| 2730 |
| 2731 |
| 2732 void Simulator::DecodeVCVTBetweenFloatingPointAndInteger(Instruction* instr) { |
| 2733 ASSERT((instr->Bit(4) == 0) && (instr->Opc1Value() == 0x7) && |
| 2734 (instr->Bits(27, 23) == 0x1D)); |
| 2735 ASSERT(((instr->Opc2Value() == 0x8) && (instr->Opc3Value() & 0x1)) || |
| 2736 (((instr->Opc2Value() >> 1) == 0x6) && (instr->Opc3Value() & 0x1))); |
| 2656 | 2737 |
| 2657 // Conversion between floating-point and integer. | 2738 // Conversion between floating-point and integer. |
| 2658 bool to_integer = (instr->Bit(18) == 1); | 2739 bool to_integer = (instr->Bit(18) == 1); |
| 2659 | 2740 |
| 2660 VFPRegPrecision src_precision = kSinglePrecision; | 2741 VFPRegPrecision src_precision = (instr->SzValue() == 1) ? kDoublePrecision |
| 2661 if (instr->SzField() == 1) { | 2742 : kSinglePrecision; |
| 2662 src_precision = kDoublePrecision; | |
| 2663 } | |
| 2664 | 2743 |
| 2665 if (to_integer) { | 2744 if (to_integer) { |
| 2745 // We are playing with code close to the C++ standard's limits below, |
| 2746 // hence the very simple code and heavy checks. |
| 2747 // |
| 2748 // Note: |
| 2749 // C++ defines default type casting from floating point to integer as |
| 2750 // (close to) rounding toward zero ("fractional part discarded"). |
| 2751 |
| 2752 int dst = instr->VFPDRegValue(kSinglePrecision); |
| 2753 int src = instr->VFPMRegValue(src_precision); |
| 2754 |
| 2755 // Bit 7 in vcvt instructions indicates if we should use the FPSCR rounding |
| 2756 // mode or the default Round to Zero mode. |
| 2757 VFPRoundingMode mode = (instr->Bit(7) != 1) ? FPSCR_rounding_mode_ |
| 2758 : RZ; |
| 2759 ASSERT((mode == RM) || (mode == RZ) || (mode == RN)); |
| 2760 |
| 2666 bool unsigned_integer = (instr->Bit(16) == 0); | 2761 bool unsigned_integer = (instr->Bit(16) == 0); |
| 2667 FPSCRRoundingModes mode; | 2762 bool double_precision = (src_precision == kDoublePrecision); |
| 2668 if (instr->Bit(7) != 1) { | 2763 |
| 2669 // Use FPSCR defined rounding mode. | 2764 double val = double_precision ? get_double_from_d_register(src) |
| 2670 mode = FPSCR_rounding_mode_; | 2765 : get_float_from_s_register(src); |
| 2671 // Only RZ and RM modes are supported. | 2766 |
| 2672 ASSERT((mode == RM) || (mode == RZ)); | 2767 int temp = unsigned_integer ? static_cast<uint32_t>(val) |
| 2768 : static_cast<int32_t>(val); |
| 2769 |
| 2770 inv_op_vfp_flag_ = get_inv_op_vfp_flag(mode, val, unsigned_integer); |
| 2771 |
| 2772 if (inv_op_vfp_flag_) { |
| 2773 temp = VFPConversionSaturate(val, unsigned_integer); |
| 2673 } else { | 2774 } else { |
| 2674 // VFP uses round towards zero by default. | 2775 switch (mode) { |
| 2675 mode = RZ; | 2776 case RN: { |
| 2777 double abs_diff = |
| 2778 unsigned_integer ? fabs(val - static_cast<uint32_t>(temp)) |
| 2779 : fabs(val - temp); |
| 2780 int val_sign = (val > 0) ? 1 : -1; |
| 2781 if (abs_diff > 0.5) { |
| 2782 temp += val_sign; |
| 2783 } else if (abs_diff == 0.5) { |
| 2784 // Round to even if exactly halfway. |
| 2785 temp = ((temp % 2) == 0) ? temp : temp + val_sign; |
| 2786 } |
| 2787 break; |
| 2788 } |
| 2789 |
| 2790 case RM: |
| 2791 temp = temp > val ? temp - 1 : temp; |
| 2792 break; |
| 2793 |
| 2794 case RZ: |
| 2795 // Nothing to do. |
| 2796 break; |
| 2797 |
| 2798 default: |
| 2799 UNREACHABLE(); |
| 2800 } |
| 2676 } | 2801 } |
| 2677 | 2802 |
| 2678 int dst = instr->VFPDRegCode(kSinglePrecision); | 2803 // Update the destination register. |
| 2679 int src = instr->VFPMRegCode(src_precision); | 2804 set_s_register_from_sinteger(dst, temp); |
| 2680 int32_t kMaxInt = v8::internal::kMaxInt; | |
| 2681 int32_t kMinInt = v8::internal::kMinInt; | |
| 2682 switch (mode) { | |
| 2683 case RM: | |
| 2684 if (src_precision == kDoublePrecision) { | |
| 2685 double val = get_double_from_d_register(src); | |
| 2686 | |
| 2687 inv_op_vfp_flag_ = (val > kMaxInt) || (val < kMinInt) || (val != val); | |
| 2688 | |
| 2689 int sint = unsigned_integer ? static_cast<uint32_t>(val) : | |
| 2690 static_cast<int32_t>(val); | |
| 2691 sint = sint > val ? sint - 1 : sint; | |
| 2692 | |
| 2693 set_s_register_from_sinteger(dst, sint); | |
| 2694 } else { | |
| 2695 float val = get_float_from_s_register(src); | |
| 2696 | |
| 2697 inv_op_vfp_flag_ = (val > kMaxInt) || (val < kMinInt) || (val != val); | |
| 2698 | |
| 2699 int sint = unsigned_integer ? static_cast<uint32_t>(val) : | |
| 2700 static_cast<int32_t>(val); | |
| 2701 sint = sint > val ? sint - 1 : sint; | |
| 2702 | |
| 2703 set_s_register_from_sinteger(dst, sint); | |
| 2704 } | |
| 2705 break; | |
| 2706 case RZ: | |
| 2707 if (src_precision == kDoublePrecision) { | |
| 2708 double val = get_double_from_d_register(src); | |
| 2709 | |
| 2710 inv_op_vfp_flag_ = (val > kMaxInt) || (val < kMinInt) || (val != val); | |
| 2711 | |
| 2712 int sint = unsigned_integer ? static_cast<uint32_t>(val) : | |
| 2713 static_cast<int32_t>(val); | |
| 2714 | |
| 2715 set_s_register_from_sinteger(dst, sint); | |
| 2716 } else { | |
| 2717 float val = get_float_from_s_register(src); | |
| 2718 | |
| 2719 inv_op_vfp_flag_ = (val > kMaxInt) || (val < kMinInt) || (val != val); | |
| 2720 | |
| 2721 int sint = unsigned_integer ? static_cast<uint32_t>(val) : | |
| 2722 static_cast<int32_t>(val); | |
| 2723 | |
| 2724 set_s_register_from_sinteger(dst, sint); | |
| 2725 } | |
| 2726 break; | |
| 2727 | |
| 2728 default: | |
| 2729 UNREACHABLE(); | |
| 2730 } | |
| 2731 | 2805 |
| 2732 } else { | 2806 } else { |
| 2733 bool unsigned_integer = (instr->Bit(7) == 0); | 2807 bool unsigned_integer = (instr->Bit(7) == 0); |
| 2734 | 2808 |
| 2735 int dst = instr->VFPDRegCode(src_precision); | 2809 int dst = instr->VFPDRegValue(src_precision); |
| 2736 int src = instr->VFPMRegCode(kSinglePrecision); | 2810 int src = instr->VFPMRegValue(kSinglePrecision); |
| 2737 | 2811 |
| 2738 int val = get_sinteger_from_s_register(src); | 2812 int val = get_sinteger_from_s_register(src); |
| 2739 | 2813 |
| 2740 if (src_precision == kDoublePrecision) { | 2814 if (src_precision == kDoublePrecision) { |
| 2741 if (unsigned_integer) { | 2815 if (unsigned_integer) { |
| 2742 set_d_register_from_double(dst, | 2816 set_d_register_from_double(dst, |
| 2743 static_cast<double>((uint32_t)val)); | 2817 static_cast<double>((uint32_t)val)); |
| 2744 } else { | 2818 } else { |
| 2745 set_d_register_from_double(dst, static_cast<double>(val)); | 2819 set_d_register_from_double(dst, static_cast<double>(val)); |
| 2746 } | 2820 } |
| 2747 } else { | 2821 } else { |
| 2748 if (unsigned_integer) { | 2822 if (unsigned_integer) { |
| 2749 set_s_register_from_float(dst, | 2823 set_s_register_from_float(dst, |
| 2750 static_cast<float>((uint32_t)val)); | 2824 static_cast<float>((uint32_t)val)); |
| 2751 } else { | 2825 } else { |
| 2752 set_s_register_from_float(dst, static_cast<float>(val)); | 2826 set_s_register_from_float(dst, static_cast<float>(val)); |
| 2753 } | 2827 } |
| 2754 } | 2828 } |
| 2755 } | 2829 } |
| 2756 } | 2830 } |
| 2757 | 2831 |
| 2758 | 2832 |
| 2759 // void Simulator::DecodeType6CoprocessorIns(Instr* instr) | 2833 // void Simulator::DecodeType6CoprocessorIns(Instruction* instr) |
| 2760 // Decode Type 6 coprocessor instructions. | 2834 // Decode Type 6 coprocessor instructions. |
| 2761 // Dm = vmov(Rt, Rt2) | 2835 // Dm = vmov(Rt, Rt2) |
| 2762 // <Rt, Rt2> = vmov(Dm) | 2836 // <Rt, Rt2> = vmov(Dm) |
| 2763 // Ddst = MEM(Rbase + 4*offset). | 2837 // Ddst = MEM(Rbase + 4*offset). |
| 2764 // MEM(Rbase + 4*offset) = Dsrc. | 2838 // MEM(Rbase + 4*offset) = Dsrc. |
| 2765 void Simulator::DecodeType6CoprocessorIns(Instr* instr) { | 2839 void Simulator::DecodeType6CoprocessorIns(Instruction* instr) { |
| 2766 ASSERT((instr->TypeField() == 6)); | 2840 ASSERT((instr->TypeValue() == 6)); |
| 2767 | 2841 |
| 2768 if (instr->CoprocessorField() == 0xA) { | 2842 if (instr->CoprocessorValue() == 0xA) { |
| 2769 switch (instr->OpcodeField()) { | 2843 switch (instr->OpcodeValue()) { |
| 2770 case 0x8: | 2844 case 0x8: |
| 2771 case 0xA: | 2845 case 0xA: |
| 2772 case 0xC: | 2846 case 0xC: |
| 2773 case 0xE: { // Load and store single precision float to memory. | 2847 case 0xE: { // Load and store single precision float to memory. |
| 2774 int rn = instr->RnField(); | 2848 int rn = instr->RnValue(); |
| 2775 int vd = instr->VFPDRegCode(kSinglePrecision); | 2849 int vd = instr->VFPDRegValue(kSinglePrecision); |
| 2776 int offset = instr->Immed8Field(); | 2850 int offset = instr->Immed8Value(); |
| 2777 if (!instr->HasU()) { | 2851 if (!instr->HasU()) { |
| 2778 offset = -offset; | 2852 offset = -offset; |
| 2779 } | 2853 } |
| 2780 | 2854 |
| 2781 int32_t address = get_register(rn) + 4 * offset; | 2855 int32_t address = get_register(rn) + 4 * offset; |
| 2782 if (instr->HasL()) { | 2856 if (instr->HasL()) { |
| 2783 // Load double from memory: vldr. | 2857 // Load double from memory: vldr. |
| 2784 set_s_register_from_sinteger(vd, ReadW(address, instr)); | 2858 set_s_register_from_sinteger(vd, ReadW(address, instr)); |
| 2785 } else { | 2859 } else { |
| 2786 // Store double to memory: vstr. | 2860 // Store double to memory: vstr. |
| 2787 WriteW(address, get_sinteger_from_s_register(vd), instr); | 2861 WriteW(address, get_sinteger_from_s_register(vd), instr); |
| 2788 } | 2862 } |
| 2789 break; | 2863 break; |
| 2790 } | 2864 } |
| 2791 default: | 2865 default: |
| 2792 UNIMPLEMENTED(); // Not used by V8. | 2866 UNIMPLEMENTED(); // Not used by V8. |
| 2793 break; | 2867 break; |
| 2794 } | 2868 } |
| 2795 } else if (instr->CoprocessorField() == 0xB) { | 2869 } else if (instr->CoprocessorValue() == 0xB) { |
| 2796 switch (instr->OpcodeField()) { | 2870 switch (instr->OpcodeValue()) { |
| 2797 case 0x2: | 2871 case 0x2: |
| 2798 // Load and store double to two GP registers | 2872 // Load and store double to two GP registers |
| 2799 if (instr->Bits(7, 4) != 0x1) { | 2873 if (instr->Bits(7, 4) != 0x1) { |
| 2800 UNIMPLEMENTED(); // Not used by V8. | 2874 UNIMPLEMENTED(); // Not used by V8. |
| 2801 } else { | 2875 } else { |
| 2802 int rt = instr->RtField(); | 2876 int rt = instr->RtValue(); |
| 2803 int rn = instr->RnField(); | 2877 int rn = instr->RnValue(); |
| 2804 int vm = instr->VmField(); | 2878 int vm = instr->VmValue(); |
| 2805 if (instr->HasL()) { | 2879 if (instr->HasL()) { |
| 2806 int32_t rt_int_value = get_sinteger_from_s_register(2*vm); | 2880 int32_t rt_int_value = get_sinteger_from_s_register(2*vm); |
| 2807 int32_t rn_int_value = get_sinteger_from_s_register(2*vm+1); | 2881 int32_t rn_int_value = get_sinteger_from_s_register(2*vm+1); |
| 2808 | 2882 |
| 2809 set_register(rt, rt_int_value); | 2883 set_register(rt, rt_int_value); |
| 2810 set_register(rn, rn_int_value); | 2884 set_register(rn, rn_int_value); |
| 2811 } else { | 2885 } else { |
| 2812 int32_t rs_val = get_register(rt); | 2886 int32_t rs_val = get_register(rt); |
| 2813 int32_t rn_val = get_register(rn); | 2887 int32_t rn_val = get_register(rn); |
| 2814 | 2888 |
| 2815 set_s_register_from_sinteger(2*vm, rs_val); | 2889 set_s_register_from_sinteger(2*vm, rs_val); |
| 2816 set_s_register_from_sinteger((2*vm+1), rn_val); | 2890 set_s_register_from_sinteger((2*vm+1), rn_val); |
| 2817 } | 2891 } |
| 2818 } | 2892 } |
| 2819 break; | 2893 break; |
| 2820 case 0x8: | 2894 case 0x8: |
| 2821 case 0xC: { // Load and store double to memory. | 2895 case 0xC: { // Load and store double to memory. |
| 2822 int rn = instr->RnField(); | 2896 int rn = instr->RnValue(); |
| 2823 int vd = instr->VdField(); | 2897 int vd = instr->VdValue(); |
| 2824 int offset = instr->Immed8Field(); | 2898 int offset = instr->Immed8Value(); |
| 2825 if (!instr->HasU()) { | 2899 if (!instr->HasU()) { |
| 2826 offset = -offset; | 2900 offset = -offset; |
| 2827 } | 2901 } |
| 2828 int32_t address = get_register(rn) + 4 * offset; | 2902 int32_t address = get_register(rn) + 4 * offset; |
| 2829 if (instr->HasL()) { | 2903 if (instr->HasL()) { |
| 2830 // Load double from memory: vldr. | 2904 // Load double from memory: vldr. |
| 2831 set_s_register_from_sinteger(2*vd, ReadW(address, instr)); | 2905 set_s_register_from_sinteger(2*vd, ReadW(address, instr)); |
| 2832 set_s_register_from_sinteger(2*vd + 1, ReadW(address + 4, instr)); | 2906 set_s_register_from_sinteger(2*vd + 1, ReadW(address + 4, instr)); |
| 2833 } else { | 2907 } else { |
| 2834 // Store double to memory: vstr. | 2908 // Store double to memory: vstr. |
| 2835 WriteW(address, get_sinteger_from_s_register(2*vd), instr); | 2909 WriteW(address, get_sinteger_from_s_register(2*vd), instr); |
| 2836 WriteW(address + 4, get_sinteger_from_s_register(2*vd + 1), instr); | 2910 WriteW(address + 4, get_sinteger_from_s_register(2*vd + 1), instr); |
| 2837 } | 2911 } |
| 2838 break; | 2912 break; |
| 2839 } | 2913 } |
| 2840 default: | 2914 default: |
| 2841 UNIMPLEMENTED(); // Not used by V8. | 2915 UNIMPLEMENTED(); // Not used by V8. |
| 2842 break; | 2916 break; |
| 2843 } | 2917 } |
| 2844 } else { | 2918 } else { |
| 2845 UNIMPLEMENTED(); // Not used by V8. | 2919 UNIMPLEMENTED(); // Not used by V8. |
| 2846 } | 2920 } |
| 2847 } | 2921 } |
| 2848 | 2922 |
| 2849 | 2923 |
| 2850 // Executes the current instruction. | 2924 // Executes the current instruction. |
| 2851 void Simulator::InstructionDecode(Instr* instr) { | 2925 void Simulator::InstructionDecode(Instruction* instr) { |
| 2852 if (v8::internal::FLAG_check_icache) { | 2926 if (v8::internal::FLAG_check_icache) { |
| 2853 CheckICache(instr); | 2927 CheckICache(instr); |
| 2854 } | 2928 } |
| 2855 pc_modified_ = false; | 2929 pc_modified_ = false; |
| 2856 if (::v8::internal::FLAG_trace_sim) { | 2930 if (::v8::internal::FLAG_trace_sim) { |
| 2857 disasm::NameConverter converter; | 2931 disasm::NameConverter converter; |
| 2858 disasm::Disassembler dasm(converter); | 2932 disasm::Disassembler dasm(converter); |
| 2859 // use a reasonably large buffer | 2933 // use a reasonably large buffer |
| 2860 v8::internal::EmbeddedVector<char, 256> buffer; | 2934 v8::internal::EmbeddedVector<char, 256> buffer; |
| 2861 dasm.InstructionDecode(buffer, | 2935 dasm.InstructionDecode(buffer, |
| 2862 reinterpret_cast<byte*>(instr)); | 2936 reinterpret_cast<byte*>(instr)); |
| 2863 PrintF(" 0x%08x %s\n", reinterpret_cast<intptr_t>(instr), buffer.start()); | 2937 PrintF(" 0x%08x %s\n", reinterpret_cast<intptr_t>(instr), buffer.start()); |
| 2864 } | 2938 } |
| 2865 if (instr->ConditionField() == special_condition) { | 2939 if (instr->ConditionField() == kSpecialCondition) { |
| 2866 UNIMPLEMENTED(); | 2940 UNIMPLEMENTED(); |
| 2867 } else if (ConditionallyExecute(instr)) { | 2941 } else if (ConditionallyExecute(instr)) { |
| 2868 switch (instr->TypeField()) { | 2942 switch (instr->TypeValue()) { |
| 2869 case 0: | 2943 case 0: |
| 2870 case 1: { | 2944 case 1: { |
| 2871 DecodeType01(instr); | 2945 DecodeType01(instr); |
| 2872 break; | 2946 break; |
| 2873 } | 2947 } |
| 2874 case 2: { | 2948 case 2: { |
| 2875 DecodeType2(instr); | 2949 DecodeType2(instr); |
| 2876 break; | 2950 break; |
| 2877 } | 2951 } |
| 2878 case 3: { | 2952 case 3: { |
| (...skipping 14 matching lines...) Expand all Loading... |
| 2893 } | 2967 } |
| 2894 case 7: { | 2968 case 7: { |
| 2895 DecodeType7(instr); | 2969 DecodeType7(instr); |
| 2896 break; | 2970 break; |
| 2897 } | 2971 } |
| 2898 default: { | 2972 default: { |
| 2899 UNIMPLEMENTED(); | 2973 UNIMPLEMENTED(); |
| 2900 break; | 2974 break; |
| 2901 } | 2975 } |
| 2902 } | 2976 } |
| 2977 // If the instruction is a non taken conditional stop, we need to skip the |
| 2978 // inlined message address. |
| 2979 } else if (instr->IsStop()) { |
| 2980 set_pc(get_pc() + 2 * Instruction::kInstrSize); |
| 2903 } | 2981 } |
| 2904 if (!pc_modified_) { | 2982 if (!pc_modified_) { |
| 2905 set_register(pc, reinterpret_cast<int32_t>(instr) + Instr::kInstrSize); | 2983 set_register(pc, reinterpret_cast<int32_t>(instr) |
| 2984 + Instruction::kInstrSize); |
| 2906 } | 2985 } |
| 2907 } | 2986 } |
| 2908 | 2987 |
| 2909 | 2988 |
| 2910 void Simulator::Execute() { | 2989 void Simulator::Execute() { |
| 2911 // Get the PC to simulate. Cannot use the accessor here as we need the | 2990 // Get the PC to simulate. Cannot use the accessor here as we need the |
| 2912 // raw PC value and not the one used as input to arithmetic instructions. | 2991 // raw PC value and not the one used as input to arithmetic instructions. |
| 2913 int program_counter = get_pc(); | 2992 int program_counter = get_pc(); |
| 2914 | 2993 |
| 2915 if (::v8::internal::FLAG_stop_sim_at == 0) { | 2994 if (::v8::internal::FLAG_stop_sim_at == 0) { |
| 2916 // Fast version of the dispatch loop without checking whether the simulator | 2995 // Fast version of the dispatch loop without checking whether the simulator |
| 2917 // should be stopping at a particular executed instruction. | 2996 // should be stopping at a particular executed instruction. |
| 2918 while (program_counter != end_sim_pc) { | 2997 while (program_counter != end_sim_pc) { |
| 2919 Instr* instr = reinterpret_cast<Instr*>(program_counter); | 2998 Instruction* instr = reinterpret_cast<Instruction*>(program_counter); |
| 2920 icount_++; | 2999 icount_++; |
| 2921 InstructionDecode(instr); | 3000 InstructionDecode(instr); |
| 2922 program_counter = get_pc(); | 3001 program_counter = get_pc(); |
| 2923 } | 3002 } |
| 2924 } else { | 3003 } else { |
| 2925 // FLAG_stop_sim_at is at the non-default value. Stop in the debugger when | 3004 // FLAG_stop_sim_at is at the non-default value. Stop in the debugger when |
| 2926 // we reach the particular instuction count. | 3005 // we reach the particular instuction count. |
| 2927 while (program_counter != end_sim_pc) { | 3006 while (program_counter != end_sim_pc) { |
| 2928 Instr* instr = reinterpret_cast<Instr*>(program_counter); | 3007 Instruction* instr = reinterpret_cast<Instruction*>(program_counter); |
| 2929 icount_++; | 3008 icount_++; |
| 2930 if (icount_ == ::v8::internal::FLAG_stop_sim_at) { | 3009 if (icount_ == ::v8::internal::FLAG_stop_sim_at) { |
| 2931 Debugger dbg(this); | 3010 Debugger dbg(this); |
| 2932 dbg.Debug(); | 3011 dbg.Debug(); |
| 2933 } else { | 3012 } else { |
| 2934 InstructionDecode(instr); | 3013 InstructionDecode(instr); |
| 2935 } | 3014 } |
| 2936 program_counter = get_pc(); | 3015 program_counter = get_pc(); |
| 2937 } | 3016 } |
| 2938 } | 3017 } |
| (...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3039 | 3118 |
| 3040 | 3119 |
| 3041 uintptr_t Simulator::PopAddress() { | 3120 uintptr_t Simulator::PopAddress() { |
| 3042 int current_sp = get_register(sp); | 3121 int current_sp = get_register(sp); |
| 3043 uintptr_t* stack_slot = reinterpret_cast<uintptr_t*>(current_sp); | 3122 uintptr_t* stack_slot = reinterpret_cast<uintptr_t*>(current_sp); |
| 3044 uintptr_t address = *stack_slot; | 3123 uintptr_t address = *stack_slot; |
| 3045 set_register(sp, current_sp + sizeof(uintptr_t)); | 3124 set_register(sp, current_sp + sizeof(uintptr_t)); |
| 3046 return address; | 3125 return address; |
| 3047 } | 3126 } |
| 3048 | 3127 |
| 3049 } } // namespace assembler::arm | 3128 } } // namespace v8::internal |
| 3050 | 3129 |
| 3051 #endif // USE_SIMULATOR | 3130 #endif // USE_SIMULATOR |
| 3052 | 3131 |
| 3053 #endif // V8_TARGET_ARCH_ARM | 3132 #endif // V8_TARGET_ARCH_ARM |
| OLD | NEW |