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