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