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 blacklisting. 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 FMOV_ws:
2760       set_wreg(dst, sreg_bits(src));
2761       break;
2762     case FMOV_xd:
2763       set_xreg(dst, dreg_bits(src));
2764       break;
2765     case FMOV_sw:
2766       set_sreg_bits(dst, wreg(src));
2767       break;
2768     case FMOV_dx:
2769       set_dreg_bits(dst, xreg(src));
2770       break;
2771 
2772     // A 32-bit input can be handled in the same way as a 64-bit input, since
2773     // the sign- or zero-extension will not affect the conversion.
2774     case SCVTF_dx:
2775       set_dreg(dst, FixedToDouble(xreg(src), 0, round));
2776       break;
2777     case SCVTF_dw:
2778       set_dreg(dst, FixedToDouble(wreg(src), 0, round));
2779       break;
2780     case UCVTF_dx:
2781       set_dreg(dst, UFixedToDouble(xreg(src), 0, round));
2782       break;
2783     case UCVTF_dw: {
2784       set_dreg(dst, UFixedToDouble(reg<uint32_t>(src), 0, round));
2785       break;
2786     }
2787     case SCVTF_sx:
2788       set_sreg(dst, FixedToFloat(xreg(src), 0, round));
2789       break;
2790     case SCVTF_sw:
2791       set_sreg(dst, FixedToFloat(wreg(src), 0, round));
2792       break;
2793     case UCVTF_sx:
2794       set_sreg(dst, UFixedToFloat(xreg(src), 0, round));
2795       break;
2796     case UCVTF_sw: {
2797       set_sreg(dst, UFixedToFloat(reg<uint32_t>(src), 0, round));
2798       break;
2799     }
2800 
2801     default:
2802       UNREACHABLE();
2803   }
2804 }
2805 
VisitFPFixedPointConvert(Instruction * instr)2806 void Simulator::VisitFPFixedPointConvert(Instruction* instr) {
2807   AssertSupportedFPCR();
2808 
2809   unsigned dst = instr->Rd();
2810   unsigned src = instr->Rn();
2811   int fbits = 64 - instr->FPScale();
2812 
2813   FPRounding round = fpcr().RMode();
2814 
2815   switch (instr->Mask(FPFixedPointConvertMask)) {
2816     // A 32-bit input can be handled in the same way as a 64-bit input, since
2817     // the sign- or zero-extension will not affect the conversion.
2818     case SCVTF_dx_fixed:
2819       set_dreg(dst, FixedToDouble(xreg(src), fbits, round));
2820       break;
2821     case SCVTF_dw_fixed:
2822       set_dreg(dst, FixedToDouble(wreg(src), fbits, round));
2823       break;
2824     case UCVTF_dx_fixed:
2825       set_dreg(dst, UFixedToDouble(xreg(src), fbits, round));
2826       break;
2827     case UCVTF_dw_fixed: {
2828       set_dreg(dst, UFixedToDouble(reg<uint32_t>(src), fbits, round));
2829       break;
2830     }
2831     case SCVTF_sx_fixed:
2832       set_sreg(dst, FixedToFloat(xreg(src), fbits, round));
2833       break;
2834     case SCVTF_sw_fixed:
2835       set_sreg(dst, FixedToFloat(wreg(src), fbits, round));
2836       break;
2837     case UCVTF_sx_fixed:
2838       set_sreg(dst, UFixedToFloat(xreg(src), fbits, round));
2839       break;
2840     case UCVTF_sw_fixed: {
2841       set_sreg(dst, UFixedToFloat(reg<uint32_t>(src), fbits, round));
2842       break;
2843     }
2844     default:
2845       UNREACHABLE();
2846   }
2847 }
2848 
VisitFPCompare(Instruction * instr)2849 void Simulator::VisitFPCompare(Instruction* instr) {
2850   AssertSupportedFPCR();
2851 
2852   switch (instr->Mask(FPCompareMask)) {
2853     case FCMP_s:
2854       FPCompare(sreg(instr->Rn()), sreg(instr->Rm()));
2855       break;
2856     case FCMP_d:
2857       FPCompare(dreg(instr->Rn()), dreg(instr->Rm()));
2858       break;
2859     case FCMP_s_zero:
2860       FPCompare(sreg(instr->Rn()), 0.0f);
2861       break;
2862     case FCMP_d_zero:
2863       FPCompare(dreg(instr->Rn()), 0.0);
2864       break;
2865     default:
2866       UNIMPLEMENTED();
2867   }
2868 }
2869 
VisitFPConditionalCompare(Instruction * instr)2870 void Simulator::VisitFPConditionalCompare(Instruction* instr) {
2871   AssertSupportedFPCR();
2872 
2873   switch (instr->Mask(FPConditionalCompareMask)) {
2874     case FCCMP_s:
2875       if (ConditionPassed(static_cast<Condition>(instr->Condition()))) {
2876         FPCompare(sreg(instr->Rn()), sreg(instr->Rm()));
2877       } else {
2878         nzcv().SetFlags(instr->Nzcv());
2879         LogSystemRegister(NZCV);
2880       }
2881       break;
2882     case FCCMP_d: {
2883       if (ConditionPassed(static_cast<Condition>(instr->Condition()))) {
2884         FPCompare(dreg(instr->Rn()), dreg(instr->Rm()));
2885       } else {
2886         // If the condition fails, set the status flags to the nzcv immediate.
2887         nzcv().SetFlags(instr->Nzcv());
2888         LogSystemRegister(NZCV);
2889       }
2890       break;
2891     }
2892     default:
2893       UNIMPLEMENTED();
2894   }
2895 }
2896 
VisitFPConditionalSelect(Instruction * instr)2897 void Simulator::VisitFPConditionalSelect(Instruction* instr) {
2898   AssertSupportedFPCR();
2899 
2900   Instr selected;
2901   if (ConditionPassed(static_cast<Condition>(instr->Condition()))) {
2902     selected = instr->Rn();
2903   } else {
2904     selected = instr->Rm();
2905   }
2906 
2907   switch (instr->Mask(FPConditionalSelectMask)) {
2908     case FCSEL_s:
2909       set_sreg(instr->Rd(), sreg(selected));
2910       break;
2911     case FCSEL_d:
2912       set_dreg(instr->Rd(), dreg(selected));
2913       break;
2914     default:
2915       UNIMPLEMENTED();
2916   }
2917 }
2918 
VisitFPDataProcessing1Source(Instruction * instr)2919 void Simulator::VisitFPDataProcessing1Source(Instruction* instr) {
2920   AssertSupportedFPCR();
2921 
2922   FPRounding fpcr_rounding = static_cast<FPRounding>(fpcr().RMode());
2923   VectorFormat vform = (instr->Mask(FP64) == FP64) ? kFormatD : kFormatS;
2924   SimVRegister& rd = vreg(instr->Rd());
2925   SimVRegister& rn = vreg(instr->Rn());
2926   bool inexact_exception = false;
2927 
2928   unsigned fd = instr->Rd();
2929   unsigned fn = instr->Rn();
2930 
2931   switch (instr->Mask(FPDataProcessing1SourceMask)) {
2932     case FMOV_s:
2933       set_sreg(fd, sreg(fn));
2934       return;
2935     case FMOV_d:
2936       set_dreg(fd, dreg(fn));
2937       return;
2938     case FABS_s:
2939     case FABS_d:
2940       fabs_(vform, vreg(fd), vreg(fn));
2941       // Explicitly log the register update whilst we have type information.
2942       LogVRegister(fd, GetPrintRegisterFormatFP(vform));
2943       return;
2944     case FNEG_s:
2945     case FNEG_d:
2946       fneg(vform, vreg(fd), vreg(fn));
2947       // Explicitly log the register update whilst we have type information.
2948       LogVRegister(fd, GetPrintRegisterFormatFP(vform));
2949       return;
2950     case FCVT_ds:
2951       set_dreg(fd, FPToDouble(sreg(fn)));
2952       return;
2953     case FCVT_sd:
2954       set_sreg(fd, FPToFloat(dreg(fn), FPTieEven));
2955       return;
2956     case FCVT_hs:
2957       set_hreg(fd, FPToFloat16(sreg(fn), FPTieEven));
2958       return;
2959     case FCVT_sh:
2960       set_sreg(fd, FPToFloat(hreg(fn)));
2961       return;
2962     case FCVT_dh:
2963       set_dreg(fd, FPToDouble(FPToFloat(hreg(fn))));
2964       return;
2965     case FCVT_hd:
2966       set_hreg(fd, FPToFloat16(dreg(fn), FPTieEven));
2967       return;
2968     case FSQRT_s:
2969     case FSQRT_d:
2970       fsqrt(vform, rd, rn);
2971       // Explicitly log the register update whilst we have type information.
2972       LogVRegister(fd, GetPrintRegisterFormatFP(vform));
2973       return;
2974     case FRINTI_s:
2975     case FRINTI_d:
2976       break;  // Use FPCR rounding mode.
2977     case FRINTX_s:
2978     case FRINTX_d:
2979       inexact_exception = true;
2980       break;
2981     case FRINTA_s:
2982     case FRINTA_d:
2983       fpcr_rounding = FPTieAway;
2984       break;
2985     case FRINTM_s:
2986     case FRINTM_d:
2987       fpcr_rounding = FPNegativeInfinity;
2988       break;
2989     case FRINTN_s:
2990     case FRINTN_d:
2991       fpcr_rounding = FPTieEven;
2992       break;
2993     case FRINTP_s:
2994     case FRINTP_d:
2995       fpcr_rounding = FPPositiveInfinity;
2996       break;
2997     case FRINTZ_s:
2998     case FRINTZ_d:
2999       fpcr_rounding = FPZero;
3000       break;
3001     default:
3002       UNIMPLEMENTED();
3003   }
3004 
3005   // Only FRINT* instructions fall through the switch above.
3006   frint(vform, rd, rn, fpcr_rounding, inexact_exception);
3007   // Explicitly log the register update whilst we have type information
3008   LogVRegister(fd, GetPrintRegisterFormatFP(vform));
3009 }
3010 
VisitFPDataProcessing2Source(Instruction * instr)3011 void Simulator::VisitFPDataProcessing2Source(Instruction* instr) {
3012   AssertSupportedFPCR();
3013 
3014   VectorFormat vform = (instr->Mask(FP64) == FP64) ? kFormatD : kFormatS;
3015   SimVRegister& rd = vreg(instr->Rd());
3016   SimVRegister& rn = vreg(instr->Rn());
3017   SimVRegister& rm = vreg(instr->Rm());
3018 
3019   switch (instr->Mask(FPDataProcessing2SourceMask)) {
3020     case FADD_s:
3021     case FADD_d:
3022       fadd(vform, rd, rn, rm);
3023       break;
3024     case FSUB_s:
3025     case FSUB_d:
3026       fsub(vform, rd, rn, rm);
3027       break;
3028     case FMUL_s:
3029     case FMUL_d:
3030       fmul(vform, rd, rn, rm);
3031       break;
3032     case FNMUL_s:
3033     case FNMUL_d:
3034       fnmul(vform, rd, rn, rm);
3035       break;
3036     case FDIV_s:
3037     case FDIV_d:
3038       fdiv(vform, rd, rn, rm);
3039       break;
3040     case FMAX_s:
3041     case FMAX_d:
3042       fmax(vform, rd, rn, rm);
3043       break;
3044     case FMIN_s:
3045     case FMIN_d:
3046       fmin(vform, rd, rn, rm);
3047       break;
3048     case FMAXNM_s:
3049     case FMAXNM_d:
3050       fmaxnm(vform, rd, rn, rm);
3051       break;
3052     case FMINNM_s:
3053     case FMINNM_d:
3054       fminnm(vform, rd, rn, rm);
3055       break;
3056     default:
3057       UNREACHABLE();
3058   }
3059   // Explicitly log the register update whilst we have type information.
3060   LogVRegister(instr->Rd(), GetPrintRegisterFormatFP(vform));
3061 }
3062 
VisitFPDataProcessing3Source(Instruction * instr)3063 void Simulator::VisitFPDataProcessing3Source(Instruction* instr) {
3064   AssertSupportedFPCR();
3065 
3066   unsigned fd = instr->Rd();
3067   unsigned fn = instr->Rn();
3068   unsigned fm = instr->Rm();
3069   unsigned fa = instr->Ra();
3070 
3071   switch (instr->Mask(FPDataProcessing3SourceMask)) {
3072     // fd = fa +/- (fn * fm)
3073     case FMADD_s:
3074       set_sreg(fd, FPMulAdd(sreg(fa), sreg(fn), sreg(fm)));
3075       break;
3076     case FMSUB_s:
3077       set_sreg(fd, FPMulAdd(sreg(fa), -sreg(fn), sreg(fm)));
3078       break;
3079     case FMADD_d:
3080       set_dreg(fd, FPMulAdd(dreg(fa), dreg(fn), dreg(fm)));
3081       break;
3082     case FMSUB_d:
3083       set_dreg(fd, FPMulAdd(dreg(fa), -dreg(fn), dreg(fm)));
3084       break;
3085     // Negated variants of the above.
3086     case FNMADD_s:
3087       set_sreg(fd, FPMulAdd(-sreg(fa), -sreg(fn), sreg(fm)));
3088       break;
3089     case FNMSUB_s:
3090       set_sreg(fd, FPMulAdd(-sreg(fa), sreg(fn), sreg(fm)));
3091       break;
3092     case FNMADD_d:
3093       set_dreg(fd, FPMulAdd(-dreg(fa), -dreg(fn), dreg(fm)));
3094       break;
3095     case FNMSUB_d:
3096       set_dreg(fd, FPMulAdd(-dreg(fa), dreg(fn), dreg(fm)));
3097       break;
3098     default:
3099       UNIMPLEMENTED();
3100   }
3101 }
3102 
FPProcessNaNs(Instruction * instr)3103 bool Simulator::FPProcessNaNs(Instruction* instr) {
3104   unsigned fd = instr->Rd();
3105   unsigned fn = instr->Rn();
3106   unsigned fm = instr->Rm();
3107   bool done = false;
3108 
3109   if (instr->Mask(FP64) == FP64) {
3110     double result = FPProcessNaNs(dreg(fn), dreg(fm));
3111     if (std::isnan(result)) {
3112       set_dreg(fd, result);
3113       done = true;
3114     }
3115   } else {
3116     float result = FPProcessNaNs(sreg(fn), sreg(fm));
3117     if (std::isnan(result)) {
3118       set_sreg(fd, result);
3119       done = true;
3120     }
3121   }
3122 
3123   return done;
3124 }
3125 
3126 // clang-format off
3127 #define PAUTH_SYSTEM_MODES(V)                            \
3128   V(A1716, 17, xreg(16),                      kPACKeyIA) \
3129   V(ASP,   30, xreg(31, Reg31IsStackPointer), kPACKeyIA)
3130 // clang-format on
3131 
VisitSystem(Instruction * instr)3132 void Simulator::VisitSystem(Instruction* instr) {
3133   // Some system instructions hijack their Op and Cp fields to represent a
3134   // range of immediates instead of indicating a different instruction. This
3135   // makes the decoding tricky.
3136   if (instr->Mask(SystemPAuthFMask) == SystemPAuthFixed) {
3137     // The BType check for PACIASP happens in CheckBType().
3138     switch (instr->Mask(SystemPAuthMask)) {
3139 #define DEFINE_PAUTH_FUNCS(SUFFIX, DST, MOD, KEY)                     \
3140   case PACI##SUFFIX:                                                  \
3141     set_xreg(DST, AddPAC(xreg(DST), MOD, KEY, kInstructionPointer));  \
3142     break;                                                            \
3143   case AUTI##SUFFIX:                                                  \
3144     set_xreg(DST, AuthPAC(xreg(DST), MOD, KEY, kInstructionPointer)); \
3145     break;
3146 
3147       PAUTH_SYSTEM_MODES(DEFINE_PAUTH_FUNCS)
3148 #undef DEFINE_PAUTH_FUNCS
3149 #undef PAUTH_SYSTEM_MODES
3150     }
3151   } else if (instr->Mask(SystemSysRegFMask) == SystemSysRegFixed) {
3152     switch (instr->Mask(SystemSysRegMask)) {
3153       case MRS: {
3154         switch (instr->ImmSystemRegister()) {
3155           case NZCV:
3156             set_xreg(instr->Rt(), nzcv().RawValue());
3157             break;
3158           case FPCR:
3159             set_xreg(instr->Rt(), fpcr().RawValue());
3160             break;
3161           default:
3162             UNIMPLEMENTED();
3163         }
3164         break;
3165       }
3166       case MSR: {
3167         switch (instr->ImmSystemRegister()) {
3168           case NZCV:
3169             nzcv().SetRawValue(wreg(instr->Rt()));
3170             LogSystemRegister(NZCV);
3171             break;
3172           case FPCR:
3173             fpcr().SetRawValue(wreg(instr->Rt()));
3174             LogSystemRegister(FPCR);
3175             break;
3176           default:
3177             UNIMPLEMENTED();
3178         }
3179         break;
3180       }
3181     }
3182   } else if (instr->Mask(SystemHintFMask) == SystemHintFixed) {
3183     DCHECK(instr->Mask(SystemHintMask) == HINT);
3184     switch (instr->ImmHint()) {
3185       case NOP:
3186       case CSDB:
3187       case BTI_jc:
3188       case BTI:
3189       case BTI_c:
3190       case BTI_j:
3191         // The BType checks happen in CheckBType().
3192         break;
3193       default:
3194         UNIMPLEMENTED();
3195     }
3196   } else if (instr->Mask(MemBarrierFMask) == MemBarrierFixed) {
3197 #if defined(V8_OS_WIN)
3198     MemoryBarrier();
3199 #else
3200     __sync_synchronize();
3201 #endif
3202   } else {
3203     UNIMPLEMENTED();
3204   }
3205 }
3206 
GetValue(const char * desc,int64_t * value)3207 bool Simulator::GetValue(const char* desc, int64_t* value) {
3208   int regnum = CodeFromName(desc);
3209   if (regnum >= 0) {
3210     unsigned code = regnum;
3211     if (code == kZeroRegCode) {
3212       // Catch the zero register and return 0.
3213       *value = 0;
3214       return true;
3215     } else if (code == kSPRegInternalCode) {
3216       // Translate the stack pointer code to 31, for Reg31IsStackPointer.
3217       code = 31;
3218     }
3219     if (desc[0] == 'w') {
3220       *value = wreg(code, Reg31IsStackPointer);
3221     } else {
3222       *value = xreg(code, Reg31IsStackPointer);
3223     }
3224     return true;
3225   } else if (strncmp(desc, "0x", 2) == 0) {
3226     return SScanF(desc + 2, "%" SCNx64, reinterpret_cast<uint64_t*>(value)) ==
3227            1;
3228   } else {
3229     return SScanF(desc, "%" SCNu64, reinterpret_cast<uint64_t*>(value)) == 1;
3230   }
3231 }
3232 
PrintValue(const char * desc)3233 bool Simulator::PrintValue(const char* desc) {
3234   if (strcmp(desc, "sp") == 0) {
3235     DCHECK(CodeFromName(desc) == static_cast<int>(kSPRegInternalCode));
3236     PrintF(stream_, "%s sp:%s 0x%016" PRIx64 "%s\n", clr_reg_name,
3237            clr_reg_value, xreg(31, Reg31IsStackPointer), clr_normal);
3238     return true;
3239   } else if (strcmp(desc, "wsp") == 0) {
3240     DCHECK(CodeFromName(desc) == static_cast<int>(kSPRegInternalCode));
3241     PrintF(stream_, "%s wsp:%s 0x%08" PRIx32 "%s\n", clr_reg_name,
3242            clr_reg_value, wreg(31, Reg31IsStackPointer), clr_normal);
3243     return true;
3244   }
3245 
3246   int i = CodeFromName(desc);
3247   static_assert(kNumberOfRegisters == kNumberOfVRegisters,
3248                 "Must be same number of Registers as VRegisters.");
3249   if (i < 0 || static_cast<unsigned>(i) >= kNumberOfVRegisters) return false;
3250 
3251   if (desc[0] == 'v') {
3252     PrintF(stream_, "%s %s:%s 0x%016" PRIx64 "%s (%s%s:%s %g%s %s:%s %g%s)\n",
3253            clr_vreg_name, VRegNameForCode(i), clr_vreg_value,
3254            bit_cast<uint64_t>(dreg(i)), clr_normal, clr_vreg_name,
3255            DRegNameForCode(i), clr_vreg_value, dreg(i), clr_vreg_name,
3256            SRegNameForCode(i), clr_vreg_value, sreg(i), clr_normal);
3257     return true;
3258   } else if (desc[0] == 'd') {
3259     PrintF(stream_, "%s %s:%s %g%s\n", clr_vreg_name, DRegNameForCode(i),
3260            clr_vreg_value, dreg(i), clr_normal);
3261     return true;
3262   } else if (desc[0] == 's') {
3263     PrintF(stream_, "%s %s:%s %g%s\n", clr_vreg_name, SRegNameForCode(i),
3264            clr_vreg_value, sreg(i), clr_normal);
3265     return true;
3266   } else if (desc[0] == 'w') {
3267     PrintF(stream_, "%s %s:%s 0x%08" PRIx32 "%s\n", clr_reg_name,
3268            WRegNameForCode(i), clr_reg_value, wreg(i), clr_normal);
3269     return true;
3270   } else {
3271     // X register names have a wide variety of starting characters, but anything
3272     // else will be an X register.
3273     PrintF(stream_, "%s %s:%s 0x%016" PRIx64 "%s\n", clr_reg_name,
3274            XRegNameForCode(i), clr_reg_value, xreg(i), clr_normal);
3275     return true;
3276   }
3277 }
3278 
Debug()3279 void Simulator::Debug() {
3280 #define COMMAND_SIZE 63
3281 #define ARG_SIZE 255
3282 
3283 #define STR(a) #a
3284 #define XSTR(a) STR(a)
3285 
3286   char cmd[COMMAND_SIZE + 1];
3287   char arg1[ARG_SIZE + 1];
3288   char arg2[ARG_SIZE + 1];
3289   char* argv[3] = {cmd, arg1, arg2};
3290 
3291   // Make sure to have a proper terminating character if reaching the limit.
3292   cmd[COMMAND_SIZE] = 0;
3293   arg1[ARG_SIZE] = 0;
3294   arg2[ARG_SIZE] = 0;
3295 
3296   bool done = false;
3297   bool cleared_log_disasm_bit = false;
3298 
3299   while (!done) {
3300     // Disassemble the next instruction to execute before doing anything else.
3301     PrintInstructionsAt(pc_, 1);
3302     // Read the command line.
3303     char* line = ReadLine("sim> ");
3304     if (line == nullptr) {
3305       break;
3306     } else {
3307       // Repeat last command by default.
3308       char* last_input = last_debugger_input();
3309       if (strcmp(line, "\n") == 0 && (last_input != nullptr)) {
3310         DeleteArray(line);
3311         line = last_input;
3312       } else {
3313         // Update the latest command ran
3314         set_last_debugger_input(line);
3315       }
3316 
3317       // Use sscanf to parse the individual parts of the command line. At the
3318       // moment no command expects more than two parameters.
3319       int argc = SScanF(line,
3320                         "%" XSTR(COMMAND_SIZE) "s "
3321                         "%" XSTR(ARG_SIZE) "s "
3322                         "%" XSTR(ARG_SIZE) "s",
3323                         cmd, arg1, arg2);
3324 
3325       // stepi / si ------------------------------------------------------------
3326       if ((strcmp(cmd, "si") == 0) || (strcmp(cmd, "stepi") == 0)) {
3327         // We are about to execute instructions, after which by default we
3328         // should increment the pc_. If it was set when reaching this debug
3329         // instruction, it has not been cleared because this instruction has not
3330         // completed yet. So clear it manually.
3331         pc_modified_ = false;
3332 
3333         if (argc == 1) {
3334           ExecuteInstruction();
3335         } else {
3336           int64_t number_of_instructions_to_execute = 1;
3337           GetValue(arg1, &number_of_instructions_to_execute);
3338 
3339           set_log_parameters(log_parameters() | LOG_DISASM);
3340           while (number_of_instructions_to_execute-- > 0) {
3341             ExecuteInstruction();
3342           }
3343           set_log_parameters(log_parameters() & ~LOG_DISASM);
3344           PrintF("\n");
3345         }
3346 
3347         // If it was necessary, the pc has already been updated or incremented
3348         // when executing the instruction. So we do not want it to be updated
3349         // again. It will be cleared when exiting.
3350         pc_modified_ = true;
3351 
3352         // next / n
3353         // --------------------------------------------------------------
3354       } else if ((strcmp(cmd, "next") == 0) || (strcmp(cmd, "n") == 0)) {
3355         // Tell the simulator to break after the next executed BL.
3356         break_on_next_ = true;
3357         // Continue.
3358         done = true;
3359 
3360         // continue / cont / c
3361         // ---------------------------------------------------
3362       } else if ((strcmp(cmd, "continue") == 0) || (strcmp(cmd, "cont") == 0) ||
3363                  (strcmp(cmd, "c") == 0)) {
3364         // Leave the debugger shell.
3365         done = true;
3366 
3367         // disassemble / disasm / di
3368         // ---------------------------------------------
3369       } else if (strcmp(cmd, "disassemble") == 0 ||
3370                  strcmp(cmd, "disasm") == 0 || strcmp(cmd, "di") == 0) {
3371         int64_t n_of_instrs_to_disasm = 10;                // default value.
3372         int64_t address = reinterpret_cast<int64_t>(pc_);  // default value.
3373         if (argc >= 2) {  // disasm <n of instrs>
3374           GetValue(arg1, &n_of_instrs_to_disasm);
3375         }
3376         if (argc >= 3) {  // disasm <n of instrs> <address>
3377           GetValue(arg2, &address);
3378         }
3379 
3380         // Disassemble.
3381         PrintInstructionsAt(reinterpret_cast<Instruction*>(address),
3382                             n_of_instrs_to_disasm);
3383         PrintF("\n");
3384 
3385         // print / p
3386         // -------------------------------------------------------------
3387       } else if ((strcmp(cmd, "print") == 0) || (strcmp(cmd, "p") == 0)) {
3388         if (argc == 2) {
3389           if (strcmp(arg1, "all") == 0) {
3390             PrintRegisters();
3391             PrintVRegisters();
3392           } else {
3393             if (!PrintValue(arg1)) {
3394               PrintF("%s unrecognized\n", arg1);
3395             }
3396           }
3397         } else {
3398           PrintF(
3399               "print <register>\n"
3400               "    Print the content of a register. (alias 'p')\n"
3401               "    'print all' will print all registers.\n"
3402               "    Use 'printobject' to get more details about the value.\n");
3403         }
3404 
3405         // printobject / po
3406         // ------------------------------------------------------
3407       } else if ((strcmp(cmd, "printobject") == 0) ||
3408                  (strcmp(cmd, "po") == 0)) {
3409         if (argc == 2) {
3410           int64_t value;
3411           StdoutStream os;
3412           if (GetValue(arg1, &value)) {
3413             Object obj(value);
3414             os << arg1 << ": \n";
3415 #ifdef DEBUG
3416             obj.Print(os);
3417             os << "\n";
3418 #else
3419             os << Brief(obj) << "\n";
3420 #endif
3421           } else {
3422             os << arg1 << " unrecognized\n";
3423           }
3424         } else {
3425           PrintF(
3426               "printobject <value>\n"
3427               "printobject <register>\n"
3428               "    Print details about the value. (alias 'po')\n");
3429         }
3430 
3431         // stack / mem
3432         // ----------------------------------------------------------
3433       } else if (strcmp(cmd, "stack") == 0 || strcmp(cmd, "mem") == 0 ||
3434                  strcmp(cmd, "dump") == 0) {
3435         int64_t* cur = nullptr;
3436         int64_t* end = nullptr;
3437         int next_arg = 1;
3438 
3439         if (strcmp(cmd, "stack") == 0) {
3440           cur = reinterpret_cast<int64_t*>(sp());
3441 
3442         } else {  // "mem"
3443           int64_t value;
3444           if (!GetValue(arg1, &value)) {
3445             PrintF("%s unrecognized\n", arg1);
3446             continue;
3447           }
3448           cur = reinterpret_cast<int64_t*>(value);
3449           next_arg++;
3450         }
3451 
3452         int64_t words = 0;
3453         if (argc == next_arg) {
3454           words = 10;
3455         } else if (argc == next_arg + 1) {
3456           if (!GetValue(argv[next_arg], &words)) {
3457             PrintF("%s unrecognized\n", argv[next_arg]);
3458             PrintF("Printing 10 double words by default");
3459             words = 10;
3460           }
3461         } else {
3462           UNREACHABLE();
3463         }
3464         end = cur + words;
3465 
3466         bool skip_obj_print = (strcmp(cmd, "dump") == 0);
3467         while (cur < end) {
3468           PrintF("  0x%016" PRIx64 ":  0x%016" PRIx64 " %10" PRId64,
3469                  reinterpret_cast<uint64_t>(cur), *cur, *cur);
3470           if (!skip_obj_print) {
3471             Object obj(*cur);
3472             Heap* current_heap = isolate_->heap();
3473             if (obj.IsSmi() ||
3474                 IsValidHeapObject(current_heap, HeapObject::cast(obj))) {
3475               PrintF(" (");
3476               if (obj.IsSmi()) {
3477                 PrintF("smi %" PRId32, Smi::ToInt(obj));
3478               } else {
3479                 obj.ShortPrint();
3480               }
3481               PrintF(")");
3482             }
3483           }
3484           PrintF("\n");
3485           cur++;
3486         }
3487 
3488         // trace / t
3489         // -------------------------------------------------------------
3490       } else if (strcmp(cmd, "trace") == 0 || strcmp(cmd, "t") == 0) {
3491         if ((log_parameters() & LOG_ALL) != LOG_ALL) {
3492           PrintF("Enabling disassembly, registers and memory write tracing\n");
3493           set_log_parameters(log_parameters() | LOG_ALL);
3494         } else {
3495           PrintF("Disabling disassembly, registers and memory write tracing\n");
3496           set_log_parameters(log_parameters() & ~LOG_ALL);
3497         }
3498 
3499         // break / b
3500         // -------------------------------------------------------------
3501       } else if (strcmp(cmd, "break") == 0 || strcmp(cmd, "b") == 0) {
3502         if (argc == 2) {
3503           int64_t value;
3504           if (GetValue(arg1, &value)) {
3505             SetBreakpoint(reinterpret_cast<Instruction*>(value));
3506           } else {
3507             PrintF("%s unrecognized\n", arg1);
3508           }
3509         } else {
3510           ListBreakpoints();
3511           PrintF("Use `break <address>` to set or disable a breakpoint\n");
3512         }
3513 
3514         // gdb
3515         // -------------------------------------------------------------------
3516       } else if (strcmp(cmd, "gdb") == 0) {
3517         PrintF("Relinquishing control to gdb.\n");
3518         base::OS::DebugBreak();
3519         PrintF("Regaining control from gdb.\n");
3520 
3521         // sysregs
3522         // ---------------------------------------------------------------
3523       } else if (strcmp(cmd, "sysregs") == 0) {
3524         PrintSystemRegisters();
3525 
3526         // help / h
3527         // --------------------------------------------------------------
3528       } else if (strcmp(cmd, "help") == 0 || strcmp(cmd, "h") == 0) {
3529         PrintF(
3530             "stepi / si\n"
3531             "    stepi <n>\n"
3532             "    Step <n> instructions.\n"
3533             "next / n\n"
3534             "    Continue execution until a BL instruction is reached.\n"
3535             "    At this point a breakpoint is set just after this BL.\n"
3536             "    Then execution is resumed. It will probably later hit the\n"
3537             "    breakpoint just set.\n"
3538             "continue / cont / c\n"
3539             "    Continue execution from here.\n"
3540             "disassemble / disasm / di\n"
3541             "    disassemble <n> <address>\n"
3542             "    Disassemble <n> instructions from current <address>.\n"
3543             "    By default <n> is 20 and <address> is the current pc.\n"
3544             "print / p\n"
3545             "    print <register>\n"
3546             "    Print the content of a register.\n"
3547             "    'print all' will print all registers.\n"
3548             "    Use 'printobject' to get more details about the value.\n"
3549             "printobject / po\n"
3550             "    printobject <value>\n"
3551             "    printobject <register>\n"
3552             "    Print details about the value.\n"
3553             "stack\n"
3554             "    stack [<words>]\n"
3555             "    Dump stack content, default dump 10 words\n"
3556             "mem\n"
3557             "    mem <address> [<words>]\n"
3558             "    Dump memory content, default dump 10 words\n"
3559             "dump\n"
3560             "    dump <address> [<words>]\n"
3561             "    Dump memory content without pretty printing JS objects, "
3562             "default dump 10 words\n"
3563             "trace / t\n"
3564             "    Toggle disassembly and register tracing\n"
3565             "break / b\n"
3566             "    break : list all breakpoints\n"
3567             "    break <address> : set / enable / disable a breakpoint.\n"
3568             "gdb\n"
3569             "    Enter gdb.\n"
3570             "sysregs\n"
3571             "    Print all system registers (including NZCV).\n");
3572       } else {
3573         PrintF("Unknown command: %s\n", cmd);
3574         PrintF("Use 'help' for more information.\n");
3575       }
3576     }
3577     if (cleared_log_disasm_bit == true) {
3578       set_log_parameters(log_parameters_ | LOG_DISASM);
3579     }
3580   }
3581 }
3582 
VisitException(Instruction * instr)3583 void Simulator::VisitException(Instruction* instr) {
3584   switch (instr->Mask(ExceptionMask)) {
3585     case HLT: {
3586       if (instr->ImmException() == kImmExceptionIsDebug) {
3587         // Read the arguments encoded inline in the instruction stream.
3588         uint32_t code;
3589         uint32_t parameters;
3590 
3591         memcpy(&code, pc_->InstructionAtOffset(kDebugCodeOffset), sizeof(code));
3592         memcpy(&parameters, pc_->InstructionAtOffset(kDebugParamsOffset),
3593                sizeof(parameters));
3594         char const* message = reinterpret_cast<char const*>(
3595             pc_->InstructionAtOffset(kDebugMessageOffset));
3596 
3597         // Always print something when we hit a debug point that breaks.
3598         // We are going to break, so printing something is not an issue in
3599         // terms of speed.
3600         if (FLAG_trace_sim_messages || FLAG_trace_sim || (parameters & BREAK)) {
3601           if (message != nullptr) {
3602             PrintF(stream_, "# %sDebugger hit %d: %s%s%s\n", clr_debug_number,
3603                    code, clr_debug_message, message, clr_normal);
3604           } else {
3605             PrintF(stream_, "# %sDebugger hit %d.%s\n", clr_debug_number, code,
3606                    clr_normal);
3607           }
3608         }
3609 
3610         // Other options.
3611         switch (parameters & kDebuggerTracingDirectivesMask) {
3612           case TRACE_ENABLE:
3613             set_log_parameters(log_parameters() | parameters);
3614             if (parameters & LOG_SYS_REGS) {
3615               PrintSystemRegisters();
3616             }
3617             if (parameters & LOG_REGS) {
3618               PrintRegisters();
3619             }
3620             if (parameters & LOG_VREGS) {
3621               PrintVRegisters();
3622             }
3623             break;
3624           case TRACE_DISABLE:
3625             set_log_parameters(log_parameters() & ~parameters);
3626             break;
3627           case TRACE_OVERRIDE:
3628             set_log_parameters(parameters);
3629             break;
3630           default:
3631             // We don't support a one-shot LOG_DISASM.
3632             DCHECK_EQ(parameters & LOG_DISASM, 0);
3633             // Don't print information that is already being traced.
3634             parameters &= ~log_parameters();
3635             // Print the requested information.
3636             if (parameters & LOG_SYS_REGS) PrintSystemRegisters();
3637             if (parameters & LOG_REGS) PrintRegisters();
3638             if (parameters & LOG_VREGS) PrintVRegisters();
3639         }
3640 
3641         // The stop parameters are inlined in the code. Skip them:
3642         //  - Skip to the end of the message string.
3643         size_t size = kDebugMessageOffset + strlen(message) + 1;
3644         pc_ = pc_->InstructionAtOffset(RoundUp(size, kInstrSize));
3645         //  - Verify that the unreachable marker is present.
3646         DCHECK(pc_->Mask(ExceptionMask) == HLT);
3647         DCHECK_EQ(pc_->ImmException(), kImmExceptionIsUnreachable);
3648         //  - Skip past the unreachable marker.
3649         set_pc(pc_->following());
3650 
3651         // Check if the debugger should break.
3652         if (parameters & BREAK) Debug();
3653 
3654       } else if (instr->ImmException() == kImmExceptionIsRedirectedCall) {
3655         DoRuntimeCall(instr);
3656       } else if (instr->ImmException() == kImmExceptionIsPrintf) {
3657         DoPrintf(instr);
3658 
3659       } else if (instr->ImmException() == kImmExceptionIsUnreachable) {
3660         fprintf(stream_, "Hit UNREACHABLE marker at PC=%p.\n",
3661                 reinterpret_cast<void*>(pc_));
3662         abort();
3663 
3664       } else {
3665         base::OS::DebugBreak();
3666       }
3667       break;
3668     }
3669     case BRK:
3670       base::OS::DebugBreak();
3671       break;
3672     default:
3673       UNIMPLEMENTED();
3674   }
3675 }
3676 
VisitNEON2RegMisc(Instruction * instr)3677 void Simulator::VisitNEON2RegMisc(Instruction* instr) {
3678   NEONFormatDecoder nfd(instr);
3679   VectorFormat vf = nfd.GetVectorFormat();
3680 
3681   // Format mapping for "long pair" instructions, [su]addlp, [su]adalp.
3682   static const NEONFormatMap map_lp = {
3683       {23, 22, 30}, {NF_4H, NF_8H, NF_2S, NF_4S, NF_1D, NF_2D}};
3684   VectorFormat vf_lp = nfd.GetVectorFormat(&map_lp);
3685 
3686   static const NEONFormatMap map_fcvtl = {{22}, {NF_4S, NF_2D}};
3687   VectorFormat vf_fcvtl = nfd.GetVectorFormat(&map_fcvtl);
3688 
3689   static const NEONFormatMap map_fcvtn = {{22, 30},
3690                                           {NF_4H, NF_8H, NF_2S, NF_4S}};
3691   VectorFormat vf_fcvtn = nfd.GetVectorFormat(&map_fcvtn);
3692 
3693   SimVRegister& rd = vreg(instr->Rd());
3694   SimVRegister& rn = vreg(instr->Rn());
3695 
3696   if (instr->Mask(NEON2RegMiscOpcode) <= NEON_NEG_opcode) {
3697     // These instructions all use a two bit size field, except NOT and RBIT,
3698     // which use the field to encode the operation.
3699     switch (instr->Mask(NEON2RegMiscMask)) {
3700       case NEON_REV64:
3701         rev64(vf, rd, rn);
3702         break;
3703       case NEON_REV32:
3704         rev32(vf, rd, rn);
3705         break;
3706       case NEON_REV16:
3707         rev16(vf, rd, rn);
3708         break;
3709       case NEON_SUQADD:
3710         suqadd(vf, rd, rn);
3711         break;
3712       case NEON_USQADD:
3713         usqadd(vf, rd, rn);
3714         break;
3715       case NEON_CLS:
3716         cls(vf, rd, rn);
3717         break;
3718       case NEON_CLZ:
3719         clz(vf, rd, rn);
3720         break;
3721       case NEON_CNT:
3722         cnt(vf, rd, rn);
3723         break;
3724       case NEON_SQABS:
3725         abs(vf, rd, rn).SignedSaturate(vf);
3726         break;
3727       case NEON_SQNEG:
3728         neg(vf, rd, rn).SignedSaturate(vf);
3729         break;
3730       case NEON_CMGT_zero:
3731         cmp(vf, rd, rn, 0, gt);
3732         break;
3733       case NEON_CMGE_zero:
3734         cmp(vf, rd, rn, 0, ge);
3735         break;
3736       case NEON_CMEQ_zero:
3737         cmp(vf, rd, rn, 0, eq);
3738         break;
3739       case NEON_CMLE_zero:
3740         cmp(vf, rd, rn, 0, le);
3741         break;
3742       case NEON_CMLT_zero:
3743         cmp(vf, rd, rn, 0, lt);
3744         break;
3745       case NEON_ABS:
3746         abs(vf, rd, rn);
3747         break;
3748       case NEON_NEG:
3749         neg(vf, rd, rn);
3750         break;
3751       case NEON_SADDLP:
3752         saddlp(vf_lp, rd, rn);
3753         break;
3754       case NEON_UADDLP:
3755         uaddlp(vf_lp, rd, rn);
3756         break;
3757       case NEON_SADALP:
3758         sadalp(vf_lp, rd, rn);
3759         break;
3760       case NEON_UADALP:
3761         uadalp(vf_lp, rd, rn);
3762         break;
3763       case NEON_RBIT_NOT:
3764         vf = nfd.GetVectorFormat(nfd.LogicalFormatMap());
3765         switch (instr->FPType()) {
3766           case 0:
3767             not_(vf, rd, rn);
3768             break;
3769           case 1:
3770             rbit(vf, rd, rn);
3771             break;
3772           default:
3773             UNIMPLEMENTED();
3774         }
3775         break;
3776     }
3777   } else {
3778     VectorFormat fpf = nfd.GetVectorFormat(nfd.FPFormatMap());
3779     FPRounding fpcr_rounding = static_cast<FPRounding>(fpcr().RMode());
3780     bool inexact_exception = false;
3781 
3782     // These instructions all use a one bit size field, except XTN, SQXTUN,
3783     // SHLL, SQXTN and UQXTN, which use a two bit size field.
3784     switch (instr->Mask(NEON2RegMiscFPMask)) {
3785       case NEON_FABS:
3786         fabs_(fpf, rd, rn);
3787         return;
3788       case NEON_FNEG:
3789         fneg(fpf, rd, rn);
3790         return;
3791       case NEON_FSQRT:
3792         fsqrt(fpf, rd, rn);
3793         return;
3794       case NEON_FCVTL:
3795         if (instr->Mask(NEON_Q)) {
3796           fcvtl2(vf_fcvtl, rd, rn);
3797         } else {
3798           fcvtl(vf_fcvtl, rd, rn);
3799         }
3800         return;
3801       case NEON_FCVTN:
3802         if (instr->Mask(NEON_Q)) {
3803           fcvtn2(vf_fcvtn, rd, rn);
3804         } else {
3805           fcvtn(vf_fcvtn, rd, rn);
3806         }
3807         return;
3808       case NEON_FCVTXN:
3809         if (instr->Mask(NEON_Q)) {
3810           fcvtxn2(vf_fcvtn, rd, rn);
3811         } else {
3812           fcvtxn(vf_fcvtn, rd, rn);
3813         }
3814         return;
3815 
3816       // The following instructions break from the switch statement, rather
3817       // than return.
3818       case NEON_FRINTI:
3819         break;  // Use FPCR rounding mode.
3820       case NEON_FRINTX:
3821         inexact_exception = true;
3822         break;
3823       case NEON_FRINTA:
3824         fpcr_rounding = FPTieAway;
3825         break;
3826       case NEON_FRINTM:
3827         fpcr_rounding = FPNegativeInfinity;
3828         break;
3829       case NEON_FRINTN:
3830         fpcr_rounding = FPTieEven;
3831         break;
3832       case NEON_FRINTP:
3833         fpcr_rounding = FPPositiveInfinity;
3834         break;
3835       case NEON_FRINTZ:
3836         fpcr_rounding = FPZero;
3837         break;
3838 
3839       // The remaining cases return to the caller.
3840       case NEON_FCVTNS:
3841         fcvts(fpf, rd, rn, FPTieEven);
3842         return;
3843       case NEON_FCVTNU:
3844         fcvtu(fpf, rd, rn, FPTieEven);
3845         return;
3846       case NEON_FCVTPS:
3847         fcvts(fpf, rd, rn, FPPositiveInfinity);
3848         return;
3849       case NEON_FCVTPU:
3850         fcvtu(fpf, rd, rn, FPPositiveInfinity);
3851         return;
3852       case NEON_FCVTMS:
3853         fcvts(fpf, rd, rn, FPNegativeInfinity);
3854         return;
3855       case NEON_FCVTMU:
3856         fcvtu(fpf, rd, rn, FPNegativeInfinity);
3857         return;
3858       case NEON_FCVTZS:
3859         fcvts(fpf, rd, rn, FPZero);
3860         return;
3861       case NEON_FCVTZU:
3862         fcvtu(fpf, rd, rn, FPZero);
3863         return;
3864       case NEON_FCVTAS:
3865         fcvts(fpf, rd, rn, FPTieAway);
3866         return;
3867       case NEON_FCVTAU:
3868         fcvtu(fpf, rd, rn, FPTieAway);
3869         return;
3870       case NEON_SCVTF:
3871         scvtf(fpf, rd, rn, 0, fpcr_rounding);
3872         return;
3873       case NEON_UCVTF:
3874         ucvtf(fpf, rd, rn, 0, fpcr_rounding);
3875         return;
3876       case NEON_URSQRTE:
3877         ursqrte(fpf, rd, rn);
3878         return;
3879       case NEON_URECPE:
3880         urecpe(fpf, rd, rn);
3881         return;
3882       case NEON_FRSQRTE:
3883         frsqrte(fpf, rd, rn);
3884         return;
3885       case NEON_FRECPE:
3886         frecpe(fpf, rd, rn, fpcr_rounding);
3887         return;
3888       case NEON_FCMGT_zero:
3889         fcmp_zero(fpf, rd, rn, gt);
3890         return;
3891       case NEON_FCMGE_zero:
3892         fcmp_zero(fpf, rd, rn, ge);
3893         return;
3894       case NEON_FCMEQ_zero:
3895         fcmp_zero(fpf, rd, rn, eq);
3896         return;
3897       case NEON_FCMLE_zero:
3898         fcmp_zero(fpf, rd, rn, le);
3899         return;
3900       case NEON_FCMLT_zero:
3901         fcmp_zero(fpf, rd, rn, lt);
3902         return;
3903       default:
3904         if ((NEON_XTN_opcode <= instr->Mask(NEON2RegMiscOpcode)) &&
3905             (instr->Mask(NEON2RegMiscOpcode) <= NEON_UQXTN_opcode)) {
3906           switch (instr->Mask(NEON2RegMiscMask)) {
3907             case NEON_XTN:
3908               xtn(vf, rd, rn);
3909               return;
3910             case NEON_SQXTN:
3911               sqxtn(vf, rd, rn);
3912               return;
3913             case NEON_UQXTN:
3914               uqxtn(vf, rd, rn);
3915               return;
3916             case NEON_SQXTUN:
3917               sqxtun(vf, rd, rn);
3918               return;
3919             case NEON_SHLL:
3920               vf = nfd.GetVectorFormat(nfd.LongIntegerFormatMap());
3921               if (instr->Mask(NEON_Q)) {
3922                 shll2(vf, rd, rn);
3923               } else {
3924                 shll(vf, rd, rn);
3925               }
3926               return;
3927             default:
3928               UNIMPLEMENTED();
3929           }
3930         } else {
3931           UNIMPLEMENTED();
3932         }
3933     }
3934 
3935     // Only FRINT* instructions fall through the switch above.
3936     frint(fpf, rd, rn, fpcr_rounding, inexact_exception);
3937   }
3938 }
3939 
VisitNEON3Same(Instruction * instr)3940 void Simulator::VisitNEON3Same(Instruction* instr) {
3941   NEONFormatDecoder nfd(instr);
3942   SimVRegister& rd = vreg(instr->Rd());
3943   SimVRegister& rn = vreg(instr->Rn());
3944   SimVRegister& rm = vreg(instr->Rm());
3945 
3946   if (instr->Mask(NEON3SameLogicalFMask) == NEON3SameLogicalFixed) {
3947     VectorFormat vf = nfd.GetVectorFormat(nfd.LogicalFormatMap());
3948     switch (instr->Mask(NEON3SameLogicalMask)) {
3949       case NEON_AND:
3950         and_(vf, rd, rn, rm);
3951         break;
3952       case NEON_ORR:
3953         orr(vf, rd, rn, rm);
3954         break;
3955       case NEON_ORN:
3956         orn(vf, rd, rn, rm);
3957         break;
3958       case NEON_EOR:
3959         eor(vf, rd, rn, rm);
3960         break;
3961       case NEON_BIC:
3962         bic(vf, rd, rn, rm);
3963         break;
3964       case NEON_BIF:
3965         bif(vf, rd, rn, rm);
3966         break;
3967       case NEON_BIT:
3968         bit(vf, rd, rn, rm);
3969         break;
3970       case NEON_BSL:
3971         bsl(vf, rd, rn, rm);
3972         break;
3973       default:
3974         UNIMPLEMENTED();
3975     }
3976   } else if (instr->Mask(NEON3SameFPFMask) == NEON3SameFPFixed) {
3977     VectorFormat vf = nfd.GetVectorFormat(nfd.FPFormatMap());
3978     switch (instr->Mask(NEON3SameFPMask)) {
3979       case NEON_FADD:
3980         fadd(vf, rd, rn, rm);
3981         break;
3982       case NEON_FSUB:
3983         fsub(vf, rd, rn, rm);
3984         break;
3985       case NEON_FMUL:
3986         fmul(vf, rd, rn, rm);
3987         break;
3988       case NEON_FDIV:
3989         fdiv(vf, rd, rn, rm);
3990         break;
3991       case NEON_FMAX:
3992         fmax(vf, rd, rn, rm);
3993         break;
3994       case NEON_FMIN:
3995         fmin(vf, rd, rn, rm);
3996         break;
3997       case NEON_FMAXNM:
3998         fmaxnm(vf, rd, rn, rm);
3999         break;
4000       case NEON_FMINNM:
4001         fminnm(vf, rd, rn, rm);
4002         break;
4003       case NEON_FMLA:
4004         fmla(vf, rd, rn, rm);
4005         break;
4006       case NEON_FMLS:
4007         fmls(vf, rd, rn, rm);
4008         break;
4009       case NEON_FMULX:
4010         fmulx(vf, rd, rn, rm);
4011         break;
4012       case NEON_FACGE:
4013         fabscmp(vf, rd, rn, rm, ge);
4014         break;
4015       case NEON_FACGT:
4016         fabscmp(vf, rd, rn, rm, gt);
4017         break;
4018       case NEON_FCMEQ:
4019         fcmp(vf, rd, rn, rm, eq);
4020         break;
4021       case NEON_FCMGE:
4022         fcmp(vf, rd, rn, rm, ge);
4023         break;
4024       case NEON_FCMGT:
4025         fcmp(vf, rd, rn, rm, gt);
4026         break;
4027       case NEON_FRECPS:
4028         frecps(vf, rd, rn, rm);
4029         break;
4030       case NEON_FRSQRTS:
4031         frsqrts(vf, rd, rn, rm);
4032         break;
4033       case NEON_FABD:
4034         fabd(vf, rd, rn, rm);
4035         break;
4036       case NEON_FADDP:
4037         faddp(vf, rd, rn, rm);
4038         break;
4039       case NEON_FMAXP:
4040         fmaxp(vf, rd, rn, rm);
4041         break;
4042       case NEON_FMAXNMP:
4043         fmaxnmp(vf, rd, rn, rm);
4044         break;
4045       case NEON_FMINP:
4046         fminp(vf, rd, rn, rm);
4047         break;
4048       case NEON_FMINNMP:
4049         fminnmp(vf, rd, rn, rm);
4050         break;
4051       default:
4052         UNIMPLEMENTED();
4053     }
4054   } else {
4055     VectorFormat vf = nfd.GetVectorFormat();
4056     switch (instr->Mask(NEON3SameMask)) {
4057       case NEON_ADD:
4058         add(vf, rd, rn, rm);
4059         break;
4060       case NEON_ADDP:
4061         addp(vf, rd, rn, rm);
4062         break;
4063       case NEON_CMEQ:
4064         cmp(vf, rd, rn, rm, eq);
4065         break;
4066       case NEON_CMGE:
4067         cmp(vf, rd, rn, rm, ge);
4068         break;
4069       case NEON_CMGT:
4070         cmp(vf, rd, rn, rm, gt);
4071         break;
4072       case NEON_CMHI:
4073         cmp(vf, rd, rn, rm, hi);
4074         break;
4075       case NEON_CMHS:
4076         cmp(vf, rd, rn, rm, hs);
4077         break;
4078       case NEON_CMTST:
4079         cmptst(vf, rd, rn, rm);
4080         break;
4081       case NEON_MLS:
4082         mls(vf, rd, rn, rm);
4083         break;
4084       case NEON_MLA:
4085         mla(vf, rd, rn, rm);
4086         break;
4087       case NEON_MUL:
4088         mul(vf, rd, rn, rm);
4089         break;
4090       case NEON_PMUL:
4091         pmul(vf, rd, rn, rm);
4092         break;
4093       case NEON_SMAX:
4094         smax(vf, rd, rn, rm);
4095         break;
4096       case NEON_SMAXP:
4097         smaxp(vf, rd, rn, rm);
4098         break;
4099       case NEON_SMIN:
4100         smin(vf, rd, rn, rm);
4101         break;
4102       case NEON_SMINP:
4103         sminp(vf, rd, rn, rm);
4104         break;
4105       case NEON_SUB:
4106         sub(vf, rd, rn, rm);
4107         break;
4108       case NEON_UMAX:
4109         umax(vf, rd, rn, rm);
4110         break;
4111       case NEON_UMAXP:
4112         umaxp(vf, rd, rn, rm);
4113         break;
4114       case NEON_UMIN:
4115         umin(vf, rd, rn, rm);
4116         break;
4117       case NEON_UMINP:
4118         uminp(vf, rd, rn, rm);
4119         break;
4120       case NEON_SSHL:
4121         sshl(vf, rd, rn, rm);
4122         break;
4123       case NEON_USHL:
4124         ushl(vf, rd, rn, rm);
4125         break;
4126       case NEON_SABD:
4127         AbsDiff(vf, rd, rn, rm, true);
4128         break;
4129       case NEON_UABD:
4130         AbsDiff(vf, rd, rn, rm, false);
4131         break;
4132       case NEON_SABA:
4133         saba(vf, rd, rn, rm);
4134         break;
4135       case NEON_UABA:
4136         uaba(vf, rd, rn, rm);
4137         break;
4138       case NEON_UQADD:
4139         add(vf, rd, rn, rm).UnsignedSaturate(vf);
4140         break;
4141       case NEON_SQADD:
4142         add(vf, rd, rn, rm).SignedSaturate(vf);
4143         break;
4144       case NEON_UQSUB:
4145         sub(vf, rd, rn, rm).UnsignedSaturate(vf);
4146         break;
4147       case NEON_SQSUB:
4148         sub(vf, rd, rn, rm).SignedSaturate(vf);
4149         break;
4150       case NEON_SQDMULH:
4151         sqdmulh(vf, rd, rn, rm);
4152         break;
4153       case NEON_SQRDMULH:
4154         sqrdmulh(vf, rd, rn, rm);
4155         break;
4156       case NEON_UQSHL:
4157         ushl(vf, rd, rn, rm).UnsignedSaturate(vf);
4158         break;
4159       case NEON_SQSHL:
4160         sshl(vf, rd, rn, rm).SignedSaturate(vf);
4161         break;
4162       case NEON_URSHL:
4163         ushl(vf, rd, rn, rm).Round(vf);
4164         break;
4165       case NEON_SRSHL:
4166         sshl(vf, rd, rn, rm).Round(vf);
4167         break;
4168       case NEON_UQRSHL:
4169         ushl(vf, rd, rn, rm).Round(vf).UnsignedSaturate(vf);
4170         break;
4171       case NEON_SQRSHL:
4172         sshl(vf, rd, rn, rm).Round(vf).SignedSaturate(vf);
4173         break;
4174       case NEON_UHADD:
4175         add(vf, rd, rn, rm).Uhalve(vf);
4176         break;
4177       case NEON_URHADD:
4178         add(vf, rd, rn, rm).Uhalve(vf).Round(vf);
4179         break;
4180       case NEON_SHADD:
4181         add(vf, rd, rn, rm).Halve(vf);
4182         break;
4183       case NEON_SRHADD:
4184         add(vf, rd, rn, rm).Halve(vf).Round(vf);
4185         break;
4186       case NEON_UHSUB:
4187         sub(vf, rd, rn, rm).Uhalve(vf);
4188         break;
4189       case NEON_SHSUB:
4190         sub(vf, rd, rn, rm).Halve(vf);
4191         break;
4192       default:
4193         UNIMPLEMENTED();
4194     }
4195   }
4196 }
4197 
VisitNEON3Different(Instruction * instr)4198 void Simulator::VisitNEON3Different(Instruction* instr) {
4199   NEONFormatDecoder nfd(instr);
4200   VectorFormat vf = nfd.GetVectorFormat();
4201   VectorFormat vf_l = nfd.GetVectorFormat(nfd.LongIntegerFormatMap());
4202 
4203   SimVRegister& rd = vreg(instr->Rd());
4204   SimVRegister& rn = vreg(instr->Rn());
4205   SimVRegister& rm = vreg(instr->Rm());
4206 
4207   switch (instr->Mask(NEON3DifferentMask)) {
4208     case NEON_PMULL:
4209       pmull(vf_l, rd, rn, rm);
4210       break;
4211     case NEON_PMULL2:
4212       pmull2(vf_l, rd, rn, rm);
4213       break;
4214     case NEON_UADDL:
4215       uaddl(vf_l, rd, rn, rm);
4216       break;
4217     case NEON_UADDL2:
4218       uaddl2(vf_l, rd, rn, rm);
4219       break;
4220     case NEON_SADDL:
4221       saddl(vf_l, rd, rn, rm);
4222       break;
4223     case NEON_SADDL2:
4224       saddl2(vf_l, rd, rn, rm);
4225       break;
4226     case NEON_USUBL:
4227       usubl(vf_l, rd, rn, rm);
4228       break;
4229     case NEON_USUBL2:
4230       usubl2(vf_l, rd, rn, rm);
4231       break;
4232     case NEON_SSUBL:
4233       ssubl(vf_l, rd, rn, rm);
4234       break;
4235     case NEON_SSUBL2:
4236       ssubl2(vf_l, rd, rn, rm);
4237       break;
4238     case NEON_SABAL:
4239       sabal(vf_l, rd, rn, rm);
4240       break;
4241     case NEON_SABAL2:
4242       sabal2(vf_l, rd, rn, rm);
4243       break;
4244     case NEON_UABAL:
4245       uabal(vf_l, rd, rn, rm);
4246       break;
4247     case NEON_UABAL2:
4248       uabal2(vf_l, rd, rn, rm);
4249       break;
4250     case NEON_SABDL:
4251       sabdl(vf_l, rd, rn, rm);
4252       break;
4253     case NEON_SABDL2:
4254       sabdl2(vf_l, rd, rn, rm);
4255       break;
4256     case NEON_UABDL:
4257       uabdl(vf_l, rd, rn, rm);
4258       break;
4259     case NEON_UABDL2:
4260       uabdl2(vf_l, rd, rn, rm);
4261       break;
4262     case NEON_SMLAL:
4263       smlal(vf_l, rd, rn, rm);
4264       break;
4265     case NEON_SMLAL2:
4266       smlal2(vf_l, rd, rn, rm);
4267       break;
4268     case NEON_UMLAL:
4269       umlal(vf_l, rd, rn, rm);
4270       break;
4271     case NEON_UMLAL2:
4272       umlal2(vf_l, rd, rn, rm);
4273       break;
4274     case NEON_SMLSL:
4275       smlsl(vf_l, rd, rn, rm);
4276       break;
4277     case NEON_SMLSL2:
4278       smlsl2(vf_l, rd, rn, rm);
4279       break;
4280     case NEON_UMLSL:
4281       umlsl(vf_l, rd, rn, rm);
4282       break;
4283     case NEON_UMLSL2:
4284       umlsl2(vf_l, rd, rn, rm);
4285       break;
4286     case NEON_SMULL:
4287       smull(vf_l, rd, rn, rm);
4288       break;
4289     case NEON_SMULL2:
4290       smull2(vf_l, rd, rn, rm);
4291       break;
4292     case NEON_UMULL:
4293       umull(vf_l, rd, rn, rm);
4294       break;
4295     case NEON_UMULL2:
4296       umull2(vf_l, rd, rn, rm);
4297       break;
4298     case NEON_SQDMLAL:
4299       sqdmlal(vf_l, rd, rn, rm);
4300       break;
4301     case NEON_SQDMLAL2:
4302       sqdmlal2(vf_l, rd, rn, rm);
4303       break;
4304     case NEON_SQDMLSL:
4305       sqdmlsl(vf_l, rd, rn, rm);
4306       break;
4307     case NEON_SQDMLSL2:
4308       sqdmlsl2(vf_l, rd, rn, rm);
4309       break;
4310     case NEON_SQDMULL:
4311       sqdmull(vf_l, rd, rn, rm);
4312       break;
4313     case NEON_SQDMULL2:
4314       sqdmull2(vf_l, rd, rn, rm);
4315       break;
4316     case NEON_UADDW:
4317       uaddw(vf_l, rd, rn, rm);
4318       break;
4319     case NEON_UADDW2:
4320       uaddw2(vf_l, rd, rn, rm);
4321       break;
4322     case NEON_SADDW:
4323       saddw(vf_l, rd, rn, rm);
4324       break;
4325     case NEON_SADDW2:
4326       saddw2(vf_l, rd, rn, rm);
4327       break;
4328     case NEON_USUBW:
4329       usubw(vf_l, rd, rn, rm);
4330       break;
4331     case NEON_USUBW2:
4332       usubw2(vf_l, rd, rn, rm);
4333       break;
4334     case NEON_SSUBW:
4335       ssubw(vf_l, rd, rn, rm);
4336       break;
4337     case NEON_SSUBW2:
4338       ssubw2(vf_l, rd, rn, rm);
4339       break;
4340     case NEON_ADDHN:
4341       addhn(vf, rd, rn, rm);
4342       break;
4343     case NEON_ADDHN2:
4344       addhn2(vf, rd, rn, rm);
4345       break;
4346     case NEON_RADDHN:
4347       raddhn(vf, rd, rn, rm);
4348       break;
4349     case NEON_RADDHN2:
4350       raddhn2(vf, rd, rn, rm);
4351       break;
4352     case NEON_SUBHN:
4353       subhn(vf, rd, rn, rm);
4354       break;
4355     case NEON_SUBHN2:
4356       subhn2(vf, rd, rn, rm);
4357       break;
4358     case NEON_RSUBHN:
4359       rsubhn(vf, rd, rn, rm);
4360       break;
4361     case NEON_RSUBHN2:
4362       rsubhn2(vf, rd, rn, rm);
4363       break;
4364     default:
4365       UNIMPLEMENTED();
4366   }
4367 }
4368 
VisitNEONAcrossLanes(Instruction * instr)4369 void Simulator::VisitNEONAcrossLanes(Instruction* instr) {
4370   NEONFormatDecoder nfd(instr);
4371 
4372   SimVRegister& rd = vreg(instr->Rd());
4373   SimVRegister& rn = vreg(instr->Rn());
4374 
4375   // The input operand's VectorFormat is passed for these instructions.
4376   if (instr->Mask(NEONAcrossLanesFPFMask) == NEONAcrossLanesFPFixed) {
4377     VectorFormat vf = nfd.GetVectorFormat(nfd.FPFormatMap());
4378 
4379     switch (instr->Mask(NEONAcrossLanesFPMask)) {
4380       case NEON_FMAXV:
4381         fmaxv(vf, rd, rn);
4382         break;
4383       case NEON_FMINV:
4384         fminv(vf, rd, rn);
4385         break;
4386       case NEON_FMAXNMV:
4387         fmaxnmv(vf, rd, rn);
4388         break;
4389       case NEON_FMINNMV:
4390         fminnmv(vf, rd, rn);
4391         break;
4392       default:
4393         UNIMPLEMENTED();
4394     }
4395   } else {
4396     VectorFormat vf = nfd.GetVectorFormat();
4397 
4398     switch (instr->Mask(NEONAcrossLanesMask)) {
4399       case NEON_ADDV:
4400         addv(vf, rd, rn);
4401         break;
4402       case NEON_SMAXV:
4403         smaxv(vf, rd, rn);
4404         break;
4405       case NEON_SMINV:
4406         sminv(vf, rd, rn);
4407         break;
4408       case NEON_UMAXV:
4409         umaxv(vf, rd, rn);
4410         break;
4411       case NEON_UMINV:
4412         uminv(vf, rd, rn);
4413         break;
4414       case NEON_SADDLV:
4415         saddlv(vf, rd, rn);
4416         break;
4417       case NEON_UADDLV:
4418         uaddlv(vf, rd, rn);
4419         break;
4420       default:
4421         UNIMPLEMENTED();
4422     }
4423   }
4424 }
4425 
VisitNEONByIndexedElement(Instruction * instr)4426 void Simulator::VisitNEONByIndexedElement(Instruction* instr) {
4427   NEONFormatDecoder nfd(instr);
4428   VectorFormat vf_r = nfd.GetVectorFormat();
4429   VectorFormat vf = nfd.GetVectorFormat(nfd.LongIntegerFormatMap());
4430 
4431   SimVRegister& rd = vreg(instr->Rd());
4432   SimVRegister& rn = vreg(instr->Rn());
4433 
4434   ByElementOp Op = nullptr;
4435 
4436   int rm_reg = instr->Rm();
4437   int index = (instr->NEONH() << 1) | instr->NEONL();
4438   if (instr->NEONSize() == 1) {
4439     rm_reg &= 0xF;
4440     index = (index << 1) | instr->NEONM();
4441   }
4442 
4443   switch (instr->Mask(NEONByIndexedElementMask)) {
4444     case NEON_MUL_byelement:
4445       Op = &Simulator::mul;
4446       vf = vf_r;
4447       break;
4448     case NEON_MLA_byelement:
4449       Op = &Simulator::mla;
4450       vf = vf_r;
4451       break;
4452     case NEON_MLS_byelement:
4453       Op = &Simulator::mls;
4454       vf = vf_r;
4455       break;
4456     case NEON_SQDMULH_byelement:
4457       Op = &Simulator::sqdmulh;
4458       vf = vf_r;
4459       break;
4460     case NEON_SQRDMULH_byelement:
4461       Op = &Simulator::sqrdmulh;
4462       vf = vf_r;
4463       break;
4464     case NEON_SMULL_byelement:
4465       if (instr->Mask(NEON_Q)) {
4466         Op = &Simulator::smull2;
4467       } else {
4468         Op = &Simulator::smull;
4469       }
4470       break;
4471     case NEON_UMULL_byelement:
4472       if (instr->Mask(NEON_Q)) {
4473         Op = &Simulator::umull2;
4474       } else {
4475         Op = &Simulator::umull;
4476       }
4477       break;
4478     case NEON_SMLAL_byelement:
4479       if (instr->Mask(NEON_Q)) {
4480         Op = &Simulator::smlal2;
4481       } else {
4482         Op = &Simulator::smlal;
4483       }
4484       break;
4485     case NEON_UMLAL_byelement:
4486       if (instr->Mask(NEON_Q)) {
4487         Op = &Simulator::umlal2;
4488       } else {
4489         Op = &Simulator::umlal;
4490       }
4491       break;
4492     case NEON_SMLSL_byelement:
4493       if (instr->Mask(NEON_Q)) {
4494         Op = &Simulator::smlsl2;
4495       } else {
4496         Op = &Simulator::smlsl;
4497       }
4498       break;
4499     case NEON_UMLSL_byelement:
4500       if (instr->Mask(NEON_Q)) {
4501         Op = &Simulator::umlsl2;
4502       } else {
4503         Op = &Simulator::umlsl;
4504       }
4505       break;
4506     case NEON_SQDMULL_byelement:
4507       if (instr->Mask(NEON_Q)) {
4508         Op = &Simulator::sqdmull2;
4509       } else {
4510         Op = &Simulator::sqdmull;
4511       }
4512       break;
4513     case NEON_SQDMLAL_byelement:
4514       if (instr->Mask(NEON_Q)) {
4515         Op = &Simulator::sqdmlal2;
4516       } else {
4517         Op = &Simulator::sqdmlal;
4518       }
4519       break;
4520     case NEON_SQDMLSL_byelement:
4521       if (instr->Mask(NEON_Q)) {
4522         Op = &Simulator::sqdmlsl2;
4523       } else {
4524         Op = &Simulator::sqdmlsl;
4525       }
4526       break;
4527     default:
4528       index = instr->NEONH();
4529       if ((instr->FPType() & 1) == 0) {
4530         index = (index << 1) | instr->NEONL();
4531       }
4532 
4533       vf = nfd.GetVectorFormat(nfd.FPFormatMap());
4534 
4535       switch (instr->Mask(NEONByIndexedElementFPMask)) {
4536         case NEON_FMUL_byelement:
4537           Op = &Simulator::fmul;
4538           break;
4539         case NEON_FMLA_byelement:
4540           Op = &Simulator::fmla;
4541           break;
4542         case NEON_FMLS_byelement:
4543           Op = &Simulator::fmls;
4544           break;
4545         case NEON_FMULX_byelement:
4546           Op = &Simulator::fmulx;
4547           break;
4548         default:
4549           UNIMPLEMENTED();
4550       }
4551   }
4552 
4553   (this->*Op)(vf, rd, rn, vreg(rm_reg), index);
4554 }
4555 
VisitNEONCopy(Instruction * instr)4556 void Simulator::VisitNEONCopy(Instruction* instr) {
4557   NEONFormatDecoder nfd(instr, NEONFormatDecoder::TriangularFormatMap());
4558   VectorFormat vf = nfd.GetVectorFormat();
4559 
4560   SimVRegister& rd = vreg(instr->Rd());
4561   SimVRegister& rn = vreg(instr->Rn());
4562   int imm5 = instr->ImmNEON5();
4563   int lsb = LowestSetBitPosition(imm5);
4564   int reg_index = imm5 >> lsb;
4565 
4566   if (instr->Mask(NEONCopyInsElementMask) == NEON_INS_ELEMENT) {
4567     int imm4 = instr->ImmNEON4();
4568     DCHECK_GE(lsb, 1);
4569     int rn_index = imm4 >> (lsb - 1);
4570     ins_element(vf, rd, reg_index, rn, rn_index);
4571   } else if (instr->Mask(NEONCopyInsGeneralMask) == NEON_INS_GENERAL) {
4572     ins_immediate(vf, rd, reg_index, xreg(instr->Rn()));
4573   } else if (instr->Mask(NEONCopyUmovMask) == NEON_UMOV) {
4574     uint64_t value = LogicVRegister(rn).Uint(vf, reg_index);
4575     value &= MaxUintFromFormat(vf);
4576     set_xreg(instr->Rd(), value);
4577   } else if (instr->Mask(NEONCopyUmovMask) == NEON_SMOV) {
4578     int64_t value = LogicVRegister(rn).Int(vf, reg_index);
4579     if (instr->NEONQ()) {
4580       set_xreg(instr->Rd(), value);
4581     } else {
4582       DCHECK(is_int32(value));
4583       set_wreg(instr->Rd(), static_cast<int32_t>(value));
4584     }
4585   } else if (instr->Mask(NEONCopyDupElementMask) == NEON_DUP_ELEMENT) {
4586     dup_element(vf, rd, rn, reg_index);
4587   } else if (instr->Mask(NEONCopyDupGeneralMask) == NEON_DUP_GENERAL) {
4588     dup_immediate(vf, rd, xreg(instr->Rn()));
4589   } else {
4590     UNIMPLEMENTED();
4591   }
4592 }
4593 
VisitNEONExtract(Instruction * instr)4594 void Simulator::VisitNEONExtract(Instruction* instr) {
4595   NEONFormatDecoder nfd(instr, NEONFormatDecoder::LogicalFormatMap());
4596   VectorFormat vf = nfd.GetVectorFormat();
4597   SimVRegister& rd = vreg(instr->Rd());
4598   SimVRegister& rn = vreg(instr->Rn());
4599   SimVRegister& rm = vreg(instr->Rm());
4600   if (instr->Mask(NEONExtractMask) == NEON_EXT) {
4601     int index = instr->ImmNEONExt();
4602     ext(vf, rd, rn, rm, index);
4603   } else {
4604     UNIMPLEMENTED();
4605   }
4606 }
4607 
NEONLoadStoreMultiStructHelper(const Instruction * instr,AddrMode addr_mode)4608 void Simulator::NEONLoadStoreMultiStructHelper(const Instruction* instr,
4609                                                AddrMode addr_mode) {
4610   NEONFormatDecoder nfd(instr, NEONFormatDecoder::LoadStoreFormatMap());
4611   VectorFormat vf = nfd.GetVectorFormat();
4612 
4613   uint64_t addr_base = xreg(instr->Rn(), Reg31IsStackPointer);
4614   int reg_size = RegisterSizeInBytesFromFormat(vf);
4615 
4616   int reg[4];
4617   uint64_t addr[4];
4618   for (int i = 0; i < 4; i++) {
4619     reg[i] = (instr->Rt() + i) % kNumberOfVRegisters;
4620     addr[i] = addr_base + (i * reg_size);
4621   }
4622   int count = 1;
4623   bool log_read = true;
4624 
4625   // Bit 23 determines whether this is an offset or post-index addressing mode.
4626   // In offset mode, bits 20 to 16 should be zero; these bits encode the
4627   // register of immediate in post-index mode.
4628   if ((instr->Bit(23) == 0) && (instr->Bits(20, 16) != 0)) {
4629     UNREACHABLE();
4630   }
4631 
4632   // We use the PostIndex mask here, as it works in this case for both Offset
4633   // and PostIndex addressing.
4634   switch (instr->Mask(NEONLoadStoreMultiStructPostIndexMask)) {
4635     case NEON_LD1_4v:
4636     case NEON_LD1_4v_post:
4637       ld1(vf, vreg(reg[3]), addr[3]);
4638       count++;
4639       V8_FALLTHROUGH;
4640     case NEON_LD1_3v:
4641     case NEON_LD1_3v_post:
4642       ld1(vf, vreg(reg[2]), addr[2]);
4643       count++;
4644       V8_FALLTHROUGH;
4645     case NEON_LD1_2v:
4646     case NEON_LD1_2v_post:
4647       ld1(vf, vreg(reg[1]), addr[1]);
4648       count++;
4649       V8_FALLTHROUGH;
4650     case NEON_LD1_1v:
4651     case NEON_LD1_1v_post:
4652       ld1(vf, vreg(reg[0]), addr[0]);
4653       break;
4654     case NEON_ST1_4v:
4655     case NEON_ST1_4v_post:
4656       st1(vf, vreg(reg[3]), addr[3]);
4657       count++;
4658       V8_FALLTHROUGH;
4659     case NEON_ST1_3v:
4660     case NEON_ST1_3v_post:
4661       st1(vf, vreg(reg[2]), addr[2]);
4662       count++;
4663       V8_FALLTHROUGH;
4664     case NEON_ST1_2v:
4665     case NEON_ST1_2v_post:
4666       st1(vf, vreg(reg[1]), addr[1]);
4667       count++;
4668       V8_FALLTHROUGH;
4669     case NEON_ST1_1v:
4670     case NEON_ST1_1v_post:
4671       st1(vf, vreg(reg[0]), addr[0]);
4672       log_read = false;
4673       break;
4674     case NEON_LD2_post:
4675     case NEON_LD2:
4676       ld2(vf, vreg(reg[0]), vreg(reg[1]), addr[0]);
4677       count = 2;
4678       break;
4679     case NEON_ST2:
4680     case NEON_ST2_post:
4681       st2(vf, vreg(reg[0]), vreg(reg[1]), addr[0]);
4682       count = 2;
4683       log_read = false;
4684       break;
4685     case NEON_LD3_post:
4686     case NEON_LD3:
4687       ld3(vf, vreg(reg[0]), vreg(reg[1]), vreg(reg[2]), addr[0]);
4688       count = 3;
4689       break;
4690     case NEON_ST3:
4691     case NEON_ST3_post:
4692       st3(vf, vreg(reg[0]), vreg(reg[1]), vreg(reg[2]), addr[0]);
4693       count = 3;
4694       log_read = false;
4695       break;
4696     case NEON_LD4_post:
4697     case NEON_LD4:
4698       ld4(vf, vreg(reg[0]), vreg(reg[1]), vreg(reg[2]), vreg(reg[3]), addr[0]);
4699       count = 4;
4700       break;
4701     case NEON_ST4:
4702     case NEON_ST4_post:
4703       st4(vf, vreg(reg[0]), vreg(reg[1]), vreg(reg[2]), vreg(reg[3]), addr[0]);
4704       count = 4;
4705       log_read = false;
4706       break;
4707     default:
4708       UNIMPLEMENTED();
4709   }
4710 
4711   {
4712     base::MutexGuard lock_guard(&GlobalMonitor::Get()->mutex);
4713     if (log_read) {
4714       local_monitor_.NotifyLoad();
4715     } else {
4716       local_monitor_.NotifyStore();
4717       GlobalMonitor::Get()->NotifyStore_Locked(&global_monitor_processor_);
4718     }
4719   }
4720 
4721   // Explicitly log the register update whilst we have type information.
4722   for (int i = 0; i < count; i++) {
4723     // For de-interleaving loads, only print the base address.
4724     int lane_size = LaneSizeInBytesFromFormat(vf);
4725     PrintRegisterFormat format = GetPrintRegisterFormatTryFP(
4726         GetPrintRegisterFormatForSize(reg_size, lane_size));
4727     if (log_read) {
4728       LogVRead(addr_base, reg[i], format);
4729     } else {
4730       LogVWrite(addr_base, reg[i], format);
4731     }
4732   }
4733 
4734   if (addr_mode == PostIndex) {
4735     int rm = instr->Rm();
4736     // The immediate post index addressing mode is indicated by rm = 31.
4737     // The immediate is implied by the number of vector registers used.
4738     addr_base +=
4739         (rm == 31) ? RegisterSizeInBytesFromFormat(vf) * count : xreg(rm);
4740     set_xreg(instr->Rn(), addr_base);
4741   } else {
4742     DCHECK_EQ(addr_mode, Offset);
4743   }
4744 }
4745 
VisitNEONLoadStoreMultiStruct(Instruction * instr)4746 void Simulator::VisitNEONLoadStoreMultiStruct(Instruction* instr) {
4747   NEONLoadStoreMultiStructHelper(instr, Offset);
4748 }
4749 
VisitNEONLoadStoreMultiStructPostIndex(Instruction * instr)4750 void Simulator::VisitNEONLoadStoreMultiStructPostIndex(Instruction* instr) {
4751   NEONLoadStoreMultiStructHelper(instr, PostIndex);
4752 }
4753 
NEONLoadStoreSingleStructHelper(const Instruction * instr,AddrMode addr_mode)4754 void Simulator::NEONLoadStoreSingleStructHelper(const Instruction* instr,
4755                                                 AddrMode addr_mode) {
4756   uint64_t addr = xreg(instr->Rn(), Reg31IsStackPointer);
4757   int rt = instr->Rt();
4758 
4759   // Bit 23 determines whether this is an offset or post-index addressing mode.
4760   // In offset mode, bits 20 to 16 should be zero; these bits encode the
4761   // register of immediate in post-index mode.
4762   DCHECK_IMPLIES(instr->Bit(23) == 0, instr->Bits(20, 16) == 0);
4763 
4764   bool do_load = false;
4765 
4766   NEONFormatDecoder nfd(instr, NEONFormatDecoder::LoadStoreFormatMap());
4767   VectorFormat vf_t = nfd.GetVectorFormat();
4768 
4769   VectorFormat vf = kFormat16B;
4770   // We use the PostIndex mask here, as it works in this case for both Offset
4771   // and PostIndex addressing.
4772   switch (instr->Mask(NEONLoadStoreSingleStructPostIndexMask)) {
4773     case NEON_LD1_b:
4774     case NEON_LD1_b_post:
4775     case NEON_LD2_b:
4776     case NEON_LD2_b_post:
4777     case NEON_LD3_b:
4778     case NEON_LD3_b_post:
4779     case NEON_LD4_b:
4780     case NEON_LD4_b_post:
4781       do_load = true;
4782       V8_FALLTHROUGH;
4783     case NEON_ST1_b:
4784     case NEON_ST1_b_post:
4785     case NEON_ST2_b:
4786     case NEON_ST2_b_post:
4787     case NEON_ST3_b:
4788     case NEON_ST3_b_post:
4789     case NEON_ST4_b:
4790     case NEON_ST4_b_post:
4791       break;
4792 
4793     case NEON_LD1_h:
4794     case NEON_LD1_h_post:
4795     case NEON_LD2_h:
4796     case NEON_LD2_h_post:
4797     case NEON_LD3_h:
4798     case NEON_LD3_h_post:
4799     case NEON_LD4_h:
4800     case NEON_LD4_h_post:
4801       do_load = true;
4802       V8_FALLTHROUGH;
4803     case NEON_ST1_h:
4804     case NEON_ST1_h_post:
4805     case NEON_ST2_h:
4806     case NEON_ST2_h_post:
4807     case NEON_ST3_h:
4808     case NEON_ST3_h_post:
4809     case NEON_ST4_h:
4810     case NEON_ST4_h_post:
4811       vf = kFormat8H;
4812       break;
4813 
4814     case NEON_LD1_s:
4815     case NEON_LD1_s_post:
4816     case NEON_LD2_s:
4817     case NEON_LD2_s_post:
4818     case NEON_LD3_s:
4819     case NEON_LD3_s_post:
4820     case NEON_LD4_s:
4821     case NEON_LD4_s_post:
4822       do_load = true;
4823       V8_FALLTHROUGH;
4824     case NEON_ST1_s:
4825     case NEON_ST1_s_post:
4826     case NEON_ST2_s:
4827     case NEON_ST2_s_post:
4828     case NEON_ST3_s:
4829     case NEON_ST3_s_post:
4830     case NEON_ST4_s:
4831     case NEON_ST4_s_post: {
4832       static_assert((NEON_LD1_s | (1 << NEONLSSize_offset)) == NEON_LD1_d,
4833                     "LSB of size distinguishes S and D registers.");
4834       static_assert(
4835           (NEON_LD1_s_post | (1 << NEONLSSize_offset)) == NEON_LD1_d_post,
4836           "LSB of size distinguishes S and D registers.");
4837       static_assert((NEON_ST1_s | (1 << NEONLSSize_offset)) == NEON_ST1_d,
4838                     "LSB of size distinguishes S and D registers.");
4839       static_assert(
4840           (NEON_ST1_s_post | (1 << NEONLSSize_offset)) == NEON_ST1_d_post,
4841           "LSB of size distinguishes S and D registers.");
4842       vf = ((instr->NEONLSSize() & 1) == 0) ? kFormat4S : kFormat2D;
4843       break;
4844     }
4845 
4846     case NEON_LD1R:
4847     case NEON_LD1R_post: {
4848       vf = vf_t;
4849       ld1r(vf, vreg(rt), addr);
4850       do_load = true;
4851       break;
4852     }
4853 
4854     case NEON_LD2R:
4855     case NEON_LD2R_post: {
4856       vf = vf_t;
4857       int rt2 = (rt + 1) % kNumberOfVRegisters;
4858       ld2r(vf, vreg(rt), vreg(rt2), addr);
4859       do_load = true;
4860       break;
4861     }
4862 
4863     case NEON_LD3R:
4864     case NEON_LD3R_post: {
4865       vf = vf_t;
4866       int rt2 = (rt + 1) % kNumberOfVRegisters;
4867       int rt3 = (rt2 + 1) % kNumberOfVRegisters;
4868       ld3r(vf, vreg(rt), vreg(rt2), vreg(rt3), addr);
4869       do_load = true;
4870       break;
4871     }
4872 
4873     case NEON_LD4R:
4874     case NEON_LD4R_post: {
4875       vf = vf_t;
4876       int rt2 = (rt + 1) % kNumberOfVRegisters;
4877       int rt3 = (rt2 + 1) % kNumberOfVRegisters;
4878       int rt4 = (rt3 + 1) % kNumberOfVRegisters;
4879       ld4r(vf, vreg(rt), vreg(rt2), vreg(rt3), vreg(rt4), addr);
4880       do_load = true;
4881       break;
4882     }
4883     default:
4884       UNIMPLEMENTED();
4885   }
4886 
4887   PrintRegisterFormat print_format =
4888       GetPrintRegisterFormatTryFP(GetPrintRegisterFormat(vf));
4889   // Make sure that the print_format only includes a single lane.
4890   print_format =
4891       static_cast<PrintRegisterFormat>(print_format & ~kPrintRegAsVectorMask);
4892 
4893   int esize = LaneSizeInBytesFromFormat(vf);
4894   int index_shift = LaneSizeInBytesLog2FromFormat(vf);
4895   int lane = instr->NEONLSIndex(index_shift);
4896   int scale = 0;
4897   int rt2 = (rt + 1) % kNumberOfVRegisters;
4898   int rt3 = (rt2 + 1) % kNumberOfVRegisters;
4899   int rt4 = (rt3 + 1) % kNumberOfVRegisters;
4900   switch (instr->Mask(NEONLoadStoreSingleLenMask)) {
4901     case NEONLoadStoreSingle1:
4902       scale = 1;
4903       if (do_load) {
4904         ld1(vf, vreg(rt), lane, addr);
4905         LogVRead(addr, rt, print_format, lane);
4906       } else {
4907         st1(vf, vreg(rt), lane, addr);
4908         LogVWrite(addr, rt, print_format, lane);
4909       }
4910       break;
4911     case NEONLoadStoreSingle2:
4912       scale = 2;
4913       if (do_load) {
4914         ld2(vf, vreg(rt), vreg(rt2), lane, addr);
4915         LogVRead(addr, rt, print_format, lane);
4916         LogVRead(addr + esize, rt2, print_format, lane);
4917       } else {
4918         st2(vf, vreg(rt), vreg(rt2), lane, addr);
4919         LogVWrite(addr, rt, print_format, lane);
4920         LogVWrite(addr + esize, rt2, print_format, lane);
4921       }
4922       break;
4923     case NEONLoadStoreSingle3:
4924       scale = 3;
4925       if (do_load) {
4926         ld3(vf, vreg(rt), vreg(rt2), vreg(rt3), lane, addr);
4927         LogVRead(addr, rt, print_format, lane);
4928         LogVRead(addr + esize, rt2, print_format, lane);
4929         LogVRead(addr + (2 * esize), rt3, print_format, lane);
4930       } else {
4931         st3(vf, vreg(rt), vreg(rt2), vreg(rt3), lane, addr);
4932         LogVWrite(addr, rt, print_format, lane);
4933         LogVWrite(addr + esize, rt2, print_format, lane);
4934         LogVWrite(addr + (2 * esize), rt3, print_format, lane);
4935       }
4936       break;
4937     case NEONLoadStoreSingle4:
4938       scale = 4;
4939       if (do_load) {
4940         ld4(vf, vreg(rt), vreg(rt2), vreg(rt3), vreg(rt4), lane, addr);
4941         LogVRead(addr, rt, print_format, lane);
4942         LogVRead(addr + esize, rt2, print_format, lane);
4943         LogVRead(addr + (2 * esize), rt3, print_format, lane);
4944         LogVRead(addr + (3 * esize), rt4, print_format, lane);
4945       } else {
4946         st4(vf, vreg(rt), vreg(rt2), vreg(rt3), vreg(rt4), lane, addr);
4947         LogVWrite(addr, rt, print_format, lane);
4948         LogVWrite(addr + esize, rt2, print_format, lane);
4949         LogVWrite(addr + (2 * esize), rt3, print_format, lane);
4950         LogVWrite(addr + (3 * esize), rt4, print_format, lane);
4951       }
4952       break;
4953     default:
4954       UNIMPLEMENTED();
4955   }
4956 
4957   {
4958     base::MutexGuard lock_guard(&GlobalMonitor::Get()->mutex);
4959     if (do_load) {
4960       local_monitor_.NotifyLoad();
4961     } else {
4962       local_monitor_.NotifyStore();
4963       GlobalMonitor::Get()->NotifyStore_Locked(&global_monitor_processor_);
4964     }
4965   }
4966 
4967   if (addr_mode == PostIndex) {
4968     int rm = instr->Rm();
4969     int lane_size = LaneSizeInBytesFromFormat(vf);
4970     set_xreg(instr->Rn(), addr + ((rm == 31) ? (scale * lane_size) : xreg(rm)));
4971   }
4972 }
4973 
VisitNEONLoadStoreSingleStruct(Instruction * instr)4974 void Simulator::VisitNEONLoadStoreSingleStruct(Instruction* instr) {
4975   NEONLoadStoreSingleStructHelper(instr, Offset);
4976 }
4977 
VisitNEONLoadStoreSingleStructPostIndex(Instruction * instr)4978 void Simulator::VisitNEONLoadStoreSingleStructPostIndex(Instruction* instr) {
4979   NEONLoadStoreSingleStructHelper(instr, PostIndex);
4980 }
4981 
VisitNEONModifiedImmediate(Instruction * instr)4982 void Simulator::VisitNEONModifiedImmediate(Instruction* instr) {
4983   SimVRegister& rd = vreg(instr->Rd());
4984   int cmode = instr->NEONCmode();
4985   int cmode_3_1 = (cmode >> 1) & 7;
4986   int cmode_3 = (cmode >> 3) & 1;
4987   int cmode_2 = (cmode >> 2) & 1;
4988   int cmode_1 = (cmode >> 1) & 1;
4989   int cmode_0 = cmode & 1;
4990   int q = instr->NEONQ();
4991   int op_bit = instr->NEONModImmOp();
4992   uint64_t imm8 = instr->ImmNEONabcdefgh();
4993 
4994   // Find the format and immediate value
4995   uint64_t imm = 0;
4996   VectorFormat vform = kFormatUndefined;
4997   switch (cmode_3_1) {
4998     case 0x0:
4999     case 0x1:
5000     case 0x2:
5001     case 0x3:
5002       vform = (q == 1) ? kFormat4S : kFormat2S;
5003       imm = imm8 << (8 * cmode_3_1);
5004       break;
5005     case 0x4:
5006     case 0x5:
5007       vform = (q == 1) ? kFormat8H : kFormat4H;
5008       imm = imm8 << (8 * cmode_1);
5009       break;
5010     case 0x6:
5011       vform = (q == 1) ? kFormat4S : kFormat2S;
5012       if (cmode_0 == 0) {
5013         imm = imm8 << 8 | 0x000000FF;
5014       } else {
5015         imm = imm8 << 16 | 0x0000FFFF;
5016       }
5017       break;
5018     case 0x7:
5019       if (cmode_0 == 0 && op_bit == 0) {
5020         vform = q ? kFormat16B : kFormat8B;
5021         imm = imm8;
5022       } else if (cmode_0 == 0 && op_bit == 1) {
5023         vform = q ? kFormat2D : kFormat1D;
5024         imm = 0;
5025         for (int i = 0; i < 8; ++i) {
5026           if (imm8 & (1ULL << i)) {
5027             imm |= (UINT64_C(0xFF) << (8 * i));
5028           }
5029         }
5030       } else {  // cmode_0 == 1, cmode == 0xF.
5031         if (op_bit == 0) {
5032           vform = q ? kFormat4S : kFormat2S;
5033           imm = bit_cast<uint32_t>(instr->ImmNEONFP32());
5034         } else if (q == 1) {
5035           vform = kFormat2D;
5036           imm = bit_cast<uint64_t>(instr->ImmNEONFP64());
5037         } else {
5038           DCHECK((q == 0) && (op_bit == 1) && (cmode == 0xF));
5039           VisitUnallocated(instr);
5040         }
5041       }
5042       break;
5043     default:
5044       UNREACHABLE();
5045   }
5046 
5047   // Find the operation.
5048   NEONModifiedImmediateOp op;
5049   if (cmode_3 == 0) {
5050     if (cmode_0 == 0) {
5051       op = op_bit ? NEONModifiedImmediate_MVNI : NEONModifiedImmediate_MOVI;
5052     } else {  // cmode<0> == '1'
5053       op = op_bit ? NEONModifiedImmediate_BIC : NEONModifiedImmediate_ORR;
5054     }
5055   } else {  // cmode<3> == '1'
5056     if (cmode_2 == 0) {
5057       if (cmode_0 == 0) {
5058         op = op_bit ? NEONModifiedImmediate_MVNI : NEONModifiedImmediate_MOVI;
5059       } else {  // cmode<0> == '1'
5060         op = op_bit ? NEONModifiedImmediate_BIC : NEONModifiedImmediate_ORR;
5061       }
5062     } else {  // cmode<2> == '1'
5063       if (cmode_1 == 0) {
5064         op = op_bit ? NEONModifiedImmediate_MVNI : NEONModifiedImmediate_MOVI;
5065       } else {  // cmode<1> == '1'
5066         if (cmode_0 == 0) {
5067           op = NEONModifiedImmediate_MOVI;
5068         } else {  // cmode<0> == '1'
5069           op = NEONModifiedImmediate_MOVI;
5070         }
5071       }
5072     }
5073   }
5074 
5075   // Call the logic function.
5076   switch (op) {
5077     case NEONModifiedImmediate_ORR:
5078       orr(vform, rd, rd, imm);
5079       break;
5080     case NEONModifiedImmediate_BIC:
5081       bic(vform, rd, rd, imm);
5082       break;
5083     case NEONModifiedImmediate_MOVI:
5084       movi(vform, rd, imm);
5085       break;
5086     case NEONModifiedImmediate_MVNI:
5087       mvni(vform, rd, imm);
5088       break;
5089     default:
5090       VisitUnimplemented(instr);
5091   }
5092 }
5093 
VisitNEONScalar2RegMisc(Instruction * instr)5094 void Simulator::VisitNEONScalar2RegMisc(Instruction* instr) {
5095   NEONFormatDecoder nfd(instr, NEONFormatDecoder::ScalarFormatMap());
5096   VectorFormat vf = nfd.GetVectorFormat();
5097 
5098   SimVRegister& rd = vreg(instr->Rd());
5099   SimVRegister& rn = vreg(instr->Rn());
5100 
5101   if (instr->Mask(NEON2RegMiscOpcode) <= NEON_NEG_scalar_opcode) {
5102     // These instructions all use a two bit size field, except NOT and RBIT,
5103     // which use the field to encode the operation.
5104     switch (instr->Mask(NEONScalar2RegMiscMask)) {
5105       case NEON_CMEQ_zero_scalar:
5106         cmp(vf, rd, rn, 0, eq);
5107         break;
5108       case NEON_CMGE_zero_scalar:
5109         cmp(vf, rd, rn, 0, ge);
5110         break;
5111       case NEON_CMGT_zero_scalar:
5112         cmp(vf, rd, rn, 0, gt);
5113         break;
5114       case NEON_CMLT_zero_scalar:
5115         cmp(vf, rd, rn, 0, lt);
5116         break;
5117       case NEON_CMLE_zero_scalar:
5118         cmp(vf, rd, rn, 0, le);
5119         break;
5120       case NEON_ABS_scalar:
5121         abs(vf, rd, rn);
5122         break;
5123       case NEON_SQABS_scalar:
5124         abs(vf, rd, rn).SignedSaturate(vf);
5125         break;
5126       case NEON_NEG_scalar:
5127         neg(vf, rd, rn);
5128         break;
5129       case NEON_SQNEG_scalar:
5130         neg(vf, rd, rn).SignedSaturate(vf);
5131         break;
5132       case NEON_SUQADD_scalar:
5133         suqadd(vf, rd, rn);
5134         break;
5135       case NEON_USQADD_scalar:
5136         usqadd(vf, rd, rn);
5137         break;
5138       default:
5139         UNIMPLEMENTED();
5140         break;
5141     }
5142   } else {
5143     VectorFormat fpf = nfd.GetVectorFormat(nfd.FPScalarFormatMap());
5144     FPRounding fpcr_rounding = static_cast<FPRounding>(fpcr().RMode());
5145 
5146     // These instructions all use a one bit size field, except SQXTUN, SQXTN
5147     // and UQXTN, which use a two bit size field.
5148     switch (instr->Mask(NEONScalar2RegMiscFPMask)) {
5149       case NEON_FRECPE_scalar:
5150         frecpe(fpf, rd, rn, fpcr_rounding);
5151         break;
5152       case NEON_FRECPX_scalar:
5153         frecpx(fpf, rd, rn);
5154         break;
5155       case NEON_FRSQRTE_scalar:
5156         frsqrte(fpf, rd, rn);
5157         break;
5158       case NEON_FCMGT_zero_scalar:
5159         fcmp_zero(fpf, rd, rn, gt);
5160         break;
5161       case NEON_FCMGE_zero_scalar:
5162         fcmp_zero(fpf, rd, rn, ge);
5163         break;
5164       case NEON_FCMEQ_zero_scalar:
5165         fcmp_zero(fpf, rd, rn, eq);
5166         break;
5167       case NEON_FCMLE_zero_scalar:
5168         fcmp_zero(fpf, rd, rn, le);
5169         break;
5170       case NEON_FCMLT_zero_scalar:
5171         fcmp_zero(fpf, rd, rn, lt);
5172         break;
5173       case NEON_SCVTF_scalar:
5174         scvtf(fpf, rd, rn, 0, fpcr_rounding);
5175         break;
5176       case NEON_UCVTF_scalar:
5177         ucvtf(fpf, rd, rn, 0, fpcr_rounding);
5178         break;
5179       case NEON_FCVTNS_scalar:
5180         fcvts(fpf, rd, rn, FPTieEven);
5181         break;
5182       case NEON_FCVTNU_scalar:
5183         fcvtu(fpf, rd, rn, FPTieEven);
5184         break;
5185       case NEON_FCVTPS_scalar:
5186         fcvts(fpf, rd, rn, FPPositiveInfinity);
5187         break;
5188       case NEON_FCVTPU_scalar:
5189         fcvtu(fpf, rd, rn, FPPositiveInfinity);
5190         break;
5191       case NEON_FCVTMS_scalar:
5192         fcvts(fpf, rd, rn, FPNegativeInfinity);
5193         break;
5194       case NEON_FCVTMU_scalar:
5195         fcvtu(fpf, rd, rn, FPNegativeInfinity);
5196         break;
5197       case NEON_FCVTZS_scalar:
5198         fcvts(fpf, rd, rn, FPZero);
5199         break;
5200       case NEON_FCVTZU_scalar:
5201         fcvtu(fpf, rd, rn, FPZero);
5202         break;
5203       case NEON_FCVTAS_scalar:
5204         fcvts(fpf, rd, rn, FPTieAway);
5205         break;
5206       case NEON_FCVTAU_scalar:
5207         fcvtu(fpf, rd, rn, FPTieAway);
5208         break;
5209       case NEON_FCVTXN_scalar:
5210         // Unlike all of the other FP instructions above, fcvtxn encodes dest
5211         // size S as size<0>=1. There's only one case, so we ignore the form.
5212         DCHECK_EQ(instr->Bit(22), 1);
5213         fcvtxn(kFormatS, rd, rn);
5214         break;
5215       default:
5216         switch (instr->Mask(NEONScalar2RegMiscMask)) {
5217           case NEON_SQXTN_scalar:
5218             sqxtn(vf, rd, rn);
5219             break;
5220           case NEON_UQXTN_scalar:
5221             uqxtn(vf, rd, rn);
5222             break;
5223           case NEON_SQXTUN_scalar:
5224             sqxtun(vf, rd, rn);
5225             break;
5226           default:
5227             UNIMPLEMENTED();
5228         }
5229     }
5230   }
5231 }
5232 
VisitNEONScalar3Diff(Instruction * instr)5233 void Simulator::VisitNEONScalar3Diff(Instruction* instr) {
5234   NEONFormatDecoder nfd(instr, NEONFormatDecoder::LongScalarFormatMap());
5235   VectorFormat vf = nfd.GetVectorFormat();
5236 
5237   SimVRegister& rd = vreg(instr->Rd());
5238   SimVRegister& rn = vreg(instr->Rn());
5239   SimVRegister& rm = vreg(instr->Rm());
5240   switch (instr->Mask(NEONScalar3DiffMask)) {
5241     case NEON_SQDMLAL_scalar:
5242       sqdmlal(vf, rd, rn, rm);
5243       break;
5244     case NEON_SQDMLSL_scalar:
5245       sqdmlsl(vf, rd, rn, rm);
5246       break;
5247     case NEON_SQDMULL_scalar:
5248       sqdmull(vf, rd, rn, rm);
5249       break;
5250     default:
5251       UNIMPLEMENTED();
5252   }
5253 }
5254 
VisitNEONScalar3Same(Instruction * instr)5255 void Simulator::VisitNEONScalar3Same(Instruction* instr) {
5256   NEONFormatDecoder nfd(instr, NEONFormatDecoder::ScalarFormatMap());
5257   VectorFormat vf = nfd.GetVectorFormat();
5258 
5259   SimVRegister& rd = vreg(instr->Rd());
5260   SimVRegister& rn = vreg(instr->Rn());
5261   SimVRegister& rm = vreg(instr->Rm());
5262 
5263   if (instr->Mask(NEONScalar3SameFPFMask) == NEONScalar3SameFPFixed) {
5264     vf = nfd.GetVectorFormat(nfd.FPScalarFormatMap());
5265     switch (instr->Mask(NEONScalar3SameFPMask)) {
5266       case NEON_FMULX_scalar:
5267         fmulx(vf, rd, rn, rm);
5268         break;
5269       case NEON_FACGE_scalar:
5270         fabscmp(vf, rd, rn, rm, ge);
5271         break;
5272       case NEON_FACGT_scalar:
5273         fabscmp(vf, rd, rn, rm, gt);
5274         break;
5275       case NEON_FCMEQ_scalar:
5276         fcmp(vf, rd, rn, rm, eq);
5277         break;
5278       case NEON_FCMGE_scalar:
5279         fcmp(vf, rd, rn, rm, ge);
5280         break;
5281       case NEON_FCMGT_scalar:
5282         fcmp(vf, rd, rn, rm, gt);
5283         break;
5284       case NEON_FRECPS_scalar:
5285         frecps(vf, rd, rn, rm);
5286         break;
5287       case NEON_FRSQRTS_scalar:
5288         frsqrts(vf, rd, rn, rm);
5289         break;
5290       case NEON_FABD_scalar:
5291         fabd(vf, rd, rn, rm);
5292         break;
5293       default:
5294         UNIMPLEMENTED();
5295     }
5296   } else {
5297     switch (instr->Mask(NEONScalar3SameMask)) {
5298       case NEON_ADD_scalar:
5299         add(vf, rd, rn, rm);
5300         break;
5301       case NEON_SUB_scalar:
5302         sub(vf, rd, rn, rm);
5303         break;
5304       case NEON_CMEQ_scalar:
5305         cmp(vf, rd, rn, rm, eq);
5306         break;
5307       case NEON_CMGE_scalar:
5308         cmp(vf, rd, rn, rm, ge);
5309         break;
5310       case NEON_CMGT_scalar:
5311         cmp(vf, rd, rn, rm, gt);
5312         break;
5313       case NEON_CMHI_scalar:
5314         cmp(vf, rd, rn, rm, hi);
5315         break;
5316       case NEON_CMHS_scalar:
5317         cmp(vf, rd, rn, rm, hs);
5318         break;
5319       case NEON_CMTST_scalar:
5320         cmptst(vf, rd, rn, rm);
5321         break;
5322       case NEON_USHL_scalar:
5323         ushl(vf, rd, rn, rm);
5324         break;
5325       case NEON_SSHL_scalar:
5326         sshl(vf, rd, rn, rm);
5327         break;
5328       case NEON_SQDMULH_scalar:
5329         sqdmulh(vf, rd, rn, rm);
5330         break;
5331       case NEON_SQRDMULH_scalar:
5332         sqrdmulh(vf, rd, rn, rm);
5333         break;
5334       case NEON_UQADD_scalar:
5335         add(vf, rd, rn, rm).UnsignedSaturate(vf);
5336         break;
5337       case NEON_SQADD_scalar:
5338         add(vf, rd, rn, rm).SignedSaturate(vf);
5339         break;
5340       case NEON_UQSUB_scalar:
5341         sub(vf, rd, rn, rm).UnsignedSaturate(vf);
5342         break;
5343       case NEON_SQSUB_scalar:
5344         sub(vf, rd, rn, rm).SignedSaturate(vf);
5345         break;
5346       case NEON_UQSHL_scalar:
5347         ushl(vf, rd, rn, rm).UnsignedSaturate(vf);
5348         break;
5349       case NEON_SQSHL_scalar:
5350         sshl(vf, rd, rn, rm).SignedSaturate(vf);
5351         break;
5352       case NEON_URSHL_scalar:
5353         ushl(vf, rd, rn, rm).Round(vf);
5354         break;
5355       case NEON_SRSHL_scalar:
5356         sshl(vf, rd, rn, rm).Round(vf);
5357         break;
5358       case NEON_UQRSHL_scalar:
5359         ushl(vf, rd, rn, rm).Round(vf).UnsignedSaturate(vf);
5360         break;
5361       case NEON_SQRSHL_scalar:
5362         sshl(vf, rd, rn, rm).Round(vf).SignedSaturate(vf);
5363         break;
5364       default:
5365         UNIMPLEMENTED();
5366     }
5367   }
5368 }
5369 
VisitNEONScalarByIndexedElement(Instruction * instr)5370 void Simulator::VisitNEONScalarByIndexedElement(Instruction* instr) {
5371   NEONFormatDecoder nfd(instr, NEONFormatDecoder::LongScalarFormatMap());
5372   VectorFormat vf = nfd.GetVectorFormat();
5373   VectorFormat vf_r = nfd.GetVectorFormat(nfd.ScalarFormatMap());
5374 
5375   SimVRegister& rd = vreg(instr->Rd());
5376   SimVRegister& rn = vreg(instr->Rn());
5377   ByElementOp Op = nullptr;
5378 
5379   int rm_reg = instr->Rm();
5380   int index = (instr->NEONH() << 1) | instr->NEONL();
5381   if (instr->NEONSize() == 1) {
5382     rm_reg &= 0xF;
5383     index = (index << 1) | instr->NEONM();
5384   }
5385 
5386   switch (instr->Mask(NEONScalarByIndexedElementMask)) {
5387     case NEON_SQDMULL_byelement_scalar:
5388       Op = &Simulator::sqdmull;
5389       break;
5390     case NEON_SQDMLAL_byelement_scalar:
5391       Op = &Simulator::sqdmlal;
5392       break;
5393     case NEON_SQDMLSL_byelement_scalar:
5394       Op = &Simulator::sqdmlsl;
5395       break;
5396     case NEON_SQDMULH_byelement_scalar:
5397       Op = &Simulator::sqdmulh;
5398       vf = vf_r;
5399       break;
5400     case NEON_SQRDMULH_byelement_scalar:
5401       Op = &Simulator::sqrdmulh;
5402       vf = vf_r;
5403       break;
5404     default:
5405       vf = nfd.GetVectorFormat(nfd.FPScalarFormatMap());
5406       index = instr->NEONH();
5407       if ((instr->FPType() & 1) == 0) {
5408         index = (index << 1) | instr->NEONL();
5409       }
5410       switch (instr->Mask(NEONScalarByIndexedElementFPMask)) {
5411         case NEON_FMUL_byelement_scalar:
5412           Op = &Simulator::fmul;
5413           break;
5414         case NEON_FMLA_byelement_scalar:
5415           Op = &Simulator::fmla;
5416           break;
5417         case NEON_FMLS_byelement_scalar:
5418           Op = &Simulator::fmls;
5419           break;
5420         case NEON_FMULX_byelement_scalar:
5421           Op = &Simulator::fmulx;
5422           break;
5423         default:
5424           UNIMPLEMENTED();
5425       }
5426   }
5427 
5428   (this->*Op)(vf, rd, rn, vreg(rm_reg), index);
5429 }
5430 
VisitNEONScalarCopy(Instruction * instr)5431 void Simulator::VisitNEONScalarCopy(Instruction* instr) {
5432   NEONFormatDecoder nfd(instr, NEONFormatDecoder::TriangularScalarFormatMap());
5433   VectorFormat vf = nfd.GetVectorFormat();
5434 
5435   SimVRegister& rd = vreg(instr->Rd());
5436   SimVRegister& rn = vreg(instr->Rn());
5437 
5438   if (instr->Mask(NEONScalarCopyMask) == NEON_DUP_ELEMENT_scalar) {
5439     int imm5 = instr->ImmNEON5();
5440     int lsb = LowestSetBitPosition(imm5);
5441     int rn_index = imm5 >> lsb;
5442     dup_element(vf, rd, rn, rn_index);
5443   } else {
5444     UNIMPLEMENTED();
5445   }
5446 }
5447 
VisitNEONScalarPairwise(Instruction * instr)5448 void Simulator::VisitNEONScalarPairwise(Instruction* instr) {
5449   NEONFormatDecoder nfd(instr, NEONFormatDecoder::FPScalarFormatMap());
5450   VectorFormat vf = nfd.GetVectorFormat();
5451 
5452   SimVRegister& rd = vreg(instr->Rd());
5453   SimVRegister& rn = vreg(instr->Rn());
5454   switch (instr->Mask(NEONScalarPairwiseMask)) {
5455     case NEON_ADDP_scalar:
5456       addp(vf, rd, rn);
5457       break;
5458     case NEON_FADDP_scalar:
5459       faddp(vf, rd, rn);
5460       break;
5461     case NEON_FMAXP_scalar:
5462       fmaxp(vf, rd, rn);
5463       break;
5464     case NEON_FMAXNMP_scalar:
5465       fmaxnmp(vf, rd, rn);
5466       break;
5467     case NEON_FMINP_scalar:
5468       fminp(vf, rd, rn);
5469       break;
5470     case NEON_FMINNMP_scalar:
5471       fminnmp(vf, rd, rn);
5472       break;
5473     default:
5474       UNIMPLEMENTED();
5475   }
5476 }
5477 
VisitNEONScalarShiftImmediate(Instruction * instr)5478 void Simulator::VisitNEONScalarShiftImmediate(Instruction* instr) {
5479   SimVRegister& rd = vreg(instr->Rd());
5480   SimVRegister& rn = vreg(instr->Rn());
5481   FPRounding fpcr_rounding = static_cast<FPRounding>(fpcr().RMode());
5482 
5483   static const NEONFormatMap map = {
5484       {22, 21, 20, 19},
5485       {NF_UNDEF, NF_B, NF_H, NF_H, NF_S, NF_S, NF_S, NF_S, NF_D, NF_D, NF_D,
5486        NF_D, NF_D, NF_D, NF_D, NF_D}};
5487   NEONFormatDecoder nfd(instr, &map);
5488   VectorFormat vf = nfd.GetVectorFormat();
5489 
5490   int highestSetBit = HighestSetBitPosition(instr->ImmNEONImmh());
5491   int immhimmb = instr->ImmNEONImmhImmb();
5492   int right_shift = (16 << highestSetBit) - immhimmb;
5493   int left_shift = immhimmb - (8 << highestSetBit);
5494   switch (instr->Mask(NEONScalarShiftImmediateMask)) {
5495     case NEON_SHL_scalar:
5496       shl(vf, rd, rn, left_shift);
5497       break;
5498     case NEON_SLI_scalar:
5499       sli(vf, rd, rn, left_shift);
5500       break;
5501     case NEON_SQSHL_imm_scalar:
5502       sqshl(vf, rd, rn, left_shift);
5503       break;
5504     case NEON_UQSHL_imm_scalar:
5505       uqshl(vf, rd, rn, left_shift);
5506       break;
5507     case NEON_SQSHLU_scalar:
5508       sqshlu(vf, rd, rn, left_shift);
5509       break;
5510     case NEON_SRI_scalar:
5511       sri(vf, rd, rn, right_shift);
5512       break;
5513     case NEON_SSHR_scalar:
5514       sshr(vf, rd, rn, right_shift);
5515       break;
5516     case NEON_USHR_scalar:
5517       ushr(vf, rd, rn, right_shift);
5518       break;
5519     case NEON_SRSHR_scalar:
5520       sshr(vf, rd, rn, right_shift).Round(vf);
5521       break;
5522     case NEON_URSHR_scalar:
5523       ushr(vf, rd, rn, right_shift).Round(vf);
5524       break;
5525     case NEON_SSRA_scalar:
5526       ssra(vf, rd, rn, right_shift);
5527       break;
5528     case NEON_USRA_scalar:
5529       usra(vf, rd, rn, right_shift);
5530       break;
5531     case NEON_SRSRA_scalar:
5532       srsra(vf, rd, rn, right_shift);
5533       break;
5534     case NEON_URSRA_scalar:
5535       ursra(vf, rd, rn, right_shift);
5536       break;
5537     case NEON_UQSHRN_scalar:
5538       uqshrn(vf, rd, rn, right_shift);
5539       break;
5540     case NEON_UQRSHRN_scalar:
5541       uqrshrn(vf, rd, rn, right_shift);
5542       break;
5543     case NEON_SQSHRN_scalar:
5544       sqshrn(vf, rd, rn, right_shift);
5545       break;
5546     case NEON_SQRSHRN_scalar:
5547       sqrshrn(vf, rd, rn, right_shift);
5548       break;
5549     case NEON_SQSHRUN_scalar:
5550       sqshrun(vf, rd, rn, right_shift);
5551       break;
5552     case NEON_SQRSHRUN_scalar:
5553       sqrshrun(vf, rd, rn, right_shift);
5554       break;
5555     case NEON_FCVTZS_imm_scalar:
5556       fcvts(vf, rd, rn, FPZero, right_shift);
5557       break;
5558     case NEON_FCVTZU_imm_scalar:
5559       fcvtu(vf, rd, rn, FPZero, right_shift);
5560       break;
5561     case NEON_SCVTF_imm_scalar:
5562       scvtf(vf, rd, rn, right_shift, fpcr_rounding);
5563       break;
5564     case NEON_UCVTF_imm_scalar:
5565       ucvtf(vf, rd, rn, right_shift, fpcr_rounding);
5566       break;
5567     default:
5568       UNIMPLEMENTED();
5569   }
5570 }
5571 
VisitNEONShiftImmediate(Instruction * instr)5572 void Simulator::VisitNEONShiftImmediate(Instruction* instr) {
5573   SimVRegister& rd = vreg(instr->Rd());
5574   SimVRegister& rn = vreg(instr->Rn());
5575   FPRounding fpcr_rounding = static_cast<FPRounding>(fpcr().RMode());
5576 
5577   // 00010->8B, 00011->16B, 001x0->4H, 001x1->8H,
5578   // 01xx0->2S, 01xx1->4S, 1xxx1->2D, all others undefined.
5579   static const NEONFormatMap map = {
5580       {22, 21, 20, 19, 30},
5581       {NF_UNDEF, NF_UNDEF, NF_8B,    NF_16B, NF_4H,    NF_8H, NF_4H,    NF_8H,
5582        NF_2S,    NF_4S,    NF_2S,    NF_4S,  NF_2S,    NF_4S, NF_2S,    NF_4S,
5583        NF_UNDEF, NF_2D,    NF_UNDEF, NF_2D,  NF_UNDEF, NF_2D, NF_UNDEF, NF_2D,
5584        NF_UNDEF, NF_2D,    NF_UNDEF, NF_2D,  NF_UNDEF, NF_2D, NF_UNDEF, NF_2D}};
5585   NEONFormatDecoder nfd(instr, &map);
5586   VectorFormat vf = nfd.GetVectorFormat();
5587 
5588   // 0001->8H, 001x->4S, 01xx->2D, all others undefined.
5589   static const NEONFormatMap map_l = {
5590       {22, 21, 20, 19},
5591       {NF_UNDEF, NF_8H, NF_4S, NF_4S, NF_2D, NF_2D, NF_2D, NF_2D}};
5592   VectorFormat vf_l = nfd.GetVectorFormat(&map_l);
5593 
5594   int highestSetBit = HighestSetBitPosition(instr->ImmNEONImmh());
5595   int immhimmb = instr->ImmNEONImmhImmb();
5596   int right_shift = (16 << highestSetBit) - immhimmb;
5597   int left_shift = immhimmb - (8 << highestSetBit);
5598 
5599   switch (instr->Mask(NEONShiftImmediateMask)) {
5600     case NEON_SHL:
5601       shl(vf, rd, rn, left_shift);
5602       break;
5603     case NEON_SLI:
5604       sli(vf, rd, rn, left_shift);
5605       break;
5606     case NEON_SQSHLU:
5607       sqshlu(vf, rd, rn, left_shift);
5608       break;
5609     case NEON_SRI:
5610       sri(vf, rd, rn, right_shift);
5611       break;
5612     case NEON_SSHR:
5613       sshr(vf, rd, rn, right_shift);
5614       break;
5615     case NEON_USHR:
5616       ushr(vf, rd, rn, right_shift);
5617       break;
5618     case NEON_SRSHR:
5619       sshr(vf, rd, rn, right_shift).Round(vf);
5620       break;
5621     case NEON_URSHR:
5622       ushr(vf, rd, rn, right_shift).Round(vf);
5623       break;
5624     case NEON_SSRA:
5625       ssra(vf, rd, rn, right_shift);
5626       break;
5627     case NEON_USRA:
5628       usra(vf, rd, rn, right_shift);
5629       break;
5630     case NEON_SRSRA:
5631       srsra(vf, rd, rn, right_shift);
5632       break;
5633     case NEON_URSRA:
5634       ursra(vf, rd, rn, right_shift);
5635       break;
5636     case NEON_SQSHL_imm:
5637       sqshl(vf, rd, rn, left_shift);
5638       break;
5639     case NEON_UQSHL_imm:
5640       uqshl(vf, rd, rn, left_shift);
5641       break;
5642     case NEON_SCVTF_imm:
5643       scvtf(vf, rd, rn, right_shift, fpcr_rounding);
5644       break;
5645     case NEON_UCVTF_imm:
5646       ucvtf(vf, rd, rn, right_shift, fpcr_rounding);
5647       break;
5648     case NEON_FCVTZS_imm:
5649       fcvts(vf, rd, rn, FPZero, right_shift);
5650       break;
5651     case NEON_FCVTZU_imm:
5652       fcvtu(vf, rd, rn, FPZero, right_shift);
5653       break;
5654     case NEON_SSHLL:
5655       vf = vf_l;
5656       if (instr->Mask(NEON_Q)) {
5657         sshll2(vf, rd, rn, left_shift);
5658       } else {
5659         sshll(vf, rd, rn, left_shift);
5660       }
5661       break;
5662     case NEON_USHLL:
5663       vf = vf_l;
5664       if (instr->Mask(NEON_Q)) {
5665         ushll2(vf, rd, rn, left_shift);
5666       } else {
5667         ushll(vf, rd, rn, left_shift);
5668       }
5669       break;
5670     case NEON_SHRN:
5671       if (instr->Mask(NEON_Q)) {
5672         shrn2(vf, rd, rn, right_shift);
5673       } else {
5674         shrn(vf, rd, rn, right_shift);
5675       }
5676       break;
5677     case NEON_RSHRN:
5678       if (instr->Mask(NEON_Q)) {
5679         rshrn2(vf, rd, rn, right_shift);
5680       } else {
5681         rshrn(vf, rd, rn, right_shift);
5682       }
5683       break;
5684     case NEON_UQSHRN:
5685       if (instr->Mask(NEON_Q)) {
5686         uqshrn2(vf, rd, rn, right_shift);
5687       } else {
5688         uqshrn(vf, rd, rn, right_shift);
5689       }
5690       break;
5691     case NEON_UQRSHRN:
5692       if (instr->Mask(NEON_Q)) {
5693         uqrshrn2(vf, rd, rn, right_shift);
5694       } else {
5695         uqrshrn(vf, rd, rn, right_shift);
5696       }
5697       break;
5698     case NEON_SQSHRN:
5699       if (instr->Mask(NEON_Q)) {
5700         sqshrn2(vf, rd, rn, right_shift);
5701       } else {
5702         sqshrn(vf, rd, rn, right_shift);
5703       }
5704       break;
5705     case NEON_SQRSHRN:
5706       if (instr->Mask(NEON_Q)) {
5707         sqrshrn2(vf, rd, rn, right_shift);
5708       } else {
5709         sqrshrn(vf, rd, rn, right_shift);
5710       }
5711       break;
5712     case NEON_SQSHRUN:
5713       if (instr->Mask(NEON_Q)) {
5714         sqshrun2(vf, rd, rn, right_shift);
5715       } else {
5716         sqshrun(vf, rd, rn, right_shift);
5717       }
5718       break;
5719     case NEON_SQRSHRUN:
5720       if (instr->Mask(NEON_Q)) {
5721         sqrshrun2(vf, rd, rn, right_shift);
5722       } else {
5723         sqrshrun(vf, rd, rn, right_shift);
5724       }
5725       break;
5726     default:
5727       UNIMPLEMENTED();
5728   }
5729 }
5730 
VisitNEONTable(Instruction * instr)5731 void Simulator::VisitNEONTable(Instruction* instr) {
5732   NEONFormatDecoder nfd(instr, NEONFormatDecoder::LogicalFormatMap());
5733   VectorFormat vf = nfd.GetVectorFormat();
5734 
5735   SimVRegister& rd = vreg(instr->Rd());
5736   SimVRegister& rn = vreg(instr->Rn());
5737   SimVRegister& rn2 = vreg((instr->Rn() + 1) % kNumberOfVRegisters);
5738   SimVRegister& rn3 = vreg((instr->Rn() + 2) % kNumberOfVRegisters);
5739   SimVRegister& rn4 = vreg((instr->Rn() + 3) % kNumberOfVRegisters);
5740   SimVRegister& rm = vreg(instr->Rm());
5741 
5742   switch (instr->Mask(NEONTableMask)) {
5743     case NEON_TBL_1v:
5744       tbl(vf, rd, rn, rm);
5745       break;
5746     case NEON_TBL_2v:
5747       tbl(vf, rd, rn, rn2, rm);
5748       break;
5749     case NEON_TBL_3v:
5750       tbl(vf, rd, rn, rn2, rn3, rm);
5751       break;
5752     case NEON_TBL_4v:
5753       tbl(vf, rd, rn, rn2, rn3, rn4, rm);
5754       break;
5755     case NEON_TBX_1v:
5756       tbx(vf, rd, rn, rm);
5757       break;
5758     case NEON_TBX_2v:
5759       tbx(vf, rd, rn, rn2, rm);
5760       break;
5761     case NEON_TBX_3v:
5762       tbx(vf, rd, rn, rn2, rn3, rm);
5763       break;
5764     case NEON_TBX_4v:
5765       tbx(vf, rd, rn, rn2, rn3, rn4, rm);
5766       break;
5767     default:
5768       UNIMPLEMENTED();
5769   }
5770 }
5771 
VisitNEONPerm(Instruction * instr)5772 void Simulator::VisitNEONPerm(Instruction* instr) {
5773   NEONFormatDecoder nfd(instr);
5774   VectorFormat vf = nfd.GetVectorFormat();
5775 
5776   SimVRegister& rd = vreg(instr->Rd());
5777   SimVRegister& rn = vreg(instr->Rn());
5778   SimVRegister& rm = vreg(instr->Rm());
5779 
5780   switch (instr->Mask(NEONPermMask)) {
5781     case NEON_TRN1:
5782       trn1(vf, rd, rn, rm);
5783       break;
5784     case NEON_TRN2:
5785       trn2(vf, rd, rn, rm);
5786       break;
5787     case NEON_UZP1:
5788       uzp1(vf, rd, rn, rm);
5789       break;
5790     case NEON_UZP2:
5791       uzp2(vf, rd, rn, rm);
5792       break;
5793     case NEON_ZIP1:
5794       zip1(vf, rd, rn, rm);
5795       break;
5796     case NEON_ZIP2:
5797       zip2(vf, rd, rn, rm);
5798       break;
5799     default:
5800       UNIMPLEMENTED();
5801   }
5802 }
5803 
DoPrintf(Instruction * instr)5804 void Simulator::DoPrintf(Instruction* instr) {
5805   DCHECK((instr->Mask(ExceptionMask) == HLT) &&
5806          (instr->ImmException() == kImmExceptionIsPrintf));
5807 
5808   // Read the arguments encoded inline in the instruction stream.
5809   uint32_t arg_count;
5810   uint32_t arg_pattern_list;
5811   STATIC_ASSERT(sizeof(*instr) == 1);
5812   memcpy(&arg_count, instr + kPrintfArgCountOffset, sizeof(arg_count));
5813   memcpy(&arg_pattern_list, instr + kPrintfArgPatternListOffset,
5814          sizeof(arg_pattern_list));
5815 
5816   DCHECK_LE(arg_count, kPrintfMaxArgCount);
5817   DCHECK_EQ(arg_pattern_list >> (kPrintfArgPatternBits * arg_count), 0);
5818 
5819   // We need to call the host printf function with a set of arguments defined by
5820   // arg_pattern_list. Because we don't know the types and sizes of the
5821   // arguments, this is very difficult to do in a robust and portable way. To
5822   // work around the problem, we pick apart the format string, and print one
5823   // format placeholder at a time.
5824 
5825   // Allocate space for the format string. We take a copy, so we can modify it.
5826   // Leave enough space for one extra character per expected argument (plus the
5827   // '\0' termination).
5828   const char* format_base = reg<const char*>(0);
5829   DCHECK_NOT_NULL(format_base);
5830   size_t length = strlen(format_base) + 1;
5831   char* const format = new char[length + arg_count];
5832 
5833   // A list of chunks, each with exactly one format placeholder.
5834   const char* chunks[kPrintfMaxArgCount];
5835 
5836   // Copy the format string and search for format placeholders.
5837   uint32_t placeholder_count = 0;
5838   char* format_scratch = format;
5839   for (size_t i = 0; i < length; i++) {
5840     if (format_base[i] != '%') {
5841       *format_scratch++ = format_base[i];
5842     } else {
5843       if (format_base[i + 1] == '%') {
5844         // Ignore explicit "%%" sequences.
5845         *format_scratch++ = format_base[i];
5846 
5847         if (placeholder_count == 0) {
5848           // The first chunk is passed to printf using "%s", so we need to
5849           // unescape "%%" sequences in this chunk. (Just skip the next '%'.)
5850           i++;
5851         } else {
5852           // Otherwise, pass through "%%" unchanged.
5853           *format_scratch++ = format_base[++i];
5854         }
5855       } else {
5856         CHECK(placeholder_count < arg_count);
5857         // Insert '\0' before placeholders, and store their locations.
5858         *format_scratch++ = '\0';
5859         chunks[placeholder_count++] = format_scratch;
5860         *format_scratch++ = format_base[i];
5861       }
5862     }
5863   }
5864   DCHECK(format_scratch <= (format + length + arg_count));
5865   CHECK(placeholder_count == arg_count);
5866 
5867   // Finally, call printf with each chunk, passing the appropriate register
5868   // argument. Normally, printf returns the number of bytes transmitted, so we
5869   // can emulate a single printf call by adding the result from each chunk. If
5870   // any call returns a negative (error) value, though, just return that value.
5871 
5872   fprintf(stream_, "%s", clr_printf);
5873 
5874   // Because '\0' is inserted before each placeholder, the first string in
5875   // 'format' contains no format placeholders and should be printed literally.
5876   int result = fprintf(stream_, "%s", format);
5877   int pcs_r = 1;  // Start at x1. x0 holds the format string.
5878   int pcs_f = 0;  // Start at d0.
5879   if (result >= 0) {
5880     for (uint32_t i = 0; i < placeholder_count; i++) {
5881       int part_result = -1;
5882 
5883       uint32_t arg_pattern = arg_pattern_list >> (i * kPrintfArgPatternBits);
5884       arg_pattern &= (1 << kPrintfArgPatternBits) - 1;
5885       switch (arg_pattern) {
5886         case kPrintfArgW:
5887           part_result = fprintf(stream_, chunks[i], wreg(pcs_r++));
5888           break;
5889         case kPrintfArgX:
5890           part_result = fprintf(stream_, chunks[i], xreg(pcs_r++));
5891           break;
5892         case kPrintfArgD:
5893           part_result = fprintf(stream_, chunks[i], dreg(pcs_f++));
5894           break;
5895         default:
5896           UNREACHABLE();
5897       }
5898 
5899       if (part_result < 0) {
5900         // Handle error values.
5901         result = part_result;
5902         break;
5903       }
5904 
5905       result += part_result;
5906     }
5907   }
5908 
5909   fprintf(stream_, "%s", clr_normal);
5910 
5911 #ifdef DEBUG
5912   CorruptAllCallerSavedCPURegisters();
5913 #endif
5914 
5915   // Printf returns its result in x0 (just like the C library's printf).
5916   set_xreg(0, result);
5917 
5918   // The printf parameters are inlined in the code, so skip them.
5919   set_pc(instr->InstructionAtOffset(kPrintfLength));
5920 
5921   // Set LR as if we'd just called a native printf function.
5922   set_lr(pc());
5923 
5924   delete[] format;
5925 }
5926 
LocalMonitor()5927 Simulator::LocalMonitor::LocalMonitor()
5928     : access_state_(MonitorAccess::Open),
5929       tagged_addr_(0),
5930       size_(TransactionSize::None) {}
5931 
Clear()5932 void Simulator::LocalMonitor::Clear() {
5933   access_state_ = MonitorAccess::Open;
5934   tagged_addr_ = 0;
5935   size_ = TransactionSize::None;
5936 }
5937 
NotifyLoad()5938 void Simulator::LocalMonitor::NotifyLoad() {
5939   if (access_state_ == MonitorAccess::Exclusive) {
5940     // A non exclusive load could clear the local monitor. As a result, it's
5941     // most strict to unconditionally clear the local monitor on load.
5942     Clear();
5943   }
5944 }
5945 
NotifyLoadExcl(uintptr_t addr,TransactionSize size)5946 void Simulator::LocalMonitor::NotifyLoadExcl(uintptr_t addr,
5947                                              TransactionSize size) {
5948   access_state_ = MonitorAccess::Exclusive;
5949   tagged_addr_ = addr;
5950   size_ = size;
5951 }
5952 
NotifyStore()5953 void Simulator::LocalMonitor::NotifyStore() {
5954   if (access_state_ == MonitorAccess::Exclusive) {
5955     // A non exclusive store could clear the local monitor. As a result, it's
5956     // most strict to unconditionally clear the local monitor on store.
5957     Clear();
5958   }
5959 }
5960 
NotifyStoreExcl(uintptr_t addr,TransactionSize size)5961 bool Simulator::LocalMonitor::NotifyStoreExcl(uintptr_t addr,
5962                                               TransactionSize size) {
5963   if (access_state_ == MonitorAccess::Exclusive) {
5964     // It is allowed for a processor to require that the address matches
5965     // exactly (B2.10.1), so this comparison does not mask addr.
5966     if (addr == tagged_addr_ && size_ == size) {
5967       Clear();
5968       return true;
5969     } else {
5970       // It is implementation-defined whether an exclusive store to a
5971       // non-tagged address will update memory. As a result, it's most strict
5972       // to unconditionally clear the local monitor.
5973       Clear();
5974       return false;
5975     }
5976   } else {
5977     DCHECK(access_state_ == MonitorAccess::Open);
5978     return false;
5979   }
5980 }
5981 
Processor()5982 Simulator::GlobalMonitor::Processor::Processor()
5983     : access_state_(MonitorAccess::Open),
5984       tagged_addr_(0),
5985       next_(nullptr),
5986       prev_(nullptr),
5987       failure_counter_(0) {}
5988 
Clear_Locked()5989 void Simulator::GlobalMonitor::Processor::Clear_Locked() {
5990   access_state_ = MonitorAccess::Open;
5991   tagged_addr_ = 0;
5992 }
5993 
NotifyLoadExcl_Locked(uintptr_t addr)5994 void Simulator::GlobalMonitor::Processor::NotifyLoadExcl_Locked(
5995     uintptr_t addr) {
5996   access_state_ = MonitorAccess::Exclusive;
5997   tagged_addr_ = addr;
5998 }
5999 
NotifyStore_Locked(bool is_requesting_processor)6000 void Simulator::GlobalMonitor::Processor::NotifyStore_Locked(
6001     bool is_requesting_processor) {
6002   if (access_state_ == MonitorAccess::Exclusive) {
6003     // A non exclusive store could clear the global monitor. As a result, it's
6004     // most strict to unconditionally clear global monitors on store.
6005     Clear_Locked();
6006   }
6007 }
6008 
NotifyStoreExcl_Locked(uintptr_t addr,bool is_requesting_processor)6009 bool Simulator::GlobalMonitor::Processor::NotifyStoreExcl_Locked(
6010     uintptr_t addr, bool is_requesting_processor) {
6011   if (access_state_ == MonitorAccess::Exclusive) {
6012     if (is_requesting_processor) {
6013       // It is allowed for a processor to require that the address matches
6014       // exactly (B2.10.2), so this comparison does not mask addr.
6015       if (addr == tagged_addr_) {
6016         Clear_Locked();
6017         // Introduce occasional stxr failures. This is to simulate the
6018         // behavior of hardware, which can randomly fail due to background
6019         // cache evictions.
6020         if (failure_counter_++ >= kMaxFailureCounter) {
6021           failure_counter_ = 0;
6022           return false;
6023         } else {
6024           return true;
6025         }
6026       }
6027     } else if ((addr & kExclusiveTaggedAddrMask) ==
6028                (tagged_addr_ & kExclusiveTaggedAddrMask)) {
6029       // Check the masked addresses when responding to a successful lock by
6030       // another processor so the implementation is more conservative (i.e. the
6031       // granularity of locking is as large as possible.)
6032       Clear_Locked();
6033       return false;
6034     }
6035   }
6036   return false;
6037 }
6038 
NotifyLoadExcl_Locked(uintptr_t addr,Processor * processor)6039 void Simulator::GlobalMonitor::NotifyLoadExcl_Locked(uintptr_t addr,
6040                                                      Processor* processor) {
6041   processor->NotifyLoadExcl_Locked(addr);
6042   PrependProcessor_Locked(processor);
6043 }
6044 
NotifyStore_Locked(Processor * processor)6045 void Simulator::GlobalMonitor::NotifyStore_Locked(Processor* processor) {
6046   // Notify each processor of the store operation.
6047   for (Processor* iter = head_; iter; iter = iter->next_) {
6048     bool is_requesting_processor = iter == processor;
6049     iter->NotifyStore_Locked(is_requesting_processor);
6050   }
6051 }
6052 
NotifyStoreExcl_Locked(uintptr_t addr,Processor * processor)6053 bool Simulator::GlobalMonitor::NotifyStoreExcl_Locked(uintptr_t addr,
6054                                                       Processor* processor) {
6055   DCHECK(IsProcessorInLinkedList_Locked(processor));
6056   if (processor->NotifyStoreExcl_Locked(addr, true)) {
6057     // Notify the other processors that this StoreExcl succeeded.
6058     for (Processor* iter = head_; iter; iter = iter->next_) {
6059       if (iter != processor) {
6060         iter->NotifyStoreExcl_Locked(addr, false);
6061       }
6062     }
6063     return true;
6064   } else {
6065     return false;
6066   }
6067 }
6068 
IsProcessorInLinkedList_Locked(Processor * processor) const6069 bool Simulator::GlobalMonitor::IsProcessorInLinkedList_Locked(
6070     Processor* processor) const {
6071   return head_ == processor || processor->next_ || processor->prev_;
6072 }
6073 
PrependProcessor_Locked(Processor * processor)6074 void Simulator::GlobalMonitor::PrependProcessor_Locked(Processor* processor) {
6075   if (IsProcessorInLinkedList_Locked(processor)) {
6076     return;
6077   }
6078 
6079   if (head_) {
6080     head_->prev_ = processor;
6081   }
6082   processor->prev_ = nullptr;
6083   processor->next_ = head_;
6084   head_ = processor;
6085 }
6086 
RemoveProcessor(Processor * processor)6087 void Simulator::GlobalMonitor::RemoveProcessor(Processor* processor) {
6088   base::MutexGuard lock_guard(&mutex);
6089   if (!IsProcessorInLinkedList_Locked(processor)) {
6090     return;
6091   }
6092 
6093   if (processor->prev_) {
6094     processor->prev_->next_ = processor->next_;
6095   } else {
6096     head_ = processor->next_;
6097   }
6098   if (processor->next_) {
6099     processor->next_->prev_ = processor->prev_;
6100   }
6101   processor->prev_ = nullptr;
6102   processor->next_ = nullptr;
6103 }
6104 
6105 #undef SScanF
6106 #undef COLOUR
6107 #undef COLOUR_BOLD
6108 #undef NORMAL
6109 #undef GREY
6110 #undef RED
6111 #undef GREEN
6112 #undef YELLOW
6113 #undef BLUE
6114 #undef MAGENTA
6115 #undef CYAN
6116 #undef WHITE
6117 #undef COMMAND_SIZE
6118 #undef ARG_SIZE
6119 #undef STR
6120 #undef XSTR
6121 
6122 }  // namespace internal
6123 }  // namespace v8
6124 
6125 #endif  // USE_SIMULATOR
6126