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