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