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