1 // Copyright 2012 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include <stdarg.h>
6 #include <stdlib.h>
7 #include <cmath>
8
9 #if V8_TARGET_ARCH_ARM
10
11 #include "src/arm/constants-arm.h"
12 #include "src/arm/simulator-arm.h"
13 #include "src/assembler.h"
14 #include "src/base/bits.h"
15 #include "src/codegen.h"
16 #include "src/disasm.h"
17 #include "src/runtime/runtime-utils.h"
18
19 #if defined(USE_SIMULATOR)
20
21 // Only build the simulator if not compiling for real ARM hardware.
22 namespace v8 {
23 namespace internal {
24
25 // static
26 base::LazyInstance<Simulator::GlobalMonitor>::type Simulator::global_monitor_ =
27 LAZY_INSTANCE_INITIALIZER;
28
29 // This macro provides a platform independent use of sscanf. The reason for
30 // SScanF not being implemented in a platform independent way through
31 // ::v8::internal::OS in the same way as SNPrintF is that the
32 // Windows C Run-Time Library does not provide vsscanf.
33 #define SScanF sscanf // NOLINT
34
35 // The ArmDebugger class is used by the simulator while debugging simulated ARM
36 // code.
37 class ArmDebugger {
38 public:
ArmDebugger(Simulator * sim)39 explicit ArmDebugger(Simulator* sim) : sim_(sim) { }
40
41 void Stop(Instruction* instr);
42 void Debug();
43
44 private:
45 static const Instr kBreakpointInstr =
46 (al | (7*B25) | (1*B24) | kBreakpoint);
47 static const Instr kNopInstr = (al | (13*B21));
48
49 Simulator* sim_;
50
51 int32_t GetRegisterValue(int regnum);
52 double GetRegisterPairDoubleValue(int regnum);
53 double GetVFPDoubleRegisterValue(int regnum);
54 bool GetValue(const char* desc, int32_t* value);
55 bool GetVFPSingleValue(const char* desc, float* value);
56 bool GetVFPDoubleValue(const char* desc, double* value);
57
58 // Set or delete a breakpoint. Returns true if successful.
59 bool SetBreakpoint(Instruction* breakpc);
60 bool DeleteBreakpoint(Instruction* breakpc);
61
62 // Undo and redo all breakpoints. This is needed to bracket disassembly and
63 // execution to skip past breakpoints when run from the debugger.
64 void UndoBreakpoints();
65 void RedoBreakpoints();
66 };
67
Stop(Instruction * instr)68 void ArmDebugger::Stop(Instruction* instr) {
69 // Get the stop code.
70 uint32_t code = instr->SvcValue() & kStopCodeMask;
71 // Print the stop message and code if it is not the default code.
72 if (code != kMaxStopCode) {
73 PrintF("Simulator hit stop %u\n", code);
74 } else {
75 PrintF("Simulator hit\n");
76 }
77 sim_->set_pc(sim_->get_pc() + 2 * Instruction::kInstrSize);
78 Debug();
79 }
80
GetRegisterValue(int regnum)81 int32_t ArmDebugger::GetRegisterValue(int regnum) {
82 if (regnum == kPCRegister) {
83 return sim_->get_pc();
84 } else {
85 return sim_->get_register(regnum);
86 }
87 }
88
GetRegisterPairDoubleValue(int regnum)89 double ArmDebugger::GetRegisterPairDoubleValue(int regnum) {
90 return sim_->get_double_from_register_pair(regnum);
91 }
92
93
GetVFPDoubleRegisterValue(int regnum)94 double ArmDebugger::GetVFPDoubleRegisterValue(int regnum) {
95 return sim_->get_double_from_d_register(regnum);
96 }
97
98
GetValue(const char * desc,int32_t * value)99 bool ArmDebugger::GetValue(const char* desc, int32_t* value) {
100 int regnum = Registers::Number(desc);
101 if (regnum != kNoRegister) {
102 *value = GetRegisterValue(regnum);
103 return true;
104 } else {
105 if (strncmp(desc, "0x", 2) == 0) {
106 return SScanF(desc + 2, "%x", reinterpret_cast<uint32_t*>(value)) == 1;
107 } else {
108 return SScanF(desc, "%u", reinterpret_cast<uint32_t*>(value)) == 1;
109 }
110 }
111 return false;
112 }
113
114
GetVFPSingleValue(const char * desc,float * value)115 bool ArmDebugger::GetVFPSingleValue(const char* desc, float* value) {
116 bool is_double;
117 int regnum = VFPRegisters::Number(desc, &is_double);
118 if (regnum != kNoRegister && !is_double) {
119 *value = sim_->get_float_from_s_register(regnum);
120 return true;
121 }
122 return false;
123 }
124
125
GetVFPDoubleValue(const char * desc,double * value)126 bool ArmDebugger::GetVFPDoubleValue(const char* desc, double* value) {
127 bool is_double;
128 int regnum = VFPRegisters::Number(desc, &is_double);
129 if (regnum != kNoRegister && is_double) {
130 *value = sim_->get_double_from_d_register(regnum);
131 return true;
132 }
133 return false;
134 }
135
136
SetBreakpoint(Instruction * breakpc)137 bool ArmDebugger::SetBreakpoint(Instruction* breakpc) {
138 // Check if a breakpoint can be set. If not return without any side-effects.
139 if (sim_->break_pc_ != NULL) {
140 return false;
141 }
142
143 // Set the breakpoint.
144 sim_->break_pc_ = breakpc;
145 sim_->break_instr_ = breakpc->InstructionBits();
146 // Not setting the breakpoint instruction in the code itself. It will be set
147 // when the debugger shell continues.
148 return true;
149 }
150
151
DeleteBreakpoint(Instruction * breakpc)152 bool ArmDebugger::DeleteBreakpoint(Instruction* breakpc) {
153 if (sim_->break_pc_ != NULL) {
154 sim_->break_pc_->SetInstructionBits(sim_->break_instr_);
155 }
156
157 sim_->break_pc_ = NULL;
158 sim_->break_instr_ = 0;
159 return true;
160 }
161
162
UndoBreakpoints()163 void ArmDebugger::UndoBreakpoints() {
164 if (sim_->break_pc_ != NULL) {
165 sim_->break_pc_->SetInstructionBits(sim_->break_instr_);
166 }
167 }
168
169
RedoBreakpoints()170 void ArmDebugger::RedoBreakpoints() {
171 if (sim_->break_pc_ != NULL) {
172 sim_->break_pc_->SetInstructionBits(kBreakpointInstr);
173 }
174 }
175
176
Debug()177 void ArmDebugger::Debug() {
178 intptr_t last_pc = -1;
179 bool done = false;
180
181 #define COMMAND_SIZE 63
182 #define ARG_SIZE 255
183
184 #define STR(a) #a
185 #define XSTR(a) STR(a)
186
187 char cmd[COMMAND_SIZE + 1];
188 char arg1[ARG_SIZE + 1];
189 char arg2[ARG_SIZE + 1];
190 char* argv[3] = { cmd, arg1, arg2 };
191
192 // make sure to have a proper terminating character if reaching the limit
193 cmd[COMMAND_SIZE] = 0;
194 arg1[ARG_SIZE] = 0;
195 arg2[ARG_SIZE] = 0;
196
197 // Undo all set breakpoints while running in the debugger shell. This will
198 // make them invisible to all commands.
199 UndoBreakpoints();
200
201 while (!done && !sim_->has_bad_pc()) {
202 if (last_pc != sim_->get_pc()) {
203 disasm::NameConverter converter;
204 disasm::Disassembler dasm(converter);
205 // use a reasonably large buffer
206 v8::internal::EmbeddedVector<char, 256> buffer;
207 dasm.InstructionDecode(buffer,
208 reinterpret_cast<byte*>(sim_->get_pc()));
209 PrintF(" 0x%08x %s\n", sim_->get_pc(), buffer.start());
210 last_pc = sim_->get_pc();
211 }
212 char* line = ReadLine("sim> ");
213 if (line == NULL) {
214 break;
215 } else {
216 char* last_input = sim_->last_debugger_input();
217 if (strcmp(line, "\n") == 0 && last_input != NULL) {
218 line = last_input;
219 } else {
220 // Ownership is transferred to sim_;
221 sim_->set_last_debugger_input(line);
222 }
223 // Use sscanf to parse the individual parts of the command line. At the
224 // moment no command expects more than two parameters.
225 int argc = SScanF(line,
226 "%" XSTR(COMMAND_SIZE) "s "
227 "%" XSTR(ARG_SIZE) "s "
228 "%" XSTR(ARG_SIZE) "s",
229 cmd, arg1, arg2);
230 if ((strcmp(cmd, "si") == 0) || (strcmp(cmd, "stepi") == 0)) {
231 sim_->InstructionDecode(reinterpret_cast<Instruction*>(sim_->get_pc()));
232 } else if ((strcmp(cmd, "c") == 0) || (strcmp(cmd, "cont") == 0)) {
233 // Execute the one instruction we broke at with breakpoints disabled.
234 sim_->InstructionDecode(reinterpret_cast<Instruction*>(sim_->get_pc()));
235 // Leave the debugger shell.
236 done = true;
237 } else if ((strcmp(cmd, "p") == 0) || (strcmp(cmd, "print") == 0)) {
238 if (argc == 2 || (argc == 3 && strcmp(arg2, "fp") == 0)) {
239 int32_t value;
240 float svalue;
241 double dvalue;
242 if (strcmp(arg1, "all") == 0) {
243 for (int i = 0; i < kNumRegisters; i++) {
244 value = GetRegisterValue(i);
245 PrintF(
246 "%3s: 0x%08x %10d",
247 RegisterConfiguration::Crankshaft()->GetGeneralRegisterName(
248 i),
249 value, value);
250 if ((argc == 3 && strcmp(arg2, "fp") == 0) &&
251 i < 8 &&
252 (i % 2) == 0) {
253 dvalue = GetRegisterPairDoubleValue(i);
254 PrintF(" (%f)\n", dvalue);
255 } else {
256 PrintF("\n");
257 }
258 }
259 for (int i = 0; i < DwVfpRegister::NumRegisters(); i++) {
260 dvalue = GetVFPDoubleRegisterValue(i);
261 uint64_t as_words = bit_cast<uint64_t>(dvalue);
262 PrintF("%3s: %f 0x%08x %08x\n",
263 VFPRegisters::Name(i, true),
264 dvalue,
265 static_cast<uint32_t>(as_words >> 32),
266 static_cast<uint32_t>(as_words & 0xffffffff));
267 }
268 } else {
269 if (GetValue(arg1, &value)) {
270 PrintF("%s: 0x%08x %d \n", arg1, value, value);
271 } else if (GetVFPSingleValue(arg1, &svalue)) {
272 uint32_t as_word = bit_cast<uint32_t>(svalue);
273 PrintF("%s: %f 0x%08x\n", arg1, svalue, as_word);
274 } else if (GetVFPDoubleValue(arg1, &dvalue)) {
275 uint64_t as_words = bit_cast<uint64_t>(dvalue);
276 PrintF("%s: %f 0x%08x %08x\n",
277 arg1,
278 dvalue,
279 static_cast<uint32_t>(as_words >> 32),
280 static_cast<uint32_t>(as_words & 0xffffffff));
281 } else {
282 PrintF("%s unrecognized\n", arg1);
283 }
284 }
285 } else {
286 PrintF("print <register>\n");
287 }
288 } else if ((strcmp(cmd, "po") == 0)
289 || (strcmp(cmd, "printobject") == 0)) {
290 if (argc == 2) {
291 int32_t value;
292 OFStream os(stdout);
293 if (GetValue(arg1, &value)) {
294 Object* obj = reinterpret_cast<Object*>(value);
295 os << arg1 << ": \n";
296 #ifdef DEBUG
297 obj->Print(os);
298 os << "\n";
299 #else
300 os << Brief(obj) << "\n";
301 #endif
302 } else {
303 os << arg1 << " unrecognized\n";
304 }
305 } else {
306 PrintF("printobject <value>\n");
307 }
308 } else if (strcmp(cmd, "stack") == 0 || strcmp(cmd, "mem") == 0) {
309 int32_t* cur = NULL;
310 int32_t* end = NULL;
311 int next_arg = 1;
312
313 if (strcmp(cmd, "stack") == 0) {
314 cur = reinterpret_cast<int32_t*>(sim_->get_register(Simulator::sp));
315 } else { // "mem"
316 int32_t value;
317 if (!GetValue(arg1, &value)) {
318 PrintF("%s unrecognized\n", arg1);
319 continue;
320 }
321 cur = reinterpret_cast<int32_t*>(value);
322 next_arg++;
323 }
324
325 int32_t words;
326 if (argc == next_arg) {
327 words = 10;
328 } else {
329 if (!GetValue(argv[next_arg], &words)) {
330 words = 10;
331 }
332 }
333 end = cur + words;
334
335 while (cur < end) {
336 PrintF(" 0x%08" V8PRIxPTR ": 0x%08x %10d",
337 reinterpret_cast<intptr_t>(cur), *cur, *cur);
338 HeapObject* obj = reinterpret_cast<HeapObject*>(*cur);
339 int value = *cur;
340 Heap* current_heap = sim_->isolate_->heap();
341 if (((value & 1) == 0) ||
342 current_heap->ContainsSlow(obj->address())) {
343 PrintF(" (");
344 if ((value & 1) == 0) {
345 PrintF("smi %d", value / 2);
346 } else {
347 obj->ShortPrint();
348 }
349 PrintF(")");
350 }
351 PrintF("\n");
352 cur++;
353 }
354 } else if (strcmp(cmd, "disasm") == 0 || strcmp(cmd, "di") == 0) {
355 disasm::NameConverter converter;
356 disasm::Disassembler dasm(converter);
357 // use a reasonably large buffer
358 v8::internal::EmbeddedVector<char, 256> buffer;
359
360 byte* prev = NULL;
361 byte* cur = NULL;
362 byte* end = NULL;
363
364 if (argc == 1) {
365 cur = reinterpret_cast<byte*>(sim_->get_pc());
366 end = cur + (10 * Instruction::kInstrSize);
367 } else if (argc == 2) {
368 int regnum = Registers::Number(arg1);
369 if (regnum != kNoRegister || strncmp(arg1, "0x", 2) == 0) {
370 // The argument is an address or a register name.
371 int32_t value;
372 if (GetValue(arg1, &value)) {
373 cur = reinterpret_cast<byte*>(value);
374 // Disassemble 10 instructions at <arg1>.
375 end = cur + (10 * Instruction::kInstrSize);
376 }
377 } else {
378 // The argument is the number of instructions.
379 int32_t value;
380 if (GetValue(arg1, &value)) {
381 cur = reinterpret_cast<byte*>(sim_->get_pc());
382 // Disassemble <arg1> instructions.
383 end = cur + (value * Instruction::kInstrSize);
384 }
385 }
386 } else {
387 int32_t value1;
388 int32_t value2;
389 if (GetValue(arg1, &value1) && GetValue(arg2, &value2)) {
390 cur = reinterpret_cast<byte*>(value1);
391 end = cur + (value2 * Instruction::kInstrSize);
392 }
393 }
394
395 while (cur < end) {
396 prev = cur;
397 cur += dasm.InstructionDecode(buffer, cur);
398 PrintF(" 0x%08" V8PRIxPTR " %s\n", reinterpret_cast<intptr_t>(prev),
399 buffer.start());
400 }
401 } else if (strcmp(cmd, "gdb") == 0) {
402 PrintF("relinquishing control to gdb\n");
403 v8::base::OS::DebugBreak();
404 PrintF("regaining control from gdb\n");
405 } else if (strcmp(cmd, "break") == 0) {
406 if (argc == 2) {
407 int32_t value;
408 if (GetValue(arg1, &value)) {
409 if (!SetBreakpoint(reinterpret_cast<Instruction*>(value))) {
410 PrintF("setting breakpoint failed\n");
411 }
412 } else {
413 PrintF("%s unrecognized\n", arg1);
414 }
415 } else {
416 PrintF("break <address>\n");
417 }
418 } else if (strcmp(cmd, "del") == 0) {
419 if (!DeleteBreakpoint(NULL)) {
420 PrintF("deleting breakpoint failed\n");
421 }
422 } else if (strcmp(cmd, "flags") == 0) {
423 PrintF("N flag: %d; ", sim_->n_flag_);
424 PrintF("Z flag: %d; ", sim_->z_flag_);
425 PrintF("C flag: %d; ", sim_->c_flag_);
426 PrintF("V flag: %d\n", sim_->v_flag_);
427 PrintF("INVALID OP flag: %d; ", sim_->inv_op_vfp_flag_);
428 PrintF("DIV BY ZERO flag: %d; ", sim_->div_zero_vfp_flag_);
429 PrintF("OVERFLOW flag: %d; ", sim_->overflow_vfp_flag_);
430 PrintF("UNDERFLOW flag: %d; ", sim_->underflow_vfp_flag_);
431 PrintF("INEXACT flag: %d;\n", sim_->inexact_vfp_flag_);
432 } else if (strcmp(cmd, "stop") == 0) {
433 int32_t value;
434 intptr_t stop_pc = sim_->get_pc() - 2 * Instruction::kInstrSize;
435 Instruction* stop_instr = reinterpret_cast<Instruction*>(stop_pc);
436 Instruction* msg_address =
437 reinterpret_cast<Instruction*>(stop_pc + Instruction::kInstrSize);
438 if ((argc == 2) && (strcmp(arg1, "unstop") == 0)) {
439 // Remove the current stop.
440 if (sim_->isStopInstruction(stop_instr)) {
441 stop_instr->SetInstructionBits(kNopInstr);
442 msg_address->SetInstructionBits(kNopInstr);
443 } else {
444 PrintF("Not at debugger stop.\n");
445 }
446 } else if (argc == 3) {
447 // Print information about all/the specified breakpoint(s).
448 if (strcmp(arg1, "info") == 0) {
449 if (strcmp(arg2, "all") == 0) {
450 PrintF("Stop information:\n");
451 for (uint32_t i = 0; i < sim_->kNumOfWatchedStops; i++) {
452 sim_->PrintStopInfo(i);
453 }
454 } else if (GetValue(arg2, &value)) {
455 sim_->PrintStopInfo(value);
456 } else {
457 PrintF("Unrecognized argument.\n");
458 }
459 } else if (strcmp(arg1, "enable") == 0) {
460 // Enable all/the specified breakpoint(s).
461 if (strcmp(arg2, "all") == 0) {
462 for (uint32_t i = 0; i < sim_->kNumOfWatchedStops; i++) {
463 sim_->EnableStop(i);
464 }
465 } else if (GetValue(arg2, &value)) {
466 sim_->EnableStop(value);
467 } else {
468 PrintF("Unrecognized argument.\n");
469 }
470 } else if (strcmp(arg1, "disable") == 0) {
471 // Disable all/the specified breakpoint(s).
472 if (strcmp(arg2, "all") == 0) {
473 for (uint32_t i = 0; i < sim_->kNumOfWatchedStops; i++) {
474 sim_->DisableStop(i);
475 }
476 } else if (GetValue(arg2, &value)) {
477 sim_->DisableStop(value);
478 } else {
479 PrintF("Unrecognized argument.\n");
480 }
481 }
482 } else {
483 PrintF("Wrong usage. Use help command for more information.\n");
484 }
485 } else if ((strcmp(cmd, "t") == 0) || strcmp(cmd, "trace") == 0) {
486 ::v8::internal::FLAG_trace_sim = !::v8::internal::FLAG_trace_sim;
487 PrintF("Trace of executed instructions is %s\n",
488 ::v8::internal::FLAG_trace_sim ? "on" : "off");
489 } else if ((strcmp(cmd, "h") == 0) || (strcmp(cmd, "help") == 0)) {
490 PrintF("cont\n");
491 PrintF(" continue execution (alias 'c')\n");
492 PrintF("stepi\n");
493 PrintF(" step one instruction (alias 'si')\n");
494 PrintF("print <register>\n");
495 PrintF(" print register content (alias 'p')\n");
496 PrintF(" use register name 'all' to print all registers\n");
497 PrintF(" add argument 'fp' to print register pair double values\n");
498 PrintF("printobject <register>\n");
499 PrintF(" print an object from a register (alias 'po')\n");
500 PrintF("flags\n");
501 PrintF(" print flags\n");
502 PrintF("stack [<words>]\n");
503 PrintF(" dump stack content, default dump 10 words)\n");
504 PrintF("mem <address> [<words>]\n");
505 PrintF(" dump memory content, default dump 10 words)\n");
506 PrintF("disasm [<instructions>]\n");
507 PrintF("disasm [<address/register>]\n");
508 PrintF("disasm [[<address/register>] <instructions>]\n");
509 PrintF(" disassemble code, default is 10 instructions\n");
510 PrintF(" from pc (alias 'di')\n");
511 PrintF("gdb\n");
512 PrintF(" enter gdb\n");
513 PrintF("break <address>\n");
514 PrintF(" set a break point on the address\n");
515 PrintF("del\n");
516 PrintF(" delete the breakpoint\n");
517 PrintF("trace (alias 't')\n");
518 PrintF(" toogle the tracing of all executed statements\n");
519 PrintF("stop feature:\n");
520 PrintF(" Description:\n");
521 PrintF(" Stops are debug instructions inserted by\n");
522 PrintF(" the Assembler::stop() function.\n");
523 PrintF(" When hitting a stop, the Simulator will\n");
524 PrintF(" stop and and give control to the ArmDebugger.\n");
525 PrintF(" The first %d stop codes are watched:\n",
526 Simulator::kNumOfWatchedStops);
527 PrintF(" - They can be enabled / disabled: the Simulator\n");
528 PrintF(" will / won't stop when hitting them.\n");
529 PrintF(" - The Simulator keeps track of how many times they \n");
530 PrintF(" are met. (See the info command.) Going over a\n");
531 PrintF(" disabled stop still increases its counter. \n");
532 PrintF(" Commands:\n");
533 PrintF(" stop info all/<code> : print infos about number <code>\n");
534 PrintF(" or all stop(s).\n");
535 PrintF(" stop enable/disable all/<code> : enables / disables\n");
536 PrintF(" all or number <code> stop(s)\n");
537 PrintF(" stop unstop\n");
538 PrintF(" ignore the stop instruction at the current location\n");
539 PrintF(" from now on\n");
540 } else {
541 PrintF("Unknown command: %s\n", cmd);
542 }
543 }
544 }
545
546 // Add all the breakpoints back to stop execution and enter the debugger
547 // shell when hit.
548 RedoBreakpoints();
549
550 #undef COMMAND_SIZE
551 #undef ARG_SIZE
552
553 #undef STR
554 #undef XSTR
555 }
556
557
ICacheMatch(void * one,void * two)558 static bool ICacheMatch(void* one, void* two) {
559 DCHECK((reinterpret_cast<intptr_t>(one) & CachePage::kPageMask) == 0);
560 DCHECK((reinterpret_cast<intptr_t>(two) & CachePage::kPageMask) == 0);
561 return one == two;
562 }
563
564
ICacheHash(void * key)565 static uint32_t ICacheHash(void* key) {
566 return static_cast<uint32_t>(reinterpret_cast<uintptr_t>(key)) >> 2;
567 }
568
569
AllOnOnePage(uintptr_t start,int size)570 static bool AllOnOnePage(uintptr_t start, int size) {
571 intptr_t start_page = (start & ~CachePage::kPageMask);
572 intptr_t end_page = ((start + size) & ~CachePage::kPageMask);
573 return start_page == end_page;
574 }
575
set_last_debugger_input(char * input)576 void Simulator::set_last_debugger_input(char* input) {
577 DeleteArray(last_debugger_input_);
578 last_debugger_input_ = input;
579 }
580
FlushICache(base::CustomMatcherHashMap * i_cache,void * start_addr,size_t size)581 void Simulator::FlushICache(base::CustomMatcherHashMap* i_cache,
582 void* start_addr, size_t size) {
583 intptr_t start = reinterpret_cast<intptr_t>(start_addr);
584 int intra_line = (start & CachePage::kLineMask);
585 start -= intra_line;
586 size += intra_line;
587 size = ((size - 1) | CachePage::kLineMask) + 1;
588 int offset = (start & CachePage::kPageMask);
589 while (!AllOnOnePage(start, size - 1)) {
590 int bytes_to_flush = CachePage::kPageSize - offset;
591 FlushOnePage(i_cache, start, bytes_to_flush);
592 start += bytes_to_flush;
593 size -= bytes_to_flush;
594 DCHECK_EQ(0, start & CachePage::kPageMask);
595 offset = 0;
596 }
597 if (size != 0) {
598 FlushOnePage(i_cache, start, size);
599 }
600 }
601
GetCachePage(base::CustomMatcherHashMap * i_cache,void * page)602 CachePage* Simulator::GetCachePage(base::CustomMatcherHashMap* i_cache,
603 void* page) {
604 base::HashMap::Entry* entry = i_cache->LookupOrInsert(page, ICacheHash(page));
605 if (entry->value == NULL) {
606 CachePage* new_page = new CachePage();
607 entry->value = new_page;
608 }
609 return reinterpret_cast<CachePage*>(entry->value);
610 }
611
612
613 // Flush from start up to and not including start + size.
FlushOnePage(base::CustomMatcherHashMap * i_cache,intptr_t start,int size)614 void Simulator::FlushOnePage(base::CustomMatcherHashMap* i_cache,
615 intptr_t start, int size) {
616 DCHECK(size <= CachePage::kPageSize);
617 DCHECK(AllOnOnePage(start, size - 1));
618 DCHECK((start & CachePage::kLineMask) == 0);
619 DCHECK((size & CachePage::kLineMask) == 0);
620 void* page = reinterpret_cast<void*>(start & (~CachePage::kPageMask));
621 int offset = (start & CachePage::kPageMask);
622 CachePage* cache_page = GetCachePage(i_cache, page);
623 char* valid_bytemap = cache_page->ValidityByte(offset);
624 memset(valid_bytemap, CachePage::LINE_INVALID, size >> CachePage::kLineShift);
625 }
626
CheckICache(base::CustomMatcherHashMap * i_cache,Instruction * instr)627 void Simulator::CheckICache(base::CustomMatcherHashMap* i_cache,
628 Instruction* instr) {
629 intptr_t address = reinterpret_cast<intptr_t>(instr);
630 void* page = reinterpret_cast<void*>(address & (~CachePage::kPageMask));
631 void* line = reinterpret_cast<void*>(address & (~CachePage::kLineMask));
632 int offset = (address & CachePage::kPageMask);
633 CachePage* cache_page = GetCachePage(i_cache, page);
634 char* cache_valid_byte = cache_page->ValidityByte(offset);
635 bool cache_hit = (*cache_valid_byte == CachePage::LINE_VALID);
636 char* cached_line = cache_page->CachedData(offset & ~CachePage::kLineMask);
637 if (cache_hit) {
638 // Check that the data in memory matches the contents of the I-cache.
639 CHECK_EQ(0,
640 memcmp(reinterpret_cast<void*>(instr),
641 cache_page->CachedData(offset), Instruction::kInstrSize));
642 } else {
643 // Cache miss. Load memory into the cache.
644 memcpy(cached_line, line, CachePage::kLineLength);
645 *cache_valid_byte = CachePage::LINE_VALID;
646 }
647 }
648
649
Initialize(Isolate * isolate)650 void Simulator::Initialize(Isolate* isolate) {
651 if (isolate->simulator_initialized()) return;
652 isolate->set_simulator_initialized(true);
653 ::v8::internal::ExternalReference::set_redirector(isolate,
654 &RedirectExternalReference);
655 }
656
657
Simulator(Isolate * isolate)658 Simulator::Simulator(Isolate* isolate) : isolate_(isolate) {
659 i_cache_ = isolate_->simulator_i_cache();
660 if (i_cache_ == NULL) {
661 i_cache_ = new base::CustomMatcherHashMap(&ICacheMatch);
662 isolate_->set_simulator_i_cache(i_cache_);
663 }
664 Initialize(isolate);
665 // Set up simulator support first. Some of this information is needed to
666 // setup the architecture state.
667 size_t stack_size = 1 * 1024*1024; // allocate 1MB for stack
668 stack_ = reinterpret_cast<char*>(malloc(stack_size));
669 pc_modified_ = false;
670 icount_ = 0;
671 break_pc_ = NULL;
672 break_instr_ = 0;
673
674 // Set up architecture state.
675 // All registers are initialized to zero to start with.
676 for (int i = 0; i < num_registers; i++) {
677 registers_[i] = 0;
678 }
679 n_flag_ = false;
680 z_flag_ = false;
681 c_flag_ = false;
682 v_flag_ = false;
683
684 // Initializing VFP registers.
685 // All registers are initialized to zero to start with
686 // even though s_registers_ & d_registers_ share the same
687 // physical registers in the target.
688 for (int i = 0; i < num_d_registers * 2; i++) {
689 vfp_registers_[i] = 0;
690 }
691 n_flag_FPSCR_ = false;
692 z_flag_FPSCR_ = false;
693 c_flag_FPSCR_ = false;
694 v_flag_FPSCR_ = false;
695 FPSCR_rounding_mode_ = RN;
696 FPSCR_default_NaN_mode_ = false;
697
698 inv_op_vfp_flag_ = false;
699 div_zero_vfp_flag_ = false;
700 overflow_vfp_flag_ = false;
701 underflow_vfp_flag_ = false;
702 inexact_vfp_flag_ = false;
703
704 // The sp is initialized to point to the bottom (high address) of the
705 // allocated stack area. To be safe in potential stack underflows we leave
706 // some buffer below.
707 registers_[sp] = reinterpret_cast<int32_t>(stack_) + stack_size - 64;
708 // The lr and pc are initialized to a known bad value that will cause an
709 // access violation if the simulator ever tries to execute it.
710 registers_[pc] = bad_lr;
711 registers_[lr] = bad_lr;
712
713 last_debugger_input_ = NULL;
714 }
715
~Simulator()716 Simulator::~Simulator() {
717 global_monitor_.Pointer()->RemoveProcessor(&global_monitor_processor_);
718 free(stack_);
719 }
720
721 // When the generated code calls an external reference we need to catch that in
722 // the simulator. The external reference will be a function compiled for the
723 // host architecture. We need to call that function instead of trying to
724 // execute it with the simulator. We do that by redirecting the external
725 // reference to a svc (Supervisor Call) instruction that is handled by
726 // the simulator. We write the original destination of the jump just at a known
727 // offset from the svc instruction so the simulator knows what to call.
728 class Redirection {
729 public:
Redirection(Isolate * isolate,void * external_function,ExternalReference::Type type)730 Redirection(Isolate* isolate, void* external_function,
731 ExternalReference::Type type)
732 : external_function_(external_function),
733 swi_instruction_(al | (0xf * B24) | kCallRtRedirected),
734 type_(type),
735 next_(NULL) {
736 next_ = isolate->simulator_redirection();
737 Simulator::current(isolate)->
738 FlushICache(isolate->simulator_i_cache(),
739 reinterpret_cast<void*>(&swi_instruction_),
740 Instruction::kInstrSize);
741 isolate->set_simulator_redirection(this);
742 }
743
address_of_swi_instruction()744 void* address_of_swi_instruction() {
745 return reinterpret_cast<void*>(&swi_instruction_);
746 }
747
external_function()748 void* external_function() { return external_function_; }
type()749 ExternalReference::Type type() { return type_; }
750
Get(Isolate * isolate,void * external_function,ExternalReference::Type type)751 static Redirection* Get(Isolate* isolate, void* external_function,
752 ExternalReference::Type type) {
753 Redirection* current = isolate->simulator_redirection();
754 for (; current != NULL; current = current->next_) {
755 if (current->external_function_ == external_function) {
756 DCHECK_EQ(current->type(), type);
757 return current;
758 }
759 }
760 return new Redirection(isolate, external_function, type);
761 }
762
FromSwiInstruction(Instruction * swi_instruction)763 static Redirection* FromSwiInstruction(Instruction* swi_instruction) {
764 char* addr_of_swi = reinterpret_cast<char*>(swi_instruction);
765 char* addr_of_redirection =
766 addr_of_swi - offsetof(Redirection, swi_instruction_);
767 return reinterpret_cast<Redirection*>(addr_of_redirection);
768 }
769
ReverseRedirection(int32_t reg)770 static void* ReverseRedirection(int32_t reg) {
771 Redirection* redirection = FromSwiInstruction(
772 reinterpret_cast<Instruction*>(reinterpret_cast<void*>(reg)));
773 return redirection->external_function();
774 }
775
DeleteChain(Redirection * redirection)776 static void DeleteChain(Redirection* redirection) {
777 while (redirection != nullptr) {
778 Redirection* next = redirection->next_;
779 delete redirection;
780 redirection = next;
781 }
782 }
783
784 private:
785 void* external_function_;
786 uint32_t swi_instruction_;
787 ExternalReference::Type type_;
788 Redirection* next_;
789 };
790
791
792 // static
TearDown(base::CustomMatcherHashMap * i_cache,Redirection * first)793 void Simulator::TearDown(base::CustomMatcherHashMap* i_cache,
794 Redirection* first) {
795 Redirection::DeleteChain(first);
796 if (i_cache != nullptr) {
797 for (base::HashMap::Entry* entry = i_cache->Start(); entry != nullptr;
798 entry = i_cache->Next(entry)) {
799 delete static_cast<CachePage*>(entry->value);
800 }
801 delete i_cache;
802 }
803 }
804
805
RedirectExternalReference(Isolate * isolate,void * external_function,ExternalReference::Type type)806 void* Simulator::RedirectExternalReference(Isolate* isolate,
807 void* external_function,
808 ExternalReference::Type type) {
809 Redirection* redirection = Redirection::Get(isolate, external_function, type);
810 return redirection->address_of_swi_instruction();
811 }
812
813
814 // Get the active Simulator for the current thread.
current(Isolate * isolate)815 Simulator* Simulator::current(Isolate* isolate) {
816 v8::internal::Isolate::PerIsolateThreadData* isolate_data =
817 isolate->FindOrAllocatePerThreadDataForThisThread();
818 DCHECK(isolate_data != NULL);
819
820 Simulator* sim = isolate_data->simulator();
821 if (sim == NULL) {
822 // TODO(146): delete the simulator object when a thread/isolate goes away.
823 sim = new Simulator(isolate);
824 isolate_data->set_simulator(sim);
825 }
826 return sim;
827 }
828
829
830 // Sets the register in the architecture state. It will also deal with updating
831 // Simulator internal state for special registers such as PC.
set_register(int reg,int32_t value)832 void Simulator::set_register(int reg, int32_t value) {
833 DCHECK((reg >= 0) && (reg < num_registers));
834 if (reg == pc) {
835 pc_modified_ = true;
836 }
837 registers_[reg] = value;
838 }
839
840
841 // Get the register from the architecture state. This function does handle
842 // the special case of accessing the PC register.
get_register(int reg) const843 int32_t Simulator::get_register(int reg) const {
844 DCHECK((reg >= 0) && (reg < num_registers));
845 // Stupid code added to avoid bug in GCC.
846 // See: http://gcc.gnu.org/bugzilla/show_bug.cgi?id=43949
847 if (reg >= num_registers) return 0;
848 // End stupid code.
849 return registers_[reg] + ((reg == pc) ? Instruction::kPCReadOffset : 0);
850 }
851
852
get_double_from_register_pair(int reg)853 double Simulator::get_double_from_register_pair(int reg) {
854 DCHECK((reg >= 0) && (reg < num_registers) && ((reg % 2) == 0));
855
856 double dm_val = 0.0;
857 // Read the bits from the unsigned integer register_[] array
858 // into the double precision floating point value and return it.
859 char buffer[2 * sizeof(vfp_registers_[0])];
860 memcpy(buffer, ®isters_[reg], 2 * sizeof(registers_[0]));
861 memcpy(&dm_val, buffer, 2 * sizeof(registers_[0]));
862 return(dm_val);
863 }
864
865
set_register_pair_from_double(int reg,double * value)866 void Simulator::set_register_pair_from_double(int reg, double* value) {
867 DCHECK((reg >= 0) && (reg < num_registers) && ((reg % 2) == 0));
868 memcpy(registers_ + reg, value, sizeof(*value));
869 }
870
871
set_dw_register(int dreg,const int * dbl)872 void Simulator::set_dw_register(int dreg, const int* dbl) {
873 DCHECK((dreg >= 0) && (dreg < num_d_registers));
874 registers_[dreg] = dbl[0];
875 registers_[dreg + 1] = dbl[1];
876 }
877
878
get_d_register(int dreg,uint64_t * value)879 void Simulator::get_d_register(int dreg, uint64_t* value) {
880 DCHECK((dreg >= 0) && (dreg < DwVfpRegister::NumRegisters()));
881 memcpy(value, vfp_registers_ + dreg * 2, sizeof(*value));
882 }
883
884
set_d_register(int dreg,const uint64_t * value)885 void Simulator::set_d_register(int dreg, const uint64_t* value) {
886 DCHECK((dreg >= 0) && (dreg < DwVfpRegister::NumRegisters()));
887 memcpy(vfp_registers_ + dreg * 2, value, sizeof(*value));
888 }
889
890
get_d_register(int dreg,uint32_t * value)891 void Simulator::get_d_register(int dreg, uint32_t* value) {
892 DCHECK((dreg >= 0) && (dreg < DwVfpRegister::NumRegisters()));
893 memcpy(value, vfp_registers_ + dreg * 2, sizeof(*value) * 2);
894 }
895
896
set_d_register(int dreg,const uint32_t * value)897 void Simulator::set_d_register(int dreg, const uint32_t* value) {
898 DCHECK((dreg >= 0) && (dreg < DwVfpRegister::NumRegisters()));
899 memcpy(vfp_registers_ + dreg * 2, value, sizeof(*value) * 2);
900 }
901
902 template <typename T>
get_q_register(int qreg,T * value)903 void Simulator::get_q_register(int qreg, T* value) {
904 DCHECK((qreg >= 0) && (qreg < num_q_registers));
905 memcpy(value, vfp_registers_ + qreg * 4, kSimd128Size);
906 }
907
908 template <typename T>
set_q_register(int qreg,const T * value)909 void Simulator::set_q_register(int qreg, const T* value) {
910 DCHECK((qreg >= 0) && (qreg < num_q_registers));
911 memcpy(vfp_registers_ + qreg * 4, value, kSimd128Size);
912 }
913
914
915 // Raw access to the PC register.
set_pc(int32_t value)916 void Simulator::set_pc(int32_t value) {
917 pc_modified_ = true;
918 registers_[pc] = value;
919 }
920
921
has_bad_pc() const922 bool Simulator::has_bad_pc() const {
923 return ((registers_[pc] == bad_lr) || (registers_[pc] == end_sim_pc));
924 }
925
926
927 // Raw access to the PC register without the special adjustment when reading.
get_pc() const928 int32_t Simulator::get_pc() const {
929 return registers_[pc];
930 }
931
932
933 // Getting from and setting into VFP registers.
set_s_register(int sreg,unsigned int value)934 void Simulator::set_s_register(int sreg, unsigned int value) {
935 DCHECK((sreg >= 0) && (sreg < num_s_registers));
936 vfp_registers_[sreg] = value;
937 }
938
939
get_s_register(int sreg) const940 unsigned int Simulator::get_s_register(int sreg) const {
941 DCHECK((sreg >= 0) && (sreg < num_s_registers));
942 return vfp_registers_[sreg];
943 }
944
945
946 template<class InputType, int register_size>
SetVFPRegister(int reg_index,const InputType & value)947 void Simulator::SetVFPRegister(int reg_index, const InputType& value) {
948 DCHECK(reg_index >= 0);
949 if (register_size == 1) DCHECK(reg_index < num_s_registers);
950 if (register_size == 2) DCHECK(reg_index < DwVfpRegister::NumRegisters());
951
952 char buffer[register_size * sizeof(vfp_registers_[0])];
953 memcpy(buffer, &value, register_size * sizeof(vfp_registers_[0]));
954 memcpy(&vfp_registers_[reg_index * register_size], buffer,
955 register_size * sizeof(vfp_registers_[0]));
956 }
957
958
959 template<class ReturnType, int register_size>
GetFromVFPRegister(int reg_index)960 ReturnType Simulator::GetFromVFPRegister(int reg_index) {
961 DCHECK(reg_index >= 0);
962 if (register_size == 1) DCHECK(reg_index < num_s_registers);
963 if (register_size == 2) DCHECK(reg_index < DwVfpRegister::NumRegisters());
964
965 ReturnType value = 0;
966 char buffer[register_size * sizeof(vfp_registers_[0])];
967 memcpy(buffer, &vfp_registers_[register_size * reg_index],
968 register_size * sizeof(vfp_registers_[0]));
969 memcpy(&value, buffer, register_size * sizeof(vfp_registers_[0]));
970 return value;
971 }
972
SetSpecialRegister(SRegisterFieldMask reg_and_mask,uint32_t value)973 void Simulator::SetSpecialRegister(SRegisterFieldMask reg_and_mask,
974 uint32_t value) {
975 // Only CPSR_f is implemented. Of that, only N, Z, C and V are implemented.
976 if ((reg_and_mask == CPSR_f) && ((value & ~kSpecialCondition) == 0)) {
977 n_flag_ = ((value & (1 << 31)) != 0);
978 z_flag_ = ((value & (1 << 30)) != 0);
979 c_flag_ = ((value & (1 << 29)) != 0);
980 v_flag_ = ((value & (1 << 28)) != 0);
981 } else {
982 UNIMPLEMENTED();
983 }
984 }
985
GetFromSpecialRegister(SRegister reg)986 uint32_t Simulator::GetFromSpecialRegister(SRegister reg) {
987 uint32_t result = 0;
988 // Only CPSR_f is implemented.
989 if (reg == CPSR) {
990 if (n_flag_) result |= (1 << 31);
991 if (z_flag_) result |= (1 << 30);
992 if (c_flag_) result |= (1 << 29);
993 if (v_flag_) result |= (1 << 28);
994 } else {
995 UNIMPLEMENTED();
996 }
997 return result;
998 }
999
1000 // Runtime FP routines take:
1001 // - two double arguments
1002 // - one double argument and zero or one integer arguments.
1003 // All are consructed here from r0-r3 or d0, d1 and r0.
GetFpArgs(double * x,double * y,int32_t * z)1004 void Simulator::GetFpArgs(double* x, double* y, int32_t* z) {
1005 if (use_eabi_hardfloat()) {
1006 *x = get_double_from_d_register(0);
1007 *y = get_double_from_d_register(1);
1008 *z = get_register(0);
1009 } else {
1010 // Registers 0 and 1 -> x.
1011 *x = get_double_from_register_pair(0);
1012 // Register 2 and 3 -> y.
1013 *y = get_double_from_register_pair(2);
1014 // Register 2 -> z
1015 *z = get_register(2);
1016 }
1017 }
1018
1019
1020 // The return value is either in r0/r1 or d0.
SetFpResult(const double & result)1021 void Simulator::SetFpResult(const double& result) {
1022 if (use_eabi_hardfloat()) {
1023 char buffer[2 * sizeof(vfp_registers_[0])];
1024 memcpy(buffer, &result, sizeof(buffer));
1025 // Copy result to d0.
1026 memcpy(vfp_registers_, buffer, sizeof(buffer));
1027 } else {
1028 char buffer[2 * sizeof(registers_[0])];
1029 memcpy(buffer, &result, sizeof(buffer));
1030 // Copy result to r0 and r1.
1031 memcpy(registers_, buffer, sizeof(buffer));
1032 }
1033 }
1034
1035
TrashCallerSaveRegisters()1036 void Simulator::TrashCallerSaveRegisters() {
1037 // We don't trash the registers with the return value.
1038 registers_[2] = 0x50Bad4U;
1039 registers_[3] = 0x50Bad4U;
1040 registers_[12] = 0x50Bad4U;
1041 }
1042
1043
ReadW(int32_t addr,Instruction * instr)1044 int Simulator::ReadW(int32_t addr, Instruction* instr) {
1045 // All supported ARM targets allow unaligned accesses, so we don't need to
1046 // check the alignment here.
1047 base::LockGuard<base::Mutex> lock_guard(&global_monitor_.Pointer()->mutex);
1048 local_monitor_.NotifyLoad(addr);
1049 intptr_t* ptr = reinterpret_cast<intptr_t*>(addr);
1050 return *ptr;
1051 }
1052
ReadExW(int32_t addr,Instruction * instr)1053 int Simulator::ReadExW(int32_t addr, Instruction* instr) {
1054 base::LockGuard<base::Mutex> lock_guard(&global_monitor_.Pointer()->mutex);
1055 local_monitor_.NotifyLoadExcl(addr, TransactionSize::Word);
1056 global_monitor_.Pointer()->NotifyLoadExcl_Locked(addr,
1057 &global_monitor_processor_);
1058 intptr_t* ptr = reinterpret_cast<intptr_t*>(addr);
1059 return *ptr;
1060 }
1061
WriteW(int32_t addr,int value,Instruction * instr)1062 void Simulator::WriteW(int32_t addr, int value, Instruction* instr) {
1063 // All supported ARM targets allow unaligned accesses, so we don't need to
1064 // check the alignment here.
1065 base::LockGuard<base::Mutex> lock_guard(&global_monitor_.Pointer()->mutex);
1066 local_monitor_.NotifyStore(addr);
1067 global_monitor_.Pointer()->NotifyStore_Locked(addr,
1068 &global_monitor_processor_);
1069 intptr_t* ptr = reinterpret_cast<intptr_t*>(addr);
1070 *ptr = value;
1071 }
1072
WriteExW(int32_t addr,int value,Instruction * instr)1073 int Simulator::WriteExW(int32_t addr, int value, Instruction* instr) {
1074 base::LockGuard<base::Mutex> lock_guard(&global_monitor_.Pointer()->mutex);
1075 if (local_monitor_.NotifyStoreExcl(addr, TransactionSize::Word) &&
1076 global_monitor_.Pointer()->NotifyStoreExcl_Locked(
1077 addr, &global_monitor_processor_)) {
1078 intptr_t* ptr = reinterpret_cast<intptr_t*>(addr);
1079 *ptr = value;
1080 return 0;
1081 } else {
1082 return 1;
1083 }
1084 }
1085
ReadHU(int32_t addr,Instruction * instr)1086 uint16_t Simulator::ReadHU(int32_t addr, Instruction* instr) {
1087 // All supported ARM targets allow unaligned accesses, so we don't need to
1088 // check the alignment here.
1089 base::LockGuard<base::Mutex> lock_guard(&global_monitor_.Pointer()->mutex);
1090 local_monitor_.NotifyLoad(addr);
1091 uint16_t* ptr = reinterpret_cast<uint16_t*>(addr);
1092 return *ptr;
1093 }
1094
ReadH(int32_t addr,Instruction * instr)1095 int16_t Simulator::ReadH(int32_t addr, Instruction* instr) {
1096 // All supported ARM targets allow unaligned accesses, so we don't need to
1097 // check the alignment here.
1098 base::LockGuard<base::Mutex> lock_guard(&global_monitor_.Pointer()->mutex);
1099 local_monitor_.NotifyLoad(addr);
1100 int16_t* ptr = reinterpret_cast<int16_t*>(addr);
1101 return *ptr;
1102 }
1103
ReadExHU(int32_t addr,Instruction * instr)1104 uint16_t Simulator::ReadExHU(int32_t addr, Instruction* instr) {
1105 base::LockGuard<base::Mutex> lock_guard(&global_monitor_.Pointer()->mutex);
1106 local_monitor_.NotifyLoadExcl(addr, TransactionSize::HalfWord);
1107 global_monitor_.Pointer()->NotifyLoadExcl_Locked(addr,
1108 &global_monitor_processor_);
1109 uint16_t* ptr = reinterpret_cast<uint16_t*>(addr);
1110 return *ptr;
1111 }
1112
WriteH(int32_t addr,uint16_t value,Instruction * instr)1113 void Simulator::WriteH(int32_t addr, uint16_t value, Instruction* instr) {
1114 // All supported ARM targets allow unaligned accesses, so we don't need to
1115 // check the alignment here.
1116 base::LockGuard<base::Mutex> lock_guard(&global_monitor_.Pointer()->mutex);
1117 local_monitor_.NotifyStore(addr);
1118 global_monitor_.Pointer()->NotifyStore_Locked(addr,
1119 &global_monitor_processor_);
1120 uint16_t* ptr = reinterpret_cast<uint16_t*>(addr);
1121 *ptr = value;
1122 }
1123
WriteH(int32_t addr,int16_t value,Instruction * instr)1124 void Simulator::WriteH(int32_t addr, int16_t value, Instruction* instr) {
1125 // All supported ARM targets allow unaligned accesses, so we don't need to
1126 // check the alignment here.
1127 base::LockGuard<base::Mutex> lock_guard(&global_monitor_.Pointer()->mutex);
1128 local_monitor_.NotifyStore(addr);
1129 global_monitor_.Pointer()->NotifyStore_Locked(addr,
1130 &global_monitor_processor_);
1131 int16_t* ptr = reinterpret_cast<int16_t*>(addr);
1132 *ptr = value;
1133 }
1134
WriteExH(int32_t addr,uint16_t value,Instruction * instr)1135 int Simulator::WriteExH(int32_t addr, uint16_t value, Instruction* instr) {
1136 base::LockGuard<base::Mutex> lock_guard(&global_monitor_.Pointer()->mutex);
1137 if (local_monitor_.NotifyStoreExcl(addr, TransactionSize::HalfWord) &&
1138 global_monitor_.Pointer()->NotifyStoreExcl_Locked(
1139 addr, &global_monitor_processor_)) {
1140 uint16_t* ptr = reinterpret_cast<uint16_t*>(addr);
1141 *ptr = value;
1142 return 0;
1143 } else {
1144 return 1;
1145 }
1146 }
1147
ReadBU(int32_t addr)1148 uint8_t Simulator::ReadBU(int32_t addr) {
1149 base::LockGuard<base::Mutex> lock_guard(&global_monitor_.Pointer()->mutex);
1150 local_monitor_.NotifyLoad(addr);
1151 uint8_t* ptr = reinterpret_cast<uint8_t*>(addr);
1152 return *ptr;
1153 }
1154
ReadB(int32_t addr)1155 int8_t Simulator::ReadB(int32_t addr) {
1156 base::LockGuard<base::Mutex> lock_guard(&global_monitor_.Pointer()->mutex);
1157 local_monitor_.NotifyLoad(addr);
1158 int8_t* ptr = reinterpret_cast<int8_t*>(addr);
1159 return *ptr;
1160 }
1161
ReadExBU(int32_t addr)1162 uint8_t Simulator::ReadExBU(int32_t addr) {
1163 base::LockGuard<base::Mutex> lock_guard(&global_monitor_.Pointer()->mutex);
1164 local_monitor_.NotifyLoadExcl(addr, TransactionSize::Byte);
1165 global_monitor_.Pointer()->NotifyLoadExcl_Locked(addr,
1166 &global_monitor_processor_);
1167 uint8_t* ptr = reinterpret_cast<uint8_t*>(addr);
1168 return *ptr;
1169 }
1170
WriteB(int32_t addr,uint8_t value)1171 void Simulator::WriteB(int32_t addr, uint8_t value) {
1172 base::LockGuard<base::Mutex> lock_guard(&global_monitor_.Pointer()->mutex);
1173 local_monitor_.NotifyStore(addr);
1174 global_monitor_.Pointer()->NotifyStore_Locked(addr,
1175 &global_monitor_processor_);
1176 uint8_t* ptr = reinterpret_cast<uint8_t*>(addr);
1177 *ptr = value;
1178 }
1179
WriteB(int32_t addr,int8_t value)1180 void Simulator::WriteB(int32_t addr, int8_t value) {
1181 base::LockGuard<base::Mutex> lock_guard(&global_monitor_.Pointer()->mutex);
1182 local_monitor_.NotifyStore(addr);
1183 global_monitor_.Pointer()->NotifyStore_Locked(addr,
1184 &global_monitor_processor_);
1185 int8_t* ptr = reinterpret_cast<int8_t*>(addr);
1186 *ptr = value;
1187 }
1188
WriteExB(int32_t addr,uint8_t value)1189 int Simulator::WriteExB(int32_t addr, uint8_t value) {
1190 base::LockGuard<base::Mutex> lock_guard(&global_monitor_.Pointer()->mutex);
1191 if (local_monitor_.NotifyStoreExcl(addr, TransactionSize::Byte) &&
1192 global_monitor_.Pointer()->NotifyStoreExcl_Locked(
1193 addr, &global_monitor_processor_)) {
1194 uint8_t* ptr = reinterpret_cast<uint8_t*>(addr);
1195 *ptr = value;
1196 return 0;
1197 } else {
1198 return 1;
1199 }
1200 }
1201
ReadDW(int32_t addr)1202 int32_t* Simulator::ReadDW(int32_t addr) {
1203 // All supported ARM targets allow unaligned accesses, so we don't need to
1204 // check the alignment here.
1205 base::LockGuard<base::Mutex> lock_guard(&global_monitor_.Pointer()->mutex);
1206 local_monitor_.NotifyLoad(addr);
1207 int32_t* ptr = reinterpret_cast<int32_t*>(addr);
1208 return ptr;
1209 }
1210
1211
WriteDW(int32_t addr,int32_t value1,int32_t value2)1212 void Simulator::WriteDW(int32_t addr, int32_t value1, int32_t value2) {
1213 // All supported ARM targets allow unaligned accesses, so we don't need to
1214 // check the alignment here.
1215 base::LockGuard<base::Mutex> lock_guard(&global_monitor_.Pointer()->mutex);
1216 local_monitor_.NotifyStore(addr);
1217 global_monitor_.Pointer()->NotifyStore_Locked(addr,
1218 &global_monitor_processor_);
1219 int32_t* ptr = reinterpret_cast<int32_t*>(addr);
1220 *ptr++ = value1;
1221 *ptr = value2;
1222 }
1223
1224
1225 // Returns the limit of the stack area to enable checking for stack overflows.
StackLimit(uintptr_t c_limit) const1226 uintptr_t Simulator::StackLimit(uintptr_t c_limit) const {
1227 // The simulator uses a separate JS stack. If we have exhausted the C stack,
1228 // we also drop down the JS limit to reflect the exhaustion on the JS stack.
1229 if (GetCurrentStackPosition() < c_limit) {
1230 return reinterpret_cast<uintptr_t>(get_sp());
1231 }
1232
1233 // Otherwise the limit is the JS stack. Leave a safety margin of 1024 bytes
1234 // to prevent overrunning the stack when pushing values.
1235 return reinterpret_cast<uintptr_t>(stack_) + 1024;
1236 }
1237
1238
1239 // Unsupported instructions use Format to print an error and stop execution.
Format(Instruction * instr,const char * format)1240 void Simulator::Format(Instruction* instr, const char* format) {
1241 PrintF("Simulator found unsupported instruction:\n 0x%08" V8PRIxPTR ": %s\n",
1242 reinterpret_cast<intptr_t>(instr), format);
1243 UNIMPLEMENTED();
1244 }
1245
1246
1247 // Checks if the current instruction should be executed based on its
1248 // condition bits.
ConditionallyExecute(Instruction * instr)1249 bool Simulator::ConditionallyExecute(Instruction* instr) {
1250 switch (instr->ConditionField()) {
1251 case eq: return z_flag_;
1252 case ne: return !z_flag_;
1253 case cs: return c_flag_;
1254 case cc: return !c_flag_;
1255 case mi: return n_flag_;
1256 case pl: return !n_flag_;
1257 case vs: return v_flag_;
1258 case vc: return !v_flag_;
1259 case hi: return c_flag_ && !z_flag_;
1260 case ls: return !c_flag_ || z_flag_;
1261 case ge: return n_flag_ == v_flag_;
1262 case lt: return n_flag_ != v_flag_;
1263 case gt: return !z_flag_ && (n_flag_ == v_flag_);
1264 case le: return z_flag_ || (n_flag_ != v_flag_);
1265 case al: return true;
1266 default: UNREACHABLE();
1267 }
1268 return false;
1269 }
1270
1271
1272 // Calculate and set the Negative and Zero flags.
SetNZFlags(int32_t val)1273 void Simulator::SetNZFlags(int32_t val) {
1274 n_flag_ = (val < 0);
1275 z_flag_ = (val == 0);
1276 }
1277
1278
1279 // Set the Carry flag.
SetCFlag(bool val)1280 void Simulator::SetCFlag(bool val) {
1281 c_flag_ = val;
1282 }
1283
1284
1285 // Set the oVerflow flag.
SetVFlag(bool val)1286 void Simulator::SetVFlag(bool val) {
1287 v_flag_ = val;
1288 }
1289
1290
1291 // Calculate C flag value for additions.
CarryFrom(int32_t left,int32_t right,int32_t carry)1292 bool Simulator::CarryFrom(int32_t left, int32_t right, int32_t carry) {
1293 uint32_t uleft = static_cast<uint32_t>(left);
1294 uint32_t uright = static_cast<uint32_t>(right);
1295 uint32_t urest = 0xffffffffU - uleft;
1296
1297 return (uright > urest) ||
1298 (carry && (((uright + 1) > urest) || (uright > (urest - 1))));
1299 }
1300
1301
1302 // Calculate C flag value for subtractions.
BorrowFrom(int32_t left,int32_t right,int32_t carry)1303 bool Simulator::BorrowFrom(int32_t left, int32_t right, int32_t carry) {
1304 uint32_t uleft = static_cast<uint32_t>(left);
1305 uint32_t uright = static_cast<uint32_t>(right);
1306
1307 return (uright > uleft) ||
1308 (!carry && (((uright + 1) > uleft) || (uright > (uleft - 1))));
1309 }
1310
1311
1312 // Calculate V flag value for additions and subtractions.
OverflowFrom(int32_t alu_out,int32_t left,int32_t right,bool addition)1313 bool Simulator::OverflowFrom(int32_t alu_out,
1314 int32_t left, int32_t right, bool addition) {
1315 bool overflow;
1316 if (addition) {
1317 // operands have the same sign
1318 overflow = ((left >= 0 && right >= 0) || (left < 0 && right < 0))
1319 // and operands and result have different sign
1320 && ((left < 0 && alu_out >= 0) || (left >= 0 && alu_out < 0));
1321 } else {
1322 // operands have different signs
1323 overflow = ((left < 0 && right >= 0) || (left >= 0 && right < 0))
1324 // and first operand and result have different signs
1325 && ((left < 0 && alu_out >= 0) || (left >= 0 && alu_out < 0));
1326 }
1327 return overflow;
1328 }
1329
1330
1331 // Support for VFP comparisons.
Compute_FPSCR_Flags(float val1,float val2)1332 void Simulator::Compute_FPSCR_Flags(float val1, float val2) {
1333 if (std::isnan(val1) || std::isnan(val2)) {
1334 n_flag_FPSCR_ = false;
1335 z_flag_FPSCR_ = false;
1336 c_flag_FPSCR_ = true;
1337 v_flag_FPSCR_ = true;
1338 // All non-NaN cases.
1339 } else if (val1 == val2) {
1340 n_flag_FPSCR_ = false;
1341 z_flag_FPSCR_ = true;
1342 c_flag_FPSCR_ = true;
1343 v_flag_FPSCR_ = false;
1344 } else if (val1 < val2) {
1345 n_flag_FPSCR_ = true;
1346 z_flag_FPSCR_ = false;
1347 c_flag_FPSCR_ = false;
1348 v_flag_FPSCR_ = false;
1349 } else {
1350 // Case when (val1 > val2).
1351 n_flag_FPSCR_ = false;
1352 z_flag_FPSCR_ = false;
1353 c_flag_FPSCR_ = true;
1354 v_flag_FPSCR_ = false;
1355 }
1356 }
1357
1358
Compute_FPSCR_Flags(double val1,double val2)1359 void Simulator::Compute_FPSCR_Flags(double val1, double val2) {
1360 if (std::isnan(val1) || std::isnan(val2)) {
1361 n_flag_FPSCR_ = false;
1362 z_flag_FPSCR_ = false;
1363 c_flag_FPSCR_ = true;
1364 v_flag_FPSCR_ = true;
1365 // All non-NaN cases.
1366 } else if (val1 == val2) {
1367 n_flag_FPSCR_ = false;
1368 z_flag_FPSCR_ = true;
1369 c_flag_FPSCR_ = true;
1370 v_flag_FPSCR_ = false;
1371 } else if (val1 < val2) {
1372 n_flag_FPSCR_ = true;
1373 z_flag_FPSCR_ = false;
1374 c_flag_FPSCR_ = false;
1375 v_flag_FPSCR_ = false;
1376 } else {
1377 // Case when (val1 > val2).
1378 n_flag_FPSCR_ = false;
1379 z_flag_FPSCR_ = false;
1380 c_flag_FPSCR_ = true;
1381 v_flag_FPSCR_ = false;
1382 }
1383 }
1384
1385
Copy_FPSCR_to_APSR()1386 void Simulator::Copy_FPSCR_to_APSR() {
1387 n_flag_ = n_flag_FPSCR_;
1388 z_flag_ = z_flag_FPSCR_;
1389 c_flag_ = c_flag_FPSCR_;
1390 v_flag_ = v_flag_FPSCR_;
1391 }
1392
1393
1394 // Addressing Mode 1 - Data-processing operands:
1395 // Get the value based on the shifter_operand with register.
GetShiftRm(Instruction * instr,bool * carry_out)1396 int32_t Simulator::GetShiftRm(Instruction* instr, bool* carry_out) {
1397 ShiftOp shift = instr->ShiftField();
1398 int shift_amount = instr->ShiftAmountValue();
1399 int32_t result = get_register(instr->RmValue());
1400 if (instr->Bit(4) == 0) {
1401 // by immediate
1402 if ((shift == ROR) && (shift_amount == 0)) {
1403 UNIMPLEMENTED();
1404 return result;
1405 } else if (((shift == LSR) || (shift == ASR)) && (shift_amount == 0)) {
1406 shift_amount = 32;
1407 }
1408 switch (shift) {
1409 case ASR: {
1410 if (shift_amount == 0) {
1411 if (result < 0) {
1412 result = 0xffffffff;
1413 *carry_out = true;
1414 } else {
1415 result = 0;
1416 *carry_out = false;
1417 }
1418 } else {
1419 result >>= (shift_amount - 1);
1420 *carry_out = (result & 1) == 1;
1421 result >>= 1;
1422 }
1423 break;
1424 }
1425
1426 case LSL: {
1427 if (shift_amount == 0) {
1428 *carry_out = c_flag_;
1429 } else {
1430 result <<= (shift_amount - 1);
1431 *carry_out = (result < 0);
1432 result <<= 1;
1433 }
1434 break;
1435 }
1436
1437 case LSR: {
1438 if (shift_amount == 0) {
1439 result = 0;
1440 *carry_out = c_flag_;
1441 } else {
1442 uint32_t uresult = static_cast<uint32_t>(result);
1443 uresult >>= (shift_amount - 1);
1444 *carry_out = (uresult & 1) == 1;
1445 uresult >>= 1;
1446 result = static_cast<int32_t>(uresult);
1447 }
1448 break;
1449 }
1450
1451 case ROR: {
1452 if (shift_amount == 0) {
1453 *carry_out = c_flag_;
1454 } else {
1455 uint32_t left = static_cast<uint32_t>(result) >> shift_amount;
1456 uint32_t right = static_cast<uint32_t>(result) << (32 - shift_amount);
1457 result = right | left;
1458 *carry_out = (static_cast<uint32_t>(result) >> 31) != 0;
1459 }
1460 break;
1461 }
1462
1463 default: {
1464 UNREACHABLE();
1465 break;
1466 }
1467 }
1468 } else {
1469 // by register
1470 int rs = instr->RsValue();
1471 shift_amount = get_register(rs) &0xff;
1472 switch (shift) {
1473 case ASR: {
1474 if (shift_amount == 0) {
1475 *carry_out = c_flag_;
1476 } else if (shift_amount < 32) {
1477 result >>= (shift_amount - 1);
1478 *carry_out = (result & 1) == 1;
1479 result >>= 1;
1480 } else {
1481 DCHECK(shift_amount >= 32);
1482 if (result < 0) {
1483 *carry_out = true;
1484 result = 0xffffffff;
1485 } else {
1486 *carry_out = false;
1487 result = 0;
1488 }
1489 }
1490 break;
1491 }
1492
1493 case LSL: {
1494 if (shift_amount == 0) {
1495 *carry_out = c_flag_;
1496 } else if (shift_amount < 32) {
1497 result <<= (shift_amount - 1);
1498 *carry_out = (result < 0);
1499 result <<= 1;
1500 } else if (shift_amount == 32) {
1501 *carry_out = (result & 1) == 1;
1502 result = 0;
1503 } else {
1504 DCHECK(shift_amount > 32);
1505 *carry_out = false;
1506 result = 0;
1507 }
1508 break;
1509 }
1510
1511 case LSR: {
1512 if (shift_amount == 0) {
1513 *carry_out = c_flag_;
1514 } else if (shift_amount < 32) {
1515 uint32_t uresult = static_cast<uint32_t>(result);
1516 uresult >>= (shift_amount - 1);
1517 *carry_out = (uresult & 1) == 1;
1518 uresult >>= 1;
1519 result = static_cast<int32_t>(uresult);
1520 } else if (shift_amount == 32) {
1521 *carry_out = (result < 0);
1522 result = 0;
1523 } else {
1524 *carry_out = false;
1525 result = 0;
1526 }
1527 break;
1528 }
1529
1530 case ROR: {
1531 if (shift_amount == 0) {
1532 *carry_out = c_flag_;
1533 } else {
1534 uint32_t left = static_cast<uint32_t>(result) >> shift_amount;
1535 uint32_t right = static_cast<uint32_t>(result) << (32 - shift_amount);
1536 result = right | left;
1537 *carry_out = (static_cast<uint32_t>(result) >> 31) != 0;
1538 }
1539 break;
1540 }
1541
1542 default: {
1543 UNREACHABLE();
1544 break;
1545 }
1546 }
1547 }
1548 return result;
1549 }
1550
1551
1552 // Addressing Mode 1 - Data-processing operands:
1553 // Get the value based on the shifter_operand with immediate.
GetImm(Instruction * instr,bool * carry_out)1554 int32_t Simulator::GetImm(Instruction* instr, bool* carry_out) {
1555 int rotate = instr->RotateValue() * 2;
1556 int immed8 = instr->Immed8Value();
1557 int imm = base::bits::RotateRight32(immed8, rotate);
1558 *carry_out = (rotate == 0) ? c_flag_ : (imm < 0);
1559 return imm;
1560 }
1561
1562
count_bits(int bit_vector)1563 static int count_bits(int bit_vector) {
1564 int count = 0;
1565 while (bit_vector != 0) {
1566 if ((bit_vector & 1) != 0) {
1567 count++;
1568 }
1569 bit_vector >>= 1;
1570 }
1571 return count;
1572 }
1573
1574
ProcessPU(Instruction * instr,int num_regs,int reg_size,intptr_t * start_address,intptr_t * end_address)1575 int32_t Simulator::ProcessPU(Instruction* instr,
1576 int num_regs,
1577 int reg_size,
1578 intptr_t* start_address,
1579 intptr_t* end_address) {
1580 int rn = instr->RnValue();
1581 int32_t rn_val = get_register(rn);
1582 switch (instr->PUField()) {
1583 case da_x: {
1584 UNIMPLEMENTED();
1585 break;
1586 }
1587 case ia_x: {
1588 *start_address = rn_val;
1589 *end_address = rn_val + (num_regs * reg_size) - reg_size;
1590 rn_val = rn_val + (num_regs * reg_size);
1591 break;
1592 }
1593 case db_x: {
1594 *start_address = rn_val - (num_regs * reg_size);
1595 *end_address = rn_val - reg_size;
1596 rn_val = *start_address;
1597 break;
1598 }
1599 case ib_x: {
1600 *start_address = rn_val + reg_size;
1601 *end_address = rn_val + (num_regs * reg_size);
1602 rn_val = *end_address;
1603 break;
1604 }
1605 default: {
1606 UNREACHABLE();
1607 break;
1608 }
1609 }
1610 return rn_val;
1611 }
1612
1613
1614 // Addressing Mode 4 - Load and Store Multiple
HandleRList(Instruction * instr,bool load)1615 void Simulator::HandleRList(Instruction* instr, bool load) {
1616 int rlist = instr->RlistValue();
1617 int num_regs = count_bits(rlist);
1618
1619 intptr_t start_address = 0;
1620 intptr_t end_address = 0;
1621 int32_t rn_val =
1622 ProcessPU(instr, num_regs, kPointerSize, &start_address, &end_address);
1623
1624 intptr_t* address = reinterpret_cast<intptr_t*>(start_address);
1625 // Catch null pointers a little earlier.
1626 DCHECK(start_address > 8191 || start_address < 0);
1627 int reg = 0;
1628 while (rlist != 0) {
1629 if ((rlist & 1) != 0) {
1630 if (load) {
1631 set_register(reg, *address);
1632 } else {
1633 *address = get_register(reg);
1634 }
1635 address += 1;
1636 }
1637 reg++;
1638 rlist >>= 1;
1639 }
1640 DCHECK(end_address == ((intptr_t)address) - 4);
1641 if (instr->HasW()) {
1642 set_register(instr->RnValue(), rn_val);
1643 }
1644 }
1645
1646
1647 // Addressing Mode 6 - Load and Store Multiple Coprocessor registers.
HandleVList(Instruction * instr)1648 void Simulator::HandleVList(Instruction* instr) {
1649 VFPRegPrecision precision =
1650 (instr->SzValue() == 0) ? kSinglePrecision : kDoublePrecision;
1651 int operand_size = (precision == kSinglePrecision) ? 4 : 8;
1652
1653 bool load = (instr->VLValue() == 0x1);
1654
1655 int vd;
1656 int num_regs;
1657 vd = instr->VFPDRegValue(precision);
1658 if (precision == kSinglePrecision) {
1659 num_regs = instr->Immed8Value();
1660 } else {
1661 num_regs = instr->Immed8Value() / 2;
1662 }
1663
1664 intptr_t start_address = 0;
1665 intptr_t end_address = 0;
1666 int32_t rn_val =
1667 ProcessPU(instr, num_regs, operand_size, &start_address, &end_address);
1668
1669 intptr_t* address = reinterpret_cast<intptr_t*>(start_address);
1670 for (int reg = vd; reg < vd + num_regs; reg++) {
1671 if (precision == kSinglePrecision) {
1672 if (load) {
1673 set_s_register_from_sinteger(
1674 reg, ReadW(reinterpret_cast<int32_t>(address), instr));
1675 } else {
1676 WriteW(reinterpret_cast<int32_t>(address),
1677 get_sinteger_from_s_register(reg), instr);
1678 }
1679 address += 1;
1680 } else {
1681 if (load) {
1682 int32_t data[] = {
1683 ReadW(reinterpret_cast<int32_t>(address), instr),
1684 ReadW(reinterpret_cast<int32_t>(address + 1), instr)
1685 };
1686 set_d_register(reg, reinterpret_cast<uint32_t*>(data));
1687 } else {
1688 uint32_t data[2];
1689 get_d_register(reg, data);
1690 WriteW(reinterpret_cast<int32_t>(address), data[0], instr);
1691 WriteW(reinterpret_cast<int32_t>(address + 1), data[1], instr);
1692 }
1693 address += 2;
1694 }
1695 }
1696 DCHECK(reinterpret_cast<intptr_t>(address) - operand_size == end_address);
1697 if (instr->HasW()) {
1698 set_register(instr->RnValue(), rn_val);
1699 }
1700 }
1701
1702
1703 // Calls into the V8 runtime are based on this very simple interface.
1704 // Note: To be able to return two values from some calls the code in runtime.cc
1705 // uses the ObjectPair which is essentially two 32-bit values stuffed into a
1706 // 64-bit value. With the code below we assume that all runtime calls return
1707 // 64 bits of result. If they don't, the r1 result register contains a bogus
1708 // value, which is fine because it is caller-saved.
1709 typedef int64_t (*SimulatorRuntimeCall)(int32_t arg0,
1710 int32_t arg1,
1711 int32_t arg2,
1712 int32_t arg3,
1713 int32_t arg4,
1714 int32_t arg5);
1715
1716 typedef ObjectTriple (*SimulatorRuntimeTripleCall)(int32_t arg0, int32_t arg1,
1717 int32_t arg2, int32_t arg3,
1718 int32_t arg4);
1719
1720 // These prototypes handle the four types of FP calls.
1721 typedef int64_t (*SimulatorRuntimeCompareCall)(double darg0, double darg1);
1722 typedef double (*SimulatorRuntimeFPFPCall)(double darg0, double darg1);
1723 typedef double (*SimulatorRuntimeFPCall)(double darg0);
1724 typedef double (*SimulatorRuntimeFPIntCall)(double darg0, int32_t arg0);
1725
1726 // This signature supports direct call in to API function native callback
1727 // (refer to InvocationCallback in v8.h).
1728 typedef void (*SimulatorRuntimeDirectApiCall)(int32_t arg0);
1729 typedef void (*SimulatorRuntimeProfilingApiCall)(int32_t arg0, void* arg1);
1730
1731 // This signature supports direct call to accessor getter callback.
1732 typedef void (*SimulatorRuntimeDirectGetterCall)(int32_t arg0, int32_t arg1);
1733 typedef void (*SimulatorRuntimeProfilingGetterCall)(
1734 int32_t arg0, int32_t arg1, void* arg2);
1735
1736 // Software interrupt instructions are used by the simulator to call into the
1737 // C-based V8 runtime.
SoftwareInterrupt(Instruction * instr)1738 void Simulator::SoftwareInterrupt(Instruction* instr) {
1739 int svc = instr->SvcValue();
1740 switch (svc) {
1741 case kCallRtRedirected: {
1742 // Check if stack is aligned. Error if not aligned is reported below to
1743 // include information on the function called.
1744 bool stack_aligned =
1745 (get_register(sp)
1746 & (::v8::internal::FLAG_sim_stack_alignment - 1)) == 0;
1747 Redirection* redirection = Redirection::FromSwiInstruction(instr);
1748 int32_t arg0 = get_register(r0);
1749 int32_t arg1 = get_register(r1);
1750 int32_t arg2 = get_register(r2);
1751 int32_t arg3 = get_register(r3);
1752 int32_t* stack_pointer = reinterpret_cast<int32_t*>(get_register(sp));
1753 int32_t arg4 = stack_pointer[0];
1754 int32_t arg5 = stack_pointer[1];
1755 bool fp_call =
1756 (redirection->type() == ExternalReference::BUILTIN_FP_FP_CALL) ||
1757 (redirection->type() == ExternalReference::BUILTIN_COMPARE_CALL) ||
1758 (redirection->type() == ExternalReference::BUILTIN_FP_CALL) ||
1759 (redirection->type() == ExternalReference::BUILTIN_FP_INT_CALL);
1760 // This is dodgy but it works because the C entry stubs are never moved.
1761 // See comment in codegen-arm.cc and bug 1242173.
1762 int32_t saved_lr = get_register(lr);
1763 intptr_t external =
1764 reinterpret_cast<intptr_t>(redirection->external_function());
1765 if (fp_call) {
1766 double dval0, dval1; // one or two double parameters
1767 int32_t ival; // zero or one integer parameters
1768 int64_t iresult = 0; // integer return value
1769 double dresult = 0; // double return value
1770 GetFpArgs(&dval0, &dval1, &ival);
1771 if (::v8::internal::FLAG_trace_sim || !stack_aligned) {
1772 SimulatorRuntimeCall generic_target =
1773 reinterpret_cast<SimulatorRuntimeCall>(external);
1774 switch (redirection->type()) {
1775 case ExternalReference::BUILTIN_FP_FP_CALL:
1776 case ExternalReference::BUILTIN_COMPARE_CALL:
1777 PrintF("Call to host function at %p with args %f, %f",
1778 static_cast<void*>(FUNCTION_ADDR(generic_target)), dval0,
1779 dval1);
1780 break;
1781 case ExternalReference::BUILTIN_FP_CALL:
1782 PrintF("Call to host function at %p with arg %f",
1783 static_cast<void*>(FUNCTION_ADDR(generic_target)), dval0);
1784 break;
1785 case ExternalReference::BUILTIN_FP_INT_CALL:
1786 PrintF("Call to host function at %p with args %f, %d",
1787 static_cast<void*>(FUNCTION_ADDR(generic_target)), dval0,
1788 ival);
1789 break;
1790 default:
1791 UNREACHABLE();
1792 break;
1793 }
1794 if (!stack_aligned) {
1795 PrintF(" with unaligned stack %08x\n", get_register(sp));
1796 }
1797 PrintF("\n");
1798 }
1799 CHECK(stack_aligned);
1800 switch (redirection->type()) {
1801 case ExternalReference::BUILTIN_COMPARE_CALL: {
1802 SimulatorRuntimeCompareCall target =
1803 reinterpret_cast<SimulatorRuntimeCompareCall>(external);
1804 iresult = target(dval0, dval1);
1805 set_register(r0, static_cast<int32_t>(iresult));
1806 set_register(r1, static_cast<int32_t>(iresult >> 32));
1807 break;
1808 }
1809 case ExternalReference::BUILTIN_FP_FP_CALL: {
1810 SimulatorRuntimeFPFPCall target =
1811 reinterpret_cast<SimulatorRuntimeFPFPCall>(external);
1812 dresult = target(dval0, dval1);
1813 SetFpResult(dresult);
1814 break;
1815 }
1816 case ExternalReference::BUILTIN_FP_CALL: {
1817 SimulatorRuntimeFPCall target =
1818 reinterpret_cast<SimulatorRuntimeFPCall>(external);
1819 dresult = target(dval0);
1820 SetFpResult(dresult);
1821 break;
1822 }
1823 case ExternalReference::BUILTIN_FP_INT_CALL: {
1824 SimulatorRuntimeFPIntCall target =
1825 reinterpret_cast<SimulatorRuntimeFPIntCall>(external);
1826 dresult = target(dval0, ival);
1827 SetFpResult(dresult);
1828 break;
1829 }
1830 default:
1831 UNREACHABLE();
1832 break;
1833 }
1834 if (::v8::internal::FLAG_trace_sim || !stack_aligned) {
1835 switch (redirection->type()) {
1836 case ExternalReference::BUILTIN_COMPARE_CALL:
1837 PrintF("Returned %08x\n", static_cast<int32_t>(iresult));
1838 break;
1839 case ExternalReference::BUILTIN_FP_FP_CALL:
1840 case ExternalReference::BUILTIN_FP_CALL:
1841 case ExternalReference::BUILTIN_FP_INT_CALL:
1842 PrintF("Returned %f\n", dresult);
1843 break;
1844 default:
1845 UNREACHABLE();
1846 break;
1847 }
1848 }
1849 } else if (redirection->type() == ExternalReference::DIRECT_API_CALL) {
1850 if (::v8::internal::FLAG_trace_sim || !stack_aligned) {
1851 PrintF("Call to host function at %p args %08x",
1852 reinterpret_cast<void*>(external), arg0);
1853 if (!stack_aligned) {
1854 PrintF(" with unaligned stack %08x\n", get_register(sp));
1855 }
1856 PrintF("\n");
1857 }
1858 CHECK(stack_aligned);
1859 SimulatorRuntimeDirectApiCall target =
1860 reinterpret_cast<SimulatorRuntimeDirectApiCall>(external);
1861 target(arg0);
1862 } else if (
1863 redirection->type() == ExternalReference::PROFILING_API_CALL) {
1864 if (::v8::internal::FLAG_trace_sim || !stack_aligned) {
1865 PrintF("Call to host function at %p args %08x %08x",
1866 reinterpret_cast<void*>(external), arg0, arg1);
1867 if (!stack_aligned) {
1868 PrintF(" with unaligned stack %08x\n", get_register(sp));
1869 }
1870 PrintF("\n");
1871 }
1872 CHECK(stack_aligned);
1873 SimulatorRuntimeProfilingApiCall target =
1874 reinterpret_cast<SimulatorRuntimeProfilingApiCall>(external);
1875 target(arg0, Redirection::ReverseRedirection(arg1));
1876 } else if (
1877 redirection->type() == ExternalReference::DIRECT_GETTER_CALL) {
1878 if (::v8::internal::FLAG_trace_sim || !stack_aligned) {
1879 PrintF("Call to host function at %p args %08x %08x",
1880 reinterpret_cast<void*>(external), arg0, arg1);
1881 if (!stack_aligned) {
1882 PrintF(" with unaligned stack %08x\n", get_register(sp));
1883 }
1884 PrintF("\n");
1885 }
1886 CHECK(stack_aligned);
1887 SimulatorRuntimeDirectGetterCall target =
1888 reinterpret_cast<SimulatorRuntimeDirectGetterCall>(external);
1889 target(arg0, arg1);
1890 } else if (
1891 redirection->type() == ExternalReference::PROFILING_GETTER_CALL) {
1892 if (::v8::internal::FLAG_trace_sim || !stack_aligned) {
1893 PrintF("Call to host function at %p args %08x %08x %08x",
1894 reinterpret_cast<void*>(external), arg0, arg1, arg2);
1895 if (!stack_aligned) {
1896 PrintF(" with unaligned stack %08x\n", get_register(sp));
1897 }
1898 PrintF("\n");
1899 }
1900 CHECK(stack_aligned);
1901 SimulatorRuntimeProfilingGetterCall target =
1902 reinterpret_cast<SimulatorRuntimeProfilingGetterCall>(
1903 external);
1904 target(arg0, arg1, Redirection::ReverseRedirection(arg2));
1905 } else if (redirection->type() ==
1906 ExternalReference::BUILTIN_CALL_TRIPLE) {
1907 // builtin call returning ObjectTriple.
1908 SimulatorRuntimeTripleCall target =
1909 reinterpret_cast<SimulatorRuntimeTripleCall>(external);
1910 if (::v8::internal::FLAG_trace_sim || !stack_aligned) {
1911 PrintF(
1912 "Call to host triple returning runtime function %p "
1913 "args %08x, %08x, %08x, %08x, %08x",
1914 static_cast<void*>(FUNCTION_ADDR(target)), arg1, arg2, arg3, arg4,
1915 arg5);
1916 if (!stack_aligned) {
1917 PrintF(" with unaligned stack %08x\n", get_register(sp));
1918 }
1919 PrintF("\n");
1920 }
1921 CHECK(stack_aligned);
1922 // arg0 is a hidden argument pointing to the return location, so don't
1923 // pass it to the target function.
1924 ObjectTriple result = target(arg1, arg2, arg3, arg4, arg5);
1925 if (::v8::internal::FLAG_trace_sim) {
1926 PrintF("Returned { %p, %p, %p }\n", static_cast<void*>(result.x),
1927 static_cast<void*>(result.y), static_cast<void*>(result.z));
1928 }
1929 // Return is passed back in address pointed to by hidden first argument.
1930 ObjectTriple* sim_result = reinterpret_cast<ObjectTriple*>(arg0);
1931 *sim_result = result;
1932 set_register(r0, arg0);
1933 } else {
1934 // builtin call.
1935 DCHECK(redirection->type() == ExternalReference::BUILTIN_CALL ||
1936 redirection->type() == ExternalReference::BUILTIN_CALL_PAIR);
1937 SimulatorRuntimeCall target =
1938 reinterpret_cast<SimulatorRuntimeCall>(external);
1939 if (::v8::internal::FLAG_trace_sim || !stack_aligned) {
1940 PrintF(
1941 "Call to host function at %p "
1942 "args %08x, %08x, %08x, %08x, %08x, %08x",
1943 static_cast<void*>(FUNCTION_ADDR(target)), arg0, arg1, arg2, arg3,
1944 arg4, arg5);
1945 if (!stack_aligned) {
1946 PrintF(" with unaligned stack %08x\n", get_register(sp));
1947 }
1948 PrintF("\n");
1949 }
1950 CHECK(stack_aligned);
1951 int64_t result = target(arg0, arg1, arg2, arg3, arg4, arg5);
1952 int32_t lo_res = static_cast<int32_t>(result);
1953 int32_t hi_res = static_cast<int32_t>(result >> 32);
1954 if (::v8::internal::FLAG_trace_sim) {
1955 PrintF("Returned %08x\n", lo_res);
1956 }
1957 set_register(r0, lo_res);
1958 set_register(r1, hi_res);
1959 }
1960 set_register(lr, saved_lr);
1961 set_pc(get_register(lr));
1962 break;
1963 }
1964 case kBreakpoint: {
1965 ArmDebugger dbg(this);
1966 dbg.Debug();
1967 break;
1968 }
1969 // stop uses all codes greater than 1 << 23.
1970 default: {
1971 if (svc >= (1 << 23)) {
1972 uint32_t code = svc & kStopCodeMask;
1973 if (isWatchedStop(code)) {
1974 IncreaseStopCounter(code);
1975 }
1976 // Stop if it is enabled, otherwise go on jumping over the stop
1977 // and the message address.
1978 if (isEnabledStop(code)) {
1979 ArmDebugger dbg(this);
1980 dbg.Stop(instr);
1981 } else {
1982 set_pc(get_pc() + 2 * Instruction::kInstrSize);
1983 }
1984 } else {
1985 // This is not a valid svc code.
1986 UNREACHABLE();
1987 break;
1988 }
1989 }
1990 }
1991 }
1992
1993
canonicalizeNaN(float value)1994 float Simulator::canonicalizeNaN(float value) {
1995 // Default NaN value, see "NaN handling" in "IEEE 754 standard implementation
1996 // choices" of the ARM Reference Manual.
1997 const uint32_t kDefaultNaN = 0x7FC00000u;
1998 if (FPSCR_default_NaN_mode_ && std::isnan(value)) {
1999 value = bit_cast<float>(kDefaultNaN);
2000 }
2001 return value;
2002 }
2003
2004
canonicalizeNaN(double value)2005 double Simulator::canonicalizeNaN(double value) {
2006 // Default NaN value, see "NaN handling" in "IEEE 754 standard implementation
2007 // choices" of the ARM Reference Manual.
2008 const uint64_t kDefaultNaN = V8_UINT64_C(0x7FF8000000000000);
2009 if (FPSCR_default_NaN_mode_ && std::isnan(value)) {
2010 value = bit_cast<double>(kDefaultNaN);
2011 }
2012 return value;
2013 }
2014
2015
2016 // Stop helper functions.
isStopInstruction(Instruction * instr)2017 bool Simulator::isStopInstruction(Instruction* instr) {
2018 return (instr->Bits(27, 24) == 0xF) && (instr->SvcValue() >= kStopCode);
2019 }
2020
2021
isWatchedStop(uint32_t code)2022 bool Simulator::isWatchedStop(uint32_t code) {
2023 DCHECK(code <= kMaxStopCode);
2024 return code < kNumOfWatchedStops;
2025 }
2026
2027
isEnabledStop(uint32_t code)2028 bool Simulator::isEnabledStop(uint32_t code) {
2029 DCHECK(code <= kMaxStopCode);
2030 // Unwatched stops are always enabled.
2031 return !isWatchedStop(code) ||
2032 !(watched_stops_[code].count & kStopDisabledBit);
2033 }
2034
2035
EnableStop(uint32_t code)2036 void Simulator::EnableStop(uint32_t code) {
2037 DCHECK(isWatchedStop(code));
2038 if (!isEnabledStop(code)) {
2039 watched_stops_[code].count &= ~kStopDisabledBit;
2040 }
2041 }
2042
2043
DisableStop(uint32_t code)2044 void Simulator::DisableStop(uint32_t code) {
2045 DCHECK(isWatchedStop(code));
2046 if (isEnabledStop(code)) {
2047 watched_stops_[code].count |= kStopDisabledBit;
2048 }
2049 }
2050
2051
IncreaseStopCounter(uint32_t code)2052 void Simulator::IncreaseStopCounter(uint32_t code) {
2053 DCHECK(code <= kMaxStopCode);
2054 DCHECK(isWatchedStop(code));
2055 if ((watched_stops_[code].count & ~(1 << 31)) == 0x7fffffff) {
2056 PrintF("Stop counter for code %i has overflowed.\n"
2057 "Enabling this code and reseting the counter to 0.\n", code);
2058 watched_stops_[code].count = 0;
2059 EnableStop(code);
2060 } else {
2061 watched_stops_[code].count++;
2062 }
2063 }
2064
2065
2066 // Print a stop status.
PrintStopInfo(uint32_t code)2067 void Simulator::PrintStopInfo(uint32_t code) {
2068 DCHECK(code <= kMaxStopCode);
2069 if (!isWatchedStop(code)) {
2070 PrintF("Stop not watched.");
2071 } else {
2072 const char* state = isEnabledStop(code) ? "Enabled" : "Disabled";
2073 int32_t count = watched_stops_[code].count & ~kStopDisabledBit;
2074 // Don't print the state of unused breakpoints.
2075 if (count != 0) {
2076 if (watched_stops_[code].desc) {
2077 PrintF("stop %i - 0x%x: \t%s, \tcounter = %i, \t%s\n",
2078 code, code, state, count, watched_stops_[code].desc);
2079 } else {
2080 PrintF("stop %i - 0x%x: \t%s, \tcounter = %i\n",
2081 code, code, state, count);
2082 }
2083 }
2084 }
2085 }
2086
2087
2088 // Handle execution based on instruction types.
2089
2090 // Instruction types 0 and 1 are both rolled into one function because they
2091 // only differ in the handling of the shifter_operand.
DecodeType01(Instruction * instr)2092 void Simulator::DecodeType01(Instruction* instr) {
2093 int type = instr->TypeValue();
2094 if ((type == 0) && instr->IsSpecialType0()) {
2095 // multiply instruction or extra loads and stores
2096 if (instr->Bits(7, 4) == 9) {
2097 if (instr->Bit(24) == 0) {
2098 // Raw field decoding here. Multiply instructions have their Rd in
2099 // funny places.
2100 int rn = instr->RnValue();
2101 int rm = instr->RmValue();
2102 int rs = instr->RsValue();
2103 int32_t rs_val = get_register(rs);
2104 int32_t rm_val = get_register(rm);
2105 if (instr->Bit(23) == 0) {
2106 if (instr->Bit(21) == 0) {
2107 // The MUL instruction description (A 4.1.33) refers to Rd as being
2108 // the destination for the operation, but it confusingly uses the
2109 // Rn field to encode it.
2110 // Format(instr, "mul'cond's 'rn, 'rm, 'rs");
2111 int rd = rn; // Remap the rn field to the Rd register.
2112 int32_t alu_out = rm_val * rs_val;
2113 set_register(rd, alu_out);
2114 if (instr->HasS()) {
2115 SetNZFlags(alu_out);
2116 }
2117 } else {
2118 int rd = instr->RdValue();
2119 int32_t acc_value = get_register(rd);
2120 if (instr->Bit(22) == 0) {
2121 // The MLA instruction description (A 4.1.28) refers to the order
2122 // of registers as "Rd, Rm, Rs, Rn". But confusingly it uses the
2123 // Rn field to encode the Rd register and the Rd field to encode
2124 // the Rn register.
2125 // Format(instr, "mla'cond's 'rn, 'rm, 'rs, 'rd");
2126 int32_t mul_out = rm_val * rs_val;
2127 int32_t result = acc_value + mul_out;
2128 set_register(rn, result);
2129 } else {
2130 // Format(instr, "mls'cond's 'rn, 'rm, 'rs, 'rd");
2131 int32_t mul_out = rm_val * rs_val;
2132 int32_t result = acc_value - mul_out;
2133 set_register(rn, result);
2134 }
2135 }
2136 } else {
2137 // The signed/long multiply instructions use the terms RdHi and RdLo
2138 // when referring to the target registers. They are mapped to the Rn
2139 // and Rd fields as follows:
2140 // RdLo == Rd
2141 // RdHi == Rn (This is confusingly stored in variable rd here
2142 // because the mul instruction from above uses the
2143 // Rn field to encode the Rd register. Good luck figuring
2144 // this out without reading the ARM instruction manual
2145 // at a very detailed level.)
2146 // Format(instr, "'um'al'cond's 'rd, 'rn, 'rs, 'rm");
2147 int rd_hi = rn; // Remap the rn field to the RdHi register.
2148 int rd_lo = instr->RdValue();
2149 int32_t hi_res = 0;
2150 int32_t lo_res = 0;
2151 if (instr->Bit(22) == 1) {
2152 int64_t left_op = static_cast<int32_t>(rm_val);
2153 int64_t right_op = static_cast<int32_t>(rs_val);
2154 uint64_t result = left_op * right_op;
2155 hi_res = static_cast<int32_t>(result >> 32);
2156 lo_res = static_cast<int32_t>(result & 0xffffffff);
2157 } else {
2158 // unsigned multiply
2159 uint64_t left_op = static_cast<uint32_t>(rm_val);
2160 uint64_t right_op = static_cast<uint32_t>(rs_val);
2161 uint64_t result = left_op * right_op;
2162 hi_res = static_cast<int32_t>(result >> 32);
2163 lo_res = static_cast<int32_t>(result & 0xffffffff);
2164 }
2165 set_register(rd_lo, lo_res);
2166 set_register(rd_hi, hi_res);
2167 if (instr->HasS()) {
2168 UNIMPLEMENTED();
2169 }
2170 }
2171 } else {
2172 if (instr->Bits(24, 23) == 3) {
2173 if (instr->Bit(20) == 1) {
2174 // ldrex
2175 int rt = instr->RtValue();
2176 int rn = instr->RnValue();
2177 int32_t addr = get_register(rn);
2178 switch (instr->Bits(22, 21)) {
2179 case 0: {
2180 // Format(instr, "ldrex'cond 'rt, ['rn]");
2181 int value = ReadExW(addr, instr);
2182 set_register(rt, value);
2183 break;
2184 }
2185 case 2: {
2186 // Format(instr, "ldrexb'cond 'rt, ['rn]");
2187 uint8_t value = ReadExBU(addr);
2188 set_register(rt, value);
2189 break;
2190 }
2191 case 3: {
2192 // Format(instr, "ldrexh'cond 'rt, ['rn]");
2193 uint16_t value = ReadExHU(addr, instr);
2194 set_register(rt, value);
2195 break;
2196 }
2197 default:
2198 UNREACHABLE();
2199 break;
2200 }
2201 } else {
2202 // The instruction is documented as strex rd, rt, [rn], but the
2203 // "rt" register is using the rm bits.
2204 int rd = instr->RdValue();
2205 int rt = instr->RmValue();
2206 int rn = instr->RnValue();
2207 int32_t addr = get_register(rn);
2208 switch (instr->Bits(22, 21)) {
2209 case 0: {
2210 // Format(instr, "strex'cond 'rd, 'rm, ['rn]");
2211 int value = get_register(rt);
2212 int status = WriteExW(addr, value, instr);
2213 set_register(rd, status);
2214 break;
2215 }
2216 case 2: {
2217 // Format(instr, "strexb'cond 'rd, 'rm, ['rn]");
2218 uint8_t value = get_register(rt);
2219 int status = WriteExB(addr, value);
2220 set_register(rd, status);
2221 break;
2222 }
2223 case 3: {
2224 // Format(instr, "strexh'cond 'rd, 'rm, ['rn]");
2225 uint16_t value = get_register(rt);
2226 int status = WriteExH(addr, value, instr);
2227 set_register(rd, status);
2228 break;
2229 }
2230 default:
2231 UNREACHABLE();
2232 break;
2233 }
2234 }
2235 } else {
2236 UNIMPLEMENTED(); // Not used by V8.
2237 }
2238 }
2239 } else {
2240 // extra load/store instructions
2241 int rd = instr->RdValue();
2242 int rn = instr->RnValue();
2243 int32_t rn_val = get_register(rn);
2244 int32_t addr = 0;
2245 if (instr->Bit(22) == 0) {
2246 int rm = instr->RmValue();
2247 int32_t rm_val = get_register(rm);
2248 switch (instr->PUField()) {
2249 case da_x: {
2250 // Format(instr, "'memop'cond'sign'h 'rd, ['rn], -'rm");
2251 DCHECK(!instr->HasW());
2252 addr = rn_val;
2253 rn_val -= rm_val;
2254 set_register(rn, rn_val);
2255 break;
2256 }
2257 case ia_x: {
2258 // Format(instr, "'memop'cond'sign'h 'rd, ['rn], +'rm");
2259 DCHECK(!instr->HasW());
2260 addr = rn_val;
2261 rn_val += rm_val;
2262 set_register(rn, rn_val);
2263 break;
2264 }
2265 case db_x: {
2266 // Format(instr, "'memop'cond'sign'h 'rd, ['rn, -'rm]'w");
2267 rn_val -= rm_val;
2268 addr = rn_val;
2269 if (instr->HasW()) {
2270 set_register(rn, rn_val);
2271 }
2272 break;
2273 }
2274 case ib_x: {
2275 // Format(instr, "'memop'cond'sign'h 'rd, ['rn, +'rm]'w");
2276 rn_val += rm_val;
2277 addr = rn_val;
2278 if (instr->HasW()) {
2279 set_register(rn, rn_val);
2280 }
2281 break;
2282 }
2283 default: {
2284 // The PU field is a 2-bit field.
2285 UNREACHABLE();
2286 break;
2287 }
2288 }
2289 } else {
2290 int32_t imm_val = (instr->ImmedHValue() << 4) | instr->ImmedLValue();
2291 switch (instr->PUField()) {
2292 case da_x: {
2293 // Format(instr, "'memop'cond'sign'h 'rd, ['rn], #-'off8");
2294 DCHECK(!instr->HasW());
2295 addr = rn_val;
2296 rn_val -= imm_val;
2297 set_register(rn, rn_val);
2298 break;
2299 }
2300 case ia_x: {
2301 // Format(instr, "'memop'cond'sign'h 'rd, ['rn], #+'off8");
2302 DCHECK(!instr->HasW());
2303 addr = rn_val;
2304 rn_val += imm_val;
2305 set_register(rn, rn_val);
2306 break;
2307 }
2308 case db_x: {
2309 // Format(instr, "'memop'cond'sign'h 'rd, ['rn, #-'off8]'w");
2310 rn_val -= imm_val;
2311 addr = rn_val;
2312 if (instr->HasW()) {
2313 set_register(rn, rn_val);
2314 }
2315 break;
2316 }
2317 case ib_x: {
2318 // Format(instr, "'memop'cond'sign'h 'rd, ['rn, #+'off8]'w");
2319 rn_val += imm_val;
2320 addr = rn_val;
2321 if (instr->HasW()) {
2322 set_register(rn, rn_val);
2323 }
2324 break;
2325 }
2326 default: {
2327 // The PU field is a 2-bit field.
2328 UNREACHABLE();
2329 break;
2330 }
2331 }
2332 }
2333 if (((instr->Bits(7, 4) & 0xd) == 0xd) && (instr->Bit(20) == 0)) {
2334 DCHECK((rd % 2) == 0);
2335 if (instr->HasH()) {
2336 // The strd instruction.
2337 int32_t value1 = get_register(rd);
2338 int32_t value2 = get_register(rd+1);
2339 WriteDW(addr, value1, value2);
2340 } else {
2341 // The ldrd instruction.
2342 int* rn_data = ReadDW(addr);
2343 set_dw_register(rd, rn_data);
2344 }
2345 } else if (instr->HasH()) {
2346 if (instr->HasSign()) {
2347 if (instr->HasL()) {
2348 int16_t val = ReadH(addr, instr);
2349 set_register(rd, val);
2350 } else {
2351 int16_t val = get_register(rd);
2352 WriteH(addr, val, instr);
2353 }
2354 } else {
2355 if (instr->HasL()) {
2356 uint16_t val = ReadHU(addr, instr);
2357 set_register(rd, val);
2358 } else {
2359 uint16_t val = get_register(rd);
2360 WriteH(addr, val, instr);
2361 }
2362 }
2363 } else {
2364 // signed byte loads
2365 DCHECK(instr->HasSign());
2366 DCHECK(instr->HasL());
2367 int8_t val = ReadB(addr);
2368 set_register(rd, val);
2369 }
2370 return;
2371 }
2372 } else if ((type == 0) && instr->IsMiscType0()) {
2373 if ((instr->Bits(27, 23) == 2) && (instr->Bits(21, 20) == 2) &&
2374 (instr->Bits(15, 4) == 0xf00)) {
2375 // MSR
2376 int rm = instr->RmValue();
2377 DCHECK_NE(pc, rm); // UNPREDICTABLE
2378 SRegisterFieldMask sreg_and_mask =
2379 instr->BitField(22, 22) | instr->BitField(19, 16);
2380 SetSpecialRegister(sreg_and_mask, get_register(rm));
2381 } else if ((instr->Bits(27, 23) == 2) && (instr->Bits(21, 20) == 0) &&
2382 (instr->Bits(11, 0) == 0)) {
2383 // MRS
2384 int rd = instr->RdValue();
2385 DCHECK_NE(pc, rd); // UNPREDICTABLE
2386 SRegister sreg = static_cast<SRegister>(instr->BitField(22, 22));
2387 set_register(rd, GetFromSpecialRegister(sreg));
2388 } else if (instr->Bits(22, 21) == 1) {
2389 int rm = instr->RmValue();
2390 switch (instr->BitField(7, 4)) {
2391 case BX:
2392 set_pc(get_register(rm));
2393 break;
2394 case BLX: {
2395 uint32_t old_pc = get_pc();
2396 set_pc(get_register(rm));
2397 set_register(lr, old_pc + Instruction::kInstrSize);
2398 break;
2399 }
2400 case BKPT: {
2401 ArmDebugger dbg(this);
2402 PrintF("Simulator hit BKPT.\n");
2403 dbg.Debug();
2404 break;
2405 }
2406 default:
2407 UNIMPLEMENTED();
2408 }
2409 } else if (instr->Bits(22, 21) == 3) {
2410 int rm = instr->RmValue();
2411 int rd = instr->RdValue();
2412 switch (instr->BitField(7, 4)) {
2413 case CLZ: {
2414 uint32_t bits = get_register(rm);
2415 int leading_zeros = 0;
2416 if (bits == 0) {
2417 leading_zeros = 32;
2418 } else {
2419 while ((bits & 0x80000000u) == 0) {
2420 bits <<= 1;
2421 leading_zeros++;
2422 }
2423 }
2424 set_register(rd, leading_zeros);
2425 break;
2426 }
2427 default:
2428 UNIMPLEMENTED();
2429 }
2430 } else {
2431 PrintF("%08x\n", instr->InstructionBits());
2432 UNIMPLEMENTED();
2433 }
2434 } else if ((type == 1) && instr->IsNopType1()) {
2435 // NOP.
2436 } else {
2437 int rd = instr->RdValue();
2438 int rn = instr->RnValue();
2439 int32_t rn_val = get_register(rn);
2440 int32_t shifter_operand = 0;
2441 bool shifter_carry_out = 0;
2442 if (type == 0) {
2443 shifter_operand = GetShiftRm(instr, &shifter_carry_out);
2444 } else {
2445 DCHECK(instr->TypeValue() == 1);
2446 shifter_operand = GetImm(instr, &shifter_carry_out);
2447 }
2448 int32_t alu_out;
2449
2450 switch (instr->OpcodeField()) {
2451 case AND: {
2452 // Format(instr, "and'cond's 'rd, 'rn, 'shift_rm");
2453 // Format(instr, "and'cond's 'rd, 'rn, 'imm");
2454 alu_out = rn_val & shifter_operand;
2455 set_register(rd, alu_out);
2456 if (instr->HasS()) {
2457 SetNZFlags(alu_out);
2458 SetCFlag(shifter_carry_out);
2459 }
2460 break;
2461 }
2462
2463 case EOR: {
2464 // Format(instr, "eor'cond's 'rd, 'rn, 'shift_rm");
2465 // Format(instr, "eor'cond's 'rd, 'rn, 'imm");
2466 alu_out = rn_val ^ shifter_operand;
2467 set_register(rd, alu_out);
2468 if (instr->HasS()) {
2469 SetNZFlags(alu_out);
2470 SetCFlag(shifter_carry_out);
2471 }
2472 break;
2473 }
2474
2475 case SUB: {
2476 // Format(instr, "sub'cond's 'rd, 'rn, 'shift_rm");
2477 // Format(instr, "sub'cond's 'rd, 'rn, 'imm");
2478 alu_out = rn_val - shifter_operand;
2479 set_register(rd, alu_out);
2480 if (instr->HasS()) {
2481 SetNZFlags(alu_out);
2482 SetCFlag(!BorrowFrom(rn_val, shifter_operand));
2483 SetVFlag(OverflowFrom(alu_out, rn_val, shifter_operand, false));
2484 }
2485 break;
2486 }
2487
2488 case RSB: {
2489 // Format(instr, "rsb'cond's 'rd, 'rn, 'shift_rm");
2490 // Format(instr, "rsb'cond's 'rd, 'rn, 'imm");
2491 alu_out = shifter_operand - rn_val;
2492 set_register(rd, alu_out);
2493 if (instr->HasS()) {
2494 SetNZFlags(alu_out);
2495 SetCFlag(!BorrowFrom(shifter_operand, rn_val));
2496 SetVFlag(OverflowFrom(alu_out, shifter_operand, rn_val, false));
2497 }
2498 break;
2499 }
2500
2501 case ADD: {
2502 // Format(instr, "add'cond's 'rd, 'rn, 'shift_rm");
2503 // Format(instr, "add'cond's 'rd, 'rn, 'imm");
2504 alu_out = rn_val + shifter_operand;
2505 set_register(rd, alu_out);
2506 if (instr->HasS()) {
2507 SetNZFlags(alu_out);
2508 SetCFlag(CarryFrom(rn_val, shifter_operand));
2509 SetVFlag(OverflowFrom(alu_out, rn_val, shifter_operand, true));
2510 }
2511 break;
2512 }
2513
2514 case ADC: {
2515 // Format(instr, "adc'cond's 'rd, 'rn, 'shift_rm");
2516 // Format(instr, "adc'cond's 'rd, 'rn, 'imm");
2517 alu_out = rn_val + shifter_operand + GetCarry();
2518 set_register(rd, alu_out);
2519 if (instr->HasS()) {
2520 SetNZFlags(alu_out);
2521 SetCFlag(CarryFrom(rn_val, shifter_operand, GetCarry()));
2522 SetVFlag(OverflowFrom(alu_out, rn_val, shifter_operand, true));
2523 }
2524 break;
2525 }
2526
2527 case SBC: {
2528 // Format(instr, "sbc'cond's 'rd, 'rn, 'shift_rm");
2529 // Format(instr, "sbc'cond's 'rd, 'rn, 'imm");
2530 alu_out = (rn_val - shifter_operand) - (GetCarry() ? 0 : 1);
2531 set_register(rd, alu_out);
2532 if (instr->HasS()) {
2533 SetNZFlags(alu_out);
2534 SetCFlag(!BorrowFrom(rn_val, shifter_operand, GetCarry()));
2535 SetVFlag(OverflowFrom(alu_out, rn_val, shifter_operand, false));
2536 }
2537 break;
2538 }
2539
2540 case RSC: {
2541 Format(instr, "rsc'cond's 'rd, 'rn, 'shift_rm");
2542 Format(instr, "rsc'cond's 'rd, 'rn, 'imm");
2543 break;
2544 }
2545
2546 case TST: {
2547 if (instr->HasS()) {
2548 // Format(instr, "tst'cond 'rn, 'shift_rm");
2549 // Format(instr, "tst'cond 'rn, 'imm");
2550 alu_out = rn_val & shifter_operand;
2551 SetNZFlags(alu_out);
2552 SetCFlag(shifter_carry_out);
2553 } else {
2554 // Format(instr, "movw'cond 'rd, 'imm").
2555 alu_out = instr->ImmedMovwMovtValue();
2556 set_register(rd, alu_out);
2557 }
2558 break;
2559 }
2560
2561 case TEQ: {
2562 if (instr->HasS()) {
2563 // Format(instr, "teq'cond 'rn, 'shift_rm");
2564 // Format(instr, "teq'cond 'rn, 'imm");
2565 alu_out = rn_val ^ shifter_operand;
2566 SetNZFlags(alu_out);
2567 SetCFlag(shifter_carry_out);
2568 } else {
2569 // Other instructions matching this pattern are handled in the
2570 // miscellaneous instructions part above.
2571 UNREACHABLE();
2572 }
2573 break;
2574 }
2575
2576 case CMP: {
2577 if (instr->HasS()) {
2578 // Format(instr, "cmp'cond 'rn, 'shift_rm");
2579 // Format(instr, "cmp'cond 'rn, 'imm");
2580 alu_out = rn_val - shifter_operand;
2581 SetNZFlags(alu_out);
2582 SetCFlag(!BorrowFrom(rn_val, shifter_operand));
2583 SetVFlag(OverflowFrom(alu_out, rn_val, shifter_operand, false));
2584 } else {
2585 // Format(instr, "movt'cond 'rd, 'imm").
2586 alu_out = (get_register(rd) & 0xffff) |
2587 (instr->ImmedMovwMovtValue() << 16);
2588 set_register(rd, alu_out);
2589 }
2590 break;
2591 }
2592
2593 case CMN: {
2594 if (instr->HasS()) {
2595 // Format(instr, "cmn'cond 'rn, 'shift_rm");
2596 // Format(instr, "cmn'cond 'rn, 'imm");
2597 alu_out = rn_val + shifter_operand;
2598 SetNZFlags(alu_out);
2599 SetCFlag(CarryFrom(rn_val, shifter_operand));
2600 SetVFlag(OverflowFrom(alu_out, rn_val, shifter_operand, true));
2601 } else {
2602 // Other instructions matching this pattern are handled in the
2603 // miscellaneous instructions part above.
2604 UNREACHABLE();
2605 }
2606 break;
2607 }
2608
2609 case ORR: {
2610 // Format(instr, "orr'cond's 'rd, 'rn, 'shift_rm");
2611 // Format(instr, "orr'cond's 'rd, 'rn, 'imm");
2612 alu_out = rn_val | shifter_operand;
2613 set_register(rd, alu_out);
2614 if (instr->HasS()) {
2615 SetNZFlags(alu_out);
2616 SetCFlag(shifter_carry_out);
2617 }
2618 break;
2619 }
2620
2621 case MOV: {
2622 // Format(instr, "mov'cond's 'rd, 'shift_rm");
2623 // Format(instr, "mov'cond's 'rd, 'imm");
2624 alu_out = shifter_operand;
2625 set_register(rd, alu_out);
2626 if (instr->HasS()) {
2627 SetNZFlags(alu_out);
2628 SetCFlag(shifter_carry_out);
2629 }
2630 break;
2631 }
2632
2633 case BIC: {
2634 // Format(instr, "bic'cond's 'rd, 'rn, 'shift_rm");
2635 // Format(instr, "bic'cond's 'rd, 'rn, 'imm");
2636 alu_out = rn_val & ~shifter_operand;
2637 set_register(rd, alu_out);
2638 if (instr->HasS()) {
2639 SetNZFlags(alu_out);
2640 SetCFlag(shifter_carry_out);
2641 }
2642 break;
2643 }
2644
2645 case MVN: {
2646 // Format(instr, "mvn'cond's 'rd, 'shift_rm");
2647 // Format(instr, "mvn'cond's 'rd, 'imm");
2648 alu_out = ~shifter_operand;
2649 set_register(rd, alu_out);
2650 if (instr->HasS()) {
2651 SetNZFlags(alu_out);
2652 SetCFlag(shifter_carry_out);
2653 }
2654 break;
2655 }
2656
2657 default: {
2658 UNREACHABLE();
2659 break;
2660 }
2661 }
2662 }
2663 }
2664
2665
DecodeType2(Instruction * instr)2666 void Simulator::DecodeType2(Instruction* instr) {
2667 int rd = instr->RdValue();
2668 int rn = instr->RnValue();
2669 int32_t rn_val = get_register(rn);
2670 int32_t im_val = instr->Offset12Value();
2671 int32_t addr = 0;
2672 switch (instr->PUField()) {
2673 case da_x: {
2674 // Format(instr, "'memop'cond'b 'rd, ['rn], #-'off12");
2675 DCHECK(!instr->HasW());
2676 addr = rn_val;
2677 rn_val -= im_val;
2678 set_register(rn, rn_val);
2679 break;
2680 }
2681 case ia_x: {
2682 // Format(instr, "'memop'cond'b 'rd, ['rn], #+'off12");
2683 DCHECK(!instr->HasW());
2684 addr = rn_val;
2685 rn_val += im_val;
2686 set_register(rn, rn_val);
2687 break;
2688 }
2689 case db_x: {
2690 // Format(instr, "'memop'cond'b 'rd, ['rn, #-'off12]'w");
2691 rn_val -= im_val;
2692 addr = rn_val;
2693 if (instr->HasW()) {
2694 set_register(rn, rn_val);
2695 }
2696 break;
2697 }
2698 case ib_x: {
2699 // Format(instr, "'memop'cond'b 'rd, ['rn, #+'off12]'w");
2700 rn_val += im_val;
2701 addr = rn_val;
2702 if (instr->HasW()) {
2703 set_register(rn, rn_val);
2704 }
2705 break;
2706 }
2707 default: {
2708 UNREACHABLE();
2709 break;
2710 }
2711 }
2712 if (instr->HasB()) {
2713 if (instr->HasL()) {
2714 byte val = ReadBU(addr);
2715 set_register(rd, val);
2716 } else {
2717 byte val = get_register(rd);
2718 WriteB(addr, val);
2719 }
2720 } else {
2721 if (instr->HasL()) {
2722 set_register(rd, ReadW(addr, instr));
2723 } else {
2724 WriteW(addr, get_register(rd), instr);
2725 }
2726 }
2727 }
2728
2729
DecodeType3(Instruction * instr)2730 void Simulator::DecodeType3(Instruction* instr) {
2731 int rd = instr->RdValue();
2732 int rn = instr->RnValue();
2733 int32_t rn_val = get_register(rn);
2734 bool shifter_carry_out = 0;
2735 int32_t shifter_operand = GetShiftRm(instr, &shifter_carry_out);
2736 int32_t addr = 0;
2737 switch (instr->PUField()) {
2738 case da_x: {
2739 DCHECK(!instr->HasW());
2740 Format(instr, "'memop'cond'b 'rd, ['rn], -'shift_rm");
2741 UNIMPLEMENTED();
2742 break;
2743 }
2744 case ia_x: {
2745 if (instr->Bit(4) == 0) {
2746 // Memop.
2747 } else {
2748 if (instr->Bit(5) == 0) {
2749 switch (instr->Bits(22, 21)) {
2750 case 0:
2751 if (instr->Bit(20) == 0) {
2752 if (instr->Bit(6) == 0) {
2753 // Pkhbt.
2754 uint32_t rn_val = get_register(rn);
2755 uint32_t rm_val = get_register(instr->RmValue());
2756 int32_t shift = instr->Bits(11, 7);
2757 rm_val <<= shift;
2758 set_register(rd, (rn_val & 0xFFFF) | (rm_val & 0xFFFF0000U));
2759 } else {
2760 // Pkhtb.
2761 uint32_t rn_val = get_register(rn);
2762 int32_t rm_val = get_register(instr->RmValue());
2763 int32_t shift = instr->Bits(11, 7);
2764 if (shift == 0) {
2765 shift = 32;
2766 }
2767 rm_val >>= shift;
2768 set_register(rd, (rn_val & 0xFFFF0000U) | (rm_val & 0xFFFF));
2769 }
2770 } else {
2771 UNIMPLEMENTED();
2772 }
2773 break;
2774 case 1:
2775 UNIMPLEMENTED();
2776 break;
2777 case 2:
2778 UNIMPLEMENTED();
2779 break;
2780 case 3: {
2781 // Usat.
2782 int32_t sat_pos = instr->Bits(20, 16);
2783 int32_t sat_val = (1 << sat_pos) - 1;
2784 int32_t shift = instr->Bits(11, 7);
2785 int32_t shift_type = instr->Bit(6);
2786 int32_t rm_val = get_register(instr->RmValue());
2787 if (shift_type == 0) { // LSL
2788 rm_val <<= shift;
2789 } else { // ASR
2790 rm_val >>= shift;
2791 }
2792 // If saturation occurs, the Q flag should be set in the CPSR.
2793 // There is no Q flag yet, and no instruction (MRS) to read the
2794 // CPSR directly.
2795 if (rm_val > sat_val) {
2796 rm_val = sat_val;
2797 } else if (rm_val < 0) {
2798 rm_val = 0;
2799 }
2800 set_register(rd, rm_val);
2801 break;
2802 }
2803 }
2804 } else {
2805 switch (instr->Bits(22, 21)) {
2806 case 0:
2807 UNIMPLEMENTED();
2808 break;
2809 case 1:
2810 if (instr->Bits(9, 6) == 1) {
2811 if (instr->Bit(20) == 0) {
2812 if (instr->Bits(19, 16) == 0xF) {
2813 // Sxtb.
2814 int32_t rm_val = get_register(instr->RmValue());
2815 int32_t rotate = instr->Bits(11, 10);
2816 switch (rotate) {
2817 case 0:
2818 break;
2819 case 1:
2820 rm_val = (rm_val >> 8) | (rm_val << 24);
2821 break;
2822 case 2:
2823 rm_val = (rm_val >> 16) | (rm_val << 16);
2824 break;
2825 case 3:
2826 rm_val = (rm_val >> 24) | (rm_val << 8);
2827 break;
2828 }
2829 set_register(rd, static_cast<int8_t>(rm_val));
2830 } else {
2831 // Sxtab.
2832 int32_t rn_val = get_register(rn);
2833 int32_t rm_val = get_register(instr->RmValue());
2834 int32_t rotate = instr->Bits(11, 10);
2835 switch (rotate) {
2836 case 0:
2837 break;
2838 case 1:
2839 rm_val = (rm_val >> 8) | (rm_val << 24);
2840 break;
2841 case 2:
2842 rm_val = (rm_val >> 16) | (rm_val << 16);
2843 break;
2844 case 3:
2845 rm_val = (rm_val >> 24) | (rm_val << 8);
2846 break;
2847 }
2848 set_register(rd, rn_val + static_cast<int8_t>(rm_val));
2849 }
2850 } else {
2851 if (instr->Bits(19, 16) == 0xF) {
2852 // Sxth.
2853 int32_t rm_val = get_register(instr->RmValue());
2854 int32_t rotate = instr->Bits(11, 10);
2855 switch (rotate) {
2856 case 0:
2857 break;
2858 case 1:
2859 rm_val = (rm_val >> 8) | (rm_val << 24);
2860 break;
2861 case 2:
2862 rm_val = (rm_val >> 16) | (rm_val << 16);
2863 break;
2864 case 3:
2865 rm_val = (rm_val >> 24) | (rm_val << 8);
2866 break;
2867 }
2868 set_register(rd, static_cast<int16_t>(rm_val));
2869 } else {
2870 // Sxtah.
2871 int32_t rn_val = get_register(rn);
2872 int32_t rm_val = get_register(instr->RmValue());
2873 int32_t rotate = instr->Bits(11, 10);
2874 switch (rotate) {
2875 case 0:
2876 break;
2877 case 1:
2878 rm_val = (rm_val >> 8) | (rm_val << 24);
2879 break;
2880 case 2:
2881 rm_val = (rm_val >> 16) | (rm_val << 16);
2882 break;
2883 case 3:
2884 rm_val = (rm_val >> 24) | (rm_val << 8);
2885 break;
2886 }
2887 set_register(rd, rn_val + static_cast<int16_t>(rm_val));
2888 }
2889 }
2890 } else {
2891 UNREACHABLE();
2892 }
2893 break;
2894 case 2:
2895 if ((instr->Bit(20) == 0) && (instr->Bits(9, 6) == 1)) {
2896 if (instr->Bits(19, 16) == 0xF) {
2897 // Uxtb16.
2898 uint32_t rm_val = get_register(instr->RmValue());
2899 int32_t rotate = instr->Bits(11, 10);
2900 switch (rotate) {
2901 case 0:
2902 break;
2903 case 1:
2904 rm_val = (rm_val >> 8) | (rm_val << 24);
2905 break;
2906 case 2:
2907 rm_val = (rm_val >> 16) | (rm_val << 16);
2908 break;
2909 case 3:
2910 rm_val = (rm_val >> 24) | (rm_val << 8);
2911 break;
2912 }
2913 set_register(rd, (rm_val & 0xFF) | (rm_val & 0xFF0000));
2914 } else {
2915 UNIMPLEMENTED();
2916 }
2917 } else {
2918 UNIMPLEMENTED();
2919 }
2920 break;
2921 case 3:
2922 if ((instr->Bits(9, 6) == 1)) {
2923 if (instr->Bit(20) == 0) {
2924 if (instr->Bits(19, 16) == 0xF) {
2925 // Uxtb.
2926 uint32_t rm_val = get_register(instr->RmValue());
2927 int32_t rotate = instr->Bits(11, 10);
2928 switch (rotate) {
2929 case 0:
2930 break;
2931 case 1:
2932 rm_val = (rm_val >> 8) | (rm_val << 24);
2933 break;
2934 case 2:
2935 rm_val = (rm_val >> 16) | (rm_val << 16);
2936 break;
2937 case 3:
2938 rm_val = (rm_val >> 24) | (rm_val << 8);
2939 break;
2940 }
2941 set_register(rd, (rm_val & 0xFF));
2942 } else {
2943 // Uxtab.
2944 uint32_t rn_val = get_register(rn);
2945 uint32_t rm_val = get_register(instr->RmValue());
2946 int32_t rotate = instr->Bits(11, 10);
2947 switch (rotate) {
2948 case 0:
2949 break;
2950 case 1:
2951 rm_val = (rm_val >> 8) | (rm_val << 24);
2952 break;
2953 case 2:
2954 rm_val = (rm_val >> 16) | (rm_val << 16);
2955 break;
2956 case 3:
2957 rm_val = (rm_val >> 24) | (rm_val << 8);
2958 break;
2959 }
2960 set_register(rd, rn_val + (rm_val & 0xFF));
2961 }
2962 } else {
2963 if (instr->Bits(19, 16) == 0xF) {
2964 // Uxth.
2965 uint32_t rm_val = get_register(instr->RmValue());
2966 int32_t rotate = instr->Bits(11, 10);
2967 switch (rotate) {
2968 case 0:
2969 break;
2970 case 1:
2971 rm_val = (rm_val >> 8) | (rm_val << 24);
2972 break;
2973 case 2:
2974 rm_val = (rm_val >> 16) | (rm_val << 16);
2975 break;
2976 case 3:
2977 rm_val = (rm_val >> 24) | (rm_val << 8);
2978 break;
2979 }
2980 set_register(rd, (rm_val & 0xFFFF));
2981 } else {
2982 // Uxtah.
2983 uint32_t rn_val = get_register(rn);
2984 uint32_t rm_val = get_register(instr->RmValue());
2985 int32_t rotate = instr->Bits(11, 10);
2986 switch (rotate) {
2987 case 0:
2988 break;
2989 case 1:
2990 rm_val = (rm_val >> 8) | (rm_val << 24);
2991 break;
2992 case 2:
2993 rm_val = (rm_val >> 16) | (rm_val << 16);
2994 break;
2995 case 3:
2996 rm_val = (rm_val >> 24) | (rm_val << 8);
2997 break;
2998 }
2999 set_register(rd, rn_val + (rm_val & 0xFFFF));
3000 }
3001 }
3002 } else {
3003 // PU == 0b01, BW == 0b11, Bits(9, 6) != 0b0001
3004 if ((instr->Bits(20, 16) == 0x1f) &&
3005 (instr->Bits(11, 4) == 0xf3)) {
3006 // Rbit.
3007 uint32_t rm_val = get_register(instr->RmValue());
3008 set_register(rd, base::bits::ReverseBits(rm_val));
3009 } else {
3010 UNIMPLEMENTED();
3011 }
3012 }
3013 break;
3014 }
3015 }
3016 return;
3017 }
3018 break;
3019 }
3020 case db_x: {
3021 if (instr->Bits(22, 20) == 0x5) {
3022 if (instr->Bits(7, 4) == 0x1) {
3023 int rm = instr->RmValue();
3024 int32_t rm_val = get_register(rm);
3025 int rs = instr->RsValue();
3026 int32_t rs_val = get_register(rs);
3027 if (instr->Bits(15, 12) == 0xF) {
3028 // SMMUL (in V8 notation matching ARM ISA format)
3029 // Format(instr, "smmul'cond 'rn, 'rm, 'rs");
3030 rn_val = base::bits::SignedMulHigh32(rm_val, rs_val);
3031 } else {
3032 // SMMLA (in V8 notation matching ARM ISA format)
3033 // Format(instr, "smmla'cond 'rn, 'rm, 'rs, 'rd");
3034 int rd = instr->RdValue();
3035 int32_t rd_val = get_register(rd);
3036 rn_val = base::bits::SignedMulHighAndAdd32(rm_val, rs_val, rd_val);
3037 }
3038 set_register(rn, rn_val);
3039 return;
3040 }
3041 }
3042 if (instr->Bits(5, 4) == 0x1) {
3043 if ((instr->Bit(22) == 0x0) && (instr->Bit(20) == 0x1)) {
3044 // (s/u)div (in V8 notation matching ARM ISA format) rn = rm/rs
3045 // Format(instr, "'(s/u)div'cond'b 'rn, 'rm, 'rs);
3046 int rm = instr->RmValue();
3047 int32_t rm_val = get_register(rm);
3048 int rs = instr->RsValue();
3049 int32_t rs_val = get_register(rs);
3050 int32_t ret_val = 0;
3051 // udiv
3052 if (instr->Bit(21) == 0x1) {
3053 ret_val = bit_cast<int32_t>(base::bits::UnsignedDiv32(
3054 bit_cast<uint32_t>(rm_val), bit_cast<uint32_t>(rs_val)));
3055 } else {
3056 ret_val = base::bits::SignedDiv32(rm_val, rs_val);
3057 }
3058 set_register(rn, ret_val);
3059 return;
3060 }
3061 }
3062 // Format(instr, "'memop'cond'b 'rd, ['rn, -'shift_rm]'w");
3063 addr = rn_val - shifter_operand;
3064 if (instr->HasW()) {
3065 set_register(rn, addr);
3066 }
3067 break;
3068 }
3069 case ib_x: {
3070 if (instr->HasW() && (instr->Bits(6, 4) == 0x5)) {
3071 uint32_t widthminus1 = static_cast<uint32_t>(instr->Bits(20, 16));
3072 uint32_t lsbit = static_cast<uint32_t>(instr->Bits(11, 7));
3073 uint32_t msbit = widthminus1 + lsbit;
3074 if (msbit <= 31) {
3075 if (instr->Bit(22)) {
3076 // ubfx - unsigned bitfield extract.
3077 uint32_t rm_val =
3078 static_cast<uint32_t>(get_register(instr->RmValue()));
3079 uint32_t extr_val = rm_val << (31 - msbit);
3080 extr_val = extr_val >> (31 - widthminus1);
3081 set_register(instr->RdValue(), extr_val);
3082 } else {
3083 // sbfx - signed bitfield extract.
3084 int32_t rm_val = get_register(instr->RmValue());
3085 int32_t extr_val = rm_val << (31 - msbit);
3086 extr_val = extr_val >> (31 - widthminus1);
3087 set_register(instr->RdValue(), extr_val);
3088 }
3089 } else {
3090 UNREACHABLE();
3091 }
3092 return;
3093 } else if (!instr->HasW() && (instr->Bits(6, 4) == 0x1)) {
3094 uint32_t lsbit = static_cast<uint32_t>(instr->Bits(11, 7));
3095 uint32_t msbit = static_cast<uint32_t>(instr->Bits(20, 16));
3096 if (msbit >= lsbit) {
3097 // bfc or bfi - bitfield clear/insert.
3098 uint32_t rd_val =
3099 static_cast<uint32_t>(get_register(instr->RdValue()));
3100 uint32_t bitcount = msbit - lsbit + 1;
3101 uint32_t mask = 0xffffffffu >> (32 - bitcount);
3102 rd_val &= ~(mask << lsbit);
3103 if (instr->RmValue() != 15) {
3104 // bfi - bitfield insert.
3105 uint32_t rm_val =
3106 static_cast<uint32_t>(get_register(instr->RmValue()));
3107 rm_val &= mask;
3108 rd_val |= rm_val << lsbit;
3109 }
3110 set_register(instr->RdValue(), rd_val);
3111 } else {
3112 UNREACHABLE();
3113 }
3114 return;
3115 } else {
3116 // Format(instr, "'memop'cond'b 'rd, ['rn, +'shift_rm]'w");
3117 addr = rn_val + shifter_operand;
3118 if (instr->HasW()) {
3119 set_register(rn, addr);
3120 }
3121 }
3122 break;
3123 }
3124 default: {
3125 UNREACHABLE();
3126 break;
3127 }
3128 }
3129 if (instr->HasB()) {
3130 if (instr->HasL()) {
3131 uint8_t byte = ReadB(addr);
3132 set_register(rd, byte);
3133 } else {
3134 uint8_t byte = get_register(rd);
3135 WriteB(addr, byte);
3136 }
3137 } else {
3138 if (instr->HasL()) {
3139 set_register(rd, ReadW(addr, instr));
3140 } else {
3141 WriteW(addr, get_register(rd), instr);
3142 }
3143 }
3144 }
3145
3146
DecodeType4(Instruction * instr)3147 void Simulator::DecodeType4(Instruction* instr) {
3148 DCHECK(instr->Bit(22) == 0); // only allowed to be set in privileged mode
3149 if (instr->HasL()) {
3150 // Format(instr, "ldm'cond'pu 'rn'w, 'rlist");
3151 HandleRList(instr, true);
3152 } else {
3153 // Format(instr, "stm'cond'pu 'rn'w, 'rlist");
3154 HandleRList(instr, false);
3155 }
3156 }
3157
3158
DecodeType5(Instruction * instr)3159 void Simulator::DecodeType5(Instruction* instr) {
3160 // Format(instr, "b'l'cond 'target");
3161 int off = (instr->SImmed24Value() << 2);
3162 intptr_t pc_address = get_pc();
3163 if (instr->HasLink()) {
3164 set_register(lr, pc_address + Instruction::kInstrSize);
3165 }
3166 int pc_reg = get_register(pc);
3167 set_pc(pc_reg + off);
3168 }
3169
3170
DecodeType6(Instruction * instr)3171 void Simulator::DecodeType6(Instruction* instr) {
3172 DecodeType6CoprocessorIns(instr);
3173 }
3174
3175
DecodeType7(Instruction * instr)3176 void Simulator::DecodeType7(Instruction* instr) {
3177 if (instr->Bit(24) == 1) {
3178 SoftwareInterrupt(instr);
3179 } else {
3180 switch (instr->CoprocessorValue()) {
3181 case 10: // Fall through.
3182 case 11:
3183 DecodeTypeVFP(instr);
3184 break;
3185 case 15:
3186 DecodeTypeCP15(instr);
3187 break;
3188 default:
3189 UNIMPLEMENTED();
3190 }
3191 }
3192 }
3193
3194
3195 // void Simulator::DecodeTypeVFP(Instruction* instr)
3196 // The Following ARMv7 VFPv instructions are currently supported.
3197 // vmov :Sn = Rt
3198 // vmov :Rt = Sn
3199 // vcvt: Dd = Sm
3200 // vcvt: Sd = Dm
3201 // vcvt.f64.s32 Dd, Dd, #<fbits>
3202 // Dd = vabs(Dm)
3203 // Sd = vabs(Sm)
3204 // Dd = vneg(Dm)
3205 // Sd = vneg(Sm)
3206 // Dd = vadd(Dn, Dm)
3207 // Sd = vadd(Sn, Sm)
3208 // Dd = vsub(Dn, Dm)
3209 // Sd = vsub(Sn, Sm)
3210 // Dd = vmul(Dn, Dm)
3211 // Sd = vmul(Sn, Sm)
3212 // Dd = vdiv(Dn, Dm)
3213 // Sd = vdiv(Sn, Sm)
3214 // vcmp(Dd, Dm)
3215 // vcmp(Sd, Sm)
3216 // Dd = vsqrt(Dm)
3217 // Sd = vsqrt(Sm)
3218 // vmrs
3219 // vdup.size Qd, Rt.
DecodeTypeVFP(Instruction * instr)3220 void Simulator::DecodeTypeVFP(Instruction* instr) {
3221 DCHECK((instr->TypeValue() == 7) && (instr->Bit(24) == 0x0) );
3222 DCHECK(instr->Bits(11, 9) == 0x5);
3223
3224 // Obtain single precision register codes.
3225 int m = instr->VFPMRegValue(kSinglePrecision);
3226 int d = instr->VFPDRegValue(kSinglePrecision);
3227 int n = instr->VFPNRegValue(kSinglePrecision);
3228 // Obtain double precision register codes.
3229 int vm = instr->VFPMRegValue(kDoublePrecision);
3230 int vd = instr->VFPDRegValue(kDoublePrecision);
3231 int vn = instr->VFPNRegValue(kDoublePrecision);
3232
3233 if (instr->Bit(4) == 0) {
3234 if (instr->Opc1Value() == 0x7) {
3235 // Other data processing instructions
3236 if ((instr->Opc2Value() == 0x0) && (instr->Opc3Value() == 0x1)) {
3237 // vmov register to register.
3238 if (instr->SzValue() == 0x1) {
3239 uint32_t data[2];
3240 get_d_register(vm, data);
3241 set_d_register(vd, data);
3242 } else {
3243 set_s_register(d, get_s_register(m));
3244 }
3245 } else if ((instr->Opc2Value() == 0x0) && (instr->Opc3Value() == 0x3)) {
3246 // vabs
3247 if (instr->SzValue() == 0x1) {
3248 double dm_value = get_double_from_d_register(vm);
3249 double dd_value = std::fabs(dm_value);
3250 dd_value = canonicalizeNaN(dd_value);
3251 set_d_register_from_double(vd, dd_value);
3252 } else {
3253 float sm_value = get_float_from_s_register(m);
3254 float sd_value = std::fabs(sm_value);
3255 sd_value = canonicalizeNaN(sd_value);
3256 set_s_register_from_float(d, sd_value);
3257 }
3258 } else if ((instr->Opc2Value() == 0x1) && (instr->Opc3Value() == 0x1)) {
3259 // vneg
3260 if (instr->SzValue() == 0x1) {
3261 double dm_value = get_double_from_d_register(vm);
3262 double dd_value = -dm_value;
3263 dd_value = canonicalizeNaN(dd_value);
3264 set_d_register_from_double(vd, dd_value);
3265 } else {
3266 float sm_value = get_float_from_s_register(m);
3267 float sd_value = -sm_value;
3268 sd_value = canonicalizeNaN(sd_value);
3269 set_s_register_from_float(d, sd_value);
3270 }
3271 } else if ((instr->Opc2Value() == 0x7) && (instr->Opc3Value() == 0x3)) {
3272 DecodeVCVTBetweenDoubleAndSingle(instr);
3273 } else if ((instr->Opc2Value() == 0x8) && (instr->Opc3Value() & 0x1)) {
3274 DecodeVCVTBetweenFloatingPointAndInteger(instr);
3275 } else if ((instr->Opc2Value() == 0xA) && (instr->Opc3Value() == 0x3) &&
3276 (instr->Bit(8) == 1)) {
3277 // vcvt.f64.s32 Dd, Dd, #<fbits>
3278 int fraction_bits = 32 - ((instr->Bits(3, 0) << 1) | instr->Bit(5));
3279 int fixed_value = get_sinteger_from_s_register(vd * 2);
3280 double divide = 1 << fraction_bits;
3281 set_d_register_from_double(vd, fixed_value / divide);
3282 } else if (((instr->Opc2Value() >> 1) == 0x6) &&
3283 (instr->Opc3Value() & 0x1)) {
3284 DecodeVCVTBetweenFloatingPointAndInteger(instr);
3285 } else if (((instr->Opc2Value() == 0x4) || (instr->Opc2Value() == 0x5)) &&
3286 (instr->Opc3Value() & 0x1)) {
3287 DecodeVCMP(instr);
3288 } else if (((instr->Opc2Value() == 0x1)) && (instr->Opc3Value() == 0x3)) {
3289 // vsqrt
3290 lazily_initialize_fast_sqrt(isolate_);
3291 if (instr->SzValue() == 0x1) {
3292 double dm_value = get_double_from_d_register(vm);
3293 double dd_value = fast_sqrt(dm_value, isolate_);
3294 dd_value = canonicalizeNaN(dd_value);
3295 set_d_register_from_double(vd, dd_value);
3296 } else {
3297 float sm_value = get_float_from_s_register(m);
3298 float sd_value = fast_sqrt(sm_value, isolate_);
3299 sd_value = canonicalizeNaN(sd_value);
3300 set_s_register_from_float(d, sd_value);
3301 }
3302 } else if (instr->Opc3Value() == 0x0) {
3303 // vmov immediate.
3304 if (instr->SzValue() == 0x1) {
3305 set_d_register_from_double(vd, instr->DoubleImmedVmov());
3306 } else {
3307 set_s_register_from_float(d, instr->DoubleImmedVmov());
3308 }
3309 } else if (((instr->Opc2Value() == 0x6)) && (instr->Opc3Value() == 0x3)) {
3310 // vrintz - truncate
3311 if (instr->SzValue() == 0x1) {
3312 double dm_value = get_double_from_d_register(vm);
3313 double dd_value = trunc(dm_value);
3314 dd_value = canonicalizeNaN(dd_value);
3315 set_d_register_from_double(vd, dd_value);
3316 } else {
3317 float sm_value = get_float_from_s_register(m);
3318 float sd_value = truncf(sm_value);
3319 sd_value = canonicalizeNaN(sd_value);
3320 set_s_register_from_float(d, sd_value);
3321 }
3322 } else {
3323 UNREACHABLE(); // Not used by V8.
3324 }
3325 } else if (instr->Opc1Value() == 0x3) {
3326 if (instr->Opc3Value() & 0x1) {
3327 // vsub
3328 if (instr->SzValue() == 0x1) {
3329 double dn_value = get_double_from_d_register(vn);
3330 double dm_value = get_double_from_d_register(vm);
3331 double dd_value = dn_value - dm_value;
3332 dd_value = canonicalizeNaN(dd_value);
3333 set_d_register_from_double(vd, dd_value);
3334 } else {
3335 float sn_value = get_float_from_s_register(n);
3336 float sm_value = get_float_from_s_register(m);
3337 float sd_value = sn_value - sm_value;
3338 sd_value = canonicalizeNaN(sd_value);
3339 set_s_register_from_float(d, sd_value);
3340 }
3341 } else {
3342 // vadd
3343 if (instr->SzValue() == 0x1) {
3344 double dn_value = get_double_from_d_register(vn);
3345 double dm_value = get_double_from_d_register(vm);
3346 double dd_value = dn_value + dm_value;
3347 dd_value = canonicalizeNaN(dd_value);
3348 set_d_register_from_double(vd, dd_value);
3349 } else {
3350 float sn_value = get_float_from_s_register(n);
3351 float sm_value = get_float_from_s_register(m);
3352 float sd_value = sn_value + sm_value;
3353 sd_value = canonicalizeNaN(sd_value);
3354 set_s_register_from_float(d, sd_value);
3355 }
3356 }
3357 } else if ((instr->Opc1Value() == 0x2) && !(instr->Opc3Value() & 0x1)) {
3358 // vmul
3359 if (instr->SzValue() == 0x1) {
3360 double dn_value = get_double_from_d_register(vn);
3361 double dm_value = get_double_from_d_register(vm);
3362 double dd_value = dn_value * dm_value;
3363 dd_value = canonicalizeNaN(dd_value);
3364 set_d_register_from_double(vd, dd_value);
3365 } else {
3366 float sn_value = get_float_from_s_register(n);
3367 float sm_value = get_float_from_s_register(m);
3368 float sd_value = sn_value * sm_value;
3369 sd_value = canonicalizeNaN(sd_value);
3370 set_s_register_from_float(d, sd_value);
3371 }
3372 } else if ((instr->Opc1Value() == 0x0)) {
3373 // vmla, vmls
3374 const bool is_vmls = (instr->Opc3Value() & 0x1);
3375 if (instr->SzValue() == 0x1) {
3376 const double dd_val = get_double_from_d_register(vd);
3377 const double dn_val = get_double_from_d_register(vn);
3378 const double dm_val = get_double_from_d_register(vm);
3379
3380 // Note: we do the mul and add/sub in separate steps to avoid getting a
3381 // result with too high precision.
3382 set_d_register_from_double(vd, dn_val * dm_val);
3383 if (is_vmls) {
3384 set_d_register_from_double(
3385 vd, canonicalizeNaN(dd_val - get_double_from_d_register(vd)));
3386 } else {
3387 set_d_register_from_double(
3388 vd, canonicalizeNaN(dd_val + get_double_from_d_register(vd)));
3389 }
3390 } else {
3391 const float sd_val = get_float_from_s_register(d);
3392 const float sn_val = get_float_from_s_register(n);
3393 const float sm_val = get_float_from_s_register(m);
3394
3395 // Note: we do the mul and add/sub in separate steps to avoid getting a
3396 // result with too high precision.
3397 set_s_register_from_float(d, sn_val * sm_val);
3398 if (is_vmls) {
3399 set_s_register_from_float(
3400 d, canonicalizeNaN(sd_val - get_float_from_s_register(d)));
3401 } else {
3402 set_s_register_from_float(
3403 d, canonicalizeNaN(sd_val + get_float_from_s_register(d)));
3404 }
3405 }
3406 } else if ((instr->Opc1Value() == 0x4) && !(instr->Opc3Value() & 0x1)) {
3407 // vdiv
3408 if (instr->SzValue() == 0x1) {
3409 double dn_value = get_double_from_d_register(vn);
3410 double dm_value = get_double_from_d_register(vm);
3411 double dd_value = dn_value / dm_value;
3412 div_zero_vfp_flag_ = (dm_value == 0);
3413 dd_value = canonicalizeNaN(dd_value);
3414 set_d_register_from_double(vd, dd_value);
3415 } else {
3416 float sn_value = get_float_from_s_register(n);
3417 float sm_value = get_float_from_s_register(m);
3418 float sd_value = sn_value / sm_value;
3419 div_zero_vfp_flag_ = (sm_value == 0);
3420 sd_value = canonicalizeNaN(sd_value);
3421 set_s_register_from_float(d, sd_value);
3422 }
3423 } else {
3424 UNIMPLEMENTED(); // Not used by V8.
3425 }
3426 } else {
3427 if ((instr->VCValue() == 0x0) &&
3428 (instr->VAValue() == 0x0)) {
3429 DecodeVMOVBetweenCoreAndSinglePrecisionRegisters(instr);
3430 } else if ((instr->VLValue() == 0x0) && (instr->VCValue() == 0x1)) {
3431 if (instr->Bit(23) == 0) {
3432 // vmov (ARM core register to scalar)
3433 int vd = instr->VFPNRegValue(kDoublePrecision);
3434 int rt = instr->RtValue();
3435 int opc1_opc2 = (instr->Bits(22, 21) << 2) | instr->Bits(6, 5);
3436 if ((opc1_opc2 & 0xb) == 0) {
3437 // NeonS32/NeonU32
3438 uint32_t data[2];
3439 get_d_register(vd, data);
3440 data[instr->Bit(21)] = get_register(rt);
3441 set_d_register(vd, data);
3442 } else {
3443 uint64_t data;
3444 get_d_register(vd, &data);
3445 uint64_t rt_value = get_register(rt);
3446 if ((opc1_opc2 & 0x8) != 0) {
3447 // NeonS8 / NeonU8
3448 int i = opc1_opc2 & 0x7;
3449 int shift = i * kBitsPerByte;
3450 const uint64_t mask = 0xFF;
3451 data &= ~(mask << shift);
3452 data |= (rt_value & mask) << shift;
3453 set_d_register(vd, &data);
3454 } else if ((opc1_opc2 & 0x1) != 0) {
3455 // NeonS16 / NeonU16
3456 int i = (opc1_opc2 >> 1) & 0x3;
3457 int shift = i * kBitsPerByte * kShortSize;
3458 const uint64_t mask = 0xFFFF;
3459 data &= ~(mask << shift);
3460 data |= (rt_value & mask) << shift;
3461 set_d_register(vd, &data);
3462 } else {
3463 UNREACHABLE(); // Not used by V8.
3464 }
3465 }
3466 } else {
3467 // vdup.size Qd, Rt.
3468 NeonSize size = Neon32;
3469 if (instr->Bit(5) != 0)
3470 size = Neon16;
3471 else if (instr->Bit(22) != 0)
3472 size = Neon8;
3473 int vd = instr->VFPNRegValue(kSimd128Precision);
3474 int rt = instr->RtValue();
3475 uint32_t rt_value = get_register(rt);
3476 uint32_t q_data[4];
3477 switch (size) {
3478 case Neon8: {
3479 rt_value &= 0xFF;
3480 uint8_t* dst = reinterpret_cast<uint8_t*>(q_data);
3481 for (int i = 0; i < 16; i++) {
3482 dst[i] = rt_value;
3483 }
3484 break;
3485 }
3486 case Neon16: {
3487 // Perform pairwise op.
3488 rt_value &= 0xFFFFu;
3489 uint32_t rt_rt = (rt_value << 16) | (rt_value & 0xFFFFu);
3490 for (int i = 0; i < 4; i++) {
3491 q_data[i] = rt_rt;
3492 }
3493 break;
3494 }
3495 case Neon32: {
3496 for (int i = 0; i < 4; i++) {
3497 q_data[i] = rt_value;
3498 }
3499 break;
3500 }
3501 default:
3502 UNREACHABLE();
3503 break;
3504 }
3505 set_q_register(vd, q_data);
3506 }
3507 } else if ((instr->VLValue() == 0x1) && (instr->VCValue() == 0x1)) {
3508 // vmov (scalar to ARM core register)
3509 int vn = instr->VFPNRegValue(kDoublePrecision);
3510 int rt = instr->RtValue();
3511 int opc1_opc2 = (instr->Bits(22, 21) << 2) | instr->Bits(6, 5);
3512 uint64_t data;
3513 get_d_register(vn, &data);
3514 if ((opc1_opc2 & 0xb) == 0) {
3515 // NeonS32 / NeonU32
3516 int32_t int_data[2];
3517 memcpy(int_data, &data, sizeof(int_data));
3518 set_register(rt, int_data[instr->Bit(21)]);
3519 } else {
3520 uint64_t data;
3521 get_d_register(vn, &data);
3522 bool u = instr->Bit(23) != 0;
3523 if ((opc1_opc2 & 0x8) != 0) {
3524 // NeonS8 / NeonU8
3525 int i = opc1_opc2 & 0x7;
3526 int shift = i * kBitsPerByte;
3527 uint32_t scalar = (data >> shift) & 0xFFu;
3528 if (!u && (scalar & 0x80) != 0) scalar |= 0xffffff00;
3529 set_register(rt, scalar);
3530 } else if ((opc1_opc2 & 0x1) != 0) {
3531 // NeonS16 / NeonU16
3532 int i = (opc1_opc2 >> 1) & 0x3;
3533 int shift = i * kBitsPerByte * kShortSize;
3534 uint32_t scalar = (data >> shift) & 0xFFFFu;
3535 if (!u && (scalar & 0x8000) != 0) scalar |= 0xffff0000;
3536 set_register(rt, scalar);
3537 } else {
3538 UNREACHABLE(); // Not used by V8.
3539 }
3540 }
3541 } else if ((instr->VLValue() == 0x1) &&
3542 (instr->VCValue() == 0x0) &&
3543 (instr->VAValue() == 0x7) &&
3544 (instr->Bits(19, 16) == 0x1)) {
3545 // vmrs
3546 uint32_t rt = instr->RtValue();
3547 if (rt == 0xF) {
3548 Copy_FPSCR_to_APSR();
3549 } else {
3550 // Emulate FPSCR from the Simulator flags.
3551 uint32_t fpscr = (n_flag_FPSCR_ << 31) |
3552 (z_flag_FPSCR_ << 30) |
3553 (c_flag_FPSCR_ << 29) |
3554 (v_flag_FPSCR_ << 28) |
3555 (FPSCR_default_NaN_mode_ << 25) |
3556 (inexact_vfp_flag_ << 4) |
3557 (underflow_vfp_flag_ << 3) |
3558 (overflow_vfp_flag_ << 2) |
3559 (div_zero_vfp_flag_ << 1) |
3560 (inv_op_vfp_flag_ << 0) |
3561 (FPSCR_rounding_mode_);
3562 set_register(rt, fpscr);
3563 }
3564 } else if ((instr->VLValue() == 0x0) &&
3565 (instr->VCValue() == 0x0) &&
3566 (instr->VAValue() == 0x7) &&
3567 (instr->Bits(19, 16) == 0x1)) {
3568 // vmsr
3569 uint32_t rt = instr->RtValue();
3570 if (rt == pc) {
3571 UNREACHABLE();
3572 } else {
3573 uint32_t rt_value = get_register(rt);
3574 n_flag_FPSCR_ = (rt_value >> 31) & 1;
3575 z_flag_FPSCR_ = (rt_value >> 30) & 1;
3576 c_flag_FPSCR_ = (rt_value >> 29) & 1;
3577 v_flag_FPSCR_ = (rt_value >> 28) & 1;
3578 FPSCR_default_NaN_mode_ = (rt_value >> 25) & 1;
3579 inexact_vfp_flag_ = (rt_value >> 4) & 1;
3580 underflow_vfp_flag_ = (rt_value >> 3) & 1;
3581 overflow_vfp_flag_ = (rt_value >> 2) & 1;
3582 div_zero_vfp_flag_ = (rt_value >> 1) & 1;
3583 inv_op_vfp_flag_ = (rt_value >> 0) & 1;
3584 FPSCR_rounding_mode_ =
3585 static_cast<VFPRoundingMode>((rt_value) & kVFPRoundingModeMask);
3586 }
3587 } else {
3588 UNIMPLEMENTED(); // Not used by V8.
3589 }
3590 }
3591 }
3592
DecodeTypeCP15(Instruction * instr)3593 void Simulator::DecodeTypeCP15(Instruction* instr) {
3594 DCHECK((instr->TypeValue() == 7) && (instr->Bit(24) == 0x0));
3595 DCHECK(instr->CoprocessorValue() == 15);
3596
3597 if (instr->Bit(4) == 1) {
3598 // mcr
3599 int crn = instr->Bits(19, 16);
3600 int crm = instr->Bits(3, 0);
3601 int opc1 = instr->Bits(23, 21);
3602 int opc2 = instr->Bits(7, 5);
3603 if ((opc1 == 0) && (crn == 7)) {
3604 // ARMv6 memory barrier operations.
3605 // Details available in ARM DDI 0406C.b, B3-1750.
3606 if (((crm == 10) && (opc2 == 5)) || // CP15DMB
3607 ((crm == 10) && (opc2 == 4)) || // CP15DSB
3608 ((crm == 5) && (opc2 == 4))) { // CP15ISB
3609 // These are ignored by the simulator for now.
3610 } else {
3611 UNIMPLEMENTED();
3612 }
3613 }
3614 } else {
3615 UNIMPLEMENTED();
3616 }
3617 }
3618
DecodeVMOVBetweenCoreAndSinglePrecisionRegisters(Instruction * instr)3619 void Simulator::DecodeVMOVBetweenCoreAndSinglePrecisionRegisters(
3620 Instruction* instr) {
3621 DCHECK((instr->Bit(4) == 1) && (instr->VCValue() == 0x0) &&
3622 (instr->VAValue() == 0x0));
3623
3624 int t = instr->RtValue();
3625 int n = instr->VFPNRegValue(kSinglePrecision);
3626 bool to_arm_register = (instr->VLValue() == 0x1);
3627
3628 if (to_arm_register) {
3629 int32_t int_value = get_sinteger_from_s_register(n);
3630 set_register(t, int_value);
3631 } else {
3632 int32_t rs_val = get_register(t);
3633 set_s_register_from_sinteger(n, rs_val);
3634 }
3635 }
3636
3637
DecodeVCMP(Instruction * instr)3638 void Simulator::DecodeVCMP(Instruction* instr) {
3639 DCHECK((instr->Bit(4) == 0) && (instr->Opc1Value() == 0x7));
3640 DCHECK(((instr->Opc2Value() == 0x4) || (instr->Opc2Value() == 0x5)) &&
3641 (instr->Opc3Value() & 0x1));
3642 // Comparison.
3643
3644 VFPRegPrecision precision = kSinglePrecision;
3645 if (instr->SzValue() == 0x1) {
3646 precision = kDoublePrecision;
3647 }
3648
3649 int d = instr->VFPDRegValue(precision);
3650 int m = 0;
3651 if (instr->Opc2Value() == 0x4) {
3652 m = instr->VFPMRegValue(precision);
3653 }
3654
3655 if (precision == kDoublePrecision) {
3656 double dd_value = get_double_from_d_register(d);
3657 double dm_value = 0.0;
3658 if (instr->Opc2Value() == 0x4) {
3659 dm_value = get_double_from_d_register(m);
3660 }
3661
3662 // Raise exceptions for quiet NaNs if necessary.
3663 if (instr->Bit(7) == 1) {
3664 if (std::isnan(dd_value)) {
3665 inv_op_vfp_flag_ = true;
3666 }
3667 }
3668
3669 Compute_FPSCR_Flags(dd_value, dm_value);
3670 } else {
3671 float sd_value = get_float_from_s_register(d);
3672 float sm_value = 0.0;
3673 if (instr->Opc2Value() == 0x4) {
3674 sm_value = get_float_from_s_register(m);
3675 }
3676
3677 // Raise exceptions for quiet NaNs if necessary.
3678 if (instr->Bit(7) == 1) {
3679 if (std::isnan(sd_value)) {
3680 inv_op_vfp_flag_ = true;
3681 }
3682 }
3683
3684 Compute_FPSCR_Flags(sd_value, sm_value);
3685 }
3686 }
3687
3688
DecodeVCVTBetweenDoubleAndSingle(Instruction * instr)3689 void Simulator::DecodeVCVTBetweenDoubleAndSingle(Instruction* instr) {
3690 DCHECK((instr->Bit(4) == 0) && (instr->Opc1Value() == 0x7));
3691 DCHECK((instr->Opc2Value() == 0x7) && (instr->Opc3Value() == 0x3));
3692
3693 VFPRegPrecision dst_precision = kDoublePrecision;
3694 VFPRegPrecision src_precision = kSinglePrecision;
3695 if (instr->SzValue() == 1) {
3696 dst_precision = kSinglePrecision;
3697 src_precision = kDoublePrecision;
3698 }
3699
3700 int dst = instr->VFPDRegValue(dst_precision);
3701 int src = instr->VFPMRegValue(src_precision);
3702
3703 if (dst_precision == kSinglePrecision) {
3704 double val = get_double_from_d_register(src);
3705 set_s_register_from_float(dst, static_cast<float>(val));
3706 } else {
3707 float val = get_float_from_s_register(src);
3708 set_d_register_from_double(dst, static_cast<double>(val));
3709 }
3710 }
3711
get_inv_op_vfp_flag(VFPRoundingMode mode,double val,bool unsigned_)3712 bool get_inv_op_vfp_flag(VFPRoundingMode mode,
3713 double val,
3714 bool unsigned_) {
3715 DCHECK((mode == RN) || (mode == RM) || (mode == RZ));
3716 double max_uint = static_cast<double>(0xffffffffu);
3717 double max_int = static_cast<double>(kMaxInt);
3718 double min_int = static_cast<double>(kMinInt);
3719
3720 // Check for NaN.
3721 if (val != val) {
3722 return true;
3723 }
3724
3725 // Check for overflow. This code works because 32bit integers can be
3726 // exactly represented by ieee-754 64bit floating-point values.
3727 switch (mode) {
3728 case RN:
3729 return unsigned_ ? (val >= (max_uint + 0.5)) ||
3730 (val < -0.5)
3731 : (val >= (max_int + 0.5)) ||
3732 (val < (min_int - 0.5));
3733
3734 case RM:
3735 return unsigned_ ? (val >= (max_uint + 1.0)) ||
3736 (val < 0)
3737 : (val >= (max_int + 1.0)) ||
3738 (val < min_int);
3739
3740 case RZ:
3741 return unsigned_ ? (val >= (max_uint + 1.0)) ||
3742 (val <= -1)
3743 : (val >= (max_int + 1.0)) ||
3744 (val <= (min_int - 1.0));
3745 default:
3746 UNREACHABLE();
3747 return true;
3748 }
3749 }
3750
3751
3752 // We call this function only if we had a vfp invalid exception.
3753 // It returns the correct saturated value.
VFPConversionSaturate(double val,bool unsigned_res)3754 int VFPConversionSaturate(double val, bool unsigned_res) {
3755 if (val != val) {
3756 return 0;
3757 } else {
3758 if (unsigned_res) {
3759 return (val < 0) ? 0 : 0xffffffffu;
3760 } else {
3761 return (val < 0) ? kMinInt : kMaxInt;
3762 }
3763 }
3764 }
3765
ConvertDoubleToInt(double val,bool unsigned_integer,VFPRoundingMode mode)3766 int32_t Simulator::ConvertDoubleToInt(double val, bool unsigned_integer,
3767 VFPRoundingMode mode) {
3768 int32_t result =
3769 unsigned_integer ? static_cast<uint32_t>(val) : static_cast<int32_t>(val);
3770
3771 inv_op_vfp_flag_ = get_inv_op_vfp_flag(mode, val, unsigned_integer);
3772
3773 double abs_diff = unsigned_integer
3774 ? std::fabs(val - static_cast<uint32_t>(result))
3775 : std::fabs(val - result);
3776
3777 inexact_vfp_flag_ = (abs_diff != 0);
3778
3779 if (inv_op_vfp_flag_) {
3780 result = VFPConversionSaturate(val, unsigned_integer);
3781 } else {
3782 switch (mode) {
3783 case RN: {
3784 int val_sign = (val > 0) ? 1 : -1;
3785 if (abs_diff > 0.5) {
3786 result += val_sign;
3787 } else if (abs_diff == 0.5) {
3788 // Round to even if exactly halfway.
3789 result = ((result % 2) == 0) ? result : result + val_sign;
3790 }
3791 break;
3792 }
3793
3794 case RM:
3795 result = result > val ? result - 1 : result;
3796 break;
3797
3798 case RZ:
3799 // Nothing to do.
3800 break;
3801
3802 default:
3803 UNREACHABLE();
3804 }
3805 }
3806 return result;
3807 }
3808
DecodeVCVTBetweenFloatingPointAndInteger(Instruction * instr)3809 void Simulator::DecodeVCVTBetweenFloatingPointAndInteger(Instruction* instr) {
3810 DCHECK((instr->Bit(4) == 0) && (instr->Opc1Value() == 0x7) &&
3811 (instr->Bits(27, 23) == 0x1D));
3812 DCHECK(((instr->Opc2Value() == 0x8) && (instr->Opc3Value() & 0x1)) ||
3813 (((instr->Opc2Value() >> 1) == 0x6) && (instr->Opc3Value() & 0x1)));
3814
3815 // Conversion between floating-point and integer.
3816 bool to_integer = (instr->Bit(18) == 1);
3817
3818 VFPRegPrecision src_precision = (instr->SzValue() == 1) ? kDoublePrecision
3819 : kSinglePrecision;
3820
3821 if (to_integer) {
3822 // We are playing with code close to the C++ standard's limits below,
3823 // hence the very simple code and heavy checks.
3824 //
3825 // Note:
3826 // C++ defines default type casting from floating point to integer as
3827 // (close to) rounding toward zero ("fractional part discarded").
3828
3829 int dst = instr->VFPDRegValue(kSinglePrecision);
3830 int src = instr->VFPMRegValue(src_precision);
3831
3832 // Bit 7 in vcvt instructions indicates if we should use the FPSCR rounding
3833 // mode or the default Round to Zero mode.
3834 VFPRoundingMode mode = (instr->Bit(7) != 1) ? FPSCR_rounding_mode_
3835 : RZ;
3836 DCHECK((mode == RM) || (mode == RZ) || (mode == RN));
3837
3838 bool unsigned_integer = (instr->Bit(16) == 0);
3839 bool double_precision = (src_precision == kDoublePrecision);
3840
3841 double val = double_precision ? get_double_from_d_register(src)
3842 : get_float_from_s_register(src);
3843
3844 int32_t temp = ConvertDoubleToInt(val, unsigned_integer, mode);
3845
3846 // Update the destination register.
3847 set_s_register_from_sinteger(dst, temp);
3848
3849 } else {
3850 bool unsigned_integer = (instr->Bit(7) == 0);
3851
3852 int dst = instr->VFPDRegValue(src_precision);
3853 int src = instr->VFPMRegValue(kSinglePrecision);
3854
3855 int val = get_sinteger_from_s_register(src);
3856
3857 if (src_precision == kDoublePrecision) {
3858 if (unsigned_integer) {
3859 set_d_register_from_double(
3860 dst, static_cast<double>(static_cast<uint32_t>(val)));
3861 } else {
3862 set_d_register_from_double(dst, static_cast<double>(val));
3863 }
3864 } else {
3865 if (unsigned_integer) {
3866 set_s_register_from_float(
3867 dst, static_cast<float>(static_cast<uint32_t>(val)));
3868 } else {
3869 set_s_register_from_float(dst, static_cast<float>(val));
3870 }
3871 }
3872 }
3873 }
3874
3875
3876 // void Simulator::DecodeType6CoprocessorIns(Instruction* instr)
3877 // Decode Type 6 coprocessor instructions.
3878 // Dm = vmov(Rt, Rt2)
3879 // <Rt, Rt2> = vmov(Dm)
3880 // Ddst = MEM(Rbase + 4*offset).
3881 // MEM(Rbase + 4*offset) = Dsrc.
DecodeType6CoprocessorIns(Instruction * instr)3882 void Simulator::DecodeType6CoprocessorIns(Instruction* instr) {
3883 DCHECK((instr->TypeValue() == 6));
3884
3885 if (instr->CoprocessorValue() == 0xA) {
3886 switch (instr->OpcodeValue()) {
3887 case 0x8:
3888 case 0xA:
3889 case 0xC:
3890 case 0xE: { // Load and store single precision float to memory.
3891 int rn = instr->RnValue();
3892 int vd = instr->VFPDRegValue(kSinglePrecision);
3893 int offset = instr->Immed8Value();
3894 if (!instr->HasU()) {
3895 offset = -offset;
3896 }
3897
3898 int32_t address = get_register(rn) + 4 * offset;
3899 // Load and store address for singles must be at least four-byte
3900 // aligned.
3901 DCHECK((address % 4) == 0);
3902 if (instr->HasL()) {
3903 // Load single from memory: vldr.
3904 set_s_register_from_sinteger(vd, ReadW(address, instr));
3905 } else {
3906 // Store single to memory: vstr.
3907 WriteW(address, get_sinteger_from_s_register(vd), instr);
3908 }
3909 break;
3910 }
3911 case 0x4:
3912 case 0x5:
3913 case 0x6:
3914 case 0x7:
3915 case 0x9:
3916 case 0xB:
3917 // Load/store multiple single from memory: vldm/vstm.
3918 HandleVList(instr);
3919 break;
3920 default:
3921 UNIMPLEMENTED(); // Not used by V8.
3922 }
3923 } else if (instr->CoprocessorValue() == 0xB) {
3924 switch (instr->OpcodeValue()) {
3925 case 0x2:
3926 // Load and store double to two GP registers
3927 if (instr->Bits(7, 6) != 0 || instr->Bit(4) != 1) {
3928 UNIMPLEMENTED(); // Not used by V8.
3929 } else {
3930 int rt = instr->RtValue();
3931 int rn = instr->RnValue();
3932 int vm = instr->VFPMRegValue(kDoublePrecision);
3933 if (instr->HasL()) {
3934 uint32_t data[2];
3935 get_d_register(vm, data);
3936 set_register(rt, data[0]);
3937 set_register(rn, data[1]);
3938 } else {
3939 int32_t data[] = { get_register(rt), get_register(rn) };
3940 set_d_register(vm, reinterpret_cast<uint32_t*>(data));
3941 }
3942 }
3943 break;
3944 case 0x8:
3945 case 0xA:
3946 case 0xC:
3947 case 0xE: { // Load and store double to memory.
3948 int rn = instr->RnValue();
3949 int vd = instr->VFPDRegValue(kDoublePrecision);
3950 int offset = instr->Immed8Value();
3951 if (!instr->HasU()) {
3952 offset = -offset;
3953 }
3954 int32_t address = get_register(rn) + 4 * offset;
3955 // Load and store address for doubles must be at least four-byte
3956 // aligned.
3957 DCHECK((address % 4) == 0);
3958 if (instr->HasL()) {
3959 // Load double from memory: vldr.
3960 int32_t data[] = {
3961 ReadW(address, instr),
3962 ReadW(address + 4, instr)
3963 };
3964 set_d_register(vd, reinterpret_cast<uint32_t*>(data));
3965 } else {
3966 // Store double to memory: vstr.
3967 uint32_t data[2];
3968 get_d_register(vd, data);
3969 WriteW(address, data[0], instr);
3970 WriteW(address + 4, data[1], instr);
3971 }
3972 break;
3973 }
3974 case 0x4:
3975 case 0x5:
3976 case 0x6:
3977 case 0x7:
3978 case 0x9:
3979 case 0xB:
3980 // Load/store multiple double from memory: vldm/vstm.
3981 HandleVList(instr);
3982 break;
3983 default:
3984 UNIMPLEMENTED(); // Not used by V8.
3985 }
3986 } else {
3987 UNIMPLEMENTED(); // Not used by V8.
3988 }
3989 }
3990
3991 // Templated operations for NEON instructions.
3992 // TODO(bbudge) Add more templates for use in DecodeSpecialCondition.
3993 template <typename T>
Widen(T value)3994 int64_t Widen(T value) {
3995 static_assert(sizeof(int64_t) > sizeof(T), "T must be int32_t or smaller");
3996 return static_cast<int64_t>(value);
3997 }
3998
3999 template <typename T>
Clamp(int64_t value)4000 T Clamp(int64_t value) {
4001 static_assert(sizeof(int64_t) > sizeof(T), "T must be int32_t or smaller");
4002 int64_t min = static_cast<int64_t>(std::numeric_limits<T>::min());
4003 int64_t max = static_cast<int64_t>(std::numeric_limits<T>::max());
4004 int64_t clamped = std::max(min, std::min(max, value));
4005 return static_cast<T>(clamped);
4006 }
4007
4008 template <typename T>
AddSaturate(Simulator * simulator,int Vd,int Vm,int Vn)4009 void AddSaturate(Simulator* simulator, int Vd, int Vm, int Vn) {
4010 static const int kLanes = 16 / sizeof(T);
4011 T src1[kLanes], src2[kLanes];
4012 simulator->get_q_register(Vn, src1);
4013 simulator->get_q_register(Vm, src2);
4014 for (int i = 0; i < kLanes; i++) {
4015 src1[i] = Clamp<T>(Widen(src1[i]) + Widen(src2[i]));
4016 }
4017 simulator->set_q_register(Vd, src1);
4018 }
4019
4020 template <typename T>
SubSaturate(Simulator * simulator,int Vd,int Vm,int Vn)4021 void SubSaturate(Simulator* simulator, int Vd, int Vm, int Vn) {
4022 static const int kLanes = 16 / sizeof(T);
4023 T src1[kLanes], src2[kLanes];
4024 simulator->get_q_register(Vn, src1);
4025 simulator->get_q_register(Vm, src2);
4026 for (int i = 0; i < kLanes; i++) {
4027 src1[i] = Clamp<T>(Widen(src1[i]) - Widen(src2[i]));
4028 }
4029 simulator->set_q_register(Vd, src1);
4030 }
4031
DecodeSpecialCondition(Instruction * instr)4032 void Simulator::DecodeSpecialCondition(Instruction* instr) {
4033 switch (instr->SpecialValue()) {
4034 case 4: {
4035 int Vd, Vm, Vn;
4036 if (instr->Bit(6) == 0) {
4037 Vd = instr->VFPDRegValue(kDoublePrecision);
4038 Vm = instr->VFPMRegValue(kDoublePrecision);
4039 Vn = instr->VFPNRegValue(kDoublePrecision);
4040 } else {
4041 Vd = instr->VFPDRegValue(kSimd128Precision);
4042 Vm = instr->VFPMRegValue(kSimd128Precision);
4043 Vn = instr->VFPNRegValue(kSimd128Precision);
4044 }
4045 switch (instr->Bits(11, 8)) {
4046 case 0x0: {
4047 if (instr->Bit(4) == 1) {
4048 // vqadd.s<size> Qd, Qm, Qn.
4049 NeonSize size = static_cast<NeonSize>(instr->Bits(21, 20));
4050 switch (size) {
4051 case Neon8:
4052 AddSaturate<int8_t>(this, Vd, Vm, Vn);
4053 break;
4054 case Neon16:
4055 AddSaturate<int16_t>(this, Vd, Vm, Vn);
4056 break;
4057 case Neon32:
4058 AddSaturate<int32_t>(this, Vd, Vm, Vn);
4059 break;
4060 default:
4061 UNREACHABLE();
4062 break;
4063 }
4064 } else {
4065 UNIMPLEMENTED();
4066 }
4067 break;
4068 }
4069 case 0x1: {
4070 if (instr->Bits(21, 20) == 2 && instr->Bit(6) == 1 &&
4071 instr->Bit(4) == 1) {
4072 // vmov Qd, Qm.
4073 // vorr, Qd, Qm, Qn.
4074 uint32_t src1[4];
4075 get_q_register(Vm, src1);
4076 if (Vm != Vn) {
4077 uint32_t src2[4];
4078 get_q_register(Vn, src2);
4079 for (int i = 0; i < 4; i++) {
4080 src1[i] = src1[i] | src2[i];
4081 }
4082 }
4083 set_q_register(Vd, src1);
4084 } else if (instr->Bits(21, 20) == 0 && instr->Bit(6) == 1 &&
4085 instr->Bit(4) == 1) {
4086 // vand Qd, Qm, Qn.
4087 uint32_t src1[4], src2[4];
4088 get_q_register(Vn, src1);
4089 get_q_register(Vm, src2);
4090 for (int i = 0; i < 4; i++) {
4091 src1[i] = src1[i] & src2[i];
4092 }
4093 set_q_register(Vd, src1);
4094 } else {
4095 UNIMPLEMENTED();
4096 }
4097 break;
4098 }
4099 case 0x2: {
4100 if (instr->Bit(4) == 1) {
4101 // vqsub.s<size> Qd, Qm, Qn.
4102 NeonSize size = static_cast<NeonSize>(instr->Bits(21, 20));
4103 switch (size) {
4104 case Neon8:
4105 SubSaturate<int8_t>(this, Vd, Vm, Vn);
4106 break;
4107 case Neon16:
4108 SubSaturate<int16_t>(this, Vd, Vm, Vn);
4109 break;
4110 case Neon32:
4111 SubSaturate<int32_t>(this, Vd, Vm, Vn);
4112 break;
4113 default:
4114 UNREACHABLE();
4115 break;
4116 }
4117 } else {
4118 UNIMPLEMENTED();
4119 }
4120 break;
4121 }
4122 case 0x3: {
4123 // vcge/vcgt.s<size> Qd, Qm, Qn.
4124 bool ge = instr->Bit(4) == 1;
4125 NeonSize size = static_cast<NeonSize>(instr->Bits(21, 20));
4126 switch (size) {
4127 case Neon8: {
4128 int8_t src1[16], src2[16];
4129 get_q_register(Vn, src1);
4130 get_q_register(Vm, src2);
4131 for (int i = 0; i < 16; i++) {
4132 if (ge)
4133 src1[i] = src1[i] >= src2[i] ? 0xFF : 0;
4134 else
4135 src1[i] = src1[i] > src2[i] ? 0xFF : 0;
4136 }
4137 set_q_register(Vd, src1);
4138 break;
4139 }
4140 case Neon16: {
4141 int16_t src1[8], src2[8];
4142 get_q_register(Vn, src1);
4143 get_q_register(Vm, src2);
4144 for (int i = 0; i < 8; i++) {
4145 if (ge)
4146 src1[i] = src1[i] >= src2[i] ? 0xFFFF : 0;
4147 else
4148 src1[i] = src1[i] > src2[i] ? 0xFFFF : 0;
4149 }
4150 set_q_register(Vd, src1);
4151 break;
4152 }
4153 case Neon32: {
4154 int32_t src1[4], src2[4];
4155 get_q_register(Vn, src1);
4156 get_q_register(Vm, src2);
4157 for (int i = 0; i < 4; i++) {
4158 if (ge)
4159 src1[i] = src1[i] >= src2[i] ? 0xFFFFFFFF : 0;
4160 else
4161 src1[i] = src1[i] > src2[i] ? 0xFFFFFFFF : 0;
4162 }
4163 set_q_register(Vd, src1);
4164 break;
4165 }
4166 default:
4167 UNREACHABLE();
4168 break;
4169 }
4170 break;
4171 }
4172 case 0x6: {
4173 // vmin/vmax.s<size> Qd, Qm, Qn.
4174 NeonSize size = static_cast<NeonSize>(instr->Bits(21, 20));
4175 bool min = instr->Bit(4) != 0;
4176 switch (size) {
4177 case Neon8: {
4178 int8_t src1[16], src2[16];
4179 get_q_register(Vn, src1);
4180 get_q_register(Vm, src2);
4181 for (int i = 0; i < 16; i++) {
4182 if (min)
4183 src1[i] = std::min(src1[i], src2[i]);
4184 else
4185 src1[i] = std::max(src1[i], src2[i]);
4186 }
4187 set_q_register(Vd, src1);
4188 break;
4189 }
4190 case Neon16: {
4191 int16_t src1[8], src2[8];
4192 get_q_register(Vn, src1);
4193 get_q_register(Vm, src2);
4194 for (int i = 0; i < 8; i++) {
4195 if (min)
4196 src1[i] = std::min(src1[i], src2[i]);
4197 else
4198 src1[i] = std::max(src1[i], src2[i]);
4199 }
4200 set_q_register(Vd, src1);
4201 break;
4202 }
4203 case Neon32: {
4204 int32_t src1[4], src2[4];
4205 get_q_register(Vn, src1);
4206 get_q_register(Vm, src2);
4207 for (int i = 0; i < 4; i++) {
4208 if (min)
4209 src1[i] = std::min(src1[i], src2[i]);
4210 else
4211 src1[i] = std::max(src1[i], src2[i]);
4212 }
4213 set_q_register(Vd, src1);
4214 break;
4215 }
4216 default:
4217 UNREACHABLE();
4218 break;
4219 }
4220 break;
4221 }
4222 case 0x8: {
4223 // vadd/vtst
4224 NeonSize size = static_cast<NeonSize>(instr->Bits(21, 20));
4225 if (instr->Bit(4) == 0) {
4226 // vadd.i<size> Qd, Qm, Qn.
4227 switch (size) {
4228 case Neon8: {
4229 uint8_t src1[16], src2[16];
4230 get_q_register(Vn, src1);
4231 get_q_register(Vm, src2);
4232 for (int i = 0; i < 16; i++) {
4233 src1[i] += src2[i];
4234 }
4235 set_q_register(Vd, src1);
4236 break;
4237 }
4238 case Neon16: {
4239 uint16_t src1[8], src2[8];
4240 get_q_register(Vn, src1);
4241 get_q_register(Vm, src2);
4242 for (int i = 0; i < 8; i++) {
4243 src1[i] += src2[i];
4244 }
4245 set_q_register(Vd, src1);
4246 break;
4247 }
4248 case Neon32: {
4249 uint32_t src1[4], src2[4];
4250 get_q_register(Vn, src1);
4251 get_q_register(Vm, src2);
4252 for (int i = 0; i < 4; i++) {
4253 src1[i] += src2[i];
4254 }
4255 set_q_register(Vd, src1);
4256 break;
4257 }
4258 default:
4259 UNREACHABLE();
4260 break;
4261 }
4262 } else {
4263 // vtst.i<size> Qd, Qm, Qn.
4264 switch (size) {
4265 case Neon8: {
4266 uint8_t src1[16], src2[16];
4267 get_q_register(Vn, src1);
4268 get_q_register(Vm, src2);
4269 for (int i = 0; i < 16; i++) {
4270 src1[i] = (src1[i] & src2[i]) != 0 ? 0xFFu : 0;
4271 }
4272 set_q_register(Vd, src1);
4273 break;
4274 }
4275 case Neon16: {
4276 uint16_t src1[8], src2[8];
4277 get_q_register(Vn, src1);
4278 get_q_register(Vm, src2);
4279 for (int i = 0; i < 8; i++) {
4280 src1[i] = (src1[i] & src2[i]) != 0 ? 0xFFFFu : 0;
4281 }
4282 set_q_register(Vd, src1);
4283 break;
4284 }
4285 case Neon32: {
4286 uint32_t src1[4], src2[4];
4287 get_q_register(Vn, src1);
4288 get_q_register(Vm, src2);
4289 for (int i = 0; i < 4; i++) {
4290 src1[i] = (src1[i] & src2[i]) != 0 ? 0xFFFFFFFFu : 0;
4291 }
4292 set_q_register(Vd, src1);
4293 break;
4294 }
4295 default:
4296 UNREACHABLE();
4297 break;
4298 }
4299 }
4300 break;
4301 }
4302 case 0x9: {
4303 if (instr->Bit(6) == 1 && instr->Bit(4) == 1) {
4304 // vmul.i<size> Qd, Qm, Qn.
4305 NeonSize size = static_cast<NeonSize>(instr->Bits(21, 20));
4306 switch (size) {
4307 case Neon8: {
4308 uint8_t src1[16], src2[16];
4309 get_q_register(Vn, src1);
4310 get_q_register(Vm, src2);
4311 for (int i = 0; i < 16; i++) {
4312 src1[i] *= src2[i];
4313 }
4314 set_q_register(Vd, src1);
4315 break;
4316 }
4317 case Neon16: {
4318 uint16_t src1[8], src2[8];
4319 get_q_register(Vn, src1);
4320 get_q_register(Vm, src2);
4321 for (int i = 0; i < 8; i++) {
4322 src1[i] *= src2[i];
4323 }
4324 set_q_register(Vd, src1);
4325 break;
4326 }
4327 case Neon32: {
4328 uint32_t src1[4], src2[4];
4329 get_q_register(Vn, src1);
4330 get_q_register(Vm, src2);
4331 for (int i = 0; i < 4; i++) {
4332 src1[i] *= src2[i];
4333 }
4334 set_q_register(Vd, src1);
4335 break;
4336 }
4337 default:
4338 UNREACHABLE();
4339 break;
4340 }
4341 } else {
4342 UNIMPLEMENTED();
4343 }
4344 break;
4345 }
4346 case 0xd: {
4347 if (instr->Bit(4) == 0) {
4348 float src1[4], src2[4];
4349 get_q_register(Vn, src1);
4350 get_q_register(Vm, src2);
4351 for (int i = 0; i < 4; i++) {
4352 if (instr->Bit(21) == 0) {
4353 // vadd.f32 Qd, Qm, Qn.
4354 src1[i] = src1[i] + src2[i];
4355 } else {
4356 // vsub.f32 Qd, Qm, Qn.
4357 src1[i] = src1[i] - src2[i];
4358 }
4359 }
4360 set_q_register(Vd, src1);
4361 } else {
4362 UNIMPLEMENTED();
4363 }
4364 break;
4365 }
4366 case 0xe: {
4367 if (instr->Bits(21, 20) == 0 && instr->Bit(4) == 0) {
4368 // vceq.f32.
4369 float src1[4], src2[4];
4370 get_q_register(Vn, src1);
4371 get_q_register(Vm, src2);
4372 uint32_t dst[4];
4373 for (int i = 0; i < 4; i++) {
4374 dst[i] = (src1[i] == src2[i]) ? 0xFFFFFFFF : 0;
4375 }
4376 set_q_register(Vd, dst);
4377 } else {
4378 UNIMPLEMENTED();
4379 }
4380 break;
4381 }
4382 case 0xf: {
4383 if (instr->Bit(20) == 0 && instr->Bit(6) == 1) {
4384 float src1[4], src2[4];
4385 get_q_register(Vn, src1);
4386 get_q_register(Vm, src2);
4387 if (instr->Bit(4) == 1) {
4388 if (instr->Bit(21) == 0) {
4389 // vrecps.f32 Qd, Qm, Qn.
4390 for (int i = 0; i < 4; i++) {
4391 src1[i] = 2.0f - src1[i] * src2[i];
4392 }
4393 } else {
4394 // vrsqrts.f32 Qd, Qm, Qn.
4395 for (int i = 0; i < 4; i++) {
4396 src1[i] = (3.0f - src1[i] * src2[i]) * 0.5f;
4397 }
4398 }
4399 } else {
4400 if (instr->Bit(21) == 1) {
4401 // vmin.f32 Qd, Qm, Qn.
4402 for (int i = 0; i < 4; i++) {
4403 src1[i] = std::min(src1[i], src2[i]);
4404 }
4405 } else {
4406 // vmax.f32 Qd, Qm, Qn.
4407 for (int i = 0; i < 4; i++) {
4408 src1[i] = std::max(src1[i], src2[i]);
4409 }
4410 }
4411 }
4412 set_q_register(Vd, src1);
4413 } else {
4414 UNIMPLEMENTED();
4415 }
4416 break;
4417 }
4418 default:
4419 UNIMPLEMENTED();
4420 break;
4421 }
4422 break;
4423 }
4424 case 5:
4425 if ((instr->Bits(18, 16) == 0) && (instr->Bits(11, 6) == 0x28) &&
4426 (instr->Bit(4) == 1)) {
4427 // vmovl signed
4428 if ((instr->VdValue() & 1) != 0) UNIMPLEMENTED();
4429 int Vd = (instr->Bit(22) << 3) | (instr->VdValue() >> 1);
4430 int Vm = (instr->Bit(5) << 4) | instr->VmValue();
4431 int imm3 = instr->Bits(21, 19);
4432 if ((imm3 != 1) && (imm3 != 2) && (imm3 != 4)) UNIMPLEMENTED();
4433 int esize = 8 * imm3;
4434 int elements = 64 / esize;
4435 int8_t from[8];
4436 get_d_register(Vm, reinterpret_cast<uint64_t*>(from));
4437 int16_t to[8];
4438 int e = 0;
4439 while (e < elements) {
4440 to[e] = from[e];
4441 e++;
4442 }
4443 set_q_register(Vd, reinterpret_cast<uint64_t*>(to));
4444 } else if (instr->Bits(21, 20) == 3 && instr->Bit(4) == 0) {
4445 // vext.
4446 int imm4 = instr->Bits(11, 8);
4447 int Vd = instr->VFPDRegValue(kSimd128Precision);
4448 int Vm = instr->VFPMRegValue(kSimd128Precision);
4449 int Vn = instr->VFPNRegValue(kSimd128Precision);
4450 uint8_t src1[16], src2[16], dst[16];
4451 get_q_register(Vn, src1);
4452 get_q_register(Vm, src2);
4453 int boundary = kSimd128Size - imm4;
4454 int i = 0;
4455 for (; i < boundary; i++) {
4456 dst[i] = src1[i + imm4];
4457 }
4458 for (; i < 16; i++) {
4459 dst[i] = src2[i - boundary];
4460 }
4461 set_q_register(Vd, dst);
4462 } else if (instr->Bits(11, 7) == 0xA && instr->Bit(4) == 1) {
4463 // vshl.i<size> Qd, Qm, shift
4464 int size = base::bits::RoundDownToPowerOfTwo32(instr->Bits(21, 16));
4465 int shift = instr->Bits(21, 16) - size;
4466 int Vd = instr->VFPDRegValue(kSimd128Precision);
4467 int Vm = instr->VFPMRegValue(kSimd128Precision);
4468 NeonSize ns = static_cast<NeonSize>(size / 16);
4469 switch (ns) {
4470 case Neon8: {
4471 uint8_t src[16];
4472 get_q_register(Vm, src);
4473 for (int i = 0; i < 16; i++) {
4474 src[i] <<= shift;
4475 }
4476 set_q_register(Vd, src);
4477 break;
4478 }
4479 case Neon16: {
4480 uint16_t src[8];
4481 get_q_register(Vm, src);
4482 for (int i = 0; i < 8; i++) {
4483 src[i] <<= shift;
4484 }
4485 set_q_register(Vd, src);
4486 break;
4487 }
4488 case Neon32: {
4489 uint32_t src[4];
4490 get_q_register(Vm, src);
4491 for (int i = 0; i < 4; i++) {
4492 src[i] <<= shift;
4493 }
4494 set_q_register(Vd, src);
4495 break;
4496 }
4497 default:
4498 UNREACHABLE();
4499 break;
4500 }
4501 } else if (instr->Bits(11, 7) == 0 && instr->Bit(4) == 1) {
4502 // vshr.s<size> Qd, Qm, shift
4503 int size = base::bits::RoundDownToPowerOfTwo32(instr->Bits(21, 16));
4504 int shift = 2 * size - instr->Bits(21, 16);
4505 int Vd = instr->VFPDRegValue(kSimd128Precision);
4506 int Vm = instr->VFPMRegValue(kSimd128Precision);
4507 NeonSize ns = static_cast<NeonSize>(size / 16);
4508 switch (ns) {
4509 case Neon8: {
4510 int8_t src[16];
4511 get_q_register(Vm, src);
4512 for (int i = 0; i < 16; i++) {
4513 src[i] = ArithmeticShiftRight(src[i], shift);
4514 }
4515 set_q_register(Vd, src);
4516 break;
4517 }
4518 case Neon16: {
4519 int16_t src[8];
4520 get_q_register(Vm, src);
4521 for (int i = 0; i < 8; i++) {
4522 src[i] = ArithmeticShiftRight(src[i], shift);
4523 }
4524 set_q_register(Vd, src);
4525 break;
4526 }
4527 case Neon32: {
4528 int32_t src[4];
4529 get_q_register(Vm, src);
4530 for (int i = 0; i < 4; i++) {
4531 src[i] = ArithmeticShiftRight(src[i], shift);
4532 }
4533 set_q_register(Vd, src);
4534 break;
4535 }
4536 default:
4537 UNREACHABLE();
4538 break;
4539 }
4540 } else {
4541 UNIMPLEMENTED();
4542 }
4543 break;
4544 case 6: {
4545 int Vd, Vm, Vn;
4546 if (instr->Bit(6) == 0) {
4547 Vd = instr->VFPDRegValue(kDoublePrecision);
4548 Vm = instr->VFPMRegValue(kDoublePrecision);
4549 Vn = instr->VFPNRegValue(kDoublePrecision);
4550 } else {
4551 Vd = instr->VFPDRegValue(kSimd128Precision);
4552 Vm = instr->VFPMRegValue(kSimd128Precision);
4553 Vn = instr->VFPNRegValue(kSimd128Precision);
4554 }
4555 switch (instr->Bits(11, 8)) {
4556 case 0x0: {
4557 if (instr->Bit(4) == 1) {
4558 // vqadd.u<size> Qd, Qm, Qn.
4559 NeonSize size = static_cast<NeonSize>(instr->Bits(21, 20));
4560 switch (size) {
4561 case Neon8:
4562 AddSaturate<uint8_t>(this, Vd, Vm, Vn);
4563 break;
4564 case Neon16:
4565 AddSaturate<uint16_t>(this, Vd, Vm, Vn);
4566 break;
4567 case Neon32:
4568 AddSaturate<uint32_t>(this, Vd, Vm, Vn);
4569 break;
4570 default:
4571 UNREACHABLE();
4572 break;
4573 }
4574 } else {
4575 UNIMPLEMENTED();
4576 }
4577 break;
4578 }
4579 case 0x1: {
4580 if (instr->Bits(21, 20) == 1 && instr->Bit(4) == 1) {
4581 // vbsl.size Qd, Qm, Qn.
4582 uint32_t dst[4], src1[4], src2[4];
4583 get_q_register(Vd, dst);
4584 get_q_register(Vn, src1);
4585 get_q_register(Vm, src2);
4586 for (int i = 0; i < 4; i++) {
4587 dst[i] = (dst[i] & src1[i]) | (~dst[i] & src2[i]);
4588 }
4589 set_q_register(Vd, dst);
4590 } else if (instr->Bits(21, 20) == 0 && instr->Bit(4) == 1) {
4591 if (instr->Bit(6) == 0) {
4592 // veor Dd, Dn, Dm
4593 uint64_t src1, src2;
4594 get_d_register(Vn, &src1);
4595 get_d_register(Vm, &src2);
4596 src1 ^= src2;
4597 set_d_register(Vd, &src1);
4598
4599 } else {
4600 // veor Qd, Qn, Qm
4601 uint32_t src1[4], src2[4];
4602 get_q_register(Vn, src1);
4603 get_q_register(Vm, src2);
4604 for (int i = 0; i < 4; i++) src1[i] ^= src2[i];
4605 set_q_register(Vd, src1);
4606 }
4607 } else {
4608 UNIMPLEMENTED();
4609 }
4610 break;
4611 }
4612 case 0x2: {
4613 if (instr->Bit(4) == 1) {
4614 // vqsub.u<size> Qd, Qm, Qn.
4615 NeonSize size = static_cast<NeonSize>(instr->Bits(21, 20));
4616 switch (size) {
4617 case Neon8:
4618 SubSaturate<uint8_t>(this, Vd, Vm, Vn);
4619 break;
4620 case Neon16:
4621 SubSaturate<uint16_t>(this, Vd, Vm, Vn);
4622 break;
4623 case Neon32:
4624 SubSaturate<uint32_t>(this, Vd, Vm, Vn);
4625 break;
4626 default:
4627 UNREACHABLE();
4628 break;
4629 }
4630 } else {
4631 UNIMPLEMENTED();
4632 }
4633 break;
4634 }
4635 case 0x3: {
4636 // vcge/vcgt.u<size> Qd, Qm, Qn.
4637 bool ge = instr->Bit(4) == 1;
4638 NeonSize size = static_cast<NeonSize>(instr->Bits(21, 20));
4639 switch (size) {
4640 case Neon8: {
4641 uint8_t src1[16], src2[16];
4642 get_q_register(Vn, src1);
4643 get_q_register(Vm, src2);
4644 for (int i = 0; i < 16; i++) {
4645 if (ge)
4646 src1[i] = src1[i] >= src2[i] ? 0xFFu : 0;
4647 else
4648 src1[i] = src1[i] > src2[i] ? 0xFFu : 0;
4649 }
4650 set_q_register(Vd, src1);
4651 break;
4652 }
4653 case Neon16: {
4654 uint16_t src1[8], src2[8];
4655 get_q_register(Vn, src1);
4656 get_q_register(Vm, src2);
4657 for (int i = 0; i < 8; i++) {
4658 if (ge)
4659 src1[i] = src1[i] >= src2[i] ? 0xFFFFu : 0;
4660 else
4661 src1[i] = src1[i] > src2[i] ? 0xFFFFu : 0;
4662 }
4663 set_q_register(Vd, src1);
4664 break;
4665 }
4666 case Neon32: {
4667 uint32_t src1[4], src2[4];
4668 get_q_register(Vn, src1);
4669 get_q_register(Vm, src2);
4670 for (int i = 0; i < 4; i++) {
4671 if (ge)
4672 src1[i] = src1[i] >= src2[i] ? 0xFFFFFFFFu : 0;
4673 else
4674 src1[i] = src1[i] > src2[i] ? 0xFFFFFFFFu : 0;
4675 }
4676 set_q_register(Vd, src1);
4677 break;
4678 }
4679 default:
4680 UNREACHABLE();
4681 break;
4682 }
4683 break;
4684 }
4685 case 0x6: {
4686 // vmin/vmax.u<size> Qd, Qm, Qn.
4687 NeonSize size = static_cast<NeonSize>(instr->Bits(21, 20));
4688 bool min = instr->Bit(4) != 0;
4689 switch (size) {
4690 case Neon8: {
4691 uint8_t src1[16], src2[16];
4692 get_q_register(Vn, src1);
4693 get_q_register(Vm, src2);
4694 for (int i = 0; i < 16; i++) {
4695 if (min)
4696 src1[i] = std::min(src1[i], src2[i]);
4697 else
4698 src1[i] = std::max(src1[i], src2[i]);
4699 }
4700 set_q_register(Vd, src1);
4701 break;
4702 }
4703 case Neon16: {
4704 uint16_t src1[8], src2[8];
4705 get_q_register(Vn, src1);
4706 get_q_register(Vm, src2);
4707 for (int i = 0; i < 8; i++) {
4708 if (min)
4709 src1[i] = std::min(src1[i], src2[i]);
4710 else
4711 src1[i] = std::max(src1[i], src2[i]);
4712 }
4713 set_q_register(Vd, src1);
4714 break;
4715 }
4716 case Neon32: {
4717 uint32_t src1[4], src2[4];
4718 get_q_register(Vn, src1);
4719 get_q_register(Vm, src2);
4720 for (int i = 0; i < 4; i++) {
4721 if (min)
4722 src1[i] = std::min(src1[i], src2[i]);
4723 else
4724 src1[i] = std::max(src1[i], src2[i]);
4725 }
4726 set_q_register(Vd, src1);
4727 break;
4728 }
4729 default:
4730 UNREACHABLE();
4731 break;
4732 }
4733 break;
4734 }
4735 case 0x8: {
4736 if (instr->Bit(4) == 0) {
4737 // vsub.size Qd, Qm, Qn.
4738 NeonSize size = static_cast<NeonSize>(instr->Bits(21, 20));
4739 switch (size) {
4740 case Neon8: {
4741 uint8_t src1[16], src2[16];
4742 get_q_register(Vn, src1);
4743 get_q_register(Vm, src2);
4744 for (int i = 0; i < 16; i++) {
4745 src1[i] -= src2[i];
4746 }
4747 set_q_register(Vd, src1);
4748 break;
4749 }
4750 case Neon16: {
4751 uint16_t src1[8], src2[8];
4752 get_q_register(Vn, src1);
4753 get_q_register(Vm, src2);
4754 for (int i = 0; i < 8; i++) {
4755 src1[i] -= src2[i];
4756 }
4757 set_q_register(Vd, src1);
4758 break;
4759 }
4760 case Neon32: {
4761 uint32_t src1[4], src2[4];
4762 get_q_register(Vn, src1);
4763 get_q_register(Vm, src2);
4764 for (int i = 0; i < 4; i++) {
4765 src1[i] -= src2[i];
4766 }
4767 set_q_register(Vd, src1);
4768 break;
4769 }
4770 default:
4771 UNREACHABLE();
4772 break;
4773 }
4774 } else {
4775 // vceq.size Qd, Qm, Qn.
4776 NeonSize size = static_cast<NeonSize>(instr->Bits(21, 20));
4777 switch (size) {
4778 case Neon8: {
4779 uint8_t src1[16], src2[16];
4780 get_q_register(Vn, src1);
4781 get_q_register(Vm, src2);
4782 for (int i = 0; i < 16; i++) {
4783 src1[i] = (src1[i] == src2[i]) ? 0xFFu : 0;
4784 }
4785 set_q_register(Vd, src1);
4786 break;
4787 }
4788 case Neon16: {
4789 uint16_t src1[8], src2[8];
4790 get_q_register(Vn, src1);
4791 get_q_register(Vm, src2);
4792 for (int i = 0; i < 8; i++) {
4793 src1[i] = (src1[i] == src2[i]) ? 0xFFFFu : 0;
4794 }
4795 set_q_register(Vd, src1);
4796 break;
4797 }
4798 case Neon32: {
4799 uint32_t src1[4], src2[4];
4800 get_q_register(Vn, src1);
4801 get_q_register(Vm, src2);
4802 for (int i = 0; i < 4; i++) {
4803 src1[i] = (src1[i] == src2[i]) ? 0xFFFFFFFFu : 0;
4804 }
4805 set_q_register(Vd, src1);
4806 break;
4807 }
4808 default:
4809 UNREACHABLE();
4810 break;
4811 }
4812 }
4813 break;
4814 }
4815 case 0xd: {
4816 if (instr->Bit(21) == 0 && instr->Bit(6) == 1 && instr->Bit(4) == 1) {
4817 // vmul.f32 Qd, Qn, Qm
4818 float src1[4], src2[4];
4819 get_q_register(Vn, src1);
4820 get_q_register(Vm, src2);
4821 for (int i = 0; i < 4; i++) {
4822 src1[i] = src1[i] * src2[i];
4823 }
4824 set_q_register(Vd, src1);
4825 } else {
4826 UNIMPLEMENTED();
4827 }
4828 break;
4829 }
4830 case 0xe: {
4831 if (instr->Bit(20) == 0 && instr->Bit(4) == 0) {
4832 // vcge/vcgt.f32 Qd, Qm, Qn
4833 bool ge = instr->Bit(21) == 0;
4834 float src1[4], src2[4];
4835 get_q_register(Vn, src1);
4836 get_q_register(Vm, src2);
4837 uint32_t dst[4];
4838 for (int i = 0; i < 4; i++) {
4839 if (ge) {
4840 dst[i] = src1[i] >= src2[i] ? 0xFFFFFFFFu : 0;
4841 } else {
4842 dst[i] = src1[i] > src2[i] ? 0xFFFFFFFFu : 0;
4843 }
4844 }
4845 set_q_register(Vd, dst);
4846 } else {
4847 UNIMPLEMENTED();
4848 }
4849 break;
4850 }
4851 default:
4852 UNREACHABLE();
4853 break;
4854 }
4855 break;
4856 }
4857 case 7:
4858 if ((instr->Bits(18, 16) == 0) && (instr->Bits(11, 6) == 0x28) &&
4859 (instr->Bit(4) == 1)) {
4860 // vmovl unsigned
4861 if ((instr->VdValue() & 1) != 0) UNIMPLEMENTED();
4862 int Vd = (instr->Bit(22) << 3) | (instr->VdValue() >> 1);
4863 int Vm = (instr->Bit(5) << 4) | instr->VmValue();
4864 int imm3 = instr->Bits(21, 19);
4865 if ((imm3 != 1) && (imm3 != 2) && (imm3 != 4)) UNIMPLEMENTED();
4866 int esize = 8 * imm3;
4867 int elements = 64 / esize;
4868 uint8_t from[8];
4869 get_d_register(Vm, reinterpret_cast<uint64_t*>(from));
4870 uint16_t to[8];
4871 int e = 0;
4872 while (e < elements) {
4873 to[e] = from[e];
4874 e++;
4875 }
4876 set_q_register(Vd, reinterpret_cast<uint64_t*>(to));
4877 } else if (instr->Opc1Value() == 7 && instr->Bit(4) == 0) {
4878 if (instr->Bits(19, 16) == 0xB && instr->Bits(11, 9) == 0x3 &&
4879 instr->Bit(6) == 1) {
4880 // vcvt.<Td>.<Tm> Qd, Qm.
4881 int Vd = instr->VFPDRegValue(kSimd128Precision);
4882 int Vm = instr->VFPMRegValue(kSimd128Precision);
4883 uint32_t q_data[4];
4884 get_q_register(Vm, q_data);
4885 int op = instr->Bits(8, 7);
4886 for (int i = 0; i < 4; i++) {
4887 switch (op) {
4888 case 0:
4889 // f32 <- s32, round towards nearest.
4890 q_data[i] = bit_cast<uint32_t>(std::round(
4891 static_cast<float>(bit_cast<int32_t>(q_data[i]))));
4892 break;
4893 case 1:
4894 // f32 <- u32, round towards nearest.
4895 q_data[i] = bit_cast<uint32_t>(
4896 std::round(static_cast<float>(q_data[i])));
4897 break;
4898 case 2:
4899 // s32 <- f32, round to zero.
4900 q_data[i] = static_cast<uint32_t>(
4901 ConvertDoubleToInt(bit_cast<float>(q_data[i]), false, RZ));
4902 break;
4903 case 3:
4904 // u32 <- f32, round to zero.
4905 q_data[i] = static_cast<uint32_t>(
4906 ConvertDoubleToInt(bit_cast<float>(q_data[i]), true, RZ));
4907 break;
4908 }
4909 }
4910 set_q_register(Vd, q_data);
4911 } else if (instr->Bits(17, 16) == 0x2 && instr->Bits(11, 7) == 0) {
4912 if (instr->Bit(6) == 0) {
4913 // vswp Dd, Dm.
4914 uint64_t dval, mval;
4915 int vd = instr->VFPDRegValue(kDoublePrecision);
4916 int vm = instr->VFPMRegValue(kDoublePrecision);
4917 get_d_register(vd, &dval);
4918 get_d_register(vm, &mval);
4919 set_d_register(vm, &dval);
4920 set_d_register(vd, &mval);
4921 } else {
4922 // vswp Qd, Qm.
4923 uint32_t dval[4], mval[4];
4924 int vd = instr->VFPDRegValue(kSimd128Precision);
4925 int vm = instr->VFPMRegValue(kSimd128Precision);
4926 get_q_register(vd, dval);
4927 get_q_register(vm, mval);
4928 set_q_register(vm, dval);
4929 set_q_register(vd, mval);
4930 }
4931 } else if (instr->Bits(11, 7) == 0x18) {
4932 // vdup.32 Qd, Sm.
4933 int vd = instr->VFPDRegValue(kSimd128Precision);
4934 int vm = instr->VFPMRegValue(kDoublePrecision);
4935 int index = instr->Bit(19);
4936 uint32_t s_data = get_s_register(vm * 2 + index);
4937 uint32_t q_data[4];
4938 for (int i = 0; i < 4; i++) q_data[i] = s_data;
4939 set_q_register(vd, q_data);
4940 } else if (instr->Bits(19, 16) == 0 && instr->Bits(11, 6) == 0x17) {
4941 // vmvn Qd, Qm.
4942 int vd = instr->VFPDRegValue(kSimd128Precision);
4943 int vm = instr->VFPMRegValue(kSimd128Precision);
4944 uint32_t q_data[4];
4945 get_q_register(vm, q_data);
4946 for (int i = 0; i < 4; i++) q_data[i] = ~q_data[i];
4947 set_q_register(vd, q_data);
4948 } else if (instr->Bits(11, 10) == 0x2) {
4949 // vtb[l,x] Dd, <list>, Dm.
4950 int vd = instr->VFPDRegValue(kDoublePrecision);
4951 int vn = instr->VFPNRegValue(kDoublePrecision);
4952 int vm = instr->VFPMRegValue(kDoublePrecision);
4953 int table_len = (instr->Bits(9, 8) + 1) * kDoubleSize;
4954 bool vtbx = instr->Bit(6) != 0; // vtbl / vtbx
4955 uint64_t destination = 0, indices = 0, result = 0;
4956 get_d_register(vd, &destination);
4957 get_d_register(vm, &indices);
4958 for (int i = 0; i < kDoubleSize; i++) {
4959 int shift = i * kBitsPerByte;
4960 int index = (indices >> shift) & 0xFF;
4961 if (index < table_len) {
4962 uint64_t table;
4963 get_d_register(vn + index / kDoubleSize, &table);
4964 result |=
4965 ((table >> ((index % kDoubleSize) * kBitsPerByte)) & 0xFF)
4966 << shift;
4967 } else if (vtbx) {
4968 result |= destination & (0xFFull << shift);
4969 }
4970 }
4971 set_d_register(vd, &result);
4972 } else if (instr->Bits(17, 16) == 0x2 && instr->Bits(11, 6) == 0x7) {
4973 // vzip.<size> Qd, Qm.
4974 NeonSize size = static_cast<NeonSize>(instr->Bits(19, 18));
4975 int Vd = instr->VFPDRegValue(kSimd128Precision);
4976 int Vm = instr->VFPMRegValue(kSimd128Precision);
4977 switch (size) {
4978 case Neon8: {
4979 uint8_t src1[16], src2[16], dst1[16], dst2[16];
4980 get_q_register(Vd, src1);
4981 get_q_register(Vm, src2);
4982 for (int i = 0; i < 8; i++) {
4983 dst1[i * 2] = src1[i];
4984 dst1[i * 2 + 1] = src2[i];
4985 dst2[i * 2] = src1[i + 8];
4986 dst2[i * 2 + 1] = src2[i + 8];
4987 }
4988 set_q_register(Vd, dst1);
4989 set_q_register(Vm, dst2);
4990 break;
4991 }
4992 case Neon16: {
4993 uint16_t src1[8], src2[8], dst1[8], dst2[8];
4994 get_q_register(Vd, src1);
4995 get_q_register(Vm, src2);
4996 for (int i = 0; i < 8; i += 2) {
4997 dst1[i] = src1[i / 2];
4998 dst1[i + 1] = src2[i / 2];
4999 dst2[i] = src1[i / 2 + 4];
5000 dst2[i + 1] = src2[i / 2 + 4];
5001 }
5002 set_q_register(Vd, dst1);
5003 set_q_register(Vm, dst2);
5004 break;
5005 }
5006 case Neon32: {
5007 uint32_t src1[4], src2[4], dst1[4], dst2[4];
5008 get_q_register(Vd, src1);
5009 get_q_register(Vm, src2);
5010 for (int i = 0; i < 2; i++) {
5011 dst1[i * 2] = src1[i];
5012 dst1[i * 2 + 1] = src2[i];
5013 dst2[i * 2] = src1[i + 2];
5014 dst2[i * 2 + 1] = src2[i + 2];
5015 }
5016 set_q_register(Vd, dst1);
5017 set_q_register(Vm, dst2);
5018 break;
5019 }
5020 default:
5021 UNREACHABLE();
5022 break;
5023 }
5024 } else if (instr->Bits(17, 16) == 0 && instr->Bits(11, 9) == 0) {
5025 // vrev<op>.size Qd, Qm
5026 int Vd = instr->VFPDRegValue(kSimd128Precision);
5027 int Vm = instr->VFPMRegValue(kSimd128Precision);
5028 NeonSize size = static_cast<NeonSize>(instr->Bits(19, 18));
5029 NeonSize op = static_cast<NeonSize>(static_cast<int>(Neon64) -
5030 instr->Bits(8, 7));
5031 switch (op) {
5032 case Neon16: {
5033 DCHECK_EQ(Neon8, size);
5034 uint8_t src[16];
5035 get_q_register(Vm, src);
5036 for (int i = 0; i < 16; i += 2) {
5037 std::swap(src[i], src[i + 1]);
5038 }
5039 set_q_register(Vd, src);
5040 break;
5041 }
5042 case Neon32: {
5043 switch (size) {
5044 case Neon16: {
5045 uint16_t src[8];
5046 get_q_register(Vm, src);
5047 for (int i = 0; i < 8; i += 2) {
5048 std::swap(src[i], src[i + 1]);
5049 }
5050 set_q_register(Vd, src);
5051 break;
5052 }
5053 case Neon8: {
5054 uint8_t src[16];
5055 get_q_register(Vm, src);
5056 for (int i = 0; i < 4; i++) {
5057 std::swap(src[i * 4], src[i * 4 + 3]);
5058 std::swap(src[i * 4 + 1], src[i * 4 + 2]);
5059 }
5060 set_q_register(Vd, src);
5061 break;
5062 }
5063 default:
5064 UNREACHABLE();
5065 break;
5066 }
5067 break;
5068 }
5069 case Neon64: {
5070 switch (size) {
5071 case Neon32: {
5072 uint32_t src[4];
5073 get_q_register(Vm, src);
5074 std::swap(src[0], src[1]);
5075 std::swap(src[2], src[3]);
5076 set_q_register(Vd, src);
5077 break;
5078 }
5079 case Neon16: {
5080 uint16_t src[8];
5081 get_q_register(Vm, src);
5082 for (int i = 0; i < 4; i++) {
5083 std::swap(src[i * 4], src[i * 4 + 3]);
5084 std::swap(src[i * 4 + 1], src[i * 4 + 2]);
5085 }
5086 set_q_register(Vd, src);
5087 break;
5088 }
5089 case Neon8: {
5090 uint8_t src[16];
5091 get_q_register(Vm, src);
5092 for (int i = 0; i < 4; i++) {
5093 std::swap(src[i], src[7 - i]);
5094 std::swap(src[i + 8], src[15 - i]);
5095 }
5096 set_q_register(Vd, src);
5097 break;
5098 }
5099 default:
5100 UNREACHABLE();
5101 break;
5102 }
5103 break;
5104 }
5105 default:
5106 UNREACHABLE();
5107 break;
5108 }
5109 } else if (instr->Bits(17, 16) == 0x1 && instr->Bit(11) == 0) {
5110 int Vd = instr->VFPDRegValue(kSimd128Precision);
5111 int Vm = instr->VFPMRegValue(kSimd128Precision);
5112 NeonSize size = static_cast<NeonSize>(instr->Bits(19, 18));
5113 if (instr->Bits(9, 6) == 0xd) {
5114 // vabs<type>.<size> Qd, Qm
5115 if (instr->Bit(10) != 0) {
5116 // floating point (clear sign bits)
5117 uint32_t src[4];
5118 get_q_register(Vm, src);
5119 for (int i = 0; i < 4; i++) {
5120 src[i] &= ~0x80000000;
5121 }
5122 set_q_register(Vd, src);
5123 } else {
5124 // signed integer
5125 switch (size) {
5126 case Neon8: {
5127 int8_t src[16];
5128 get_q_register(Vm, src);
5129 for (int i = 0; i < 16; i++) {
5130 src[i] = std::abs(src[i]);
5131 }
5132 set_q_register(Vd, src);
5133 break;
5134 }
5135 case Neon16: {
5136 int16_t src[8];
5137 get_q_register(Vm, src);
5138 for (int i = 0; i < 8; i++) {
5139 src[i] = std::abs(src[i]);
5140 }
5141 set_q_register(Vd, src);
5142 break;
5143 }
5144 case Neon32: {
5145 int32_t src[4];
5146 get_q_register(Vm, src);
5147 for (int i = 0; i < 4; i++) {
5148 src[i] = std::abs(src[i]);
5149 }
5150 set_q_register(Vd, src);
5151 break;
5152 }
5153 default:
5154 UNIMPLEMENTED();
5155 break;
5156 }
5157 }
5158 } else if (instr->Bits(9, 6) == 0xf) {
5159 // vneg<type>.<size> Qd, Qm (signed integer)
5160 if (instr->Bit(10) != 0) {
5161 // floating point (toggle sign bits)
5162 uint32_t src[4];
5163 get_q_register(Vm, src);
5164 for (int i = 0; i < 4; i++) {
5165 src[i] ^= 0x80000000;
5166 }
5167 set_q_register(Vd, src);
5168 } else {
5169 // signed integer
5170 switch (size) {
5171 case Neon8: {
5172 int8_t src[16];
5173 get_q_register(Vm, src);
5174 for (int i = 0; i < 16; i++) {
5175 src[i] = -src[i];
5176 }
5177 set_q_register(Vd, src);
5178 break;
5179 }
5180 case Neon16:
5181 int16_t src[8];
5182 get_q_register(Vm, src);
5183 for (int i = 0; i < 8; i++) {
5184 src[i] = -src[i];
5185 }
5186 set_q_register(Vd, src);
5187 break;
5188 case Neon32: {
5189 int32_t src[4];
5190 get_q_register(Vm, src);
5191 for (int i = 0; i < 4; i++) {
5192 src[i] = -src[i];
5193 }
5194 set_q_register(Vd, src);
5195 break;
5196 }
5197 default:
5198 UNIMPLEMENTED();
5199 break;
5200 }
5201 }
5202 } else {
5203 UNIMPLEMENTED();
5204 }
5205 } else if (instr->Bits(19, 18) == 0x2 && instr->Bits(11, 8) == 0x5) {
5206 // vrecpe/vrsqrte.f32 Qd, Qm.
5207 int Vd = instr->VFPDRegValue(kSimd128Precision);
5208 int Vm = instr->VFPMRegValue(kSimd128Precision);
5209 uint32_t src[4];
5210 get_q_register(Vm, src);
5211 if (instr->Bit(7) == 0) {
5212 for (int i = 0; i < 4; i++) {
5213 float denom = bit_cast<float>(src[i]);
5214 div_zero_vfp_flag_ = (denom == 0);
5215 float result = 1.0f / denom;
5216 result = canonicalizeNaN(result);
5217 src[i] = bit_cast<uint32_t>(result);
5218 }
5219 } else {
5220 lazily_initialize_fast_sqrt(isolate_);
5221 for (int i = 0; i < 4; i++) {
5222 float radicand = bit_cast<float>(src[i]);
5223 float result = 1.0f / fast_sqrt(radicand, isolate_);
5224 result = canonicalizeNaN(result);
5225 src[i] = bit_cast<uint32_t>(result);
5226 }
5227 }
5228 set_q_register(Vd, src);
5229 } else {
5230 UNIMPLEMENTED();
5231 }
5232 } else if (instr->Bits(11, 7) == 0 && instr->Bit(4) == 1) {
5233 // vshr.u<size> Qd, Qm, shift
5234 int size = base::bits::RoundDownToPowerOfTwo32(instr->Bits(21, 16));
5235 int shift = 2 * size - instr->Bits(21, 16);
5236 int Vd = instr->VFPDRegValue(kSimd128Precision);
5237 int Vm = instr->VFPMRegValue(kSimd128Precision);
5238 NeonSize ns = static_cast<NeonSize>(size / 16);
5239 switch (ns) {
5240 case Neon8: {
5241 uint8_t src[16];
5242 get_q_register(Vm, src);
5243 for (int i = 0; i < 16; i++) {
5244 src[i] >>= shift;
5245 }
5246 set_q_register(Vd, src);
5247 break;
5248 }
5249 case Neon16: {
5250 uint16_t src[8];
5251 get_q_register(Vm, src);
5252 for (int i = 0; i < 8; i++) {
5253 src[i] >>= shift;
5254 }
5255 set_q_register(Vd, src);
5256 break;
5257 }
5258 case Neon32: {
5259 uint32_t src[4];
5260 get_q_register(Vm, src);
5261 for (int i = 0; i < 4; i++) {
5262 src[i] >>= shift;
5263 }
5264 set_q_register(Vd, src);
5265 break;
5266 }
5267 default:
5268 UNREACHABLE();
5269 break;
5270 }
5271 } else {
5272 UNIMPLEMENTED();
5273 }
5274 break;
5275 case 8:
5276 if (instr->Bits(21, 20) == 0) {
5277 // vst1
5278 int Vd = (instr->Bit(22) << 4) | instr->VdValue();
5279 int Rn = instr->VnValue();
5280 int type = instr->Bits(11, 8);
5281 int Rm = instr->VmValue();
5282 int32_t address = get_register(Rn);
5283 int regs = 0;
5284 switch (type) {
5285 case nlt_1:
5286 regs = 1;
5287 break;
5288 case nlt_2:
5289 regs = 2;
5290 break;
5291 case nlt_3:
5292 regs = 3;
5293 break;
5294 case nlt_4:
5295 regs = 4;
5296 break;
5297 default:
5298 UNIMPLEMENTED();
5299 break;
5300 }
5301 int r = 0;
5302 while (r < regs) {
5303 uint32_t data[2];
5304 get_d_register(Vd + r, data);
5305 WriteW(address, data[0], instr);
5306 WriteW(address + 4, data[1], instr);
5307 address += 8;
5308 r++;
5309 }
5310 if (Rm != 15) {
5311 if (Rm == 13) {
5312 set_register(Rn, address);
5313 } else {
5314 set_register(Rn, get_register(Rn) + get_register(Rm));
5315 }
5316 }
5317 } else if (instr->Bits(21, 20) == 2) {
5318 // vld1
5319 int Vd = (instr->Bit(22) << 4) | instr->VdValue();
5320 int Rn = instr->VnValue();
5321 int type = instr->Bits(11, 8);
5322 int Rm = instr->VmValue();
5323 int32_t address = get_register(Rn);
5324 int regs = 0;
5325 switch (type) {
5326 case nlt_1:
5327 regs = 1;
5328 break;
5329 case nlt_2:
5330 regs = 2;
5331 break;
5332 case nlt_3:
5333 regs = 3;
5334 break;
5335 case nlt_4:
5336 regs = 4;
5337 break;
5338 default:
5339 UNIMPLEMENTED();
5340 break;
5341 }
5342 int r = 0;
5343 while (r < regs) {
5344 uint32_t data[2];
5345 data[0] = ReadW(address, instr);
5346 data[1] = ReadW(address + 4, instr);
5347 set_d_register(Vd + r, data);
5348 address += 8;
5349 r++;
5350 }
5351 if (Rm != 15) {
5352 if (Rm == 13) {
5353 set_register(Rn, address);
5354 } else {
5355 set_register(Rn, get_register(Rn) + get_register(Rm));
5356 }
5357 }
5358 } else {
5359 UNIMPLEMENTED();
5360 }
5361 break;
5362 case 0xA:
5363 case 0xB:
5364 if ((instr->Bits(22, 20) == 5) && (instr->Bits(15, 12) == 0xf)) {
5365 // pld: ignore instruction.
5366 } else if (instr->SpecialValue() == 0xA && instr->Bits(22, 20) == 7) {
5367 // dsb, dmb, isb: ignore instruction for now.
5368 // TODO(binji): implement
5369 // Also refer to the ARMv6 CP15 equivalents in DecodeTypeCP15.
5370 } else {
5371 UNIMPLEMENTED();
5372 }
5373 break;
5374 case 0x1D:
5375 if (instr->Opc1Value() == 0x7 && instr->Opc3Value() == 0x1 &&
5376 instr->Bits(11, 9) == 0x5 && instr->Bits(19, 18) == 0x2) {
5377 if (instr->SzValue() == 0x1) {
5378 int vm = instr->VFPMRegValue(kDoublePrecision);
5379 int vd = instr->VFPDRegValue(kDoublePrecision);
5380 double dm_value = get_double_from_d_register(vm);
5381 double dd_value = 0.0;
5382 int rounding_mode = instr->Bits(17, 16);
5383 switch (rounding_mode) {
5384 case 0x0: // vrinta - round with ties to away from zero
5385 dd_value = round(dm_value);
5386 break;
5387 case 0x1: { // vrintn - round with ties to even
5388 dd_value = nearbyint(dm_value);
5389 break;
5390 }
5391 case 0x2: // vrintp - ceil
5392 dd_value = ceil(dm_value);
5393 break;
5394 case 0x3: // vrintm - floor
5395 dd_value = floor(dm_value);
5396 break;
5397 default:
5398 UNREACHABLE(); // Case analysis is exhaustive.
5399 break;
5400 }
5401 dd_value = canonicalizeNaN(dd_value);
5402 set_d_register_from_double(vd, dd_value);
5403 } else {
5404 int m = instr->VFPMRegValue(kSinglePrecision);
5405 int d = instr->VFPDRegValue(kSinglePrecision);
5406 float sm_value = get_float_from_s_register(m);
5407 float sd_value = 0.0;
5408 int rounding_mode = instr->Bits(17, 16);
5409 switch (rounding_mode) {
5410 case 0x0: // vrinta - round with ties to away from zero
5411 sd_value = roundf(sm_value);
5412 break;
5413 case 0x1: { // vrintn - round with ties to even
5414 sd_value = nearbyintf(sm_value);
5415 break;
5416 }
5417 case 0x2: // vrintp - ceil
5418 sd_value = ceilf(sm_value);
5419 break;
5420 case 0x3: // vrintm - floor
5421 sd_value = floorf(sm_value);
5422 break;
5423 default:
5424 UNREACHABLE(); // Case analysis is exhaustive.
5425 break;
5426 }
5427 sd_value = canonicalizeNaN(sd_value);
5428 set_s_register_from_float(d, sd_value);
5429 }
5430 } else if ((instr->Opc1Value() == 0x4) && (instr->Bits(11, 9) == 0x5) &&
5431 (instr->Bit(4) == 0x0)) {
5432 if (instr->SzValue() == 0x1) {
5433 int m = instr->VFPMRegValue(kDoublePrecision);
5434 int n = instr->VFPNRegValue(kDoublePrecision);
5435 int d = instr->VFPDRegValue(kDoublePrecision);
5436 double dn_value = get_double_from_d_register(n);
5437 double dm_value = get_double_from_d_register(m);
5438 double dd_value;
5439 if (instr->Bit(6) == 0x1) { // vminnm
5440 if ((dn_value < dm_value) || std::isnan(dm_value)) {
5441 dd_value = dn_value;
5442 } else if ((dm_value < dn_value) || std::isnan(dn_value)) {
5443 dd_value = dm_value;
5444 } else {
5445 DCHECK_EQ(dn_value, dm_value);
5446 // Make sure that we pick the most negative sign for +/-0.
5447 dd_value = std::signbit(dn_value) ? dn_value : dm_value;
5448 }
5449 } else { // vmaxnm
5450 if ((dn_value > dm_value) || std::isnan(dm_value)) {
5451 dd_value = dn_value;
5452 } else if ((dm_value > dn_value) || std::isnan(dn_value)) {
5453 dd_value = dm_value;
5454 } else {
5455 DCHECK_EQ(dn_value, dm_value);
5456 // Make sure that we pick the most positive sign for +/-0.
5457 dd_value = std::signbit(dn_value) ? dm_value : dn_value;
5458 }
5459 }
5460 dd_value = canonicalizeNaN(dd_value);
5461 set_d_register_from_double(d, dd_value);
5462 } else {
5463 int m = instr->VFPMRegValue(kSinglePrecision);
5464 int n = instr->VFPNRegValue(kSinglePrecision);
5465 int d = instr->VFPDRegValue(kSinglePrecision);
5466 float sn_value = get_float_from_s_register(n);
5467 float sm_value = get_float_from_s_register(m);
5468 float sd_value;
5469 if (instr->Bit(6) == 0x1) { // vminnm
5470 if ((sn_value < sm_value) || std::isnan(sm_value)) {
5471 sd_value = sn_value;
5472 } else if ((sm_value < sn_value) || std::isnan(sn_value)) {
5473 sd_value = sm_value;
5474 } else {
5475 DCHECK_EQ(sn_value, sm_value);
5476 // Make sure that we pick the most negative sign for +/-0.
5477 sd_value = std::signbit(sn_value) ? sn_value : sm_value;
5478 }
5479 } else { // vmaxnm
5480 if ((sn_value > sm_value) || std::isnan(sm_value)) {
5481 sd_value = sn_value;
5482 } else if ((sm_value > sn_value) || std::isnan(sn_value)) {
5483 sd_value = sm_value;
5484 } else {
5485 DCHECK_EQ(sn_value, sm_value);
5486 // Make sure that we pick the most positive sign for +/-0.
5487 sd_value = std::signbit(sn_value) ? sm_value : sn_value;
5488 }
5489 }
5490 sd_value = canonicalizeNaN(sd_value);
5491 set_s_register_from_float(d, sd_value);
5492 }
5493 } else {
5494 UNIMPLEMENTED();
5495 }
5496 break;
5497 case 0x1C:
5498 if ((instr->Bits(11, 9) == 0x5) && (instr->Bit(6) == 0) &&
5499 (instr->Bit(4) == 0)) {
5500 // VSEL* (floating-point)
5501 bool condition_holds;
5502 switch (instr->Bits(21, 20)) {
5503 case 0x0: // VSELEQ
5504 condition_holds = (z_flag_ == 1);
5505 break;
5506 case 0x1: // VSELVS
5507 condition_holds = (v_flag_ == 1);
5508 break;
5509 case 0x2: // VSELGE
5510 condition_holds = (n_flag_ == v_flag_);
5511 break;
5512 case 0x3: // VSELGT
5513 condition_holds = ((z_flag_ == 0) && (n_flag_ == v_flag_));
5514 break;
5515 default:
5516 UNREACHABLE(); // Case analysis is exhaustive.
5517 break;
5518 }
5519 if (instr->SzValue() == 0x1) {
5520 int n = instr->VFPNRegValue(kDoublePrecision);
5521 int m = instr->VFPMRegValue(kDoublePrecision);
5522 int d = instr->VFPDRegValue(kDoublePrecision);
5523 double result = get_double_from_d_register(condition_holds ? n : m);
5524 set_d_register_from_double(d, result);
5525 } else {
5526 int n = instr->VFPNRegValue(kSinglePrecision);
5527 int m = instr->VFPMRegValue(kSinglePrecision);
5528 int d = instr->VFPDRegValue(kSinglePrecision);
5529 float result = get_float_from_s_register(condition_holds ? n : m);
5530 set_s_register_from_float(d, result);
5531 }
5532 } else {
5533 UNIMPLEMENTED();
5534 }
5535 break;
5536 default:
5537 UNIMPLEMENTED();
5538 break;
5539 }
5540 }
5541
5542
5543 // Executes the current instruction.
InstructionDecode(Instruction * instr)5544 void Simulator::InstructionDecode(Instruction* instr) {
5545 if (v8::internal::FLAG_check_icache) {
5546 CheckICache(isolate_->simulator_i_cache(), instr);
5547 }
5548 pc_modified_ = false;
5549 if (::v8::internal::FLAG_trace_sim) {
5550 disasm::NameConverter converter;
5551 disasm::Disassembler dasm(converter);
5552 // use a reasonably large buffer
5553 v8::internal::EmbeddedVector<char, 256> buffer;
5554 dasm.InstructionDecode(buffer,
5555 reinterpret_cast<byte*>(instr));
5556 PrintF(" 0x%08" V8PRIxPTR " %s\n", reinterpret_cast<intptr_t>(instr),
5557 buffer.start());
5558 }
5559 if (instr->ConditionField() == kSpecialCondition) {
5560 DecodeSpecialCondition(instr);
5561 } else if (ConditionallyExecute(instr)) {
5562 switch (instr->TypeValue()) {
5563 case 0:
5564 case 1: {
5565 DecodeType01(instr);
5566 break;
5567 }
5568 case 2: {
5569 DecodeType2(instr);
5570 break;
5571 }
5572 case 3: {
5573 DecodeType3(instr);
5574 break;
5575 }
5576 case 4: {
5577 DecodeType4(instr);
5578 break;
5579 }
5580 case 5: {
5581 DecodeType5(instr);
5582 break;
5583 }
5584 case 6: {
5585 DecodeType6(instr);
5586 break;
5587 }
5588 case 7: {
5589 DecodeType7(instr);
5590 break;
5591 }
5592 default: {
5593 UNIMPLEMENTED();
5594 break;
5595 }
5596 }
5597 // If the instruction is a non taken conditional stop, we need to skip the
5598 // inlined message address.
5599 } else if (instr->IsStop()) {
5600 set_pc(get_pc() + 2 * Instruction::kInstrSize);
5601 }
5602 if (!pc_modified_) {
5603 set_register(pc, reinterpret_cast<int32_t>(instr)
5604 + Instruction::kInstrSize);
5605 }
5606 }
5607
5608
Execute()5609 void Simulator::Execute() {
5610 // Get the PC to simulate. Cannot use the accessor here as we need the
5611 // raw PC value and not the one used as input to arithmetic instructions.
5612 int program_counter = get_pc();
5613
5614 if (::v8::internal::FLAG_stop_sim_at == 0) {
5615 // Fast version of the dispatch loop without checking whether the simulator
5616 // should be stopping at a particular executed instruction.
5617 while (program_counter != end_sim_pc) {
5618 Instruction* instr = reinterpret_cast<Instruction*>(program_counter);
5619 icount_++;
5620 InstructionDecode(instr);
5621 program_counter = get_pc();
5622 }
5623 } else {
5624 // FLAG_stop_sim_at is at the non-default value. Stop in the debugger when
5625 // we reach the particular instuction count.
5626 while (program_counter != end_sim_pc) {
5627 Instruction* instr = reinterpret_cast<Instruction*>(program_counter);
5628 icount_++;
5629 if (icount_ == ::v8::internal::FLAG_stop_sim_at) {
5630 ArmDebugger dbg(this);
5631 dbg.Debug();
5632 } else {
5633 InstructionDecode(instr);
5634 }
5635 program_counter = get_pc();
5636 }
5637 }
5638 }
5639
5640
CallInternal(byte * entry)5641 void Simulator::CallInternal(byte* entry) {
5642 // Adjust JS-based stack limit to C-based stack limit.
5643 isolate_->stack_guard()->AdjustStackLimitForSimulator();
5644
5645 // Prepare to execute the code at entry
5646 set_register(pc, reinterpret_cast<int32_t>(entry));
5647 // Put down marker for end of simulation. The simulator will stop simulation
5648 // when the PC reaches this value. By saving the "end simulation" value into
5649 // the LR the simulation stops when returning to this call point.
5650 set_register(lr, end_sim_pc);
5651
5652 // Remember the values of callee-saved registers.
5653 // The code below assumes that r9 is not used as sb (static base) in
5654 // simulator code and therefore is regarded as a callee-saved register.
5655 int32_t r4_val = get_register(r4);
5656 int32_t r5_val = get_register(r5);
5657 int32_t r6_val = get_register(r6);
5658 int32_t r7_val = get_register(r7);
5659 int32_t r8_val = get_register(r8);
5660 int32_t r9_val = get_register(r9);
5661 int32_t r10_val = get_register(r10);
5662 int32_t r11_val = get_register(r11);
5663
5664 // Set up the callee-saved registers with a known value. To be able to check
5665 // that they are preserved properly across JS execution.
5666 int32_t callee_saved_value = icount_;
5667 set_register(r4, callee_saved_value);
5668 set_register(r5, callee_saved_value);
5669 set_register(r6, callee_saved_value);
5670 set_register(r7, callee_saved_value);
5671 set_register(r8, callee_saved_value);
5672 set_register(r9, callee_saved_value);
5673 set_register(r10, callee_saved_value);
5674 set_register(r11, callee_saved_value);
5675
5676 // Start the simulation
5677 Execute();
5678
5679 // Check that the callee-saved registers have been preserved.
5680 CHECK_EQ(callee_saved_value, get_register(r4));
5681 CHECK_EQ(callee_saved_value, get_register(r5));
5682 CHECK_EQ(callee_saved_value, get_register(r6));
5683 CHECK_EQ(callee_saved_value, get_register(r7));
5684 CHECK_EQ(callee_saved_value, get_register(r8));
5685 CHECK_EQ(callee_saved_value, get_register(r9));
5686 CHECK_EQ(callee_saved_value, get_register(r10));
5687 CHECK_EQ(callee_saved_value, get_register(r11));
5688
5689 // Restore callee-saved registers with the original value.
5690 set_register(r4, r4_val);
5691 set_register(r5, r5_val);
5692 set_register(r6, r6_val);
5693 set_register(r7, r7_val);
5694 set_register(r8, r8_val);
5695 set_register(r9, r9_val);
5696 set_register(r10, r10_val);
5697 set_register(r11, r11_val);
5698 }
5699
5700
Call(byte * entry,int argument_count,...)5701 int32_t Simulator::Call(byte* entry, int argument_count, ...) {
5702 va_list parameters;
5703 va_start(parameters, argument_count);
5704 // Set up arguments
5705
5706 // First four arguments passed in registers.
5707 DCHECK(argument_count >= 4);
5708 set_register(r0, va_arg(parameters, int32_t));
5709 set_register(r1, va_arg(parameters, int32_t));
5710 set_register(r2, va_arg(parameters, int32_t));
5711 set_register(r3, va_arg(parameters, int32_t));
5712
5713 // Remaining arguments passed on stack.
5714 int original_stack = get_register(sp);
5715 // Compute position of stack on entry to generated code.
5716 int entry_stack = (original_stack - (argument_count - 4) * sizeof(int32_t));
5717 if (base::OS::ActivationFrameAlignment() != 0) {
5718 entry_stack &= -base::OS::ActivationFrameAlignment();
5719 }
5720 // Store remaining arguments on stack, from low to high memory.
5721 intptr_t* stack_argument = reinterpret_cast<intptr_t*>(entry_stack);
5722 for (int i = 4; i < argument_count; i++) {
5723 stack_argument[i - 4] = va_arg(parameters, int32_t);
5724 }
5725 va_end(parameters);
5726 set_register(sp, entry_stack);
5727
5728 CallInternal(entry);
5729
5730 // Pop stack passed arguments.
5731 CHECK_EQ(entry_stack, get_register(sp));
5732 set_register(sp, original_stack);
5733
5734 int32_t result = get_register(r0);
5735 return result;
5736 }
5737
5738
CallFP(byte * entry,double d0,double d1)5739 void Simulator::CallFP(byte* entry, double d0, double d1) {
5740 if (use_eabi_hardfloat()) {
5741 set_d_register_from_double(0, d0);
5742 set_d_register_from_double(1, d1);
5743 } else {
5744 set_register_pair_from_double(0, &d0);
5745 set_register_pair_from_double(2, &d1);
5746 }
5747 CallInternal(entry);
5748 }
5749
5750
CallFPReturnsInt(byte * entry,double d0,double d1)5751 int32_t Simulator::CallFPReturnsInt(byte* entry, double d0, double d1) {
5752 CallFP(entry, d0, d1);
5753 int32_t result = get_register(r0);
5754 return result;
5755 }
5756
5757
CallFPReturnsDouble(byte * entry,double d0,double d1)5758 double Simulator::CallFPReturnsDouble(byte* entry, double d0, double d1) {
5759 CallFP(entry, d0, d1);
5760 if (use_eabi_hardfloat()) {
5761 return get_double_from_d_register(0);
5762 } else {
5763 return get_double_from_register_pair(0);
5764 }
5765 }
5766
5767
PushAddress(uintptr_t address)5768 uintptr_t Simulator::PushAddress(uintptr_t address) {
5769 int new_sp = get_register(sp) - sizeof(uintptr_t);
5770 uintptr_t* stack_slot = reinterpret_cast<uintptr_t*>(new_sp);
5771 *stack_slot = address;
5772 set_register(sp, new_sp);
5773 return new_sp;
5774 }
5775
5776
PopAddress()5777 uintptr_t Simulator::PopAddress() {
5778 int current_sp = get_register(sp);
5779 uintptr_t* stack_slot = reinterpret_cast<uintptr_t*>(current_sp);
5780 uintptr_t address = *stack_slot;
5781 set_register(sp, current_sp + sizeof(uintptr_t));
5782 return address;
5783 }
5784
LocalMonitor()5785 Simulator::LocalMonitor::LocalMonitor()
5786 : access_state_(MonitorAccess::Open),
5787 tagged_addr_(0),
5788 size_(TransactionSize::None) {}
5789
Clear()5790 void Simulator::LocalMonitor::Clear() {
5791 access_state_ = MonitorAccess::Open;
5792 tagged_addr_ = 0;
5793 size_ = TransactionSize::None;
5794 }
5795
NotifyLoad(int32_t addr)5796 void Simulator::LocalMonitor::NotifyLoad(int32_t addr) {
5797 if (access_state_ == MonitorAccess::Exclusive) {
5798 // A load could cause a cache eviction which will affect the monitor. As a
5799 // result, it's most strict to unconditionally clear the local monitor on
5800 // load.
5801 Clear();
5802 }
5803 }
5804
NotifyLoadExcl(int32_t addr,TransactionSize size)5805 void Simulator::LocalMonitor::NotifyLoadExcl(int32_t addr,
5806 TransactionSize size) {
5807 access_state_ = MonitorAccess::Exclusive;
5808 tagged_addr_ = addr;
5809 size_ = size;
5810 }
5811
NotifyStore(int32_t addr)5812 void Simulator::LocalMonitor::NotifyStore(int32_t addr) {
5813 if (access_state_ == MonitorAccess::Exclusive) {
5814 // It is implementation-defined whether a non-exclusive store to an address
5815 // covered by the local monitor during exclusive access transitions to open
5816 // or exclusive access. See ARM DDI 0406C.b, A3.4.1.
5817 //
5818 // However, a store could cause a cache eviction which will affect the
5819 // monitor. As a result, it's most strict to unconditionally clear the
5820 // local monitor on store.
5821 Clear();
5822 }
5823 }
5824
NotifyStoreExcl(int32_t addr,TransactionSize size)5825 bool Simulator::LocalMonitor::NotifyStoreExcl(int32_t addr,
5826 TransactionSize size) {
5827 if (access_state_ == MonitorAccess::Exclusive) {
5828 // It is allowed for a processor to require that the address matches
5829 // exactly (A3.4.5), so this comparison does not mask addr.
5830 if (addr == tagged_addr_ && size_ == size) {
5831 Clear();
5832 return true;
5833 } else {
5834 // It is implementation-defined whether an exclusive store to a
5835 // non-tagged address will update memory. Behavior is unpredictable if
5836 // the transaction size of the exclusive store differs from that of the
5837 // exclusive load. See ARM DDI 0406C.b, A3.4.5.
5838 Clear();
5839 return false;
5840 }
5841 } else {
5842 DCHECK(access_state_ == MonitorAccess::Open);
5843 return false;
5844 }
5845 }
5846
Processor()5847 Simulator::GlobalMonitor::Processor::Processor()
5848 : access_state_(MonitorAccess::Open),
5849 tagged_addr_(0),
5850 next_(nullptr),
5851 prev_(nullptr),
5852 failure_counter_(0) {}
5853
Clear_Locked()5854 void Simulator::GlobalMonitor::Processor::Clear_Locked() {
5855 access_state_ = MonitorAccess::Open;
5856 tagged_addr_ = 0;
5857 }
5858
NotifyLoadExcl_Locked(int32_t addr)5859 void Simulator::GlobalMonitor::Processor::NotifyLoadExcl_Locked(int32_t addr) {
5860 access_state_ = MonitorAccess::Exclusive;
5861 tagged_addr_ = addr;
5862 }
5863
NotifyStore_Locked(int32_t addr,bool is_requesting_processor)5864 void Simulator::GlobalMonitor::Processor::NotifyStore_Locked(
5865 int32_t addr, bool is_requesting_processor) {
5866 if (access_state_ == MonitorAccess::Exclusive) {
5867 // It is implementation-defined whether a non-exclusive store by the
5868 // requesting processor to an address covered by the global monitor
5869 // during exclusive access transitions to open or exclusive access.
5870 //
5871 // For any other processor, the access state always transitions to open
5872 // access.
5873 //
5874 // See ARM DDI 0406C.b, A3.4.2.
5875 //
5876 // However, similar to the local monitor, it is possible that a store
5877 // caused a cache eviction, which can affect the montior, so
5878 // conservatively, we always clear the monitor.
5879 Clear_Locked();
5880 }
5881 }
5882
NotifyStoreExcl_Locked(int32_t addr,bool is_requesting_processor)5883 bool Simulator::GlobalMonitor::Processor::NotifyStoreExcl_Locked(
5884 int32_t addr, bool is_requesting_processor) {
5885 if (access_state_ == MonitorAccess::Exclusive) {
5886 if (is_requesting_processor) {
5887 // It is allowed for a processor to require that the address matches
5888 // exactly (A3.4.5), so this comparison does not mask addr.
5889 if (addr == tagged_addr_) {
5890 // The access state for the requesting processor after a successful
5891 // exclusive store is implementation-defined, but according to the ARM
5892 // DDI, this has no effect on the subsequent operation of the global
5893 // monitor.
5894 Clear_Locked();
5895 // Introduce occasional strex failures. This is to simulate the
5896 // behavior of hardware, which can randomly fail due to background
5897 // cache evictions.
5898 if (failure_counter_++ >= kMaxFailureCounter) {
5899 failure_counter_ = 0;
5900 return false;
5901 } else {
5902 return true;
5903 }
5904 }
5905 } else if ((addr & kExclusiveTaggedAddrMask) ==
5906 (tagged_addr_ & kExclusiveTaggedAddrMask)) {
5907 // Check the masked addresses when responding to a successful lock by
5908 // another processor so the implementation is more conservative (i.e. the
5909 // granularity of locking is as large as possible.)
5910 Clear_Locked();
5911 return false;
5912 }
5913 }
5914 return false;
5915 }
5916
GlobalMonitor()5917 Simulator::GlobalMonitor::GlobalMonitor() : head_(nullptr) {}
5918
NotifyLoadExcl_Locked(int32_t addr,Processor * processor)5919 void Simulator::GlobalMonitor::NotifyLoadExcl_Locked(int32_t addr,
5920 Processor* processor) {
5921 processor->NotifyLoadExcl_Locked(addr);
5922 PrependProcessor_Locked(processor);
5923 }
5924
NotifyStore_Locked(int32_t addr,Processor * processor)5925 void Simulator::GlobalMonitor::NotifyStore_Locked(int32_t addr,
5926 Processor* processor) {
5927 // Notify each processor of the store operation.
5928 for (Processor* iter = head_; iter; iter = iter->next_) {
5929 bool is_requesting_processor = iter == processor;
5930 iter->NotifyStore_Locked(addr, is_requesting_processor);
5931 }
5932 }
5933
NotifyStoreExcl_Locked(int32_t addr,Processor * processor)5934 bool Simulator::GlobalMonitor::NotifyStoreExcl_Locked(int32_t addr,
5935 Processor* processor) {
5936 DCHECK(IsProcessorInLinkedList_Locked(processor));
5937 if (processor->NotifyStoreExcl_Locked(addr, true)) {
5938 // Notify the other processors that this StoreExcl succeeded.
5939 for (Processor* iter = head_; iter; iter = iter->next_) {
5940 if (iter != processor) {
5941 iter->NotifyStoreExcl_Locked(addr, false);
5942 }
5943 }
5944 return true;
5945 } else {
5946 return false;
5947 }
5948 }
5949
IsProcessorInLinkedList_Locked(Processor * processor) const5950 bool Simulator::GlobalMonitor::IsProcessorInLinkedList_Locked(
5951 Processor* processor) const {
5952 return head_ == processor || processor->next_ || processor->prev_;
5953 }
5954
PrependProcessor_Locked(Processor * processor)5955 void Simulator::GlobalMonitor::PrependProcessor_Locked(Processor* processor) {
5956 if (IsProcessorInLinkedList_Locked(processor)) {
5957 return;
5958 }
5959
5960 if (head_) {
5961 head_->prev_ = processor;
5962 }
5963 processor->prev_ = nullptr;
5964 processor->next_ = head_;
5965 head_ = processor;
5966 }
5967
RemoveProcessor(Processor * processor)5968 void Simulator::GlobalMonitor::RemoveProcessor(Processor* processor) {
5969 base::LockGuard<base::Mutex> lock_guard(&mutex);
5970 if (!IsProcessorInLinkedList_Locked(processor)) {
5971 return;
5972 }
5973
5974 if (processor->prev_) {
5975 processor->prev_->next_ = processor->next_;
5976 } else {
5977 head_ = processor->next_;
5978 }
5979 if (processor->next_) {
5980 processor->next_->prev_ = processor->prev_;
5981 }
5982 processor->prev_ = nullptr;
5983 processor->next_ = nullptr;
5984 }
5985
5986 } // namespace internal
5987 } // namespace v8
5988
5989 #endif // USE_SIMULATOR
5990
5991 #endif // V8_TARGET_ARCH_ARM
5992