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 <stdlib.h>
6 #include <cmath>
7 #include <cstdarg>
8
9 #if V8_TARGET_ARCH_ARM64
10
11 #include "src/arm64/decoder-arm64-inl.h"
12 #include "src/arm64/simulator-arm64.h"
13 #include "src/assembler.h"
14 #include "src/codegen.h"
15 #include "src/disasm.h"
16 #include "src/macro-assembler.h"
17 #include "src/ostreams.h"
18
19 namespace v8 {
20 namespace internal {
21
22 #if defined(USE_SIMULATOR)
23
24
25 // This macro provides a platform independent use of sscanf. The reason for
26 // SScanF not being implemented in a platform independent way through
27 // ::v8::internal::OS in the same way as SNPrintF is that the
28 // Windows C Run-Time Library does not provide vsscanf.
29 #define SScanF sscanf // NOLINT
30
31
32 // Helpers for colors.
33 #define COLOUR(colour_code) "\033[0;" colour_code "m"
34 #define COLOUR_BOLD(colour_code) "\033[1;" colour_code "m"
35 #define NORMAL ""
36 #define GREY "30"
37 #define RED "31"
38 #define GREEN "32"
39 #define YELLOW "33"
40 #define BLUE "34"
41 #define MAGENTA "35"
42 #define CYAN "36"
43 #define WHITE "37"
44 typedef char const * const TEXT_COLOUR;
45 TEXT_COLOUR clr_normal = FLAG_log_colour ? COLOUR(NORMAL) : "";
46 TEXT_COLOUR clr_flag_name = FLAG_log_colour ? COLOUR_BOLD(WHITE) : "";
47 TEXT_COLOUR clr_flag_value = FLAG_log_colour ? COLOUR(NORMAL) : "";
48 TEXT_COLOUR clr_reg_name = FLAG_log_colour ? COLOUR_BOLD(CYAN) : "";
49 TEXT_COLOUR clr_reg_value = FLAG_log_colour ? COLOUR(CYAN) : "";
50 TEXT_COLOUR clr_fpreg_name = FLAG_log_colour ? COLOUR_BOLD(MAGENTA) : "";
51 TEXT_COLOUR clr_fpreg_value = FLAG_log_colour ? COLOUR(MAGENTA) : "";
52 TEXT_COLOUR clr_memory_address = FLAG_log_colour ? COLOUR_BOLD(BLUE) : "";
53 TEXT_COLOUR clr_debug_number = FLAG_log_colour ? COLOUR_BOLD(YELLOW) : "";
54 TEXT_COLOUR clr_debug_message = FLAG_log_colour ? COLOUR(YELLOW) : "";
55 TEXT_COLOUR clr_printf = FLAG_log_colour ? COLOUR(GREEN) : "";
56
57
58 // This is basically the same as PrintF, with a guard for FLAG_trace_sim.
TraceSim(const char * format,...)59 void Simulator::TraceSim(const char* format, ...) {
60 if (FLAG_trace_sim) {
61 va_list arguments;
62 va_start(arguments, format);
63 base::OS::VFPrint(stream_, format, arguments);
64 va_end(arguments);
65 }
66 }
67
68
69 const Instruction* Simulator::kEndOfSimAddress = NULL;
70
71
SetBits(int msb,int lsb,uint32_t bits)72 void SimSystemRegister::SetBits(int msb, int lsb, uint32_t bits) {
73 int width = msb - lsb + 1;
74 DCHECK(is_uintn(bits, width) || is_intn(bits, width));
75
76 bits <<= lsb;
77 uint32_t mask = ((1 << width) - 1) << lsb;
78 DCHECK((mask & write_ignore_mask_) == 0);
79
80 value_ = (value_ & ~mask) | (bits & mask);
81 }
82
83
DefaultValueFor(SystemRegister id)84 SimSystemRegister SimSystemRegister::DefaultValueFor(SystemRegister id) {
85 switch (id) {
86 case NZCV:
87 return SimSystemRegister(0x00000000, NZCVWriteIgnoreMask);
88 case FPCR:
89 return SimSystemRegister(0x00000000, FPCRWriteIgnoreMask);
90 default:
91 UNREACHABLE();
92 return SimSystemRegister();
93 }
94 }
95
96
Initialize(Isolate * isolate)97 void Simulator::Initialize(Isolate* isolate) {
98 if (isolate->simulator_initialized()) return;
99 isolate->set_simulator_initialized(true);
100 ExternalReference::set_redirector(isolate, &RedirectExternalReference);
101 }
102
103
104 // Get the active Simulator for the current thread.
current(Isolate * isolate)105 Simulator* Simulator::current(Isolate* isolate) {
106 Isolate::PerIsolateThreadData* isolate_data =
107 isolate->FindOrAllocatePerThreadDataForThisThread();
108 DCHECK(isolate_data != NULL);
109
110 Simulator* sim = isolate_data->simulator();
111 if (sim == NULL) {
112 if (FLAG_trace_sim || FLAG_log_instruction_stats || FLAG_debug_sim) {
113 sim = new Simulator(new Decoder<DispatchingDecoderVisitor>(), isolate);
114 } else {
115 sim = new Decoder<Simulator>();
116 sim->isolate_ = isolate;
117 }
118 isolate_data->set_simulator(sim);
119 }
120 return sim;
121 }
122
123
CallVoid(byte * entry,CallArgument * args)124 void Simulator::CallVoid(byte* entry, CallArgument* args) {
125 int index_x = 0;
126 int index_d = 0;
127
128 std::vector<int64_t> stack_args(0);
129 for (int i = 0; !args[i].IsEnd(); i++) {
130 CallArgument arg = args[i];
131 if (arg.IsX() && (index_x < 8)) {
132 set_xreg(index_x++, arg.bits());
133 } else if (arg.IsD() && (index_d < 8)) {
134 set_dreg_bits(index_d++, arg.bits());
135 } else {
136 DCHECK(arg.IsD() || arg.IsX());
137 stack_args.push_back(arg.bits());
138 }
139 }
140
141 // Process stack arguments, and make sure the stack is suitably aligned.
142 uintptr_t original_stack = sp();
143 uintptr_t entry_stack = original_stack -
144 stack_args.size() * sizeof(stack_args[0]);
145 if (base::OS::ActivationFrameAlignment() != 0) {
146 entry_stack &= -base::OS::ActivationFrameAlignment();
147 }
148 char * stack = reinterpret_cast<char*>(entry_stack);
149 std::vector<int64_t>::const_iterator it;
150 for (it = stack_args.begin(); it != stack_args.end(); it++) {
151 memcpy(stack, &(*it), sizeof(*it));
152 stack += sizeof(*it);
153 }
154
155 DCHECK(reinterpret_cast<uintptr_t>(stack) <= original_stack);
156 set_sp(entry_stack);
157
158 // Call the generated code.
159 set_pc(entry);
160 set_lr(kEndOfSimAddress);
161 CheckPCSComplianceAndRun();
162
163 set_sp(original_stack);
164 }
165
166
CallInt64(byte * entry,CallArgument * args)167 int64_t Simulator::CallInt64(byte* entry, CallArgument* args) {
168 CallVoid(entry, args);
169 return xreg(0);
170 }
171
172
CallDouble(byte * entry,CallArgument * args)173 double Simulator::CallDouble(byte* entry, CallArgument* args) {
174 CallVoid(entry, args);
175 return dreg(0);
176 }
177
178
CallJS(byte * entry,Object * new_target,Object * target,Object * revc,int64_t argc,Object *** argv)179 int64_t Simulator::CallJS(byte* entry,
180 Object* new_target,
181 Object* target,
182 Object* revc,
183 int64_t argc,
184 Object*** argv) {
185 CallArgument args[] = {
186 CallArgument(new_target),
187 CallArgument(target),
188 CallArgument(revc),
189 CallArgument(argc),
190 CallArgument(argv),
191 CallArgument::End()
192 };
193 return CallInt64(entry, args);
194 }
195
196
CallRegExp(byte * entry,String * input,int64_t start_offset,const byte * input_start,const byte * input_end,int * output,int64_t output_size,Address stack_base,int64_t direct_call,void * return_address,Isolate * isolate)197 int64_t Simulator::CallRegExp(byte* entry,
198 String* input,
199 int64_t start_offset,
200 const byte* input_start,
201 const byte* input_end,
202 int* output,
203 int64_t output_size,
204 Address stack_base,
205 int64_t direct_call,
206 void* return_address,
207 Isolate* isolate) {
208 CallArgument args[] = {
209 CallArgument(input),
210 CallArgument(start_offset),
211 CallArgument(input_start),
212 CallArgument(input_end),
213 CallArgument(output),
214 CallArgument(output_size),
215 CallArgument(stack_base),
216 CallArgument(direct_call),
217 CallArgument(return_address),
218 CallArgument(isolate),
219 CallArgument::End()
220 };
221 return CallInt64(entry, args);
222 }
223
224
CheckPCSComplianceAndRun()225 void Simulator::CheckPCSComplianceAndRun() {
226 // Adjust JS-based stack limit to C-based stack limit.
227 isolate_->stack_guard()->AdjustStackLimitForSimulator();
228
229 #ifdef DEBUG
230 CHECK_EQ(kNumberOfCalleeSavedRegisters, kCalleeSaved.Count());
231 CHECK_EQ(kNumberOfCalleeSavedFPRegisters, kCalleeSavedFP.Count());
232
233 int64_t saved_registers[kNumberOfCalleeSavedRegisters];
234 uint64_t saved_fpregisters[kNumberOfCalleeSavedFPRegisters];
235
236 CPURegList register_list = kCalleeSaved;
237 CPURegList fpregister_list = kCalleeSavedFP;
238
239 for (int i = 0; i < kNumberOfCalleeSavedRegisters; i++) {
240 // x31 is not a caller saved register, so no need to specify if we want
241 // the stack or zero.
242 saved_registers[i] = xreg(register_list.PopLowestIndex().code());
243 }
244 for (int i = 0; i < kNumberOfCalleeSavedFPRegisters; i++) {
245 saved_fpregisters[i] =
246 dreg_bits(fpregister_list.PopLowestIndex().code());
247 }
248 int64_t original_stack = sp();
249 #endif
250 // Start the simulation!
251 Run();
252 #ifdef DEBUG
253 CHECK_EQ(original_stack, sp());
254 // Check that callee-saved registers have been preserved.
255 register_list = kCalleeSaved;
256 fpregister_list = kCalleeSavedFP;
257 for (int i = 0; i < kNumberOfCalleeSavedRegisters; i++) {
258 CHECK_EQ(saved_registers[i], xreg(register_list.PopLowestIndex().code()));
259 }
260 for (int i = 0; i < kNumberOfCalleeSavedFPRegisters; i++) {
261 DCHECK(saved_fpregisters[i] ==
262 dreg_bits(fpregister_list.PopLowestIndex().code()));
263 }
264
265 // Corrupt caller saved register minus the return regiters.
266
267 // In theory x0 to x7 can be used for return values, but V8 only uses x0, x1
268 // for now .
269 register_list = kCallerSaved;
270 register_list.Remove(x0);
271 register_list.Remove(x1);
272
273 // In theory d0 to d7 can be used for return values, but V8 only uses d0
274 // for now .
275 fpregister_list = kCallerSavedFP;
276 fpregister_list.Remove(d0);
277
278 CorruptRegisters(®ister_list, kCallerSavedRegisterCorruptionValue);
279 CorruptRegisters(&fpregister_list, kCallerSavedFPRegisterCorruptionValue);
280 #endif
281 }
282
283
284 #ifdef DEBUG
285 // The least significant byte of the curruption value holds the corresponding
286 // register's code.
CorruptRegisters(CPURegList * list,uint64_t value)287 void Simulator::CorruptRegisters(CPURegList* list, uint64_t value) {
288 if (list->type() == CPURegister::kRegister) {
289 while (!list->IsEmpty()) {
290 unsigned code = list->PopLowestIndex().code();
291 set_xreg(code, value | code);
292 }
293 } else {
294 DCHECK(list->type() == CPURegister::kFPRegister);
295 while (!list->IsEmpty()) {
296 unsigned code = list->PopLowestIndex().code();
297 set_dreg_bits(code, value | code);
298 }
299 }
300 }
301
302
CorruptAllCallerSavedCPURegisters()303 void Simulator::CorruptAllCallerSavedCPURegisters() {
304 // Corrupt alters its parameter so copy them first.
305 CPURegList register_list = kCallerSaved;
306 CPURegList fpregister_list = kCallerSavedFP;
307
308 CorruptRegisters(®ister_list, kCallerSavedRegisterCorruptionValue);
309 CorruptRegisters(&fpregister_list, kCallerSavedFPRegisterCorruptionValue);
310 }
311 #endif
312
313
314 // Extending the stack by 2 * 64 bits is required for stack alignment purposes.
PushAddress(uintptr_t address)315 uintptr_t Simulator::PushAddress(uintptr_t address) {
316 DCHECK(sizeof(uintptr_t) < 2 * kXRegSize);
317 intptr_t new_sp = sp() - 2 * kXRegSize;
318 uintptr_t* alignment_slot =
319 reinterpret_cast<uintptr_t*>(new_sp + kXRegSize);
320 memcpy(alignment_slot, &kSlotsZapValue, kPointerSize);
321 uintptr_t* stack_slot = reinterpret_cast<uintptr_t*>(new_sp);
322 memcpy(stack_slot, &address, kPointerSize);
323 set_sp(new_sp);
324 return new_sp;
325 }
326
327
PopAddress()328 uintptr_t Simulator::PopAddress() {
329 intptr_t current_sp = sp();
330 uintptr_t* stack_slot = reinterpret_cast<uintptr_t*>(current_sp);
331 uintptr_t address = *stack_slot;
332 DCHECK(sizeof(uintptr_t) < 2 * kXRegSize);
333 set_sp(current_sp + 2 * kXRegSize);
334 return address;
335 }
336
337
338 // Returns the limit of the stack area to enable checking for stack overflows.
StackLimit(uintptr_t c_limit) const339 uintptr_t Simulator::StackLimit(uintptr_t c_limit) const {
340 // The simulator uses a separate JS stack. If we have exhausted the C stack,
341 // we also drop down the JS limit to reflect the exhaustion on the JS stack.
342 if (GetCurrentStackPosition() < c_limit) {
343 return reinterpret_cast<uintptr_t>(get_sp());
344 }
345
346 // Otherwise the limit is the JS stack. Leave a safety margin of 1024 bytes
347 // to prevent overrunning the stack when pushing values.
348 return stack_limit_ + 1024;
349 }
350
351
Simulator(Decoder<DispatchingDecoderVisitor> * decoder,Isolate * isolate,FILE * stream)352 Simulator::Simulator(Decoder<DispatchingDecoderVisitor>* decoder,
353 Isolate* isolate, FILE* stream)
354 : decoder_(decoder),
355 last_debugger_input_(NULL),
356 log_parameters_(NO_PARAM),
357 isolate_(isolate) {
358 // Setup the decoder.
359 decoder_->AppendVisitor(this);
360
361 Init(stream);
362
363 if (FLAG_trace_sim) {
364 decoder_->InsertVisitorBefore(print_disasm_, this);
365 log_parameters_ = LOG_ALL;
366 }
367
368 if (FLAG_log_instruction_stats) {
369 instrument_ = new Instrument(FLAG_log_instruction_file,
370 FLAG_log_instruction_period);
371 decoder_->AppendVisitor(instrument_);
372 }
373 }
374
375
Simulator()376 Simulator::Simulator()
377 : decoder_(NULL),
378 last_debugger_input_(NULL),
379 log_parameters_(NO_PARAM),
380 isolate_(NULL) {
381 Init(stdout);
382 CHECK(!FLAG_trace_sim && !FLAG_log_instruction_stats);
383 }
384
385
Init(FILE * stream)386 void Simulator::Init(FILE* stream) {
387 ResetState();
388
389 // Allocate and setup the simulator stack.
390 stack_size_ = (FLAG_sim_stack_size * KB) + (2 * stack_protection_size_);
391 stack_ = reinterpret_cast<uintptr_t>(new byte[stack_size_]);
392 stack_limit_ = stack_ + stack_protection_size_;
393 uintptr_t tos = stack_ + stack_size_ - stack_protection_size_;
394 // The stack pointer must be 16-byte aligned.
395 set_sp(tos & ~0xfUL);
396
397 stream_ = stream;
398 print_disasm_ = new PrintDisassembler(stream_);
399
400 // The debugger needs to disassemble code without the simulator executing an
401 // instruction, so we create a dedicated decoder.
402 disassembler_decoder_ = new Decoder<DispatchingDecoderVisitor>();
403 disassembler_decoder_->AppendVisitor(print_disasm_);
404 }
405
406
ResetState()407 void Simulator::ResetState() {
408 // Reset the system registers.
409 nzcv_ = SimSystemRegister::DefaultValueFor(NZCV);
410 fpcr_ = SimSystemRegister::DefaultValueFor(FPCR);
411
412 // Reset registers to 0.
413 pc_ = NULL;
414 for (unsigned i = 0; i < kNumberOfRegisters; i++) {
415 set_xreg(i, 0xbadbeef);
416 }
417 for (unsigned i = 0; i < kNumberOfFPRegisters; i++) {
418 // Set FP registers to a value that is NaN in both 32-bit and 64-bit FP.
419 set_dreg_bits(i, 0x7ff000007f800001UL);
420 }
421 // Returning to address 0 exits the Simulator.
422 set_lr(kEndOfSimAddress);
423
424 // Reset debug helpers.
425 breakpoints_.empty();
426 break_on_next_ = false;
427 }
428
429
~Simulator()430 Simulator::~Simulator() {
431 delete[] reinterpret_cast<byte*>(stack_);
432 if (FLAG_log_instruction_stats) {
433 delete instrument_;
434 }
435 delete disassembler_decoder_;
436 delete print_disasm_;
437 DeleteArray(last_debugger_input_);
438 delete decoder_;
439 }
440
441
Run()442 void Simulator::Run() {
443 pc_modified_ = false;
444 while (pc_ != kEndOfSimAddress) {
445 ExecuteInstruction();
446 }
447 }
448
449
RunFrom(Instruction * start)450 void Simulator::RunFrom(Instruction* start) {
451 set_pc(start);
452 Run();
453 }
454
455
456 // When the generated code calls an external reference we need to catch that in
457 // the simulator. The external reference will be a function compiled for the
458 // host architecture. We need to call that function instead of trying to
459 // execute it with the simulator. We do that by redirecting the external
460 // reference to a svc (Supervisor Call) instruction that is handled by
461 // the simulator. We write the original destination of the jump just at a known
462 // offset from the svc instruction so the simulator knows what to call.
463 class Redirection {
464 public:
Redirection(Isolate * isolate,void * external_function,ExternalReference::Type type)465 Redirection(Isolate* isolate, void* external_function,
466 ExternalReference::Type type)
467 : external_function_(external_function), type_(type), next_(NULL) {
468 redirect_call_.SetInstructionBits(
469 HLT | Assembler::ImmException(kImmExceptionIsRedirectedCall));
470 next_ = isolate->simulator_redirection();
471 // TODO(all): Simulator flush I cache
472 isolate->set_simulator_redirection(this);
473 }
474
address_of_redirect_call()475 void* address_of_redirect_call() {
476 return reinterpret_cast<void*>(&redirect_call_);
477 }
478
479 template <typename T>
external_function()480 T external_function() { return reinterpret_cast<T>(external_function_); }
481
type()482 ExternalReference::Type type() { return type_; }
483
Get(Isolate * isolate,void * external_function,ExternalReference::Type type)484 static Redirection* Get(Isolate* isolate, void* external_function,
485 ExternalReference::Type type) {
486 Redirection* current = isolate->simulator_redirection();
487 for (; current != NULL; current = current->next_) {
488 if (current->external_function_ == external_function) {
489 DCHECK_EQ(current->type(), type);
490 return current;
491 }
492 }
493 return new Redirection(isolate, external_function, type);
494 }
495
FromHltInstruction(Instruction * redirect_call)496 static Redirection* FromHltInstruction(Instruction* redirect_call) {
497 char* addr_of_hlt = reinterpret_cast<char*>(redirect_call);
498 char* addr_of_redirection =
499 addr_of_hlt - offsetof(Redirection, redirect_call_);
500 return reinterpret_cast<Redirection*>(addr_of_redirection);
501 }
502
ReverseRedirection(int64_t reg)503 static void* ReverseRedirection(int64_t reg) {
504 Redirection* redirection =
505 FromHltInstruction(reinterpret_cast<Instruction*>(reg));
506 return redirection->external_function<void*>();
507 }
508
DeleteChain(Redirection * redirection)509 static void DeleteChain(Redirection* redirection) {
510 while (redirection != nullptr) {
511 Redirection* next = redirection->next_;
512 delete redirection;
513 redirection = next;
514 }
515 }
516
517 private:
518 void* external_function_;
519 Instruction redirect_call_;
520 ExternalReference::Type type_;
521 Redirection* next_;
522 };
523
524
525 // static
TearDown(HashMap * i_cache,Redirection * first)526 void Simulator::TearDown(HashMap* i_cache, Redirection* first) {
527 Redirection::DeleteChain(first);
528 }
529
530
531 // Calls into the V8 runtime are based on this very simple interface.
532 // Note: To be able to return two values from some calls the code in runtime.cc
533 // uses the ObjectPair structure.
534 // The simulator assumes all runtime calls return two 64-bits values. If they
535 // don't, register x1 is clobbered. This is fine because x1 is caller-saved.
536 struct ObjectPair {
537 int64_t res0;
538 int64_t res1;
539 };
540
541
542 typedef ObjectPair (*SimulatorRuntimeCall)(int64_t arg0,
543 int64_t arg1,
544 int64_t arg2,
545 int64_t arg3,
546 int64_t arg4,
547 int64_t arg5,
548 int64_t arg6,
549 int64_t arg7);
550
551 typedef int64_t (*SimulatorRuntimeCompareCall)(double arg1, double arg2);
552 typedef double (*SimulatorRuntimeFPFPCall)(double arg1, double arg2);
553 typedef double (*SimulatorRuntimeFPCall)(double arg1);
554 typedef double (*SimulatorRuntimeFPIntCall)(double arg1, int32_t arg2);
555
556 // This signature supports direct call in to API function native callback
557 // (refer to InvocationCallback in v8.h).
558 typedef void (*SimulatorRuntimeDirectApiCall)(int64_t arg0);
559 typedef void (*SimulatorRuntimeProfilingApiCall)(int64_t arg0, void* arg1);
560
561 // This signature supports direct call to accessor getter callback.
562 typedef void (*SimulatorRuntimeDirectGetterCall)(int64_t arg0, int64_t arg1);
563 typedef void (*SimulatorRuntimeProfilingGetterCall)(int64_t arg0, int64_t arg1,
564 void* arg2);
565
DoRuntimeCall(Instruction * instr)566 void Simulator::DoRuntimeCall(Instruction* instr) {
567 Redirection* redirection = Redirection::FromHltInstruction(instr);
568
569 // The called C code might itself call simulated code, so any
570 // caller-saved registers (including lr) could still be clobbered by a
571 // redirected call.
572 Instruction* return_address = lr();
573
574 int64_t external = redirection->external_function<int64_t>();
575
576 TraceSim("Call to host function at %p\n",
577 redirection->external_function<void*>());
578
579 // SP must be 16-byte-aligned at the call interface.
580 bool stack_alignment_exception = ((sp() & 0xf) != 0);
581 if (stack_alignment_exception) {
582 TraceSim(" with unaligned stack 0x%016" PRIx64 ".\n", sp());
583 FATAL("ALIGNMENT EXCEPTION");
584 }
585
586 switch (redirection->type()) {
587 default:
588 TraceSim("Type: Unknown.\n");
589 UNREACHABLE();
590 break;
591
592 case ExternalReference::BUILTIN_CALL: {
593 // Object* f(v8::internal::Arguments).
594 TraceSim("Type: BUILTIN_CALL\n");
595 SimulatorRuntimeCall target =
596 reinterpret_cast<SimulatorRuntimeCall>(external);
597
598 // We don't know how many arguments are being passed, but we can
599 // pass 8 without touching the stack. They will be ignored by the
600 // host function if they aren't used.
601 TraceSim("Arguments: "
602 "0x%016" PRIx64 ", 0x%016" PRIx64 ", "
603 "0x%016" PRIx64 ", 0x%016" PRIx64 ", "
604 "0x%016" PRIx64 ", 0x%016" PRIx64 ", "
605 "0x%016" PRIx64 ", 0x%016" PRIx64,
606 xreg(0), xreg(1), xreg(2), xreg(3),
607 xreg(4), xreg(5), xreg(6), xreg(7));
608 ObjectPair result = target(xreg(0), xreg(1), xreg(2), xreg(3),
609 xreg(4), xreg(5), xreg(6), xreg(7));
610 TraceSim("Returned: {0x%" PRIx64 ", 0x%" PRIx64 "}\n",
611 result.res0, result.res1);
612 #ifdef DEBUG
613 CorruptAllCallerSavedCPURegisters();
614 #endif
615 set_xreg(0, result.res0);
616 set_xreg(1, result.res1);
617 break;
618 }
619
620 case ExternalReference::DIRECT_API_CALL: {
621 // void f(v8::FunctionCallbackInfo&)
622 TraceSim("Type: DIRECT_API_CALL\n");
623 SimulatorRuntimeDirectApiCall target =
624 reinterpret_cast<SimulatorRuntimeDirectApiCall>(external);
625 TraceSim("Arguments: 0x%016" PRIx64 "\n", xreg(0));
626 target(xreg(0));
627 TraceSim("No return value.");
628 #ifdef DEBUG
629 CorruptAllCallerSavedCPURegisters();
630 #endif
631 break;
632 }
633
634 case ExternalReference::BUILTIN_COMPARE_CALL: {
635 // int f(double, double)
636 TraceSim("Type: BUILTIN_COMPARE_CALL\n");
637 SimulatorRuntimeCompareCall target =
638 reinterpret_cast<SimulatorRuntimeCompareCall>(external);
639 TraceSim("Arguments: %f, %f\n", dreg(0), dreg(1));
640 int64_t result = target(dreg(0), dreg(1));
641 TraceSim("Returned: %" PRId64 "\n", result);
642 #ifdef DEBUG
643 CorruptAllCallerSavedCPURegisters();
644 #endif
645 set_xreg(0, result);
646 break;
647 }
648
649 case ExternalReference::BUILTIN_FP_CALL: {
650 // double f(double)
651 TraceSim("Type: BUILTIN_FP_CALL\n");
652 SimulatorRuntimeFPCall target =
653 reinterpret_cast<SimulatorRuntimeFPCall>(external);
654 TraceSim("Argument: %f\n", dreg(0));
655 double result = target(dreg(0));
656 TraceSim("Returned: %f\n", result);
657 #ifdef DEBUG
658 CorruptAllCallerSavedCPURegisters();
659 #endif
660 set_dreg(0, result);
661 break;
662 }
663
664 case ExternalReference::BUILTIN_FP_FP_CALL: {
665 // double f(double, double)
666 TraceSim("Type: BUILTIN_FP_FP_CALL\n");
667 SimulatorRuntimeFPFPCall target =
668 reinterpret_cast<SimulatorRuntimeFPFPCall>(external);
669 TraceSim("Arguments: %f, %f\n", dreg(0), dreg(1));
670 double result = target(dreg(0), dreg(1));
671 TraceSim("Returned: %f\n", result);
672 #ifdef DEBUG
673 CorruptAllCallerSavedCPURegisters();
674 #endif
675 set_dreg(0, result);
676 break;
677 }
678
679 case ExternalReference::BUILTIN_FP_INT_CALL: {
680 // double f(double, int)
681 TraceSim("Type: BUILTIN_FP_INT_CALL\n");
682 SimulatorRuntimeFPIntCall target =
683 reinterpret_cast<SimulatorRuntimeFPIntCall>(external);
684 TraceSim("Arguments: %f, %d\n", dreg(0), wreg(0));
685 double result = target(dreg(0), wreg(0));
686 TraceSim("Returned: %f\n", result);
687 #ifdef DEBUG
688 CorruptAllCallerSavedCPURegisters();
689 #endif
690 set_dreg(0, result);
691 break;
692 }
693
694 case ExternalReference::DIRECT_GETTER_CALL: {
695 // void f(Local<String> property, PropertyCallbackInfo& info)
696 TraceSim("Type: DIRECT_GETTER_CALL\n");
697 SimulatorRuntimeDirectGetterCall target =
698 reinterpret_cast<SimulatorRuntimeDirectGetterCall>(external);
699 TraceSim("Arguments: 0x%016" PRIx64 ", 0x%016" PRIx64 "\n",
700 xreg(0), xreg(1));
701 target(xreg(0), xreg(1));
702 TraceSim("No return value.");
703 #ifdef DEBUG
704 CorruptAllCallerSavedCPURegisters();
705 #endif
706 break;
707 }
708
709 case ExternalReference::PROFILING_API_CALL: {
710 // void f(v8::FunctionCallbackInfo&, v8::FunctionCallback)
711 TraceSim("Type: PROFILING_API_CALL\n");
712 SimulatorRuntimeProfilingApiCall target =
713 reinterpret_cast<SimulatorRuntimeProfilingApiCall>(external);
714 void* arg1 = Redirection::ReverseRedirection(xreg(1));
715 TraceSim("Arguments: 0x%016" PRIx64 ", %p\n", xreg(0), arg1);
716 target(xreg(0), arg1);
717 TraceSim("No return value.");
718 #ifdef DEBUG
719 CorruptAllCallerSavedCPURegisters();
720 #endif
721 break;
722 }
723
724 case ExternalReference::PROFILING_GETTER_CALL: {
725 // void f(Local<String> property, PropertyCallbackInfo& info,
726 // AccessorNameGetterCallback callback)
727 TraceSim("Type: PROFILING_GETTER_CALL\n");
728 SimulatorRuntimeProfilingGetterCall target =
729 reinterpret_cast<SimulatorRuntimeProfilingGetterCall>(
730 external);
731 void* arg2 = Redirection::ReverseRedirection(xreg(2));
732 TraceSim("Arguments: 0x%016" PRIx64 ", 0x%016" PRIx64 ", %p\n",
733 xreg(0), xreg(1), arg2);
734 target(xreg(0), xreg(1), arg2);
735 TraceSim("No return value.");
736 #ifdef DEBUG
737 CorruptAllCallerSavedCPURegisters();
738 #endif
739 break;
740 }
741 }
742
743 set_lr(return_address);
744 set_pc(return_address);
745 }
746
747
RedirectExternalReference(Isolate * isolate,void * external_function,ExternalReference::Type type)748 void* Simulator::RedirectExternalReference(Isolate* isolate,
749 void* external_function,
750 ExternalReference::Type type) {
751 Redirection* redirection = Redirection::Get(isolate, external_function, type);
752 return redirection->address_of_redirect_call();
753 }
754
755
756 const char* Simulator::xreg_names[] = {
757 "x0", "x1", "x2", "x3", "x4", "x5", "x6", "x7",
758 "x8", "x9", "x10", "x11", "x12", "x13", "x14", "x15",
759 "ip0", "ip1", "x18", "x19", "x20", "x21", "x22", "x23",
760 "x24", "x25", "x26", "cp", "jssp", "fp", "lr", "xzr", "csp"};
761
762 const char* Simulator::wreg_names[] = {
763 "w0", "w1", "w2", "w3", "w4", "w5", "w6", "w7",
764 "w8", "w9", "w10", "w11", "w12", "w13", "w14", "w15",
765 "w16", "w17", "w18", "w19", "w20", "w21", "w22", "w23",
766 "w24", "w25", "w26", "wcp", "wjssp", "wfp", "wlr", "wzr", "wcsp"};
767
768 const char* Simulator::sreg_names[] = {
769 "s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7",
770 "s8", "s9", "s10", "s11", "s12", "s13", "s14", "s15",
771 "s16", "s17", "s18", "s19", "s20", "s21", "s22", "s23",
772 "s24", "s25", "s26", "s27", "s28", "s29", "s30", "s31"};
773
774 const char* Simulator::dreg_names[] = {
775 "d0", "d1", "d2", "d3", "d4", "d5", "d6", "d7",
776 "d8", "d9", "d10", "d11", "d12", "d13", "d14", "d15",
777 "d16", "d17", "d18", "d19", "d20", "d21", "d22", "d23",
778 "d24", "d25", "d26", "d27", "d28", "d29", "d30", "d31"};
779
780 const char* Simulator::vreg_names[] = {
781 "v0", "v1", "v2", "v3", "v4", "v5", "v6", "v7",
782 "v8", "v9", "v10", "v11", "v12", "v13", "v14", "v15",
783 "v16", "v17", "v18", "v19", "v20", "v21", "v22", "v23",
784 "v24", "v25", "v26", "v27", "v28", "v29", "v30", "v31"};
785
786
WRegNameForCode(unsigned code,Reg31Mode mode)787 const char* Simulator::WRegNameForCode(unsigned code, Reg31Mode mode) {
788 STATIC_ASSERT(arraysize(Simulator::wreg_names) == (kNumberOfRegisters + 1));
789 DCHECK(code < kNumberOfRegisters);
790 // The modulo operator has no effect here, but it silences a broken GCC
791 // warning about out-of-bounds array accesses.
792 code %= kNumberOfRegisters;
793
794 // If the code represents the stack pointer, index the name after zr.
795 if ((code == kZeroRegCode) && (mode == Reg31IsStackPointer)) {
796 code = kZeroRegCode + 1;
797 }
798 return wreg_names[code];
799 }
800
801
XRegNameForCode(unsigned code,Reg31Mode mode)802 const char* Simulator::XRegNameForCode(unsigned code, Reg31Mode mode) {
803 STATIC_ASSERT(arraysize(Simulator::xreg_names) == (kNumberOfRegisters + 1));
804 DCHECK(code < kNumberOfRegisters);
805 code %= kNumberOfRegisters;
806
807 // If the code represents the stack pointer, index the name after zr.
808 if ((code == kZeroRegCode) && (mode == Reg31IsStackPointer)) {
809 code = kZeroRegCode + 1;
810 }
811 return xreg_names[code];
812 }
813
814
SRegNameForCode(unsigned code)815 const char* Simulator::SRegNameForCode(unsigned code) {
816 STATIC_ASSERT(arraysize(Simulator::sreg_names) == kNumberOfFPRegisters);
817 DCHECK(code < kNumberOfFPRegisters);
818 return sreg_names[code % kNumberOfFPRegisters];
819 }
820
821
DRegNameForCode(unsigned code)822 const char* Simulator::DRegNameForCode(unsigned code) {
823 STATIC_ASSERT(arraysize(Simulator::dreg_names) == kNumberOfFPRegisters);
824 DCHECK(code < kNumberOfFPRegisters);
825 return dreg_names[code % kNumberOfFPRegisters];
826 }
827
828
VRegNameForCode(unsigned code)829 const char* Simulator::VRegNameForCode(unsigned code) {
830 STATIC_ASSERT(arraysize(Simulator::vreg_names) == kNumberOfFPRegisters);
831 DCHECK(code < kNumberOfFPRegisters);
832 return vreg_names[code % kNumberOfFPRegisters];
833 }
834
835
CodeFromName(const char * name)836 int Simulator::CodeFromName(const char* name) {
837 for (unsigned i = 0; i < kNumberOfRegisters; i++) {
838 if ((strcmp(xreg_names[i], name) == 0) ||
839 (strcmp(wreg_names[i], name) == 0)) {
840 return i;
841 }
842 }
843 for (unsigned i = 0; i < kNumberOfFPRegisters; i++) {
844 if ((strcmp(vreg_names[i], name) == 0) ||
845 (strcmp(dreg_names[i], name) == 0) ||
846 (strcmp(sreg_names[i], name) == 0)) {
847 return i;
848 }
849 }
850 if ((strcmp("csp", name) == 0) || (strcmp("wcsp", name) == 0)) {
851 return kSPRegInternalCode;
852 }
853 return -1;
854 }
855
856
857 // Helpers ---------------------------------------------------------------------
858 template <typename T>
AddWithCarry(bool set_flags,T src1,T src2,T carry_in)859 T Simulator::AddWithCarry(bool set_flags,
860 T src1,
861 T src2,
862 T carry_in) {
863 typedef typename make_unsigned<T>::type unsignedT;
864 DCHECK((carry_in == 0) || (carry_in == 1));
865
866 T signed_sum = src1 + src2 + carry_in;
867 T result = signed_sum;
868
869 bool N, Z, C, V;
870
871 // Compute the C flag
872 unsignedT u1 = static_cast<unsignedT>(src1);
873 unsignedT u2 = static_cast<unsignedT>(src2);
874 unsignedT urest = std::numeric_limits<unsignedT>::max() - u1;
875 C = (u2 > urest) || (carry_in && (((u2 + 1) > urest) || (u2 > (urest - 1))));
876
877 // Overflow iff the sign bit is the same for the two inputs and different
878 // for the result.
879 V = ((src1 ^ src2) >= 0) && ((src1 ^ result) < 0);
880
881 N = CalcNFlag(result);
882 Z = CalcZFlag(result);
883
884 if (set_flags) {
885 nzcv().SetN(N);
886 nzcv().SetZ(Z);
887 nzcv().SetC(C);
888 nzcv().SetV(V);
889 LogSystemRegister(NZCV);
890 }
891 return result;
892 }
893
894
895 template<typename T>
AddSubWithCarry(Instruction * instr)896 void Simulator::AddSubWithCarry(Instruction* instr) {
897 T op2 = reg<T>(instr->Rm());
898 T new_val;
899
900 if ((instr->Mask(AddSubOpMask) == SUB) || instr->Mask(AddSubOpMask) == SUBS) {
901 op2 = ~op2;
902 }
903
904 new_val = AddWithCarry<T>(instr->FlagsUpdate(),
905 reg<T>(instr->Rn()),
906 op2,
907 nzcv().C());
908
909 set_reg<T>(instr->Rd(), new_val);
910 }
911
912 template <typename T>
ShiftOperand(T value,Shift shift_type,unsigned amount)913 T Simulator::ShiftOperand(T value, Shift shift_type, unsigned amount) {
914 typedef typename make_unsigned<T>::type unsignedT;
915
916 if (amount == 0) {
917 return value;
918 }
919
920 switch (shift_type) {
921 case LSL:
922 return value << amount;
923 case LSR:
924 return static_cast<unsignedT>(value) >> amount;
925 case ASR:
926 return value >> amount;
927 case ROR: {
928 unsignedT mask = (static_cast<unsignedT>(1) << amount) - 1;
929 return (static_cast<unsignedT>(value) >> amount) |
930 ((value & mask) << (sizeof(mask) * 8 - amount));
931 }
932 default:
933 UNIMPLEMENTED();
934 return 0;
935 }
936 }
937
938
939 template <typename T>
ExtendValue(T value,Extend extend_type,unsigned left_shift)940 T Simulator::ExtendValue(T value, Extend extend_type, unsigned left_shift) {
941 const unsigned kSignExtendBShift = (sizeof(T) - 1) * 8;
942 const unsigned kSignExtendHShift = (sizeof(T) - 2) * 8;
943 const unsigned kSignExtendWShift = (sizeof(T) - 4) * 8;
944
945 switch (extend_type) {
946 case UXTB:
947 value &= kByteMask;
948 break;
949 case UXTH:
950 value &= kHalfWordMask;
951 break;
952 case UXTW:
953 value &= kWordMask;
954 break;
955 case SXTB:
956 value = (value << kSignExtendBShift) >> kSignExtendBShift;
957 break;
958 case SXTH:
959 value = (value << kSignExtendHShift) >> kSignExtendHShift;
960 break;
961 case SXTW:
962 value = (value << kSignExtendWShift) >> kSignExtendWShift;
963 break;
964 case UXTX:
965 case SXTX:
966 break;
967 default:
968 UNREACHABLE();
969 }
970 return value << left_shift;
971 }
972
973
974 template <typename T>
Extract(Instruction * instr)975 void Simulator::Extract(Instruction* instr) {
976 unsigned lsb = instr->ImmS();
977 T op2 = reg<T>(instr->Rm());
978 T result = op2;
979
980 if (lsb) {
981 T op1 = reg<T>(instr->Rn());
982 result = op2 >> lsb | (op1 << ((sizeof(T) * 8) - lsb));
983 }
984 set_reg<T>(instr->Rd(), result);
985 }
986
987
FPDefaultNaN() const988 template<> double Simulator::FPDefaultNaN<double>() const {
989 return kFP64DefaultNaN;
990 }
991
992
FPDefaultNaN() const993 template<> float Simulator::FPDefaultNaN<float>() const {
994 return kFP32DefaultNaN;
995 }
996
997
FPCompare(double val0,double val1)998 void Simulator::FPCompare(double val0, double val1) {
999 AssertSupportedFPCR();
1000
1001 // TODO(jbramley): This assumes that the C++ implementation handles
1002 // comparisons in the way that we expect (as per AssertSupportedFPCR()).
1003 if ((std::isnan(val0) != 0) || (std::isnan(val1) != 0)) {
1004 nzcv().SetRawValue(FPUnorderedFlag);
1005 } else if (val0 < val1) {
1006 nzcv().SetRawValue(FPLessThanFlag);
1007 } else if (val0 > val1) {
1008 nzcv().SetRawValue(FPGreaterThanFlag);
1009 } else if (val0 == val1) {
1010 nzcv().SetRawValue(FPEqualFlag);
1011 } else {
1012 UNREACHABLE();
1013 }
1014 LogSystemRegister(NZCV);
1015 }
1016
1017
SetBreakpoint(Instruction * location)1018 void Simulator::SetBreakpoint(Instruction* location) {
1019 for (unsigned i = 0; i < breakpoints_.size(); i++) {
1020 if (breakpoints_.at(i).location == location) {
1021 PrintF(stream_,
1022 "Existing breakpoint at %p was %s\n",
1023 reinterpret_cast<void*>(location),
1024 breakpoints_.at(i).enabled ? "disabled" : "enabled");
1025 breakpoints_.at(i).enabled = !breakpoints_.at(i).enabled;
1026 return;
1027 }
1028 }
1029 Breakpoint new_breakpoint = {location, true};
1030 breakpoints_.push_back(new_breakpoint);
1031 PrintF(stream_,
1032 "Set a breakpoint at %p\n", reinterpret_cast<void*>(location));
1033 }
1034
1035
ListBreakpoints()1036 void Simulator::ListBreakpoints() {
1037 PrintF(stream_, "Breakpoints:\n");
1038 for (unsigned i = 0; i < breakpoints_.size(); i++) {
1039 PrintF(stream_, "%p : %s\n",
1040 reinterpret_cast<void*>(breakpoints_.at(i).location),
1041 breakpoints_.at(i).enabled ? "enabled" : "disabled");
1042 }
1043 }
1044
1045
CheckBreakpoints()1046 void Simulator::CheckBreakpoints() {
1047 bool hit_a_breakpoint = false;
1048 for (unsigned i = 0; i < breakpoints_.size(); i++) {
1049 if ((breakpoints_.at(i).location == pc_) &&
1050 breakpoints_.at(i).enabled) {
1051 hit_a_breakpoint = true;
1052 // Disable this breakpoint.
1053 breakpoints_.at(i).enabled = false;
1054 }
1055 }
1056 if (hit_a_breakpoint) {
1057 PrintF(stream_, "Hit and disabled a breakpoint at %p.\n",
1058 reinterpret_cast<void*>(pc_));
1059 Debug();
1060 }
1061 }
1062
1063
CheckBreakNext()1064 void Simulator::CheckBreakNext() {
1065 // If the current instruction is a BL, insert a breakpoint just after it.
1066 if (break_on_next_ && pc_->IsBranchAndLinkToRegister()) {
1067 SetBreakpoint(pc_->following());
1068 break_on_next_ = false;
1069 }
1070 }
1071
1072
PrintInstructionsAt(Instruction * start,uint64_t count)1073 void Simulator::PrintInstructionsAt(Instruction* start, uint64_t count) {
1074 Instruction* end = start->InstructionAtOffset(count * kInstructionSize);
1075 for (Instruction* pc = start; pc < end; pc = pc->following()) {
1076 disassembler_decoder_->Decode(pc);
1077 }
1078 }
1079
1080
PrintSystemRegisters()1081 void Simulator::PrintSystemRegisters() {
1082 PrintSystemRegister(NZCV);
1083 PrintSystemRegister(FPCR);
1084 }
1085
1086
PrintRegisters()1087 void Simulator::PrintRegisters() {
1088 for (unsigned i = 0; i < kNumberOfRegisters; i++) {
1089 PrintRegister(i);
1090 }
1091 }
1092
1093
PrintFPRegisters()1094 void Simulator::PrintFPRegisters() {
1095 for (unsigned i = 0; i < kNumberOfFPRegisters; i++) {
1096 PrintFPRegister(i);
1097 }
1098 }
1099
1100
PrintRegister(unsigned code,Reg31Mode r31mode)1101 void Simulator::PrintRegister(unsigned code, Reg31Mode r31mode) {
1102 // Don't print writes into xzr.
1103 if ((code == kZeroRegCode) && (r31mode == Reg31IsZeroRegister)) {
1104 return;
1105 }
1106
1107 // The template is "# x<code>:value".
1108 fprintf(stream_, "# %s%5s: %s0x%016" PRIx64 "%s\n",
1109 clr_reg_name, XRegNameForCode(code, r31mode),
1110 clr_reg_value, reg<uint64_t>(code, r31mode), clr_normal);
1111 }
1112
1113
PrintFPRegister(unsigned code,PrintFPRegisterSizes sizes)1114 void Simulator::PrintFPRegister(unsigned code, PrintFPRegisterSizes sizes) {
1115 // The template is "# v<code>:bits (d<code>:value, ...)".
1116
1117 DCHECK(sizes != 0);
1118 DCHECK((sizes & kPrintAllFPRegValues) == sizes);
1119
1120 // Print the raw bits.
1121 fprintf(stream_, "# %s%5s: %s0x%016" PRIx64 "%s (",
1122 clr_fpreg_name, VRegNameForCode(code),
1123 clr_fpreg_value, fpreg<uint64_t>(code), clr_normal);
1124
1125 // Print all requested value interpretations.
1126 bool need_separator = false;
1127 if (sizes & kPrintDRegValue) {
1128 fprintf(stream_, "%s%s%s: %s%g%s",
1129 need_separator ? ", " : "",
1130 clr_fpreg_name, DRegNameForCode(code),
1131 clr_fpreg_value, fpreg<double>(code), clr_normal);
1132 need_separator = true;
1133 }
1134
1135 if (sizes & kPrintSRegValue) {
1136 fprintf(stream_, "%s%s%s: %s%g%s",
1137 need_separator ? ", " : "",
1138 clr_fpreg_name, SRegNameForCode(code),
1139 clr_fpreg_value, fpreg<float>(code), clr_normal);
1140 need_separator = true;
1141 }
1142
1143 // End the value list.
1144 fprintf(stream_, ")\n");
1145 }
1146
1147
PrintSystemRegister(SystemRegister id)1148 void Simulator::PrintSystemRegister(SystemRegister id) {
1149 switch (id) {
1150 case NZCV:
1151 fprintf(stream_, "# %sNZCV: %sN:%d Z:%d C:%d V:%d%s\n",
1152 clr_flag_name, clr_flag_value,
1153 nzcv().N(), nzcv().Z(), nzcv().C(), nzcv().V(),
1154 clr_normal);
1155 break;
1156 case FPCR: {
1157 static const char * rmode[] = {
1158 "0b00 (Round to Nearest)",
1159 "0b01 (Round towards Plus Infinity)",
1160 "0b10 (Round towards Minus Infinity)",
1161 "0b11 (Round towards Zero)"
1162 };
1163 DCHECK(fpcr().RMode() < arraysize(rmode));
1164 fprintf(stream_,
1165 "# %sFPCR: %sAHP:%d DN:%d FZ:%d RMode:%s%s\n",
1166 clr_flag_name, clr_flag_value,
1167 fpcr().AHP(), fpcr().DN(), fpcr().FZ(), rmode[fpcr().RMode()],
1168 clr_normal);
1169 break;
1170 }
1171 default:
1172 UNREACHABLE();
1173 }
1174 }
1175
1176
PrintRead(uintptr_t address,size_t size,unsigned reg_code)1177 void Simulator::PrintRead(uintptr_t address,
1178 size_t size,
1179 unsigned reg_code) {
1180 USE(size); // Size is unused here.
1181
1182 // The template is "# x<code>:value <- address".
1183 fprintf(stream_, "# %s%5s: %s0x%016" PRIx64 "%s",
1184 clr_reg_name, XRegNameForCode(reg_code),
1185 clr_reg_value, reg<uint64_t>(reg_code), clr_normal);
1186
1187 fprintf(stream_, " <- %s0x%016" PRIxPTR "%s\n",
1188 clr_memory_address, address, clr_normal);
1189 }
1190
1191
PrintReadFP(uintptr_t address,size_t size,unsigned reg_code)1192 void Simulator::PrintReadFP(uintptr_t address,
1193 size_t size,
1194 unsigned reg_code) {
1195 // The template is "# reg:bits (reg:value) <- address".
1196 switch (size) {
1197 case kSRegSize:
1198 fprintf(stream_, "# %s%5s: %s0x%016" PRIx64 "%s (%s%s: %s%gf%s)",
1199 clr_fpreg_name, VRegNameForCode(reg_code),
1200 clr_fpreg_value, fpreg<uint64_t>(reg_code), clr_normal,
1201 clr_fpreg_name, SRegNameForCode(reg_code),
1202 clr_fpreg_value, fpreg<float>(reg_code), clr_normal);
1203 break;
1204 case kDRegSize:
1205 fprintf(stream_, "# %s%5s: %s0x%016" PRIx64 "%s (%s%s: %s%g%s)",
1206 clr_fpreg_name, VRegNameForCode(reg_code),
1207 clr_fpreg_value, fpreg<uint64_t>(reg_code), clr_normal,
1208 clr_fpreg_name, DRegNameForCode(reg_code),
1209 clr_fpreg_value, fpreg<double>(reg_code), clr_normal);
1210 break;
1211 default:
1212 UNREACHABLE();
1213 }
1214
1215 fprintf(stream_, " <- %s0x%016" PRIxPTR "%s\n",
1216 clr_memory_address, address, clr_normal);
1217 }
1218
1219
PrintWrite(uintptr_t address,size_t size,unsigned reg_code)1220 void Simulator::PrintWrite(uintptr_t address,
1221 size_t size,
1222 unsigned reg_code) {
1223 // The template is "# reg:value -> address". To keep the trace tidy and
1224 // readable, the value is aligned with the values in the register trace.
1225 switch (size) {
1226 case kByteSizeInBytes:
1227 fprintf(stream_, "# %s%5s<7:0>: %s0x%02" PRIx8 "%s",
1228 clr_reg_name, WRegNameForCode(reg_code),
1229 clr_reg_value, reg<uint8_t>(reg_code), clr_normal);
1230 break;
1231 case kHalfWordSizeInBytes:
1232 fprintf(stream_, "# %s%5s<15:0>: %s0x%04" PRIx16 "%s",
1233 clr_reg_name, WRegNameForCode(reg_code),
1234 clr_reg_value, reg<uint16_t>(reg_code), clr_normal);
1235 break;
1236 case kWRegSize:
1237 fprintf(stream_, "# %s%5s: %s0x%08" PRIx32 "%s",
1238 clr_reg_name, WRegNameForCode(reg_code),
1239 clr_reg_value, reg<uint32_t>(reg_code), clr_normal);
1240 break;
1241 case kXRegSize:
1242 fprintf(stream_, "# %s%5s: %s0x%016" PRIx64 "%s",
1243 clr_reg_name, XRegNameForCode(reg_code),
1244 clr_reg_value, reg<uint64_t>(reg_code), clr_normal);
1245 break;
1246 default:
1247 UNREACHABLE();
1248 }
1249
1250 fprintf(stream_, " -> %s0x%016" PRIxPTR "%s\n",
1251 clr_memory_address, address, clr_normal);
1252 }
1253
1254
PrintWriteFP(uintptr_t address,size_t size,unsigned reg_code)1255 void Simulator::PrintWriteFP(uintptr_t address,
1256 size_t size,
1257 unsigned reg_code) {
1258 // The template is "# reg:bits (reg:value) -> address". To keep the trace tidy
1259 // and readable, the value is aligned with the values in the register trace.
1260 switch (size) {
1261 case kSRegSize:
1262 fprintf(stream_, "# %s%5s<31:0>: %s0x%08" PRIx32 "%s (%s%s: %s%gf%s)",
1263 clr_fpreg_name, VRegNameForCode(reg_code),
1264 clr_fpreg_value, fpreg<uint32_t>(reg_code), clr_normal,
1265 clr_fpreg_name, SRegNameForCode(reg_code),
1266 clr_fpreg_value, fpreg<float>(reg_code), clr_normal);
1267 break;
1268 case kDRegSize:
1269 fprintf(stream_, "# %s%5s: %s0x%016" PRIx64 "%s (%s%s: %s%g%s)",
1270 clr_fpreg_name, VRegNameForCode(reg_code),
1271 clr_fpreg_value, fpreg<uint64_t>(reg_code), clr_normal,
1272 clr_fpreg_name, DRegNameForCode(reg_code),
1273 clr_fpreg_value, fpreg<double>(reg_code), clr_normal);
1274 break;
1275 default:
1276 UNREACHABLE();
1277 }
1278
1279 fprintf(stream_, " -> %s0x%016" PRIxPTR "%s\n",
1280 clr_memory_address, address, clr_normal);
1281 }
1282
1283
1284 // Visitors---------------------------------------------------------------------
1285
VisitUnimplemented(Instruction * instr)1286 void Simulator::VisitUnimplemented(Instruction* instr) {
1287 fprintf(stream_, "Unimplemented instruction at %p: 0x%08" PRIx32 "\n",
1288 reinterpret_cast<void*>(instr), instr->InstructionBits());
1289 UNIMPLEMENTED();
1290 }
1291
1292
VisitUnallocated(Instruction * instr)1293 void Simulator::VisitUnallocated(Instruction* instr) {
1294 fprintf(stream_, "Unallocated instruction at %p: 0x%08" PRIx32 "\n",
1295 reinterpret_cast<void*>(instr), instr->InstructionBits());
1296 UNIMPLEMENTED();
1297 }
1298
1299
VisitPCRelAddressing(Instruction * instr)1300 void Simulator::VisitPCRelAddressing(Instruction* instr) {
1301 switch (instr->Mask(PCRelAddressingMask)) {
1302 case ADR:
1303 set_reg(instr->Rd(), instr->ImmPCOffsetTarget());
1304 break;
1305 case ADRP: // Not implemented in the assembler.
1306 UNIMPLEMENTED();
1307 break;
1308 default:
1309 UNREACHABLE();
1310 break;
1311 }
1312 }
1313
1314
VisitUnconditionalBranch(Instruction * instr)1315 void Simulator::VisitUnconditionalBranch(Instruction* instr) {
1316 switch (instr->Mask(UnconditionalBranchMask)) {
1317 case BL:
1318 set_lr(instr->following());
1319 // Fall through.
1320 case B:
1321 set_pc(instr->ImmPCOffsetTarget());
1322 break;
1323 default:
1324 UNREACHABLE();
1325 }
1326 }
1327
1328
VisitConditionalBranch(Instruction * instr)1329 void Simulator::VisitConditionalBranch(Instruction* instr) {
1330 DCHECK(instr->Mask(ConditionalBranchMask) == B_cond);
1331 if (ConditionPassed(static_cast<Condition>(instr->ConditionBranch()))) {
1332 set_pc(instr->ImmPCOffsetTarget());
1333 }
1334 }
1335
1336
VisitUnconditionalBranchToRegister(Instruction * instr)1337 void Simulator::VisitUnconditionalBranchToRegister(Instruction* instr) {
1338 Instruction* target = reg<Instruction*>(instr->Rn());
1339 switch (instr->Mask(UnconditionalBranchToRegisterMask)) {
1340 case BLR: {
1341 set_lr(instr->following());
1342 if (instr->Rn() == 31) {
1343 // BLR XZR is used as a guard for the constant pool. We should never hit
1344 // this, but if we do trap to allow debugging.
1345 Debug();
1346 }
1347 // Fall through.
1348 }
1349 case BR:
1350 case RET: set_pc(target); break;
1351 default: UNIMPLEMENTED();
1352 }
1353 }
1354
1355
VisitTestBranch(Instruction * instr)1356 void Simulator::VisitTestBranch(Instruction* instr) {
1357 unsigned bit_pos = (instr->ImmTestBranchBit5() << 5) |
1358 instr->ImmTestBranchBit40();
1359 bool take_branch = ((xreg(instr->Rt()) & (1UL << bit_pos)) == 0);
1360 switch (instr->Mask(TestBranchMask)) {
1361 case TBZ: break;
1362 case TBNZ: take_branch = !take_branch; break;
1363 default: UNIMPLEMENTED();
1364 }
1365 if (take_branch) {
1366 set_pc(instr->ImmPCOffsetTarget());
1367 }
1368 }
1369
1370
VisitCompareBranch(Instruction * instr)1371 void Simulator::VisitCompareBranch(Instruction* instr) {
1372 unsigned rt = instr->Rt();
1373 bool take_branch = false;
1374 switch (instr->Mask(CompareBranchMask)) {
1375 case CBZ_w: take_branch = (wreg(rt) == 0); break;
1376 case CBZ_x: take_branch = (xreg(rt) == 0); break;
1377 case CBNZ_w: take_branch = (wreg(rt) != 0); break;
1378 case CBNZ_x: take_branch = (xreg(rt) != 0); break;
1379 default: UNIMPLEMENTED();
1380 }
1381 if (take_branch) {
1382 set_pc(instr->ImmPCOffsetTarget());
1383 }
1384 }
1385
1386
1387 template<typename T>
AddSubHelper(Instruction * instr,T op2)1388 void Simulator::AddSubHelper(Instruction* instr, T op2) {
1389 bool set_flags = instr->FlagsUpdate();
1390 T new_val = 0;
1391 Instr operation = instr->Mask(AddSubOpMask);
1392
1393 switch (operation) {
1394 case ADD:
1395 case ADDS: {
1396 new_val = AddWithCarry<T>(set_flags,
1397 reg<T>(instr->Rn(), instr->RnMode()),
1398 op2);
1399 break;
1400 }
1401 case SUB:
1402 case SUBS: {
1403 new_val = AddWithCarry<T>(set_flags,
1404 reg<T>(instr->Rn(), instr->RnMode()),
1405 ~op2,
1406 1);
1407 break;
1408 }
1409 default: UNREACHABLE();
1410 }
1411
1412 set_reg<T>(instr->Rd(), new_val, instr->RdMode());
1413 }
1414
1415
VisitAddSubShifted(Instruction * instr)1416 void Simulator::VisitAddSubShifted(Instruction* instr) {
1417 Shift shift_type = static_cast<Shift>(instr->ShiftDP());
1418 unsigned shift_amount = instr->ImmDPShift();
1419
1420 if (instr->SixtyFourBits()) {
1421 int64_t op2 = ShiftOperand(xreg(instr->Rm()), shift_type, shift_amount);
1422 AddSubHelper(instr, op2);
1423 } else {
1424 int32_t op2 = static_cast<int32_t>(
1425 ShiftOperand(wreg(instr->Rm()), shift_type, shift_amount));
1426 AddSubHelper(instr, op2);
1427 }
1428 }
1429
1430
VisitAddSubImmediate(Instruction * instr)1431 void Simulator::VisitAddSubImmediate(Instruction* instr) {
1432 int64_t op2 = instr->ImmAddSub() << ((instr->ShiftAddSub() == 1) ? 12 : 0);
1433 if (instr->SixtyFourBits()) {
1434 AddSubHelper<int64_t>(instr, op2);
1435 } else {
1436 AddSubHelper<int32_t>(instr, static_cast<int32_t>(op2));
1437 }
1438 }
1439
1440
VisitAddSubExtended(Instruction * instr)1441 void Simulator::VisitAddSubExtended(Instruction* instr) {
1442 Extend ext = static_cast<Extend>(instr->ExtendMode());
1443 unsigned left_shift = instr->ImmExtendShift();
1444 if (instr->SixtyFourBits()) {
1445 int64_t op2 = ExtendValue(xreg(instr->Rm()), ext, left_shift);
1446 AddSubHelper(instr, op2);
1447 } else {
1448 int32_t op2 = ExtendValue(wreg(instr->Rm()), ext, left_shift);
1449 AddSubHelper(instr, op2);
1450 }
1451 }
1452
1453
VisitAddSubWithCarry(Instruction * instr)1454 void Simulator::VisitAddSubWithCarry(Instruction* instr) {
1455 if (instr->SixtyFourBits()) {
1456 AddSubWithCarry<int64_t>(instr);
1457 } else {
1458 AddSubWithCarry<int32_t>(instr);
1459 }
1460 }
1461
1462
VisitLogicalShifted(Instruction * instr)1463 void Simulator::VisitLogicalShifted(Instruction* instr) {
1464 Shift shift_type = static_cast<Shift>(instr->ShiftDP());
1465 unsigned shift_amount = instr->ImmDPShift();
1466
1467 if (instr->SixtyFourBits()) {
1468 int64_t op2 = ShiftOperand(xreg(instr->Rm()), shift_type, shift_amount);
1469 op2 = (instr->Mask(NOT) == NOT) ? ~op2 : op2;
1470 LogicalHelper<int64_t>(instr, op2);
1471 } else {
1472 int32_t op2 = ShiftOperand(wreg(instr->Rm()), shift_type, shift_amount);
1473 op2 = (instr->Mask(NOT) == NOT) ? ~op2 : op2;
1474 LogicalHelper<int32_t>(instr, op2);
1475 }
1476 }
1477
1478
VisitLogicalImmediate(Instruction * instr)1479 void Simulator::VisitLogicalImmediate(Instruction* instr) {
1480 if (instr->SixtyFourBits()) {
1481 LogicalHelper<int64_t>(instr, instr->ImmLogical());
1482 } else {
1483 LogicalHelper<int32_t>(instr, static_cast<int32_t>(instr->ImmLogical()));
1484 }
1485 }
1486
1487
1488 template<typename T>
LogicalHelper(Instruction * instr,T op2)1489 void Simulator::LogicalHelper(Instruction* instr, T op2) {
1490 T op1 = reg<T>(instr->Rn());
1491 T result = 0;
1492 bool update_flags = false;
1493
1494 // Switch on the logical operation, stripping out the NOT bit, as it has a
1495 // different meaning for logical immediate instructions.
1496 switch (instr->Mask(LogicalOpMask & ~NOT)) {
1497 case ANDS: update_flags = true; // Fall through.
1498 case AND: result = op1 & op2; break;
1499 case ORR: result = op1 | op2; break;
1500 case EOR: result = op1 ^ op2; break;
1501 default:
1502 UNIMPLEMENTED();
1503 }
1504
1505 if (update_flags) {
1506 nzcv().SetN(CalcNFlag(result));
1507 nzcv().SetZ(CalcZFlag(result));
1508 nzcv().SetC(0);
1509 nzcv().SetV(0);
1510 LogSystemRegister(NZCV);
1511 }
1512
1513 set_reg<T>(instr->Rd(), result, instr->RdMode());
1514 }
1515
1516
VisitConditionalCompareRegister(Instruction * instr)1517 void Simulator::VisitConditionalCompareRegister(Instruction* instr) {
1518 if (instr->SixtyFourBits()) {
1519 ConditionalCompareHelper(instr, xreg(instr->Rm()));
1520 } else {
1521 ConditionalCompareHelper(instr, wreg(instr->Rm()));
1522 }
1523 }
1524
1525
VisitConditionalCompareImmediate(Instruction * instr)1526 void Simulator::VisitConditionalCompareImmediate(Instruction* instr) {
1527 if (instr->SixtyFourBits()) {
1528 ConditionalCompareHelper<int64_t>(instr, instr->ImmCondCmp());
1529 } else {
1530 ConditionalCompareHelper<int32_t>(instr, instr->ImmCondCmp());
1531 }
1532 }
1533
1534
1535 template<typename T>
ConditionalCompareHelper(Instruction * instr,T op2)1536 void Simulator::ConditionalCompareHelper(Instruction* instr, T op2) {
1537 T op1 = reg<T>(instr->Rn());
1538
1539 if (ConditionPassed(static_cast<Condition>(instr->Condition()))) {
1540 // If the condition passes, set the status flags to the result of comparing
1541 // the operands.
1542 if (instr->Mask(ConditionalCompareMask) == CCMP) {
1543 AddWithCarry<T>(true, op1, ~op2, 1);
1544 } else {
1545 DCHECK(instr->Mask(ConditionalCompareMask) == CCMN);
1546 AddWithCarry<T>(true, op1, op2, 0);
1547 }
1548 } else {
1549 // If the condition fails, set the status flags to the nzcv immediate.
1550 nzcv().SetFlags(instr->Nzcv());
1551 LogSystemRegister(NZCV);
1552 }
1553 }
1554
1555
VisitLoadStoreUnsignedOffset(Instruction * instr)1556 void Simulator::VisitLoadStoreUnsignedOffset(Instruction* instr) {
1557 int offset = instr->ImmLSUnsigned() << instr->SizeLS();
1558 LoadStoreHelper(instr, offset, Offset);
1559 }
1560
1561
VisitLoadStoreUnscaledOffset(Instruction * instr)1562 void Simulator::VisitLoadStoreUnscaledOffset(Instruction* instr) {
1563 LoadStoreHelper(instr, instr->ImmLS(), Offset);
1564 }
1565
1566
VisitLoadStorePreIndex(Instruction * instr)1567 void Simulator::VisitLoadStorePreIndex(Instruction* instr) {
1568 LoadStoreHelper(instr, instr->ImmLS(), PreIndex);
1569 }
1570
1571
VisitLoadStorePostIndex(Instruction * instr)1572 void Simulator::VisitLoadStorePostIndex(Instruction* instr) {
1573 LoadStoreHelper(instr, instr->ImmLS(), PostIndex);
1574 }
1575
1576
VisitLoadStoreRegisterOffset(Instruction * instr)1577 void Simulator::VisitLoadStoreRegisterOffset(Instruction* instr) {
1578 Extend ext = static_cast<Extend>(instr->ExtendMode());
1579 DCHECK((ext == UXTW) || (ext == UXTX) || (ext == SXTW) || (ext == SXTX));
1580 unsigned shift_amount = instr->ImmShiftLS() * instr->SizeLS();
1581
1582 int64_t offset = ExtendValue(xreg(instr->Rm()), ext, shift_amount);
1583 LoadStoreHelper(instr, offset, Offset);
1584 }
1585
1586
LoadStoreHelper(Instruction * instr,int64_t offset,AddrMode addrmode)1587 void Simulator::LoadStoreHelper(Instruction* instr,
1588 int64_t offset,
1589 AddrMode addrmode) {
1590 unsigned srcdst = instr->Rt();
1591 unsigned addr_reg = instr->Rn();
1592 uintptr_t address = LoadStoreAddress(addr_reg, offset, addrmode);
1593 uintptr_t stack = 0;
1594
1595 // Handle the writeback for stores before the store. On a CPU the writeback
1596 // and the store are atomic, but when running on the simulator it is possible
1597 // to be interrupted in between. The simulator is not thread safe and V8 does
1598 // not require it to be to run JavaScript therefore the profiler may sample
1599 // the "simulated" CPU in the middle of load/store with writeback. The code
1600 // below ensures that push operations are safe even when interrupted: the
1601 // stack pointer will be decremented before adding an element to the stack.
1602 if (instr->IsStore()) {
1603 LoadStoreWriteBack(addr_reg, offset, addrmode);
1604
1605 // For store the address post writeback is used to check access below the
1606 // stack.
1607 stack = sp();
1608 }
1609
1610 LoadStoreOp op = static_cast<LoadStoreOp>(instr->Mask(LoadStoreOpMask));
1611 switch (op) {
1612 // Use _no_log variants to suppress the register trace (LOG_REGS,
1613 // LOG_FP_REGS). We will print a more detailed log.
1614 case LDRB_w: set_wreg_no_log(srcdst, MemoryRead<uint8_t>(address)); break;
1615 case LDRH_w: set_wreg_no_log(srcdst, MemoryRead<uint16_t>(address)); break;
1616 case LDR_w: set_wreg_no_log(srcdst, MemoryRead<uint32_t>(address)); break;
1617 case LDR_x: set_xreg_no_log(srcdst, MemoryRead<uint64_t>(address)); break;
1618 case LDRSB_w: set_wreg_no_log(srcdst, MemoryRead<int8_t>(address)); break;
1619 case LDRSH_w: set_wreg_no_log(srcdst, MemoryRead<int16_t>(address)); break;
1620 case LDRSB_x: set_xreg_no_log(srcdst, MemoryRead<int8_t>(address)); break;
1621 case LDRSH_x: set_xreg_no_log(srcdst, MemoryRead<int16_t>(address)); break;
1622 case LDRSW_x: set_xreg_no_log(srcdst, MemoryRead<int32_t>(address)); break;
1623 case LDR_s: set_sreg_no_log(srcdst, MemoryRead<float>(address)); break;
1624 case LDR_d: set_dreg_no_log(srcdst, MemoryRead<double>(address)); break;
1625
1626 case STRB_w: MemoryWrite<uint8_t>(address, wreg(srcdst)); break;
1627 case STRH_w: MemoryWrite<uint16_t>(address, wreg(srcdst)); break;
1628 case STR_w: MemoryWrite<uint32_t>(address, wreg(srcdst)); break;
1629 case STR_x: MemoryWrite<uint64_t>(address, xreg(srcdst)); break;
1630 case STR_s: MemoryWrite<float>(address, sreg(srcdst)); break;
1631 case STR_d: MemoryWrite<double>(address, dreg(srcdst)); break;
1632
1633 default: UNIMPLEMENTED();
1634 }
1635
1636 // Print a detailed trace (including the memory address) instead of the basic
1637 // register:value trace generated by set_*reg().
1638 size_t access_size = 1 << instr->SizeLS();
1639 if (instr->IsLoad()) {
1640 if ((op == LDR_s) || (op == LDR_d)) {
1641 LogReadFP(address, access_size, srcdst);
1642 } else {
1643 LogRead(address, access_size, srcdst);
1644 }
1645 } else {
1646 if ((op == STR_s) || (op == STR_d)) {
1647 LogWriteFP(address, access_size, srcdst);
1648 } else {
1649 LogWrite(address, access_size, srcdst);
1650 }
1651 }
1652
1653 // Handle the writeback for loads after the load to ensure safe pop
1654 // operation even when interrupted in the middle of it. The stack pointer
1655 // is only updated after the load so pop(fp) will never break the invariant
1656 // sp <= fp expected while walking the stack in the sampler.
1657 if (instr->IsLoad()) {
1658 // For loads the address pre writeback is used to check access below the
1659 // stack.
1660 stack = sp();
1661
1662 LoadStoreWriteBack(addr_reg, offset, addrmode);
1663 }
1664
1665 // Accesses below the stack pointer (but above the platform stack limit) are
1666 // not allowed in the ABI.
1667 CheckMemoryAccess(address, stack);
1668 }
1669
1670
VisitLoadStorePairOffset(Instruction * instr)1671 void Simulator::VisitLoadStorePairOffset(Instruction* instr) {
1672 LoadStorePairHelper(instr, Offset);
1673 }
1674
1675
VisitLoadStorePairPreIndex(Instruction * instr)1676 void Simulator::VisitLoadStorePairPreIndex(Instruction* instr) {
1677 LoadStorePairHelper(instr, PreIndex);
1678 }
1679
1680
VisitLoadStorePairPostIndex(Instruction * instr)1681 void Simulator::VisitLoadStorePairPostIndex(Instruction* instr) {
1682 LoadStorePairHelper(instr, PostIndex);
1683 }
1684
1685
LoadStorePairHelper(Instruction * instr,AddrMode addrmode)1686 void Simulator::LoadStorePairHelper(Instruction* instr,
1687 AddrMode addrmode) {
1688 unsigned rt = instr->Rt();
1689 unsigned rt2 = instr->Rt2();
1690 unsigned addr_reg = instr->Rn();
1691 size_t access_size = 1 << instr->SizeLSPair();
1692 int64_t offset = instr->ImmLSPair() * access_size;
1693 uintptr_t address = LoadStoreAddress(addr_reg, offset, addrmode);
1694 uintptr_t address2 = address + access_size;
1695 uintptr_t stack = 0;
1696
1697 // Handle the writeback for stores before the store. On a CPU the writeback
1698 // and the store are atomic, but when running on the simulator it is possible
1699 // to be interrupted in between. The simulator is not thread safe and V8 does
1700 // not require it to be to run JavaScript therefore the profiler may sample
1701 // the "simulated" CPU in the middle of load/store with writeback. The code
1702 // below ensures that push operations are safe even when interrupted: the
1703 // stack pointer will be decremented before adding an element to the stack.
1704 if (instr->IsStore()) {
1705 LoadStoreWriteBack(addr_reg, offset, addrmode);
1706
1707 // For store the address post writeback is used to check access below the
1708 // stack.
1709 stack = sp();
1710 }
1711
1712 LoadStorePairOp op =
1713 static_cast<LoadStorePairOp>(instr->Mask(LoadStorePairMask));
1714
1715 // 'rt' and 'rt2' can only be aliased for stores.
1716 DCHECK(((op & LoadStorePairLBit) == 0) || (rt != rt2));
1717
1718 switch (op) {
1719 // Use _no_log variants to suppress the register trace (LOG_REGS,
1720 // LOG_FP_REGS). We will print a more detailed log.
1721 case LDP_w: {
1722 DCHECK(access_size == kWRegSize);
1723 set_wreg_no_log(rt, MemoryRead<uint32_t>(address));
1724 set_wreg_no_log(rt2, MemoryRead<uint32_t>(address2));
1725 break;
1726 }
1727 case LDP_s: {
1728 DCHECK(access_size == kSRegSize);
1729 set_sreg_no_log(rt, MemoryRead<float>(address));
1730 set_sreg_no_log(rt2, MemoryRead<float>(address2));
1731 break;
1732 }
1733 case LDP_x: {
1734 DCHECK(access_size == kXRegSize);
1735 set_xreg_no_log(rt, MemoryRead<uint64_t>(address));
1736 set_xreg_no_log(rt2, MemoryRead<uint64_t>(address2));
1737 break;
1738 }
1739 case LDP_d: {
1740 DCHECK(access_size == kDRegSize);
1741 set_dreg_no_log(rt, MemoryRead<double>(address));
1742 set_dreg_no_log(rt2, MemoryRead<double>(address2));
1743 break;
1744 }
1745 case LDPSW_x: {
1746 DCHECK(access_size == kWRegSize);
1747 set_xreg_no_log(rt, MemoryRead<int32_t>(address));
1748 set_xreg_no_log(rt2, MemoryRead<int32_t>(address2));
1749 break;
1750 }
1751 case STP_w: {
1752 DCHECK(access_size == kWRegSize);
1753 MemoryWrite<uint32_t>(address, wreg(rt));
1754 MemoryWrite<uint32_t>(address2, wreg(rt2));
1755 break;
1756 }
1757 case STP_s: {
1758 DCHECK(access_size == kSRegSize);
1759 MemoryWrite<float>(address, sreg(rt));
1760 MemoryWrite<float>(address2, sreg(rt2));
1761 break;
1762 }
1763 case STP_x: {
1764 DCHECK(access_size == kXRegSize);
1765 MemoryWrite<uint64_t>(address, xreg(rt));
1766 MemoryWrite<uint64_t>(address2, xreg(rt2));
1767 break;
1768 }
1769 case STP_d: {
1770 DCHECK(access_size == kDRegSize);
1771 MemoryWrite<double>(address, dreg(rt));
1772 MemoryWrite<double>(address2, dreg(rt2));
1773 break;
1774 }
1775 default: UNREACHABLE();
1776 }
1777
1778 // Print a detailed trace (including the memory address) instead of the basic
1779 // register:value trace generated by set_*reg().
1780 if (instr->IsLoad()) {
1781 if ((op == LDP_s) || (op == LDP_d)) {
1782 LogReadFP(address, access_size, rt);
1783 LogReadFP(address2, access_size, rt2);
1784 } else {
1785 LogRead(address, access_size, rt);
1786 LogRead(address2, access_size, rt2);
1787 }
1788 } else {
1789 if ((op == STP_s) || (op == STP_d)) {
1790 LogWriteFP(address, access_size, rt);
1791 LogWriteFP(address2, access_size, rt2);
1792 } else {
1793 LogWrite(address, access_size, rt);
1794 LogWrite(address2, access_size, rt2);
1795 }
1796 }
1797
1798 // Handle the writeback for loads after the load to ensure safe pop
1799 // operation even when interrupted in the middle of it. The stack pointer
1800 // is only updated after the load so pop(fp) will never break the invariant
1801 // sp <= fp expected while walking the stack in the sampler.
1802 if (instr->IsLoad()) {
1803 // For loads the address pre writeback is used to check access below the
1804 // stack.
1805 stack = sp();
1806
1807 LoadStoreWriteBack(addr_reg, offset, addrmode);
1808 }
1809
1810 // Accesses below the stack pointer (but above the platform stack limit) are
1811 // not allowed in the ABI.
1812 CheckMemoryAccess(address, stack);
1813 }
1814
1815
VisitLoadLiteral(Instruction * instr)1816 void Simulator::VisitLoadLiteral(Instruction* instr) {
1817 uintptr_t address = instr->LiteralAddress();
1818 unsigned rt = instr->Rt();
1819
1820 switch (instr->Mask(LoadLiteralMask)) {
1821 // Use _no_log variants to suppress the register trace (LOG_REGS,
1822 // LOG_FP_REGS), then print a more detailed log.
1823 case LDR_w_lit:
1824 set_wreg_no_log(rt, MemoryRead<uint32_t>(address));
1825 LogRead(address, kWRegSize, rt);
1826 break;
1827 case LDR_x_lit:
1828 set_xreg_no_log(rt, MemoryRead<uint64_t>(address));
1829 LogRead(address, kXRegSize, rt);
1830 break;
1831 case LDR_s_lit:
1832 set_sreg_no_log(rt, MemoryRead<float>(address));
1833 LogReadFP(address, kSRegSize, rt);
1834 break;
1835 case LDR_d_lit:
1836 set_dreg_no_log(rt, MemoryRead<double>(address));
1837 LogReadFP(address, kDRegSize, rt);
1838 break;
1839 default: UNREACHABLE();
1840 }
1841 }
1842
1843
LoadStoreAddress(unsigned addr_reg,int64_t offset,AddrMode addrmode)1844 uintptr_t Simulator::LoadStoreAddress(unsigned addr_reg, int64_t offset,
1845 AddrMode addrmode) {
1846 const unsigned kSPRegCode = kSPRegInternalCode & kRegCodeMask;
1847 uint64_t address = xreg(addr_reg, Reg31IsStackPointer);
1848 if ((addr_reg == kSPRegCode) && ((address % 16) != 0)) {
1849 // When the base register is SP the stack pointer is required to be
1850 // quadword aligned prior to the address calculation and write-backs.
1851 // Misalignment will cause a stack alignment fault.
1852 FATAL("ALIGNMENT EXCEPTION");
1853 }
1854
1855 if ((addrmode == Offset) || (addrmode == PreIndex)) {
1856 address += offset;
1857 }
1858
1859 return address;
1860 }
1861
1862
LoadStoreWriteBack(unsigned addr_reg,int64_t offset,AddrMode addrmode)1863 void Simulator::LoadStoreWriteBack(unsigned addr_reg,
1864 int64_t offset,
1865 AddrMode addrmode) {
1866 if ((addrmode == PreIndex) || (addrmode == PostIndex)) {
1867 DCHECK(offset != 0);
1868 uint64_t address = xreg(addr_reg, Reg31IsStackPointer);
1869 set_reg(addr_reg, address + offset, Reg31IsStackPointer);
1870 }
1871 }
1872
1873
CheckMemoryAccess(uintptr_t address,uintptr_t stack)1874 void Simulator::CheckMemoryAccess(uintptr_t address, uintptr_t stack) {
1875 if ((address >= stack_limit_) && (address < stack)) {
1876 fprintf(stream_, "ACCESS BELOW STACK POINTER:\n");
1877 fprintf(stream_, " sp is here: 0x%016" PRIx64 "\n",
1878 static_cast<uint64_t>(stack));
1879 fprintf(stream_, " access was here: 0x%016" PRIx64 "\n",
1880 static_cast<uint64_t>(address));
1881 fprintf(stream_, " stack limit is here: 0x%016" PRIx64 "\n",
1882 static_cast<uint64_t>(stack_limit_));
1883 fprintf(stream_, "\n");
1884 FATAL("ACCESS BELOW STACK POINTER");
1885 }
1886 }
1887
1888
VisitMoveWideImmediate(Instruction * instr)1889 void Simulator::VisitMoveWideImmediate(Instruction* instr) {
1890 MoveWideImmediateOp mov_op =
1891 static_cast<MoveWideImmediateOp>(instr->Mask(MoveWideImmediateMask));
1892 int64_t new_xn_val = 0;
1893
1894 bool is_64_bits = instr->SixtyFourBits() == 1;
1895 // Shift is limited for W operations.
1896 DCHECK(is_64_bits || (instr->ShiftMoveWide() < 2));
1897
1898 // Get the shifted immediate.
1899 int64_t shift = instr->ShiftMoveWide() * 16;
1900 int64_t shifted_imm16 = static_cast<int64_t>(instr->ImmMoveWide()) << shift;
1901
1902 // Compute the new value.
1903 switch (mov_op) {
1904 case MOVN_w:
1905 case MOVN_x: {
1906 new_xn_val = ~shifted_imm16;
1907 if (!is_64_bits) new_xn_val &= kWRegMask;
1908 break;
1909 }
1910 case MOVK_w:
1911 case MOVK_x: {
1912 unsigned reg_code = instr->Rd();
1913 int64_t prev_xn_val = is_64_bits ? xreg(reg_code)
1914 : wreg(reg_code);
1915 new_xn_val = (prev_xn_val & ~(0xffffL << shift)) | shifted_imm16;
1916 break;
1917 }
1918 case MOVZ_w:
1919 case MOVZ_x: {
1920 new_xn_val = shifted_imm16;
1921 break;
1922 }
1923 default:
1924 UNREACHABLE();
1925 }
1926
1927 // Update the destination register.
1928 set_xreg(instr->Rd(), new_xn_val);
1929 }
1930
1931
VisitConditionalSelect(Instruction * instr)1932 void Simulator::VisitConditionalSelect(Instruction* instr) {
1933 uint64_t new_val = xreg(instr->Rn());
1934 if (ConditionFailed(static_cast<Condition>(instr->Condition()))) {
1935 new_val = xreg(instr->Rm());
1936 switch (instr->Mask(ConditionalSelectMask)) {
1937 case CSEL_w:
1938 case CSEL_x:
1939 break;
1940 case CSINC_w:
1941 case CSINC_x:
1942 new_val++;
1943 break;
1944 case CSINV_w:
1945 case CSINV_x:
1946 new_val = ~new_val;
1947 break;
1948 case CSNEG_w:
1949 case CSNEG_x:
1950 new_val = -new_val;
1951 break;
1952 default: UNIMPLEMENTED();
1953 }
1954 }
1955 if (instr->SixtyFourBits()) {
1956 set_xreg(instr->Rd(), new_val);
1957 } else {
1958 set_wreg(instr->Rd(), static_cast<uint32_t>(new_val));
1959 }
1960 }
1961
1962
VisitDataProcessing1Source(Instruction * instr)1963 void Simulator::VisitDataProcessing1Source(Instruction* instr) {
1964 unsigned dst = instr->Rd();
1965 unsigned src = instr->Rn();
1966
1967 switch (instr->Mask(DataProcessing1SourceMask)) {
1968 case RBIT_w:
1969 set_wreg(dst, ReverseBits(wreg(src)));
1970 break;
1971 case RBIT_x:
1972 set_xreg(dst, ReverseBits(xreg(src)));
1973 break;
1974 case REV16_w:
1975 set_wreg(dst, ReverseBytes(wreg(src), 1));
1976 break;
1977 case REV16_x:
1978 set_xreg(dst, ReverseBytes(xreg(src), 1));
1979 break;
1980 case REV_w:
1981 set_wreg(dst, ReverseBytes(wreg(src), 2));
1982 break;
1983 case REV32_x:
1984 set_xreg(dst, ReverseBytes(xreg(src), 2));
1985 break;
1986 case REV_x:
1987 set_xreg(dst, ReverseBytes(xreg(src), 3));
1988 break;
1989 case CLZ_w: set_wreg(dst, CountLeadingZeros(wreg(src), kWRegSizeInBits));
1990 break;
1991 case CLZ_x: set_xreg(dst, CountLeadingZeros(xreg(src), kXRegSizeInBits));
1992 break;
1993 case CLS_w: {
1994 set_wreg(dst, CountLeadingSignBits(wreg(src), kWRegSizeInBits));
1995 break;
1996 }
1997 case CLS_x: {
1998 set_xreg(dst, CountLeadingSignBits(xreg(src), kXRegSizeInBits));
1999 break;
2000 }
2001 default: UNIMPLEMENTED();
2002 }
2003 }
2004
2005
2006 template <typename T>
DataProcessing2Source(Instruction * instr)2007 void Simulator::DataProcessing2Source(Instruction* instr) {
2008 Shift shift_op = NO_SHIFT;
2009 T result = 0;
2010 switch (instr->Mask(DataProcessing2SourceMask)) {
2011 case SDIV_w:
2012 case SDIV_x: {
2013 T rn = reg<T>(instr->Rn());
2014 T rm = reg<T>(instr->Rm());
2015 if ((rn == std::numeric_limits<T>::min()) && (rm == -1)) {
2016 result = std::numeric_limits<T>::min();
2017 } else if (rm == 0) {
2018 // Division by zero can be trapped, but not on A-class processors.
2019 result = 0;
2020 } else {
2021 result = rn / rm;
2022 }
2023 break;
2024 }
2025 case UDIV_w:
2026 case UDIV_x: {
2027 typedef typename make_unsigned<T>::type unsignedT;
2028 unsignedT rn = static_cast<unsignedT>(reg<T>(instr->Rn()));
2029 unsignedT rm = static_cast<unsignedT>(reg<T>(instr->Rm()));
2030 if (rm == 0) {
2031 // Division by zero can be trapped, but not on A-class processors.
2032 result = 0;
2033 } else {
2034 result = rn / rm;
2035 }
2036 break;
2037 }
2038 case LSLV_w:
2039 case LSLV_x: shift_op = LSL; break;
2040 case LSRV_w:
2041 case LSRV_x: shift_op = LSR; break;
2042 case ASRV_w:
2043 case ASRV_x: shift_op = ASR; break;
2044 case RORV_w:
2045 case RORV_x: shift_op = ROR; break;
2046 default: UNIMPLEMENTED();
2047 }
2048
2049 if (shift_op != NO_SHIFT) {
2050 // Shift distance encoded in the least-significant five/six bits of the
2051 // register.
2052 unsigned shift = wreg(instr->Rm());
2053 if (sizeof(T) == kWRegSize) {
2054 shift &= kShiftAmountWRegMask;
2055 } else {
2056 shift &= kShiftAmountXRegMask;
2057 }
2058 result = ShiftOperand(reg<T>(instr->Rn()), shift_op, shift);
2059 }
2060 set_reg<T>(instr->Rd(), result);
2061 }
2062
2063
VisitDataProcessing2Source(Instruction * instr)2064 void Simulator::VisitDataProcessing2Source(Instruction* instr) {
2065 if (instr->SixtyFourBits()) {
2066 DataProcessing2Source<int64_t>(instr);
2067 } else {
2068 DataProcessing2Source<int32_t>(instr);
2069 }
2070 }
2071
2072
2073 // The algorithm used is described in section 8.2 of
2074 // Hacker's Delight, by Henry S. Warren, Jr.
2075 // It assumes that a right shift on a signed integer is an arithmetic shift.
MultiplyHighSigned(int64_t u,int64_t v)2076 static int64_t MultiplyHighSigned(int64_t u, int64_t v) {
2077 uint64_t u0, v0, w0;
2078 int64_t u1, v1, w1, w2, t;
2079
2080 u0 = u & 0xffffffffL;
2081 u1 = u >> 32;
2082 v0 = v & 0xffffffffL;
2083 v1 = v >> 32;
2084
2085 w0 = u0 * v0;
2086 t = u1 * v0 + (w0 >> 32);
2087 w1 = t & 0xffffffffL;
2088 w2 = t >> 32;
2089 w1 = u0 * v1 + w1;
2090
2091 return u1 * v1 + w2 + (w1 >> 32);
2092 }
2093
2094
VisitDataProcessing3Source(Instruction * instr)2095 void Simulator::VisitDataProcessing3Source(Instruction* instr) {
2096 int64_t result = 0;
2097 // Extract and sign- or zero-extend 32-bit arguments for widening operations.
2098 uint64_t rn_u32 = reg<uint32_t>(instr->Rn());
2099 uint64_t rm_u32 = reg<uint32_t>(instr->Rm());
2100 int64_t rn_s32 = reg<int32_t>(instr->Rn());
2101 int64_t rm_s32 = reg<int32_t>(instr->Rm());
2102 switch (instr->Mask(DataProcessing3SourceMask)) {
2103 case MADD_w:
2104 case MADD_x:
2105 result = xreg(instr->Ra()) + (xreg(instr->Rn()) * xreg(instr->Rm()));
2106 break;
2107 case MSUB_w:
2108 case MSUB_x:
2109 result = xreg(instr->Ra()) - (xreg(instr->Rn()) * xreg(instr->Rm()));
2110 break;
2111 case SMADDL_x: result = xreg(instr->Ra()) + (rn_s32 * rm_s32); break;
2112 case SMSUBL_x: result = xreg(instr->Ra()) - (rn_s32 * rm_s32); break;
2113 case UMADDL_x: result = xreg(instr->Ra()) + (rn_u32 * rm_u32); break;
2114 case UMSUBL_x: result = xreg(instr->Ra()) - (rn_u32 * rm_u32); break;
2115 case SMULH_x:
2116 DCHECK(instr->Ra() == kZeroRegCode);
2117 result = MultiplyHighSigned(xreg(instr->Rn()), xreg(instr->Rm()));
2118 break;
2119 default: UNIMPLEMENTED();
2120 }
2121
2122 if (instr->SixtyFourBits()) {
2123 set_xreg(instr->Rd(), result);
2124 } else {
2125 set_wreg(instr->Rd(), static_cast<int32_t>(result));
2126 }
2127 }
2128
2129
2130 template <typename T>
BitfieldHelper(Instruction * instr)2131 void Simulator::BitfieldHelper(Instruction* instr) {
2132 typedef typename make_unsigned<T>::type unsignedT;
2133 T reg_size = sizeof(T) * 8;
2134 T R = instr->ImmR();
2135 T S = instr->ImmS();
2136 T diff = S - R;
2137 T mask;
2138 if (diff >= 0) {
2139 mask = diff < reg_size - 1 ? (static_cast<T>(1) << (diff + 1)) - 1
2140 : static_cast<T>(-1);
2141 } else {
2142 uint64_t umask = ((1L << (S + 1)) - 1);
2143 umask = (umask >> R) | (umask << (reg_size - R));
2144 mask = static_cast<T>(umask);
2145 diff += reg_size;
2146 }
2147
2148 // inzero indicates if the extracted bitfield is inserted into the
2149 // destination register value or in zero.
2150 // If extend is true, extend the sign of the extracted bitfield.
2151 bool inzero = false;
2152 bool extend = false;
2153 switch (instr->Mask(BitfieldMask)) {
2154 case BFM_x:
2155 case BFM_w:
2156 break;
2157 case SBFM_x:
2158 case SBFM_w:
2159 inzero = true;
2160 extend = true;
2161 break;
2162 case UBFM_x:
2163 case UBFM_w:
2164 inzero = true;
2165 break;
2166 default:
2167 UNIMPLEMENTED();
2168 }
2169
2170 T dst = inzero ? 0 : reg<T>(instr->Rd());
2171 T src = reg<T>(instr->Rn());
2172 // Rotate source bitfield into place.
2173 T result = (static_cast<unsignedT>(src) >> R) | (src << (reg_size - R));
2174 // Determine the sign extension.
2175 T topbits_preshift = (static_cast<T>(1) << (reg_size - diff - 1)) - 1;
2176 T signbits = (extend && ((src >> S) & 1) ? topbits_preshift : 0)
2177 << (diff + 1);
2178
2179 // Merge sign extension, dest/zero and bitfield.
2180 result = signbits | (result & mask) | (dst & ~mask);
2181
2182 set_reg<T>(instr->Rd(), result);
2183 }
2184
2185
VisitBitfield(Instruction * instr)2186 void Simulator::VisitBitfield(Instruction* instr) {
2187 if (instr->SixtyFourBits()) {
2188 BitfieldHelper<int64_t>(instr);
2189 } else {
2190 BitfieldHelper<int32_t>(instr);
2191 }
2192 }
2193
2194
VisitExtract(Instruction * instr)2195 void Simulator::VisitExtract(Instruction* instr) {
2196 if (instr->SixtyFourBits()) {
2197 Extract<uint64_t>(instr);
2198 } else {
2199 Extract<uint32_t>(instr);
2200 }
2201 }
2202
2203
VisitFPImmediate(Instruction * instr)2204 void Simulator::VisitFPImmediate(Instruction* instr) {
2205 AssertSupportedFPCR();
2206
2207 unsigned dest = instr->Rd();
2208 switch (instr->Mask(FPImmediateMask)) {
2209 case FMOV_s_imm: set_sreg(dest, instr->ImmFP32()); break;
2210 case FMOV_d_imm: set_dreg(dest, instr->ImmFP64()); break;
2211 default: UNREACHABLE();
2212 }
2213 }
2214
2215
VisitFPIntegerConvert(Instruction * instr)2216 void Simulator::VisitFPIntegerConvert(Instruction* instr) {
2217 AssertSupportedFPCR();
2218
2219 unsigned dst = instr->Rd();
2220 unsigned src = instr->Rn();
2221
2222 FPRounding round = fpcr().RMode();
2223
2224 switch (instr->Mask(FPIntegerConvertMask)) {
2225 case FCVTAS_ws: set_wreg(dst, FPToInt32(sreg(src), FPTieAway)); break;
2226 case FCVTAS_xs: set_xreg(dst, FPToInt64(sreg(src), FPTieAway)); break;
2227 case FCVTAS_wd: set_wreg(dst, FPToInt32(dreg(src), FPTieAway)); break;
2228 case FCVTAS_xd: set_xreg(dst, FPToInt64(dreg(src), FPTieAway)); break;
2229 case FCVTAU_ws: set_wreg(dst, FPToUInt32(sreg(src), FPTieAway)); break;
2230 case FCVTAU_xs: set_xreg(dst, FPToUInt64(sreg(src), FPTieAway)); break;
2231 case FCVTAU_wd: set_wreg(dst, FPToUInt32(dreg(src), FPTieAway)); break;
2232 case FCVTAU_xd: set_xreg(dst, FPToUInt64(dreg(src), FPTieAway)); break;
2233 case FCVTMS_ws:
2234 set_wreg(dst, FPToInt32(sreg(src), FPNegativeInfinity));
2235 break;
2236 case FCVTMS_xs:
2237 set_xreg(dst, FPToInt64(sreg(src), FPNegativeInfinity));
2238 break;
2239 case FCVTMS_wd:
2240 set_wreg(dst, FPToInt32(dreg(src), FPNegativeInfinity));
2241 break;
2242 case FCVTMS_xd:
2243 set_xreg(dst, FPToInt64(dreg(src), FPNegativeInfinity));
2244 break;
2245 case FCVTMU_ws:
2246 set_wreg(dst, FPToUInt32(sreg(src), FPNegativeInfinity));
2247 break;
2248 case FCVTMU_xs:
2249 set_xreg(dst, FPToUInt64(sreg(src), FPNegativeInfinity));
2250 break;
2251 case FCVTMU_wd:
2252 set_wreg(dst, FPToUInt32(dreg(src), FPNegativeInfinity));
2253 break;
2254 case FCVTMU_xd:
2255 set_xreg(dst, FPToUInt64(dreg(src), FPNegativeInfinity));
2256 break;
2257 case FCVTNS_ws: set_wreg(dst, FPToInt32(sreg(src), FPTieEven)); break;
2258 case FCVTNS_xs: set_xreg(dst, FPToInt64(sreg(src), FPTieEven)); break;
2259 case FCVTNS_wd: set_wreg(dst, FPToInt32(dreg(src), FPTieEven)); break;
2260 case FCVTNS_xd: set_xreg(dst, FPToInt64(dreg(src), FPTieEven)); break;
2261 case FCVTNU_ws: set_wreg(dst, FPToUInt32(sreg(src), FPTieEven)); break;
2262 case FCVTNU_xs: set_xreg(dst, FPToUInt64(sreg(src), FPTieEven)); break;
2263 case FCVTNU_wd: set_wreg(dst, FPToUInt32(dreg(src), FPTieEven)); break;
2264 case FCVTNU_xd: set_xreg(dst, FPToUInt64(dreg(src), FPTieEven)); break;
2265 case FCVTZS_ws: set_wreg(dst, FPToInt32(sreg(src), FPZero)); break;
2266 case FCVTZS_xs: set_xreg(dst, FPToInt64(sreg(src), FPZero)); break;
2267 case FCVTZS_wd: set_wreg(dst, FPToInt32(dreg(src), FPZero)); break;
2268 case FCVTZS_xd: set_xreg(dst, FPToInt64(dreg(src), FPZero)); break;
2269 case FCVTZU_ws: set_wreg(dst, FPToUInt32(sreg(src), FPZero)); break;
2270 case FCVTZU_xs: set_xreg(dst, FPToUInt64(sreg(src), FPZero)); break;
2271 case FCVTZU_wd: set_wreg(dst, FPToUInt32(dreg(src), FPZero)); break;
2272 case FCVTZU_xd: set_xreg(dst, FPToUInt64(dreg(src), FPZero)); break;
2273 case FMOV_ws: set_wreg(dst, sreg_bits(src)); break;
2274 case FMOV_xd: set_xreg(dst, dreg_bits(src)); break;
2275 case FMOV_sw: set_sreg_bits(dst, wreg(src)); break;
2276 case FMOV_dx: set_dreg_bits(dst, xreg(src)); break;
2277
2278 // A 32-bit input can be handled in the same way as a 64-bit input, since
2279 // the sign- or zero-extension will not affect the conversion.
2280 case SCVTF_dx: set_dreg(dst, FixedToDouble(xreg(src), 0, round)); break;
2281 case SCVTF_dw: set_dreg(dst, FixedToDouble(wreg(src), 0, round)); break;
2282 case UCVTF_dx: set_dreg(dst, UFixedToDouble(xreg(src), 0, round)); break;
2283 case UCVTF_dw: {
2284 set_dreg(dst, UFixedToDouble(reg<uint32_t>(src), 0, round));
2285 break;
2286 }
2287 case SCVTF_sx: set_sreg(dst, FixedToFloat(xreg(src), 0, round)); break;
2288 case SCVTF_sw: set_sreg(dst, FixedToFloat(wreg(src), 0, round)); break;
2289 case UCVTF_sx: set_sreg(dst, UFixedToFloat(xreg(src), 0, round)); break;
2290 case UCVTF_sw: {
2291 set_sreg(dst, UFixedToFloat(reg<uint32_t>(src), 0, round));
2292 break;
2293 }
2294
2295 default: UNREACHABLE();
2296 }
2297 }
2298
2299
VisitFPFixedPointConvert(Instruction * instr)2300 void Simulator::VisitFPFixedPointConvert(Instruction* instr) {
2301 AssertSupportedFPCR();
2302
2303 unsigned dst = instr->Rd();
2304 unsigned src = instr->Rn();
2305 int fbits = 64 - instr->FPScale();
2306
2307 FPRounding round = fpcr().RMode();
2308
2309 switch (instr->Mask(FPFixedPointConvertMask)) {
2310 // A 32-bit input can be handled in the same way as a 64-bit input, since
2311 // the sign- or zero-extension will not affect the conversion.
2312 case SCVTF_dx_fixed:
2313 set_dreg(dst, FixedToDouble(xreg(src), fbits, round));
2314 break;
2315 case SCVTF_dw_fixed:
2316 set_dreg(dst, FixedToDouble(wreg(src), fbits, round));
2317 break;
2318 case UCVTF_dx_fixed:
2319 set_dreg(dst, UFixedToDouble(xreg(src), fbits, round));
2320 break;
2321 case UCVTF_dw_fixed: {
2322 set_dreg(dst,
2323 UFixedToDouble(reg<uint32_t>(src), fbits, round));
2324 break;
2325 }
2326 case SCVTF_sx_fixed:
2327 set_sreg(dst, FixedToFloat(xreg(src), fbits, round));
2328 break;
2329 case SCVTF_sw_fixed:
2330 set_sreg(dst, FixedToFloat(wreg(src), fbits, round));
2331 break;
2332 case UCVTF_sx_fixed:
2333 set_sreg(dst, UFixedToFloat(xreg(src), fbits, round));
2334 break;
2335 case UCVTF_sw_fixed: {
2336 set_sreg(dst,
2337 UFixedToFloat(reg<uint32_t>(src), fbits, round));
2338 break;
2339 }
2340 default: UNREACHABLE();
2341 }
2342 }
2343
2344
FPToInt32(double value,FPRounding rmode)2345 int32_t Simulator::FPToInt32(double value, FPRounding rmode) {
2346 value = FPRoundInt(value, rmode);
2347 if (value >= kWMaxInt) {
2348 return kWMaxInt;
2349 } else if (value < kWMinInt) {
2350 return kWMinInt;
2351 }
2352 return std::isnan(value) ? 0 : static_cast<int32_t>(value);
2353 }
2354
2355
FPToInt64(double value,FPRounding rmode)2356 int64_t Simulator::FPToInt64(double value, FPRounding rmode) {
2357 value = FPRoundInt(value, rmode);
2358 if (value >= kXMaxInt) {
2359 return kXMaxInt;
2360 } else if (value < kXMinInt) {
2361 return kXMinInt;
2362 }
2363 return std::isnan(value) ? 0 : static_cast<int64_t>(value);
2364 }
2365
2366
FPToUInt32(double value,FPRounding rmode)2367 uint32_t Simulator::FPToUInt32(double value, FPRounding rmode) {
2368 value = FPRoundInt(value, rmode);
2369 if (value >= kWMaxUInt) {
2370 return kWMaxUInt;
2371 } else if (value < 0.0) {
2372 return 0;
2373 }
2374 return std::isnan(value) ? 0 : static_cast<uint32_t>(value);
2375 }
2376
2377
FPToUInt64(double value,FPRounding rmode)2378 uint64_t Simulator::FPToUInt64(double value, FPRounding rmode) {
2379 value = FPRoundInt(value, rmode);
2380 if (value >= kXMaxUInt) {
2381 return kXMaxUInt;
2382 } else if (value < 0.0) {
2383 return 0;
2384 }
2385 return std::isnan(value) ? 0 : static_cast<uint64_t>(value);
2386 }
2387
2388
VisitFPCompare(Instruction * instr)2389 void Simulator::VisitFPCompare(Instruction* instr) {
2390 AssertSupportedFPCR();
2391
2392 unsigned reg_size = (instr->Mask(FP64) == FP64) ? kDRegSizeInBits
2393 : kSRegSizeInBits;
2394 double fn_val = fpreg(reg_size, instr->Rn());
2395
2396 switch (instr->Mask(FPCompareMask)) {
2397 case FCMP_s:
2398 case FCMP_d: FPCompare(fn_val, fpreg(reg_size, instr->Rm())); break;
2399 case FCMP_s_zero:
2400 case FCMP_d_zero: FPCompare(fn_val, 0.0); break;
2401 default: UNIMPLEMENTED();
2402 }
2403 }
2404
2405
VisitFPConditionalCompare(Instruction * instr)2406 void Simulator::VisitFPConditionalCompare(Instruction* instr) {
2407 AssertSupportedFPCR();
2408
2409 switch (instr->Mask(FPConditionalCompareMask)) {
2410 case FCCMP_s:
2411 case FCCMP_d: {
2412 if (ConditionPassed(static_cast<Condition>(instr->Condition()))) {
2413 // If the condition passes, set the status flags to the result of
2414 // comparing the operands.
2415 unsigned reg_size = (instr->Mask(FP64) == FP64) ? kDRegSizeInBits
2416 : kSRegSizeInBits;
2417 FPCompare(fpreg(reg_size, instr->Rn()), fpreg(reg_size, instr->Rm()));
2418 } else {
2419 // If the condition fails, set the status flags to the nzcv immediate.
2420 nzcv().SetFlags(instr->Nzcv());
2421 LogSystemRegister(NZCV);
2422 }
2423 break;
2424 }
2425 default: UNIMPLEMENTED();
2426 }
2427 }
2428
2429
VisitFPConditionalSelect(Instruction * instr)2430 void Simulator::VisitFPConditionalSelect(Instruction* instr) {
2431 AssertSupportedFPCR();
2432
2433 Instr selected;
2434 if (ConditionPassed(static_cast<Condition>(instr->Condition()))) {
2435 selected = instr->Rn();
2436 } else {
2437 selected = instr->Rm();
2438 }
2439
2440 switch (instr->Mask(FPConditionalSelectMask)) {
2441 case FCSEL_s: set_sreg(instr->Rd(), sreg(selected)); break;
2442 case FCSEL_d: set_dreg(instr->Rd(), dreg(selected)); break;
2443 default: UNIMPLEMENTED();
2444 }
2445 }
2446
2447
VisitFPDataProcessing1Source(Instruction * instr)2448 void Simulator::VisitFPDataProcessing1Source(Instruction* instr) {
2449 AssertSupportedFPCR();
2450
2451 unsigned fd = instr->Rd();
2452 unsigned fn = instr->Rn();
2453
2454 switch (instr->Mask(FPDataProcessing1SourceMask)) {
2455 case FMOV_s: set_sreg(fd, sreg(fn)); break;
2456 case FMOV_d: set_dreg(fd, dreg(fn)); break;
2457 case FABS_s: set_sreg(fd, std::fabs(sreg(fn))); break;
2458 case FABS_d: set_dreg(fd, std::fabs(dreg(fn))); break;
2459 case FNEG_s: set_sreg(fd, -sreg(fn)); break;
2460 case FNEG_d: set_dreg(fd, -dreg(fn)); break;
2461 case FSQRT_s: set_sreg(fd, FPSqrt(sreg(fn))); break;
2462 case FSQRT_d: set_dreg(fd, FPSqrt(dreg(fn))); break;
2463 case FRINTA_s: set_sreg(fd, FPRoundInt(sreg(fn), FPTieAway)); break;
2464 case FRINTA_d: set_dreg(fd, FPRoundInt(dreg(fn), FPTieAway)); break;
2465 case FRINTM_s:
2466 set_sreg(fd, FPRoundInt(sreg(fn), FPNegativeInfinity)); break;
2467 case FRINTM_d:
2468 set_dreg(fd, FPRoundInt(dreg(fn), FPNegativeInfinity)); break;
2469 case FRINTP_s:
2470 set_sreg(fd, FPRoundInt(sreg(fn), FPPositiveInfinity));
2471 break;
2472 case FRINTP_d:
2473 set_dreg(fd, FPRoundInt(dreg(fn), FPPositiveInfinity));
2474 break;
2475 case FRINTN_s: set_sreg(fd, FPRoundInt(sreg(fn), FPTieEven)); break;
2476 case FRINTN_d: set_dreg(fd, FPRoundInt(dreg(fn), FPTieEven)); break;
2477 case FRINTZ_s: set_sreg(fd, FPRoundInt(sreg(fn), FPZero)); break;
2478 case FRINTZ_d: set_dreg(fd, FPRoundInt(dreg(fn), FPZero)); break;
2479 case FCVT_ds: set_dreg(fd, FPToDouble(sreg(fn))); break;
2480 case FCVT_sd: set_sreg(fd, FPToFloat(dreg(fn), FPTieEven)); break;
2481 default: UNIMPLEMENTED();
2482 }
2483 }
2484
2485
2486 // Assemble the specified IEEE-754 components into the target type and apply
2487 // appropriate rounding.
2488 // sign: 0 = positive, 1 = negative
2489 // exponent: Unbiased IEEE-754 exponent.
2490 // mantissa: The mantissa of the input. The top bit (which is not encoded for
2491 // normal IEEE-754 values) must not be omitted. This bit has the
2492 // value 'pow(2, exponent)'.
2493 //
2494 // The input value is assumed to be a normalized value. That is, the input may
2495 // not be infinity or NaN. If the source value is subnormal, it must be
2496 // normalized before calling this function such that the highest set bit in the
2497 // mantissa has the value 'pow(2, exponent)'.
2498 //
2499 // Callers should use FPRoundToFloat or FPRoundToDouble directly, rather than
2500 // calling a templated FPRound.
2501 template <class T, int ebits, int mbits>
FPRound(int64_t sign,int64_t exponent,uint64_t mantissa,FPRounding round_mode)2502 static T FPRound(int64_t sign, int64_t exponent, uint64_t mantissa,
2503 FPRounding round_mode) {
2504 DCHECK((sign == 0) || (sign == 1));
2505
2506 // Only the FPTieEven rounding mode is implemented.
2507 DCHECK(round_mode == FPTieEven);
2508 USE(round_mode);
2509
2510 // Rounding can promote subnormals to normals, and normals to infinities. For
2511 // example, a double with exponent 127 (FLT_MAX_EXP) would appear to be
2512 // encodable as a float, but rounding based on the low-order mantissa bits
2513 // could make it overflow. With ties-to-even rounding, this value would become
2514 // an infinity.
2515
2516 // ---- Rounding Method ----
2517 //
2518 // The exponent is irrelevant in the rounding operation, so we treat the
2519 // lowest-order bit that will fit into the result ('onebit') as having
2520 // the value '1'. Similarly, the highest-order bit that won't fit into
2521 // the result ('halfbit') has the value '0.5'. The 'point' sits between
2522 // 'onebit' and 'halfbit':
2523 //
2524 // These bits fit into the result.
2525 // |---------------------|
2526 // mantissa = 0bxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
2527 // ||
2528 // / |
2529 // / halfbit
2530 // onebit
2531 //
2532 // For subnormal outputs, the range of representable bits is smaller and
2533 // the position of onebit and halfbit depends on the exponent of the
2534 // input, but the method is otherwise similar.
2535 //
2536 // onebit(frac)
2537 // |
2538 // | halfbit(frac) halfbit(adjusted)
2539 // | / /
2540 // | | |
2541 // 0b00.0 (exact) -> 0b00.0 (exact) -> 0b00
2542 // 0b00.0... -> 0b00.0... -> 0b00
2543 // 0b00.1 (exact) -> 0b00.0111..111 -> 0b00
2544 // 0b00.1... -> 0b00.1... -> 0b01
2545 // 0b01.0 (exact) -> 0b01.0 (exact) -> 0b01
2546 // 0b01.0... -> 0b01.0... -> 0b01
2547 // 0b01.1 (exact) -> 0b01.1 (exact) -> 0b10
2548 // 0b01.1... -> 0b01.1... -> 0b10
2549 // 0b10.0 (exact) -> 0b10.0 (exact) -> 0b10
2550 // 0b10.0... -> 0b10.0... -> 0b10
2551 // 0b10.1 (exact) -> 0b10.0111..111 -> 0b10
2552 // 0b10.1... -> 0b10.1... -> 0b11
2553 // 0b11.0 (exact) -> 0b11.0 (exact) -> 0b11
2554 // ... / | / |
2555 // / | / |
2556 // / |
2557 // adjusted = frac - (halfbit(mantissa) & ~onebit(frac)); / |
2558 //
2559 // mantissa = (mantissa >> shift) + halfbit(adjusted);
2560
2561 static const int mantissa_offset = 0;
2562 static const int exponent_offset = mantissa_offset + mbits;
2563 static const int sign_offset = exponent_offset + ebits;
2564 STATIC_ASSERT(sign_offset == (sizeof(T) * kByteSize - 1));
2565
2566 // Bail out early for zero inputs.
2567 if (mantissa == 0) {
2568 return static_cast<T>(sign << sign_offset);
2569 }
2570
2571 // If all bits in the exponent are set, the value is infinite or NaN.
2572 // This is true for all binary IEEE-754 formats.
2573 static const int infinite_exponent = (1 << ebits) - 1;
2574 static const int max_normal_exponent = infinite_exponent - 1;
2575
2576 // Apply the exponent bias to encode it for the result. Doing this early makes
2577 // it easy to detect values that will be infinite or subnormal.
2578 exponent += max_normal_exponent >> 1;
2579
2580 if (exponent > max_normal_exponent) {
2581 // Overflow: The input is too large for the result type to represent. The
2582 // FPTieEven rounding mode handles overflows using infinities.
2583 exponent = infinite_exponent;
2584 mantissa = 0;
2585 return static_cast<T>((sign << sign_offset) |
2586 (exponent << exponent_offset) |
2587 (mantissa << mantissa_offset));
2588 }
2589
2590 // Calculate the shift required to move the top mantissa bit to the proper
2591 // place in the destination type.
2592 const int highest_significant_bit = 63 - CountLeadingZeros(mantissa, 64);
2593 int shift = highest_significant_bit - mbits;
2594
2595 if (exponent <= 0) {
2596 // The output will be subnormal (before rounding).
2597
2598 // For subnormal outputs, the shift must be adjusted by the exponent. The +1
2599 // is necessary because the exponent of a subnormal value (encoded as 0) is
2600 // the same as the exponent of the smallest normal value (encoded as 1).
2601 shift += -exponent + 1;
2602
2603 // Handle inputs that would produce a zero output.
2604 //
2605 // Shifts higher than highest_significant_bit+1 will always produce a zero
2606 // result. A shift of exactly highest_significant_bit+1 might produce a
2607 // non-zero result after rounding.
2608 if (shift > (highest_significant_bit + 1)) {
2609 // The result will always be +/-0.0.
2610 return static_cast<T>(sign << sign_offset);
2611 }
2612
2613 // Properly encode the exponent for a subnormal output.
2614 exponent = 0;
2615 } else {
2616 // Clear the topmost mantissa bit, since this is not encoded in IEEE-754
2617 // normal values.
2618 mantissa &= ~(1UL << highest_significant_bit);
2619 }
2620
2621 if (shift > 0) {
2622 // We have to shift the mantissa to the right. Some precision is lost, so we
2623 // need to apply rounding.
2624 uint64_t onebit_mantissa = (mantissa >> (shift)) & 1;
2625 uint64_t halfbit_mantissa = (mantissa >> (shift-1)) & 1;
2626 uint64_t adjusted = mantissa - (halfbit_mantissa & ~onebit_mantissa);
2627 T halfbit_adjusted = (adjusted >> (shift-1)) & 1;
2628
2629 T result =
2630 static_cast<T>((sign << sign_offset) | (exponent << exponent_offset) |
2631 ((mantissa >> shift) << mantissa_offset));
2632
2633 // A very large mantissa can overflow during rounding. If this happens, the
2634 // exponent should be incremented and the mantissa set to 1.0 (encoded as
2635 // 0). Applying halfbit_adjusted after assembling the float has the nice
2636 // side-effect that this case is handled for free.
2637 //
2638 // This also handles cases where a very large finite value overflows to
2639 // infinity, or where a very large subnormal value overflows to become
2640 // normal.
2641 return result + halfbit_adjusted;
2642 } else {
2643 // We have to shift the mantissa to the left (or not at all). The input
2644 // mantissa is exactly representable in the output mantissa, so apply no
2645 // rounding correction.
2646 return static_cast<T>((sign << sign_offset) |
2647 (exponent << exponent_offset) |
2648 ((mantissa << -shift) << mantissa_offset));
2649 }
2650 }
2651
2652
2653 // See FPRound for a description of this function.
FPRoundToDouble(int64_t sign,int64_t exponent,uint64_t mantissa,FPRounding round_mode)2654 static inline double FPRoundToDouble(int64_t sign, int64_t exponent,
2655 uint64_t mantissa, FPRounding round_mode) {
2656 int64_t bits =
2657 FPRound<int64_t, kDoubleExponentBits, kDoubleMantissaBits>(sign,
2658 exponent,
2659 mantissa,
2660 round_mode);
2661 return rawbits_to_double(bits);
2662 }
2663
2664
2665 // See FPRound for a description of this function.
FPRoundToFloat(int64_t sign,int64_t exponent,uint64_t mantissa,FPRounding round_mode)2666 static inline float FPRoundToFloat(int64_t sign, int64_t exponent,
2667 uint64_t mantissa, FPRounding round_mode) {
2668 int32_t bits =
2669 FPRound<int32_t, kFloatExponentBits, kFloatMantissaBits>(sign,
2670 exponent,
2671 mantissa,
2672 round_mode);
2673 return rawbits_to_float(bits);
2674 }
2675
2676
FixedToDouble(int64_t src,int fbits,FPRounding round)2677 double Simulator::FixedToDouble(int64_t src, int fbits, FPRounding round) {
2678 if (src >= 0) {
2679 return UFixedToDouble(src, fbits, round);
2680 } else {
2681 // This works for all negative values, including INT64_MIN.
2682 return -UFixedToDouble(-src, fbits, round);
2683 }
2684 }
2685
2686
UFixedToDouble(uint64_t src,int fbits,FPRounding round)2687 double Simulator::UFixedToDouble(uint64_t src, int fbits, FPRounding round) {
2688 // An input of 0 is a special case because the result is effectively
2689 // subnormal: The exponent is encoded as 0 and there is no implicit 1 bit.
2690 if (src == 0) {
2691 return 0.0;
2692 }
2693
2694 // Calculate the exponent. The highest significant bit will have the value
2695 // 2^exponent.
2696 const int highest_significant_bit = 63 - CountLeadingZeros(src, 64);
2697 const int64_t exponent = highest_significant_bit - fbits;
2698
2699 return FPRoundToDouble(0, exponent, src, round);
2700 }
2701
2702
FixedToFloat(int64_t src,int fbits,FPRounding round)2703 float Simulator::FixedToFloat(int64_t src, int fbits, FPRounding round) {
2704 if (src >= 0) {
2705 return UFixedToFloat(src, fbits, round);
2706 } else {
2707 // This works for all negative values, including INT64_MIN.
2708 return -UFixedToFloat(-src, fbits, round);
2709 }
2710 }
2711
2712
UFixedToFloat(uint64_t src,int fbits,FPRounding round)2713 float Simulator::UFixedToFloat(uint64_t src, int fbits, FPRounding round) {
2714 // An input of 0 is a special case because the result is effectively
2715 // subnormal: The exponent is encoded as 0 and there is no implicit 1 bit.
2716 if (src == 0) {
2717 return 0.0f;
2718 }
2719
2720 // Calculate the exponent. The highest significant bit will have the value
2721 // 2^exponent.
2722 const int highest_significant_bit = 63 - CountLeadingZeros(src, 64);
2723 const int32_t exponent = highest_significant_bit - fbits;
2724
2725 return FPRoundToFloat(0, exponent, src, round);
2726 }
2727
2728
FPRoundInt(double value,FPRounding round_mode)2729 double Simulator::FPRoundInt(double value, FPRounding round_mode) {
2730 if ((value == 0.0) || (value == kFP64PositiveInfinity) ||
2731 (value == kFP64NegativeInfinity)) {
2732 return value;
2733 } else if (std::isnan(value)) {
2734 return FPProcessNaN(value);
2735 }
2736
2737 double int_result = floor(value);
2738 double error = value - int_result;
2739 switch (round_mode) {
2740 case FPTieAway: {
2741 // Take care of correctly handling the range ]-0.5, -0.0], which must
2742 // yield -0.0.
2743 if ((-0.5 < value) && (value < 0.0)) {
2744 int_result = -0.0;
2745
2746 } else if ((error > 0.5) || ((error == 0.5) && (int_result >= 0.0))) {
2747 // If the error is greater than 0.5, or is equal to 0.5 and the integer
2748 // result is positive, round up.
2749 int_result++;
2750 }
2751 break;
2752 }
2753 case FPTieEven: {
2754 // Take care of correctly handling the range [-0.5, -0.0], which must
2755 // yield -0.0.
2756 if ((-0.5 <= value) && (value < 0.0)) {
2757 int_result = -0.0;
2758
2759 // If the error is greater than 0.5, or is equal to 0.5 and the integer
2760 // result is odd, round up.
2761 } else if ((error > 0.5) ||
2762 ((error == 0.5) && (modulo(int_result, 2) != 0))) {
2763 int_result++;
2764 }
2765 break;
2766 }
2767 case FPZero: {
2768 // If value > 0 then we take floor(value)
2769 // otherwise, ceil(value)
2770 if (value < 0) {
2771 int_result = ceil(value);
2772 }
2773 break;
2774 }
2775 case FPNegativeInfinity: {
2776 // We always use floor(value).
2777 break;
2778 }
2779 case FPPositiveInfinity: {
2780 int_result = ceil(value);
2781 break;
2782 }
2783 default: UNIMPLEMENTED();
2784 }
2785 return int_result;
2786 }
2787
2788
FPToDouble(float value)2789 double Simulator::FPToDouble(float value) {
2790 switch (std::fpclassify(value)) {
2791 case FP_NAN: {
2792 if (fpcr().DN()) return kFP64DefaultNaN;
2793
2794 // Convert NaNs as the processor would:
2795 // - The sign is propagated.
2796 // - The payload (mantissa) is transferred entirely, except that the top
2797 // bit is forced to '1', making the result a quiet NaN. The unused
2798 // (low-order) payload bits are set to 0.
2799 uint32_t raw = float_to_rawbits(value);
2800
2801 uint64_t sign = raw >> 31;
2802 uint64_t exponent = (1 << 11) - 1;
2803 uint64_t payload = unsigned_bitextract_64(21, 0, raw);
2804 payload <<= (52 - 23); // The unused low-order bits should be 0.
2805 payload |= (1L << 51); // Force a quiet NaN.
2806
2807 return rawbits_to_double((sign << 63) | (exponent << 52) | payload);
2808 }
2809
2810 case FP_ZERO:
2811 case FP_NORMAL:
2812 case FP_SUBNORMAL:
2813 case FP_INFINITE: {
2814 // All other inputs are preserved in a standard cast, because every value
2815 // representable using an IEEE-754 float is also representable using an
2816 // IEEE-754 double.
2817 return static_cast<double>(value);
2818 }
2819 }
2820
2821 UNREACHABLE();
2822 return static_cast<double>(value);
2823 }
2824
2825
FPToFloat(double value,FPRounding round_mode)2826 float Simulator::FPToFloat(double value, FPRounding round_mode) {
2827 // Only the FPTieEven rounding mode is implemented.
2828 DCHECK(round_mode == FPTieEven);
2829 USE(round_mode);
2830
2831 switch (std::fpclassify(value)) {
2832 case FP_NAN: {
2833 if (fpcr().DN()) return kFP32DefaultNaN;
2834
2835 // Convert NaNs as the processor would:
2836 // - The sign is propagated.
2837 // - The payload (mantissa) is transferred as much as possible, except
2838 // that the top bit is forced to '1', making the result a quiet NaN.
2839 uint64_t raw = double_to_rawbits(value);
2840
2841 uint32_t sign = raw >> 63;
2842 uint32_t exponent = (1 << 8) - 1;
2843 uint32_t payload =
2844 static_cast<uint32_t>(unsigned_bitextract_64(50, 52 - 23, raw));
2845 payload |= (1 << 22); // Force a quiet NaN.
2846
2847 return rawbits_to_float((sign << 31) | (exponent << 23) | payload);
2848 }
2849
2850 case FP_ZERO:
2851 case FP_INFINITE: {
2852 // In a C++ cast, any value representable in the target type will be
2853 // unchanged. This is always the case for +/-0.0 and infinities.
2854 return static_cast<float>(value);
2855 }
2856
2857 case FP_NORMAL:
2858 case FP_SUBNORMAL: {
2859 // Convert double-to-float as the processor would, assuming that FPCR.FZ
2860 // (flush-to-zero) is not set.
2861 uint64_t raw = double_to_rawbits(value);
2862 // Extract the IEEE-754 double components.
2863 uint32_t sign = raw >> 63;
2864 // Extract the exponent and remove the IEEE-754 encoding bias.
2865 int32_t exponent =
2866 static_cast<int32_t>(unsigned_bitextract_64(62, 52, raw)) - 1023;
2867 // Extract the mantissa and add the implicit '1' bit.
2868 uint64_t mantissa = unsigned_bitextract_64(51, 0, raw);
2869 if (std::fpclassify(value) == FP_NORMAL) {
2870 mantissa |= (1UL << 52);
2871 }
2872 return FPRoundToFloat(sign, exponent, mantissa, round_mode);
2873 }
2874 }
2875
2876 UNREACHABLE();
2877 return value;
2878 }
2879
2880
VisitFPDataProcessing2Source(Instruction * instr)2881 void Simulator::VisitFPDataProcessing2Source(Instruction* instr) {
2882 AssertSupportedFPCR();
2883
2884 unsigned fd = instr->Rd();
2885 unsigned fn = instr->Rn();
2886 unsigned fm = instr->Rm();
2887
2888 // Fmaxnm and Fminnm have special NaN handling.
2889 switch (instr->Mask(FPDataProcessing2SourceMask)) {
2890 case FMAXNM_s: set_sreg(fd, FPMaxNM(sreg(fn), sreg(fm))); return;
2891 case FMAXNM_d: set_dreg(fd, FPMaxNM(dreg(fn), dreg(fm))); return;
2892 case FMINNM_s: set_sreg(fd, FPMinNM(sreg(fn), sreg(fm))); return;
2893 case FMINNM_d: set_dreg(fd, FPMinNM(dreg(fn), dreg(fm))); return;
2894 default:
2895 break; // Fall through.
2896 }
2897
2898 if (FPProcessNaNs(instr)) return;
2899
2900 switch (instr->Mask(FPDataProcessing2SourceMask)) {
2901 case FADD_s: set_sreg(fd, FPAdd(sreg(fn), sreg(fm))); break;
2902 case FADD_d: set_dreg(fd, FPAdd(dreg(fn), dreg(fm))); break;
2903 case FSUB_s: set_sreg(fd, FPSub(sreg(fn), sreg(fm))); break;
2904 case FSUB_d: set_dreg(fd, FPSub(dreg(fn), dreg(fm))); break;
2905 case FMUL_s: set_sreg(fd, FPMul(sreg(fn), sreg(fm))); break;
2906 case FMUL_d: set_dreg(fd, FPMul(dreg(fn), dreg(fm))); break;
2907 case FDIV_s: set_sreg(fd, FPDiv(sreg(fn), sreg(fm))); break;
2908 case FDIV_d: set_dreg(fd, FPDiv(dreg(fn), dreg(fm))); break;
2909 case FMAX_s: set_sreg(fd, FPMax(sreg(fn), sreg(fm))); break;
2910 case FMAX_d: set_dreg(fd, FPMax(dreg(fn), dreg(fm))); break;
2911 case FMIN_s: set_sreg(fd, FPMin(sreg(fn), sreg(fm))); break;
2912 case FMIN_d: set_dreg(fd, FPMin(dreg(fn), dreg(fm))); break;
2913 case FMAXNM_s:
2914 case FMAXNM_d:
2915 case FMINNM_s:
2916 case FMINNM_d:
2917 // These were handled before the standard FPProcessNaNs() stage.
2918 UNREACHABLE();
2919 default: UNIMPLEMENTED();
2920 }
2921 }
2922
2923
VisitFPDataProcessing3Source(Instruction * instr)2924 void Simulator::VisitFPDataProcessing3Source(Instruction* instr) {
2925 AssertSupportedFPCR();
2926
2927 unsigned fd = instr->Rd();
2928 unsigned fn = instr->Rn();
2929 unsigned fm = instr->Rm();
2930 unsigned fa = instr->Ra();
2931
2932 switch (instr->Mask(FPDataProcessing3SourceMask)) {
2933 // fd = fa +/- (fn * fm)
2934 case FMADD_s: set_sreg(fd, FPMulAdd(sreg(fa), sreg(fn), sreg(fm))); break;
2935 case FMSUB_s: set_sreg(fd, FPMulAdd(sreg(fa), -sreg(fn), sreg(fm))); break;
2936 case FMADD_d: set_dreg(fd, FPMulAdd(dreg(fa), dreg(fn), dreg(fm))); break;
2937 case FMSUB_d: set_dreg(fd, FPMulAdd(dreg(fa), -dreg(fn), dreg(fm))); break;
2938 // Negated variants of the above.
2939 case FNMADD_s:
2940 set_sreg(fd, FPMulAdd(-sreg(fa), -sreg(fn), sreg(fm)));
2941 break;
2942 case FNMSUB_s:
2943 set_sreg(fd, FPMulAdd(-sreg(fa), sreg(fn), sreg(fm)));
2944 break;
2945 case FNMADD_d:
2946 set_dreg(fd, FPMulAdd(-dreg(fa), -dreg(fn), dreg(fm)));
2947 break;
2948 case FNMSUB_d:
2949 set_dreg(fd, FPMulAdd(-dreg(fa), dreg(fn), dreg(fm)));
2950 break;
2951 default: UNIMPLEMENTED();
2952 }
2953 }
2954
2955
2956 template <typename T>
FPAdd(T op1,T op2)2957 T Simulator::FPAdd(T op1, T op2) {
2958 // NaNs should be handled elsewhere.
2959 DCHECK(!std::isnan(op1) && !std::isnan(op2));
2960
2961 if (std::isinf(op1) && std::isinf(op2) && (op1 != op2)) {
2962 // inf + -inf returns the default NaN.
2963 return FPDefaultNaN<T>();
2964 } else {
2965 // Other cases should be handled by standard arithmetic.
2966 return op1 + op2;
2967 }
2968 }
2969
2970
2971 template <typename T>
FPDiv(T op1,T op2)2972 T Simulator::FPDiv(T op1, T op2) {
2973 // NaNs should be handled elsewhere.
2974 DCHECK(!std::isnan(op1) && !std::isnan(op2));
2975
2976 if ((std::isinf(op1) && std::isinf(op2)) || ((op1 == 0.0) && (op2 == 0.0))) {
2977 // inf / inf and 0.0 / 0.0 return the default NaN.
2978 return FPDefaultNaN<T>();
2979 } else {
2980 // Other cases should be handled by standard arithmetic.
2981 return op1 / op2;
2982 }
2983 }
2984
2985
2986 template <typename T>
FPMax(T a,T b)2987 T Simulator::FPMax(T a, T b) {
2988 // NaNs should be handled elsewhere.
2989 DCHECK(!std::isnan(a) && !std::isnan(b));
2990
2991 if ((a == 0.0) && (b == 0.0) &&
2992 (copysign(1.0, a) != copysign(1.0, b))) {
2993 // a and b are zero, and the sign differs: return +0.0.
2994 return 0.0;
2995 } else {
2996 return (a > b) ? a : b;
2997 }
2998 }
2999
3000
3001 template <typename T>
FPMaxNM(T a,T b)3002 T Simulator::FPMaxNM(T a, T b) {
3003 if (IsQuietNaN(a) && !IsQuietNaN(b)) {
3004 a = kFP64NegativeInfinity;
3005 } else if (!IsQuietNaN(a) && IsQuietNaN(b)) {
3006 b = kFP64NegativeInfinity;
3007 }
3008
3009 T result = FPProcessNaNs(a, b);
3010 return std::isnan(result) ? result : FPMax(a, b);
3011 }
3012
3013 template <typename T>
FPMin(T a,T b)3014 T Simulator::FPMin(T a, T b) {
3015 // NaNs should be handled elsewhere.
3016 DCHECK(!std::isnan(a) && !std::isnan(b));
3017
3018 if ((a == 0.0) && (b == 0.0) &&
3019 (copysign(1.0, a) != copysign(1.0, b))) {
3020 // a and b are zero, and the sign differs: return -0.0.
3021 return -0.0;
3022 } else {
3023 return (a < b) ? a : b;
3024 }
3025 }
3026
3027
3028 template <typename T>
FPMinNM(T a,T b)3029 T Simulator::FPMinNM(T a, T b) {
3030 if (IsQuietNaN(a) && !IsQuietNaN(b)) {
3031 a = kFP64PositiveInfinity;
3032 } else if (!IsQuietNaN(a) && IsQuietNaN(b)) {
3033 b = kFP64PositiveInfinity;
3034 }
3035
3036 T result = FPProcessNaNs(a, b);
3037 return std::isnan(result) ? result : FPMin(a, b);
3038 }
3039
3040
3041 template <typename T>
FPMul(T op1,T op2)3042 T Simulator::FPMul(T op1, T op2) {
3043 // NaNs should be handled elsewhere.
3044 DCHECK(!std::isnan(op1) && !std::isnan(op2));
3045
3046 if ((std::isinf(op1) && (op2 == 0.0)) || (std::isinf(op2) && (op1 == 0.0))) {
3047 // inf * 0.0 returns the default NaN.
3048 return FPDefaultNaN<T>();
3049 } else {
3050 // Other cases should be handled by standard arithmetic.
3051 return op1 * op2;
3052 }
3053 }
3054
3055
3056 template<typename T>
FPMulAdd(T a,T op1,T op2)3057 T Simulator::FPMulAdd(T a, T op1, T op2) {
3058 T result = FPProcessNaNs3(a, op1, op2);
3059
3060 T sign_a = copysign(1.0, a);
3061 T sign_prod = copysign(1.0, op1) * copysign(1.0, op2);
3062 bool isinf_prod = std::isinf(op1) || std::isinf(op2);
3063 bool operation_generates_nan =
3064 (std::isinf(op1) && (op2 == 0.0)) || // inf * 0.0
3065 (std::isinf(op2) && (op1 == 0.0)) || // 0.0 * inf
3066 (std::isinf(a) && isinf_prod && (sign_a != sign_prod)); // inf - inf
3067
3068 if (std::isnan(result)) {
3069 // Generated NaNs override quiet NaNs propagated from a.
3070 if (operation_generates_nan && IsQuietNaN(a)) {
3071 return FPDefaultNaN<T>();
3072 } else {
3073 return result;
3074 }
3075 }
3076
3077 // If the operation would produce a NaN, return the default NaN.
3078 if (operation_generates_nan) {
3079 return FPDefaultNaN<T>();
3080 }
3081
3082 // Work around broken fma implementations for exact zero results: The sign of
3083 // exact 0.0 results is positive unless both a and op1 * op2 are negative.
3084 if (((op1 == 0.0) || (op2 == 0.0)) && (a == 0.0)) {
3085 return ((sign_a < 0) && (sign_prod < 0)) ? -0.0 : 0.0;
3086 }
3087
3088 result = FusedMultiplyAdd(op1, op2, a);
3089 DCHECK(!std::isnan(result));
3090
3091 // Work around broken fma implementations for rounded zero results: If a is
3092 // 0.0, the sign of the result is the sign of op1 * op2 before rounding.
3093 if ((a == 0.0) && (result == 0.0)) {
3094 return copysign(0.0, sign_prod);
3095 }
3096
3097 return result;
3098 }
3099
3100
3101 template <typename T>
FPSqrt(T op)3102 T Simulator::FPSqrt(T op) {
3103 if (std::isnan(op)) {
3104 return FPProcessNaN(op);
3105 } else if (op < 0.0) {
3106 return FPDefaultNaN<T>();
3107 } else {
3108 lazily_initialize_fast_sqrt(isolate_);
3109 return fast_sqrt(op, isolate_);
3110 }
3111 }
3112
3113
3114 template <typename T>
FPSub(T op1,T op2)3115 T Simulator::FPSub(T op1, T op2) {
3116 // NaNs should be handled elsewhere.
3117 DCHECK(!std::isnan(op1) && !std::isnan(op2));
3118
3119 if (std::isinf(op1) && std::isinf(op2) && (op1 == op2)) {
3120 // inf - inf returns the default NaN.
3121 return FPDefaultNaN<T>();
3122 } else {
3123 // Other cases should be handled by standard arithmetic.
3124 return op1 - op2;
3125 }
3126 }
3127
3128
3129 template <typename T>
FPProcessNaN(T op)3130 T Simulator::FPProcessNaN(T op) {
3131 DCHECK(std::isnan(op));
3132 return fpcr().DN() ? FPDefaultNaN<T>() : ToQuietNaN(op);
3133 }
3134
3135
3136 template <typename T>
FPProcessNaNs(T op1,T op2)3137 T Simulator::FPProcessNaNs(T op1, T op2) {
3138 if (IsSignallingNaN(op1)) {
3139 return FPProcessNaN(op1);
3140 } else if (IsSignallingNaN(op2)) {
3141 return FPProcessNaN(op2);
3142 } else if (std::isnan(op1)) {
3143 DCHECK(IsQuietNaN(op1));
3144 return FPProcessNaN(op1);
3145 } else if (std::isnan(op2)) {
3146 DCHECK(IsQuietNaN(op2));
3147 return FPProcessNaN(op2);
3148 } else {
3149 return 0.0;
3150 }
3151 }
3152
3153
3154 template <typename T>
FPProcessNaNs3(T op1,T op2,T op3)3155 T Simulator::FPProcessNaNs3(T op1, T op2, T op3) {
3156 if (IsSignallingNaN(op1)) {
3157 return FPProcessNaN(op1);
3158 } else if (IsSignallingNaN(op2)) {
3159 return FPProcessNaN(op2);
3160 } else if (IsSignallingNaN(op3)) {
3161 return FPProcessNaN(op3);
3162 } else if (std::isnan(op1)) {
3163 DCHECK(IsQuietNaN(op1));
3164 return FPProcessNaN(op1);
3165 } else if (std::isnan(op2)) {
3166 DCHECK(IsQuietNaN(op2));
3167 return FPProcessNaN(op2);
3168 } else if (std::isnan(op3)) {
3169 DCHECK(IsQuietNaN(op3));
3170 return FPProcessNaN(op3);
3171 } else {
3172 return 0.0;
3173 }
3174 }
3175
3176
FPProcessNaNs(Instruction * instr)3177 bool Simulator::FPProcessNaNs(Instruction* instr) {
3178 unsigned fd = instr->Rd();
3179 unsigned fn = instr->Rn();
3180 unsigned fm = instr->Rm();
3181 bool done = false;
3182
3183 if (instr->Mask(FP64) == FP64) {
3184 double result = FPProcessNaNs(dreg(fn), dreg(fm));
3185 if (std::isnan(result)) {
3186 set_dreg(fd, result);
3187 done = true;
3188 }
3189 } else {
3190 float result = FPProcessNaNs(sreg(fn), sreg(fm));
3191 if (std::isnan(result)) {
3192 set_sreg(fd, result);
3193 done = true;
3194 }
3195 }
3196
3197 return done;
3198 }
3199
3200
VisitSystem(Instruction * instr)3201 void Simulator::VisitSystem(Instruction* instr) {
3202 // Some system instructions hijack their Op and Cp fields to represent a
3203 // range of immediates instead of indicating a different instruction. This
3204 // makes the decoding tricky.
3205 if (instr->Mask(SystemSysRegFMask) == SystemSysRegFixed) {
3206 switch (instr->Mask(SystemSysRegMask)) {
3207 case MRS: {
3208 switch (instr->ImmSystemRegister()) {
3209 case NZCV: set_xreg(instr->Rt(), nzcv().RawValue()); break;
3210 case FPCR: set_xreg(instr->Rt(), fpcr().RawValue()); break;
3211 default: UNIMPLEMENTED();
3212 }
3213 break;
3214 }
3215 case MSR: {
3216 switch (instr->ImmSystemRegister()) {
3217 case NZCV:
3218 nzcv().SetRawValue(wreg(instr->Rt()));
3219 LogSystemRegister(NZCV);
3220 break;
3221 case FPCR:
3222 fpcr().SetRawValue(wreg(instr->Rt()));
3223 LogSystemRegister(FPCR);
3224 break;
3225 default: UNIMPLEMENTED();
3226 }
3227 break;
3228 }
3229 }
3230 } else if (instr->Mask(SystemHintFMask) == SystemHintFixed) {
3231 DCHECK(instr->Mask(SystemHintMask) == HINT);
3232 switch (instr->ImmHint()) {
3233 case NOP: break;
3234 default: UNIMPLEMENTED();
3235 }
3236 } else if (instr->Mask(MemBarrierFMask) == MemBarrierFixed) {
3237 __sync_synchronize();
3238 } else {
3239 UNIMPLEMENTED();
3240 }
3241 }
3242
3243
GetValue(const char * desc,int64_t * value)3244 bool Simulator::GetValue(const char* desc, int64_t* value) {
3245 int regnum = CodeFromName(desc);
3246 if (regnum >= 0) {
3247 unsigned code = regnum;
3248 if (code == kZeroRegCode) {
3249 // Catch the zero register and return 0.
3250 *value = 0;
3251 return true;
3252 } else if (code == kSPRegInternalCode) {
3253 // Translate the stack pointer code to 31, for Reg31IsStackPointer.
3254 code = 31;
3255 }
3256 if (desc[0] == 'w') {
3257 *value = wreg(code, Reg31IsStackPointer);
3258 } else {
3259 *value = xreg(code, Reg31IsStackPointer);
3260 }
3261 return true;
3262 } else if (strncmp(desc, "0x", 2) == 0) {
3263 return SScanF(desc + 2, "%" SCNx64,
3264 reinterpret_cast<uint64_t*>(value)) == 1;
3265 } else {
3266 return SScanF(desc, "%" SCNu64,
3267 reinterpret_cast<uint64_t*>(value)) == 1;
3268 }
3269 }
3270
3271
PrintValue(const char * desc)3272 bool Simulator::PrintValue(const char* desc) {
3273 if (strcmp(desc, "csp") == 0) {
3274 DCHECK(CodeFromName(desc) == static_cast<int>(kSPRegInternalCode));
3275 PrintF(stream_, "%s csp:%s 0x%016" PRIx64 "%s\n",
3276 clr_reg_name, clr_reg_value, xreg(31, Reg31IsStackPointer), clr_normal);
3277 return true;
3278 } else if (strcmp(desc, "wcsp") == 0) {
3279 DCHECK(CodeFromName(desc) == static_cast<int>(kSPRegInternalCode));
3280 PrintF(stream_, "%s wcsp:%s 0x%08" PRIx32 "%s\n",
3281 clr_reg_name, clr_reg_value, wreg(31, Reg31IsStackPointer), clr_normal);
3282 return true;
3283 }
3284
3285 int i = CodeFromName(desc);
3286 STATIC_ASSERT(kNumberOfRegisters == kNumberOfFPRegisters);
3287 if (i < 0 || static_cast<unsigned>(i) >= kNumberOfFPRegisters) return false;
3288
3289 if (desc[0] == 'v') {
3290 PrintF(stream_, "%s %s:%s 0x%016" PRIx64 "%s (%s%s:%s %g%s %s:%s %g%s)\n",
3291 clr_fpreg_name, VRegNameForCode(i),
3292 clr_fpreg_value, double_to_rawbits(dreg(i)),
3293 clr_normal,
3294 clr_fpreg_name, DRegNameForCode(i),
3295 clr_fpreg_value, dreg(i),
3296 clr_fpreg_name, SRegNameForCode(i),
3297 clr_fpreg_value, sreg(i),
3298 clr_normal);
3299 return true;
3300 } else if (desc[0] == 'd') {
3301 PrintF(stream_, "%s %s:%s %g%s\n",
3302 clr_fpreg_name, DRegNameForCode(i),
3303 clr_fpreg_value, dreg(i),
3304 clr_normal);
3305 return true;
3306 } else if (desc[0] == 's') {
3307 PrintF(stream_, "%s %s:%s %g%s\n",
3308 clr_fpreg_name, SRegNameForCode(i),
3309 clr_fpreg_value, sreg(i),
3310 clr_normal);
3311 return true;
3312 } else if (desc[0] == 'w') {
3313 PrintF(stream_, "%s %s:%s 0x%08" PRIx32 "%s\n",
3314 clr_reg_name, WRegNameForCode(i), clr_reg_value, wreg(i), clr_normal);
3315 return true;
3316 } else {
3317 // X register names have a wide variety of starting characters, but anything
3318 // else will be an X register.
3319 PrintF(stream_, "%s %s:%s 0x%016" PRIx64 "%s\n",
3320 clr_reg_name, XRegNameForCode(i), clr_reg_value, xreg(i), clr_normal);
3321 return true;
3322 }
3323 }
3324
3325
Debug()3326 void Simulator::Debug() {
3327 #define COMMAND_SIZE 63
3328 #define ARG_SIZE 255
3329
3330 #define STR(a) #a
3331 #define XSTR(a) STR(a)
3332
3333 char cmd[COMMAND_SIZE + 1];
3334 char arg1[ARG_SIZE + 1];
3335 char arg2[ARG_SIZE + 1];
3336 char* argv[3] = { cmd, arg1, arg2 };
3337
3338 // Make sure to have a proper terminating character if reaching the limit.
3339 cmd[COMMAND_SIZE] = 0;
3340 arg1[ARG_SIZE] = 0;
3341 arg2[ARG_SIZE] = 0;
3342
3343 bool done = false;
3344 bool cleared_log_disasm_bit = false;
3345
3346 while (!done) {
3347 // Disassemble the next instruction to execute before doing anything else.
3348 PrintInstructionsAt(pc_, 1);
3349 // Read the command line.
3350 char* line = ReadLine("sim> ");
3351 if (line == NULL) {
3352 break;
3353 } else {
3354 // Repeat last command by default.
3355 char* last_input = last_debugger_input();
3356 if (strcmp(line, "\n") == 0 && (last_input != NULL)) {
3357 DeleteArray(line);
3358 line = last_input;
3359 } else {
3360 // Update the latest command ran
3361 set_last_debugger_input(line);
3362 }
3363
3364 // Use sscanf to parse the individual parts of the command line. At the
3365 // moment no command expects more than two parameters.
3366 int argc = SScanF(line,
3367 "%" XSTR(COMMAND_SIZE) "s "
3368 "%" XSTR(ARG_SIZE) "s "
3369 "%" XSTR(ARG_SIZE) "s",
3370 cmd, arg1, arg2);
3371
3372 // stepi / si ------------------------------------------------------------
3373 if ((strcmp(cmd, "si") == 0) || (strcmp(cmd, "stepi") == 0)) {
3374 // We are about to execute instructions, after which by default we
3375 // should increment the pc_. If it was set when reaching this debug
3376 // instruction, it has not been cleared because this instruction has not
3377 // completed yet. So clear it manually.
3378 pc_modified_ = false;
3379
3380 if (argc == 1) {
3381 ExecuteInstruction();
3382 } else {
3383 int64_t number_of_instructions_to_execute = 1;
3384 GetValue(arg1, &number_of_instructions_to_execute);
3385
3386 set_log_parameters(log_parameters() | LOG_DISASM);
3387 while (number_of_instructions_to_execute-- > 0) {
3388 ExecuteInstruction();
3389 }
3390 set_log_parameters(log_parameters() & ~LOG_DISASM);
3391 PrintF("\n");
3392 }
3393
3394 // If it was necessary, the pc has already been updated or incremented
3395 // when executing the instruction. So we do not want it to be updated
3396 // again. It will be cleared when exiting.
3397 pc_modified_ = true;
3398
3399 // next / n --------------------------------------------------------------
3400 } else if ((strcmp(cmd, "next") == 0) || (strcmp(cmd, "n") == 0)) {
3401 // Tell the simulator to break after the next executed BL.
3402 break_on_next_ = true;
3403 // Continue.
3404 done = true;
3405
3406 // continue / cont / c ---------------------------------------------------
3407 } else if ((strcmp(cmd, "continue") == 0) ||
3408 (strcmp(cmd, "cont") == 0) ||
3409 (strcmp(cmd, "c") == 0)) {
3410 // Leave the debugger shell.
3411 done = true;
3412
3413 // disassemble / disasm / di ---------------------------------------------
3414 } else if (strcmp(cmd, "disassemble") == 0 ||
3415 strcmp(cmd, "disasm") == 0 ||
3416 strcmp(cmd, "di") == 0) {
3417 int64_t n_of_instrs_to_disasm = 10; // default value.
3418 int64_t address = reinterpret_cast<int64_t>(pc_); // default value.
3419 if (argc >= 2) { // disasm <n of instrs>
3420 GetValue(arg1, &n_of_instrs_to_disasm);
3421 }
3422 if (argc >= 3) { // disasm <n of instrs> <address>
3423 GetValue(arg2, &address);
3424 }
3425
3426 // Disassemble.
3427 PrintInstructionsAt(reinterpret_cast<Instruction*>(address),
3428 n_of_instrs_to_disasm);
3429 PrintF("\n");
3430
3431 // print / p -------------------------------------------------------------
3432 } else if ((strcmp(cmd, "print") == 0) || (strcmp(cmd, "p") == 0)) {
3433 if (argc == 2) {
3434 if (strcmp(arg1, "all") == 0) {
3435 PrintRegisters();
3436 PrintFPRegisters();
3437 } else {
3438 if (!PrintValue(arg1)) {
3439 PrintF("%s unrecognized\n", arg1);
3440 }
3441 }
3442 } else {
3443 PrintF(
3444 "print <register>\n"
3445 " Print the content of a register. (alias 'p')\n"
3446 " 'print all' will print all registers.\n"
3447 " Use 'printobject' to get more details about the value.\n");
3448 }
3449
3450 // printobject / po ------------------------------------------------------
3451 } else if ((strcmp(cmd, "printobject") == 0) ||
3452 (strcmp(cmd, "po") == 0)) {
3453 if (argc == 2) {
3454 int64_t value;
3455 OFStream os(stdout);
3456 if (GetValue(arg1, &value)) {
3457 Object* obj = reinterpret_cast<Object*>(value);
3458 os << arg1 << ": \n";
3459 #ifdef DEBUG
3460 obj->Print(os);
3461 os << "\n";
3462 #else
3463 os << Brief(obj) << "\n";
3464 #endif
3465 } else {
3466 os << arg1 << " unrecognized\n";
3467 }
3468 } else {
3469 PrintF("printobject <value>\n"
3470 "printobject <register>\n"
3471 " Print details about the value. (alias 'po')\n");
3472 }
3473
3474 // stack / mem ----------------------------------------------------------
3475 } else if (strcmp(cmd, "stack") == 0 || strcmp(cmd, "mem") == 0) {
3476 int64_t* cur = NULL;
3477 int64_t* end = NULL;
3478 int next_arg = 1;
3479
3480 if (strcmp(cmd, "stack") == 0) {
3481 cur = reinterpret_cast<int64_t*>(jssp());
3482
3483 } else { // "mem"
3484 int64_t value;
3485 if (!GetValue(arg1, &value)) {
3486 PrintF("%s unrecognized\n", arg1);
3487 continue;
3488 }
3489 cur = reinterpret_cast<int64_t*>(value);
3490 next_arg++;
3491 }
3492
3493 int64_t words = 0;
3494 if (argc == next_arg) {
3495 words = 10;
3496 } else if (argc == next_arg + 1) {
3497 if (!GetValue(argv[next_arg], &words)) {
3498 PrintF("%s unrecognized\n", argv[next_arg]);
3499 PrintF("Printing 10 double words by default");
3500 words = 10;
3501 }
3502 } else {
3503 UNREACHABLE();
3504 }
3505 end = cur + words;
3506
3507 while (cur < end) {
3508 PrintF(" 0x%016" PRIx64 ": 0x%016" PRIx64 " %10" PRId64,
3509 reinterpret_cast<uint64_t>(cur), *cur, *cur);
3510 HeapObject* obj = reinterpret_cast<HeapObject*>(*cur);
3511 int64_t value = *cur;
3512 Heap* current_heap = isolate_->heap();
3513 if (((value & 1) == 0) || current_heap->Contains(obj)) {
3514 PrintF(" (");
3515 if ((value & kSmiTagMask) == 0) {
3516 STATIC_ASSERT(kSmiValueSize == 32);
3517 int32_t untagged = (value >> kSmiShift) & 0xffffffff;
3518 PrintF("smi %" PRId32, untagged);
3519 } else {
3520 obj->ShortPrint();
3521 }
3522 PrintF(")");
3523 }
3524 PrintF("\n");
3525 cur++;
3526 }
3527
3528 // trace / t -------------------------------------------------------------
3529 } else if (strcmp(cmd, "trace") == 0 || strcmp(cmd, "t") == 0) {
3530 if ((log_parameters() & (LOG_DISASM | LOG_REGS)) !=
3531 (LOG_DISASM | LOG_REGS)) {
3532 PrintF("Enabling disassembly and registers tracing\n");
3533 set_log_parameters(log_parameters() | LOG_DISASM | LOG_REGS);
3534 } else {
3535 PrintF("Disabling disassembly and registers tracing\n");
3536 set_log_parameters(log_parameters() & ~(LOG_DISASM | LOG_REGS));
3537 }
3538
3539 // break / b -------------------------------------------------------------
3540 } else if (strcmp(cmd, "break") == 0 || strcmp(cmd, "b") == 0) {
3541 if (argc == 2) {
3542 int64_t value;
3543 if (GetValue(arg1, &value)) {
3544 SetBreakpoint(reinterpret_cast<Instruction*>(value));
3545 } else {
3546 PrintF("%s unrecognized\n", arg1);
3547 }
3548 } else {
3549 ListBreakpoints();
3550 PrintF("Use `break <address>` to set or disable a breakpoint\n");
3551 }
3552
3553 // gdb -------------------------------------------------------------------
3554 } else if (strcmp(cmd, "gdb") == 0) {
3555 PrintF("Relinquishing control to gdb.\n");
3556 base::OS::DebugBreak();
3557 PrintF("Regaining control from gdb.\n");
3558
3559 // sysregs ---------------------------------------------------------------
3560 } else if (strcmp(cmd, "sysregs") == 0) {
3561 PrintSystemRegisters();
3562
3563 // help / h --------------------------------------------------------------
3564 } else if (strcmp(cmd, "help") == 0 || strcmp(cmd, "h") == 0) {
3565 PrintF(
3566 "stepi / si\n"
3567 " stepi <n>\n"
3568 " Step <n> instructions.\n"
3569 "next / n\n"
3570 " Continue execution until a BL instruction is reached.\n"
3571 " At this point a breakpoint is set just after this BL.\n"
3572 " Then execution is resumed. It will probably later hit the\n"
3573 " breakpoint just set.\n"
3574 "continue / cont / c\n"
3575 " Continue execution from here.\n"
3576 "disassemble / disasm / di\n"
3577 " disassemble <n> <address>\n"
3578 " Disassemble <n> instructions from current <address>.\n"
3579 " By default <n> is 20 and <address> is the current pc.\n"
3580 "print / p\n"
3581 " print <register>\n"
3582 " Print the content of a register.\n"
3583 " 'print all' will print all registers.\n"
3584 " Use 'printobject' to get more details about the value.\n"
3585 "printobject / po\n"
3586 " printobject <value>\n"
3587 " printobject <register>\n"
3588 " Print details about the value.\n"
3589 "stack\n"
3590 " stack [<words>]\n"
3591 " Dump stack content, default dump 10 words\n"
3592 "mem\n"
3593 " mem <address> [<words>]\n"
3594 " Dump memory content, default dump 10 words\n"
3595 "trace / t\n"
3596 " Toggle disassembly and register tracing\n"
3597 "break / b\n"
3598 " break : list all breakpoints\n"
3599 " break <address> : set / enable / disable a breakpoint.\n"
3600 "gdb\n"
3601 " Enter gdb.\n"
3602 "sysregs\n"
3603 " Print all system registers (including NZCV).\n");
3604 } else {
3605 PrintF("Unknown command: %s\n", cmd);
3606 PrintF("Use 'help' for more information.\n");
3607 }
3608 }
3609 if (cleared_log_disasm_bit == true) {
3610 set_log_parameters(log_parameters_ | LOG_DISASM);
3611 }
3612 }
3613 }
3614
3615
VisitException(Instruction * instr)3616 void Simulator::VisitException(Instruction* instr) {
3617 switch (instr->Mask(ExceptionMask)) {
3618 case HLT: {
3619 if (instr->ImmException() == kImmExceptionIsDebug) {
3620 // Read the arguments encoded inline in the instruction stream.
3621 uint32_t code;
3622 uint32_t parameters;
3623
3624 memcpy(&code,
3625 pc_->InstructionAtOffset(kDebugCodeOffset),
3626 sizeof(code));
3627 memcpy(¶meters,
3628 pc_->InstructionAtOffset(kDebugParamsOffset),
3629 sizeof(parameters));
3630 char const *message =
3631 reinterpret_cast<char const*>(
3632 pc_->InstructionAtOffset(kDebugMessageOffset));
3633
3634 // Always print something when we hit a debug point that breaks.
3635 // We are going to break, so printing something is not an issue in
3636 // terms of speed.
3637 if (FLAG_trace_sim_messages || FLAG_trace_sim || (parameters & BREAK)) {
3638 if (message != NULL) {
3639 PrintF(stream_,
3640 "# %sDebugger hit %d: %s%s%s\n",
3641 clr_debug_number,
3642 code,
3643 clr_debug_message,
3644 message,
3645 clr_normal);
3646 } else {
3647 PrintF(stream_,
3648 "# %sDebugger hit %d.%s\n",
3649 clr_debug_number,
3650 code,
3651 clr_normal);
3652 }
3653 }
3654
3655 // Other options.
3656 switch (parameters & kDebuggerTracingDirectivesMask) {
3657 case TRACE_ENABLE:
3658 set_log_parameters(log_parameters() | parameters);
3659 if (parameters & LOG_SYS_REGS) { PrintSystemRegisters(); }
3660 if (parameters & LOG_REGS) { PrintRegisters(); }
3661 if (parameters & LOG_FP_REGS) { PrintFPRegisters(); }
3662 break;
3663 case TRACE_DISABLE:
3664 set_log_parameters(log_parameters() & ~parameters);
3665 break;
3666 case TRACE_OVERRIDE:
3667 set_log_parameters(parameters);
3668 break;
3669 default:
3670 // We don't support a one-shot LOG_DISASM.
3671 DCHECK((parameters & LOG_DISASM) == 0);
3672 // Don't print information that is already being traced.
3673 parameters &= ~log_parameters();
3674 // Print the requested information.
3675 if (parameters & LOG_SYS_REGS) PrintSystemRegisters();
3676 if (parameters & LOG_REGS) PrintRegisters();
3677 if (parameters & LOG_FP_REGS) PrintFPRegisters();
3678 }
3679
3680 // The stop parameters are inlined in the code. Skip them:
3681 // - Skip to the end of the message string.
3682 size_t size = kDebugMessageOffset + strlen(message) + 1;
3683 pc_ = pc_->InstructionAtOffset(RoundUp(size, kInstructionSize));
3684 // - Verify that the unreachable marker is present.
3685 DCHECK(pc_->Mask(ExceptionMask) == HLT);
3686 DCHECK(pc_->ImmException() == kImmExceptionIsUnreachable);
3687 // - Skip past the unreachable marker.
3688 set_pc(pc_->following());
3689
3690 // Check if the debugger should break.
3691 if (parameters & BREAK) Debug();
3692
3693 } else if (instr->ImmException() == kImmExceptionIsRedirectedCall) {
3694 DoRuntimeCall(instr);
3695 } else if (instr->ImmException() == kImmExceptionIsPrintf) {
3696 DoPrintf(instr);
3697
3698 } else if (instr->ImmException() == kImmExceptionIsUnreachable) {
3699 fprintf(stream_, "Hit UNREACHABLE marker at PC=%p.\n",
3700 reinterpret_cast<void*>(pc_));
3701 abort();
3702
3703 } else {
3704 base::OS::DebugBreak();
3705 }
3706 break;
3707 }
3708
3709 default:
3710 UNIMPLEMENTED();
3711 }
3712 }
3713
3714
DoPrintf(Instruction * instr)3715 void Simulator::DoPrintf(Instruction* instr) {
3716 DCHECK((instr->Mask(ExceptionMask) == HLT) &&
3717 (instr->ImmException() == kImmExceptionIsPrintf));
3718
3719 // Read the arguments encoded inline in the instruction stream.
3720 uint32_t arg_count;
3721 uint32_t arg_pattern_list;
3722 STATIC_ASSERT(sizeof(*instr) == 1);
3723 memcpy(&arg_count,
3724 instr + kPrintfArgCountOffset,
3725 sizeof(arg_count));
3726 memcpy(&arg_pattern_list,
3727 instr + kPrintfArgPatternListOffset,
3728 sizeof(arg_pattern_list));
3729
3730 DCHECK(arg_count <= kPrintfMaxArgCount);
3731 DCHECK((arg_pattern_list >> (kPrintfArgPatternBits * arg_count)) == 0);
3732
3733 // We need to call the host printf function with a set of arguments defined by
3734 // arg_pattern_list. Because we don't know the types and sizes of the
3735 // arguments, this is very difficult to do in a robust and portable way. To
3736 // work around the problem, we pick apart the format string, and print one
3737 // format placeholder at a time.
3738
3739 // Allocate space for the format string. We take a copy, so we can modify it.
3740 // Leave enough space for one extra character per expected argument (plus the
3741 // '\0' termination).
3742 const char * format_base = reg<const char *>(0);
3743 DCHECK(format_base != NULL);
3744 size_t length = strlen(format_base) + 1;
3745 char * const format = new char[length + arg_count];
3746
3747 // A list of chunks, each with exactly one format placeholder.
3748 const char * chunks[kPrintfMaxArgCount];
3749
3750 // Copy the format string and search for format placeholders.
3751 uint32_t placeholder_count = 0;
3752 char * format_scratch = format;
3753 for (size_t i = 0; i < length; i++) {
3754 if (format_base[i] != '%') {
3755 *format_scratch++ = format_base[i];
3756 } else {
3757 if (format_base[i + 1] == '%') {
3758 // Ignore explicit "%%" sequences.
3759 *format_scratch++ = format_base[i];
3760
3761 if (placeholder_count == 0) {
3762 // The first chunk is passed to printf using "%s", so we need to
3763 // unescape "%%" sequences in this chunk. (Just skip the next '%'.)
3764 i++;
3765 } else {
3766 // Otherwise, pass through "%%" unchanged.
3767 *format_scratch++ = format_base[++i];
3768 }
3769 } else {
3770 CHECK(placeholder_count < arg_count);
3771 // Insert '\0' before placeholders, and store their locations.
3772 *format_scratch++ = '\0';
3773 chunks[placeholder_count++] = format_scratch;
3774 *format_scratch++ = format_base[i];
3775 }
3776 }
3777 }
3778 DCHECK(format_scratch <= (format + length + arg_count));
3779 CHECK(placeholder_count == arg_count);
3780
3781 // Finally, call printf with each chunk, passing the appropriate register
3782 // argument. Normally, printf returns the number of bytes transmitted, so we
3783 // can emulate a single printf call by adding the result from each chunk. If
3784 // any call returns a negative (error) value, though, just return that value.
3785
3786 fprintf(stream_, "%s", clr_printf);
3787
3788 // Because '\0' is inserted before each placeholder, the first string in
3789 // 'format' contains no format placeholders and should be printed literally.
3790 int result = fprintf(stream_, "%s", format);
3791 int pcs_r = 1; // Start at x1. x0 holds the format string.
3792 int pcs_f = 0; // Start at d0.
3793 if (result >= 0) {
3794 for (uint32_t i = 0; i < placeholder_count; i++) {
3795 int part_result = -1;
3796
3797 uint32_t arg_pattern = arg_pattern_list >> (i * kPrintfArgPatternBits);
3798 arg_pattern &= (1 << kPrintfArgPatternBits) - 1;
3799 switch (arg_pattern) {
3800 case kPrintfArgW:
3801 part_result = fprintf(stream_, chunks[i], wreg(pcs_r++));
3802 break;
3803 case kPrintfArgX:
3804 part_result = fprintf(stream_, chunks[i], xreg(pcs_r++));
3805 break;
3806 case kPrintfArgD:
3807 part_result = fprintf(stream_, chunks[i], dreg(pcs_f++));
3808 break;
3809 default: UNREACHABLE();
3810 }
3811
3812 if (part_result < 0) {
3813 // Handle error values.
3814 result = part_result;
3815 break;
3816 }
3817
3818 result += part_result;
3819 }
3820 }
3821
3822 fprintf(stream_, "%s", clr_normal);
3823
3824 #ifdef DEBUG
3825 CorruptAllCallerSavedCPURegisters();
3826 #endif
3827
3828 // Printf returns its result in x0 (just like the C library's printf).
3829 set_xreg(0, result);
3830
3831 // The printf parameters are inlined in the code, so skip them.
3832 set_pc(instr->InstructionAtOffset(kPrintfLength));
3833
3834 // Set LR as if we'd just called a native printf function.
3835 set_lr(pc());
3836
3837 delete[] format;
3838 }
3839
3840
3841 #endif // USE_SIMULATOR
3842
3843 } // namespace internal
3844 } // namespace v8
3845
3846 #endif // V8_TARGET_ARCH_ARM64
3847