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