Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(205)

Side by Side Diff: src/a64/simulator-a64.cc

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

Powered by Google App Engine
This is Rietveld 408576698