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

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

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