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