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