V8 API Reference, 7.2.502.16 (for Deno 0.2.4)
simulator-arm64.cc
1 // Copyright 2013 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 <stdlib.h>
6 #include <cmath>
7 #include <cstdarg>
8 #include <type_traits>
9 
10 #if V8_TARGET_ARCH_ARM64
11 
12 #include "src/arm64/decoder-arm64-inl.h"
13 #include "src/arm64/simulator-arm64.h"
14 #include "src/assembler-inl.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/ostreams.h"
20 #include "src/runtime/runtime-utils.h"
21 
22 namespace v8 {
23 namespace internal {
24 
25 #if defined(USE_SIMULATOR)
26 
27 
28 // This macro provides a platform independent use of sscanf. The reason for
29 // SScanF not being implemented in a platform independent way through
30 // ::v8::internal::OS in the same way as SNPrintF is that the
31 // Windows C Run-Time Library does not provide vsscanf.
32 #define SScanF sscanf // NOLINT
33 
34 
35 // Helpers for colors.
36 #define COLOUR(colour_code) "\033[0;" colour_code "m"
37 #define COLOUR_BOLD(colour_code) "\033[1;" colour_code "m"
38 #define NORMAL ""
39 #define GREY "30"
40 #define RED "31"
41 #define GREEN "32"
42 #define YELLOW "33"
43 #define BLUE "34"
44 #define MAGENTA "35"
45 #define CYAN "36"
46 #define WHITE "37"
47 
48 typedef char const * const TEXT_COLOUR;
49 TEXT_COLOUR clr_normal = FLAG_log_colour ? COLOUR(NORMAL) : "";
50 TEXT_COLOUR clr_flag_name = FLAG_log_colour ? COLOUR_BOLD(WHITE) : "";
51 TEXT_COLOUR clr_flag_value = FLAG_log_colour ? COLOUR(NORMAL) : "";
52 TEXT_COLOUR clr_reg_name = FLAG_log_colour ? COLOUR_BOLD(CYAN) : "";
53 TEXT_COLOUR clr_reg_value = FLAG_log_colour ? COLOUR(CYAN) : "";
54 TEXT_COLOUR clr_vreg_name = FLAG_log_colour ? COLOUR_BOLD(MAGENTA) : "";
55 TEXT_COLOUR clr_vreg_value = FLAG_log_colour ? COLOUR(MAGENTA) : "";
56 TEXT_COLOUR clr_memory_address = FLAG_log_colour ? COLOUR_BOLD(BLUE) : "";
57 TEXT_COLOUR clr_debug_number = FLAG_log_colour ? COLOUR_BOLD(YELLOW) : "";
58 TEXT_COLOUR clr_debug_message = FLAG_log_colour ? COLOUR(YELLOW) : "";
59 TEXT_COLOUR clr_printf = FLAG_log_colour ? COLOUR(GREEN) : "";
60 
61 // static
62 base::LazyInstance<Simulator::GlobalMonitor>::type Simulator::global_monitor_ =
63  LAZY_INSTANCE_INITIALIZER;
64 
65 // This is basically the same as PrintF, with a guard for FLAG_trace_sim.
66 void Simulator::TraceSim(const char* format, ...) {
67  if (FLAG_trace_sim) {
68  va_list arguments;
69  va_start(arguments, format);
70  base::OS::VFPrint(stream_, format, arguments);
71  va_end(arguments);
72  }
73 }
74 
75 const Instruction* Simulator::kEndOfSimAddress = nullptr;
76 
77 void SimSystemRegister::SetBits(int msb, int lsb, uint32_t bits) {
78  int width = msb - lsb + 1;
79  DCHECK(is_uintn(bits, width) || is_intn(bits, width));
80 
81  bits <<= lsb;
82  uint32_t mask = ((1 << width) - 1) << lsb;
83  DCHECK_EQ(mask & write_ignore_mask_, 0);
84 
85  value_ = (value_ & ~mask) | (bits & mask);
86 }
87 
88 
89 SimSystemRegister SimSystemRegister::DefaultValueFor(SystemRegister id) {
90  switch (id) {
91  case NZCV:
92  return SimSystemRegister(0x00000000, NZCVWriteIgnoreMask);
93  case FPCR:
94  return SimSystemRegister(0x00000000, FPCRWriteIgnoreMask);
95  default:
96  UNREACHABLE();
97  }
98 }
99 
100 
101 // Get the active Simulator for the current thread.
102 Simulator* Simulator::current(Isolate* isolate) {
103  Isolate::PerIsolateThreadData* isolate_data =
104  isolate->FindOrAllocatePerThreadDataForThisThread();
105  DCHECK_NOT_NULL(isolate_data);
106 
107  Simulator* sim = isolate_data->simulator();
108  if (sim == nullptr) {
109  if (FLAG_trace_sim || FLAG_log_instruction_stats || FLAG_debug_sim) {
110  sim = new Simulator(new Decoder<DispatchingDecoderVisitor>(), isolate);
111  } else {
112  sim = new Decoder<Simulator>();
113  sim->isolate_ = isolate;
114  }
115  isolate_data->set_simulator(sim);
116  }
117  return sim;
118 }
119 
120 void Simulator::CallImpl(Address entry, CallArgument* args) {
121  int index_x = 0;
122  int index_d = 0;
123 
124  std::vector<int64_t> stack_args(0);
125  for (int i = 0; !args[i].IsEnd(); i++) {
126  CallArgument arg = args[i];
127  if (arg.IsX() && (index_x < 8)) {
128  set_xreg(index_x++, arg.bits());
129  } else if (arg.IsD() && (index_d < 8)) {
130  set_dreg_bits(index_d++, arg.bits());
131  } else {
132  DCHECK(arg.IsD() || arg.IsX());
133  stack_args.push_back(arg.bits());
134  }
135  }
136 
137  // Process stack arguments, and make sure the stack is suitably aligned.
138  uintptr_t original_stack = sp();
139  uintptr_t entry_stack = original_stack -
140  stack_args.size() * sizeof(stack_args[0]);
141  if (base::OS::ActivationFrameAlignment() != 0) {
142  entry_stack &= -base::OS::ActivationFrameAlignment();
143  }
144  char * stack = reinterpret_cast<char*>(entry_stack);
145  std::vector<int64_t>::const_iterator it;
146  for (it = stack_args.begin(); it != stack_args.end(); it++) {
147  memcpy(stack, &(*it), sizeof(*it));
148  stack += sizeof(*it);
149  }
150 
151  DCHECK(reinterpret_cast<uintptr_t>(stack) <= original_stack);
152  set_sp(entry_stack);
153 
154  // Call the generated code.
155  set_pc(entry);
156  set_lr(kEndOfSimAddress);
157  CheckPCSComplianceAndRun();
158 
159  set_sp(original_stack);
160 }
161 
162 void Simulator::CheckPCSComplianceAndRun() {
163  // Adjust JS-based stack limit to C-based stack limit.
164  isolate_->stack_guard()->AdjustStackLimitForSimulator();
165 
166 #ifdef DEBUG
167  DCHECK_EQ(kNumberOfCalleeSavedRegisters, kCalleeSaved.Count());
168  DCHECK_EQ(kNumberOfCalleeSavedVRegisters, kCalleeSavedV.Count());
169 
170  int64_t saved_registers[kNumberOfCalleeSavedRegisters];
171  uint64_t saved_fpregisters[kNumberOfCalleeSavedVRegisters];
172 
173  CPURegList register_list = kCalleeSaved;
174  CPURegList fpregister_list = kCalleeSavedV;
175 
176  for (int i = 0; i < kNumberOfCalleeSavedRegisters; i++) {
177  // x31 is not a caller saved register, so no need to specify if we want
178  // the stack or zero.
179  saved_registers[i] = xreg(register_list.PopLowestIndex().code());
180  }
181  for (int i = 0; i < kNumberOfCalleeSavedVRegisters; i++) {
182  saved_fpregisters[i] =
183  dreg_bits(fpregister_list.PopLowestIndex().code());
184  }
185  int64_t original_stack = sp();
186 #endif
187  // Start the simulation!
188  Run();
189 #ifdef DEBUG
190  DCHECK_EQ(original_stack, sp());
191  // Check that callee-saved registers have been preserved.
192  register_list = kCalleeSaved;
193  fpregister_list = kCalleeSavedV;
194  for (int i = 0; i < kNumberOfCalleeSavedRegisters; i++) {
195  DCHECK_EQ(saved_registers[i], xreg(register_list.PopLowestIndex().code()));
196  }
197  for (int i = 0; i < kNumberOfCalleeSavedVRegisters; i++) {
198  DCHECK(saved_fpregisters[i] ==
199  dreg_bits(fpregister_list.PopLowestIndex().code()));
200  }
201 
202  // Corrupt caller saved register minus the return regiters.
203 
204  // In theory x0 to x7 can be used for return values, but V8 only uses x0, x1
205  // for now .
206  register_list = kCallerSaved;
207  register_list.Remove(x0);
208  register_list.Remove(x1);
209 
210  // In theory d0 to d7 can be used for return values, but V8 only uses d0
211  // for now .
212  fpregister_list = kCallerSavedV;
213  fpregister_list.Remove(d0);
214 
215  CorruptRegisters(&register_list, kCallerSavedRegisterCorruptionValue);
216  CorruptRegisters(&fpregister_list, kCallerSavedVRegisterCorruptionValue);
217 #endif
218 }
219 
220 
221 #ifdef DEBUG
222 // The least significant byte of the curruption value holds the corresponding
223 // register's code.
224 void Simulator::CorruptRegisters(CPURegList* list, uint64_t value) {
225  if (list->type() == CPURegister::kRegister) {
226  while (!list->IsEmpty()) {
227  unsigned code = list->PopLowestIndex().code();
228  set_xreg(code, value | code);
229  }
230  } else {
231  DCHECK_EQ(list->type(), CPURegister::kVRegister);
232  while (!list->IsEmpty()) {
233  unsigned code = list->PopLowestIndex().code();
234  set_dreg_bits(code, value | code);
235  }
236  }
237 }
238 
239 
240 void Simulator::CorruptAllCallerSavedCPURegisters() {
241  // Corrupt alters its parameter so copy them first.
242  CPURegList register_list = kCallerSaved;
243  CPURegList fpregister_list = kCallerSavedV;
244 
245  CorruptRegisters(&register_list, kCallerSavedRegisterCorruptionValue);
246  CorruptRegisters(&fpregister_list, kCallerSavedVRegisterCorruptionValue);
247 }
248 #endif
249 
250 
251 // Extending the stack by 2 * 64 bits is required for stack alignment purposes.
252 uintptr_t Simulator::PushAddress(uintptr_t address) {
253  DCHECK(sizeof(uintptr_t) < 2 * kXRegSize);
254  intptr_t new_sp = sp() - 2 * kXRegSize;
255  uintptr_t* alignment_slot =
256  reinterpret_cast<uintptr_t*>(new_sp + kXRegSize);
257  memcpy(alignment_slot, &kSlotsZapValue, kPointerSize);
258  uintptr_t* stack_slot = reinterpret_cast<uintptr_t*>(new_sp);
259  memcpy(stack_slot, &address, kPointerSize);
260  set_sp(new_sp);
261  return new_sp;
262 }
263 
264 
265 uintptr_t Simulator::PopAddress() {
266  intptr_t current_sp = sp();
267  uintptr_t* stack_slot = reinterpret_cast<uintptr_t*>(current_sp);
268  uintptr_t address = *stack_slot;
269  DCHECK_LT(sizeof(uintptr_t), 2 * kXRegSize);
270  set_sp(current_sp + 2 * kXRegSize);
271  return address;
272 }
273 
274 
275 // Returns the limit of the stack area to enable checking for stack overflows.
276 uintptr_t Simulator::StackLimit(uintptr_t c_limit) const {
277  // The simulator uses a separate JS stack. If we have exhausted the C stack,
278  // we also drop down the JS limit to reflect the exhaustion on the JS stack.
279  if (GetCurrentStackPosition() < c_limit) {
280  return get_sp();
281  }
282 
283  // Otherwise the limit is the JS stack. Leave a safety margin of 1024 bytes
284  // to prevent overrunning the stack when pushing values.
285  return stack_limit_ + 1024;
286 }
287 
288 void Simulator::SetRedirectInstruction(Instruction* instruction) {
289  instruction->SetInstructionBits(
290  HLT | Assembler::ImmException(kImmExceptionIsRedirectedCall));
291 }
292 
293 Simulator::Simulator(Decoder<DispatchingDecoderVisitor>* decoder,
294  Isolate* isolate, FILE* stream)
295  : decoder_(decoder),
296  last_debugger_input_(nullptr),
297  log_parameters_(NO_PARAM),
298  isolate_(isolate) {
299  // Setup the decoder.
300  decoder_->AppendVisitor(this);
301 
302  Init(stream);
303 
304  if (FLAG_trace_sim) {
305  decoder_->InsertVisitorBefore(print_disasm_, this);
306  log_parameters_ = LOG_ALL;
307  }
308 
309  if (FLAG_log_instruction_stats) {
310  instrument_ = new Instrument(FLAG_log_instruction_file,
311  FLAG_log_instruction_period);
312  decoder_->AppendVisitor(instrument_);
313  }
314 }
315 
316 Simulator::Simulator()
317  : decoder_(nullptr),
318  last_debugger_input_(nullptr),
319  log_parameters_(NO_PARAM),
320  isolate_(nullptr) {
321  Init(stdout);
322  CHECK(!FLAG_trace_sim && !FLAG_log_instruction_stats);
323 }
324 
325 
326 void Simulator::Init(FILE* stream) {
327  ResetState();
328 
329  // Allocate and setup the simulator stack.
330  stack_size_ = (FLAG_sim_stack_size * KB) + (2 * stack_protection_size_);
331  stack_ = reinterpret_cast<uintptr_t>(new byte[stack_size_]);
332  stack_limit_ = stack_ + stack_protection_size_;
333  uintptr_t tos = stack_ + stack_size_ - stack_protection_size_;
334  // The stack pointer must be 16-byte aligned.
335  set_sp(tos & ~0xFULL);
336 
337  stream_ = stream;
338  print_disasm_ = new PrintDisassembler(stream_);
339 
340  // The debugger needs to disassemble code without the simulator executing an
341  // instruction, so we create a dedicated decoder.
342  disassembler_decoder_ = new Decoder<DispatchingDecoderVisitor>();
343  disassembler_decoder_->AppendVisitor(print_disasm_);
344 }
345 
346 
347 void Simulator::ResetState() {
348  // Reset the system registers.
349  nzcv_ = SimSystemRegister::DefaultValueFor(NZCV);
350  fpcr_ = SimSystemRegister::DefaultValueFor(FPCR);
351 
352  // Reset registers to 0.
353  pc_ = nullptr;
354  for (unsigned i = 0; i < kNumberOfRegisters; i++) {
355  set_xreg(i, 0xBADBEEF);
356  }
357  for (unsigned i = 0; i < kNumberOfVRegisters; i++) {
358  // Set FP registers to a value that is NaN in both 32-bit and 64-bit FP.
359  set_dreg_bits(i, 0x7FF000007F800001UL);
360  }
361  // Returning to address 0 exits the Simulator.
362  set_lr(kEndOfSimAddress);
363 
364  // Reset debug helpers.
365  breakpoints_.clear();
366  break_on_next_ = false;
367 }
368 
369 
370 Simulator::~Simulator() {
371  global_monitor_.Pointer()->RemoveProcessor(&global_monitor_processor_);
372  delete[] reinterpret_cast<byte*>(stack_);
373  if (FLAG_log_instruction_stats) {
374  delete instrument_;
375  }
376  delete disassembler_decoder_;
377  delete print_disasm_;
378  DeleteArray(last_debugger_input_);
379  delete decoder_;
380 }
381 
382 
383 void Simulator::Run() {
384  // Flush any written registers before executing anything, so that
385  // manually-set registers are logged _before_ the first instruction.
386  LogAllWrittenRegisters();
387 
388  pc_modified_ = false;
389  while (pc_ != kEndOfSimAddress) {
390  ExecuteInstruction();
391  }
392 }
393 
394 
395 void Simulator::RunFrom(Instruction* start) {
396  set_pc(start);
397  Run();
398 }
399 
400 
401 // Calls into the V8 runtime are based on this very simple interface.
402 // Note: To be able to return two values from some calls the code in runtime.cc
403 // uses the ObjectPair structure.
404 // The simulator assumes all runtime calls return two 64-bits values. If they
405 // don't, register x1 is clobbered. This is fine because x1 is caller-saved.
406 #if defined(V8_OS_WIN)
407 typedef int64_t (*SimulatorRuntimeCall_ReturnPtr)(int64_t arg0, int64_t arg1,
408  int64_t arg2, int64_t arg3,
409  int64_t arg4, int64_t arg5,
410  int64_t arg6, int64_t arg7,
411  int64_t arg8);
412 #endif
413 
414 typedef ObjectPair (*SimulatorRuntimeCall)(int64_t arg0, int64_t arg1,
415  int64_t arg2, int64_t arg3,
416  int64_t arg4, int64_t arg5,
417  int64_t arg6, int64_t arg7,
418  int64_t arg8);
419 
420 typedef int64_t (*SimulatorRuntimeCompareCall)(double arg1, double arg2);
421 typedef double (*SimulatorRuntimeFPFPCall)(double arg1, double arg2);
422 typedef double (*SimulatorRuntimeFPCall)(double arg1);
423 typedef double (*SimulatorRuntimeFPIntCall)(double arg1, int32_t arg2);
424 
425 // This signature supports direct call in to API function native callback
426 // (refer to InvocationCallback in v8.h).
427 typedef void (*SimulatorRuntimeDirectApiCall)(int64_t arg0);
428 typedef void (*SimulatorRuntimeProfilingApiCall)(int64_t arg0, void* arg1);
429 
430 // This signature supports direct call to accessor getter callback.
431 typedef void (*SimulatorRuntimeDirectGetterCall)(int64_t arg0, int64_t arg1);
432 typedef void (*SimulatorRuntimeProfilingGetterCall)(int64_t arg0, int64_t arg1,
433  void* arg2);
434 
435 void Simulator::DoRuntimeCall(Instruction* instr) {
436  Redirection* redirection = Redirection::FromInstruction(instr);
437 
438  // The called C code might itself call simulated code, so any
439  // caller-saved registers (including lr) could still be clobbered by a
440  // redirected call.
441  Instruction* return_address = lr();
442 
443  int64_t external =
444  reinterpret_cast<int64_t>(redirection->external_function());
445 
446  TraceSim("Call to host function at %p\n", redirection->external_function());
447 
448  // SP must be 16-byte-aligned at the call interface.
449  bool stack_alignment_exception = ((sp() & 0xF) != 0);
450  if (stack_alignment_exception) {
451  TraceSim(" with unaligned stack 0x%016" PRIx64 ".\n", sp());
452  FATAL("ALIGNMENT EXCEPTION");
453  }
454 
455  int64_t* stack_pointer = reinterpret_cast<int64_t*>(sp());
456 
457  const int64_t arg0 = xreg(0);
458  const int64_t arg1 = xreg(1);
459  const int64_t arg2 = xreg(2);
460  const int64_t arg3 = xreg(3);
461  const int64_t arg4 = xreg(4);
462  const int64_t arg5 = xreg(5);
463  const int64_t arg6 = xreg(6);
464  const int64_t arg7 = xreg(7);
465  const int64_t arg8 = stack_pointer[0];
466  STATIC_ASSERT(kMaxCParameters == 9);
467 
468  switch (redirection->type()) {
469  default:
470  TraceSim("Type: Unknown.\n");
471  UNREACHABLE();
472  break;
473 
474  case ExternalReference::BUILTIN_CALL:
475 #if defined(V8_OS_WIN)
476  {
477  // Object* f(v8::internal::Arguments).
478  TraceSim("Type: BUILTIN_CALL\n");
479 
480  // When this simulator runs on Windows x64 host, function with ObjectPair
481  // return type accepts an implicit pointer to caller allocated memory for
482  // ObjectPair as return value. This diverges the calling convention from
483  // function which returns primitive type, so function returns ObjectPair
484  // and primitive type cannot share implementation.
485 
486  // We don't know how many arguments are being passed, but we can
487  // pass 8 without touching the stack. They will be ignored by the
488  // host function if they aren't used.
489  TraceSim(
490  "Arguments: "
491  "0x%016" PRIx64 ", 0x%016" PRIx64
492  ", "
493  "0x%016" PRIx64 ", 0x%016" PRIx64
494  ", "
495  "0x%016" PRIx64 ", 0x%016" PRIx64
496  ", "
497  "0x%016" PRIx64 ", 0x%016" PRIx64
498  ", "
499  "0x%016" PRIx64,
500  arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8);
501 
502  SimulatorRuntimeCall_ReturnPtr target =
503  reinterpret_cast<SimulatorRuntimeCall_ReturnPtr>(external);
504 
505  int64_t result =
506  target(arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8);
507  TraceSim("Returned: 0x%16\n", result);
508 #ifdef DEBUG
509  CorruptAllCallerSavedCPURegisters();
510 #endif
511  set_xreg(0, result);
512 
513  break;
514  }
515 #endif
516  case ExternalReference::BUILTIN_CALL_PAIR: {
517  // Object* f(v8::internal::Arguments) or
518  // ObjectPair f(v8::internal::Arguments).
519  TraceSim("Type: BUILTIN_CALL\n");
520 
521  // We don't know how many arguments are being passed, but we can
522  // pass 8 without touching the stack. They will be ignored by the
523  // host function if they aren't used.
524  TraceSim(
525  "Arguments: "
526  "0x%016" PRIx64 ", 0x%016" PRIx64
527  ", "
528  "0x%016" PRIx64 ", 0x%016" PRIx64
529  ", "
530  "0x%016" PRIx64 ", 0x%016" PRIx64
531  ", "
532  "0x%016" PRIx64 ", 0x%016" PRIx64
533  ", "
534  "0x%016" PRIx64,
535  arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8);
536  SimulatorRuntimeCall target =
537  reinterpret_cast<SimulatorRuntimeCall>(external);
538  ObjectPair result =
539  target(arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8);
540  TraceSim("Returned: {%p, %p}\n", static_cast<void*>(result.x),
541  static_cast<void*>(result.y));
542 #ifdef DEBUG
543  CorruptAllCallerSavedCPURegisters();
544 #endif
545  set_xreg(0, reinterpret_cast<int64_t>(result.x));
546  set_xreg(1, reinterpret_cast<int64_t>(result.y));
547  break;
548  }
549 
550  case ExternalReference::DIRECT_API_CALL: {
551  // void f(v8::FunctionCallbackInfo&)
552  TraceSim("Type: DIRECT_API_CALL\n");
553  SimulatorRuntimeDirectApiCall target =
554  reinterpret_cast<SimulatorRuntimeDirectApiCall>(external);
555  TraceSim("Arguments: 0x%016" PRIx64 "\n", xreg(0));
556  target(xreg(0));
557  TraceSim("No return value.");
558 #ifdef DEBUG
559  CorruptAllCallerSavedCPURegisters();
560 #endif
561  break;
562  }
563 
564  case ExternalReference::BUILTIN_COMPARE_CALL: {
565  // int f(double, double)
566  TraceSim("Type: BUILTIN_COMPARE_CALL\n");
567  SimulatorRuntimeCompareCall target =
568  reinterpret_cast<SimulatorRuntimeCompareCall>(external);
569  TraceSim("Arguments: %f, %f\n", dreg(0), dreg(1));
570  int64_t result = target(dreg(0), dreg(1));
571  TraceSim("Returned: %" PRId64 "\n", result);
572 #ifdef DEBUG
573  CorruptAllCallerSavedCPURegisters();
574 #endif
575  set_xreg(0, result);
576  break;
577  }
578 
579  case ExternalReference::BUILTIN_FP_CALL: {
580  // double f(double)
581  TraceSim("Type: BUILTIN_FP_CALL\n");
582  SimulatorRuntimeFPCall target =
583  reinterpret_cast<SimulatorRuntimeFPCall>(external);
584  TraceSim("Argument: %f\n", dreg(0));
585  double result = target(dreg(0));
586  TraceSim("Returned: %f\n", result);
587 #ifdef DEBUG
588  CorruptAllCallerSavedCPURegisters();
589 #endif
590  set_dreg(0, result);
591  break;
592  }
593 
594  case ExternalReference::BUILTIN_FP_FP_CALL: {
595  // double f(double, double)
596  TraceSim("Type: BUILTIN_FP_FP_CALL\n");
597  SimulatorRuntimeFPFPCall target =
598  reinterpret_cast<SimulatorRuntimeFPFPCall>(external);
599  TraceSim("Arguments: %f, %f\n", dreg(0), dreg(1));
600  double result = target(dreg(0), dreg(1));
601  TraceSim("Returned: %f\n", result);
602 #ifdef DEBUG
603  CorruptAllCallerSavedCPURegisters();
604 #endif
605  set_dreg(0, result);
606  break;
607  }
608 
609  case ExternalReference::BUILTIN_FP_INT_CALL: {
610  // double f(double, int)
611  TraceSim("Type: BUILTIN_FP_INT_CALL\n");
612  SimulatorRuntimeFPIntCall target =
613  reinterpret_cast<SimulatorRuntimeFPIntCall>(external);
614  TraceSim("Arguments: %f, %d\n", dreg(0), wreg(0));
615  double result = target(dreg(0), wreg(0));
616  TraceSim("Returned: %f\n", result);
617 #ifdef DEBUG
618  CorruptAllCallerSavedCPURegisters();
619 #endif
620  set_dreg(0, result);
621  break;
622  }
623 
624  case ExternalReference::DIRECT_GETTER_CALL: {
625  // void f(Local<String> property, PropertyCallbackInfo& info)
626  TraceSim("Type: DIRECT_GETTER_CALL\n");
627  SimulatorRuntimeDirectGetterCall target =
628  reinterpret_cast<SimulatorRuntimeDirectGetterCall>(external);
629  TraceSim("Arguments: 0x%016" PRIx64 ", 0x%016" PRIx64 "\n",
630  xreg(0), xreg(1));
631  target(xreg(0), xreg(1));
632  TraceSim("No return value.");
633 #ifdef DEBUG
634  CorruptAllCallerSavedCPURegisters();
635 #endif
636  break;
637  }
638 
639  case ExternalReference::PROFILING_API_CALL: {
640  // void f(v8::FunctionCallbackInfo&, v8::FunctionCallback)
641  TraceSim("Type: PROFILING_API_CALL\n");
642  SimulatorRuntimeProfilingApiCall target =
643  reinterpret_cast<SimulatorRuntimeProfilingApiCall>(external);
644  void* arg1 = Redirection::ReverseRedirection(xreg(1));
645  TraceSim("Arguments: 0x%016" PRIx64 ", %p\n", xreg(0), arg1);
646  target(xreg(0), arg1);
647  TraceSim("No return value.");
648 #ifdef DEBUG
649  CorruptAllCallerSavedCPURegisters();
650 #endif
651  break;
652  }
653 
654  case ExternalReference::PROFILING_GETTER_CALL: {
655  // void f(Local<String> property, PropertyCallbackInfo& info,
656  // AccessorNameGetterCallback callback)
657  TraceSim("Type: PROFILING_GETTER_CALL\n");
658  SimulatorRuntimeProfilingGetterCall target =
659  reinterpret_cast<SimulatorRuntimeProfilingGetterCall>(
660  external);
661  void* arg2 = Redirection::ReverseRedirection(xreg(2));
662  TraceSim("Arguments: 0x%016" PRIx64 ", 0x%016" PRIx64 ", %p\n",
663  xreg(0), xreg(1), arg2);
664  target(xreg(0), xreg(1), arg2);
665  TraceSim("No return value.");
666 #ifdef DEBUG
667  CorruptAllCallerSavedCPURegisters();
668 #endif
669  break;
670  }
671  }
672 
673  set_lr(return_address);
674  set_pc(return_address);
675 }
676 
677 const char* Simulator::xreg_names[] = {
678  "x0", "x1", "x2", "x3", "x4", "x5", "x6", "x7", "x8", "x9", "x10",
679  "x11", "x12", "x13", "x14", "x15", "ip0", "ip1", "x18", "x19", "x20", "x21",
680  "x22", "x23", "x24", "x25", "x26", "cp", "x28", "fp", "lr", "xzr", "sp"};
681 
682 const char* Simulator::wreg_names[] = {
683  "w0", "w1", "w2", "w3", "w4", "w5", "w6", "w7", "w8",
684  "w9", "w10", "w11", "w12", "w13", "w14", "w15", "w16", "w17",
685  "w18", "w19", "w20", "w21", "w22", "w23", "w24", "w25", "w26",
686  "wcp", "w28", "wfp", "wlr", "wzr", "wsp"};
687 
688 const char* Simulator::sreg_names[] = {
689 "s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7",
690 "s8", "s9", "s10", "s11", "s12", "s13", "s14", "s15",
691 "s16", "s17", "s18", "s19", "s20", "s21", "s22", "s23",
692 "s24", "s25", "s26", "s27", "s28", "s29", "s30", "s31"};
693 
694 const char* Simulator::dreg_names[] = {
695 "d0", "d1", "d2", "d3", "d4", "d5", "d6", "d7",
696 "d8", "d9", "d10", "d11", "d12", "d13", "d14", "d15",
697 "d16", "d17", "d18", "d19", "d20", "d21", "d22", "d23",
698 "d24", "d25", "d26", "d27", "d28", "d29", "d30", "d31"};
699 
700 const char* Simulator::vreg_names[] = {
701 "v0", "v1", "v2", "v3", "v4", "v5", "v6", "v7",
702 "v8", "v9", "v10", "v11", "v12", "v13", "v14", "v15",
703 "v16", "v17", "v18", "v19", "v20", "v21", "v22", "v23",
704 "v24", "v25", "v26", "v27", "v28", "v29", "v30", "v31"};
705 
706 
707 const char* Simulator::WRegNameForCode(unsigned code, Reg31Mode mode) {
708  static_assert(arraysize(Simulator::wreg_names) == (kNumberOfRegisters + 1),
709  "Array must be large enough to hold all register names.");
710  DCHECK_LT(code, static_cast<unsigned>(kNumberOfRegisters));
711  // The modulo operator has no effect here, but it silences a broken GCC
712  // warning about out-of-bounds array accesses.
713  code %= kNumberOfRegisters;
714 
715  // If the code represents the stack pointer, index the name after zr.
716  if ((code == kZeroRegCode) && (mode == Reg31IsStackPointer)) {
717  code = kZeroRegCode + 1;
718  }
719  return wreg_names[code];
720 }
721 
722 
723 const char* Simulator::XRegNameForCode(unsigned code, Reg31Mode mode) {
724  static_assert(arraysize(Simulator::xreg_names) == (kNumberOfRegisters + 1),
725  "Array must be large enough to hold all register names.");
726  DCHECK_LT(code, static_cast<unsigned>(kNumberOfRegisters));
727  code %= kNumberOfRegisters;
728 
729  // If the code represents the stack pointer, index the name after zr.
730  if ((code == kZeroRegCode) && (mode == Reg31IsStackPointer)) {
731  code = kZeroRegCode + 1;
732  }
733  return xreg_names[code];
734 }
735 
736 
737 const char* Simulator::SRegNameForCode(unsigned code) {
738  static_assert(arraysize(Simulator::sreg_names) == kNumberOfVRegisters,
739  "Array must be large enough to hold all register names.");
740  DCHECK_LT(code, static_cast<unsigned>(kNumberOfVRegisters));
741  return sreg_names[code % kNumberOfVRegisters];
742 }
743 
744 
745 const char* Simulator::DRegNameForCode(unsigned code) {
746  static_assert(arraysize(Simulator::dreg_names) == kNumberOfVRegisters,
747  "Array must be large enough to hold all register names.");
748  DCHECK_LT(code, static_cast<unsigned>(kNumberOfVRegisters));
749  return dreg_names[code % kNumberOfVRegisters];
750 }
751 
752 
753 const char* Simulator::VRegNameForCode(unsigned code) {
754  static_assert(arraysize(Simulator::vreg_names) == kNumberOfVRegisters,
755  "Array must be large enough to hold all register names.");
756  DCHECK_LT(code, static_cast<unsigned>(kNumberOfVRegisters));
757  return vreg_names[code % kNumberOfVRegisters];
758 }
759 
760 void LogicVRegister::ReadUintFromMem(VectorFormat vform, int index,
761  uint64_t addr) const {
762  switch (LaneSizeInBitsFromFormat(vform)) {
763  case 8:
764  register_.Insert(index, SimMemory::Read<uint8_t>(addr));
765  break;
766  case 16:
767  register_.Insert(index, SimMemory::Read<uint16_t>(addr));
768  break;
769  case 32:
770  register_.Insert(index, SimMemory::Read<uint32_t>(addr));
771  break;
772  case 64:
773  register_.Insert(index, SimMemory::Read<uint64_t>(addr));
774  break;
775  default:
776  UNREACHABLE();
777  return;
778  }
779 }
780 
781 void LogicVRegister::WriteUintToMem(VectorFormat vform, int index,
782  uint64_t addr) const {
783  switch (LaneSizeInBitsFromFormat(vform)) {
784  case 8:
785  SimMemory::Write<uint8_t>(addr, static_cast<uint8_t>(Uint(vform, index)));
786  break;
787  case 16:
788  SimMemory::Write<uint16_t>(addr,
789  static_cast<uint16_t>(Uint(vform, index)));
790  break;
791  case 32:
792  SimMemory::Write<uint32_t>(addr,
793  static_cast<uint32_t>(Uint(vform, index)));
794  break;
795  case 64:
796  SimMemory::Write<uint64_t>(addr, Uint(vform, index));
797  break;
798  default:
799  UNREACHABLE();
800  return;
801  }
802 }
803 
804 
805 int Simulator::CodeFromName(const char* name) {
806  for (unsigned i = 0; i < kNumberOfRegisters; i++) {
807  if ((strcmp(xreg_names[i], name) == 0) ||
808  (strcmp(wreg_names[i], name) == 0)) {
809  return i;
810  }
811  }
812  for (unsigned i = 0; i < kNumberOfVRegisters; i++) {
813  if ((strcmp(vreg_names[i], name) == 0) ||
814  (strcmp(dreg_names[i], name) == 0) ||
815  (strcmp(sreg_names[i], name) == 0)) {
816  return i;
817  }
818  }
819  if ((strcmp("sp", name) == 0) || (strcmp("wsp", name) == 0)) {
820  return kSPRegInternalCode;
821  }
822  return -1;
823 }
824 
825 
826 // Helpers ---------------------------------------------------------------------
827 template <typename T>
828 T Simulator::AddWithCarry(bool set_flags, T left, T right, int carry_in) {
829  // Use unsigned types to avoid implementation-defined overflow behaviour.
830  static_assert(std::is_unsigned<T>::value, "operands must be unsigned");
831  static_assert((sizeof(T) == kWRegSize) || (sizeof(T) == kXRegSize),
832  "Only W- or X-sized operands are tested");
833 
834  DCHECK((carry_in == 0) || (carry_in == 1));
835  T result = left + right + carry_in;
836 
837  if (set_flags) {
838  nzcv().SetN(CalcNFlag(result));
839  nzcv().SetZ(CalcZFlag(result));
840 
841  // Compute the C flag by comparing the result to the max unsigned integer.
842  T max_uint_2op = std::numeric_limits<T>::max() - carry_in;
843  nzcv().SetC((left > max_uint_2op) || ((max_uint_2op - left) < right));
844 
845  // Overflow iff the sign bit is the same for the two inputs and different
846  // for the result.
847  T sign_mask = T(1) << (sizeof(T) * 8 - 1);
848  T left_sign = left & sign_mask;
849  T right_sign = right & sign_mask;
850  T result_sign = result & sign_mask;
851  nzcv().SetV((left_sign == right_sign) && (left_sign != result_sign));
852 
853  LogSystemRegister(NZCV);
854  }
855  return result;
856 }
857 
858 
859 template<typename T>
860 void Simulator::AddSubWithCarry(Instruction* instr) {
861  // Use unsigned types to avoid implementation-defined overflow behaviour.
862  static_assert(std::is_unsigned<T>::value, "operands must be unsigned");
863 
864  T op2 = reg<T>(instr->Rm());
865  T new_val;
866 
867  if ((instr->Mask(AddSubOpMask) == SUB) || instr->Mask(AddSubOpMask) == SUBS) {
868  op2 = ~op2;
869  }
870 
871  new_val = AddWithCarry<T>(instr->FlagsUpdate(),
872  reg<T>(instr->Rn()),
873  op2,
874  nzcv().C());
875 
876  set_reg<T>(instr->Rd(), new_val);
877 }
878 
879 template <typename T>
880 T Simulator::ShiftOperand(T value, Shift shift_type, unsigned amount) {
881  typedef typename std::make_unsigned<T>::type unsignedT;
882 
883  if (amount == 0) {
884  return value;
885  }
886 
887  switch (shift_type) {
888  case LSL:
889  return value << amount;
890  case LSR:
891  return static_cast<unsignedT>(value) >> amount;
892  case ASR:
893  return value >> amount;
894  case ROR: {
895  unsignedT mask = (static_cast<unsignedT>(1) << amount) - 1;
896  return (static_cast<unsignedT>(value) >> amount) |
897  ((value & mask) << (sizeof(mask) * 8 - amount));
898  }
899  default:
900  UNIMPLEMENTED();
901  return 0;
902  }
903 }
904 
905 
906 template <typename T>
907 T Simulator::ExtendValue(T value, Extend extend_type, unsigned left_shift) {
908  const unsigned kSignExtendBShift = (sizeof(T) - 1) * 8;
909  const unsigned kSignExtendHShift = (sizeof(T) - 2) * 8;
910  const unsigned kSignExtendWShift = (sizeof(T) - 4) * 8;
911 
912  switch (extend_type) {
913  case UXTB:
914  value &= kByteMask;
915  break;
916  case UXTH:
917  value &= kHalfWordMask;
918  break;
919  case UXTW:
920  value &= kWordMask;
921  break;
922  case SXTB:
923  value = (value << kSignExtendBShift) >> kSignExtendBShift;
924  break;
925  case SXTH:
926  value = (value << kSignExtendHShift) >> kSignExtendHShift;
927  break;
928  case SXTW:
929  value = (value << kSignExtendWShift) >> kSignExtendWShift;
930  break;
931  case UXTX:
932  case SXTX:
933  break;
934  default:
935  UNREACHABLE();
936  }
937  return value << left_shift;
938 }
939 
940 
941 template <typename T>
942 void Simulator::Extract(Instruction* instr) {
943  unsigned lsb = instr->ImmS();
944  T op2 = reg<T>(instr->Rm());
945  T result = op2;
946 
947  if (lsb) {
948  T op1 = reg<T>(instr->Rn());
949  result = op2 >> lsb | (op1 << ((sizeof(T) * 8) - lsb));
950  }
951  set_reg<T>(instr->Rd(), result);
952 }
953 
954 
955 void Simulator::FPCompare(double val0, double val1) {
956  AssertSupportedFPCR();
957 
958  // TODO(jbramley): This assumes that the C++ implementation handles
959  // comparisons in the way that we expect (as per AssertSupportedFPCR()).
960  if ((std::isnan(val0) != 0) || (std::isnan(val1) != 0)) {
961  nzcv().SetRawValue(FPUnorderedFlag);
962  } else if (val0 < val1) {
963  nzcv().SetRawValue(FPLessThanFlag);
964  } else if (val0 > val1) {
965  nzcv().SetRawValue(FPGreaterThanFlag);
966  } else if (val0 == val1) {
967  nzcv().SetRawValue(FPEqualFlag);
968  } else {
969  UNREACHABLE();
970  }
971  LogSystemRegister(NZCV);
972 }
973 
974 Simulator::PrintRegisterFormat Simulator::GetPrintRegisterFormatForSize(
975  size_t reg_size, size_t lane_size) {
976  DCHECK_GE(reg_size, lane_size);
977 
978  uint32_t format = 0;
979  if (reg_size != lane_size) {
980  switch (reg_size) {
981  default:
982  UNREACHABLE();
983  case kQRegSize:
984  format = kPrintRegAsQVector;
985  break;
986  case kDRegSize:
987  format = kPrintRegAsDVector;
988  break;
989  }
990  }
991 
992  switch (lane_size) {
993  default:
994  UNREACHABLE();
995  case kQRegSize:
996  format |= kPrintReg1Q;
997  break;
998  case kDRegSize:
999  format |= kPrintReg1D;
1000  break;
1001  case kSRegSize:
1002  format |= kPrintReg1S;
1003  break;
1004  case kHRegSize:
1005  format |= kPrintReg1H;
1006  break;
1007  case kBRegSize:
1008  format |= kPrintReg1B;
1009  break;
1010  }
1011 
1012  // These sizes would be duplicate case labels.
1013  static_assert(kXRegSize == kDRegSize, "X and D registers must be same size.");
1014  static_assert(kWRegSize == kSRegSize, "W and S registers must be same size.");
1015  static_assert(kPrintXReg == kPrintReg1D,
1016  "X and D register printing code is shared.");
1017  static_assert(kPrintWReg == kPrintReg1S,
1018  "W and S register printing code is shared.");
1019 
1020  return static_cast<PrintRegisterFormat>(format);
1021 }
1022 
1023 Simulator::PrintRegisterFormat Simulator::GetPrintRegisterFormat(
1024  VectorFormat vform) {
1025  switch (vform) {
1026  default:
1027  UNREACHABLE();
1028  case kFormat16B:
1029  return kPrintReg16B;
1030  case kFormat8B:
1031  return kPrintReg8B;
1032  case kFormat8H:
1033  return kPrintReg8H;
1034  case kFormat4H:
1035  return kPrintReg4H;
1036  case kFormat4S:
1037  return kPrintReg4S;
1038  case kFormat2S:
1039  return kPrintReg2S;
1040  case kFormat2D:
1041  return kPrintReg2D;
1042  case kFormat1D:
1043  return kPrintReg1D;
1044 
1045  case kFormatB:
1046  return kPrintReg1B;
1047  case kFormatH:
1048  return kPrintReg1H;
1049  case kFormatS:
1050  return kPrintReg1S;
1051  case kFormatD:
1052  return kPrintReg1D;
1053  }
1054 }
1055 
1056 Simulator::PrintRegisterFormat Simulator::GetPrintRegisterFormatFP(
1057  VectorFormat vform) {
1058  switch (vform) {
1059  default:
1060  UNREACHABLE();
1061  case kFormat4S:
1062  return kPrintReg4SFP;
1063  case kFormat2S:
1064  return kPrintReg2SFP;
1065  case kFormat2D:
1066  return kPrintReg2DFP;
1067  case kFormat1D:
1068  return kPrintReg1DFP;
1069 
1070  case kFormatS:
1071  return kPrintReg1SFP;
1072  case kFormatD:
1073  return kPrintReg1DFP;
1074  }
1075 }
1076 
1077 void Simulator::SetBreakpoint(Instruction* location) {
1078  for (unsigned i = 0; i < breakpoints_.size(); i++) {
1079  if (breakpoints_.at(i).location == location) {
1080  PrintF(stream_,
1081  "Existing breakpoint at %p was %s\n",
1082  reinterpret_cast<void*>(location),
1083  breakpoints_.at(i).enabled ? "disabled" : "enabled");
1084  breakpoints_.at(i).enabled = !breakpoints_.at(i).enabled;
1085  return;
1086  }
1087  }
1088  Breakpoint new_breakpoint = {location, true};
1089  breakpoints_.push_back(new_breakpoint);
1090  PrintF(stream_,
1091  "Set a breakpoint at %p\n", reinterpret_cast<void*>(location));
1092 }
1093 
1094 
1095 void Simulator::ListBreakpoints() {
1096  PrintF(stream_, "Breakpoints:\n");
1097  for (unsigned i = 0; i < breakpoints_.size(); i++) {
1098  PrintF(stream_, "%p : %s\n",
1099  reinterpret_cast<void*>(breakpoints_.at(i).location),
1100  breakpoints_.at(i).enabled ? "enabled" : "disabled");
1101  }
1102 }
1103 
1104 
1105 void Simulator::CheckBreakpoints() {
1106  bool hit_a_breakpoint = false;
1107  for (unsigned i = 0; i < breakpoints_.size(); i++) {
1108  if ((breakpoints_.at(i).location == pc_) &&
1109  breakpoints_.at(i).enabled) {
1110  hit_a_breakpoint = true;
1111  // Disable this breakpoint.
1112  breakpoints_.at(i).enabled = false;
1113  }
1114  }
1115  if (hit_a_breakpoint) {
1116  PrintF(stream_, "Hit and disabled a breakpoint at %p.\n",
1117  reinterpret_cast<void*>(pc_));
1118  Debug();
1119  }
1120 }
1121 
1122 
1123 void Simulator::CheckBreakNext() {
1124  // If the current instruction is a BL, insert a breakpoint just after it.
1125  if (break_on_next_ && pc_->IsBranchAndLinkToRegister()) {
1126  SetBreakpoint(pc_->following());
1127  break_on_next_ = false;
1128  }
1129 }
1130 
1131 
1132 void Simulator::PrintInstructionsAt(Instruction* start, uint64_t count) {
1133  Instruction* end = start->InstructionAtOffset(count * kInstrSize);
1134  for (Instruction* pc = start; pc < end; pc = pc->following()) {
1135  disassembler_decoder_->Decode(pc);
1136  }
1137 }
1138 
1139 void Simulator::PrintWrittenRegisters() {
1140  for (unsigned i = 0; i < kNumberOfRegisters; i++) {
1141  if (registers_[i].WrittenSinceLastLog()) PrintRegister(i);
1142  }
1143 }
1144 
1145 void Simulator::PrintWrittenVRegisters() {
1146  for (unsigned i = 0; i < kNumberOfVRegisters; i++) {
1147  // At this point there is no type information, so print as a raw 1Q.
1148  if (vregisters_[i].WrittenSinceLastLog()) PrintVRegister(i, kPrintReg1Q);
1149  }
1150 }
1151 
1152 void Simulator::PrintSystemRegisters() {
1153  PrintSystemRegister(NZCV);
1154  PrintSystemRegister(FPCR);
1155 }
1156 
1157 
1158 void Simulator::PrintRegisters() {
1159  for (unsigned i = 0; i < kNumberOfRegisters; i++) {
1160  PrintRegister(i);
1161  }
1162 }
1163 
1164 void Simulator::PrintVRegisters() {
1165  for (unsigned i = 0; i < kNumberOfVRegisters; i++) {
1166  // At this point there is no type information, so print as a raw 1Q.
1167  PrintVRegister(i, kPrintReg1Q);
1168  }
1169 }
1170 
1171 
1172 void Simulator::PrintRegister(unsigned code, Reg31Mode r31mode) {
1173  registers_[code].NotifyRegisterLogged();
1174 
1175  // Don't print writes into xzr.
1176  if ((code == kZeroRegCode) && (r31mode == Reg31IsZeroRegister)) {
1177  return;
1178  }
1179 
1180  // The template for all x and w registers:
1181  // "# x{code}: 0x{value}"
1182  // "# w{code}: 0x{value}"
1183 
1184  PrintRegisterRawHelper(code, r31mode);
1185  fprintf(stream_, "\n");
1186 }
1187 
1188 // Print a register's name and raw value.
1189 //
1190 // The `bytes` and `lsb` arguments can be used to limit the bytes that are
1191 // printed. These arguments are intended for use in cases where register hasn't
1192 // actually been updated (such as in PrintVWrite).
1193 //
1194 // No newline is printed. This allows the caller to print more details (such as
1195 // a floating-point interpretation or a memory access annotation).
1196 void Simulator::PrintVRegisterRawHelper(unsigned code, int bytes, int lsb) {
1197  // The template for vector types:
1198  // "# v{code}: 0xFFEEDDCCBBAA99887766554433221100".
1199  // An example with bytes=4 and lsb=8:
1200  // "# v{code}: 0xBBAA9988 ".
1201  fprintf(stream_, "# %s%5s: %s", clr_vreg_name, VRegNameForCode(code),
1202  clr_vreg_value);
1203 
1204  int msb = lsb + bytes - 1;
1205  int byte = kQRegSize - 1;
1206 
1207  // Print leading padding spaces. (Two spaces per byte.)
1208  while (byte > msb) {
1209  fprintf(stream_, " ");
1210  byte--;
1211  }
1212 
1213  // Print the specified part of the value, byte by byte.
1214  qreg_t rawbits = qreg(code);
1215  fprintf(stream_, "0x");
1216  while (byte >= lsb) {
1217  fprintf(stream_, "%02x", rawbits.val[byte]);
1218  byte--;
1219  }
1220 
1221  // Print trailing padding spaces.
1222  while (byte >= 0) {
1223  fprintf(stream_, " ");
1224  byte--;
1225  }
1226  fprintf(stream_, "%s", clr_normal);
1227 }
1228 
1229 // Print each of the specified lanes of a register as a float or double value.
1230 //
1231 // The `lane_count` and `lslane` arguments can be used to limit the lanes that
1232 // are printed. These arguments are intended for use in cases where register
1233 // hasn't actually been updated (such as in PrintVWrite).
1234 //
1235 // No newline is printed. This allows the caller to print more details (such as
1236 // a memory access annotation).
1237 void Simulator::PrintVRegisterFPHelper(unsigned code,
1238  unsigned lane_size_in_bytes,
1239  int lane_count, int rightmost_lane) {
1240  DCHECK((lane_size_in_bytes == kSRegSize) ||
1241  (lane_size_in_bytes == kDRegSize));
1242 
1243  unsigned msb = (lane_count + rightmost_lane) * lane_size_in_bytes;
1244  DCHECK_LE(msb, static_cast<unsigned>(kQRegSize));
1245 
1246  // For scalar types ((lane_count == 1) && (rightmost_lane == 0)), a register
1247  // name is used:
1248  // " (s{code}: {value})"
1249  // " (d{code}: {value})"
1250  // For vector types, "..." is used to represent one or more omitted lanes.
1251  // " (..., {value}, {value}, ...)"
1252  if ((lane_count == 1) && (rightmost_lane == 0)) {
1253  const char* name = (lane_size_in_bytes == kSRegSize)
1254  ? SRegNameForCode(code)
1255  : DRegNameForCode(code);
1256  fprintf(stream_, " (%s%s: ", clr_vreg_name, name);
1257  } else {
1258  if (msb < (kQRegSize - 1)) {
1259  fprintf(stream_, " (..., ");
1260  } else {
1261  fprintf(stream_, " (");
1262  }
1263  }
1264 
1265  // Print the list of values.
1266  const char* separator = "";
1267  int leftmost_lane = rightmost_lane + lane_count - 1;
1268  for (int lane = leftmost_lane; lane >= rightmost_lane; lane--) {
1269  double value = (lane_size_in_bytes == kSRegSize)
1270  ? vreg(code).Get<float>(lane)
1271  : vreg(code).Get<double>(lane);
1272  fprintf(stream_, "%s%s%#g%s", separator, clr_vreg_value, value, clr_normal);
1273  separator = ", ";
1274  }
1275 
1276  if (rightmost_lane > 0) {
1277  fprintf(stream_, ", ...");
1278  }
1279  fprintf(stream_, ")");
1280 }
1281 
1282 // Print a register's name and raw value.
1283 //
1284 // Only the least-significant `size_in_bytes` bytes of the register are printed,
1285 // but the value is aligned as if the whole register had been printed.
1286 //
1287 // For typical register updates, size_in_bytes should be set to kXRegSize
1288 // -- the default -- so that the whole register is printed. Other values of
1289 // size_in_bytes are intended for use when the register hasn't actually been
1290 // updated (such as in PrintWrite).
1291 //
1292 // No newline is printed. This allows the caller to print more details (such as
1293 // a memory access annotation).
1294 void Simulator::PrintRegisterRawHelper(unsigned code, Reg31Mode r31mode,
1295  int size_in_bytes) {
1296  // The template for all supported sizes.
1297  // "# x{code}: 0xFFEEDDCCBBAA9988"
1298  // "# w{code}: 0xBBAA9988"
1299  // "# w{code}<15:0>: 0x9988"
1300  // "# w{code}<7:0>: 0x88"
1301  unsigned padding_chars = (kXRegSize - size_in_bytes) * 2;
1302 
1303  const char* name = "";
1304  const char* suffix = "";
1305  switch (size_in_bytes) {
1306  case kXRegSize:
1307  name = XRegNameForCode(code, r31mode);
1308  break;
1309  case kWRegSize:
1310  name = WRegNameForCode(code, r31mode);
1311  break;
1312  case 2:
1313  name = WRegNameForCode(code, r31mode);
1314  suffix = "<15:0>";
1315  padding_chars -= strlen(suffix);
1316  break;
1317  case 1:
1318  name = WRegNameForCode(code, r31mode);
1319  suffix = "<7:0>";
1320  padding_chars -= strlen(suffix);
1321  break;
1322  default:
1323  UNREACHABLE();
1324  }
1325  fprintf(stream_, "# %s%5s%s: ", clr_reg_name, name, suffix);
1326 
1327  // Print leading padding spaces.
1328  DCHECK_LT(padding_chars, kXRegSize * 2U);
1329  for (unsigned i = 0; i < padding_chars; i++) {
1330  putc(' ', stream_);
1331  }
1332 
1333  // Print the specified bits in hexadecimal format.
1334  uint64_t bits = reg<uint64_t>(code, r31mode);
1335  bits &= kXRegMask >> ((kXRegSize - size_in_bytes) * 8);
1336  static_assert(sizeof(bits) == kXRegSize,
1337  "X registers and uint64_t must be the same size.");
1338 
1339  int chars = size_in_bytes * 2;
1340  fprintf(stream_, "%s0x%0*" PRIx64 "%s", clr_reg_value, chars, bits,
1341  clr_normal);
1342 }
1343 
1344 void Simulator::PrintVRegister(unsigned code, PrintRegisterFormat format) {
1345  vregisters_[code].NotifyRegisterLogged();
1346 
1347  int lane_size_log2 = format & kPrintRegLaneSizeMask;
1348 
1349  int reg_size_log2;
1350  if (format & kPrintRegAsQVector) {
1351  reg_size_log2 = kQRegSizeLog2;
1352  } else if (format & kPrintRegAsDVector) {
1353  reg_size_log2 = kDRegSizeLog2;
1354  } else {
1355  // Scalar types.
1356  reg_size_log2 = lane_size_log2;
1357  }
1358 
1359  int lane_count = 1 << (reg_size_log2 - lane_size_log2);
1360  int lane_size = 1 << lane_size_log2;
1361 
1362  // The template for vector types:
1363  // "# v{code}: 0x{rawbits} (..., {value}, ...)".
1364  // The template for scalar types:
1365  // "# v{code}: 0x{rawbits} ({reg}:{value})".
1366  // The values in parentheses after the bit representations are floating-point
1367  // interpretations. They are displayed only if the kPrintVRegAsFP bit is set.
1368 
1369  PrintVRegisterRawHelper(code);
1370  if (format & kPrintRegAsFP) {
1371  PrintVRegisterFPHelper(code, lane_size, lane_count);
1372  }
1373 
1374  fprintf(stream_, "\n");
1375 }
1376 
1377 
1378 void Simulator::PrintSystemRegister(SystemRegister id) {
1379  switch (id) {
1380  case NZCV:
1381  fprintf(stream_, "# %sNZCV: %sN:%d Z:%d C:%d V:%d%s\n",
1382  clr_flag_name, clr_flag_value,
1383  nzcv().N(), nzcv().Z(), nzcv().C(), nzcv().V(),
1384  clr_normal);
1385  break;
1386  case FPCR: {
1387  static const char * rmode[] = {
1388  "0b00 (Round to Nearest)",
1389  "0b01 (Round towards Plus Infinity)",
1390  "0b10 (Round towards Minus Infinity)",
1391  "0b11 (Round towards Zero)"
1392  };
1393  DCHECK(fpcr().RMode() < arraysize(rmode));
1394  fprintf(stream_,
1395  "# %sFPCR: %sAHP:%d DN:%d FZ:%d RMode:%s%s\n",
1396  clr_flag_name, clr_flag_value,
1397  fpcr().AHP(), fpcr().DN(), fpcr().FZ(), rmode[fpcr().RMode()],
1398  clr_normal);
1399  break;
1400  }
1401  default:
1402  UNREACHABLE();
1403  }
1404 }
1405 
1406 void Simulator::PrintRead(uintptr_t address, unsigned reg_code,
1407  PrintRegisterFormat format) {
1408  registers_[reg_code].NotifyRegisterLogged();
1409 
1410  USE(format);
1411 
1412  // The template is "# {reg}: 0x{value} <- {address}".
1413  PrintRegisterRawHelper(reg_code, Reg31IsZeroRegister);
1414  fprintf(stream_, " <- %s0x%016" PRIxPTR "%s\n",
1415  clr_memory_address, address, clr_normal);
1416 }
1417 
1418 void Simulator::PrintVRead(uintptr_t address, unsigned reg_code,
1419  PrintRegisterFormat format, unsigned lane) {
1420  vregisters_[reg_code].NotifyRegisterLogged();
1421 
1422  // The template is "# v{code}: 0x{rawbits} <- address".
1423  PrintVRegisterRawHelper(reg_code);
1424  if (format & kPrintRegAsFP) {
1425  PrintVRegisterFPHelper(reg_code, GetPrintRegLaneSizeInBytes(format),
1426  GetPrintRegLaneCount(format), lane);
1427  }
1428  fprintf(stream_, " <- %s0x%016" PRIxPTR "%s\n",
1429  clr_memory_address, address, clr_normal);
1430 }
1431 
1432 void Simulator::PrintWrite(uintptr_t address, unsigned reg_code,
1433  PrintRegisterFormat format) {
1434  DCHECK_EQ(GetPrintRegLaneCount(format), 1U);
1435 
1436  // The template is "# v{code}: 0x{value} -> {address}". To keep the trace tidy
1437  // and readable, the value is aligned with the values in the register trace.
1438  PrintRegisterRawHelper(reg_code, Reg31IsZeroRegister,
1439  GetPrintRegSizeInBytes(format));
1440  fprintf(stream_, " -> %s0x%016" PRIxPTR "%s\n",
1441  clr_memory_address, address, clr_normal);
1442 }
1443 
1444 void Simulator::PrintVWrite(uintptr_t address, unsigned reg_code,
1445  PrintRegisterFormat format, unsigned lane) {
1446  // The templates:
1447  // "# v{code}: 0x{rawbits} -> {address}"
1448  // "# v{code}: 0x{rawbits} (..., {value}, ...) -> {address}".
1449  // "# v{code}: 0x{rawbits} ({reg}:{value}) -> {address}"
1450  // Because this trace doesn't represent a change to the source register's
1451  // value, only the relevant part of the value is printed. To keep the trace
1452  // tidy and readable, the raw value is aligned with the other values in the
1453  // register trace.
1454  int lane_count = GetPrintRegLaneCount(format);
1455  int lane_size = GetPrintRegLaneSizeInBytes(format);
1456  int reg_size = GetPrintRegSizeInBytes(format);
1457  PrintVRegisterRawHelper(reg_code, reg_size, lane_size * lane);
1458  if (format & kPrintRegAsFP) {
1459  PrintVRegisterFPHelper(reg_code, lane_size, lane_count, lane);
1460  }
1461  fprintf(stream_, " -> %s0x%016" PRIxPTR "%s\n",
1462  clr_memory_address, address, clr_normal);
1463 }
1464 
1465 
1466 // Visitors---------------------------------------------------------------------
1467 
1468 void Simulator::VisitUnimplemented(Instruction* instr) {
1469  fprintf(stream_, "Unimplemented instruction at %p: 0x%08" PRIx32 "\n",
1470  reinterpret_cast<void*>(instr), instr->InstructionBits());
1471  UNIMPLEMENTED();
1472 }
1473 
1474 
1475 void Simulator::VisitUnallocated(Instruction* instr) {
1476  fprintf(stream_, "Unallocated instruction at %p: 0x%08" PRIx32 "\n",
1477  reinterpret_cast<void*>(instr), instr->InstructionBits());
1478  UNIMPLEMENTED();
1479 }
1480 
1481 
1482 void Simulator::VisitPCRelAddressing(Instruction* instr) {
1483  switch (instr->Mask(PCRelAddressingMask)) {
1484  case ADR:
1485  set_reg(instr->Rd(), instr->ImmPCOffsetTarget());
1486  break;
1487  case ADRP: // Not implemented in the assembler.
1488  UNIMPLEMENTED();
1489  break;
1490  default:
1491  UNREACHABLE();
1492  break;
1493  }
1494 }
1495 
1496 
1497 void Simulator::VisitUnconditionalBranch(Instruction* instr) {
1498  switch (instr->Mask(UnconditionalBranchMask)) {
1499  case BL:
1500  set_lr(instr->following());
1501  V8_FALLTHROUGH;
1502  case B:
1503  set_pc(instr->ImmPCOffsetTarget());
1504  break;
1505  default:
1506  UNREACHABLE();
1507  }
1508 }
1509 
1510 
1511 void Simulator::VisitConditionalBranch(Instruction* instr) {
1512  DCHECK(instr->Mask(ConditionalBranchMask) == B_cond);
1513  if (ConditionPassed(static_cast<Condition>(instr->ConditionBranch()))) {
1514  set_pc(instr->ImmPCOffsetTarget());
1515  }
1516 }
1517 
1518 
1519 void Simulator::VisitUnconditionalBranchToRegister(Instruction* instr) {
1520  Instruction* target = reg<Instruction*>(instr->Rn());
1521  switch (instr->Mask(UnconditionalBranchToRegisterMask)) {
1522  case BLR: {
1523  set_lr(instr->following());
1524  if (instr->Rn() == 31) {
1525  // BLR XZR is used as a guard for the constant pool. We should never hit
1526  // this, but if we do trap to allow debugging.
1527  Debug();
1528  }
1529  V8_FALLTHROUGH;
1530  }
1531  case BR:
1532  case RET: set_pc(target); break;
1533  default: UNIMPLEMENTED();
1534  }
1535 }
1536 
1537 
1538 void Simulator::VisitTestBranch(Instruction* instr) {
1539  unsigned bit_pos = (instr->ImmTestBranchBit5() << 5) |
1540  instr->ImmTestBranchBit40();
1541  bool take_branch = ((xreg(instr->Rt()) & (1ULL << bit_pos)) == 0);
1542  switch (instr->Mask(TestBranchMask)) {
1543  case TBZ: break;
1544  case TBNZ: take_branch = !take_branch; break;
1545  default: UNIMPLEMENTED();
1546  }
1547  if (take_branch) {
1548  set_pc(instr->ImmPCOffsetTarget());
1549  }
1550 }
1551 
1552 
1553 void Simulator::VisitCompareBranch(Instruction* instr) {
1554  unsigned rt = instr->Rt();
1555  bool take_branch = false;
1556  switch (instr->Mask(CompareBranchMask)) {
1557  case CBZ_w: take_branch = (wreg(rt) == 0); break;
1558  case CBZ_x: take_branch = (xreg(rt) == 0); break;
1559  case CBNZ_w: take_branch = (wreg(rt) != 0); break;
1560  case CBNZ_x: take_branch = (xreg(rt) != 0); break;
1561  default: UNIMPLEMENTED();
1562  }
1563  if (take_branch) {
1564  set_pc(instr->ImmPCOffsetTarget());
1565  }
1566 }
1567 
1568 
1569 template<typename T>
1570 void Simulator::AddSubHelper(Instruction* instr, T op2) {
1571  // Use unsigned types to avoid implementation-defined overflow behaviour.
1572  static_assert(std::is_unsigned<T>::value, "operands must be unsigned");
1573 
1574  bool set_flags = instr->FlagsUpdate();
1575  T new_val = 0;
1576  Instr operation = instr->Mask(AddSubOpMask);
1577 
1578  switch (operation) {
1579  case ADD:
1580  case ADDS: {
1581  new_val = AddWithCarry<T>(set_flags,
1582  reg<T>(instr->Rn(), instr->RnMode()),
1583  op2);
1584  break;
1585  }
1586  case SUB:
1587  case SUBS: {
1588  new_val = AddWithCarry<T>(set_flags,
1589  reg<T>(instr->Rn(), instr->RnMode()),
1590  ~op2,
1591  1);
1592  break;
1593  }
1594  default: UNREACHABLE();
1595  }
1596 
1597  set_reg<T>(instr->Rd(), new_val, instr->RdMode());
1598 }
1599 
1600 
1601 void Simulator::VisitAddSubShifted(Instruction* instr) {
1602  Shift shift_type = static_cast<Shift>(instr->ShiftDP());
1603  unsigned shift_amount = instr->ImmDPShift();
1604 
1605  if (instr->SixtyFourBits()) {
1606  uint64_t op2 = ShiftOperand(xreg(instr->Rm()), shift_type, shift_amount);
1607  AddSubHelper(instr, op2);
1608  } else {
1609  uint32_t op2 = ShiftOperand(wreg(instr->Rm()), shift_type, shift_amount);
1610  AddSubHelper(instr, op2);
1611  }
1612 }
1613 
1614 
1615 void Simulator::VisitAddSubImmediate(Instruction* instr) {
1616  int64_t op2 = instr->ImmAddSub() << ((instr->ShiftAddSub() == 1) ? 12 : 0);
1617  if (instr->SixtyFourBits()) {
1618  AddSubHelper(instr, static_cast<uint64_t>(op2));
1619  } else {
1620  AddSubHelper(instr, static_cast<uint32_t>(op2));
1621  }
1622 }
1623 
1624 
1625 void Simulator::VisitAddSubExtended(Instruction* instr) {
1626  Extend ext = static_cast<Extend>(instr->ExtendMode());
1627  unsigned left_shift = instr->ImmExtendShift();
1628  if (instr->SixtyFourBits()) {
1629  uint64_t op2 = ExtendValue(xreg(instr->Rm()), ext, left_shift);
1630  AddSubHelper(instr, op2);
1631  } else {
1632  uint32_t op2 = ExtendValue(wreg(instr->Rm()), ext, left_shift);
1633  AddSubHelper(instr, op2);
1634  }
1635 }
1636 
1637 
1638 void Simulator::VisitAddSubWithCarry(Instruction* instr) {
1639  if (instr->SixtyFourBits()) {
1640  AddSubWithCarry<uint64_t>(instr);
1641  } else {
1642  AddSubWithCarry<uint32_t>(instr);
1643  }
1644 }
1645 
1646 
1647 void Simulator::VisitLogicalShifted(Instruction* instr) {
1648  Shift shift_type = static_cast<Shift>(instr->ShiftDP());
1649  unsigned shift_amount = instr->ImmDPShift();
1650 
1651  if (instr->SixtyFourBits()) {
1652  uint64_t op2 = ShiftOperand(xreg(instr->Rm()), shift_type, shift_amount);
1653  op2 = (instr->Mask(NOT) == NOT) ? ~op2 : op2;
1654  LogicalHelper(instr, op2);
1655  } else {
1656  uint32_t op2 = ShiftOperand(wreg(instr->Rm()), shift_type, shift_amount);
1657  op2 = (instr->Mask(NOT) == NOT) ? ~op2 : op2;
1658  LogicalHelper(instr, op2);
1659  }
1660 }
1661 
1662 
1663 void Simulator::VisitLogicalImmediate(Instruction* instr) {
1664  if (instr->SixtyFourBits()) {
1665  LogicalHelper(instr, static_cast<uint64_t>(instr->ImmLogical()));
1666  } else {
1667  LogicalHelper(instr, static_cast<uint32_t>(instr->ImmLogical()));
1668  }
1669 }
1670 
1671 
1672 template<typename T>
1673 void Simulator::LogicalHelper(Instruction* instr, T op2) {
1674  T op1 = reg<T>(instr->Rn());
1675  T result = 0;
1676  bool update_flags = false;
1677 
1678  // Switch on the logical operation, stripping out the NOT bit, as it has a
1679  // different meaning for logical immediate instructions.
1680  switch (instr->Mask(LogicalOpMask & ~NOT)) {
1681  case ANDS: update_flags = true; V8_FALLTHROUGH;
1682  case AND: result = op1 & op2; break;
1683  case ORR: result = op1 | op2; break;
1684  case EOR: result = op1 ^ op2; break;
1685  default:
1686  UNIMPLEMENTED();
1687  }
1688 
1689  if (update_flags) {
1690  nzcv().SetN(CalcNFlag(result));
1691  nzcv().SetZ(CalcZFlag(result));
1692  nzcv().SetC(0);
1693  nzcv().SetV(0);
1694  LogSystemRegister(NZCV);
1695  }
1696 
1697  set_reg<T>(instr->Rd(), result, instr->RdMode());
1698 }
1699 
1700 
1701 void Simulator::VisitConditionalCompareRegister(Instruction* instr) {
1702  if (instr->SixtyFourBits()) {
1703  ConditionalCompareHelper(instr, static_cast<uint64_t>(xreg(instr->Rm())));
1704  } else {
1705  ConditionalCompareHelper(instr, static_cast<uint32_t>(wreg(instr->Rm())));
1706  }
1707 }
1708 
1709 
1710 void Simulator::VisitConditionalCompareImmediate(Instruction* instr) {
1711  if (instr->SixtyFourBits()) {
1712  ConditionalCompareHelper(instr, static_cast<uint64_t>(instr->ImmCondCmp()));
1713  } else {
1714  ConditionalCompareHelper(instr, static_cast<uint32_t>(instr->ImmCondCmp()));
1715  }
1716 }
1717 
1718 
1719 template<typename T>
1720 void Simulator::ConditionalCompareHelper(Instruction* instr, T op2) {
1721  // Use unsigned types to avoid implementation-defined overflow behaviour.
1722  static_assert(std::is_unsigned<T>::value, "operands must be unsigned");
1723 
1724  T op1 = reg<T>(instr->Rn());
1725 
1726  if (ConditionPassed(static_cast<Condition>(instr->Condition()))) {
1727  // If the condition passes, set the status flags to the result of comparing
1728  // the operands.
1729  if (instr->Mask(ConditionalCompareMask) == CCMP) {
1730  AddWithCarry<T>(true, op1, ~op2, 1);
1731  } else {
1732  DCHECK(instr->Mask(ConditionalCompareMask) == CCMN);
1733  AddWithCarry<T>(true, op1, op2, 0);
1734  }
1735  } else {
1736  // If the condition fails, set the status flags to the nzcv immediate.
1737  nzcv().SetFlags(instr->Nzcv());
1738  LogSystemRegister(NZCV);
1739  }
1740 }
1741 
1742 
1743 void Simulator::VisitLoadStoreUnsignedOffset(Instruction* instr) {
1744  int offset = instr->ImmLSUnsigned() << instr->SizeLS();
1745  LoadStoreHelper(instr, offset, Offset);
1746 }
1747 
1748 
1749 void Simulator::VisitLoadStoreUnscaledOffset(Instruction* instr) {
1750  LoadStoreHelper(instr, instr->ImmLS(), Offset);
1751 }
1752 
1753 
1754 void Simulator::VisitLoadStorePreIndex(Instruction* instr) {
1755  LoadStoreHelper(instr, instr->ImmLS(), PreIndex);
1756 }
1757 
1758 
1759 void Simulator::VisitLoadStorePostIndex(Instruction* instr) {
1760  LoadStoreHelper(instr, instr->ImmLS(), PostIndex);
1761 }
1762 
1763 
1764 void Simulator::VisitLoadStoreRegisterOffset(Instruction* instr) {
1765  Extend ext = static_cast<Extend>(instr->ExtendMode());
1766  DCHECK((ext == UXTW) || (ext == UXTX) || (ext == SXTW) || (ext == SXTX));
1767  unsigned shift_amount = instr->ImmShiftLS() * instr->SizeLS();
1768 
1769  int64_t offset = ExtendValue(xreg(instr->Rm()), ext, shift_amount);
1770  LoadStoreHelper(instr, offset, Offset);
1771 }
1772 
1773 
1774 void Simulator::LoadStoreHelper(Instruction* instr,
1775  int64_t offset,
1776  AddrMode addrmode) {
1777  unsigned srcdst = instr->Rt();
1778  unsigned addr_reg = instr->Rn();
1779  uintptr_t address = LoadStoreAddress(addr_reg, offset, addrmode);
1780  uintptr_t stack = 0;
1781 
1782  {
1783  base::MutexGuard lock_guard(&global_monitor_.Pointer()->mutex);
1784  if (instr->IsLoad()) {
1785  local_monitor_.NotifyLoad();
1786  } else {
1787  local_monitor_.NotifyStore();
1788  global_monitor_.Pointer()->NotifyStore_Locked(&global_monitor_processor_);
1789  }
1790  }
1791 
1792  // Handle the writeback for stores before the store. On a CPU the writeback
1793  // and the store are atomic, but when running on the simulator it is possible
1794  // to be interrupted in between. The simulator is not thread safe and V8 does
1795  // not require it to be to run JavaScript therefore the profiler may sample
1796  // the "simulated" CPU in the middle of load/store with writeback. The code
1797  // below ensures that push operations are safe even when interrupted: the
1798  // stack pointer will be decremented before adding an element to the stack.
1799  if (instr->IsStore()) {
1800  LoadStoreWriteBack(addr_reg, offset, addrmode);
1801 
1802  // For store the address post writeback is used to check access below the
1803  // stack.
1804  stack = sp();
1805  }
1806 
1807  LoadStoreOp op = static_cast<LoadStoreOp>(instr->Mask(LoadStoreMask));
1808  switch (op) {
1809  // Use _no_log variants to suppress the register trace (LOG_REGS,
1810  // LOG_VREGS). We will print a more detailed log.
1811  case LDRB_w: set_wreg_no_log(srcdst, MemoryRead<uint8_t>(address)); break;
1812  case LDRH_w: set_wreg_no_log(srcdst, MemoryRead<uint16_t>(address)); break;
1813  case LDR_w: set_wreg_no_log(srcdst, MemoryRead<uint32_t>(address)); break;
1814  case LDR_x: set_xreg_no_log(srcdst, MemoryRead<uint64_t>(address)); break;
1815  case LDRSB_w: set_wreg_no_log(srcdst, MemoryRead<int8_t>(address)); break;
1816  case LDRSH_w: set_wreg_no_log(srcdst, MemoryRead<int16_t>(address)); break;
1817  case LDRSB_x: set_xreg_no_log(srcdst, MemoryRead<int8_t>(address)); break;
1818  case LDRSH_x: set_xreg_no_log(srcdst, MemoryRead<int16_t>(address)); break;
1819  case LDRSW_x: set_xreg_no_log(srcdst, MemoryRead<int32_t>(address)); break;
1820  case LDR_b:
1821  set_breg_no_log(srcdst, MemoryRead<uint8_t>(address));
1822  break;
1823  case LDR_h:
1824  set_hreg_no_log(srcdst, MemoryRead<uint16_t>(address));
1825  break;
1826  case LDR_s: set_sreg_no_log(srcdst, MemoryRead<float>(address)); break;
1827  case LDR_d: set_dreg_no_log(srcdst, MemoryRead<double>(address)); break;
1828  case LDR_q:
1829  set_qreg_no_log(srcdst, MemoryRead<qreg_t>(address));
1830  break;
1831 
1832  case STRB_w: MemoryWrite<uint8_t>(address, wreg(srcdst)); break;
1833  case STRH_w: MemoryWrite<uint16_t>(address, wreg(srcdst)); break;
1834  case STR_w: MemoryWrite<uint32_t>(address, wreg(srcdst)); break;
1835  case STR_x: MemoryWrite<uint64_t>(address, xreg(srcdst)); break;
1836  case STR_b:
1837  MemoryWrite<uint8_t>(address, breg(srcdst));
1838  break;
1839  case STR_h:
1840  MemoryWrite<uint16_t>(address, hreg(srcdst));
1841  break;
1842  case STR_s: MemoryWrite<float>(address, sreg(srcdst)); break;
1843  case STR_d: MemoryWrite<double>(address, dreg(srcdst)); break;
1844  case STR_q:
1845  MemoryWrite<qreg_t>(address, qreg(srcdst));
1846  break;
1847 
1848  default: UNIMPLEMENTED();
1849  }
1850 
1851  // Print a detailed trace (including the memory address) instead of the basic
1852  // register:value trace generated by set_*reg().
1853  unsigned access_size = 1 << instr->SizeLS();
1854  if (instr->IsLoad()) {
1855  if ((op == LDR_s) || (op == LDR_d)) {
1856  LogVRead(address, srcdst, GetPrintRegisterFormatForSizeFP(access_size));
1857  } else if ((op == LDR_b) || (op == LDR_h) || (op == LDR_q)) {
1858  LogVRead(address, srcdst, GetPrintRegisterFormatForSize(access_size));
1859  } else {
1860  LogRead(address, srcdst, GetPrintRegisterFormatForSize(access_size));
1861  }
1862  } else {
1863  if ((op == STR_s) || (op == STR_d)) {
1864  LogVWrite(address, srcdst, GetPrintRegisterFormatForSizeFP(access_size));
1865  } else if ((op == STR_b) || (op == STR_h) || (op == STR_q)) {
1866  LogVWrite(address, srcdst, GetPrintRegisterFormatForSize(access_size));
1867  } else {
1868  LogWrite(address, srcdst, GetPrintRegisterFormatForSize(access_size));
1869  }
1870  }
1871 
1872  // Handle the writeback for loads after the load to ensure safe pop
1873  // operation even when interrupted in the middle of it. The stack pointer
1874  // is only updated after the load so pop(fp) will never break the invariant
1875  // sp <= fp expected while walking the stack in the sampler.
1876  if (instr->IsLoad()) {
1877  // For loads the address pre writeback is used to check access below the
1878  // stack.
1879  stack = sp();
1880 
1881  LoadStoreWriteBack(addr_reg, offset, addrmode);
1882  }
1883 
1884  // Accesses below the stack pointer (but above the platform stack limit) are
1885  // not allowed in the ABI.
1886  CheckMemoryAccess(address, stack);
1887 }
1888 
1889 
1890 void Simulator::VisitLoadStorePairOffset(Instruction* instr) {
1891  LoadStorePairHelper(instr, Offset);
1892 }
1893 
1894 
1895 void Simulator::VisitLoadStorePairPreIndex(Instruction* instr) {
1896  LoadStorePairHelper(instr, PreIndex);
1897 }
1898 
1899 
1900 void Simulator::VisitLoadStorePairPostIndex(Instruction* instr) {
1901  LoadStorePairHelper(instr, PostIndex);
1902 }
1903 
1904 
1905 void Simulator::LoadStorePairHelper(Instruction* instr,
1906  AddrMode addrmode) {
1907  unsigned rt = instr->Rt();
1908  unsigned rt2 = instr->Rt2();
1909  unsigned addr_reg = instr->Rn();
1910  size_t access_size = 1ULL << instr->SizeLSPair();
1911  int64_t offset = instr->ImmLSPair() * access_size;
1912  uintptr_t address = LoadStoreAddress(addr_reg, offset, addrmode);
1913  uintptr_t address2 = address + access_size;
1914  uintptr_t stack = 0;
1915 
1916  {
1917  base::MutexGuard lock_guard(&global_monitor_.Pointer()->mutex);
1918  if (instr->IsLoad()) {
1919  local_monitor_.NotifyLoad();
1920  } else {
1921  local_monitor_.NotifyStore();
1922  global_monitor_.Pointer()->NotifyStore_Locked(&global_monitor_processor_);
1923  }
1924  }
1925 
1926  // Handle the writeback for stores before the store. On a CPU the writeback
1927  // and the store are atomic, but when running on the simulator it is possible
1928  // to be interrupted in between. The simulator is not thread safe and V8 does
1929  // not require it to be to run JavaScript therefore the profiler may sample
1930  // the "simulated" CPU in the middle of load/store with writeback. The code
1931  // below ensures that push operations are safe even when interrupted: the
1932  // stack pointer will be decremented before adding an element to the stack.
1933  if (instr->IsStore()) {
1934  LoadStoreWriteBack(addr_reg, offset, addrmode);
1935 
1936  // For store the address post writeback is used to check access below the
1937  // stack.
1938  stack = sp();
1939  }
1940 
1941  LoadStorePairOp op =
1942  static_cast<LoadStorePairOp>(instr->Mask(LoadStorePairMask));
1943 
1944  // 'rt' and 'rt2' can only be aliased for stores.
1945  DCHECK(((op & LoadStorePairLBit) == 0) || (rt != rt2));
1946 
1947  switch (op) {
1948  // Use _no_log variants to suppress the register trace (LOG_REGS,
1949  // LOG_VREGS). We will print a more detailed log.
1950  case LDP_w: {
1951  DCHECK_EQ(access_size, static_cast<unsigned>(kWRegSize));
1952  set_wreg_no_log(rt, MemoryRead<uint32_t>(address));
1953  set_wreg_no_log(rt2, MemoryRead<uint32_t>(address2));
1954  break;
1955  }
1956  case LDP_s: {
1957  DCHECK_EQ(access_size, static_cast<unsigned>(kSRegSize));
1958  set_sreg_no_log(rt, MemoryRead<float>(address));
1959  set_sreg_no_log(rt2, MemoryRead<float>(address2));
1960  break;
1961  }
1962  case LDP_x: {
1963  DCHECK_EQ(access_size, static_cast<unsigned>(kXRegSize));
1964  set_xreg_no_log(rt, MemoryRead<uint64_t>(address));
1965  set_xreg_no_log(rt2, MemoryRead<uint64_t>(address2));
1966  break;
1967  }
1968  case LDP_d: {
1969  DCHECK_EQ(access_size, static_cast<unsigned>(kDRegSize));
1970  set_dreg_no_log(rt, MemoryRead<double>(address));
1971  set_dreg_no_log(rt2, MemoryRead<double>(address2));
1972  break;
1973  }
1974  case LDP_q: {
1975  DCHECK_EQ(access_size, static_cast<unsigned>(kQRegSize));
1976  set_qreg(rt, MemoryRead<qreg_t>(address), NoRegLog);
1977  set_qreg(rt2, MemoryRead<qreg_t>(address2), NoRegLog);
1978  break;
1979  }
1980  case LDPSW_x: {
1981  DCHECK_EQ(access_size, static_cast<unsigned>(kWRegSize));
1982  set_xreg_no_log(rt, MemoryRead<int32_t>(address));
1983  set_xreg_no_log(rt2, MemoryRead<int32_t>(address2));
1984  break;
1985  }
1986  case STP_w: {
1987  DCHECK_EQ(access_size, static_cast<unsigned>(kWRegSize));
1988  MemoryWrite<uint32_t>(address, wreg(rt));
1989  MemoryWrite<uint32_t>(address2, wreg(rt2));
1990  break;
1991  }
1992  case STP_s: {
1993  DCHECK_EQ(access_size, static_cast<unsigned>(kSRegSize));
1994  MemoryWrite<float>(address, sreg(rt));
1995  MemoryWrite<float>(address2, sreg(rt2));
1996  break;
1997  }
1998  case STP_x: {
1999  DCHECK_EQ(access_size, static_cast<unsigned>(kXRegSize));
2000  MemoryWrite<uint64_t>(address, xreg(rt));
2001  MemoryWrite<uint64_t>(address2, xreg(rt2));
2002  break;
2003  }
2004  case STP_d: {
2005  DCHECK_EQ(access_size, static_cast<unsigned>(kDRegSize));
2006  MemoryWrite<double>(address, dreg(rt));
2007  MemoryWrite<double>(address2, dreg(rt2));
2008  break;
2009  }
2010  case STP_q: {
2011  DCHECK_EQ(access_size, static_cast<unsigned>(kQRegSize));
2012  MemoryWrite<qreg_t>(address, qreg(rt));
2013  MemoryWrite<qreg_t>(address2, qreg(rt2));
2014  break;
2015  }
2016  default: UNREACHABLE();
2017  }
2018 
2019  // Print a detailed trace (including the memory address) instead of the basic
2020  // register:value trace generated by set_*reg().
2021  if (instr->IsLoad()) {
2022  if ((op == LDP_s) || (op == LDP_d)) {
2023  LogVRead(address, rt, GetPrintRegisterFormatForSizeFP(access_size));
2024  LogVRead(address2, rt2, GetPrintRegisterFormatForSizeFP(access_size));
2025  } else if (op == LDP_q) {
2026  LogVRead(address, rt, GetPrintRegisterFormatForSize(access_size));
2027  LogVRead(address2, rt2, GetPrintRegisterFormatForSize(access_size));
2028  } else {
2029  LogRead(address, rt, GetPrintRegisterFormatForSize(access_size));
2030  LogRead(address2, rt2, GetPrintRegisterFormatForSize(access_size));
2031  }
2032  } else {
2033  if ((op == STP_s) || (op == STP_d)) {
2034  LogVWrite(address, rt, GetPrintRegisterFormatForSizeFP(access_size));
2035  LogVWrite(address2, rt2, GetPrintRegisterFormatForSizeFP(access_size));
2036  } else if (op == STP_q) {
2037  LogVWrite(address, rt, GetPrintRegisterFormatForSize(access_size));
2038  LogVWrite(address2, rt2, GetPrintRegisterFormatForSize(access_size));
2039  } else {
2040  LogWrite(address, rt, GetPrintRegisterFormatForSize(access_size));
2041  LogWrite(address2, rt2, GetPrintRegisterFormatForSize(access_size));
2042  }
2043  }
2044 
2045  // Handle the writeback for loads after the load to ensure safe pop
2046  // operation even when interrupted in the middle of it. The stack pointer
2047  // is only updated after the load so pop(fp) will never break the invariant
2048  // sp <= fp expected while walking the stack in the sampler.
2049  if (instr->IsLoad()) {
2050  // For loads the address pre writeback is used to check access below the
2051  // stack.
2052  stack = sp();
2053 
2054  LoadStoreWriteBack(addr_reg, offset, addrmode);
2055  }
2056 
2057  // Accesses below the stack pointer (but above the platform stack limit) are
2058  // not allowed in the ABI.
2059  CheckMemoryAccess(address, stack);
2060 }
2061 
2062 
2063 void Simulator::VisitLoadLiteral(Instruction* instr) {
2064  uintptr_t address = instr->LiteralAddress();
2065  unsigned rt = instr->Rt();
2066 
2067  {
2068  base::MutexGuard lock_guard(&global_monitor_.Pointer()->mutex);
2069  local_monitor_.NotifyLoad();
2070  }
2071 
2072  switch (instr->Mask(LoadLiteralMask)) {
2073  // Use _no_log variants to suppress the register trace (LOG_REGS,
2074  // LOG_VREGS), then print a more detailed log.
2075  case LDR_w_lit:
2076  set_wreg_no_log(rt, MemoryRead<uint32_t>(address));
2077  LogRead(address, rt, kPrintWReg);
2078  break;
2079  case LDR_x_lit:
2080  set_xreg_no_log(rt, MemoryRead<uint64_t>(address));
2081  LogRead(address, rt, kPrintXReg);
2082  break;
2083  case LDR_s_lit:
2084  set_sreg_no_log(rt, MemoryRead<float>(address));
2085  LogVRead(address, rt, kPrintSReg);
2086  break;
2087  case LDR_d_lit:
2088  set_dreg_no_log(rt, MemoryRead<double>(address));
2089  LogVRead(address, rt, kPrintDReg);
2090  break;
2091  default: UNREACHABLE();
2092  }
2093 }
2094 
2095 
2096 uintptr_t Simulator::LoadStoreAddress(unsigned addr_reg, int64_t offset,
2097  AddrMode addrmode) {
2098  const unsigned kSPRegCode = kSPRegInternalCode & kRegCodeMask;
2099  uint64_t address = xreg(addr_reg, Reg31IsStackPointer);
2100  if ((addr_reg == kSPRegCode) && ((address % 16) != 0)) {
2101  // When the base register is SP the stack pointer is required to be
2102  // quadword aligned prior to the address calculation and write-backs.
2103  // Misalignment will cause a stack alignment fault.
2104  FATAL("ALIGNMENT EXCEPTION");
2105  }
2106 
2107  if ((addrmode == Offset) || (addrmode == PreIndex)) {
2108  address += offset;
2109  }
2110 
2111  return address;
2112 }
2113 
2114 
2115 void Simulator::LoadStoreWriteBack(unsigned addr_reg,
2116  int64_t offset,
2117  AddrMode addrmode) {
2118  if ((addrmode == PreIndex) || (addrmode == PostIndex)) {
2119  DCHECK_NE(offset, 0);
2120  uint64_t address = xreg(addr_reg, Reg31IsStackPointer);
2121  set_reg(addr_reg, address + offset, Reg31IsStackPointer);
2122  }
2123 }
2124 
2125 Simulator::TransactionSize Simulator::get_transaction_size(unsigned size) {
2126  switch (size) {
2127  case 0:
2128  return TransactionSize::None;
2129  case 1:
2130  return TransactionSize::Byte;
2131  case 2:
2132  return TransactionSize::HalfWord;
2133  case 4:
2134  return TransactionSize::Word;
2135  case 8:
2136  return TransactionSize::DoubleWord;
2137  default:
2138  UNREACHABLE();
2139  }
2140  return TransactionSize::None;
2141 }
2142 
2143 void Simulator::VisitLoadStoreAcquireRelease(Instruction* instr) {
2144  unsigned rt = instr->Rt();
2145  unsigned rn = instr->Rn();
2146  LoadStoreAcquireReleaseOp op = static_cast<LoadStoreAcquireReleaseOp>(
2147  instr->Mask(LoadStoreAcquireReleaseMask));
2148  int32_t is_acquire_release = instr->LoadStoreXAcquireRelease();
2149  int32_t is_exclusive = (instr->LoadStoreXNotExclusive() == 0);
2150  int32_t is_load = instr->LoadStoreXLoad();
2151  int32_t is_pair = instr->LoadStoreXPair();
2152  USE(is_acquire_release);
2153  USE(is_pair);
2154  DCHECK_NE(is_acquire_release, 0); // Non-acquire/release unimplemented.
2155  DCHECK_EQ(is_pair, 0); // Pair unimplemented.
2156  unsigned access_size = 1 << instr->LoadStoreXSizeLog2();
2157  uintptr_t address = LoadStoreAddress(rn, 0, AddrMode::Offset);
2158  DCHECK_EQ(address % access_size, 0);
2159  base::MutexGuard lock_guard(&global_monitor_.Pointer()->mutex);
2160  if (is_load != 0) {
2161  if (is_exclusive) {
2162  local_monitor_.NotifyLoadExcl(address, get_transaction_size(access_size));
2163  global_monitor_.Pointer()->NotifyLoadExcl_Locked(
2164  address, &global_monitor_processor_);
2165  } else {
2166  local_monitor_.NotifyLoad();
2167  }
2168  switch (op) {
2169  case LDAR_b:
2170  case LDAXR_b:
2171  set_wreg_no_log(rt, MemoryRead<uint8_t>(address));
2172  break;
2173  case LDAR_h:
2174  case LDAXR_h:
2175  set_wreg_no_log(rt, MemoryRead<uint16_t>(address));
2176  break;
2177  case LDAR_w:
2178  case LDAXR_w:
2179  set_wreg_no_log(rt, MemoryRead<uint32_t>(address));
2180  break;
2181  case LDAR_x:
2182  case LDAXR_x:
2183  set_xreg_no_log(rt, MemoryRead<uint64_t>(address));
2184  break;
2185  default:
2186  UNIMPLEMENTED();
2187  }
2188  LogRead(address, rt, GetPrintRegisterFormatForSize(access_size));
2189  } else {
2190  if (is_exclusive) {
2191  unsigned rs = instr->Rs();
2192  DCHECK_NE(rs, rt);
2193  DCHECK_NE(rs, rn);
2194  if (local_monitor_.NotifyStoreExcl(address,
2195  get_transaction_size(access_size)) &&
2196  global_monitor_.Pointer()->NotifyStoreExcl_Locked(
2197  address, &global_monitor_processor_)) {
2198  switch (op) {
2199  case STLXR_b:
2200  MemoryWrite<uint8_t>(address, wreg(rt));
2201  break;
2202  case STLXR_h:
2203  MemoryWrite<uint16_t>(address, wreg(rt));
2204  break;
2205  case STLXR_w:
2206  MemoryWrite<uint32_t>(address, wreg(rt));
2207  break;
2208  case STLXR_x:
2209  MemoryWrite<uint64_t>(address, xreg(rt));
2210  break;
2211  default:
2212  UNIMPLEMENTED();
2213  }
2214  LogWrite(address, rt, GetPrintRegisterFormatForSize(access_size));
2215  set_wreg(rs, 0);
2216  } else {
2217  set_wreg(rs, 1);
2218  }
2219  } else {
2220  local_monitor_.NotifyStore();
2221  global_monitor_.Pointer()->NotifyStore_Locked(&global_monitor_processor_);
2222  switch (op) {
2223  case STLR_b:
2224  MemoryWrite<uint8_t>(address, wreg(rt));
2225  break;
2226  case STLR_h:
2227  MemoryWrite<uint16_t>(address, wreg(rt));
2228  break;
2229  case STLR_w:
2230  MemoryWrite<uint32_t>(address, wreg(rt));
2231  break;
2232  case STLR_x:
2233  MemoryWrite<uint64_t>(address, xreg(rt));
2234  break;
2235  default:
2236  UNIMPLEMENTED();
2237  }
2238  }
2239  }
2240 }
2241 
2242 void Simulator::CheckMemoryAccess(uintptr_t address, uintptr_t stack) {
2243  if ((address >= stack_limit_) && (address < stack)) {
2244  fprintf(stream_, "ACCESS BELOW STACK POINTER:\n");
2245  fprintf(stream_, " sp is here: 0x%016" PRIx64 "\n",
2246  static_cast<uint64_t>(stack));
2247  fprintf(stream_, " access was here: 0x%016" PRIx64 "\n",
2248  static_cast<uint64_t>(address));
2249  fprintf(stream_, " stack limit is here: 0x%016" PRIx64 "\n",
2250  static_cast<uint64_t>(stack_limit_));
2251  fprintf(stream_, "\n");
2252  FATAL("ACCESS BELOW STACK POINTER");
2253  }
2254 }
2255 
2256 
2257 void Simulator::VisitMoveWideImmediate(Instruction* instr) {
2258  MoveWideImmediateOp mov_op =
2259  static_cast<MoveWideImmediateOp>(instr->Mask(MoveWideImmediateMask));
2260  int64_t new_xn_val = 0;
2261 
2262  bool is_64_bits = instr->SixtyFourBits() == 1;
2263  // Shift is limited for W operations.
2264  DCHECK(is_64_bits || (instr->ShiftMoveWide() < 2));
2265 
2266  // Get the shifted immediate.
2267  int64_t shift = instr->ShiftMoveWide() * 16;
2268  int64_t shifted_imm16 = static_cast<int64_t>(instr->ImmMoveWide()) << shift;
2269 
2270  // Compute the new value.
2271  switch (mov_op) {
2272  case MOVN_w:
2273  case MOVN_x: {
2274  new_xn_val = ~shifted_imm16;
2275  if (!is_64_bits) new_xn_val &= kWRegMask;
2276  break;
2277  }
2278  case MOVK_w:
2279  case MOVK_x: {
2280  unsigned reg_code = instr->Rd();
2281  int64_t prev_xn_val = is_64_bits ? xreg(reg_code)
2282  : wreg(reg_code);
2283  new_xn_val = (prev_xn_val & ~(0xFFFFL << shift)) | shifted_imm16;
2284  break;
2285  }
2286  case MOVZ_w:
2287  case MOVZ_x: {
2288  new_xn_val = shifted_imm16;
2289  break;
2290  }
2291  default:
2292  UNREACHABLE();
2293  }
2294 
2295  // Update the destination register.
2296  set_xreg(instr->Rd(), new_xn_val);
2297 }
2298 
2299 
2300 void Simulator::VisitConditionalSelect(Instruction* instr) {
2301  uint64_t new_val = xreg(instr->Rn());
2302  if (ConditionFailed(static_cast<Condition>(instr->Condition()))) {
2303  new_val = xreg(instr->Rm());
2304  switch (instr->Mask(ConditionalSelectMask)) {
2305  case CSEL_w:
2306  case CSEL_x:
2307  break;
2308  case CSINC_w:
2309  case CSINC_x:
2310  new_val++;
2311  break;
2312  case CSINV_w:
2313  case CSINV_x:
2314  new_val = ~new_val;
2315  break;
2316  case CSNEG_w:
2317  case CSNEG_x:
2318  new_val = (uint64_t)(-(int64_t)new_val);
2319  break;
2320  default: UNIMPLEMENTED();
2321  }
2322  }
2323  if (instr->SixtyFourBits()) {
2324  set_xreg(instr->Rd(), new_val);
2325  } else {
2326  set_wreg(instr->Rd(), static_cast<uint32_t>(new_val));
2327  }
2328 }
2329 
2330 
2331 void Simulator::VisitDataProcessing1Source(Instruction* instr) {
2332  unsigned dst = instr->Rd();
2333  unsigned src = instr->Rn();
2334 
2335  switch (instr->Mask(DataProcessing1SourceMask)) {
2336  case RBIT_w:
2337  set_wreg(dst, base::bits::ReverseBits(wreg(src)));
2338  break;
2339  case RBIT_x:
2340  set_xreg(dst, base::bits::ReverseBits(xreg(src)));
2341  break;
2342  case REV16_w:
2343  set_wreg(dst, ReverseBytes(wreg(src), 1));
2344  break;
2345  case REV16_x:
2346  set_xreg(dst, ReverseBytes(xreg(src), 1));
2347  break;
2348  case REV_w:
2349  set_wreg(dst, ReverseBytes(wreg(src), 2));
2350  break;
2351  case REV32_x:
2352  set_xreg(dst, ReverseBytes(xreg(src), 2));
2353  break;
2354  case REV_x:
2355  set_xreg(dst, ReverseBytes(xreg(src), 3));
2356  break;
2357  case CLZ_w: set_wreg(dst, CountLeadingZeros(wreg(src), kWRegSizeInBits));
2358  break;
2359  case CLZ_x: set_xreg(dst, CountLeadingZeros(xreg(src), kXRegSizeInBits));
2360  break;
2361  case CLS_w: {
2362  set_wreg(dst, CountLeadingSignBits(wreg(src), kWRegSizeInBits));
2363  break;
2364  }
2365  case CLS_x: {
2366  set_xreg(dst, CountLeadingSignBits(xreg(src), kXRegSizeInBits));
2367  break;
2368  }
2369  default: UNIMPLEMENTED();
2370  }
2371 }
2372 
2373 
2374 template <typename T>
2375 void Simulator::DataProcessing2Source(Instruction* instr) {
2376  Shift shift_op = NO_SHIFT;
2377  T result = 0;
2378  switch (instr->Mask(DataProcessing2SourceMask)) {
2379  case SDIV_w:
2380  case SDIV_x: {
2381  T rn = reg<T>(instr->Rn());
2382  T rm = reg<T>(instr->Rm());
2383  if ((rn == std::numeric_limits<T>::min()) && (rm == -1)) {
2384  result = std::numeric_limits<T>::min();
2385  } else if (rm == 0) {
2386  // Division by zero can be trapped, but not on A-class processors.
2387  result = 0;
2388  } else {
2389  result = rn / rm;
2390  }
2391  break;
2392  }
2393  case UDIV_w:
2394  case UDIV_x: {
2395  typedef typename std::make_unsigned<T>::type unsignedT;
2396  unsignedT rn = static_cast<unsignedT>(reg<T>(instr->Rn()));
2397  unsignedT rm = static_cast<unsignedT>(reg<T>(instr->Rm()));
2398  if (rm == 0) {
2399  // Division by zero can be trapped, but not on A-class processors.
2400  result = 0;
2401  } else {
2402  result = rn / rm;
2403  }
2404  break;
2405  }
2406  case LSLV_w:
2407  case LSLV_x: shift_op = LSL; break;
2408  case LSRV_w:
2409  case LSRV_x: shift_op = LSR; break;
2410  case ASRV_w:
2411  case ASRV_x: shift_op = ASR; break;
2412  case RORV_w:
2413  case RORV_x: shift_op = ROR; break;
2414  default: UNIMPLEMENTED();
2415  }
2416 
2417  if (shift_op != NO_SHIFT) {
2418  // Shift distance encoded in the least-significant five/six bits of the
2419  // register.
2420  unsigned shift = wreg(instr->Rm());
2421  if (sizeof(T) == kWRegSize) {
2422  shift &= kShiftAmountWRegMask;
2423  } else {
2424  shift &= kShiftAmountXRegMask;
2425  }
2426  result = ShiftOperand(reg<T>(instr->Rn()), shift_op, shift);
2427  }
2428  set_reg<T>(instr->Rd(), result);
2429 }
2430 
2431 
2432 void Simulator::VisitDataProcessing2Source(Instruction* instr) {
2433  if (instr->SixtyFourBits()) {
2434  DataProcessing2Source<int64_t>(instr);
2435  } else {
2436  DataProcessing2Source<int32_t>(instr);
2437  }
2438 }
2439 
2440 
2441 // The algorithm used is described in section 8.2 of
2442 // Hacker's Delight, by Henry S. Warren, Jr.
2443 // It assumes that a right shift on a signed integer is an arithmetic shift.
2444 static int64_t MultiplyHighSigned(int64_t u, int64_t v) {
2445  uint64_t u0, v0, w0;
2446  int64_t u1, v1, w1, w2, t;
2447 
2448  u0 = u & 0xFFFFFFFFLL;
2449  u1 = u >> 32;
2450  v0 = v & 0xFFFFFFFFLL;
2451  v1 = v >> 32;
2452 
2453  w0 = u0 * v0;
2454  t = u1 * v0 + (w0 >> 32);
2455  w1 = t & 0xFFFFFFFFLL;
2456  w2 = t >> 32;
2457  w1 = u0 * v1 + w1;
2458 
2459  return u1 * v1 + w2 + (w1 >> 32);
2460 }
2461 
2462 
2463 void Simulator::VisitDataProcessing3Source(Instruction* instr) {
2464  int64_t result = 0;
2465  // Extract and sign- or zero-extend 32-bit arguments for widening operations.
2466  uint64_t rn_u32 = reg<uint32_t>(instr->Rn());
2467  uint64_t rm_u32 = reg<uint32_t>(instr->Rm());
2468  int64_t rn_s32 = reg<int32_t>(instr->Rn());
2469  int64_t rm_s32 = reg<int32_t>(instr->Rm());
2470  switch (instr->Mask(DataProcessing3SourceMask)) {
2471  case MADD_w:
2472  case MADD_x:
2473  result = xreg(instr->Ra()) + (xreg(instr->Rn()) * xreg(instr->Rm()));
2474  break;
2475  case MSUB_w:
2476  case MSUB_x:
2477  result = xreg(instr->Ra()) - (xreg(instr->Rn()) * xreg(instr->Rm()));
2478  break;
2479  case SMADDL_x: result = xreg(instr->Ra()) + (rn_s32 * rm_s32); break;
2480  case SMSUBL_x: result = xreg(instr->Ra()) - (rn_s32 * rm_s32); break;
2481  case UMADDL_x: result = xreg(instr->Ra()) + (rn_u32 * rm_u32); break;
2482  case UMSUBL_x: result = xreg(instr->Ra()) - (rn_u32 * rm_u32); break;
2483  case SMULH_x:
2484  DCHECK_EQ(instr->Ra(), kZeroRegCode);
2485  result = MultiplyHighSigned(xreg(instr->Rn()), xreg(instr->Rm()));
2486  break;
2487  default: UNIMPLEMENTED();
2488  }
2489 
2490  if (instr->SixtyFourBits()) {
2491  set_xreg(instr->Rd(), result);
2492  } else {
2493  set_wreg(instr->Rd(), static_cast<int32_t>(result));
2494  }
2495 }
2496 
2497 
2498 template <typename T>
2499 void Simulator::BitfieldHelper(Instruction* instr) {
2500  typedef typename std::make_unsigned<T>::type unsignedT;
2501  T reg_size = sizeof(T) * 8;
2502  T R = instr->ImmR();
2503  T S = instr->ImmS();
2504  T diff = S - R;
2505  T mask;
2506  if (diff >= 0) {
2507  mask = diff < reg_size - 1 ? (static_cast<T>(1) << (diff + 1)) - 1
2508  : static_cast<T>(-1);
2509  } else {
2510  uint64_t umask = ((1LL << (S + 1)) - 1);
2511  umask = (umask >> R) | (umask << (reg_size - R));
2512  mask = static_cast<T>(umask);
2513  diff += reg_size;
2514  }
2515 
2516  // inzero indicates if the extracted bitfield is inserted into the
2517  // destination register value or in zero.
2518  // If extend is true, extend the sign of the extracted bitfield.
2519  bool inzero = false;
2520  bool extend = false;
2521  switch (instr->Mask(BitfieldMask)) {
2522  case BFM_x:
2523  case BFM_w:
2524  break;
2525  case SBFM_x:
2526  case SBFM_w:
2527  inzero = true;
2528  extend = true;
2529  break;
2530  case UBFM_x:
2531  case UBFM_w:
2532  inzero = true;
2533  break;
2534  default:
2535  UNIMPLEMENTED();
2536  }
2537 
2538  T dst = inzero ? 0 : reg<T>(instr->Rd());
2539  T src = reg<T>(instr->Rn());
2540  // Rotate source bitfield into place.
2541  T result = (static_cast<unsignedT>(src) >> R) | (src << (reg_size - R));
2542  // Determine the sign extension.
2543  T topbits_preshift = (static_cast<T>(1) << (reg_size - diff - 1)) - 1;
2544  T signbits = (extend && ((src >> S) & 1) ? topbits_preshift : 0)
2545  << (diff + 1);
2546 
2547  // Merge sign extension, dest/zero and bitfield.
2548  result = signbits | (result & mask) | (dst & ~mask);
2549 
2550  set_reg<T>(instr->Rd(), result);
2551 }
2552 
2553 
2554 void Simulator::VisitBitfield(Instruction* instr) {
2555  if (instr->SixtyFourBits()) {
2556  BitfieldHelper<int64_t>(instr);
2557  } else {
2558  BitfieldHelper<int32_t>(instr);
2559  }
2560 }
2561 
2562 
2563 void Simulator::VisitExtract(Instruction* instr) {
2564  if (instr->SixtyFourBits()) {
2565  Extract<uint64_t>(instr);
2566  } else {
2567  Extract<uint32_t>(instr);
2568  }
2569 }
2570 
2571 
2572 void Simulator::VisitFPImmediate(Instruction* instr) {
2573  AssertSupportedFPCR();
2574 
2575  unsigned dest = instr->Rd();
2576  switch (instr->Mask(FPImmediateMask)) {
2577  case FMOV_s_imm: set_sreg(dest, instr->ImmFP32()); break;
2578  case FMOV_d_imm: set_dreg(dest, instr->ImmFP64()); break;
2579  default: UNREACHABLE();
2580  }
2581 }
2582 
2583 
2584 void Simulator::VisitFPIntegerConvert(Instruction* instr) {
2585  AssertSupportedFPCR();
2586 
2587  unsigned dst = instr->Rd();
2588  unsigned src = instr->Rn();
2589 
2590  FPRounding round = fpcr().RMode();
2591 
2592  switch (instr->Mask(FPIntegerConvertMask)) {
2593  case FCVTAS_ws: set_wreg(dst, FPToInt32(sreg(src), FPTieAway)); break;
2594  case FCVTAS_xs: set_xreg(dst, FPToInt64(sreg(src), FPTieAway)); break;
2595  case FCVTAS_wd: set_wreg(dst, FPToInt32(dreg(src), FPTieAway)); break;
2596  case FCVTAS_xd: set_xreg(dst, FPToInt64(dreg(src), FPTieAway)); break;
2597  case FCVTAU_ws: set_wreg(dst, FPToUInt32(sreg(src), FPTieAway)); break;
2598  case FCVTAU_xs: set_xreg(dst, FPToUInt64(sreg(src), FPTieAway)); break;
2599  case FCVTAU_wd: set_wreg(dst, FPToUInt32(dreg(src), FPTieAway)); break;
2600  case FCVTAU_xd: set_xreg(dst, FPToUInt64(dreg(src), FPTieAway)); break;
2601  case FCVTMS_ws:
2602  set_wreg(dst, FPToInt32(sreg(src), FPNegativeInfinity));
2603  break;
2604  case FCVTMS_xs:
2605  set_xreg(dst, FPToInt64(sreg(src), FPNegativeInfinity));
2606  break;
2607  case FCVTMS_wd:
2608  set_wreg(dst, FPToInt32(dreg(src), FPNegativeInfinity));
2609  break;
2610  case FCVTMS_xd:
2611  set_xreg(dst, FPToInt64(dreg(src), FPNegativeInfinity));
2612  break;
2613  case FCVTMU_ws:
2614  set_wreg(dst, FPToUInt32(sreg(src), FPNegativeInfinity));
2615  break;
2616  case FCVTMU_xs:
2617  set_xreg(dst, FPToUInt64(sreg(src), FPNegativeInfinity));
2618  break;
2619  case FCVTMU_wd:
2620  set_wreg(dst, FPToUInt32(dreg(src), FPNegativeInfinity));
2621  break;
2622  case FCVTMU_xd:
2623  set_xreg(dst, FPToUInt64(dreg(src), FPNegativeInfinity));
2624  break;
2625  case FCVTNS_ws: set_wreg(dst, FPToInt32(sreg(src), FPTieEven)); break;
2626  case FCVTNS_xs: set_xreg(dst, FPToInt64(sreg(src), FPTieEven)); break;
2627  case FCVTNS_wd: set_wreg(dst, FPToInt32(dreg(src), FPTieEven)); break;
2628  case FCVTNS_xd: set_xreg(dst, FPToInt64(dreg(src), FPTieEven)); break;
2629  case FCVTNU_ws: set_wreg(dst, FPToUInt32(sreg(src), FPTieEven)); break;
2630  case FCVTNU_xs: set_xreg(dst, FPToUInt64(sreg(src), FPTieEven)); break;
2631  case FCVTNU_wd: set_wreg(dst, FPToUInt32(dreg(src), FPTieEven)); break;
2632  case FCVTNU_xd: set_xreg(dst, FPToUInt64(dreg(src), FPTieEven)); break;
2633  case FCVTZS_ws: set_wreg(dst, FPToInt32(sreg(src), FPZero)); break;
2634  case FCVTZS_xs: set_xreg(dst, FPToInt64(sreg(src), FPZero)); break;
2635  case FCVTZS_wd: set_wreg(dst, FPToInt32(dreg(src), FPZero)); break;
2636  case FCVTZS_xd: set_xreg(dst, FPToInt64(dreg(src), FPZero)); break;
2637  case FCVTZU_ws: set_wreg(dst, FPToUInt32(sreg(src), FPZero)); break;
2638  case FCVTZU_xs: set_xreg(dst, FPToUInt64(sreg(src), FPZero)); break;
2639  case FCVTZU_wd: set_wreg(dst, FPToUInt32(dreg(src), FPZero)); break;
2640  case FCVTZU_xd: set_xreg(dst, FPToUInt64(dreg(src), FPZero)); break;
2641  case FMOV_ws: set_wreg(dst, sreg_bits(src)); break;
2642  case FMOV_xd: set_xreg(dst, dreg_bits(src)); break;
2643  case FMOV_sw: set_sreg_bits(dst, wreg(src)); break;
2644  case FMOV_dx: set_dreg_bits(dst, xreg(src)); break;
2645 
2646  // A 32-bit input can be handled in the same way as a 64-bit input, since
2647  // the sign- or zero-extension will not affect the conversion.
2648  case SCVTF_dx: set_dreg(dst, FixedToDouble(xreg(src), 0, round)); break;
2649  case SCVTF_dw: set_dreg(dst, FixedToDouble(wreg(src), 0, round)); break;
2650  case UCVTF_dx: set_dreg(dst, UFixedToDouble(xreg(src), 0, round)); break;
2651  case UCVTF_dw: {
2652  set_dreg(dst, UFixedToDouble(reg<uint32_t>(src), 0, round));
2653  break;
2654  }
2655  case SCVTF_sx: set_sreg(dst, FixedToFloat(xreg(src), 0, round)); break;
2656  case SCVTF_sw: set_sreg(dst, FixedToFloat(wreg(src), 0, round)); break;
2657  case UCVTF_sx: set_sreg(dst, UFixedToFloat(xreg(src), 0, round)); break;
2658  case UCVTF_sw: {
2659  set_sreg(dst, UFixedToFloat(reg<uint32_t>(src), 0, round));
2660  break;
2661  }
2662 
2663  default: UNREACHABLE();
2664  }
2665 }
2666 
2667 
2668 void Simulator::VisitFPFixedPointConvert(Instruction* instr) {
2669  AssertSupportedFPCR();
2670 
2671  unsigned dst = instr->Rd();
2672  unsigned src = instr->Rn();
2673  int fbits = 64 - instr->FPScale();
2674 
2675  FPRounding round = fpcr().RMode();
2676 
2677  switch (instr->Mask(FPFixedPointConvertMask)) {
2678  // A 32-bit input can be handled in the same way as a 64-bit input, since
2679  // the sign- or zero-extension will not affect the conversion.
2680  case SCVTF_dx_fixed:
2681  set_dreg(dst, FixedToDouble(xreg(src), fbits, round));
2682  break;
2683  case SCVTF_dw_fixed:
2684  set_dreg(dst, FixedToDouble(wreg(src), fbits, round));
2685  break;
2686  case UCVTF_dx_fixed:
2687  set_dreg(dst, UFixedToDouble(xreg(src), fbits, round));
2688  break;
2689  case UCVTF_dw_fixed: {
2690  set_dreg(dst,
2691  UFixedToDouble(reg<uint32_t>(src), fbits, round));
2692  break;
2693  }
2694  case SCVTF_sx_fixed:
2695  set_sreg(dst, FixedToFloat(xreg(src), fbits, round));
2696  break;
2697  case SCVTF_sw_fixed:
2698  set_sreg(dst, FixedToFloat(wreg(src), fbits, round));
2699  break;
2700  case UCVTF_sx_fixed:
2701  set_sreg(dst, UFixedToFloat(xreg(src), fbits, round));
2702  break;
2703  case UCVTF_sw_fixed: {
2704  set_sreg(dst,
2705  UFixedToFloat(reg<uint32_t>(src), fbits, round));
2706  break;
2707  }
2708  default: UNREACHABLE();
2709  }
2710 }
2711 
2712 
2713 void Simulator::VisitFPCompare(Instruction* instr) {
2714  AssertSupportedFPCR();
2715 
2716  switch (instr->Mask(FPCompareMask)) {
2717  case FCMP_s:
2718  FPCompare(sreg(instr->Rn()), sreg(instr->Rm()));
2719  break;
2720  case FCMP_d:
2721  FPCompare(dreg(instr->Rn()), dreg(instr->Rm()));
2722  break;
2723  case FCMP_s_zero:
2724  FPCompare(sreg(instr->Rn()), 0.0f);
2725  break;
2726  case FCMP_d_zero:
2727  FPCompare(dreg(instr->Rn()), 0.0);
2728  break;
2729  default: UNIMPLEMENTED();
2730  }
2731 }
2732 
2733 
2734 void Simulator::VisitFPConditionalCompare(Instruction* instr) {
2735  AssertSupportedFPCR();
2736 
2737  switch (instr->Mask(FPConditionalCompareMask)) {
2738  case FCCMP_s:
2739  if (ConditionPassed(static_cast<Condition>(instr->Condition()))) {
2740  FPCompare(sreg(instr->Rn()), sreg(instr->Rm()));
2741  } else {
2742  nzcv().SetFlags(instr->Nzcv());
2743  LogSystemRegister(NZCV);
2744  }
2745  break;
2746  case FCCMP_d: {
2747  if (ConditionPassed(static_cast<Condition>(instr->Condition()))) {
2748  FPCompare(dreg(instr->Rn()), dreg(instr->Rm()));
2749  } else {
2750  // If the condition fails, set the status flags to the nzcv immediate.
2751  nzcv().SetFlags(instr->Nzcv());
2752  LogSystemRegister(NZCV);
2753  }
2754  break;
2755  }
2756  default: UNIMPLEMENTED();
2757  }
2758 }
2759 
2760 
2761 void Simulator::VisitFPConditionalSelect(Instruction* instr) {
2762  AssertSupportedFPCR();
2763 
2764  Instr selected;
2765  if (ConditionPassed(static_cast<Condition>(instr->Condition()))) {
2766  selected = instr->Rn();
2767  } else {
2768  selected = instr->Rm();
2769  }
2770 
2771  switch (instr->Mask(FPConditionalSelectMask)) {
2772  case FCSEL_s: set_sreg(instr->Rd(), sreg(selected)); break;
2773  case FCSEL_d: set_dreg(instr->Rd(), dreg(selected)); break;
2774  default: UNIMPLEMENTED();
2775  }
2776 }
2777 
2778 
2779 void Simulator::VisitFPDataProcessing1Source(Instruction* instr) {
2780  AssertSupportedFPCR();
2781 
2782  FPRounding fpcr_rounding = static_cast<FPRounding>(fpcr().RMode());
2783  VectorFormat vform = (instr->Mask(FP64) == FP64) ? kFormatD : kFormatS;
2784  SimVRegister& rd = vreg(instr->Rd());
2785  SimVRegister& rn = vreg(instr->Rn());
2786  bool inexact_exception = false;
2787 
2788  unsigned fd = instr->Rd();
2789  unsigned fn = instr->Rn();
2790 
2791  switch (instr->Mask(FPDataProcessing1SourceMask)) {
2792  case FMOV_s:
2793  set_sreg(fd, sreg(fn));
2794  return;
2795  case FMOV_d:
2796  set_dreg(fd, dreg(fn));
2797  return;
2798  case FABS_s:
2799  case FABS_d:
2800  fabs_(vform, vreg(fd), vreg(fn));
2801  // Explicitly log the register update whilst we have type information.
2802  LogVRegister(fd, GetPrintRegisterFormatFP(vform));
2803  return;
2804  case FNEG_s:
2805  case FNEG_d:
2806  fneg(vform, vreg(fd), vreg(fn));
2807  // Explicitly log the register update whilst we have type information.
2808  LogVRegister(fd, GetPrintRegisterFormatFP(vform));
2809  return;
2810  case FCVT_ds:
2811  set_dreg(fd, FPToDouble(sreg(fn)));
2812  return;
2813  case FCVT_sd:
2814  set_sreg(fd, FPToFloat(dreg(fn), FPTieEven));
2815  return;
2816  case FCVT_hs:
2817  set_hreg(fd, FPToFloat16(sreg(fn), FPTieEven));
2818  return;
2819  case FCVT_sh:
2820  set_sreg(fd, FPToFloat(hreg(fn)));
2821  return;
2822  case FCVT_dh:
2823  set_dreg(fd, FPToDouble(FPToFloat(hreg(fn))));
2824  return;
2825  case FCVT_hd:
2826  set_hreg(fd, FPToFloat16(dreg(fn), FPTieEven));
2827  return;
2828  case FSQRT_s:
2829  case FSQRT_d:
2830  fsqrt(vform, rd, rn);
2831  // Explicitly log the register update whilst we have type information.
2832  LogVRegister(fd, GetPrintRegisterFormatFP(vform));
2833  return;
2834  case FRINTI_s:
2835  case FRINTI_d:
2836  break; // Use FPCR rounding mode.
2837  case FRINTX_s:
2838  case FRINTX_d:
2839  inexact_exception = true;
2840  break;
2841  case FRINTA_s:
2842  case FRINTA_d:
2843  fpcr_rounding = FPTieAway;
2844  break;
2845  case FRINTM_s:
2846  case FRINTM_d:
2847  fpcr_rounding = FPNegativeInfinity;
2848  break;
2849  case FRINTN_s:
2850  case FRINTN_d:
2851  fpcr_rounding = FPTieEven;
2852  break;
2853  case FRINTP_s:
2854  case FRINTP_d:
2855  fpcr_rounding = FPPositiveInfinity;
2856  break;
2857  case FRINTZ_s:
2858  case FRINTZ_d:
2859  fpcr_rounding = FPZero;
2860  break;
2861  default:
2862  UNIMPLEMENTED();
2863  }
2864 
2865  // Only FRINT* instructions fall through the switch above.
2866  frint(vform, rd, rn, fpcr_rounding, inexact_exception);
2867  // Explicitly log the register update whilst we have type information
2868  LogVRegister(fd, GetPrintRegisterFormatFP(vform));
2869 }
2870 
2871 void Simulator::VisitFPDataProcessing2Source(Instruction* instr) {
2872  AssertSupportedFPCR();
2873 
2874  VectorFormat vform = (instr->Mask(FP64) == FP64) ? kFormatD : kFormatS;
2875  SimVRegister& rd = vreg(instr->Rd());
2876  SimVRegister& rn = vreg(instr->Rn());
2877  SimVRegister& rm = vreg(instr->Rm());
2878 
2879  switch (instr->Mask(FPDataProcessing2SourceMask)) {
2880  case FADD_s:
2881  case FADD_d:
2882  fadd(vform, rd, rn, rm);
2883  break;
2884  case FSUB_s:
2885  case FSUB_d:
2886  fsub(vform, rd, rn, rm);
2887  break;
2888  case FMUL_s:
2889  case FMUL_d:
2890  fmul(vform, rd, rn, rm);
2891  break;
2892  case FNMUL_s:
2893  case FNMUL_d:
2894  fnmul(vform, rd, rn, rm);
2895  break;
2896  case FDIV_s:
2897  case FDIV_d:
2898  fdiv(vform, rd, rn, rm);
2899  break;
2900  case FMAX_s:
2901  case FMAX_d:
2902  fmax(vform, rd, rn, rm);
2903  break;
2904  case FMIN_s:
2905  case FMIN_d:
2906  fmin(vform, rd, rn, rm);
2907  break;
2908  case FMAXNM_s:
2909  case FMAXNM_d:
2910  fmaxnm(vform, rd, rn, rm);
2911  break;
2912  case FMINNM_s:
2913  case FMINNM_d:
2914  fminnm(vform, rd, rn, rm);
2915  break;
2916  default:
2917  UNREACHABLE();
2918  }
2919  // Explicitly log the register update whilst we have type information.
2920  LogVRegister(instr->Rd(), GetPrintRegisterFormatFP(vform));
2921 }
2922 
2923 void Simulator::VisitFPDataProcessing3Source(Instruction* instr) {
2924  AssertSupportedFPCR();
2925 
2926  unsigned fd = instr->Rd();
2927  unsigned fn = instr->Rn();
2928  unsigned fm = instr->Rm();
2929  unsigned fa = instr->Ra();
2930 
2931  switch (instr->Mask(FPDataProcessing3SourceMask)) {
2932  // fd = fa +/- (fn * fm)
2933  case FMADD_s:
2934  set_sreg(fd, FPMulAdd(sreg(fa), sreg(fn), sreg(fm)));
2935  break;
2936  case FMSUB_s:
2937  set_sreg(fd, FPMulAdd(sreg(fa), -sreg(fn), sreg(fm)));
2938  break;
2939  case FMADD_d:
2940  set_dreg(fd, FPMulAdd(dreg(fa), dreg(fn), dreg(fm)));
2941  break;
2942  case FMSUB_d:
2943  set_dreg(fd, FPMulAdd(dreg(fa), -dreg(fn), dreg(fm)));
2944  break;
2945  // Negated variants of the above.
2946  case FNMADD_s:
2947  set_sreg(fd, FPMulAdd(-sreg(fa), -sreg(fn), sreg(fm)));
2948  break;
2949  case FNMSUB_s:
2950  set_sreg(fd, FPMulAdd(-sreg(fa), sreg(fn), sreg(fm)));
2951  break;
2952  case FNMADD_d:
2953  set_dreg(fd, FPMulAdd(-dreg(fa), -dreg(fn), dreg(fm)));
2954  break;
2955  case FNMSUB_d:
2956  set_dreg(fd, FPMulAdd(-dreg(fa), dreg(fn), dreg(fm)));
2957  break;
2958  default:
2959  UNIMPLEMENTED();
2960  }
2961 }
2962 
2963 bool Simulator::FPProcessNaNs(Instruction* instr) {
2964  unsigned fd = instr->Rd();
2965  unsigned fn = instr->Rn();
2966  unsigned fm = instr->Rm();
2967  bool done = false;
2968 
2969  if (instr->Mask(FP64) == FP64) {
2970  double result = FPProcessNaNs(dreg(fn), dreg(fm));
2971  if (std::isnan(result)) {
2972  set_dreg(fd, result);
2973  done = true;
2974  }
2975  } else {
2976  float result = FPProcessNaNs(sreg(fn), sreg(fm));
2977  if (std::isnan(result)) {
2978  set_sreg(fd, result);
2979  done = true;
2980  }
2981  }
2982 
2983  return done;
2984 }
2985 
2986 
2987 void Simulator::VisitSystem(Instruction* instr) {
2988  // Some system instructions hijack their Op and Cp fields to represent a
2989  // range of immediates instead of indicating a different instruction. This
2990  // makes the decoding tricky.
2991  if (instr->Mask(SystemSysRegFMask) == SystemSysRegFixed) {
2992  switch (instr->Mask(SystemSysRegMask)) {
2993  case MRS: {
2994  switch (instr->ImmSystemRegister()) {
2995  case NZCV: set_xreg(instr->Rt(), nzcv().RawValue()); break;
2996  case FPCR: set_xreg(instr->Rt(), fpcr().RawValue()); break;
2997  default: UNIMPLEMENTED();
2998  }
2999  break;
3000  }
3001  case MSR: {
3002  switch (instr->ImmSystemRegister()) {
3003  case NZCV:
3004  nzcv().SetRawValue(wreg(instr->Rt()));
3005  LogSystemRegister(NZCV);
3006  break;
3007  case FPCR:
3008  fpcr().SetRawValue(wreg(instr->Rt()));
3009  LogSystemRegister(FPCR);
3010  break;
3011  default: UNIMPLEMENTED();
3012  }
3013  break;
3014  }
3015  }
3016  } else if (instr->Mask(SystemHintFMask) == SystemHintFixed) {
3017  DCHECK(instr->Mask(SystemHintMask) == HINT);
3018  switch (instr->ImmHint()) {
3019  case NOP:
3020  case CSDB:
3021  break;
3022  default: UNIMPLEMENTED();
3023  }
3024  } else if (instr->Mask(MemBarrierFMask) == MemBarrierFixed) {
3025 #if defined(V8_OS_WIN)
3026  MemoryBarrier();
3027 #else
3028  __sync_synchronize();
3029 #endif
3030  } else {
3031  UNIMPLEMENTED();
3032  }
3033 }
3034 
3035 
3036 bool Simulator::GetValue(const char* desc, int64_t* value) {
3037  int regnum = CodeFromName(desc);
3038  if (regnum >= 0) {
3039  unsigned code = regnum;
3040  if (code == kZeroRegCode) {
3041  // Catch the zero register and return 0.
3042  *value = 0;
3043  return true;
3044  } else if (code == kSPRegInternalCode) {
3045  // Translate the stack pointer code to 31, for Reg31IsStackPointer.
3046  code = 31;
3047  }
3048  if (desc[0] == 'w') {
3049  *value = wreg(code, Reg31IsStackPointer);
3050  } else {
3051  *value = xreg(code, Reg31IsStackPointer);
3052  }
3053  return true;
3054  } else if (strncmp(desc, "0x", 2) == 0) {
3055  return SScanF(desc + 2, "%" SCNx64,
3056  reinterpret_cast<uint64_t*>(value)) == 1;
3057  } else {
3058  return SScanF(desc, "%" SCNu64,
3059  reinterpret_cast<uint64_t*>(value)) == 1;
3060  }
3061 }
3062 
3063 
3064 bool Simulator::PrintValue(const char* desc) {
3065  if (strcmp(desc, "sp") == 0) {
3066  DCHECK(CodeFromName(desc) == static_cast<int>(kSPRegInternalCode));
3067  PrintF(stream_, "%s sp:%s 0x%016" PRIx64 "%s\n", clr_reg_name,
3068  clr_reg_value, xreg(31, Reg31IsStackPointer), clr_normal);
3069  return true;
3070  } else if (strcmp(desc, "wsp") == 0) {
3071  DCHECK(CodeFromName(desc) == static_cast<int>(kSPRegInternalCode));
3072  PrintF(stream_, "%s wsp:%s 0x%08" PRIx32 "%s\n", clr_reg_name,
3073  clr_reg_value, wreg(31, Reg31IsStackPointer), clr_normal);
3074  return true;
3075  }
3076 
3077  int i = CodeFromName(desc);
3078  static_assert(kNumberOfRegisters == kNumberOfVRegisters,
3079  "Must be same number of Registers as VRegisters.");
3080  if (i < 0 || static_cast<unsigned>(i) >= kNumberOfVRegisters) return false;
3081 
3082  if (desc[0] == 'v') {
3083  PrintF(stream_, "%s %s:%s 0x%016" PRIx64 "%s (%s%s:%s %g%s %s:%s %g%s)\n",
3084  clr_vreg_name, VRegNameForCode(i), clr_vreg_value,
3085  bit_cast<uint64_t>(dreg(i)), clr_normal, clr_vreg_name,
3086  DRegNameForCode(i), clr_vreg_value, dreg(i), clr_vreg_name,
3087  SRegNameForCode(i), clr_vreg_value, sreg(i), clr_normal);
3088  return true;
3089  } else if (desc[0] == 'd') {
3090  PrintF(stream_, "%s %s:%s %g%s\n", clr_vreg_name, DRegNameForCode(i),
3091  clr_vreg_value, dreg(i), clr_normal);
3092  return true;
3093  } else if (desc[0] == 's') {
3094  PrintF(stream_, "%s %s:%s %g%s\n", clr_vreg_name, SRegNameForCode(i),
3095  clr_vreg_value, sreg(i), clr_normal);
3096  return true;
3097  } else if (desc[0] == 'w') {
3098  PrintF(stream_, "%s %s:%s 0x%08" PRIx32 "%s\n",
3099  clr_reg_name, WRegNameForCode(i), clr_reg_value, wreg(i), clr_normal);
3100  return true;
3101  } else {
3102  // X register names have a wide variety of starting characters, but anything
3103  // else will be an X register.
3104  PrintF(stream_, "%s %s:%s 0x%016" PRIx64 "%s\n",
3105  clr_reg_name, XRegNameForCode(i), clr_reg_value, xreg(i), clr_normal);
3106  return true;
3107  }
3108 }
3109 
3110 
3111 void Simulator::Debug() {
3112 #define COMMAND_SIZE 63
3113 #define ARG_SIZE 255
3114 
3115 #define STR(a) #a
3116 #define XSTR(a) STR(a)
3117 
3118  char cmd[COMMAND_SIZE + 1];
3119  char arg1[ARG_SIZE + 1];
3120  char arg2[ARG_SIZE + 1];
3121  char* argv[3] = { cmd, arg1, arg2 };
3122 
3123  // Make sure to have a proper terminating character if reaching the limit.
3124  cmd[COMMAND_SIZE] = 0;
3125  arg1[ARG_SIZE] = 0;
3126  arg2[ARG_SIZE] = 0;
3127 
3128  bool done = false;
3129  bool cleared_log_disasm_bit = false;
3130 
3131  while (!done) {
3132  // Disassemble the next instruction to execute before doing anything else.
3133  PrintInstructionsAt(pc_, 1);
3134  // Read the command line.
3135  char* line = ReadLine("sim> ");
3136  if (line == nullptr) {
3137  break;
3138  } else {
3139  // Repeat last command by default.
3140  char* last_input = last_debugger_input();
3141  if (strcmp(line, "\n") == 0 && (last_input != nullptr)) {
3142  DeleteArray(line);
3143  line = last_input;
3144  } else {
3145  // Update the latest command ran
3146  set_last_debugger_input(line);
3147  }
3148 
3149  // Use sscanf to parse the individual parts of the command line. At the
3150  // moment no command expects more than two parameters.
3151  int argc = SScanF(line,
3152  "%" XSTR(COMMAND_SIZE) "s "
3153  "%" XSTR(ARG_SIZE) "s "
3154  "%" XSTR(ARG_SIZE) "s",
3155  cmd, arg1, arg2);
3156 
3157  // stepi / si ------------------------------------------------------------
3158  if ((strcmp(cmd, "si") == 0) || (strcmp(cmd, "stepi") == 0)) {
3159  // We are about to execute instructions, after which by default we
3160  // should increment the pc_. If it was set when reaching this debug
3161  // instruction, it has not been cleared because this instruction has not
3162  // completed yet. So clear it manually.
3163  pc_modified_ = false;
3164 
3165  if (argc == 1) {
3166  ExecuteInstruction();
3167  } else {
3168  int64_t number_of_instructions_to_execute = 1;
3169  GetValue(arg1, &number_of_instructions_to_execute);
3170 
3171  set_log_parameters(log_parameters() | LOG_DISASM);
3172  while (number_of_instructions_to_execute-- > 0) {
3173  ExecuteInstruction();
3174  }
3175  set_log_parameters(log_parameters() & ~LOG_DISASM);
3176  PrintF("\n");
3177  }
3178 
3179  // If it was necessary, the pc has already been updated or incremented
3180  // when executing the instruction. So we do not want it to be updated
3181  // again. It will be cleared when exiting.
3182  pc_modified_ = true;
3183 
3184  // next / n --------------------------------------------------------------
3185  } else if ((strcmp(cmd, "next") == 0) || (strcmp(cmd, "n") == 0)) {
3186  // Tell the simulator to break after the next executed BL.
3187  break_on_next_ = true;
3188  // Continue.
3189  done = true;
3190 
3191  // continue / cont / c ---------------------------------------------------
3192  } else if ((strcmp(cmd, "continue") == 0) ||
3193  (strcmp(cmd, "cont") == 0) ||
3194  (strcmp(cmd, "c") == 0)) {
3195  // Leave the debugger shell.
3196  done = true;
3197 
3198  // disassemble / disasm / di ---------------------------------------------
3199  } else if (strcmp(cmd, "disassemble") == 0 ||
3200  strcmp(cmd, "disasm") == 0 ||
3201  strcmp(cmd, "di") == 0) {
3202  int64_t n_of_instrs_to_disasm = 10; // default value.
3203  int64_t address = reinterpret_cast<int64_t>(pc_); // default value.
3204  if (argc >= 2) { // disasm <n of instrs>
3205  GetValue(arg1, &n_of_instrs_to_disasm);
3206  }
3207  if (argc >= 3) { // disasm <n of instrs> <address>
3208  GetValue(arg2, &address);
3209  }
3210 
3211  // Disassemble.
3212  PrintInstructionsAt(reinterpret_cast<Instruction*>(address),
3213  n_of_instrs_to_disasm);
3214  PrintF("\n");
3215 
3216  // print / p -------------------------------------------------------------
3217  } else if ((strcmp(cmd, "print") == 0) || (strcmp(cmd, "p") == 0)) {
3218  if (argc == 2) {
3219  if (strcmp(arg1, "all") == 0) {
3220  PrintRegisters();
3221  PrintVRegisters();
3222  } else {
3223  if (!PrintValue(arg1)) {
3224  PrintF("%s unrecognized\n", arg1);
3225  }
3226  }
3227  } else {
3228  PrintF(
3229  "print <register>\n"
3230  " Print the content of a register. (alias 'p')\n"
3231  " 'print all' will print all registers.\n"
3232  " Use 'printobject' to get more details about the value.\n");
3233  }
3234 
3235  // printobject / po ------------------------------------------------------
3236  } else if ((strcmp(cmd, "printobject") == 0) ||
3237  (strcmp(cmd, "po") == 0)) {
3238  if (argc == 2) {
3239  int64_t value;
3240  StdoutStream os;
3241  if (GetValue(arg1, &value)) {
3242  Object* obj = reinterpret_cast<Object*>(value);
3243  os << arg1 << ": \n";
3244 #ifdef DEBUG
3245  obj->Print(os);
3246  os << "\n";
3247 #else
3248  os << Brief(obj) << "\n";
3249 #endif
3250  } else {
3251  os << arg1 << " unrecognized\n";
3252  }
3253  } else {
3254  PrintF("printobject <value>\n"
3255  "printobject <register>\n"
3256  " Print details about the value. (alias 'po')\n");
3257  }
3258 
3259  // stack / mem ----------------------------------------------------------
3260  } else if (strcmp(cmd, "stack") == 0 || strcmp(cmd, "mem") == 0) {
3261  int64_t* cur = nullptr;
3262  int64_t* end = nullptr;
3263  int next_arg = 1;
3264 
3265  if (strcmp(cmd, "stack") == 0) {
3266  cur = reinterpret_cast<int64_t*>(sp());
3267 
3268  } else { // "mem"
3269  int64_t value;
3270  if (!GetValue(arg1, &value)) {
3271  PrintF("%s unrecognized\n", arg1);
3272  continue;
3273  }
3274  cur = reinterpret_cast<int64_t*>(value);
3275  next_arg++;
3276  }
3277 
3278  int64_t words = 0;
3279  if (argc == next_arg) {
3280  words = 10;
3281  } else if (argc == next_arg + 1) {
3282  if (!GetValue(argv[next_arg], &words)) {
3283  PrintF("%s unrecognized\n", argv[next_arg]);
3284  PrintF("Printing 10 double words by default");
3285  words = 10;
3286  }
3287  } else {
3288  UNREACHABLE();
3289  }
3290  end = cur + words;
3291 
3292  while (cur < end) {
3293  PrintF(" 0x%016" PRIx64 ": 0x%016" PRIx64 " %10" PRId64,
3294  reinterpret_cast<uint64_t>(cur), *cur, *cur);
3295  HeapObject* obj = reinterpret_cast<HeapObject*>(*cur);
3296  int64_t value = *cur;
3297  Heap* current_heap = isolate_->heap();
3298  if (((value & 1) == 0) || current_heap->Contains(obj)) {
3299  PrintF(" (");
3300  if ((value & kSmiTagMask) == 0) {
3301  DCHECK(SmiValuesAre32Bits() || SmiValuesAre31Bits());
3302  int32_t untagged = (value >> kSmiShift) & 0xFFFFFFFF;
3303  PrintF("smi %" PRId32, untagged);
3304  } else {
3305  obj->ShortPrint();
3306  }
3307  PrintF(")");
3308  }
3309  PrintF("\n");
3310  cur++;
3311  }
3312 
3313  // trace / t -------------------------------------------------------------
3314  } else if (strcmp(cmd, "trace") == 0 || strcmp(cmd, "t") == 0) {
3315  if ((log_parameters() & (LOG_DISASM | LOG_REGS)) !=
3316  (LOG_DISASM | LOG_REGS)) {
3317  PrintF("Enabling disassembly and registers tracing\n");
3318  set_log_parameters(log_parameters() | LOG_DISASM | LOG_REGS);
3319  } else {
3320  PrintF("Disabling disassembly and registers tracing\n");
3321  set_log_parameters(log_parameters() & ~(LOG_DISASM | LOG_REGS));
3322  }
3323 
3324  // break / b -------------------------------------------------------------
3325  } else if (strcmp(cmd, "break") == 0 || strcmp(cmd, "b") == 0) {
3326  if (argc == 2) {
3327  int64_t value;
3328  if (GetValue(arg1, &value)) {
3329  SetBreakpoint(reinterpret_cast<Instruction*>(value));
3330  } else {
3331  PrintF("%s unrecognized\n", arg1);
3332  }
3333  } else {
3334  ListBreakpoints();
3335  PrintF("Use `break <address>` to set or disable a breakpoint\n");
3336  }
3337 
3338  // gdb -------------------------------------------------------------------
3339  } else if (strcmp(cmd, "gdb") == 0) {
3340  PrintF("Relinquishing control to gdb.\n");
3341  base::OS::DebugBreak();
3342  PrintF("Regaining control from gdb.\n");
3343 
3344  // sysregs ---------------------------------------------------------------
3345  } else if (strcmp(cmd, "sysregs") == 0) {
3346  PrintSystemRegisters();
3347 
3348  // help / h --------------------------------------------------------------
3349  } else if (strcmp(cmd, "help") == 0 || strcmp(cmd, "h") == 0) {
3350  PrintF(
3351  "stepi / si\n"
3352  " stepi <n>\n"
3353  " Step <n> instructions.\n"
3354  "next / n\n"
3355  " Continue execution until a BL instruction is reached.\n"
3356  " At this point a breakpoint is set just after this BL.\n"
3357  " Then execution is resumed. It will probably later hit the\n"
3358  " breakpoint just set.\n"
3359  "continue / cont / c\n"
3360  " Continue execution from here.\n"
3361  "disassemble / disasm / di\n"
3362  " disassemble <n> <address>\n"
3363  " Disassemble <n> instructions from current <address>.\n"
3364  " By default <n> is 20 and <address> is the current pc.\n"
3365  "print / p\n"
3366  " print <register>\n"
3367  " Print the content of a register.\n"
3368  " 'print all' will print all registers.\n"
3369  " Use 'printobject' to get more details about the value.\n"
3370  "printobject / po\n"
3371  " printobject <value>\n"
3372  " printobject <register>\n"
3373  " Print details about the value.\n"
3374  "stack\n"
3375  " stack [<words>]\n"
3376  " Dump stack content, default dump 10 words\n"
3377  "mem\n"
3378  " mem <address> [<words>]\n"
3379  " Dump memory content, default dump 10 words\n"
3380  "trace / t\n"
3381  " Toggle disassembly and register tracing\n"
3382  "break / b\n"
3383  " break : list all breakpoints\n"
3384  " break <address> : set / enable / disable a breakpoint.\n"
3385  "gdb\n"
3386  " Enter gdb.\n"
3387  "sysregs\n"
3388  " Print all system registers (including NZCV).\n");
3389  } else {
3390  PrintF("Unknown command: %s\n", cmd);
3391  PrintF("Use 'help' for more information.\n");
3392  }
3393  }
3394  if (cleared_log_disasm_bit == true) {
3395  set_log_parameters(log_parameters_ | LOG_DISASM);
3396  }
3397  }
3398 }
3399 
3400 
3401 void Simulator::VisitException(Instruction* instr) {
3402  switch (instr->Mask(ExceptionMask)) {
3403  case HLT: {
3404  if (instr->ImmException() == kImmExceptionIsDebug) {
3405  // Read the arguments encoded inline in the instruction stream.
3406  uint32_t code;
3407  uint32_t parameters;
3408 
3409  memcpy(&code,
3410  pc_->InstructionAtOffset(kDebugCodeOffset),
3411  sizeof(code));
3412  memcpy(&parameters,
3413  pc_->InstructionAtOffset(kDebugParamsOffset),
3414  sizeof(parameters));
3415  char const *message =
3416  reinterpret_cast<char const*>(
3417  pc_->InstructionAtOffset(kDebugMessageOffset));
3418 
3419  // Always print something when we hit a debug point that breaks.
3420  // We are going to break, so printing something is not an issue in
3421  // terms of speed.
3422  if (FLAG_trace_sim_messages || FLAG_trace_sim || (parameters & BREAK)) {
3423  if (message != nullptr) {
3424  PrintF(stream_,
3425  "# %sDebugger hit %d: %s%s%s\n",
3426  clr_debug_number,
3427  code,
3428  clr_debug_message,
3429  message,
3430  clr_normal);
3431  } else {
3432  PrintF(stream_,
3433  "# %sDebugger hit %d.%s\n",
3434  clr_debug_number,
3435  code,
3436  clr_normal);
3437  }
3438  }
3439 
3440  // Other options.
3441  switch (parameters & kDebuggerTracingDirectivesMask) {
3442  case TRACE_ENABLE:
3443  set_log_parameters(log_parameters() | parameters);
3444  if (parameters & LOG_SYS_REGS) { PrintSystemRegisters(); }
3445  if (parameters & LOG_REGS) { PrintRegisters(); }
3446  if (parameters & LOG_VREGS) {
3447  PrintVRegisters();
3448  }
3449  break;
3450  case TRACE_DISABLE:
3451  set_log_parameters(log_parameters() & ~parameters);
3452  break;
3453  case TRACE_OVERRIDE:
3454  set_log_parameters(parameters);
3455  break;
3456  default:
3457  // We don't support a one-shot LOG_DISASM.
3458  DCHECK_EQ(parameters & LOG_DISASM, 0);
3459  // Don't print information that is already being traced.
3460  parameters &= ~log_parameters();
3461  // Print the requested information.
3462  if (parameters & LOG_SYS_REGS) PrintSystemRegisters();
3463  if (parameters & LOG_REGS) PrintRegisters();
3464  if (parameters & LOG_VREGS) PrintVRegisters();
3465  }
3466 
3467  // The stop parameters are inlined in the code. Skip them:
3468  // - Skip to the end of the message string.
3469  size_t size = kDebugMessageOffset + strlen(message) + 1;
3470  pc_ = pc_->InstructionAtOffset(RoundUp(size, kInstrSize));
3471  // - Verify that the unreachable marker is present.
3472  DCHECK(pc_->Mask(ExceptionMask) == HLT);
3473  DCHECK_EQ(pc_->ImmException(), kImmExceptionIsUnreachable);
3474  // - Skip past the unreachable marker.
3475  set_pc(pc_->following());
3476 
3477  // Check if the debugger should break.
3478  if (parameters & BREAK) Debug();
3479 
3480  } else if (instr->ImmException() == kImmExceptionIsRedirectedCall) {
3481  DoRuntimeCall(instr);
3482  } else if (instr->ImmException() == kImmExceptionIsPrintf) {
3483  DoPrintf(instr);
3484 
3485  } else if (instr->ImmException() == kImmExceptionIsUnreachable) {
3486  fprintf(stream_, "Hit UNREACHABLE marker at PC=%p.\n",
3487  reinterpret_cast<void*>(pc_));
3488  abort();
3489 
3490  } else {
3491  base::OS::DebugBreak();
3492  }
3493  break;
3494  }
3495  case BRK:
3496  base::OS::DebugBreak();
3497  break;
3498  default:
3499  UNIMPLEMENTED();
3500  }
3501 }
3502 
3503 void Simulator::VisitNEON2RegMisc(Instruction* instr) {
3504  NEONFormatDecoder nfd(instr);
3505  VectorFormat vf = nfd.GetVectorFormat();
3506 
3507  // Format mapping for "long pair" instructions, [su]addlp, [su]adalp.
3508  static const NEONFormatMap map_lp = {
3509  {23, 22, 30}, {NF_4H, NF_8H, NF_2S, NF_4S, NF_1D, NF_2D}};
3510  VectorFormat vf_lp = nfd.GetVectorFormat(&map_lp);
3511 
3512  static const NEONFormatMap map_fcvtl = {{22}, {NF_4S, NF_2D}};
3513  VectorFormat vf_fcvtl = nfd.GetVectorFormat(&map_fcvtl);
3514 
3515  static const NEONFormatMap map_fcvtn = {{22, 30},
3516  {NF_4H, NF_8H, NF_2S, NF_4S}};
3517  VectorFormat vf_fcvtn = nfd.GetVectorFormat(&map_fcvtn);
3518 
3519  SimVRegister& rd = vreg(instr->Rd());
3520  SimVRegister& rn = vreg(instr->Rn());
3521 
3522  if (instr->Mask(NEON2RegMiscOpcode) <= NEON_NEG_opcode) {
3523  // These instructions all use a two bit size field, except NOT and RBIT,
3524  // which use the field to encode the operation.
3525  switch (instr->Mask(NEON2RegMiscMask)) {
3526  case NEON_REV64:
3527  rev64(vf, rd, rn);
3528  break;
3529  case NEON_REV32:
3530  rev32(vf, rd, rn);
3531  break;
3532  case NEON_REV16:
3533  rev16(vf, rd, rn);
3534  break;
3535  case NEON_SUQADD:
3536  suqadd(vf, rd, rn);
3537  break;
3538  case NEON_USQADD:
3539  usqadd(vf, rd, rn);
3540  break;
3541  case NEON_CLS:
3542  cls(vf, rd, rn);
3543  break;
3544  case NEON_CLZ:
3545  clz(vf, rd, rn);
3546  break;
3547  case NEON_CNT:
3548  cnt(vf, rd, rn);
3549  break;
3550  case NEON_SQABS:
3551  abs(vf, rd, rn).SignedSaturate(vf);
3552  break;
3553  case NEON_SQNEG:
3554  neg(vf, rd, rn).SignedSaturate(vf);
3555  break;
3556  case NEON_CMGT_zero:
3557  cmp(vf, rd, rn, 0, gt);
3558  break;
3559  case NEON_CMGE_zero:
3560  cmp(vf, rd, rn, 0, ge);
3561  break;
3562  case NEON_CMEQ_zero:
3563  cmp(vf, rd, rn, 0, eq);
3564  break;
3565  case NEON_CMLE_zero:
3566  cmp(vf, rd, rn, 0, le);
3567  break;
3568  case NEON_CMLT_zero:
3569  cmp(vf, rd, rn, 0, lt);
3570  break;
3571  case NEON_ABS:
3572  abs(vf, rd, rn);
3573  break;
3574  case NEON_NEG:
3575  neg(vf, rd, rn);
3576  break;
3577  case NEON_SADDLP:
3578  saddlp(vf_lp, rd, rn);
3579  break;
3580  case NEON_UADDLP:
3581  uaddlp(vf_lp, rd, rn);
3582  break;
3583  case NEON_SADALP:
3584  sadalp(vf_lp, rd, rn);
3585  break;
3586  case NEON_UADALP:
3587  uadalp(vf_lp, rd, rn);
3588  break;
3589  case NEON_RBIT_NOT:
3590  vf = nfd.GetVectorFormat(nfd.LogicalFormatMap());
3591  switch (instr->FPType()) {
3592  case 0:
3593  not_(vf, rd, rn);
3594  break;
3595  case 1:
3596  rbit(vf, rd, rn);
3597  break;
3598  default:
3599  UNIMPLEMENTED();
3600  }
3601  break;
3602  }
3603  } else {
3604  VectorFormat fpf = nfd.GetVectorFormat(nfd.FPFormatMap());
3605  FPRounding fpcr_rounding = static_cast<FPRounding>(fpcr().RMode());
3606  bool inexact_exception = false;
3607 
3608  // These instructions all use a one bit size field, except XTN, SQXTUN,
3609  // SHLL, SQXTN and UQXTN, which use a two bit size field.
3610  switch (instr->Mask(NEON2RegMiscFPMask)) {
3611  case NEON_FABS:
3612  fabs_(fpf, rd, rn);
3613  return;
3614  case NEON_FNEG:
3615  fneg(fpf, rd, rn);
3616  return;
3617  case NEON_FSQRT:
3618  fsqrt(fpf, rd, rn);
3619  return;
3620  case NEON_FCVTL:
3621  if (instr->Mask(NEON_Q)) {
3622  fcvtl2(vf_fcvtl, rd, rn);
3623  } else {
3624  fcvtl(vf_fcvtl, rd, rn);
3625  }
3626  return;
3627  case NEON_FCVTN:
3628  if (instr->Mask(NEON_Q)) {
3629  fcvtn2(vf_fcvtn, rd, rn);
3630  } else {
3631  fcvtn(vf_fcvtn, rd, rn);
3632  }
3633  return;
3634  case NEON_FCVTXN:
3635  if (instr->Mask(NEON_Q)) {
3636  fcvtxn2(vf_fcvtn, rd, rn);
3637  } else {
3638  fcvtxn(vf_fcvtn, rd, rn);
3639  }
3640  return;
3641 
3642  // The following instructions break from the switch statement, rather
3643  // than return.
3644  case NEON_FRINTI:
3645  break; // Use FPCR rounding mode.
3646  case NEON_FRINTX:
3647  inexact_exception = true;
3648  break;
3649  case NEON_FRINTA:
3650  fpcr_rounding = FPTieAway;
3651  break;
3652  case NEON_FRINTM:
3653  fpcr_rounding = FPNegativeInfinity;
3654  break;
3655  case NEON_FRINTN:
3656  fpcr_rounding = FPTieEven;
3657  break;
3658  case NEON_FRINTP:
3659  fpcr_rounding = FPPositiveInfinity;
3660  break;
3661  case NEON_FRINTZ:
3662  fpcr_rounding = FPZero;
3663  break;
3664 
3665  // The remaining cases return to the caller.
3666  case NEON_FCVTNS:
3667  fcvts(fpf, rd, rn, FPTieEven);
3668  return;
3669  case NEON_FCVTNU:
3670  fcvtu(fpf, rd, rn, FPTieEven);
3671  return;
3672  case NEON_FCVTPS:
3673  fcvts(fpf, rd, rn, FPPositiveInfinity);
3674  return;
3675  case NEON_FCVTPU:
3676  fcvtu(fpf, rd, rn, FPPositiveInfinity);
3677  return;
3678  case NEON_FCVTMS:
3679  fcvts(fpf, rd, rn, FPNegativeInfinity);
3680  return;
3681  case NEON_FCVTMU:
3682  fcvtu(fpf, rd, rn, FPNegativeInfinity);
3683  return;
3684  case NEON_FCVTZS:
3685  fcvts(fpf, rd, rn, FPZero);
3686  return;
3687  case NEON_FCVTZU:
3688  fcvtu(fpf, rd, rn, FPZero);
3689  return;
3690  case NEON_FCVTAS:
3691  fcvts(fpf, rd, rn, FPTieAway);
3692  return;
3693  case NEON_FCVTAU:
3694  fcvtu(fpf, rd, rn, FPTieAway);
3695  return;
3696  case NEON_SCVTF:
3697  scvtf(fpf, rd, rn, 0, fpcr_rounding);
3698  return;
3699  case NEON_UCVTF:
3700  ucvtf(fpf, rd, rn, 0, fpcr_rounding);
3701  return;
3702  case NEON_URSQRTE:
3703  ursqrte(fpf, rd, rn);
3704  return;
3705  case NEON_URECPE:
3706  urecpe(fpf, rd, rn);
3707  return;
3708  case NEON_FRSQRTE:
3709  frsqrte(fpf, rd, rn);
3710  return;
3711  case NEON_FRECPE:
3712  frecpe(fpf, rd, rn, fpcr_rounding);
3713  return;
3714  case NEON_FCMGT_zero:
3715  fcmp_zero(fpf, rd, rn, gt);
3716  return;
3717  case NEON_FCMGE_zero:
3718  fcmp_zero(fpf, rd, rn, ge);
3719  return;
3720  case NEON_FCMEQ_zero:
3721  fcmp_zero(fpf, rd, rn, eq);
3722  return;
3723  case NEON_FCMLE_zero:
3724  fcmp_zero(fpf, rd, rn, le);
3725  return;
3726  case NEON_FCMLT_zero:
3727  fcmp_zero(fpf, rd, rn, lt);
3728  return;
3729  default:
3730  if ((NEON_XTN_opcode <= instr->Mask(NEON2RegMiscOpcode)) &&
3731  (instr->Mask(NEON2RegMiscOpcode) <= NEON_UQXTN_opcode)) {
3732  switch (instr->Mask(NEON2RegMiscMask)) {
3733  case NEON_XTN:
3734  xtn(vf, rd, rn);
3735  return;
3736  case NEON_SQXTN:
3737  sqxtn(vf, rd, rn);
3738  return;
3739  case NEON_UQXTN:
3740  uqxtn(vf, rd, rn);
3741  return;
3742  case NEON_SQXTUN:
3743  sqxtun(vf, rd, rn);
3744  return;
3745  case NEON_SHLL:
3746  vf = nfd.GetVectorFormat(nfd.LongIntegerFormatMap());
3747  if (instr->Mask(NEON_Q)) {
3748  shll2(vf, rd, rn);
3749  } else {
3750  shll(vf, rd, rn);
3751  }
3752  return;
3753  default:
3754  UNIMPLEMENTED();
3755  }
3756  } else {
3757  UNIMPLEMENTED();
3758  }
3759  }
3760 
3761  // Only FRINT* instructions fall through the switch above.
3762  frint(fpf, rd, rn, fpcr_rounding, inexact_exception);
3763  }
3764 }
3765 
3766 void Simulator::VisitNEON3Same(Instruction* instr) {
3767  NEONFormatDecoder nfd(instr);
3768  SimVRegister& rd = vreg(instr->Rd());
3769  SimVRegister& rn = vreg(instr->Rn());
3770  SimVRegister& rm = vreg(instr->Rm());
3771 
3772  if (instr->Mask(NEON3SameLogicalFMask) == NEON3SameLogicalFixed) {
3773  VectorFormat vf = nfd.GetVectorFormat(nfd.LogicalFormatMap());
3774  switch (instr->Mask(NEON3SameLogicalMask)) {
3775  case NEON_AND:
3776  and_(vf, rd, rn, rm);
3777  break;
3778  case NEON_ORR:
3779  orr(vf, rd, rn, rm);
3780  break;
3781  case NEON_ORN:
3782  orn(vf, rd, rn, rm);
3783  break;
3784  case NEON_EOR:
3785  eor(vf, rd, rn, rm);
3786  break;
3787  case NEON_BIC:
3788  bic(vf, rd, rn, rm);
3789  break;
3790  case NEON_BIF:
3791  bif(vf, rd, rn, rm);
3792  break;
3793  case NEON_BIT:
3794  bit(vf, rd, rn, rm);
3795  break;
3796  case NEON_BSL:
3797  bsl(vf, rd, rn, rm);
3798  break;
3799  default:
3800  UNIMPLEMENTED();
3801  }
3802  } else if (instr->Mask(NEON3SameFPFMask) == NEON3SameFPFixed) {
3803  VectorFormat vf = nfd.GetVectorFormat(nfd.FPFormatMap());
3804  switch (instr->Mask(NEON3SameFPMask)) {
3805  case NEON_FADD:
3806  fadd(vf, rd, rn, rm);
3807  break;
3808  case NEON_FSUB:
3809  fsub(vf, rd, rn, rm);
3810  break;
3811  case NEON_FMUL:
3812  fmul(vf, rd, rn, rm);
3813  break;
3814  case NEON_FDIV:
3815  fdiv(vf, rd, rn, rm);
3816  break;
3817  case NEON_FMAX:
3818  fmax(vf, rd, rn, rm);
3819  break;
3820  case NEON_FMIN:
3821  fmin(vf, rd, rn, rm);
3822  break;
3823  case NEON_FMAXNM:
3824  fmaxnm(vf, rd, rn, rm);
3825  break;
3826  case NEON_FMINNM:
3827  fminnm(vf, rd, rn, rm);
3828  break;
3829  case NEON_FMLA:
3830  fmla(vf, rd, rn, rm);
3831  break;
3832  case NEON_FMLS:
3833  fmls(vf, rd, rn, rm);
3834  break;
3835  case NEON_FMULX:
3836  fmulx(vf, rd, rn, rm);
3837  break;
3838  case NEON_FACGE:
3839  fabscmp(vf, rd, rn, rm, ge);
3840  break;
3841  case NEON_FACGT:
3842  fabscmp(vf, rd, rn, rm, gt);
3843  break;
3844  case NEON_FCMEQ:
3845  fcmp(vf, rd, rn, rm, eq);
3846  break;
3847  case NEON_FCMGE:
3848  fcmp(vf, rd, rn, rm, ge);
3849  break;
3850  case NEON_FCMGT:
3851  fcmp(vf, rd, rn, rm, gt);
3852  break;
3853  case NEON_FRECPS:
3854  frecps(vf, rd, rn, rm);
3855  break;
3856  case NEON_FRSQRTS:
3857  frsqrts(vf, rd, rn, rm);
3858  break;
3859  case NEON_FABD:
3860  fabd(vf, rd, rn, rm);
3861  break;
3862  case NEON_FADDP:
3863  faddp(vf, rd, rn, rm);
3864  break;
3865  case NEON_FMAXP:
3866  fmaxp(vf, rd, rn, rm);
3867  break;
3868  case NEON_FMAXNMP:
3869  fmaxnmp(vf, rd, rn, rm);
3870  break;
3871  case NEON_FMINP:
3872  fminp(vf, rd, rn, rm);
3873  break;
3874  case NEON_FMINNMP:
3875  fminnmp(vf, rd, rn, rm);
3876  break;
3877  default:
3878  UNIMPLEMENTED();
3879  }
3880  } else {
3881  VectorFormat vf = nfd.GetVectorFormat();
3882  switch (instr->Mask(NEON3SameMask)) {
3883  case NEON_ADD:
3884  add(vf, rd, rn, rm);
3885  break;
3886  case NEON_ADDP:
3887  addp(vf, rd, rn, rm);
3888  break;
3889  case NEON_CMEQ:
3890  cmp(vf, rd, rn, rm, eq);
3891  break;
3892  case NEON_CMGE:
3893  cmp(vf, rd, rn, rm, ge);
3894  break;
3895  case NEON_CMGT:
3896  cmp(vf, rd, rn, rm, gt);
3897  break;
3898  case NEON_CMHI:
3899  cmp(vf, rd, rn, rm, hi);
3900  break;
3901  case NEON_CMHS:
3902  cmp(vf, rd, rn, rm, hs);
3903  break;
3904  case NEON_CMTST:
3905  cmptst(vf, rd, rn, rm);
3906  break;
3907  case NEON_MLS:
3908  mls(vf, rd, rn, rm);
3909  break;
3910  case NEON_MLA:
3911  mla(vf, rd, rn, rm);
3912  break;
3913  case NEON_MUL:
3914  mul(vf, rd, rn, rm);
3915  break;
3916  case NEON_PMUL:
3917  pmul(vf, rd, rn, rm);
3918  break;
3919  case NEON_SMAX:
3920  smax(vf, rd, rn, rm);
3921  break;
3922  case NEON_SMAXP:
3923  smaxp(vf, rd, rn, rm);
3924  break;
3925  case NEON_SMIN:
3926  smin(vf, rd, rn, rm);
3927  break;
3928  case NEON_SMINP:
3929  sminp(vf, rd, rn, rm);
3930  break;
3931  case NEON_SUB:
3932  sub(vf, rd, rn, rm);
3933  break;
3934  case NEON_UMAX:
3935  umax(vf, rd, rn, rm);
3936  break;
3937  case NEON_UMAXP:
3938  umaxp(vf, rd, rn, rm);
3939  break;
3940  case NEON_UMIN:
3941  umin(vf, rd, rn, rm);
3942  break;
3943  case NEON_UMINP:
3944  uminp(vf, rd, rn, rm);
3945  break;
3946  case NEON_SSHL:
3947  sshl(vf, rd, rn, rm);
3948  break;
3949  case NEON_USHL:
3950  ushl(vf, rd, rn, rm);
3951  break;
3952  case NEON_SABD:
3953  AbsDiff(vf, rd, rn, rm, true);
3954  break;
3955  case NEON_UABD:
3956  AbsDiff(vf, rd, rn, rm, false);
3957  break;
3958  case NEON_SABA:
3959  saba(vf, rd, rn, rm);
3960  break;
3961  case NEON_UABA:
3962  uaba(vf, rd, rn, rm);
3963  break;
3964  case NEON_UQADD:
3965  add(vf, rd, rn, rm).UnsignedSaturate(vf);
3966  break;
3967  case NEON_SQADD:
3968  add(vf, rd, rn, rm).SignedSaturate(vf);
3969  break;
3970  case NEON_UQSUB:
3971  sub(vf, rd, rn, rm).UnsignedSaturate(vf);
3972  break;
3973  case NEON_SQSUB:
3974  sub(vf, rd, rn, rm).SignedSaturate(vf);
3975  break;
3976  case NEON_SQDMULH:
3977  sqdmulh(vf, rd, rn, rm);
3978  break;
3979  case NEON_SQRDMULH:
3980  sqrdmulh(vf, rd, rn, rm);
3981  break;
3982  case NEON_UQSHL:
3983  ushl(vf, rd, rn, rm).UnsignedSaturate(vf);
3984  break;
3985  case NEON_SQSHL:
3986  sshl(vf, rd, rn, rm).SignedSaturate(vf);
3987  break;
3988  case NEON_URSHL:
3989  ushl(vf, rd, rn, rm).Round(vf);
3990  break;
3991  case NEON_SRSHL:
3992  sshl(vf, rd, rn, rm).Round(vf);
3993  break;
3994  case NEON_UQRSHL:
3995  ushl(vf, rd, rn, rm).Round(vf).UnsignedSaturate(vf);
3996  break;
3997  case NEON_SQRSHL:
3998  sshl(vf, rd, rn, rm).Round(vf).SignedSaturate(vf);
3999  break;
4000  case NEON_UHADD:
4001  add(vf, rd, rn, rm).Uhalve(vf);
4002  break;
4003  case NEON_URHADD:
4004  add(vf, rd, rn, rm).Uhalve(vf).Round(vf);
4005  break;
4006  case NEON_SHADD:
4007  add(vf, rd, rn, rm).Halve(vf);
4008  break;
4009  case NEON_SRHADD:
4010  add(vf, rd, rn, rm).Halve(vf).Round(vf);
4011  break;
4012  case NEON_UHSUB:
4013  sub(vf, rd, rn, rm).Uhalve(vf);
4014  break;
4015  case NEON_SHSUB:
4016  sub(vf, rd, rn, rm).Halve(vf);
4017  break;
4018  default:
4019  UNIMPLEMENTED();
4020  }
4021  }
4022 }
4023 
4024 void Simulator::VisitNEON3Different(Instruction* instr) {
4025  NEONFormatDecoder nfd(instr);
4026  VectorFormat vf = nfd.GetVectorFormat();
4027  VectorFormat vf_l = nfd.GetVectorFormat(nfd.LongIntegerFormatMap());
4028 
4029  SimVRegister& rd = vreg(instr->Rd());
4030  SimVRegister& rn = vreg(instr->Rn());
4031  SimVRegister& rm = vreg(instr->Rm());
4032 
4033  switch (instr->Mask(NEON3DifferentMask)) {
4034  case NEON_PMULL:
4035  pmull(vf_l, rd, rn, rm);
4036  break;
4037  case NEON_PMULL2:
4038  pmull2(vf_l, rd, rn, rm);
4039  break;
4040  case NEON_UADDL:
4041  uaddl(vf_l, rd, rn, rm);
4042  break;
4043  case NEON_UADDL2:
4044  uaddl2(vf_l, rd, rn, rm);
4045  break;
4046  case NEON_SADDL:
4047  saddl(vf_l, rd, rn, rm);
4048  break;
4049  case NEON_SADDL2:
4050  saddl2(vf_l, rd, rn, rm);
4051  break;
4052  case NEON_USUBL:
4053  usubl(vf_l, rd, rn, rm);
4054  break;
4055  case NEON_USUBL2:
4056  usubl2(vf_l, rd, rn, rm);
4057  break;
4058  case NEON_SSUBL:
4059  ssubl(vf_l, rd, rn, rm);
4060  break;
4061  case NEON_SSUBL2:
4062  ssubl2(vf_l, rd, rn, rm);
4063  break;
4064  case NEON_SABAL:
4065  sabal(vf_l, rd, rn, rm);
4066  break;
4067  case NEON_SABAL2:
4068  sabal2(vf_l, rd, rn, rm);
4069  break;
4070  case NEON_UABAL:
4071  uabal(vf_l, rd, rn, rm);
4072  break;
4073  case NEON_UABAL2:
4074  uabal2(vf_l, rd, rn, rm);
4075  break;
4076  case NEON_SABDL:
4077  sabdl(vf_l, rd, rn, rm);
4078  break;
4079  case NEON_SABDL2:
4080  sabdl2(vf_l, rd, rn, rm);
4081  break;
4082  case NEON_UABDL:
4083  uabdl(vf_l, rd, rn, rm);
4084  break;
4085  case NEON_UABDL2:
4086  uabdl2(vf_l, rd, rn, rm);
4087  break;
4088  case NEON_SMLAL:
4089  smlal(vf_l, rd, rn, rm);
4090  break;
4091  case NEON_SMLAL2:
4092  smlal2(vf_l, rd, rn, rm);
4093  break;
4094  case NEON_UMLAL:
4095  umlal(vf_l, rd, rn, rm);
4096  break;
4097  case NEON_UMLAL2:
4098  umlal2(vf_l, rd, rn, rm);
4099  break;
4100  case NEON_SMLSL:
4101  smlsl(vf_l, rd, rn, rm);
4102  break;
4103  case NEON_SMLSL2:
4104  smlsl2(vf_l, rd, rn, rm);
4105  break;
4106  case NEON_UMLSL:
4107  umlsl(vf_l, rd, rn, rm);
4108  break;
4109  case NEON_UMLSL2:
4110  umlsl2(vf_l, rd, rn, rm);
4111  break;
4112  case NEON_SMULL:
4113  smull(vf_l, rd, rn, rm);
4114  break;
4115  case NEON_SMULL2:
4116  smull2(vf_l, rd, rn, rm);
4117  break;
4118  case NEON_UMULL:
4119  umull(vf_l, rd, rn, rm);
4120  break;
4121  case NEON_UMULL2:
4122  umull2(vf_l, rd, rn, rm);
4123  break;
4124  case NEON_SQDMLAL:
4125  sqdmlal(vf_l, rd, rn, rm);
4126  break;
4127  case NEON_SQDMLAL2:
4128  sqdmlal2(vf_l, rd, rn, rm);
4129  break;
4130  case NEON_SQDMLSL:
4131  sqdmlsl(vf_l, rd, rn, rm);
4132  break;
4133  case NEON_SQDMLSL2:
4134  sqdmlsl2(vf_l, rd, rn, rm);
4135  break;
4136  case NEON_SQDMULL:
4137  sqdmull(vf_l, rd, rn, rm);
4138  break;
4139  case NEON_SQDMULL2:
4140  sqdmull2(vf_l, rd, rn, rm);
4141  break;
4142  case NEON_UADDW:
4143  uaddw(vf_l, rd, rn, rm);
4144  break;
4145  case NEON_UADDW2:
4146  uaddw2(vf_l, rd, rn, rm);
4147  break;
4148  case NEON_SADDW:
4149  saddw(vf_l, rd, rn, rm);
4150  break;
4151  case NEON_SADDW2:
4152  saddw2(vf_l, rd, rn, rm);
4153  break;
4154  case NEON_USUBW:
4155  usubw(vf_l, rd, rn, rm);
4156  break;
4157  case NEON_USUBW2:
4158  usubw2(vf_l, rd, rn, rm);
4159  break;
4160  case NEON_SSUBW:
4161  ssubw(vf_l, rd, rn, rm);
4162  break;
4163  case NEON_SSUBW2:
4164  ssubw2(vf_l, rd, rn, rm);
4165  break;
4166  case NEON_ADDHN:
4167  addhn(vf, rd, rn, rm);
4168  break;
4169  case NEON_ADDHN2:
4170  addhn2(vf, rd, rn, rm);
4171  break;
4172  case NEON_RADDHN:
4173  raddhn(vf, rd, rn, rm);
4174  break;
4175  case NEON_RADDHN2:
4176  raddhn2(vf, rd, rn, rm);
4177  break;
4178  case NEON_SUBHN:
4179  subhn(vf, rd, rn, rm);
4180  break;
4181  case NEON_SUBHN2:
4182  subhn2(vf, rd, rn, rm);
4183  break;
4184  case NEON_RSUBHN:
4185  rsubhn(vf, rd, rn, rm);
4186  break;
4187  case NEON_RSUBHN2:
4188  rsubhn2(vf, rd, rn, rm);
4189  break;
4190  default:
4191  UNIMPLEMENTED();
4192  }
4193 }
4194 
4195 void Simulator::VisitNEONAcrossLanes(Instruction* instr) {
4196  NEONFormatDecoder nfd(instr);
4197 
4198  SimVRegister& rd = vreg(instr->Rd());
4199  SimVRegister& rn = vreg(instr->Rn());
4200 
4201  // The input operand's VectorFormat is passed for these instructions.
4202  if (instr->Mask(NEONAcrossLanesFPFMask) == NEONAcrossLanesFPFixed) {
4203  VectorFormat vf = nfd.GetVectorFormat(nfd.FPFormatMap());
4204 
4205  switch (instr->Mask(NEONAcrossLanesFPMask)) {
4206  case NEON_FMAXV:
4207  fmaxv(vf, rd, rn);
4208  break;
4209  case NEON_FMINV:
4210  fminv(vf, rd, rn);
4211  break;
4212  case NEON_FMAXNMV:
4213  fmaxnmv(vf, rd, rn);
4214  break;
4215  case NEON_FMINNMV:
4216  fminnmv(vf, rd, rn);
4217  break;
4218  default:
4219  UNIMPLEMENTED();
4220  }
4221  } else {
4222  VectorFormat vf = nfd.GetVectorFormat();
4223 
4224  switch (instr->Mask(NEONAcrossLanesMask)) {
4225  case NEON_ADDV:
4226  addv(vf, rd, rn);
4227  break;
4228  case NEON_SMAXV:
4229  smaxv(vf, rd, rn);
4230  break;
4231  case NEON_SMINV:
4232  sminv(vf, rd, rn);
4233  break;
4234  case NEON_UMAXV:
4235  umaxv(vf, rd, rn);
4236  break;
4237  case NEON_UMINV:
4238  uminv(vf, rd, rn);
4239  break;
4240  case NEON_SADDLV:
4241  saddlv(vf, rd, rn);
4242  break;
4243  case NEON_UADDLV:
4244  uaddlv(vf, rd, rn);
4245  break;
4246  default:
4247  UNIMPLEMENTED();
4248  }
4249  }
4250 }
4251 
4252 void Simulator::VisitNEONByIndexedElement(Instruction* instr) {
4253  NEONFormatDecoder nfd(instr);
4254  VectorFormat vf_r = nfd.GetVectorFormat();
4255  VectorFormat vf = nfd.GetVectorFormat(nfd.LongIntegerFormatMap());
4256 
4257  SimVRegister& rd = vreg(instr->Rd());
4258  SimVRegister& rn = vreg(instr->Rn());
4259 
4260  ByElementOp Op = nullptr;
4261 
4262  int rm_reg = instr->Rm();
4263  int index = (instr->NEONH() << 1) | instr->NEONL();
4264  if (instr->NEONSize() == 1) {
4265  rm_reg &= 0xF;
4266  index = (index << 1) | instr->NEONM();
4267  }
4268 
4269  switch (instr->Mask(NEONByIndexedElementMask)) {
4270  case NEON_MUL_byelement:
4271  Op = &Simulator::mul;
4272  vf = vf_r;
4273  break;
4274  case NEON_MLA_byelement:
4275  Op = &Simulator::mla;
4276  vf = vf_r;
4277  break;
4278  case NEON_MLS_byelement:
4279  Op = &Simulator::mls;
4280  vf = vf_r;
4281  break;
4282  case NEON_SQDMULH_byelement:
4283  Op = &Simulator::sqdmulh;
4284  vf = vf_r;
4285  break;
4286  case NEON_SQRDMULH_byelement:
4287  Op = &Simulator::sqrdmulh;
4288  vf = vf_r;
4289  break;
4290  case NEON_SMULL_byelement:
4291  if (instr->Mask(NEON_Q)) {
4292  Op = &Simulator::smull2;
4293  } else {
4294  Op = &Simulator::smull;
4295  }
4296  break;
4297  case NEON_UMULL_byelement:
4298  if (instr->Mask(NEON_Q)) {
4299  Op = &Simulator::umull2;
4300  } else {
4301  Op = &Simulator::umull;
4302  }
4303  break;
4304  case NEON_SMLAL_byelement:
4305  if (instr->Mask(NEON_Q)) {
4306  Op = &Simulator::smlal2;
4307  } else {
4308  Op = &Simulator::smlal;
4309  }
4310  break;
4311  case NEON_UMLAL_byelement:
4312  if (instr->Mask(NEON_Q)) {
4313  Op = &Simulator::umlal2;
4314  } else {
4315  Op = &Simulator::umlal;
4316  }
4317  break;
4318  case NEON_SMLSL_byelement:
4319  if (instr->Mask(NEON_Q)) {
4320  Op = &Simulator::smlsl2;
4321  } else {
4322  Op = &Simulator::smlsl;
4323  }
4324  break;
4325  case NEON_UMLSL_byelement:
4326  if (instr->Mask(NEON_Q)) {
4327  Op = &Simulator::umlsl2;
4328  } else {
4329  Op = &Simulator::umlsl;
4330  }
4331  break;
4332  case NEON_SQDMULL_byelement:
4333  if (instr->Mask(NEON_Q)) {
4334  Op = &Simulator::sqdmull2;
4335  } else {
4336  Op = &Simulator::sqdmull;
4337  }
4338  break;
4339  case NEON_SQDMLAL_byelement:
4340  if (instr->Mask(NEON_Q)) {
4341  Op = &Simulator::sqdmlal2;
4342  } else {
4343  Op = &Simulator::sqdmlal;
4344  }
4345  break;
4346  case NEON_SQDMLSL_byelement:
4347  if (instr->Mask(NEON_Q)) {
4348  Op = &Simulator::sqdmlsl2;
4349  } else {
4350  Op = &Simulator::sqdmlsl;
4351  }
4352  break;
4353  default:
4354  index = instr->NEONH();
4355  if ((instr->FPType() & 1) == 0) {
4356  index = (index << 1) | instr->NEONL();
4357  }
4358 
4359  vf = nfd.GetVectorFormat(nfd.FPFormatMap());
4360 
4361  switch (instr->Mask(NEONByIndexedElementFPMask)) {
4362  case NEON_FMUL_byelement:
4363  Op = &Simulator::fmul;
4364  break;
4365  case NEON_FMLA_byelement:
4366  Op = &Simulator::fmla;
4367  break;
4368  case NEON_FMLS_byelement:
4369  Op = &Simulator::fmls;
4370  break;
4371  case NEON_FMULX_byelement:
4372  Op = &Simulator::fmulx;
4373  break;
4374  default:
4375  UNIMPLEMENTED();
4376  }
4377  }
4378 
4379  (this->*Op)(vf, rd, rn, vreg(rm_reg), index);
4380 }
4381 
4382 void Simulator::VisitNEONCopy(Instruction* instr) {
4383  NEONFormatDecoder nfd(instr, NEONFormatDecoder::TriangularFormatMap());
4384  VectorFormat vf = nfd.GetVectorFormat();
4385 
4386  SimVRegister& rd = vreg(instr->Rd());
4387  SimVRegister& rn = vreg(instr->Rn());
4388  int imm5 = instr->ImmNEON5();
4389  int lsb = LowestSetBitPosition(imm5);
4390  int reg_index = imm5 >> lsb;
4391 
4392  if (instr->Mask(NEONCopyInsElementMask) == NEON_INS_ELEMENT) {
4393  int imm4 = instr->ImmNEON4();
4394  DCHECK_GE(lsb, 1);
4395  int rn_index = imm4 >> (lsb - 1);
4396  ins_element(vf, rd, reg_index, rn, rn_index);
4397  } else if (instr->Mask(NEONCopyInsGeneralMask) == NEON_INS_GENERAL) {
4398  ins_immediate(vf, rd, reg_index, xreg(instr->Rn()));
4399  } else if (instr->Mask(NEONCopyUmovMask) == NEON_UMOV) {
4400  uint64_t value = LogicVRegister(rn).Uint(vf, reg_index);
4401  value &= MaxUintFromFormat(vf);
4402  set_xreg(instr->Rd(), value);
4403  } else if (instr->Mask(NEONCopyUmovMask) == NEON_SMOV) {
4404  int64_t value = LogicVRegister(rn).Int(vf, reg_index);
4405  if (instr->NEONQ()) {
4406  set_xreg(instr->Rd(), value);
4407  } else {
4408  DCHECK(is_int32(value));
4409  set_wreg(instr->Rd(), static_cast<int32_t>(value));
4410  }
4411  } else if (instr->Mask(NEONCopyDupElementMask) == NEON_DUP_ELEMENT) {
4412  dup_element(vf, rd, rn, reg_index);
4413  } else if (instr->Mask(NEONCopyDupGeneralMask) == NEON_DUP_GENERAL) {
4414  dup_immediate(vf, rd, xreg(instr->Rn()));
4415  } else {
4416  UNIMPLEMENTED();
4417  }
4418 }
4419 
4420 void Simulator::VisitNEONExtract(Instruction* instr) {
4421  NEONFormatDecoder nfd(instr, NEONFormatDecoder::LogicalFormatMap());
4422  VectorFormat vf = nfd.GetVectorFormat();
4423  SimVRegister& rd = vreg(instr->Rd());
4424  SimVRegister& rn = vreg(instr->Rn());
4425  SimVRegister& rm = vreg(instr->Rm());
4426  if (instr->Mask(NEONExtractMask) == NEON_EXT) {
4427  int index = instr->ImmNEONExt();
4428  ext(vf, rd, rn, rm, index);
4429  } else {
4430  UNIMPLEMENTED();
4431  }
4432 }
4433 
4434 void Simulator::NEONLoadStoreMultiStructHelper(const Instruction* instr,
4435  AddrMode addr_mode) {
4436  NEONFormatDecoder nfd(instr, NEONFormatDecoder::LoadStoreFormatMap());
4437  VectorFormat vf = nfd.GetVectorFormat();
4438 
4439  uint64_t addr_base = xreg(instr->Rn(), Reg31IsStackPointer);
4440  int reg_size = RegisterSizeInBytesFromFormat(vf);
4441 
4442  int reg[4];
4443  uint64_t addr[4];
4444  for (int i = 0; i < 4; i++) {
4445  reg[i] = (instr->Rt() + i) % kNumberOfVRegisters;
4446  addr[i] = addr_base + (i * reg_size);
4447  }
4448  int count = 1;
4449  bool log_read = true;
4450 
4451  // Bit 23 determines whether this is an offset or post-index addressing mode.
4452  // In offset mode, bits 20 to 16 should be zero; these bits encode the
4453  // register of immediate in post-index mode.
4454  if ((instr->Bit(23) == 0) && (instr->Bits(20, 16) != 0)) {
4455  UNREACHABLE();
4456  }
4457 
4458  // We use the PostIndex mask here, as it works in this case for both Offset
4459  // and PostIndex addressing.
4460  switch (instr->Mask(NEONLoadStoreMultiStructPostIndexMask)) {
4461  case NEON_LD1_4v:
4462  case NEON_LD1_4v_post:
4463  ld1(vf, vreg(reg[3]), addr[3]);
4464  count++;
4465  V8_FALLTHROUGH;
4466  case NEON_LD1_3v:
4467  case NEON_LD1_3v_post:
4468  ld1(vf, vreg(reg[2]), addr[2]);
4469  count++;
4470  V8_FALLTHROUGH;
4471  case NEON_LD1_2v:
4472  case NEON_LD1_2v_post:
4473  ld1(vf, vreg(reg[1]), addr[1]);
4474  count++;
4475  V8_FALLTHROUGH;
4476  case NEON_LD1_1v:
4477  case NEON_LD1_1v_post:
4478  ld1(vf, vreg(reg[0]), addr[0]);
4479  break;
4480  case NEON_ST1_4v:
4481  case NEON_ST1_4v_post:
4482  st1(vf, vreg(reg[3]), addr[3]);
4483  count++;
4484  V8_FALLTHROUGH;
4485  case NEON_ST1_3v:
4486  case NEON_ST1_3v_post:
4487  st1(vf, vreg(reg[2]), addr[2]);
4488  count++;
4489  V8_FALLTHROUGH;
4490  case NEON_ST1_2v:
4491  case NEON_ST1_2v_post:
4492  st1(vf, vreg(reg[1]), addr[1]);
4493  count++;
4494  V8_FALLTHROUGH;
4495  case NEON_ST1_1v:
4496  case NEON_ST1_1v_post:
4497  st1(vf, vreg(reg[0]), addr[0]);
4498  log_read = false;
4499  break;
4500  case NEON_LD2_post:
4501  case NEON_LD2:
4502  ld2(vf, vreg(reg[0]), vreg(reg[1]), addr[0]);
4503  count = 2;
4504  break;
4505  case NEON_ST2:
4506  case NEON_ST2_post:
4507  st2(vf, vreg(reg[0]), vreg(reg[1]), addr[0]);
4508  count = 2;
4509  log_read = false;
4510  break;
4511  case NEON_LD3_post:
4512  case NEON_LD3:
4513  ld3(vf, vreg(reg[0]), vreg(reg[1]), vreg(reg[2]), addr[0]);
4514  count = 3;
4515  break;
4516  case NEON_ST3:
4517  case NEON_ST3_post:
4518  st3(vf, vreg(reg[0]), vreg(reg[1]), vreg(reg[2]), addr[0]);
4519  count = 3;
4520  log_read = false;
4521  break;
4522  case NEON_LD4_post:
4523  case NEON_LD4:
4524  ld4(vf, vreg(reg[0]), vreg(reg[1]), vreg(reg[2]), vreg(reg[3]), addr[0]);
4525  count = 4;
4526  break;
4527  case NEON_ST4:
4528  case NEON_ST4_post:
4529  st4(vf, vreg(reg[0]), vreg(reg[1]), vreg(reg[2]), vreg(reg[3]), addr[0]);
4530  count = 4;
4531  log_read = false;
4532  break;
4533  default:
4534  UNIMPLEMENTED();
4535  }
4536 
4537  {
4538  base::MutexGuard lock_guard(&global_monitor_.Pointer()->mutex);
4539  if (log_read) {
4540  local_monitor_.NotifyLoad();
4541  } else {
4542  local_monitor_.NotifyStore();
4543  global_monitor_.Pointer()->NotifyStore_Locked(&global_monitor_processor_);
4544  }
4545  }
4546 
4547  // Explicitly log the register update whilst we have type information.
4548  for (int i = 0; i < count; i++) {
4549  // For de-interleaving loads, only print the base address.
4550  int lane_size = LaneSizeInBytesFromFormat(vf);
4551  PrintRegisterFormat format = GetPrintRegisterFormatTryFP(
4552  GetPrintRegisterFormatForSize(reg_size, lane_size));
4553  if (log_read) {
4554  LogVRead(addr_base, reg[i], format);
4555  } else {
4556  LogVWrite(addr_base, reg[i], format);
4557  }
4558  }
4559 
4560  if (addr_mode == PostIndex) {
4561  int rm = instr->Rm();
4562  // The immediate post index addressing mode is indicated by rm = 31.
4563  // The immediate is implied by the number of vector registers used.
4564  addr_base +=
4565  (rm == 31) ? RegisterSizeInBytesFromFormat(vf) * count : xreg(rm);
4566  set_xreg(instr->Rn(), addr_base);
4567  } else {
4568  DCHECK_EQ(addr_mode, Offset);
4569  }
4570 }
4571 
4572 void Simulator::VisitNEONLoadStoreMultiStruct(Instruction* instr) {
4573  NEONLoadStoreMultiStructHelper(instr, Offset);
4574 }
4575 
4576 void Simulator::VisitNEONLoadStoreMultiStructPostIndex(Instruction* instr) {
4577  NEONLoadStoreMultiStructHelper(instr, PostIndex);
4578 }
4579 
4580 void Simulator::NEONLoadStoreSingleStructHelper(const Instruction* instr,
4581  AddrMode addr_mode) {
4582  uint64_t addr = xreg(instr->Rn(), Reg31IsStackPointer);
4583  int rt = instr->Rt();
4584 
4585  // Bit 23 determines whether this is an offset or post-index addressing mode.
4586  // In offset mode, bits 20 to 16 should be zero; these bits encode the
4587  // register of immediate in post-index mode.
4588  DCHECK_IMPLIES(instr->Bit(23) == 0, instr->Bits(20, 16) == 0);
4589 
4590  bool do_load = false;
4591 
4592  NEONFormatDecoder nfd(instr, NEONFormatDecoder::LoadStoreFormatMap());
4593  VectorFormat vf_t = nfd.GetVectorFormat();
4594 
4595  VectorFormat vf = kFormat16B;
4596  // We use the PostIndex mask here, as it works in this case for both Offset
4597  // and PostIndex addressing.
4598  switch (instr->Mask(NEONLoadStoreSingleStructPostIndexMask)) {
4599  case NEON_LD1_b:
4600  case NEON_LD1_b_post:
4601  case NEON_LD2_b:
4602  case NEON_LD2_b_post:
4603  case NEON_LD3_b:
4604  case NEON_LD3_b_post:
4605  case NEON_LD4_b:
4606  case NEON_LD4_b_post:
4607  do_load = true;
4608  V8_FALLTHROUGH;
4609  case NEON_ST1_b:
4610  case NEON_ST1_b_post:
4611  case NEON_ST2_b:
4612  case NEON_ST2_b_post:
4613  case NEON_ST3_b:
4614  case NEON_ST3_b_post:
4615  case NEON_ST4_b:
4616  case NEON_ST4_b_post:
4617  break;
4618 
4619  case NEON_LD1_h:
4620  case NEON_LD1_h_post:
4621  case NEON_LD2_h:
4622  case NEON_LD2_h_post:
4623  case NEON_LD3_h:
4624  case NEON_LD3_h_post:
4625  case NEON_LD4_h:
4626  case NEON_LD4_h_post:
4627  do_load = true;
4628  V8_FALLTHROUGH;
4629  case NEON_ST1_h:
4630  case NEON_ST1_h_post:
4631  case NEON_ST2_h:
4632  case NEON_ST2_h_post:
4633  case NEON_ST3_h:
4634  case NEON_ST3_h_post:
4635  case NEON_ST4_h:
4636  case NEON_ST4_h_post:
4637  vf = kFormat8H;
4638  break;
4639 
4640  case NEON_LD1_s:
4641  case NEON_LD1_s_post:
4642  case NEON_LD2_s:
4643  case NEON_LD2_s_post:
4644  case NEON_LD3_s:
4645  case NEON_LD3_s_post:
4646  case NEON_LD4_s:
4647  case NEON_LD4_s_post:
4648  do_load = true;
4649  V8_FALLTHROUGH;
4650  case NEON_ST1_s:
4651  case NEON_ST1_s_post:
4652  case NEON_ST2_s:
4653  case NEON_ST2_s_post:
4654  case NEON_ST3_s:
4655  case NEON_ST3_s_post:
4656  case NEON_ST4_s:
4657  case NEON_ST4_s_post: {
4658  static_assert((NEON_LD1_s | (1 << NEONLSSize_offset)) == NEON_LD1_d,
4659  "LSB of size distinguishes S and D registers.");
4660  static_assert(
4661  (NEON_LD1_s_post | (1 << NEONLSSize_offset)) == NEON_LD1_d_post,
4662  "LSB of size distinguishes S and D registers.");
4663  static_assert((NEON_ST1_s | (1 << NEONLSSize_offset)) == NEON_ST1_d,
4664  "LSB of size distinguishes S and D registers.");
4665  static_assert(
4666  (NEON_ST1_s_post | (1 << NEONLSSize_offset)) == NEON_ST1_d_post,
4667  "LSB of size distinguishes S and D registers.");
4668  vf = ((instr->NEONLSSize() & 1) == 0) ? kFormat4S : kFormat2D;
4669  break;
4670  }
4671 
4672  case NEON_LD1R:
4673  case NEON_LD1R_post: {
4674  vf = vf_t;
4675  ld1r(vf, vreg(rt), addr);
4676  do_load = true;
4677  break;
4678  }
4679 
4680  case NEON_LD2R:
4681  case NEON_LD2R_post: {
4682  vf = vf_t;
4683  int rt2 = (rt + 1) % kNumberOfVRegisters;
4684  ld2r(vf, vreg(rt), vreg(rt2), addr);
4685  do_load = true;
4686  break;
4687  }
4688 
4689  case NEON_LD3R:
4690  case NEON_LD3R_post: {
4691  vf = vf_t;
4692  int rt2 = (rt + 1) % kNumberOfVRegisters;
4693  int rt3 = (rt2 + 1) % kNumberOfVRegisters;
4694  ld3r(vf, vreg(rt), vreg(rt2), vreg(rt3), addr);
4695  do_load = true;
4696  break;
4697  }
4698 
4699  case NEON_LD4R:
4700  case NEON_LD4R_post: {
4701  vf = vf_t;
4702  int rt2 = (rt + 1) % kNumberOfVRegisters;
4703  int rt3 = (rt2 + 1) % kNumberOfVRegisters;
4704  int rt4 = (rt3 + 1) % kNumberOfVRegisters;
4705  ld4r(vf, vreg(rt), vreg(rt2), vreg(rt3), vreg(rt4), addr);
4706  do_load = true;
4707  break;
4708  }
4709  default:
4710  UNIMPLEMENTED();
4711  }
4712 
4713  PrintRegisterFormat print_format =
4714  GetPrintRegisterFormatTryFP(GetPrintRegisterFormat(vf));
4715  // Make sure that the print_format only includes a single lane.
4716  print_format =
4717  static_cast<PrintRegisterFormat>(print_format & ~kPrintRegAsVectorMask);
4718 
4719  int esize = LaneSizeInBytesFromFormat(vf);
4720  int index_shift = LaneSizeInBytesLog2FromFormat(vf);
4721  int lane = instr->NEONLSIndex(index_shift);
4722  int scale = 0;
4723  int rt2 = (rt + 1) % kNumberOfVRegisters;
4724  int rt3 = (rt2 + 1) % kNumberOfVRegisters;
4725  int rt4 = (rt3 + 1) % kNumberOfVRegisters;
4726  switch (instr->Mask(NEONLoadStoreSingleLenMask)) {
4727  case NEONLoadStoreSingle1:
4728  scale = 1;
4729  if (do_load) {
4730  ld1(vf, vreg(rt), lane, addr);
4731  LogVRead(addr, rt, print_format, lane);
4732  } else {
4733  st1(vf, vreg(rt), lane, addr);
4734  LogVWrite(addr, rt, print_format, lane);
4735  }
4736  break;
4737  case NEONLoadStoreSingle2:
4738  scale = 2;
4739  if (do_load) {
4740  ld2(vf, vreg(rt), vreg(rt2), lane, addr);
4741  LogVRead(addr, rt, print_format, lane);
4742  LogVRead(addr + esize, rt2, print_format, lane);
4743  } else {
4744  st2(vf, vreg(rt), vreg(rt2), lane, addr);
4745  LogVWrite(addr, rt, print_format, lane);
4746  LogVWrite(addr + esize, rt2, print_format, lane);
4747  }
4748  break;
4749  case NEONLoadStoreSingle3:
4750  scale = 3;
4751  if (do_load) {
4752  ld3(vf, vreg(rt), vreg(rt2), vreg(rt3), lane, addr);
4753  LogVRead(addr, rt, print_format, lane);
4754  LogVRead(addr + esize, rt2, print_format, lane);
4755  LogVRead(addr + (2 * esize), rt3, print_format, lane);
4756  } else {
4757  st3(vf, vreg(rt), vreg(rt2), vreg(rt3), lane, addr);
4758  LogVWrite(addr, rt, print_format, lane);
4759  LogVWrite(addr + esize, rt2, print_format, lane);
4760  LogVWrite(addr + (2 * esize), rt3, print_format, lane);
4761  }
4762  break;
4763  case NEONLoadStoreSingle4:
4764  scale = 4;
4765  if (do_load) {
4766  ld4(vf, vreg(rt), vreg(rt2), vreg(rt3), vreg(rt4), lane, addr);
4767  LogVRead(addr, rt, print_format, lane);
4768  LogVRead(addr + esize, rt2, print_format, lane);
4769  LogVRead(addr + (2 * esize), rt3, print_format, lane);
4770  LogVRead(addr + (3 * esize), rt4, print_format, lane);
4771  } else {
4772  st4(vf, vreg(rt), vreg(rt2), vreg(rt3), vreg(rt4), lane, addr);
4773  LogVWrite(addr, rt, print_format, lane);
4774  LogVWrite(addr + esize, rt2, print_format, lane);
4775  LogVWrite(addr + (2 * esize), rt3, print_format, lane);
4776  LogVWrite(addr + (3 * esize), rt4, print_format, lane);
4777  }
4778  break;
4779  default:
4780  UNIMPLEMENTED();
4781  }
4782 
4783  {
4784  base::MutexGuard lock_guard(&global_monitor_.Pointer()->mutex);
4785  if (do_load) {
4786  local_monitor_.NotifyLoad();
4787  } else {
4788  local_monitor_.NotifyStore();
4789  global_monitor_.Pointer()->NotifyStore_Locked(&global_monitor_processor_);
4790  }
4791  }
4792 
4793  if (addr_mode == PostIndex) {
4794  int rm = instr->Rm();
4795  int lane_size = LaneSizeInBytesFromFormat(vf);
4796  set_xreg(instr->Rn(), addr + ((rm == 31) ? (scale * lane_size) : xreg(rm)));
4797  }
4798 }
4799 
4800 void Simulator::VisitNEONLoadStoreSingleStruct(Instruction* instr) {
4801  NEONLoadStoreSingleStructHelper(instr, Offset);
4802 }
4803 
4804 void Simulator::VisitNEONLoadStoreSingleStructPostIndex(Instruction* instr) {
4805  NEONLoadStoreSingleStructHelper(instr, PostIndex);
4806 }
4807 
4808 void Simulator::VisitNEONModifiedImmediate(Instruction* instr) {
4809  SimVRegister& rd = vreg(instr->Rd());
4810  int cmode = instr->NEONCmode();
4811  int cmode_3_1 = (cmode >> 1) & 7;
4812  int cmode_3 = (cmode >> 3) & 1;
4813  int cmode_2 = (cmode >> 2) & 1;
4814  int cmode_1 = (cmode >> 1) & 1;
4815  int cmode_0 = cmode & 1;
4816  int q = instr->NEONQ();
4817  int op_bit = instr->NEONModImmOp();
4818  uint64_t imm8 = instr->ImmNEONabcdefgh();
4819 
4820  // Find the format and immediate value
4821  uint64_t imm = 0;
4822  VectorFormat vform = kFormatUndefined;
4823  switch (cmode_3_1) {
4824  case 0x0:
4825  case 0x1:
4826  case 0x2:
4827  case 0x3:
4828  vform = (q == 1) ? kFormat4S : kFormat2S;
4829  imm = imm8 << (8 * cmode_3_1);
4830  break;
4831  case 0x4:
4832  case 0x5:
4833  vform = (q == 1) ? kFormat8H : kFormat4H;
4834  imm = imm8 << (8 * cmode_1);
4835  break;
4836  case 0x6:
4837  vform = (q == 1) ? kFormat4S : kFormat2S;
4838  if (cmode_0 == 0) {
4839  imm = imm8 << 8 | 0x000000FF;
4840  } else {
4841  imm = imm8 << 16 | 0x0000FFFF;
4842  }
4843  break;
4844  case 0x7:
4845  if (cmode_0 == 0 && op_bit == 0) {
4846  vform = q ? kFormat16B : kFormat8B;
4847  imm = imm8;
4848  } else if (cmode_0 == 0 && op_bit == 1) {
4849  vform = q ? kFormat2D : kFormat1D;
4850  imm = 0;
4851  for (int i = 0; i < 8; ++i) {
4852  if (imm8 & (1ULL << i)) {
4853  imm |= (UINT64_C(0xFF) << (8 * i));
4854  }
4855  }
4856  } else { // cmode_0 == 1, cmode == 0xF.
4857  if (op_bit == 0) {
4858  vform = q ? kFormat4S : kFormat2S;
4859  imm = bit_cast<uint32_t>(instr->ImmNEONFP32());
4860  } else if (q == 1) {
4861  vform = kFormat2D;
4862  imm = bit_cast<uint64_t>(instr->ImmNEONFP64());
4863  } else {
4864  DCHECK((q == 0) && (op_bit == 1) && (cmode == 0xF));
4865  VisitUnallocated(instr);
4866  }
4867  }
4868  break;
4869  default:
4870  UNREACHABLE();
4871  }
4872 
4873  // Find the operation.
4874  NEONModifiedImmediateOp op;
4875  if (cmode_3 == 0) {
4876  if (cmode_0 == 0) {
4877  op = op_bit ? NEONModifiedImmediate_MVNI : NEONModifiedImmediate_MOVI;
4878  } else { // cmode<0> == '1'
4879  op = op_bit ? NEONModifiedImmediate_BIC : NEONModifiedImmediate_ORR;
4880  }
4881  } else { // cmode<3> == '1'
4882  if (cmode_2 == 0) {
4883  if (cmode_0 == 0) {
4884  op = op_bit ? NEONModifiedImmediate_MVNI : NEONModifiedImmediate_MOVI;
4885  } else { // cmode<0> == '1'
4886  op = op_bit ? NEONModifiedImmediate_BIC : NEONModifiedImmediate_ORR;
4887  }
4888  } else { // cmode<2> == '1'
4889  if (cmode_1 == 0) {
4890  op = op_bit ? NEONModifiedImmediate_MVNI : NEONModifiedImmediate_MOVI;
4891  } else { // cmode<1> == '1'
4892  if (cmode_0 == 0) {
4893  op = NEONModifiedImmediate_MOVI;
4894  } else { // cmode<0> == '1'
4895  op = NEONModifiedImmediate_MOVI;
4896  }
4897  }
4898  }
4899  }
4900 
4901  // Call the logic function.
4902  switch (op) {
4903  case NEONModifiedImmediate_ORR:
4904  orr(vform, rd, rd, imm);
4905  break;
4906  case NEONModifiedImmediate_BIC:
4907  bic(vform, rd, rd, imm);
4908  break;
4909  case NEONModifiedImmediate_MOVI:
4910  movi(vform, rd, imm);
4911  break;
4912  case NEONModifiedImmediate_MVNI:
4913  mvni(vform, rd, imm);
4914  break;
4915  default:
4916  VisitUnimplemented(instr);
4917  }
4918 }
4919 
4920 void Simulator::VisitNEONScalar2RegMisc(Instruction* instr) {
4921  NEONFormatDecoder nfd(instr, NEONFormatDecoder::ScalarFormatMap());
4922  VectorFormat vf = nfd.GetVectorFormat();
4923 
4924  SimVRegister& rd = vreg(instr->Rd());
4925  SimVRegister& rn = vreg(instr->Rn());
4926 
4927  if (instr->Mask(NEON2RegMiscOpcode) <= NEON_NEG_scalar_opcode) {
4928  // These instructions all use a two bit size field, except NOT and RBIT,
4929  // which use the field to encode the operation.
4930  switch (instr->Mask(NEONScalar2RegMiscMask)) {
4931  case NEON_CMEQ_zero_scalar:
4932  cmp(vf, rd, rn, 0, eq);
4933  break;
4934  case NEON_CMGE_zero_scalar:
4935  cmp(vf, rd, rn, 0, ge);
4936  break;
4937  case NEON_CMGT_zero_scalar:
4938  cmp(vf, rd, rn, 0, gt);
4939  break;
4940  case NEON_CMLT_zero_scalar:
4941  cmp(vf, rd, rn, 0, lt);
4942  break;
4943  case NEON_CMLE_zero_scalar:
4944  cmp(vf, rd, rn, 0, le);
4945  break;
4946  case NEON_ABS_scalar:
4947  abs(vf, rd, rn);
4948  break;
4949  case NEON_SQABS_scalar:
4950  abs(vf, rd, rn).SignedSaturate(vf);
4951  break;
4952  case NEON_NEG_scalar:
4953  neg(vf, rd, rn);
4954  break;
4955  case NEON_SQNEG_scalar:
4956  neg(vf, rd, rn).SignedSaturate(vf);
4957  break;
4958  case NEON_SUQADD_scalar:
4959  suqadd(vf, rd, rn);
4960  break;
4961  case NEON_USQADD_scalar:
4962  usqadd(vf, rd, rn);
4963  break;
4964  default:
4965  UNIMPLEMENTED();
4966  break;
4967  }
4968  } else {
4969  VectorFormat fpf = nfd.GetVectorFormat(nfd.FPScalarFormatMap());
4970  FPRounding fpcr_rounding = static_cast<FPRounding>(fpcr().RMode());
4971 
4972  // These instructions all use a one bit size field, except SQXTUN, SQXTN
4973  // and UQXTN, which use a two bit size field.
4974  switch (instr->Mask(NEONScalar2RegMiscFPMask)) {
4975  case NEON_FRECPE_scalar:
4976  frecpe(fpf, rd, rn, fpcr_rounding);
4977  break;
4978  case NEON_FRECPX_scalar:
4979  frecpx(fpf, rd, rn);
4980  break;
4981  case NEON_FRSQRTE_scalar:
4982  frsqrte(fpf, rd, rn);
4983  break;
4984  case NEON_FCMGT_zero_scalar:
4985  fcmp_zero(fpf, rd, rn, gt);
4986  break;
4987  case NEON_FCMGE_zero_scalar:
4988  fcmp_zero(fpf, rd, rn, ge);
4989  break;
4990  case NEON_FCMEQ_zero_scalar:
4991  fcmp_zero(fpf, rd, rn, eq);
4992  break;
4993  case NEON_FCMLE_zero_scalar:
4994  fcmp_zero(fpf, rd, rn, le);
4995  break;
4996  case NEON_FCMLT_zero_scalar:
4997  fcmp_zero(fpf, rd, rn, lt);
4998  break;
4999  case NEON_SCVTF_scalar:
5000  scvtf(fpf, rd, rn, 0, fpcr_rounding);
5001  break;
5002  case NEON_UCVTF_scalar:
5003  ucvtf(fpf, rd, rn, 0, fpcr_rounding);
5004  break;
5005  case NEON_FCVTNS_scalar:
5006  fcvts(fpf, rd, rn, FPTieEven);
5007  break;
5008  case NEON_FCVTNU_scalar:
5009  fcvtu(fpf, rd, rn, FPTieEven);
5010  break;
5011  case NEON_FCVTPS_scalar:
5012  fcvts(fpf, rd, rn, FPPositiveInfinity);
5013  break;
5014  case NEON_FCVTPU_scalar:
5015  fcvtu(fpf, rd, rn, FPPositiveInfinity);
5016  break;
5017  case NEON_FCVTMS_scalar:
5018  fcvts(fpf, rd, rn, FPNegativeInfinity);
5019  break;
5020  case NEON_FCVTMU_scalar:
5021  fcvtu(fpf, rd, rn, FPNegativeInfinity);
5022  break;
5023  case NEON_FCVTZS_scalar:
5024  fcvts(fpf, rd, rn, FPZero);
5025  break;
5026  case NEON_FCVTZU_scalar:
5027  fcvtu(fpf, rd, rn, FPZero);
5028  break;
5029  case NEON_FCVTAS_scalar:
5030  fcvts(fpf, rd, rn, FPTieAway);
5031  break;
5032  case NEON_FCVTAU_scalar:
5033  fcvtu(fpf, rd, rn, FPTieAway);
5034  break;
5035  case NEON_FCVTXN_scalar:
5036  // Unlike all of the other FP instructions above, fcvtxn encodes dest
5037  // size S as size<0>=1. There's only one case, so we ignore the form.
5038  DCHECK_EQ(instr->Bit(22), 1);
5039  fcvtxn(kFormatS, rd, rn);
5040  break;
5041  default:
5042  switch (instr->Mask(NEONScalar2RegMiscMask)) {
5043  case NEON_SQXTN_scalar:
5044  sqxtn(vf, rd, rn);
5045  break;
5046  case NEON_UQXTN_scalar:
5047  uqxtn(vf, rd, rn);
5048  break;
5049  case NEON_SQXTUN_scalar:
5050  sqxtun(vf, rd, rn);
5051  break;
5052  default:
5053  UNIMPLEMENTED();
5054  }
5055  }
5056  }
5057 }
5058 
5059 void Simulator::VisitNEONScalar3Diff(Instruction* instr) {
5060  NEONFormatDecoder nfd(instr, NEONFormatDecoder::LongScalarFormatMap());
5061  VectorFormat vf = nfd.GetVectorFormat();
5062 
5063  SimVRegister& rd = vreg(instr->Rd());
5064  SimVRegister& rn = vreg(instr->Rn());
5065  SimVRegister& rm = vreg(instr->Rm());
5066  switch (instr->Mask(NEONScalar3DiffMask)) {
5067  case NEON_SQDMLAL_scalar:
5068  sqdmlal(vf, rd, rn, rm);
5069  break;
5070  case NEON_SQDMLSL_scalar:
5071  sqdmlsl(vf, rd, rn, rm);
5072  break;
5073  case NEON_SQDMULL_scalar:
5074  sqdmull(vf, rd, rn, rm);
5075  break;
5076  default:
5077  UNIMPLEMENTED();
5078  }
5079 }
5080 
5081 void Simulator::VisitNEONScalar3Same(Instruction* instr) {
5082  NEONFormatDecoder nfd(instr, NEONFormatDecoder::ScalarFormatMap());
5083  VectorFormat vf = nfd.GetVectorFormat();
5084 
5085  SimVRegister& rd = vreg(instr->Rd());
5086  SimVRegister& rn = vreg(instr->Rn());
5087  SimVRegister& rm = vreg(instr->Rm());
5088 
5089  if (instr->Mask(NEONScalar3SameFPFMask) == NEONScalar3SameFPFixed) {
5090  vf = nfd.GetVectorFormat(nfd.FPScalarFormatMap());
5091  switch (instr->Mask(NEONScalar3SameFPMask)) {
5092  case NEON_FMULX_scalar:
5093  fmulx(vf, rd, rn, rm);
5094  break;
5095  case NEON_FACGE_scalar:
5096  fabscmp(vf, rd, rn, rm, ge);
5097  break;
5098  case NEON_FACGT_scalar:
5099  fabscmp(vf, rd, rn, rm, gt);
5100  break;
5101  case NEON_FCMEQ_scalar:
5102  fcmp(vf, rd, rn, rm, eq);
5103  break;
5104  case NEON_FCMGE_scalar:
5105  fcmp(vf, rd, rn, rm, ge);
5106  break;
5107  case NEON_FCMGT_scalar:
5108  fcmp(vf, rd, rn, rm, gt);
5109  break;
5110  case NEON_FRECPS_scalar:
5111  frecps(vf, rd, rn, rm);
5112  break;
5113  case NEON_FRSQRTS_scalar:
5114  frsqrts(vf, rd, rn, rm);
5115  break;
5116  case NEON_FABD_scalar:
5117  fabd(vf, rd, rn, rm);
5118  break;
5119  default:
5120  UNIMPLEMENTED();
5121  }
5122  } else {
5123  switch (instr->Mask(NEONScalar3SameMask)) {
5124  case NEON_ADD_scalar:
5125  add(vf, rd, rn, rm);
5126  break;
5127  case NEON_SUB_scalar:
5128  sub(vf, rd, rn, rm);
5129  break;
5130  case NEON_CMEQ_scalar:
5131  cmp(vf, rd, rn, rm, eq);
5132  break;
5133  case NEON_CMGE_scalar:
5134  cmp(vf, rd, rn, rm, ge);
5135  break;
5136  case NEON_CMGT_scalar:
5137  cmp(vf, rd, rn, rm, gt);
5138  break;
5139  case NEON_CMHI_scalar:
5140  cmp(vf, rd, rn, rm, hi);
5141  break;
5142  case NEON_CMHS_scalar:
5143  cmp(vf, rd, rn, rm, hs);
5144  break;
5145  case NEON_CMTST_scalar:
5146  cmptst(vf, rd, rn, rm);
5147  break;
5148  case NEON_USHL_scalar:
5149  ushl(vf, rd, rn, rm);
5150  break;
5151  case NEON_SSHL_scalar:
5152  sshl(vf, rd, rn, rm);
5153  break;
5154  case NEON_SQDMULH_scalar:
5155  sqdmulh(vf, rd, rn, rm);
5156  break;
5157  case NEON_SQRDMULH_scalar:
5158  sqrdmulh(vf, rd, rn, rm);
5159  break;
5160  case NEON_UQADD_scalar:
5161  add(vf, rd, rn, rm).UnsignedSaturate(vf);
5162  break;
5163  case NEON_SQADD_scalar:
5164  add(vf, rd, rn, rm).SignedSaturate(vf);
5165  break;
5166  case NEON_UQSUB_scalar:
5167  sub(vf, rd, rn, rm).UnsignedSaturate(vf);
5168  break;
5169  case NEON_SQSUB_scalar:
5170  sub(vf, rd, rn, rm).SignedSaturate(vf);
5171  break;
5172  case NEON_UQSHL_scalar:
5173  ushl(vf, rd, rn, rm).UnsignedSaturate(vf);
5174  break;
5175  case NEON_SQSHL_scalar:
5176  sshl(vf, rd, rn, rm).SignedSaturate(vf);
5177  break;
5178  case NEON_URSHL_scalar:
5179  ushl(vf, rd, rn, rm).Round(vf);
5180  break;
5181  case NEON_SRSHL_scalar:
5182  sshl(vf, rd, rn, rm).Round(vf);
5183  break;
5184  case NEON_UQRSHL_scalar:
5185  ushl(vf, rd, rn, rm).Round(vf).UnsignedSaturate(vf);
5186  break;
5187  case NEON_SQRSHL_scalar:
5188  sshl(vf, rd, rn, rm).Round(vf).SignedSaturate(vf);
5189  break;
5190  default:
5191  UNIMPLEMENTED();
5192  }
5193  }
5194 }
5195 
5196 void Simulator::VisitNEONScalarByIndexedElement(Instruction* instr) {
5197  NEONFormatDecoder nfd(instr, NEONFormatDecoder::LongScalarFormatMap());
5198  VectorFormat vf = nfd.GetVectorFormat();
5199  VectorFormat vf_r = nfd.GetVectorFormat(nfd.ScalarFormatMap());
5200 
5201  SimVRegister& rd = vreg(instr->Rd());
5202  SimVRegister& rn = vreg(instr->Rn());
5203  ByElementOp Op = nullptr;
5204 
5205  int rm_reg = instr->Rm();
5206  int index = (instr->NEONH() << 1) | instr->NEONL();
5207  if (instr->NEONSize() == 1) {
5208  rm_reg &= 0xF;
5209  index = (index << 1) | instr->NEONM();
5210  }
5211 
5212  switch (instr->Mask(NEONScalarByIndexedElementMask)) {
5213  case NEON_SQDMULL_byelement_scalar:
5214  Op = &Simulator::sqdmull;
5215  break;
5216  case NEON_SQDMLAL_byelement_scalar:
5217  Op = &Simulator::sqdmlal;
5218  break;
5219  case NEON_SQDMLSL_byelement_scalar:
5220  Op = &Simulator::sqdmlsl;
5221  break;
5222  case NEON_SQDMULH_byelement_scalar:
5223  Op = &Simulator::sqdmulh;
5224  vf = vf_r;
5225  break;
5226  case NEON_SQRDMULH_byelement_scalar:
5227  Op = &Simulator::sqrdmulh;
5228  vf = vf_r;
5229  break;
5230  default:
5231  vf = nfd.GetVectorFormat(nfd.FPScalarFormatMap());
5232  index = instr->NEONH();
5233  if ((instr->FPType() & 1) == 0) {
5234  index = (index << 1) | instr->NEONL();
5235  }
5236  switch (instr->Mask(NEONScalarByIndexedElementFPMask)) {
5237  case NEON_FMUL_byelement_scalar:
5238  Op = &Simulator::fmul;
5239  break;
5240  case NEON_FMLA_byelement_scalar:
5241  Op = &Simulator::fmla;
5242  break;
5243  case NEON_FMLS_byelement_scalar:
5244  Op = &Simulator::fmls;
5245  break;
5246  case NEON_FMULX_byelement_scalar:
5247  Op = &Simulator::fmulx;
5248  break;
5249  default:
5250  UNIMPLEMENTED();
5251  }
5252  }
5253 
5254  (this->*Op)(vf, rd, rn, vreg(rm_reg), index);
5255 }
5256 
5257 void Simulator::VisitNEONScalarCopy(Instruction* instr) {
5258  NEONFormatDecoder nfd(instr, NEONFormatDecoder::TriangularScalarFormatMap());
5259  VectorFormat vf = nfd.GetVectorFormat();
5260 
5261  SimVRegister& rd = vreg(instr->Rd());
5262  SimVRegister& rn = vreg(instr->Rn());
5263 
5264  if (instr->Mask(NEONScalarCopyMask) == NEON_DUP_ELEMENT_scalar) {
5265  int imm5 = instr->ImmNEON5();
5266  int lsb = LowestSetBitPosition(imm5);
5267  int rn_index = imm5 >> lsb;
5268  dup_element(vf, rd, rn, rn_index);
5269  } else {
5270  UNIMPLEMENTED();
5271  }
5272 }
5273 
5274 void Simulator::VisitNEONScalarPairwise(Instruction* instr) {
5275  NEONFormatDecoder nfd(instr, NEONFormatDecoder::FPScalarFormatMap());
5276  VectorFormat vf = nfd.GetVectorFormat();
5277 
5278  SimVRegister& rd = vreg(instr->Rd());
5279  SimVRegister& rn = vreg(instr->Rn());
5280  switch (instr->Mask(NEONScalarPairwiseMask)) {
5281  case NEON_ADDP_scalar:
5282  addp(vf, rd, rn);
5283  break;
5284  case NEON_FADDP_scalar:
5285  faddp(vf, rd, rn);
5286  break;
5287  case NEON_FMAXP_scalar:
5288  fmaxp(vf, rd, rn);
5289  break;
5290  case NEON_FMAXNMP_scalar:
5291  fmaxnmp(vf, rd, rn);
5292  break;
5293  case NEON_FMINP_scalar:
5294  fminp(vf, rd, rn);
5295  break;
5296  case NEON_FMINNMP_scalar:
5297  fminnmp(vf, rd, rn);
5298  break;
5299  default:
5300  UNIMPLEMENTED();
5301  }
5302 }
5303 
5304 void Simulator::VisitNEONScalarShiftImmediate(Instruction* instr) {
5305  SimVRegister& rd = vreg(instr->Rd());
5306  SimVRegister& rn = vreg(instr->Rn());
5307  FPRounding fpcr_rounding = static_cast<FPRounding>(fpcr().RMode());
5308 
5309  static const NEONFormatMap map = {
5310  {22, 21, 20, 19},
5311  {NF_UNDEF, NF_B, NF_H, NF_H, NF_S, NF_S, NF_S, NF_S, NF_D, NF_D, NF_D,
5312  NF_D, NF_D, NF_D, NF_D, NF_D}};
5313  NEONFormatDecoder nfd(instr, &map);
5314  VectorFormat vf = nfd.GetVectorFormat();
5315 
5316  int highestSetBit = HighestSetBitPosition(instr->ImmNEONImmh());
5317  int immhimmb = instr->ImmNEONImmhImmb();
5318  int right_shift = (16 << highestSetBit) - immhimmb;
5319  int left_shift = immhimmb - (8 << highestSetBit);
5320  switch (instr->Mask(NEONScalarShiftImmediateMask)) {
5321  case NEON_SHL_scalar:
5322  shl(vf, rd, rn, left_shift);
5323  break;
5324  case NEON_SLI_scalar:
5325  sli(vf, rd, rn, left_shift);
5326  break;
5327  case NEON_SQSHL_imm_scalar:
5328  sqshl(vf, rd, rn, left_shift);
5329  break;
5330  case NEON_UQSHL_imm_scalar:
5331  uqshl(vf, rd, rn, left_shift);
5332  break;
5333  case NEON_SQSHLU_scalar:
5334  sqshlu(vf, rd, rn, left_shift);
5335  break;
5336  case NEON_SRI_scalar:
5337  sri(vf, rd, rn, right_shift);
5338  break;
5339  case NEON_SSHR_scalar:
5340  sshr(vf, rd, rn, right_shift);
5341  break;
5342  case NEON_USHR_scalar:
5343  ushr(vf, rd, rn, right_shift);
5344  break;
5345  case NEON_SRSHR_scalar:
5346  sshr(vf, rd, rn, right_shift).Round(vf);
5347  break;
5348  case NEON_URSHR_scalar:
5349  ushr(vf, rd, rn, right_shift).Round(vf);
5350  break;
5351  case NEON_SSRA_scalar:
5352  ssra(vf, rd, rn, right_shift);
5353  break;
5354  case NEON_USRA_scalar:
5355  usra(vf, rd, rn, right_shift);
5356  break;
5357  case NEON_SRSRA_scalar:
5358  srsra(vf, rd, rn, right_shift);
5359  break;
5360  case NEON_URSRA_scalar:
5361  ursra(vf, rd, rn, right_shift);
5362  break;
5363  case NEON_UQSHRN_scalar:
5364  uqshrn(vf, rd, rn, right_shift);
5365  break;
5366  case NEON_UQRSHRN_scalar:
5367  uqrshrn(vf, rd, rn, right_shift);
5368  break;
5369  case NEON_SQSHRN_scalar:
5370  sqshrn(vf, rd, rn, right_shift);
5371  break;
5372  case NEON_SQRSHRN_scalar:
5373  sqrshrn(vf, rd, rn, right_shift);
5374  break;
5375  case NEON_SQSHRUN_scalar:
5376  sqshrun(vf, rd, rn, right_shift);
5377  break;
5378  case NEON_SQRSHRUN_scalar:
5379  sqrshrun(vf, rd, rn, right_shift);
5380  break;
5381  case NEON_FCVTZS_imm_scalar:
5382  fcvts(vf, rd, rn, FPZero, right_shift);
5383  break;
5384  case NEON_FCVTZU_imm_scalar:
5385  fcvtu(vf, rd, rn, FPZero, right_shift);
5386  break;
5387  case NEON_SCVTF_imm_scalar:
5388  scvtf(vf, rd, rn, right_shift, fpcr_rounding);
5389  break;
5390  case NEON_UCVTF_imm_scalar:
5391  ucvtf(vf, rd, rn, right_shift, fpcr_rounding);
5392  break;
5393  default:
5394  UNIMPLEMENTED();
5395  }
5396 }
5397 
5398 void Simulator::VisitNEONShiftImmediate(Instruction* instr) {
5399  SimVRegister& rd = vreg(instr->Rd());
5400  SimVRegister& rn = vreg(instr->Rn());
5401  FPRounding fpcr_rounding = static_cast<FPRounding>(fpcr().RMode());
5402 
5403  // 00010->8B, 00011->16B, 001x0->4H, 001x1->8H,
5404  // 01xx0->2S, 01xx1->4S, 1xxx1->2D, all others undefined.
5405  static const NEONFormatMap map = {
5406  {22, 21, 20, 19, 30},
5407  {NF_UNDEF, NF_UNDEF, NF_8B, NF_16B, NF_4H, NF_8H, NF_4H, NF_8H,
5408  NF_2S, NF_4S, NF_2S, NF_4S, NF_2S, NF_4S, NF_2S, NF_4S,
5409  NF_UNDEF, NF_2D, NF_UNDEF, NF_2D, NF_UNDEF, NF_2D, NF_UNDEF, NF_2D,
5410  NF_UNDEF, NF_2D, NF_UNDEF, NF_2D, NF_UNDEF, NF_2D, NF_UNDEF, NF_2D}};
5411  NEONFormatDecoder nfd(instr, &map);
5412  VectorFormat vf = nfd.GetVectorFormat();
5413 
5414  // 0001->8H, 001x->4S, 01xx->2D, all others undefined.
5415  static const NEONFormatMap map_l = {
5416  {22, 21, 20, 19},
5417  {NF_UNDEF, NF_8H, NF_4S, NF_4S, NF_2D, NF_2D, NF_2D, NF_2D}};
5418  VectorFormat vf_l = nfd.GetVectorFormat(&map_l);
5419 
5420  int highestSetBit = HighestSetBitPosition(instr->ImmNEONImmh());
5421  int immhimmb = instr->ImmNEONImmhImmb();
5422  int right_shift = (16 << highestSetBit) - immhimmb;
5423  int left_shift = immhimmb - (8 << highestSetBit);
5424 
5425  switch (instr->Mask(NEONShiftImmediateMask)) {
5426  case NEON_SHL:
5427  shl(vf, rd, rn, left_shift);
5428  break;
5429  case NEON_SLI:
5430  sli(vf, rd, rn, left_shift);
5431  break;
5432  case NEON_SQSHLU:
5433  sqshlu(vf, rd, rn, left_shift);
5434  break;
5435  case NEON_SRI:
5436  sri(vf, rd, rn, right_shift);
5437  break;
5438  case NEON_SSHR:
5439  sshr(vf, rd, rn, right_shift);
5440  break;
5441  case NEON_USHR:
5442  ushr(vf, rd, rn, right_shift);
5443  break;
5444  case NEON_SRSHR:
5445  sshr(vf, rd, rn, right_shift).Round(vf);
5446  break;
5447  case NEON_URSHR:
5448  ushr(vf, rd, rn, right_shift).Round(vf);
5449  break;
5450  case NEON_SSRA:
5451  ssra(vf, rd, rn, right_shift);
5452  break;
5453  case NEON_USRA:
5454  usra(vf, rd, rn, right_shift);
5455  break;
5456  case NEON_SRSRA:
5457  srsra(vf, rd, rn, right_shift);
5458  break;
5459  case NEON_URSRA:
5460  ursra(vf, rd, rn, right_shift);
5461  break;
5462  case NEON_SQSHL_imm:
5463  sqshl(vf, rd, rn, left_shift);
5464  break;
5465  case NEON_UQSHL_imm:
5466  uqshl(vf, rd, rn, left_shift);
5467  break;
5468  case NEON_SCVTF_imm:
5469  scvtf(vf, rd, rn, right_shift, fpcr_rounding);
5470  break;
5471  case NEON_UCVTF_imm:
5472  ucvtf(vf, rd, rn, right_shift, fpcr_rounding);
5473  break;
5474  case NEON_FCVTZS_imm:
5475  fcvts(vf, rd, rn, FPZero, right_shift);
5476  break;
5477  case NEON_FCVTZU_imm:
5478  fcvtu(vf, rd, rn, FPZero, right_shift);
5479  break;
5480  case NEON_SSHLL:
5481  vf = vf_l;
5482  if (instr->Mask(NEON_Q)) {
5483  sshll2(vf, rd, rn, left_shift);
5484  } else {
5485  sshll(vf, rd, rn, left_shift);
5486  }
5487  break;
5488  case NEON_USHLL:
5489  vf = vf_l;
5490  if (instr->Mask(NEON_Q)) {
5491  ushll2(vf, rd, rn, left_shift);
5492  } else {
5493  ushll(vf, rd, rn, left_shift);
5494  }
5495  break;
5496  case NEON_SHRN:
5497  if (instr->Mask(NEON_Q)) {
5498  shrn2(vf, rd, rn, right_shift);
5499  } else {
5500  shrn(vf, rd, rn, right_shift);
5501  }
5502  break;
5503  case NEON_RSHRN:
5504  if (instr->Mask(NEON_Q)) {
5505  rshrn2(vf, rd, rn, right_shift);
5506  } else {
5507  rshrn(vf, rd, rn, right_shift);
5508  }
5509  break;
5510  case NEON_UQSHRN:
5511  if (instr->Mask(NEON_Q)) {
5512  uqshrn2(vf, rd, rn, right_shift);
5513  } else {
5514  uqshrn(vf, rd, rn, right_shift);
5515  }
5516  break;
5517  case NEON_UQRSHRN:
5518  if (instr->Mask(NEON_Q)) {
5519  uqrshrn2(vf, rd, rn, right_shift);
5520  } else {
5521  uqrshrn(vf, rd, rn, right_shift);
5522  }
5523  break;
5524  case NEON_SQSHRN:
5525  if (instr->Mask(NEON_Q)) {
5526  sqshrn2(vf, rd, rn, right_shift);
5527  } else {
5528  sqshrn(vf, rd, rn, right_shift);
5529  }
5530  break;
5531  case NEON_SQRSHRN:
5532  if (instr->Mask(NEON_Q)) {
5533  sqrshrn2(vf, rd, rn, right_shift);
5534  } else {
5535  sqrshrn(vf, rd, rn, right_shift);
5536  }
5537  break;
5538  case NEON_SQSHRUN:
5539  if (instr->Mask(NEON_Q)) {
5540  sqshrun2(vf, rd, rn, right_shift);
5541  } else {
5542  sqshrun(vf, rd, rn, right_shift);
5543  }
5544  break;
5545  case NEON_SQRSHRUN:
5546  if (instr->Mask(NEON_Q)) {
5547  sqrshrun2(vf, rd, rn, right_shift);
5548  } else {
5549  sqrshrun(vf, rd, rn, right_shift);
5550  }
5551  break;
5552  default:
5553  UNIMPLEMENTED();
5554  }
5555 }
5556 
5557 void Simulator::VisitNEONTable(Instruction* instr) {
5558  NEONFormatDecoder nfd(instr, NEONFormatDecoder::LogicalFormatMap());
5559  VectorFormat vf = nfd.GetVectorFormat();
5560 
5561  SimVRegister& rd = vreg(instr->Rd());
5562  SimVRegister& rn = vreg(instr->Rn());
5563  SimVRegister& rn2 = vreg((instr->Rn() + 1) % kNumberOfVRegisters);
5564  SimVRegister& rn3 = vreg((instr->Rn() + 2) % kNumberOfVRegisters);
5565  SimVRegister& rn4 = vreg((instr->Rn() + 3) % kNumberOfVRegisters);
5566  SimVRegister& rm = vreg(instr->Rm());
5567 
5568  switch (instr->Mask(NEONTableMask)) {
5569  case NEON_TBL_1v:
5570  tbl(vf, rd, rn, rm);
5571  break;
5572  case NEON_TBL_2v:
5573  tbl(vf, rd, rn, rn2, rm);
5574  break;
5575  case NEON_TBL_3v:
5576  tbl(vf, rd, rn, rn2, rn3, rm);
5577  break;
5578  case NEON_TBL_4v:
5579  tbl(vf, rd, rn, rn2, rn3, rn4, rm);
5580  break;
5581  case NEON_TBX_1v:
5582  tbx(vf, rd, rn, rm);
5583  break;
5584  case NEON_TBX_2v:
5585  tbx(vf, rd, rn, rn2, rm);
5586  break;
5587  case NEON_TBX_3v:
5588  tbx(vf, rd, rn, rn2, rn3, rm);
5589  break;
5590  case NEON_TBX_4v:
5591  tbx(vf, rd, rn, rn2, rn3, rn4, rm);
5592  break;
5593  default:
5594  UNIMPLEMENTED();
5595  }
5596 }
5597 
5598 void Simulator::VisitNEONPerm(Instruction* instr) {
5599  NEONFormatDecoder nfd(instr);
5600  VectorFormat vf = nfd.GetVectorFormat();
5601 
5602  SimVRegister& rd = vreg(instr->Rd());
5603  SimVRegister& rn = vreg(instr->Rn());
5604  SimVRegister& rm = vreg(instr->Rm());
5605 
5606  switch (instr->Mask(NEONPermMask)) {
5607  case NEON_TRN1:
5608  trn1(vf, rd, rn, rm);
5609  break;
5610  case NEON_TRN2:
5611  trn2(vf, rd, rn, rm);
5612  break;
5613  case NEON_UZP1:
5614  uzp1(vf, rd, rn, rm);
5615  break;
5616  case NEON_UZP2:
5617  uzp2(vf, rd, rn, rm);
5618  break;
5619  case NEON_ZIP1:
5620  zip1(vf, rd, rn, rm);
5621  break;
5622  case NEON_ZIP2:
5623  zip2(vf, rd, rn, rm);
5624  break;
5625  default:
5626  UNIMPLEMENTED();
5627  }
5628 }
5629 
5630 void Simulator::DoPrintf(Instruction* instr) {
5631  DCHECK((instr->Mask(ExceptionMask) == HLT) &&
5632  (instr->ImmException() == kImmExceptionIsPrintf));
5633 
5634  // Read the arguments encoded inline in the instruction stream.
5635  uint32_t arg_count;
5636  uint32_t arg_pattern_list;
5637  STATIC_ASSERT(sizeof(*instr) == 1);
5638  memcpy(&arg_count,
5639  instr + kPrintfArgCountOffset,
5640  sizeof(arg_count));
5641  memcpy(&arg_pattern_list,
5642  instr + kPrintfArgPatternListOffset,
5643  sizeof(arg_pattern_list));
5644 
5645  DCHECK_LE(arg_count, kPrintfMaxArgCount);
5646  DCHECK_EQ(arg_pattern_list >> (kPrintfArgPatternBits * arg_count), 0);
5647 
5648  // We need to call the host printf function with a set of arguments defined by
5649  // arg_pattern_list. Because we don't know the types and sizes of the
5650  // arguments, this is very difficult to do in a robust and portable way. To
5651  // work around the problem, we pick apart the format string, and print one
5652  // format placeholder at a time.
5653 
5654  // Allocate space for the format string. We take a copy, so we can modify it.
5655  // Leave enough space for one extra character per expected argument (plus the
5656  // '\0' termination).
5657  const char * format_base = reg<const char *>(0);
5658  DCHECK_NOT_NULL(format_base);
5659  size_t length = strlen(format_base) + 1;
5660  char * const format = new char[length + arg_count];
5661 
5662  // A list of chunks, each with exactly one format placeholder.
5663  const char * chunks[kPrintfMaxArgCount];
5664 
5665  // Copy the format string and search for format placeholders.
5666  uint32_t placeholder_count = 0;
5667  char * format_scratch = format;
5668  for (size_t i = 0; i < length; i++) {
5669  if (format_base[i] != '%') {
5670  *format_scratch++ = format_base[i];
5671  } else {
5672  if (format_base[i + 1] == '%') {
5673  // Ignore explicit "%%" sequences.
5674  *format_scratch++ = format_base[i];
5675 
5676  if (placeholder_count == 0) {
5677  // The first chunk is passed to printf using "%s", so we need to
5678  // unescape "%%" sequences in this chunk. (Just skip the next '%'.)
5679  i++;
5680  } else {
5681  // Otherwise, pass through "%%" unchanged.
5682  *format_scratch++ = format_base[++i];
5683  }
5684  } else {
5685  CHECK(placeholder_count < arg_count);
5686  // Insert '\0' before placeholders, and store their locations.
5687  *format_scratch++ = '\0';
5688  chunks[placeholder_count++] = format_scratch;
5689  *format_scratch++ = format_base[i];
5690  }
5691  }
5692  }
5693  DCHECK(format_scratch <= (format + length + arg_count));
5694  CHECK(placeholder_count == arg_count);
5695 
5696  // Finally, call printf with each chunk, passing the appropriate register
5697  // argument. Normally, printf returns the number of bytes transmitted, so we
5698  // can emulate a single printf call by adding the result from each chunk. If
5699  // any call returns a negative (error) value, though, just return that value.
5700 
5701  fprintf(stream_, "%s", clr_printf);
5702 
5703  // Because '\0' is inserted before each placeholder, the first string in
5704  // 'format' contains no format placeholders and should be printed literally.
5705  int result = fprintf(stream_, "%s", format);
5706  int pcs_r = 1; // Start at x1. x0 holds the format string.
5707  int pcs_f = 0; // Start at d0.
5708  if (result >= 0) {
5709  for (uint32_t i = 0; i < placeholder_count; i++) {
5710  int part_result = -1;
5711 
5712  uint32_t arg_pattern = arg_pattern_list >> (i * kPrintfArgPatternBits);
5713  arg_pattern &= (1 << kPrintfArgPatternBits) - 1;
5714  switch (arg_pattern) {
5715  case kPrintfArgW:
5716  part_result = fprintf(stream_, chunks[i], wreg(pcs_r++));
5717  break;
5718  case kPrintfArgX:
5719  part_result = fprintf(stream_, chunks[i], xreg(pcs_r++));
5720  break;
5721  case kPrintfArgD:
5722  part_result = fprintf(stream_, chunks[i], dreg(pcs_f++));
5723  break;
5724  default: UNREACHABLE();
5725  }
5726 
5727  if (part_result < 0) {
5728  // Handle error values.
5729  result = part_result;
5730  break;
5731  }
5732 
5733  result += part_result;
5734  }
5735  }
5736 
5737  fprintf(stream_, "%s", clr_normal);
5738 
5739 #ifdef DEBUG
5740  CorruptAllCallerSavedCPURegisters();
5741 #endif
5742 
5743  // Printf returns its result in x0 (just like the C library's printf).
5744  set_xreg(0, result);
5745 
5746  // The printf parameters are inlined in the code, so skip them.
5747  set_pc(instr->InstructionAtOffset(kPrintfLength));
5748 
5749  // Set LR as if we'd just called a native printf function.
5750  set_lr(pc());
5751 
5752  delete[] format;
5753 }
5754 
5755 Simulator::LocalMonitor::LocalMonitor()
5756  : access_state_(MonitorAccess::Open),
5757  tagged_addr_(0),
5758  size_(TransactionSize::None) {}
5759 
5760 void Simulator::LocalMonitor::Clear() {
5761  access_state_ = MonitorAccess::Open;
5762  tagged_addr_ = 0;
5763  size_ = TransactionSize::None;
5764 }
5765 
5766 void Simulator::LocalMonitor::NotifyLoad() {
5767  if (access_state_ == MonitorAccess::Exclusive) {
5768  // A non exclusive load could clear the local monitor. As a result, it's
5769  // most strict to unconditionally clear the local monitor on load.
5770  Clear();
5771  }
5772 }
5773 
5774 void Simulator::LocalMonitor::NotifyLoadExcl(uintptr_t addr,
5775  TransactionSize size) {
5776  access_state_ = MonitorAccess::Exclusive;
5777  tagged_addr_ = addr;
5778  size_ = size;
5779 }
5780 
5781 void Simulator::LocalMonitor::NotifyStore() {
5782  if (access_state_ == MonitorAccess::Exclusive) {
5783  // A non exclusive store could clear the local monitor. As a result, it's
5784  // most strict to unconditionally clear the local monitor on store.
5785  Clear();
5786  }
5787 }
5788 
5789 bool Simulator::LocalMonitor::NotifyStoreExcl(uintptr_t addr,
5790  TransactionSize size) {
5791  if (access_state_ == MonitorAccess::Exclusive) {
5792  // It is allowed for a processor to require that the address matches
5793  // exactly (B2.10.1), so this comparison does not mask addr.
5794  if (addr == tagged_addr_ && size_ == size) {
5795  Clear();
5796  return true;
5797  } else {
5798  // It is implementation-defined whether an exclusive store to a
5799  // non-tagged address will update memory. As a result, it's most strict
5800  // to unconditionally clear the local monitor.
5801  Clear();
5802  return false;
5803  }
5804  } else {
5805  DCHECK(access_state_ == MonitorAccess::Open);
5806  return false;
5807  }
5808 }
5809 
5810 Simulator::GlobalMonitor::Processor::Processor()
5811  : access_state_(MonitorAccess::Open),
5812  tagged_addr_(0),
5813  next_(nullptr),
5814  prev_(nullptr),
5815  failure_counter_(0) {}
5816 
5817 void Simulator::GlobalMonitor::Processor::Clear_Locked() {
5818  access_state_ = MonitorAccess::Open;
5819  tagged_addr_ = 0;
5820 }
5821 
5822 void Simulator::GlobalMonitor::Processor::NotifyLoadExcl_Locked(
5823  uintptr_t addr) {
5824  access_state_ = MonitorAccess::Exclusive;
5825  tagged_addr_ = addr;
5826 }
5827 
5828 void Simulator::GlobalMonitor::Processor::NotifyStore_Locked(
5829  bool is_requesting_processor) {
5830  if (access_state_ == MonitorAccess::Exclusive) {
5831  // A non exclusive store could clear the global monitor. As a result, it's
5832  // most strict to unconditionally clear global monitors on store.
5833  Clear_Locked();
5834  }
5835 }
5836 
5837 bool Simulator::GlobalMonitor::Processor::NotifyStoreExcl_Locked(
5838  uintptr_t addr, bool is_requesting_processor) {
5839  if (access_state_ == MonitorAccess::Exclusive) {
5840  if (is_requesting_processor) {
5841  // It is allowed for a processor to require that the address matches
5842  // exactly (B2.10.2), so this comparison does not mask addr.
5843  if (addr == tagged_addr_) {
5844  Clear_Locked();
5845  // Introduce occasional stxr failures. This is to simulate the
5846  // behavior of hardware, which can randomly fail due to background
5847  // cache evictions.
5848  if (failure_counter_++ >= kMaxFailureCounter) {
5849  failure_counter_ = 0;
5850  return false;
5851  } else {
5852  return true;
5853  }
5854  }
5855  } else if ((addr & kExclusiveTaggedAddrMask) ==
5856  (tagged_addr_ & kExclusiveTaggedAddrMask)) {
5857  // Check the masked addresses when responding to a successful lock by
5858  // another processor so the implementation is more conservative (i.e. the
5859  // granularity of locking is as large as possible.)
5860  Clear_Locked();
5861  return false;
5862  }
5863  }
5864  return false;
5865 }
5866 
5867 Simulator::GlobalMonitor::GlobalMonitor() : head_(nullptr) {}
5868 
5869 void Simulator::GlobalMonitor::NotifyLoadExcl_Locked(uintptr_t addr,
5870  Processor* processor) {
5871  processor->NotifyLoadExcl_Locked(addr);
5872  PrependProcessor_Locked(processor);
5873 }
5874 
5875 void Simulator::GlobalMonitor::NotifyStore_Locked(Processor* processor) {
5876  // Notify each processor of the store operation.
5877  for (Processor* iter = head_; iter; iter = iter->next_) {
5878  bool is_requesting_processor = iter == processor;
5879  iter->NotifyStore_Locked(is_requesting_processor);
5880  }
5881 }
5882 
5883 bool Simulator::GlobalMonitor::NotifyStoreExcl_Locked(uintptr_t addr,
5884  Processor* processor) {
5885  DCHECK(IsProcessorInLinkedList_Locked(processor));
5886  if (processor->NotifyStoreExcl_Locked(addr, true)) {
5887  // Notify the other processors that this StoreExcl succeeded.
5888  for (Processor* iter = head_; iter; iter = iter->next_) {
5889  if (iter != processor) {
5890  iter->NotifyStoreExcl_Locked(addr, false);
5891  }
5892  }
5893  return true;
5894  } else {
5895  return false;
5896  }
5897 }
5898 
5899 bool Simulator::GlobalMonitor::IsProcessorInLinkedList_Locked(
5900  Processor* processor) const {
5901  return head_ == processor || processor->next_ || processor->prev_;
5902 }
5903 
5904 void Simulator::GlobalMonitor::PrependProcessor_Locked(Processor* processor) {
5905  if (IsProcessorInLinkedList_Locked(processor)) {
5906  return;
5907  }
5908 
5909  if (head_) {
5910  head_->prev_ = processor;
5911  }
5912  processor->prev_ = nullptr;
5913  processor->next_ = head_;
5914  head_ = processor;
5915 }
5916 
5917 void Simulator::GlobalMonitor::RemoveProcessor(Processor* processor) {
5918  base::MutexGuard lock_guard(&mutex);
5919  if (!IsProcessorInLinkedList_Locked(processor)) {
5920  return;
5921  }
5922 
5923  if (processor->prev_) {
5924  processor->prev_->next_ = processor->next_;
5925  } else {
5926  head_ = processor->next_;
5927  }
5928  if (processor->next_) {
5929  processor->next_->prev_ = processor->prev_;
5930  }
5931  processor->prev_ = nullptr;
5932  processor->next_ = nullptr;
5933 }
5934 
5935 #endif // USE_SIMULATOR
5936 
5937 } // namespace internal
5938 } // namespace v8
5939 
5940 #endif // V8_TARGET_ARCH_ARM64
Definition: libplatform.h:13
Definition: v8.h:3134