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

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

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