blob: 06e52a7626e78ee742647caf57656c5500d3cf6d [file] [log] [blame]
Ben Murdochda12d292016-06-02 14:46:10 +01001// Copyright 2014 the V8 project authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include <stdarg.h>
6#include <stdlib.h>
7#include <cmath>
8
9#if V8_TARGET_ARCH_S390
10
11#include "src/assembler.h"
12#include "src/base/bits.h"
13#include "src/codegen.h"
14#include "src/disasm.h"
15#include "src/runtime/runtime-utils.h"
16#include "src/s390/constants-s390.h"
17#include "src/s390/frames-s390.h"
18#include "src/s390/simulator-s390.h"
19#if defined(USE_SIMULATOR)
20
21// Only build the simulator if not compiling for real s390 hardware.
22namespace v8 {
23namespace internal {
24
25// This macro provides a platform independent use of sscanf. The reason for
26// SScanF not being implemented in a platform independent way through
27// ::v8::internal::OS in the same way as SNPrintF is that the
28// Windows C Run-Time Library does not provide vsscanf.
29#define SScanF sscanf // NOLINT
30
31// The S390Debugger class is used by the simulator while debugging simulated
32// z/Architecture code.
33class S390Debugger {
34 public:
35 explicit S390Debugger(Simulator* sim) : sim_(sim) {}
36 ~S390Debugger();
37
38 void Stop(Instruction* instr);
39 void Debug();
40
41 private:
42#if V8_TARGET_LITTLE_ENDIAN
43 static const Instr kBreakpointInstr = (0x0000FFB2); // TRAP4 0000
44 static const Instr kNopInstr = (0x00160016); // OR r0, r0 x2
45#else
46 static const Instr kBreakpointInstr = (0xB2FF0000); // TRAP4 0000
47 static const Instr kNopInstr = (0x16001600); // OR r0, r0 x2
48#endif
49
50 Simulator* sim_;
51
52 intptr_t GetRegisterValue(int regnum);
53 double GetRegisterPairDoubleValue(int regnum);
54 double GetFPDoubleRegisterValue(int regnum);
55 float GetFPFloatRegisterValue(int regnum);
56 bool GetValue(const char* desc, intptr_t* value);
57 bool GetFPDoubleValue(const char* desc, double* value);
58
59 // Set or delete a breakpoint. Returns true if successful.
60 bool SetBreakpoint(Instruction* break_pc);
61 bool DeleteBreakpoint(Instruction* break_pc);
62
63 // Undo and redo all breakpoints. This is needed to bracket disassembly and
64 // execution to skip past breakpoints when run from the debugger.
65 void UndoBreakpoints();
66 void RedoBreakpoints();
67};
68
69S390Debugger::~S390Debugger() {}
70
71#ifdef GENERATED_CODE_COVERAGE
72static FILE* coverage_log = NULL;
73
74static void InitializeCoverage() {
75 char* file_name = getenv("V8_GENERATED_CODE_COVERAGE_LOG");
76 if (file_name != NULL) {
77 coverage_log = fopen(file_name, "aw+");
78 }
79}
80
81void S390Debugger::Stop(Instruction* instr) {
82 // Get the stop code.
83 uint32_t code = instr->SvcValue() & kStopCodeMask;
84 // Retrieve the encoded address, which comes just after this stop.
85 char** msg_address =
86 reinterpret_cast<char**>(sim_->get_pc() + sizeof(FourByteInstr));
87 char* msg = *msg_address;
88 DCHECK(msg != NULL);
89
90 // Update this stop description.
91 if (isWatchedStop(code) && !watched_stops_[code].desc) {
92 watched_stops_[code].desc = msg;
93 }
94
95 if (strlen(msg) > 0) {
96 if (coverage_log != NULL) {
97 fprintf(coverage_log, "%s\n", msg);
98 fflush(coverage_log);
99 }
100 // Overwrite the instruction and address with nops.
101 instr->SetInstructionBits(kNopInstr);
102 reinterpret_cast<Instruction*>(msg_address)->SetInstructionBits(kNopInstr);
103 }
104 sim_->set_pc(sim_->get_pc() + sizeof(FourByteInstr) + kPointerSize);
105}
106
107#else // ndef GENERATED_CODE_COVERAGE
108
109static void InitializeCoverage() {}
110
111void S390Debugger::Stop(Instruction* instr) {
112 // Get the stop code.
113 // use of kStopCodeMask not right on PowerPC
114 uint32_t code = instr->SvcValue() & kStopCodeMask;
115 // Retrieve the encoded address, which comes just after this stop.
116 char* msg = *reinterpret_cast<char**>(sim_->get_pc() + sizeof(FourByteInstr));
117 // Update this stop description.
118 if (sim_->isWatchedStop(code) && !sim_->watched_stops_[code].desc) {
119 sim_->watched_stops_[code].desc = msg;
120 }
121 // Print the stop message and code if it is not the default code.
122 if (code != kMaxStopCode) {
123 PrintF("Simulator hit stop %u: %s\n", code, msg);
124 } else {
125 PrintF("Simulator hit %s\n", msg);
126 }
127 sim_->set_pc(sim_->get_pc() + sizeof(FourByteInstr) + kPointerSize);
128 Debug();
129}
130#endif
131
132intptr_t S390Debugger::GetRegisterValue(int regnum) {
133 return sim_->get_register(regnum);
134}
135
136double S390Debugger::GetRegisterPairDoubleValue(int regnum) {
137 return sim_->get_double_from_register_pair(regnum);
138}
139
140double S390Debugger::GetFPDoubleRegisterValue(int regnum) {
141 return sim_->get_double_from_d_register(regnum);
142}
143
144float S390Debugger::GetFPFloatRegisterValue(int regnum) {
145 return sim_->get_float32_from_d_register(regnum);
146}
147
148bool S390Debugger::GetValue(const char* desc, intptr_t* value) {
149 int regnum = Registers::Number(desc);
150 if (regnum != kNoRegister) {
151 *value = GetRegisterValue(regnum);
152 return true;
153 } else {
154 if (strncmp(desc, "0x", 2) == 0) {
155 return SScanF(desc + 2, "%" V8PRIxPTR,
156 reinterpret_cast<uintptr_t*>(value)) == 1;
157 } else {
158 return SScanF(desc, "%" V8PRIuPTR, reinterpret_cast<uintptr_t*>(value)) ==
159 1;
160 }
161 }
162 return false;
163}
164
165bool S390Debugger::GetFPDoubleValue(const char* desc, double* value) {
166 int regnum = DoubleRegisters::Number(desc);
167 if (regnum != kNoRegister) {
168 *value = sim_->get_double_from_d_register(regnum);
169 return true;
170 }
171 return false;
172}
173
174bool S390Debugger::SetBreakpoint(Instruction* break_pc) {
175 // Check if a breakpoint can be set. If not return without any side-effects.
176 if (sim_->break_pc_ != NULL) {
177 return false;
178 }
179
180 // Set the breakpoint.
181 sim_->break_pc_ = break_pc;
182 sim_->break_instr_ = break_pc->InstructionBits();
183 // Not setting the breakpoint instruction in the code itself. It will be set
184 // when the debugger shell continues.
185 return true;
186}
187
188bool S390Debugger::DeleteBreakpoint(Instruction* break_pc) {
189 if (sim_->break_pc_ != NULL) {
190 sim_->break_pc_->SetInstructionBits(sim_->break_instr_);
191 }
192
193 sim_->break_pc_ = NULL;
194 sim_->break_instr_ = 0;
195 return true;
196}
197
198void S390Debugger::UndoBreakpoints() {
199 if (sim_->break_pc_ != NULL) {
200 sim_->break_pc_->SetInstructionBits(sim_->break_instr_);
201 }
202}
203
204void S390Debugger::RedoBreakpoints() {
205 if (sim_->break_pc_ != NULL) {
206 sim_->break_pc_->SetInstructionBits(kBreakpointInstr);
207 }
208}
209
210void S390Debugger::Debug() {
211 intptr_t last_pc = -1;
212 bool done = false;
213
214#define COMMAND_SIZE 63
215#define ARG_SIZE 255
216
217#define STR(a) #a
218#define XSTR(a) STR(a)
219
220 char cmd[COMMAND_SIZE + 1];
221 char arg1[ARG_SIZE + 1];
222 char arg2[ARG_SIZE + 1];
223 char* argv[3] = {cmd, arg1, arg2};
224
225 // make sure to have a proper terminating character if reaching the limit
226 cmd[COMMAND_SIZE] = 0;
227 arg1[ARG_SIZE] = 0;
228 arg2[ARG_SIZE] = 0;
229
230 // Undo all set breakpoints while running in the debugger shell. This will
231 // make them invisible to all commands.
232 UndoBreakpoints();
233 // Disable tracing while simulating
234 bool trace = ::v8::internal::FLAG_trace_sim;
235 ::v8::internal::FLAG_trace_sim = false;
236
237 while (!done && !sim_->has_bad_pc()) {
238 if (last_pc != sim_->get_pc()) {
239 disasm::NameConverter converter;
240 disasm::Disassembler dasm(converter);
241 // use a reasonably large buffer
242 v8::internal::EmbeddedVector<char, 256> buffer;
243 dasm.InstructionDecode(buffer, reinterpret_cast<byte*>(sim_->get_pc()));
244 PrintF(" 0x%08" V8PRIxPTR " %s\n", sim_->get_pc(), buffer.start());
245 last_pc = sim_->get_pc();
246 }
247 char* line = ReadLine("sim> ");
248 if (line == NULL) {
249 break;
250 } else {
251 char* last_input = sim_->last_debugger_input();
252 if (strcmp(line, "\n") == 0 && last_input != NULL) {
253 line = last_input;
254 } else {
255 // Ownership is transferred to sim_;
256 sim_->set_last_debugger_input(line);
257 }
258 // Use sscanf to parse the individual parts of the command line. At the
259 // moment no command expects more than two parameters.
260 int argc = SScanF(line,
261 "%" XSTR(COMMAND_SIZE) "s "
262 "%" XSTR(ARG_SIZE) "s "
263 "%" XSTR(ARG_SIZE) "s",
264 cmd, arg1, arg2);
265 if ((strcmp(cmd, "si") == 0) || (strcmp(cmd, "stepi") == 0)) {
266 intptr_t value;
267
268 // If at a breakpoint, proceed past it.
269 if ((reinterpret_cast<Instruction*>(sim_->get_pc()))
270 ->InstructionBits() == 0x7d821008) {
271 sim_->set_pc(sim_->get_pc() + sizeof(FourByteInstr));
272 } else {
273 sim_->ExecuteInstruction(
274 reinterpret_cast<Instruction*>(sim_->get_pc()));
275 }
276
277 if (argc == 2 && last_pc != sim_->get_pc() && GetValue(arg1, &value)) {
278 for (int i = 1; (!sim_->has_bad_pc()) && i < value; i++) {
279 disasm::NameConverter converter;
280 disasm::Disassembler dasm(converter);
281 // use a reasonably large buffer
282 v8::internal::EmbeddedVector<char, 256> buffer;
283 dasm.InstructionDecode(buffer,
284 reinterpret_cast<byte*>(sim_->get_pc()));
285 PrintF(" 0x%08" V8PRIxPTR " %s\n", sim_->get_pc(),
286 buffer.start());
287 sim_->ExecuteInstruction(
288 reinterpret_cast<Instruction*>(sim_->get_pc()));
289 }
290 }
291 } else if ((strcmp(cmd, "c") == 0) || (strcmp(cmd, "cont") == 0)) {
292 // If at a breakpoint, proceed past it.
293 if ((reinterpret_cast<Instruction*>(sim_->get_pc()))
294 ->InstructionBits() == 0x7d821008) {
295 sim_->set_pc(sim_->get_pc() + sizeof(FourByteInstr));
296 } else {
297 // Execute the one instruction we broke at with breakpoints disabled.
298 sim_->ExecuteInstruction(
299 reinterpret_cast<Instruction*>(sim_->get_pc()));
300 }
301 // Leave the debugger shell.
302 done = true;
303 } else if ((strcmp(cmd, "p") == 0) || (strcmp(cmd, "print") == 0)) {
304 if (argc == 2 || (argc == 3 && strcmp(arg2, "fp") == 0)) {
305 intptr_t value;
306 double dvalue;
307 if (strcmp(arg1, "all") == 0) {
308 for (int i = 0; i < kNumRegisters; i++) {
309 value = GetRegisterValue(i);
310 PrintF(" %3s: %08" V8PRIxPTR,
311 Register::from_code(i).ToString(), value);
312 if ((argc == 3 && strcmp(arg2, "fp") == 0) && i < 8 &&
313 (i % 2) == 0) {
314 dvalue = GetRegisterPairDoubleValue(i);
315 PrintF(" (%f)\n", dvalue);
316 } else if (i != 0 && !((i + 1) & 3)) {
317 PrintF("\n");
318 }
319 }
320 PrintF(" pc: %08" V8PRIxPTR " cr: %08x\n", sim_->special_reg_pc_,
321 sim_->condition_reg_);
322 } else if (strcmp(arg1, "alld") == 0) {
323 for (int i = 0; i < kNumRegisters; i++) {
324 value = GetRegisterValue(i);
325 PrintF(" %3s: %08" V8PRIxPTR " %11" V8PRIdPTR,
326 Register::from_code(i).ToString(), value, value);
327 if ((argc == 3 && strcmp(arg2, "fp") == 0) && i < 8 &&
328 (i % 2) == 0) {
329 dvalue = GetRegisterPairDoubleValue(i);
330 PrintF(" (%f)\n", dvalue);
331 } else if (!((i + 1) % 2)) {
332 PrintF("\n");
333 }
334 }
335 PrintF(" pc: %08" V8PRIxPTR " cr: %08x\n", sim_->special_reg_pc_,
336 sim_->condition_reg_);
337 } else if (strcmp(arg1, "allf") == 0) {
338 for (int i = 0; i < DoubleRegister::kNumRegisters; i++) {
339 float fvalue = GetFPFloatRegisterValue(i);
340 uint32_t as_words = bit_cast<uint32_t>(fvalue);
341 PrintF("%3s: %f 0x%08x\n",
342 DoubleRegister::from_code(i).ToString(), fvalue, as_words);
343 }
344 } else if (strcmp(arg1, "alld") == 0) {
345 for (int i = 0; i < DoubleRegister::kNumRegisters; i++) {
346 dvalue = GetFPDoubleRegisterValue(i);
347 uint64_t as_words = bit_cast<uint64_t>(dvalue);
348 PrintF("%3s: %f 0x%08x %08x\n",
349 DoubleRegister::from_code(i).ToString(), dvalue,
350 static_cast<uint32_t>(as_words >> 32),
351 static_cast<uint32_t>(as_words & 0xffffffff));
352 }
353 } else if (arg1[0] == 'r' &&
354 (arg1[1] >= '0' && arg1[1] <= '2' &&
355 (arg1[2] == '\0' || (arg1[2] >= '0' && arg1[2] <= '5' &&
356 arg1[3] == '\0')))) {
357 int regnum = strtoul(&arg1[1], 0, 10);
358 if (regnum != kNoRegister) {
359 value = GetRegisterValue(regnum);
360 PrintF("%s: 0x%08" V8PRIxPTR " %" V8PRIdPTR "\n", arg1, value,
361 value);
362 } else {
363 PrintF("%s unrecognized\n", arg1);
364 }
365 } else {
366 if (GetValue(arg1, &value)) {
367 PrintF("%s: 0x%08" V8PRIxPTR " %" V8PRIdPTR "\n", arg1, value,
368 value);
369 } else if (GetFPDoubleValue(arg1, &dvalue)) {
370 uint64_t as_words = bit_cast<uint64_t>(dvalue);
371 PrintF("%s: %f 0x%08x %08x\n", arg1, dvalue,
372 static_cast<uint32_t>(as_words >> 32),
373 static_cast<uint32_t>(as_words & 0xffffffff));
374 } else {
375 PrintF("%s unrecognized\n", arg1);
376 }
377 }
378 } else {
379 PrintF("print <register>\n");
380 }
381 } else if ((strcmp(cmd, "po") == 0) ||
382 (strcmp(cmd, "printobject") == 0)) {
383 if (argc == 2) {
384 intptr_t value;
385 OFStream os(stdout);
386 if (GetValue(arg1, &value)) {
387 Object* obj = reinterpret_cast<Object*>(value);
388 os << arg1 << ": \n";
389#ifdef DEBUG
390 obj->Print(os);
391 os << "\n";
392#else
393 os << Brief(obj) << "\n";
394#endif
395 } else {
396 os << arg1 << " unrecognized\n";
397 }
398 } else {
399 PrintF("printobject <value>\n");
400 }
401 } else if (strcmp(cmd, "setpc") == 0) {
402 intptr_t value;
403
404 if (!GetValue(arg1, &value)) {
405 PrintF("%s unrecognized\n", arg1);
406 continue;
407 }
408 sim_->set_pc(value);
409 } else if (strcmp(cmd, "stack") == 0 || strcmp(cmd, "mem") == 0) {
410 intptr_t* cur = NULL;
411 intptr_t* end = NULL;
412 int next_arg = 1;
413
414 if (strcmp(cmd, "stack") == 0) {
415 cur = reinterpret_cast<intptr_t*>(sim_->get_register(Simulator::sp));
416 } else { // "mem"
417 intptr_t value;
418 if (!GetValue(arg1, &value)) {
419 PrintF("%s unrecognized\n", arg1);
420 continue;
421 }
422 cur = reinterpret_cast<intptr_t*>(value);
423 next_arg++;
424 }
425
426 intptr_t words; // likely inaccurate variable name for 64bit
427 if (argc == next_arg) {
428 words = 10;
429 } else {
430 if (!GetValue(argv[next_arg], &words)) {
431 words = 10;
432 }
433 }
434 end = cur + words;
435
436 while (cur < end) {
437 PrintF(" 0x%08" V8PRIxPTR ": 0x%08" V8PRIxPTR " %10" V8PRIdPTR,
438 reinterpret_cast<intptr_t>(cur), *cur, *cur);
439 HeapObject* obj = reinterpret_cast<HeapObject*>(*cur);
440 intptr_t value = *cur;
441 Heap* current_heap = sim_->isolate_->heap();
442 if (((value & 1) == 0) ||
443 current_heap->ContainsSlow(obj->address())) {
444 PrintF("(smi %d)", PlatformSmiTagging::SmiToInt(obj));
445 } else if (current_heap->Contains(obj)) {
446 PrintF(" (");
447 obj->ShortPrint();
448 PrintF(")");
449 }
450 PrintF("\n");
451 cur++;
452 }
453 } else if (strcmp(cmd, "disasm") == 0 || strcmp(cmd, "di") == 0) {
454 disasm::NameConverter converter;
455 disasm::Disassembler dasm(converter);
456 // use a reasonably large buffer
457 v8::internal::EmbeddedVector<char, 256> buffer;
458
459 byte* prev = NULL;
460 byte* cur = NULL;
461 // Default number of instructions to disassemble.
462 int32_t numInstructions = 10;
463
464 if (argc == 1) {
465 cur = reinterpret_cast<byte*>(sim_->get_pc());
466 } else if (argc == 2) {
467 int regnum = Registers::Number(arg1);
468 if (regnum != kNoRegister || strncmp(arg1, "0x", 2) == 0) {
469 // The argument is an address or a register name.
470 intptr_t value;
471 if (GetValue(arg1, &value)) {
472 cur = reinterpret_cast<byte*>(value);
473 }
474 } else {
475 // The argument is the number of instructions.
476 intptr_t value;
477 if (GetValue(arg1, &value)) {
478 cur = reinterpret_cast<byte*>(sim_->get_pc());
479 // Disassemble <arg1> instructions.
480 numInstructions = static_cast<int32_t>(value);
481 }
482 }
483 } else {
484 intptr_t value1;
485 intptr_t value2;
486 if (GetValue(arg1, &value1) && GetValue(arg2, &value2)) {
487 cur = reinterpret_cast<byte*>(value1);
488 // Disassemble <arg2> instructions.
489 numInstructions = static_cast<int32_t>(value2);
490 }
491 }
492
493 while (numInstructions > 0) {
494 prev = cur;
495 cur += dasm.InstructionDecode(buffer, cur);
496 PrintF(" 0x%08" V8PRIxPTR " %s\n", reinterpret_cast<intptr_t>(prev),
497 buffer.start());
498 numInstructions--;
499 }
500 } else if (strcmp(cmd, "gdb") == 0) {
501 PrintF("relinquishing control to gdb\n");
502 v8::base::OS::DebugBreak();
503 PrintF("regaining control from gdb\n");
504 } else if (strcmp(cmd, "break") == 0) {
505 if (argc == 2) {
506 intptr_t value;
507 if (GetValue(arg1, &value)) {
508 if (!SetBreakpoint(reinterpret_cast<Instruction*>(value))) {
509 PrintF("setting breakpoint failed\n");
510 }
511 } else {
512 PrintF("%s unrecognized\n", arg1);
513 }
514 } else {
515 PrintF("break <address>\n");
516 }
517 } else if (strcmp(cmd, "del") == 0) {
518 if (!DeleteBreakpoint(NULL)) {
519 PrintF("deleting breakpoint failed\n");
520 }
521 } else if (strcmp(cmd, "cr") == 0) {
522 PrintF("Condition reg: %08x\n", sim_->condition_reg_);
523 } else if (strcmp(cmd, "stop") == 0) {
524 intptr_t value;
525 intptr_t stop_pc =
526 sim_->get_pc() - (sizeof(FourByteInstr) + kPointerSize);
527 Instruction* stop_instr = reinterpret_cast<Instruction*>(stop_pc);
528 Instruction* msg_address =
529 reinterpret_cast<Instruction*>(stop_pc + sizeof(FourByteInstr));
530 if ((argc == 2) && (strcmp(arg1, "unstop") == 0)) {
531 // Remove the current stop.
532 if (sim_->isStopInstruction(stop_instr)) {
533 stop_instr->SetInstructionBits(kNopInstr);
534 msg_address->SetInstructionBits(kNopInstr);
535 } else {
536 PrintF("Not at debugger stop.\n");
537 }
538 } else if (argc == 3) {
539 // Print information about all/the specified breakpoint(s).
540 if (strcmp(arg1, "info") == 0) {
541 if (strcmp(arg2, "all") == 0) {
542 PrintF("Stop information:\n");
543 for (uint32_t i = 0; i < sim_->kNumOfWatchedStops; i++) {
544 sim_->PrintStopInfo(i);
545 }
546 } else if (GetValue(arg2, &value)) {
547 sim_->PrintStopInfo(value);
548 } else {
549 PrintF("Unrecognized argument.\n");
550 }
551 } else if (strcmp(arg1, "enable") == 0) {
552 // Enable all/the specified breakpoint(s).
553 if (strcmp(arg2, "all") == 0) {
554 for (uint32_t i = 0; i < sim_->kNumOfWatchedStops; i++) {
555 sim_->EnableStop(i);
556 }
557 } else if (GetValue(arg2, &value)) {
558 sim_->EnableStop(value);
559 } else {
560 PrintF("Unrecognized argument.\n");
561 }
562 } else if (strcmp(arg1, "disable") == 0) {
563 // Disable all/the specified breakpoint(s).
564 if (strcmp(arg2, "all") == 0) {
565 for (uint32_t i = 0; i < sim_->kNumOfWatchedStops; i++) {
566 sim_->DisableStop(i);
567 }
568 } else if (GetValue(arg2, &value)) {
569 sim_->DisableStop(value);
570 } else {
571 PrintF("Unrecognized argument.\n");
572 }
573 }
574 } else {
575 PrintF("Wrong usage. Use help command for more information.\n");
576 }
577 } else if ((strcmp(cmd, "t") == 0) || strcmp(cmd, "trace") == 0) {
578 ::v8::internal::FLAG_trace_sim = !::v8::internal::FLAG_trace_sim;
579 PrintF("Trace of executed instructions is %s\n",
580 ::v8::internal::FLAG_trace_sim ? "on" : "off");
581 } else if ((strcmp(cmd, "h") == 0) || (strcmp(cmd, "help") == 0)) {
582 PrintF("cont\n");
583 PrintF(" continue execution (alias 'c')\n");
584 PrintF("stepi [num instructions]\n");
585 PrintF(" step one/num instruction(s) (alias 'si')\n");
586 PrintF("print <register>\n");
587 PrintF(" print register content (alias 'p')\n");
588 PrintF(" use register name 'all' to display all integer registers\n");
589 PrintF(
590 " use register name 'alld' to display integer registers "
591 "with decimal values\n");
592 PrintF(" use register name 'rN' to display register number 'N'\n");
593 PrintF(" add argument 'fp' to print register pair double values\n");
594 PrintF(
595 " use register name 'allf' to display floating-point "
596 "registers\n");
597 PrintF("printobject <register>\n");
598 PrintF(" print an object from a register (alias 'po')\n");
599 PrintF("cr\n");
600 PrintF(" print condition register\n");
601 PrintF("stack [<num words>]\n");
602 PrintF(" dump stack content, default dump 10 words)\n");
603 PrintF("mem <address> [<num words>]\n");
604 PrintF(" dump memory content, default dump 10 words)\n");
605 PrintF("disasm [<instructions>]\n");
606 PrintF("disasm [<address/register>]\n");
607 PrintF("disasm [[<address/register>] <instructions>]\n");
608 PrintF(" disassemble code, default is 10 instructions\n");
609 PrintF(" from pc (alias 'di')\n");
610 PrintF("gdb\n");
611 PrintF(" enter gdb\n");
612 PrintF("break <address>\n");
613 PrintF(" set a break point on the address\n");
614 PrintF("del\n");
615 PrintF(" delete the breakpoint\n");
616 PrintF("trace (alias 't')\n");
617 PrintF(" toogle the tracing of all executed statements\n");
618 PrintF("stop feature:\n");
619 PrintF(" Description:\n");
620 PrintF(" Stops are debug instructions inserted by\n");
621 PrintF(" the Assembler::stop() function.\n");
622 PrintF(" When hitting a stop, the Simulator will\n");
623 PrintF(" stop and and give control to the S390Debugger.\n");
624 PrintF(" The first %d stop codes are watched:\n",
625 Simulator::kNumOfWatchedStops);
626 PrintF(" - They can be enabled / disabled: the Simulator\n");
627 PrintF(" will / won't stop when hitting them.\n");
628 PrintF(" - The Simulator keeps track of how many times they \n");
629 PrintF(" are met. (See the info command.) Going over a\n");
630 PrintF(" disabled stop still increases its counter. \n");
631 PrintF(" Commands:\n");
632 PrintF(" stop info all/<code> : print infos about number <code>\n");
633 PrintF(" or all stop(s).\n");
634 PrintF(" stop enable/disable all/<code> : enables / disables\n");
635 PrintF(" all or number <code> stop(s)\n");
636 PrintF(" stop unstop\n");
637 PrintF(" ignore the stop instruction at the current location\n");
638 PrintF(" from now on\n");
639 } else {
640 PrintF("Unknown command: %s\n", cmd);
641 }
642 }
643 }
644
645 // Add all the breakpoints back to stop execution and enter the debugger
646 // shell when hit.
647 RedoBreakpoints();
648 // Restore tracing
649 ::v8::internal::FLAG_trace_sim = trace;
650
651#undef COMMAND_SIZE
652#undef ARG_SIZE
653
654#undef STR
655#undef XSTR
656}
657
658static bool ICacheMatch(void* one, void* two) {
659 DCHECK((reinterpret_cast<intptr_t>(one) & CachePage::kPageMask) == 0);
660 DCHECK((reinterpret_cast<intptr_t>(two) & CachePage::kPageMask) == 0);
661 return one == two;
662}
663
664static uint32_t ICacheHash(void* key) {
665 return static_cast<uint32_t>(reinterpret_cast<uintptr_t>(key)) >> 2;
666}
667
668static bool AllOnOnePage(uintptr_t start, int size) {
669 intptr_t start_page = (start & ~CachePage::kPageMask);
670 intptr_t end_page = ((start + size) & ~CachePage::kPageMask);
671 return start_page == end_page;
672}
673
674void Simulator::set_last_debugger_input(char* input) {
675 DeleteArray(last_debugger_input_);
676 last_debugger_input_ = input;
677}
678
679void Simulator::FlushICache(v8::internal::HashMap* i_cache, void* start_addr,
680 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(v8::internal::HashMap* i_cache, void* page) {
701 v8::internal::HashMap::Entry* entry =
702 i_cache->LookupOrInsert(page, ICacheHash(page));
703 if (entry->value == NULL) {
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(v8::internal::HashMap* i_cache, intptr_t start,
712 int size) {
713 DCHECK(size <= CachePage::kPageSize);
714 DCHECK(AllOnOnePage(start, size - 1));
715 DCHECK((start & CachePage::kLineMask) == 0);
716 DCHECK((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(v8::internal::HashMap* 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(memcmp(reinterpret_cast<void*>(instr),
737 cache_page->CachedData(offset), sizeof(FourByteInstr)),
738 0);
739 } else {
740 // Cache miss. Load memory into the cache.
741 memcpy(cached_line, line, CachePage::kLineLength);
742 *cache_valid_byte = CachePage::LINE_VALID;
743 }
744}
745
746void Simulator::Initialize(Isolate* isolate) {
747 if (isolate->simulator_initialized()) return;
748 isolate->set_simulator_initialized(true);
749 ::v8::internal::ExternalReference::set_redirector(isolate,
750 &RedirectExternalReference);
751}
752
753Simulator::Simulator(Isolate* isolate) : isolate_(isolate) {
754 i_cache_ = isolate_->simulator_i_cache();
755 if (i_cache_ == NULL) {
756 i_cache_ = new v8::internal::HashMap(&ICacheMatch);
757 isolate_->set_simulator_i_cache(i_cache_);
758 }
759 Initialize(isolate);
760// Set up simulator support first. Some of this information is needed to
761// setup the architecture state.
762#if V8_TARGET_ARCH_S390X
763 size_t stack_size = FLAG_sim_stack_size * KB;
764#else
765 size_t stack_size = MB; // allocate 1MB for stack
766#endif
767 stack_size += 2 * stack_protection_size_;
768 stack_ = reinterpret_cast<char*>(malloc(stack_size));
769 pc_modified_ = false;
770 icount_ = 0;
771 break_pc_ = NULL;
772 break_instr_ = 0;
773
774// make sure our register type can hold exactly 4/8 bytes
775#ifdef V8_TARGET_ARCH_S390X
776 DCHECK(sizeof(intptr_t) == 8);
777#else
778 DCHECK(sizeof(intptr_t) == 4);
779#endif
780 // Set up architecture state.
781 // All registers are initialized to zero to start with.
782 for (int i = 0; i < kNumGPRs; i++) {
783 registers_[i] = 0;
784 }
785 condition_reg_ = 0;
786 special_reg_pc_ = 0;
787
788 // Initializing FP registers.
789 for (int i = 0; i < kNumFPRs; i++) {
790 fp_registers_[i] = 0.0;
791 }
792
793 // The sp is initialized to point to the bottom (high address) of the
794 // allocated stack area. To be safe in potential stack underflows we leave
795 // some buffer below.
796 registers_[sp] =
797 reinterpret_cast<intptr_t>(stack_) + stack_size - stack_protection_size_;
798 InitializeCoverage();
799
800 last_debugger_input_ = NULL;
801}
802
803Simulator::~Simulator() { free(stack_); }
804
805// When the generated code calls an external reference we need to catch that in
806// the simulator. The external reference will be a function compiled for the
807// host architecture. We need to call that function instead of trying to
808// execute it with the simulator. We do that by redirecting the external
809// reference to a svc (Supervisor Call) instruction that is handled by
810// the simulator. We write the original destination of the jump just at a known
811// offset from the svc instruction so the simulator knows what to call.
812class Redirection {
813 public:
814 Redirection(Isolate* isolate, void* external_function,
815 ExternalReference::Type type)
816 : external_function_(external_function),
817// we use TRAP4 here (0xBF22)
818#if V8_TARGET_LITTLE_ENDIAN
819 swi_instruction_(0x1000FFB2),
820#else
821 swi_instruction_(0xB2FF0000 | kCallRtRedirected),
822#endif
823 type_(type),
824 next_(NULL) {
825 next_ = isolate->simulator_redirection();
826 Simulator::current(isolate)->FlushICache(
827 isolate->simulator_i_cache(),
828 reinterpret_cast<void*>(&swi_instruction_), sizeof(FourByteInstr));
829 isolate->set_simulator_redirection(this);
830 if (ABI_USES_FUNCTION_DESCRIPTORS) {
831 function_descriptor_[0] = reinterpret_cast<intptr_t>(&swi_instruction_);
832 function_descriptor_[1] = 0;
833 function_descriptor_[2] = 0;
834 }
835 }
836
837 void* address() {
838 if (ABI_USES_FUNCTION_DESCRIPTORS) {
839 return reinterpret_cast<void*>(function_descriptor_);
840 } else {
841 return reinterpret_cast<void*>(&swi_instruction_);
842 }
843 }
844
845 void* external_function() { return external_function_; }
846 ExternalReference::Type type() { return type_; }
847
848 static Redirection* Get(Isolate* isolate, void* external_function,
849 ExternalReference::Type type) {
850 Redirection* current = isolate->simulator_redirection();
851 for (; current != NULL; current = current->next_) {
852 if (current->external_function_ == external_function) {
853 DCHECK_EQ(current->type(), type);
854 return current;
855 }
856 }
857 return new Redirection(isolate, external_function, type);
858 }
859
860 static Redirection* FromSwiInstruction(Instruction* swi_instruction) {
861 char* addr_of_swi = reinterpret_cast<char*>(swi_instruction);
862 char* addr_of_redirection =
863 addr_of_swi - offsetof(Redirection, swi_instruction_);
864 return reinterpret_cast<Redirection*>(addr_of_redirection);
865 }
866
867 static Redirection* FromAddress(void* address) {
868 int delta = ABI_USES_FUNCTION_DESCRIPTORS
869 ? offsetof(Redirection, function_descriptor_)
870 : offsetof(Redirection, swi_instruction_);
871 char* addr_of_redirection = reinterpret_cast<char*>(address) - delta;
872 return reinterpret_cast<Redirection*>(addr_of_redirection);
873 }
874
875 static void* ReverseRedirection(intptr_t reg) {
876 Redirection* redirection = FromAddress(reinterpret_cast<void*>(reg));
877 return redirection->external_function();
878 }
879
880 static void DeleteChain(Redirection* redirection) {
881 while (redirection != nullptr) {
882 Redirection* next = redirection->next_;
883 delete redirection;
884 redirection = next;
885 }
886 }
887
888 private:
889 void* external_function_;
890 uint32_t swi_instruction_;
891 ExternalReference::Type type_;
892 Redirection* next_;
893 intptr_t function_descriptor_[3];
894};
895
896// static
897void Simulator::TearDown(HashMap* i_cache, Redirection* first) {
898 Redirection::DeleteChain(first);
899 if (i_cache != nullptr) {
900 for (HashMap::Entry* entry = i_cache->Start(); entry != nullptr;
901 entry = i_cache->Next(entry)) {
902 delete static_cast<CachePage*>(entry->value);
903 }
904 delete i_cache;
905 }
906}
907
908void* Simulator::RedirectExternalReference(Isolate* isolate,
909 void* external_function,
910 ExternalReference::Type type) {
911 Redirection* redirection = Redirection::Get(isolate, external_function, type);
912 return redirection->address();
913}
914
915// Get the active Simulator for the current thread.
916Simulator* Simulator::current(Isolate* isolate) {
917 v8::internal::Isolate::PerIsolateThreadData* isolate_data =
918 isolate->FindOrAllocatePerThreadDataForThisThread();
919 DCHECK(isolate_data != NULL);
920
921 Simulator* sim = isolate_data->simulator();
922 if (sim == NULL) {
923 // TODO(146): delete the simulator object when a thread/isolate goes away.
924 sim = new Simulator(isolate);
925 isolate_data->set_simulator(sim);
926 }
927 return sim;
928}
929
930// Sets the register in the architecture state.
931void Simulator::set_register(int reg, uint64_t value) {
932 DCHECK((reg >= 0) && (reg < kNumGPRs));
933 registers_[reg] = value;
934}
935
936// Get the register from the architecture state.
937uint64_t Simulator::get_register(int reg) const {
938 DCHECK((reg >= 0) && (reg < kNumGPRs));
939 // Stupid code added to avoid bug in GCC.
940 // See: http://gcc.gnu.org/bugzilla/show_bug.cgi?id=43949
941 if (reg >= kNumGPRs) return 0;
942 // End stupid code.
943 return registers_[reg];
944}
945
946template <typename T>
947T Simulator::get_low_register(int reg) const {
948 DCHECK((reg >= 0) && (reg < kNumGPRs));
949 // Stupid code added to avoid bug in GCC.
950 // See: http://gcc.gnu.org/bugzilla/show_bug.cgi?id=43949
951 if (reg >= kNumGPRs) return 0;
952 // End stupid code.
953 return static_cast<T>(registers_[reg] & 0xFFFFFFFF);
954}
955
956template <typename T>
957T Simulator::get_high_register(int reg) const {
958 DCHECK((reg >= 0) && (reg < kNumGPRs));
959 // Stupid code added to avoid bug in GCC.
960 // See: http://gcc.gnu.org/bugzilla/show_bug.cgi?id=43949
961 if (reg >= kNumGPRs) return 0;
962 // End stupid code.
963 return static_cast<T>(registers_[reg] >> 32);
964}
965
966void Simulator::set_low_register(int reg, uint32_t value) {
967 uint64_t shifted_val = static_cast<uint64_t>(value);
968 uint64_t orig_val = static_cast<uint64_t>(registers_[reg]);
969 uint64_t result = (orig_val >> 32 << 32) | shifted_val;
970 registers_[reg] = result;
971}
972
973void Simulator::set_high_register(int reg, uint32_t value) {
974 uint64_t shifted_val = static_cast<uint64_t>(value) << 32;
975 uint64_t orig_val = static_cast<uint64_t>(registers_[reg]);
976 uint64_t result = (orig_val & 0xFFFFFFFF) | shifted_val;
977 registers_[reg] = result;
978}
979
980double Simulator::get_double_from_register_pair(int reg) {
981 DCHECK((reg >= 0) && (reg < kNumGPRs) && ((reg % 2) == 0));
982
983 double dm_val = 0.0;
984#if 0 && !V8_TARGET_ARCH_S390X // doesn't make sense in 64bit mode
985 // Read the bits from the unsigned integer register_[] array
986 // into the double precision floating point value and return it.
987 char buffer[sizeof(fp_registers_[0])];
988 memcpy(buffer, &registers_[reg], 2 * sizeof(registers_[0]));
989 memcpy(&dm_val, buffer, 2 * sizeof(registers_[0]));
990#endif
991 return (dm_val);
992}
993
994// Raw access to the PC register.
995void Simulator::set_pc(intptr_t value) {
996 pc_modified_ = true;
997 special_reg_pc_ = value;
998}
999
1000bool Simulator::has_bad_pc() const {
1001 return ((special_reg_pc_ == bad_lr) || (special_reg_pc_ == end_sim_pc));
1002}
1003
1004// Raw access to the PC register without the special adjustment when reading.
1005intptr_t Simulator::get_pc() const { return special_reg_pc_; }
1006
1007// Runtime FP routines take:
1008// - two double arguments
1009// - one double argument and zero or one integer arguments.
1010// All are consructed here from d1, d2 and r2.
1011void Simulator::GetFpArgs(double* x, double* y, intptr_t* z) {
1012 *x = get_double_from_d_register(0);
1013 *y = get_double_from_d_register(2);
1014 *z = get_register(2);
1015}
1016
1017// The return value is in d0.
1018void Simulator::SetFpResult(const double& result) {
1019 set_d_register_from_double(0, result);
1020}
1021
1022void Simulator::TrashCallerSaveRegisters() {
1023// We don't trash the registers with the return value.
1024#if 0 // A good idea to trash volatile registers, needs to be done
1025 registers_[2] = 0x50Bad4U;
1026 registers_[3] = 0x50Bad4U;
1027 registers_[12] = 0x50Bad4U;
1028#endif
1029}
1030
1031uint32_t Simulator::ReadWU(intptr_t addr, Instruction* instr) {
1032 uint32_t* ptr = reinterpret_cast<uint32_t*>(addr);
1033 return *ptr;
1034}
1035
1036int32_t Simulator::ReadW(intptr_t addr, Instruction* instr) {
1037 int32_t* ptr = reinterpret_cast<int32_t*>(addr);
1038 return *ptr;
1039}
1040
1041void Simulator::WriteW(intptr_t addr, uint32_t value, Instruction* instr) {
1042 uint32_t* ptr = reinterpret_cast<uint32_t*>(addr);
1043 *ptr = value;
1044 return;
1045}
1046
1047void Simulator::WriteW(intptr_t addr, int32_t value, Instruction* instr) {
1048 int32_t* ptr = reinterpret_cast<int32_t*>(addr);
1049 *ptr = value;
1050 return;
1051}
1052
1053uint16_t Simulator::ReadHU(intptr_t addr, Instruction* instr) {
1054 uint16_t* ptr = reinterpret_cast<uint16_t*>(addr);
1055 return *ptr;
1056}
1057
1058int16_t Simulator::ReadH(intptr_t addr, Instruction* instr) {
1059 int16_t* ptr = reinterpret_cast<int16_t*>(addr);
1060 return *ptr;
1061}
1062
1063void Simulator::WriteH(intptr_t addr, uint16_t value, Instruction* instr) {
1064 uint16_t* ptr = reinterpret_cast<uint16_t*>(addr);
1065 *ptr = value;
1066 return;
1067}
1068
1069void Simulator::WriteH(intptr_t addr, int16_t value, Instruction* instr) {
1070 int16_t* ptr = reinterpret_cast<int16_t*>(addr);
1071 *ptr = value;
1072 return;
1073}
1074
1075uint8_t Simulator::ReadBU(intptr_t addr) {
1076 uint8_t* ptr = reinterpret_cast<uint8_t*>(addr);
1077 return *ptr;
1078}
1079
1080int8_t Simulator::ReadB(intptr_t addr) {
1081 int8_t* ptr = reinterpret_cast<int8_t*>(addr);
1082 return *ptr;
1083}
1084
1085void Simulator::WriteB(intptr_t addr, uint8_t value) {
1086 uint8_t* ptr = reinterpret_cast<uint8_t*>(addr);
1087 *ptr = value;
1088}
1089
1090void Simulator::WriteB(intptr_t addr, int8_t value) {
1091 int8_t* ptr = reinterpret_cast<int8_t*>(addr);
1092 *ptr = value;
1093}
1094
1095int64_t Simulator::ReadDW(intptr_t addr) {
1096 int64_t* ptr = reinterpret_cast<int64_t*>(addr);
1097 return *ptr;
1098}
1099
1100void Simulator::WriteDW(intptr_t addr, int64_t value) {
1101 int64_t* ptr = reinterpret_cast<int64_t*>(addr);
1102 *ptr = value;
1103 return;
1104}
1105
1106/**
1107 * Reads a double value from memory at given address.
1108 */
1109double Simulator::ReadDouble(intptr_t addr) {
1110 double* ptr = reinterpret_cast<double*>(addr);
1111 return *ptr;
1112}
1113
1114// Returns the limit of the stack area to enable checking for stack overflows.
1115uintptr_t Simulator::StackLimit(uintptr_t c_limit) const {
1116 // The simulator uses a separate JS stack. If we have exhausted the C stack,
1117 // we also drop down the JS limit to reflect the exhaustion on the JS stack.
1118 if (GetCurrentStackPosition() < c_limit) {
1119 return reinterpret_cast<uintptr_t>(get_sp());
1120 }
1121
1122 // Otherwise the limit is the JS stack. Leave a safety margin to prevent
1123 // overrunning the stack when pushing values.
1124 return reinterpret_cast<uintptr_t>(stack_) + stack_protection_size_;
1125}
1126
1127// Unsupported instructions use Format to print an error and stop execution.
1128void Simulator::Format(Instruction* instr, const char* format) {
1129 PrintF("Simulator found unsupported instruction:\n 0x%08" V8PRIxPTR ": %s\n",
1130 reinterpret_cast<intptr_t>(instr), format);
1131 UNIMPLEMENTED();
1132}
1133
1134// Calculate C flag value for additions.
1135bool Simulator::CarryFrom(int32_t left, int32_t right, int32_t carry) {
1136 uint32_t uleft = static_cast<uint32_t>(left);
1137 uint32_t uright = static_cast<uint32_t>(right);
1138 uint32_t urest = 0xffffffffU - uleft;
1139
1140 return (uright > urest) ||
1141 (carry && (((uright + 1) > urest) || (uright > (urest - 1))));
1142}
1143
1144// Calculate C flag value for subtractions.
1145bool Simulator::BorrowFrom(int32_t left, int32_t right) {
1146 uint32_t uleft = static_cast<uint32_t>(left);
1147 uint32_t uright = static_cast<uint32_t>(right);
1148
1149 return (uright > uleft);
1150}
1151
1152// Calculate V flag value for additions and subtractions.
1153template <typename T1>
1154bool Simulator::OverflowFromSigned(T1 alu_out, T1 left, T1 right,
1155 bool addition) {
1156 bool overflow;
1157 if (addition) {
1158 // operands have the same sign
1159 overflow = ((left >= 0 && right >= 0) || (left < 0 && right < 0))
1160 // and operands and result have different sign
1161 && ((left < 0 && alu_out >= 0) || (left >= 0 && alu_out < 0));
1162 } else {
1163 // operands have different signs
1164 overflow = ((left < 0 && right >= 0) || (left >= 0 && right < 0))
1165 // and first operand and result have different signs
1166 && ((left < 0 && alu_out >= 0) || (left >= 0 && alu_out < 0));
1167 }
1168 return overflow;
1169}
1170
1171#if V8_TARGET_ARCH_S390X
1172static void decodeObjectPair(ObjectPair* pair, intptr_t* x, intptr_t* y) {
1173 *x = reinterpret_cast<intptr_t>(pair->x);
1174 *y = reinterpret_cast<intptr_t>(pair->y);
1175}
1176#else
1177static void decodeObjectPair(ObjectPair* pair, intptr_t* x, intptr_t* y) {
1178#if V8_TARGET_BIG_ENDIAN
1179 *x = static_cast<int32_t>(*pair >> 32);
1180 *y = static_cast<int32_t>(*pair);
1181#else
1182 *x = static_cast<int32_t>(*pair);
1183 *y = static_cast<int32_t>(*pair >> 32);
1184#endif
1185}
1186#endif
1187
1188// Calls into the V8 runtime.
1189typedef intptr_t (*SimulatorRuntimeCall)(intptr_t arg0, intptr_t arg1,
1190 intptr_t arg2, intptr_t arg3,
1191 intptr_t arg4, intptr_t arg5);
1192typedef ObjectPair (*SimulatorRuntimePairCall)(intptr_t arg0, intptr_t arg1,
1193 intptr_t arg2, intptr_t arg3,
1194 intptr_t arg4, intptr_t arg5);
1195typedef ObjectTriple (*SimulatorRuntimeTripleCall)(intptr_t arg0, intptr_t arg1,
1196 intptr_t arg2, intptr_t arg3,
1197 intptr_t arg4,
1198 intptr_t arg5);
1199
1200// These prototypes handle the four types of FP calls.
1201typedef int (*SimulatorRuntimeCompareCall)(double darg0, double darg1);
1202typedef double (*SimulatorRuntimeFPFPCall)(double darg0, double darg1);
1203typedef double (*SimulatorRuntimeFPCall)(double darg0);
1204typedef double (*SimulatorRuntimeFPIntCall)(double darg0, intptr_t arg0);
1205
1206// This signature supports direct call in to API function native callback
1207// (refer to InvocationCallback in v8.h).
1208typedef void (*SimulatorRuntimeDirectApiCall)(intptr_t arg0);
1209typedef void (*SimulatorRuntimeProfilingApiCall)(intptr_t arg0, void* arg1);
1210
1211// This signature supports direct call to accessor getter callback.
1212typedef void (*SimulatorRuntimeDirectGetterCall)(intptr_t arg0, intptr_t arg1);
1213typedef void (*SimulatorRuntimeProfilingGetterCall)(intptr_t arg0,
1214 intptr_t arg1, void* arg2);
1215
1216// Software interrupt instructions are used by the simulator to call into the
1217// C-based V8 runtime.
1218void Simulator::SoftwareInterrupt(Instruction* instr) {
1219 int svc = instr->SvcValue();
1220 switch (svc) {
1221 case kCallRtRedirected: {
1222 // Check if stack is aligned. Error if not aligned is reported below to
1223 // include information on the function called.
1224 bool stack_aligned =
1225 (get_register(sp) & (::v8::internal::FLAG_sim_stack_alignment - 1)) ==
1226 0;
1227 Redirection* redirection = Redirection::FromSwiInstruction(instr);
1228 const int kArgCount = 6;
1229 int arg0_regnum = 2;
1230 intptr_t result_buffer = 0;
1231 bool uses_result_buffer =
1232 redirection->type() == ExternalReference::BUILTIN_CALL_TRIPLE ||
1233 (redirection->type() == ExternalReference::BUILTIN_CALL_PAIR &&
1234 !ABI_RETURNS_OBJECTPAIR_IN_REGS);
1235 if (uses_result_buffer) {
1236 result_buffer = get_register(r2);
1237 arg0_regnum++;
1238 }
1239 intptr_t arg[kArgCount];
1240 for (int i = 0; i < kArgCount - 1; i++) {
1241 arg[i] = get_register(arg0_regnum + i);
1242 }
1243 intptr_t* stack_pointer = reinterpret_cast<intptr_t*>(get_register(sp));
1244 arg[5] = stack_pointer[kCalleeRegisterSaveAreaSize / kPointerSize];
1245 bool fp_call =
1246 (redirection->type() == ExternalReference::BUILTIN_FP_FP_CALL) ||
1247 (redirection->type() == ExternalReference::BUILTIN_COMPARE_CALL) ||
1248 (redirection->type() == ExternalReference::BUILTIN_FP_CALL) ||
1249 (redirection->type() == ExternalReference::BUILTIN_FP_INT_CALL);
1250
1251 // Place the return address on the stack, making the call GC safe.
1252 *reinterpret_cast<intptr_t*>(get_register(sp) +
1253 kStackFrameRASlot * kPointerSize) =
1254 get_register(r14);
1255
1256 intptr_t external =
1257 reinterpret_cast<intptr_t>(redirection->external_function());
1258 if (fp_call) {
1259 double dval0, dval1; // one or two double parameters
1260 intptr_t ival; // zero or one integer parameters
1261 int iresult = 0; // integer return value
1262 double dresult = 0; // double return value
1263 GetFpArgs(&dval0, &dval1, &ival);
1264 if (::v8::internal::FLAG_trace_sim || !stack_aligned) {
1265 SimulatorRuntimeCall generic_target =
1266 reinterpret_cast<SimulatorRuntimeCall>(external);
1267 switch (redirection->type()) {
1268 case ExternalReference::BUILTIN_FP_FP_CALL:
1269 case ExternalReference::BUILTIN_COMPARE_CALL:
1270 PrintF("Call to host function at %p with args %f, %f",
1271 FUNCTION_ADDR(generic_target), dval0, dval1);
1272 break;
1273 case ExternalReference::BUILTIN_FP_CALL:
1274 PrintF("Call to host function at %p with arg %f",
1275 FUNCTION_ADDR(generic_target), dval0);
1276 break;
1277 case ExternalReference::BUILTIN_FP_INT_CALL:
1278 PrintF("Call to host function at %p with args %f, %" V8PRIdPTR,
1279 FUNCTION_ADDR(generic_target), dval0, ival);
1280 break;
1281 default:
1282 UNREACHABLE();
1283 break;
1284 }
1285 if (!stack_aligned) {
1286 PrintF(" with unaligned stack %08" V8PRIxPTR "\n",
1287 static_cast<intptr_t>(get_register(sp)));
1288 }
1289 PrintF("\n");
1290 }
1291 CHECK(stack_aligned);
1292 switch (redirection->type()) {
1293 case ExternalReference::BUILTIN_COMPARE_CALL: {
1294 SimulatorRuntimeCompareCall target =
1295 reinterpret_cast<SimulatorRuntimeCompareCall>(external);
1296 iresult = target(dval0, dval1);
1297 set_register(r2, iresult);
1298 break;
1299 }
1300 case ExternalReference::BUILTIN_FP_FP_CALL: {
1301 SimulatorRuntimeFPFPCall target =
1302 reinterpret_cast<SimulatorRuntimeFPFPCall>(external);
1303 dresult = target(dval0, dval1);
1304 SetFpResult(dresult);
1305 break;
1306 }
1307 case ExternalReference::BUILTIN_FP_CALL: {
1308 SimulatorRuntimeFPCall target =
1309 reinterpret_cast<SimulatorRuntimeFPCall>(external);
1310 dresult = target(dval0);
1311 SetFpResult(dresult);
1312 break;
1313 }
1314 case ExternalReference::BUILTIN_FP_INT_CALL: {
1315 SimulatorRuntimeFPIntCall target =
1316 reinterpret_cast<SimulatorRuntimeFPIntCall>(external);
1317 dresult = target(dval0, ival);
1318 SetFpResult(dresult);
1319 break;
1320 }
1321 default:
1322 UNREACHABLE();
1323 break;
1324 }
1325 if (::v8::internal::FLAG_trace_sim || !stack_aligned) {
1326 switch (redirection->type()) {
1327 case ExternalReference::BUILTIN_COMPARE_CALL:
1328 PrintF("Returned %08x\n", iresult);
1329 break;
1330 case ExternalReference::BUILTIN_FP_FP_CALL:
1331 case ExternalReference::BUILTIN_FP_CALL:
1332 case ExternalReference::BUILTIN_FP_INT_CALL:
1333 PrintF("Returned %f\n", dresult);
1334 break;
1335 default:
1336 UNREACHABLE();
1337 break;
1338 }
1339 }
1340 } else if (redirection->type() == ExternalReference::DIRECT_API_CALL) {
1341 // See callers of MacroAssembler::CallApiFunctionAndReturn for
1342 // explanation of register usage.
1343 if (::v8::internal::FLAG_trace_sim || !stack_aligned) {
1344 PrintF("Call to host function at %p args %08" V8PRIxPTR,
1345 reinterpret_cast<void*>(external), arg[0]);
1346 if (!stack_aligned) {
1347 PrintF(" with unaligned stack %08" V8PRIxPTR "\n",
1348 static_cast<intptr_t>(get_register(sp)));
1349 }
1350 PrintF("\n");
1351 }
1352 CHECK(stack_aligned);
1353 SimulatorRuntimeDirectApiCall target =
1354 reinterpret_cast<SimulatorRuntimeDirectApiCall>(external);
1355 target(arg[0]);
1356 } else if (redirection->type() == ExternalReference::PROFILING_API_CALL) {
1357 // See callers of MacroAssembler::CallApiFunctionAndReturn for
1358 // explanation of register usage.
1359 if (::v8::internal::FLAG_trace_sim || !stack_aligned) {
1360 PrintF("Call to host function at %p args %08" V8PRIxPTR
1361 " %08" V8PRIxPTR,
1362 reinterpret_cast<void*>(external), arg[0], arg[1]);
1363 if (!stack_aligned) {
1364 PrintF(" with unaligned stack %08" V8PRIxPTR "\n",
1365 static_cast<intptr_t>(get_register(sp)));
1366 }
1367 PrintF("\n");
1368 }
1369 CHECK(stack_aligned);
1370 SimulatorRuntimeProfilingApiCall target =
1371 reinterpret_cast<SimulatorRuntimeProfilingApiCall>(external);
1372 target(arg[0], Redirection::ReverseRedirection(arg[1]));
1373 } else if (redirection->type() == ExternalReference::DIRECT_GETTER_CALL) {
1374 // See callers of MacroAssembler::CallApiFunctionAndReturn for
1375 // explanation of register usage.
1376 if (::v8::internal::FLAG_trace_sim || !stack_aligned) {
1377 PrintF("Call to host function at %p args %08" V8PRIxPTR
1378 " %08" V8PRIxPTR,
1379 reinterpret_cast<void*>(external), arg[0], arg[1]);
1380 if (!stack_aligned) {
1381 PrintF(" with unaligned stack %08" V8PRIxPTR "\n",
1382 static_cast<intptr_t>(get_register(sp)));
1383 }
1384 PrintF("\n");
1385 }
1386 CHECK(stack_aligned);
1387 SimulatorRuntimeDirectGetterCall target =
1388 reinterpret_cast<SimulatorRuntimeDirectGetterCall>(external);
1389 if (!ABI_PASSES_HANDLES_IN_REGS) {
1390 arg[0] = *(reinterpret_cast<intptr_t*>(arg[0]));
1391 }
1392 target(arg[0], arg[1]);
1393 } else if (redirection->type() ==
1394 ExternalReference::PROFILING_GETTER_CALL) {
1395 if (::v8::internal::FLAG_trace_sim || !stack_aligned) {
1396 PrintF("Call to host function at %p args %08" V8PRIxPTR
1397 " %08" V8PRIxPTR " %08" V8PRIxPTR,
1398 reinterpret_cast<void*>(external), arg[0], arg[1], arg[2]);
1399 if (!stack_aligned) {
1400 PrintF(" with unaligned stack %08" V8PRIxPTR "\n",
1401 static_cast<intptr_t>(get_register(sp)));
1402 }
1403 PrintF("\n");
1404 }
1405 CHECK(stack_aligned);
1406 SimulatorRuntimeProfilingGetterCall target =
1407 reinterpret_cast<SimulatorRuntimeProfilingGetterCall>(external);
1408 if (!ABI_PASSES_HANDLES_IN_REGS) {
1409 arg[0] = *(reinterpret_cast<intptr_t*>(arg[0]));
1410 }
1411 target(arg[0], arg[1], Redirection::ReverseRedirection(arg[2]));
1412 } else {
1413 // builtin call.
1414 if (::v8::internal::FLAG_trace_sim || !stack_aligned) {
1415 SimulatorRuntimeCall target =
1416 reinterpret_cast<SimulatorRuntimeCall>(external);
1417 PrintF(
1418 "Call to host function at %p,\n"
1419 "\t\t\t\targs %08" V8PRIxPTR ", %08" V8PRIxPTR ", %08" V8PRIxPTR
1420 ", %08" V8PRIxPTR ", %08" V8PRIxPTR ", %08" V8PRIxPTR,
1421 FUNCTION_ADDR(target), arg[0], arg[1], arg[2], arg[3], arg[4],
1422 arg[5]);
1423 if (!stack_aligned) {
1424 PrintF(" with unaligned stack %08" V8PRIxPTR "\n",
1425 static_cast<intptr_t>(get_register(sp)));
1426 }
1427 PrintF("\n");
1428 }
1429 CHECK(stack_aligned);
1430 if (redirection->type() == ExternalReference::BUILTIN_CALL_TRIPLE) {
1431 SimulatorRuntimeTripleCall target =
1432 reinterpret_cast<SimulatorRuntimeTripleCall>(external);
1433 ObjectTriple result =
1434 target(arg[0], arg[1], arg[2], arg[3], arg[4], arg[5]);
1435 if (::v8::internal::FLAG_trace_sim) {
1436 PrintF("Returned {%08" V8PRIxPTR ", %08" V8PRIxPTR ", %08" V8PRIxPTR
1437 "}\n",
1438 reinterpret_cast<intptr_t>(result.x),
1439 reinterpret_cast<intptr_t>(result.y),
1440 reinterpret_cast<intptr_t>(result.z));
1441 }
1442 memcpy(reinterpret_cast<void*>(result_buffer), &result,
1443 sizeof(ObjectTriple));
1444 set_register(r2, result_buffer);
1445 } else {
1446 if (redirection->type() == ExternalReference::BUILTIN_CALL_PAIR) {
1447 SimulatorRuntimePairCall target =
1448 reinterpret_cast<SimulatorRuntimePairCall>(external);
1449 ObjectPair result =
1450 target(arg[0], arg[1], arg[2], arg[3], arg[4], arg[5]);
1451 intptr_t x;
1452 intptr_t y;
1453 decodeObjectPair(&result, &x, &y);
1454 if (::v8::internal::FLAG_trace_sim) {
1455 PrintF("Returned {%08" V8PRIxPTR ", %08" V8PRIxPTR "}\n", x, y);
1456 }
1457 if (ABI_RETURNS_OBJECTPAIR_IN_REGS) {
1458 set_register(r2, x);
1459 set_register(r3, y);
1460 } else {
1461 memcpy(reinterpret_cast<void*>(result_buffer), &result,
1462 sizeof(ObjectPair));
1463 set_register(r2, result_buffer);
1464 }
1465 } else {
1466 DCHECK(redirection->type() == ExternalReference::BUILTIN_CALL);
1467 SimulatorRuntimeCall target =
1468 reinterpret_cast<SimulatorRuntimeCall>(external);
1469 intptr_t result =
1470 target(arg[0], arg[1], arg[2], arg[3], arg[4], arg[5]);
1471 if (::v8::internal::FLAG_trace_sim) {
1472 PrintF("Returned %08" V8PRIxPTR "\n", result);
1473 }
1474 set_register(r2, result);
1475 }
1476 }
1477 // #if !V8_TARGET_ARCH_S390X
1478 // DCHECK(redirection->type() ==
1479 // ExternalReference::BUILTIN_CALL);
1480 // SimulatorRuntimeCall target =
1481 // reinterpret_cast<SimulatorRuntimeCall>(external);
1482 // int64_t result = target(arg[0], arg[1], arg[2], arg[3],
1483 // arg[4],
1484 // arg[5]);
1485 // int32_t lo_res = static_cast<int32_t>(result);
1486 // int32_t hi_res = static_cast<int32_t>(result >> 32);
1487 // #if !V8_TARGET_LITTLE_ENDIAN
1488 // if (::v8::internal::FLAG_trace_sim) {
1489 // PrintF("Returned %08x\n", hi_res);
1490 // }
1491 // set_register(r2, hi_res);
1492 // set_register(r3, lo_res);
1493 // #else
1494 // if (::v8::internal::FLAG_trace_sim) {
1495 // PrintF("Returned %08x\n", lo_res);
1496 // }
1497 // set_register(r2, lo_res);
1498 // set_register(r3, hi_res);
1499 // #endif
1500 // #else
1501 // if (redirection->type() == ExternalReference::BUILTIN_CALL) {
1502 // SimulatorRuntimeCall target =
1503 // reinterpret_cast<SimulatorRuntimeCall>(external);
1504 // intptr_t result = target(arg[0], arg[1], arg[2], arg[3],
1505 // arg[4],
1506 // arg[5]);
1507 // if (::v8::internal::FLAG_trace_sim) {
1508 // PrintF("Returned %08" V8PRIxPTR "\n", result);
1509 // }
1510 // set_register(r2, result);
1511 // } else {
1512 // DCHECK(redirection->type() ==
1513 // ExternalReference::BUILTIN_CALL_PAIR);
1514 // SimulatorRuntimePairCall target =
1515 // reinterpret_cast<SimulatorRuntimePairCall>(external);
1516 // ObjectPair result = target(arg[0], arg[1], arg[2], arg[3],
1517 // arg[4], arg[5]);
1518 // if (::v8::internal::FLAG_trace_sim) {
1519 // PrintF("Returned %08" V8PRIxPTR ", %08" V8PRIxPTR "\n",
1520 // result.x, result.y);
1521 // }
1522 // #if ABI_RETURNS_OBJECTPAIR_IN_REGS
1523 // set_register(r2, result.x);
1524 // set_register(r3, result.y);
1525 // #else
1526 // memcpy(reinterpret_cast<void *>(result_buffer), &result,
1527 // sizeof(ObjectPair));
1528 // #endif
1529 // }
1530 // #endif
1531 }
1532 int64_t saved_lr = *reinterpret_cast<intptr_t*>(
1533 get_register(sp) + kStackFrameRASlot * kPointerSize);
1534#if (!V8_TARGET_ARCH_S390X && V8_HOST_ARCH_S390)
1535 // On zLinux-31, the saved_lr might be tagged with a high bit of 1.
1536 // Cleanse it before proceeding with simulation.
1537 saved_lr &= 0x7FFFFFFF;
1538#endif
1539 set_pc(saved_lr);
1540 break;
1541 }
1542 case kBreakpoint: {
1543 S390Debugger dbg(this);
1544 dbg.Debug();
1545 break;
1546 }
1547 // stop uses all codes greater than 1 << 23.
1548 default: {
1549 if (svc >= (1 << 23)) {
1550 uint32_t code = svc & kStopCodeMask;
1551 if (isWatchedStop(code)) {
1552 IncreaseStopCounter(code);
1553 }
1554 // Stop if it is enabled, otherwise go on jumping over the stop
1555 // and the message address.
1556 if (isEnabledStop(code)) {
1557 S390Debugger dbg(this);
1558 dbg.Stop(instr);
1559 } else {
1560 set_pc(get_pc() + sizeof(FourByteInstr) + kPointerSize);
1561 }
1562 } else {
1563 // This is not a valid svc code.
1564 UNREACHABLE();
1565 break;
1566 }
1567 }
1568 }
1569}
1570
1571// Stop helper functions.
1572bool Simulator::isStopInstruction(Instruction* instr) {
1573 return (instr->Bits(27, 24) == 0xF) && (instr->SvcValue() >= kStopCode);
1574}
1575
1576bool Simulator::isWatchedStop(uint32_t code) {
1577 DCHECK(code <= kMaxStopCode);
1578 return code < kNumOfWatchedStops;
1579}
1580
1581bool Simulator::isEnabledStop(uint32_t code) {
1582 DCHECK(code <= kMaxStopCode);
1583 // Unwatched stops are always enabled.
1584 return !isWatchedStop(code) ||
1585 !(watched_stops_[code].count & kStopDisabledBit);
1586}
1587
1588void Simulator::EnableStop(uint32_t code) {
1589 DCHECK(isWatchedStop(code));
1590 if (!isEnabledStop(code)) {
1591 watched_stops_[code].count &= ~kStopDisabledBit;
1592 }
1593}
1594
1595void Simulator::DisableStop(uint32_t code) {
1596 DCHECK(isWatchedStop(code));
1597 if (isEnabledStop(code)) {
1598 watched_stops_[code].count |= kStopDisabledBit;
1599 }
1600}
1601
1602void Simulator::IncreaseStopCounter(uint32_t code) {
1603 DCHECK(code <= kMaxStopCode);
1604 DCHECK(isWatchedStop(code));
1605 if ((watched_stops_[code].count & ~(1 << 31)) == 0x7fffffff) {
1606 PrintF(
1607 "Stop counter for code %i has overflowed.\n"
1608 "Enabling this code and reseting the counter to 0.\n",
1609 code);
1610 watched_stops_[code].count = 0;
1611 EnableStop(code);
1612 } else {
1613 watched_stops_[code].count++;
1614 }
1615}
1616
1617// Print a stop status.
1618void Simulator::PrintStopInfo(uint32_t code) {
1619 DCHECK(code <= kMaxStopCode);
1620 if (!isWatchedStop(code)) {
1621 PrintF("Stop not watched.");
1622 } else {
1623 const char* state = isEnabledStop(code) ? "Enabled" : "Disabled";
1624 int32_t count = watched_stops_[code].count & ~kStopDisabledBit;
1625 // Don't print the state of unused breakpoints.
1626 if (count != 0) {
1627 if (watched_stops_[code].desc) {
1628 PrintF("stop %i - 0x%x: \t%s, \tcounter = %i, \t%s\n", code, code,
1629 state, count, watched_stops_[code].desc);
1630 } else {
1631 PrintF("stop %i - 0x%x: \t%s, \tcounter = %i\n", code, code, state,
1632 count);
1633 }
1634 }
1635 }
1636}
1637
1638// Method for checking overflow on signed addition:
1639// Test src1 and src2 have opposite sign,
1640// (1) No overflow if they have opposite sign
1641// (2) Test the result and one of the operands have opposite sign
1642// (a) No overflow if they don't have opposite sign
1643// (b) Overflow if opposite
1644#define CheckOverflowForIntAdd(src1, src2, type) \
1645 OverflowFromSigned<type>(src1 + src2, src1, src2, true);
1646
1647#define CheckOverflowForIntSub(src1, src2, type) \
1648 OverflowFromSigned<type>(src1 - src2, src1, src2, false);
1649
1650// Method for checking overflow on unsigned addtion
1651#define CheckOverflowForUIntAdd(src1, src2) \
1652 ((src1) + (src2) < (src1) || (src1) + (src2) < (src2))
1653
1654// Method for checking overflow on unsigned subtraction
1655#define CheckOverflowForUIntSub(src1, src2) ((src1) - (src2) > (src1))
1656
1657// Method for checking overflow on multiplication
1658#define CheckOverflowForMul(src1, src2) (((src1) * (src2)) / (src2) != (src1))
1659
1660// Method for checking overflow on shift right
1661#define CheckOverflowForShiftRight(src1, src2) \
1662 (((src1) >> (src2)) << (src2) != (src1))
1663
1664// Method for checking overflow on shift left
1665#define CheckOverflowForShiftLeft(src1, src2) \
1666 (((src1) << (src2)) >> (src2) != (src1))
1667
1668// S390 Decode and simulate helpers
1669bool Simulator::DecodeTwoByte(Instruction* instr) {
1670 Opcode op = instr->S390OpcodeValue();
1671
1672 switch (op) {
1673 // RR format instructions
1674 case AR:
1675 case SR:
1676 case MR:
1677 case DR:
1678 case OR:
1679 case NR:
1680 case XR: {
1681 RRInstruction* rrinst = reinterpret_cast<RRInstruction*>(instr);
1682 int r1 = rrinst->R1Value();
1683 int r2 = rrinst->R2Value();
1684 int32_t r1_val = get_low_register<int32_t>(r1);
1685 int32_t r2_val = get_low_register<int32_t>(r2);
1686 bool isOF = false;
1687 switch (op) {
1688 case AR:
1689 isOF = CheckOverflowForIntAdd(r1_val, r2_val, int32_t);
1690 r1_val += r2_val;
1691 SetS390ConditionCode<int32_t>(r1_val, 0);
1692 SetS390OverflowCode(isOF);
1693 break;
1694 case SR:
1695 isOF = CheckOverflowForIntSub(r1_val, r2_val, int32_t);
1696 r1_val -= r2_val;
1697 SetS390ConditionCode<int32_t>(r1_val, 0);
1698 SetS390OverflowCode(isOF);
1699 break;
1700 case OR:
1701 r1_val |= r2_val;
1702 SetS390BitWiseConditionCode<uint32_t>(r1_val);
1703 break;
1704 case NR:
1705 r1_val &= r2_val;
1706 SetS390BitWiseConditionCode<uint32_t>(r1_val);
1707 break;
1708 case XR:
1709 r1_val ^= r2_val;
1710 SetS390BitWiseConditionCode<uint32_t>(r1_val);
1711 break;
1712 case MR: {
1713 DCHECK(r1 % 2 == 0);
1714 r1_val = get_low_register<int32_t>(r1 + 1);
1715 int64_t product =
1716 static_cast<int64_t>(r1_val) * static_cast<int64_t>(r2_val);
1717 int32_t high_bits = product >> 32;
1718 r1_val = high_bits;
1719 int32_t low_bits = product & 0x00000000FFFFFFFF;
1720 set_low_register(r1, high_bits);
1721 set_low_register(r1 + 1, low_bits);
1722 break;
1723 }
1724 case DR: {
1725 // reg-reg pair should be even-odd pair, assert r1 is an even register
1726 DCHECK(r1 % 2 == 0);
1727 // leftmost 32 bits of the dividend are in r1
1728 // rightmost 32 bits of the dividend are in r1+1
1729 // get the signed value from r1
1730 int64_t dividend = static_cast<int64_t>(r1_val) << 32;
1731 // get unsigned value from r1+1
1732 // avoid addition with sign-extended r1+1 value
1733 dividend += get_low_register<uint32_t>(r1 + 1);
1734 int32_t remainder = dividend % r2_val;
1735 int32_t quotient = dividend / r2_val;
1736 r1_val = remainder;
1737 set_low_register(r1, remainder);
1738 set_low_register(r1 + 1, quotient);
1739 break; // reg pair
1740 }
1741 default:
1742 UNREACHABLE();
1743 break;
1744 }
1745 set_low_register(r1, r1_val);
1746 break;
1747 }
1748 case LR: {
1749 RRInstruction* rrinst = reinterpret_cast<RRInstruction*>(instr);
1750 int r1 = rrinst->R1Value();
1751 int r2 = rrinst->R2Value();
1752 set_low_register(r1, get_low_register<int32_t>(r2));
1753 break;
1754 }
1755 case LDR: {
1756 RRInstruction* rrinst = reinterpret_cast<RRInstruction*>(instr);
1757 int r1 = rrinst->R1Value();
1758 int r2 = rrinst->R2Value();
1759 int64_t r2_val = get_d_register(r2);
1760 set_d_register(r1, r2_val);
1761 break;
1762 }
1763 case CR: {
1764 RRInstruction* rrinst = reinterpret_cast<RRInstruction*>(instr);
1765 int r1 = rrinst->R1Value();
1766 int r2 = rrinst->R2Value();
1767 int32_t r1_val = get_low_register<int32_t>(r1);
1768 int32_t r2_val = get_low_register<int32_t>(r2);
1769 SetS390ConditionCode<int32_t>(r1_val, r2_val);
1770 break;
1771 }
1772 case CLR: {
1773 RRInstruction* rrinst = reinterpret_cast<RRInstruction*>(instr);
1774 int r1 = rrinst->R1Value();
1775 int r2 = rrinst->R2Value();
1776 uint32_t r1_val = get_low_register<uint32_t>(r1);
1777 uint32_t r2_val = get_low_register<uint32_t>(r2);
1778 SetS390ConditionCode<uint32_t>(r1_val, r2_val);
1779 break;
1780 }
1781 case BCR: {
1782 RRInstruction* rrinst = reinterpret_cast<RRInstruction*>(instr);
1783 int r1 = rrinst->R1Value();
1784 int r2 = rrinst->R2Value();
1785 if (TestConditionCode(Condition(r1))) {
1786 intptr_t r2_val = get_register(r2);
1787#if (!V8_TARGET_ARCH_S390X && V8_HOST_ARCH_S390)
1788 // On 31-bit, the top most bit may be 0 or 1, but is ignored by the
1789 // hardware. Cleanse the top bit before jumping to it, unless it's one
1790 // of the special PCs
1791 if (r2_val != bad_lr && r2_val != end_sim_pc) r2_val &= 0x7FFFFFFF;
1792#endif
1793 set_pc(r2_val);
1794 }
1795 break;
1796 }
1797 case LTR: {
1798 RRInstruction* rrinst = reinterpret_cast<RRInstruction*>(instr);
1799 int r1 = rrinst->R1Value();
1800 int r2 = rrinst->R2Value();
1801 int32_t r2_val = get_low_register<int32_t>(r2);
1802 SetS390ConditionCode<int32_t>(r2_val, 0);
1803 set_low_register(r1, r2_val);
1804 break;
1805 }
1806 case ALR:
1807 case SLR: {
1808 RRInstruction* rrinst = reinterpret_cast<RRInstruction*>(instr);
1809 int r1 = rrinst->R1Value();
1810 int r2 = rrinst->R2Value();
1811 uint32_t r1_val = get_low_register<uint32_t>(r1);
1812 uint32_t r2_val = get_low_register<uint32_t>(r2);
1813 uint32_t alu_out = 0;
1814 bool isOF = false;
1815 if (ALR == op) {
1816 alu_out = r1_val + r2_val;
1817 isOF = CheckOverflowForUIntAdd(r1_val, r2_val);
1818 } else if (SLR == op) {
1819 alu_out = r1_val - r2_val;
1820 isOF = CheckOverflowForUIntSub(r1_val, r2_val);
1821 } else {
1822 UNREACHABLE();
1823 }
1824 set_low_register(r1, alu_out);
1825 SetS390ConditionCodeCarry<uint32_t>(alu_out, isOF);
1826 break;
1827 }
1828 case LNR: {
1829 // Load Negative (32)
1830 RRInstruction* rrinst = reinterpret_cast<RRInstruction*>(instr);
1831 int r1 = rrinst->R1Value();
1832 int r2 = rrinst->R2Value();
1833 int32_t r2_val = get_low_register<int32_t>(r2);
1834 r2_val = (r2_val >= 0) ? -r2_val : r2_val; // If pos, then negate it.
1835 set_low_register(r1, r2_val);
1836 condition_reg_ = (r2_val == 0) ? CC_EQ : CC_LT; // CC0 - result is zero
1837 // CC1 - result is negative
1838 break;
1839 }
1840 case BASR: {
1841 RRInstruction* rrinst = reinterpret_cast<RRInstruction*>(instr);
1842 int r1 = rrinst->R1Value();
1843 int r2 = rrinst->R2Value();
1844 intptr_t link_addr = get_pc() + 2;
1845 // If R2 is zero, the BASR does not branch.
1846 int64_t r2_val = (r2 == 0) ? link_addr : get_register(r2);
1847#if (!V8_TARGET_ARCH_S390X && V8_HOST_ARCH_S390)
1848 // On 31-bit, the top most bit may be 0 or 1, which can cause issues
1849 // for stackwalker. The top bit should either be cleanse before being
1850 // pushed onto the stack, or during stack walking when dereferenced.
1851 // For simulator, we'll take the worst case scenario and always tag
1852 // the high bit, to flush out more problems.
1853 link_addr |= 0x80000000;
1854#endif
1855 set_register(r1, link_addr);
1856 set_pc(r2_val);
1857 break;
1858 }
1859 case LCR: {
1860 RRInstruction* rrinst = reinterpret_cast<RRInstruction*>(instr);
1861 int r1 = rrinst->R1Value();
1862 int r2 = rrinst->R2Value();
1863 int32_t r2_val = get_low_register<int32_t>(r2);
1864 int32_t original_r2_val = r2_val;
1865 r2_val = ~r2_val;
1866 r2_val = r2_val + 1;
1867 set_low_register(r1, r2_val);
1868 SetS390ConditionCode<int32_t>(r2_val, 0);
1869 // Checks for overflow where r2_val = -2147483648.
1870 // Cannot do int comparison due to GCC 4.8 bug on x86.
1871 // Detect INT_MIN alternatively, as it is the only value where both
1872 // original and result are negative due to overflow.
1873 if (r2_val < 0 && original_r2_val < 0) {
1874 SetS390OverflowCode(true);
1875 }
1876 break;
1877 }
1878 case BKPT: {
1879 set_pc(get_pc() + 2);
1880 S390Debugger dbg(this);
1881 dbg.Debug();
1882 break;
1883 }
1884 default:
1885 UNREACHABLE();
1886 return false;
1887 break;
1888 }
1889 return true;
1890}
1891
1892// Decode routine for four-byte instructions
1893bool Simulator::DecodeFourByte(Instruction* instr) {
1894 Opcode op = instr->S390OpcodeValue();
1895
1896 // Pre-cast instruction to various types
1897 RREInstruction* rreInst = reinterpret_cast<RREInstruction*>(instr);
1898 SIInstruction* siInstr = reinterpret_cast<SIInstruction*>(instr);
1899
1900 switch (op) {
1901 case POPCNT_Z: {
1902 int r1 = rreInst->R1Value();
1903 int r2 = rreInst->R2Value();
1904 int64_t r2_val = get_register(r2);
1905 int64_t r1_val = 0;
1906
1907 uint8_t* r2_val_ptr = reinterpret_cast<uint8_t*>(&r2_val);
1908 uint8_t* r1_val_ptr = reinterpret_cast<uint8_t*>(&r1_val);
1909 for (int i = 0; i < 8; i++) {
1910 uint32_t x = static_cast<uint32_t>(r2_val_ptr[i]);
1911#if defined(__GNUC__)
1912 r1_val_ptr[i] = __builtin_popcount(x);
1913#else
1914#error unsupport __builtin_popcount
1915#endif
1916 }
1917
1918 set_register(r1, static_cast<uint64_t>(r1_val));
1919 break;
1920 }
1921 case LLGFR: {
1922 int r1 = rreInst->R1Value();
1923 int r2 = rreInst->R2Value();
1924 int32_t r2_val = get_low_register<int32_t>(r2);
1925 uint64_t r2_finalval =
1926 (static_cast<uint64_t>(r2_val) & 0x00000000ffffffff);
1927 set_register(r1, r2_finalval);
1928 break;
1929 }
1930 case EX: {
1931 RXInstruction* rxinst = reinterpret_cast<RXInstruction*>(instr);
1932 int r1 = rxinst->R1Value();
1933 int b2 = rxinst->B2Value();
1934 int x2 = rxinst->X2Value();
1935 int64_t b2_val = (b2 == 0) ? 0 : get_register(b2);
1936 int64_t x2_val = (x2 == 0) ? 0 : get_register(x2);
1937 intptr_t d2_val = rxinst->D2Value();
1938 int32_t r1_val = get_low_register<int32_t>(r1);
1939
1940 SixByteInstr the_instr = Instruction::InstructionBits(
1941 reinterpret_cast<const byte*>(b2_val + x2_val + d2_val));
1942 int length = Instruction::InstructionLength(
1943 reinterpret_cast<const byte*>(b2_val + x2_val + d2_val));
1944
1945 char new_instr_buf[8];
1946 char* addr = reinterpret_cast<char*>(&new_instr_buf[0]);
1947 the_instr |= static_cast<SixByteInstr>(r1_val & 0xff)
1948 << (8 * length - 16);
1949 Instruction::SetInstructionBits<SixByteInstr>(
1950 reinterpret_cast<byte*>(addr), static_cast<SixByteInstr>(the_instr));
1951 ExecuteInstruction(reinterpret_cast<Instruction*>(addr), false);
1952 break;
1953 }
1954 case LGR: {
1955 // Load Register (64)
1956 int r1 = rreInst->R1Value();
1957 int r2 = rreInst->R2Value();
1958 set_register(r1, get_register(r2));
1959 break;
1960 }
1961 case LDGR: {
1962 // Load FPR from GPR (L <- 64)
1963 uint64_t int_val = get_register(rreInst->R2Value());
1964 // double double_val = bit_cast<double, uint64_t>(int_val);
1965 // set_d_register_from_double(rreInst->R1Value(), double_val);
1966 set_d_register(rreInst->R1Value(), int_val);
1967 break;
1968 }
1969 case LGDR: {
1970 // Load GPR from FPR (64 <- L)
1971 int64_t double_val = get_d_register(rreInst->R2Value());
1972 set_register(rreInst->R1Value(), double_val);
1973 break;
1974 }
1975 case LTGR: {
1976 // Load Register (64)
1977 int r1 = rreInst->R1Value();
1978 int r2 = rreInst->R2Value();
1979 int64_t r2_val = get_register(r2);
1980 SetS390ConditionCode<int64_t>(r2_val, 0);
1981 set_register(r1, get_register(r2));
1982 break;
1983 }
1984 case LZDR: {
1985 int r1 = rreInst->R1Value();
1986 set_d_register_from_double(r1, 0.0);
1987 break;
1988 }
1989 case LTEBR: {
1990 RREInstruction* rreinst = reinterpret_cast<RREInstruction*>(instr);
1991 int r1 = rreinst->R1Value();
1992 int r2 = rreinst->R2Value();
1993 int64_t r2_val = get_d_register(r2);
1994 float fr2_val = get_float32_from_d_register(r2);
1995 SetS390ConditionCode<float>(fr2_val, 0.0);
1996 set_d_register(r1, r2_val);
1997 break;
1998 }
1999 case LTDBR: {
2000 RREInstruction* rreinst = reinterpret_cast<RREInstruction*>(instr);
2001 int r1 = rreinst->R1Value();
2002 int r2 = rreinst->R2Value();
2003 int64_t r2_val = get_d_register(r2);
2004 SetS390ConditionCode<double>(bit_cast<double, int64_t>(r2_val), 0.0);
2005 set_d_register(r1, r2_val);
2006 break;
2007 }
2008 case CGR: {
2009 // Compare (64)
2010 int64_t r1_val = get_register(rreInst->R1Value());
2011 int64_t r2_val = get_register(rreInst->R2Value());
2012 SetS390ConditionCode<int64_t>(r1_val, r2_val);
2013 break;
2014 }
2015 case CLGR: {
2016 // Compare Logical (64)
2017 uint64_t r1_val = static_cast<uint64_t>(get_register(rreInst->R1Value()));
2018 uint64_t r2_val = static_cast<uint64_t>(get_register(rreInst->R2Value()));
2019 SetS390ConditionCode<uint64_t>(r1_val, r2_val);
2020 break;
2021 }
2022 case LH: {
2023 // Load Halfword
2024 RXInstruction* rxinst = reinterpret_cast<RXInstruction*>(instr);
2025 int r1 = rxinst->R1Value();
2026 int x2 = rxinst->X2Value();
2027 int b2 = rxinst->B2Value();
2028
2029 int64_t x2_val = (x2 == 0) ? 0 : get_register(x2);
2030 int64_t b2_val = (b2 == 0) ? 0 : get_register(b2);
2031 intptr_t d2_val = rxinst->D2Value();
2032 intptr_t mem_addr = x2_val + b2_val + d2_val;
2033
2034 int32_t result = static_cast<int32_t>(ReadH(mem_addr, instr));
2035 set_low_register(r1, result);
2036 break;
2037 }
2038 case LHI: {
2039 RIInstruction* riinst = reinterpret_cast<RIInstruction*>(instr);
2040 int r1 = riinst->R1Value();
2041 int i = riinst->I2Value();
2042 set_low_register(r1, i);
2043 break;
2044 }
2045 case LGHI: {
2046 RIInstruction* riinst = reinterpret_cast<RIInstruction*>(instr);
2047 int r1 = riinst->R1Value();
2048 int64_t i = riinst->I2Value();
2049 set_register(r1, i);
2050 break;
2051 }
2052 case CHI: {
2053 RIInstruction* riinst = reinterpret_cast<RIInstruction*>(instr);
2054 int r1 = riinst->R1Value();
2055 int16_t i = riinst->I2Value();
2056 int32_t r1_val = get_low_register<int32_t>(r1);
2057 SetS390ConditionCode<int32_t>(r1_val, i);
2058 break;
2059 }
2060 case CGHI: {
2061 RIInstruction* riinst = reinterpret_cast<RIInstruction*>(instr);
2062 int r1 = riinst->R1Value();
2063 int64_t i = static_cast<int64_t>(riinst->I2Value());
2064 int64_t r1_val = get_register(r1);
2065 SetS390ConditionCode<int64_t>(r1_val, i);
2066 break;
2067 }
2068 case BRAS: {
2069 // Branch Relative and Save
2070 RILInstruction* rilInstr = reinterpret_cast<RILInstruction*>(instr);
2071 int r1 = rilInstr->R1Value();
2072 intptr_t d2 = rilInstr->I2Value();
2073 intptr_t pc = get_pc();
2074 // Set PC of next instruction to register
2075 set_register(r1, pc + sizeof(FourByteInstr));
2076 // Update PC to branch target
2077 set_pc(pc + d2 * 2);
2078 break;
2079 }
2080 case BRC: {
2081 // Branch Relative on Condition
2082 RIInstruction* riinst = reinterpret_cast<RIInstruction*>(instr);
2083 int m1 = riinst->M1Value();
2084 if (TestConditionCode((Condition)m1)) {
2085 intptr_t offset = riinst->I2Value() * 2;
2086 set_pc(get_pc() + offset);
2087 }
2088 break;
2089 }
2090 case BRCT:
2091 case BRCTG: {
2092 // Branch On Count (32/64).
2093 RIInstruction* riinst = reinterpret_cast<RIInstruction*>(instr);
2094 int r1 = riinst->R1Value();
2095 int64_t value =
2096 (op == BRCT) ? get_low_register<int32_t>(r1) : get_register(r1);
2097 if (BRCT == op)
2098 set_low_register(r1, --value);
2099 else
2100 set_register(r1, --value);
2101 // Branch if value != 0
2102 if (value != 0) {
2103 intptr_t offset = riinst->I2Value() * 2;
2104 set_pc(get_pc() + offset);
2105 }
2106 break;
2107 }
2108 case BXH: {
2109 RSInstruction* rsinst = reinterpret_cast<RSInstruction*>(instr);
2110 int r1 = rsinst->R1Value();
2111 int r3 = rsinst->R3Value();
2112 int b2 = rsinst->B2Value();
2113 int d2 = rsinst->D2Value();
2114
2115 // r1_val is the first operand, r3_val is the increment
2116 int32_t r1_val = r1 == 0 ? 0 : get_register(r1);
2117 int32_t r3_val = r2 == 0 ? 0 : get_register(r3);
2118 intptr_t b2_val = b2 == 0 ? 0 : get_register(b2);
2119 intptr_t branch_address = b2_val + d2;
2120 // increment r1_val
2121 r1_val += r3_val;
2122
2123 // if the increment is even, then it designates a pair of registers
2124 // and the contents of the even and odd registers of the pair are used as
2125 // the increment and compare value respectively. If the increment is odd,
2126 // the increment itself is used as both the increment and compare value
2127 int32_t compare_val = r3 % 2 == 0 ? get_register(r3 + 1) : r3_val;
2128 if (r1_val > compare_val) {
2129 // branch to address if r1_val is greater than compare value
2130 set_pc(branch_address);
2131 }
2132
2133 // update contents of register in r1 with the new incremented value
2134 set_register(r1, r1_val);
2135 break;
2136 }
2137 case IIHH:
2138 case IIHL:
2139 case IILH:
2140 case IILL: {
2141 UNIMPLEMENTED();
2142 break;
2143 }
2144 case STM:
2145 case LM: {
2146 // Store Multiple 32-bits.
2147 RSInstruction* rsinstr = reinterpret_cast<RSInstruction*>(instr);
2148 int r1 = rsinstr->R1Value();
2149 int r3 = rsinstr->R3Value();
2150 int rb = rsinstr->B2Value();
2151 int offset = rsinstr->D2Value();
2152
2153 // Regs roll around if r3 is less than r1.
2154 // Artifically increase r3 by 16 so we can calculate
2155 // the number of regs stored properly.
2156 if (r3 < r1) r3 += 16;
2157
2158 int32_t rb_val = (rb == 0) ? 0 : get_low_register<int32_t>(rb);
2159
2160 // Store each register in ascending order.
2161 for (int i = 0; i <= r3 - r1; i++) {
2162 if (op == STM) {
2163 int32_t value = get_low_register<int32_t>((r1 + i) % 16);
2164 WriteW(rb_val + offset + 4 * i, value, instr);
2165 } else if (op == LM) {
2166 int32_t value = ReadW(rb_val + offset + 4 * i, instr);
2167 set_low_register((r1 + i) % 16, value);
2168 }
2169 }
2170 break;
2171 }
2172 case SLL:
2173 case SRL: {
2174 RSInstruction* rsInstr = reinterpret_cast<RSInstruction*>(instr);
2175 int r1 = rsInstr->R1Value();
2176 int b2 = rsInstr->B2Value();
2177 intptr_t d2 = rsInstr->D2Value();
2178 // only takes rightmost 6bits
2179 int64_t b2_val = b2 == 0 ? 0 : get_register(b2);
2180 int shiftBits = (b2_val + d2) & 0x3F;
2181 uint32_t r1_val = get_low_register<uint32_t>(r1);
2182 uint32_t alu_out = 0;
2183 if (SLL == op) {
2184 alu_out = r1_val << shiftBits;
2185 } else if (SRL == op) {
2186 alu_out = r1_val >> shiftBits;
2187 } else {
2188 UNREACHABLE();
2189 }
2190 set_low_register(r1, alu_out);
2191 break;
2192 }
2193 case SLDL: {
2194 RSInstruction* rsInstr = reinterpret_cast<RSInstruction*>(instr);
2195 int r1 = rsInstr->R1Value();
2196 int b2 = rsInstr->B2Value();
2197 intptr_t d2 = rsInstr->D2Value();
2198 // only takes rightmost 6bits
2199 int64_t b2_val = b2 == 0 ? 0 : get_register(b2);
2200 int shiftBits = (b2_val + d2) & 0x3F;
2201
2202 DCHECK(r1 % 2 == 0);
2203 uint32_t r1_val = get_low_register<uint32_t>(r1);
2204 uint32_t r1_next_val = get_low_register<uint32_t>(r1 + 1);
2205 uint64_t alu_out = (static_cast<uint64_t>(r1_val) << 32) |
2206 (static_cast<uint64_t>(r1_next_val));
2207 alu_out <<= shiftBits;
2208 set_low_register(r1 + 1, static_cast<uint32_t>(alu_out));
2209 set_low_register(r1, static_cast<uint32_t>(alu_out >> 32));
2210 break;
2211 }
2212 case SLA:
2213 case SRA: {
2214 RSInstruction* rsInstr = reinterpret_cast<RSInstruction*>(instr);
2215 int r1 = rsInstr->R1Value();
2216 int b2 = rsInstr->B2Value();
2217 intptr_t d2 = rsInstr->D2Value();
2218 // only takes rightmost 6bits
2219 int64_t b2_val = b2 == 0 ? 0 : get_register(b2);
2220 int shiftBits = (b2_val + d2) & 0x3F;
2221 int32_t r1_val = get_low_register<int32_t>(r1);
2222 int32_t alu_out = 0;
2223 bool isOF = false;
2224 if (op == SLA) {
2225 isOF = CheckOverflowForShiftLeft(r1_val, shiftBits);
2226 alu_out = r1_val << shiftBits;
2227 } else if (op == SRA) {
2228 alu_out = r1_val >> shiftBits;
2229 }
2230 set_low_register(r1, alu_out);
2231 SetS390ConditionCode<int32_t>(alu_out, 0);
2232 SetS390OverflowCode(isOF);
2233 break;
2234 }
2235 case LLHR: {
2236 UNIMPLEMENTED();
2237 break;
2238 }
2239 case LLGHR: {
2240 UNIMPLEMENTED();
2241 break;
2242 }
2243 case L:
2244 case LA:
2245 case LD:
2246 case LE: {
2247 RXInstruction* rxinst = reinterpret_cast<RXInstruction*>(instr);
2248 int b2 = rxinst->B2Value();
2249 int x2 = rxinst->X2Value();
2250 int32_t r1 = rxinst->R1Value();
2251 int64_t b2_val = (b2 == 0) ? 0 : get_register(b2);
2252 int64_t x2_val = (x2 == 0) ? 0 : get_register(x2);
2253 intptr_t d2_val = rxinst->D2Value();
2254 intptr_t addr = b2_val + x2_val + d2_val;
2255 if (op == L) {
2256 int32_t mem_val = ReadW(addr, instr);
2257 set_low_register(r1, mem_val);
2258 } else if (op == LA) {
2259 set_register(r1, addr);
2260 } else if (op == LD) {
2261 int64_t dbl_val = *reinterpret_cast<int64_t*>(addr);
2262 set_d_register(r1, dbl_val);
2263 } else if (op == LE) {
2264 float float_val = *reinterpret_cast<float*>(addr);
2265 set_d_register_from_float32(r1, float_val);
2266 }
2267 break;
2268 }
2269 case C:
2270 case CL: {
2271 RXInstruction* rxinst = reinterpret_cast<RXInstruction*>(instr);
2272 int b2 = rxinst->B2Value();
2273 int x2 = rxinst->X2Value();
2274 int32_t r1_val = get_low_register<int32_t>(rxinst->R1Value());
2275 int64_t b2_val = (b2 == 0) ? 0 : get_register(b2);
2276 int64_t x2_val = (x2 == 0) ? 0 : get_register(x2);
2277 intptr_t d2_val = rxinst->D2Value();
2278 intptr_t addr = b2_val + x2_val + d2_val;
2279 int32_t mem_val = ReadW(addr, instr);
2280 if (C == op)
2281 SetS390ConditionCode<int32_t>(r1_val, mem_val);
2282 else if (CL == op)
2283 SetS390ConditionCode<uint32_t>(r1_val, mem_val);
2284 break;
2285 }
2286 case CLI: {
2287 // Compare Immediate (Mem - Imm) (8)
2288 int b1 = siInstr->B1Value();
2289 int64_t b1_val = (b1 == 0) ? 0 : get_register(b1);
2290 intptr_t d1_val = siInstr->D1Value();
2291 intptr_t addr = b1_val + d1_val;
2292 uint8_t mem_val = ReadB(addr);
2293 uint8_t imm_val = siInstr->I2Value();
2294 SetS390ConditionCode<uint8_t>(mem_val, imm_val);
2295 break;
2296 }
2297 case TM: {
2298 // Test Under Mask (Mem - Imm) (8)
2299 int b1 = siInstr->B1Value();
2300 int64_t b1_val = (b1 == 0) ? 0 : get_register(b1);
2301 intptr_t d1_val = siInstr->D1Value();
2302 intptr_t addr = b1_val + d1_val;
2303 uint8_t mem_val = ReadB(addr);
2304 uint8_t imm_val = siInstr->I2Value();
2305 uint8_t selected_bits = mem_val & imm_val;
2306 // CC0: Selected bits are zero
2307 // CC1: Selected bits mixed zeros and ones
2308 // CC3: Selected bits all ones
2309 if (0 == selected_bits) {
2310 condition_reg_ = CC_EQ; // CC0
2311 } else if (selected_bits == imm_val) {
2312 condition_reg_ = 0x1; // CC3
2313 } else {
2314 condition_reg_ = 0x4; // CC1
2315 }
2316 break;
2317 }
2318 case ST:
2319 case STE:
2320 case STD: {
2321 RXInstruction* rxinst = reinterpret_cast<RXInstruction*>(instr);
2322 int b2 = rxinst->B2Value();
2323 int x2 = rxinst->X2Value();
2324 int32_t r1_val = get_low_register<int32_t>(rxinst->R1Value());
2325 int64_t b2_val = (b2 == 0) ? 0 : get_register(b2);
2326 int64_t x2_val = (x2 == 0) ? 0 : get_register(x2);
2327 intptr_t d2_val = rxinst->D2Value();
2328 intptr_t addr = b2_val + x2_val + d2_val;
2329 if (op == ST) {
2330 WriteW(addr, r1_val, instr);
2331 } else if (op == STD) {
2332 int64_t frs_val = get_d_register(rxinst->R1Value());
2333 WriteDW(addr, frs_val);
2334 } else if (op == STE) {
2335 int64_t frs_val = get_d_register(rxinst->R1Value()) >> 32;
2336 WriteW(addr, static_cast<int32_t>(frs_val), instr);
2337 }
2338 break;
2339 }
2340 case LTGFR:
2341 case LGFR: {
2342 // Load and Test Register (64 <- 32) (Sign Extends 32-bit val)
2343 // Load Register (64 <- 32) (Sign Extends 32-bit val)
2344 RREInstruction* rreInstr = reinterpret_cast<RREInstruction*>(instr);
2345 int r1 = rreInstr->R1Value();
2346 int r2 = rreInstr->R2Value();
2347 int32_t r2_val = get_low_register<int32_t>(r2);
2348 int64_t result = static_cast<int64_t>(r2_val);
2349 set_register(r1, result);
2350
2351 if (LTGFR == op) SetS390ConditionCode<int64_t>(result, 0);
2352 break;
2353 }
2354 case LNGR: {
2355 // Load Negative (64)
2356 int r1 = rreInst->R1Value();
2357 int r2 = rreInst->R2Value();
2358 int64_t r2_val = get_register(r2);
2359 r2_val = (r2_val >= 0) ? -r2_val : r2_val; // If pos, then negate it.
2360 set_register(r1, r2_val);
2361 condition_reg_ = (r2_val == 0) ? CC_EQ : CC_LT; // CC0 - result is zero
2362 // CC1 - result is negative
2363 break;
2364 }
2365 case TRAP4: {
2366 // whack the space of the caller allocated stack
2367 int64_t sp_addr = get_register(sp);
2368 for (int i = 0; i < kCalleeRegisterSaveAreaSize / kPointerSize; ++i) {
2369 // we dont want to whack the RA (r14)
2370 if (i != 14) (reinterpret_cast<intptr_t*>(sp_addr))[i] = 0xdeadbabe;
2371 }
2372 SoftwareInterrupt(instr);
2373 break;
2374 }
2375 case STC: {
2376 // Store Character/Byte
2377 RXInstruction* rxinst = reinterpret_cast<RXInstruction*>(instr);
2378 int b2 = rxinst->B2Value();
2379 int x2 = rxinst->X2Value();
2380 uint8_t r1_val = get_low_register<int32_t>(rxinst->R1Value());
2381 int64_t b2_val = (b2 == 0) ? 0 : get_register(b2);
2382 int64_t x2_val = (x2 == 0) ? 0 : get_register(x2);
2383 intptr_t d2_val = rxinst->D2Value();
2384 intptr_t mem_addr = b2_val + x2_val + d2_val;
2385 WriteB(mem_addr, r1_val);
2386 break;
2387 }
2388 case STH: {
2389 RXInstruction* rxinst = reinterpret_cast<RXInstruction*>(instr);
2390 int b2 = rxinst->B2Value();
2391 int x2 = rxinst->X2Value();
2392 int16_t r1_val = get_low_register<int32_t>(rxinst->R1Value());
2393 int64_t b2_val = (b2 == 0) ? 0 : get_register(b2);
2394 int64_t x2_val = (x2 == 0) ? 0 : get_register(x2);
2395 intptr_t d2_val = rxinst->D2Value();
2396 intptr_t mem_addr = b2_val + x2_val + d2_val;
2397 WriteH(mem_addr, r1_val, instr);
2398 break;
2399 }
2400#if V8_TARGET_ARCH_S390X
2401 case LCGR: {
2402 int r1 = rreInst->R1Value();
2403 int r2 = rreInst->R2Value();
2404 int64_t r2_val = get_register(r2);
2405 r2_val = ~r2_val;
2406 r2_val = r2_val + 1;
2407 set_register(r1, r2_val);
2408 SetS390ConditionCode<int64_t>(r2_val, 0);
2409 // if the input is INT_MIN, loading its compliment would be overflowing
2410 if (r2_val < 0 && (r2_val + 1) > 0) {
2411 SetS390OverflowCode(true);
2412 }
2413 break;
2414 }
2415#endif
2416 case SRDA: {
2417 RSInstruction* rsInstr = reinterpret_cast<RSInstruction*>(instr);
2418 int r1 = rsInstr->R1Value();
2419 DCHECK(r1 % 2 == 0); // must be a reg pair
2420 int b2 = rsInstr->B2Value();
2421 intptr_t d2 = rsInstr->D2Value();
2422 // only takes rightmost 6bits
2423 int64_t b2_val = b2 == 0 ? 0 : get_register(b2);
2424 int shiftBits = (b2_val + d2) & 0x3F;
2425 int64_t opnd1 = static_cast<int64_t>(get_low_register<int32_t>(r1)) << 32;
2426 int64_t opnd2 = static_cast<uint64_t>(get_low_register<uint32_t>(r1 + 1));
2427 int64_t r1_val = opnd1 + opnd2;
2428 int64_t alu_out = r1_val >> shiftBits;
2429 set_low_register(r1, alu_out >> 32);
2430 set_low_register(r1 + 1, alu_out & 0x00000000FFFFFFFF);
2431 SetS390ConditionCode<int32_t>(alu_out, 0);
2432 break;
2433 }
2434 case SRDL: {
2435 RSInstruction* rsInstr = reinterpret_cast<RSInstruction*>(instr);
2436 int r1 = rsInstr->R1Value();
2437 DCHECK(r1 % 2 == 0); // must be a reg pair
2438 int b2 = rsInstr->B2Value();
2439 intptr_t d2 = rsInstr->D2Value();
2440 // only takes rightmost 6bits
2441 int64_t b2_val = b2 == 0 ? 0 : get_register(b2);
2442 int shiftBits = (b2_val + d2) & 0x3F;
2443 uint64_t opnd1 = static_cast<uint64_t>(get_low_register<uint32_t>(r1))
2444 << 32;
2445 uint64_t opnd2 =
2446 static_cast<uint64_t>(get_low_register<uint32_t>(r1 + 1));
2447 uint64_t r1_val = opnd1 | opnd2;
2448 uint64_t alu_out = r1_val >> shiftBits;
2449 set_low_register(r1, alu_out >> 32);
2450 set_low_register(r1 + 1, alu_out & 0x00000000FFFFFFFF);
2451 SetS390ConditionCode<int32_t>(alu_out, 0);
2452 break;
2453 }
2454 default: { return DecodeFourByteArithmetic(instr); }
2455 }
2456 return true;
2457}
2458
2459bool Simulator::DecodeFourByteArithmetic64Bit(Instruction* instr) {
2460 Opcode op = instr->S390OpcodeValue();
2461
2462 RRFInstruction* rrfInst = reinterpret_cast<RRFInstruction*>(instr);
2463 RREInstruction* rreInst = reinterpret_cast<RREInstruction*>(instr);
2464
2465 switch (op) {
2466 case AGR:
2467 case SGR:
2468 case OGR:
2469 case NGR:
2470 case XGR: {
2471 int r1 = rreInst->R1Value();
2472 int r2 = rreInst->R2Value();
2473 int64_t r1_val = get_register(r1);
2474 int64_t r2_val = get_register(r2);
2475 bool isOF = false;
2476 switch (op) {
2477 case AGR:
2478 isOF = CheckOverflowForIntAdd(r1_val, r2_val, int64_t);
2479 r1_val += r2_val;
2480 SetS390ConditionCode<int64_t>(r1_val, 0);
2481 SetS390OverflowCode(isOF);
2482 break;
2483 case SGR:
2484 isOF = CheckOverflowForIntSub(r1_val, r2_val, int64_t);
2485 r1_val -= r2_val;
2486 SetS390ConditionCode<int64_t>(r1_val, 0);
2487 SetS390OverflowCode(isOF);
2488 break;
2489 case OGR:
2490 r1_val |= r2_val;
2491 SetS390BitWiseConditionCode<uint64_t>(r1_val);
2492 break;
2493 case NGR:
2494 r1_val &= r2_val;
2495 SetS390BitWiseConditionCode<uint64_t>(r1_val);
2496 break;
2497 case XGR:
2498 r1_val ^= r2_val;
2499 SetS390BitWiseConditionCode<uint64_t>(r1_val);
2500 break;
2501 default:
2502 UNREACHABLE();
2503 break;
2504 }
2505 set_register(r1, r1_val);
2506 break;
2507 }
2508 case AGFR: {
2509 // Add Register (64 <- 32) (Sign Extends 32-bit val)
2510 int r1 = rreInst->R1Value();
2511 int r2 = rreInst->R2Value();
2512 int64_t r1_val = get_register(r1);
2513 int64_t r2_val = static_cast<int64_t>(get_low_register<int32_t>(r2));
2514 bool isOF = CheckOverflowForIntAdd(r1_val, r2_val, int64_t);
2515 r1_val += r2_val;
2516 SetS390ConditionCode<int64_t>(r1_val, 0);
2517 SetS390OverflowCode(isOF);
2518 set_register(r1, r1_val);
2519 break;
2520 }
2521 case SGFR: {
2522 // Sub Reg (64 <- 32)
2523 int r1 = rreInst->R1Value();
2524 int r2 = rreInst->R2Value();
2525 int64_t r1_val = get_register(r1);
2526 int64_t r2_val = static_cast<int64_t>(get_low_register<int32_t>(r2));
2527 bool isOF = false;
2528 isOF = CheckOverflowForIntSub(r1_val, r2_val, int64_t);
2529 r1_val -= r2_val;
2530 SetS390ConditionCode<int64_t>(r1_val, 0);
2531 SetS390OverflowCode(isOF);
2532 set_register(r1, r1_val);
2533 break;
2534 }
2535 case AGRK:
2536 case SGRK:
2537 case NGRK:
2538 case OGRK:
2539 case XGRK: {
2540 // 64-bit Non-clobbering arithmetics / bitwise ops.
2541 int r1 = rrfInst->R1Value();
2542 int r2 = rrfInst->R2Value();
2543 int r3 = rrfInst->R3Value();
2544 int64_t r2_val = get_register(r2);
2545 int64_t r3_val = get_register(r3);
2546 if (AGRK == op) {
2547 bool isOF = CheckOverflowForIntAdd(r2_val, r3_val, int64_t);
2548 SetS390ConditionCode<int64_t>(r2_val + r3_val, 0);
2549 SetS390OverflowCode(isOF);
2550 set_register(r1, r2_val + r3_val);
2551 } else if (SGRK == op) {
2552 bool isOF = CheckOverflowForIntSub(r2_val, r3_val, int64_t);
2553 SetS390ConditionCode<int64_t>(r2_val - r3_val, 0);
2554 SetS390OverflowCode(isOF);
2555 set_register(r1, r2_val - r3_val);
2556 } else {
2557 // Assume bitwise operation here
2558 uint64_t bitwise_result = 0;
2559 if (NGRK == op) {
2560 bitwise_result = r2_val & r3_val;
2561 } else if (OGRK == op) {
2562 bitwise_result = r2_val | r3_val;
2563 } else if (XGRK == op) {
2564 bitwise_result = r2_val ^ r3_val;
2565 }
2566 SetS390BitWiseConditionCode<uint64_t>(bitwise_result);
2567 set_register(r1, bitwise_result);
2568 }
2569 break;
2570 }
2571 case ALGRK:
2572 case SLGRK: {
2573 // 64-bit Non-clobbering unsigned arithmetics
2574 int r1 = rrfInst->R1Value();
2575 int r2 = rrfInst->R2Value();
2576 int r3 = rrfInst->R3Value();
2577 uint64_t r2_val = get_register(r2);
2578 uint64_t r3_val = get_register(r3);
2579 if (ALGRK == op) {
2580 bool isOF = CheckOverflowForUIntAdd(r2_val, r3_val);
2581 SetS390ConditionCode<uint64_t>(r2_val + r3_val, 0);
2582 SetS390OverflowCode(isOF);
2583 set_register(r1, r2_val + r3_val);
2584 } else if (SLGRK == op) {
2585 bool isOF = CheckOverflowForUIntSub(r2_val, r3_val);
2586 SetS390ConditionCode<uint64_t>(r2_val - r3_val, 0);
2587 SetS390OverflowCode(isOF);
2588 set_register(r1, r2_val - r3_val);
2589 }
2590 }
2591 case AGHI:
2592 case MGHI: {
2593 RIInstruction* riinst = reinterpret_cast<RIInstruction*>(instr);
2594 int32_t r1 = riinst->R1Value();
2595 int64_t i = static_cast<int64_t>(riinst->I2Value());
2596 int64_t r1_val = get_register(r1);
2597 bool isOF = false;
2598 switch (op) {
2599 case AGHI:
2600 isOF = CheckOverflowForIntAdd(r1_val, i, int64_t);
2601 r1_val += i;
2602 break;
2603 case MGHI:
2604 isOF = CheckOverflowForMul(r1_val, i);
2605 r1_val *= i;
2606 break; // no overflow indication is given
2607 default:
2608 break;
2609 }
2610 set_register(r1, r1_val);
2611 SetS390ConditionCode<int32_t>(r1_val, 0);
2612 SetS390OverflowCode(isOF);
2613 break;
2614 }
2615 default:
2616 UNREACHABLE();
2617 }
2618 return true;
2619}
2620
2621/**
2622 * Decodes and simulates four byte arithmetic instructions
2623 */
2624bool Simulator::DecodeFourByteArithmetic(Instruction* instr) {
2625 Opcode op = instr->S390OpcodeValue();
2626
2627 // Pre-cast instruction to various types
2628 RRFInstruction* rrfInst = reinterpret_cast<RRFInstruction*>(instr);
2629
2630 switch (op) {
2631 case AGR:
2632 case SGR:
2633 case OGR:
2634 case NGR:
2635 case XGR:
2636 case AGFR:
2637 case SGFR: {
2638 DecodeFourByteArithmetic64Bit(instr);
2639 break;
2640 }
2641 case ARK:
2642 case SRK:
2643 case NRK:
2644 case ORK:
2645 case XRK: {
2646 // 32-bit Non-clobbering arithmetics / bitwise ops
2647 int r1 = rrfInst->R1Value();
2648 int r2 = rrfInst->R2Value();
2649 int r3 = rrfInst->R3Value();
2650 int32_t r2_val = get_low_register<int32_t>(r2);
2651 int32_t r3_val = get_low_register<int32_t>(r3);
2652 if (ARK == op) {
2653 bool isOF = CheckOverflowForIntAdd(r2_val, r3_val, int32_t);
2654 SetS390ConditionCode<int32_t>(r2_val + r3_val, 0);
2655 SetS390OverflowCode(isOF);
2656 set_low_register(r1, r2_val + r3_val);
2657 } else if (SRK == op) {
2658 bool isOF = CheckOverflowForIntSub(r2_val, r3_val, int32_t);
2659 SetS390ConditionCode<int32_t>(r2_val - r3_val, 0);
2660 SetS390OverflowCode(isOF);
2661 set_low_register(r1, r2_val - r3_val);
2662 } else {
2663 // Assume bitwise operation here
2664 uint32_t bitwise_result = 0;
2665 if (NRK == op) {
2666 bitwise_result = r2_val & r3_val;
2667 } else if (ORK == op) {
2668 bitwise_result = r2_val | r3_val;
2669 } else if (XRK == op) {
2670 bitwise_result = r2_val ^ r3_val;
2671 }
2672 SetS390BitWiseConditionCode<uint32_t>(bitwise_result);
2673 set_low_register(r1, bitwise_result);
2674 }
2675 break;
2676 }
2677 case ALRK:
2678 case SLRK: {
2679 // 32-bit Non-clobbering unsigned arithmetics
2680 int r1 = rrfInst->R1Value();
2681 int r2 = rrfInst->R2Value();
2682 int r3 = rrfInst->R3Value();
2683 uint32_t r2_val = get_low_register<uint32_t>(r2);
2684 uint32_t r3_val = get_low_register<uint32_t>(r3);
2685 if (ALRK == op) {
2686 bool isOF = CheckOverflowForUIntAdd(r2_val, r3_val);
2687 SetS390ConditionCode<uint32_t>(r2_val + r3_val, 0);
2688 SetS390OverflowCode(isOF);
2689 set_low_register(r1, r2_val + r3_val);
2690 } else if (SLRK == op) {
2691 bool isOF = CheckOverflowForUIntSub(r2_val, r3_val);
2692 SetS390ConditionCode<uint32_t>(r2_val - r3_val, 0);
2693 SetS390OverflowCode(isOF);
2694 set_low_register(r1, r2_val - r3_val);
2695 }
2696 break;
2697 }
2698 case AGRK:
2699 case SGRK:
2700 case NGRK:
2701 case OGRK:
2702 case XGRK: {
2703 DecodeFourByteArithmetic64Bit(instr);
2704 break;
2705 }
2706 case ALGRK:
2707 case SLGRK: {
2708 DecodeFourByteArithmetic64Bit(instr);
2709 break;
2710 }
2711 case AHI:
2712 case MHI: {
2713 RIInstruction* riinst = reinterpret_cast<RIInstruction*>(instr);
2714 int32_t r1 = riinst->R1Value();
2715 int32_t i = riinst->I2Value();
2716 int32_t r1_val = get_low_register<int32_t>(r1);
2717 bool isOF = false;
2718 switch (op) {
2719 case AHI:
2720 isOF = CheckOverflowForIntAdd(r1_val, i, int32_t);
2721 r1_val += i;
2722 break;
2723 case MHI:
2724 isOF = CheckOverflowForMul(r1_val, i);
2725 r1_val *= i;
2726 break; // no overflow indication is given
2727 default:
2728 break;
2729 }
2730 set_low_register(r1, r1_val);
2731 SetS390ConditionCode<int32_t>(r1_val, 0);
2732 SetS390OverflowCode(isOF);
2733 break;
2734 }
2735 case AGHI:
2736 case MGHI: {
2737 DecodeFourByteArithmetic64Bit(instr);
2738 break;
2739 }
2740 case MLR: {
2741 RREInstruction* rreinst = reinterpret_cast<RREInstruction*>(instr);
2742 int r1 = rreinst->R1Value();
2743 int r2 = rreinst->R2Value();
2744 DCHECK(r1 % 2 == 0);
2745
2746 uint32_t r1_val = get_low_register<uint32_t>(r1 + 1);
2747 uint32_t r2_val = get_low_register<uint32_t>(r2);
2748 uint64_t product =
2749 static_cast<uint64_t>(r1_val) * static_cast<uint64_t>(r2_val);
2750 int32_t high_bits = product >> 32;
2751 int32_t low_bits = product & 0x00000000FFFFFFFF;
2752 set_low_register(r1, high_bits);
2753 set_low_register(r1 + 1, low_bits);
2754 break;
2755 }
2756 case DLGR: {
2757#ifdef V8_TARGET_ARCH_S390X
2758 RREInstruction* rreinst = reinterpret_cast<RREInstruction*>(instr);
2759 int r1 = rreinst->R1Value();
2760 int r2 = rreinst->R2Value();
2761 uint64_t r1_val = get_register(r1);
2762 uint64_t r2_val = get_register(r2);
2763 DCHECK(r1 % 2 == 0);
2764 unsigned __int128 dividend = static_cast<unsigned __int128>(r1_val) << 64;
2765 dividend += get_register(r1 + 1);
2766 uint64_t remainder = dividend % r2_val;
2767 uint64_t quotient = dividend / r2_val;
2768 r1_val = remainder;
2769 set_register(r1, remainder);
2770 set_register(r1 + 1, quotient);
2771#else
2772 UNREACHABLE();
2773#endif
2774 break;
2775 }
2776 case DLR: {
2777 RREInstruction* rreinst = reinterpret_cast<RREInstruction*>(instr);
2778 int r1 = rreinst->R1Value();
2779 int r2 = rreinst->R2Value();
2780 uint32_t r1_val = get_low_register<uint32_t>(r1);
2781 uint32_t r2_val = get_low_register<uint32_t>(r2);
2782 DCHECK(r1 % 2 == 0);
2783 uint64_t dividend = static_cast<uint64_t>(r1_val) << 32;
2784 dividend += get_low_register<uint32_t>(r1 + 1);
2785 uint32_t remainder = dividend % r2_val;
2786 uint32_t quotient = dividend / r2_val;
2787 r1_val = remainder;
2788 set_low_register(r1, remainder);
2789 set_low_register(r1 + 1, quotient);
2790 break;
2791 }
2792 case A:
2793 case S:
2794 case M:
2795 case D:
2796 case O:
2797 case N:
2798 case X: {
2799 // 32-bit Reg-Mem instructions
2800 RXInstruction* rxinst = reinterpret_cast<RXInstruction*>(instr);
2801 int b2 = rxinst->B2Value();
2802 int x2 = rxinst->X2Value();
2803 int32_t r1_val = get_low_register<int32_t>(rxinst->R1Value());
2804 int64_t b2_val = (b2 == 0) ? 0 : get_register(b2);
2805 int64_t x2_val = (x2 == 0) ? 0 : get_register(x2);
2806 intptr_t d2_val = rxinst->D2Value();
2807 int32_t mem_val = ReadW(b2_val + x2_val + d2_val, instr);
2808 int32_t alu_out = 0;
2809 bool isOF = false;
2810 switch (op) {
2811 case A:
2812 isOF = CheckOverflowForIntAdd(r1_val, mem_val, int32_t);
2813 alu_out = r1_val + mem_val;
2814 SetS390ConditionCode<int32_t>(alu_out, 0);
2815 SetS390OverflowCode(isOF);
2816 break;
2817 case S:
2818 isOF = CheckOverflowForIntSub(r1_val, mem_val, int32_t);
2819 alu_out = r1_val - mem_val;
2820 SetS390ConditionCode<int32_t>(alu_out, 0);
2821 SetS390OverflowCode(isOF);
2822 break;
2823 case M:
2824 case D:
2825 UNIMPLEMENTED();
2826 break;
2827 case O:
2828 alu_out = r1_val | mem_val;
2829 SetS390BitWiseConditionCode<uint32_t>(alu_out);
2830 break;
2831 case N:
2832 alu_out = r1_val & mem_val;
2833 SetS390BitWiseConditionCode<uint32_t>(alu_out);
2834 break;
2835 case X:
2836 alu_out = r1_val ^ mem_val;
2837 SetS390BitWiseConditionCode<uint32_t>(alu_out);
2838 break;
2839 default:
2840 UNREACHABLE();
2841 break;
2842 }
2843 set_low_register(r1, alu_out);
2844 break;
2845 }
2846 case OILL:
2847 case OIHL: {
2848 RIInstruction* riInst = reinterpret_cast<RIInstruction*>(instr);
2849 int r1 = riInst->R1Value();
2850 int i = riInst->I2Value();
2851 int32_t r1_val = get_low_register<int32_t>(r1);
2852 if (OILL == op) {
2853 // CC is set based on the 16 bits that are AND'd
2854 SetS390BitWiseConditionCode<uint16_t>(r1_val | i);
2855 } else if (OILH == op) {
2856 // CC is set based on the 16 bits that are AND'd
2857 SetS390BitWiseConditionCode<uint16_t>((r1_val >> 16) | i);
2858 i = i << 16;
2859 } else {
2860 UNIMPLEMENTED();
2861 }
2862 set_low_register(r1, r1_val | i);
2863 break;
2864 }
2865 case NILL:
2866 case NILH: {
2867 RIInstruction* riInst = reinterpret_cast<RIInstruction*>(instr);
2868 int r1 = riInst->R1Value();
2869 int i = riInst->I2Value();
2870 int32_t r1_val = get_low_register<int32_t>(r1);
2871 if (NILL == op) {
2872 // CC is set based on the 16 bits that are AND'd
2873 SetS390BitWiseConditionCode<uint16_t>(r1_val & i);
2874 i |= 0xFFFF0000;
2875 } else if (NILH == op) {
2876 // CC is set based on the 16 bits that are AND'd
2877 SetS390BitWiseConditionCode<uint16_t>((r1_val >> 16) & i);
2878 i = (i << 16) | 0x0000FFFF;
2879 } else {
2880 UNIMPLEMENTED();
2881 }
2882 set_low_register(r1, r1_val & i);
2883 break;
2884 }
2885 case AH:
2886 case SH:
2887 case MH: {
2888 RXInstruction* rxinst = reinterpret_cast<RXInstruction*>(instr);
2889 int b2 = rxinst->B2Value();
2890 int x2 = rxinst->X2Value();
2891 int32_t r1_val = get_low_register<int32_t>(rxinst->R1Value());
2892 int64_t b2_val = (b2 == 0) ? 0 : get_register(b2);
2893 int64_t x2_val = (x2 == 0) ? 0 : get_register(x2);
2894 intptr_t d2_val = rxinst->D2Value();
2895 intptr_t addr = b2_val + x2_val + d2_val;
2896 int32_t mem_val = static_cast<int32_t>(ReadH(addr, instr));
2897 int32_t alu_out = 0;
2898 bool isOF = false;
2899 if (AH == op) {
2900 isOF = CheckOverflowForIntAdd(r1_val, mem_val, int32_t);
2901 alu_out = r1_val + mem_val;
2902 } else if (SH == op) {
2903 isOF = CheckOverflowForIntSub(r1_val, mem_val, int32_t);
2904 alu_out = r1_val - mem_val;
2905 } else if (MH == op) {
2906 alu_out = r1_val * mem_val;
2907 } else {
2908 UNREACHABLE();
2909 }
2910 set_low_register(r1, alu_out);
2911 if (MH != op) { // MH does not change condition code
2912 SetS390ConditionCode<int32_t>(alu_out, 0);
2913 SetS390OverflowCode(isOF);
2914 }
2915 break;
2916 }
2917 case DSGR: {
2918 RREInstruction* rreInst = reinterpret_cast<RREInstruction*>(instr);
2919 int r1 = rreInst->R1Value();
2920 int r2 = rreInst->R2Value();
2921
2922 DCHECK(r1 % 2 == 0);
2923
2924 int64_t dividend = get_register(r1 + 1);
2925 int64_t divisor = get_register(r2);
2926 set_register(r1, dividend % divisor);
2927 set_register(r1 + 1, dividend / divisor);
2928
2929 break;
2930 }
2931 case FLOGR: {
2932 RREInstruction* rreInst = reinterpret_cast<RREInstruction*>(instr);
2933 int r1 = rreInst->R1Value();
2934 int r2 = rreInst->R2Value();
2935
2936 DCHECK(r1 % 2 == 0);
2937
2938 int64_t r2_val = get_register(r2);
2939
2940 int i = 0;
2941 for (; i < 64; i++) {
2942 if (r2_val < 0) break;
2943 r2_val <<= 1;
2944 }
2945
2946 r2_val = get_register(r2);
2947
2948 int64_t mask = ~(1 << (63 - i));
2949 set_register(r1, i);
2950 set_register(r1 + 1, r2_val & mask);
2951
2952 break;
2953 }
2954 case MSR:
2955 case MSGR: { // they do not set overflow code
2956 RREInstruction* rreInst = reinterpret_cast<RREInstruction*>(instr);
2957 int r1 = rreInst->R1Value();
2958 int r2 = rreInst->R2Value();
2959 if (op == MSR) {
2960 int32_t r1_val = get_low_register<int32_t>(r1);
2961 int32_t r2_val = get_low_register<int32_t>(r2);
2962 set_low_register(r1, r1_val * r2_val);
2963 } else if (op == MSGR) {
2964 int64_t r1_val = get_register(r1);
2965 int64_t r2_val = get_register(r2);
2966 set_register(r1, r1_val * r2_val);
2967 } else {
2968 UNREACHABLE();
2969 }
2970 break;
2971 }
2972 case MS: {
2973 RXInstruction* rxinst = reinterpret_cast<RXInstruction*>(instr);
2974 int r1 = rxinst->R1Value();
2975 int b2 = rxinst->B2Value();
2976 int x2 = rxinst->X2Value();
2977 int64_t x2_val = (x2 == 0) ? 0 : get_register(x2);
2978 int64_t b2_val = (b2 == 0) ? 0 : get_register(b2);
2979 intptr_t d2_val = rxinst->D2Value();
2980 int32_t mem_val = ReadW(b2_val + x2_val + d2_val, instr);
2981 int32_t r1_val = get_low_register<int32_t>(r1);
2982 set_low_register(r1, r1_val * mem_val);
2983 break;
2984 }
2985 case LGBR:
2986 case LBR: {
2987 RREInstruction* rrinst = reinterpret_cast<RREInstruction*>(instr);
2988 int r1 = rrinst->R1Value();
2989 int r2 = rrinst->R2Value();
2990#ifdef V8_TARGET_ARCH_S390X
2991 int64_t r2_val = get_low_register<int64_t>(r2);
2992 r2_val <<= 56;
2993 r2_val >>= 56;
2994 set_register(r1, r2_val);
2995#else
2996 int32_t r2_val = get_low_register<int32_t>(r2);
2997 r2_val <<= 24;
2998 r2_val >>= 24;
2999 set_low_register(r1, r2_val);
3000#endif
3001 break;
3002 }
3003 case LGHR:
3004 case LHR: {
3005 RREInstruction* rrinst = reinterpret_cast<RREInstruction*>(instr);
3006 int r1 = rrinst->R1Value();
3007 int r2 = rrinst->R2Value();
3008#ifdef V8_TARGET_ARCH_S390X
3009 int64_t r2_val = get_low_register<int64_t>(r2);
3010 r2_val <<= 48;
3011 r2_val >>= 48;
3012 set_register(r1, r2_val);
3013#else
3014 int32_t r2_val = get_low_register<int32_t>(r2);
3015 r2_val <<= 16;
3016 r2_val >>= 16;
3017 set_low_register(r1, r2_val);
3018#endif
3019 break;
3020 }
3021 case ALCR: {
3022 RREInstruction* rrinst = reinterpret_cast<RREInstruction*>(instr);
3023 int r1 = rrinst->R1Value();
3024 int r2 = rrinst->R2Value();
3025 uint32_t r1_val = get_low_register<uint32_t>(r1);
3026 uint32_t r2_val = get_low_register<uint32_t>(r2);
3027 uint32_t alu_out = 0;
3028 bool isOF = false;
3029
3030 alu_out = r1_val + r2_val;
3031 bool isOF_original = CheckOverflowForUIntAdd(r1_val, r2_val);
3032 if (TestConditionCode((Condition)2) || TestConditionCode((Condition)3)) {
3033 alu_out = alu_out + 1;
3034 isOF = isOF_original || CheckOverflowForUIntAdd(alu_out, 1);
3035 } else {
3036 isOF = isOF_original;
3037 }
3038 set_low_register(r1, alu_out);
3039 SetS390ConditionCodeCarry<uint32_t>(alu_out, isOF);
3040 break;
3041 }
3042 case SLBR: {
3043 RREInstruction* rrinst = reinterpret_cast<RREInstruction*>(instr);
3044 int r1 = rrinst->R1Value();
3045 int r2 = rrinst->R2Value();
3046 uint32_t r1_val = get_low_register<uint32_t>(r1);
3047 uint32_t r2_val = get_low_register<uint32_t>(r2);
3048 uint32_t alu_out = 0;
3049 bool isOF = false;
3050
3051 alu_out = r1_val - r2_val;
3052 bool isOF_original = CheckOverflowForUIntSub(r1_val, r2_val);
3053 if (TestConditionCode((Condition)2) || TestConditionCode((Condition)3)) {
3054 alu_out = alu_out - 1;
3055 isOF = isOF_original || CheckOverflowForUIntSub(alu_out, 1);
3056 } else {
3057 isOF = isOF_original;
3058 }
3059 set_low_register(r1, alu_out);
3060 SetS390ConditionCodeCarry<uint32_t>(alu_out, isOF);
3061 break;
3062 }
3063 default: { return DecodeFourByteFloatingPoint(instr); }
3064 }
3065 return true;
3066}
3067
3068void Simulator::DecodeFourByteFloatingPointIntConversion(Instruction* instr) {
3069 Opcode op = instr->S390OpcodeValue();
3070 switch (op) {
3071 case CDLFBR:
3072 case CDLGBR:
3073 case CELGBR:
3074 case CLFDBR:
3075 case CLGDBR:
3076 case CELFBR:
3077 case CLGEBR:
3078 case CLFEBR: {
3079 RREInstruction* rreInstr = reinterpret_cast<RREInstruction*>(instr);
3080 int r1 = rreInstr->R1Value();
3081 int r2 = rreInstr->R2Value();
3082 if (op == CDLFBR) {
3083 uint32_t r2_val = get_low_register<uint32_t>(r2);
3084 double r1_val = static_cast<double>(r2_val);
3085 set_d_register_from_double(r1, r1_val);
3086 } else if (op == CELFBR) {
3087 uint32_t r2_val = get_low_register<uint32_t>(r2);
3088 float r1_val = static_cast<float>(r2_val);
3089 set_d_register_from_float32(r1, r1_val);
3090 } else if (op == CDLGBR) {
3091 uint64_t r2_val = get_register(r2);
3092 double r1_val = static_cast<double>(r2_val);
3093 set_d_register_from_double(r1, r1_val);
3094 } else if (op == CELGBR) {
3095 uint64_t r2_val = get_register(r2);
3096 float r1_val = static_cast<float>(r2_val);
3097 set_d_register_from_float32(r1, r1_val);
3098 } else if (op == CLFDBR) {
3099 double r2_val = get_double_from_d_register(r2);
3100 uint32_t r1_val = static_cast<uint32_t>(r2_val);
3101 set_low_register(r1, r1_val);
3102 SetS390ConvertConditionCode<double>(r2_val, r1_val, UINT32_MAX);
3103 } else if (op == CLFEBR) {
3104 float r2_val = get_float32_from_d_register(r2);
3105 uint32_t r1_val = static_cast<uint32_t>(r2_val);
3106 set_low_register(r1, r1_val);
3107 SetS390ConvertConditionCode<double>(r2_val, r1_val, UINT32_MAX);
3108 } else if (op == CLGDBR) {
3109 double r2_val = get_double_from_d_register(r2);
3110 uint64_t r1_val = static_cast<uint64_t>(r2_val);
3111 set_register(r1, r1_val);
3112 SetS390ConvertConditionCode<double>(r2_val, r1_val, UINT64_MAX);
3113 } else if (op == CLGEBR) {
3114 float r2_val = get_float32_from_d_register(r2);
3115 uint64_t r1_val = static_cast<uint64_t>(r2_val);
3116 set_register(r1, r1_val);
3117 SetS390ConvertConditionCode<double>(r2_val, r1_val, UINT64_MAX);
3118 }
3119 break;
3120 }
3121 default:
3122 UNREACHABLE();
3123 }
3124}
3125
3126void Simulator::DecodeFourByteFloatingPointRound(Instruction* instr) {
3127 Opcode op = instr->S390OpcodeValue();
3128 RREInstruction* rreInstr = reinterpret_cast<RREInstruction*>(instr);
3129 int r1 = rreInstr->R1Value();
3130 int r2 = rreInstr->R2Value();
3131 double r2_val = get_double_from_d_register(r2);
3132 float r2_fval = get_float32_from_d_register(r2);
3133
3134 switch (op) {
3135 case CFDBR: {
3136 int mask_val = rreInstr->M3Value();
3137 int32_t r1_val = 0;
3138
3139 SetS390RoundConditionCode(r2_val, INT32_MAX, INT32_MIN);
3140
3141 switch (mask_val) {
3142 case CURRENT_ROUNDING_MODE:
3143 case ROUND_TO_PREPARE_FOR_SHORTER_PRECISION: {
3144 r1_val = static_cast<int32_t>(r2_val);
3145 break;
3146 }
3147 case ROUND_TO_NEAREST_WITH_TIES_AWAY_FROM_0: {
3148 double ceil_val = std::ceil(r2_val);
3149 double floor_val = std::floor(r2_val);
3150 double sub_val1 = std::fabs(r2_val - floor_val);
3151 double sub_val2 = std::fabs(r2_val - ceil_val);
3152 if (sub_val1 > sub_val2) {
3153 r1_val = static_cast<int32_t>(ceil_val);
3154 } else if (sub_val1 < sub_val2) {
3155 r1_val = static_cast<int32_t>(floor_val);
3156 } else { // round away from zero:
3157 if (r2_val > 0.0) {
3158 r1_val = static_cast<int32_t>(ceil_val);
3159 } else {
3160 r1_val = static_cast<int32_t>(floor_val);
3161 }
3162 }
3163 break;
3164 }
3165 case ROUND_TO_NEAREST_WITH_TIES_TO_EVEN: {
3166 double ceil_val = std::ceil(r2_val);
3167 double floor_val = std::floor(r2_val);
3168 double sub_val1 = std::fabs(r2_val - floor_val);
3169 double sub_val2 = std::fabs(r2_val - ceil_val);
3170 if (sub_val1 > sub_val2) {
3171 r1_val = static_cast<int32_t>(ceil_val);
3172 } else if (sub_val1 < sub_val2) {
3173 r1_val = static_cast<int32_t>(floor_val);
3174 } else { // check which one is even:
3175 int32_t c_v = static_cast<int32_t>(ceil_val);
3176 int32_t f_v = static_cast<int32_t>(floor_val);
3177 if (f_v % 2 == 0)
3178 r1_val = f_v;
3179 else
3180 r1_val = c_v;
3181 }
3182 break;
3183 }
3184 case ROUND_TOWARD_0: {
3185 // check for overflow, cast r2_val to 64bit integer
3186 // then check value within the range of INT_MIN and INT_MAX
3187 // and set condition code accordingly
3188 int64_t temp = static_cast<int64_t>(r2_val);
3189 if (temp < INT_MIN || temp > INT_MAX) {
3190 condition_reg_ = CC_OF;
3191 }
3192 r1_val = static_cast<int32_t>(r2_val);
3193 break;
3194 }
3195 case ROUND_TOWARD_PLUS_INFINITE: {
3196 r1_val = static_cast<int32_t>(std::ceil(r2_val));
3197 break;
3198 }
3199 case ROUND_TOWARD_MINUS_INFINITE: {
3200 // check for overflow, cast r2_val to 64bit integer
3201 // then check value within the range of INT_MIN and INT_MAX
3202 // and set condition code accordingly
3203 int64_t temp = static_cast<int64_t>(std::floor(r2_val));
3204 if (temp < INT_MIN || temp > INT_MAX) {
3205 condition_reg_ = CC_OF;
3206 }
3207 r1_val = static_cast<int32_t>(std::floor(r2_val));
3208 break;
3209 }
3210 default:
3211 UNREACHABLE();
3212 }
3213 set_low_register(r1, r1_val);
3214 break;
3215 }
3216 case CGDBR: {
3217 int mask_val = rreInstr->M3Value();
3218 int64_t r1_val = 0;
3219
3220 SetS390RoundConditionCode(r2_val, INT64_MAX, INT64_MIN);
3221
3222 switch (mask_val) {
3223 case CURRENT_ROUNDING_MODE:
3224 case ROUND_TO_NEAREST_WITH_TIES_AWAY_FROM_0:
3225 case ROUND_TO_PREPARE_FOR_SHORTER_PRECISION: {
3226 UNIMPLEMENTED();
3227 break;
3228 }
3229 case ROUND_TO_NEAREST_WITH_TIES_TO_EVEN: {
3230 double ceil_val = std::ceil(r2_val);
3231 double floor_val = std::floor(r2_val);
3232 if (std::abs(r2_val - floor_val) > std::abs(r2_val - ceil_val)) {
3233 r1_val = static_cast<int64_t>(ceil_val);
3234 } else if (std::abs(r2_val - floor_val) <
3235 std::abs(r2_val - ceil_val)) {
3236 r1_val = static_cast<int64_t>(floor_val);
3237 } else { // check which one is even:
3238 int64_t c_v = static_cast<int64_t>(ceil_val);
3239 int64_t f_v = static_cast<int64_t>(floor_val);
3240 if (f_v % 2 == 0)
3241 r1_val = f_v;
3242 else
3243 r1_val = c_v;
3244 }
3245 break;
3246 }
3247 case ROUND_TOWARD_0: {
3248 r1_val = static_cast<int64_t>(r2_val);
3249 break;
3250 }
3251 case ROUND_TOWARD_PLUS_INFINITE: {
3252 r1_val = static_cast<int64_t>(std::ceil(r2_val));
3253 break;
3254 }
3255 case ROUND_TOWARD_MINUS_INFINITE: {
3256 r1_val = static_cast<int64_t>(std::floor(r2_val));
3257 break;
3258 }
3259 default:
3260 UNREACHABLE();
3261 }
3262 set_register(r1, r1_val);
3263 break;
3264 }
3265 case CGEBR: {
3266 int mask_val = rreInstr->M3Value();
3267 int64_t r1_val = 0;
3268
3269 SetS390RoundConditionCode(r2_fval, INT64_MAX, INT64_MIN);
3270
3271 switch (mask_val) {
3272 case CURRENT_ROUNDING_MODE:
3273 case ROUND_TO_NEAREST_WITH_TIES_AWAY_FROM_0:
3274 case ROUND_TO_PREPARE_FOR_SHORTER_PRECISION: {
3275 UNIMPLEMENTED();
3276 break;
3277 }
3278 case ROUND_TO_NEAREST_WITH_TIES_TO_EVEN: {
3279 float ceil_val = std::ceil(r2_fval);
3280 float floor_val = std::floor(r2_fval);
3281 if (std::abs(r2_fval - floor_val) > std::abs(r2_fval - ceil_val)) {
3282 r1_val = static_cast<int64_t>(ceil_val);
3283 } else if (std::abs(r2_fval - floor_val) <
3284 std::abs(r2_fval - ceil_val)) {
3285 r1_val = static_cast<int64_t>(floor_val);
3286 } else { // check which one is even:
3287 int64_t c_v = static_cast<int64_t>(ceil_val);
3288 int64_t f_v = static_cast<int64_t>(floor_val);
3289 if (f_v % 2 == 0)
3290 r1_val = f_v;
3291 else
3292 r1_val = c_v;
3293 }
3294 break;
3295 }
3296 case ROUND_TOWARD_0: {
3297 r1_val = static_cast<int64_t>(r2_fval);
3298 break;
3299 }
3300 case ROUND_TOWARD_PLUS_INFINITE: {
3301 r1_val = static_cast<int64_t>(std::ceil(r2_fval));
3302 break;
3303 }
3304 case ROUND_TOWARD_MINUS_INFINITE: {
3305 r1_val = static_cast<int64_t>(std::floor(r2_fval));
3306 break;
3307 }
3308 default:
3309 UNREACHABLE();
3310 }
3311 set_register(r1, r1_val);
3312 break;
3313 }
3314 case CFEBR: {
3315 int mask_val = rreInstr->M3Value();
3316 int32_t r1_val = 0;
3317
3318 SetS390RoundConditionCode(r2_fval, INT32_MAX, INT32_MIN);
3319
3320 switch (mask_val) {
3321 case CURRENT_ROUNDING_MODE:
3322 case ROUND_TO_PREPARE_FOR_SHORTER_PRECISION: {
3323 r1_val = static_cast<int32_t>(r2_fval);
3324 break;
3325 }
3326 case ROUND_TO_NEAREST_WITH_TIES_AWAY_FROM_0: {
3327 float ceil_val = std::ceil(r2_fval);
3328 float floor_val = std::floor(r2_fval);
3329 float sub_val1 = std::fabs(r2_fval - floor_val);
3330 float sub_val2 = std::fabs(r2_fval - ceil_val);
3331 if (sub_val1 > sub_val2) {
3332 r1_val = static_cast<int32_t>(ceil_val);
3333 } else if (sub_val1 < sub_val2) {
3334 r1_val = static_cast<int32_t>(floor_val);
3335 } else { // round away from zero:
3336 if (r2_fval > 0.0) {
3337 r1_val = static_cast<int32_t>(ceil_val);
3338 } else {
3339 r1_val = static_cast<int32_t>(floor_val);
3340 }
3341 }
3342 break;
3343 }
3344 case ROUND_TO_NEAREST_WITH_TIES_TO_EVEN: {
3345 float ceil_val = std::ceil(r2_fval);
3346 float floor_val = std::floor(r2_fval);
3347 float sub_val1 = std::fabs(r2_fval - floor_val);
3348 float sub_val2 = std::fabs(r2_fval - ceil_val);
3349 if (sub_val1 > sub_val2) {
3350 r1_val = static_cast<int32_t>(ceil_val);
3351 } else if (sub_val1 < sub_val2) {
3352 r1_val = static_cast<int32_t>(floor_val);
3353 } else { // check which one is even:
3354 int32_t c_v = static_cast<int32_t>(ceil_val);
3355 int32_t f_v = static_cast<int32_t>(floor_val);
3356 if (f_v % 2 == 0)
3357 r1_val = f_v;
3358 else
3359 r1_val = c_v;
3360 }
3361 break;
3362 }
3363 case ROUND_TOWARD_0: {
3364 // check for overflow, cast r2_fval to 64bit integer
3365 // then check value within the range of INT_MIN and INT_MAX
3366 // and set condition code accordingly
3367 int64_t temp = static_cast<int64_t>(r2_fval);
3368 if (temp < INT_MIN || temp > INT_MAX) {
3369 condition_reg_ = CC_OF;
3370 }
3371 r1_val = static_cast<int32_t>(r2_fval);
3372 break;
3373 }
3374 case ROUND_TOWARD_PLUS_INFINITE: {
3375 r1_val = static_cast<int32_t>(std::ceil(r2_fval));
3376 break;
3377 }
3378 case ROUND_TOWARD_MINUS_INFINITE: {
3379 // check for overflow, cast r2_fval to 64bit integer
3380 // then check value within the range of INT_MIN and INT_MAX
3381 // and set condition code accordingly
3382 int64_t temp = static_cast<int64_t>(std::floor(r2_fval));
3383 if (temp < INT_MIN || temp > INT_MAX) {
3384 condition_reg_ = CC_OF;
3385 }
3386 r1_val = static_cast<int32_t>(std::floor(r2_fval));
3387 break;
3388 }
3389 default:
3390 UNREACHABLE();
3391 }
3392 set_low_register(r1, r1_val);
3393
3394 break;
3395 }
3396 default:
3397 UNREACHABLE();
3398 }
3399}
3400
3401/**
3402 * Decodes and simulates four byte floating point instructions
3403 */
3404bool Simulator::DecodeFourByteFloatingPoint(Instruction* instr) {
3405 Opcode op = instr->S390OpcodeValue();
3406
3407 switch (op) {
3408 case ADBR:
3409 case AEBR:
3410 case SDBR:
3411 case SEBR:
3412 case MDBR:
3413 case MEEBR:
3414 case MADBR:
3415 case DDBR:
3416 case DEBR:
3417 case CDBR:
3418 case CEBR:
3419 case CDFBR:
3420 case CDGBR:
3421 case CEGBR:
3422 case CGEBR:
3423 case CFDBR:
3424 case CGDBR:
3425 case SQDBR:
3426 case SQEBR:
3427 case CFEBR:
3428 case CEFBR:
3429 case LCDBR:
3430 case LPDBR:
3431 case LPEBR: {
3432 RREInstruction* rreInstr = reinterpret_cast<RREInstruction*>(instr);
3433 int r1 = rreInstr->R1Value();
3434 int r2 = rreInstr->R2Value();
3435 double r1_val = get_double_from_d_register(r1);
3436 double r2_val = get_double_from_d_register(r2);
3437 float fr1_val = get_float32_from_d_register(r1);
3438 float fr2_val = get_float32_from_d_register(r2);
3439 if (op == ADBR) {
3440 r1_val += r2_val;
3441 set_d_register_from_double(r1, r1_val);
3442 SetS390ConditionCode<double>(r1_val, 0);
3443 } else if (op == AEBR) {
3444 fr1_val += fr2_val;
3445 set_d_register_from_float32(r1, fr1_val);
3446 SetS390ConditionCode<float>(fr1_val, 0);
3447 } else if (op == SDBR) {
3448 r1_val -= r2_val;
3449 set_d_register_from_double(r1, r1_val);
3450 SetS390ConditionCode<double>(r1_val, 0);
3451 } else if (op == SEBR) {
3452 fr1_val -= fr2_val;
3453 set_d_register_from_float32(r1, fr1_val);
3454 SetS390ConditionCode<float>(fr1_val, 0);
3455 } else if (op == MDBR) {
3456 r1_val *= r2_val;
3457 set_d_register_from_double(r1, r1_val);
3458 SetS390ConditionCode<double>(r1_val, 0);
3459 } else if (op == MEEBR) {
3460 fr1_val *= fr2_val;
3461 set_d_register_from_float32(r1, fr1_val);
3462 SetS390ConditionCode<float>(fr1_val, 0);
3463 } else if (op == MADBR) {
3464 RRDInstruction* rrdInstr = reinterpret_cast<RRDInstruction*>(instr);
3465 int r1 = rrdInstr->R1Value();
3466 int r2 = rrdInstr->R2Value();
3467 int r3 = rrdInstr->R3Value();
3468 double r1_val = get_double_from_d_register(r1);
3469 double r2_val = get_double_from_d_register(r2);
3470 double r3_val = get_double_from_d_register(r3);
3471 r1_val += r2_val * r3_val;
3472 set_d_register_from_double(r1, r1_val);
3473 SetS390ConditionCode<double>(r1_val, 0);
3474 } else if (op == DDBR) {
3475 r1_val /= r2_val;
3476 set_d_register_from_double(r1, r1_val);
3477 SetS390ConditionCode<double>(r1_val, 0);
3478 } else if (op == DEBR) {
3479 fr1_val /= fr2_val;
3480 set_d_register_from_float32(r1, fr1_val);
3481 SetS390ConditionCode<float>(fr1_val, 0);
3482 } else if (op == CDBR) {
3483 if (isNaN(r1_val) || isNaN(r2_val)) {
3484 condition_reg_ = CC_OF;
3485 } else {
3486 SetS390ConditionCode<double>(r1_val, r2_val);
3487 }
3488 } else if (op == CEBR) {
3489 if (isNaN(fr1_val) || isNaN(fr2_val)) {
3490 condition_reg_ = CC_OF;
3491 } else {
3492 SetS390ConditionCode<float>(fr1_val, fr2_val);
3493 }
3494 } else if (op == CDGBR) {
3495 int64_t r2_val = get_register(r2);
3496 double r1_val = static_cast<double>(r2_val);
3497 set_d_register_from_double(r1, r1_val);
3498 } else if (op == CEGBR) {
3499 int64_t fr2_val = get_register(r2);
3500 float fr1_val = static_cast<float>(fr2_val);
3501 set_d_register_from_float32(r1, fr1_val);
3502 } else if (op == CDFBR) {
3503 int32_t r2_val = get_low_register<int32_t>(r2);
3504 double r1_val = static_cast<double>(r2_val);
3505 set_d_register_from_double(r1, r1_val);
3506 } else if (op == CEFBR) {
3507 int32_t fr2_val = get_low_register<int32_t>(r2);
3508 float fr1_val = static_cast<float>(fr2_val);
3509 set_d_register_from_float32(r1, fr1_val);
3510 } else if (op == CFDBR) {
3511 DecodeFourByteFloatingPointRound(instr);
3512 } else if (op == CGDBR) {
3513 DecodeFourByteFloatingPointRound(instr);
3514 } else if (op == CGEBR) {
3515 DecodeFourByteFloatingPointRound(instr);
3516 } else if (op == SQDBR) {
3517 r1_val = std::sqrt(r2_val);
3518 set_d_register_from_double(r1, r1_val);
3519 } else if (op == SQEBR) {
3520 fr1_val = std::sqrt(fr2_val);
3521 set_d_register_from_float32(r1, fr1_val);
3522 } else if (op == CFEBR) {
3523 DecodeFourByteFloatingPointRound(instr);
3524 } else if (op == LCDBR) {
3525 r1_val = -r2_val;
3526 set_d_register_from_double(r1, r1_val);
3527 if (r2_val != r2_val) { // input is NaN
3528 condition_reg_ = CC_OF;
3529 } else if (r2_val == 0) {
3530 condition_reg_ = CC_EQ;
3531 } else if (r2_val < 0) {
3532 condition_reg_ = CC_LT;
3533 } else if (r2_val > 0) {
3534 condition_reg_ = CC_GT;
3535 }
3536 } else if (op == LPDBR) {
3537 r1_val = std::fabs(r2_val);
3538 set_d_register_from_double(r1, r1_val);
3539 if (r2_val != r2_val) { // input is NaN
3540 condition_reg_ = CC_OF;
3541 } else if (r2_val == 0) {
3542 condition_reg_ = CC_EQ;
3543 } else {
3544 condition_reg_ = CC_GT;
3545 }
3546 } else if (op == LPEBR) {
3547 fr1_val = std::fabs(fr2_val);
3548 set_d_register_from_float32(r1, fr1_val);
3549 if (fr2_val != fr2_val) { // input is NaN
3550 condition_reg_ = CC_OF;
3551 } else if (fr2_val == 0) {
3552 condition_reg_ = CC_EQ;
3553 } else {
3554 condition_reg_ = CC_GT;
3555 }
3556 } else {
3557 UNREACHABLE();
3558 }
3559 break;
3560 }
3561 case CDLFBR:
3562 case CDLGBR:
3563 case CELGBR:
3564 case CLFDBR:
3565 case CELFBR:
3566 case CLGDBR:
3567 case CLGEBR:
3568 case CLFEBR: {
3569 DecodeFourByteFloatingPointIntConversion(instr);
3570 break;
3571 }
3572 case TMLL: {
3573 RIInstruction* riinst = reinterpret_cast<RIInstruction*>(instr);
3574 int r1 = riinst->R1Value();
3575 int mask = riinst->I2Value() & 0x0000FFFF;
3576 if (mask == 0) {
3577 condition_reg_ = 0x0;
3578 break;
3579 }
3580 uint32_t r1_val = get_low_register<uint32_t>(r1);
3581 r1_val = r1_val & 0x0000FFFF; // uses only the last 16bits
3582
3583 // Test if all selected bits are Zero
3584 bool allSelectedBitsAreZeros = true;
3585 for (int i = 0; i < 15; i++) {
3586 if (mask & (1 << i)) {
3587 if (r1_val & (1 << i)) {
3588 allSelectedBitsAreZeros = false;
3589 break;
3590 }
3591 }
3592 }
3593 if (allSelectedBitsAreZeros) {
3594 condition_reg_ = 0x8;
3595 break; // Done!
3596 }
3597
3598 // Test if all selected bits are one
3599 bool allSelectedBitsAreOnes = true;
3600 for (int i = 0; i < 15; i++) {
3601 if (mask & (1 << i)) {
3602 if (!(r1_val & (1 << i))) {
3603 allSelectedBitsAreOnes = false;
3604 break;
3605 }
3606 }
3607 }
3608 if (allSelectedBitsAreOnes) {
3609 condition_reg_ = 0x1;
3610 break; // Done!
3611 }
3612
3613 // Now we know selected bits mixed zeros and ones
3614 // Test if the leftmost bit is zero or one
3615 for (int i = 14; i >= 0; i--) {
3616 if (mask & (1 << i)) {
3617 if (r1_val & (1 << i)) {
3618 // leftmost bit is one
3619 condition_reg_ = 0x2;
3620 } else {
3621 // leftmost bit is zero
3622 condition_reg_ = 0x4;
3623 }
3624 break; // Done!
3625 }
3626 }
3627 break;
3628 }
3629 case LEDBR: {
3630 RREInstruction* rreInst = reinterpret_cast<RREInstruction*>(instr);
3631 int r1 = rreInst->R1Value();
3632 int r2 = rreInst->R2Value();
3633 double r2_val = get_double_from_d_register(r2);
3634 set_d_register_from_float32(r1, static_cast<float>(r2_val));
3635 break;
3636 }
3637 case FIDBRA: {
3638 RRFInstruction* rrfInst = reinterpret_cast<RRFInstruction*>(instr);
3639 int r1 = rrfInst->R1Value();
3640 int r2 = rrfInst->R2Value();
3641 int m3 = rrfInst->M3Value();
3642 double r2_val = get_double_from_d_register(r2);
3643 DCHECK(rrfInst->M4Value() == 0);
3644 switch (m3) {
3645 case Assembler::FIDBRA_ROUND_TO_NEAREST_AWAY_FROM_0:
3646 set_d_register_from_double(r1, round(r2_val));
3647 break;
3648 case Assembler::FIDBRA_ROUND_TOWARD_0:
3649 set_d_register_from_double(r1, trunc(r2_val));
3650 break;
3651 case Assembler::FIDBRA_ROUND_TOWARD_POS_INF:
3652 set_d_register_from_double(r1, std::ceil(r2_val));
3653 break;
3654 case Assembler::FIDBRA_ROUND_TOWARD_NEG_INF:
3655 set_d_register_from_double(r1, std::floor(r2_val));
3656 break;
3657 default:
3658 UNIMPLEMENTED();
3659 break;
3660 }
3661 break;
3662 }
3663 case FIEBRA: {
3664 RRFInstruction* rrfInst = reinterpret_cast<RRFInstruction*>(instr);
3665 int r1 = rrfInst->R1Value();
3666 int r2 = rrfInst->R2Value();
3667 int m3 = rrfInst->M3Value();
3668 float r2_val = get_float32_from_d_register(r2);
3669 DCHECK(rrfInst->M4Value() == 0);
3670 switch (m3) {
3671 case Assembler::FIDBRA_ROUND_TO_NEAREST_AWAY_FROM_0:
3672 set_d_register_from_float32(r1, round(r2_val));
3673 break;
3674 case Assembler::FIDBRA_ROUND_TOWARD_0:
3675 set_d_register_from_float32(r1, trunc(r2_val));
3676 break;
3677 case Assembler::FIDBRA_ROUND_TOWARD_POS_INF:
3678 set_d_register_from_float32(r1, std::ceil(r2_val));
3679 break;
3680 case Assembler::FIDBRA_ROUND_TOWARD_NEG_INF:
3681 set_d_register_from_float32(r1, std::floor(r2_val));
3682 break;
3683 default:
3684 UNIMPLEMENTED();
3685 break;
3686 }
3687 break;
3688 }
3689 case MSDBR: {
3690 UNIMPLEMENTED();
3691 break;
3692 }
3693 case LDEBR: {
3694 RREInstruction* rreInstr = reinterpret_cast<RREInstruction*>(instr);
3695 int r1 = rreInstr->R1Value();
3696 int r2 = rreInstr->R2Value();
3697 float fp_val = get_float32_from_d_register(r2);
3698 double db_val = static_cast<double>(fp_val);
3699 set_d_register_from_double(r1, db_val);
3700 break;
3701 }
3702 default: {
3703 UNREACHABLE();
3704 return false;
3705 }
3706 }
3707 return true;
3708}
3709
3710// Decode routine for six-byte instructions
3711bool Simulator::DecodeSixByte(Instruction* instr) {
3712 Opcode op = instr->S390OpcodeValue();
3713
3714 // Pre-cast instruction to various types
3715 RIEInstruction* rieInstr = reinterpret_cast<RIEInstruction*>(instr);
3716 RILInstruction* rilInstr = reinterpret_cast<RILInstruction*>(instr);
3717 RSYInstruction* rsyInstr = reinterpret_cast<RSYInstruction*>(instr);
3718 RXEInstruction* rxeInstr = reinterpret_cast<RXEInstruction*>(instr);
3719 RXYInstruction* rxyInstr = reinterpret_cast<RXYInstruction*>(instr);
3720 SIYInstruction* siyInstr = reinterpret_cast<SIYInstruction*>(instr);
3721 SILInstruction* silInstr = reinterpret_cast<SILInstruction*>(instr);
3722 SSInstruction* ssInstr = reinterpret_cast<SSInstruction*>(instr);
3723
3724 switch (op) {
3725 case CLIY: {
3726 // Compare Immediate (Mem - Imm) (8)
3727 int b1 = siyInstr->B1Value();
3728 int64_t b1_val = (b1 == 0) ? 0 : get_register(b1);
3729 intptr_t d1_val = siyInstr->D1Value();
3730 intptr_t addr = b1_val + d1_val;
3731 uint8_t mem_val = ReadB(addr);
3732 uint8_t imm_val = siyInstr->I2Value();
3733 SetS390ConditionCode<uint8_t>(mem_val, imm_val);
3734 break;
3735 }
3736 case TMY: {
3737 // Test Under Mask (Mem - Imm) (8)
3738 int b1 = siyInstr->B1Value();
3739 int64_t b1_val = (b1 == 0) ? 0 : get_register(b1);
3740 intptr_t d1_val = siyInstr->D1Value();
3741 intptr_t addr = b1_val + d1_val;
3742 uint8_t mem_val = ReadB(addr);
3743 uint8_t imm_val = siyInstr->I2Value();
3744 uint8_t selected_bits = mem_val & imm_val;
3745 // CC0: Selected bits are zero
3746 // CC1: Selected bits mixed zeros and ones
3747 // CC3: Selected bits all ones
3748 if (0 == selected_bits) {
3749 condition_reg_ = CC_EQ; // CC0
3750 } else if (selected_bits == imm_val) {
3751 condition_reg_ = 0x1; // CC3
3752 } else {
3753 condition_reg_ = 0x4; // CC1
3754 }
3755 break;
3756 }
3757 case LDEB: {
3758 // Load Float
3759 int r1 = rxeInstr->R1Value();
3760 int rb = rxeInstr->B2Value();
3761 int rx = rxeInstr->X2Value();
3762 int offset = rxeInstr->D2Value();
3763 int64_t rb_val = (rb == 0) ? 0 : get_register(rb);
3764 int64_t rx_val = (rx == 0) ? 0 : get_register(rx);
3765 double ret = static_cast<double>(
3766 *reinterpret_cast<float*>(rx_val + rb_val + offset));
3767 set_d_register_from_double(r1, ret);
3768 break;
3769 }
3770 case LAY: {
3771 // Load Address
3772 int r1 = rxyInstr->R1Value();
3773 int rb = rxyInstr->B2Value();
3774 int rx = rxyInstr->X2Value();
3775 int offset = rxyInstr->D2Value();
3776 int64_t rb_val = (rb == 0) ? 0 : get_register(rb);
3777 int64_t rx_val = (rx == 0) ? 0 : get_register(rx);
3778 set_register(r1, rx_val + rb_val + offset);
3779 break;
3780 }
3781 case LARL: {
3782 // Load Addresss Relative Long
3783 int r1 = rilInstr->R1Value();
3784 intptr_t offset = rilInstr->I2Value() * 2;
3785 set_register(r1, get_pc() + offset);
3786 break;
3787 }
3788 case LLILF: {
3789 // Load Logical into lower 32-bits (zero extend upper 32-bits)
3790 int r1 = rilInstr->R1Value();
3791 uint64_t imm = static_cast<uint64_t>(rilInstr->I2UnsignedValue());
3792 set_register(r1, imm);
3793 break;
3794 }
3795 case LLIHF: {
3796 // Load Logical Immediate into high word
3797 int r1 = rilInstr->R1Value();
3798 uint64_t imm = static_cast<uint64_t>(rilInstr->I2UnsignedValue());
3799 set_register(r1, imm << 32);
3800 break;
3801 }
3802 case OILF:
3803 case NILF:
3804 case IILF: {
3805 // Bitwise Op on lower 32-bits
3806 int r1 = rilInstr->R1Value();
3807 uint32_t imm = rilInstr->I2UnsignedValue();
3808 uint32_t alu_out = get_low_register<uint32_t>(r1);
3809 if (NILF == op) {
3810 alu_out &= imm;
3811 SetS390BitWiseConditionCode<uint32_t>(alu_out);
3812 } else if (OILF == op) {
3813 alu_out |= imm;
3814 SetS390BitWiseConditionCode<uint32_t>(alu_out);
3815 } else if (op == IILF) {
3816 alu_out = imm;
3817 } else {
3818 DCHECK(false);
3819 }
3820 set_low_register(r1, alu_out);
3821 break;
3822 }
3823 case OIHF:
3824 case NIHF:
3825 case IIHF: {
3826 // Bitwise Op on upper 32-bits
3827 int r1 = rilInstr->R1Value();
3828 uint32_t imm = rilInstr->I2Value();
3829 uint32_t alu_out = get_high_register<uint32_t>(r1);
3830 if (op == NIHF) {
3831 alu_out &= imm;
3832 SetS390BitWiseConditionCode<uint32_t>(alu_out);
3833 } else if (op == OIHF) {
3834 alu_out |= imm;
3835 SetS390BitWiseConditionCode<uint32_t>(alu_out);
3836 } else if (op == IIHF) {
3837 alu_out = imm;
3838 } else {
3839 DCHECK(false);
3840 }
3841 set_high_register(r1, alu_out);
3842 break;
3843 }
3844 case CLFI: {
3845 // Compare Logical with Immediate (32)
3846 int r1 = rilInstr->R1Value();
3847 uint32_t imm = rilInstr->I2UnsignedValue();
3848 SetS390ConditionCode<uint32_t>(get_low_register<uint32_t>(r1), imm);
3849 break;
3850 }
3851 case CFI: {
3852 // Compare with Immediate (32)
3853 int r1 = rilInstr->R1Value();
3854 int32_t imm = rilInstr->I2Value();
3855 SetS390ConditionCode<int32_t>(get_low_register<int32_t>(r1), imm);
3856 break;
3857 }
3858 case CLGFI: {
3859 // Compare Logical with Immediate (64)
3860 int r1 = rilInstr->R1Value();
3861 uint64_t imm = static_cast<uint64_t>(rilInstr->I2UnsignedValue());
3862 SetS390ConditionCode<uint64_t>(get_register(r1), imm);
3863 break;
3864 }
3865 case CGFI: {
3866 // Compare with Immediate (64)
3867 int r1 = rilInstr->R1Value();
3868 int64_t imm = static_cast<int64_t>(rilInstr->I2Value());
3869 SetS390ConditionCode<int64_t>(get_register(r1), imm);
3870 break;
3871 }
3872 case BRASL: {
3873 // Branch and Save Relative Long
3874 int r1 = rilInstr->R1Value();
3875 intptr_t d2 = rilInstr->I2Value();
3876 intptr_t pc = get_pc();
3877 set_register(r1, pc + 6); // save next instruction to register
3878 set_pc(pc + d2 * 2); // update register
3879 break;
3880 }
3881 case BRCL: {
3882 // Branch on Condition Relative Long
3883 Condition m1 = (Condition)rilInstr->R1Value();
3884 if (TestConditionCode((Condition)m1)) {
3885 intptr_t offset = rilInstr->I2Value() * 2;
3886 set_pc(get_pc() + offset);
3887 }
3888 break;
3889 }
3890 case LMG:
3891 case STMG: {
3892 // Store Multiple 64-bits.
3893 int r1 = rsyInstr->R1Value();
3894 int r3 = rsyInstr->R3Value();
3895 int rb = rsyInstr->B2Value();
3896 int offset = rsyInstr->D2Value();
3897
3898 // Regs roll around if r3 is less than r1.
3899 // Artifically increase r3 by 16 so we can calculate
3900 // the number of regs stored properly.
3901 if (r3 < r1) r3 += 16;
3902
3903 int64_t rb_val = (rb == 0) ? 0 : get_register(rb);
3904
3905 // Store each register in ascending order.
3906 for (int i = 0; i <= r3 - r1; i++) {
3907 if (op == LMG) {
3908 int64_t value = ReadDW(rb_val + offset + 8 * i);
3909 set_register((r1 + i) % 16, value);
3910 } else if (op == STMG) {
3911 int64_t value = get_register((r1 + i) % 16);
3912 WriteDW(rb_val + offset + 8 * i, value);
3913 } else {
3914 DCHECK(false);
3915 }
3916 }
3917 break;
3918 }
3919 case SLLK:
3920 case RLL:
3921 case SRLK:
3922 case SLLG:
3923 case RLLG:
3924 case SRLG: {
3925 DecodeSixByteBitShift(instr);
3926 break;
3927 }
3928 case SLAK:
3929 case SRAK: {
3930 // 32-bit non-clobbering shift-left/right arithmetic
3931 int r1 = rsyInstr->R1Value();
3932 int r3 = rsyInstr->R3Value();
3933 int b2 = rsyInstr->B2Value();
3934 intptr_t d2 = rsyInstr->D2Value();
3935 // only takes rightmost 6 bits
3936 int64_t b2_val = (b2 == 0) ? 0 : get_register(b2);
3937 int shiftBits = (b2_val + d2) & 0x3F;
3938 int32_t r3_val = get_low_register<int32_t>(r3);
3939 int32_t alu_out = 0;
3940 bool isOF = false;
3941 if (op == SLAK) {
3942 isOF = CheckOverflowForShiftLeft(r3_val, shiftBits);
3943 alu_out = r3_val << shiftBits;
3944 } else if (op == SRAK) {
3945 alu_out = r3_val >> shiftBits;
3946 }
3947 set_low_register(r1, alu_out);
3948 SetS390ConditionCode<int32_t>(alu_out, 0);
3949 SetS390OverflowCode(isOF);
3950 break;
3951 }
3952 case SLAG:
3953 case SRAG: {
3954 // 64-bit non-clobbering shift-left/right arithmetic
3955 int r1 = rsyInstr->R1Value();
3956 int r3 = rsyInstr->R3Value();
3957 int b2 = rsyInstr->B2Value();
3958 intptr_t d2 = rsyInstr->D2Value();
3959 // only takes rightmost 6 bits
3960 int64_t b2_val = (b2 == 0) ? 0 : get_register(b2);
3961 int shiftBits = (b2_val + d2) & 0x3F;
3962 int64_t r3_val = get_register(r3);
3963 intptr_t alu_out = 0;
3964 bool isOF = false;
3965 if (op == SLAG) {
3966 isOF = CheckOverflowForShiftLeft(r3_val, shiftBits);
3967 alu_out = r3_val << shiftBits;
3968 } else if (op == SRAG) {
3969 alu_out = r3_val >> shiftBits;
3970 }
3971 set_register(r1, alu_out);
3972 SetS390ConditionCode<intptr_t>(alu_out, 0);
3973 SetS390OverflowCode(isOF);
3974 break;
3975 }
3976 case LMY:
3977 case STMY: {
3978 RSYInstruction* rsyInstr = reinterpret_cast<RSYInstruction*>(instr);
3979 // Load/Store Multiple (32)
3980 int r1 = rsyInstr->R1Value();
3981 int r3 = rsyInstr->R3Value();
3982 int b2 = rsyInstr->B2Value();
3983 int offset = rsyInstr->D2Value();
3984
3985 // Regs roll around if r3 is less than r1.
3986 // Artifically increase r3 by 16 so we can calculate
3987 // the number of regs stored properly.
3988 if (r3 < r1) r3 += 16;
3989
3990 int32_t b2_val = (b2 == 0) ? 0 : get_low_register<int32_t>(b2);
3991
3992 // Store each register in ascending order.
3993 for (int i = 0; i <= r3 - r1; i++) {
3994 if (op == LMY) {
3995 int32_t value = ReadW(b2_val + offset + 4 * i, instr);
3996 set_low_register((r1 + i) % 16, value);
3997 } else {
3998 int32_t value = get_low_register<int32_t>((r1 + i) % 16);
3999 WriteW(b2_val + offset + 4 * i, value, instr);
4000 }
4001 }
4002 break;
4003 }
4004 case LT:
4005 case LTG: {
4006 // Load and Test (32/64)
4007 int r1 = rxyInstr->R1Value();
4008 int x2 = rxyInstr->X2Value();
4009 int b2 = rxyInstr->B2Value();
4010 int d2 = rxyInstr->D2Value();
4011
4012 int64_t x2_val = (x2 == 0) ? 0 : get_register(x2);
4013 int64_t b2_val = (b2 == 0) ? 0 : get_register(b2);
4014 intptr_t addr = x2_val + b2_val + d2;
4015
4016 if (op == LT) {
4017 int32_t value = ReadW(addr, instr);
4018 set_low_register(r1, value);
4019 SetS390ConditionCode<int32_t>(value, 0);
4020 } else if (op == LTG) {
4021 int64_t value = ReadDW(addr);
4022 set_register(r1, value);
4023 SetS390ConditionCode<int64_t>(value, 0);
4024 }
4025 break;
4026 }
4027 case LY:
4028 case LB:
4029 case LGB:
4030 case LG:
4031 case LGF:
4032 case LGH:
4033 case LLGF:
4034 case STG:
4035 case STY:
4036 case STCY:
4037 case STHY:
4038 case STEY:
4039 case LDY:
4040 case LHY:
4041 case STDY:
4042 case LEY: {
4043 // Miscellaneous Loads and Stores
4044 int r1 = rxyInstr->R1Value();
4045 int x2 = rxyInstr->X2Value();
4046 int b2 = rxyInstr->B2Value();
4047 int d2 = rxyInstr->D2Value();
4048 int64_t x2_val = (x2 == 0) ? 0 : get_register(x2);
4049 int64_t b2_val = (b2 == 0) ? 0 : get_register(b2);
4050 intptr_t addr = x2_val + b2_val + d2;
4051 if (op == LY) {
4052 uint32_t mem_val = ReadWU(addr, instr);
4053 set_low_register(r1, mem_val);
4054 } else if (op == LB) {
4055 int32_t mem_val = ReadB(addr);
4056 set_low_register(r1, mem_val);
4057 } else if (op == LGB) {
4058 int64_t mem_val = ReadB(addr);
4059 set_register(r1, mem_val);
4060 } else if (op == LG) {
4061 int64_t mem_val = ReadDW(addr);
4062 set_register(r1, mem_val);
4063 } else if (op == LGF) {
4064 int64_t mem_val = static_cast<int64_t>(ReadW(addr, instr));
4065 set_register(r1, mem_val);
4066 } else if (op == LGH) {
4067 int64_t mem_val = static_cast<int64_t>(ReadH(addr, instr));
4068 set_register(r1, mem_val);
4069 } else if (op == LLGF) {
4070 // int r1 = rreInst->R1Value();
4071 // int r2 = rreInst->R2Value();
4072 // int32_t r2_val = get_low_register<int32_t>(r2);
4073 // uint64_t r2_finalval = (static_cast<uint64_t>(r2_val)
4074 // & 0x00000000ffffffff);
4075 // set_register(r1, r2_finalval);
4076 // break;
4077 uint64_t mem_val = static_cast<uint64_t>(ReadWU(addr, instr));
4078 set_register(r1, mem_val);
4079 } else if (op == LDY) {
4080 uint64_t dbl_val = *reinterpret_cast<uint64_t*>(addr);
4081 set_d_register(r1, dbl_val);
4082 } else if (op == STEY) {
4083 int64_t frs_val = get_d_register(r1) >> 32;
4084 WriteW(addr, static_cast<int32_t>(frs_val), instr);
4085 } else if (op == LEY) {
4086 float float_val = *reinterpret_cast<float*>(addr);
4087 set_d_register_from_float32(r1, float_val);
4088 } else if (op == STY) {
4089 uint32_t value = get_low_register<uint32_t>(r1);
4090 WriteW(addr, value, instr);
4091 } else if (op == STG) {
4092 uint64_t value = get_register(r1);
4093 WriteDW(addr, value);
4094 } else if (op == STDY) {
4095 int64_t frs_val = get_d_register(r1);
4096 WriteDW(addr, frs_val);
4097 } else if (op == STCY) {
4098 uint8_t value = get_low_register<uint32_t>(r1);
4099 WriteB(addr, value);
4100 } else if (op == STHY) {
4101 uint16_t value = get_low_register<uint32_t>(r1);
4102 WriteH(addr, value, instr);
4103 } else if (op == LHY) {
4104 int32_t result = static_cast<int32_t>(ReadH(addr, instr));
4105 set_low_register(r1, result);
4106 }
4107 break;
4108 }
4109 case MVC: {
4110 // Move Character
4111 int b1 = ssInstr->B1Value();
4112 intptr_t d1 = ssInstr->D1Value();
4113 int b2 = ssInstr->B2Value();
4114 intptr_t d2 = ssInstr->D2Value();
4115 int length = ssInstr->Length();
4116 int64_t b1_val = (b1 == 0) ? 0 : get_register(b1);
4117 int64_t b2_val = (b2 == 0) ? 0 : get_register(b2);
4118 intptr_t src_addr = b2_val + d2;
4119 intptr_t dst_addr = b1_val + d1;
4120 // remember that the length is the actual length - 1
4121 for (int i = 0; i < length + 1; ++i) {
4122 WriteB(dst_addr++, ReadB(src_addr++));
4123 }
4124 break;
4125 }
4126 case MVHI: {
4127 // Move Integer (32)
4128 int b1 = silInstr->B1Value();
4129 intptr_t d1 = silInstr->D1Value();
4130 int16_t i2 = silInstr->I2Value();
4131 int64_t b1_val = (b1 == 0) ? 0 : get_register(b1);
4132 intptr_t src_addr = b1_val + d1;
4133 WriteW(src_addr, i2, instr);
4134 break;
4135 }
4136 case MVGHI: {
4137 // Move Integer (64)
4138 int b1 = silInstr->B1Value();
4139 intptr_t d1 = silInstr->D1Value();
4140 int16_t i2 = silInstr->I2Value();
4141 int64_t b1_val = (b1 == 0) ? 0 : get_register(b1);
4142 intptr_t src_addr = b1_val + d1;
4143 WriteDW(src_addr, i2);
4144 break;
4145 }
4146 case LLH:
4147 case LLGH: {
4148 // Load Logical Halfworld
4149 int r1 = rxyInstr->R1Value();
4150 int b2 = rxyInstr->B2Value();
4151 int x2 = rxyInstr->X2Value();
4152 int64_t b2_val = (b2 == 0) ? 0 : get_register(b2);
4153 int64_t x2_val = (x2 == 0) ? 0 : get_register(x2);
4154 intptr_t d2_val = rxyInstr->D2Value();
4155 uint16_t mem_val = ReadHU(b2_val + d2_val + x2_val, instr);
4156 if (op == LLH) {
4157 set_low_register(r1, mem_val);
4158 } else if (op == LLGH) {
4159 set_register(r1, mem_val);
4160 } else {
4161 UNREACHABLE();
4162 }
4163 break;
4164 }
4165 case LLC:
4166 case LLGC: {
4167 // Load Logical Character - loads a byte and zero extends.
4168 int r1 = rxyInstr->R1Value();
4169 int b2 = rxyInstr->B2Value();
4170 int x2 = rxyInstr->X2Value();
4171 int64_t b2_val = (b2 == 0) ? 0 : get_register(b2);
4172 int64_t x2_val = (x2 == 0) ? 0 : get_register(x2);
4173 intptr_t d2_val = rxyInstr->D2Value();
4174 uint8_t mem_val = ReadBU(b2_val + d2_val + x2_val);
4175 if (op == LLC) {
4176 set_low_register(r1, static_cast<uint32_t>(mem_val));
4177 } else if (op == LLGC) {
4178 set_register(r1, static_cast<uint64_t>(mem_val));
4179 } else {
4180 UNREACHABLE();
4181 }
4182 break;
4183 }
4184 case XIHF:
4185 case XILF: {
4186 int r1 = rilInstr->R1Value();
4187 uint32_t imm = rilInstr->I2UnsignedValue();
4188 uint32_t alu_out = 0;
4189 if (op == XILF) {
4190 alu_out = get_low_register<uint32_t>(r1);
4191 alu_out = alu_out ^ imm;
4192 set_low_register(r1, alu_out);
4193 } else if (op == XIHF) {
4194 alu_out = get_high_register<uint32_t>(r1);
4195 alu_out = alu_out ^ imm;
4196 set_high_register(r1, alu_out);
4197 } else {
4198 UNREACHABLE();
4199 }
4200 SetS390BitWiseConditionCode<uint32_t>(alu_out);
4201 break;
4202 }
4203 case RISBG: {
4204 // Rotate then insert selected bits
4205 int r1 = rieInstr->R1Value();
4206 int r2 = rieInstr->R2Value();
4207 // Starting Bit Position is Bits 2-7 of I3 field
4208 uint32_t start_bit = rieInstr->I3Value() & 0x3F;
4209 // Ending Bit Position is Bits 2-7 of I4 field
4210 uint32_t end_bit = rieInstr->I4Value() & 0x3F;
4211 // Shift Amount is Bits 2-7 of I5 field
4212 uint32_t shift_amount = rieInstr->I5Value() & 0x3F;
4213 // Zero out Remaining (unslected) bits if Bit 0 of I4 is 1.
4214 bool zero_remaining = (0 != (rieInstr->I4Value() & 0x80));
4215
4216 uint64_t src_val = get_register(r2);
4217
4218 // Rotate Left by Shift Amount first
4219 uint64_t rotated_val =
4220 (src_val << shift_amount) | (src_val >> (64 - shift_amount));
4221 int32_t width = end_bit - start_bit + 1;
4222
4223 uint64_t selection_mask = 0;
4224 if (width < 64) {
4225 selection_mask = (static_cast<uint64_t>(1) << width) - 1;
4226 } else {
4227 selection_mask = static_cast<uint64_t>(static_cast<int64_t>(-1));
4228 }
4229 selection_mask = selection_mask << (63 - end_bit);
4230
4231 uint64_t selected_val = rotated_val & selection_mask;
4232
4233 if (!zero_remaining) {
4234 // Merged the unselected bits from the original value
4235 selected_val = (src_val & ~selection_mask) | selected_val;
4236 }
4237
4238 // Condition code is set by treating result as 64-bit signed int
4239 SetS390ConditionCode<int64_t>(selected_val, 0);
4240 set_register(r1, selected_val);
4241 break;
4242 }
4243 default:
4244 return DecodeSixByteArithmetic(instr);
4245 }
4246 return true;
4247}
4248
4249void Simulator::DecodeSixByteBitShift(Instruction* instr) {
4250 Opcode op = instr->S390OpcodeValue();
4251
4252 // Pre-cast instruction to various types
4253
4254 RSYInstruction* rsyInstr = reinterpret_cast<RSYInstruction*>(instr);
4255
4256 switch (op) {
4257 case SLLK:
4258 case RLL:
4259 case SRLK: {
4260 // For SLLK/SRLL, the 32-bit third operand is shifted the number
4261 // of bits specified by the second-operand address, and the result is
4262 // placed at the first-operand location. Except for when the R1 and R3
4263 // fields designate the same register, the third operand remains
4264 // unchanged in general register R3.
4265 int r1 = rsyInstr->R1Value();
4266 int r3 = rsyInstr->R3Value();
4267 int b2 = rsyInstr->B2Value();
4268 intptr_t d2 = rsyInstr->D2Value();
4269 // only takes rightmost 6 bits
4270 int64_t b2_val = (b2 == 0) ? 0 : get_register(b2);
4271 int shiftBits = (b2_val + d2) & 0x3F;
4272 // unsigned
4273 uint32_t r3_val = get_low_register<uint32_t>(r3);
4274 uint32_t alu_out = 0;
4275 if (SLLK == op) {
4276 alu_out = r3_val << shiftBits;
4277 } else if (SRLK == op) {
4278 alu_out = r3_val >> shiftBits;
4279 } else if (RLL == op) {
4280 uint32_t rotateBits = r3_val >> (32 - shiftBits);
4281 alu_out = (r3_val << shiftBits) | (rotateBits);
4282 } else {
4283 UNREACHABLE();
4284 }
4285 set_low_register(r1, alu_out);
4286 break;
4287 }
4288 case SLLG:
4289 case RLLG:
4290 case SRLG: {
4291 // For SLLG/SRLG, the 64-bit third operand is shifted the number
4292 // of bits specified by the second-operand address, and the result is
4293 // placed at the first-operand location. Except for when the R1 and R3
4294 // fields designate the same register, the third operand remains
4295 // unchanged in general register R3.
4296 int r1 = rsyInstr->R1Value();
4297 int r3 = rsyInstr->R3Value();
4298 int b2 = rsyInstr->B2Value();
4299 intptr_t d2 = rsyInstr->D2Value();
4300 // only takes rightmost 6 bits
4301 int64_t b2_val = (b2 == 0) ? 0 : get_register(b2);
4302 int shiftBits = (b2_val + d2) & 0x3F;
4303 // unsigned
4304 uint64_t r3_val = get_register(r3);
4305 uint64_t alu_out = 0;
4306 if (op == SLLG) {
4307 alu_out = r3_val << shiftBits;
4308 } else if (op == SRLG) {
4309 alu_out = r3_val >> shiftBits;
4310 } else if (op == RLLG) {
4311 uint64_t rotateBits = r3_val >> (64 - shiftBits);
4312 alu_out = (r3_val << shiftBits) | (rotateBits);
4313 } else {
4314 UNREACHABLE();
4315 }
4316 set_register(r1, alu_out);
4317 break;
4318 }
4319 default:
4320 UNREACHABLE();
4321 }
4322}
4323
4324/**
4325 * Decodes and simulates six byte arithmetic instructions
4326 */
4327bool Simulator::DecodeSixByteArithmetic(Instruction* instr) {
4328 Opcode op = instr->S390OpcodeValue();
4329
4330 // Pre-cast instruction to various types
4331 SIYInstruction* siyInstr = reinterpret_cast<SIYInstruction*>(instr);
4332
4333 switch (op) {
4334 case CDB:
4335 case ADB:
4336 case SDB:
4337 case MDB:
4338 case DDB:
4339 case SQDB: {
4340 RXEInstruction* rxeInstr = reinterpret_cast<RXEInstruction*>(instr);
4341 int b2 = rxeInstr->B2Value();
4342 int x2 = rxeInstr->X2Value();
4343 int64_t b2_val = (b2 == 0) ? 0 : get_register(b2);
4344 int64_t x2_val = (x2 == 0) ? 0 : get_register(x2);
4345 intptr_t d2_val = rxeInstr->D2Value();
4346 double r1_val = get_double_from_d_register(rxeInstr->R1Value());
4347 double dbl_val = ReadDouble(b2_val + x2_val + d2_val);
4348
4349 switch (op) {
4350 case CDB:
4351 SetS390ConditionCode<double>(r1_val, dbl_val);
4352 break;
4353 case ADB:
4354 r1_val += dbl_val;
4355 set_d_register_from_double(r1, r1_val);
4356 SetS390ConditionCode<double>(r1_val, 0);
4357 break;
4358 case SDB:
4359 r1_val -= dbl_val;
4360 set_d_register_from_double(r1, r1_val);
4361 SetS390ConditionCode<double>(r1_val, 0);
4362 break;
4363 case MDB:
4364 r1_val *= dbl_val;
4365 set_d_register_from_double(r1, r1_val);
4366 SetS390ConditionCode<double>(r1_val, 0);
4367 break;
4368 case DDB:
4369 r1_val /= dbl_val;
4370 set_d_register_from_double(r1, r1_val);
4371 SetS390ConditionCode<double>(r1_val, 0);
4372 break;
4373 case SQDB:
4374 r1_val = std::sqrt(dbl_val);
4375 set_d_register_from_double(r1, r1_val);
4376 default:
4377 UNREACHABLE();
4378 break;
4379 }
4380 break;
4381 }
4382 case LRV:
4383 case LRVH:
4384 case STRV:
4385 case STRVH: {
4386 RXYInstruction* rxyInstr = reinterpret_cast<RXYInstruction*>(instr);
4387 int r1 = rxyInstr->R1Value();
4388 int x2 = rxyInstr->X2Value();
4389 int b2 = rxyInstr->B2Value();
4390 int d2 = rxyInstr->D2Value();
4391 int32_t r1_val = get_low_register<int32_t>(r1);
4392 int64_t x2_val = (x2 == 0) ? 0 : get_register(x2);
4393 int64_t b2_val = (b2 == 0) ? 0 : get_register(b2);
4394 intptr_t mem_addr = b2_val + x2_val + d2;
4395
4396 if (op == LRVH) {
4397 int16_t mem_val = ReadH(mem_addr, instr);
4398 int32_t result = ByteReverse(mem_val) & 0x0000ffff;
4399 result |= r1_val & 0xffff0000;
4400 set_low_register(r1, result);
4401 } else if (op == LRV) {
4402 int32_t mem_val = ReadW(mem_addr, instr);
4403 set_low_register(r1, ByteReverse(mem_val));
4404 } else if (op == STRVH) {
4405 int16_t result = static_cast<int16_t>(r1_val >> 16);
4406 WriteH(mem_addr, ByteReverse(result), instr);
4407 } else if (op == STRV) {
4408 WriteW(mem_addr, ByteReverse(r1_val), instr);
4409 }
4410
4411 break;
4412 }
4413 case AHIK:
4414 case AGHIK: {
4415 // Non-clobbering Add Halfword Immediate
4416 RIEInstruction* rieInst = reinterpret_cast<RIEInstruction*>(instr);
4417 int r1 = rieInst->R1Value();
4418 int r2 = rieInst->R2Value();
4419 bool isOF = false;
4420 if (AHIK == op) {
4421 // 32-bit Add
4422 int32_t r2_val = get_low_register<int32_t>(r2);
4423 int32_t imm = rieInst->I6Value();
4424 isOF = CheckOverflowForIntAdd(r2_val, imm, int32_t);
4425 set_low_register(r1, r2_val + imm);
4426 SetS390ConditionCode<int32_t>(r2_val + imm, 0);
4427 } else if (AGHIK == op) {
4428 // 64-bit Add
4429 int64_t r2_val = get_register(r2);
4430 int64_t imm = static_cast<int64_t>(rieInst->I6Value());
4431 isOF = CheckOverflowForIntAdd(r2_val, imm, int64_t);
4432 set_register(r1, r2_val + imm);
4433 SetS390ConditionCode<int64_t>(r2_val + imm, 0);
4434 }
4435 SetS390OverflowCode(isOF);
4436 break;
4437 }
4438 case ALFI:
4439 case SLFI: {
4440 RILInstruction* rilInstr = reinterpret_cast<RILInstruction*>(instr);
4441 int r1 = rilInstr->R1Value();
4442 uint32_t imm = rilInstr->I2UnsignedValue();
4443 uint32_t alu_out = get_low_register<uint32_t>(r1);
4444 if (op == ALFI) {
4445 alu_out += imm;
4446 } else if (op == SLFI) {
4447 alu_out -= imm;
4448 }
4449 SetS390ConditionCode<uint32_t>(alu_out, 0);
4450 set_low_register(r1, alu_out);
4451 break;
4452 }
4453 case ML: {
4454 UNIMPLEMENTED();
4455 break;
4456 }
4457 case AY:
4458 case SY:
4459 case NY:
4460 case OY:
4461 case XY:
4462 case CY: {
4463 RXYInstruction* rxyInstr = reinterpret_cast<RXYInstruction*>(instr);
4464 int r1 = rxyInstr->R1Value();
4465 int x2 = rxyInstr->X2Value();
4466 int b2 = rxyInstr->B2Value();
4467 int d2 = rxyInstr->D2Value();
4468 int64_t x2_val = (x2 == 0) ? 0 : get_register(x2);
4469 int64_t b2_val = (b2 == 0) ? 0 : get_register(b2);
4470 int32_t alu_out = get_low_register<int32_t>(r1);
4471 int32_t mem_val = ReadW(b2_val + x2_val + d2, instr);
4472 bool isOF = false;
4473 if (op == AY) {
4474 isOF = CheckOverflowForIntAdd(alu_out, mem_val, int32_t);
4475 alu_out += mem_val;
4476 SetS390ConditionCode<int32_t>(alu_out, 0);
4477 SetS390OverflowCode(isOF);
4478 } else if (op == SY) {
4479 isOF = CheckOverflowForIntSub(alu_out, mem_val, int32_t);
4480 alu_out -= mem_val;
4481 SetS390ConditionCode<int32_t>(alu_out, 0);
4482 SetS390OverflowCode(isOF);
4483 } else if (op == NY) {
4484 alu_out &= mem_val;
4485 SetS390BitWiseConditionCode<uint32_t>(alu_out);
4486 } else if (op == OY) {
4487 alu_out |= mem_val;
4488 SetS390BitWiseConditionCode<uint32_t>(alu_out);
4489 } else if (op == XY) {
4490 alu_out ^= mem_val;
4491 SetS390BitWiseConditionCode<uint32_t>(alu_out);
4492 } else if (op == CY) {
4493 SetS390ConditionCode<int32_t>(alu_out, mem_val);
4494 }
4495 if (op != CY) {
4496 set_low_register(r1, alu_out);
4497 }
4498 break;
4499 }
4500 case AHY:
4501 case SHY: {
4502 RXYInstruction* rxyInstr = reinterpret_cast<RXYInstruction*>(instr);
4503 int32_t r1_val = get_low_register<int32_t>(rxyInstr->R1Value());
4504 int b2 = rxyInstr->B2Value();
4505 int x2 = rxyInstr->X2Value();
4506 int64_t b2_val = (b2 == 0) ? 0 : get_register(b2);
4507 int64_t x2_val = (x2 == 0) ? 0 : get_register(x2);
4508 intptr_t d2_val = rxyInstr->D2Value();
4509 int32_t mem_val =
4510 static_cast<int32_t>(ReadH(b2_val + d2_val + x2_val, instr));
4511 int32_t alu_out = 0;
4512 bool isOF = false;
4513 switch (op) {
4514 case AHY:
4515 alu_out = r1_val + mem_val;
4516 isOF = CheckOverflowForIntAdd(r1_val, mem_val, int32_t);
4517 break;
4518 case SHY:
4519 alu_out = r1_val - mem_val;
4520 isOF = CheckOverflowForIntSub(r1_val, mem_val, int64_t);
4521 break;
4522 default:
4523 UNREACHABLE();
4524 break;
4525 }
4526 set_low_register(r1, alu_out);
4527 SetS390ConditionCode<int32_t>(alu_out, 0);
4528 SetS390OverflowCode(isOF);
4529 break;
4530 }
4531 case AG:
4532 case SG:
4533 case NG:
4534 case OG:
4535 case XG:
4536 case CG:
4537 case CLG: {
4538 RXYInstruction* rxyInstr = reinterpret_cast<RXYInstruction*>(instr);
4539 int r1 = rxyInstr->R1Value();
4540 int x2 = rxyInstr->X2Value();
4541 int b2 = rxyInstr->B2Value();
4542 int d2 = rxyInstr->D2Value();
4543 int64_t x2_val = (x2 == 0) ? 0 : get_register(x2);
4544 int64_t b2_val = (b2 == 0) ? 0 : get_register(b2);
4545 int64_t alu_out = get_register(r1);
4546 int64_t mem_val = ReadDW(b2_val + x2_val + d2);
4547
4548 switch (op) {
4549 case AG: {
4550 alu_out += mem_val;
4551 SetS390ConditionCode<int32_t>(alu_out, 0);
4552 break;
4553 }
4554 case SG: {
4555 alu_out -= mem_val;
4556 SetS390ConditionCode<int32_t>(alu_out, 0);
4557 break;
4558 }
4559 case NG: {
4560 alu_out &= mem_val;
4561 SetS390BitWiseConditionCode<uint32_t>(alu_out);
4562 break;
4563 }
4564 case OG: {
4565 alu_out |= mem_val;
4566 SetS390BitWiseConditionCode<uint32_t>(alu_out);
4567 break;
4568 }
4569 case XG: {
4570 alu_out ^= mem_val;
4571 SetS390BitWiseConditionCode<uint32_t>(alu_out);
4572 break;
4573 }
4574 case CG: {
4575 SetS390ConditionCode<int64_t>(alu_out, mem_val);
4576 break;
4577 }
4578 case CLG: {
4579 SetS390ConditionCode<uint64_t>(alu_out, mem_val);
4580 break;
4581 }
4582 default: {
4583 DCHECK(false);
4584 break;
4585 }
4586 }
4587
4588 if (op != CG) {
4589 set_register(r1, alu_out);
4590 }
4591 break;
4592 }
4593 case ALY:
4594 case SLY:
4595 case CLY: {
4596 RXYInstruction* rxyInstr = reinterpret_cast<RXYInstruction*>(instr);
4597 int r1 = rxyInstr->R1Value();
4598 int x2 = rxyInstr->X2Value();
4599 int b2 = rxyInstr->B2Value();
4600 int d2 = rxyInstr->D2Value();
4601 int64_t x2_val = (x2 == 0) ? 0 : get_register(x2);
4602 int64_t b2_val = (b2 == 0) ? 0 : get_register(b2);
4603 uint32_t alu_out = get_low_register<uint32_t>(r1);
4604 uint32_t mem_val = ReadWU(b2_val + x2_val + d2, instr);
4605
4606 if (op == ALY) {
4607 alu_out += mem_val;
4608 set_low_register(r1, alu_out);
4609 SetS390ConditionCode<uint32_t>(alu_out, 0);
4610 } else if (op == SLY) {
4611 alu_out -= mem_val;
4612 set_low_register(r1, alu_out);
4613 SetS390ConditionCode<uint32_t>(alu_out, 0);
4614 } else if (op == CLY) {
4615 SetS390ConditionCode<uint32_t>(alu_out, mem_val);
4616 }
4617 break;
4618 }
4619 case AGFI:
4620 case AFI: {
4621 // Clobbering Add Word Immediate
4622 RILInstruction* rilInstr = reinterpret_cast<RILInstruction*>(instr);
4623 int32_t r1 = rilInstr->R1Value();
4624 bool isOF = false;
4625 if (AFI == op) {
4626 // 32-bit Add (Register + 32-bit Immediate)
4627 int32_t r1_val = get_low_register<int32_t>(r1);
4628 int32_t i2 = rilInstr->I2Value();
4629 isOF = CheckOverflowForIntAdd(r1_val, i2, int32_t);
4630 int32_t alu_out = r1_val + i2;
4631 set_low_register(r1, alu_out);
4632 SetS390ConditionCode<int32_t>(alu_out, 0);
4633 } else if (AGFI == op) {
4634 // 64-bit Add (Register + 32-bit Imm)
4635 int64_t r1_val = get_register(r1);
4636 int64_t i2 = static_cast<int64_t>(rilInstr->I2Value());
4637 isOF = CheckOverflowForIntAdd(r1_val, i2, int64_t);
4638 int64_t alu_out = r1_val + i2;
4639 set_register(r1, alu_out);
4640 SetS390ConditionCode<int64_t>(alu_out, 0);
4641 }
4642 SetS390OverflowCode(isOF);
4643 break;
4644 }
4645 case ASI: {
4646 // TODO(bcleung): Change all fooInstr->I2Value() to template functions.
4647 // The below static cast to 8 bit and then to 32 bit is necessary
4648 // because siyInstr->I2Value() returns a uint8_t, which a direct
4649 // cast to int32_t could incorrectly interpret.
4650 int8_t i2_8bit = static_cast<int8_t>(siyInstr->I2Value());
4651 int32_t i2 = static_cast<int32_t>(i2_8bit);
4652 int b1 = siyInstr->B1Value();
4653 intptr_t b1_val = (b1 == 0) ? 0 : get_register(b1);
4654
4655 int d1_val = siyInstr->D1Value();
4656 intptr_t addr = b1_val + d1_val;
4657
4658 int32_t mem_val = ReadW(addr, instr);
4659 bool isOF = CheckOverflowForIntAdd(mem_val, i2, int32_t);
4660 int32_t alu_out = mem_val + i2;
4661 SetS390ConditionCode<int32_t>(alu_out, 0);
4662 SetS390OverflowCode(isOF);
4663 WriteW(addr, alu_out, instr);
4664 break;
4665 }
4666 case AGSI: {
4667 // TODO(bcleung): Change all fooInstr->I2Value() to template functions.
4668 // The below static cast to 8 bit and then to 32 bit is necessary
4669 // because siyInstr->I2Value() returns a uint8_t, which a direct
4670 // cast to int32_t could incorrectly interpret.
4671 int8_t i2_8bit = static_cast<int8_t>(siyInstr->I2Value());
4672 int64_t i2 = static_cast<int64_t>(i2_8bit);
4673 int b1 = siyInstr->B1Value();
4674 intptr_t b1_val = (b1 == 0) ? 0 : get_register(b1);
4675
4676 int d1_val = siyInstr->D1Value();
4677 intptr_t addr = b1_val + d1_val;
4678
4679 int64_t mem_val = ReadDW(addr);
4680 int isOF = CheckOverflowForIntAdd(mem_val, i2, int64_t);
4681 int64_t alu_out = mem_val + i2;
4682 SetS390ConditionCode<uint64_t>(alu_out, 0);
4683 SetS390OverflowCode(isOF);
4684 WriteDW(addr, alu_out);
4685 break;
4686 }
4687 case AGF:
4688 case SGF:
4689 case ALG:
4690 case SLG: {
4691#ifndef V8_TARGET_ARCH_S390X
4692 DCHECK(false);
4693#endif
4694 RXYInstruction* rxyInstr = reinterpret_cast<RXYInstruction*>(instr);
4695 int r1 = rxyInstr->R1Value();
4696 uint64_t r1_val = get_register(rxyInstr->R1Value());
4697 int b2 = rxyInstr->B2Value();
4698 int x2 = rxyInstr->X2Value();
4699 int64_t b2_val = (b2 == 0) ? 0 : get_register(b2);
4700 int64_t x2_val = (x2 == 0) ? 0 : get_register(x2);
4701 intptr_t d2_val = rxyInstr->D2Value();
4702 uint64_t alu_out = r1_val;
4703 if (op == ALG) {
4704 uint64_t mem_val =
4705 static_cast<uint64_t>(ReadDW(b2_val + d2_val + x2_val));
4706 alu_out += mem_val;
4707 SetS390ConditionCode<uint64_t>(alu_out, 0);
4708 } else if (op == SLG) {
4709 uint64_t mem_val =
4710 static_cast<uint64_t>(ReadDW(b2_val + d2_val + x2_val));
4711 alu_out -= mem_val;
4712 SetS390ConditionCode<uint64_t>(alu_out, 0);
4713 } else if (op == AGF) {
4714 uint32_t mem_val = ReadW(b2_val + d2_val + x2_val, instr);
4715 alu_out += mem_val;
4716 SetS390ConditionCode<int64_t>(alu_out, 0);
4717 } else if (op == SGF) {
4718 uint32_t mem_val = ReadW(b2_val + d2_val + x2_val, instr);
4719 alu_out -= mem_val;
4720 SetS390ConditionCode<int64_t>(alu_out, 0);
4721 } else {
4722 DCHECK(false);
4723 }
4724 set_register(r1, alu_out);
4725 break;
4726 }
4727 case ALGFI:
4728 case SLGFI: {
4729#ifndef V8_TARGET_ARCH_S390X
4730 // should only be called on 64bit
4731 DCHECK(false);
4732#endif
4733 RILInstruction* rilInstr = reinterpret_cast<RILInstruction*>(instr);
4734 int r1 = rilInstr->R1Value();
4735 uint32_t i2 = rilInstr->I2UnsignedValue();
4736 uint64_t r1_val = (uint64_t)(get_register(r1));
4737 uint64_t alu_out;
4738 if (op == ALGFI)
4739 alu_out = r1_val + i2;
4740 else
4741 alu_out = r1_val - i2;
4742 set_register(r1, (intptr_t)alu_out);
4743 SetS390ConditionCode<uint64_t>(alu_out, 0);
4744 break;
4745 }
4746 case MSY:
4747 case MSG: {
4748 RXYInstruction* rxyInstr = reinterpret_cast<RXYInstruction*>(instr);
4749 int r1 = rxyInstr->R1Value();
4750 int b2 = rxyInstr->B2Value();
4751 int x2 = rxyInstr->X2Value();
4752 int64_t b2_val = (b2 == 0) ? 0 : get_register(b2);
4753 int64_t x2_val = (x2 == 0) ? 0 : get_register(x2);
4754 intptr_t d2_val = rxyInstr->D2Value();
4755 if (op == MSY) {
4756 int32_t mem_val = ReadW(b2_val + d2_val + x2_val, instr);
4757 int32_t r1_val = get_low_register<int32_t>(r1);
4758 set_low_register(r1, mem_val * r1_val);
4759 } else if (op == MSG) {
4760 int64_t mem_val = ReadDW(b2_val + d2_val + x2_val);
4761 int64_t r1_val = get_register(r1);
4762 set_register(r1, mem_val * r1_val);
4763 } else {
4764 UNREACHABLE();
4765 }
4766 break;
4767 }
4768 case MSFI:
4769 case MSGFI: {
4770 RILInstruction* rilinst = reinterpret_cast<RILInstruction*>(instr);
4771 int r1 = rilinst->R1Value();
4772 int32_t i2 = rilinst->I2Value();
4773 if (op == MSFI) {
4774 int32_t alu_out = get_low_register<int32_t>(r1);
4775 alu_out = alu_out * i2;
4776 set_low_register(r1, alu_out);
4777 } else if (op == MSGFI) {
4778 int64_t alu_out = get_register(r1);
4779 alu_out = alu_out * i2;
4780 set_register(r1, alu_out);
4781 } else {
4782 UNREACHABLE();
4783 }
4784 break;
4785 }
4786 default:
4787 UNREACHABLE();
4788 return false;
4789 }
4790 return true;
4791}
4792
4793int16_t Simulator::ByteReverse(int16_t hword) {
4794 return (hword << 8) | ((hword >> 8) & 0x00ff);
4795}
4796
4797int32_t Simulator::ByteReverse(int32_t word) {
4798 int32_t result = word << 24;
4799 result |= (word << 8) & 0x00ff0000;
4800 result |= (word >> 8) & 0x0000ff00;
4801 result |= (word >> 24) & 0x00000ff;
4802 return result;
4803}
4804
4805// Executes the current instruction.
4806void Simulator::ExecuteInstruction(Instruction* instr, bool auto_incr_pc) {
4807 if (v8::internal::FLAG_check_icache) {
4808 CheckICache(isolate_->simulator_i_cache(), instr);
4809 }
4810 pc_modified_ = false;
4811 if (::v8::internal::FLAG_trace_sim) {
4812 disasm::NameConverter converter;
4813 disasm::Disassembler dasm(converter);
4814 // use a reasonably large buffer
4815 v8::internal::EmbeddedVector<char, 256> buffer;
4816 dasm.InstructionDecode(buffer, reinterpret_cast<byte*>(instr));
4817#ifdef V8_TARGET_ARCH_S390X
4818 PrintF("%05ld %08" V8PRIxPTR " %s\n", icount_,
4819 reinterpret_cast<intptr_t>(instr), buffer.start());
4820#else
4821 PrintF("%05lld %08" V8PRIxPTR " %s\n", icount_,
4822 reinterpret_cast<intptr_t>(instr), buffer.start());
4823#endif
4824 // Flush stdout to prevent incomplete file output during abnormal exits
4825 // This is caused by the output being buffered before being written to file
4826 fflush(stdout);
4827 }
4828
4829 // Try to simulate as S390 Instruction first.
4830 bool processed = true;
4831
4832 int instrLength = instr->InstructionLength();
4833 if (instrLength == 2)
4834 processed = DecodeTwoByte(instr);
4835 else if (instrLength == 4)
4836 processed = DecodeFourByte(instr);
4837 else if (instrLength == 6)
4838 processed = DecodeSixByte(instr);
4839
4840 if (processed) {
4841 if (!pc_modified_ && auto_incr_pc) {
4842 set_pc(reinterpret_cast<intptr_t>(instr) + instrLength);
4843 }
4844 return;
4845 }
4846}
4847
4848void Simulator::DebugStart() {
4849 S390Debugger dbg(this);
4850 dbg.Debug();
4851}
4852
4853void Simulator::Execute() {
4854 // Get the PC to simulate. Cannot use the accessor here as we need the
4855 // raw PC value and not the one used as input to arithmetic instructions.
4856 intptr_t program_counter = get_pc();
4857
4858 if (::v8::internal::FLAG_stop_sim_at == 0) {
4859 // Fast version of the dispatch loop without checking whether the simulator
4860 // should be stopping at a particular executed instruction.
4861 while (program_counter != end_sim_pc) {
4862 Instruction* instr = reinterpret_cast<Instruction*>(program_counter);
4863 icount_++;
4864 ExecuteInstruction(instr);
4865 program_counter = get_pc();
4866 }
4867 } else {
4868 // FLAG_stop_sim_at is at the non-default value. Stop in the debugger when
4869 // we reach the particular instuction count.
4870 while (program_counter != end_sim_pc) {
4871 Instruction* instr = reinterpret_cast<Instruction*>(program_counter);
4872 icount_++;
4873 if (icount_ == ::v8::internal::FLAG_stop_sim_at) {
4874 S390Debugger dbg(this);
4875 dbg.Debug();
4876 } else {
4877 ExecuteInstruction(instr);
4878 }
4879 program_counter = get_pc();
4880 }
4881 }
4882}
4883
4884void Simulator::CallInternal(byte* entry, int reg_arg_count) {
4885 // Prepare to execute the code at entry
4886 if (ABI_USES_FUNCTION_DESCRIPTORS) {
4887 // entry is the function descriptor
4888 set_pc(*(reinterpret_cast<intptr_t*>(entry)));
4889 } else {
4890 // entry is the instruction address
4891 set_pc(reinterpret_cast<intptr_t>(entry));
4892 }
4893 // Remember the values of non-volatile registers.
4894 int64_t r6_val = get_register(r6);
4895 int64_t r7_val = get_register(r7);
4896 int64_t r8_val = get_register(r8);
4897 int64_t r9_val = get_register(r9);
4898 int64_t r10_val = get_register(r10);
4899 int64_t r11_val = get_register(r11);
4900 int64_t r12_val = get_register(r12);
4901 int64_t r13_val = get_register(r13);
4902
4903 if (ABI_CALL_VIA_IP) {
4904 // Put target address in ip (for JS prologue).
4905 set_register(ip, get_pc());
4906 }
4907
4908 // Put down marker for end of simulation. The simulator will stop simulation
4909 // when the PC reaches this value. By saving the "end simulation" value into
4910 // the LR the simulation stops when returning to this call point.
4911 registers_[14] = end_sim_pc;
4912
4913 // Set up the non-volatile registers with a known value. To be able to check
4914 // that they are preserved properly across JS execution.
4915 intptr_t callee_saved_value = icount_;
4916 if (reg_arg_count < 5) {
4917 set_register(r6, callee_saved_value + 6);
4918 }
4919 set_register(r7, callee_saved_value + 7);
4920 set_register(r8, callee_saved_value + 8);
4921 set_register(r9, callee_saved_value + 9);
4922 set_register(r10, callee_saved_value + 10);
4923 set_register(r11, callee_saved_value + 11);
4924 set_register(r12, callee_saved_value + 12);
4925 set_register(r13, callee_saved_value + 13);
4926
4927 // Start the simulation
4928 Execute();
4929
4930// Check that the non-volatile registers have been preserved.
4931#ifndef V8_TARGET_ARCH_S390X
4932 if (reg_arg_count < 5) {
4933 DCHECK_EQ(callee_saved_value + 6, get_low_register<int32_t>(r6));
4934 }
4935 DCHECK_EQ(callee_saved_value + 7, get_low_register<int32_t>(r7));
4936 DCHECK_EQ(callee_saved_value + 8, get_low_register<int32_t>(r8));
4937 DCHECK_EQ(callee_saved_value + 9, get_low_register<int32_t>(r9));
4938 DCHECK_EQ(callee_saved_value + 10, get_low_register<int32_t>(r10));
4939 DCHECK_EQ(callee_saved_value + 11, get_low_register<int32_t>(r11));
4940 DCHECK_EQ(callee_saved_value + 12, get_low_register<int32_t>(r12));
4941 DCHECK_EQ(callee_saved_value + 13, get_low_register<int32_t>(r13));
4942#else
4943 if (reg_arg_count < 5) {
4944 DCHECK_EQ(callee_saved_value + 6, get_register(r6));
4945 }
4946 DCHECK_EQ(callee_saved_value + 7, get_register(r7));
4947 DCHECK_EQ(callee_saved_value + 8, get_register(r8));
4948 DCHECK_EQ(callee_saved_value + 9, get_register(r9));
4949 DCHECK_EQ(callee_saved_value + 10, get_register(r10));
4950 DCHECK_EQ(callee_saved_value + 11, get_register(r11));
4951 DCHECK_EQ(callee_saved_value + 12, get_register(r12));
4952 DCHECK_EQ(callee_saved_value + 13, get_register(r13));
4953#endif
4954
4955 // Restore non-volatile registers with the original value.
4956 set_register(r6, r6_val);
4957 set_register(r7, r7_val);
4958 set_register(r8, r8_val);
4959 set_register(r9, r9_val);
4960 set_register(r10, r10_val);
4961 set_register(r11, r11_val);
4962 set_register(r12, r12_val);
4963 set_register(r13, r13_val);
4964}
4965
4966intptr_t Simulator::Call(byte* entry, int argument_count, ...) {
4967 // Remember the values of non-volatile registers.
4968 int64_t r6_val = get_register(r6);
4969 int64_t r7_val = get_register(r7);
4970 int64_t r8_val = get_register(r8);
4971 int64_t r9_val = get_register(r9);
4972 int64_t r10_val = get_register(r10);
4973 int64_t r11_val = get_register(r11);
4974 int64_t r12_val = get_register(r12);
4975 int64_t r13_val = get_register(r13);
4976
4977 va_list parameters;
4978 va_start(parameters, argument_count);
4979 // Set up arguments
4980
4981 // First 5 arguments passed in registers r2-r6.
4982 int reg_arg_count = (argument_count > 5) ? 5 : argument_count;
4983 int stack_arg_count = argument_count - reg_arg_count;
4984 for (int i = 0; i < reg_arg_count; i++) {
4985 intptr_t value = va_arg(parameters, intptr_t);
4986 set_register(i + 2, value);
4987 }
4988
4989 // Remaining arguments passed on stack.
4990 int64_t original_stack = get_register(sp);
4991 // Compute position of stack on entry to generated code.
4992 intptr_t entry_stack =
4993 (original_stack -
4994 (kCalleeRegisterSaveAreaSize + stack_arg_count * sizeof(intptr_t)));
4995 if (base::OS::ActivationFrameAlignment() != 0) {
4996 entry_stack &= -base::OS::ActivationFrameAlignment();
4997 }
4998
4999 // Store remaining arguments on stack, from low to high memory.
5000 intptr_t* stack_argument =
5001 reinterpret_cast<intptr_t*>(entry_stack + kCalleeRegisterSaveAreaSize);
5002 for (int i = 0; i < stack_arg_count; i++) {
5003 intptr_t value = va_arg(parameters, intptr_t);
5004 stack_argument[i] = value;
5005 }
5006 va_end(parameters);
5007 set_register(sp, entry_stack);
5008
5009// Prepare to execute the code at entry
5010#if ABI_USES_FUNCTION_DESCRIPTORS
5011 // entry is the function descriptor
5012 set_pc(*(reinterpret_cast<intptr_t*>(entry)));
5013#else
5014 // entry is the instruction address
5015 set_pc(reinterpret_cast<intptr_t>(entry));
5016#endif
5017
5018 // Put target address in ip (for JS prologue).
5019 set_register(r12, get_pc());
5020
5021 // Put down marker for end of simulation. The simulator will stop simulation
5022 // when the PC reaches this value. By saving the "end simulation" value into
5023 // the LR the simulation stops when returning to this call point.
5024 registers_[14] = end_sim_pc;
5025
5026 // Set up the non-volatile registers with a known value. To be able to check
5027 // that they are preserved properly across JS execution.
5028 intptr_t callee_saved_value = icount_;
5029 if (reg_arg_count < 5) {
5030 set_register(r6, callee_saved_value + 6);
5031 }
5032 set_register(r7, callee_saved_value + 7);
5033 set_register(r8, callee_saved_value + 8);
5034 set_register(r9, callee_saved_value + 9);
5035 set_register(r10, callee_saved_value + 10);
5036 set_register(r11, callee_saved_value + 11);
5037 set_register(r12, callee_saved_value + 12);
5038 set_register(r13, callee_saved_value + 13);
5039
5040 // Start the simulation
5041 Execute();
5042
5043// Check that the non-volatile registers have been preserved.
5044#ifndef V8_TARGET_ARCH_S390X
5045 if (reg_arg_count < 5) {
5046 DCHECK_EQ(callee_saved_value + 6, get_low_register<int32_t>(r6));
5047 }
5048 DCHECK_EQ(callee_saved_value + 7, get_low_register<int32_t>(r7));
5049 DCHECK_EQ(callee_saved_value + 8, get_low_register<int32_t>(r8));
5050 DCHECK_EQ(callee_saved_value + 9, get_low_register<int32_t>(r9));
5051 DCHECK_EQ(callee_saved_value + 10, get_low_register<int32_t>(r10));
5052 DCHECK_EQ(callee_saved_value + 11, get_low_register<int32_t>(r11));
5053 DCHECK_EQ(callee_saved_value + 12, get_low_register<int32_t>(r12));
5054 DCHECK_EQ(callee_saved_value + 13, get_low_register<int32_t>(r13));
5055#else
5056 if (reg_arg_count < 5) {
5057 DCHECK_EQ(callee_saved_value + 6, get_register(r6));
5058 }
5059 DCHECK_EQ(callee_saved_value + 7, get_register(r7));
5060 DCHECK_EQ(callee_saved_value + 8, get_register(r8));
5061 DCHECK_EQ(callee_saved_value + 9, get_register(r9));
5062 DCHECK_EQ(callee_saved_value + 10, get_register(r10));
5063 DCHECK_EQ(callee_saved_value + 11, get_register(r11));
5064 DCHECK_EQ(callee_saved_value + 12, get_register(r12));
5065 DCHECK_EQ(callee_saved_value + 13, get_register(r13));
5066#endif
5067
5068 // Restore non-volatile registers with the original value.
5069 set_register(r6, r6_val);
5070 set_register(r7, r7_val);
5071 set_register(r8, r8_val);
5072 set_register(r9, r9_val);
5073 set_register(r10, r10_val);
5074 set_register(r11, r11_val);
5075 set_register(r12, r12_val);
5076 set_register(r13, r13_val);
5077// Pop stack passed arguments.
5078
5079#ifndef V8_TARGET_ARCH_S390X
5080 DCHECK_EQ(entry_stack, get_low_register<int32_t>(sp));
5081#else
5082 DCHECK_EQ(entry_stack, get_register(sp));
5083#endif
5084 set_register(sp, original_stack);
5085
5086 // Return value register
5087 intptr_t result = get_register(r2);
5088 return result;
5089}
5090
5091void Simulator::CallFP(byte* entry, double d0, double d1) {
5092 set_d_register_from_double(0, d0);
5093 set_d_register_from_double(1, d1);
5094 CallInternal(entry);
5095}
5096
5097int32_t Simulator::CallFPReturnsInt(byte* entry, double d0, double d1) {
5098 CallFP(entry, d0, d1);
5099 int32_t result = get_register(r2);
5100 return result;
5101}
5102
5103double Simulator::CallFPReturnsDouble(byte* entry, double d0, double d1) {
5104 CallFP(entry, d0, d1);
5105 return get_double_from_d_register(0);
5106}
5107
5108uintptr_t Simulator::PushAddress(uintptr_t address) {
5109 uintptr_t new_sp = get_register(sp) - sizeof(uintptr_t);
5110 uintptr_t* stack_slot = reinterpret_cast<uintptr_t*>(new_sp);
5111 *stack_slot = address;
5112 set_register(sp, new_sp);
5113 return new_sp;
5114}
5115
5116uintptr_t Simulator::PopAddress() {
5117 uintptr_t current_sp = get_register(sp);
5118 uintptr_t* stack_slot = reinterpret_cast<uintptr_t*>(current_sp);
5119 uintptr_t address = *stack_slot;
5120 set_register(sp, current_sp + sizeof(uintptr_t));
5121 return address;
5122}
5123
5124} // namespace internal
5125} // namespace v8
5126
5127#endif // USE_SIMULATOR
5128#endif // V8_TARGET_ARCH_S390