1 // Copyright 2014 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "src/execution/ppc/simulator-ppc.h"
6
7 #if defined(USE_SIMULATOR)
8
9 #include <stdarg.h>
10 #include <stdlib.h>
11
12 #include <cmath>
13
14 #include "src/base/bits.h"
15 #include "src/base/lazy-instance.h"
16 #include "src/base/overflowing-math.h"
17 #include "src/base/platform/platform.h"
18 #include "src/base/platform/wrappers.h"
19 #include "src/codegen/assembler.h"
20 #include "src/codegen/macro-assembler.h"
21 #include "src/codegen/ppc/constants-ppc.h"
22 #include "src/codegen/register-configuration.h"
23 #include "src/diagnostics/disasm.h"
24 #include "src/execution/ppc/frame-constants-ppc.h"
25 #include "src/heap/combined-heap.h"
26 #include "src/heap/heap-inl.h" // For CodeSpaceMemoryModificationScope.
27 #include "src/objects/objects-inl.h"
28 #include "src/runtime/runtime-utils.h"
29 #include "src/utils/ostreams.h"
30
31 // Only build the simulator if not compiling for real PPC hardware.
32 namespace v8 {
33 namespace internal {
34
35 DEFINE_LAZY_LEAKY_OBJECT_GETTER(Simulator::GlobalMonitor,
36 Simulator::GlobalMonitor::Get)
37
38 // This macro provides a platform independent use of sscanf. The reason for
39 // SScanF not being implemented in a platform independent way through
40 // ::v8::internal::OS in the same way as SNPrintF is that the
41 // Windows C Run-Time Library does not provide vsscanf.
42 #define SScanF sscanf
43
44 // The PPCDebugger class is used by the simulator while debugging simulated
45 // PowerPC code.
46 class PPCDebugger {
47 public:
PPCDebugger(Simulator * sim)48 explicit PPCDebugger(Simulator* sim) : sim_(sim) {}
49 void Debug();
50
51 private:
52 static const Instr kBreakpointInstr = (TWI | 0x1F * B21);
53 static const Instr kNopInstr = (ORI); // ori, 0,0,0
54
55 Simulator* sim_;
56
57 intptr_t GetRegisterValue(int regnum);
58 double GetRegisterPairDoubleValue(int regnum);
59 double GetFPDoubleRegisterValue(int regnum);
60 bool GetValue(const char* desc, intptr_t* value);
61 bool GetFPDoubleValue(const char* desc, double* value);
62
63 // Set or delete breakpoint (there can be only one).
64 bool SetBreakpoint(Instruction* break_pc);
65 void DeleteBreakpoint();
66
67 // Undo and redo the breakpoint. This is needed to bracket disassembly and
68 // execution to skip past the breakpoint when run from the debugger.
69 void UndoBreakpoint();
70 void RedoBreakpoint();
71 };
72
DebugAtNextPC()73 void Simulator::DebugAtNextPC() {
74 PrintF("Starting debugger on the next instruction:\n");
75 set_pc(get_pc() + kInstrSize);
76 PPCDebugger(this).Debug();
77 }
78
GetRegisterValue(int regnum)79 intptr_t PPCDebugger::GetRegisterValue(int regnum) {
80 return sim_->get_register(regnum);
81 }
82
GetRegisterPairDoubleValue(int regnum)83 double PPCDebugger::GetRegisterPairDoubleValue(int regnum) {
84 return sim_->get_double_from_register_pair(regnum);
85 }
86
GetFPDoubleRegisterValue(int regnum)87 double PPCDebugger::GetFPDoubleRegisterValue(int regnum) {
88 return sim_->get_double_from_d_register(regnum);
89 }
90
GetValue(const char * desc,intptr_t * value)91 bool PPCDebugger::GetValue(const char* desc, intptr_t* value) {
92 int regnum = Registers::Number(desc);
93 if (regnum != kNoRegister) {
94 *value = GetRegisterValue(regnum);
95 return true;
96 }
97 if (strncmp(desc, "0x", 2) == 0) {
98 return SScanF(desc + 2, "%" V8PRIxPTR,
99 reinterpret_cast<uintptr_t*>(value)) == 1;
100 }
101 return SScanF(desc, "%" V8PRIuPTR, reinterpret_cast<uintptr_t*>(value)) == 1;
102 }
103
GetFPDoubleValue(const char * desc,double * value)104 bool PPCDebugger::GetFPDoubleValue(const char* desc, double* value) {
105 int regnum = DoubleRegisters::Number(desc);
106 if (regnum != kNoRegister) {
107 *value = sim_->get_double_from_d_register(regnum);
108 return true;
109 }
110 return false;
111 }
112
SetBreakpoint(Instruction * break_pc)113 bool PPCDebugger::SetBreakpoint(Instruction* break_pc) {
114 // Check if a breakpoint can be set. If not return without any side-effects.
115 if (sim_->break_pc_ != nullptr) {
116 return false;
117 }
118
119 // Set the breakpoint.
120 sim_->break_pc_ = break_pc;
121 sim_->break_instr_ = break_pc->InstructionBits();
122 // Not setting the breakpoint instruction in the code itself. It will be set
123 // when the debugger shell continues.
124 return true;
125 }
126
127 namespace {
128 // This function is dangerous, but it's only available in non-production
129 // (simulator) builds.
SetInstructionBitsInCodeSpace(Instruction * instr,Instr value,Heap * heap)130 void SetInstructionBitsInCodeSpace(Instruction* instr, Instr value,
131 Heap* heap) {
132 CodeSpaceMemoryModificationScope scope(heap);
133 instr->SetInstructionBits(value);
134 }
135 } // namespace
136
DeleteBreakpoint()137 void PPCDebugger::DeleteBreakpoint() {
138 UndoBreakpoint();
139 sim_->break_pc_ = nullptr;
140 sim_->break_instr_ = 0;
141 }
142
UndoBreakpoint()143 void PPCDebugger::UndoBreakpoint() {
144 if (sim_->break_pc_ != nullptr) {
145 SetInstructionBitsInCodeSpace(sim_->break_pc_, sim_->break_instr_,
146 sim_->isolate_->heap());
147 }
148 }
149
RedoBreakpoint()150 void PPCDebugger::RedoBreakpoint() {
151 if (sim_->break_pc_ != nullptr) {
152 SetInstructionBitsInCodeSpace(sim_->break_pc_, kBreakpointInstr,
153 sim_->isolate_->heap());
154 }
155 }
156
Debug()157 void PPCDebugger::Debug() {
158 intptr_t last_pc = -1;
159 bool done = false;
160
161 #define COMMAND_SIZE 63
162 #define ARG_SIZE 255
163
164 #define STR(a) #a
165 #define XSTR(a) STR(a)
166
167 char cmd[COMMAND_SIZE + 1];
168 char arg1[ARG_SIZE + 1];
169 char arg2[ARG_SIZE + 1];
170 char* argv[3] = {cmd, arg1, arg2};
171
172 // make sure to have a proper terminating character if reaching the limit
173 cmd[COMMAND_SIZE] = 0;
174 arg1[ARG_SIZE] = 0;
175 arg2[ARG_SIZE] = 0;
176
177 // Unset breakpoint while running in the debugger shell, making it invisible
178 // to all commands.
179 UndoBreakpoint();
180 // Disable tracing while simulating
181 bool trace = ::v8::internal::FLAG_trace_sim;
182 ::v8::internal::FLAG_trace_sim = false;
183
184 while (!done && !sim_->has_bad_pc()) {
185 if (last_pc != sim_->get_pc()) {
186 disasm::NameConverter converter;
187 disasm::Disassembler dasm(converter);
188 // use a reasonably large buffer
189 v8::base::EmbeddedVector<char, 256> buffer;
190 dasm.InstructionDecode(buffer, reinterpret_cast<byte*>(sim_->get_pc()));
191 PrintF(" 0x%08" V8PRIxPTR " %s\n", sim_->get_pc(), buffer.begin());
192 last_pc = sim_->get_pc();
193 }
194 char* line = ReadLine("sim> ");
195 if (line == nullptr) {
196 break;
197 } else {
198 char* last_input = sim_->last_debugger_input();
199 if (strcmp(line, "\n") == 0 && last_input != nullptr) {
200 line = last_input;
201 } else {
202 // Ownership is transferred to sim_;
203 sim_->set_last_debugger_input(line);
204 }
205 // Use sscanf to parse the individual parts of the command line. At the
206 // moment no command expects more than two parameters.
207 int argc = SScanF(line,
208 "%" XSTR(COMMAND_SIZE) "s "
209 "%" XSTR(ARG_SIZE) "s "
210 "%" XSTR(ARG_SIZE) "s",
211 cmd, arg1, arg2);
212 if ((strcmp(cmd, "si") == 0) || (strcmp(cmd, "stepi") == 0)) {
213 intptr_t value;
214
215 // If at a breakpoint, proceed past it.
216 if ((reinterpret_cast<Instruction*>(sim_->get_pc()))
217 ->InstructionBits() == 0x7D821008) {
218 sim_->set_pc(sim_->get_pc() + kInstrSize);
219 } else {
220 sim_->ExecuteInstruction(
221 reinterpret_cast<Instruction*>(sim_->get_pc()));
222 }
223
224 if (argc == 2 && last_pc != sim_->get_pc() && GetValue(arg1, &value)) {
225 for (int i = 1; i < value; i++) {
226 disasm::NameConverter converter;
227 disasm::Disassembler dasm(converter);
228 // use a reasonably large buffer
229 v8::base::EmbeddedVector<char, 256> buffer;
230 dasm.InstructionDecode(buffer,
231 reinterpret_cast<byte*>(sim_->get_pc()));
232 PrintF(" 0x%08" V8PRIxPTR " %s\n", sim_->get_pc(),
233 buffer.begin());
234 sim_->ExecuteInstruction(
235 reinterpret_cast<Instruction*>(sim_->get_pc()));
236 }
237 }
238 } else if ((strcmp(cmd, "c") == 0) || (strcmp(cmd, "cont") == 0)) {
239 // If at a breakpoint, proceed past it.
240 if ((reinterpret_cast<Instruction*>(sim_->get_pc()))
241 ->InstructionBits() == 0x7D821008) {
242 sim_->set_pc(sim_->get_pc() + kInstrSize);
243 } else {
244 // Execute the one instruction we broke at with breakpoints disabled.
245 sim_->ExecuteInstruction(
246 reinterpret_cast<Instruction*>(sim_->get_pc()));
247 }
248 // Leave the debugger shell.
249 done = true;
250 } else if ((strcmp(cmd, "p") == 0) || (strcmp(cmd, "print") == 0)) {
251 if (argc == 2 || (argc == 3 && strcmp(arg2, "fp") == 0)) {
252 intptr_t value;
253 double dvalue;
254 if (strcmp(arg1, "all") == 0) {
255 for (int i = 0; i < kNumRegisters; i++) {
256 value = GetRegisterValue(i);
257 PrintF(" %3s: %08" V8PRIxPTR,
258 RegisterName(Register::from_code(i)), value);
259 if ((argc == 3 && strcmp(arg2, "fp") == 0) && i < 8 &&
260 (i % 2) == 0) {
261 dvalue = GetRegisterPairDoubleValue(i);
262 PrintF(" (%f)\n", dvalue);
263 } else if (i != 0 && !((i + 1) & 3)) {
264 PrintF("\n");
265 }
266 }
267 PrintF(" pc: %08" V8PRIxPTR " lr: %08" V8PRIxPTR
268 " "
269 "ctr: %08" V8PRIxPTR " xer: %08x cr: %08x\n",
270 sim_->special_reg_pc_, sim_->special_reg_lr_,
271 sim_->special_reg_ctr_, sim_->special_reg_xer_,
272 sim_->condition_reg_);
273 } else if (strcmp(arg1, "alld") == 0) {
274 for (int i = 0; i < kNumRegisters; i++) {
275 value = GetRegisterValue(i);
276 PrintF(" %3s: %08" V8PRIxPTR " %11" V8PRIdPTR,
277 RegisterName(Register::from_code(i)), value, value);
278 if ((argc == 3 && strcmp(arg2, "fp") == 0) && i < 8 &&
279 (i % 2) == 0) {
280 dvalue = GetRegisterPairDoubleValue(i);
281 PrintF(" (%f)\n", dvalue);
282 } else if (!((i + 1) % 2)) {
283 PrintF("\n");
284 }
285 }
286 PrintF(" pc: %08" V8PRIxPTR " lr: %08" V8PRIxPTR
287 " "
288 "ctr: %08" V8PRIxPTR " xer: %08x cr: %08x\n",
289 sim_->special_reg_pc_, sim_->special_reg_lr_,
290 sim_->special_reg_ctr_, sim_->special_reg_xer_,
291 sim_->condition_reg_);
292 } else if (strcmp(arg1, "allf") == 0) {
293 for (int i = 0; i < DoubleRegister::kNumRegisters; i++) {
294 dvalue = GetFPDoubleRegisterValue(i);
295 uint64_t as_words = bit_cast<uint64_t>(dvalue);
296 PrintF("%3s: %f 0x%08x %08x\n",
297 RegisterName(DoubleRegister::from_code(i)), dvalue,
298 static_cast<uint32_t>(as_words >> 32),
299 static_cast<uint32_t>(as_words & 0xFFFFFFFF));
300 }
301 } else if (arg1[0] == 'r' &&
302 (arg1[1] >= '0' && arg1[1] <= '9' &&
303 (arg1[2] == '\0' || (arg1[2] >= '0' && arg1[2] <= '9' &&
304 arg1[3] == '\0')))) {
305 int regnum = strtoul(&arg1[1], 0, 10);
306 if (regnum != kNoRegister) {
307 value = GetRegisterValue(regnum);
308 PrintF("%s: 0x%08" V8PRIxPTR " %" V8PRIdPTR "\n", arg1, value,
309 value);
310 } else {
311 PrintF("%s unrecognized\n", arg1);
312 }
313 } else {
314 if (GetValue(arg1, &value)) {
315 PrintF("%s: 0x%08" V8PRIxPTR " %" V8PRIdPTR "\n", arg1, value,
316 value);
317 } else if (GetFPDoubleValue(arg1, &dvalue)) {
318 uint64_t as_words = bit_cast<uint64_t>(dvalue);
319 PrintF("%s: %f 0x%08x %08x\n", arg1, dvalue,
320 static_cast<uint32_t>(as_words >> 32),
321 static_cast<uint32_t>(as_words & 0xFFFFFFFF));
322 } else {
323 PrintF("%s unrecognized\n", arg1);
324 }
325 }
326 } else {
327 PrintF("print <register>\n");
328 }
329 } else if ((strcmp(cmd, "po") == 0) ||
330 (strcmp(cmd, "printobject") == 0)) {
331 if (argc == 2) {
332 intptr_t value;
333 StdoutStream os;
334 if (GetValue(arg1, &value)) {
335 Object obj(value);
336 os << arg1 << ": \n";
337 #ifdef DEBUG
338 obj.Print(os);
339 os << "\n";
340 #else
341 os << Brief(obj) << "\n";
342 #endif
343 } else {
344 os << arg1 << " unrecognized\n";
345 }
346 } else {
347 PrintF("printobject <value>\n");
348 }
349 } else if (strcmp(cmd, "setpc") == 0) {
350 intptr_t value;
351
352 if (!GetValue(arg1, &value)) {
353 PrintF("%s unrecognized\n", arg1);
354 continue;
355 }
356 sim_->set_pc(value);
357 } else if (strcmp(cmd, "stack") == 0 || strcmp(cmd, "mem") == 0 ||
358 strcmp(cmd, "dump") == 0) {
359 intptr_t* cur = nullptr;
360 intptr_t* end = nullptr;
361 int next_arg = 1;
362
363 if (strcmp(cmd, "stack") == 0) {
364 cur = reinterpret_cast<intptr_t*>(sim_->get_register(Simulator::sp));
365 } else { // "mem"
366 intptr_t value;
367 if (!GetValue(arg1, &value)) {
368 PrintF("%s unrecognized\n", arg1);
369 continue;
370 }
371 cur = reinterpret_cast<intptr_t*>(value);
372 next_arg++;
373 }
374
375 intptr_t words; // likely inaccurate variable name for 64bit
376 if (argc == next_arg) {
377 words = 10;
378 } else {
379 if (!GetValue(argv[next_arg], &words)) {
380 words = 10;
381 }
382 }
383 end = cur + words;
384
385 bool skip_obj_print = (strcmp(cmd, "dump") == 0);
386 while (cur < end) {
387 PrintF(" 0x%08" V8PRIxPTR ": 0x%08" V8PRIxPTR " %10" V8PRIdPTR,
388 reinterpret_cast<intptr_t>(cur), *cur, *cur);
389 Object obj(*cur);
390 Heap* current_heap = sim_->isolate_->heap();
391 if (!skip_obj_print) {
392 if (obj.IsSmi() ||
393 IsValidHeapObject(current_heap, HeapObject::cast(obj))) {
394 PrintF(" (");
395 if (obj.IsSmi()) {
396 PrintF("smi %d", Smi::ToInt(obj));
397 } else {
398 obj.ShortPrint();
399 }
400 PrintF(")");
401 }
402 }
403 PrintF("\n");
404 cur++;
405 }
406 } else if (strcmp(cmd, "disasm") == 0 || strcmp(cmd, "di") == 0) {
407 disasm::NameConverter converter;
408 disasm::Disassembler dasm(converter);
409 // use a reasonably large buffer
410 v8::base::EmbeddedVector<char, 256> buffer;
411
412 byte* prev = nullptr;
413 byte* cur = nullptr;
414 byte* end = nullptr;
415
416 if (argc == 1) {
417 cur = reinterpret_cast<byte*>(sim_->get_pc());
418 end = cur + (10 * kInstrSize);
419 } else if (argc == 2) {
420 int regnum = Registers::Number(arg1);
421 if (regnum != kNoRegister || strncmp(arg1, "0x", 2) == 0) {
422 // The argument is an address or a register name.
423 intptr_t value;
424 if (GetValue(arg1, &value)) {
425 cur = reinterpret_cast<byte*>(value);
426 // Disassemble 10 instructions at <arg1>.
427 end = cur + (10 * kInstrSize);
428 }
429 } else {
430 // The argument is the number of instructions.
431 intptr_t value;
432 if (GetValue(arg1, &value)) {
433 cur = reinterpret_cast<byte*>(sim_->get_pc());
434 // Disassemble <arg1> instructions.
435 end = cur + (value * kInstrSize);
436 }
437 }
438 } else {
439 intptr_t value1;
440 intptr_t value2;
441 if (GetValue(arg1, &value1) && GetValue(arg2, &value2)) {
442 cur = reinterpret_cast<byte*>(value1);
443 end = cur + (value2 * kInstrSize);
444 }
445 }
446
447 while (cur < end) {
448 prev = cur;
449 cur += dasm.InstructionDecode(buffer, cur);
450 PrintF(" 0x%08" V8PRIxPTR " %s\n", reinterpret_cast<intptr_t>(prev),
451 buffer.begin());
452 }
453 } else if (strcmp(cmd, "gdb") == 0) {
454 PrintF("relinquishing control to gdb\n");
455 v8::base::OS::DebugBreak();
456 PrintF("regaining control from gdb\n");
457 } else if (strcmp(cmd, "break") == 0) {
458 if (argc == 2) {
459 intptr_t value;
460 if (GetValue(arg1, &value)) {
461 if (!SetBreakpoint(reinterpret_cast<Instruction*>(value))) {
462 PrintF("setting breakpoint failed\n");
463 }
464 } else {
465 PrintF("%s unrecognized\n", arg1);
466 }
467 } else {
468 PrintF("break <address>\n");
469 }
470 } else if (strcmp(cmd, "del") == 0) {
471 DeleteBreakpoint();
472 } else if (strcmp(cmd, "cr") == 0) {
473 PrintF("Condition reg: %08x\n", sim_->condition_reg_);
474 } else if (strcmp(cmd, "lr") == 0) {
475 PrintF("Link reg: %08" V8PRIxPTR "\n", sim_->special_reg_lr_);
476 } else if (strcmp(cmd, "ctr") == 0) {
477 PrintF("Ctr reg: %08" V8PRIxPTR "\n", sim_->special_reg_ctr_);
478 } else if (strcmp(cmd, "xer") == 0) {
479 PrintF("XER: %08x\n", sim_->special_reg_xer_);
480 } else if (strcmp(cmd, "fpscr") == 0) {
481 PrintF("FPSCR: %08x\n", sim_->fp_condition_reg_);
482 } else if (strcmp(cmd, "stop") == 0) {
483 intptr_t value;
484 intptr_t stop_pc = sim_->get_pc() - (kInstrSize + kSystemPointerSize);
485 Instruction* stop_instr = reinterpret_cast<Instruction*>(stop_pc);
486 Instruction* msg_address =
487 reinterpret_cast<Instruction*>(stop_pc + kInstrSize);
488 if ((argc == 2) && (strcmp(arg1, "unstop") == 0)) {
489 // Remove the current stop.
490 if (sim_->isStopInstruction(stop_instr)) {
491 SetInstructionBitsInCodeSpace(stop_instr, kNopInstr,
492 sim_->isolate_->heap());
493 msg_address->SetInstructionBits(kNopInstr);
494 } else {
495 PrintF("Not at debugger stop.\n");
496 }
497 } else if (argc == 3) {
498 // Print information about all/the specified breakpoint(s).
499 if (strcmp(arg1, "info") == 0) {
500 if (strcmp(arg2, "all") == 0) {
501 PrintF("Stop information:\n");
502 for (uint32_t i = 0; i < sim_->kNumOfWatchedStops; i++) {
503 sim_->PrintStopInfo(i);
504 }
505 } else if (GetValue(arg2, &value)) {
506 sim_->PrintStopInfo(value);
507 } else {
508 PrintF("Unrecognized argument.\n");
509 }
510 } else if (strcmp(arg1, "enable") == 0) {
511 // Enable all/the specified breakpoint(s).
512 if (strcmp(arg2, "all") == 0) {
513 for (uint32_t i = 0; i < sim_->kNumOfWatchedStops; i++) {
514 sim_->EnableStop(i);
515 }
516 } else if (GetValue(arg2, &value)) {
517 sim_->EnableStop(value);
518 } else {
519 PrintF("Unrecognized argument.\n");
520 }
521 } else if (strcmp(arg1, "disable") == 0) {
522 // Disable all/the specified breakpoint(s).
523 if (strcmp(arg2, "all") == 0) {
524 for (uint32_t i = 0; i < sim_->kNumOfWatchedStops; i++) {
525 sim_->DisableStop(i);
526 }
527 } else if (GetValue(arg2, &value)) {
528 sim_->DisableStop(value);
529 } else {
530 PrintF("Unrecognized argument.\n");
531 }
532 }
533 } else {
534 PrintF("Wrong usage. Use help command for more information.\n");
535 }
536 } else if ((strcmp(cmd, "t") == 0) || strcmp(cmd, "trace") == 0) {
537 ::v8::internal::FLAG_trace_sim = !::v8::internal::FLAG_trace_sim;
538 PrintF("Trace of executed instructions is %s\n",
539 ::v8::internal::FLAG_trace_sim ? "on" : "off");
540 } else if ((strcmp(cmd, "h") == 0) || (strcmp(cmd, "help") == 0)) {
541 PrintF("cont\n");
542 PrintF(" continue execution (alias 'c')\n");
543 PrintF("stepi [num instructions]\n");
544 PrintF(" step one/num instruction(s) (alias 'si')\n");
545 PrintF("print <register>\n");
546 PrintF(" print register content (alias 'p')\n");
547 PrintF(" use register name 'all' to display all integer registers\n");
548 PrintF(
549 " use register name 'alld' to display integer registers "
550 "with decimal values\n");
551 PrintF(" use register name 'rN' to display register number 'N'\n");
552 PrintF(" add argument 'fp' to print register pair double values\n");
553 PrintF(
554 " use register name 'allf' to display floating-point "
555 "registers\n");
556 PrintF("printobject <register>\n");
557 PrintF(" print an object from a register (alias 'po')\n");
558 PrintF("cr\n");
559 PrintF(" print condition register\n");
560 PrintF("lr\n");
561 PrintF(" print link register\n");
562 PrintF("ctr\n");
563 PrintF(" print ctr register\n");
564 PrintF("xer\n");
565 PrintF(" print XER\n");
566 PrintF("fpscr\n");
567 PrintF(" print FPSCR\n");
568 PrintF("stack [<num words>]\n");
569 PrintF(" dump stack content, default dump 10 words)\n");
570 PrintF("mem <address> [<num words>]\n");
571 PrintF(" dump memory content, default dump 10 words)\n");
572 PrintF("dump [<words>]\n");
573 PrintF(
574 " dump memory content without pretty printing JS objects, default "
575 "dump 10 words)\n");
576 PrintF("disasm [<instructions>]\n");
577 PrintF("disasm [<address/register>]\n");
578 PrintF("disasm [[<address/register>] <instructions>]\n");
579 PrintF(" disassemble code, default is 10 instructions\n");
580 PrintF(" from pc (alias 'di')\n");
581 PrintF("gdb\n");
582 PrintF(" enter gdb\n");
583 PrintF("break <address>\n");
584 PrintF(" set a break point on the address\n");
585 PrintF("del\n");
586 PrintF(" delete the breakpoint\n");
587 PrintF("trace (alias 't')\n");
588 PrintF(" toogle the tracing of all executed statements\n");
589 PrintF("stop feature:\n");
590 PrintF(" Description:\n");
591 PrintF(" Stops are debug instructions inserted by\n");
592 PrintF(" the Assembler::stop() function.\n");
593 PrintF(" When hitting a stop, the Simulator will\n");
594 PrintF(" stop and give control to the PPCDebugger.\n");
595 PrintF(" The first %d stop codes are watched:\n",
596 Simulator::kNumOfWatchedStops);
597 PrintF(" - They can be enabled / disabled: the Simulator\n");
598 PrintF(" will / won't stop when hitting them.\n");
599 PrintF(" - The Simulator keeps track of how many times they \n");
600 PrintF(" are met. (See the info command.) Going over a\n");
601 PrintF(" disabled stop still increases its counter. \n");
602 PrintF(" Commands:\n");
603 PrintF(" stop info all/<code> : print infos about number <code>\n");
604 PrintF(" or all stop(s).\n");
605 PrintF(" stop enable/disable all/<code> : enables / disables\n");
606 PrintF(" all or number <code> stop(s)\n");
607 PrintF(" stop unstop\n");
608 PrintF(" ignore the stop instruction at the current location\n");
609 PrintF(" from now on\n");
610 } else {
611 PrintF("Unknown command: %s\n", cmd);
612 }
613 }
614 }
615
616 // Reinstall breakpoint to stop execution and enter the debugger shell when
617 // hit.
618 RedoBreakpoint();
619 // Restore tracing
620 ::v8::internal::FLAG_trace_sim = trace;
621
622 #undef COMMAND_SIZE
623 #undef ARG_SIZE
624
625 #undef STR
626 #undef XSTR
627 }
628
ICacheMatch(void * one,void * two)629 bool Simulator::ICacheMatch(void* one, void* two) {
630 DCHECK_EQ(reinterpret_cast<intptr_t>(one) & CachePage::kPageMask, 0);
631 DCHECK_EQ(reinterpret_cast<intptr_t>(two) & CachePage::kPageMask, 0);
632 return one == two;
633 }
634
ICacheHash(void * key)635 static uint32_t ICacheHash(void* key) {
636 return static_cast<uint32_t>(reinterpret_cast<uintptr_t>(key)) >> 2;
637 }
638
AllOnOnePage(uintptr_t start,int size)639 static bool AllOnOnePage(uintptr_t start, int size) {
640 intptr_t start_page = (start & ~CachePage::kPageMask);
641 intptr_t end_page = ((start + size) & ~CachePage::kPageMask);
642 return start_page == end_page;
643 }
644
is_snan(float input)645 static bool is_snan(float input) {
646 uint32_t kQuietNanFPBit = 1 << 22;
647 uint32_t InputAsUint = bit_cast<uint32_t>(input);
648 return isnan(input) && ((InputAsUint & kQuietNanFPBit) == 0);
649 }
650
is_snan(double input)651 static bool is_snan(double input) {
652 uint64_t kQuietNanDPBit = 1L << 51;
653 uint64_t InputAsUint = bit_cast<uint64_t>(input);
654 return isnan(input) && ((InputAsUint & kQuietNanDPBit) == 0);
655 }
656
set_last_debugger_input(char * input)657 void Simulator::set_last_debugger_input(char* input) {
658 DeleteArray(last_debugger_input_);
659 last_debugger_input_ = input;
660 }
661
SetRedirectInstruction(Instruction * instruction)662 void Simulator::SetRedirectInstruction(Instruction* instruction) {
663 instruction->SetInstructionBits(rtCallRedirInstr | kCallRtRedirected);
664 }
665
FlushICache(base::CustomMatcherHashMap * i_cache,void * start_addr,size_t size)666 void Simulator::FlushICache(base::CustomMatcherHashMap* i_cache,
667 void* start_addr, size_t size) {
668 intptr_t start = reinterpret_cast<intptr_t>(start_addr);
669 int intra_line = (start & CachePage::kLineMask);
670 start -= intra_line;
671 size += intra_line;
672 size = ((size - 1) | CachePage::kLineMask) + 1;
673 int offset = (start & CachePage::kPageMask);
674 while (!AllOnOnePage(start, size - 1)) {
675 int bytes_to_flush = CachePage::kPageSize - offset;
676 FlushOnePage(i_cache, start, bytes_to_flush);
677 start += bytes_to_flush;
678 size -= bytes_to_flush;
679 DCHECK_EQ(0, static_cast<int>(start & CachePage::kPageMask));
680 offset = 0;
681 }
682 if (size != 0) {
683 FlushOnePage(i_cache, start, size);
684 }
685 }
686
GetCachePage(base::CustomMatcherHashMap * i_cache,void * page)687 CachePage* Simulator::GetCachePage(base::CustomMatcherHashMap* i_cache,
688 void* page) {
689 base::HashMap::Entry* entry = i_cache->LookupOrInsert(page, ICacheHash(page));
690 if (entry->value == nullptr) {
691 CachePage* new_page = new CachePage();
692 entry->value = new_page;
693 }
694 return reinterpret_cast<CachePage*>(entry->value);
695 }
696
697 // Flush from start up to and not including start + size.
FlushOnePage(base::CustomMatcherHashMap * i_cache,intptr_t start,int size)698 void Simulator::FlushOnePage(base::CustomMatcherHashMap* i_cache,
699 intptr_t start, int size) {
700 DCHECK_LE(size, CachePage::kPageSize);
701 DCHECK(AllOnOnePage(start, size - 1));
702 DCHECK_EQ(start & CachePage::kLineMask, 0);
703 DCHECK_EQ(size & CachePage::kLineMask, 0);
704 void* page = reinterpret_cast<void*>(start & (~CachePage::kPageMask));
705 int offset = (start & CachePage::kPageMask);
706 CachePage* cache_page = GetCachePage(i_cache, page);
707 char* valid_bytemap = cache_page->ValidityByte(offset);
708 memset(valid_bytemap, CachePage::LINE_INVALID, size >> CachePage::kLineShift);
709 }
710
CheckICache(base::CustomMatcherHashMap * i_cache,Instruction * instr)711 void Simulator::CheckICache(base::CustomMatcherHashMap* i_cache,
712 Instruction* instr) {
713 intptr_t address = reinterpret_cast<intptr_t>(instr);
714 void* page = reinterpret_cast<void*>(address & (~CachePage::kPageMask));
715 void* line = reinterpret_cast<void*>(address & (~CachePage::kLineMask));
716 int offset = (address & CachePage::kPageMask);
717 CachePage* cache_page = GetCachePage(i_cache, page);
718 char* cache_valid_byte = cache_page->ValidityByte(offset);
719 bool cache_hit = (*cache_valid_byte == CachePage::LINE_VALID);
720 char* cached_line = cache_page->CachedData(offset & ~CachePage::kLineMask);
721 if (cache_hit) {
722 // Check that the data in memory matches the contents of the I-cache.
723 CHECK_EQ(0, memcmp(reinterpret_cast<void*>(instr),
724 cache_page->CachedData(offset), kInstrSize));
725 } else {
726 // Cache miss. Load memory into the cache.
727 memcpy(cached_line, line, CachePage::kLineLength);
728 *cache_valid_byte = CachePage::LINE_VALID;
729 }
730 }
731
Simulator(Isolate * isolate)732 Simulator::Simulator(Isolate* isolate) : isolate_(isolate) {
733 // Set up simulator support first. Some of this information is needed to
734 // setup the architecture state.
735 #if V8_TARGET_ARCH_PPC64
736 size_t stack_size = FLAG_sim_stack_size * KB;
737 #else
738 size_t stack_size = MB; // allocate 1MB for stack
739 #endif
740 stack_size += 2 * stack_protection_size_;
741 stack_ = reinterpret_cast<char*>(base::Malloc(stack_size));
742 pc_modified_ = false;
743 icount_ = 0;
744 break_pc_ = nullptr;
745 break_instr_ = 0;
746
747 // Set up architecture state.
748 // All registers are initialized to zero to start with.
749 for (int i = 0; i < kNumGPRs; i++) {
750 registers_[i] = 0;
751 }
752 condition_reg_ = 0;
753 fp_condition_reg_ = 0;
754 special_reg_pc_ = 0;
755 special_reg_lr_ = 0;
756 special_reg_ctr_ = 0;
757
758 // Initializing FP registers.
759 for (int i = 0; i < kNumFPRs; i++) {
760 fp_registers_[i] = 0.0;
761 }
762
763 // The sp is initialized to point to the bottom (high address) of the
764 // allocated stack area. To be safe in potential stack underflows we leave
765 // some buffer below.
766 registers_[sp] =
767 reinterpret_cast<intptr_t>(stack_) + stack_size - stack_protection_size_;
768
769 last_debugger_input_ = nullptr;
770 }
771
~Simulator()772 Simulator::~Simulator() { base::Free(stack_); }
773
774 // Get the active Simulator for the current thread.
current(Isolate * isolate)775 Simulator* Simulator::current(Isolate* isolate) {
776 v8::internal::Isolate::PerIsolateThreadData* isolate_data =
777 isolate->FindOrAllocatePerThreadDataForThisThread();
778 DCHECK_NOT_NULL(isolate_data);
779
780 Simulator* sim = isolate_data->simulator();
781 if (sim == nullptr) {
782 // TODO(146): delete the simulator object when a thread/isolate goes away.
783 sim = new Simulator(isolate);
784 isolate_data->set_simulator(sim);
785 }
786 return sim;
787 }
788
789 // Sets the register in the architecture state.
set_register(int reg,intptr_t value)790 void Simulator::set_register(int reg, intptr_t value) {
791 DCHECK((reg >= 0) && (reg < kNumGPRs));
792 registers_[reg] = value;
793 }
794
795 // Get the register from the architecture state.
get_register(int reg) const796 intptr_t Simulator::get_register(int reg) const {
797 DCHECK((reg >= 0) && (reg < kNumGPRs));
798 // Stupid code added to avoid bug in GCC.
799 // See: http://gcc.gnu.org/bugzilla/show_bug.cgi?id=43949
800 if (reg >= kNumGPRs) return 0;
801 // End stupid code.
802 return registers_[reg];
803 }
804
get_double_from_register_pair(int reg)805 double Simulator::get_double_from_register_pair(int reg) {
806 DCHECK((reg >= 0) && (reg < kNumGPRs) && ((reg % 2) == 0));
807
808 double dm_val = 0.0;
809 #if !V8_TARGET_ARCH_PPC64 // doesn't make sense in 64bit mode
810 // Read the bits from the unsigned integer register_[] array
811 // into the double precision floating point value and return it.
812 char buffer[sizeof(fp_registers_[0])];
813 memcpy(buffer, ®isters_[reg], 2 * sizeof(registers_[0]));
814 memcpy(&dm_val, buffer, 2 * sizeof(registers_[0]));
815 #endif
816 return (dm_val);
817 }
818
819 // Raw access to the PC register.
set_pc(intptr_t value)820 void Simulator::set_pc(intptr_t value) {
821 pc_modified_ = true;
822 special_reg_pc_ = value;
823 }
824
has_bad_pc() const825 bool Simulator::has_bad_pc() const {
826 return ((special_reg_pc_ == bad_lr) || (special_reg_pc_ == end_sim_pc));
827 }
828
829 // Raw access to the PC register without the special adjustment when reading.
get_pc() const830 intptr_t Simulator::get_pc() const { return special_reg_pc_; }
831
832 // Accessor to the internal Link Register
get_lr() const833 intptr_t Simulator::get_lr() const { return special_reg_lr_; }
834
835 // Runtime FP routines take:
836 // - two double arguments
837 // - one double argument and zero or one integer arguments.
838 // All are consructed here from d1, d2 and r3.
GetFpArgs(double * x,double * y,intptr_t * z)839 void Simulator::GetFpArgs(double* x, double* y, intptr_t* z) {
840 *x = get_double_from_d_register(1);
841 *y = get_double_from_d_register(2);
842 *z = get_register(3);
843 }
844
845 // The return value is in d1.
SetFpResult(const double & result)846 void Simulator::SetFpResult(const double& result) {
847 set_d_register_from_double(1, result);
848 }
849
TrashCallerSaveRegisters()850 void Simulator::TrashCallerSaveRegisters() {
851 // We don't trash the registers with the return value.
852 #if 0 // A good idea to trash volatile registers, needs to be done
853 registers_[2] = 0x50BAD4U;
854 registers_[3] = 0x50BAD4U;
855 registers_[12] = 0x50BAD4U;
856 #endif
857 }
858
859 #define GENERATE_RW_FUNC(size, type) \
860 type Simulator::Read##size(uintptr_t addr) { \
861 type value; \
862 Read(addr, &value); \
863 return value; \
864 } \
865 type Simulator::ReadEx##size(uintptr_t addr) { \
866 type value; \
867 ReadEx(addr, &value); \
868 return value; \
869 } \
870 void Simulator::Write##size(uintptr_t addr, type value) { \
871 Write(addr, value); \
872 } \
873 int32_t Simulator::WriteEx##size(uintptr_t addr, type value) { \
874 return WriteEx(addr, value); \
875 }
876
RW_VAR_LIST(GENERATE_RW_FUNC)877 RW_VAR_LIST(GENERATE_RW_FUNC)
878 #undef GENERATE_RW_FUNC
879
880 // Returns the limit of the stack area to enable checking for stack overflows.
881 uintptr_t Simulator::StackLimit(uintptr_t c_limit) const {
882 // The simulator uses a separate JS stack. If we have exhausted the C stack,
883 // we also drop down the JS limit to reflect the exhaustion on the JS stack.
884 if (base::Stack::GetCurrentStackPosition() < c_limit) {
885 return reinterpret_cast<uintptr_t>(get_sp());
886 }
887
888 // Otherwise the limit is the JS stack. Leave a safety margin to prevent
889 // overrunning the stack when pushing values.
890 return reinterpret_cast<uintptr_t>(stack_) + stack_protection_size_;
891 }
892
893 // Unsupported instructions use Format to print an error and stop execution.
Format(Instruction * instr,const char * format)894 void Simulator::Format(Instruction* instr, const char* format) {
895 PrintF("Simulator found unsupported instruction:\n 0x%08" V8PRIxPTR ": %s\n",
896 reinterpret_cast<intptr_t>(instr), format);
897 UNIMPLEMENTED();
898 }
899
900 // Calculate C flag value for additions.
CarryFrom(int32_t left,int32_t right,int32_t carry)901 bool Simulator::CarryFrom(int32_t left, int32_t right, int32_t carry) {
902 uint32_t uleft = static_cast<uint32_t>(left);
903 uint32_t uright = static_cast<uint32_t>(right);
904 uint32_t urest = 0xFFFFFFFFU - uleft;
905
906 return (uright > urest) ||
907 (carry && (((uright + 1) > urest) || (uright > (urest - 1))));
908 }
909
910 // Calculate C flag value for subtractions.
BorrowFrom(int32_t left,int32_t right)911 bool Simulator::BorrowFrom(int32_t left, int32_t right) {
912 uint32_t uleft = static_cast<uint32_t>(left);
913 uint32_t uright = static_cast<uint32_t>(right);
914
915 return (uright > uleft);
916 }
917
918 // Calculate V flag value for additions and subtractions.
OverflowFrom(int32_t alu_out,int32_t left,int32_t right,bool addition)919 bool Simulator::OverflowFrom(int32_t alu_out, int32_t left, int32_t right,
920 bool addition) {
921 bool overflow;
922 if (addition) {
923 // operands have the same sign
924 overflow = ((left >= 0 && right >= 0) || (left < 0 && right < 0))
925 // and operands and result have different sign
926 && ((left < 0 && alu_out >= 0) || (left >= 0 && alu_out < 0));
927 } else {
928 // operands have different signs
929 overflow = ((left < 0 && right >= 0) || (left >= 0 && right < 0))
930 // and first operand and result have different signs
931 && ((left < 0 && alu_out >= 0) || (left >= 0 && alu_out < 0));
932 }
933 return overflow;
934 }
935
decodeObjectPair(ObjectPair * pair,intptr_t * x,intptr_t * y)936 static void decodeObjectPair(ObjectPair* pair, intptr_t* x, intptr_t* y) {
937 *x = static_cast<intptr_t>(pair->x);
938 *y = static_cast<intptr_t>(pair->y);
939 }
940
941 // Calls into the V8 runtime.
942 using SimulatorRuntimeCall = intptr_t (*)(
943 intptr_t arg0, intptr_t arg1, intptr_t arg2, intptr_t arg3, intptr_t arg4,
944 intptr_t arg5, intptr_t arg6, intptr_t arg7, intptr_t arg8, intptr_t arg9,
945 intptr_t arg10, intptr_t arg11, intptr_t arg12, intptr_t arg13,
946 intptr_t arg14, intptr_t arg15, intptr_t arg16, intptr_t arg17,
947 intptr_t arg18, intptr_t arg19);
948 using SimulatorRuntimePairCall = ObjectPair (*)(
949 intptr_t arg0, intptr_t arg1, intptr_t arg2, intptr_t arg3, intptr_t arg4,
950 intptr_t arg5, intptr_t arg6, intptr_t arg7, intptr_t arg8, intptr_t arg9,
951 intptr_t arg10, intptr_t arg11, intptr_t arg12, intptr_t arg13,
952 intptr_t arg14, intptr_t arg15, intptr_t arg16, intptr_t arg17,
953 intptr_t arg18, intptr_t arg19);
954
955 // These prototypes handle the four types of FP calls.
956 using SimulatorRuntimeCompareCall = int (*)(double darg0, double darg1);
957 using SimulatorRuntimeFPFPCall = double (*)(double darg0, double darg1);
958 using SimulatorRuntimeFPCall = double (*)(double darg0);
959 using SimulatorRuntimeFPIntCall = double (*)(double darg0, intptr_t arg0);
960
961 // This signature supports direct call in to API function native callback
962 // (refer to InvocationCallback in v8.h).
963 using SimulatorRuntimeDirectApiCall = void (*)(intptr_t arg0);
964 using SimulatorRuntimeProfilingApiCall = void (*)(intptr_t arg0, void* arg1);
965
966 // This signature supports direct call to accessor getter callback.
967 using SimulatorRuntimeDirectGetterCall = void (*)(intptr_t arg0, intptr_t arg1);
968 using SimulatorRuntimeProfilingGetterCall = void (*)(intptr_t arg0,
969 intptr_t arg1, void* arg2);
970
971 // Software interrupt instructions are used by the simulator to call into the
972 // C-based V8 runtime.
SoftwareInterrupt(Instruction * instr)973 void Simulator::SoftwareInterrupt(Instruction* instr) {
974 int svc = instr->SvcValue();
975 switch (svc) {
976 case kCallRtRedirected: {
977 // Check if stack is aligned. Error if not aligned is reported below to
978 // include information on the function called.
979 bool stack_aligned =
980 (get_register(sp) & (::v8::internal::FLAG_sim_stack_alignment - 1)) ==
981 0;
982 Redirection* redirection = Redirection::FromInstruction(instr);
983 const int kArgCount = 20;
984 const int kRegisterArgCount = 8;
985 int arg0_regnum = 3;
986 intptr_t result_buffer = 0;
987 bool uses_result_buffer =
988 (redirection->type() == ExternalReference::BUILTIN_CALL_PAIR &&
989 !ABI_RETURNS_OBJECT_PAIRS_IN_REGS);
990 if (uses_result_buffer) {
991 result_buffer = get_register(r3);
992 arg0_regnum++;
993 }
994 intptr_t arg[kArgCount];
995 // First eight arguments in registers r3-r10.
996 for (int i = 0; i < kRegisterArgCount; i++) {
997 arg[i] = get_register(arg0_regnum + i);
998 }
999 intptr_t* stack_pointer = reinterpret_cast<intptr_t*>(get_register(sp));
1000 // Remaining argument on stack
1001 for (int i = kRegisterArgCount, j = 0; i < kArgCount; i++, j++) {
1002 arg[i] = stack_pointer[kStackFrameExtraParamSlot + j];
1003 }
1004 STATIC_ASSERT(kArgCount == kRegisterArgCount + 12);
1005 STATIC_ASSERT(kMaxCParameters == kArgCount);
1006 bool fp_call =
1007 (redirection->type() == ExternalReference::BUILTIN_FP_FP_CALL) ||
1008 (redirection->type() == ExternalReference::BUILTIN_COMPARE_CALL) ||
1009 (redirection->type() == ExternalReference::BUILTIN_FP_CALL) ||
1010 (redirection->type() == ExternalReference::BUILTIN_FP_INT_CALL);
1011 // This is dodgy but it works because the C entry stubs are never moved.
1012 // See comment in codegen-arm.cc and bug 1242173.
1013 intptr_t saved_lr = special_reg_lr_;
1014 intptr_t external =
1015 reinterpret_cast<intptr_t>(redirection->external_function());
1016 if (fp_call) {
1017 double dval0, dval1; // one or two double parameters
1018 intptr_t ival; // zero or one integer parameters
1019 int iresult = 0; // integer return value
1020 double dresult = 0; // double return value
1021 GetFpArgs(&dval0, &dval1, &ival);
1022 if (::v8::internal::FLAG_trace_sim || !stack_aligned) {
1023 SimulatorRuntimeCall generic_target =
1024 reinterpret_cast<SimulatorRuntimeCall>(external);
1025 switch (redirection->type()) {
1026 case ExternalReference::BUILTIN_FP_FP_CALL:
1027 case ExternalReference::BUILTIN_COMPARE_CALL:
1028 PrintF("Call to host function at %p with args %f, %f",
1029 reinterpret_cast<void*>(FUNCTION_ADDR(generic_target)),
1030 dval0, dval1);
1031 break;
1032 case ExternalReference::BUILTIN_FP_CALL:
1033 PrintF("Call to host function at %p with arg %f",
1034 reinterpret_cast<void*>(FUNCTION_ADDR(generic_target)),
1035 dval0);
1036 break;
1037 case ExternalReference::BUILTIN_FP_INT_CALL:
1038 PrintF("Call to host function at %p with args %f, %" V8PRIdPTR,
1039 reinterpret_cast<void*>(FUNCTION_ADDR(generic_target)),
1040 dval0, ival);
1041 break;
1042 default:
1043 UNREACHABLE();
1044 }
1045 if (!stack_aligned) {
1046 PrintF(" with unaligned stack %08" V8PRIxPTR "\n",
1047 get_register(sp));
1048 }
1049 PrintF("\n");
1050 }
1051 CHECK(stack_aligned);
1052 switch (redirection->type()) {
1053 case ExternalReference::BUILTIN_COMPARE_CALL: {
1054 SimulatorRuntimeCompareCall target =
1055 reinterpret_cast<SimulatorRuntimeCompareCall>(external);
1056 iresult = target(dval0, dval1);
1057 set_register(r3, iresult);
1058 break;
1059 }
1060 case ExternalReference::BUILTIN_FP_FP_CALL: {
1061 SimulatorRuntimeFPFPCall target =
1062 reinterpret_cast<SimulatorRuntimeFPFPCall>(external);
1063 dresult = target(dval0, dval1);
1064 SetFpResult(dresult);
1065 break;
1066 }
1067 case ExternalReference::BUILTIN_FP_CALL: {
1068 SimulatorRuntimeFPCall target =
1069 reinterpret_cast<SimulatorRuntimeFPCall>(external);
1070 dresult = target(dval0);
1071 SetFpResult(dresult);
1072 break;
1073 }
1074 case ExternalReference::BUILTIN_FP_INT_CALL: {
1075 SimulatorRuntimeFPIntCall target =
1076 reinterpret_cast<SimulatorRuntimeFPIntCall>(external);
1077 dresult = target(dval0, ival);
1078 SetFpResult(dresult);
1079 break;
1080 }
1081 default:
1082 UNREACHABLE();
1083 }
1084 if (::v8::internal::FLAG_trace_sim || !stack_aligned) {
1085 switch (redirection->type()) {
1086 case ExternalReference::BUILTIN_COMPARE_CALL:
1087 PrintF("Returned %08x\n", iresult);
1088 break;
1089 case ExternalReference::BUILTIN_FP_FP_CALL:
1090 case ExternalReference::BUILTIN_FP_CALL:
1091 case ExternalReference::BUILTIN_FP_INT_CALL:
1092 PrintF("Returned %f\n", dresult);
1093 break;
1094 default:
1095 UNREACHABLE();
1096 }
1097 }
1098 } else if (redirection->type() == ExternalReference::DIRECT_API_CALL) {
1099 // See callers of MacroAssembler::CallApiFunctionAndReturn for
1100 // explanation of register usage.
1101 if (::v8::internal::FLAG_trace_sim || !stack_aligned) {
1102 PrintF("Call to host function at %p args %08" V8PRIxPTR,
1103 reinterpret_cast<void*>(external), arg[0]);
1104 if (!stack_aligned) {
1105 PrintF(" with unaligned stack %08" V8PRIxPTR "\n",
1106 get_register(sp));
1107 }
1108 PrintF("\n");
1109 }
1110 CHECK(stack_aligned);
1111 SimulatorRuntimeDirectApiCall target =
1112 reinterpret_cast<SimulatorRuntimeDirectApiCall>(external);
1113 target(arg[0]);
1114 } else if (redirection->type() == ExternalReference::PROFILING_API_CALL) {
1115 // See callers of MacroAssembler::CallApiFunctionAndReturn for
1116 // explanation of register usage.
1117 if (::v8::internal::FLAG_trace_sim || !stack_aligned) {
1118 PrintF("Call to host function at %p args %08" V8PRIxPTR
1119 " %08" V8PRIxPTR,
1120 reinterpret_cast<void*>(external), arg[0], arg[1]);
1121 if (!stack_aligned) {
1122 PrintF(" with unaligned stack %08" V8PRIxPTR "\n",
1123 get_register(sp));
1124 }
1125 PrintF("\n");
1126 }
1127 CHECK(stack_aligned);
1128 SimulatorRuntimeProfilingApiCall target =
1129 reinterpret_cast<SimulatorRuntimeProfilingApiCall>(external);
1130 target(arg[0], Redirection::ReverseRedirection(arg[1]));
1131 } else if (redirection->type() == ExternalReference::DIRECT_GETTER_CALL) {
1132 // See callers of MacroAssembler::CallApiFunctionAndReturn for
1133 // explanation of register usage.
1134 if (::v8::internal::FLAG_trace_sim || !stack_aligned) {
1135 PrintF("Call to host function at %p args %08" V8PRIxPTR
1136 " %08" V8PRIxPTR,
1137 reinterpret_cast<void*>(external), arg[0], arg[1]);
1138 if (!stack_aligned) {
1139 PrintF(" with unaligned stack %08" V8PRIxPTR "\n",
1140 get_register(sp));
1141 }
1142 PrintF("\n");
1143 }
1144 CHECK(stack_aligned);
1145 SimulatorRuntimeDirectGetterCall target =
1146 reinterpret_cast<SimulatorRuntimeDirectGetterCall>(external);
1147 if (!ABI_PASSES_HANDLES_IN_REGS) {
1148 arg[0] = bit_cast<intptr_t>(arg[0]);
1149 }
1150 target(arg[0], arg[1]);
1151 } else if (redirection->type() ==
1152 ExternalReference::PROFILING_GETTER_CALL) {
1153 if (::v8::internal::FLAG_trace_sim || !stack_aligned) {
1154 PrintF("Call to host function at %p args %08" V8PRIxPTR
1155 " %08" V8PRIxPTR " %08" V8PRIxPTR,
1156 reinterpret_cast<void*>(external), arg[0], arg[1], arg[2]);
1157 if (!stack_aligned) {
1158 PrintF(" with unaligned stack %08" V8PRIxPTR "\n",
1159 get_register(sp));
1160 }
1161 PrintF("\n");
1162 }
1163 CHECK(stack_aligned);
1164 SimulatorRuntimeProfilingGetterCall target =
1165 reinterpret_cast<SimulatorRuntimeProfilingGetterCall>(external);
1166 if (!ABI_PASSES_HANDLES_IN_REGS) {
1167 arg[0] = bit_cast<intptr_t>(arg[0]);
1168 }
1169 target(arg[0], arg[1], Redirection::ReverseRedirection(arg[2]));
1170 } else {
1171 // builtin call.
1172 if (::v8::internal::FLAG_trace_sim || !stack_aligned) {
1173 SimulatorRuntimeCall target =
1174 reinterpret_cast<SimulatorRuntimeCall>(external);
1175 PrintF(
1176 "Call to host function at %p,\n"
1177 "\t\t\t\targs %08" V8PRIxPTR ", %08" V8PRIxPTR ", %08" V8PRIxPTR
1178 ", %08" V8PRIxPTR ", %08" V8PRIxPTR ", %08" V8PRIxPTR
1179 ", %08" V8PRIxPTR ", %08" V8PRIxPTR ", %08" V8PRIxPTR
1180 ", %08" V8PRIxPTR ", %08" V8PRIxPTR ", %08" V8PRIxPTR
1181 ", %08" V8PRIxPTR ", %08" V8PRIxPTR ", %08" V8PRIxPTR
1182 ", %08" V8PRIxPTR ", %08" V8PRIxPTR ", %08" V8PRIxPTR
1183 ", %08" V8PRIxPTR ", %08" V8PRIxPTR,
1184 reinterpret_cast<void*>(FUNCTION_ADDR(target)), arg[0], arg[1],
1185 arg[2], arg[3], arg[4], arg[5], arg[6], arg[7], arg[8], arg[9],
1186 arg[10], arg[11], arg[12], arg[13], arg[14], arg[15], arg[16],
1187 arg[17], arg[18], arg[19]);
1188 if (!stack_aligned) {
1189 PrintF(" with unaligned stack %08" V8PRIxPTR "\n",
1190 get_register(sp));
1191 }
1192 PrintF("\n");
1193 }
1194 CHECK(stack_aligned);
1195 if (redirection->type() == ExternalReference::BUILTIN_CALL_PAIR) {
1196 SimulatorRuntimePairCall target =
1197 reinterpret_cast<SimulatorRuntimePairCall>(external);
1198 ObjectPair result =
1199 target(arg[0], arg[1], arg[2], arg[3], arg[4], arg[5], arg[6],
1200 arg[7], arg[8], arg[9], arg[10], arg[11], arg[12], arg[13],
1201 arg[14], arg[15], arg[16], arg[17], arg[18], arg[19]);
1202 intptr_t x;
1203 intptr_t y;
1204 decodeObjectPair(&result, &x, &y);
1205 if (::v8::internal::FLAG_trace_sim) {
1206 PrintF("Returned {%08" V8PRIxPTR ", %08" V8PRIxPTR "}\n", x, y);
1207 }
1208 if (ABI_RETURNS_OBJECT_PAIRS_IN_REGS) {
1209 set_register(r3, x);
1210 set_register(r4, y);
1211 } else {
1212 memcpy(reinterpret_cast<void*>(result_buffer), &result,
1213 sizeof(ObjectPair));
1214 set_register(r3, result_buffer);
1215 }
1216 } else {
1217 // FAST_C_CALL is temporarily handled here as well, because we lack
1218 // proper support for direct C calls with FP params in the simulator.
1219 // The generic BUILTIN_CALL path assumes all parameters are passed in
1220 // the GP registers, thus supporting calling the slow callback without
1221 // crashing. The reason for that is that in the mjsunit tests we check
1222 // the `fast_c_api.supports_fp_params` (which is false on
1223 // non-simulator builds for arm/arm64), thus we expect that the slow
1224 // path will be called. And since the slow path passes the arguments
1225 // as a `const FunctionCallbackInfo<Value>&` (which is a GP argument),
1226 // the call is made correctly.
1227 DCHECK(redirection->type() == ExternalReference::BUILTIN_CALL ||
1228 redirection->type() == ExternalReference::FAST_C_CALL);
1229 SimulatorRuntimeCall target =
1230 reinterpret_cast<SimulatorRuntimeCall>(external);
1231 intptr_t result =
1232 target(arg[0], arg[1], arg[2], arg[3], arg[4], arg[5], arg[6],
1233 arg[7], arg[8], arg[9], arg[10], arg[11], arg[12], arg[13],
1234 arg[14], arg[15], arg[16], arg[17], arg[18], arg[19]);
1235 if (::v8::internal::FLAG_trace_sim) {
1236 PrintF("Returned %08" V8PRIxPTR "\n", result);
1237 }
1238 set_register(r3, result);
1239 }
1240 }
1241 set_pc(saved_lr);
1242 break;
1243 }
1244 case kBreakpoint:
1245 PPCDebugger(this).Debug();
1246 break;
1247 // stop uses all codes greater than 1 << 23.
1248 default:
1249 if (svc >= (1 << 23)) {
1250 uint32_t code = svc & kStopCodeMask;
1251 if (isWatchedStop(code)) {
1252 IncreaseStopCounter(code);
1253 }
1254 // Stop if it is enabled, otherwise go on jumping over the stop
1255 // and the message address.
1256 if (isEnabledStop(code)) {
1257 if (code != kMaxStopCode) {
1258 PrintF("Simulator hit stop %u. ", code);
1259 } else {
1260 PrintF("Simulator hit stop. ");
1261 }
1262 DebugAtNextPC();
1263 } else {
1264 set_pc(get_pc() + kInstrSize + kSystemPointerSize);
1265 }
1266 } else {
1267 // This is not a valid svc code.
1268 UNREACHABLE();
1269 }
1270 }
1271 }
1272
1273 // Stop helper functions.
isStopInstruction(Instruction * instr)1274 bool Simulator::isStopInstruction(Instruction* instr) {
1275 return (instr->Bits(27, 24) == 0xF) && (instr->SvcValue() >= kStopCode);
1276 }
1277
isWatchedStop(uint32_t code)1278 bool Simulator::isWatchedStop(uint32_t code) {
1279 DCHECK_LE(code, kMaxStopCode);
1280 return code < kNumOfWatchedStops;
1281 }
1282
isEnabledStop(uint32_t code)1283 bool Simulator::isEnabledStop(uint32_t code) {
1284 DCHECK_LE(code, kMaxStopCode);
1285 // Unwatched stops are always enabled.
1286 return !isWatchedStop(code) ||
1287 !(watched_stops_[code].count & kStopDisabledBit);
1288 }
1289
EnableStop(uint32_t code)1290 void Simulator::EnableStop(uint32_t code) {
1291 DCHECK(isWatchedStop(code));
1292 if (!isEnabledStop(code)) {
1293 watched_stops_[code].count &= ~kStopDisabledBit;
1294 }
1295 }
1296
DisableStop(uint32_t code)1297 void Simulator::DisableStop(uint32_t code) {
1298 DCHECK(isWatchedStop(code));
1299 if (isEnabledStop(code)) {
1300 watched_stops_[code].count |= kStopDisabledBit;
1301 }
1302 }
1303
IncreaseStopCounter(uint32_t code)1304 void Simulator::IncreaseStopCounter(uint32_t code) {
1305 DCHECK_LE(code, kMaxStopCode);
1306 DCHECK(isWatchedStop(code));
1307 if ((watched_stops_[code].count & ~(1 << 31)) == 0x7FFFFFFF) {
1308 PrintF(
1309 "Stop counter for code %i has overflowed.\n"
1310 "Enabling this code and reseting the counter to 0.\n",
1311 code);
1312 watched_stops_[code].count = 0;
1313 EnableStop(code);
1314 } else {
1315 watched_stops_[code].count++;
1316 }
1317 }
1318
1319 // Print a stop status.
PrintStopInfo(uint32_t code)1320 void Simulator::PrintStopInfo(uint32_t code) {
1321 DCHECK_LE(code, kMaxStopCode);
1322 if (!isWatchedStop(code)) {
1323 PrintF("Stop not watched.");
1324 } else {
1325 const char* state = isEnabledStop(code) ? "Enabled" : "Disabled";
1326 int32_t count = watched_stops_[code].count & ~kStopDisabledBit;
1327 // Don't print the state of unused breakpoints.
1328 if (count != 0) {
1329 if (watched_stops_[code].desc) {
1330 PrintF("stop %i - 0x%x: \t%s, \tcounter = %i, \t%s\n", code, code,
1331 state, count, watched_stops_[code].desc);
1332 } else {
1333 PrintF("stop %i - 0x%x: \t%s, \tcounter = %i\n", code, code, state,
1334 count);
1335 }
1336 }
1337 }
1338 }
1339
SetCR0(intptr_t result,bool setSO)1340 void Simulator::SetCR0(intptr_t result, bool setSO) {
1341 int bf = 0;
1342 if (result < 0) {
1343 bf |= 0x80000000;
1344 }
1345 if (result > 0) {
1346 bf |= 0x40000000;
1347 }
1348 if (result == 0) {
1349 bf |= 0x20000000;
1350 }
1351 if (setSO) {
1352 bf |= 0x10000000;
1353 }
1354 condition_reg_ = (condition_reg_ & ~0xF0000000) | bf;
1355 }
1356
SetCR6(bool true_for_all,bool false_for_all)1357 void Simulator::SetCR6(bool true_for_all, bool false_for_all) {
1358 int32_t clear_cr6_mask = 0xFFFFFF0F;
1359 if (true_for_all) {
1360 condition_reg_ = (condition_reg_ & clear_cr6_mask) | 0x80;
1361 } else if (false_for_all) {
1362 condition_reg_ = (condition_reg_ & clear_cr6_mask) | 0x20;
1363 }
1364 }
1365
ExecuteBranchConditional(Instruction * instr,BCType type)1366 void Simulator::ExecuteBranchConditional(Instruction* instr, BCType type) {
1367 int bo = instr->Bits(25, 21) << 21;
1368 int condition_bit = instr->Bits(20, 16);
1369 int condition_mask = 0x80000000 >> condition_bit;
1370 switch (bo) {
1371 case DCBNZF: // Decrement CTR; branch if CTR != 0 and condition false
1372 case DCBEZF: // Decrement CTR; branch if CTR == 0 and condition false
1373 UNIMPLEMENTED();
1374 case BF: { // Branch if condition false
1375 if (condition_reg_ & condition_mask) return;
1376 break;
1377 }
1378 case DCBNZT: // Decrement CTR; branch if CTR != 0 and condition true
1379 case DCBEZT: // Decrement CTR; branch if CTR == 0 and condition true
1380 UNIMPLEMENTED();
1381 case BT: { // Branch if condition true
1382 if (!(condition_reg_ & condition_mask)) return;
1383 break;
1384 }
1385 case DCBNZ: // Decrement CTR; branch if CTR != 0
1386 case DCBEZ: // Decrement CTR; branch if CTR == 0
1387 special_reg_ctr_ -= 1;
1388 if ((special_reg_ctr_ == 0) != (bo == DCBEZ)) return;
1389 break;
1390 case BA: { // Branch always
1391 break;
1392 }
1393 default:
1394 UNIMPLEMENTED(); // Invalid encoding
1395 }
1396
1397 intptr_t old_pc = get_pc();
1398
1399 switch (type) {
1400 case BC_OFFSET: {
1401 int offset = (instr->Bits(15, 2) << 18) >> 16;
1402 set_pc(old_pc + offset);
1403 break;
1404 }
1405 case BC_LINK_REG:
1406 set_pc(special_reg_lr_);
1407 break;
1408 case BC_CTR_REG:
1409 set_pc(special_reg_ctr_);
1410 break;
1411 }
1412
1413 if (instr->Bit(0) == 1) { // LK flag set
1414 special_reg_lr_ = old_pc + 4;
1415 }
1416 }
1417
1418 // Vector instruction helpers.
1419 #define GET_ADDRESS(a, b, a_val, b_val) \
1420 intptr_t a_val = a == 0 ? 0 : get_register(a); \
1421 intptr_t b_val = get_register(b);
1422 #define DECODE_VX_INSTRUCTION(d, a, b, source_or_target) \
1423 int d = instr->R##source_or_target##Value(); \
1424 int a = instr->RAValue(); \
1425 int b = instr->RBValue();
1426 #define FOR_EACH_LANE(i, type) \
1427 for (uint32_t i = 0; i < kSimd128Size / sizeof(type); i++)
1428 template <typename A, typename T, typename Operation>
VectorCompareOp(Simulator * sim,Instruction * instr,bool is_fp,Operation op)1429 void VectorCompareOp(Simulator* sim, Instruction* instr, bool is_fp,
1430 Operation op) {
1431 DECODE_VX_INSTRUCTION(t, a, b, T)
1432 bool true_for_all = true, false_for_all = true;
1433 FOR_EACH_LANE(i, A) {
1434 A a_val = sim->get_simd_register_by_lane<A>(a, i);
1435 A b_val = sim->get_simd_register_by_lane<A>(b, i);
1436 T t_val = 0;
1437 bool is_not_nan = is_fp ? !isnan(a_val) && !isnan(b_val) : true;
1438 if (is_not_nan && op(a_val, b_val)) {
1439 false_for_all = false;
1440 t_val = -1; // Set all bits to 1 indicating true.
1441 } else {
1442 true_for_all = false;
1443 }
1444 sim->set_simd_register_by_lane<T>(t, i, t_val);
1445 }
1446 if (instr->Bit(10)) { // RC bit set.
1447 sim->SetCR6(true_for_all, false_for_all);
1448 }
1449 }
1450
1451 template <typename S, typename T>
VectorConverFromFPSaturate(Simulator * sim,Instruction * instr,T min_val,T max_val,bool even_lane_result=false)1452 void VectorConverFromFPSaturate(Simulator* sim, Instruction* instr, T min_val,
1453 T max_val, bool even_lane_result = false) {
1454 int t = instr->RTValue();
1455 int b = instr->RBValue();
1456 FOR_EACH_LANE(i, S) {
1457 T t_val;
1458 double b_val = static_cast<double>(sim->get_simd_register_by_lane<S>(b, i));
1459 if (isnan(b_val)) {
1460 t_val = min_val;
1461 } else {
1462 // Round Towards Zero.
1463 b_val = std::trunc(b_val);
1464 if (b_val < min_val) {
1465 t_val = min_val;
1466 } else if (b_val > max_val) {
1467 t_val = max_val;
1468 } else {
1469 t_val = static_cast<T>(b_val);
1470 }
1471 }
1472 sim->set_simd_register_by_lane<T>(t, even_lane_result ? 2 * i : i, t_val);
1473 }
1474 }
1475
1476 template <typename S, typename T>
VectorPackSaturate(Simulator * sim,Instruction * instr,S min_val,S max_val)1477 void VectorPackSaturate(Simulator* sim, Instruction* instr, S min_val,
1478 S max_val) {
1479 DECODE_VX_INSTRUCTION(t, a, b, T)
1480 int src = a;
1481 int count = 0;
1482 S value = 0;
1483 // Setup a temp array to avoid overwriting dst mid loop.
1484 T temps[kSimd128Size / sizeof(T)] = {0};
1485 for (size_t i = 0; i < kSimd128Size / sizeof(T); i++, count++) {
1486 if (count == kSimd128Size / sizeof(S)) {
1487 src = b;
1488 count = 0;
1489 }
1490 value = sim->get_simd_register_by_lane<S>(src, count);
1491 if (value > max_val) {
1492 value = max_val;
1493 } else if (value < min_val) {
1494 value = min_val;
1495 }
1496 temps[i] = static_cast<T>(value);
1497 }
1498 FOR_EACH_LANE(i, T) { sim->set_simd_register_by_lane<T>(t, i, temps[i]); }
1499 }
1500
1501 template <typename T>
VSXFPMin(T x,T y)1502 T VSXFPMin(T x, T y) {
1503 // Handle NaN.
1504 // TODO(miladfarca): include the payload of src1.
1505 if (std::isnan(x) && std::isnan(y)) return NAN;
1506 // Handle +0 and -0.
1507 if (std::signbit(x) < std::signbit(y)) return y;
1508 if (std::signbit(y) < std::signbit(x)) return x;
1509 return std::fmin(x, y);
1510 }
1511
1512 template <typename T>
VSXFPMax(T x,T y)1513 T VSXFPMax(T x, T y) {
1514 // Handle NaN.
1515 // TODO(miladfarca): include the payload of src1.
1516 if (std::isnan(x) && std::isnan(y)) return NAN;
1517 // Handle +0 and -0.
1518 if (std::signbit(x) < std::signbit(y)) return x;
1519 if (std::signbit(y) < std::signbit(x)) return y;
1520 return std::fmax(x, y);
1521 }
1522
VMXFPMin(float x,float y)1523 float VMXFPMin(float x, float y) {
1524 // Handle NaN.
1525 if (std::isnan(x) || std::isnan(y)) return NAN;
1526 // Handle +0 and -0.
1527 if (std::signbit(x) < std::signbit(y)) return y;
1528 if (std::signbit(y) < std::signbit(x)) return x;
1529 return x < y ? x : y;
1530 }
1531
VMXFPMax(float x,float y)1532 float VMXFPMax(float x, float y) {
1533 // Handle NaN.
1534 if (std::isnan(x) || std::isnan(y)) return NAN;
1535 // Handle +0 and -0.
1536 if (std::signbit(x) < std::signbit(y)) return x;
1537 if (std::signbit(y) < std::signbit(x)) return y;
1538 return x > y ? x : y;
1539 }
1540
ExecuteGeneric(Instruction * instr)1541 void Simulator::ExecuteGeneric(Instruction* instr) {
1542 uint32_t opcode = instr->OpcodeBase();
1543 switch (opcode) {
1544 // Prefixed instructions.
1545 case PLOAD_STORE_8LS:
1546 case PLOAD_STORE_MLS: {
1547 // TODO(miladfarca): Simulate PC-relative capability indicated by the R
1548 // bit.
1549 DCHECK_NE(instr->Bit(20), 1);
1550 // Read prefix value.
1551 uint64_t prefix_value = instr->Bits(17, 0);
1552 // Read suffix (next instruction).
1553 Instruction* next_instr = bit_cast<Instruction*>(get_pc() + kInstrSize);
1554 uint16_t suffix_value = next_instr->Bits(15, 0);
1555 int64_t im_val = SIGN_EXT_IMM34((prefix_value << 16) | suffix_value);
1556 switch (next_instr->OpcodeBase()) {
1557 // Prefixed ADDI.
1558 case ADDI: {
1559 int rt = next_instr->RTValue();
1560 int ra = next_instr->RAValue();
1561 intptr_t alu_out;
1562 if (ra == 0) {
1563 alu_out = im_val;
1564 } else {
1565 intptr_t ra_val = get_register(ra);
1566 alu_out = ra_val + im_val;
1567 }
1568 set_register(rt, alu_out);
1569 break;
1570 }
1571 // Prefixed LBZ.
1572 case LBZ: {
1573 int ra = next_instr->RAValue();
1574 int rt = next_instr->RTValue();
1575 intptr_t ra_val = ra == 0 ? 0 : get_register(ra);
1576 set_register(rt, ReadB(ra_val + im_val) & 0xFF);
1577 break;
1578 }
1579 // Prefixed LHZ.
1580 case LHZ: {
1581 int ra = next_instr->RAValue();
1582 int rt = next_instr->RTValue();
1583 intptr_t ra_val = ra == 0 ? 0 : get_register(ra);
1584 uintptr_t result = ReadHU(ra_val + im_val) & 0xFFFF;
1585 set_register(rt, result);
1586 break;
1587 }
1588 // Prefixed LHA.
1589 case LHA: {
1590 int ra = next_instr->RAValue();
1591 int rt = next_instr->RTValue();
1592 intptr_t ra_val = ra == 0 ? 0 : get_register(ra);
1593 intptr_t result = ReadH(ra_val + im_val);
1594 set_register(rt, result);
1595 break;
1596 }
1597 // Prefixed LWZ.
1598 case LWZ: {
1599 int ra = next_instr->RAValue();
1600 int rt = next_instr->RTValue();
1601 intptr_t ra_val = ra == 0 ? 0 : get_register(ra);
1602 set_register(rt, ReadWU(ra_val + im_val));
1603 break;
1604 }
1605 // Prefixed LWA.
1606 case PPLWA: {
1607 int ra = next_instr->RAValue();
1608 int rt = next_instr->RTValue();
1609 int64_t ra_val = ra == 0 ? 0 : get_register(ra);
1610 set_register(rt, ReadW(ra_val + im_val));
1611 break;
1612 }
1613 // Prefixed LD.
1614 case PPLD: {
1615 int ra = next_instr->RAValue();
1616 int rt = next_instr->RTValue();
1617 int64_t ra_val = ra == 0 ? 0 : get_register(ra);
1618 set_register(rt, ReadDW(ra_val + im_val));
1619 break;
1620 }
1621 // Prefixed LFS.
1622 case LFS: {
1623 int frt = next_instr->RTValue();
1624 int ra = next_instr->RAValue();
1625 intptr_t ra_val = ra == 0 ? 0 : get_register(ra);
1626 int32_t val = ReadW(ra_val + im_val);
1627 float* fptr = reinterpret_cast<float*>(&val);
1628 #if V8_HOST_ARCH_IA32 || V8_HOST_ARCH_X64
1629 // Conversion using double changes sNan to qNan on ia32/x64
1630 if ((val & 0x7F800000) == 0x7F800000) {
1631 int64_t dval = static_cast<int64_t>(val);
1632 dval = ((dval & 0xC0000000) << 32) | ((dval & 0x40000000) << 31) |
1633 ((dval & 0x40000000) << 30) | ((dval & 0x7FFFFFFF) << 29) |
1634 0x0;
1635 set_d_register(frt, dval);
1636 } else {
1637 set_d_register_from_double(frt, static_cast<double>(*fptr));
1638 }
1639 #else
1640 set_d_register_from_double(frt, static_cast<double>(*fptr));
1641 #endif
1642 break;
1643 }
1644 // Prefixed LFD.
1645 case LFD: {
1646 int frt = next_instr->RTValue();
1647 int ra = next_instr->RAValue();
1648 intptr_t ra_val = ra == 0 ? 0 : get_register(ra);
1649 int64_t dptr = ReadDW(ra_val + im_val);
1650 set_d_register(frt, dptr);
1651 break;
1652 }
1653 default:
1654 UNREACHABLE();
1655 }
1656 // We have now executed instructions at this as well as next pc.
1657 set_pc(get_pc() + (2 * kInstrSize));
1658 break;
1659 }
1660 case SUBFIC: {
1661 int rt = instr->RTValue();
1662 int ra = instr->RAValue();
1663 intptr_t ra_val = get_register(ra);
1664 int32_t im_val = instr->Bits(15, 0);
1665 im_val = SIGN_EXT_IMM16(im_val);
1666 intptr_t alu_out = im_val - ra_val;
1667 set_register(rt, alu_out);
1668 // todo - handle RC bit
1669 break;
1670 }
1671 case CMPLI: {
1672 int ra = instr->RAValue();
1673 uint32_t im_val = instr->Bits(15, 0);
1674 int cr = instr->Bits(25, 23);
1675 uint32_t bf = 0;
1676 #if V8_TARGET_ARCH_PPC64
1677 int L = instr->Bit(21);
1678 if (L) {
1679 #endif
1680 uintptr_t ra_val = get_register(ra);
1681 if (ra_val < im_val) {
1682 bf |= 0x80000000;
1683 }
1684 if (ra_val > im_val) {
1685 bf |= 0x40000000;
1686 }
1687 if (ra_val == im_val) {
1688 bf |= 0x20000000;
1689 }
1690 #if V8_TARGET_ARCH_PPC64
1691 } else {
1692 uint32_t ra_val = get_register(ra);
1693 if (ra_val < im_val) {
1694 bf |= 0x80000000;
1695 }
1696 if (ra_val > im_val) {
1697 bf |= 0x40000000;
1698 }
1699 if (ra_val == im_val) {
1700 bf |= 0x20000000;
1701 }
1702 }
1703 #endif
1704 uint32_t condition_mask = 0xF0000000U >> (cr * 4);
1705 uint32_t condition = bf >> (cr * 4);
1706 condition_reg_ = (condition_reg_ & ~condition_mask) | condition;
1707 break;
1708 }
1709 case CMPI: {
1710 int ra = instr->RAValue();
1711 int32_t im_val = instr->Bits(15, 0);
1712 im_val = SIGN_EXT_IMM16(im_val);
1713 int cr = instr->Bits(25, 23);
1714 uint32_t bf = 0;
1715 #if V8_TARGET_ARCH_PPC64
1716 int L = instr->Bit(21);
1717 if (L) {
1718 #endif
1719 intptr_t ra_val = get_register(ra);
1720 if (ra_val < im_val) {
1721 bf |= 0x80000000;
1722 }
1723 if (ra_val > im_val) {
1724 bf |= 0x40000000;
1725 }
1726 if (ra_val == im_val) {
1727 bf |= 0x20000000;
1728 }
1729 #if V8_TARGET_ARCH_PPC64
1730 } else {
1731 int32_t ra_val = get_register(ra);
1732 if (ra_val < im_val) {
1733 bf |= 0x80000000;
1734 }
1735 if (ra_val > im_val) {
1736 bf |= 0x40000000;
1737 }
1738 if (ra_val == im_val) {
1739 bf |= 0x20000000;
1740 }
1741 }
1742 #endif
1743 uint32_t condition_mask = 0xF0000000U >> (cr * 4);
1744 uint32_t condition = bf >> (cr * 4);
1745 condition_reg_ = (condition_reg_ & ~condition_mask) | condition;
1746 break;
1747 }
1748 case ADDIC: {
1749 int rt = instr->RTValue();
1750 int ra = instr->RAValue();
1751 uintptr_t ra_val = get_register(ra);
1752 uintptr_t im_val = SIGN_EXT_IMM16(instr->Bits(15, 0));
1753 uintptr_t alu_out = ra_val + im_val;
1754 // Check overflow
1755 if (~ra_val < im_val) {
1756 special_reg_xer_ = (special_reg_xer_ & ~0xF0000000) | 0x20000000;
1757 } else {
1758 special_reg_xer_ &= ~0xF0000000;
1759 }
1760 set_register(rt, alu_out);
1761 break;
1762 }
1763 case ADDI: {
1764 int rt = instr->RTValue();
1765 int ra = instr->RAValue();
1766 int32_t im_val = SIGN_EXT_IMM16(instr->Bits(15, 0));
1767 intptr_t alu_out;
1768 if (ra == 0) {
1769 alu_out = im_val;
1770 } else {
1771 intptr_t ra_val = get_register(ra);
1772 alu_out = ra_val + im_val;
1773 }
1774 set_register(rt, alu_out);
1775 // todo - handle RC bit
1776 break;
1777 }
1778 case ADDIS: {
1779 int rt = instr->RTValue();
1780 int ra = instr->RAValue();
1781 int32_t im_val = (instr->Bits(15, 0) << 16);
1782 intptr_t alu_out;
1783 if (ra == 0) { // treat r0 as zero
1784 alu_out = im_val;
1785 } else {
1786 intptr_t ra_val = get_register(ra);
1787 alu_out = ra_val + im_val;
1788 }
1789 set_register(rt, alu_out);
1790 break;
1791 }
1792 case BCX: {
1793 ExecuteBranchConditional(instr, BC_OFFSET);
1794 break;
1795 }
1796 case BX: {
1797 int offset = (instr->Bits(25, 2) << 8) >> 6;
1798 if (instr->Bit(0) == 1) { // LK flag set
1799 special_reg_lr_ = get_pc() + 4;
1800 }
1801 set_pc(get_pc() + offset);
1802 // todo - AA flag
1803 break;
1804 }
1805 case MCRF:
1806 UNIMPLEMENTED(); // Not used by V8.
1807 case BCLRX:
1808 ExecuteBranchConditional(instr, BC_LINK_REG);
1809 break;
1810 case BCCTRX:
1811 ExecuteBranchConditional(instr, BC_CTR_REG);
1812 break;
1813 case CRNOR:
1814 case RFI:
1815 case CRANDC:
1816 UNIMPLEMENTED();
1817 case ISYNC: {
1818 // todo - simulate isync
1819 break;
1820 }
1821 case CRXOR: {
1822 int bt = instr->Bits(25, 21);
1823 int ba = instr->Bits(20, 16);
1824 int bb = instr->Bits(15, 11);
1825 int ba_val = ((0x80000000 >> ba) & condition_reg_) == 0 ? 0 : 1;
1826 int bb_val = ((0x80000000 >> bb) & condition_reg_) == 0 ? 0 : 1;
1827 int bt_val = ba_val ^ bb_val;
1828 bt_val = bt_val << (31 - bt); // shift bit to correct destination
1829 condition_reg_ &= ~(0x80000000 >> bt);
1830 condition_reg_ |= bt_val;
1831 break;
1832 }
1833 case CREQV: {
1834 int bt = instr->Bits(25, 21);
1835 int ba = instr->Bits(20, 16);
1836 int bb = instr->Bits(15, 11);
1837 int ba_val = ((0x80000000 >> ba) & condition_reg_) == 0 ? 0 : 1;
1838 int bb_val = ((0x80000000 >> bb) & condition_reg_) == 0 ? 0 : 1;
1839 int bt_val = 1 - (ba_val ^ bb_val);
1840 bt_val = bt_val << (31 - bt); // shift bit to correct destination
1841 condition_reg_ &= ~(0x80000000 >> bt);
1842 condition_reg_ |= bt_val;
1843 break;
1844 }
1845 case CRNAND:
1846 case CRAND:
1847 case CRORC:
1848 case CROR: {
1849 UNIMPLEMENTED(); // Not used by V8.
1850 }
1851 case RLWIMIX: {
1852 int ra = instr->RAValue();
1853 int rs = instr->RSValue();
1854 uint32_t rs_val = get_register(rs);
1855 int32_t ra_val = get_register(ra);
1856 int sh = instr->Bits(15, 11);
1857 int mb = instr->Bits(10, 6);
1858 int me = instr->Bits(5, 1);
1859 uint32_t result = base::bits::RotateLeft32(rs_val, sh);
1860 int mask = 0;
1861 if (mb < me + 1) {
1862 int bit = 0x80000000 >> mb;
1863 for (; mb <= me; mb++) {
1864 mask |= bit;
1865 bit >>= 1;
1866 }
1867 } else if (mb == me + 1) {
1868 mask = 0xFFFFFFFF;
1869 } else { // mb > me+1
1870 int bit = 0x80000000 >> (me + 1); // needs to be tested
1871 mask = 0xFFFFFFFF;
1872 for (; me < mb; me++) {
1873 mask ^= bit;
1874 bit >>= 1;
1875 }
1876 }
1877 result &= mask;
1878 ra_val &= ~mask;
1879 result |= ra_val;
1880 set_register(ra, result);
1881 if (instr->Bit(0)) { // RC bit set
1882 SetCR0(result);
1883 }
1884 break;
1885 }
1886 case RLWINMX:
1887 case RLWNMX: {
1888 int ra = instr->RAValue();
1889 int rs = instr->RSValue();
1890 uint32_t rs_val = get_register(rs);
1891 int sh = 0;
1892 if (opcode == RLWINMX) {
1893 sh = instr->Bits(15, 11);
1894 } else {
1895 int rb = instr->RBValue();
1896 uint32_t rb_val = get_register(rb);
1897 sh = (rb_val & 0x1F);
1898 }
1899 int mb = instr->Bits(10, 6);
1900 int me = instr->Bits(5, 1);
1901 uint32_t result = base::bits::RotateLeft32(rs_val, sh);
1902 int mask = 0;
1903 if (mb < me + 1) {
1904 int bit = 0x80000000 >> mb;
1905 for (; mb <= me; mb++) {
1906 mask |= bit;
1907 bit >>= 1;
1908 }
1909 } else if (mb == me + 1) {
1910 mask = 0xFFFFFFFF;
1911 } else { // mb > me+1
1912 int bit = 0x80000000 >> (me + 1); // needs to be tested
1913 mask = 0xFFFFFFFF;
1914 for (; me < mb; me++) {
1915 mask ^= bit;
1916 bit >>= 1;
1917 }
1918 }
1919 result &= mask;
1920 set_register(ra, result);
1921 if (instr->Bit(0)) { // RC bit set
1922 SetCR0(result);
1923 }
1924 break;
1925 }
1926 case ORI: {
1927 int rs = instr->RSValue();
1928 int ra = instr->RAValue();
1929 intptr_t rs_val = get_register(rs);
1930 uint32_t im_val = instr->Bits(15, 0);
1931 intptr_t alu_out = rs_val | im_val;
1932 set_register(ra, alu_out);
1933 break;
1934 }
1935 case ORIS: {
1936 int rs = instr->RSValue();
1937 int ra = instr->RAValue();
1938 intptr_t rs_val = get_register(rs);
1939 uint32_t im_val = instr->Bits(15, 0);
1940 intptr_t alu_out = rs_val | (im_val << 16);
1941 set_register(ra, alu_out);
1942 break;
1943 }
1944 case XORI: {
1945 int rs = instr->RSValue();
1946 int ra = instr->RAValue();
1947 intptr_t rs_val = get_register(rs);
1948 uint32_t im_val = instr->Bits(15, 0);
1949 intptr_t alu_out = rs_val ^ im_val;
1950 set_register(ra, alu_out);
1951 // todo - set condition based SO bit
1952 break;
1953 }
1954 case XORIS: {
1955 int rs = instr->RSValue();
1956 int ra = instr->RAValue();
1957 intptr_t rs_val = get_register(rs);
1958 uint32_t im_val = instr->Bits(15, 0);
1959 intptr_t alu_out = rs_val ^ (im_val << 16);
1960 set_register(ra, alu_out);
1961 break;
1962 }
1963 case ANDIx: {
1964 int rs = instr->RSValue();
1965 int ra = instr->RAValue();
1966 intptr_t rs_val = get_register(rs);
1967 uint32_t im_val = instr->Bits(15, 0);
1968 intptr_t alu_out = rs_val & im_val;
1969 set_register(ra, alu_out);
1970 SetCR0(alu_out);
1971 break;
1972 }
1973 case ANDISx: {
1974 int rs = instr->RSValue();
1975 int ra = instr->RAValue();
1976 intptr_t rs_val = get_register(rs);
1977 uint32_t im_val = instr->Bits(15, 0);
1978 intptr_t alu_out = rs_val & (im_val << 16);
1979 set_register(ra, alu_out);
1980 SetCR0(alu_out);
1981 break;
1982 }
1983 case SRWX: {
1984 int rs = instr->RSValue();
1985 int ra = instr->RAValue();
1986 int rb = instr->RBValue();
1987 uint32_t rs_val = get_register(rs);
1988 uintptr_t rb_val = get_register(rb) & 0x3F;
1989 intptr_t result = (rb_val > 31) ? 0 : rs_val >> rb_val;
1990 set_register(ra, result);
1991 if (instr->Bit(0)) { // RC bit set
1992 SetCR0(result);
1993 }
1994 break;
1995 }
1996 #if V8_TARGET_ARCH_PPC64
1997 case SRDX: {
1998 int rs = instr->RSValue();
1999 int ra = instr->RAValue();
2000 int rb = instr->RBValue();
2001 uintptr_t rs_val = get_register(rs);
2002 uintptr_t rb_val = get_register(rb) & 0x7F;
2003 intptr_t result = (rb_val > 63) ? 0 : rs_val >> rb_val;
2004 set_register(ra, result);
2005 if (instr->Bit(0)) { // RC bit set
2006 SetCR0(result);
2007 }
2008 break;
2009 }
2010 #endif
2011 case MODUW: {
2012 int rt = instr->RTValue();
2013 int ra = instr->RAValue();
2014 int rb = instr->RBValue();
2015 uint32_t ra_val = get_register(ra);
2016 uint32_t rb_val = get_register(rb);
2017 uint32_t alu_out = (rb_val == 0) ? -1 : ra_val % rb_val;
2018 set_register(rt, alu_out);
2019 break;
2020 }
2021 #if V8_TARGET_ARCH_PPC64
2022 case MODUD: {
2023 int rt = instr->RTValue();
2024 int ra = instr->RAValue();
2025 int rb = instr->RBValue();
2026 uint64_t ra_val = get_register(ra);
2027 uint64_t rb_val = get_register(rb);
2028 uint64_t alu_out = (rb_val == 0) ? -1 : ra_val % rb_val;
2029 set_register(rt, alu_out);
2030 break;
2031 }
2032 #endif
2033 case MODSW: {
2034 int rt = instr->RTValue();
2035 int ra = instr->RAValue();
2036 int rb = instr->RBValue();
2037 int32_t ra_val = get_register(ra);
2038 int32_t rb_val = get_register(rb);
2039 bool overflow = (ra_val == kMinInt && rb_val == -1);
2040 // result is undefined if divisor is zero or if operation
2041 // is 0x80000000 / -1.
2042 int32_t alu_out = (rb_val == 0 || overflow) ? -1 : ra_val % rb_val;
2043 set_register(rt, alu_out);
2044 break;
2045 }
2046 #if V8_TARGET_ARCH_PPC64
2047 case MODSD: {
2048 int rt = instr->RTValue();
2049 int ra = instr->RAValue();
2050 int rb = instr->RBValue();
2051 int64_t ra_val = get_register(ra);
2052 int64_t rb_val = get_register(rb);
2053 int64_t one = 1; // work-around gcc
2054 int64_t kMinLongLong = (one << 63);
2055 // result is undefined if divisor is zero or if operation
2056 // is 0x80000000_00000000 / -1.
2057 int64_t alu_out =
2058 (rb_val == 0 || (ra_val == kMinLongLong && rb_val == -1))
2059 ? -1
2060 : ra_val % rb_val;
2061 set_register(rt, alu_out);
2062 break;
2063 }
2064 #endif
2065 case SRAW: {
2066 int rs = instr->RSValue();
2067 int ra = instr->RAValue();
2068 int rb = instr->RBValue();
2069 int32_t rs_val = get_register(rs);
2070 intptr_t rb_val = get_register(rb) & 0x3F;
2071 intptr_t result = (rb_val > 31) ? rs_val >> 31 : rs_val >> rb_val;
2072 set_register(ra, result);
2073 if (instr->Bit(0)) { // RC bit set
2074 SetCR0(result);
2075 }
2076 break;
2077 }
2078 #if V8_TARGET_ARCH_PPC64
2079 case SRAD: {
2080 int rs = instr->RSValue();
2081 int ra = instr->RAValue();
2082 int rb = instr->RBValue();
2083 intptr_t rs_val = get_register(rs);
2084 intptr_t rb_val = get_register(rb) & 0x7F;
2085 intptr_t result = (rb_val > 63) ? rs_val >> 63 : rs_val >> rb_val;
2086 set_register(ra, result);
2087 if (instr->Bit(0)) { // RC bit set
2088 SetCR0(result);
2089 }
2090 break;
2091 }
2092 #endif
2093 case SRAWIX: {
2094 int ra = instr->RAValue();
2095 int rs = instr->RSValue();
2096 int sh = instr->Bits(15, 11);
2097 int32_t rs_val = get_register(rs);
2098 intptr_t result = rs_val >> sh;
2099 set_register(ra, result);
2100 if (instr->Bit(0)) { // RC bit set
2101 SetCR0(result);
2102 }
2103 break;
2104 }
2105 #if V8_TARGET_ARCH_PPC64
2106 case EXTSW: {
2107 const int shift = kBitsPerSystemPointer - 32;
2108 int ra = instr->RAValue();
2109 int rs = instr->RSValue();
2110 intptr_t rs_val = get_register(rs);
2111 intptr_t ra_val = (rs_val << shift) >> shift;
2112 set_register(ra, ra_val);
2113 if (instr->Bit(0)) { // RC bit set
2114 SetCR0(ra_val);
2115 }
2116 break;
2117 }
2118 #endif
2119 case EXTSH: {
2120 const int shift = kBitsPerSystemPointer - 16;
2121 int ra = instr->RAValue();
2122 int rs = instr->RSValue();
2123 intptr_t rs_val = get_register(rs);
2124 intptr_t ra_val = (rs_val << shift) >> shift;
2125 set_register(ra, ra_val);
2126 if (instr->Bit(0)) { // RC bit set
2127 SetCR0(ra_val);
2128 }
2129 break;
2130 }
2131 case EXTSB: {
2132 const int shift = kBitsPerSystemPointer - 8;
2133 int ra = instr->RAValue();
2134 int rs = instr->RSValue();
2135 intptr_t rs_val = get_register(rs);
2136 intptr_t ra_val = (rs_val << shift) >> shift;
2137 set_register(ra, ra_val);
2138 if (instr->Bit(0)) { // RC bit set
2139 SetCR0(ra_val);
2140 }
2141 break;
2142 }
2143 case LFSUX:
2144 case LFSX: {
2145 int frt = instr->RTValue();
2146 int ra = instr->RAValue();
2147 int rb = instr->RBValue();
2148 intptr_t ra_val = ra == 0 ? 0 : get_register(ra);
2149 intptr_t rb_val = get_register(rb);
2150 int32_t val = ReadW(ra_val + rb_val);
2151 float* fptr = reinterpret_cast<float*>(&val);
2152 #if V8_HOST_ARCH_IA32 || V8_HOST_ARCH_X64
2153 // Conversion using double changes sNan to qNan on ia32/x64
2154 if ((val & 0x7F800000) == 0x7F800000) {
2155 int64_t dval = static_cast<int64_t>(val);
2156 dval = ((dval & 0xC0000000) << 32) | ((dval & 0x40000000) << 31) |
2157 ((dval & 0x40000000) << 30) | ((dval & 0x7FFFFFFF) << 29) | 0x0;
2158 set_d_register(frt, dval);
2159 } else {
2160 set_d_register_from_double(frt, static_cast<double>(*fptr));
2161 }
2162 #else
2163 set_d_register_from_double(frt, static_cast<double>(*fptr));
2164 #endif
2165 if (opcode == LFSUX) {
2166 DCHECK_NE(ra, 0);
2167 set_register(ra, ra_val + rb_val);
2168 }
2169 break;
2170 }
2171 case LFDUX:
2172 case LFDX: {
2173 int frt = instr->RTValue();
2174 int ra = instr->RAValue();
2175 int rb = instr->RBValue();
2176 intptr_t ra_val = ra == 0 ? 0 : get_register(ra);
2177 intptr_t rb_val = get_register(rb);
2178 int64_t dptr = ReadDW(ra_val + rb_val);
2179 set_d_register(frt, dptr);
2180 if (opcode == LFDUX) {
2181 DCHECK_NE(ra, 0);
2182 set_register(ra, ra_val + rb_val);
2183 }
2184 break;
2185 }
2186 case STFSUX:
2187 V8_FALLTHROUGH;
2188 case STFSX: {
2189 int frs = instr->RSValue();
2190 int ra = instr->RAValue();
2191 int rb = instr->RBValue();
2192 intptr_t ra_val = ra == 0 ? 0 : get_register(ra);
2193 intptr_t rb_val = get_register(rb);
2194 float frs_val = static_cast<float>(get_double_from_d_register(frs));
2195 int32_t* p = reinterpret_cast<int32_t*>(&frs_val);
2196 #if V8_HOST_ARCH_IA32 || V8_HOST_ARCH_X64
2197 // Conversion using double changes sNan to qNan on ia32/x64
2198 int32_t sval = 0;
2199 int64_t dval = get_d_register(frs);
2200 if ((dval & 0x7FF0000000000000) == 0x7FF0000000000000) {
2201 sval = ((dval & 0xC000000000000000) >> 32) |
2202 ((dval & 0x07FFFFFFE0000000) >> 29);
2203 p = &sval;
2204 } else {
2205 p = reinterpret_cast<int32_t*>(&frs_val);
2206 }
2207 #else
2208 p = reinterpret_cast<int32_t*>(&frs_val);
2209 #endif
2210 WriteW(ra_val + rb_val, *p);
2211 if (opcode == STFSUX) {
2212 DCHECK_NE(ra, 0);
2213 set_register(ra, ra_val + rb_val);
2214 }
2215 break;
2216 }
2217 case STFDUX:
2218 V8_FALLTHROUGH;
2219 case STFDX: {
2220 int frs = instr->RSValue();
2221 int ra = instr->RAValue();
2222 int rb = instr->RBValue();
2223 intptr_t ra_val = ra == 0 ? 0 : get_register(ra);
2224 intptr_t rb_val = get_register(rb);
2225 int64_t frs_val = get_d_register(frs);
2226 WriteDW(ra_val + rb_val, frs_val);
2227 if (opcode == STFDUX) {
2228 DCHECK_NE(ra, 0);
2229 set_register(ra, ra_val + rb_val);
2230 }
2231 break;
2232 }
2233 case POPCNTW: {
2234 int rs = instr->RSValue();
2235 int ra = instr->RAValue();
2236 uintptr_t rs_val = get_register(rs);
2237 uintptr_t count = 0;
2238 int n = 0;
2239 uintptr_t bit = 0x80000000;
2240 for (; n < 32; n++) {
2241 if (bit & rs_val) count++;
2242 bit >>= 1;
2243 }
2244 set_register(ra, count);
2245 break;
2246 }
2247 #if V8_TARGET_ARCH_PPC64
2248 case POPCNTD: {
2249 int rs = instr->RSValue();
2250 int ra = instr->RAValue();
2251 uintptr_t rs_val = get_register(rs);
2252 uintptr_t count = 0;
2253 int n = 0;
2254 uintptr_t bit = 0x8000000000000000UL;
2255 for (; n < 64; n++) {
2256 if (bit & rs_val) count++;
2257 bit >>= 1;
2258 }
2259 set_register(ra, count);
2260 break;
2261 }
2262 #endif
2263 case SYNC: {
2264 // todo - simulate sync
2265 __sync_synchronize();
2266 break;
2267 }
2268 case ICBI: {
2269 // todo - simulate icbi
2270 break;
2271 }
2272
2273 case LWZU:
2274 case LWZ: {
2275 int ra = instr->RAValue();
2276 int rt = instr->RTValue();
2277 intptr_t ra_val = ra == 0 ? 0 : get_register(ra);
2278 int offset = SIGN_EXT_IMM16(instr->Bits(15, 0));
2279 set_register(rt, ReadWU(ra_val + offset));
2280 if (opcode == LWZU) {
2281 DCHECK_NE(ra, 0);
2282 set_register(ra, ra_val + offset);
2283 }
2284 break;
2285 }
2286
2287 case LBZU:
2288 case LBZ: {
2289 int ra = instr->RAValue();
2290 int rt = instr->RTValue();
2291 intptr_t ra_val = ra == 0 ? 0 : get_register(ra);
2292 int offset = SIGN_EXT_IMM16(instr->Bits(15, 0));
2293 set_register(rt, ReadB(ra_val + offset) & 0xFF);
2294 if (opcode == LBZU) {
2295 DCHECK_NE(ra, 0);
2296 set_register(ra, ra_val + offset);
2297 }
2298 break;
2299 }
2300
2301 case STWU:
2302 case STW: {
2303 int ra = instr->RAValue();
2304 int rs = instr->RSValue();
2305 intptr_t ra_val = ra == 0 ? 0 : get_register(ra);
2306 int32_t rs_val = get_register(rs);
2307 int offset = SIGN_EXT_IMM16(instr->Bits(15, 0));
2308 WriteW(ra_val + offset, rs_val);
2309 if (opcode == STWU) {
2310 DCHECK_NE(ra, 0);
2311 set_register(ra, ra_val + offset);
2312 }
2313 break;
2314 }
2315 case SRADIX: {
2316 int ra = instr->RAValue();
2317 int rs = instr->RSValue();
2318 int sh = (instr->Bits(15, 11) | (instr->Bit(1) << 5));
2319 intptr_t rs_val = get_register(rs);
2320 intptr_t result = rs_val >> sh;
2321 set_register(ra, result);
2322 if (instr->Bit(0)) { // RC bit set
2323 SetCR0(result);
2324 }
2325 break;
2326 }
2327 case STBCX: {
2328 int rs = instr->RSValue();
2329 int ra = instr->RAValue();
2330 int rb = instr->RBValue();
2331 intptr_t ra_val = ra == 0 ? 0 : get_register(ra);
2332 int8_t rs_val = get_register(rs);
2333 intptr_t rb_val = get_register(rb);
2334 SetCR0(WriteExB(ra_val + rb_val, rs_val));
2335 break;
2336 }
2337 case STHCX: {
2338 int rs = instr->RSValue();
2339 int ra = instr->RAValue();
2340 int rb = instr->RBValue();
2341 intptr_t ra_val = ra == 0 ? 0 : get_register(ra);
2342 int16_t rs_val = get_register(rs);
2343 intptr_t rb_val = get_register(rb);
2344 SetCR0(WriteExH(ra_val + rb_val, rs_val));
2345 break;
2346 }
2347 case STWCX: {
2348 int rs = instr->RSValue();
2349 int ra = instr->RAValue();
2350 int rb = instr->RBValue();
2351 intptr_t ra_val = ra == 0 ? 0 : get_register(ra);
2352 int32_t rs_val = get_register(rs);
2353 intptr_t rb_val = get_register(rb);
2354 SetCR0(WriteExW(ra_val + rb_val, rs_val));
2355 break;
2356 }
2357 case STDCX: {
2358 int rs = instr->RSValue();
2359 int ra = instr->RAValue();
2360 int rb = instr->RBValue();
2361 intptr_t ra_val = ra == 0 ? 0 : get_register(ra);
2362 int64_t rs_val = get_register(rs);
2363 intptr_t rb_val = get_register(rb);
2364 SetCR0(WriteExDW(ra_val + rb_val, rs_val));
2365 break;
2366 }
2367 case TW: {
2368 // used for call redirection in simulation mode
2369 SoftwareInterrupt(instr);
2370 break;
2371 }
2372 case CMP: {
2373 int ra = instr->RAValue();
2374 int rb = instr->RBValue();
2375 int cr = instr->Bits(25, 23);
2376 uint32_t bf = 0;
2377 #if V8_TARGET_ARCH_PPC64
2378 int L = instr->Bit(21);
2379 if (L) {
2380 #endif
2381 intptr_t ra_val = get_register(ra);
2382 intptr_t rb_val = get_register(rb);
2383 if (ra_val < rb_val) {
2384 bf |= 0x80000000;
2385 }
2386 if (ra_val > rb_val) {
2387 bf |= 0x40000000;
2388 }
2389 if (ra_val == rb_val) {
2390 bf |= 0x20000000;
2391 }
2392 #if V8_TARGET_ARCH_PPC64
2393 } else {
2394 int32_t ra_val = get_register(ra);
2395 int32_t rb_val = get_register(rb);
2396 if (ra_val < rb_val) {
2397 bf |= 0x80000000;
2398 }
2399 if (ra_val > rb_val) {
2400 bf |= 0x40000000;
2401 }
2402 if (ra_val == rb_val) {
2403 bf |= 0x20000000;
2404 }
2405 }
2406 #endif
2407 uint32_t condition_mask = 0xF0000000U >> (cr * 4);
2408 uint32_t condition = bf >> (cr * 4);
2409 condition_reg_ = (condition_reg_ & ~condition_mask) | condition;
2410 break;
2411 }
2412 case SUBFCX: {
2413 int rt = instr->RTValue();
2414 int ra = instr->RAValue();
2415 int rb = instr->RBValue();
2416 // int oe = instr->Bit(10);
2417 uintptr_t ra_val = get_register(ra);
2418 uintptr_t rb_val = get_register(rb);
2419 uintptr_t alu_out = ~ra_val + rb_val + 1;
2420 // Set carry
2421 if (ra_val <= rb_val) {
2422 special_reg_xer_ = (special_reg_xer_ & ~0xF0000000) | 0x20000000;
2423 } else {
2424 special_reg_xer_ &= ~0xF0000000;
2425 }
2426 set_register(rt, alu_out);
2427 if (instr->Bit(0)) { // RC bit set
2428 SetCR0(alu_out);
2429 }
2430 // todo - handle OE bit
2431 break;
2432 }
2433 case SUBFEX: {
2434 int rt = instr->RTValue();
2435 int ra = instr->RAValue();
2436 int rb = instr->RBValue();
2437 // int oe = instr->Bit(10);
2438 uintptr_t ra_val = get_register(ra);
2439 uintptr_t rb_val = get_register(rb);
2440 uintptr_t alu_out = ~ra_val + rb_val;
2441 if (special_reg_xer_ & 0x20000000) {
2442 alu_out += 1;
2443 }
2444 set_register(rt, alu_out);
2445 if (instr->Bit(0)) { // RC bit set
2446 SetCR0(static_cast<intptr_t>(alu_out));
2447 }
2448 // todo - handle OE bit
2449 break;
2450 }
2451 case ADDCX: {
2452 int rt = instr->RTValue();
2453 int ra = instr->RAValue();
2454 int rb = instr->RBValue();
2455 // int oe = instr->Bit(10);
2456 uintptr_t ra_val = get_register(ra);
2457 uintptr_t rb_val = get_register(rb);
2458 uintptr_t alu_out = ra_val + rb_val;
2459 // Set carry
2460 if (~ra_val < rb_val) {
2461 special_reg_xer_ = (special_reg_xer_ & ~0xF0000000) | 0x20000000;
2462 } else {
2463 special_reg_xer_ &= ~0xF0000000;
2464 }
2465 set_register(rt, alu_out);
2466 if (instr->Bit(0)) { // RC bit set
2467 SetCR0(static_cast<intptr_t>(alu_out));
2468 }
2469 // todo - handle OE bit
2470 break;
2471 }
2472 case ADDEX: {
2473 int rt = instr->RTValue();
2474 int ra = instr->RAValue();
2475 int rb = instr->RBValue();
2476 // int oe = instr->Bit(10);
2477 uintptr_t ra_val = get_register(ra);
2478 uintptr_t rb_val = get_register(rb);
2479 uintptr_t alu_out = ra_val + rb_val;
2480 if (special_reg_xer_ & 0x20000000) {
2481 alu_out += 1;
2482 }
2483 set_register(rt, alu_out);
2484 if (instr->Bit(0)) { // RC bit set
2485 SetCR0(static_cast<intptr_t>(alu_out));
2486 }
2487 // todo - handle OE bit
2488 break;
2489 }
2490 case MULHWX: {
2491 int rt = instr->RTValue();
2492 int ra = instr->RAValue();
2493 int rb = instr->RBValue();
2494 int32_t ra_val = (get_register(ra) & 0xFFFFFFFF);
2495 int32_t rb_val = (get_register(rb) & 0xFFFFFFFF);
2496 int64_t alu_out = (int64_t)ra_val * (int64_t)rb_val;
2497 // High 32 bits of the result is undefined,
2498 // Which is simulated here by adding random bits.
2499 alu_out = (alu_out >> 32) | 0x421000000000000;
2500 set_register(rt, alu_out);
2501 if (instr->Bit(0)) { // RC bit set
2502 SetCR0(static_cast<intptr_t>(alu_out));
2503 }
2504 break;
2505 }
2506 case MULHWUX: {
2507 int rt = instr->RTValue();
2508 int ra = instr->RAValue();
2509 int rb = instr->RBValue();
2510 uint32_t ra_val = (get_register(ra) & 0xFFFFFFFF);
2511 uint32_t rb_val = (get_register(rb) & 0xFFFFFFFF);
2512 uint64_t alu_out = (uint64_t)ra_val * (uint64_t)rb_val;
2513 // High 32 bits of the result is undefined,
2514 // Which is simulated here by adding random bits.
2515 alu_out = (alu_out >> 32) | 0x421000000000000;
2516 set_register(rt, alu_out);
2517 if (instr->Bit(0)) { // RC bit set
2518 SetCR0(static_cast<intptr_t>(alu_out));
2519 }
2520 break;
2521 }
2522 case NEGX: {
2523 int rt = instr->RTValue();
2524 int ra = instr->RAValue();
2525 intptr_t ra_val = get_register(ra);
2526 intptr_t alu_out = 1 + ~ra_val;
2527 #if V8_TARGET_ARCH_PPC64
2528 intptr_t one = 1; // work-around gcc
2529 intptr_t kOverflowVal = (one << 63);
2530 #else
2531 intptr_t kOverflowVal = kMinInt;
2532 #endif
2533 set_register(rt, alu_out);
2534 if (instr->Bit(10)) { // OE bit set
2535 if (ra_val == kOverflowVal) {
2536 special_reg_xer_ |= 0xC0000000; // set SO,OV
2537 } else {
2538 special_reg_xer_ &= ~0x40000000; // clear OV
2539 }
2540 }
2541 if (instr->Bit(0)) { // RC bit set
2542 bool setSO = (special_reg_xer_ & 0x80000000);
2543 SetCR0(alu_out, setSO);
2544 }
2545 break;
2546 }
2547 case SLWX: {
2548 int rs = instr->RSValue();
2549 int ra = instr->RAValue();
2550 int rb = instr->RBValue();
2551 uint32_t rs_val = get_register(rs);
2552 uintptr_t rb_val = get_register(rb) & 0x3F;
2553 uint32_t result = (rb_val > 31) ? 0 : rs_val << rb_val;
2554 set_register(ra, result);
2555 if (instr->Bit(0)) { // RC bit set
2556 SetCR0(result);
2557 }
2558 break;
2559 }
2560 #if V8_TARGET_ARCH_PPC64
2561 case SLDX: {
2562 int rs = instr->RSValue();
2563 int ra = instr->RAValue();
2564 int rb = instr->RBValue();
2565 uintptr_t rs_val = get_register(rs);
2566 uintptr_t rb_val = get_register(rb) & 0x7F;
2567 uintptr_t result = (rb_val > 63) ? 0 : rs_val << rb_val;
2568 set_register(ra, result);
2569 if (instr->Bit(0)) { // RC bit set
2570 SetCR0(result);
2571 }
2572 break;
2573 }
2574 case MFVSRD: {
2575 int frt = instr->RTValue();
2576 int ra = instr->RAValue();
2577 int64_t frt_val;
2578 if (!instr->Bit(0)) {
2579 // if double reg (TX=0).
2580 frt_val = get_d_register(frt);
2581 } else {
2582 // if simd reg (TX=1).
2583 DCHECK_EQ(instr->Bit(0), 1);
2584 frt_val = get_simd_register_by_lane<int64_t>(frt, 0);
2585 }
2586 set_register(ra, frt_val);
2587 break;
2588 }
2589 case MFVSRWZ: {
2590 DCHECK(!instr->Bit(0));
2591 int frt = instr->RTValue();
2592 int ra = instr->RAValue();
2593 int64_t frt_val = get_d_register(frt);
2594 set_register(ra, static_cast<uint32_t>(frt_val));
2595 break;
2596 }
2597 case MTVSRD: {
2598 int frt = instr->RTValue();
2599 int ra = instr->RAValue();
2600 int64_t ra_val = get_register(ra);
2601 if (!instr->Bit(0)) {
2602 // if double reg (TX=0).
2603 set_d_register(frt, ra_val);
2604 } else {
2605 // if simd reg (TX=1).
2606 DCHECK_EQ(instr->Bit(0), 1);
2607 set_simd_register_by_lane<int64_t>(frt, 0,
2608 static_cast<int64_t>(ra_val));
2609 // Low 64 bits of the result is undefined,
2610 // Which is simulated here by adding random bits.
2611 set_simd_register_by_lane<int64_t>(
2612 frt, 1, static_cast<int64_t>(0x123456789ABCD));
2613 }
2614 break;
2615 }
2616 case MTVSRDD: {
2617 int xt = instr->RTValue();
2618 int ra = instr->RAValue();
2619 int rb = instr->RBValue();
2620 set_simd_register_by_lane<int64_t>(
2621 xt, 0, static_cast<int64_t>(get_register(ra)));
2622 set_simd_register_by_lane<int64_t>(
2623 xt, 1, static_cast<int64_t>(get_register(rb)));
2624 break;
2625 }
2626 case MTVSRWA: {
2627 DCHECK(!instr->Bit(0));
2628 int frt = instr->RTValue();
2629 int ra = instr->RAValue();
2630 int64_t ra_val = static_cast<int32_t>(get_register(ra));
2631 set_d_register(frt, ra_val);
2632 break;
2633 }
2634 case MTVSRWZ: {
2635 DCHECK(!instr->Bit(0));
2636 int frt = instr->RTValue();
2637 int ra = instr->RAValue();
2638 uint64_t ra_val = static_cast<uint32_t>(get_register(ra));
2639 set_d_register(frt, ra_val);
2640 break;
2641 }
2642 #endif
2643 case CNTLZWX: {
2644 int rs = instr->RSValue();
2645 int ra = instr->RAValue();
2646 uintptr_t rs_val = get_register(rs);
2647 uintptr_t count = 0;
2648 int n = 0;
2649 uintptr_t bit = 0x80000000;
2650 for (; n < 32; n++) {
2651 if (bit & rs_val) break;
2652 count++;
2653 bit >>= 1;
2654 }
2655 set_register(ra, count);
2656 if (instr->Bit(0)) { // RC Bit set
2657 int bf = 0;
2658 if (count > 0) {
2659 bf |= 0x40000000;
2660 }
2661 if (count == 0) {
2662 bf |= 0x20000000;
2663 }
2664 condition_reg_ = (condition_reg_ & ~0xF0000000) | bf;
2665 }
2666 break;
2667 }
2668 case CNTLZDX: {
2669 int rs = instr->RSValue();
2670 int ra = instr->RAValue();
2671 uintptr_t rs_val = get_register(rs);
2672 uintptr_t count = 0;
2673 int n = 0;
2674 uintptr_t bit = 0x8000000000000000UL;
2675 for (; n < 64; n++) {
2676 if (bit & rs_val) break;
2677 count++;
2678 bit >>= 1;
2679 }
2680 set_register(ra, count);
2681 if (instr->Bit(0)) { // RC Bit set
2682 int bf = 0;
2683 if (count > 0) {
2684 bf |= 0x40000000;
2685 }
2686 if (count == 0) {
2687 bf |= 0x20000000;
2688 }
2689 condition_reg_ = (condition_reg_ & ~0xF0000000) | bf;
2690 }
2691 break;
2692 }
2693 case CNTTZWX: {
2694 int rs = instr->RSValue();
2695 int ra = instr->RAValue();
2696 uint32_t rs_val = static_cast<uint32_t>(get_register(rs));
2697 uintptr_t count = rs_val == 0 ? 32 : __builtin_ctz(rs_val);
2698 set_register(ra, count);
2699 if (instr->Bit(0)) { // RC Bit set
2700 int bf = 0;
2701 if (count > 0) {
2702 bf |= 0x40000000;
2703 }
2704 if (count == 0) {
2705 bf |= 0x20000000;
2706 }
2707 condition_reg_ = (condition_reg_ & ~0xF0000000) | bf;
2708 }
2709 break;
2710 }
2711 case CNTTZDX: {
2712 int rs = instr->RSValue();
2713 int ra = instr->RAValue();
2714 uint64_t rs_val = get_register(rs);
2715 uintptr_t count = rs_val == 0 ? 64 : __builtin_ctzl(rs_val);
2716 set_register(ra, count);
2717 if (instr->Bit(0)) { // RC Bit set
2718 int bf = 0;
2719 if (count > 0) {
2720 bf |= 0x40000000;
2721 }
2722 if (count == 0) {
2723 bf |= 0x20000000;
2724 }
2725 condition_reg_ = (condition_reg_ & ~0xF0000000) | bf;
2726 }
2727 break;
2728 }
2729 case ANDX: {
2730 int rs = instr->RSValue();
2731 int ra = instr->RAValue();
2732 int rb = instr->RBValue();
2733 intptr_t rs_val = get_register(rs);
2734 intptr_t rb_val = get_register(rb);
2735 intptr_t alu_out = rs_val & rb_val;
2736 set_register(ra, alu_out);
2737 if (instr->Bit(0)) { // RC Bit set
2738 SetCR0(alu_out);
2739 }
2740 break;
2741 }
2742 case ANDCX: {
2743 int rs = instr->RSValue();
2744 int ra = instr->RAValue();
2745 int rb = instr->RBValue();
2746 intptr_t rs_val = get_register(rs);
2747 intptr_t rb_val = get_register(rb);
2748 intptr_t alu_out = rs_val & ~rb_val;
2749 set_register(ra, alu_out);
2750 if (instr->Bit(0)) { // RC Bit set
2751 SetCR0(alu_out);
2752 }
2753 break;
2754 }
2755 case CMPL: {
2756 int ra = instr->RAValue();
2757 int rb = instr->RBValue();
2758 int cr = instr->Bits(25, 23);
2759 uint32_t bf = 0;
2760 #if V8_TARGET_ARCH_PPC64
2761 int L = instr->Bit(21);
2762 if (L) {
2763 #endif
2764 uintptr_t ra_val = get_register(ra);
2765 uintptr_t rb_val = get_register(rb);
2766 if (ra_val < rb_val) {
2767 bf |= 0x80000000;
2768 }
2769 if (ra_val > rb_val) {
2770 bf |= 0x40000000;
2771 }
2772 if (ra_val == rb_val) {
2773 bf |= 0x20000000;
2774 }
2775 #if V8_TARGET_ARCH_PPC64
2776 } else {
2777 uint32_t ra_val = get_register(ra);
2778 uint32_t rb_val = get_register(rb);
2779 if (ra_val < rb_val) {
2780 bf |= 0x80000000;
2781 }
2782 if (ra_val > rb_val) {
2783 bf |= 0x40000000;
2784 }
2785 if (ra_val == rb_val) {
2786 bf |= 0x20000000;
2787 }
2788 }
2789 #endif
2790 uint32_t condition_mask = 0xF0000000U >> (cr * 4);
2791 uint32_t condition = bf >> (cr * 4);
2792 condition_reg_ = (condition_reg_ & ~condition_mask) | condition;
2793 break;
2794 }
2795 case SUBFX: {
2796 int rt = instr->RTValue();
2797 int ra = instr->RAValue();
2798 int rb = instr->RBValue();
2799 // int oe = instr->Bit(10);
2800 intptr_t ra_val = get_register(ra);
2801 intptr_t rb_val = get_register(rb);
2802 intptr_t alu_out = rb_val - ra_val;
2803 // todo - figure out underflow
2804 set_register(rt, alu_out);
2805 if (instr->Bit(0)) { // RC Bit set
2806 SetCR0(alu_out);
2807 }
2808 // todo - handle OE bit
2809 break;
2810 }
2811 case ADDZEX: {
2812 int rt = instr->RTValue();
2813 int ra = instr->RAValue();
2814 intptr_t ra_val = get_register(ra);
2815 if (special_reg_xer_ & 0x20000000) {
2816 ra_val += 1;
2817 }
2818 set_register(rt, ra_val);
2819 if (instr->Bit(0)) { // RC bit set
2820 SetCR0(ra_val);
2821 }
2822 // todo - handle OE bit
2823 break;
2824 }
2825 case NORX: {
2826 int rs = instr->RSValue();
2827 int ra = instr->RAValue();
2828 int rb = instr->RBValue();
2829 intptr_t rs_val = get_register(rs);
2830 intptr_t rb_val = get_register(rb);
2831 intptr_t alu_out = ~(rs_val | rb_val);
2832 set_register(ra, alu_out);
2833 if (instr->Bit(0)) { // RC bit set
2834 SetCR0(alu_out);
2835 }
2836 break;
2837 }
2838 case MULLW: {
2839 int rt = instr->RTValue();
2840 int ra = instr->RAValue();
2841 int rb = instr->RBValue();
2842 int32_t ra_val = (get_register(ra) & 0xFFFFFFFF);
2843 int32_t rb_val = (get_register(rb) & 0xFFFFFFFF);
2844 int32_t alu_out = ra_val * rb_val;
2845 set_register(rt, alu_out);
2846 if (instr->Bit(0)) { // RC bit set
2847 SetCR0(alu_out);
2848 }
2849 // todo - handle OE bit
2850 break;
2851 }
2852 #if V8_TARGET_ARCH_PPC64
2853 case MULLD: {
2854 int rt = instr->RTValue();
2855 int ra = instr->RAValue();
2856 int rb = instr->RBValue();
2857 int64_t ra_val = get_register(ra);
2858 int64_t rb_val = get_register(rb);
2859 int64_t alu_out = ra_val * rb_val;
2860 set_register(rt, alu_out);
2861 if (instr->Bit(0)) { // RC bit set
2862 SetCR0(alu_out);
2863 }
2864 // todo - handle OE bit
2865 break;
2866 }
2867 #endif
2868 case DIVW: {
2869 int rt = instr->RTValue();
2870 int ra = instr->RAValue();
2871 int rb = instr->RBValue();
2872 int32_t ra_val = get_register(ra);
2873 int32_t rb_val = get_register(rb);
2874 bool overflow = (ra_val == kMinInt && rb_val == -1);
2875 // result is undefined if divisor is zero or if operation
2876 // is 0x80000000 / -1.
2877 int32_t alu_out = (rb_val == 0 || overflow) ? -1 : ra_val / rb_val;
2878 set_register(rt, alu_out);
2879 if (instr->Bit(10)) { // OE bit set
2880 if (overflow) {
2881 special_reg_xer_ |= 0xC0000000; // set SO,OV
2882 } else {
2883 special_reg_xer_ &= ~0x40000000; // clear OV
2884 }
2885 }
2886 if (instr->Bit(0)) { // RC bit set
2887 bool setSO = (special_reg_xer_ & 0x80000000);
2888 SetCR0(alu_out, setSO);
2889 }
2890 break;
2891 }
2892 case DIVWU: {
2893 int rt = instr->RTValue();
2894 int ra = instr->RAValue();
2895 int rb = instr->RBValue();
2896 uint32_t ra_val = get_register(ra);
2897 uint32_t rb_val = get_register(rb);
2898 bool overflow = (rb_val == 0);
2899 // result is undefined if divisor is zero
2900 uint32_t alu_out = (overflow) ? -1 : ra_val / rb_val;
2901 set_register(rt, alu_out);
2902 if (instr->Bit(10)) { // OE bit set
2903 if (overflow) {
2904 special_reg_xer_ |= 0xC0000000; // set SO,OV
2905 } else {
2906 special_reg_xer_ &= ~0x40000000; // clear OV
2907 }
2908 }
2909 if (instr->Bit(0)) { // RC bit set
2910 bool setSO = (special_reg_xer_ & 0x80000000);
2911 SetCR0(alu_out, setSO);
2912 }
2913 break;
2914 }
2915 #if V8_TARGET_ARCH_PPC64
2916 case DIVD: {
2917 int rt = instr->RTValue();
2918 int ra = instr->RAValue();
2919 int rb = instr->RBValue();
2920 int64_t ra_val = get_register(ra);
2921 int64_t rb_val = get_register(rb);
2922 int64_t one = 1; // work-around gcc
2923 int64_t kMinLongLong = (one << 63);
2924 // result is undefined if divisor is zero or if operation
2925 // is 0x80000000_00000000 / -1.
2926 int64_t alu_out =
2927 (rb_val == 0 || (ra_val == kMinLongLong && rb_val == -1))
2928 ? -1
2929 : ra_val / rb_val;
2930 set_register(rt, alu_out);
2931 if (instr->Bit(0)) { // RC bit set
2932 SetCR0(alu_out);
2933 }
2934 // todo - handle OE bit
2935 break;
2936 }
2937 case DIVDU: {
2938 int rt = instr->RTValue();
2939 int ra = instr->RAValue();
2940 int rb = instr->RBValue();
2941 uint64_t ra_val = get_register(ra);
2942 uint64_t rb_val = get_register(rb);
2943 // result is undefined if divisor is zero
2944 uint64_t alu_out = (rb_val == 0) ? -1 : ra_val / rb_val;
2945 set_register(rt, alu_out);
2946 if (instr->Bit(0)) { // RC bit set
2947 SetCR0(alu_out);
2948 }
2949 // todo - handle OE bit
2950 break;
2951 }
2952 #endif
2953 case ADDX: {
2954 int rt = instr->RTValue();
2955 int ra = instr->RAValue();
2956 int rb = instr->RBValue();
2957 // int oe = instr->Bit(10);
2958 intptr_t ra_val = get_register(ra);
2959 intptr_t rb_val = get_register(rb);
2960 intptr_t alu_out = ra_val + rb_val;
2961 set_register(rt, alu_out);
2962 if (instr->Bit(0)) { // RC bit set
2963 SetCR0(alu_out);
2964 }
2965 // todo - handle OE bit
2966 break;
2967 }
2968 case XORX: {
2969 int rs = instr->RSValue();
2970 int ra = instr->RAValue();
2971 int rb = instr->RBValue();
2972 intptr_t rs_val = get_register(rs);
2973 intptr_t rb_val = get_register(rb);
2974 intptr_t alu_out = rs_val ^ rb_val;
2975 set_register(ra, alu_out);
2976 if (instr->Bit(0)) { // RC bit set
2977 SetCR0(alu_out);
2978 }
2979 break;
2980 }
2981 case ORX: {
2982 int rs = instr->RSValue();
2983 int ra = instr->RAValue();
2984 int rb = instr->RBValue();
2985 intptr_t rs_val = get_register(rs);
2986 intptr_t rb_val = get_register(rb);
2987 intptr_t alu_out = rs_val | rb_val;
2988 set_register(ra, alu_out);
2989 if (instr->Bit(0)) { // RC bit set
2990 SetCR0(alu_out);
2991 }
2992 break;
2993 }
2994 case ORC: {
2995 int rs = instr->RSValue();
2996 int ra = instr->RAValue();
2997 int rb = instr->RBValue();
2998 intptr_t rs_val = get_register(rs);
2999 intptr_t rb_val = get_register(rb);
3000 intptr_t alu_out = rs_val | ~rb_val;
3001 set_register(ra, alu_out);
3002 if (instr->Bit(0)) { // RC bit set
3003 SetCR0(alu_out);
3004 }
3005 break;
3006 }
3007 case MFSPR: {
3008 int rt = instr->RTValue();
3009 int spr = instr->Bits(20, 11);
3010 if (spr != 256) {
3011 UNIMPLEMENTED(); // Only LRLR supported
3012 }
3013 set_register(rt, special_reg_lr_);
3014 break;
3015 }
3016 case MTSPR: {
3017 int rt = instr->RTValue();
3018 intptr_t rt_val = get_register(rt);
3019 int spr = instr->Bits(20, 11);
3020 if (spr == 256) {
3021 special_reg_lr_ = rt_val;
3022 } else if (spr == 288) {
3023 special_reg_ctr_ = rt_val;
3024 } else if (spr == 32) {
3025 special_reg_xer_ = rt_val;
3026 } else {
3027 UNIMPLEMENTED(); // Only LR supported
3028 }
3029 break;
3030 }
3031 case MFCR: {
3032 int rt = instr->RTValue();
3033 set_register(rt, condition_reg_);
3034 break;
3035 }
3036 case STWUX:
3037 case STWX: {
3038 int rs = instr->RSValue();
3039 int ra = instr->RAValue();
3040 int rb = instr->RBValue();
3041 intptr_t ra_val = ra == 0 ? 0 : get_register(ra);
3042 int32_t rs_val = get_register(rs);
3043 intptr_t rb_val = get_register(rb);
3044 WriteW(ra_val + rb_val, rs_val);
3045 if (opcode == STWUX) {
3046 DCHECK_NE(ra, 0);
3047 set_register(ra, ra_val + rb_val);
3048 }
3049 break;
3050 }
3051 case STBUX:
3052 case STBX: {
3053 int rs = instr->RSValue();
3054 int ra = instr->RAValue();
3055 int rb = instr->RBValue();
3056 intptr_t ra_val = ra == 0 ? 0 : get_register(ra);
3057 int8_t rs_val = get_register(rs);
3058 intptr_t rb_val = get_register(rb);
3059 WriteB(ra_val + rb_val, rs_val);
3060 if (opcode == STBUX) {
3061 DCHECK_NE(ra, 0);
3062 set_register(ra, ra_val + rb_val);
3063 }
3064 break;
3065 }
3066 case STHUX:
3067 case STHX: {
3068 int rs = instr->RSValue();
3069 int ra = instr->RAValue();
3070 int rb = instr->RBValue();
3071 intptr_t ra_val = ra == 0 ? 0 : get_register(ra);
3072 int16_t rs_val = get_register(rs);
3073 intptr_t rb_val = get_register(rb);
3074 WriteH(ra_val + rb_val, rs_val);
3075 if (opcode == STHUX) {
3076 DCHECK_NE(ra, 0);
3077 set_register(ra, ra_val + rb_val);
3078 }
3079 break;
3080 }
3081 case LWZX:
3082 case LWZUX: {
3083 int rt = instr->RTValue();
3084 int ra = instr->RAValue();
3085 int rb = instr->RBValue();
3086 intptr_t ra_val = ra == 0 ? 0 : get_register(ra);
3087 intptr_t rb_val = get_register(rb);
3088 set_register(rt, ReadWU(ra_val + rb_val));
3089 if (opcode == LWZUX) {
3090 DCHECK(ra != 0 && ra != rt);
3091 set_register(ra, ra_val + rb_val);
3092 }
3093 break;
3094 }
3095 #if V8_TARGET_ARCH_PPC64
3096 case LWAX: {
3097 int rt = instr->RTValue();
3098 int ra = instr->RAValue();
3099 int rb = instr->RBValue();
3100 intptr_t ra_val = ra == 0 ? 0 : get_register(ra);
3101 intptr_t rb_val = get_register(rb);
3102 set_register(rt, ReadW(ra_val + rb_val));
3103 break;
3104 }
3105 case LDX:
3106 case LDUX: {
3107 int rt = instr->RTValue();
3108 int ra = instr->RAValue();
3109 int rb = instr->RBValue();
3110 intptr_t ra_val = ra == 0 ? 0 : get_register(ra);
3111 intptr_t rb_val = get_register(rb);
3112 intptr_t result = ReadDW(ra_val + rb_val);
3113 set_register(rt, result);
3114 if (opcode == LDUX) {
3115 DCHECK(ra != 0 && ra != rt);
3116 set_register(ra, ra_val + rb_val);
3117 }
3118 break;
3119 }
3120 case LDBRX: {
3121 int rt = instr->RTValue();
3122 int ra = instr->RAValue();
3123 int rb = instr->RBValue();
3124 intptr_t ra_val = ra == 0 ? 0 : get_register(ra);
3125 intptr_t rb_val = get_register(rb);
3126 intptr_t result = __builtin_bswap64(ReadDW(ra_val + rb_val));
3127 set_register(rt, result);
3128 break;
3129 }
3130 case LWBRX: {
3131 int rt = instr->RTValue();
3132 int ra = instr->RAValue();
3133 int rb = instr->RBValue();
3134 intptr_t ra_val = ra == 0 ? 0 : get_register(ra);
3135 intptr_t rb_val = get_register(rb);
3136 intptr_t result = __builtin_bswap32(ReadW(ra_val + rb_val));
3137 set_register(rt, result);
3138 break;
3139 }
3140 case STDBRX: {
3141 int rs = instr->RSValue();
3142 int ra = instr->RAValue();
3143 int rb = instr->RBValue();
3144 intptr_t ra_val = ra == 0 ? 0 : get_register(ra);
3145 intptr_t rs_val = get_register(rs);
3146 intptr_t rb_val = get_register(rb);
3147 WriteDW(ra_val + rb_val, __builtin_bswap64(rs_val));
3148 break;
3149 }
3150 case STWBRX: {
3151 int rs = instr->RSValue();
3152 int ra = instr->RAValue();
3153 int rb = instr->RBValue();
3154 intptr_t ra_val = ra == 0 ? 0 : get_register(ra);
3155 intptr_t rs_val = get_register(rs);
3156 intptr_t rb_val = get_register(rb);
3157 WriteW(ra_val + rb_val, __builtin_bswap32(rs_val));
3158 break;
3159 }
3160 case STHBRX: {
3161 int rs = instr->RSValue();
3162 int ra = instr->RAValue();
3163 int rb = instr->RBValue();
3164 intptr_t ra_val = ra == 0 ? 0 : get_register(ra);
3165 intptr_t rs_val = get_register(rs);
3166 intptr_t rb_val = get_register(rb);
3167 WriteH(ra_val + rb_val, __builtin_bswap16(rs_val));
3168 break;
3169 }
3170 case STDX:
3171 case STDUX: {
3172 int rs = instr->RSValue();
3173 int ra = instr->RAValue();
3174 int rb = instr->RBValue();
3175 intptr_t ra_val = ra == 0 ? 0 : get_register(ra);
3176 intptr_t rs_val = get_register(rs);
3177 intptr_t rb_val = get_register(rb);
3178 WriteDW(ra_val + rb_val, rs_val);
3179 if (opcode == STDUX) {
3180 DCHECK_NE(ra, 0);
3181 set_register(ra, ra_val + rb_val);
3182 }
3183 break;
3184 }
3185 #endif
3186 case LBZX:
3187 case LBZUX: {
3188 int rt = instr->RTValue();
3189 int ra = instr->RAValue();
3190 int rb = instr->RBValue();
3191 intptr_t ra_val = ra == 0 ? 0 : get_register(ra);
3192 intptr_t rb_val = get_register(rb);
3193 set_register(rt, ReadBU(ra_val + rb_val) & 0xFF);
3194 if (opcode == LBZUX) {
3195 DCHECK(ra != 0 && ra != rt);
3196 set_register(ra, ra_val + rb_val);
3197 }
3198 break;
3199 }
3200 case LHZX:
3201 case LHZUX: {
3202 int rt = instr->RTValue();
3203 int ra = instr->RAValue();
3204 int rb = instr->RBValue();
3205 intptr_t ra_val = ra == 0 ? 0 : get_register(ra);
3206 intptr_t rb_val = get_register(rb);
3207 set_register(rt, ReadHU(ra_val + rb_val) & 0xFFFF);
3208 if (opcode == LHZUX) {
3209 DCHECK(ra != 0 && ra != rt);
3210 set_register(ra, ra_val + rb_val);
3211 }
3212 break;
3213 }
3214 case LHAX: {
3215 int rt = instr->RTValue();
3216 int ra = instr->RAValue();
3217 int rb = instr->RBValue();
3218 intptr_t ra_val = ra == 0 ? 0 : get_register(ra);
3219 intptr_t rb_val = get_register(rb);
3220 set_register(rt, ReadH(ra_val + rb_val));
3221 break;
3222 }
3223 case LBARX: {
3224 int rt = instr->RTValue();
3225 int ra = instr->RAValue();
3226 int rb = instr->RBValue();
3227 intptr_t ra_val = ra == 0 ? 0 : get_register(ra);
3228 intptr_t rb_val = get_register(rb);
3229 set_register(rt, ReadExBU(ra_val + rb_val) & 0xFF);
3230 break;
3231 }
3232 case LHARX: {
3233 int rt = instr->RTValue();
3234 int ra = instr->RAValue();
3235 int rb = instr->RBValue();
3236 intptr_t ra_val = ra == 0 ? 0 : get_register(ra);
3237 intptr_t rb_val = get_register(rb);
3238 set_register(rt, ReadExHU(ra_val + rb_val));
3239 break;
3240 }
3241 case LWARX: {
3242 int rt = instr->RTValue();
3243 int ra = instr->RAValue();
3244 int rb = instr->RBValue();
3245 intptr_t ra_val = ra == 0 ? 0 : get_register(ra);
3246 intptr_t rb_val = get_register(rb);
3247 set_register(rt, ReadExWU(ra_val + rb_val));
3248 break;
3249 }
3250 case LDARX: {
3251 int rt = instr->RTValue();
3252 int ra = instr->RAValue();
3253 int rb = instr->RBValue();
3254 intptr_t ra_val = ra == 0 ? 0 : get_register(ra);
3255 intptr_t rb_val = get_register(rb);
3256 set_register(rt, ReadExDWU(ra_val + rb_val));
3257 break;
3258 }
3259 case DCBF: {
3260 // todo - simulate dcbf
3261 break;
3262 }
3263 case ISEL: {
3264 int rt = instr->RTValue();
3265 int ra = instr->RAValue();
3266 int rb = instr->RBValue();
3267 int condition_bit = instr->RCValue();
3268 int condition_mask = 0x80000000 >> condition_bit;
3269 intptr_t ra_val = (ra == 0) ? 0 : get_register(ra);
3270 intptr_t rb_val = get_register(rb);
3271 intptr_t value = (condition_reg_ & condition_mask) ? ra_val : rb_val;
3272 set_register(rt, value);
3273 break;
3274 }
3275
3276 case STBU:
3277 case STB: {
3278 int ra = instr->RAValue();
3279 int rs = instr->RSValue();
3280 intptr_t ra_val = ra == 0 ? 0 : get_register(ra);
3281 int8_t rs_val = get_register(rs);
3282 int offset = SIGN_EXT_IMM16(instr->Bits(15, 0));
3283 WriteB(ra_val + offset, rs_val);
3284 if (opcode == STBU) {
3285 DCHECK_NE(ra, 0);
3286 set_register(ra, ra_val + offset);
3287 }
3288 break;
3289 }
3290
3291 case LHZU:
3292 case LHZ: {
3293 int ra = instr->RAValue();
3294 int rt = instr->RTValue();
3295 intptr_t ra_val = ra == 0 ? 0 : get_register(ra);
3296 int offset = SIGN_EXT_IMM16(instr->Bits(15, 0));
3297 uintptr_t result = ReadHU(ra_val + offset) & 0xFFFF;
3298 set_register(rt, result);
3299 if (opcode == LHZU) {
3300 set_register(ra, ra_val + offset);
3301 }
3302 break;
3303 }
3304
3305 case LHA:
3306 case LHAU: {
3307 int ra = instr->RAValue();
3308 int rt = instr->RTValue();
3309 intptr_t ra_val = ra == 0 ? 0 : get_register(ra);
3310 int offset = SIGN_EXT_IMM16(instr->Bits(15, 0));
3311 intptr_t result = ReadH(ra_val + offset);
3312 set_register(rt, result);
3313 if (opcode == LHAU) {
3314 set_register(ra, ra_val + offset);
3315 }
3316 break;
3317 }
3318
3319 case STHU:
3320 case STH: {
3321 int ra = instr->RAValue();
3322 int rs = instr->RSValue();
3323 intptr_t ra_val = ra == 0 ? 0 : get_register(ra);
3324 int16_t rs_val = get_register(rs);
3325 int offset = SIGN_EXT_IMM16(instr->Bits(15, 0));
3326 WriteH(ra_val + offset, rs_val);
3327 if (opcode == STHU) {
3328 DCHECK_NE(ra, 0);
3329 set_register(ra, ra_val + offset);
3330 }
3331 break;
3332 }
3333
3334 case LMW:
3335 case STMW: {
3336 UNIMPLEMENTED();
3337 }
3338
3339 case LFSU:
3340 case LFS: {
3341 int frt = instr->RTValue();
3342 int ra = instr->RAValue();
3343 int32_t offset = SIGN_EXT_IMM16(instr->Bits(15, 0));
3344 intptr_t ra_val = ra == 0 ? 0 : get_register(ra);
3345 int32_t val = ReadW(ra_val + offset);
3346 float* fptr = reinterpret_cast<float*>(&val);
3347 #if V8_HOST_ARCH_IA32 || V8_HOST_ARCH_X64
3348 // Conversion using double changes sNan to qNan on ia32/x64
3349 if ((val & 0x7F800000) == 0x7F800000) {
3350 int64_t dval = static_cast<int64_t>(val);
3351 dval = ((dval & 0xC0000000) << 32) | ((dval & 0x40000000) << 31) |
3352 ((dval & 0x40000000) << 30) | ((dval & 0x7FFFFFFF) << 29) | 0x0;
3353 set_d_register(frt, dval);
3354 } else {
3355 set_d_register_from_double(frt, static_cast<double>(*fptr));
3356 }
3357 #else
3358 set_d_register_from_double(frt, static_cast<double>(*fptr));
3359 #endif
3360 if (opcode == LFSU) {
3361 DCHECK_NE(ra, 0);
3362 set_register(ra, ra_val + offset);
3363 }
3364 break;
3365 }
3366
3367 case LFDU:
3368 case LFD: {
3369 int frt = instr->RTValue();
3370 int ra = instr->RAValue();
3371 int32_t offset = SIGN_EXT_IMM16(instr->Bits(15, 0));
3372 intptr_t ra_val = ra == 0 ? 0 : get_register(ra);
3373 int64_t dptr = ReadDW(ra_val + offset);
3374 set_d_register(frt, dptr);
3375 if (opcode == LFDU) {
3376 DCHECK_NE(ra, 0);
3377 set_register(ra, ra_val + offset);
3378 }
3379 break;
3380 }
3381
3382 case STFSU:
3383 V8_FALLTHROUGH;
3384 case STFS: {
3385 int frs = instr->RSValue();
3386 int ra = instr->RAValue();
3387 int32_t offset = SIGN_EXT_IMM16(instr->Bits(15, 0));
3388 intptr_t ra_val = ra == 0 ? 0 : get_register(ra);
3389 float frs_val = static_cast<float>(get_double_from_d_register(frs));
3390 int32_t* p;
3391 #if V8_HOST_ARCH_IA32 || V8_HOST_ARCH_X64
3392 // Conversion using double changes sNan to qNan on ia32/x64
3393 int32_t sval = 0;
3394 int64_t dval = get_d_register(frs);
3395 if ((dval & 0x7FF0000000000000) == 0x7FF0000000000000) {
3396 sval = ((dval & 0xC000000000000000) >> 32) |
3397 ((dval & 0x07FFFFFFE0000000) >> 29);
3398 p = &sval;
3399 } else {
3400 p = reinterpret_cast<int32_t*>(&frs_val);
3401 }
3402 #else
3403 p = reinterpret_cast<int32_t*>(&frs_val);
3404 #endif
3405 WriteW(ra_val + offset, *p);
3406 if (opcode == STFSU) {
3407 DCHECK_NE(ra, 0);
3408 set_register(ra, ra_val + offset);
3409 }
3410 break;
3411 }
3412 case STFDU:
3413 case STFD: {
3414 int frs = instr->RSValue();
3415 int ra = instr->RAValue();
3416 int32_t offset = SIGN_EXT_IMM16(instr->Bits(15, 0));
3417 intptr_t ra_val = ra == 0 ? 0 : get_register(ra);
3418 int64_t frs_val = get_d_register(frs);
3419 WriteDW(ra_val + offset, frs_val);
3420 if (opcode == STFDU) {
3421 DCHECK_NE(ra, 0);
3422 set_register(ra, ra_val + offset);
3423 }
3424 break;
3425 }
3426 case BRW: {
3427 constexpr int kBitsPerWord = 32;
3428 int rs = instr->RSValue();
3429 int ra = instr->RAValue();
3430 uint64_t rs_val = get_register(rs);
3431 uint32_t rs_high = rs_val >> kBitsPerWord;
3432 uint32_t rs_low = (rs_val << kBitsPerWord) >> kBitsPerWord;
3433 uint64_t result = __builtin_bswap32(rs_high);
3434 result = (result << kBitsPerWord) | __builtin_bswap32(rs_low);
3435 set_register(ra, result);
3436 break;
3437 }
3438 case BRD: {
3439 int rs = instr->RSValue();
3440 int ra = instr->RAValue();
3441 uint64_t rs_val = get_register(rs);
3442 set_register(ra, __builtin_bswap64(rs_val));
3443 break;
3444 }
3445 case FCFIDS: {
3446 // fcfids
3447 int frt = instr->RTValue();
3448 int frb = instr->RBValue();
3449 int64_t frb_val = get_d_register(frb);
3450 double frt_val = static_cast<float>(frb_val);
3451 set_d_register_from_double(frt, frt_val);
3452 return;
3453 }
3454 case FCFIDUS: {
3455 // fcfidus
3456 int frt = instr->RTValue();
3457 int frb = instr->RBValue();
3458 uint64_t frb_val = get_d_register(frb);
3459 double frt_val = static_cast<float>(frb_val);
3460 set_d_register_from_double(frt, frt_val);
3461 return;
3462 }
3463
3464 case FDIV: {
3465 int frt = instr->RTValue();
3466 int fra = instr->RAValue();
3467 int frb = instr->RBValue();
3468 double fra_val = get_double_from_d_register(fra);
3469 double frb_val = get_double_from_d_register(frb);
3470 double frt_val = fra_val / frb_val;
3471 set_d_register_from_double(frt, frt_val);
3472 return;
3473 }
3474 case FSUB: {
3475 int frt = instr->RTValue();
3476 int fra = instr->RAValue();
3477 int frb = instr->RBValue();
3478 double fra_val = get_double_from_d_register(fra);
3479 double frb_val = get_double_from_d_register(frb);
3480 double frt_val = fra_val - frb_val;
3481 set_d_register_from_double(frt, frt_val);
3482 return;
3483 }
3484 case FADD: {
3485 int frt = instr->RTValue();
3486 int fra = instr->RAValue();
3487 int frb = instr->RBValue();
3488 double fra_val = get_double_from_d_register(fra);
3489 double frb_val = get_double_from_d_register(frb);
3490 double frt_val = fra_val + frb_val;
3491 set_d_register_from_double(frt, frt_val);
3492 return;
3493 }
3494 case FSQRT: {
3495 int frt = instr->RTValue();
3496 int frb = instr->RBValue();
3497 double frb_val = get_double_from_d_register(frb);
3498 double frt_val = std::sqrt(frb_val);
3499 set_d_register_from_double(frt, frt_val);
3500 return;
3501 }
3502 case FSEL: {
3503 int frt = instr->RTValue();
3504 int fra = instr->RAValue();
3505 int frb = instr->RBValue();
3506 int frc = instr->RCValue();
3507 double fra_val = get_double_from_d_register(fra);
3508 double frb_val = get_double_from_d_register(frb);
3509 double frc_val = get_double_from_d_register(frc);
3510 double frt_val = ((fra_val >= 0.0) ? frc_val : frb_val);
3511 set_d_register_from_double(frt, frt_val);
3512 return;
3513 }
3514 case FMUL: {
3515 int frt = instr->RTValue();
3516 int fra = instr->RAValue();
3517 int frc = instr->RCValue();
3518 double fra_val = get_double_from_d_register(fra);
3519 double frc_val = get_double_from_d_register(frc);
3520 double frt_val = fra_val * frc_val;
3521 set_d_register_from_double(frt, frt_val);
3522 return;
3523 }
3524 case FMSUB: {
3525 int frt = instr->RTValue();
3526 int fra = instr->RAValue();
3527 int frb = instr->RBValue();
3528 int frc = instr->RCValue();
3529 double fra_val = get_double_from_d_register(fra);
3530 double frb_val = get_double_from_d_register(frb);
3531 double frc_val = get_double_from_d_register(frc);
3532 double frt_val = (fra_val * frc_val) - frb_val;
3533 set_d_register_from_double(frt, frt_val);
3534 return;
3535 }
3536 case FMADD: {
3537 int frt = instr->RTValue();
3538 int fra = instr->RAValue();
3539 int frb = instr->RBValue();
3540 int frc = instr->RCValue();
3541 double fra_val = get_double_from_d_register(fra);
3542 double frb_val = get_double_from_d_register(frb);
3543 double frc_val = get_double_from_d_register(frc);
3544 double frt_val = (fra_val * frc_val) + frb_val;
3545 set_d_register_from_double(frt, frt_val);
3546 return;
3547 }
3548 case FCMPU: {
3549 int fra = instr->RAValue();
3550 int frb = instr->RBValue();
3551 double fra_val = get_double_from_d_register(fra);
3552 double frb_val = get_double_from_d_register(frb);
3553 int cr = instr->Bits(25, 23);
3554 int bf = 0;
3555 if (fra_val < frb_val) {
3556 bf |= 0x80000000;
3557 }
3558 if (fra_val > frb_val) {
3559 bf |= 0x40000000;
3560 }
3561 if (fra_val == frb_val) {
3562 bf |= 0x20000000;
3563 }
3564 if (std::isunordered(fra_val, frb_val)) {
3565 bf |= 0x10000000;
3566 }
3567 int condition_mask = 0xF0000000 >> (cr * 4);
3568 int condition = bf >> (cr * 4);
3569 condition_reg_ = (condition_reg_ & ~condition_mask) | condition;
3570 return;
3571 }
3572 case FRIN: {
3573 int frt = instr->RTValue();
3574 int frb = instr->RBValue();
3575 double frb_val = get_double_from_d_register(frb);
3576 double frt_val = std::round(frb_val);
3577 set_d_register_from_double(frt, frt_val);
3578 if (instr->Bit(0)) { // RC bit set
3579 // UNIMPLEMENTED();
3580 }
3581 return;
3582 }
3583 case FRIZ: {
3584 int frt = instr->RTValue();
3585 int frb = instr->RBValue();
3586 double frb_val = get_double_from_d_register(frb);
3587 double frt_val = std::trunc(frb_val);
3588 set_d_register_from_double(frt, frt_val);
3589 if (instr->Bit(0)) { // RC bit set
3590 // UNIMPLEMENTED();
3591 }
3592 return;
3593 }
3594 case FRIP: {
3595 int frt = instr->RTValue();
3596 int frb = instr->RBValue();
3597 double frb_val = get_double_from_d_register(frb);
3598 double frt_val = std::ceil(frb_val);
3599 set_d_register_from_double(frt, frt_val);
3600 if (instr->Bit(0)) { // RC bit set
3601 // UNIMPLEMENTED();
3602 }
3603 return;
3604 }
3605 case FRIM: {
3606 int frt = instr->RTValue();
3607 int frb = instr->RBValue();
3608 double frb_val = get_double_from_d_register(frb);
3609 double frt_val = std::floor(frb_val);
3610 set_d_register_from_double(frt, frt_val);
3611 if (instr->Bit(0)) { // RC bit set
3612 // UNIMPLEMENTED();
3613 }
3614 return;
3615 }
3616 case FRSP: {
3617 int frt = instr->RTValue();
3618 int frb = instr->RBValue();
3619 // frsp round 8-byte double-precision value to
3620 // single-precision value
3621 double frb_val = get_double_from_d_register(frb);
3622 double frt_val = static_cast<float>(frb_val);
3623 set_d_register_from_double(frt, frt_val);
3624 if (instr->Bit(0)) { // RC bit set
3625 // UNIMPLEMENTED();
3626 }
3627 return;
3628 }
3629 case FCFID: {
3630 int frt = instr->RTValue();
3631 int frb = instr->RBValue();
3632 int64_t frb_val = get_d_register(frb);
3633 double frt_val = static_cast<double>(frb_val);
3634 set_d_register_from_double(frt, frt_val);
3635 return;
3636 }
3637 case FCFIDU: {
3638 int frt = instr->RTValue();
3639 int frb = instr->RBValue();
3640 uint64_t frb_val = get_d_register(frb);
3641 double frt_val = static_cast<double>(frb_val);
3642 set_d_register_from_double(frt, frt_val);
3643 return;
3644 }
3645 case FCTID:
3646 case FCTIDZ: {
3647 int frt = instr->RTValue();
3648 int frb = instr->RBValue();
3649 double frb_val = get_double_from_d_register(frb);
3650 int mode = (opcode == FCTIDZ) ? kRoundToZero
3651 : (fp_condition_reg_ & kFPRoundingModeMask);
3652 int64_t frt_val;
3653 int64_t one = 1; // work-around gcc
3654 int64_t kMinVal = (one << 63);
3655 int64_t kMaxVal = kMinVal - 1;
3656 bool invalid_convert = false;
3657
3658 if (std::isnan(frb_val)) {
3659 frt_val = kMinVal;
3660 invalid_convert = true;
3661 } else {
3662 switch (mode) {
3663 case kRoundToZero:
3664 frb_val = std::trunc(frb_val);
3665 break;
3666 case kRoundToPlusInf:
3667 frb_val = std::ceil(frb_val);
3668 break;
3669 case kRoundToMinusInf:
3670 frb_val = std::floor(frb_val);
3671 break;
3672 default:
3673 UNIMPLEMENTED(); // Not used by V8.
3674 }
3675 if (frb_val < static_cast<double>(kMinVal)) {
3676 frt_val = kMinVal;
3677 invalid_convert = true;
3678 } else if (frb_val >= static_cast<double>(kMaxVal)) {
3679 frt_val = kMaxVal;
3680 invalid_convert = true;
3681 } else {
3682 frt_val = (int64_t)frb_val;
3683 }
3684 }
3685 set_d_register(frt, frt_val);
3686 if (invalid_convert) SetFPSCR(VXCVI);
3687 return;
3688 }
3689 case FCTIDU:
3690 case FCTIDUZ: {
3691 int frt = instr->RTValue();
3692 int frb = instr->RBValue();
3693 double frb_val = get_double_from_d_register(frb);
3694 int mode = (opcode == FCTIDUZ)
3695 ? kRoundToZero
3696 : (fp_condition_reg_ & kFPRoundingModeMask);
3697 uint64_t frt_val;
3698 uint64_t kMinVal = 0;
3699 uint64_t kMaxVal = kMinVal - 1;
3700 bool invalid_convert = false;
3701
3702 if (std::isnan(frb_val)) {
3703 frt_val = kMinVal;
3704 invalid_convert = true;
3705 } else {
3706 switch (mode) {
3707 case kRoundToZero:
3708 frb_val = std::trunc(frb_val);
3709 break;
3710 case kRoundToPlusInf:
3711 frb_val = std::ceil(frb_val);
3712 break;
3713 case kRoundToMinusInf:
3714 frb_val = std::floor(frb_val);
3715 break;
3716 default:
3717 UNIMPLEMENTED(); // Not used by V8.
3718 }
3719 if (frb_val < static_cast<double>(kMinVal)) {
3720 frt_val = kMinVal;
3721 invalid_convert = true;
3722 } else if (frb_val >= static_cast<double>(kMaxVal)) {
3723 frt_val = kMaxVal;
3724 invalid_convert = true;
3725 } else {
3726 frt_val = (uint64_t)frb_val;
3727 }
3728 }
3729 set_d_register(frt, frt_val);
3730 if (invalid_convert) SetFPSCR(VXCVI);
3731 return;
3732 }
3733 case FCTIW:
3734 case FCTIWZ: {
3735 int frt = instr->RTValue();
3736 int frb = instr->RBValue();
3737 double frb_val = get_double_from_d_register(frb);
3738 int mode = (opcode == FCTIWZ) ? kRoundToZero
3739 : (fp_condition_reg_ & kFPRoundingModeMask);
3740 int64_t frt_val;
3741 int64_t kMinVal = kMinInt;
3742 int64_t kMaxVal = kMaxInt;
3743 bool invalid_convert = false;
3744
3745 if (std::isnan(frb_val)) {
3746 frt_val = kMinVal;
3747 } else {
3748 switch (mode) {
3749 case kRoundToZero:
3750 frb_val = std::trunc(frb_val);
3751 break;
3752 case kRoundToPlusInf:
3753 frb_val = std::ceil(frb_val);
3754 break;
3755 case kRoundToMinusInf:
3756 frb_val = std::floor(frb_val);
3757 break;
3758 case kRoundToNearest: {
3759 double orig = frb_val;
3760 frb_val = lround(frb_val);
3761 // Round to even if exactly halfway. (lround rounds up)
3762 if (std::fabs(frb_val - orig) == 0.5 && ((int64_t)frb_val % 2)) {
3763 frb_val += ((frb_val > 0) ? -1.0 : 1.0);
3764 }
3765 break;
3766 }
3767 default:
3768 UNIMPLEMENTED(); // Not used by V8.
3769 }
3770 if (frb_val < kMinVal) {
3771 frt_val = kMinVal;
3772 invalid_convert = true;
3773 } else if (frb_val > kMaxVal) {
3774 frt_val = kMaxVal;
3775 invalid_convert = true;
3776 } else {
3777 frt_val = (int64_t)frb_val;
3778 }
3779 }
3780 set_d_register(frt, frt_val);
3781 if (invalid_convert) SetFPSCR(VXCVI);
3782 return;
3783 }
3784 case FCTIWU:
3785 case FCTIWUZ: {
3786 int frt = instr->RTValue();
3787 int frb = instr->RBValue();
3788 double frb_val = get_double_from_d_register(frb);
3789 int mode = (opcode == FCTIWUZ)
3790 ? kRoundToZero
3791 : (fp_condition_reg_ & kFPRoundingModeMask);
3792 uint64_t frt_val;
3793 uint64_t kMinVal = kMinUInt32;
3794 uint64_t kMaxVal = kMaxUInt32;
3795 bool invalid_convert = false;
3796
3797 if (std::isnan(frb_val)) {
3798 frt_val = kMinVal;
3799 } else {
3800 switch (mode) {
3801 case kRoundToZero:
3802 frb_val = std::trunc(frb_val);
3803 break;
3804 case kRoundToPlusInf:
3805 frb_val = std::ceil(frb_val);
3806 break;
3807 case kRoundToMinusInf:
3808 frb_val = std::floor(frb_val);
3809 break;
3810 default:
3811 UNIMPLEMENTED(); // Not used by V8.
3812 }
3813 if (frb_val < kMinVal) {
3814 frt_val = kMinVal;
3815 invalid_convert = true;
3816 } else if (frb_val > kMaxVal) {
3817 frt_val = kMaxVal;
3818 invalid_convert = true;
3819 } else {
3820 frt_val = (uint64_t)frb_val;
3821 }
3822 }
3823 set_d_register(frt, frt_val);
3824 if (invalid_convert) SetFPSCR(VXCVI);
3825 return;
3826 }
3827 case FNEG: {
3828 int frt = instr->RTValue();
3829 int frb = instr->RBValue();
3830 double frb_val = get_double_from_d_register(frb);
3831 double frt_val = -frb_val;
3832 set_d_register_from_double(frt, frt_val);
3833 return;
3834 }
3835 case FCPSGN: {
3836 int frt = instr->RTValue();
3837 int frb = instr->RBValue();
3838 int fra = instr->RAValue();
3839 double frb_val = get_double_from_d_register(frb);
3840 double fra_val = get_double_from_d_register(fra);
3841 double frt_val = std::copysign(frb_val, fra_val);
3842 set_d_register_from_double(frt, frt_val);
3843 return;
3844 }
3845 case FMR: {
3846 int frt = instr->RTValue();
3847 int frb = instr->RBValue();
3848 int64_t frb_val = get_d_register(frb);
3849 set_d_register(frt, frb_val);
3850 return;
3851 }
3852 case MTFSFI: {
3853 int bf = instr->Bits(25, 23);
3854 int imm = instr->Bits(15, 12);
3855 int fp_condition_mask = 0xF0000000 >> (bf * 4);
3856 fp_condition_reg_ &= ~fp_condition_mask;
3857 fp_condition_reg_ |= (imm << (28 - (bf * 4)));
3858 if (instr->Bit(0)) { // RC bit set
3859 condition_reg_ &= 0xF0FFFFFF;
3860 condition_reg_ |= (imm << 23);
3861 }
3862 return;
3863 }
3864 case MTFSF: {
3865 int frb = instr->RBValue();
3866 int64_t frb_dval = get_d_register(frb);
3867 int32_t frb_ival = static_cast<int32_t>((frb_dval)&0xFFFFFFFF);
3868 int l = instr->Bits(25, 25);
3869 if (l == 1) {
3870 fp_condition_reg_ = frb_ival;
3871 } else {
3872 UNIMPLEMENTED();
3873 }
3874 if (instr->Bit(0)) { // RC bit set
3875 UNIMPLEMENTED();
3876 // int w = instr->Bits(16, 16);
3877 // int flm = instr->Bits(24, 17);
3878 }
3879 return;
3880 }
3881 case MFFS: {
3882 int frt = instr->RTValue();
3883 int64_t lval = static_cast<int64_t>(fp_condition_reg_);
3884 set_d_register(frt, lval);
3885 return;
3886 }
3887 case MCRFS: {
3888 int bf = instr->Bits(25, 23);
3889 int bfa = instr->Bits(20, 18);
3890 int cr_shift = (7 - bf) * CRWIDTH;
3891 int fp_shift = (7 - bfa) * CRWIDTH;
3892 int field_val = (fp_condition_reg_ >> fp_shift) & 0xF;
3893 condition_reg_ &= ~(0x0F << cr_shift);
3894 condition_reg_ |= (field_val << cr_shift);
3895 // Clear copied exception bits
3896 switch (bfa) {
3897 case 5:
3898 ClearFPSCR(VXSOFT);
3899 ClearFPSCR(VXSQRT);
3900 ClearFPSCR(VXCVI);
3901 break;
3902 default:
3903 UNIMPLEMENTED();
3904 }
3905 return;
3906 }
3907 case MTFSB0: {
3908 int bt = instr->Bits(25, 21);
3909 ClearFPSCR(bt);
3910 if (instr->Bit(0)) { // RC bit set
3911 UNIMPLEMENTED();
3912 }
3913 return;
3914 }
3915 case MTFSB1: {
3916 int bt = instr->Bits(25, 21);
3917 SetFPSCR(bt);
3918 if (instr->Bit(0)) { // RC bit set
3919 UNIMPLEMENTED();
3920 }
3921 return;
3922 }
3923 case FABS: {
3924 int frt = instr->RTValue();
3925 int frb = instr->RBValue();
3926 double frb_val = get_double_from_d_register(frb);
3927 double frt_val = std::fabs(frb_val);
3928 set_d_register_from_double(frt, frt_val);
3929 return;
3930 }
3931
3932 #if V8_TARGET_ARCH_PPC64
3933 case RLDICL: {
3934 int ra = instr->RAValue();
3935 int rs = instr->RSValue();
3936 uintptr_t rs_val = get_register(rs);
3937 int sh = (instr->Bits(15, 11) | (instr->Bit(1) << 5));
3938 int mb = (instr->Bits(10, 6) | (instr->Bit(5) << 5));
3939 DCHECK(sh >= 0 && sh <= 63);
3940 DCHECK(mb >= 0 && mb <= 63);
3941 uintptr_t result = base::bits::RotateLeft64(rs_val, sh);
3942 uintptr_t mask = 0xFFFFFFFFFFFFFFFF >> mb;
3943 result &= mask;
3944 set_register(ra, result);
3945 if (instr->Bit(0)) { // RC bit set
3946 SetCR0(result);
3947 }
3948 return;
3949 }
3950 case RLDICR: {
3951 int ra = instr->RAValue();
3952 int rs = instr->RSValue();
3953 uintptr_t rs_val = get_register(rs);
3954 int sh = (instr->Bits(15, 11) | (instr->Bit(1) << 5));
3955 int me = (instr->Bits(10, 6) | (instr->Bit(5) << 5));
3956 DCHECK(sh >= 0 && sh <= 63);
3957 DCHECK(me >= 0 && me <= 63);
3958 uintptr_t result = base::bits::RotateLeft64(rs_val, sh);
3959 uintptr_t mask = 0xFFFFFFFFFFFFFFFF << (63 - me);
3960 result &= mask;
3961 set_register(ra, result);
3962 if (instr->Bit(0)) { // RC bit set
3963 SetCR0(result);
3964 }
3965 return;
3966 }
3967 case RLDIC: {
3968 int ra = instr->RAValue();
3969 int rs = instr->RSValue();
3970 uintptr_t rs_val = get_register(rs);
3971 int sh = (instr->Bits(15, 11) | (instr->Bit(1) << 5));
3972 int mb = (instr->Bits(10, 6) | (instr->Bit(5) << 5));
3973 DCHECK(sh >= 0 && sh <= 63);
3974 DCHECK(mb >= 0 && mb <= 63);
3975 uintptr_t result = base::bits::RotateLeft64(rs_val, sh);
3976 uintptr_t mask = (0xFFFFFFFFFFFFFFFF >> mb) & (0xFFFFFFFFFFFFFFFF << sh);
3977 result &= mask;
3978 set_register(ra, result);
3979 if (instr->Bit(0)) { // RC bit set
3980 SetCR0(result);
3981 }
3982 return;
3983 }
3984 case RLDIMI: {
3985 int ra = instr->RAValue();
3986 int rs = instr->RSValue();
3987 uintptr_t rs_val = get_register(rs);
3988 intptr_t ra_val = get_register(ra);
3989 int sh = (instr->Bits(15, 11) | (instr->Bit(1) << 5));
3990 int mb = (instr->Bits(10, 6) | (instr->Bit(5) << 5));
3991 int me = 63 - sh;
3992 uintptr_t result = base::bits::RotateLeft64(rs_val, sh);
3993 uintptr_t mask = 0;
3994 if (mb < me + 1) {
3995 uintptr_t bit = 0x8000000000000000 >> mb;
3996 for (; mb <= me; mb++) {
3997 mask |= bit;
3998 bit >>= 1;
3999 }
4000 } else if (mb == me + 1) {
4001 mask = 0xFFFFFFFFFFFFFFFF;
4002 } else { // mb > me+1
4003 uintptr_t bit = 0x8000000000000000 >> (me + 1); // needs to be tested
4004 mask = 0xFFFFFFFFFFFFFFFF;
4005 for (; me < mb; me++) {
4006 mask ^= bit;
4007 bit >>= 1;
4008 }
4009 }
4010 result &= mask;
4011 ra_val &= ~mask;
4012 result |= ra_val;
4013 set_register(ra, result);
4014 if (instr->Bit(0)) { // RC bit set
4015 SetCR0(result);
4016 }
4017 return;
4018 }
4019 case RLDCL: {
4020 int ra = instr->RAValue();
4021 int rs = instr->RSValue();
4022 int rb = instr->RBValue();
4023 uintptr_t rs_val = get_register(rs);
4024 uintptr_t rb_val = get_register(rb);
4025 int sh = (rb_val & 0x3F);
4026 int mb = (instr->Bits(10, 6) | (instr->Bit(5) << 5));
4027 DCHECK(sh >= 0 && sh <= 63);
4028 DCHECK(mb >= 0 && mb <= 63);
4029 uintptr_t result = base::bits::RotateLeft64(rs_val, sh);
4030 uintptr_t mask = 0xFFFFFFFFFFFFFFFF >> mb;
4031 result &= mask;
4032 set_register(ra, result);
4033 if (instr->Bit(0)) { // RC bit set
4034 SetCR0(result);
4035 }
4036 return;
4037 }
4038
4039 case LD:
4040 case LDU:
4041 case LWA: {
4042 int ra = instr->RAValue();
4043 int rt = instr->RTValue();
4044 int64_t ra_val = ra == 0 ? 0 : get_register(ra);
4045 int offset = SIGN_EXT_IMM16(instr->Bits(15, 0) & ~3);
4046 switch (instr->Bits(1, 0)) {
4047 case 0: { // ld
4048 intptr_t result = ReadDW(ra_val + offset);
4049 set_register(rt, result);
4050 break;
4051 }
4052 case 1: { // ldu
4053 intptr_t result = ReadDW(ra_val + offset);
4054 set_register(rt, result);
4055 DCHECK_NE(ra, 0);
4056 set_register(ra, ra_val + offset);
4057 break;
4058 }
4059 case 2: { // lwa
4060 intptr_t result = ReadW(ra_val + offset);
4061 set_register(rt, result);
4062 break;
4063 }
4064 }
4065 break;
4066 }
4067
4068 case STD:
4069 case STDU: {
4070 int ra = instr->RAValue();
4071 int rs = instr->RSValue();
4072 int64_t ra_val = ra == 0 ? 0 : get_register(ra);
4073 int64_t rs_val = get_register(rs);
4074 int offset = SIGN_EXT_IMM16(instr->Bits(15, 0) & ~3);
4075 WriteDW(ra_val + offset, rs_val);
4076 if (opcode == STDU) {
4077 DCHECK_NE(ra, 0);
4078 set_register(ra, ra_val + offset);
4079 }
4080 break;
4081 }
4082 #endif
4083
4084 case XSADDDP: {
4085 int frt = instr->RTValue();
4086 int fra = instr->RAValue();
4087 int frb = instr->RBValue();
4088 double fra_val = get_double_from_d_register(fra);
4089 double frb_val = get_double_from_d_register(frb);
4090 double frt_val = fra_val + frb_val;
4091 set_d_register_from_double(frt, frt_val);
4092 return;
4093 }
4094 case XSSUBDP: {
4095 int frt = instr->RTValue();
4096 int fra = instr->RAValue();
4097 int frb = instr->RBValue();
4098 double fra_val = get_double_from_d_register(fra);
4099 double frb_val = get_double_from_d_register(frb);
4100 double frt_val = fra_val - frb_val;
4101 set_d_register_from_double(frt, frt_val);
4102 return;
4103 }
4104 case XSMULDP: {
4105 int frt = instr->RTValue();
4106 int fra = instr->RAValue();
4107 int frb = instr->RBValue();
4108 double fra_val = get_double_from_d_register(fra);
4109 double frb_val = get_double_from_d_register(frb);
4110 double frt_val = fra_val * frb_val;
4111 set_d_register_from_double(frt, frt_val);
4112 return;
4113 }
4114 case XSDIVDP: {
4115 int frt = instr->RTValue();
4116 int fra = instr->RAValue();
4117 int frb = instr->RBValue();
4118 double fra_val = get_double_from_d_register(fra);
4119 double frb_val = get_double_from_d_register(frb);
4120 double frt_val = fra_val / frb_val;
4121 set_d_register_from_double(frt, frt_val);
4122 return;
4123 }
4124 case MTCRF: {
4125 int rs = instr->RSValue();
4126 uint32_t rs_val = static_cast<int32_t>(get_register(rs));
4127 uint8_t fxm = instr->Bits(19, 12);
4128 uint8_t bit_mask = 0x80;
4129 const int field_bit_count = 4;
4130 const int max_field_index = 7;
4131 uint32_t result = 0;
4132 for (int i = 0; i <= max_field_index; i++) {
4133 result <<= field_bit_count;
4134 uint32_t source = condition_reg_;
4135 if ((bit_mask & fxm) != 0) {
4136 // take it from rs.
4137 source = rs_val;
4138 }
4139 result |= ((source << i * field_bit_count) >> i * field_bit_count) >>
4140 (max_field_index - i) * field_bit_count;
4141 bit_mask >>= 1;
4142 }
4143 condition_reg_ = result;
4144 break;
4145 }
4146 // Vector instructions.
4147 case LVX: {
4148 DECODE_VX_INSTRUCTION(vrt, ra, rb, T)
4149 GET_ADDRESS(ra, rb, ra_val, rb_val)
4150 intptr_t addr = (ra_val + rb_val) & 0xFFFFFFFFFFFFFFF0;
4151 simdr_t* ptr = reinterpret_cast<simdr_t*>(addr);
4152 set_simd_register(vrt, *ptr);
4153 break;
4154 }
4155 case STVX: {
4156 DECODE_VX_INSTRUCTION(vrs, ra, rb, S)
4157 GET_ADDRESS(ra, rb, ra_val, rb_val)
4158 __int128 vrs_val = bit_cast<__int128>(get_simd_register(vrs).int8);
4159 WriteQW((ra_val + rb_val) & 0xFFFFFFFFFFFFFFF0, vrs_val);
4160 break;
4161 }
4162 case LXVD: {
4163 DECODE_VX_INSTRUCTION(xt, ra, rb, T)
4164 GET_ADDRESS(ra, rb, ra_val, rb_val)
4165 set_simd_register_by_lane<int64_t>(xt, 0, ReadDW(ra_val + rb_val));
4166 set_simd_register_by_lane<int64_t>(
4167 xt, 1, ReadDW(ra_val + rb_val + kSystemPointerSize));
4168 break;
4169 }
4170 case LXVX: {
4171 DECODE_VX_INSTRUCTION(vrt, ra, rb, T)
4172 GET_ADDRESS(ra, rb, ra_val, rb_val)
4173 intptr_t addr = ra_val + rb_val;
4174 simdr_t* ptr = reinterpret_cast<simdr_t*>(addr);
4175 set_simd_register(vrt, *ptr);
4176 break;
4177 }
4178 case STXVD: {
4179 DECODE_VX_INSTRUCTION(xs, ra, rb, S)
4180 GET_ADDRESS(ra, rb, ra_val, rb_val)
4181 WriteDW(ra_val + rb_val, get_simd_register_by_lane<int64_t>(xs, 0));
4182 WriteDW(ra_val + rb_val + kSystemPointerSize,
4183 get_simd_register_by_lane<int64_t>(xs, 1));
4184 break;
4185 }
4186 case STXVX: {
4187 DECODE_VX_INSTRUCTION(vrs, ra, rb, S)
4188 GET_ADDRESS(ra, rb, ra_val, rb_val)
4189 intptr_t addr = ra_val + rb_val;
4190 __int128 vrs_val = bit_cast<__int128>(get_simd_register(vrs).int8);
4191 WriteQW(addr, vrs_val);
4192 break;
4193 }
4194 case LXSIBZX: {
4195 DECODE_VX_INSTRUCTION(xt, ra, rb, T)
4196 GET_ADDRESS(ra, rb, ra_val, rb_val)
4197 set_simd_register_by_lane<uint64_t>(xt, 0, ReadBU(ra_val + rb_val));
4198 break;
4199 }
4200 case LXSIHZX: {
4201 DECODE_VX_INSTRUCTION(xt, ra, rb, T)
4202 GET_ADDRESS(ra, rb, ra_val, rb_val)
4203 set_simd_register_by_lane<uint64_t>(xt, 0, ReadHU(ra_val + rb_val));
4204 break;
4205 }
4206 case LXSIWZX: {
4207 DECODE_VX_INSTRUCTION(xt, ra, rb, T)
4208 GET_ADDRESS(ra, rb, ra_val, rb_val)
4209 set_simd_register_by_lane<uint64_t>(xt, 0, ReadWU(ra_val + rb_val));
4210 break;
4211 }
4212 case LXSDX: {
4213 DECODE_VX_INSTRUCTION(xt, ra, rb, T)
4214 GET_ADDRESS(ra, rb, ra_val, rb_val)
4215 set_simd_register_by_lane<int64_t>(xt, 0, ReadDW(ra_val + rb_val));
4216 break;
4217 }
4218 case STXSIBX: {
4219 DECODE_VX_INSTRUCTION(xs, ra, rb, S)
4220 GET_ADDRESS(ra, rb, ra_val, rb_val)
4221 WriteB(ra_val + rb_val, get_simd_register_by_lane<int8_t>(xs, 7));
4222 break;
4223 }
4224 case STXSIHX: {
4225 DECODE_VX_INSTRUCTION(xs, ra, rb, S)
4226 GET_ADDRESS(ra, rb, ra_val, rb_val)
4227 WriteH(ra_val + rb_val, get_simd_register_by_lane<int16_t>(xs, 3));
4228 break;
4229 }
4230 case STXSIWX: {
4231 DECODE_VX_INSTRUCTION(xs, ra, rb, S)
4232 GET_ADDRESS(ra, rb, ra_val, rb_val)
4233 WriteW(ra_val + rb_val, get_simd_register_by_lane<int32_t>(xs, 1));
4234 break;
4235 }
4236 case STXSDX: {
4237 DECODE_VX_INSTRUCTION(xs, ra, rb, S)
4238 GET_ADDRESS(ra, rb, ra_val, rb_val)
4239 WriteDW(ra_val + rb_val, get_simd_register_by_lane<int64_t>(xs, 0));
4240 break;
4241 }
4242 case XXBRQ: {
4243 int t = instr->RTValue();
4244 int b = instr->RBValue();
4245 __int128 xb_val = bit_cast<__int128>(get_simd_register(b).int8);
4246 __int128 xb_val_reversed = __builtin_bswap128(xb_val);
4247 simdr_t simdr_xb = bit_cast<simdr_t>(xb_val_reversed);
4248 set_simd_register(t, simdr_xb);
4249 break;
4250 }
4251 #define VSPLT(type) \
4252 uint8_t uim = instr->Bits(19, 16); \
4253 int vrt = instr->RTValue(); \
4254 int vrb = instr->RBValue(); \
4255 type value = get_simd_register_by_lane<type>(vrb, uim); \
4256 FOR_EACH_LANE(i, type) { set_simd_register_by_lane<type>(vrt, i, value); }
4257 case VSPLTW: {
4258 VSPLT(int32_t)
4259 break;
4260 }
4261 case VSPLTH: {
4262 VSPLT(int16_t)
4263 break;
4264 }
4265 case VSPLTB: {
4266 VSPLT(int8_t)
4267 break;
4268 }
4269 case XXSPLTIB: {
4270 int8_t imm8 = instr->Bits(18, 11);
4271 int t = instr->RTValue();
4272 FOR_EACH_LANE(i, int8_t) {
4273 set_simd_register_by_lane<int8_t>(t, i, imm8);
4274 }
4275 break;
4276 }
4277 #undef VSPLT
4278 #define VSPLTI(type) \
4279 type sim = static_cast<type>(SIGN_EXT_IMM5(instr->Bits(20, 16))); \
4280 int vrt = instr->RTValue(); \
4281 FOR_EACH_LANE(i, type) { set_simd_register_by_lane<type>(vrt, i, sim); }
4282 case VSPLTISW: {
4283 VSPLTI(int32_t)
4284 break;
4285 }
4286 case VSPLTISH: {
4287 VSPLTI(int16_t)
4288 break;
4289 }
4290 case VSPLTISB: {
4291 VSPLTI(int8_t)
4292 break;
4293 }
4294 #undef VSPLTI
4295 #define VINSERT(type, element) \
4296 uint8_t uim = instr->Bits(19, 16); \
4297 int vrt = instr->RTValue(); \
4298 int vrb = instr->RBValue(); \
4299 set_simd_register_bytes<type>( \
4300 vrt, uim, get_simd_register_by_lane<type>(vrb, element));
4301 case VINSERTD: {
4302 VINSERT(int64_t, 0)
4303 break;
4304 }
4305 case VINSERTW: {
4306 VINSERT(int32_t, 1)
4307 break;
4308 }
4309 case VINSERTH: {
4310 VINSERT(int16_t, 3)
4311 break;
4312 }
4313 case VINSERTB: {
4314 VINSERT(int8_t, 7)
4315 break;
4316 }
4317 #undef VINSERT
4318 #define VINSERT_IMMEDIATE(type) \
4319 uint8_t uim = instr->Bits(19, 16); \
4320 int vrt = instr->RTValue(); \
4321 int rb = instr->RBValue(); \
4322 type src = static_cast<type>(get_register(rb)); \
4323 set_simd_register_bytes<type>(vrt, uim, src);
4324 case VINSD: {
4325 VINSERT_IMMEDIATE(int64_t)
4326 break;
4327 }
4328 case VINSW: {
4329 VINSERT_IMMEDIATE(int32_t)
4330 break;
4331 }
4332 #undef VINSERT_IMMEDIATE
4333 #define VEXTRACT(type, element) \
4334 uint8_t uim = instr->Bits(19, 16); \
4335 int vrt = instr->RTValue(); \
4336 int vrb = instr->RBValue(); \
4337 type val = get_simd_register_bytes<type>(vrb, uim); \
4338 set_simd_register_by_lane<uint64_t>(vrt, 0, 0); \
4339 set_simd_register_by_lane<uint64_t>(vrt, 1, 0); \
4340 set_simd_register_by_lane<type>(vrt, element, val);
4341 case VEXTRACTD: {
4342 VEXTRACT(uint64_t, 0)
4343 break;
4344 }
4345 case VEXTRACTUW: {
4346 VEXTRACT(uint32_t, 1)
4347 break;
4348 }
4349 case VEXTRACTUH: {
4350 VEXTRACT(uint16_t, 3)
4351 break;
4352 }
4353 case VEXTRACTUB: {
4354 VEXTRACT(uint8_t, 7)
4355 break;
4356 }
4357 #undef VEXTRACT
4358 #define VECTOR_LOGICAL_OP(expr) \
4359 DECODE_VX_INSTRUCTION(t, a, b, T) \
4360 FOR_EACH_LANE(i, int64_t) { \
4361 int64_t a_val = get_simd_register_by_lane<int64_t>(a, i); \
4362 int64_t b_val = get_simd_register_by_lane<int64_t>(b, i); \
4363 set_simd_register_by_lane<int64_t>(t, i, expr); \
4364 }
4365 case VAND: {
4366 VECTOR_LOGICAL_OP(a_val & b_val)
4367 break;
4368 }
4369 case VANDC: {
4370 VECTOR_LOGICAL_OP(a_val & (~b_val))
4371 break;
4372 }
4373 case VOR: {
4374 VECTOR_LOGICAL_OP(a_val | b_val)
4375 break;
4376 }
4377 case VNOR: {
4378 VECTOR_LOGICAL_OP(~(a_val | b_val))
4379 break;
4380 }
4381 case VXOR: {
4382 VECTOR_LOGICAL_OP(a_val ^ b_val)
4383 break;
4384 }
4385 #undef VECTOR_LOGICAL_OP
4386 #define VECTOR_ARITHMETIC_OP(type, op) \
4387 DECODE_VX_INSTRUCTION(t, a, b, T) \
4388 FOR_EACH_LANE(i, type) { \
4389 set_simd_register_by_lane<type>( \
4390 t, i, \
4391 get_simd_register_by_lane<type>(a, i) \
4392 op get_simd_register_by_lane<type>(b, i)); \
4393 }
4394 case XVADDDP: {
4395 VECTOR_ARITHMETIC_OP(double, +)
4396 break;
4397 }
4398 case XVSUBDP: {
4399 VECTOR_ARITHMETIC_OP(double, -)
4400 break;
4401 }
4402 case XVMULDP: {
4403 VECTOR_ARITHMETIC_OP(double, *)
4404 break;
4405 }
4406 case XVDIVDP: {
4407 VECTOR_ARITHMETIC_OP(double, /)
4408 break;
4409 }
4410 case VADDFP: {
4411 VECTOR_ARITHMETIC_OP(float, +)
4412 break;
4413 }
4414 case VSUBFP: {
4415 VECTOR_ARITHMETIC_OP(float, -)
4416 break;
4417 }
4418 case XVMULSP: {
4419 VECTOR_ARITHMETIC_OP(float, *)
4420 break;
4421 }
4422 case XVDIVSP: {
4423 VECTOR_ARITHMETIC_OP(float, /)
4424 break;
4425 }
4426 case VADDUDM: {
4427 VECTOR_ARITHMETIC_OP(int64_t, +)
4428 break;
4429 }
4430 case VSUBUDM: {
4431 VECTOR_ARITHMETIC_OP(int64_t, -)
4432 break;
4433 }
4434 case VMULLD: {
4435 VECTOR_ARITHMETIC_OP(int64_t, *)
4436 break;
4437 }
4438 case VADDUWM: {
4439 VECTOR_ARITHMETIC_OP(int32_t, +)
4440 break;
4441 }
4442 case VSUBUWM: {
4443 VECTOR_ARITHMETIC_OP(int32_t, -)
4444 break;
4445 }
4446 case VMULUWM: {
4447 VECTOR_ARITHMETIC_OP(int32_t, *)
4448 break;
4449 }
4450 case VADDUHM: {
4451 VECTOR_ARITHMETIC_OP(int16_t, +)
4452 break;
4453 }
4454 case VSUBUHM: {
4455 VECTOR_ARITHMETIC_OP(int16_t, -)
4456 break;
4457 }
4458 case VADDUBM: {
4459 VECTOR_ARITHMETIC_OP(int8_t, +)
4460 break;
4461 }
4462 case VSUBUBM: {
4463 VECTOR_ARITHMETIC_OP(int8_t, -)
4464 break;
4465 }
4466 #define VECTOR_MULTIPLY_EVEN_ODD(input_type, result_type, is_odd) \
4467 DECODE_VX_INSTRUCTION(t, a, b, T) \
4468 size_t i = 0, j = 0, k = 0; \
4469 size_t lane_size = sizeof(input_type); \
4470 if (is_odd) { \
4471 i = 1; \
4472 j = lane_size; \
4473 } \
4474 for (; j < kSimd128Size; i += 2, j += lane_size * 2, k++) { \
4475 result_type src0 = \
4476 static_cast<result_type>(get_simd_register_by_lane<input_type>(a, i)); \
4477 result_type src1 = \
4478 static_cast<result_type>(get_simd_register_by_lane<input_type>(b, i)); \
4479 set_simd_register_by_lane<result_type>(t, k, src0 * src1); \
4480 }
4481 case VMULEUB: {
4482 VECTOR_MULTIPLY_EVEN_ODD(uint8_t, uint16_t, false)
4483 break;
4484 }
4485 case VMULESB: {
4486 VECTOR_MULTIPLY_EVEN_ODD(int8_t, int16_t, false)
4487 break;
4488 }
4489 case VMULOUB: {
4490 VECTOR_MULTIPLY_EVEN_ODD(uint8_t, uint16_t, true)
4491 break;
4492 }
4493 case VMULOSB: {
4494 VECTOR_MULTIPLY_EVEN_ODD(int8_t, int16_t, true)
4495 break;
4496 }
4497 case VMULEUH: {
4498 VECTOR_MULTIPLY_EVEN_ODD(uint16_t, uint32_t, false)
4499 break;
4500 }
4501 case VMULESH: {
4502 VECTOR_MULTIPLY_EVEN_ODD(int16_t, int32_t, false)
4503 break;
4504 }
4505 case VMULOUH: {
4506 VECTOR_MULTIPLY_EVEN_ODD(uint16_t, uint32_t, true)
4507 break;
4508 }
4509 case VMULOSH: {
4510 VECTOR_MULTIPLY_EVEN_ODD(int16_t, int32_t, true)
4511 break;
4512 }
4513 case VMULEUW: {
4514 VECTOR_MULTIPLY_EVEN_ODD(uint32_t, uint64_t, false)
4515 break;
4516 }
4517 case VMULESW: {
4518 VECTOR_MULTIPLY_EVEN_ODD(int32_t, int64_t, false)
4519 break;
4520 }
4521 case VMULOUW: {
4522 VECTOR_MULTIPLY_EVEN_ODD(uint32_t, uint64_t, true)
4523 break;
4524 }
4525 case VMULOSW: {
4526 VECTOR_MULTIPLY_EVEN_ODD(int32_t, int64_t, true)
4527 break;
4528 }
4529 #undef VECTOR_MULTIPLY_EVEN_ODD
4530 #define VECTOR_MERGE(type, is_low_side) \
4531 DECODE_VX_INSTRUCTION(t, a, b, T) \
4532 constexpr size_t index_limit = (kSimd128Size / sizeof(type)) / 2; \
4533 for (size_t i = 0, source_index = is_low_side ? i + index_limit : i; \
4534 i < index_limit; i++, source_index++) { \
4535 set_simd_register_by_lane<type>( \
4536 t, 2 * i, get_simd_register_by_lane<type>(a, source_index)); \
4537 set_simd_register_by_lane<type>( \
4538 t, (2 * i) + 1, get_simd_register_by_lane<type>(b, source_index)); \
4539 }
4540 case VMRGLW: {
4541 VECTOR_MERGE(int32_t, true)
4542 break;
4543 }
4544 case VMRGHW: {
4545 VECTOR_MERGE(int32_t, false)
4546 break;
4547 }
4548 case VMRGLH: {
4549 VECTOR_MERGE(int16_t, true)
4550 break;
4551 }
4552 case VMRGHH: {
4553 VECTOR_MERGE(int16_t, false)
4554 break;
4555 }
4556 #undef VECTOR_MERGE
4557 #undef VECTOR_ARITHMETIC_OP
4558 #define VECTOR_MIN_MAX_OP(type, op) \
4559 DECODE_VX_INSTRUCTION(t, a, b, T) \
4560 FOR_EACH_LANE(i, type) { \
4561 type a_val = get_simd_register_by_lane<type>(a, i); \
4562 type b_val = get_simd_register_by_lane<type>(b, i); \
4563 set_simd_register_by_lane<type>(t, i, a_val op b_val ? a_val : b_val); \
4564 }
4565 case XSMINDP: {
4566 DECODE_VX_INSTRUCTION(t, a, b, T)
4567 double a_val = get_double_from_d_register(a);
4568 double b_val = get_double_from_d_register(b);
4569 set_d_register_from_double(t, VSXFPMin<double>(a_val, b_val));
4570 break;
4571 }
4572 case XSMAXDP: {
4573 DECODE_VX_INSTRUCTION(t, a, b, T)
4574 double a_val = get_double_from_d_register(a);
4575 double b_val = get_double_from_d_register(b);
4576 set_d_register_from_double(t, VSXFPMax<double>(a_val, b_val));
4577 break;
4578 }
4579 case XVMINDP: {
4580 DECODE_VX_INSTRUCTION(t, a, b, T)
4581 FOR_EACH_LANE(i, double) {
4582 double a_val = get_simd_register_by_lane<double>(a, i);
4583 double b_val = get_simd_register_by_lane<double>(b, i);
4584 set_simd_register_by_lane<double>(t, i, VSXFPMin<double>(a_val, b_val));
4585 }
4586 break;
4587 }
4588 case XVMAXDP: {
4589 DECODE_VX_INSTRUCTION(t, a, b, T)
4590 FOR_EACH_LANE(i, double) {
4591 double a_val = get_simd_register_by_lane<double>(a, i);
4592 double b_val = get_simd_register_by_lane<double>(b, i);
4593 set_simd_register_by_lane<double>(t, i, VSXFPMax<double>(a_val, b_val));
4594 }
4595 break;
4596 }
4597 case VMINFP: {
4598 DECODE_VX_INSTRUCTION(t, a, b, T)
4599 FOR_EACH_LANE(i, float) {
4600 float a_val = get_simd_register_by_lane<float>(a, i);
4601 float b_val = get_simd_register_by_lane<float>(b, i);
4602 set_simd_register_by_lane<float>(t, i, VMXFPMin(a_val, b_val));
4603 }
4604 break;
4605 }
4606 case VMAXFP: {
4607 DECODE_VX_INSTRUCTION(t, a, b, T)
4608 FOR_EACH_LANE(i, float) {
4609 float a_val = get_simd_register_by_lane<float>(a, i);
4610 float b_val = get_simd_register_by_lane<float>(b, i);
4611 set_simd_register_by_lane<float>(t, i, VMXFPMax(a_val, b_val));
4612 }
4613 break;
4614 }
4615 case VMINSD: {
4616 VECTOR_MIN_MAX_OP(int64_t, <)
4617 break;
4618 }
4619 case VMINUD: {
4620 VECTOR_MIN_MAX_OP(uint64_t, <)
4621 break;
4622 }
4623 case VMINSW: {
4624 VECTOR_MIN_MAX_OP(int32_t, <)
4625 break;
4626 }
4627 case VMINUW: {
4628 VECTOR_MIN_MAX_OP(uint32_t, <)
4629 break;
4630 }
4631 case VMINSH: {
4632 VECTOR_MIN_MAX_OP(int16_t, <)
4633 break;
4634 }
4635 case VMINUH: {
4636 VECTOR_MIN_MAX_OP(uint16_t, <)
4637 break;
4638 }
4639 case VMINSB: {
4640 VECTOR_MIN_MAX_OP(int8_t, <)
4641 break;
4642 }
4643 case VMINUB: {
4644 VECTOR_MIN_MAX_OP(uint8_t, <)
4645 break;
4646 }
4647 case VMAXSD: {
4648 VECTOR_MIN_MAX_OP(int64_t, >)
4649 break;
4650 }
4651 case VMAXUD: {
4652 VECTOR_MIN_MAX_OP(uint64_t, >)
4653 break;
4654 }
4655 case VMAXSW: {
4656 VECTOR_MIN_MAX_OP(int32_t, >)
4657 break;
4658 }
4659 case VMAXUW: {
4660 VECTOR_MIN_MAX_OP(uint32_t, >)
4661 break;
4662 }
4663 case VMAXSH: {
4664 VECTOR_MIN_MAX_OP(int16_t, >)
4665 break;
4666 }
4667 case VMAXUH: {
4668 VECTOR_MIN_MAX_OP(uint16_t, >)
4669 break;
4670 }
4671 case VMAXSB: {
4672 VECTOR_MIN_MAX_OP(int8_t, >)
4673 break;
4674 }
4675 case VMAXUB: {
4676 VECTOR_MIN_MAX_OP(uint8_t, >)
4677 break;
4678 }
4679 #undef VECTOR_MIN_MAX_OP
4680 #define VECTOR_SHIFT_OP(type, op, mask) \
4681 DECODE_VX_INSTRUCTION(t, a, b, T) \
4682 FOR_EACH_LANE(i, type) { \
4683 set_simd_register_by_lane<type>( \
4684 t, i, \
4685 get_simd_register_by_lane<type>(a, i) \
4686 op(get_simd_register_by_lane<type>(b, i) & mask)); \
4687 }
4688 case VSLD: {
4689 VECTOR_SHIFT_OP(int64_t, <<, 0x3f)
4690 break;
4691 }
4692 case VSRAD: {
4693 VECTOR_SHIFT_OP(int64_t, >>, 0x3f)
4694 break;
4695 }
4696 case VSRD: {
4697 VECTOR_SHIFT_OP(uint64_t, >>, 0x3f)
4698 break;
4699 }
4700 case VSLW: {
4701 VECTOR_SHIFT_OP(int32_t, <<, 0x1f)
4702 break;
4703 }
4704 case VSRAW: {
4705 VECTOR_SHIFT_OP(int32_t, >>, 0x1f)
4706 break;
4707 }
4708 case VSRW: {
4709 VECTOR_SHIFT_OP(uint32_t, >>, 0x1f)
4710 break;
4711 }
4712 case VSLH: {
4713 VECTOR_SHIFT_OP(int16_t, <<, 0xf)
4714 break;
4715 }
4716 case VSRAH: {
4717 VECTOR_SHIFT_OP(int16_t, >>, 0xf)
4718 break;
4719 }
4720 case VSRH: {
4721 VECTOR_SHIFT_OP(uint16_t, >>, 0xf)
4722 break;
4723 }
4724 case VSLB: {
4725 VECTOR_SHIFT_OP(int8_t, <<, 0x7)
4726 break;
4727 }
4728 case VSRAB: {
4729 VECTOR_SHIFT_OP(int8_t, >>, 0x7)
4730 break;
4731 }
4732 case VSRB: {
4733 VECTOR_SHIFT_OP(uint8_t, >>, 0x7)
4734 break;
4735 }
4736 #undef VECTOR_SHIFT_OP
4737 #define VECTOR_COMPARE_OP(type_in, type_out, is_fp, op) \
4738 VectorCompareOp<type_in, type_out>( \
4739 this, instr, is_fp, [](type_in a, type_in b) { return a op b; });
4740 case XVCMPEQDP: {
4741 VECTOR_COMPARE_OP(double, int64_t, true, ==)
4742 break;
4743 }
4744 case XVCMPGEDP: {
4745 VECTOR_COMPARE_OP(double, int64_t, true, >=)
4746 break;
4747 }
4748 case XVCMPGTDP: {
4749 VECTOR_COMPARE_OP(double, int64_t, true, >)
4750 break;
4751 }
4752 case XVCMPEQSP: {
4753 VECTOR_COMPARE_OP(float, int32_t, true, ==)
4754 break;
4755 }
4756 case XVCMPGESP: {
4757 VECTOR_COMPARE_OP(float, int32_t, true, >=)
4758 break;
4759 }
4760 case XVCMPGTSP: {
4761 VECTOR_COMPARE_OP(float, int32_t, true, >)
4762 break;
4763 }
4764 case VCMPEQUD: {
4765 VECTOR_COMPARE_OP(uint64_t, int64_t, false, ==)
4766 break;
4767 }
4768 case VCMPGTSD: {
4769 VECTOR_COMPARE_OP(int64_t, int64_t, false, >)
4770 break;
4771 }
4772 case VCMPGTUD: {
4773 VECTOR_COMPARE_OP(uint64_t, int64_t, false, >)
4774 break;
4775 }
4776 case VCMPEQUW: {
4777 VECTOR_COMPARE_OP(uint32_t, int32_t, false, ==)
4778 break;
4779 }
4780 case VCMPGTSW: {
4781 VECTOR_COMPARE_OP(int32_t, int32_t, false, >)
4782 break;
4783 }
4784 case VCMPGTUW: {
4785 VECTOR_COMPARE_OP(uint32_t, int32_t, false, >)
4786 break;
4787 }
4788 case VCMPEQUH: {
4789 VECTOR_COMPARE_OP(uint16_t, int16_t, false, ==)
4790 break;
4791 }
4792 case VCMPGTSH: {
4793 VECTOR_COMPARE_OP(int16_t, int16_t, false, >)
4794 break;
4795 }
4796 case VCMPGTUH: {
4797 VECTOR_COMPARE_OP(uint16_t, int16_t, false, >)
4798 break;
4799 }
4800 case VCMPEQUB: {
4801 VECTOR_COMPARE_OP(uint8_t, int8_t, false, ==)
4802 break;
4803 }
4804 case VCMPGTSB: {
4805 VECTOR_COMPARE_OP(int8_t, int8_t, false, >)
4806 break;
4807 }
4808 case VCMPGTUB: {
4809 VECTOR_COMPARE_OP(uint8_t, int8_t, false, >)
4810 break;
4811 }
4812 #undef VECTOR_COMPARE_OP
4813 case XVCVSPSXWS: {
4814 VectorConverFromFPSaturate<float, int32_t>(this, instr, kMinInt, kMaxInt);
4815 break;
4816 }
4817 case XVCVSPUXWS: {
4818 VectorConverFromFPSaturate<float, uint32_t>(this, instr, 0, kMaxUInt32);
4819 break;
4820 }
4821 case XVCVDPSXWS: {
4822 VectorConverFromFPSaturate<double, int32_t>(this, instr, kMinInt, kMaxInt,
4823 true);
4824 break;
4825 }
4826 case XVCVDPUXWS: {
4827 VectorConverFromFPSaturate<double, uint32_t>(this, instr, 0, kMaxUInt32,
4828 true);
4829 break;
4830 }
4831 case XVCVSXWSP: {
4832 int t = instr->RTValue();
4833 int b = instr->RBValue();
4834 FOR_EACH_LANE(i, int32_t) {
4835 int32_t b_val = get_simd_register_by_lane<int32_t>(b, i);
4836 set_simd_register_by_lane<float>(t, i, static_cast<float>(b_val));
4837 }
4838 break;
4839 }
4840 case XVCVUXWSP: {
4841 int t = instr->RTValue();
4842 int b = instr->RBValue();
4843 FOR_EACH_LANE(i, uint32_t) {
4844 uint32_t b_val = get_simd_register_by_lane<uint32_t>(b, i);
4845 set_simd_register_by_lane<float>(t, i, static_cast<float>(b_val));
4846 }
4847 break;
4848 }
4849 case XVCVSXDDP: {
4850 int t = instr->RTValue();
4851 int b = instr->RBValue();
4852 FOR_EACH_LANE(i, int64_t) {
4853 int64_t b_val = get_simd_register_by_lane<int64_t>(b, i);
4854 set_simd_register_by_lane<double>(t, i, static_cast<double>(b_val));
4855 }
4856 break;
4857 }
4858 case XVCVUXDDP: {
4859 int t = instr->RTValue();
4860 int b = instr->RBValue();
4861 FOR_EACH_LANE(i, uint64_t) {
4862 uint64_t b_val = get_simd_register_by_lane<uint64_t>(b, i);
4863 set_simd_register_by_lane<double>(t, i, static_cast<double>(b_val));
4864 }
4865 break;
4866 }
4867 case XVCVSPDP: {
4868 int t = instr->RTValue();
4869 int b = instr->RBValue();
4870 FOR_EACH_LANE(i, double) {
4871 float b_val = get_simd_register_by_lane<float>(b, 2 * i);
4872 set_simd_register_by_lane<double>(t, i, static_cast<double>(b_val));
4873 }
4874 break;
4875 }
4876 case XVCVDPSP: {
4877 int t = instr->RTValue();
4878 int b = instr->RBValue();
4879 FOR_EACH_LANE(i, double) {
4880 double b_val = get_simd_register_by_lane<double>(b, i);
4881 set_simd_register_by_lane<float>(t, 2 * i, static_cast<float>(b_val));
4882 }
4883 break;
4884 }
4885 case XSCVSPDPN: {
4886 int t = instr->RTValue();
4887 int b = instr->RBValue();
4888 uint64_t double_bits = get_d_register(b);
4889 // Value is at the high 32 bits of the register.
4890 float f =
4891 bit_cast<float, uint32_t>(static_cast<uint32_t>(double_bits >> 32));
4892 double_bits = bit_cast<uint64_t, double>(static_cast<double>(f));
4893 // Preserve snan.
4894 if (is_snan(f)) {
4895 double_bits &= 0xFFF7FFFFFFFFFFFFU; // Clear bit 51.
4896 }
4897 set_d_register(t, double_bits);
4898 break;
4899 }
4900 case XSCVDPSPN: {
4901 int t = instr->RTValue();
4902 int b = instr->RBValue();
4903 double b_val = get_double_from_d_register(b);
4904 uint64_t float_bits = static_cast<uint64_t>(
4905 bit_cast<uint32_t, float>(static_cast<float>(b_val)));
4906 // Preserve snan.
4907 if (is_snan(b_val)) {
4908 float_bits &= 0xFFBFFFFFU; // Clear bit 22.
4909 }
4910 // fp result is placed in both 32bit halfs of the dst.
4911 float_bits = (float_bits << 32) | float_bits;
4912 set_d_register(t, float_bits);
4913 break;
4914 }
4915 #define VECTOR_UNPACK(S, D, if_high_side) \
4916 int t = instr->RTValue(); \
4917 int b = instr->RBValue(); \
4918 constexpr size_t kItemCount = kSimd128Size / sizeof(D); \
4919 D temps[kItemCount] = {0}; \
4920 /* Avoid overwriting src if src and dst are the same register. */ \
4921 FOR_EACH_LANE(i, D) { \
4922 temps[i] = get_simd_register_by_lane<S>(b, i, if_high_side); \
4923 } \
4924 FOR_EACH_LANE(i, D) { \
4925 set_simd_register_by_lane<D>(t, i, temps[i], if_high_side); \
4926 }
4927 case VUPKHSB: {
4928 VECTOR_UNPACK(int8_t, int16_t, true)
4929 break;
4930 }
4931 case VUPKHSH: {
4932 VECTOR_UNPACK(int16_t, int32_t, true)
4933 break;
4934 }
4935 case VUPKHSW: {
4936 VECTOR_UNPACK(int32_t, int64_t, true)
4937 break;
4938 }
4939 case VUPKLSB: {
4940 VECTOR_UNPACK(int8_t, int16_t, false)
4941 break;
4942 }
4943 case VUPKLSH: {
4944 VECTOR_UNPACK(int16_t, int32_t, false)
4945 break;
4946 }
4947 case VUPKLSW: {
4948 VECTOR_UNPACK(int32_t, int64_t, false)
4949 break;
4950 }
4951 #undef VECTOR_UNPACK
4952 case VPKSWSS: {
4953 VectorPackSaturate<int32_t, int16_t>(this, instr, kMinInt16, kMaxInt16);
4954 break;
4955 }
4956 case VPKSWUS: {
4957 VectorPackSaturate<int32_t, uint16_t>(this, instr, 0, kMaxUInt16);
4958 break;
4959 }
4960 case VPKSHSS: {
4961 VectorPackSaturate<int16_t, int8_t>(this, instr, kMinInt8, kMaxInt8);
4962 break;
4963 }
4964 case VPKSHUS: {
4965 VectorPackSaturate<int16_t, uint8_t>(this, instr, 0, kMaxUInt8);
4966 break;
4967 }
4968 #define VECTOR_ADD_SUB_SATURATE(intermediate_type, result_type, op, min_val, \
4969 max_val) \
4970 DECODE_VX_INSTRUCTION(t, a, b, T) \
4971 FOR_EACH_LANE(i, result_type) { \
4972 intermediate_type a_val = static_cast<intermediate_type>( \
4973 get_simd_register_by_lane<result_type>(a, i)); \
4974 intermediate_type b_val = static_cast<intermediate_type>( \
4975 get_simd_register_by_lane<result_type>(b, i)); \
4976 intermediate_type t_val = a_val op b_val; \
4977 if (t_val > max_val) \
4978 t_val = max_val; \
4979 else if (t_val < min_val) \
4980 t_val = min_val; \
4981 set_simd_register_by_lane<result_type>(t, i, \
4982 static_cast<result_type>(t_val)); \
4983 }
4984 case VADDSHS: {
4985 VECTOR_ADD_SUB_SATURATE(int32_t, int16_t, +, kMinInt16, kMaxInt16)
4986 break;
4987 }
4988 case VSUBSHS: {
4989 VECTOR_ADD_SUB_SATURATE(int32_t, int16_t, -, kMinInt16, kMaxInt16)
4990 break;
4991 }
4992 case VADDUHS: {
4993 VECTOR_ADD_SUB_SATURATE(int32_t, uint16_t, +, 0, kMaxUInt16)
4994 break;
4995 }
4996 case VSUBUHS: {
4997 VECTOR_ADD_SUB_SATURATE(int32_t, uint16_t, -, 0, kMaxUInt16)
4998 break;
4999 }
5000 case VADDSBS: {
5001 VECTOR_ADD_SUB_SATURATE(int16_t, int8_t, +, kMinInt8, kMaxInt8)
5002 break;
5003 }
5004 case VSUBSBS: {
5005 VECTOR_ADD_SUB_SATURATE(int16_t, int8_t, -, kMinInt8, kMaxInt8)
5006 break;
5007 }
5008 case VADDUBS: {
5009 VECTOR_ADD_SUB_SATURATE(int16_t, uint8_t, +, 0, kMaxUInt8)
5010 break;
5011 }
5012 case VSUBUBS: {
5013 VECTOR_ADD_SUB_SATURATE(int16_t, uint8_t, -, 0, kMaxUInt8)
5014 break;
5015 }
5016 #undef VECTOR_ADD_SUB_SATURATE
5017 #define VECTOR_FP_ROUNDING(type, op) \
5018 int t = instr->RTValue(); \
5019 int b = instr->RBValue(); \
5020 FOR_EACH_LANE(i, type) { \
5021 type b_val = get_simd_register_by_lane<type>(b, i); \
5022 set_simd_register_by_lane<type>(t, i, std::op(b_val)); \
5023 }
5024 case XVRDPIP: {
5025 VECTOR_FP_ROUNDING(double, ceil)
5026 break;
5027 }
5028 case XVRDPIM: {
5029 VECTOR_FP_ROUNDING(double, floor)
5030 break;
5031 }
5032 case XVRDPIZ: {
5033 VECTOR_FP_ROUNDING(double, trunc)
5034 break;
5035 }
5036 case XVRDPI: {
5037 VECTOR_FP_ROUNDING(double, nearbyint)
5038 break;
5039 }
5040 case XVRSPIP: {
5041 VECTOR_FP_ROUNDING(float, ceilf)
5042 break;
5043 }
5044 case XVRSPIM: {
5045 VECTOR_FP_ROUNDING(float, floorf)
5046 break;
5047 }
5048 case XVRSPIZ: {
5049 VECTOR_FP_ROUNDING(float, truncf)
5050 break;
5051 }
5052 case XVRSPI: {
5053 VECTOR_FP_ROUNDING(float, nearbyintf)
5054 break;
5055 }
5056 #undef VECTOR_FP_ROUNDING
5057 case VSEL: {
5058 int vrt = instr->RTValue();
5059 int vra = instr->RAValue();
5060 int vrb = instr->RBValue();
5061 int vrc = instr->RCValue();
5062 unsigned __int128 src_1 = bit_cast<__int128>(get_simd_register(vra).int8);
5063 unsigned __int128 src_2 = bit_cast<__int128>(get_simd_register(vrb).int8);
5064 unsigned __int128 src_3 = bit_cast<__int128>(get_simd_register(vrc).int8);
5065 unsigned __int128 tmp = (src_1 & ~src_3) | (src_2 & src_3);
5066 simdr_t* result = bit_cast<simdr_t*>(&tmp);
5067 set_simd_register(vrt, *result);
5068 break;
5069 }
5070 case VPERM: {
5071 int vrt = instr->RTValue();
5072 int vra = instr->RAValue();
5073 int vrb = instr->RBValue();
5074 int vrc = instr->RCValue();
5075 int8_t temp[kSimd128Size] = {0};
5076 FOR_EACH_LANE(i, int8_t) {
5077 int8_t lane_num = get_simd_register_by_lane<int8_t>(vrc, i);
5078 // Get the five least significant bits.
5079 lane_num = (lane_num << 3) >> 3;
5080 int reg = vra;
5081 if (lane_num >= kSimd128Size) {
5082 lane_num = lane_num - kSimd128Size;
5083 reg = vrb;
5084 }
5085 temp[i] = get_simd_register_by_lane<int8_t>(reg, lane_num);
5086 }
5087 FOR_EACH_LANE(i, int8_t) {
5088 set_simd_register_by_lane<int8_t>(vrt, i, temp[i]);
5089 }
5090 break;
5091 }
5092 case VBPERMQ: {
5093 DECODE_VX_INSTRUCTION(t, a, b, T)
5094 uint16_t result_bits = 0;
5095 unsigned __int128 src_bits =
5096 bit_cast<__int128>(get_simd_register(a).int8);
5097 for (int i = 0; i < kSimd128Size; i++) {
5098 result_bits <<= 1;
5099 uint8_t selected_bit_index = get_simd_register_by_lane<uint8_t>(b, i);
5100 if (selected_bit_index < (kSimd128Size * kBitsPerByte)) {
5101 unsigned __int128 bit_value = (src_bits << selected_bit_index) >>
5102 (kSimd128Size * kBitsPerByte - 1);
5103 result_bits |= bit_value;
5104 }
5105 }
5106 set_simd_register_by_lane<uint64_t>(t, 0, 0);
5107 set_simd_register_by_lane<uint64_t>(t, 1, 0);
5108 set_simd_register_by_lane<uint16_t>(t, 3, result_bits);
5109 break;
5110 }
5111 #define VECTOR_FP_QF(type, sign) \
5112 DECODE_VX_INSTRUCTION(t, a, b, T) \
5113 FOR_EACH_LANE(i, type) { \
5114 type a_val = get_simd_register_by_lane<type>(a, i); \
5115 type b_val = get_simd_register_by_lane<type>(b, i); \
5116 type t_val = get_simd_register_by_lane<type>(t, i); \
5117 type reuslt = sign * ((sign * b_val) + (a_val * t_val)); \
5118 if (isinf(a_val)) reuslt = a_val; \
5119 if (isinf(b_val)) reuslt = b_val; \
5120 if (isinf(t_val)) reuslt = t_val; \
5121 set_simd_register_by_lane<type>(t, i, reuslt); \
5122 }
5123 case XVMADDMDP: {
5124 VECTOR_FP_QF(double, +1)
5125 break;
5126 }
5127 case XVNMSUBMDP: {
5128 VECTOR_FP_QF(double, -1)
5129 break;
5130 }
5131 case XVMADDMSP: {
5132 VECTOR_FP_QF(float, +1)
5133 break;
5134 }
5135 case XVNMSUBMSP: {
5136 VECTOR_FP_QF(float, -1)
5137 break;
5138 }
5139 #undef VECTOR_FP_QF
5140 case VMHRADDSHS: {
5141 int vrt = instr->RTValue();
5142 int vra = instr->RAValue();
5143 int vrb = instr->RBValue();
5144 int vrc = instr->RCValue();
5145 FOR_EACH_LANE(i, int16_t) {
5146 int16_t vra_val = get_simd_register_by_lane<int16_t>(vra, i);
5147 int16_t vrb_val = get_simd_register_by_lane<int16_t>(vrb, i);
5148 int16_t vrc_val = get_simd_register_by_lane<int16_t>(vrc, i);
5149 int32_t temp = vra_val * vrb_val;
5150 temp = (temp + 0x00004000) >> 15;
5151 temp += vrc_val;
5152 if (temp > kMaxInt16)
5153 temp = kMaxInt16;
5154 else if (temp < kMinInt16)
5155 temp = kMinInt16;
5156 set_simd_register_by_lane<int16_t>(vrt, i, static_cast<int16_t>(temp));
5157 }
5158 break;
5159 }
5160 case VMSUMSHM: {
5161 int vrt = instr->RTValue();
5162 int vra = instr->RAValue();
5163 int vrb = instr->RBValue();
5164 int vrc = instr->RCValue();
5165 FOR_EACH_LANE(i, int32_t) {
5166 int16_t vra_1_val = get_simd_register_by_lane<int16_t>(vra, 2 * i);
5167 int16_t vra_2_val =
5168 get_simd_register_by_lane<int16_t>(vra, (2 * i) + 1);
5169 int16_t vrb_1_val = get_simd_register_by_lane<int16_t>(vrb, 2 * i);
5170 int16_t vrb_2_val =
5171 get_simd_register_by_lane<int16_t>(vrb, (2 * i) + 1);
5172 int32_t vrc_val = get_simd_register_by_lane<int32_t>(vrc, i);
5173 int32_t temp1 = vra_1_val * vrb_1_val, temp2 = vra_2_val * vrb_2_val;
5174 temp1 = temp1 + temp2 + vrc_val;
5175 set_simd_register_by_lane<int32_t>(vrt, i, temp1);
5176 }
5177 break;
5178 }
5179 case VMLADDUHM: {
5180 int vrt = instr->RTValue();
5181 int vra = instr->RAValue();
5182 int vrb = instr->RBValue();
5183 int vrc = instr->RCValue();
5184 FOR_EACH_LANE(i, uint16_t) {
5185 uint16_t vra_val = get_simd_register_by_lane<uint16_t>(vra, i);
5186 uint16_t vrb_val = get_simd_register_by_lane<uint16_t>(vrb, i);
5187 uint16_t vrc_val = get_simd_register_by_lane<uint16_t>(vrc, i);
5188 set_simd_register_by_lane<uint16_t>(vrt, i,
5189 (vra_val * vrb_val) + vrc_val);
5190 }
5191 break;
5192 }
5193 #define VECTOR_UNARY_OP(type, op) \
5194 int t = instr->RTValue(); \
5195 int b = instr->RBValue(); \
5196 FOR_EACH_LANE(i, type) { \
5197 set_simd_register_by_lane<type>( \
5198 t, i, op(get_simd_register_by_lane<type>(b, i))); \
5199 }
5200 case XVABSDP: {
5201 VECTOR_UNARY_OP(double, std::abs)
5202 break;
5203 }
5204 case XVNEGDP: {
5205 VECTOR_UNARY_OP(double, -)
5206 break;
5207 }
5208 case XVSQRTDP: {
5209 VECTOR_UNARY_OP(double, std::sqrt)
5210 break;
5211 }
5212 case XVABSSP: {
5213 VECTOR_UNARY_OP(float, std::abs)
5214 break;
5215 }
5216 case XVNEGSP: {
5217 VECTOR_UNARY_OP(float, -)
5218 break;
5219 }
5220 case XVSQRTSP: {
5221 VECTOR_UNARY_OP(float, std::sqrt)
5222 break;
5223 }
5224 case XVRESP: {
5225 VECTOR_UNARY_OP(float, base::Recip)
5226 break;
5227 }
5228 case XVRSQRTESP: {
5229 VECTOR_UNARY_OP(float, base::RecipSqrt)
5230 break;
5231 }
5232 case VNEGW: {
5233 VECTOR_UNARY_OP(int32_t, -)
5234 break;
5235 }
5236 case VNEGD: {
5237 VECTOR_UNARY_OP(int64_t, -)
5238 break;
5239 }
5240 #undef VECTOR_UNARY_OP
5241 #define VECTOR_ROUNDING_AVERAGE(intermediate_type, result_type) \
5242 DECODE_VX_INSTRUCTION(t, a, b, T) \
5243 FOR_EACH_LANE(i, result_type) { \
5244 intermediate_type a_val = static_cast<intermediate_type>( \
5245 get_simd_register_by_lane<result_type>(a, i)); \
5246 intermediate_type b_val = static_cast<intermediate_type>( \
5247 get_simd_register_by_lane<result_type>(b, i)); \
5248 intermediate_type t_val = ((a_val + b_val) + 1) >> 1; \
5249 set_simd_register_by_lane<result_type>(t, i, \
5250 static_cast<result_type>(t_val)); \
5251 }
5252 case VAVGUH: {
5253 VECTOR_ROUNDING_AVERAGE(uint32_t, uint16_t)
5254 break;
5255 }
5256 case VAVGUB: {
5257 VECTOR_ROUNDING_AVERAGE(uint16_t, uint8_t)
5258 break;
5259 }
5260 #undef VECTOR_ROUNDING_AVERAGE
5261 case VPOPCNTB: {
5262 int t = instr->RTValue();
5263 int b = instr->RBValue();
5264 FOR_EACH_LANE(i, uint8_t) {
5265 set_simd_register_by_lane<uint8_t>(
5266 t, i,
5267 base::bits::CountPopulation(
5268 get_simd_register_by_lane<uint8_t>(b, i)));
5269 }
5270 break;
5271 }
5272 #define EXTRACT_MASK(type) \
5273 int rt = instr->RTValue(); \
5274 int vrb = instr->RBValue(); \
5275 uint64_t result = 0; \
5276 FOR_EACH_LANE(i, type) { \
5277 if (i > 0) result <<= 1; \
5278 result |= std::signbit(get_simd_register_by_lane<type>(vrb, i)); \
5279 } \
5280 set_register(rt, result);
5281 case VEXTRACTDM: {
5282 EXTRACT_MASK(int64_t)
5283 break;
5284 }
5285 case VEXTRACTWM: {
5286 EXTRACT_MASK(int32_t)
5287 break;
5288 }
5289 case VEXTRACTHM: {
5290 EXTRACT_MASK(int16_t)
5291 break;
5292 }
5293 case VEXTRACTBM: {
5294 EXTRACT_MASK(int8_t)
5295 break;
5296 }
5297 #undef EXTRACT_MASK
5298 #undef FOR_EACH_LANE
5299 #undef DECODE_VX_INSTRUCTION
5300 #undef GET_ADDRESS
5301 default: {
5302 UNIMPLEMENTED();
5303 }
5304 }
5305 }
5306
Trace(Instruction * instr)5307 void Simulator::Trace(Instruction* instr) {
5308 disasm::NameConverter converter;
5309 disasm::Disassembler dasm(converter);
5310 // use a reasonably large buffer
5311 v8::base::EmbeddedVector<char, 256> buffer;
5312 dasm.InstructionDecode(buffer, reinterpret_cast<byte*>(instr));
5313 PrintF("%05d %08" V8PRIxPTR " %s\n", icount_,
5314 reinterpret_cast<intptr_t>(instr), buffer.begin());
5315 }
5316
5317 // Executes the current instruction.
ExecuteInstruction(Instruction * instr)5318 void Simulator::ExecuteInstruction(Instruction* instr) {
5319 if (v8::internal::FLAG_check_icache) {
5320 CheckICache(i_cache(), instr);
5321 }
5322 pc_modified_ = false;
5323 if (::v8::internal::FLAG_trace_sim) {
5324 Trace(instr);
5325 }
5326 uint32_t opcode = instr->OpcodeField();
5327 if (opcode == TWI) {
5328 SoftwareInterrupt(instr);
5329 } else {
5330 ExecuteGeneric(instr);
5331 }
5332 if (!pc_modified_) {
5333 set_pc(reinterpret_cast<intptr_t>(instr) + kInstrSize);
5334 }
5335 }
5336
Execute()5337 void Simulator::Execute() {
5338 // Get the PC to simulate. Cannot use the accessor here as we need the
5339 // raw PC value and not the one used as input to arithmetic instructions.
5340 intptr_t program_counter = get_pc();
5341
5342 if (::v8::internal::FLAG_stop_sim_at == 0) {
5343 // Fast version of the dispatch loop without checking whether the simulator
5344 // should be stopping at a particular executed instruction.
5345 while (program_counter != end_sim_pc) {
5346 Instruction* instr = reinterpret_cast<Instruction*>(program_counter);
5347 icount_++;
5348 ExecuteInstruction(instr);
5349 program_counter = get_pc();
5350 }
5351 } else {
5352 // FLAG_stop_sim_at is at the non-default value. Stop in the debugger when
5353 // we reach the particular instruction count.
5354 while (program_counter != end_sim_pc) {
5355 Instruction* instr = reinterpret_cast<Instruction*>(program_counter);
5356 icount_++;
5357 if (icount_ == ::v8::internal::FLAG_stop_sim_at) {
5358 PPCDebugger dbg(this);
5359 dbg.Debug();
5360 } else {
5361 ExecuteInstruction(instr);
5362 }
5363 program_counter = get_pc();
5364 }
5365 }
5366 }
5367
CallInternal(Address entry)5368 void Simulator::CallInternal(Address entry) {
5369 // Adjust JS-based stack limit to C-based stack limit.
5370 isolate_->stack_guard()->AdjustStackLimitForSimulator();
5371
5372 // Prepare to execute the code at entry
5373 if (ABI_USES_FUNCTION_DESCRIPTORS) {
5374 // entry is the function descriptor
5375 set_pc(*(bit_cast<intptr_t*>(entry)));
5376 } else {
5377 // entry is the instruction address
5378 set_pc(static_cast<intptr_t>(entry));
5379 }
5380
5381 if (ABI_CALL_VIA_IP) {
5382 // Put target address in ip (for JS prologue).
5383 set_register(r12, get_pc());
5384 }
5385
5386 // Put down marker for end of simulation. The simulator will stop simulation
5387 // when the PC reaches this value. By saving the "end simulation" value into
5388 // the LR the simulation stops when returning to this call point.
5389 special_reg_lr_ = end_sim_pc;
5390
5391 // Remember the values of non-volatile registers.
5392 intptr_t r2_val = get_register(r2);
5393 intptr_t r13_val = get_register(r13);
5394 intptr_t r14_val = get_register(r14);
5395 intptr_t r15_val = get_register(r15);
5396 intptr_t r16_val = get_register(r16);
5397 intptr_t r17_val = get_register(r17);
5398 intptr_t r18_val = get_register(r18);
5399 intptr_t r19_val = get_register(r19);
5400 intptr_t r20_val = get_register(r20);
5401 intptr_t r21_val = get_register(r21);
5402 intptr_t r22_val = get_register(r22);
5403 intptr_t r23_val = get_register(r23);
5404 intptr_t r24_val = get_register(r24);
5405 intptr_t r25_val = get_register(r25);
5406 intptr_t r26_val = get_register(r26);
5407 intptr_t r27_val = get_register(r27);
5408 intptr_t r28_val = get_register(r28);
5409 intptr_t r29_val = get_register(r29);
5410 intptr_t r30_val = get_register(r30);
5411 intptr_t r31_val = get_register(fp);
5412
5413 // Set up the non-volatile registers with a known value. To be able to check
5414 // that they are preserved properly across JS execution.
5415 intptr_t callee_saved_value = icount_;
5416 set_register(r2, callee_saved_value);
5417 set_register(r13, callee_saved_value);
5418 set_register(r14, callee_saved_value);
5419 set_register(r15, callee_saved_value);
5420 set_register(r16, callee_saved_value);
5421 set_register(r17, callee_saved_value);
5422 set_register(r18, callee_saved_value);
5423 set_register(r19, callee_saved_value);
5424 set_register(r20, callee_saved_value);
5425 set_register(r21, callee_saved_value);
5426 set_register(r22, callee_saved_value);
5427 set_register(r23, callee_saved_value);
5428 set_register(r24, callee_saved_value);
5429 set_register(r25, callee_saved_value);
5430 set_register(r26, callee_saved_value);
5431 set_register(r27, callee_saved_value);
5432 set_register(r28, callee_saved_value);
5433 set_register(r29, callee_saved_value);
5434 set_register(r30, callee_saved_value);
5435 set_register(fp, callee_saved_value);
5436
5437 // Start the simulation
5438 Execute();
5439
5440 // Check that the non-volatile registers have been preserved.
5441 if (ABI_TOC_REGISTER != 2) {
5442 CHECK_EQ(callee_saved_value, get_register(r2));
5443 }
5444 if (ABI_TOC_REGISTER != 13) {
5445 CHECK_EQ(callee_saved_value, get_register(r13));
5446 }
5447 CHECK_EQ(callee_saved_value, get_register(r14));
5448 CHECK_EQ(callee_saved_value, get_register(r15));
5449 CHECK_EQ(callee_saved_value, get_register(r16));
5450 CHECK_EQ(callee_saved_value, get_register(r17));
5451 CHECK_EQ(callee_saved_value, get_register(r18));
5452 CHECK_EQ(callee_saved_value, get_register(r19));
5453 CHECK_EQ(callee_saved_value, get_register(r20));
5454 CHECK_EQ(callee_saved_value, get_register(r21));
5455 CHECK_EQ(callee_saved_value, get_register(r22));
5456 CHECK_EQ(callee_saved_value, get_register(r23));
5457 CHECK_EQ(callee_saved_value, get_register(r24));
5458 CHECK_EQ(callee_saved_value, get_register(r25));
5459 CHECK_EQ(callee_saved_value, get_register(r26));
5460 CHECK_EQ(callee_saved_value, get_register(r27));
5461 CHECK_EQ(callee_saved_value, get_register(r28));
5462 CHECK_EQ(callee_saved_value, get_register(r29));
5463 CHECK_EQ(callee_saved_value, get_register(r30));
5464 CHECK_EQ(callee_saved_value, get_register(fp));
5465
5466 // Restore non-volatile registers with the original value.
5467 set_register(r2, r2_val);
5468 set_register(r13, r13_val);
5469 set_register(r14, r14_val);
5470 set_register(r15, r15_val);
5471 set_register(r16, r16_val);
5472 set_register(r17, r17_val);
5473 set_register(r18, r18_val);
5474 set_register(r19, r19_val);
5475 set_register(r20, r20_val);
5476 set_register(r21, r21_val);
5477 set_register(r22, r22_val);
5478 set_register(r23, r23_val);
5479 set_register(r24, r24_val);
5480 set_register(r25, r25_val);
5481 set_register(r26, r26_val);
5482 set_register(r27, r27_val);
5483 set_register(r28, r28_val);
5484 set_register(r29, r29_val);
5485 set_register(r30, r30_val);
5486 set_register(fp, r31_val);
5487 }
5488
CallImpl(Address entry,int argument_count,const intptr_t * arguments)5489 intptr_t Simulator::CallImpl(Address entry, int argument_count,
5490 const intptr_t* arguments) {
5491 // Set up arguments
5492
5493 // First eight arguments passed in registers r3-r10.
5494 int reg_arg_count = std::min(8, argument_count);
5495 int stack_arg_count = argument_count - reg_arg_count;
5496 for (int i = 0; i < reg_arg_count; i++) {
5497 set_register(i + 3, arguments[i]);
5498 }
5499
5500 // Remaining arguments passed on stack.
5501 intptr_t original_stack = get_register(sp);
5502 // Compute position of stack on entry to generated code.
5503 intptr_t entry_stack =
5504 (original_stack -
5505 (kNumRequiredStackFrameSlots + stack_arg_count) * sizeof(intptr_t));
5506 if (base::OS::ActivationFrameAlignment() != 0) {
5507 entry_stack &= -base::OS::ActivationFrameAlignment();
5508 }
5509 // Store remaining arguments on stack, from low to high memory.
5510 // +2 is a hack for the LR slot + old SP on PPC
5511 intptr_t* stack_argument =
5512 reinterpret_cast<intptr_t*>(entry_stack) + kStackFrameExtraParamSlot;
5513 memcpy(stack_argument, arguments + reg_arg_count,
5514 stack_arg_count * sizeof(*arguments));
5515 set_register(sp, entry_stack);
5516
5517 CallInternal(entry);
5518
5519 // Pop stack passed arguments.
5520 CHECK_EQ(entry_stack, get_register(sp));
5521 set_register(sp, original_stack);
5522
5523 return get_register(r3);
5524 }
5525
CallFP(Address entry,double d0,double d1)5526 void Simulator::CallFP(Address entry, double d0, double d1) {
5527 set_d_register_from_double(1, d0);
5528 set_d_register_from_double(2, d1);
5529 CallInternal(entry);
5530 }
5531
CallFPReturnsInt(Address entry,double d0,double d1)5532 int32_t Simulator::CallFPReturnsInt(Address entry, double d0, double d1) {
5533 CallFP(entry, d0, d1);
5534 int32_t result = get_register(r3);
5535 return result;
5536 }
5537
CallFPReturnsDouble(Address entry,double d0,double d1)5538 double Simulator::CallFPReturnsDouble(Address entry, double d0, double d1) {
5539 CallFP(entry, d0, d1);
5540 return get_double_from_d_register(1);
5541 }
5542
PushAddress(uintptr_t address)5543 uintptr_t Simulator::PushAddress(uintptr_t address) {
5544 uintptr_t new_sp = get_register(sp) - sizeof(uintptr_t);
5545 uintptr_t* stack_slot = reinterpret_cast<uintptr_t*>(new_sp);
5546 *stack_slot = address;
5547 set_register(sp, new_sp);
5548 return new_sp;
5549 }
5550
PopAddress()5551 uintptr_t Simulator::PopAddress() {
5552 uintptr_t current_sp = get_register(sp);
5553 uintptr_t* stack_slot = reinterpret_cast<uintptr_t*>(current_sp);
5554 uintptr_t address = *stack_slot;
5555 set_register(sp, current_sp + sizeof(uintptr_t));
5556 return address;
5557 }
5558
Clear()5559 void Simulator::GlobalMonitor::Clear() {
5560 access_state_ = MonitorAccess::Open;
5561 tagged_addr_ = 0;
5562 size_ = TransactionSize::None;
5563 thread_id_ = ThreadId::Invalid();
5564 }
5565
NotifyLoadExcl(uintptr_t addr,TransactionSize size,ThreadId thread_id)5566 void Simulator::GlobalMonitor::NotifyLoadExcl(uintptr_t addr,
5567 TransactionSize size,
5568 ThreadId thread_id) {
5569 // TODO(s390): By using Global Monitors, we are effectively limiting one
5570 // active reservation across all processors. This would potentially serialize
5571 // parallel threads executing load&reserve + store conditional on unrelated
5572 // memory. Technically, this implementation would still make the simulator
5573 // adhere to the spec, but seems overly heavy-handed.
5574 access_state_ = MonitorAccess::Exclusive;
5575 tagged_addr_ = addr;
5576 size_ = size;
5577 thread_id_ = thread_id;
5578 }
5579
NotifyStore(uintptr_t addr,TransactionSize size,ThreadId thread_id)5580 void Simulator::GlobalMonitor::NotifyStore(uintptr_t addr, TransactionSize size,
5581 ThreadId thread_id) {
5582 if (access_state_ == MonitorAccess::Exclusive) {
5583 // Calculate if the transaction has been overlapped
5584 uintptr_t transaction_start = addr;
5585 uintptr_t transaction_end = addr + static_cast<uintptr_t>(size);
5586 uintptr_t exclusive_transaction_start = tagged_addr_;
5587 uintptr_t exclusive_transaction_end =
5588 tagged_addr_ + static_cast<uintptr_t>(size_);
5589 bool is_not_overlapped = transaction_end < exclusive_transaction_start ||
5590 exclusive_transaction_end < transaction_start;
5591 if (!is_not_overlapped && thread_id_ != thread_id) {
5592 Clear();
5593 }
5594 }
5595 }
5596
NotifyStoreExcl(uintptr_t addr,TransactionSize size,ThreadId thread_id)5597 bool Simulator::GlobalMonitor::NotifyStoreExcl(uintptr_t addr,
5598 TransactionSize size,
5599 ThreadId thread_id) {
5600 bool permission = access_state_ == MonitorAccess::Exclusive &&
5601 addr == tagged_addr_ && size_ == size &&
5602 thread_id_ == thread_id;
5603 // The reservation is cleared if the processor holding the reservation
5604 // executes a store conditional instruction to any address.
5605 Clear();
5606 return permission;
5607 }
5608
5609 } // namespace internal
5610 } // namespace v8
5611
5612 #undef SScanF
5613 #endif // USE_SIMULATOR
5614