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