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