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