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

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

Issue 422063005: Contribution of PowerPC port. (Closed) Base URL: http://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: re-upload - catch up to 8/19 level Created 6 years, 3 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
OLDNEW
(Empty)
1 // Copyright 2012 the V8 project authors. All rights reserved.
2 //
3 // Copyright IBM Corp. 2012, 2013. All rights reserved.
4 //
5 // Use of this source code is governed by a BSD-style license that can be
6 // found in the LICENSE file.
7
8 #include <stdarg.h>
9 #include <stdlib.h>
10 #include <cmath>
11
12 #include "src/v8.h"
13
14 #if V8_TARGET_ARCH_PPC
15
16 #include "src/assembler.h"
17 #include "src/codegen.h"
18 #include "src/disasm.h"
19 #include "src/ppc/constants-ppc.h"
20 #include "src/ppc/frames-ppc.h"
21 #include "src/ppc/simulator-ppc.h"
22
23 #if defined(USE_SIMULATOR)
24
25 // Only build the simulator if not compiling for real PPC hardware.
26 namespace v8 {
27 namespace internal {
28
29 // This macro provides a platform independent use of sscanf. The reason for
30 // SScanF not being implemented in a platform independent way through
31 // ::v8::internal::OS in the same way as SNPrintF is that the
32 // Windows C Run-Time Library does not provide vsscanf.
33 #define SScanF sscanf // NOLINT
34
35 // The PPCDebugger class is used by the simulator while debugging simulated
36 // PowerPC code.
37 class PPCDebugger {
38 public:
39 explicit PPCDebugger(Simulator* sim) : sim_(sim) {}
40 ~PPCDebugger();
41
42 void Stop(Instruction* instr);
43 void Info(Instruction* instr);
44 void Debug();
45
46 private:
47 static const Instr kBreakpointInstr = (TWI | 0x1f * B21);
48 static const Instr kNopInstr = (ORI); // ori, 0,0,0
49
50 Simulator* sim_;
51
52 intptr_t GetRegisterValue(int regnum);
53 double GetRegisterPairDoubleValue(int regnum);
54 double GetFPDoubleRegisterValue(int regnum);
55 bool GetValue(const char* desc, intptr_t* value);
56 bool GetFPDoubleValue(const char* desc, double* value);
57
58 // Set or delete a breakpoint. Returns true if successful.
59 bool SetBreakpoint(Instruction* break_pc);
60 bool DeleteBreakpoint(Instruction* break_pc);
61
62 // Undo and redo all breakpoints. This is needed to bracket disassembly and
63 // execution to skip past breakpoints when run from the debugger.
64 void UndoBreakpoints();
65 void RedoBreakpoints();
66 };
67
68
69 PPCDebugger::~PPCDebugger() {}
70
71
72 #ifdef GENERATED_CODE_COVERAGE
73 static FILE* coverage_log = NULL;
74
75
76 static void InitializeCoverage() {
77 char* file_name = getenv("V8_GENERATED_CODE_COVERAGE_LOG");
78 if (file_name != NULL) {
79 coverage_log = fopen(file_name, "aw+");
80 }
81 }
82
83
84 void PPCDebugger::Stop(Instruction* instr) { // roohack need to fix for PPC
85 // Get the stop code.
86 uint32_t code = instr->SvcValue() & kStopCodeMask;
87 // Retrieve the encoded address, which comes just after this stop.
88 char** msg_address =
89 reinterpret_cast<char**>(sim_->get_pc() + Instruction::kInstrSize);
90 char* msg = *msg_address;
91 DCHECK(msg != NULL);
92
93 // Update this stop description.
94 if (isWatchedStop(code) && !watched_stops_[code].desc) {
95 watched_stops_[code].desc = msg;
96 }
97
98 if (strlen(msg) > 0) {
99 if (coverage_log != NULL) {
100 fprintf(coverage_log, "%s\n", msg);
101 fflush(coverage_log);
102 }
103 // Overwrite the instruction and address with nops.
104 instr->SetInstructionBits(kNopInstr);
105 reinterpret_cast<Instruction*>(msg_address)->SetInstructionBits(kNopInstr);
106 }
107 sim_->set_pc(sim_->get_pc() + Instruction::kInstrSize + kPointerSize);
108 }
109
110 #else // ndef GENERATED_CODE_COVERAGE
111
112 static void InitializeCoverage() {}
113
114
115 void PPCDebugger::Stop(Instruction* instr) {
116 // Get the stop code.
117 // use of kStopCodeMask not right on PowerPC
118 uint32_t code = instr->SvcValue() & kStopCodeMask;
119 // Retrieve the encoded address, which comes just after this stop.
120 char* msg =
121 *reinterpret_cast<char**>(sim_->get_pc() + Instruction::kInstrSize);
122 // Update this stop description.
123 if (sim_->isWatchedStop(code) && !sim_->watched_stops_[code].desc) {
124 sim_->watched_stops_[code].desc = msg;
125 }
126 // Print the stop message and code if it is not the default code.
127 if (code != kMaxStopCode) {
128 PrintF("Simulator hit stop %u: %s\n", code, msg);
129 } else {
130 PrintF("Simulator hit %s\n", msg);
131 }
132 sim_->set_pc(sim_->get_pc() + Instruction::kInstrSize + kPointerSize);
133 Debug();
134 }
135 #endif
136
137
138 void PPCDebugger::Info(Instruction* instr) {
139 // Retrieve the encoded address immediately following the Info breakpoint.
140 char* msg =
141 *reinterpret_cast<char**>(sim_->get_pc() + Instruction::kInstrSize);
142 PrintF("Simulator info %s\n", msg);
143 sim_->set_pc(sim_->get_pc() + Instruction::kInstrSize + kPointerSize);
144 }
145
146
147 intptr_t PPCDebugger::GetRegisterValue(int regnum) {
148 return sim_->get_register(regnum);
149 }
150
151
152 double PPCDebugger::GetRegisterPairDoubleValue(int regnum) {
153 return sim_->get_double_from_register_pair(regnum);
154 }
155
156
157 double PPCDebugger::GetFPDoubleRegisterValue(int regnum) {
158 return sim_->get_double_from_d_register(regnum);
159 }
160
161
162 bool PPCDebugger::GetValue(const char* desc, intptr_t* value) {
163 int regnum = Registers::Number(desc);
164 if (regnum != kNoRegister) {
165 *value = GetRegisterValue(regnum);
166 return true;
167 } else {
168 if (strncmp(desc, "0x", 2) == 0) {
169 return SScanF(desc + 2, "%" V8PRIxPTR,
170 reinterpret_cast<uintptr_t*>(value)) == 1;
171 } else {
172 return SScanF(desc, "%" V8PRIuPTR, reinterpret_cast<uintptr_t*>(value)) ==
173 1;
174 }
175 }
176 return false;
177 }
178
179
180 bool PPCDebugger::GetFPDoubleValue(const char* desc, double* value) {
181 int regnum = FPRegisters::Number(desc);
182 if (regnum != kNoRegister) {
183 *value = sim_->get_double_from_d_register(regnum);
184 return true;
185 }
186 return false;
187 }
188
189
190 bool PPCDebugger::SetBreakpoint(Instruction* break_pc) {
191 // Check if a breakpoint can be set. If not return without any side-effects.
192 if (sim_->break_pc_ != NULL) {
193 return false;
194 }
195
196 // Set the breakpoint.
197 sim_->break_pc_ = break_pc;
198 sim_->break_instr_ = break_pc->InstructionBits();
199 // Not setting the breakpoint instruction in the code itself. It will be set
200 // when the debugger shell continues.
201 return true;
202 }
203
204
205 bool PPCDebugger::DeleteBreakpoint(Instruction* break_pc) {
206 if (sim_->break_pc_ != NULL) {
207 sim_->break_pc_->SetInstructionBits(sim_->break_instr_);
208 }
209
210 sim_->break_pc_ = NULL;
211 sim_->break_instr_ = 0;
212 return true;
213 }
214
215
216 void PPCDebugger::UndoBreakpoints() {
217 if (sim_->break_pc_ != NULL) {
218 sim_->break_pc_->SetInstructionBits(sim_->break_instr_);
219 }
220 }
221
222
223 void PPCDebugger::RedoBreakpoints() {
224 if (sim_->break_pc_ != NULL) {
225 sim_->break_pc_->SetInstructionBits(kBreakpointInstr);
226 }
227 }
228
229
230 void PPCDebugger::Debug() {
231 intptr_t last_pc = -1;
232 bool done = false;
233
234 #define COMMAND_SIZE 63
235 #define ARG_SIZE 255
236
237 #define STR(a) #a
238 #define XSTR(a) STR(a)
239
240 char cmd[COMMAND_SIZE + 1];
241 char arg1[ARG_SIZE + 1];
242 char arg2[ARG_SIZE + 1];
243 char* argv[3] = {cmd, arg1, arg2};
244
245 // make sure to have a proper terminating character if reaching the limit
246 cmd[COMMAND_SIZE] = 0;
247 arg1[ARG_SIZE] = 0;
248 arg2[ARG_SIZE] = 0;
249
250 // Undo all set breakpoints while running in the debugger shell. This will
251 // make them invisible to all commands.
252 UndoBreakpoints();
253 // Disable tracing while simulating
254 bool trace = ::v8::internal::FLAG_trace_sim;
255 ::v8::internal::FLAG_trace_sim = false;
256
257 while (!done && !sim_->has_bad_pc()) {
258 if (last_pc != sim_->get_pc()) {
259 disasm::NameConverter converter;
260 disasm::Disassembler dasm(converter);
261 // use a reasonably large buffer
262 v8::internal::EmbeddedVector<char, 256> buffer;
263 dasm.InstructionDecode(buffer, reinterpret_cast<byte*>(sim_->get_pc()));
264 PrintF(" 0x%08" V8PRIxPTR " %s\n", sim_->get_pc(), buffer.start());
265 last_pc = sim_->get_pc();
266 }
267 char* line = ReadLine("sim> ");
268 if (line == NULL) {
269 break;
270 } else {
271 char* last_input = sim_->last_debugger_input();
272 if (strcmp(line, "\n") == 0 && last_input != NULL) {
273 line = last_input;
274 } else {
275 // Ownership is transferred to sim_;
276 sim_->set_last_debugger_input(line);
277 }
278 // Use sscanf to parse the individual parts of the command line. At the
279 // moment no command expects more than two parameters.
280 int argc = SScanF(line,
281 "%" XSTR(COMMAND_SIZE) "s "
282 "%" XSTR(ARG_SIZE) "s "
283 "%" XSTR(ARG_SIZE) "s",
284 cmd, arg1, arg2);
285 if ((strcmp(cmd, "si") == 0) || (strcmp(cmd, "stepi") == 0)) {
286 intptr_t value;
287
288 // If at a breakpoint, proceed past it.
289 if ((reinterpret_cast<Instruction*>(sim_->get_pc()))
290 ->InstructionBits() == 0x7d821008) {
291 sim_->set_pc(sim_->get_pc() + Instruction::kInstrSize);
292 } else {
293 sim_->ExecuteInstruction(
294 reinterpret_cast<Instruction*>(sim_->get_pc()));
295 }
296
297 if (argc == 2 && last_pc != sim_->get_pc() && GetValue(arg1, &value)) {
298 for (int i = 1; i < value; i++) {
299 disasm::NameConverter converter;
300 disasm::Disassembler dasm(converter);
301 // use a reasonably large buffer
302 v8::internal::EmbeddedVector<char, 256> buffer;
303 dasm.InstructionDecode(buffer,
304 reinterpret_cast<byte*>(sim_->get_pc()));
305 PrintF(" 0x%08" V8PRIxPTR " %s\n", sim_->get_pc(),
306 buffer.start());
307 sim_->ExecuteInstruction(
308 reinterpret_cast<Instruction*>(sim_->get_pc()));
309 }
310 }
311 } else if ((strcmp(cmd, "c") == 0) || (strcmp(cmd, "cont") == 0)) {
312 // If at a breakpoint, proceed past it.
313 if ((reinterpret_cast<Instruction*>(sim_->get_pc()))
314 ->InstructionBits() == 0x7d821008) {
315 sim_->set_pc(sim_->get_pc() + Instruction::kInstrSize);
316 } else {
317 // Execute the one instruction we broke at with breakpoints disabled.
318 sim_->ExecuteInstruction(
319 reinterpret_cast<Instruction*>(sim_->get_pc()));
320 }
321 // Leave the debugger shell.
322 done = true;
323 } else if ((strcmp(cmd, "p") == 0) || (strcmp(cmd, "print") == 0)) {
324 if (argc == 2 || (argc == 3 && strcmp(arg2, "fp") == 0)) {
325 intptr_t value;
326 double dvalue;
327 if (strcmp(arg1, "all") == 0) {
328 for (int i = 0; i < kNumRegisters; i++) {
329 value = GetRegisterValue(i);
330 PrintF(" %3s: %08" V8PRIxPTR, Registers::Name(i), value);
331 if ((argc == 3 && strcmp(arg2, "fp") == 0) && i < 8 &&
332 (i % 2) == 0) {
333 dvalue = GetRegisterPairDoubleValue(i);
334 PrintF(" (%f)\n", dvalue);
335 } else if (i != 0 && !((i + 1) & 3)) {
336 PrintF("\n");
337 }
338 }
339 PrintF(" pc: %08" V8PRIxPTR " lr: %08" V8PRIxPTR
340 " "
341 "ctr: %08" V8PRIxPTR " xer: %08x cr: %08x\n",
342 sim_->special_reg_pc_, sim_->special_reg_lr_,
343 sim_->special_reg_ctr_, sim_->special_reg_xer_,
344 sim_->condition_reg_);
345 } else if (strcmp(arg1, "alld") == 0) {
346 for (int i = 0; i < kNumRegisters; i++) {
347 value = GetRegisterValue(i);
348 PrintF(" %3s: %08" V8PRIxPTR " %11" V8PRIdPTR,
349 Registers::Name(i), value, value);
350 if ((argc == 3 && strcmp(arg2, "fp") == 0) && i < 8 &&
351 (i % 2) == 0) {
352 dvalue = GetRegisterPairDoubleValue(i);
353 PrintF(" (%f)\n", dvalue);
354 } else if (!((i + 1) % 2)) {
355 PrintF("\n");
356 }
357 }
358 PrintF(" pc: %08" V8PRIxPTR " lr: %08" V8PRIxPTR
359 " "
360 "ctr: %08" V8PRIxPTR " xer: %08x cr: %08x\n",
361 sim_->special_reg_pc_, sim_->special_reg_lr_,
362 sim_->special_reg_ctr_, sim_->special_reg_xer_,
363 sim_->condition_reg_);
364 } else if (strcmp(arg1, "allf") == 0) {
365 for (int i = 0; i < DoubleRegister::kNumRegisters; i++) {
366 dvalue = GetFPDoubleRegisterValue(i);
367 uint64_t as_words = BitCast<uint64_t>(dvalue);
368 PrintF("%3s: %f 0x%08x %08x\n", FPRegisters::Name(i), dvalue,
369 static_cast<uint32_t>(as_words >> 32),
370 static_cast<uint32_t>(as_words & 0xffffffff));
371 }
372 } else if (arg1[0] == 'r' &&
373 (arg1[1] >= '0' && arg1[1] <= '9' &&
374 (arg1[2] == '\0' || (arg1[2] >= '0' && arg1[2] <= '9' &&
375 arg1[3] == '\0')))) {
376 int regnum = strtoul(&arg1[1], 0, 10);
377 if (regnum != kNoRegister) {
378 value = GetRegisterValue(regnum);
379 PrintF("%s: 0x%08" V8PRIxPTR " %" V8PRIdPTR "\n", arg1, value,
380 value);
381 } else {
382 PrintF("%s unrecognized\n", arg1);
383 }
384 } else {
385 if (GetValue(arg1, &value)) {
386 PrintF("%s: 0x%08" V8PRIxPTR " %" V8PRIdPTR "\n", arg1, value,
387 value);
388 } else if (GetFPDoubleValue(arg1, &dvalue)) {
389 uint64_t as_words = BitCast<uint64_t>(dvalue);
390 PrintF("%s: %f 0x%08x %08x\n", arg1, dvalue,
391 static_cast<uint32_t>(as_words >> 32),
392 static_cast<uint32_t>(as_words & 0xffffffff));
393 } else {
394 PrintF("%s unrecognized\n", arg1);
395 }
396 }
397 } else {
398 PrintF("print <register>\n");
399 }
400 } else if ((strcmp(cmd, "po") == 0) ||
401 (strcmp(cmd, "printobject") == 0)) {
402 if (argc == 2) {
403 intptr_t value;
404 OFStream os(stdout);
405 if (GetValue(arg1, &value)) {
406 Object* obj = reinterpret_cast<Object*>(value);
407 os << arg1 << ": \n";
408 #ifdef DEBUG
409 obj->Print(os);
410 os << "\n";
411 #else
412 os << Brief(obj) << "\n";
413 #endif
414 } else {
415 os << arg1 << " unrecognized\n";
416 }
417 } else {
418 PrintF("printobject <value>\n");
419 }
420 } else if (strcmp(cmd, "setpc") == 0) {
421 intptr_t value;
422
423 if (!GetValue(arg1, &value)) {
424 PrintF("%s unrecognized\n", arg1);
425 continue;
426 }
427 sim_->set_pc(value);
428 } else if (strcmp(cmd, "stack") == 0 || strcmp(cmd, "mem") == 0) {
429 intptr_t* cur = NULL;
430 intptr_t* end = NULL;
431 int next_arg = 1;
432
433 if (strcmp(cmd, "stack") == 0) {
434 cur = reinterpret_cast<intptr_t*>(sim_->get_register(Simulator::sp));
435 } else { // "mem"
436 intptr_t value;
437 if (!GetValue(arg1, &value)) {
438 PrintF("%s unrecognized\n", arg1);
439 continue;
440 }
441 cur = reinterpret_cast<intptr_t*>(value);
442 next_arg++;
443 }
444
445 intptr_t words; // likely inaccurate variable name for 64bit
446 if (argc == next_arg) {
447 words = 10;
448 } else {
449 if (!GetValue(argv[next_arg], &words)) {
450 words = 10;
451 }
452 }
453 end = cur + words;
454
455 while (cur < end) {
456 PrintF(" 0x%08" V8PRIxPTR ": 0x%08" V8PRIxPTR " %10" V8PRIdPTR,
457 reinterpret_cast<intptr_t>(cur), *cur, *cur);
458 HeapObject* obj = reinterpret_cast<HeapObject*>(*cur);
459 intptr_t value = *cur;
460 Heap* current_heap = v8::internal::Isolate::Current()->heap();
461 if (((value & 1) == 0) || current_heap->Contains(obj)) {
462 PrintF(" (");
463 if ((value & 1) == 0) {
464 PrintF("smi %d", PlatformSmiTagging::SmiToInt(obj));
465 } else {
466 obj->ShortPrint();
467 }
468 PrintF(")");
469 }
470 PrintF("\n");
471 cur++;
472 }
473 } else if (strcmp(cmd, "disasm") == 0 || strcmp(cmd, "di") == 0) {
474 disasm::NameConverter converter;
475 disasm::Disassembler dasm(converter);
476 // use a reasonably large buffer
477 v8::internal::EmbeddedVector<char, 256> buffer;
478
479 byte* prev = NULL;
480 byte* cur = NULL;
481 byte* end = NULL;
482
483 if (argc == 1) {
484 cur = reinterpret_cast<byte*>(sim_->get_pc());
485 end = cur + (10 * Instruction::kInstrSize);
486 } else if (argc == 2) {
487 int regnum = Registers::Number(arg1);
488 if (regnum != kNoRegister || strncmp(arg1, "0x", 2) == 0) {
489 // The argument is an address or a register name.
490 intptr_t value;
491 if (GetValue(arg1, &value)) {
492 cur = reinterpret_cast<byte*>(value);
493 // Disassemble 10 instructions at <arg1>.
494 end = cur + (10 * Instruction::kInstrSize);
495 }
496 } else {
497 // The argument is the number of instructions.
498 intptr_t value;
499 if (GetValue(arg1, &value)) {
500 cur = reinterpret_cast<byte*>(sim_->get_pc());
501 // Disassemble <arg1> instructions.
502 end = cur + (value * Instruction::kInstrSize);
503 }
504 }
505 } else {
506 intptr_t value1;
507 intptr_t value2;
508 if (GetValue(arg1, &value1) && GetValue(arg2, &value2)) {
509 cur = reinterpret_cast<byte*>(value1);
510 end = cur + (value2 * Instruction::kInstrSize);
511 }
512 }
513
514 while (cur < end) {
515 prev = cur;
516 cur += dasm.InstructionDecode(buffer, cur);
517 PrintF(" 0x%08" V8PRIxPTR " %s\n", reinterpret_cast<intptr_t>(prev),
518 buffer.start());
519 }
520 } else if (strcmp(cmd, "gdb") == 0) {
521 PrintF("relinquishing control to gdb\n");
522 v8::base::OS::DebugBreak();
523 PrintF("regaining control from gdb\n");
524 } else if (strcmp(cmd, "break") == 0) {
525 if (argc == 2) {
526 intptr_t value;
527 if (GetValue(arg1, &value)) {
528 if (!SetBreakpoint(reinterpret_cast<Instruction*>(value))) {
529 PrintF("setting breakpoint failed\n");
530 }
531 } else {
532 PrintF("%s unrecognized\n", arg1);
533 }
534 } else {
535 PrintF("break <address>\n");
536 }
537 } else if (strcmp(cmd, "del") == 0) {
538 if (!DeleteBreakpoint(NULL)) {
539 PrintF("deleting breakpoint failed\n");
540 }
541 } else if (strcmp(cmd, "cr") == 0) {
542 PrintF("Condition reg: %08x\n", sim_->condition_reg_);
543 } else if (strcmp(cmd, "lr") == 0) {
544 PrintF("Link reg: %08" V8PRIxPTR "\n", sim_->special_reg_lr_);
545 } else if (strcmp(cmd, "ctr") == 0) {
546 PrintF("Ctr reg: %08" V8PRIxPTR "\n", sim_->special_reg_ctr_);
547 } else if (strcmp(cmd, "xer") == 0) {
548 PrintF("XER: %08x\n", sim_->special_reg_xer_);
549 } else if (strcmp(cmd, "fpscr") == 0) {
550 PrintF("FPSCR: %08x\n", sim_->fp_condition_reg_);
551 } else if (strcmp(cmd, "stop") == 0) {
552 intptr_t value;
553 intptr_t stop_pc =
554 sim_->get_pc() - (Instruction::kInstrSize + kPointerSize);
555 Instruction* stop_instr = reinterpret_cast<Instruction*>(stop_pc);
556 Instruction* msg_address =
557 reinterpret_cast<Instruction*>(stop_pc + Instruction::kInstrSize);
558 if ((argc == 2) && (strcmp(arg1, "unstop") == 0)) {
559 // Remove the current stop.
560 if (sim_->isStopInstruction(stop_instr)) {
561 stop_instr->SetInstructionBits(kNopInstr);
562 msg_address->SetInstructionBits(kNopInstr);
563 } else {
564 PrintF("Not at debugger stop.\n");
565 }
566 } else if (argc == 3) {
567 // Print information about all/the specified breakpoint(s).
568 if (strcmp(arg1, "info") == 0) {
569 if (strcmp(arg2, "all") == 0) {
570 PrintF("Stop information:\n");
571 for (uint32_t i = 0; i < sim_->kNumOfWatchedStops; i++) {
572 sim_->PrintStopInfo(i);
573 }
574 } else if (GetValue(arg2, &value)) {
575 sim_->PrintStopInfo(value);
576 } else {
577 PrintF("Unrecognized argument.\n");
578 }
579 } else if (strcmp(arg1, "enable") == 0) {
580 // Enable all/the specified breakpoint(s).
581 if (strcmp(arg2, "all") == 0) {
582 for (uint32_t i = 0; i < sim_->kNumOfWatchedStops; i++) {
583 sim_->EnableStop(i);
584 }
585 } else if (GetValue(arg2, &value)) {
586 sim_->EnableStop(value);
587 } else {
588 PrintF("Unrecognized argument.\n");
589 }
590 } else if (strcmp(arg1, "disable") == 0) {
591 // Disable all/the specified breakpoint(s).
592 if (strcmp(arg2, "all") == 0) {
593 for (uint32_t i = 0; i < sim_->kNumOfWatchedStops; i++) {
594 sim_->DisableStop(i);
595 }
596 } else if (GetValue(arg2, &value)) {
597 sim_->DisableStop(value);
598 } else {
599 PrintF("Unrecognized argument.\n");
600 }
601 }
602 } else {
603 PrintF("Wrong usage. Use help command for more information.\n");
604 }
605 } else if ((strcmp(cmd, "t") == 0) || strcmp(cmd, "trace") == 0) {
606 ::v8::internal::FLAG_trace_sim = !::v8::internal::FLAG_trace_sim;
607 PrintF("Trace of executed instructions is %s\n",
608 ::v8::internal::FLAG_trace_sim ? "on" : "off");
609 } else if ((strcmp(cmd, "h") == 0) || (strcmp(cmd, "help") == 0)) {
610 PrintF("cont\n");
611 PrintF(" continue execution (alias 'c')\n");
612 PrintF("stepi [num instructions]\n");
613 PrintF(" step one/num instruction(s) (alias 'si')\n");
614 PrintF("print <register>\n");
615 PrintF(" print register content (alias 'p')\n");
616 PrintF(" use register name 'all' to display all integer registers\n");
617 PrintF(
618 " use register name 'alld' to display integer registers "
619 "with decimal values\n");
620 PrintF(" use register name 'rN' to display register number 'N'\n");
621 PrintF(" add argument 'fp' to print register pair double values\n");
622 PrintF(
623 " use register name 'allf' to display floating-point "
624 "registers\n");
625 PrintF("printobject <register>\n");
626 PrintF(" print an object from a register (alias 'po')\n");
627 PrintF("cr\n");
628 PrintF(" print condition register\n");
629 PrintF("lr\n");
630 PrintF(" print link register\n");
631 PrintF("ctr\n");
632 PrintF(" print ctr register\n");
633 PrintF("xer\n");
634 PrintF(" print XER\n");
635 PrintF("fpscr\n");
636 PrintF(" print FPSCR\n");
637 PrintF("stack [<num words>]\n");
638 PrintF(" dump stack content, default dump 10 words)\n");
639 PrintF("mem <address> [<num words>]\n");
640 PrintF(" dump memory content, default dump 10 words)\n");
641 PrintF("disasm [<instructions>]\n");
642 PrintF("disasm [<address/register>]\n");
643 PrintF("disasm [[<address/register>] <instructions>]\n");
644 PrintF(" disassemble code, default is 10 instructions\n");
645 PrintF(" from pc (alias 'di')\n");
646 PrintF("gdb\n");
647 PrintF(" enter gdb\n");
648 PrintF("break <address>\n");
649 PrintF(" set a break point on the address\n");
650 PrintF("del\n");
651 PrintF(" delete the breakpoint\n");
652 PrintF("trace (alias 't')\n");
653 PrintF(" toogle the tracing of all executed statements\n");
654 PrintF("stop feature:\n");
655 PrintF(" Description:\n");
656 PrintF(" Stops are debug instructions inserted by\n");
657 PrintF(" the Assembler::stop() function.\n");
658 PrintF(" When hitting a stop, the Simulator will\n");
659 PrintF(" stop and and give control to the PPCDebugger.\n");
660 PrintF(" The first %d stop codes are watched:\n",
661 Simulator::kNumOfWatchedStops);
662 PrintF(" - They can be enabled / disabled: the Simulator\n");
663 PrintF(" will / won't stop when hitting them.\n");
664 PrintF(" - The Simulator keeps track of how many times they \n");
665 PrintF(" are met. (See the info command.) Going over a\n");
666 PrintF(" disabled stop still increases its counter. \n");
667 PrintF(" Commands:\n");
668 PrintF(" stop info all/<code> : print infos about number <code>\n");
669 PrintF(" or all stop(s).\n");
670 PrintF(" stop enable/disable all/<code> : enables / disables\n");
671 PrintF(" all or number <code> stop(s)\n");
672 PrintF(" stop unstop\n");
673 PrintF(" ignore the stop instruction at the current location\n");
674 PrintF(" from now on\n");
675 } else {
676 PrintF("Unknown command: %s\n", cmd);
677 }
678 }
679 }
680
681 // Add all the breakpoints back to stop execution and enter the debugger
682 // shell when hit.
683 RedoBreakpoints();
684 // Restore tracing
685 ::v8::internal::FLAG_trace_sim = trace;
686
687 #undef COMMAND_SIZE
688 #undef ARG_SIZE
689
690 #undef STR
691 #undef XSTR
692 }
693
694
695 static bool ICacheMatch(void* one, void* two) {
696 DCHECK((reinterpret_cast<intptr_t>(one) & CachePage::kPageMask) == 0);
697 DCHECK((reinterpret_cast<intptr_t>(two) & CachePage::kPageMask) == 0);
698 return one == two;
699 }
700
701
702 static uint32_t ICacheHash(void* key) {
703 return static_cast<uint32_t>(reinterpret_cast<uintptr_t>(key)) >> 2;
704 }
705
706
707 static bool AllOnOnePage(uintptr_t start, int size) {
708 intptr_t start_page = (start & ~CachePage::kPageMask);
709 intptr_t end_page = ((start + size) & ~CachePage::kPageMask);
710 return start_page == end_page;
711 }
712
713
714 void Simulator::set_last_debugger_input(char* input) {
715 DeleteArray(last_debugger_input_);
716 last_debugger_input_ = input;
717 }
718
719
720 void Simulator::FlushICache(v8::internal::HashMap* i_cache, void* start_addr,
721 size_t size) {
722 intptr_t start = reinterpret_cast<intptr_t>(start_addr);
723 int intra_line = (start & CachePage::kLineMask);
724 start -= intra_line;
725 size += intra_line;
726 size = ((size - 1) | CachePage::kLineMask) + 1;
727 int offset = (start & CachePage::kPageMask);
728 while (!AllOnOnePage(start, size - 1)) {
729 int bytes_to_flush = CachePage::kPageSize - offset;
730 FlushOnePage(i_cache, start, bytes_to_flush);
731 start += bytes_to_flush;
732 size -= bytes_to_flush;
733 DCHECK_EQ(0, static_cast<int>(start & CachePage::kPageMask));
734 offset = 0;
735 }
736 if (size != 0) {
737 FlushOnePage(i_cache, start, size);
738 }
739 }
740
741
742 CachePage* Simulator::GetCachePage(v8::internal::HashMap* i_cache, void* page) {
743 v8::internal::HashMap::Entry* entry =
744 i_cache->Lookup(page, ICacheHash(page), true);
745 if (entry->value == NULL) {
746 CachePage* new_page = new CachePage();
747 entry->value = new_page;
748 }
749 return reinterpret_cast<CachePage*>(entry->value);
750 }
751
752
753 // Flush from start up to and not including start + size.
754 void Simulator::FlushOnePage(v8::internal::HashMap* i_cache, intptr_t start,
755 int size) {
756 DCHECK(size <= CachePage::kPageSize);
757 DCHECK(AllOnOnePage(start, size - 1));
758 DCHECK((start & CachePage::kLineMask) == 0);
759 DCHECK((size & CachePage::kLineMask) == 0);
760 void* page = reinterpret_cast<void*>(start & (~CachePage::kPageMask));
761 int offset = (start & CachePage::kPageMask);
762 CachePage* cache_page = GetCachePage(i_cache, page);
763 char* valid_bytemap = cache_page->ValidityByte(offset);
764 memset(valid_bytemap, CachePage::LINE_INVALID, size >> CachePage::kLineShift);
765 }
766
767
768 void Simulator::CheckICache(v8::internal::HashMap* i_cache,
769 Instruction* instr) {
770 intptr_t address = reinterpret_cast<intptr_t>(instr);
771 void* page = reinterpret_cast<void*>(address & (~CachePage::kPageMask));
772 void* line = reinterpret_cast<void*>(address & (~CachePage::kLineMask));
773 int offset = (address & CachePage::kPageMask);
774 CachePage* cache_page = GetCachePage(i_cache, page);
775 char* cache_valid_byte = cache_page->ValidityByte(offset);
776 bool cache_hit = (*cache_valid_byte == CachePage::LINE_VALID);
777 char* cached_line = cache_page->CachedData(offset & ~CachePage::kLineMask);
778 if (cache_hit) {
779 // Check that the data in memory matches the contents of the I-cache.
780 CHECK_EQ(0,
781 memcmp(reinterpret_cast<void*>(instr),
782 cache_page->CachedData(offset), Instruction::kInstrSize));
783 } else {
784 // Cache miss. Load memory into the cache.
785 memcpy(cached_line, line, CachePage::kLineLength);
786 *cache_valid_byte = CachePage::LINE_VALID;
787 }
788 }
789
790
791 void Simulator::Initialize(Isolate* isolate) {
792 if (isolate->simulator_initialized()) return;
793 isolate->set_simulator_initialized(true);
794 ::v8::internal::ExternalReference::set_redirector(isolate,
795 &RedirectExternalReference);
796 }
797
798
799 Simulator::Simulator(Isolate* isolate) : isolate_(isolate) {
800 i_cache_ = isolate_->simulator_i_cache();
801 if (i_cache_ == NULL) {
802 i_cache_ = new v8::internal::HashMap(&ICacheMatch);
803 isolate_->set_simulator_i_cache(i_cache_);
804 }
805 Initialize(isolate);
806 // Set up simulator support first. Some of this information is needed to
807 // setup the architecture state.
808 #if V8_TARGET_ARCH_PPC64
809 size_t stack_size = 2 * 1024 * 1024; // allocate 2MB for stack
810 #else
811 size_t stack_size = 1 * 1024 * 1024; // allocate 1MB for stack
812 #endif
813 stack_ = reinterpret_cast<char*>(malloc(stack_size));
814 pc_modified_ = false;
815 icount_ = 0;
816 break_pc_ = NULL;
817 break_instr_ = 0;
818
819 // Set up architecture state.
820 // All registers are initialized to zero to start with.
821 for (int i = 0; i < kNumGPRs; i++) {
822 registers_[i] = 0;
823 }
824 condition_reg_ = 0;
825 fp_condition_reg_ = 0;
826 special_reg_pc_ = 0;
827 special_reg_lr_ = 0;
828 special_reg_ctr_ = 0;
829
830 // Initializing FP registers.
831 for (int i = 0; i < kNumFPRs; i++) {
832 fp_registers_[i] = 0.0;
833 }
834
835 // The sp is initialized to point to the bottom (high address) of the
836 // allocated stack area. To be safe in potential stack underflows we leave
837 // some buffer below.
838 registers_[sp] = reinterpret_cast<intptr_t>(stack_) + stack_size - 64;
839 InitializeCoverage();
840
841 last_debugger_input_ = NULL;
842 }
843
844
845 Simulator::~Simulator() {}
846
847
848 // When the generated code calls an external reference we need to catch that in
849 // the simulator. The external reference will be a function compiled for the
850 // host architecture. We need to call that function instead of trying to
851 // execute it with the simulator. We do that by redirecting the external
852 // reference to a svc (Supervisor Call) instruction that is handled by
853 // the simulator. We write the original destination of the jump just at a known
854 // offset from the svc instruction so the simulator knows what to call.
855 class Redirection {
856 public:
857 Redirection(void* external_function, ExternalReference::Type type)
858 : external_function_(external_function),
859 swi_instruction_(rtCallRedirInstr | kCallRtRedirected),
860 type_(type),
861 next_(NULL) {
862 Isolate* isolate = Isolate::Current();
863 next_ = isolate->simulator_redirection();
864 Simulator::current(isolate)->FlushICache(
865 isolate->simulator_i_cache(),
866 reinterpret_cast<void*>(&swi_instruction_), Instruction::kInstrSize);
867 isolate->set_simulator_redirection(this);
868 }
869
870 void* address_of_swi_instruction() {
871 return reinterpret_cast<void*>(&swi_instruction_);
872 }
873
874 void* external_function() { return external_function_; }
875 ExternalReference::Type type() { return type_; }
876
877 static Redirection* Get(void* external_function,
878 ExternalReference::Type type) {
879 Isolate* isolate = Isolate::Current();
880 Redirection* current = isolate->simulator_redirection();
881 for (; current != NULL; current = current->next_) {
882 if (current->external_function_ == external_function) {
883 DCHECK_EQ(current->type(), type);
884 return current;
885 }
886 }
887 return new Redirection(external_function, type);
888 }
889
890 static Redirection* FromSwiInstruction(Instruction* swi_instruction) {
891 char* addr_of_swi = reinterpret_cast<char*>(swi_instruction);
892 char* addr_of_redirection =
893 addr_of_swi - OFFSET_OF(Redirection, swi_instruction_);
894 return reinterpret_cast<Redirection*>(addr_of_redirection);
895 }
896
897 static void* ReverseRedirection(intptr_t reg) {
898 Redirection* redirection = FromSwiInstruction(
899 reinterpret_cast<Instruction*>(reinterpret_cast<void*>(reg)));
900 return redirection->external_function();
901 }
902
903 private:
904 void* external_function_;
905 uint32_t swi_instruction_;
906 ExternalReference::Type type_;
907 Redirection* next_;
908 };
909
910
911 void* Simulator::RedirectExternalReference(void* external_function,
912 ExternalReference::Type type) {
913 Redirection* redirection = Redirection::Get(external_function, type);
914 return redirection->address_of_swi_instruction();
915 }
916
917
918 // Get the active Simulator for the current thread.
919 Simulator* Simulator::current(Isolate* isolate) {
920 v8::internal::Isolate::PerIsolateThreadData* isolate_data =
921 isolate->FindOrAllocatePerThreadDataForThisThread();
922 DCHECK(isolate_data != NULL);
923
924 Simulator* sim = isolate_data->simulator();
925 if (sim == NULL) {
926 // TODO(146): delete the simulator object when a thread/isolate goes away.
927 sim = new Simulator(isolate);
928 isolate_data->set_simulator(sim);
929 }
930 return sim;
931 }
932
933
934 // Sets the register in the architecture state.
935 void Simulator::set_register(int reg, intptr_t value) {
936 DCHECK((reg >= 0) && (reg < kNumGPRs));
937 registers_[reg] = value;
938 }
939
940
941 // Get the register from the architecture state.
942 intptr_t Simulator::get_register(int reg) const {
943 DCHECK((reg >= 0) && (reg < kNumGPRs));
944 // Stupid code added to avoid bug in GCC.
945 // See: http://gcc.gnu.org/bugzilla/show_bug.cgi?id=43949
946 if (reg >= kNumGPRs) return 0;
947 // End stupid code.
948 return registers_[reg];
949 }
950
951
952 double Simulator::get_double_from_register_pair(int reg) {
953 DCHECK((reg >= 0) && (reg < kNumGPRs) && ((reg % 2) == 0));
954
955 double dm_val = 0.0;
956 #if !V8_TARGET_ARCH_PPC64 // doesn't make sense in 64bit mode
957 // Read the bits from the unsigned integer register_[] array
958 // into the double precision floating point value and return it.
959 char buffer[sizeof(fp_registers_[0])];
960 memcpy(buffer, &registers_[reg], 2 * sizeof(registers_[0]));
961 memcpy(&dm_val, buffer, 2 * sizeof(registers_[0]));
962 #endif
963 return (dm_val);
964 }
965
966
967 // Raw access to the PC register.
968 void Simulator::set_pc(intptr_t value) {
969 pc_modified_ = true;
970 special_reg_pc_ = value;
971 }
972
973
974 bool Simulator::has_bad_pc() const {
975 return ((special_reg_pc_ == bad_lr) || (special_reg_pc_ == end_sim_pc));
976 }
977
978
979 // Raw access to the PC register without the special adjustment when reading.
980 intptr_t Simulator::get_pc() const { return special_reg_pc_; }
981
982
983 // Runtime FP routines take:
984 // - two double arguments
985 // - one double argument and zero or one integer arguments.
986 // All are consructed here from d1, d2 and r3.
987 void Simulator::GetFpArgs(double* x, double* y, intptr_t* z) {
988 *x = get_double_from_d_register(1);
989 *y = get_double_from_d_register(2);
990 *z = get_register(3);
991 }
992
993
994 // The return value is in d1.
995 void Simulator::SetFpResult(const double& result) { fp_registers_[1] = result; }
996
997
998 void Simulator::TrashCallerSaveRegisters() {
999 // We don't trash the registers with the return value.
1000 #if 0 // A good idea to trash volatile registers, needs to be done
1001 registers_[2] = 0x50Bad4U;
1002 registers_[3] = 0x50Bad4U;
1003 registers_[12] = 0x50Bad4U;
1004 #endif
1005 }
1006
1007
1008 uint32_t Simulator::ReadWU(intptr_t addr, Instruction* instr) {
1009 uint32_t* ptr = reinterpret_cast<uint32_t*>(addr);
1010 return *ptr;
1011 }
1012
1013
1014 int32_t Simulator::ReadW(intptr_t addr, Instruction* instr) {
1015 int32_t* ptr = reinterpret_cast<int32_t*>(addr);
1016 return *ptr;
1017 }
1018
1019
1020 void Simulator::WriteW(intptr_t addr, uint32_t value, Instruction* instr) {
1021 uint32_t* ptr = reinterpret_cast<uint32_t*>(addr);
1022 *ptr = value;
1023 return;
1024 }
1025
1026
1027 void Simulator::WriteW(intptr_t addr, int32_t value, Instruction* instr) {
1028 int32_t* ptr = reinterpret_cast<int32_t*>(addr);
1029 *ptr = value;
1030 return;
1031 }
1032
1033
1034 uint16_t Simulator::ReadHU(intptr_t addr, Instruction* instr) {
1035 uint16_t* ptr = reinterpret_cast<uint16_t*>(addr);
1036 return *ptr;
1037 }
1038
1039
1040 int16_t Simulator::ReadH(intptr_t addr, Instruction* instr) {
1041 int16_t* ptr = reinterpret_cast<int16_t*>(addr);
1042 return *ptr;
1043 }
1044
1045
1046 void Simulator::WriteH(intptr_t addr, uint16_t value, Instruction* instr) {
1047 uint16_t* ptr = reinterpret_cast<uint16_t*>(addr);
1048 *ptr = value;
1049 return;
1050 }
1051
1052
1053 void Simulator::WriteH(intptr_t addr, int16_t value, Instruction* instr) {
1054 int16_t* ptr = reinterpret_cast<int16_t*>(addr);
1055 *ptr = value;
1056 return;
1057 }
1058
1059
1060 uint8_t Simulator::ReadBU(intptr_t addr) {
1061 uint8_t* ptr = reinterpret_cast<uint8_t*>(addr);
1062 return *ptr;
1063 }
1064
1065
1066 int8_t Simulator::ReadB(intptr_t addr) {
1067 int8_t* ptr = reinterpret_cast<int8_t*>(addr);
1068 return *ptr;
1069 }
1070
1071
1072 void Simulator::WriteB(intptr_t addr, uint8_t value) {
1073 uint8_t* ptr = reinterpret_cast<uint8_t*>(addr);
1074 *ptr = value;
1075 }
1076
1077
1078 void Simulator::WriteB(intptr_t addr, int8_t value) {
1079 int8_t* ptr = reinterpret_cast<int8_t*>(addr);
1080 *ptr = value;
1081 }
1082
1083
1084 intptr_t* Simulator::ReadDW(intptr_t addr) {
1085 intptr_t* ptr = reinterpret_cast<intptr_t*>(addr);
1086 return ptr;
1087 }
1088
1089
1090 void Simulator::WriteDW(intptr_t addr, int64_t value) {
1091 int64_t* ptr = reinterpret_cast<int64_t*>(addr);
1092 *ptr = value;
1093 return;
1094 }
1095
1096
1097 // Returns the limit of the stack area to enable checking for stack overflows.
1098 uintptr_t Simulator::StackLimit() const {
1099 // Leave a safety margin of 1024 bytes to prevent overrunning the stack when
1100 // pushing values.
1101 return reinterpret_cast<uintptr_t>(stack_) + 1024;
1102 }
1103
1104
1105 // Unsupported instructions use Format to print an error and stop execution.
1106 void Simulator::Format(Instruction* instr, const char* format) {
1107 PrintF("Simulator found unsupported instruction:\n 0x%08" V8PRIxPTR ": %s\n",
1108 reinterpret_cast<intptr_t>(instr), format);
1109 UNIMPLEMENTED();
1110 }
1111
1112
1113 // Calculate C flag value for additions.
1114 bool Simulator::CarryFrom(int32_t left, int32_t right, int32_t carry) {
1115 uint32_t uleft = static_cast<uint32_t>(left);
1116 uint32_t uright = static_cast<uint32_t>(right);
1117 uint32_t urest = 0xffffffffU - uleft;
1118
1119 return (uright > urest) ||
1120 (carry && (((uright + 1) > urest) || (uright > (urest - 1))));
1121 }
1122
1123
1124 // Calculate C flag value for subtractions.
1125 bool Simulator::BorrowFrom(int32_t left, int32_t right) {
1126 uint32_t uleft = static_cast<uint32_t>(left);
1127 uint32_t uright = static_cast<uint32_t>(right);
1128
1129 return (uright > uleft);
1130 }
1131
1132
1133 // Calculate V flag value for additions and subtractions.
1134 bool Simulator::OverflowFrom(int32_t alu_out, int32_t left, int32_t right,
1135 bool addition) {
1136 bool overflow;
1137 if (addition) {
1138 // operands have the same sign
1139 overflow = ((left >= 0 && right >= 0) || (left < 0 && right < 0))
1140 // and operands and result have different sign
1141 &&
1142 ((left < 0 && alu_out >= 0) || (left >= 0 && alu_out < 0));
1143 } else {
1144 // operands have different signs
1145 overflow = ((left < 0 && right >= 0) || (left >= 0 && right < 0))
1146 // and first operand and result have different signs
1147 &&
1148 ((left < 0 && alu_out >= 0) || (left >= 0 && alu_out < 0));
1149 }
1150 return overflow;
1151 }
1152
1153
1154 #if !V8_TARGET_ARCH_PPC64
1155 // Calls into the V8 runtime are based on this very simple interface.
1156 // Note: To be able to return two values from some calls the code in runtime.cc
1157 // uses the ObjectPair which is essentially two 32-bit values stuffed into a
1158 // 64-bit value. With the code below we assume that all runtime calls return
1159 // 64 bits of result. If they don't, the r4 result register contains a bogus
1160 // value, which is fine because it is caller-saved.
1161 typedef int64_t (*SimulatorRuntimeCall)(intptr_t arg0, intptr_t arg1,
1162 intptr_t arg2, intptr_t arg3,
1163 intptr_t arg4, intptr_t arg5);
1164 #else
1165 // For 64-bit, we need to be more explicit.
1166 typedef intptr_t (*SimulatorRuntimeCall)(intptr_t arg0, intptr_t arg1,
1167 intptr_t arg2, intptr_t arg3,
1168 intptr_t arg4, intptr_t arg5);
1169 struct ObjectPair {
1170 intptr_t x;
1171 intptr_t y;
1172 };
1173
1174 typedef struct ObjectPair (*SimulatorRuntimeObjectPairCall)(
1175 intptr_t arg0, intptr_t arg1, intptr_t arg2, intptr_t arg3, intptr_t arg4,
1176 intptr_t arg5);
1177 #endif
1178
1179 // These prototypes handle the four types of FP calls.
1180 typedef int (*SimulatorRuntimeCompareCall)(double darg0, double darg1);
1181 typedef double (*SimulatorRuntimeFPFPCall)(double darg0, double darg1);
1182 typedef double (*SimulatorRuntimeFPCall)(double darg0);
1183 typedef double (*SimulatorRuntimeFPIntCall)(double darg0, intptr_t arg0);
1184
1185 // This signature supports direct call in to API function native callback
1186 // (refer to InvocationCallback in v8.h).
1187 typedef void (*SimulatorRuntimeDirectApiCall)(intptr_t arg0);
1188 typedef void (*SimulatorRuntimeProfilingApiCall)(intptr_t arg0, void* arg1);
1189
1190 // This signature supports direct call to accessor getter callback.
1191 typedef void (*SimulatorRuntimeDirectGetterCall)(intptr_t arg0, intptr_t arg1);
1192 typedef void (*SimulatorRuntimeProfilingGetterCall)(intptr_t arg0,
1193 intptr_t arg1, void* arg2);
1194
1195 // Software interrupt instructions are used by the simulator to call into the
1196 // C-based V8 runtime.
1197 void Simulator::SoftwareInterrupt(Instruction* instr) {
1198 int svc = instr->SvcValue();
1199 switch (svc) {
1200 case kCallRtRedirected: {
1201 // Check if stack is aligned. Error if not aligned is reported below to
1202 // include information on the function called.
1203 bool stack_aligned =
1204 (get_register(sp) & (::v8::internal::FLAG_sim_stack_alignment - 1)) ==
1205 0;
1206 Redirection* redirection = Redirection::FromSwiInstruction(instr);
1207 const int kArgCount = 6;
1208 int arg0_regnum = 3;
1209 #if V8_TARGET_ARCH_PPC64 && !ABI_RETURNS_OBJECT_PAIRS_IN_REGS
1210 intptr_t result_buffer = 0;
1211 if (redirection->type() == ExternalReference::BUILTIN_OBJECTPAIR_CALL) {
1212 result_buffer = get_register(r3);
1213 arg0_regnum++;
1214 }
1215 #endif
1216 intptr_t arg[kArgCount];
1217 for (int i = 0; i < kArgCount; i++) {
1218 arg[i] = get_register(arg0_regnum + i);
1219 }
1220 bool fp_call =
1221 (redirection->type() == ExternalReference::BUILTIN_FP_FP_CALL) ||
1222 (redirection->type() == ExternalReference::BUILTIN_COMPARE_CALL) ||
1223 (redirection->type() == ExternalReference::BUILTIN_FP_CALL) ||
1224 (redirection->type() == ExternalReference::BUILTIN_FP_INT_CALL);
1225 // This is dodgy but it works because the C entry stubs are never moved.
1226 // See comment in codegen-arm.cc and bug 1242173.
1227 intptr_t saved_lr = special_reg_lr_;
1228 intptr_t external =
1229 reinterpret_cast<intptr_t>(redirection->external_function());
1230 if (fp_call) {
1231 double dval0, dval1; // one or two double parameters
1232 intptr_t ival; // zero or one integer parameters
1233 int iresult = 0; // integer return value
1234 double dresult = 0; // double return value
1235 GetFpArgs(&dval0, &dval1, &ival);
1236 if (::v8::internal::FLAG_trace_sim || !stack_aligned) {
1237 SimulatorRuntimeCall generic_target =
1238 reinterpret_cast<SimulatorRuntimeCall>(external);
1239 switch (redirection->type()) {
1240 case ExternalReference::BUILTIN_FP_FP_CALL:
1241 case ExternalReference::BUILTIN_COMPARE_CALL:
1242 PrintF("Call to host function at %p with args %f, %f",
1243 FUNCTION_ADDR(generic_target), dval0, dval1);
1244 break;
1245 case ExternalReference::BUILTIN_FP_CALL:
1246 PrintF("Call to host function at %p with arg %f",
1247 FUNCTION_ADDR(generic_target), dval0);
1248 break;
1249 case ExternalReference::BUILTIN_FP_INT_CALL:
1250 PrintF("Call to host function at %p with args %f, %" V8PRIdPTR,
1251 FUNCTION_ADDR(generic_target), dval0, ival);
1252 break;
1253 default:
1254 UNREACHABLE();
1255 break;
1256 }
1257 if (!stack_aligned) {
1258 PrintF(" with unaligned stack %08" V8PRIxPTR "\n",
1259 get_register(sp));
1260 }
1261 PrintF("\n");
1262 }
1263 CHECK(stack_aligned);
1264 switch (redirection->type()) {
1265 case ExternalReference::BUILTIN_COMPARE_CALL: {
1266 SimulatorRuntimeCompareCall target =
1267 reinterpret_cast<SimulatorRuntimeCompareCall>(external);
1268 iresult = target(dval0, dval1);
1269 set_register(r3, iresult);
1270 break;
1271 }
1272 case ExternalReference::BUILTIN_FP_FP_CALL: {
1273 SimulatorRuntimeFPFPCall target =
1274 reinterpret_cast<SimulatorRuntimeFPFPCall>(external);
1275 dresult = target(dval0, dval1);
1276 SetFpResult(dresult);
1277 break;
1278 }
1279 case ExternalReference::BUILTIN_FP_CALL: {
1280 SimulatorRuntimeFPCall target =
1281 reinterpret_cast<SimulatorRuntimeFPCall>(external);
1282 dresult = target(dval0);
1283 SetFpResult(dresult);
1284 break;
1285 }
1286 case ExternalReference::BUILTIN_FP_INT_CALL: {
1287 SimulatorRuntimeFPIntCall target =
1288 reinterpret_cast<SimulatorRuntimeFPIntCall>(external);
1289 dresult = target(dval0, ival);
1290 SetFpResult(dresult);
1291 break;
1292 }
1293 default:
1294 UNREACHABLE();
1295 break;
1296 }
1297 if (::v8::internal::FLAG_trace_sim || !stack_aligned) {
1298 switch (redirection->type()) {
1299 case ExternalReference::BUILTIN_COMPARE_CALL:
1300 PrintF("Returned %08x\n", iresult);
1301 break;
1302 case ExternalReference::BUILTIN_FP_FP_CALL:
1303 case ExternalReference::BUILTIN_FP_CALL:
1304 case ExternalReference::BUILTIN_FP_INT_CALL:
1305 PrintF("Returned %f\n", dresult);
1306 break;
1307 default:
1308 UNREACHABLE();
1309 break;
1310 }
1311 }
1312 } else if (redirection->type() == ExternalReference::DIRECT_API_CALL) {
1313 // See callers of MacroAssembler::CallApiFunctionAndReturn for
1314 // explanation of register usage.
1315 if (::v8::internal::FLAG_trace_sim || !stack_aligned) {
1316 PrintF("Call to host function at %p args %08" V8PRIxPTR,
1317 reinterpret_cast<void*>(external), arg[0]);
1318 if (!stack_aligned) {
1319 PrintF(" with unaligned stack %08" V8PRIxPTR "\n",
1320 get_register(sp));
1321 }
1322 PrintF("\n");
1323 }
1324 CHECK(stack_aligned);
1325 SimulatorRuntimeDirectApiCall target =
1326 reinterpret_cast<SimulatorRuntimeDirectApiCall>(external);
1327 target(arg[0]);
1328 } else if (redirection->type() == ExternalReference::PROFILING_API_CALL) {
1329 // See callers of MacroAssembler::CallApiFunctionAndReturn for
1330 // explanation of register usage.
1331 if (::v8::internal::FLAG_trace_sim || !stack_aligned) {
1332 PrintF("Call to host function at %p args %08" V8PRIxPTR
1333 " %08" V8PRIxPTR,
1334 reinterpret_cast<void*>(external), arg[0], arg[1]);
1335 if (!stack_aligned) {
1336 PrintF(" with unaligned stack %08" V8PRIxPTR "\n",
1337 get_register(sp));
1338 }
1339 PrintF("\n");
1340 }
1341 CHECK(stack_aligned);
1342 SimulatorRuntimeProfilingApiCall target =
1343 reinterpret_cast<SimulatorRuntimeProfilingApiCall>(external);
1344 target(arg[0], Redirection::ReverseRedirection(arg[1]));
1345 } else if (redirection->type() == ExternalReference::DIRECT_GETTER_CALL) {
1346 // See callers of MacroAssembler::CallApiFunctionAndReturn for
1347 // explanation of register usage.
1348 if (::v8::internal::FLAG_trace_sim || !stack_aligned) {
1349 PrintF("Call to host function at %p args %08" V8PRIxPTR
1350 " %08" V8PRIxPTR,
1351 reinterpret_cast<void*>(external), arg[0], arg[1]);
1352 if (!stack_aligned) {
1353 PrintF(" with unaligned stack %08" V8PRIxPTR "\n",
1354 get_register(sp));
1355 }
1356 PrintF("\n");
1357 }
1358 CHECK(stack_aligned);
1359 SimulatorRuntimeDirectGetterCall target =
1360 reinterpret_cast<SimulatorRuntimeDirectGetterCall>(external);
1361 #if !ABI_PASSES_HANDLES_IN_REGS
1362 arg[0] = *(reinterpret_cast<intptr_t*>(arg[0]));
1363 #endif
1364 target(arg[0], arg[1]);
1365 } else if (redirection->type() ==
1366 ExternalReference::PROFILING_GETTER_CALL) {
1367 if (::v8::internal::FLAG_trace_sim || !stack_aligned) {
1368 PrintF("Call to host function at %p args %08" V8PRIxPTR
1369 " %08" V8PRIxPTR " %08" V8PRIxPTR,
1370 reinterpret_cast<void*>(external), arg[0], arg[1], arg[2]);
1371 if (!stack_aligned) {
1372 PrintF(" with unaligned stack %08" V8PRIxPTR "\n",
1373 get_register(sp));
1374 }
1375 PrintF("\n");
1376 }
1377 CHECK(stack_aligned);
1378 SimulatorRuntimeProfilingGetterCall target =
1379 reinterpret_cast<SimulatorRuntimeProfilingGetterCall>(external);
1380 #if !ABI_PASSES_HANDLES_IN_REGS
1381 arg[0] = *(reinterpret_cast<intptr_t*>(arg[0]));
1382 #endif
1383 target(arg[0], arg[1], Redirection::ReverseRedirection(arg[2]));
1384 } else {
1385 // builtin call.
1386 if (::v8::internal::FLAG_trace_sim || !stack_aligned) {
1387 SimulatorRuntimeCall target =
1388 reinterpret_cast<SimulatorRuntimeCall>(external);
1389 PrintF(
1390 "Call to host function at %p,\n"
1391 "\t\t\t\targs %08" V8PRIxPTR ", %08" V8PRIxPTR ", %08" V8PRIxPTR
1392 ", %08" V8PRIxPTR ", %08" V8PRIxPTR ", %08" V8PRIxPTR,
1393 FUNCTION_ADDR(target), arg[0], arg[1], arg[2], arg[3], arg[4],
1394 arg[5]);
1395 if (!stack_aligned) {
1396 PrintF(" with unaligned stack %08" V8PRIxPTR "\n",
1397 get_register(sp));
1398 }
1399 PrintF("\n");
1400 }
1401 CHECK(stack_aligned);
1402 #if !V8_TARGET_ARCH_PPC64
1403 DCHECK(redirection->type() == ExternalReference::BUILTIN_CALL);
1404 SimulatorRuntimeCall target =
1405 reinterpret_cast<SimulatorRuntimeCall>(external);
1406 int64_t result = target(arg[0], arg[1], arg[2], arg[3], arg[4], arg[5]);
1407 int32_t lo_res = static_cast<int32_t>(result);
1408 int32_t hi_res = static_cast<int32_t>(result >> 32);
1409 #if V8_TARGET_BIG_ENDIAN
1410 if (::v8::internal::FLAG_trace_sim) {
1411 PrintF("Returned %08x\n", hi_res);
1412 }
1413 set_register(r3, hi_res);
1414 set_register(r4, lo_res);
1415 #else
1416 if (::v8::internal::FLAG_trace_sim) {
1417 PrintF("Returned %08x\n", lo_res);
1418 }
1419 set_register(r3, lo_res);
1420 set_register(r4, hi_res);
1421 #endif
1422 #else
1423 if (redirection->type() == ExternalReference::BUILTIN_CALL) {
1424 SimulatorRuntimeCall target =
1425 reinterpret_cast<SimulatorRuntimeCall>(external);
1426 intptr_t result =
1427 target(arg[0], arg[1], arg[2], arg[3], arg[4], arg[5]);
1428 if (::v8::internal::FLAG_trace_sim) {
1429 PrintF("Returned %08" V8PRIxPTR "\n", result);
1430 }
1431 set_register(r3, result);
1432 } else {
1433 DCHECK(redirection->type() ==
1434 ExternalReference::BUILTIN_OBJECTPAIR_CALL);
1435 SimulatorRuntimeObjectPairCall target =
1436 reinterpret_cast<SimulatorRuntimeObjectPairCall>(external);
1437 struct ObjectPair result =
1438 target(arg[0], arg[1], arg[2], arg[3], arg[4], arg[5]);
1439 if (::v8::internal::FLAG_trace_sim) {
1440 PrintF("Returned %08" V8PRIxPTR ", %08" V8PRIxPTR "\n", result.x,
1441 result.y);
1442 }
1443 #if ABI_RETURNS_OBJECT_PAIRS_IN_REGS
1444 set_register(r3, result.x);
1445 set_register(r4, result.y);
1446 #else
1447 memcpy(reinterpret_cast<void*>(result_buffer), &result,
1448 sizeof(struct ObjectPair));
1449 #endif
1450 }
1451 #endif
1452 }
1453 set_pc(saved_lr);
1454 break;
1455 }
1456 case kBreakpoint: {
1457 PPCDebugger dbg(this);
1458 dbg.Debug();
1459 break;
1460 }
1461 case kInfo: {
1462 PPCDebugger dbg(this);
1463 dbg.Info(instr);
1464 break;
1465 }
1466 // stop uses all codes greater than 1 << 23.
1467 default: {
1468 if (svc >= (1 << 23)) {
1469 uint32_t code = svc & kStopCodeMask;
1470 if (isWatchedStop(code)) {
1471 IncreaseStopCounter(code);
1472 }
1473 // Stop if it is enabled, otherwise go on jumping over the stop
1474 // and the message address.
1475 if (isEnabledStop(code)) {
1476 PPCDebugger dbg(this);
1477 dbg.Stop(instr);
1478 } else {
1479 set_pc(get_pc() + Instruction::kInstrSize + kPointerSize);
1480 }
1481 } else {
1482 // This is not a valid svc code.
1483 UNREACHABLE();
1484 break;
1485 }
1486 }
1487 }
1488 }
1489
1490
1491 // Stop helper functions.
1492 bool Simulator::isStopInstruction(Instruction* instr) {
1493 return (instr->Bits(27, 24) == 0xF) && (instr->SvcValue() >= kStopCode);
1494 }
1495
1496
1497 bool Simulator::isWatchedStop(uint32_t code) {
1498 DCHECK(code <= kMaxStopCode);
1499 return code < kNumOfWatchedStops;
1500 }
1501
1502
1503 bool Simulator::isEnabledStop(uint32_t code) {
1504 DCHECK(code <= kMaxStopCode);
1505 // Unwatched stops are always enabled.
1506 return !isWatchedStop(code) ||
1507 !(watched_stops_[code].count & kStopDisabledBit);
1508 }
1509
1510
1511 void Simulator::EnableStop(uint32_t code) {
1512 DCHECK(isWatchedStop(code));
1513 if (!isEnabledStop(code)) {
1514 watched_stops_[code].count &= ~kStopDisabledBit;
1515 }
1516 }
1517
1518
1519 void Simulator::DisableStop(uint32_t code) {
1520 DCHECK(isWatchedStop(code));
1521 if (isEnabledStop(code)) {
1522 watched_stops_[code].count |= kStopDisabledBit;
1523 }
1524 }
1525
1526
1527 void Simulator::IncreaseStopCounter(uint32_t code) {
1528 DCHECK(code <= kMaxStopCode);
1529 DCHECK(isWatchedStop(code));
1530 if ((watched_stops_[code].count & ~(1 << 31)) == 0x7fffffff) {
1531 PrintF(
1532 "Stop counter for code %i has overflowed.\n"
1533 "Enabling this code and reseting the counter to 0.\n",
1534 code);
1535 watched_stops_[code].count = 0;
1536 EnableStop(code);
1537 } else {
1538 watched_stops_[code].count++;
1539 }
1540 }
1541
1542
1543 // Print a stop status.
1544 void Simulator::PrintStopInfo(uint32_t code) {
1545 DCHECK(code <= kMaxStopCode);
1546 if (!isWatchedStop(code)) {
1547 PrintF("Stop not watched.");
1548 } else {
1549 const char* state = isEnabledStop(code) ? "Enabled" : "Disabled";
1550 int32_t count = watched_stops_[code].count & ~kStopDisabledBit;
1551 // Don't print the state of unused breakpoints.
1552 if (count != 0) {
1553 if (watched_stops_[code].desc) {
1554 PrintF("stop %i - 0x%x: \t%s, \tcounter = %i, \t%s\n", code, code,
1555 state, count, watched_stops_[code].desc);
1556 } else {
1557 PrintF("stop %i - 0x%x: \t%s, \tcounter = %i\n", code, code, state,
1558 count);
1559 }
1560 }
1561 }
1562 }
1563
1564
1565 void Simulator::SetCR0(intptr_t result, bool setSO) {
1566 int bf = 0;
1567 if (result < 0) {
1568 bf |= 0x80000000;
1569 }
1570 if (result > 0) {
1571 bf |= 0x40000000;
1572 }
1573 if (result == 0) {
1574 bf |= 0x20000000;
1575 }
1576 if (setSO) {
1577 bf |= 0x10000000;
1578 }
1579 condition_reg_ = (condition_reg_ & ~0xF0000000) | bf;
1580 }
1581
1582
1583 void Simulator::ExecuteBranchConditional(Instruction* instr) {
1584 int bo = instr->Bits(25, 21) << 21;
1585 int offset = (instr->Bits(15, 2) << 18) >> 16;
1586 int condition_bit = instr->Bits(20, 16);
1587 int condition_mask = 0x80000000 >> condition_bit;
1588 switch (bo) {
1589 case DCBNZF: // Decrement CTR; branch if CTR != 0 and condition false
1590 case DCBEZF: // Decrement CTR; branch if CTR == 0 and condition false
1591 UNIMPLEMENTED();
1592 case BF: { // Branch if condition false
1593 if (!(condition_reg_ & condition_mask)) {
1594 if (instr->Bit(0) == 1) { // LK flag set
1595 special_reg_lr_ = get_pc() + 4;
1596 }
1597 set_pc(get_pc() + offset);
1598 }
1599 break;
1600 }
1601 case DCBNZT: // Decrement CTR; branch if CTR != 0 and condition true
1602 case DCBEZT: // Decrement CTR; branch if CTR == 0 and condition true
1603 UNIMPLEMENTED();
1604 case BT: { // Branch if condition true
1605 if (condition_reg_ & condition_mask) {
1606 if (instr->Bit(0) == 1) { // LK flag set
1607 special_reg_lr_ = get_pc() + 4;
1608 }
1609 set_pc(get_pc() + offset);
1610 }
1611 break;
1612 }
1613 case DCBNZ: // Decrement CTR; branch if CTR != 0
1614 case DCBEZ: // Decrement CTR; branch if CTR == 0
1615 special_reg_ctr_ -= 1;
1616 if ((special_reg_ctr_ == 0) == (bo == DCBEZ)) {
1617 if (instr->Bit(0) == 1) { // LK flag set
1618 special_reg_lr_ = get_pc() + 4;
1619 }
1620 set_pc(get_pc() + offset);
1621 }
1622 break;
1623 case BA: { // Branch always
1624 if (instr->Bit(0) == 1) { // LK flag set
1625 special_reg_lr_ = get_pc() + 4;
1626 }
1627 set_pc(get_pc() + offset);
1628 break;
1629 }
1630 default:
1631 UNIMPLEMENTED(); // Invalid encoding
1632 }
1633 }
1634
1635
1636 // Handle execution based on instruction types.
1637 void Simulator::ExecuteExt1(Instruction* instr) {
1638 switch (instr->Bits(10, 1) << 1) {
1639 case MCRF:
1640 UNIMPLEMENTED(); // Not used by V8.
1641 case BCLRX: {
1642 // need to check BO flag
1643 intptr_t old_pc = get_pc();
1644 set_pc(special_reg_lr_);
1645 if (instr->Bit(0) == 1) { // LK flag set
1646 special_reg_lr_ = old_pc + 4;
1647 }
1648 break;
1649 }
1650 case BCCTRX: {
1651 // need to check BO flag
1652 intptr_t old_pc = get_pc();
1653 set_pc(special_reg_ctr_);
1654 if (instr->Bit(0) == 1) { // LK flag set
1655 special_reg_lr_ = old_pc + 4;
1656 }
1657 break;
1658 }
1659 case CRNOR:
1660 case RFI:
1661 case CRANDC:
1662 UNIMPLEMENTED();
1663 case ISYNC: {
1664 // todo - simulate isync
1665 break;
1666 }
1667 case CRXOR: {
1668 int bt = instr->Bits(25, 21);
1669 int ba = instr->Bits(20, 16);
1670 int bb = instr->Bits(15, 11);
1671 int ba_val = ((0x80000000 >> ba) & condition_reg_) == 0 ? 0 : 1;
1672 int bb_val = ((0x80000000 >> bb) & condition_reg_) == 0 ? 0 : 1;
1673 int bt_val = ba_val ^ bb_val;
1674 bt_val = bt_val << (31 - bt); // shift bit to correct destination
1675 condition_reg_ &= ~(0x80000000 >> bt);
1676 condition_reg_ |= bt_val;
1677 break;
1678 }
1679 case CREQV: {
1680 int bt = instr->Bits(25, 21);
1681 int ba = instr->Bits(20, 16);
1682 int bb = instr->Bits(15, 11);
1683 int ba_val = ((0x80000000 >> ba) & condition_reg_) == 0 ? 0 : 1;
1684 int bb_val = ((0x80000000 >> bb) & condition_reg_) == 0 ? 0 : 1;
1685 int bt_val = 1 - (ba_val ^ bb_val);
1686 bt_val = bt_val << (31 - bt); // shift bit to correct destination
1687 condition_reg_ &= ~(0x80000000 >> bt);
1688 condition_reg_ |= bt_val;
1689 break;
1690 }
1691 case CRNAND:
1692 case CRAND:
1693 case CRORC:
1694 case CROR:
1695 default: {
1696 UNIMPLEMENTED(); // Not used by V8.
1697 }
1698 }
1699 }
1700
1701
1702 bool Simulator::ExecuteExt2_10bit(Instruction* instr) {
1703 bool found = true;
1704
1705 int opcode = instr->Bits(10, 1) << 1;
1706 switch (opcode) {
1707 case SRWX: {
1708 int rs = instr->RSValue();
1709 int ra = instr->RAValue();
1710 int rb = instr->RBValue();
1711 uint32_t rs_val = get_register(rs);
1712 uintptr_t rb_val = get_register(rb);
1713 intptr_t result = rs_val >> (rb_val & 0x3f);
1714 set_register(ra, result);
1715 if (instr->Bit(0)) { // RC bit set
1716 SetCR0(result);
1717 }
1718 break;
1719 }
1720 #if V8_TARGET_ARCH_PPC64
1721 case SRDX: {
1722 int rs = instr->RSValue();
1723 int ra = instr->RAValue();
1724 int rb = instr->RBValue();
1725 uintptr_t rs_val = get_register(rs);
1726 uintptr_t rb_val = get_register(rb);
1727 intptr_t result = rs_val >> (rb_val & 0x7f);
1728 set_register(ra, result);
1729 if (instr->Bit(0)) { // RC bit set
1730 SetCR0(result);
1731 }
1732 break;
1733 }
1734 #endif
1735 case SRAW: {
1736 int rs = instr->RSValue();
1737 int ra = instr->RAValue();
1738 int rb = instr->RBValue();
1739 int32_t rs_val = get_register(rs);
1740 intptr_t rb_val = get_register(rb);
1741 intptr_t result = rs_val >> (rb_val & 0x3f);
1742 set_register(ra, result);
1743 if (instr->Bit(0)) { // RC bit set
1744 SetCR0(result);
1745 }
1746 break;
1747 }
1748 #if V8_TARGET_ARCH_PPC64
1749 case SRAD: {
1750 int rs = instr->RSValue();
1751 int ra = instr->RAValue();
1752 int rb = instr->RBValue();
1753 intptr_t rs_val = get_register(rs);
1754 intptr_t rb_val = get_register(rb);
1755 intptr_t result = rs_val >> (rb_val & 0x7f);
1756 set_register(ra, result);
1757 if (instr->Bit(0)) { // RC bit set
1758 SetCR0(result);
1759 }
1760 break;
1761 }
1762 #endif
1763 case SRAWIX: {
1764 int ra = instr->RAValue();
1765 int rs = instr->RSValue();
1766 int sh = instr->Bits(15, 11);
1767 int32_t rs_val = get_register(rs);
1768 intptr_t result = rs_val >> sh;
1769 set_register(ra, result);
1770 if (instr->Bit(0)) { // RC bit set
1771 SetCR0(result);
1772 }
1773 break;
1774 }
1775 #if V8_TARGET_ARCH_PPC64
1776 case EXTSW: {
1777 const int shift = kBitsPerPointer - 32;
1778 int ra = instr->RAValue();
1779 int rs = instr->RSValue();
1780 intptr_t rs_val = get_register(rs);
1781 intptr_t ra_val = (rs_val << shift) >> shift;
1782 set_register(ra, ra_val);
1783 if (instr->Bit(0)) { // RC bit set
1784 SetCR0(ra_val);
1785 }
1786 break;
1787 }
1788 #endif
1789 case EXTSH: {
1790 const int shift = kBitsPerPointer - 16;
1791 int ra = instr->RAValue();
1792 int rs = instr->RSValue();
1793 intptr_t rs_val = get_register(rs);
1794 intptr_t ra_val = (rs_val << shift) >> shift;
1795 set_register(ra, ra_val);
1796 if (instr->Bit(0)) { // RC bit set
1797 SetCR0(ra_val);
1798 }
1799 break;
1800 }
1801 case EXTSB: {
1802 const int shift = kBitsPerPointer - 8;
1803 int ra = instr->RAValue();
1804 int rs = instr->RSValue();
1805 intptr_t rs_val = get_register(rs);
1806 intptr_t ra_val = (rs_val << shift) >> shift;
1807 set_register(ra, ra_val);
1808 if (instr->Bit(0)) { // RC bit set
1809 SetCR0(ra_val);
1810 }
1811 break;
1812 }
1813 case LFSUX:
1814 case LFSX: {
1815 int frt = instr->RTValue();
1816 int ra = instr->RAValue();
1817 int rb = instr->RBValue();
1818 intptr_t ra_val = ra == 0 ? 0 : get_register(ra);
1819 intptr_t rb_val = get_register(rb);
1820 int32_t val = ReadW(ra_val + rb_val, instr);
1821 float* fptr = reinterpret_cast<float*>(&val);
1822 set_d_register_from_double(frt, static_cast<double>(*fptr));
1823 if (opcode == LFSUX) {
1824 DCHECK(ra != 0);
1825 set_register(ra, ra_val + rb_val);
1826 }
1827 break;
1828 }
1829 case LFDUX:
1830 case LFDX: {
1831 int frt = instr->RTValue();
1832 int ra = instr->RAValue();
1833 int rb = instr->RBValue();
1834 intptr_t ra_val = ra == 0 ? 0 : get_register(ra);
1835 intptr_t rb_val = get_register(rb);
1836 double* dptr = reinterpret_cast<double*>(ReadDW(ra_val + rb_val));
1837 set_d_register_from_double(frt, *dptr);
1838 if (opcode == LFDUX) {
1839 DCHECK(ra != 0);
1840 set_register(ra, ra_val + rb_val);
1841 }
1842 break;
1843 }
1844 case STFSUX: {
1845 case STFSX:
1846 int frs = instr->RSValue();
1847 int ra = instr->RAValue();
1848 int rb = instr->RBValue();
1849 intptr_t ra_val = ra == 0 ? 0 : get_register(ra);
1850 intptr_t rb_val = get_register(rb);
1851 float frs_val = static_cast<float>(get_double_from_d_register(frs));
1852 int32_t* p = reinterpret_cast<int32_t*>(&frs_val);
1853 WriteW(ra_val + rb_val, *p, instr);
1854 if (opcode == STFSUX) {
1855 DCHECK(ra != 0);
1856 set_register(ra, ra_val + rb_val);
1857 }
1858 break;
1859 }
1860 case STFDUX: {
1861 case STFDX:
1862 int frs = instr->RSValue();
1863 int ra = instr->RAValue();
1864 int rb = instr->RBValue();
1865 intptr_t ra_val = ra == 0 ? 0 : get_register(ra);
1866 intptr_t rb_val = get_register(rb);
1867 double frs_val = get_double_from_d_register(frs);
1868 int64_t* p = reinterpret_cast<int64_t*>(&frs_val);
1869 WriteDW(ra_val + rb_val, *p);
1870 if (opcode == STFDUX) {
1871 DCHECK(ra != 0);
1872 set_register(ra, ra_val + rb_val);
1873 }
1874 break;
1875 }
1876 case SYNC: {
1877 // todo - simulate sync
1878 break;
1879 }
1880 case ICBI: {
1881 // todo - simulate icbi
1882 break;
1883 }
1884 default: {
1885 found = false;
1886 break;
1887 }
1888 }
1889
1890 if (found) return found;
1891
1892 found = true;
1893 opcode = instr->Bits(10, 2) << 2;
1894 switch (opcode) {
1895 case SRADIX: {
1896 int ra = instr->RAValue();
1897 int rs = instr->RSValue();
1898 int sh = (instr->Bits(15, 11) | (instr->Bit(1) << 5));
1899 intptr_t rs_val = get_register(rs);
1900 intptr_t result = rs_val >> sh;
1901 set_register(ra, result);
1902 if (instr->Bit(0)) { // RC bit set
1903 SetCR0(result);
1904 }
1905 break;
1906 }
1907 default: {
1908 found = false;
1909 break;
1910 }
1911 }
1912
1913 return found;
1914 }
1915
1916
1917 bool Simulator::ExecuteExt2_9bit_part1(Instruction* instr) {
1918 bool found = true;
1919
1920 int opcode = instr->Bits(9, 1) << 1;
1921 switch (opcode) {
1922 case TW: {
1923 // used for call redirection in simulation mode
1924 SoftwareInterrupt(instr);
1925 break;
1926 }
1927 case CMP: {
1928 int ra = instr->RAValue();
1929 int rb = instr->RBValue();
1930 int cr = instr->Bits(25, 23);
1931 uint32_t bf = 0;
1932 #if V8_TARGET_ARCH_PPC64
1933 int L = instr->Bit(21);
1934 if (L) {
1935 #endif
1936 intptr_t ra_val = get_register(ra);
1937 intptr_t rb_val = get_register(rb);
1938 if (ra_val < rb_val) {
1939 bf |= 0x80000000;
1940 }
1941 if (ra_val > rb_val) {
1942 bf |= 0x40000000;
1943 }
1944 if (ra_val == rb_val) {
1945 bf |= 0x20000000;
1946 }
1947 #if V8_TARGET_ARCH_PPC64
1948 } else {
1949 int32_t ra_val = get_register(ra);
1950 int32_t rb_val = get_register(rb);
1951 if (ra_val < rb_val) {
1952 bf |= 0x80000000;
1953 }
1954 if (ra_val > rb_val) {
1955 bf |= 0x40000000;
1956 }
1957 if (ra_val == rb_val) {
1958 bf |= 0x20000000;
1959 }
1960 }
1961 #endif
1962 uint32_t condition_mask = 0xF0000000U >> (cr * 4);
1963 uint32_t condition = bf >> (cr * 4);
1964 condition_reg_ = (condition_reg_ & ~condition_mask) | condition;
1965 break;
1966 }
1967 case SUBFCX: {
1968 int rt = instr->RTValue();
1969 int ra = instr->RAValue();
1970 int rb = instr->RBValue();
1971 // int oe = instr->Bit(10);
1972 uintptr_t ra_val = get_register(ra);
1973 uintptr_t rb_val = get_register(rb);
1974 uintptr_t alu_out = ~ra_val + rb_val + 1;
1975 set_register(rt, alu_out);
1976 // If the sign of rb and alu_out don't match, carry = 0
1977 if ((alu_out ^ rb_val) & 0x80000000) {
1978 special_reg_xer_ &= ~0xF0000000;
1979 } else {
1980 special_reg_xer_ = (special_reg_xer_ & ~0xF0000000) | 0x20000000;
1981 }
1982 if (instr->Bit(0)) { // RC bit set
1983 SetCR0(alu_out);
1984 }
1985 // todo - handle OE bit
1986 break;
1987 }
1988 case ADDCX: {
1989 int rt = instr->RTValue();
1990 int ra = instr->RAValue();
1991 int rb = instr->RBValue();
1992 // int oe = instr->Bit(10);
1993 uintptr_t ra_val = get_register(ra);
1994 uintptr_t rb_val = get_register(rb);
1995 uintptr_t alu_out = ra_val + rb_val;
1996 // Check overflow
1997 if (~ra_val < rb_val) {
1998 special_reg_xer_ = (special_reg_xer_ & ~0xF0000000) | 0x20000000;
1999 } else {
2000 special_reg_xer_ &= ~0xF0000000;
2001 }
2002 set_register(rt, alu_out);
2003 if (instr->Bit(0)) { // RC bit set
2004 SetCR0(static_cast<intptr_t>(alu_out));
2005 }
2006 // todo - handle OE bit
2007 break;
2008 }
2009 case MULHWX: {
2010 int rt = instr->RTValue();
2011 int ra = instr->RAValue();
2012 int rb = instr->RBValue();
2013 int32_t ra_val = (get_register(ra) & 0xFFFFFFFF);
2014 int32_t rb_val = (get_register(rb) & 0xFFFFFFFF);
2015 int64_t alu_out = (int64_t)ra_val * (int64_t)rb_val;
2016 alu_out >>= 32;
2017 set_register(rt, alu_out);
2018 if (instr->Bit(0)) { // RC bit set
2019 SetCR0(static_cast<intptr_t>(alu_out));
2020 }
2021 // todo - handle OE bit
2022 break;
2023 }
2024 case NEGX: {
2025 int rt = instr->RTValue();
2026 int ra = instr->RAValue();
2027 intptr_t ra_val = get_register(ra);
2028 intptr_t alu_out = 1 + ~ra_val;
2029 #if V8_TARGET_ARCH_PPC64
2030 intptr_t one = 1; // work-around gcc
2031 intptr_t kOverflowVal = (one << 63);
2032 #else
2033 intptr_t kOverflowVal = kMinInt;
2034 #endif
2035 set_register(rt, alu_out);
2036 if (instr->Bit(10)) { // OE bit set
2037 if (ra_val == kOverflowVal) {
2038 special_reg_xer_ |= 0xC0000000; // set SO,OV
2039 } else {
2040 special_reg_xer_ &= ~0x40000000; // clear OV
2041 }
2042 }
2043 if (instr->Bit(0)) { // RC bit set
2044 bool setSO = (special_reg_xer_ & 0x80000000);
2045 SetCR0(alu_out, setSO);
2046 }
2047 break;
2048 }
2049 case SLWX: {
2050 int rs = instr->RSValue();
2051 int ra = instr->RAValue();
2052 int rb = instr->RBValue();
2053 uint32_t rs_val = get_register(rs);
2054 uintptr_t rb_val = get_register(rb);
2055 uint32_t result = rs_val << (rb_val & 0x3f);
2056 set_register(ra, result);
2057 if (instr->Bit(0)) { // RC bit set
2058 SetCR0(result);
2059 }
2060 break;
2061 }
2062 #if V8_TARGET_ARCH_PPC64
2063 case SLDX: {
2064 int rs = instr->RSValue();
2065 int ra = instr->RAValue();
2066 int rb = instr->RBValue();
2067 uintptr_t rs_val = get_register(rs);
2068 uintptr_t rb_val = get_register(rb);
2069 uintptr_t result = rs_val << (rb_val & 0x7f);
2070 set_register(ra, result);
2071 if (instr->Bit(0)) { // RC bit set
2072 SetCR0(result);
2073 }
2074 break;
2075 }
2076 case MFVSRD: {
2077 DCHECK(!instr->Bit(0));
2078 int frt = instr->RTValue();
2079 int ra = instr->RAValue();
2080 double frt_val = get_double_from_d_register(frt);
2081 int64_t* p = reinterpret_cast<int64_t*>(&frt_val);
2082 set_register(ra, *p);
2083 break;
2084 }
2085 case MFVSRWZ: {
2086 DCHECK(!instr->Bit(0));
2087 int frt = instr->RTValue();
2088 int ra = instr->RAValue();
2089 double frt_val = get_double_from_d_register(frt);
2090 int64_t* p = reinterpret_cast<int64_t*>(&frt_val);
2091 set_register(ra, static_cast<uint32_t>(*p));
2092 break;
2093 }
2094 case MTVSRD: {
2095 DCHECK(!instr->Bit(0));
2096 int frt = instr->RTValue();
2097 int ra = instr->RAValue();
2098 int64_t ra_val = get_register(ra);
2099 double* p = reinterpret_cast<double*>(&ra_val);
2100 set_d_register_from_double(frt, *p);
2101 break;
2102 }
2103 case MTVSRWA: {
2104 DCHECK(!instr->Bit(0));
2105 int frt = instr->RTValue();
2106 int ra = instr->RAValue();
2107 int64_t ra_val = static_cast<int32_t>(get_register(ra));
2108 double* p = reinterpret_cast<double*>(&ra_val);
2109 set_d_register_from_double(frt, *p);
2110 break;
2111 }
2112 case MTVSRWZ: {
2113 DCHECK(!instr->Bit(0));
2114 int frt = instr->RTValue();
2115 int ra = instr->RAValue();
2116 uint64_t ra_val = static_cast<uint32_t>(get_register(ra));
2117 double* p = reinterpret_cast<double*>(&ra_val);
2118 set_d_register_from_double(frt, *p);
2119 break;
2120 }
2121 #endif
2122 default: {
2123 found = false;
2124 break;
2125 }
2126 }
2127
2128 return found;
2129 }
2130
2131
2132 void Simulator::ExecuteExt2_9bit_part2(Instruction* instr) {
2133 int opcode = instr->Bits(9, 1) << 1;
2134 switch (opcode) {
2135 case CNTLZWX: {
2136 int rs = instr->RSValue();
2137 int ra = instr->RAValue();
2138 uintptr_t rs_val = get_register(rs);
2139 uintptr_t count = 0;
2140 int n = 0;
2141 uintptr_t bit = 0x80000000;
2142 for (; n < 32; n++) {
2143 if (bit & rs_val) break;
2144 count++;
2145 bit >>= 1;
2146 }
2147 set_register(ra, count);
2148 if (instr->Bit(0)) { // RC Bit set
2149 int bf = 0;
2150 if (count > 0) {
2151 bf |= 0x40000000;
2152 }
2153 if (count == 0) {
2154 bf |= 0x20000000;
2155 }
2156 condition_reg_ = (condition_reg_ & ~0xF0000000) | bf;
2157 }
2158 break;
2159 }
2160 #if V8_TARGET_ARCH_PPC64
2161 case CNTLZDX: {
2162 int rs = instr->RSValue();
2163 int ra = instr->RAValue();
2164 uintptr_t rs_val = get_register(rs);
2165 uintptr_t count = 0;
2166 int n = 0;
2167 uintptr_t bit = 0x8000000000000000UL;
2168 for (; n < 64; n++) {
2169 if (bit & rs_val) break;
2170 count++;
2171 bit >>= 1;
2172 }
2173 set_register(ra, count);
2174 if (instr->Bit(0)) { // RC Bit set
2175 int bf = 0;
2176 if (count > 0) {
2177 bf |= 0x40000000;
2178 }
2179 if (count == 0) {
2180 bf |= 0x20000000;
2181 }
2182 condition_reg_ = (condition_reg_ & ~0xF0000000) | bf;
2183 }
2184 break;
2185 }
2186 #endif
2187 case ANDX: {
2188 int rs = instr->RSValue();
2189 int ra = instr->RAValue();
2190 int rb = instr->RBValue();
2191 intptr_t rs_val = get_register(rs);
2192 intptr_t rb_val = get_register(rb);
2193 intptr_t alu_out = rs_val & rb_val;
2194 set_register(ra, alu_out);
2195 if (instr->Bit(0)) { // RC Bit set
2196 SetCR0(alu_out);
2197 }
2198 break;
2199 }
2200 case ANDCX: {
2201 int rs = instr->RSValue();
2202 int ra = instr->RAValue();
2203 int rb = instr->RBValue();
2204 intptr_t rs_val = get_register(rs);
2205 intptr_t rb_val = get_register(rb);
2206 intptr_t alu_out = rs_val & ~rb_val;
2207 set_register(ra, alu_out);
2208 if (instr->Bit(0)) { // RC Bit set
2209 SetCR0(alu_out);
2210 }
2211 break;
2212 }
2213 case CMPL: {
2214 int ra = instr->RAValue();
2215 int rb = instr->RBValue();
2216 int cr = instr->Bits(25, 23);
2217 uint32_t bf = 0;
2218 #if V8_TARGET_ARCH_PPC64
2219 int L = instr->Bit(21);
2220 if (L) {
2221 #endif
2222 uintptr_t ra_val = get_register(ra);
2223 uintptr_t rb_val = get_register(rb);
2224 if (ra_val < rb_val) {
2225 bf |= 0x80000000;
2226 }
2227 if (ra_val > rb_val) {
2228 bf |= 0x40000000;
2229 }
2230 if (ra_val == rb_val) {
2231 bf |= 0x20000000;
2232 }
2233 #if V8_TARGET_ARCH_PPC64
2234 } else {
2235 uint32_t ra_val = get_register(ra);
2236 uint32_t rb_val = get_register(rb);
2237 if (ra_val < rb_val) {
2238 bf |= 0x80000000;
2239 }
2240 if (ra_val > rb_val) {
2241 bf |= 0x40000000;
2242 }
2243 if (ra_val == rb_val) {
2244 bf |= 0x20000000;
2245 }
2246 }
2247 #endif
2248 uint32_t condition_mask = 0xF0000000U >> (cr * 4);
2249 uint32_t condition = bf >> (cr * 4);
2250 condition_reg_ = (condition_reg_ & ~condition_mask) | condition;
2251 break;
2252 }
2253 case SUBFX: {
2254 int rt = instr->RTValue();
2255 int ra = instr->RAValue();
2256 int rb = instr->RBValue();
2257 // int oe = instr->Bit(10);
2258 intptr_t ra_val = get_register(ra);
2259 intptr_t rb_val = get_register(rb);
2260 intptr_t alu_out = rb_val - ra_val;
2261 // todo - figure out underflow
2262 set_register(rt, alu_out);
2263 if (instr->Bit(0)) { // RC Bit set
2264 SetCR0(alu_out);
2265 }
2266 // todo - handle OE bit
2267 break;
2268 }
2269 case ADDZEX: {
2270 int rt = instr->RTValue();
2271 int ra = instr->RAValue();
2272 intptr_t ra_val = get_register(ra);
2273 if (special_reg_xer_ & 0x20000000) {
2274 ra_val += 1;
2275 }
2276 set_register(rt, ra_val);
2277 if (instr->Bit(0)) { // RC bit set
2278 SetCR0(ra_val);
2279 }
2280 // todo - handle OE bit
2281 break;
2282 }
2283 case NORX: {
2284 int rs = instr->RSValue();
2285 int ra = instr->RAValue();
2286 int rb = instr->RBValue();
2287 intptr_t rs_val = get_register(rs);
2288 intptr_t rb_val = get_register(rb);
2289 intptr_t alu_out = ~(rs_val | rb_val);
2290 set_register(ra, alu_out);
2291 if (instr->Bit(0)) { // RC bit set
2292 SetCR0(alu_out);
2293 }
2294 break;
2295 }
2296 case MULLW: {
2297 int rt = instr->RTValue();
2298 int ra = instr->RAValue();
2299 int rb = instr->RBValue();
2300 int32_t ra_val = (get_register(ra) & 0xFFFFFFFF);
2301 int32_t rb_val = (get_register(rb) & 0xFFFFFFFF);
2302 int32_t alu_out = ra_val * rb_val;
2303 set_register(rt, alu_out);
2304 if (instr->Bit(0)) { // RC bit set
2305 SetCR0(alu_out);
2306 }
2307 // todo - handle OE bit
2308 break;
2309 }
2310 #if V8_TARGET_ARCH_PPC64
2311 case MULLD: {
2312 int rt = instr->RTValue();
2313 int ra = instr->RAValue();
2314 int rb = instr->RBValue();
2315 int64_t ra_val = get_register(ra);
2316 int64_t rb_val = get_register(rb);
2317 int64_t alu_out = ra_val * rb_val;
2318 set_register(rt, alu_out);
2319 if (instr->Bit(0)) { // RC bit set
2320 SetCR0(alu_out);
2321 }
2322 // todo - handle OE bit
2323 break;
2324 }
2325 #endif
2326 case DIVW: {
2327 int rt = instr->RTValue();
2328 int ra = instr->RAValue();
2329 int rb = instr->RBValue();
2330 int32_t ra_val = get_register(ra);
2331 int32_t rb_val = get_register(rb);
2332 bool overflow = (ra_val == kMinInt && rb_val == -1);
2333 // result is undefined if divisor is zero or if operation
2334 // is 0x80000000 / -1.
2335 int32_t alu_out = (rb_val == 0 || overflow) ? -1 : ra_val / rb_val;
2336 set_register(rt, alu_out);
2337 if (instr->Bit(10)) { // OE bit set
2338 if (overflow) {
2339 special_reg_xer_ |= 0xC0000000; // set SO,OV
2340 } else {
2341 special_reg_xer_ &= ~0x40000000; // clear OV
2342 }
2343 }
2344 if (instr->Bit(0)) { // RC bit set
2345 bool setSO = (special_reg_xer_ & 0x80000000);
2346 SetCR0(alu_out, setSO);
2347 }
2348 break;
2349 }
2350 #if V8_TARGET_ARCH_PPC64
2351 case DIVD: {
2352 int rt = instr->RTValue();
2353 int ra = instr->RAValue();
2354 int rb = instr->RBValue();
2355 int64_t ra_val = get_register(ra);
2356 int64_t rb_val = get_register(rb);
2357 int64_t one = 1; // work-around gcc
2358 int64_t kMinLongLong = (one << 63);
2359 // result is undefined if divisor is zero or if operation
2360 // is 0x80000000_00000000 / -1.
2361 int64_t alu_out =
2362 (rb_val == 0 || (ra_val == kMinLongLong && rb_val == -1))
2363 ? -1
2364 : ra_val / rb_val;
2365 set_register(rt, alu_out);
2366 if (instr->Bit(0)) { // RC bit set
2367 SetCR0(alu_out);
2368 }
2369 // todo - handle OE bit
2370 break;
2371 }
2372 #endif
2373 case ADDX: {
2374 int rt = instr->RTValue();
2375 int ra = instr->RAValue();
2376 int rb = instr->RBValue();
2377 // int oe = instr->Bit(10);
2378 intptr_t ra_val = get_register(ra);
2379 intptr_t rb_val = get_register(rb);
2380 intptr_t alu_out = ra_val + rb_val;
2381 set_register(rt, alu_out);
2382 if (instr->Bit(0)) { // RC bit set
2383 SetCR0(alu_out);
2384 }
2385 // todo - handle OE bit
2386 break;
2387 }
2388 case XORX: {
2389 int rs = instr->RSValue();
2390 int ra = instr->RAValue();
2391 int rb = instr->RBValue();
2392 intptr_t rs_val = get_register(rs);
2393 intptr_t rb_val = get_register(rb);
2394 intptr_t alu_out = rs_val ^ rb_val;
2395 set_register(ra, alu_out);
2396 if (instr->Bit(0)) { // RC bit set
2397 SetCR0(alu_out);
2398 }
2399 break;
2400 }
2401 case ORX: {
2402 int rs = instr->RSValue();
2403 int ra = instr->RAValue();
2404 int rb = instr->RBValue();
2405 intptr_t rs_val = get_register(rs);
2406 intptr_t rb_val = get_register(rb);
2407 intptr_t alu_out = rs_val | rb_val;
2408 set_register(ra, alu_out);
2409 if (instr->Bit(0)) { // RC bit set
2410 SetCR0(alu_out);
2411 }
2412 break;
2413 }
2414 case MFSPR: {
2415 int rt = instr->RTValue();
2416 int spr = instr->Bits(20, 11);
2417 if (spr != 256) {
2418 UNIMPLEMENTED(); // Only LRLR supported
2419 }
2420 set_register(rt, special_reg_lr_);
2421 break;
2422 }
2423 case MTSPR: {
2424 int rt = instr->RTValue();
2425 intptr_t rt_val = get_register(rt);
2426 int spr = instr->Bits(20, 11);
2427 if (spr == 256) {
2428 special_reg_lr_ = rt_val;
2429 } else if (spr == 288) {
2430 special_reg_ctr_ = rt_val;
2431 } else if (spr == 32) {
2432 special_reg_xer_ = rt_val;
2433 } else {
2434 UNIMPLEMENTED(); // Only LR supported
2435 }
2436 break;
2437 }
2438 case MFCR: {
2439 int rt = instr->RTValue();
2440 set_register(rt, condition_reg_);
2441 break;
2442 }
2443 case STWUX:
2444 case STWX: {
2445 int rs = instr->RSValue();
2446 int ra = instr->RAValue();
2447 int rb = instr->RBValue();
2448 intptr_t ra_val = ra == 0 ? 0 : get_register(ra);
2449 int32_t rs_val = get_register(rs);
2450 intptr_t rb_val = get_register(rb);
2451 WriteW(ra_val + rb_val, rs_val, instr);
2452 if (opcode == STWUX) {
2453 DCHECK(ra != 0);
2454 set_register(ra, ra_val + rb_val);
2455 }
2456 break;
2457 }
2458 case STBUX:
2459 case STBX: {
2460 int rs = instr->RSValue();
2461 int ra = instr->RAValue();
2462 int rb = instr->RBValue();
2463 intptr_t ra_val = ra == 0 ? 0 : get_register(ra);
2464 int8_t rs_val = get_register(rs);
2465 intptr_t rb_val = get_register(rb);
2466 WriteB(ra_val + rb_val, rs_val);
2467 if (opcode == STBUX) {
2468 DCHECK(ra != 0);
2469 set_register(ra, ra_val + rb_val);
2470 }
2471 break;
2472 }
2473 case STHUX:
2474 case STHX: {
2475 int rs = instr->RSValue();
2476 int ra = instr->RAValue();
2477 int rb = instr->RBValue();
2478 intptr_t ra_val = ra == 0 ? 0 : get_register(ra);
2479 int16_t rs_val = get_register(rs);
2480 intptr_t rb_val = get_register(rb);
2481 WriteH(ra_val + rb_val, rs_val, instr);
2482 if (opcode == STHUX) {
2483 DCHECK(ra != 0);
2484 set_register(ra, ra_val + rb_val);
2485 }
2486 break;
2487 }
2488 case LWZX:
2489 case LWZUX: {
2490 int rt = instr->RTValue();
2491 int ra = instr->RAValue();
2492 int rb = instr->RBValue();
2493 intptr_t ra_val = ra == 0 ? 0 : get_register(ra);
2494 intptr_t rb_val = get_register(rb);
2495 set_register(rt, ReadWU(ra_val + rb_val, instr));
2496 if (opcode == LWZUX) {
2497 DCHECK(ra != 0 && ra != rt);
2498 set_register(ra, ra_val + rb_val);
2499 }
2500 break;
2501 }
2502 #if V8_TARGET_ARCH_PPC64
2503 case LDX:
2504 case LDUX: {
2505 int rt = instr->RTValue();
2506 int ra = instr->RAValue();
2507 int rb = instr->RBValue();
2508 intptr_t ra_val = ra == 0 ? 0 : get_register(ra);
2509 intptr_t rb_val = get_register(rb);
2510 intptr_t* result = ReadDW(ra_val + rb_val);
2511 set_register(rt, *result);
2512 if (opcode == LDUX) {
2513 DCHECK(ra != 0 && ra != rt);
2514 set_register(ra, ra_val + rb_val);
2515 }
2516 break;
2517 }
2518 case STDX:
2519 case STDUX: {
2520 int rs = instr->RSValue();
2521 int ra = instr->RAValue();
2522 int rb = instr->RBValue();
2523 intptr_t ra_val = ra == 0 ? 0 : get_register(ra);
2524 intptr_t rs_val = get_register(rs);
2525 intptr_t rb_val = get_register(rb);
2526 WriteDW(ra_val + rb_val, rs_val);
2527 if (opcode == STDUX) {
2528 DCHECK(ra != 0);
2529 set_register(ra, ra_val + rb_val);
2530 }
2531 break;
2532 }
2533 #endif
2534 case LBZX:
2535 case LBZUX: {
2536 int rt = instr->RTValue();
2537 int ra = instr->RAValue();
2538 int rb = instr->RBValue();
2539 intptr_t ra_val = ra == 0 ? 0 : get_register(ra);
2540 intptr_t rb_val = get_register(rb);
2541 set_register(rt, ReadBU(ra_val + rb_val) & 0xFF);
2542 if (opcode == LBZUX) {
2543 DCHECK(ra != 0 && ra != rt);
2544 set_register(ra, ra_val + rb_val);
2545 }
2546 break;
2547 }
2548 case LHZX:
2549 case LHZUX: {
2550 int rt = instr->RTValue();
2551 int ra = instr->RAValue();
2552 int rb = instr->RBValue();
2553 intptr_t ra_val = ra == 0 ? 0 : get_register(ra);
2554 intptr_t rb_val = get_register(rb);
2555 set_register(rt, ReadHU(ra_val + rb_val, instr) & 0xFFFF);
2556 if (opcode == LHZUX) {
2557 DCHECK(ra != 0 && ra != rt);
2558 set_register(ra, ra_val + rb_val);
2559 }
2560 break;
2561 }
2562 case DCBF: {
2563 // todo - simulate dcbf
2564 break;
2565 }
2566 default: {
2567 PrintF("Unimplemented: %08x\n", instr->InstructionBits());
2568 UNIMPLEMENTED(); // Not used by V8.
2569 }
2570 }
2571 }
2572
2573
2574 void Simulator::ExecuteExt2(Instruction* instr) {
2575 // Check first the 10-1 bit versions
2576 if (ExecuteExt2_10bit(instr)) return;
2577 // Now look at the lesser encodings
2578 if (ExecuteExt2_9bit_part1(instr)) return;
2579 ExecuteExt2_9bit_part2(instr);
2580 }
2581
2582
2583 void Simulator::ExecuteExt4(Instruction* instr) {
2584 switch (instr->Bits(5, 1) << 1) {
2585 case FDIV: {
2586 int frt = instr->RTValue();
2587 int fra = instr->RAValue();
2588 int frb = instr->RBValue();
2589 double fra_val = get_double_from_d_register(fra);
2590 double frb_val = get_double_from_d_register(frb);
2591 double frt_val = fra_val / frb_val;
2592 set_d_register_from_double(frt, frt_val);
2593 return;
2594 }
2595 case FSUB: {
2596 int frt = instr->RTValue();
2597 int fra = instr->RAValue();
2598 int frb = instr->RBValue();
2599 double fra_val = get_double_from_d_register(fra);
2600 double frb_val = get_double_from_d_register(frb);
2601 double frt_val = fra_val - frb_val;
2602 set_d_register_from_double(frt, frt_val);
2603 return;
2604 }
2605 case FADD: {
2606 int frt = instr->RTValue();
2607 int fra = instr->RAValue();
2608 int frb = instr->RBValue();
2609 double fra_val = get_double_from_d_register(fra);
2610 double frb_val = get_double_from_d_register(frb);
2611 double frt_val = fra_val + frb_val;
2612 set_d_register_from_double(frt, frt_val);
2613 return;
2614 }
2615 case FSQRT: {
2616 int frt = instr->RTValue();
2617 int frb = instr->RBValue();
2618 double frb_val = get_double_from_d_register(frb);
2619 double frt_val = std::sqrt(frb_val);
2620 set_d_register_from_double(frt, frt_val);
2621 return;
2622 }
2623 case FSEL: {
2624 int frt = instr->RTValue();
2625 int fra = instr->RAValue();
2626 int frb = instr->RBValue();
2627 int frc = instr->RCValue();
2628 double fra_val = get_double_from_d_register(fra);
2629 double frb_val = get_double_from_d_register(frb);
2630 double frc_val = get_double_from_d_register(frc);
2631 double frt_val = ((fra_val >= 0.0) ? frc_val : frb_val);
2632 set_d_register_from_double(frt, frt_val);
2633 return;
2634 }
2635 case FMUL: {
2636 int frt = instr->RTValue();
2637 int fra = instr->RAValue();
2638 int frc = instr->RCValue();
2639 double fra_val = get_double_from_d_register(fra);
2640 double frc_val = get_double_from_d_register(frc);
2641 double frt_val = fra_val * frc_val;
2642 set_d_register_from_double(frt, frt_val);
2643 return;
2644 }
2645 case FMSUB: {
2646 int frt = instr->RTValue();
2647 int fra = instr->RAValue();
2648 int frb = instr->RBValue();
2649 int frc = instr->RCValue();
2650 double fra_val = get_double_from_d_register(fra);
2651 double frb_val = get_double_from_d_register(frb);
2652 double frc_val = get_double_from_d_register(frc);
2653 double frt_val = (fra_val * frc_val) - frb_val;
2654 set_d_register_from_double(frt, frt_val);
2655 return;
2656 }
2657 case FMADD: {
2658 int frt = instr->RTValue();
2659 int fra = instr->RAValue();
2660 int frb = instr->RBValue();
2661 int frc = instr->RCValue();
2662 double fra_val = get_double_from_d_register(fra);
2663 double frb_val = get_double_from_d_register(frb);
2664 double frc_val = get_double_from_d_register(frc);
2665 double frt_val = (fra_val * frc_val) + frb_val;
2666 set_d_register_from_double(frt, frt_val);
2667 return;
2668 }
2669 }
2670 int opcode = instr->Bits(10, 1) << 1;
2671 switch (opcode) {
2672 case FCMPU: {
2673 int fra = instr->RAValue();
2674 int frb = instr->RBValue();
2675 double fra_val = get_double_from_d_register(fra);
2676 double frb_val = get_double_from_d_register(frb);
2677 int cr = instr->Bits(25, 23);
2678 int bf = 0;
2679 if (fra_val < frb_val) {
2680 bf |= 0x80000000;
2681 }
2682 if (fra_val > frb_val) {
2683 bf |= 0x40000000;
2684 }
2685 if (fra_val == frb_val) {
2686 bf |= 0x20000000;
2687 }
2688 if (std::isunordered(fra_val, frb_val)) {
2689 bf |= 0x10000000;
2690 }
2691 int condition_mask = 0xF0000000 >> (cr * 4);
2692 int condition = bf >> (cr * 4);
2693 condition_reg_ = (condition_reg_ & ~condition_mask) | condition;
2694 return;
2695 }
2696 case FRSP: {
2697 int frt = instr->RTValue();
2698 int frb = instr->RBValue();
2699 double frb_val = get_double_from_d_register(frb);
2700 // frsp round 8-byte double-precision value to 8-byte
2701 // single-precision value, ignore the round here
2702 set_d_register_from_double(frt, frb_val);
2703 if (instr->Bit(0)) { // RC bit set
2704 // UNIMPLEMENTED();
2705 }
2706 return;
2707 }
2708 case FCFID: {
2709 int frt = instr->RTValue();
2710 int frb = instr->RBValue();
2711 double t_val = get_double_from_d_register(frb);
2712 int64_t* frb_val_p = reinterpret_cast<int64_t*>(&t_val);
2713 double frt_val = static_cast<double>(*frb_val_p);
2714 set_d_register_from_double(frt, frt_val);
2715 return;
2716 }
2717 case FCTID: {
2718 int frt = instr->RTValue();
2719 int frb = instr->RBValue();
2720 double frb_val = get_double_from_d_register(frb);
2721 int64_t frt_val;
2722 int64_t one = 1; // work-around gcc
2723 int64_t kMinLongLong = (one << 63);
2724 int64_t kMaxLongLong = kMinLongLong - 1;
2725
2726 if (frb_val > kMaxLongLong) {
2727 frt_val = kMaxLongLong;
2728 } else if (frb_val < kMinLongLong) {
2729 frt_val = kMinLongLong;
2730 } else {
2731 switch (fp_condition_reg_ & kFPRoundingModeMask) {
2732 case kRoundToZero:
2733 frt_val = (int64_t)frb_val;
2734 break;
2735 case kRoundToPlusInf:
2736 frt_val = (int64_t)std::ceil(frb_val);
2737 break;
2738 case kRoundToMinusInf:
2739 frt_val = (int64_t)std::floor(frb_val);
2740 break;
2741 default:
2742 frt_val = (int64_t)frb_val;
2743 UNIMPLEMENTED(); // Not used by V8.
2744 break;
2745 }
2746 }
2747 double* p = reinterpret_cast<double*>(&frt_val);
2748 set_d_register_from_double(frt, *p);
2749 return;
2750 }
2751 case FCTIDZ: {
2752 int frt = instr->RTValue();
2753 int frb = instr->RBValue();
2754 double frb_val = get_double_from_d_register(frb);
2755 int64_t frt_val;
2756 int64_t one = 1; // work-around gcc
2757 int64_t kMinLongLong = (one << 63);
2758 int64_t kMaxLongLong = kMinLongLong - 1;
2759
2760 if (frb_val > kMaxLongLong) {
2761 frt_val = kMaxLongLong;
2762 } else if (frb_val < kMinLongLong) {
2763 frt_val = kMinLongLong;
2764 } else {
2765 frt_val = (int64_t)frb_val;
2766 }
2767 double* p = reinterpret_cast<double*>(&frt_val);
2768 set_d_register_from_double(frt, *p);
2769 return;
2770 }
2771 case FCTIW:
2772 case FCTIWZ: {
2773 int frt = instr->RTValue();
2774 int frb = instr->RBValue();
2775 double frb_val = get_double_from_d_register(frb);
2776 int64_t frt_val;
2777 if (frb_val > kMaxInt) {
2778 frt_val = kMaxInt;
2779 } else if (frb_val < kMinInt) {
2780 frt_val = kMinInt;
2781 } else {
2782 if (opcode == FCTIWZ) {
2783 frt_val = (int64_t)frb_val;
2784 } else {
2785 switch (fp_condition_reg_ & kFPRoundingModeMask) {
2786 case kRoundToZero:
2787 frt_val = (int64_t)frb_val;
2788 break;
2789 case kRoundToPlusInf:
2790 frt_val = (int64_t)std::ceil(frb_val);
2791 break;
2792 case kRoundToMinusInf:
2793 frt_val = (int64_t)std::floor(frb_val);
2794 break;
2795 case kRoundToNearest:
2796 frt_val = (int64_t)lround(frb_val);
2797
2798 // Round to even if exactly halfway. (lround rounds up)
2799 if (std::fabs(static_cast<double>(frt_val) - frb_val) == 0.5 &&
2800 (frt_val % 2)) {
2801 frt_val += ((frt_val > 0) ? -1 : 1);
2802 }
2803
2804 break;
2805 default:
2806 DCHECK(false);
2807 frt_val = (int64_t)frb_val;
2808 break;
2809 }
2810 }
2811 }
2812 double* p = reinterpret_cast<double*>(&frt_val);
2813 set_d_register_from_double(frt, *p);
2814 return;
2815 }
2816 case FNEG: {
2817 int frt = instr->RTValue();
2818 int frb = instr->RBValue();
2819 double frb_val = get_double_from_d_register(frb);
2820 double frt_val = -frb_val;
2821 set_d_register_from_double(frt, frt_val);
2822 return;
2823 }
2824 case FMR: {
2825 int frt = instr->RTValue();
2826 int frb = instr->RBValue();
2827 double frb_val = get_double_from_d_register(frb);
2828 double frt_val = frb_val;
2829 set_d_register_from_double(frt, frt_val);
2830 return;
2831 }
2832 case MTFSFI: {
2833 int bf = instr->Bits(25, 23);
2834 int imm = instr->Bits(15, 12);
2835 int fp_condition_mask = 0xF0000000 >> (bf * 4);
2836 fp_condition_reg_ &= ~fp_condition_mask;
2837 fp_condition_reg_ |= (imm << (28 - (bf * 4)));
2838 if (instr->Bit(0)) { // RC bit set
2839 condition_reg_ &= 0xF0FFFFFF;
2840 condition_reg_ |= (imm << 23);
2841 }
2842 return;
2843 }
2844 case MTFSF: {
2845 int frb = instr->RBValue();
2846 double frb_dval = get_double_from_d_register(frb);
2847 int64_t* p = reinterpret_cast<int64_t*>(&frb_dval);
2848 int32_t frb_ival = static_cast<int32_t>((*p) & 0xffffffff);
2849 int l = instr->Bits(25, 25);
2850 if (l == 1) {
2851 fp_condition_reg_ = frb_ival;
2852 } else {
2853 UNIMPLEMENTED();
2854 }
2855 if (instr->Bit(0)) { // RC bit set
2856 UNIMPLEMENTED();
2857 // int w = instr->Bits(16, 16);
2858 // int flm = instr->Bits(24, 17);
2859 }
2860 return;
2861 }
2862 case MFFS: {
2863 int frt = instr->RTValue();
2864 int64_t lval = static_cast<int64_t>(fp_condition_reg_);
2865 double* p = reinterpret_cast<double*>(&lval);
2866 set_d_register_from_double(frt, *p);
2867 return;
2868 }
2869 case FABS: {
2870 int frt = instr->RTValue();
2871 int frb = instr->RBValue();
2872 double frb_val = get_double_from_d_register(frb);
2873 double frt_val = std::fabs(frb_val);
2874 set_d_register_from_double(frt, frt_val);
2875 return;
2876 }
2877 case FRIM: {
2878 int frt = instr->RTValue();
2879 int frb = instr->RBValue();
2880 double frb_val = get_double_from_d_register(frb);
2881 int64_t floor_val = (int64_t)frb_val;
2882 if (floor_val > frb_val) floor_val--;
2883 double frt_val = static_cast<double>(floor_val);
2884 set_d_register_from_double(frt, frt_val);
2885 return;
2886 }
2887 }
2888 UNIMPLEMENTED(); // Not used by V8.
2889 }
2890
2891 #if V8_TARGET_ARCH_PPC64
2892 void Simulator::ExecuteExt5(Instruction* instr) {
2893 switch (instr->Bits(4, 2) << 2) {
2894 case RLDICL: {
2895 int ra = instr->RAValue();
2896 int rs = instr->RSValue();
2897 uintptr_t rs_val = get_register(rs);
2898 int sh = (instr->Bits(15, 11) | (instr->Bit(1) << 5));
2899 int mb = (instr->Bits(10, 6) | (instr->Bit(5) << 5));
2900 DCHECK(sh >= 0 && sh <= 63);
2901 DCHECK(mb >= 0 && mb <= 63);
2902 // rotate left
2903 uintptr_t result = (rs_val << sh) | (rs_val >> (64 - sh));
2904 uintptr_t mask = 0xffffffffffffffff >> mb;
2905 result &= mask;
2906 set_register(ra, result);
2907 if (instr->Bit(0)) { // RC bit set
2908 SetCR0(result);
2909 }
2910 return;
2911 }
2912 case RLDICR: {
2913 int ra = instr->RAValue();
2914 int rs = instr->RSValue();
2915 uintptr_t rs_val = get_register(rs);
2916 int sh = (instr->Bits(15, 11) | (instr->Bit(1) << 5));
2917 int me = (instr->Bits(10, 6) | (instr->Bit(5) << 5));
2918 DCHECK(sh >= 0 && sh <= 63);
2919 DCHECK(me >= 0 && me <= 63);
2920 // rotate left
2921 uintptr_t result = (rs_val << sh) | (rs_val >> (64 - sh));
2922 uintptr_t mask = 0xffffffffffffffff << (63 - me);
2923 result &= mask;
2924 set_register(ra, result);
2925 if (instr->Bit(0)) { // RC bit set
2926 SetCR0(result);
2927 }
2928 return;
2929 }
2930 case RLDIC: {
2931 int ra = instr->RAValue();
2932 int rs = instr->RSValue();
2933 uintptr_t rs_val = get_register(rs);
2934 int sh = (instr->Bits(15, 11) | (instr->Bit(1) << 5));
2935 int mb = (instr->Bits(10, 6) | (instr->Bit(5) << 5));
2936 DCHECK(sh >= 0 && sh <= 63);
2937 DCHECK(mb >= 0 && mb <= 63);
2938 // rotate left
2939 uintptr_t result = (rs_val << sh) | (rs_val >> (64 - sh));
2940 uintptr_t mask = (0xffffffffffffffff >> mb) & (0xffffffffffffffff << sh);
2941 result &= mask;
2942 set_register(ra, result);
2943 if (instr->Bit(0)) { // RC bit set
2944 SetCR0(result);
2945 }
2946 return;
2947 }
2948 case RLDIMI: {
2949 int ra = instr->RAValue();
2950 int rs = instr->RSValue();
2951 uintptr_t rs_val = get_register(rs);
2952 intptr_t ra_val = get_register(ra);
2953 int sh = (instr->Bits(15, 11) | (instr->Bit(1) << 5));
2954 int mb = (instr->Bits(10, 6) | (instr->Bit(5) << 5));
2955 int me = 63 - sh;
2956 // rotate left
2957 uintptr_t result = (rs_val << sh) | (rs_val >> (64 - sh));
2958 uintptr_t mask = 0;
2959 if (mb < me + 1) {
2960 uintptr_t bit = 0x8000000000000000 >> mb;
2961 for (; mb <= me; mb++) {
2962 mask |= bit;
2963 bit >>= 1;
2964 }
2965 } else if (mb == me + 1) {
2966 mask = 0xffffffffffffffff;
2967 } else { // mb > me+1
2968 uintptr_t bit = 0x8000000000000000 >> (me + 1); // needs to be tested
2969 mask = 0xffffffffffffffff;
2970 for (; me < mb; me++) {
2971 mask ^= bit;
2972 bit >>= 1;
2973 }
2974 }
2975 result &= mask;
2976 ra_val &= ~mask;
2977 result |= ra_val;
2978 set_register(ra, result);
2979 if (instr->Bit(0)) { // RC bit set
2980 SetCR0(result);
2981 }
2982 return;
2983 }
2984 }
2985 switch (instr->Bits(4, 1) << 1) {
2986 case RLDCL: {
2987 int ra = instr->RAValue();
2988 int rs = instr->RSValue();
2989 int rb = instr->RBValue();
2990 uintptr_t rs_val = get_register(rs);
2991 uintptr_t rb_val = get_register(rb);
2992 int sh = (rb_val & 0x3f);
2993 int mb = (instr->Bits(10, 6) | (instr->Bit(5) << 5));
2994 DCHECK(sh >= 0 && sh <= 63);
2995 DCHECK(mb >= 0 && mb <= 63);
2996 // rotate left
2997 uintptr_t result = (rs_val << sh) | (rs_val >> (64 - sh));
2998 uintptr_t mask = 0xffffffffffffffff >> mb;
2999 result &= mask;
3000 set_register(ra, result);
3001 if (instr->Bit(0)) { // RC bit set
3002 SetCR0(result);
3003 }
3004 return;
3005 }
3006 }
3007 UNIMPLEMENTED(); // Not used by V8.
3008 }
3009 #endif
3010
3011
3012 void Simulator::ExecuteGeneric(Instruction* instr) {
3013 int opcode = instr->OpcodeValue() << 26;
3014 switch (opcode) {
3015 case SUBFIC: {
3016 int rt = instr->RTValue();
3017 int ra = instr->RAValue();
3018 intptr_t ra_val = get_register(ra);
3019 int32_t im_val = instr->Bits(15, 0);
3020 im_val = SIGN_EXT_IMM16(im_val);
3021 intptr_t alu_out = im_val - ra_val;
3022 set_register(rt, alu_out);
3023 // todo - handle RC bit
3024 break;
3025 }
3026 case CMPLI: {
3027 int ra = instr->RAValue();
3028 uint32_t im_val = instr->Bits(15, 0);
3029 int cr = instr->Bits(25, 23);
3030 uint32_t bf = 0;
3031 #if V8_TARGET_ARCH_PPC64
3032 int L = instr->Bit(21);
3033 if (L) {
3034 #endif
3035 uintptr_t ra_val = get_register(ra);
3036 if (ra_val < im_val) {
3037 bf |= 0x80000000;
3038 }
3039 if (ra_val > im_val) {
3040 bf |= 0x40000000;
3041 }
3042 if (ra_val == im_val) {
3043 bf |= 0x20000000;
3044 }
3045 #if V8_TARGET_ARCH_PPC64
3046 } else {
3047 uint32_t ra_val = get_register(ra);
3048 if (ra_val < im_val) {
3049 bf |= 0x80000000;
3050 }
3051 if (ra_val > im_val) {
3052 bf |= 0x40000000;
3053 }
3054 if (ra_val == im_val) {
3055 bf |= 0x20000000;
3056 }
3057 }
3058 #endif
3059 uint32_t condition_mask = 0xF0000000U >> (cr * 4);
3060 uint32_t condition = bf >> (cr * 4);
3061 condition_reg_ = (condition_reg_ & ~condition_mask) | condition;
3062 break;
3063 }
3064 case CMPI: {
3065 int ra = instr->RAValue();
3066 int32_t im_val = instr->Bits(15, 0);
3067 im_val = SIGN_EXT_IMM16(im_val);
3068 int cr = instr->Bits(25, 23);
3069 uint32_t bf = 0;
3070 #if V8_TARGET_ARCH_PPC64
3071 int L = instr->Bit(21);
3072 if (L) {
3073 #endif
3074 intptr_t ra_val = get_register(ra);
3075 if (ra_val < im_val) {
3076 bf |= 0x80000000;
3077 }
3078 if (ra_val > im_val) {
3079 bf |= 0x40000000;
3080 }
3081 if (ra_val == im_val) {
3082 bf |= 0x20000000;
3083 }
3084 #if V8_TARGET_ARCH_PPC64
3085 } else {
3086 int32_t ra_val = get_register(ra);
3087 if (ra_val < im_val) {
3088 bf |= 0x80000000;
3089 }
3090 if (ra_val > im_val) {
3091 bf |= 0x40000000;
3092 }
3093 if (ra_val == im_val) {
3094 bf |= 0x20000000;
3095 }
3096 }
3097 #endif
3098 uint32_t condition_mask = 0xF0000000U >> (cr * 4);
3099 uint32_t condition = bf >> (cr * 4);
3100 condition_reg_ = (condition_reg_ & ~condition_mask) | condition;
3101 break;
3102 }
3103 case ADDIC: {
3104 int rt = instr->RTValue();
3105 int ra = instr->RAValue();
3106 uintptr_t ra_val = get_register(ra);
3107 uintptr_t im_val = SIGN_EXT_IMM16(instr->Bits(15, 0));
3108 uintptr_t alu_out = ra_val + im_val;
3109 // Check overflow
3110 if (~ra_val < im_val) {
3111 special_reg_xer_ = (special_reg_xer_ & ~0xF0000000) | 0x20000000;
3112 } else {
3113 special_reg_xer_ &= ~0xF0000000;
3114 }
3115 set_register(rt, alu_out);
3116 break;
3117 }
3118 case ADDI: {
3119 int rt = instr->RTValue();
3120 int ra = instr->RAValue();
3121 int32_t im_val = SIGN_EXT_IMM16(instr->Bits(15, 0));
3122 intptr_t alu_out;
3123 if (ra == 0) {
3124 alu_out = im_val;
3125 } else {
3126 intptr_t ra_val = get_register(ra);
3127 alu_out = ra_val + im_val;
3128 }
3129 set_register(rt, alu_out);
3130 // todo - handle RC bit
3131 break;
3132 }
3133 case ADDIS: {
3134 int rt = instr->RTValue();
3135 int ra = instr->RAValue();
3136 int32_t im_val = (instr->Bits(15, 0) << 16);
3137 intptr_t alu_out;
3138 if (ra == 0) { // treat r0 as zero
3139 alu_out = im_val;
3140 } else {
3141 intptr_t ra_val = get_register(ra);
3142 alu_out = ra_val + im_val;
3143 }
3144 set_register(rt, alu_out);
3145 break;
3146 }
3147 case BCX: {
3148 ExecuteBranchConditional(instr);
3149 break;
3150 }
3151 case BX: {
3152 int offset = (instr->Bits(25, 2) << 8) >> 6;
3153 if (instr->Bit(0) == 1) { // LK flag set
3154 special_reg_lr_ = get_pc() + 4;
3155 }
3156 set_pc(get_pc() + offset);
3157 // todo - AA flag
3158 break;
3159 }
3160 case EXT1: {
3161 ExecuteExt1(instr);
3162 break;
3163 }
3164 case RLWIMIX: {
3165 int ra = instr->RAValue();
3166 int rs = instr->RSValue();
3167 uint32_t rs_val = get_register(rs);
3168 int32_t ra_val = get_register(ra);
3169 int sh = instr->Bits(15, 11);
3170 int mb = instr->Bits(10, 6);
3171 int me = instr->Bits(5, 1);
3172 // rotate left
3173 uint32_t result = (rs_val << sh) | (rs_val >> (32 - sh));
3174 int mask = 0;
3175 if (mb < me + 1) {
3176 int bit = 0x80000000 >> mb;
3177 for (; mb <= me; mb++) {
3178 mask |= bit;
3179 bit >>= 1;
3180 }
3181 } else if (mb == me + 1) {
3182 mask = 0xffffffff;
3183 } else { // mb > me+1
3184 int bit = 0x80000000 >> (me + 1); // needs to be tested
3185 mask = 0xffffffff;
3186 for (; me < mb; me++) {
3187 mask ^= bit;
3188 bit >>= 1;
3189 }
3190 }
3191 result &= mask;
3192 ra_val &= ~mask;
3193 result |= ra_val;
3194 set_register(ra, result);
3195 if (instr->Bit(0)) { // RC bit set
3196 SetCR0(result);
3197 }
3198 break;
3199 }
3200 case RLWINMX:
3201 case RLWNMX: {
3202 int ra = instr->RAValue();
3203 int rs = instr->RSValue();
3204 uint32_t rs_val = get_register(rs);
3205 int sh = 0;
3206 if (opcode == RLWINMX) {
3207 sh = instr->Bits(15, 11);
3208 } else {
3209 int rb = instr->RBValue();
3210 uint32_t rb_val = get_register(rb);
3211 sh = (rb_val & 0x1f);
3212 }
3213 int mb = instr->Bits(10, 6);
3214 int me = instr->Bits(5, 1);
3215 // rotate left
3216 uint32_t result = (rs_val << sh) | (rs_val >> (32 - sh));
3217 int mask = 0;
3218 if (mb < me + 1) {
3219 int bit = 0x80000000 >> mb;
3220 for (; mb <= me; mb++) {
3221 mask |= bit;
3222 bit >>= 1;
3223 }
3224 } else if (mb == me + 1) {
3225 mask = 0xffffffff;
3226 } else { // mb > me+1
3227 int bit = 0x80000000 >> (me + 1); // needs to be tested
3228 mask = 0xffffffff;
3229 for (; me < mb; me++) {
3230 mask ^= bit;
3231 bit >>= 1;
3232 }
3233 }
3234 result &= mask;
3235 set_register(ra, result);
3236 if (instr->Bit(0)) { // RC bit set
3237 SetCR0(result);
3238 }
3239 break;
3240 }
3241 case ORI: {
3242 int rs = instr->RSValue();
3243 int ra = instr->RAValue();
3244 intptr_t rs_val = get_register(rs);
3245 uint32_t im_val = instr->Bits(15, 0);
3246 intptr_t alu_out = rs_val | im_val;
3247 set_register(ra, alu_out);
3248 break;
3249 }
3250 case ORIS: {
3251 int rs = instr->RSValue();
3252 int ra = instr->RAValue();
3253 intptr_t rs_val = get_register(rs);
3254 uint32_t im_val = instr->Bits(15, 0);
3255 intptr_t alu_out = rs_val | (im_val << 16);
3256 set_register(ra, alu_out);
3257 break;
3258 }
3259 case XORI: {
3260 int rs = instr->RSValue();
3261 int ra = instr->RAValue();
3262 intptr_t rs_val = get_register(rs);
3263 uint32_t im_val = instr->Bits(15, 0);
3264 intptr_t alu_out = rs_val ^ im_val;
3265 set_register(ra, alu_out);
3266 // todo - set condition based SO bit
3267 break;
3268 }
3269 case XORIS: {
3270 int rs = instr->RSValue();
3271 int ra = instr->RAValue();
3272 intptr_t rs_val = get_register(rs);
3273 uint32_t im_val = instr->Bits(15, 0);
3274 intptr_t alu_out = rs_val ^ (im_val << 16);
3275 set_register(ra, alu_out);
3276 break;
3277 }
3278 case ANDIx: {
3279 int rs = instr->RSValue();
3280 int ra = instr->RAValue();
3281 intptr_t rs_val = get_register(rs);
3282 uint32_t im_val = instr->Bits(15, 0);
3283 intptr_t alu_out = rs_val & im_val;
3284 set_register(ra, alu_out);
3285 SetCR0(alu_out);
3286 break;
3287 }
3288 case ANDISx: {
3289 int rs = instr->RSValue();
3290 int ra = instr->RAValue();
3291 intptr_t rs_val = get_register(rs);
3292 uint32_t im_val = instr->Bits(15, 0);
3293 intptr_t alu_out = rs_val & (im_val << 16);
3294 set_register(ra, alu_out);
3295 SetCR0(alu_out);
3296 break;
3297 }
3298 case EXT2: {
3299 ExecuteExt2(instr);
3300 break;
3301 }
3302
3303 case LWZU:
3304 case LWZ: {
3305 int ra = instr->RAValue();
3306 int rt = instr->RTValue();
3307 intptr_t ra_val = ra == 0 ? 0 : get_register(ra);
3308 int offset = SIGN_EXT_IMM16(instr->Bits(15, 0));
3309 set_register(rt, ReadWU(ra_val + offset, instr));
3310 if (opcode == LWZU) {
3311 DCHECK(ra != 0);
3312 set_register(ra, ra_val + offset);
3313 }
3314 break;
3315 }
3316
3317 case LBZU:
3318 case LBZ: {
3319 int ra = instr->RAValue();
3320 int rt = instr->RTValue();
3321 intptr_t ra_val = ra == 0 ? 0 : get_register(ra);
3322 int offset = SIGN_EXT_IMM16(instr->Bits(15, 0));
3323 set_register(rt, ReadB(ra_val + offset) & 0xFF);
3324 if (opcode == LBZU) {
3325 DCHECK(ra != 0);
3326 set_register(ra, ra_val + offset);
3327 }
3328 break;
3329 }
3330
3331 case STWU:
3332 case STW: {
3333 int ra = instr->RAValue();
3334 int rs = instr->RSValue();
3335 intptr_t ra_val = ra == 0 ? 0 : get_register(ra);
3336 int32_t rs_val = get_register(rs);
3337 int offset = SIGN_EXT_IMM16(instr->Bits(15, 0));
3338 WriteW(ra_val + offset, rs_val, instr);
3339 if (opcode == STWU) {
3340 DCHECK(ra != 0);
3341 set_register(ra, ra_val + offset);
3342 }
3343 // printf("r%d %08x -> %08x\n", rs, rs_val, offset); // 0xdead
3344 break;
3345 }
3346
3347 case STBU:
3348 case STB: {
3349 int ra = instr->RAValue();
3350 int rs = instr->RSValue();
3351 intptr_t ra_val = ra == 0 ? 0 : get_register(ra);
3352 int8_t rs_val = get_register(rs);
3353 int offset = SIGN_EXT_IMM16(instr->Bits(15, 0));
3354 WriteB(ra_val + offset, rs_val);
3355 if (opcode == STBU) {
3356 DCHECK(ra != 0);
3357 set_register(ra, ra_val + offset);
3358 }
3359 break;
3360 }
3361
3362 case LHZU:
3363 case LHZ: {
3364 int ra = instr->RAValue();
3365 int rt = instr->RTValue();
3366 intptr_t ra_val = ra == 0 ? 0 : get_register(ra);
3367 int offset = SIGN_EXT_IMM16(instr->Bits(15, 0));
3368 uintptr_t result = ReadHU(ra_val + offset, instr) & 0xffff;
3369 set_register(rt, result);
3370 if (opcode == LHZU) {
3371 DCHECK(ra != 0);
3372 set_register(ra, ra_val + offset);
3373 }
3374 break;
3375 }
3376
3377 case LHA:
3378 case LHAU: {
3379 UNIMPLEMENTED();
3380 break;
3381 }
3382
3383 case STHU:
3384 case STH: {
3385 int ra = instr->RAValue();
3386 int rs = instr->RSValue();
3387 intptr_t ra_val = ra == 0 ? 0 : get_register(ra);
3388 int16_t rs_val = get_register(rs);
3389 int offset = SIGN_EXT_IMM16(instr->Bits(15, 0));
3390 WriteH(ra_val + offset, rs_val, instr);
3391 if (opcode == STHU) {
3392 DCHECK(ra != 0);
3393 set_register(ra, ra_val + offset);
3394 }
3395 break;
3396 }
3397
3398 case LMW:
3399 case STMW: {
3400 UNIMPLEMENTED();
3401 break;
3402 }
3403
3404 case LFSU:
3405 case LFS: {
3406 int frt = instr->RTValue();
3407 int ra = instr->RAValue();
3408 int32_t offset = SIGN_EXT_IMM16(instr->Bits(15, 0));
3409 intptr_t ra_val = ra == 0 ? 0 : get_register(ra);
3410 int32_t val = ReadW(ra_val + offset, instr);
3411 float* fptr = reinterpret_cast<float*>(&val);
3412 set_d_register_from_double(frt, static_cast<double>(*fptr));
3413 if (opcode == LFSU) {
3414 DCHECK(ra != 0);
3415 set_register(ra, ra_val + offset);
3416 }
3417 break;
3418 }
3419
3420 case LFDU:
3421 case LFD: {
3422 int frt = instr->RTValue();
3423 int ra = instr->RAValue();
3424 int32_t offset = SIGN_EXT_IMM16(instr->Bits(15, 0));
3425 intptr_t ra_val = ra == 0 ? 0 : get_register(ra);
3426 double* dptr = reinterpret_cast<double*>(ReadDW(ra_val + offset));
3427 set_d_register_from_double(frt, *dptr);
3428 if (opcode == LFDU) {
3429 DCHECK(ra != 0);
3430 set_register(ra, ra_val + offset);
3431 }
3432 break;
3433 }
3434
3435 case STFSU: {
3436 case STFS:
3437 int frs = instr->RSValue();
3438 int ra = instr->RAValue();
3439 int32_t offset = SIGN_EXT_IMM16(instr->Bits(15, 0));
3440 intptr_t ra_val = ra == 0 ? 0 : get_register(ra);
3441 float frs_val = static_cast<float>(get_double_from_d_register(frs));
3442 int32_t* p = reinterpret_cast<int32_t*>(&frs_val);
3443 WriteW(ra_val + offset, *p, instr);
3444 if (opcode == STFSU) {
3445 DCHECK(ra != 0);
3446 set_register(ra, ra_val + offset);
3447 }
3448 break;
3449 }
3450
3451 case STFDU:
3452 case STFD: {
3453 int frs = instr->RSValue();
3454 int ra = instr->RAValue();
3455 int32_t offset = SIGN_EXT_IMM16(instr->Bits(15, 0));
3456 intptr_t ra_val = ra == 0 ? 0 : get_register(ra);
3457 double frs_val = get_double_from_d_register(frs);
3458 int64_t* p = reinterpret_cast<int64_t*>(&frs_val);
3459 WriteDW(ra_val + offset, *p);
3460 if (opcode == STFDU) {
3461 DCHECK(ra != 0);
3462 set_register(ra, ra_val + offset);
3463 }
3464 break;
3465 }
3466
3467 case EXT3:
3468 UNIMPLEMENTED();
3469 case EXT4: {
3470 ExecuteExt4(instr);
3471 break;
3472 }
3473
3474 #if V8_TARGET_ARCH_PPC64
3475 case EXT5: {
3476 ExecuteExt5(instr);
3477 break;
3478 }
3479 case LD: {
3480 int ra = instr->RAValue();
3481 int rt = instr->RTValue();
3482 int64_t ra_val = ra == 0 ? 0 : get_register(ra);
3483 int offset = SIGN_EXT_IMM16(instr->Bits(15, 0) & ~3);
3484 switch (instr->Bits(1, 0)) {
3485 case 0: { // ld
3486 intptr_t* result = ReadDW(ra_val + offset);
3487 set_register(rt, *result);
3488 break;
3489 }
3490 case 1: { // ldu
3491 intptr_t* result = ReadDW(ra_val + offset);
3492 set_register(rt, *result);
3493 DCHECK(ra != 0);
3494 set_register(ra, ra_val + offset);
3495 break;
3496 }
3497 case 2: { // lwa
3498 intptr_t result = ReadW(ra_val + offset, instr);
3499 set_register(rt, result);
3500 break;
3501 }
3502 }
3503 break;
3504 }
3505
3506 case STD: {
3507 int ra = instr->RAValue();
3508 int rs = instr->RSValue();
3509 int64_t ra_val = ra == 0 ? 0 : get_register(ra);
3510 int64_t rs_val = get_register(rs);
3511 int offset = SIGN_EXT_IMM16(instr->Bits(15, 0) & ~3);
3512 WriteDW(ra_val + offset, rs_val);
3513 if (instr->Bit(0) == 1) { // This is the STDU form
3514 DCHECK(ra != 0);
3515 set_register(ra, ra_val + offset);
3516 }
3517 break;
3518 }
3519 #endif
3520
3521 case FAKE_OPCODE: {
3522 if (instr->Bits(MARKER_SUBOPCODE_BIT, MARKER_SUBOPCODE_BIT) == 1) {
3523 int marker_code = instr->Bits(STUB_MARKER_HIGH_BIT, 0);
3524 DCHECK(marker_code < F_NEXT_AVAILABLE_STUB_MARKER);
3525 PrintF("Hit stub-marker: %d (EMIT_STUB_MARKER)\n", marker_code);
3526 } else {
3527 int fake_opcode = instr->Bits(FAKE_OPCODE_HIGH_BIT, 0);
3528 if (fake_opcode == fBKPT) {
3529 PPCDebugger dbg(this);
3530 PrintF("Simulator hit BKPT.\n");
3531 dbg.Debug();
3532 } else {
3533 DCHECK(fake_opcode < fLastFaker);
3534 PrintF("Hit ARM opcode: %d(FAKE_OPCODE defined in constant-ppc.h)\n",
3535 fake_opcode);
3536 UNIMPLEMENTED();
3537 }
3538 }
3539 break;
3540 }
3541
3542 default: {
3543 UNIMPLEMENTED();
3544 break;
3545 }
3546 }
3547 } // NOLINT - disable function size check
3548
3549
3550 void Simulator::Trace(Instruction* instr) {
3551 disasm::NameConverter converter;
3552 disasm::Disassembler dasm(converter);
3553 // use a reasonably large buffer
3554 v8::internal::EmbeddedVector<char, 256> buffer;
3555 dasm.InstructionDecode(buffer, reinterpret_cast<byte*>(instr));
3556 PrintF("%05d %08" V8PRIxPTR " %s\n", icount_,
3557 reinterpret_cast<intptr_t>(instr), buffer.start());
3558 }
3559
3560
3561 // Executes the current instruction.
3562 void Simulator::ExecuteInstruction(Instruction* instr) {
3563 if (v8::internal::FLAG_check_icache) {
3564 CheckICache(isolate_->simulator_i_cache(), instr);
3565 }
3566 pc_modified_ = false;
3567 if (::v8::internal::FLAG_trace_sim) {
3568 Trace(instr);
3569 }
3570 int opcode = instr->OpcodeValue() << 26;
3571 if (opcode == TWI) {
3572 SoftwareInterrupt(instr);
3573 } else {
3574 ExecuteGeneric(instr);
3575 }
3576 if (!pc_modified_) {
3577 set_pc(reinterpret_cast<intptr_t>(instr) + Instruction::kInstrSize);
3578 }
3579 }
3580
3581
3582 void Simulator::Execute() {
3583 // Get the PC to simulate. Cannot use the accessor here as we need the
3584 // raw PC value and not the one used as input to arithmetic instructions.
3585 intptr_t program_counter = get_pc();
3586
3587 if (::v8::internal::FLAG_stop_sim_at == 0) {
3588 // Fast version of the dispatch loop without checking whether the simulator
3589 // should be stopping at a particular executed instruction.
3590 while (program_counter != end_sim_pc) {
3591 Instruction* instr = reinterpret_cast<Instruction*>(program_counter);
3592 icount_++;
3593 ExecuteInstruction(instr);
3594 program_counter = get_pc();
3595 }
3596 } else {
3597 // FLAG_stop_sim_at is at the non-default value. Stop in the debugger when
3598 // we reach the particular instuction count.
3599 while (program_counter != end_sim_pc) {
3600 Instruction* instr = reinterpret_cast<Instruction*>(program_counter);
3601 icount_++;
3602 if (icount_ == ::v8::internal::FLAG_stop_sim_at) {
3603 PPCDebugger dbg(this);
3604 dbg.Debug();
3605 } else {
3606 ExecuteInstruction(instr);
3607 }
3608 program_counter = get_pc();
3609 }
3610 }
3611 }
3612
3613
3614 void Simulator::CallInternal(byte* entry) {
3615 // Prepare to execute the code at entry
3616 #if ABI_USES_FUNCTION_DESCRIPTORS
3617 // entry is the function descriptor
3618 set_pc(*(reinterpret_cast<intptr_t*>(entry)));
3619 #else
3620 // entry is the instruction address
3621 set_pc(reinterpret_cast<intptr_t>(entry));
3622 #endif
3623
3624 // Put down marker for end of simulation. The simulator will stop simulation
3625 // when the PC reaches this value. By saving the "end simulation" value into
3626 // the LR the simulation stops when returning to this call point.
3627 special_reg_lr_ = end_sim_pc;
3628
3629 // Remember the values of non-volatile registers.
3630 intptr_t r2_val = get_register(r2);
3631 intptr_t r13_val = get_register(r13);
3632 intptr_t r14_val = get_register(r14);
3633 intptr_t r15_val = get_register(r15);
3634 intptr_t r16_val = get_register(r16);
3635 intptr_t r17_val = get_register(r17);
3636 intptr_t r18_val = get_register(r18);
3637 intptr_t r19_val = get_register(r19);
3638 intptr_t r20_val = get_register(r20);
3639 intptr_t r21_val = get_register(r21);
3640 intptr_t r22_val = get_register(r22);
3641 intptr_t r23_val = get_register(r23);
3642 intptr_t r24_val = get_register(r24);
3643 intptr_t r25_val = get_register(r25);
3644 intptr_t r26_val = get_register(r26);
3645 intptr_t r27_val = get_register(r27);
3646 intptr_t r28_val = get_register(r28);
3647 intptr_t r29_val = get_register(r29);
3648 intptr_t r30_val = get_register(r30);
3649 intptr_t r31_val = get_register(fp);
3650
3651 // Set up the non-volatile registers with a known value. To be able to check
3652 // that they are preserved properly across JS execution.
3653 intptr_t callee_saved_value = icount_;
3654 set_register(r2, callee_saved_value);
3655 set_register(r13, callee_saved_value);
3656 set_register(r14, callee_saved_value);
3657 set_register(r15, callee_saved_value);
3658 set_register(r16, callee_saved_value);
3659 set_register(r17, callee_saved_value);
3660 set_register(r18, callee_saved_value);
3661 set_register(r19, callee_saved_value);
3662 set_register(r20, callee_saved_value);
3663 set_register(r21, callee_saved_value);
3664 set_register(r22, callee_saved_value);
3665 set_register(r23, callee_saved_value);
3666 set_register(r24, callee_saved_value);
3667 set_register(r25, callee_saved_value);
3668 set_register(r26, callee_saved_value);
3669 set_register(r27, callee_saved_value);
3670 set_register(r28, callee_saved_value);
3671 set_register(r29, callee_saved_value);
3672 set_register(r30, callee_saved_value);
3673 set_register(fp, callee_saved_value);
3674
3675 // Start the simulation
3676 Execute();
3677
3678 // Check that the non-volatile registers have been preserved.
3679 CHECK_EQ(callee_saved_value, get_register(r2));
3680 CHECK_EQ(callee_saved_value, get_register(r13));
3681 CHECK_EQ(callee_saved_value, get_register(r14));
3682 CHECK_EQ(callee_saved_value, get_register(r15));
3683 CHECK_EQ(callee_saved_value, get_register(r16));
3684 CHECK_EQ(callee_saved_value, get_register(r17));
3685 CHECK_EQ(callee_saved_value, get_register(r18));
3686 CHECK_EQ(callee_saved_value, get_register(r19));
3687 CHECK_EQ(callee_saved_value, get_register(r20));
3688 CHECK_EQ(callee_saved_value, get_register(r21));
3689 CHECK_EQ(callee_saved_value, get_register(r22));
3690 CHECK_EQ(callee_saved_value, get_register(r23));
3691 CHECK_EQ(callee_saved_value, get_register(r24));
3692 CHECK_EQ(callee_saved_value, get_register(r25));
3693 CHECK_EQ(callee_saved_value, get_register(r26));
3694 CHECK_EQ(callee_saved_value, get_register(r27));
3695 CHECK_EQ(callee_saved_value, get_register(r28));
3696 CHECK_EQ(callee_saved_value, get_register(r29));
3697 CHECK_EQ(callee_saved_value, get_register(r30));
3698 CHECK_EQ(callee_saved_value, get_register(fp));
3699
3700 // Restore non-volatile registers with the original value.
3701 set_register(r2, r2_val);
3702 set_register(r13, r13_val);
3703 set_register(r14, r14_val);
3704 set_register(r15, r15_val);
3705 set_register(r16, r16_val);
3706 set_register(r17, r17_val);
3707 set_register(r18, r18_val);
3708 set_register(r19, r19_val);
3709 set_register(r20, r20_val);
3710 set_register(r21, r21_val);
3711 set_register(r22, r22_val);
3712 set_register(r23, r23_val);
3713 set_register(r24, r24_val);
3714 set_register(r25, r25_val);
3715 set_register(r26, r26_val);
3716 set_register(r27, r27_val);
3717 set_register(r28, r28_val);
3718 set_register(r29, r29_val);
3719 set_register(r30, r30_val);
3720 set_register(fp, r31_val);
3721 }
3722
3723
3724 intptr_t Simulator::Call(byte* entry, int argument_count, ...) {
3725 va_list parameters;
3726 va_start(parameters, argument_count);
3727 // Set up arguments
3728
3729 // First eight arguments passed in registers r3-r10.
3730 int reg_arg_count = (argument_count > 8) ? 8 : argument_count;
3731 int stack_arg_count = argument_count - reg_arg_count;
3732 for (int i = 0; i < reg_arg_count; i++) {
3733 set_register(i + 3, va_arg(parameters, intptr_t));
3734 }
3735
3736 // Remaining arguments passed on stack.
3737 intptr_t original_stack = get_register(sp);
3738 // Compute position of stack on entry to generated code.
3739 intptr_t entry_stack =
3740 (original_stack -
3741 (kNumRequiredStackFrameSlots + stack_arg_count) * sizeof(intptr_t));
3742 if (base::OS::ActivationFrameAlignment() != 0) {
3743 entry_stack &= -base::OS::ActivationFrameAlignment();
3744 }
3745 // Store remaining arguments on stack, from low to high memory.
3746 // +2 is a hack for the LR slot + old SP on PPC
3747 intptr_t* stack_argument =
3748 reinterpret_cast<intptr_t*>(entry_stack) + kStackFrameExtraParamSlot;
3749 for (int i = 0; i < stack_arg_count; i++) {
3750 stack_argument[i] = va_arg(parameters, intptr_t);
3751 }
3752 va_end(parameters);
3753 set_register(sp, entry_stack);
3754
3755 CallInternal(entry);
3756
3757 // Pop stack passed arguments.
3758 CHECK_EQ(entry_stack, get_register(sp));
3759 set_register(sp, original_stack);
3760
3761 intptr_t result = get_register(r3);
3762 return result;
3763 }
3764
3765
3766 void Simulator::CallFP(byte* entry, double d0, double d1) {
3767 set_d_register_from_double(1, d0);
3768 set_d_register_from_double(2, d1);
3769 CallInternal(entry);
3770 }
3771
3772
3773 int32_t Simulator::CallFPReturnsInt(byte* entry, double d0, double d1) {
3774 CallFP(entry, d0, d1);
3775 int32_t result = get_register(r3);
3776 return result;
3777 }
3778
3779
3780 double Simulator::CallFPReturnsDouble(byte* entry, double d0, double d1) {
3781 CallFP(entry, d0, d1);
3782 return get_double_from_d_register(1);
3783 }
3784
3785
3786 uintptr_t Simulator::PushAddress(uintptr_t address) {
3787 uintptr_t new_sp = get_register(sp) - sizeof(uintptr_t);
3788 uintptr_t* stack_slot = reinterpret_cast<uintptr_t*>(new_sp);
3789 *stack_slot = address;
3790 set_register(sp, new_sp);
3791 return new_sp;
3792 }
3793
3794
3795 uintptr_t Simulator::PopAddress() {
3796 uintptr_t current_sp = get_register(sp);
3797 uintptr_t* stack_slot = reinterpret_cast<uintptr_t*>(current_sp);
3798 uintptr_t address = *stack_slot;
3799 set_register(sp, current_sp + sizeof(uintptr_t));
3800 return address;
3801 }
3802 }
3803 } // namespace v8::internal
3804
3805 #endif // USE_SIMULATOR
3806 #endif // V8_TARGET_ARCH_PPC
OLDNEW
« src/hydrogen-bch.cc ('K') | « src/ppc/simulator-ppc.h ('k') | src/ppc/stub-cache-ppc.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698