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