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

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

Issue 1725243004: S390: Initial impl of S390 asm, masm, code-stubs,... (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Updated BUILD.gn + cpu-s390.cc to addr @jochen's comments. Created 4 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright 2014 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include <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.
22 namespace v8 {
23 namespace 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.
33 class 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
69 S390Debugger::~S390Debugger() {}
70
71 #ifdef GENERATED_CODE_COVERAGE
72 static FILE* coverage_log = NULL;
73
74 static 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
81 void 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
109 static void InitializeCoverage() {}
110
111 void 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
132 intptr_t S390Debugger::GetRegisterValue(int regnum) {
133 return sim_->get_register(regnum);
134 }
135
136 double S390Debugger::GetRegisterPairDoubleValue(int regnum) {
137 return sim_->get_double_from_register_pair(regnum);
138 }
139
140 double S390Debugger::GetFPDoubleRegisterValue(int regnum) {
141 return sim_->get_double_from_d_register(regnum);
142 }
143
144 float S390Debugger::GetFPFloatRegisterValue(int regnum) {
145 return sim_->get_float32_from_d_register(regnum);
146 }
147
148 bool 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
165 bool 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
174 bool 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
188 bool 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
198 void S390Debugger::UndoBreakpoints() {
199 if (sim_->break_pc_ != NULL) {
200 sim_->break_pc_->SetInstructionBits(sim_->break_instr_);
201 }
202 }
203
204 void S390Debugger::RedoBreakpoints() {
205 if (sim_->break_pc_ != NULL) {
206 sim_->break_pc_->SetInstructionBits(kBreakpointInstr);
207 }
208 }
209
210 void 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
658 static 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
664 static uint32_t ICacheHash(void* key) {
665 return static_cast<uint32_t>(reinterpret_cast<uintptr_t>(key)) >> 2;
666 }
667
668 static 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
674 void Simulator::set_last_debugger_input(char* input) {
675 DeleteArray(last_debugger_input_);
676 last_debugger_input_ = input;
677 }
678
679 void 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
700 CachePage* 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.
711 void 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
724 void 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
746 void 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
753 Simulator::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
803 Simulator::~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.
812 class 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
897 void 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
908 void* 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.
916 Simulator* 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.
931 void 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.
937 uint64_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
946 template <typename T>
947 T 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
956 template <typename T>
957 T 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
966 void 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
973 void 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
980 double 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.
995 void Simulator::set_pc(intptr_t value) {
996 pc_modified_ = true;
997 special_reg_pc_ = value;
998 }
999
1000 bool 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.
1005 intptr_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.
1011 void 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.
1018 void Simulator::SetFpResult(const double& result) {
1019 set_d_register_from_double(0, result);
1020 }
1021
1022 void 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
1031 uint32_t Simulator::ReadWU(intptr_t addr, Instruction* instr) {
1032 uint32_t* ptr = reinterpret_cast<uint32_t*>(addr);
1033 return *ptr;
1034 }
1035
1036 int32_t Simulator::ReadW(intptr_t addr, Instruction* instr) {
1037 int32_t* ptr = reinterpret_cast<int32_t*>(addr);
1038 return *ptr;
1039 }
1040
1041 void 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
1047 void 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
1053 uint16_t Simulator::ReadHU(intptr_t addr, Instruction* instr) {
1054 uint16_t* ptr = reinterpret_cast<uint16_t*>(addr);
1055 return *ptr;
1056 }
1057
1058 int16_t Simulator::ReadH(intptr_t addr, Instruction* instr) {
1059 int16_t* ptr = reinterpret_cast<int16_t*>(addr);
1060 return *ptr;
1061 }
1062
1063 void 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
1069 void 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
1075 uint8_t Simulator::ReadBU(intptr_t addr) {
1076 uint8_t* ptr = reinterpret_cast<uint8_t*>(addr);
1077 return *ptr;
1078 }
1079
1080 int8_t Simulator::ReadB(intptr_t addr) {
1081 int8_t* ptr = reinterpret_cast<int8_t*>(addr);
1082 return *ptr;
1083 }
1084
1085 void Simulator::WriteB(intptr_t addr, uint8_t value) {
1086 uint8_t* ptr = reinterpret_cast<uint8_t*>(addr);
1087 *ptr = value;
1088 }
1089
1090 void Simulator::WriteB(intptr_t addr, int8_t value) {
1091 int8_t* ptr = reinterpret_cast<int8_t*>(addr);
1092 *ptr = value;
1093 }
1094
1095 int64_t Simulator::ReadDW(intptr_t addr) {
1096 int64_t* ptr = reinterpret_cast<int64_t*>(addr);
1097 return *ptr;
1098 }
1099
1100 void 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 */
1109 double 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.
1115 uintptr_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.
1128 void 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.
1135 bool 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.
1145 bool 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.
1153 bool Simulator::OverflowFrom(int32_t alu_out, int32_t left, int32_t right,
1154 bool addition) {
1155 bool overflow;
1156 if (addition) {
1157 // operands have the same sign
1158 overflow = ((left >= 0 && right >= 0) || (left < 0 && right < 0))
1159 // and operands and result have different sign
1160 && ((left < 0 && alu_out >= 0) || (left >= 0 && alu_out < 0));
1161 } else {
1162 // operands have different signs
1163 overflow = ((left < 0 && right >= 0) || (left >= 0 && right < 0))
1164 // and first operand and result have different signs
1165 && ((left < 0 && alu_out >= 0) || (left >= 0 && alu_out < 0));
1166 }
1167 return overflow;
1168 }
1169
1170 #if V8_TARGET_ARCH_S390X
1171 static void decodeObjectPair(ObjectPair* pair, intptr_t* x, intptr_t* y) {
1172 *x = reinterpret_cast<intptr_t>(pair->x);
1173 *y = reinterpret_cast<intptr_t>(pair->y);
1174 }
1175 #else
1176 static void decodeObjectPair(ObjectPair* pair, intptr_t* x, intptr_t* y) {
1177 #if V8_TARGET_BIG_ENDIAN
1178 *x = static_cast<int32_t>(*pair >> 32);
1179 *y = static_cast<int32_t>(*pair);
1180 #else
1181 *x = static_cast<int32_t>(*pair);
1182 *y = static_cast<int32_t>(*pair >> 32);
1183 #endif
1184 }
1185 #endif
1186
1187 // Calls into the V8 runtime.
1188 typedef intptr_t (*SimulatorRuntimeCall)(intptr_t arg0, intptr_t arg1,
1189 intptr_t arg2, intptr_t arg3,
1190 intptr_t arg4, intptr_t arg5);
1191 typedef ObjectPair (*SimulatorRuntimePairCall)(intptr_t arg0, intptr_t arg1,
1192 intptr_t arg2, intptr_t arg3,
1193 intptr_t arg4, intptr_t arg5);
1194 typedef ObjectTriple (*SimulatorRuntimeTripleCall)(intptr_t arg0, intptr_t arg1,
1195 intptr_t arg2, intptr_t arg3,
1196 intptr_t arg4,
1197 intptr_t arg5);
1198
1199 // These prototypes handle the four types of FP calls.
1200 typedef int (*SimulatorRuntimeCompareCall)(double darg0, double darg1);
1201 typedef double (*SimulatorRuntimeFPFPCall)(double darg0, double darg1);
1202 typedef double (*SimulatorRuntimeFPCall)(double darg0);
1203 typedef double (*SimulatorRuntimeFPIntCall)(double darg0, intptr_t arg0);
1204
1205 // This signature supports direct call in to API function native callback
1206 // (refer to InvocationCallback in v8.h).
1207 typedef void (*SimulatorRuntimeDirectApiCall)(intptr_t arg0);
1208 typedef void (*SimulatorRuntimeProfilingApiCall)(intptr_t arg0, void* arg1);
1209
1210 // This signature supports direct call to accessor getter callback.
1211 typedef void (*SimulatorRuntimeDirectGetterCall)(intptr_t arg0, intptr_t arg1);
1212 typedef void (*SimulatorRuntimeProfilingGetterCall)(intptr_t arg0,
1213 intptr_t arg1, void* arg2);
1214
1215 // Software interrupt instructions are used by the simulator to call into the
1216 // C-based V8 runtime.
1217 void Simulator::SoftwareInterrupt(Instruction* instr) {
1218 int svc = instr->SvcValue();
1219 switch (svc) {
1220 case kCallRtRedirected: {
1221 // Check if stack is aligned. Error if not aligned is reported below to
1222 // include information on the function called.
1223 bool stack_aligned =
1224 (get_register(sp) & (::v8::internal::FLAG_sim_stack_alignment - 1)) ==
1225 0;
1226 Redirection* redirection = Redirection::FromSwiInstruction(instr);
1227 const int kArgCount = 6;
1228 int arg0_regnum = 2;
1229 intptr_t result_buffer = 0;
1230 bool uses_result_buffer =
1231 redirection->type() == ExternalReference::BUILTIN_CALL_TRIPLE ||
1232 (redirection->type() == ExternalReference::BUILTIN_CALL_PAIR &&
1233 !ABI_RETURNS_OBJECTPAIR_IN_REGS);
1234 if (uses_result_buffer) {
1235 result_buffer = get_register(r2);
1236 arg0_regnum++;
1237 }
1238 intptr_t arg[kArgCount];
1239 for (int i = 0; i < kArgCount - 1; i++) {
1240 arg[i] = get_register(arg0_regnum + i);
1241 }
1242 intptr_t* stack_pointer = reinterpret_cast<intptr_t*>(get_register(sp));
1243 arg[5] = stack_pointer[kCalleeRegisterSaveAreaSize / kPointerSize];
1244 bool fp_call =
1245 (redirection->type() == ExternalReference::BUILTIN_FP_FP_CALL) ||
1246 (redirection->type() == ExternalReference::BUILTIN_COMPARE_CALL) ||
1247 (redirection->type() == ExternalReference::BUILTIN_FP_CALL) ||
1248 (redirection->type() == ExternalReference::BUILTIN_FP_INT_CALL);
1249
1250 // Place the return address on the stack, making the call GC safe.
1251 *reinterpret_cast<intptr_t*>(get_register(sp) +
1252 kStackFrameRASlot * kPointerSize) =
1253 get_register(r14);
1254
1255 intptr_t external =
1256 reinterpret_cast<intptr_t>(redirection->external_function());
1257 if (fp_call) {
1258 double dval0, dval1; // one or two double parameters
1259 intptr_t ival; // zero or one integer parameters
1260 int iresult = 0; // integer return value
1261 double dresult = 0; // double return value
1262 GetFpArgs(&dval0, &dval1, &ival);
1263 if (::v8::internal::FLAG_trace_sim || !stack_aligned) {
1264 SimulatorRuntimeCall generic_target =
1265 reinterpret_cast<SimulatorRuntimeCall>(external);
1266 switch (redirection->type()) {
1267 case ExternalReference::BUILTIN_FP_FP_CALL:
1268 case ExternalReference::BUILTIN_COMPARE_CALL:
1269 PrintF("Call to host function at %p with args %f, %f",
1270 FUNCTION_ADDR(generic_target), dval0, dval1);
1271 break;
1272 case ExternalReference::BUILTIN_FP_CALL:
1273 PrintF("Call to host function at %p with arg %f",
1274 FUNCTION_ADDR(generic_target), dval0);
1275 break;
1276 case ExternalReference::BUILTIN_FP_INT_CALL:
1277 PrintF("Call to host function at %p with args %f, %" V8PRIdPTR,
1278 FUNCTION_ADDR(generic_target), dval0, ival);
1279 break;
1280 default:
1281 UNREACHABLE();
1282 break;
1283 }
1284 if (!stack_aligned) {
1285 PrintF(" with unaligned stack %08" V8PRIxPTR "\n",
1286 static_cast<intptr_t>(get_register(sp)));
1287 }
1288 PrintF("\n");
1289 }
1290 CHECK(stack_aligned);
1291 switch (redirection->type()) {
1292 case ExternalReference::BUILTIN_COMPARE_CALL: {
1293 SimulatorRuntimeCompareCall target =
1294 reinterpret_cast<SimulatorRuntimeCompareCall>(external);
1295 iresult = target(dval0, dval1);
1296 set_register(r2, iresult);
1297 break;
1298 }
1299 case ExternalReference::BUILTIN_FP_FP_CALL: {
1300 SimulatorRuntimeFPFPCall target =
1301 reinterpret_cast<SimulatorRuntimeFPFPCall>(external);
1302 dresult = target(dval0, dval1);
1303 SetFpResult(dresult);
1304 break;
1305 }
1306 case ExternalReference::BUILTIN_FP_CALL: {
1307 SimulatorRuntimeFPCall target =
1308 reinterpret_cast<SimulatorRuntimeFPCall>(external);
1309 dresult = target(dval0);
1310 SetFpResult(dresult);
1311 break;
1312 }
1313 case ExternalReference::BUILTIN_FP_INT_CALL: {
1314 SimulatorRuntimeFPIntCall target =
1315 reinterpret_cast<SimulatorRuntimeFPIntCall>(external);
1316 dresult = target(dval0, ival);
1317 SetFpResult(dresult);
1318 break;
1319 }
1320 default:
1321 UNREACHABLE();
1322 break;
1323 }
1324 if (::v8::internal::FLAG_trace_sim || !stack_aligned) {
1325 switch (redirection->type()) {
1326 case ExternalReference::BUILTIN_COMPARE_CALL:
1327 PrintF("Returned %08x\n", iresult);
1328 break;
1329 case ExternalReference::BUILTIN_FP_FP_CALL:
1330 case ExternalReference::BUILTIN_FP_CALL:
1331 case ExternalReference::BUILTIN_FP_INT_CALL:
1332 PrintF("Returned %f\n", dresult);
1333 break;
1334 default:
1335 UNREACHABLE();
1336 break;
1337 }
1338 }
1339 } else if (redirection->type() == ExternalReference::DIRECT_API_CALL) {
1340 // See callers of MacroAssembler::CallApiFunctionAndReturn for
1341 // explanation of register usage.
1342 if (::v8::internal::FLAG_trace_sim || !stack_aligned) {
1343 PrintF("Call to host function at %p args %08" V8PRIxPTR,
1344 reinterpret_cast<void*>(external), arg[0]);
1345 if (!stack_aligned) {
1346 PrintF(" with unaligned stack %08" V8PRIxPTR "\n",
1347 static_cast<intptr_t>(get_register(sp)));
1348 }
1349 PrintF("\n");
1350 }
1351 CHECK(stack_aligned);
1352 SimulatorRuntimeDirectApiCall target =
1353 reinterpret_cast<SimulatorRuntimeDirectApiCall>(external);
1354 target(arg[0]);
1355 } else if (redirection->type() == ExternalReference::PROFILING_API_CALL) {
1356 // See callers of MacroAssembler::CallApiFunctionAndReturn for
1357 // explanation of register usage.
1358 if (::v8::internal::FLAG_trace_sim || !stack_aligned) {
1359 PrintF("Call to host function at %p args %08" V8PRIxPTR
1360 " %08" V8PRIxPTR,
1361 reinterpret_cast<void*>(external), arg[0], arg[1]);
1362 if (!stack_aligned) {
1363 PrintF(" with unaligned stack %08" V8PRIxPTR "\n",
1364 static_cast<intptr_t>(get_register(sp)));
1365 }
1366 PrintF("\n");
1367 }
1368 CHECK(stack_aligned);
1369 SimulatorRuntimeProfilingApiCall target =
1370 reinterpret_cast<SimulatorRuntimeProfilingApiCall>(external);
1371 target(arg[0], Redirection::ReverseRedirection(arg[1]));
1372 } else if (redirection->type() == ExternalReference::DIRECT_GETTER_CALL) {
1373 // See callers of MacroAssembler::CallApiFunctionAndReturn for
1374 // explanation of register usage.
1375 if (::v8::internal::FLAG_trace_sim || !stack_aligned) {
1376 PrintF("Call to host function at %p args %08" V8PRIxPTR
1377 " %08" V8PRIxPTR,
1378 reinterpret_cast<void*>(external), arg[0], arg[1]);
1379 if (!stack_aligned) {
1380 PrintF(" with unaligned stack %08" V8PRIxPTR "\n",
1381 static_cast<intptr_t>(get_register(sp)));
1382 }
1383 PrintF("\n");
1384 }
1385 CHECK(stack_aligned);
1386 SimulatorRuntimeDirectGetterCall target =
1387 reinterpret_cast<SimulatorRuntimeDirectGetterCall>(external);
1388 if (!ABI_PASSES_HANDLES_IN_REGS) {
1389 arg[0] = *(reinterpret_cast<intptr_t*>(arg[0]));
1390 }
1391 target(arg[0], arg[1]);
1392 } else if (redirection->type() ==
1393 ExternalReference::PROFILING_GETTER_CALL) {
1394 if (::v8::internal::FLAG_trace_sim || !stack_aligned) {
1395 PrintF("Call to host function at %p args %08" V8PRIxPTR
1396 " %08" V8PRIxPTR " %08" V8PRIxPTR,
1397 reinterpret_cast<void*>(external), arg[0], arg[1], arg[2]);
1398 if (!stack_aligned) {
1399 PrintF(" with unaligned stack %08" V8PRIxPTR "\n",
1400 static_cast<intptr_t>(get_register(sp)));
1401 }
1402 PrintF("\n");
1403 }
1404 CHECK(stack_aligned);
1405 SimulatorRuntimeProfilingGetterCall target =
1406 reinterpret_cast<SimulatorRuntimeProfilingGetterCall>(external);
1407 if (!ABI_PASSES_HANDLES_IN_REGS) {
1408 arg[0] = *(reinterpret_cast<intptr_t*>(arg[0]));
1409 }
1410 target(arg[0], arg[1], Redirection::ReverseRedirection(arg[2]));
1411 } else {
1412 // builtin call.
1413 if (::v8::internal::FLAG_trace_sim || !stack_aligned) {
1414 SimulatorRuntimeCall target =
1415 reinterpret_cast<SimulatorRuntimeCall>(external);
1416 PrintF(
1417 "Call to host function at %p,\n"
1418 "\t\t\t\targs %08" V8PRIxPTR ", %08" V8PRIxPTR ", %08" V8PRIxPTR
1419 ", %08" V8PRIxPTR ", %08" V8PRIxPTR ", %08" V8PRIxPTR,
1420 FUNCTION_ADDR(target), arg[0], arg[1], arg[2], arg[3], arg[4],
1421 arg[5]);
1422 if (!stack_aligned) {
1423 PrintF(" with unaligned stack %08" V8PRIxPTR "\n",
1424 static_cast<intptr_t>(get_register(sp)));
1425 }
1426 PrintF("\n");
1427 }
1428 CHECK(stack_aligned);
1429 if (redirection->type() == ExternalReference::BUILTIN_CALL_TRIPLE) {
1430 SimulatorRuntimeTripleCall target =
1431 reinterpret_cast<SimulatorRuntimeTripleCall>(external);
1432 ObjectTriple result =
1433 target(arg[0], arg[1], arg[2], arg[3], arg[4], arg[5]);
1434 if (::v8::internal::FLAG_trace_sim) {
1435 PrintF("Returned {%08" V8PRIxPTR ", %08" V8PRIxPTR ", %08" V8PRIxPTR
1436 "}\n",
1437 reinterpret_cast<intptr_t>(result.x),
1438 reinterpret_cast<intptr_t>(result.y),
1439 reinterpret_cast<intptr_t>(result.z));
1440 }
1441 memcpy(reinterpret_cast<void*>(result_buffer), &result,
1442 sizeof(ObjectTriple));
1443 set_register(r2, result_buffer);
1444 } else {
1445 if (redirection->type() == ExternalReference::BUILTIN_CALL_PAIR) {
1446 SimulatorRuntimePairCall target =
1447 reinterpret_cast<SimulatorRuntimePairCall>(external);
1448 ObjectPair result =
1449 target(arg[0], arg[1], arg[2], arg[3], arg[4], arg[5]);
1450 intptr_t x;
1451 intptr_t y;
1452 decodeObjectPair(&result, &x, &y);
1453 if (::v8::internal::FLAG_trace_sim) {
1454 PrintF("Returned {%08" V8PRIxPTR ", %08" V8PRIxPTR "}\n", x, y);
1455 }
1456 if (ABI_RETURNS_OBJECTPAIR_IN_REGS) {
1457 set_register(r2, x);
1458 set_register(r3, y);
1459 } else {
1460 memcpy(reinterpret_cast<void*>(result_buffer), &result,
1461 sizeof(ObjectPair));
1462 set_register(r2, result_buffer);
1463 }
1464 } else {
1465 DCHECK(redirection->type() == ExternalReference::BUILTIN_CALL);
1466 SimulatorRuntimeCall target =
1467 reinterpret_cast<SimulatorRuntimeCall>(external);
1468 intptr_t result =
1469 target(arg[0], arg[1], arg[2], arg[3], arg[4], arg[5]);
1470 if (::v8::internal::FLAG_trace_sim) {
1471 PrintF("Returned %08" V8PRIxPTR "\n", result);
1472 }
1473 set_register(r2, result);
1474 }
1475 }
1476 // #if !V8_TARGET_ARCH_S390X
1477 // DCHECK(redirection->type() ==
1478 // ExternalReference::BUILTIN_CALL);
1479 // SimulatorRuntimeCall target =
1480 // reinterpret_cast<SimulatorRuntimeCall>(external);
1481 // int64_t result = target(arg[0], arg[1], arg[2], arg[3],
1482 // arg[4],
1483 // arg[5]);
1484 // int32_t lo_res = static_cast<int32_t>(result);
1485 // int32_t hi_res = static_cast<int32_t>(result >> 32);
1486 // #if !V8_TARGET_LITTLE_ENDIAN
1487 // if (::v8::internal::FLAG_trace_sim) {
1488 // PrintF("Returned %08x\n", hi_res);
1489 // }
1490 // set_register(r2, hi_res);
1491 // set_register(r3, lo_res);
1492 // #else
1493 // if (::v8::internal::FLAG_trace_sim) {
1494 // PrintF("Returned %08x\n", lo_res);
1495 // }
1496 // set_register(r2, lo_res);
1497 // set_register(r3, hi_res);
1498 // #endif
1499 // #else
1500 // if (redirection->type() == ExternalReference::BUILTIN_CALL) {
1501 // SimulatorRuntimeCall target =
1502 // reinterpret_cast<SimulatorRuntimeCall>(external);
1503 // intptr_t result = target(arg[0], arg[1], arg[2], arg[3],
1504 // arg[4],
1505 // arg[5]);
1506 // if (::v8::internal::FLAG_trace_sim) {
1507 // PrintF("Returned %08" V8PRIxPTR "\n", result);
1508 // }
1509 // set_register(r2, result);
1510 // } else {
1511 // DCHECK(redirection->type() ==
1512 // ExternalReference::BUILTIN_CALL_PAIR);
1513 // SimulatorRuntimePairCall target =
1514 // reinterpret_cast<SimulatorRuntimePairCall>(external);
1515 // ObjectPair result = target(arg[0], arg[1], arg[2], arg[3],
1516 // arg[4], arg[5]);
1517 // if (::v8::internal::FLAG_trace_sim) {
1518 // PrintF("Returned %08" V8PRIxPTR ", %08" V8PRIxPTR "\n",
1519 // result.x, result.y);
1520 // }
1521 // #if ABI_RETURNS_OBJECTPAIR_IN_REGS
1522 // set_register(r2, result.x);
1523 // set_register(r3, result.y);
1524 // #else
1525 // memcpy(reinterpret_cast<void *>(result_buffer), &result,
1526 // sizeof(ObjectPair));
1527 // #endif
1528 // }
1529 // #endif
1530 }
1531 int64_t saved_lr = *reinterpret_cast<intptr_t*>(
1532 get_register(sp) + kStackFrameRASlot * kPointerSize);
1533 #if (!V8_TARGET_ARCH_S390X && V8_HOST_ARCH_S390)
1534 // On zLinux-31, the saved_lr might be tagged with a high bit of 1.
1535 // Cleanse it before proceeding with simulation.
1536 saved_lr &= 0x7FFFFFFF;
1537 #endif
1538 set_pc(saved_lr);
1539 break;
1540 }
1541 case kBreakpoint: {
1542 S390Debugger dbg(this);
1543 dbg.Debug();
1544 break;
1545 }
1546 // stop uses all codes greater than 1 << 23.
1547 default: {
1548 if (svc >= (1 << 23)) {
1549 uint32_t code = svc & kStopCodeMask;
1550 if (isWatchedStop(code)) {
1551 IncreaseStopCounter(code);
1552 }
1553 // Stop if it is enabled, otherwise go on jumping over the stop
1554 // and the message address.
1555 if (isEnabledStop(code)) {
1556 S390Debugger dbg(this);
1557 dbg.Stop(instr);
1558 } else {
1559 set_pc(get_pc() + sizeof(FourByteInstr) + kPointerSize);
1560 }
1561 } else {
1562 // This is not a valid svc code.
1563 UNREACHABLE();
1564 break;
1565 }
1566 }
1567 }
1568 }
1569
1570 // Stop helper functions.
1571 bool Simulator::isStopInstruction(Instruction* instr) {
1572 return (instr->Bits(27, 24) == 0xF) && (instr->SvcValue() >= kStopCode);
1573 }
1574
1575 bool Simulator::isWatchedStop(uint32_t code) {
1576 DCHECK(code <= kMaxStopCode);
1577 return code < kNumOfWatchedStops;
1578 }
1579
1580 bool Simulator::isEnabledStop(uint32_t code) {
1581 DCHECK(code <= kMaxStopCode);
1582 // Unwatched stops are always enabled.
1583 return !isWatchedStop(code) ||
1584 !(watched_stops_[code].count & kStopDisabledBit);
1585 }
1586
1587 void Simulator::EnableStop(uint32_t code) {
1588 DCHECK(isWatchedStop(code));
1589 if (!isEnabledStop(code)) {
1590 watched_stops_[code].count &= ~kStopDisabledBit;
1591 }
1592 }
1593
1594 void Simulator::DisableStop(uint32_t code) {
1595 DCHECK(isWatchedStop(code));
1596 if (isEnabledStop(code)) {
1597 watched_stops_[code].count |= kStopDisabledBit;
1598 }
1599 }
1600
1601 void Simulator::IncreaseStopCounter(uint32_t code) {
1602 DCHECK(code <= kMaxStopCode);
1603 DCHECK(isWatchedStop(code));
1604 if ((watched_stops_[code].count & ~(1 << 31)) == 0x7fffffff) {
1605 PrintF(
1606 "Stop counter for code %i has overflowed.\n"
1607 "Enabling this code and reseting the counter to 0.\n",
1608 code);
1609 watched_stops_[code].count = 0;
1610 EnableStop(code);
1611 } else {
1612 watched_stops_[code].count++;
1613 }
1614 }
1615
1616 // Print a stop status.
1617 void Simulator::PrintStopInfo(uint32_t code) {
1618 DCHECK(code <= kMaxStopCode);
1619 if (!isWatchedStop(code)) {
1620 PrintF("Stop not watched.");
1621 } else {
1622 const char* state = isEnabledStop(code) ? "Enabled" : "Disabled";
1623 int32_t count = watched_stops_[code].count & ~kStopDisabledBit;
1624 // Don't print the state of unused breakpoints.
1625 if (count != 0) {
1626 if (watched_stops_[code].desc) {
1627 PrintF("stop %i - 0x%x: \t%s, \tcounter = %i, \t%s\n", code, code,
1628 state, count, watched_stops_[code].desc);
1629 } else {
1630 PrintF("stop %i - 0x%x: \t%s, \tcounter = %i\n", code, code, state,
1631 count);
1632 }
1633 }
1634 }
1635 }
1636
1637 // Method for checking overflow on signed addition:
1638 // Test src1 and src2 have opposite sign,
1639 // (1) No overflow if they have opposite sign
1640 // (2) Test the result and one of the operands have opposite sign
1641 // (a) No overflow if they don't have opposite sign
1642 // (b) Overflow if opposite
1643 #define CheckOverflowForIntAdd(src1, src2) \
1644 (((src1) ^ (src2)) < 0 ? false : ((((src1) + (src2)) ^ (src1)) < 0))
1645
1646 // Method for checking overflow on signed subtraction:
1647 #define CheckOverflowForIntSub(src1, src2) \
1648 (((src1 - src2) < src1) != (src2 > 0))
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
1669 bool 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);
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);
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 SetS390ConditionCode<uint32_t>(alu_out, 0);
1826 SetS390OverflowCode(isOF);
1827 break;
1828 }
1829 case LNR: {
1830 // Load Negative (32)
1831 RRInstruction* rrinst = reinterpret_cast<RRInstruction*>(instr);
1832 int r1 = rrinst->R1Value();
1833 int r2 = rrinst->R2Value();
1834 int32_t r2_val = get_low_register<int32_t>(r2);
1835 r2_val = (r2_val >= 0) ? -r2_val : r2_val; // If pos, then negate it.
1836 set_low_register(r1, r2_val);
1837 condition_reg_ = (r2_val == 0) ? CC_EQ : CC_LT; // CC0 - result is zero
1838 // CC1 - result is negative
1839 break;
1840 }
1841 case BASR: {
1842 RRInstruction* rrinst = reinterpret_cast<RRInstruction*>(instr);
1843 int r1 = rrinst->R1Value();
1844 int r2 = rrinst->R2Value();
1845 intptr_t link_addr = get_pc() + 2;
1846 // If R2 is zero, the BASR does not branch.
1847 int64_t r2_val = (r2 == 0) ? link_addr : get_register(r2);
1848 #if (!V8_TARGET_ARCH_S390X && V8_HOST_ARCH_S390)
1849 // On 31-bit, the top most bit may be 0 or 1, which can cause issues
1850 // for stackwalker. The top bit should either be cleanse before being
1851 // pushed onto the stack, or during stack walking when dereferenced.
1852 // For simulator, we'll take the worst case scenario and always tag
1853 // the high bit, to flush out more problems.
1854 link_addr |= 0x80000000;
1855 #endif
1856 set_register(r1, link_addr);
1857 set_pc(r2_val);
1858 break;
1859 }
1860 case LCR: {
1861 RRInstruction* rrinst = reinterpret_cast<RRInstruction*>(instr);
1862 int r1 = rrinst->R1Value();
1863 int r2 = rrinst->R2Value();
1864 int32_t r2_val = get_low_register<int32_t>(r2);
1865 int32_t original_r2_val = r2_val;
1866 r2_val = ~r2_val;
1867 r2_val = r2_val + 1;
1868 set_low_register(r1, r2_val);
1869 SetS390ConditionCode<int32_t>(r2_val, 0);
1870 // Checks for overflow where r2_val = -2147483648.
1871 // Cannot do int comparison due to GCC 4.8 bug on x86.
1872 // Detect INT_MIN alternatively, as it is the only value where both
1873 // original and result are negative due to overflow.
1874 if (r2_val < 0 && original_r2_val < 0) {
1875 SetS390OverflowCode(true);
1876 }
1877 break;
1878 }
1879 case BKPT: {
1880 set_pc(get_pc() + 2);
1881 S390Debugger dbg(this);
1882 dbg.Debug();
1883 break;
1884 }
1885 default:
1886 UNREACHABLE();
1887 return false;
1888 break;
1889 }
1890 return true;
1891 }
1892
1893 // Decode routine for four-byte instructions
1894 bool Simulator::DecodeFourByte(Instruction* instr) {
1895 Opcode op = instr->S390OpcodeValue();
1896
1897 // Pre-cast instruction to various types
1898 RREInstruction* rreInst = reinterpret_cast<RREInstruction*>(instr);
1899 SIInstruction* siInstr = reinterpret_cast<SIInstruction*>(instr);
1900
1901 switch (op) {
1902 case POPCNT_Z: {
1903 int r1 = rreInst->R1Value();
1904 int r2 = rreInst->R2Value();
1905 int64_t r2_val = get_register(r2);
1906 int64_t r1_val = 0;
1907
1908 uint8_t* r2_val_ptr = reinterpret_cast<uint8_t*>(&r2_val);
1909 uint8_t* r1_val_ptr = reinterpret_cast<uint8_t*>(&r1_val);
1910 for (int i = 0; i < 8; i++) {
1911 uint32_t x = static_cast<uint32_t>(r2_val_ptr[i]);
1912 #if defined(__GNUC__)
1913 r1_val_ptr[i] = __builtin_popcount(x);
1914 #else
1915 #error unsupport __builtin_popcount
1916 #endif
1917 }
1918
1919 set_register(r1, static_cast<uint64_t>(r1_val));
1920 break;
1921 }
1922 case LLGFR: {
1923 int r1 = rreInst->R1Value();
1924 int r2 = rreInst->R2Value();
1925 int32_t r2_val = get_low_register<int32_t>(r2);
1926 uint64_t r2_finalval =
1927 (static_cast<uint64_t>(r2_val) & 0x00000000ffffffff);
1928 set_register(r1, r2_finalval);
1929 break;
1930 }
1931 case EX: {
1932 RXInstruction* rxinst = reinterpret_cast<RXInstruction*>(instr);
1933 int r1 = rxinst->R1Value();
1934 int b2 = rxinst->B2Value();
1935 int x2 = rxinst->X2Value();
1936 int64_t b2_val = (b2 == 0) ? 0 : get_register(b2);
1937 int64_t x2_val = (x2 == 0) ? 0 : get_register(x2);
1938 intptr_t d2_val = rxinst->D2Value();
1939 int32_t r1_val = get_low_register<int32_t>(r1);
1940
1941 SixByteInstr the_instr = Instruction::InstructionBits(
1942 reinterpret_cast<const byte*>(b2_val + x2_val + d2_val));
1943 int length = Instruction::InstructionLength(
1944 reinterpret_cast<const byte*>(b2_val + x2_val + d2_val));
1945
1946 char new_instr_buf[8];
1947 char* addr = reinterpret_cast<char*>(&new_instr_buf[0]);
1948 the_instr |= static_cast<SixByteInstr>(r1_val & 0xff)
1949 << (8 * length - 16);
1950 Instruction::SetInstructionBits<SixByteInstr>(
1951 reinterpret_cast<byte*>(addr), static_cast<SixByteInstr>(the_instr));
1952 ExecuteInstruction(reinterpret_cast<Instruction*>(addr), false);
1953 break;
1954 }
1955 case LGR: {
1956 // Load Register (64)
1957 int r1 = rreInst->R1Value();
1958 int r2 = rreInst->R2Value();
1959 set_register(r1, get_register(r2));
1960 break;
1961 }
1962 case LDGR: {
1963 // Load FPR from GPR (L <- 64)
1964 uint64_t int_val = get_register(rreInst->R2Value());
1965 // double double_val = bit_cast<double, uint64_t>(int_val);
1966 // set_d_register_from_double(rreInst->R1Value(), double_val);
1967 set_d_register(rreInst->R1Value(), int_val);
1968 break;
1969 }
1970 case LGDR: {
1971 // Load GPR from FPR (64 <- L)
1972 int64_t double_val = get_d_register(rreInst->R2Value());
1973 set_register(rreInst->R1Value(), double_val);
1974 break;
1975 }
1976 case LTGR: {
1977 // Load Register (64)
1978 int r1 = rreInst->R1Value();
1979 int r2 = rreInst->R2Value();
1980 int64_t r2_val = get_register(r2);
1981 SetS390ConditionCode<int64_t>(r2_val, 0);
1982 set_register(r1, get_register(r2));
1983 break;
1984 }
1985 case LZDR: {
1986 int r1 = rreInst->R1Value();
1987 set_d_register_from_double(r1, 0.0);
1988 break;
1989 }
1990 case LTEBR: {
1991 RREInstruction* rreinst = reinterpret_cast<RREInstruction*>(instr);
1992 int r1 = rreinst->R1Value();
1993 int r2 = rreinst->R2Value();
1994 int64_t r2_val = get_d_register(r2);
1995 float fr2_val = get_float32_from_d_register(r2);
1996 SetS390ConditionCode<float>(fr2_val, 0.0);
1997 set_d_register(r1, r2_val);
1998 break;
1999 }
2000 case LTDBR: {
2001 RREInstruction* rreinst = reinterpret_cast<RREInstruction*>(instr);
2002 int r1 = rreinst->R1Value();
2003 int r2 = rreinst->R2Value();
2004 int64_t r2_val = get_d_register(r2);
2005 SetS390ConditionCode<double>(bit_cast<double, int64_t>(r2_val), 0.0);
2006 set_d_register(r1, r2_val);
2007 break;
2008 }
2009 case CGR: {
2010 // Compare (64)
2011 int64_t r1_val = get_register(rreInst->R1Value());
2012 int64_t r2_val = get_register(rreInst->R2Value());
2013 SetS390ConditionCode<int64_t>(r1_val, r2_val);
2014 break;
2015 }
2016 case CLGR: {
2017 // Compare Logical (64)
2018 uint64_t r1_val = static_cast<uint64_t>(get_register(rreInst->R1Value()));
2019 uint64_t r2_val = static_cast<uint64_t>(get_register(rreInst->R2Value()));
2020 SetS390ConditionCode<uint64_t>(r1_val, r2_val);
2021 break;
2022 }
2023 case LH: {
2024 // Load Halfword
2025 RXInstruction* rxinst = reinterpret_cast<RXInstruction*>(instr);
2026 int r1 = rxinst->R1Value();
2027 int x2 = rxinst->X2Value();
2028 int b2 = rxinst->B2Value();
2029
2030 int64_t x2_val = (x2 == 0) ? 0 : get_register(x2);
2031 int64_t b2_val = (b2 == 0) ? 0 : get_register(b2);
2032 intptr_t d2_val = rxinst->D2Value();
2033 intptr_t mem_addr = x2_val + b2_val + d2_val;
2034
2035 int32_t result = static_cast<int32_t>(ReadH(mem_addr, instr));
2036 set_low_register(r1, result);
2037 break;
2038 }
2039 case LHI: {
2040 RIInstruction* riinst = reinterpret_cast<RIInstruction*>(instr);
2041 int r1 = riinst->R1Value();
2042 int i = riinst->I2Value();
2043 set_low_register(r1, i);
2044 break;
2045 }
2046 case LGHI: {
2047 RIInstruction* riinst = reinterpret_cast<RIInstruction*>(instr);
2048 int r1 = riinst->R1Value();
2049 int64_t i = riinst->I2Value();
2050 set_register(r1, i);
2051 break;
2052 }
2053 case CHI: {
2054 RIInstruction* riinst = reinterpret_cast<RIInstruction*>(instr);
2055 int r1 = riinst->R1Value();
2056 int16_t i = riinst->I2Value();
2057 int32_t r1_val = get_low_register<int32_t>(r1);
2058 SetS390ConditionCode<int32_t>(r1_val, i);
2059 break;
2060 }
2061 case CGHI: {
2062 RIInstruction* riinst = reinterpret_cast<RIInstruction*>(instr);
2063 int r1 = riinst->R1Value();
2064 int64_t i = static_cast<int64_t>(riinst->I2Value());
2065 int64_t r1_val = get_register(r1);
2066 SetS390ConditionCode<int64_t>(r1_val, i);
2067 break;
2068 }
2069 case BRAS: {
2070 // Branch Relative and Save
2071 RILInstruction* rilInstr = reinterpret_cast<RILInstruction*>(instr);
2072 int r1 = rilInstr->R1Value();
2073 intptr_t d2 = rilInstr->I2Value();
2074 intptr_t pc = get_pc();
2075 // Set PC of next instruction to register
2076 set_register(r1, pc + sizeof(FourByteInstr));
2077 // Update PC to branch target
2078 set_pc(pc + d2 * 2);
2079 break;
2080 }
2081 case BRC: {
2082 // Branch Relative on Condition
2083 RIInstruction* riinst = reinterpret_cast<RIInstruction*>(instr);
2084 int m1 = riinst->M1Value();
2085 if (TestConditionCode((Condition)m1)) {
2086 intptr_t offset = riinst->I2Value() * 2;
2087 set_pc(get_pc() + offset);
2088 }
2089 break;
2090 }
2091 case BRCT:
2092 case BRCTG: {
2093 // Branch On Count (32/64).
2094 RIInstruction* riinst = reinterpret_cast<RIInstruction*>(instr);
2095 int r1 = riinst->R1Value();
2096 int64_t value =
2097 (op == BRCT) ? get_low_register<int32_t>(r1) : get_register(r1);
2098 if (BRCT == op)
2099 set_low_register(r1, --value);
2100 else
2101 set_register(r1, --value);
2102 // Branch if value != 0
2103 if (value != 0) {
2104 intptr_t offset = riinst->I2Value() * 2;
2105 set_pc(get_pc() + offset);
2106 }
2107 break;
2108 }
2109 case BXH: {
2110 RSInstruction* rsinst = reinterpret_cast<RSInstruction*>(instr);
2111 int r1 = rsinst->R1Value();
2112 int r3 = rsinst->R3Value();
2113 int b2 = rsinst->B2Value();
2114 int d2 = rsinst->D2Value();
2115
2116 // r1_val is the first operand, r3_val is the increment
2117 int32_t r1_val = r1 == 0 ? 0 : get_register(r1);
2118 int32_t r3_val = r2 == 0 ? 0 : get_register(r3);
2119 intptr_t b2_val = b2 == 0 ? 0 : get_register(b2);
2120 intptr_t branch_address = b2_val + d2;
2121 // increment r1_val
2122 r1_val += r3_val;
2123
2124 // if the increment is even, then it designates a pair of registers
2125 // and the contents of the even and odd registers of the pair are used as
2126 // the increment and compare value respectively. If the increment is odd,
2127 // the increment itself is used as both the increment and compare value
2128 int32_t compare_val = r3 % 2 == 0 ? get_register(r3 + 1) : r3_val;
2129 if (r1_val > compare_val) {
2130 // branch to address if r1_val is greater than compare value
2131 set_pc(branch_address);
2132 }
2133
2134 // update contents of register in r1 with the new incremented value
2135 set_register(r1, r1_val);
2136 break;
2137 }
2138 case IIHH:
2139 case IIHL:
2140 case IILH:
2141 case IILL: {
2142 UNIMPLEMENTED();
2143 break;
2144 }
2145 case STM:
2146 case LM: {
2147 // Store Multiple 32-bits.
2148 RSInstruction* rsinstr = reinterpret_cast<RSInstruction*>(instr);
2149 int r1 = rsinstr->R1Value();
2150 int r3 = rsinstr->R3Value();
2151 int rb = rsinstr->B2Value();
2152 int offset = rsinstr->D2Value();
2153
2154 // Regs roll around if r3 is less than r1.
2155 // Artifically increase r3 by 16 so we can calculate
2156 // the number of regs stored properly.
2157 if (r3 < r1) r3 += 16;
2158
2159 int32_t rb_val = (rb == 0) ? 0 : get_low_register<int32_t>(rb);
2160
2161 // Store each register in ascending order.
2162 for (int i = 0; i <= r3 - r1; i++) {
2163 if (op == STM) {
2164 int32_t value = get_low_register<int32_t>((r1 + i) % 16);
2165 WriteW(rb_val + offset + 4 * i, value, instr);
2166 } else if (op == LM) {
2167 int32_t value = ReadW(rb_val + offset + 4 * i, instr);
2168 set_low_register((r1 + i) % 16, value);
2169 }
2170 }
2171 break;
2172 }
2173 case SLL:
2174 case SRL: {
2175 RSInstruction* rsInstr = reinterpret_cast<RSInstruction*>(instr);
2176 int r1 = rsInstr->R1Value();
2177 int b2 = rsInstr->B2Value();
2178 intptr_t d2 = rsInstr->D2Value();
2179 // only takes rightmost 6bits
2180 int64_t b2_val = b2 == 0 ? 0 : get_register(b2);
2181 int shiftBits = (b2_val + d2) & 0x3F;
2182 uint32_t r1_val = get_low_register<uint32_t>(r1);
2183 uint32_t alu_out = 0;
2184 if (SLL == op) {
2185 alu_out = r1_val << shiftBits;
2186 } else if (SRL == op) {
2187 alu_out = r1_val >> shiftBits;
2188 } else {
2189 UNREACHABLE();
2190 }
2191 set_low_register(r1, alu_out);
2192 break;
2193 }
2194 case SLA:
2195 case SRA: {
2196 RSInstruction* rsInstr = reinterpret_cast<RSInstruction*>(instr);
2197 int r1 = rsInstr->R1Value();
2198 int b2 = rsInstr->B2Value();
2199 intptr_t d2 = rsInstr->D2Value();
2200 // only takes rightmost 6bits
2201 int64_t b2_val = b2 == 0 ? 0 : get_register(b2);
2202 int shiftBits = (b2_val + d2) & 0x3F;
2203 int32_t r1_val = get_low_register<int32_t>(r1);
2204 int32_t alu_out = 0;
2205 bool isOF = false;
2206 if (op == SLA) {
2207 isOF = CheckOverflowForShiftLeft(r1_val, shiftBits);
2208 alu_out = r1_val << shiftBits;
2209 } else if (op == SRA) {
2210 alu_out = r1_val >> shiftBits;
2211 }
2212 set_low_register(r1, alu_out);
2213 SetS390ConditionCode<int32_t>(alu_out, 0);
2214 SetS390OverflowCode(isOF);
2215 break;
2216 }
2217 case LLHR: {
2218 UNIMPLEMENTED();
2219 break;
2220 }
2221 case LLGHR: {
2222 UNIMPLEMENTED();
2223 break;
2224 }
2225 case L:
2226 case LA:
2227 case LD:
2228 case LE: {
2229 RXInstruction* rxinst = reinterpret_cast<RXInstruction*>(instr);
2230 int b2 = rxinst->B2Value();
2231 int x2 = rxinst->X2Value();
2232 int32_t r1 = rxinst->R1Value();
2233 int64_t b2_val = (b2 == 0) ? 0 : get_register(b2);
2234 int64_t x2_val = (x2 == 0) ? 0 : get_register(x2);
2235 intptr_t d2_val = rxinst->D2Value();
2236 intptr_t addr = b2_val + x2_val + d2_val;
2237 if (op == L) {
2238 int32_t mem_val = ReadW(addr, instr);
2239 set_low_register(r1, mem_val);
2240 } else if (op == LA) {
2241 set_register(r1, addr);
2242 } else if (op == LD) {
2243 int64_t dbl_val = *reinterpret_cast<int64_t*>(addr);
2244 set_d_register(r1, dbl_val);
2245 } else if (op == LE) {
2246 float float_val = *reinterpret_cast<float*>(addr);
2247 set_d_register_from_float32(r1, float_val);
2248 }
2249 break;
2250 }
2251 case C:
2252 case CL: {
2253 RXInstruction* rxinst = reinterpret_cast<RXInstruction*>(instr);
2254 int b2 = rxinst->B2Value();
2255 int x2 = rxinst->X2Value();
2256 int32_t r1_val = get_low_register<int32_t>(rxinst->R1Value());
2257 int64_t b2_val = (b2 == 0) ? 0 : get_register(b2);
2258 int64_t x2_val = (x2 == 0) ? 0 : get_register(x2);
2259 intptr_t d2_val = rxinst->D2Value();
2260 intptr_t addr = b2_val + x2_val + d2_val;
2261 int32_t mem_val = ReadW(addr, instr);
2262 if (C == op)
2263 SetS390ConditionCode<int32_t>(r1_val, mem_val);
2264 else if (CL == op)
2265 SetS390ConditionCode<uint32_t>(r1_val, mem_val);
2266 break;
2267 }
2268 case CLI: {
2269 // Compare Immediate (Mem - Imm) (8)
2270 int b1 = siInstr->B1Value();
2271 int64_t b1_val = (b1 == 0) ? 0 : get_register(b1);
2272 intptr_t d1_val = siInstr->D1Value();
2273 intptr_t addr = b1_val + d1_val;
2274 uint8_t mem_val = ReadB(addr);
2275 uint8_t imm_val = siInstr->I2Value();
2276 SetS390ConditionCode<uint8_t>(mem_val, imm_val);
2277 break;
2278 }
2279 case TM: {
2280 // Test Under Mask (Mem - Imm) (8)
2281 int b1 = siInstr->B1Value();
2282 int64_t b1_val = (b1 == 0) ? 0 : get_register(b1);
2283 intptr_t d1_val = siInstr->D1Value();
2284 intptr_t addr = b1_val + d1_val;
2285 uint8_t mem_val = ReadB(addr);
2286 uint8_t imm_val = siInstr->I2Value();
2287 uint8_t selected_bits = mem_val & imm_val;
2288 // CC0: Selected bits are zero
2289 // CC1: Selected bits mixed zeros and ones
2290 // CC3: Selected bits all ones
2291 if (0 == selected_bits) {
2292 condition_reg_ = CC_EQ; // CC0
2293 } else if (selected_bits == imm_val) {
2294 condition_reg_ = 0x1; // CC3
2295 } else {
2296 condition_reg_ = 0x4; // CC1
2297 }
2298 break;
2299 }
2300 case ST:
2301 case STE:
2302 case STD: {
2303 RXInstruction* rxinst = reinterpret_cast<RXInstruction*>(instr);
2304 int b2 = rxinst->B2Value();
2305 int x2 = rxinst->X2Value();
2306 int32_t r1_val = get_low_register<int32_t>(rxinst->R1Value());
2307 int64_t b2_val = (b2 == 0) ? 0 : get_register(b2);
2308 int64_t x2_val = (x2 == 0) ? 0 : get_register(x2);
2309 intptr_t d2_val = rxinst->D2Value();
2310 intptr_t addr = b2_val + x2_val + d2_val;
2311 if (op == ST) {
2312 WriteW(addr, r1_val, instr);
2313 } else if (op == STD) {
2314 int64_t frs_val = get_d_register(rxinst->R1Value());
2315 WriteDW(addr, frs_val);
2316 } else if (op == STE) {
2317 int64_t frs_val = get_d_register(rxinst->R1Value()) >> 32;
2318 WriteW(addr, static_cast<int32_t>(frs_val), instr);
2319 }
2320 break;
2321 }
2322 case LTGFR:
2323 case LGFR: {
2324 // Load and Test Register (64 <- 32) (Sign Extends 32-bit val)
2325 // Load Register (64 <- 32) (Sign Extends 32-bit val)
2326 RREInstruction* rreInstr = reinterpret_cast<RREInstruction*>(instr);
2327 int r1 = rreInstr->R1Value();
2328 int r2 = rreInstr->R2Value();
2329 int32_t r2_val = get_low_register<int32_t>(r2);
2330 int64_t result = static_cast<int64_t>(r2_val);
2331 set_register(r1, result);
2332
2333 if (LTGFR == op) SetS390ConditionCode<int64_t>(result, 0);
2334 break;
2335 }
2336 case LNGR: {
2337 // Load Negative (64)
2338 int r1 = rreInst->R1Value();
2339 int r2 = rreInst->R2Value();
2340 int64_t r2_val = get_register(r2);
2341 r2_val = (r2_val >= 0) ? -r2_val : r2_val; // If pos, then negate it.
2342 set_register(r1, r2_val);
2343 condition_reg_ = (r2_val == 0) ? CC_EQ : CC_LT; // CC0 - result is zero
2344 // CC1 - result is negative
2345 break;
2346 }
2347 case TRAP4: {
2348 // whack the space of the caller allocated stack
2349 int64_t sp_addr = get_register(sp);
2350 for (int i = 0; i < kCalleeRegisterSaveAreaSize / kPointerSize; ++i) {
2351 // we dont want to whack the RA (r14)
2352 if (i != 14) (reinterpret_cast<intptr_t*>(sp_addr))[i] = 0xdeadbabe;
2353 }
2354 SoftwareInterrupt(instr);
2355 break;
2356 }
2357 case STC: {
2358 // Store Character/Byte
2359 RXInstruction* rxinst = reinterpret_cast<RXInstruction*>(instr);
2360 int b2 = rxinst->B2Value();
2361 int x2 = rxinst->X2Value();
2362 uint8_t r1_val = get_low_register<int32_t>(rxinst->R1Value());
2363 int64_t b2_val = (b2 == 0) ? 0 : get_register(b2);
2364 int64_t x2_val = (x2 == 0) ? 0 : get_register(x2);
2365 intptr_t d2_val = rxinst->D2Value();
2366 intptr_t mem_addr = b2_val + x2_val + d2_val;
2367 WriteB(mem_addr, r1_val);
2368 break;
2369 }
2370 case STH: {
2371 RXInstruction* rxinst = reinterpret_cast<RXInstruction*>(instr);
2372 int b2 = rxinst->B2Value();
2373 int x2 = rxinst->X2Value();
2374 int16_t r1_val = get_low_register<int32_t>(rxinst->R1Value());
2375 int64_t b2_val = (b2 == 0) ? 0 : get_register(b2);
2376 int64_t x2_val = (x2 == 0) ? 0 : get_register(x2);
2377 intptr_t d2_val = rxinst->D2Value();
2378 intptr_t mem_addr = b2_val + x2_val + d2_val;
2379 WriteH(mem_addr, r1_val, instr);
2380 break;
2381 }
2382 #if V8_TARGET_ARCH_S390X
2383 case LCGR: {
2384 int r1 = rreInst->R1Value();
2385 int r2 = rreInst->R2Value();
2386 int64_t r2_val = get_register(r2);
2387 r2_val = ~r2_val;
2388 r2_val = r2_val + 1;
2389 set_register(r1, r2_val);
2390 SetS390ConditionCode<int64_t>(r2_val, 0);
2391 // if the input is INT_MIN, loading its compliment would be overflowing
2392 if (r2_val < 0 && (r2_val + 1) > 0) {
2393 SetS390OverflowCode(true);
2394 }
2395 break;
2396 }
2397 #endif
2398 case SRDA: {
2399 RSInstruction* rsInstr = reinterpret_cast<RSInstruction*>(instr);
2400 int r1 = rsInstr->R1Value();
2401 DCHECK(r1 % 2 == 0); // must be a reg pair
2402 int b2 = rsInstr->B2Value();
2403 intptr_t d2 = rsInstr->D2Value();
2404 // only takes rightmost 6bits
2405 int64_t b2_val = b2 == 0 ? 0 : get_register(b2);
2406 int shiftBits = (b2_val + d2) & 0x3F;
2407 int64_t opnd1 = static_cast<int64_t>(get_low_register<int32_t>(r1)) << 32;
2408 int64_t opnd2 = static_cast<uint64_t>(get_low_register<uint32_t>(r1 + 1));
2409 int64_t r1_val = opnd1 + opnd2;
2410 int64_t alu_out = r1_val >> shiftBits;
2411 set_low_register(r1, alu_out >> 32);
2412 set_low_register(r1 + 1, alu_out & 0x00000000FFFFFFFF);
2413 SetS390ConditionCode<int32_t>(alu_out, 0);
2414 break;
2415 }
2416 case SRDL: {
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 uint64_t opnd1 = static_cast<uint64_t>(get_low_register<uint32_t>(r1))
2426 << 32;
2427 uint64_t opnd2 =
2428 static_cast<uint64_t>(get_low_register<uint32_t>(r1 + 1));
2429 uint64_t r1_val = opnd1 | opnd2;
2430 uint64_t alu_out = r1_val >> shiftBits;
2431 set_low_register(r1, alu_out >> 32);
2432 set_low_register(r1 + 1, alu_out & 0x00000000FFFFFFFF);
2433 SetS390ConditionCode<int32_t>(alu_out, 0);
2434 break;
2435 }
2436 default: { return DecodeFourByteArithmetic(instr); }
2437 }
2438 return true;
2439 }
2440
2441 /**
2442 * Decodes and simulates four byte arithmetic instructions
2443 */
2444 bool Simulator::DecodeFourByteArithmetic(Instruction* instr) {
2445 Opcode op = instr->S390OpcodeValue();
2446
2447 // Pre-cast instruction to various types
2448 RRFInstruction* rrfInst = reinterpret_cast<RRFInstruction*>(instr);
2449 RREInstruction* rreInst = reinterpret_cast<RREInstruction*>(instr);
2450
2451 switch (op) {
2452 case AGR:
2453 case SGR:
2454 case OGR:
2455 case NGR:
2456 case XGR: {
2457 int r1 = rreInst->R1Value();
2458 int r2 = rreInst->R2Value();
2459 int64_t r1_val = get_register(r1);
2460 int64_t r2_val = get_register(r2);
2461 bool isOF = false;
2462 switch (op) {
2463 case AGR:
2464 isOF = CheckOverflowForIntAdd(r1_val, r2_val);
2465 r1_val += r2_val;
2466 SetS390ConditionCode<int64_t>(r1_val, 0);
2467 SetS390OverflowCode(isOF);
2468 break;
2469 case SGR:
2470 isOF = CheckOverflowForIntSub(r1_val, r2_val);
2471 r1_val -= r2_val;
2472 SetS390ConditionCode<int64_t>(r1_val, 0);
2473 SetS390OverflowCode(isOF);
2474 break;
2475 case OGR:
2476 r1_val |= r2_val;
2477 SetS390BitWiseConditionCode<uint64_t>(r1_val);
2478 break;
2479 case NGR:
2480 r1_val &= r2_val;
2481 SetS390BitWiseConditionCode<uint64_t>(r1_val);
2482 break;
2483 case XGR:
2484 r1_val ^= r2_val;
2485 SetS390BitWiseConditionCode<uint64_t>(r1_val);
2486 break;
2487 default:
2488 UNREACHABLE();
2489 break;
2490 }
2491 set_register(r1, r1_val);
2492 break;
2493 }
2494 case AGFR: {
2495 // Add Register (64 <- 32) (Sign Extends 32-bit val)
2496 int r1 = rreInst->R1Value();
2497 int r2 = rreInst->R2Value();
2498 int64_t r1_val = get_register(r1);
2499 int64_t r2_val = static_cast<int64_t>(get_low_register<int32_t>(r2));
2500 bool isOF = CheckOverflowForIntAdd(r1_val, r2_val);
2501 r1_val += r2_val;
2502 SetS390ConditionCode<int64_t>(r1_val, 0);
2503 SetS390OverflowCode(isOF);
2504 set_register(r1, r1_val);
2505 break;
2506 }
2507 case SGFR: {
2508 // Sub Reg (64 <- 32)
2509 int r1 = rreInst->R1Value();
2510 int r2 = rreInst->R2Value();
2511 int64_t r1_val = get_register(r1);
2512 int64_t r2_val = static_cast<int64_t>(get_low_register<int32_t>(r2));
2513 bool isOF = false;
2514 isOF = CheckOverflowForIntSub(r1_val, r2_val);
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 ARK:
2522 case SRK:
2523 case NRK:
2524 case ORK:
2525 case XRK: {
2526 // 32-bit Non-clobbering arithmetics / bitwise ops
2527 int r1 = rrfInst->R1Value();
2528 int r2 = rrfInst->R2Value();
2529 int r3 = rrfInst->R3Value();
2530 int32_t r2_val = get_low_register<int32_t>(r2);
2531 int32_t r3_val = get_low_register<int32_t>(r3);
2532 if (ARK == op) {
2533 bool isOF = CheckOverflowForIntAdd(r2_val, r3_val);
2534 SetS390ConditionCode<int32_t>(r2_val + r3_val, 0);
2535 SetS390OverflowCode(isOF);
2536 set_low_register(r1, r2_val + r3_val);
2537 } else if (SRK == op) {
2538 bool isOF = CheckOverflowForIntSub(r2_val, r3_val);
2539 SetS390ConditionCode<int32_t>(r2_val - r3_val, 0);
2540 SetS390OverflowCode(isOF);
2541 set_low_register(r1, r2_val - r3_val);
2542 } else {
2543 // Assume bitwise operation here
2544 uint32_t bitwise_result = 0;
2545 if (NRK == op) {
2546 bitwise_result = r2_val & r3_val;
2547 } else if (ORK == op) {
2548 bitwise_result = r2_val | r3_val;
2549 } else if (XRK == op) {
2550 bitwise_result = r2_val ^ r3_val;
2551 }
2552 SetS390BitWiseConditionCode<uint32_t>(bitwise_result);
2553 set_low_register(r1, bitwise_result);
2554 }
2555 break;
2556 }
2557 case ALRK:
2558 case SLRK: {
2559 // 32-bit Non-clobbering unsigned arithmetics
2560 int r1 = rrfInst->R1Value();
2561 int r2 = rrfInst->R2Value();
2562 int r3 = rrfInst->R3Value();
2563 uint32_t r2_val = get_low_register<uint32_t>(r2);
2564 uint32_t r3_val = get_low_register<uint32_t>(r3);
2565 if (ALRK == op) {
2566 bool isOF = CheckOverflowForUIntAdd(r2_val, r3_val);
2567 SetS390ConditionCode<uint32_t>(r2_val + r3_val, 0);
2568 SetS390OverflowCode(isOF);
2569 set_low_register(r1, r2_val + r3_val);
2570 } else if (SLRK == op) {
2571 bool isOF = CheckOverflowForUIntSub(r2_val, r3_val);
2572 SetS390ConditionCode<uint32_t>(r2_val - r3_val, 0);
2573 SetS390OverflowCode(isOF);
2574 set_low_register(r1, r2_val - r3_val);
2575 }
2576 break;
2577 }
2578 case AGRK:
2579 case SGRK:
2580 case NGRK:
2581 case OGRK:
2582 case XGRK: {
2583 // 64-bit Non-clobbering arithmetics / bitwise ops.
2584 int r1 = rrfInst->R1Value();
2585 int r2 = rrfInst->R2Value();
2586 int r3 = rrfInst->R3Value();
2587 int64_t r2_val = get_register(r2);
2588 int64_t r3_val = get_register(r3);
2589 if (AGRK == op) {
2590 bool isOF = CheckOverflowForIntAdd(r2_val, r3_val);
2591 SetS390ConditionCode<int64_t>(r2_val + r3_val, 0);
2592 SetS390OverflowCode(isOF);
2593 set_register(r1, r2_val + r3_val);
2594 } else if (SGRK == op) {
2595 bool isOF = CheckOverflowForIntSub(r2_val, r3_val);
2596 SetS390ConditionCode<int64_t>(r2_val - r3_val, 0);
2597 SetS390OverflowCode(isOF);
2598 set_register(r1, r2_val - r3_val);
2599 } else {
2600 // Assume bitwise operation here
2601 uint64_t bitwise_result = 0;
2602 if (NGRK == op) {
2603 bitwise_result = r2_val & r3_val;
2604 } else if (OGRK == op) {
2605 bitwise_result = r2_val | r3_val;
2606 } else if (XGRK == op) {
2607 bitwise_result = r2_val ^ r3_val;
2608 }
2609 SetS390BitWiseConditionCode<uint64_t>(bitwise_result);
2610 set_register(r1, bitwise_result);
2611 }
2612 break;
2613 }
2614 case ALGRK:
2615 case SLGRK: {
2616 // 64-bit Non-clobbering unsigned arithmetics
2617 int r1 = rrfInst->R1Value();
2618 int r2 = rrfInst->R2Value();
2619 int r3 = rrfInst->R3Value();
2620 uint64_t r2_val = get_register(r2);
2621 uint64_t r3_val = get_register(r3);
2622 if (ALGRK == op) {
2623 bool isOF = CheckOverflowForUIntAdd(r2_val, r3_val);
2624 SetS390ConditionCode<uint64_t>(r2_val + r3_val, 0);
2625 SetS390OverflowCode(isOF);
2626 set_register(r1, r2_val + r3_val);
2627 } else if (SLGRK == op) {
2628 bool isOF = CheckOverflowForUIntSub(r2_val, r3_val);
2629 SetS390ConditionCode<uint64_t>(r2_val - r3_val, 0);
2630 SetS390OverflowCode(isOF);
2631 set_register(r1, r2_val - r3_val);
2632 }
2633 break;
2634 }
2635 case AHI:
2636 case MHI: {
2637 RIInstruction* riinst = reinterpret_cast<RIInstruction*>(instr);
2638 int r1 = riinst->R1Value();
2639 int i = riinst->I2Value();
2640 int32_t r1_val = get_low_register<int32_t>(r1);
2641 bool isOF = false;
2642 switch (op) {
2643 case AHI:
2644 isOF = CheckOverflowForIntAdd(r1_val, i);
2645 r1_val += i;
2646 break;
2647 case MHI:
2648 isOF = CheckOverflowForMul(r1_val, i);
2649 r1_val *= i;
2650 break; // no overflow indication is given
2651 default:
2652 break;
2653 }
2654 set_low_register(r1, r1_val);
2655 SetS390ConditionCode<int32_t>(r1_val, 0);
2656 SetS390OverflowCode(isOF);
2657 break;
2658 }
2659 case AGHI:
2660 case MGHI: {
2661 RIInstruction* riinst = reinterpret_cast<RIInstruction*>(instr);
2662 int r1 = riinst->R1Value();
2663 int64_t i = static_cast<int64_t>(riinst->I2Value());
2664 int64_t r1_val = get_register(r1);
2665 bool isOF = false;
2666 switch (op) {
2667 case AGHI:
2668 isOF = CheckOverflowForIntAdd(r1_val, i);
2669 r1_val += i;
2670 break;
2671 case MGHI:
2672 isOF = CheckOverflowForMul(r1_val, i);
2673 r1_val *= i;
2674 break; // no overflow indication is given
2675 default:
2676 break;
2677 }
2678 set_register(r1, r1_val);
2679 SetS390ConditionCode<int32_t>(r1_val, 0);
2680 SetS390OverflowCode(isOF);
2681 break;
2682 }
2683 case MLR: {
2684 RREInstruction* rreinst = reinterpret_cast<RREInstruction*>(instr);
2685 int r1 = rreinst->R1Value();
2686 int r2 = rreinst->R2Value();
2687 DCHECK(r1 % 2 == 0);
2688
2689 uint32_t r1_val = get_low_register<uint32_t>(r1 + 1);
2690 uint32_t r2_val = get_low_register<uint32_t>(r2);
2691 uint64_t product =
2692 static_cast<uint64_t>(r1_val) * static_cast<uint64_t>(r2_val);
2693 int32_t high_bits = product >> 32;
2694 int32_t low_bits = product & 0x00000000FFFFFFFF;
2695 set_low_register(r1, high_bits);
2696 set_low_register(r1 + 1, low_bits);
2697 break;
2698 }
2699 case DLGR: {
2700 #ifdef V8_TARGET_ARCH_S390X
2701 RREInstruction* rreinst = reinterpret_cast<RREInstruction*>(instr);
2702 int r1 = rreinst->R1Value();
2703 int r2 = rreinst->R2Value();
2704 uint64_t r1_val = static_cast<uint64_t>(r1);
2705 uint64_t r2_val = static_cast<uint64_t>(r2);
2706 DCHECK(r1 % 2 == 0);
2707 unsigned __int128 dividend = static_cast<unsigned __int128>(r1_val) << 64;
2708 dividend += static_cast<uint64_t>(r1 + 1);
2709 uint64_t remainder = dividend % r2_val;
2710 uint64_t quotient = dividend / r2_val;
2711 r1_val = remainder;
2712 set_register(r1, remainder);
2713 set_register(r1 + 1, quotient);
2714 #else
2715 UNREACHABLE();
2716 #endif
2717 break;
2718 }
2719 case DLR: {
2720 RREInstruction* rreinst = reinterpret_cast<RREInstruction*>(instr);
2721 int r1 = rreinst->R1Value();
2722 int r2 = rreinst->R2Value();
2723 uint32_t r1_val = get_low_register<uint32_t>(r1);
2724 uint32_t r2_val = get_low_register<uint32_t>(r2);
2725 DCHECK(r1 % 2 == 0);
2726 uint64_t dividend = static_cast<uint64_t>(r1_val) << 32;
2727 dividend += get_low_register<uint32_t>(r1 + 1);
2728 uint32_t remainder = dividend % r2_val;
2729 uint32_t quotient = dividend / r2_val;
2730 r1_val = remainder;
2731 set_low_register(r1, remainder);
2732 set_low_register(r1 + 1, quotient);
2733 break;
2734 }
2735 case A:
2736 case S:
2737 case M:
2738 case D:
2739 case O:
2740 case N:
2741 case X: {
2742 // 32-bit Reg-Mem instructions
2743 RXInstruction* rxinst = reinterpret_cast<RXInstruction*>(instr);
2744 int b2 = rxinst->B2Value();
2745 int x2 = rxinst->X2Value();
2746 int32_t r1_val = get_low_register<int32_t>(rxinst->R1Value());
2747 int64_t b2_val = (b2 == 0) ? 0 : get_register(b2);
2748 int64_t x2_val = (x2 == 0) ? 0 : get_register(x2);
2749 intptr_t d2_val = rxinst->D2Value();
2750 int32_t mem_val = ReadW(b2_val + x2_val + d2_val, instr);
2751 int32_t alu_out = 0;
2752 bool isOF = false;
2753 switch (op) {
2754 case A:
2755 isOF = CheckOverflowForIntAdd(r1_val, mem_val);
2756 alu_out = r1_val + mem_val;
2757 SetS390ConditionCode<int32_t>(alu_out, 0);
2758 SetS390OverflowCode(isOF);
2759 break;
2760 case S:
2761 isOF = CheckOverflowForIntSub(r1_val, mem_val);
2762 alu_out = r1_val - mem_val;
2763 SetS390ConditionCode<int32_t>(alu_out, 0);
2764 SetS390OverflowCode(isOF);
2765 break;
2766 case M:
2767 case D:
2768 UNIMPLEMENTED();
2769 break;
2770 case O:
2771 alu_out = r1_val | mem_val;
2772 SetS390BitWiseConditionCode<uint32_t>(alu_out);
2773 break;
2774 case N:
2775 alu_out = r1_val & mem_val;
2776 SetS390BitWiseConditionCode<uint32_t>(alu_out);
2777 break;
2778 case X:
2779 alu_out = r1_val ^ mem_val;
2780 SetS390BitWiseConditionCode<uint32_t>(alu_out);
2781 break;
2782 default:
2783 UNREACHABLE();
2784 break;
2785 }
2786 set_low_register(r1, alu_out);
2787 break;
2788 }
2789 case OILL:
2790 case OIHL: {
2791 RIInstruction* riInst = reinterpret_cast<RIInstruction*>(instr);
2792 int r1 = riInst->R1Value();
2793 int i = riInst->I2Value();
2794 int32_t r1_val = get_low_register<int32_t>(r1);
2795 if (OILL == op) {
2796 // CC is set based on the 16 bits that are AND'd
2797 SetS390BitWiseConditionCode<uint16_t>(r1_val | i);
2798 } else if (OILH == op) {
2799 // CC is set based on the 16 bits that are AND'd
2800 SetS390BitWiseConditionCode<uint16_t>((r1_val >> 16) | i);
2801 i = i << 16;
2802 } else {
2803 UNIMPLEMENTED();
2804 }
2805 set_low_register(r1, r1_val | i);
2806 break;
2807 }
2808 case NILL:
2809 case NILH: {
2810 RIInstruction* riInst = reinterpret_cast<RIInstruction*>(instr);
2811 int r1 = riInst->R1Value();
2812 int i = riInst->I2Value();
2813 int32_t r1_val = get_low_register<int32_t>(r1);
2814 if (NILL == op) {
2815 // CC is set based on the 16 bits that are AND'd
2816 SetS390BitWiseConditionCode<uint16_t>(r1_val & i);
2817 i |= 0xFFFF0000;
2818 } else if (NILH == op) {
2819 // CC is set based on the 16 bits that are AND'd
2820 SetS390BitWiseConditionCode<uint16_t>((r1_val >> 16) & i);
2821 i = (i << 16) | 0x0000FFFF;
2822 } else {
2823 UNIMPLEMENTED();
2824 }
2825 set_low_register(r1, r1_val & i);
2826 break;
2827 }
2828 case AH:
2829 case SH:
2830 case MH: {
2831 RXInstruction* rxinst = reinterpret_cast<RXInstruction*>(instr);
2832 int b2 = rxinst->B2Value();
2833 int x2 = rxinst->X2Value();
2834 int32_t r1_val = get_low_register<int32_t>(rxinst->R1Value());
2835 int64_t b2_val = (b2 == 0) ? 0 : get_register(b2);
2836 int64_t x2_val = (x2 == 0) ? 0 : get_register(x2);
2837 intptr_t d2_val = rxinst->D2Value();
2838 intptr_t addr = b2_val + x2_val + d2_val;
2839 int16_t mem_val = ReadH(addr, instr);
2840 int32_t alu_out = 0;
2841 bool isOF = false;
2842 if (AH == op) {
2843 isOF = CheckOverflowForIntAdd(r1_val, mem_val);
2844 alu_out = r1_val + mem_val;
2845 } else if (SH == op) {
2846 isOF = CheckOverflowForIntSub(r1_val, mem_val);
2847 alu_out = r1_val - mem_val;
2848 } else if (MH == op) {
2849 alu_out = r1_val * mem_val;
2850 } else {
2851 UNREACHABLE();
2852 }
2853 set_low_register(r1, alu_out);
2854 if (MH != op) { // MH does not change condition code
2855 SetS390ConditionCode<int32_t>(alu_out, 0);
2856 SetS390OverflowCode(isOF);
2857 }
2858 break;
2859 }
2860 case DSGR: {
2861 RREInstruction* rreInst = reinterpret_cast<RREInstruction*>(instr);
2862 int r1 = rreInst->R1Value();
2863 int r2 = rreInst->R2Value();
2864
2865 DCHECK(r1 % 2 == 0);
2866
2867 int64_t dividend = get_register(r1 + 1);
2868 int64_t divisor = get_register(r2);
2869 set_register(r1, dividend % divisor);
2870 set_register(r1 + 1, dividend / divisor);
2871
2872 break;
2873 }
2874 case FLOGR: {
2875 RREInstruction* rreInst = reinterpret_cast<RREInstruction*>(instr);
2876 int r1 = rreInst->R1Value();
2877 int r2 = rreInst->R2Value();
2878
2879 DCHECK(r1 % 2 == 0);
2880
2881 int64_t r2_val = get_register(r2);
2882
2883 int i = 0;
2884 for (; i < 64; i++) {
2885 if (r2_val < 0) break;
2886 r2_val <<= 1;
2887 }
2888
2889 r2_val = get_register(r2);
2890
2891 int64_t mask = ~(1 << (63 - i));
2892 set_register(r1, i);
2893 set_register(r1 + 1, r2_val & mask);
2894
2895 break;
2896 }
2897 case MSR:
2898 case MSGR: { // they do not set overflow code
2899 RREInstruction* rreInst = reinterpret_cast<RREInstruction*>(instr);
2900 int r1 = rreInst->R1Value();
2901 int r2 = rreInst->R2Value();
2902 if (op == MSR) {
2903 int32_t r1_val = get_low_register<int32_t>(r1);
2904 int32_t r2_val = get_low_register<int32_t>(r2);
2905 set_low_register(r1, r1_val * r2_val);
2906 } else if (op == MSGR) {
2907 int64_t r1_val = get_register(r1);
2908 int64_t r2_val = get_register(r2);
2909 set_register(r1, r1_val * r2_val);
2910 } else {
2911 UNREACHABLE();
2912 }
2913 break;
2914 }
2915 case MS: {
2916 RXInstruction* rxinst = reinterpret_cast<RXInstruction*>(instr);
2917 int r1 = rxinst->R1Value();
2918 int b2 = rxinst->B2Value();
2919 int x2 = rxinst->X2Value();
2920 int64_t x2_val = (x2 == 0) ? 0 : get_register(x2);
2921 int64_t b2_val = (b2 == 0) ? 0 : get_register(b2);
2922 intptr_t d2_val = rxinst->D2Value();
2923 int32_t mem_val = ReadW(b2_val + x2_val + d2_val, instr);
2924 int32_t r1_val = get_low_register<int32_t>(r1);
2925 set_low_register(r1, r1_val * mem_val);
2926 break;
2927 }
2928 case LGBR:
2929 case LBR: {
2930 RREInstruction* rrinst = reinterpret_cast<RREInstruction*>(instr);
2931 int r1 = rrinst->R1Value();
2932 int r2 = rrinst->R2Value();
2933 #ifdef V8_TARGET_ARCH_S390X
2934 int64_t r2_val = get_low_register<int64_t>(r2);
2935 r2_val <<= 56;
2936 r2_val >>= 56;
2937 set_register(r1, r2_val);
2938 #else
2939 int32_t r2_val = get_low_register<int32_t>(r2);
2940 r2_val <<= 24;
2941 r2_val >>= 24;
2942 set_low_register(r1, r2_val);
2943 #endif
2944 break;
2945 }
2946 case LGHR:
2947 case LHR: {
2948 RREInstruction* rrinst = reinterpret_cast<RREInstruction*>(instr);
2949 int r1 = rrinst->R1Value();
2950 int r2 = rrinst->R2Value();
2951 #ifdef V8_TARGET_ARCH_S390X
2952 int64_t r2_val = get_low_register<int64_t>(r2);
2953 r2_val <<= 48;
2954 r2_val >>= 48;
2955 set_register(r1, r2_val);
2956 #else
2957 int32_t r2_val = get_low_register<int32_t>(r2);
2958 r2_val <<= 16;
2959 r2_val >>= 16;
2960 set_low_register(r1, r2_val);
2961 #endif
2962 break;
2963 }
2964 default: { return DecodeFourByteFloatingPoint(instr); }
2965 }
2966 return true;
2967 }
2968
2969 void Simulator::DecodeFourByteFloatingPointIntConversion(Instruction* instr) {
2970 Opcode op = instr->S390OpcodeValue();
2971 switch (op) {
2972 case CDLFBR:
2973 case CDLGBR:
2974 case CELGBR:
2975 case CLFDBR:
2976 case CLGDBR:
2977 case CELFBR:
2978 case CLGEBR: {
2979 RREInstruction* rreInstr = reinterpret_cast<RREInstruction*>(instr);
2980 int r1 = rreInstr->R1Value();
2981 int r2 = rreInstr->R2Value();
2982 if (op == CDLFBR) {
2983 uint32_t r2_val = get_low_register<uint32_t>(r2);
2984 double r1_val = static_cast<double>(r2_val);
2985 set_d_register_from_double(r1, r1_val);
2986 } else if (op == CELFBR) {
2987 uint32_t r2_val = get_low_register<uint32_t>(r2);
2988 float r1_val = static_cast<float>(r2_val);
2989 set_d_register_from_float32(r1, r1_val);
2990 } else if (op == CDLGBR) {
2991 uint64_t r2_val = get_register(r2);
2992 double r1_val = static_cast<double>(r2_val);
2993 set_d_register_from_double(r1, r1_val);
2994 } else if (op == CELGBR) {
2995 uint64_t r2_val = get_register(r2);
2996 float r1_val = static_cast<float>(r2_val);
2997 set_d_register_from_float32(r1, r1_val);
2998 } else if (op == CLFDBR) {
2999 double r2_val = get_double_from_d_register(r2);
3000 uint32_t r1_val = static_cast<uint32_t>(r2_val);
3001 set_low_register(r1, r1_val);
3002 SetS390ConditionCode<double>(r2_val, 0);
3003 } else if (op == CLGDBR) {
3004 double r2_val = get_double_from_d_register(r2);
3005 uint64_t r1_val = static_cast<uint64_t>(r2_val);
3006 set_register(r1, r1_val);
3007 SetS390ConditionCode<double>(r2_val, 0);
3008 } else if (op == CLGEBR) {
3009 float r2_val = get_float32_from_d_register(r2);
3010 uint64_t r1_val = static_cast<uint64_t>(r2_val);
3011 set_register(r1, r1_val);
3012 SetS390ConditionCode<double>(r2_val, 0);
3013 }
3014 break;
3015 }
3016 default:
3017 UNREACHABLE();
3018 }
3019 }
3020
3021 void Simulator::DecodeFourByteFloatingPointRound(Instruction* instr) {
3022 Opcode op = instr->S390OpcodeValue();
3023 RREInstruction* rreInstr = reinterpret_cast<RREInstruction*>(instr);
3024 int r1 = rreInstr->R1Value();
3025 int r2 = rreInstr->R2Value();
3026 double r2_val = get_double_from_d_register(r2);
3027 float r2_fval = get_float32_from_d_register(r2);
3028
3029 switch (op) {
3030 case CFDBR: {
3031 int mask_val = rreInstr->M3Value();
3032 int32_t r1_val = 0;
3033
3034 if (r2_val == 0.0)
3035 condition_reg_ = 8;
3036 else if (r2_val < 0.0)
3037 condition_reg_ = 4;
3038 else if (r2_val > 0.0)
3039 condition_reg_ = 2;
3040 else
3041 condition_reg_ = 1;
3042
3043 switch (mask_val) {
3044 case CURRENT_ROUNDING_MODE:
3045 case ROUND_TO_PREPARE_FOR_SHORTER_PRECISION: {
3046 r1_val = static_cast<int32_t>(r2_val);
3047 break;
3048 }
3049 case ROUND_TO_NEAREST_WITH_TIES_AWAY_FROM_0: {
3050 double ceil_val = std::ceil(r2_val);
3051 double floor_val = std::floor(r2_val);
3052 double sub_val1 = std::fabs(r2_val - floor_val);
3053 double sub_val2 = std::fabs(r2_val - ceil_val);
3054 if (sub_val1 > sub_val2) {
3055 r1_val = static_cast<int32_t>(ceil_val);
3056 } else if (sub_val1 < sub_val2) {
3057 r1_val = static_cast<int32_t>(floor_val);
3058 } else { // round away from zero:
3059 if (r2_val > 0.0) {
3060 r1_val = static_cast<int32_t>(ceil_val);
3061 } else {
3062 r1_val = static_cast<int32_t>(floor_val);
3063 }
3064 }
3065 break;
3066 }
3067 case ROUND_TO_NEAREST_WITH_TIES_TO_EVEN: {
3068 double ceil_val = std::ceil(r2_val);
3069 double floor_val = std::floor(r2_val);
3070 double sub_val1 = std::fabs(r2_val - floor_val);
3071 double sub_val2 = std::fabs(r2_val - ceil_val);
3072 if (sub_val1 > sub_val2) {
3073 r1_val = static_cast<int32_t>(ceil_val);
3074 } else if (sub_val1 < sub_val2) {
3075 r1_val = static_cast<int32_t>(floor_val);
3076 } else { // check which one is even:
3077 int32_t c_v = static_cast<int32_t>(ceil_val);
3078 int32_t f_v = static_cast<int32_t>(floor_val);
3079 if (f_v % 2 == 0)
3080 r1_val = f_v;
3081 else
3082 r1_val = c_v;
3083 }
3084 break;
3085 }
3086 case ROUND_TOWARD_0: {
3087 // check for overflow, cast r2_val to 64bit integer
3088 // then check value within the range of INT_MIN and INT_MAX
3089 // and set condition code accordingly
3090 int64_t temp = static_cast<int64_t>(r2_val);
3091 if (temp < INT_MIN || temp > INT_MAX) {
3092 condition_reg_ = CC_OF;
3093 }
3094 r1_val = static_cast<int32_t>(r2_val);
3095 break;
3096 }
3097 case ROUND_TOWARD_PLUS_INFINITE: {
3098 r1_val = static_cast<int32_t>(std::ceil(r2_val));
3099 break;
3100 }
3101 case ROUND_TOWARD_MINUS_INFINITE: {
3102 // check for overflow, cast r2_val to 64bit integer
3103 // then check value within the range of INT_MIN and INT_MAX
3104 // and set condition code accordingly
3105 int64_t temp = static_cast<int64_t>(std::floor(r2_val));
3106 if (temp < INT_MIN || temp > INT_MAX) {
3107 condition_reg_ = CC_OF;
3108 }
3109 r1_val = static_cast<int32_t>(std::floor(r2_val));
3110 break;
3111 }
3112 default:
3113 UNREACHABLE();
3114 }
3115 set_low_register(r1, r1_val);
3116 break;
3117 }
3118 case CGDBR: {
3119 int mask_val = rreInstr->M3Value();
3120 int64_t r1_val = 0;
3121
3122 if (r2_val == 0.0)
3123 condition_reg_ = 8;
3124 else if (r2_val < 0.0)
3125 condition_reg_ = 4;
3126 else if (r2_val > 0.0)
3127 condition_reg_ = 2;
3128 else
3129 condition_reg_ = 1;
3130
3131 switch (mask_val) {
3132 case CURRENT_ROUNDING_MODE:
3133 case ROUND_TO_NEAREST_WITH_TIES_AWAY_FROM_0:
3134 case ROUND_TO_PREPARE_FOR_SHORTER_PRECISION: {
3135 UNIMPLEMENTED();
3136 break;
3137 }
3138 case ROUND_TO_NEAREST_WITH_TIES_TO_EVEN: {
3139 double ceil_val = std::ceil(r2_val);
3140 double floor_val = std::floor(r2_val);
3141 if (std::abs(r2_val - floor_val) > std::abs(r2_val - ceil_val)) {
3142 r1_val = static_cast<int64_t>(ceil_val);
3143 } else if (std::abs(r2_val - floor_val) <
3144 std::abs(r2_val - ceil_val)) {
3145 r1_val = static_cast<int64_t>(floor_val);
3146 } else { // check which one is even:
3147 int64_t c_v = static_cast<int64_t>(ceil_val);
3148 int64_t f_v = static_cast<int64_t>(floor_val);
3149 if (f_v % 2 == 0)
3150 r1_val = f_v;
3151 else
3152 r1_val = c_v;
3153 }
3154 break;
3155 }
3156 case ROUND_TOWARD_0: {
3157 r1_val = static_cast<int64_t>(r2_val);
3158 break;
3159 }
3160 case ROUND_TOWARD_PLUS_INFINITE: {
3161 r1_val = static_cast<int64_t>(std::ceil(r2_val));
3162 break;
3163 }
3164 case ROUND_TOWARD_MINUS_INFINITE: {
3165 r1_val = static_cast<int64_t>(std::floor(r2_val));
3166 break;
3167 }
3168 default:
3169 UNREACHABLE();
3170 }
3171 set_register(r1, r1_val);
3172 break;
3173 }
3174 case CGEBR: {
3175 int mask_val = rreInstr->M3Value();
3176 int64_t r1_val = 0;
3177
3178 if (r2_fval == 0.0)
3179 condition_reg_ = 8;
3180 else if (r2_fval < 0.0)
3181 condition_reg_ = 4;
3182 else if (r2_fval > 0.0)
3183 condition_reg_ = 2;
3184 else
3185 condition_reg_ = 1;
3186
3187 switch (mask_val) {
3188 case CURRENT_ROUNDING_MODE:
3189 case ROUND_TO_NEAREST_WITH_TIES_AWAY_FROM_0:
3190 case ROUND_TO_PREPARE_FOR_SHORTER_PRECISION: {
3191 UNIMPLEMENTED();
3192 break;
3193 }
3194 case ROUND_TO_NEAREST_WITH_TIES_TO_EVEN: {
3195 float ceil_val = std::ceil(r2_fval);
3196 float floor_val = std::floor(r2_fval);
3197 if (std::abs(r2_fval - floor_val) > std::abs(r2_fval - ceil_val)) {
3198 r1_val = static_cast<int64_t>(ceil_val);
3199 } else if (std::abs(r2_fval - floor_val) <
3200 std::abs(r2_fval - ceil_val)) {
3201 r1_val = static_cast<int64_t>(floor_val);
3202 } else { // check which one is even:
3203 int64_t c_v = static_cast<int64_t>(ceil_val);
3204 int64_t f_v = static_cast<int64_t>(floor_val);
3205 if (f_v % 2 == 0)
3206 r1_val = f_v;
3207 else
3208 r1_val = c_v;
3209 }
3210 break;
3211 }
3212 case ROUND_TOWARD_0: {
3213 r1_val = static_cast<int64_t>(r2_fval);
3214 break;
3215 }
3216 case ROUND_TOWARD_PLUS_INFINITE: {
3217 r1_val = static_cast<int64_t>(std::ceil(r2_fval));
3218 break;
3219 }
3220 case ROUND_TOWARD_MINUS_INFINITE: {
3221 r1_val = static_cast<int64_t>(std::floor(r2_fval));
3222 break;
3223 }
3224 default:
3225 UNREACHABLE();
3226 }
3227 set_register(r1, r1_val);
3228 break;
3229 }
3230 case CFEBR: {
3231 int mask_val = rreInstr->M3Value();
3232 int32_t r1_val = 0;
3233
3234 if (r2_fval == 0.0)
3235 condition_reg_ = 8;
3236 else if (r2_fval < 0.0)
3237 condition_reg_ = 4;
3238 else if (r2_fval > 0.0)
3239 condition_reg_ = 2;
3240 else
3241 condition_reg_ = 1;
3242
3243 switch (mask_val) {
3244 case CURRENT_ROUNDING_MODE:
3245 case ROUND_TO_PREPARE_FOR_SHORTER_PRECISION: {
3246 r1_val = static_cast<int32_t>(r2_fval);
3247 break;
3248 }
3249 case ROUND_TO_NEAREST_WITH_TIES_AWAY_FROM_0: {
3250 float ceil_val = std::ceil(r2_fval);
3251 float floor_val = std::floor(r2_fval);
3252 float sub_val1 = std::fabs(r2_fval - floor_val);
3253 float sub_val2 = std::fabs(r2_fval - ceil_val);
3254 if (sub_val1 > sub_val2) {
3255 r1_val = static_cast<int32_t>(ceil_val);
3256 } else if (sub_val1 < sub_val2) {
3257 r1_val = static_cast<int32_t>(floor_val);
3258 } else { // round away from zero:
3259 if (r2_fval > 0.0) {
3260 r1_val = static_cast<int32_t>(ceil_val);
3261 } else {
3262 r1_val = static_cast<int32_t>(floor_val);
3263 }
3264 }
3265 break;
3266 }
3267 case ROUND_TO_NEAREST_WITH_TIES_TO_EVEN: {
3268 float ceil_val = std::ceil(r2_fval);
3269 float floor_val = std::floor(r2_fval);
3270 float sub_val1 = std::fabs(r2_fval - floor_val);
3271 float sub_val2 = std::fabs(r2_fval - ceil_val);
3272 if (sub_val1 > sub_val2) {
3273 r1_val = static_cast<int32_t>(ceil_val);
3274 } else if (sub_val1 < sub_val2) {
3275 r1_val = static_cast<int32_t>(floor_val);
3276 } else { // check which one is even:
3277 int32_t c_v = static_cast<int32_t>(ceil_val);
3278 int32_t f_v = static_cast<int32_t>(floor_val);
3279 if (f_v % 2 == 0)
3280 r1_val = f_v;
3281 else
3282 r1_val = c_v;
3283 }
3284 break;
3285 }
3286 case ROUND_TOWARD_0: {
3287 // check for overflow, cast r2_fval to 64bit integer
3288 // then check value within the range of INT_MIN and INT_MAX
3289 // and set condition code accordingly
3290 int64_t temp = static_cast<int64_t>(r2_fval);
3291 if (temp < INT_MIN || temp > INT_MAX) {
3292 condition_reg_ = CC_OF;
3293 }
3294 r1_val = static_cast<int32_t>(r2_fval);
3295 break;
3296 }
3297 case ROUND_TOWARD_PLUS_INFINITE: {
3298 r1_val = static_cast<int32_t>(std::ceil(r2_fval));
3299 break;
3300 }
3301 case ROUND_TOWARD_MINUS_INFINITE: {
3302 // check for overflow, cast r2_fval to 64bit integer
3303 // then check value within the range of INT_MIN and INT_MAX
3304 // and set condition code accordingly
3305 int64_t temp = static_cast<int64_t>(std::floor(r2_fval));
3306 if (temp < INT_MIN || temp > INT_MAX) {
3307 condition_reg_ = CC_OF;
3308 }
3309 r1_val = static_cast<int32_t>(std::floor(r2_fval));
3310 break;
3311 }
3312 default:
3313 UNREACHABLE();
3314 }
3315 set_low_register(r1, r1_val);
3316
3317 break;
3318 }
3319 default:
3320 UNREACHABLE();
3321 }
3322 }
3323
3324 /**
3325 * Decodes and simulates four byte floating point instructions
3326 */
3327 bool Simulator::DecodeFourByteFloatingPoint(Instruction* instr) {
3328 Opcode op = instr->S390OpcodeValue();
3329
3330 switch (op) {
3331 case ADBR:
3332 case AEBR:
3333 case SDBR:
3334 case SEBR:
3335 case MDBR:
3336 case MEEBR:
3337 case MADBR:
3338 case DDBR:
3339 case DEBR:
3340 case CDBR:
3341 case CEBR:
3342 case CDFBR:
3343 case CDGBR:
3344 case CEGBR:
3345 case CGEBR:
3346 case CFDBR:
3347 case CGDBR:
3348 case SQDBR:
3349 case SQEBR:
3350 case CFEBR:
3351 case CEFBR:
3352 case LCDBR:
3353 case LPDBR:
3354 case LPEBR: {
3355 RREInstruction* rreInstr = reinterpret_cast<RREInstruction*>(instr);
3356 int r1 = rreInstr->R1Value();
3357 int r2 = rreInstr->R2Value();
3358 double r1_val = get_double_from_d_register(r1);
3359 double r2_val = get_double_from_d_register(r2);
3360 float fr1_val = get_float32_from_d_register(r1);
3361 float fr2_val = get_float32_from_d_register(r2);
3362 if (op == ADBR) {
3363 r1_val += r2_val;
3364 set_d_register_from_double(r1, r1_val);
3365 SetS390ConditionCode<double>(r1_val, 0);
3366 } else if (op == AEBR) {
3367 fr1_val += fr2_val;
3368 set_d_register_from_float32(r1, fr1_val);
3369 SetS390ConditionCode<float>(fr1_val, 0);
3370 } else if (op == SDBR) {
3371 r1_val -= r2_val;
3372 set_d_register_from_double(r1, r1_val);
3373 SetS390ConditionCode<double>(r1_val, 0);
3374 } else if (op == SEBR) {
3375 fr1_val -= fr2_val;
3376 set_d_register_from_float32(r1, fr1_val);
3377 SetS390ConditionCode<float>(fr1_val, 0);
3378 } else if (op == MDBR) {
3379 r1_val *= r2_val;
3380 set_d_register_from_double(r1, r1_val);
3381 SetS390ConditionCode<double>(r1_val, 0);
3382 } else if (op == MEEBR) {
3383 fr1_val *= fr2_val;
3384 set_d_register_from_float32(r1, fr1_val);
3385 SetS390ConditionCode<float>(fr1_val, 0);
3386 } else if (op == MADBR) {
3387 RRDInstruction* rrdInstr = reinterpret_cast<RRDInstruction*>(instr);
3388 int r1 = rrdInstr->R1Value();
3389 int r2 = rrdInstr->R2Value();
3390 int r3 = rrdInstr->R3Value();
3391 double r1_val = get_double_from_d_register(r1);
3392 double r2_val = get_double_from_d_register(r2);
3393 double r3_val = get_double_from_d_register(r3);
3394 r1_val += r2_val * r3_val;
3395 set_d_register_from_double(r1, r1_val);
3396 SetS390ConditionCode<double>(r1_val, 0);
3397 } else if (op == DDBR) {
3398 r1_val /= r2_val;
3399 set_d_register_from_double(r1, r1_val);
3400 SetS390ConditionCode<double>(r1_val, 0);
3401 } else if (op == DEBR) {
3402 fr1_val /= fr2_val;
3403 set_d_register_from_float32(r1, fr1_val);
3404 SetS390ConditionCode<float>(fr1_val, 0);
3405 } else if (op == CDBR) {
3406 if (isNaN(r1_val) || isNaN(r2_val)) {
3407 condition_reg_ = CC_OF;
3408 } else {
3409 SetS390ConditionCode<double>(r1_val, r2_val);
3410 }
3411 } else if (op == CEBR) {
3412 if (isNaN(r1_val) || isNaN(r2_val)) {
3413 condition_reg_ = CC_OF;
3414 } else {
3415 SetS390ConditionCode<float>(r1_val, r2_val);
3416 }
3417 } else if (op == CDGBR) {
3418 int64_t r2_val = get_register(r2);
3419 double r1_val = static_cast<double>(r2_val);
3420 set_d_register_from_double(r1, r1_val);
3421 } else if (op == CEGBR) {
3422 int64_t fr2_val = get_register(r2);
3423 float fr1_val = static_cast<float>(fr2_val);
3424 set_d_register_from_float32(r1, fr1_val);
3425 } else if (op == CDFBR) {
3426 int32_t r2_val = get_low_register<int32_t>(r2);
3427 double r1_val = static_cast<double>(r2_val);
3428 set_d_register_from_double(r1, r1_val);
3429 } else if (op == CEFBR) {
3430 int32_t fr2_val = get_low_register<int32_t>(r2);
3431 float fr1_val = static_cast<float>(fr2_val);
3432 set_d_register_from_float32(r1, fr1_val);
3433 } else if (op == CFDBR) {
3434 DecodeFourByteFloatingPointRound(instr);
3435 } else if (op == CGDBR) {
3436 DecodeFourByteFloatingPointRound(instr);
3437 } else if (op == CGEBR) {
3438 DecodeFourByteFloatingPointRound(instr);
3439 } else if (op == SQDBR) {
3440 r1_val = std::sqrt(r2_val);
3441 set_d_register_from_double(r1, r1_val);
3442 } else if (op == SQEBR) {
3443 r1_val = std::sqrt(r2_val);
3444 set_d_register_from_float32(r1, r1_val);
3445 } else if (op == CFEBR) {
3446 DecodeFourByteFloatingPointRound(instr);
3447 } else if (op == LCDBR) {
3448 r1_val = -r2_val;
3449 set_d_register_from_double(r1, r1_val);
3450 if (r2_val != r2_val) { // input is NaN
3451 condition_reg_ = CC_OF;
3452 } else if (r2_val == 0) {
3453 condition_reg_ = CC_EQ;
3454 } else if (r2_val < 0) {
3455 condition_reg_ = CC_LT;
3456 } else if (r2_val > 0) {
3457 condition_reg_ = CC_GT;
3458 }
3459 } else if (op == LPDBR) {
3460 r1_val = std::fabs(r2_val);
3461 set_d_register_from_double(r1, r1_val);
3462 if (r2_val != r2_val) { // input is NaN
3463 condition_reg_ = CC_OF;
3464 } else if (r2_val == 0) {
3465 condition_reg_ = CC_EQ;
3466 } else {
3467 condition_reg_ = CC_GT;
3468 }
3469 } else if (op == LPEBR) {
3470 fr1_val = std::fabs(fr2_val);
3471 set_d_register_from_float32(r1, fr1_val);
3472 if (fr2_val != fr2_val) { // input is NaN
3473 condition_reg_ = CC_OF;
3474 } else if (fr2_val == 0) {
3475 condition_reg_ = CC_EQ;
3476 } else {
3477 condition_reg_ = CC_GT;
3478 }
3479 } else {
3480 UNREACHABLE();
3481 }
3482 break;
3483 }
3484 case CDLFBR:
3485 case CDLGBR:
3486 case CELGBR:
3487 case CLFDBR:
3488 case CELFBR:
3489 case CLGDBR:
3490 case CLGEBR: {
3491 DecodeFourByteFloatingPointIntConversion(instr);
3492 break;
3493 }
3494 case TMLL: {
3495 RIInstruction* riinst = reinterpret_cast<RIInstruction*>(instr);
3496 int r1 = riinst->R1Value();
3497 int mask = riinst->I2Value() & 0x0000FFFF;
3498 if (mask == 0) {
3499 condition_reg_ = 0x0;
3500 break;
3501 }
3502 uint32_t r1_val = get_low_register<uint32_t>(r1);
3503 r1_val = r1_val & 0x0000FFFF; // uses only the last 16bits
3504
3505 // Test if all selected bits are Zero
3506 bool allSelectedBitsAreZeros = true;
3507 for (int i = 0; i < 15; i++) {
3508 if (mask & (1 << i)) {
3509 if (r1_val & (1 << i)) {
3510 allSelectedBitsAreZeros = false;
3511 break;
3512 }
3513 }
3514 }
3515 if (allSelectedBitsAreZeros) {
3516 condition_reg_ = 0x8;
3517 break; // Done!
3518 }
3519
3520 // Test if all selected bits are one
3521 bool allSelectedBitsAreOnes = true;
3522 for (int i = 0; i < 15; i++) {
3523 if (mask & (1 << i)) {
3524 if (!(r1_val & (1 << i))) {
3525 allSelectedBitsAreOnes = false;
3526 break;
3527 }
3528 }
3529 }
3530 if (allSelectedBitsAreOnes) {
3531 condition_reg_ = 0x1;
3532 break; // Done!
3533 }
3534
3535 // Now we know selected bits mixed zeros and ones
3536 // Test if the leftmost bit is zero or one
3537 for (int i = 14; i >= 0; i--) {
3538 if (mask & (1 << i)) {
3539 if (r1_val & (1 << i)) {
3540 // leftmost bit is one
3541 condition_reg_ = 0x2;
3542 } else {
3543 // leftmost bit is zero
3544 condition_reg_ = 0x4;
3545 }
3546 break; // Done!
3547 }
3548 }
3549 break;
3550 }
3551 case LEDBR: {
3552 RREInstruction* rreInst = reinterpret_cast<RREInstruction*>(instr);
3553 int r1 = rreInst->R1Value();
3554 int r2 = rreInst->R2Value();
3555 double r2_val = get_double_from_d_register(r2);
3556 set_d_register_from_float32(r1, static_cast<float>(r2_val));
3557 break;
3558 }
3559 case FIDBRA: {
3560 RRFInstruction* rrfInst = reinterpret_cast<RRFInstruction*>(instr);
3561 int r1 = rrfInst->R1Value();
3562 int r2 = rrfInst->R2Value();
3563 int m3 = rrfInst->M3Value();
3564 double r2_val = get_double_from_d_register(r2);
3565 DCHECK(rrfInst->M4Value() == 0);
3566 switch (m3) {
3567 case Assembler::FIDBRA_ROUND_TO_NEAREST_AWAY_FROM_0:
3568 set_d_register_from_double(r1, round(r2_val));
3569 break;
3570 case Assembler::FIDBRA_ROUND_TOWARD_0:
3571 set_d_register_from_double(r1, trunc(r2_val));
3572 break;
3573 case Assembler::FIDBRA_ROUND_TOWARD_POS_INF:
3574 set_d_register_from_double(r1, std::ceil(r2_val));
3575 break;
3576 case Assembler::FIDBRA_ROUND_TOWARD_NEG_INF:
3577 set_d_register_from_double(r1, std::floor(r2_val));
3578 break;
3579 default:
3580 UNIMPLEMENTED();
3581 break;
3582 }
3583 break;
3584 }
3585 case FIEBRA: {
3586 RRFInstruction* rrfInst = reinterpret_cast<RRFInstruction*>(instr);
3587 int r1 = rrfInst->R1Value();
3588 int r2 = rrfInst->R2Value();
3589 int m3 = rrfInst->M3Value();
3590 float r2_val = get_float32_from_d_register(r2);
3591 DCHECK(rrfInst->M4Value() == 0);
3592 switch (m3) {
3593 case Assembler::FIDBRA_ROUND_TO_NEAREST_AWAY_FROM_0:
3594 set_d_register_from_float32(r1, round(r2_val));
3595 break;
3596 case Assembler::FIDBRA_ROUND_TOWARD_0:
3597 set_d_register_from_float32(r1, trunc(r2_val));
3598 break;
3599 case Assembler::FIDBRA_ROUND_TOWARD_POS_INF:
3600 set_d_register_from_float32(r1, std::ceil(r2_val));
3601 break;
3602 case Assembler::FIDBRA_ROUND_TOWARD_NEG_INF:
3603 set_d_register_from_float32(r1, std::floor(r2_val));
3604 break;
3605 default:
3606 UNIMPLEMENTED();
3607 break;
3608 }
3609 break;
3610 }
3611 case MSDBR: {
3612 UNIMPLEMENTED();
3613 break;
3614 }
3615 case LDEBR: {
3616 RREInstruction* rreInstr = reinterpret_cast<RREInstruction*>(instr);
3617 int r1 = rreInstr->R1Value();
3618 int r2 = rreInstr->R2Value();
3619 float fp_val = get_float32_from_d_register(r2);
3620 double db_val = static_cast<double>(fp_val);
3621 set_d_register_from_double(r1, db_val);
3622 break;
3623 }
3624 default: {
3625 UNREACHABLE();
3626 return false;
3627 }
3628 }
3629 return true;
3630 }
3631
3632 // Decode routine for six-byte instructions
3633 bool Simulator::DecodeSixByte(Instruction* instr) {
3634 Opcode op = instr->S390OpcodeValue();
3635
3636 // Pre-cast instruction to various types
3637 RIEInstruction* rieInstr = reinterpret_cast<RIEInstruction*>(instr);
3638 RILInstruction* rilInstr = reinterpret_cast<RILInstruction*>(instr);
3639 RSYInstruction* rsyInstr = reinterpret_cast<RSYInstruction*>(instr);
3640 RXEInstruction* rxeInstr = reinterpret_cast<RXEInstruction*>(instr);
3641 RXYInstruction* rxyInstr = reinterpret_cast<RXYInstruction*>(instr);
3642 SIYInstruction* siyInstr = reinterpret_cast<SIYInstruction*>(instr);
3643 SILInstruction* silInstr = reinterpret_cast<SILInstruction*>(instr);
3644 SSInstruction* ssInstr = reinterpret_cast<SSInstruction*>(instr);
3645
3646 switch (op) {
3647 case CLIY: {
3648 // Compare Immediate (Mem - Imm) (8)
3649 int b1 = siyInstr->B1Value();
3650 int64_t b1_val = (b1 == 0) ? 0 : get_register(b1);
3651 intptr_t d1_val = siyInstr->D1Value();
3652 intptr_t addr = b1_val + d1_val;
3653 uint8_t mem_val = ReadB(addr);
3654 uint8_t imm_val = siyInstr->I2Value();
3655 SetS390ConditionCode<uint8_t>(mem_val, imm_val);
3656 break;
3657 }
3658 case TMY: {
3659 // Test Under Mask (Mem - Imm) (8)
3660 int b1 = siyInstr->B1Value();
3661 int64_t b1_val = (b1 == 0) ? 0 : get_register(b1);
3662 intptr_t d1_val = siyInstr->D1Value();
3663 intptr_t addr = b1_val + d1_val;
3664 uint8_t mem_val = ReadB(addr);
3665 uint8_t imm_val = siyInstr->I2Value();
3666 uint8_t selected_bits = mem_val & imm_val;
3667 // CC0: Selected bits are zero
3668 // CC1: Selected bits mixed zeros and ones
3669 // CC3: Selected bits all ones
3670 if (0 == selected_bits) {
3671 condition_reg_ = CC_EQ; // CC0
3672 } else if (selected_bits == imm_val) {
3673 condition_reg_ = 0x1; // CC3
3674 } else {
3675 condition_reg_ = 0x4; // CC1
3676 }
3677 break;
3678 }
3679 case LDEB: {
3680 // Load Float
3681 int r1 = rxeInstr->R1Value();
3682 int rb = rxeInstr->B2Value();
3683 int rx = rxeInstr->X2Value();
3684 int offset = rxeInstr->D2Value();
3685 int64_t rb_val = (rb == 0) ? 0 : get_register(rb);
3686 int64_t rx_val = (rx == 0) ? 0 : get_register(rx);
3687 double ret = static_cast<double>(
3688 *reinterpret_cast<float*>(rx_val + rb_val + offset));
3689 set_d_register_from_double(r1, ret);
3690 break;
3691 }
3692 case LAY: {
3693 // Load Address
3694 int r1 = rxyInstr->R1Value();
3695 int rb = rxyInstr->B2Value();
3696 int rx = rxyInstr->X2Value();
3697 int offset = rxyInstr->D2Value();
3698 int64_t rb_val = (rb == 0) ? 0 : get_register(rb);
3699 int64_t rx_val = (rx == 0) ? 0 : get_register(rx);
3700 set_register(r1, rx_val + rb_val + offset);
3701 break;
3702 }
3703 case LARL: {
3704 // Load Addresss Relative Long
3705 int r1 = rilInstr->R1Value();
3706 intptr_t offset = rilInstr->I2Value() * 2;
3707 set_register(r1, get_pc() + offset);
3708 break;
3709 }
3710 case LLILF: {
3711 // Load Logical into lower 32-bits (zero extend upper 32-bits)
3712 int r1 = rilInstr->R1Value();
3713 uint64_t imm = static_cast<uint64_t>(rilInstr->I2UnsignedValue());
3714 set_register(r1, imm);
3715 break;
3716 }
3717 case LLIHF: {
3718 // Load Logical Immediate into high word
3719 int r1 = rilInstr->R1Value();
3720 uint64_t imm = static_cast<uint64_t>(rilInstr->I2UnsignedValue());
3721 set_register(r1, imm << 32);
3722 break;
3723 }
3724 case OILF:
3725 case NILF:
3726 case IILF: {
3727 // Bitwise Op on lower 32-bits
3728 int r1 = rilInstr->R1Value();
3729 uint32_t imm = rilInstr->I2UnsignedValue();
3730 uint32_t alu_out = get_low_register<uint32_t>(r1);
3731 if (NILF == op) {
3732 alu_out &= imm;
3733 SetS390BitWiseConditionCode<uint32_t>(alu_out);
3734 } else if (OILF == op) {
3735 alu_out |= imm;
3736 SetS390BitWiseConditionCode<uint32_t>(alu_out);
3737 } else if (op == IILF) {
3738 alu_out = imm;
3739 } else {
3740 DCHECK(false);
3741 }
3742 set_low_register(r1, alu_out);
3743 break;
3744 }
3745 case OIHF:
3746 case NIHF:
3747 case IIHF: {
3748 // Bitwise Op on upper 32-bits
3749 int r1 = rilInstr->R1Value();
3750 uint32_t imm = rilInstr->I2Value();
3751 uint32_t alu_out = get_high_register<uint32_t>(r1);
3752 if (op == NIHF) {
3753 alu_out &= imm;
3754 SetS390BitWiseConditionCode<uint32_t>(alu_out);
3755 } else if (op == OIHF) {
3756 alu_out |= imm;
3757 SetS390BitWiseConditionCode<uint32_t>(alu_out);
3758 } else if (op == IIHF) {
3759 alu_out = imm;
3760 } else {
3761 DCHECK(false);
3762 }
3763 set_high_register(r1, alu_out);
3764 break;
3765 }
3766 case CLFI: {
3767 // Compare Logical with Immediate (32)
3768 int r1 = rilInstr->R1Value();
3769 uint32_t imm = rilInstr->I2UnsignedValue();
3770 SetS390ConditionCode<uint32_t>(get_low_register<uint32_t>(r1), imm);
3771 break;
3772 }
3773 case CFI: {
3774 // Compare with Immediate (32)
3775 int r1 = rilInstr->R1Value();
3776 int32_t imm = rilInstr->I2Value();
3777 SetS390ConditionCode<int32_t>(get_low_register<int32_t>(r1), imm);
3778 break;
3779 }
3780 case CLGFI: {
3781 // Compare Logical with Immediate (64)
3782 int r1 = rilInstr->R1Value();
3783 uint64_t imm = static_cast<uint64_t>(rilInstr->I2UnsignedValue());
3784 SetS390ConditionCode<uint64_t>(get_register(r1), imm);
3785 break;
3786 }
3787 case CGFI: {
3788 // Compare with Immediate (64)
3789 int r1 = rilInstr->R1Value();
3790 int64_t imm = static_cast<int64_t>(rilInstr->I2Value());
3791 SetS390ConditionCode<int64_t>(get_register(r1), imm);
3792 break;
3793 }
3794 case BRASL: {
3795 // Branch and Save Relative Long
3796 int r1 = rilInstr->R1Value();
3797 intptr_t d2 = rilInstr->I2Value();
3798 intptr_t pc = get_pc();
3799 set_register(r1, pc + 6); // save next instruction to register
3800 set_pc(pc + d2 * 2); // update register
3801 break;
3802 }
3803 case BRCL: {
3804 // Branch on Condition Relative Long
3805 Condition m1 = (Condition)rilInstr->R1Value();
3806 if (TestConditionCode((Condition)m1)) {
3807 intptr_t offset = rilInstr->I2Value() * 2;
3808 set_pc(get_pc() + offset);
3809 }
3810 break;
3811 }
3812 case LMG:
3813 case STMG: {
3814 // Store Multiple 64-bits.
3815 int r1 = rsyInstr->R1Value();
3816 int r3 = rsyInstr->R3Value();
3817 int rb = rsyInstr->B2Value();
3818 int offset = rsyInstr->D2Value();
3819
3820 // Regs roll around if r3 is less than r1.
3821 // Artifically increase r3 by 16 so we can calculate
3822 // the number of regs stored properly.
3823 if (r3 < r1) r3 += 16;
3824
3825 int64_t rb_val = (rb == 0) ? 0 : get_register(rb);
3826
3827 // Store each register in ascending order.
3828 for (int i = 0; i <= r3 - r1; i++) {
3829 if (op == LMG) {
3830 int64_t value = ReadDW(rb_val + offset + 8 * i);
3831 set_register((r1 + i) % 16, value);
3832 } else if (op == STMG) {
3833 int64_t value = get_register((r1 + i) % 16);
3834 WriteDW(rb_val + offset + 8 * i, value);
3835 } else {
3836 DCHECK(false);
3837 }
3838 }
3839 break;
3840 }
3841 case SLLK:
3842 case RLL:
3843 case SRLK: {
3844 // For SLLK/SRLL, the 32-bit third operand is shifted the number
3845 // of bits specified by the second-operand address, and the result is
3846 // placed at the first-operand location. Except for when the R1 and R3
3847 // fields designate the same register, the third operand remains
3848 // unchanged in general register R3.
3849 int r1 = rsyInstr->R1Value();
3850 int r3 = rsyInstr->R3Value();
3851 int b2 = rsyInstr->B2Value();
3852 intptr_t d2 = rsyInstr->D2Value();
3853 // only takes rightmost 6 bits
3854 int64_t b2_val = (b2 == 0) ? 0 : get_register(b2);
3855 int shiftBits = (b2_val + d2) & 0x3F;
3856 // unsigned
3857 uint32_t r3_val = get_low_register<uint32_t>(r3);
3858 uint32_t alu_out = 0;
3859 if (SLLK == op) {
3860 alu_out = r3_val << shiftBits;
3861 } else if (SRLK == op) {
3862 alu_out = r3_val >> shiftBits;
3863 } else if (RLL == op) {
3864 uint32_t rotateBits = r3_val >> (32 - shiftBits);
3865 alu_out = (r3_val << shiftBits) | (rotateBits);
3866 } else {
3867 UNREACHABLE();
3868 }
3869 set_low_register(r1, alu_out);
3870 break;
3871 }
3872 case SLLG:
3873 case SRLG: {
3874 // For SLLG/SRLG, the 64-bit third operand is shifted the number
3875 // of bits specified by the second-operand address, and the result is
3876 // placed at the first-operand location. Except for when the R1 and R3
3877 // fields designate the same register, the third operand remains
3878 // unchanged in general register R3.
3879 int r1 = rsyInstr->R1Value();
3880 int r3 = rsyInstr->R3Value();
3881 int b2 = rsyInstr->B2Value();
3882 intptr_t d2 = rsyInstr->D2Value();
3883 // only takes rightmost 6 bits
3884 int64_t b2_val = (b2 == 0) ? 0 : get_register(b2);
3885 int shiftBits = (b2_val + d2) & 0x3F;
3886 // unsigned
3887 uint64_t r3_val = get_register(r3);
3888 uint64_t alu_out = 0;
3889 if (op == SLLG) {
3890 alu_out = r3_val << shiftBits;
3891 } else if (op == SRLG) {
3892 alu_out = r3_val >> shiftBits;
3893 } else {
3894 UNREACHABLE();
3895 }
3896 set_register(r1, alu_out);
3897 break;
3898 }
3899 case SLAK:
3900 case SRAK: {
3901 // 32-bit non-clobbering shift-left/right arithmetic
3902 int r1 = rsyInstr->R1Value();
3903 int r3 = rsyInstr->R3Value();
3904 int b2 = rsyInstr->B2Value();
3905 intptr_t d2 = rsyInstr->D2Value();
3906 // only takes rightmost 6 bits
3907 int64_t b2_val = (b2 == 0) ? 0 : get_register(b2);
3908 int shiftBits = (b2_val + d2) & 0x3F;
3909 int32_t r3_val = get_low_register<int32_t>(r3);
3910 int32_t alu_out = 0;
3911 bool isOF = false;
3912 if (op == SLAK) {
3913 isOF = CheckOverflowForShiftLeft(r3_val, shiftBits);
3914 alu_out = r3_val << shiftBits;
3915 } else if (op == SRAK) {
3916 alu_out = r3_val >> shiftBits;
3917 }
3918 set_low_register(r1, alu_out);
3919 SetS390ConditionCode<int32_t>(alu_out, 0);
3920 SetS390OverflowCode(isOF);
3921 break;
3922 }
3923 case SLAG:
3924 case SRAG: {
3925 // 64-bit non-clobbering shift-left/right arithmetic
3926 int r1 = rsyInstr->R1Value();
3927 int r3 = rsyInstr->R3Value();
3928 int b2 = rsyInstr->B2Value();
3929 intptr_t d2 = rsyInstr->D2Value();
3930 // only takes rightmost 6 bits
3931 int64_t b2_val = (b2 == 0) ? 0 : get_register(b2);
3932 int shiftBits = (b2_val + d2) & 0x3F;
3933 int64_t r3_val = get_register(r3);
3934 intptr_t alu_out = 0;
3935 bool isOF = false;
3936 if (op == SLAG) {
3937 isOF = CheckOverflowForShiftLeft(r3_val, shiftBits);
3938 alu_out = r3_val << shiftBits;
3939 } else if (op == SRAG) {
3940 alu_out = r3_val >> shiftBits;
3941 }
3942 set_register(r1, alu_out);
3943 SetS390ConditionCode<intptr_t>(alu_out, 0);
3944 SetS390OverflowCode(isOF);
3945 break;
3946 }
3947 case LMY:
3948 case STMY: {
3949 RSYInstruction* rsyInstr = reinterpret_cast<RSYInstruction*>(instr);
3950 // Load/Store Multiple (32)
3951 int r1 = rsyInstr->R1Value();
3952 int r3 = rsyInstr->R3Value();
3953 int b2 = rsyInstr->B2Value();
3954 int offset = rsyInstr->D2Value();
3955
3956 // Regs roll around if r3 is less than r1.
3957 // Artifically increase r3 by 16 so we can calculate
3958 // the number of regs stored properly.
3959 if (r3 < r1) r3 += 16;
3960
3961 int32_t b2_val = (b2 == 0) ? 0 : get_low_register<int32_t>(b2);
3962
3963 // Store each register in ascending order.
3964 for (int i = 0; i <= r3 - r1; i++) {
3965 if (op == LMY) {
3966 int32_t value = ReadW(b2_val + offset + 4 * i, instr);
3967 set_low_register((r1 + i) % 16, value);
3968 } else {
3969 int32_t value = get_low_register<int32_t>((r1 + i) % 16);
3970 WriteW(b2_val + offset + 4 * i, value, instr);
3971 }
3972 }
3973 break;
3974 }
3975 case LT:
3976 case LTG: {
3977 // Load and Test (32/64)
3978 int r1 = rxyInstr->R1Value();
3979 int x2 = rxyInstr->X2Value();
3980 int b2 = rxyInstr->B2Value();
3981 int d2 = rxyInstr->D2Value();
3982
3983 int64_t x2_val = (x2 == 0) ? 0 : get_register(x2);
3984 int64_t b2_val = (b2 == 0) ? 0 : get_register(b2);
3985 intptr_t addr = x2_val + b2_val + d2;
3986
3987 if (op == LT) {
3988 int32_t value = ReadW(addr, instr);
3989 set_low_register(r1, value);
3990 SetS390ConditionCode<int32_t>(value, 0);
3991 } else if (op == LTG) {
3992 int64_t value = ReadDW(addr);
3993 set_register(r1, value);
3994 SetS390ConditionCode<int64_t>(value, 0);
3995 }
3996 break;
3997 }
3998 case LY:
3999 case LB:
4000 case LGB:
4001 case LG:
4002 case LGF:
4003 case LGH:
4004 case LLGF:
4005 case STG:
4006 case STY:
4007 case STCY:
4008 case STHY:
4009 case STEY:
4010 case LDY:
4011 case LHY:
4012 case STDY:
4013 case LEY: {
4014 // Miscellaneous Loads and Stores
4015 int r1 = rxyInstr->R1Value();
4016 int x2 = rxyInstr->X2Value();
4017 int b2 = rxyInstr->B2Value();
4018 int d2 = rxyInstr->D2Value();
4019 int64_t x2_val = (x2 == 0) ? 0 : get_register(x2);
4020 int64_t b2_val = (b2 == 0) ? 0 : get_register(b2);
4021 intptr_t addr = x2_val + b2_val + d2;
4022 if (op == LY) {
4023 uint32_t mem_val = ReadWU(addr, instr);
4024 set_low_register(r1, mem_val);
4025 } else if (op == LB) {
4026 int32_t mem_val = ReadB(addr);
4027 set_low_register(r1, mem_val);
4028 } else if (op == LGB) {
4029 int64_t mem_val = ReadB(addr);
4030 set_register(r1, mem_val);
4031 } else if (op == LG) {
4032 int64_t mem_val = ReadDW(addr);
4033 set_register(r1, mem_val);
4034 } else if (op == LGF) {
4035 int64_t mem_val = static_cast<int64_t>(ReadW(addr, instr));
4036 set_register(r1, mem_val);
4037 } else if (op == LGH) {
4038 int64_t mem_val = static_cast<int64_t>(ReadH(addr, instr));
4039 set_register(r1, mem_val);
4040 } else if (op == LLGF) {
4041 // int r1 = rreInst->R1Value();
4042 // int r2 = rreInst->R2Value();
4043 // int32_t r2_val = get_low_register<int32_t>(r2);
4044 // uint64_t r2_finalval = (static_cast<uint64_t>(r2_val)
4045 // & 0x00000000ffffffff);
4046 // set_register(r1, r2_finalval);
4047 // break;
4048 uint64_t mem_val = static_cast<uint64_t>(ReadWU(addr, instr));
4049 set_register(r1, mem_val);
4050 } else if (op == LDY) {
4051 uint64_t dbl_val = *reinterpret_cast<uint64_t*>(addr);
4052 set_d_register(r1, dbl_val);
4053 } else if (op == STEY) {
4054 int64_t frs_val = get_d_register(r1) >> 32;
4055 WriteW(addr, static_cast<int32_t>(frs_val), instr);
4056 } else if (op == LEY) {
4057 float float_val = *reinterpret_cast<float*>(addr);
4058 set_d_register_from_float32(r1, float_val);
4059 } else if (op == STY) {
4060 uint32_t value = get_low_register<uint32_t>(r1);
4061 WriteW(addr, value, instr);
4062 } else if (op == STG) {
4063 uint64_t value = get_register(r1);
4064 WriteDW(addr, value);
4065 } else if (op == STDY) {
4066 int64_t frs_val = get_d_register(r1);
4067 WriteDW(addr, frs_val);
4068 } else if (op == STCY) {
4069 uint8_t value = get_low_register<uint32_t>(r1);
4070 WriteB(addr, value);
4071 } else if (op == STHY) {
4072 uint16_t value = get_low_register<uint32_t>(r1);
4073 WriteH(addr, value, instr);
4074 } else if (op == LHY) {
4075 int32_t result = static_cast<int32_t>(ReadH(addr, instr));
4076 set_low_register(r1, result);
4077 }
4078 break;
4079 }
4080 case MVC: {
4081 // Move Character
4082 int b1 = ssInstr->B1Value();
4083 intptr_t d1 = ssInstr->D1Value();
4084 int b2 = ssInstr->B2Value();
4085 intptr_t d2 = ssInstr->D2Value();
4086 int length = ssInstr->Length();
4087 int64_t b1_val = (b1 == 0) ? 0 : get_register(b1);
4088 int64_t b2_val = (b2 == 0) ? 0 : get_register(b2);
4089 intptr_t src_addr = b2_val + d2;
4090 intptr_t dst_addr = b1_val + d1;
4091 // remember that the length is the actual length - 1
4092 for (int i = 0; i < length + 1; ++i) {
4093 WriteB(dst_addr++, ReadB(src_addr++));
4094 }
4095 break;
4096 }
4097 case MVHI: {
4098 // Move Integer (32)
4099 int b1 = silInstr->B1Value();
4100 intptr_t d1 = silInstr->D1Value();
4101 int16_t i2 = silInstr->I2Value();
4102 int64_t b1_val = (b1 == 0) ? 0 : get_register(b1);
4103 intptr_t src_addr = b1_val + d1;
4104 WriteW(src_addr, i2, instr);
4105 break;
4106 }
4107 case MVGHI: {
4108 // Move Integer (64)
4109 int b1 = silInstr->B1Value();
4110 intptr_t d1 = silInstr->D1Value();
4111 int16_t i2 = silInstr->I2Value();
4112 int64_t b1_val = (b1 == 0) ? 0 : get_register(b1);
4113 intptr_t src_addr = b1_val + d1;
4114 WriteDW(src_addr, i2);
4115 break;
4116 }
4117 case LLH:
4118 case LLGH: {
4119 // Load Logical Halfworld
4120 int r1 = rxyInstr->R1Value();
4121 int b2 = rxyInstr->B2Value();
4122 int x2 = rxyInstr->X2Value();
4123 int64_t b2_val = (b2 == 0) ? 0 : get_register(b2);
4124 int64_t x2_val = (x2 == 0) ? 0 : get_register(x2);
4125 intptr_t d2_val = rxyInstr->D2Value();
4126 uint16_t mem_val = ReadHU(b2_val + d2_val + x2_val, instr);
4127 if (op == LLH) {
4128 set_low_register(r1, mem_val);
4129 } else if (op == LLGH) {
4130 set_register(r1, mem_val);
4131 } else {
4132 UNREACHABLE();
4133 }
4134 break;
4135 }
4136 case LLC:
4137 case LLGC: {
4138 // Load Logical Character - loads a byte and zero extends.
4139 int r1 = rxyInstr->R1Value();
4140 int b2 = rxyInstr->B2Value();
4141 int x2 = rxyInstr->X2Value();
4142 int64_t b2_val = (b2 == 0) ? 0 : get_register(b2);
4143 int64_t x2_val = (x2 == 0) ? 0 : get_register(x2);
4144 intptr_t d2_val = rxyInstr->D2Value();
4145 uint8_t mem_val = ReadBU(b2_val + d2_val + x2_val);
4146 if (op == LLC) {
4147 set_low_register(r1, static_cast<uint32_t>(mem_val));
4148 } else if (op == LLGC) {
4149 set_register(r1, static_cast<uint64_t>(mem_val));
4150 } else {
4151 UNREACHABLE();
4152 }
4153 break;
4154 }
4155 case XIHF:
4156 case XILF: {
4157 int r1 = rilInstr->R1Value();
4158 uint32_t imm = rilInstr->I2UnsignedValue();
4159 uint32_t alu_out = 0;
4160 if (op == XILF) {
4161 alu_out = get_low_register<uint32_t>(r1);
4162 alu_out = alu_out ^ imm;
4163 set_low_register(r1, alu_out);
4164 } else if (op == XIHF) {
4165 alu_out = get_high_register<uint32_t>(r1);
4166 alu_out = alu_out ^ imm;
4167 set_high_register(r1, alu_out);
4168 } else {
4169 UNREACHABLE();
4170 }
4171 SetS390BitWiseConditionCode<uint32_t>(alu_out);
4172 break;
4173 }
4174 case RISBG: {
4175 // Rotate then insert selected bits
4176 int r1 = rieInstr->R1Value();
4177 int r2 = rieInstr->R2Value();
4178 // Starting Bit Position is Bits 2-7 of I3 field
4179 uint32_t start_bit = rieInstr->I3Value() & 0x3F;
4180 // Ending Bit Position is Bits 2-7 of I4 field
4181 uint32_t end_bit = rieInstr->I4Value() & 0x3F;
4182 // Shift Amount is Bits 2-7 of I5 field
4183 uint32_t shift_amount = rieInstr->I5Value() & 0x3F;
4184 // Zero out Remaining (unslected) bits if Bit 0 of I4 is 1.
4185 bool zero_remaining = (0 != (rieInstr->I4Value() & 0x80));
4186
4187 uint64_t src_val = get_register(r2);
4188
4189 // Rotate Left by Shift Amount first
4190 uint64_t rotated_val =
4191 (src_val << shift_amount) | (src_val >> (64 - shift_amount));
4192 int32_t width = end_bit - start_bit + 1;
4193
4194 uint64_t selection_mask = 0;
4195 if (width < 64) {
4196 selection_mask = (static_cast<uint64_t>(1) << width) - 1;
4197 } else {
4198 selection_mask = static_cast<uint64_t>(static_cast<int64_t>(-1));
4199 }
4200 selection_mask = selection_mask << (63 - end_bit);
4201
4202 uint64_t selected_val = rotated_val & selection_mask;
4203
4204 if (!zero_remaining) {
4205 // Merged the unselected bits from the original value
4206 selected_val = (src_val & ~selection_mask) | selected_val;
4207 }
4208
4209 // Condition code is set by treating result as 64-bit signed int
4210 SetS390ConditionCode<int64_t>(selected_val, 0);
4211 set_register(r1, selected_val);
4212 break;
4213 }
4214 default:
4215 return DecodeSixByteArithmetic(instr);
4216 }
4217 return true;
4218 }
4219
4220 /**
4221 * Decodes and simulates six byte arithmetic instructions
4222 */
4223 bool Simulator::DecodeSixByteArithmetic(Instruction* instr) {
4224 Opcode op = instr->S390OpcodeValue();
4225
4226 // Pre-cast instruction to various types
4227 SIYInstruction* siyInstr = reinterpret_cast<SIYInstruction*>(instr);
4228
4229 switch (op) {
4230 case CDB:
4231 case ADB:
4232 case SDB:
4233 case MDB:
4234 case DDB:
4235 case SQDB: {
4236 RXEInstruction* rxeInstr = reinterpret_cast<RXEInstruction*>(instr);
4237 int b2 = rxeInstr->B2Value();
4238 int x2 = rxeInstr->X2Value();
4239 int64_t b2_val = (b2 == 0) ? 0 : get_register(b2);
4240 int64_t x2_val = (x2 == 0) ? 0 : get_register(x2);
4241 intptr_t d2_val = rxeInstr->D2Value();
4242 double r1_val = get_double_from_d_register(rxeInstr->R1Value());
4243 double dbl_val = ReadDouble(b2_val + x2_val + d2_val);
4244
4245 switch (op) {
4246 case CDB:
4247 SetS390ConditionCode<double>(r1_val, dbl_val);
4248 break;
4249 case ADB:
4250 r1_val += dbl_val;
4251 set_d_register_from_double(r1, r1_val);
4252 SetS390ConditionCode<double>(r1_val, 0);
4253 break;
4254 case SDB:
4255 r1_val -= dbl_val;
4256 set_d_register_from_double(r1, r1_val);
4257 SetS390ConditionCode<double>(r1_val, 0);
4258 break;
4259 case MDB:
4260 r1_val *= dbl_val;
4261 set_d_register_from_double(r1, r1_val);
4262 SetS390ConditionCode<double>(r1_val, 0);
4263 break;
4264 case DDB:
4265 r1_val /= dbl_val;
4266 set_d_register_from_double(r1, r1_val);
4267 SetS390ConditionCode<double>(r1_val, 0);
4268 break;
4269 case SQDB:
4270 r1_val = std::sqrt(dbl_val);
4271 set_d_register_from_double(r1, r1_val);
4272 default:
4273 UNREACHABLE();
4274 break;
4275 }
4276 break;
4277 }
4278 case LRV:
4279 case LRVH:
4280 case STRV:
4281 case STRVH: {
4282 RXYInstruction* rxyInstr = reinterpret_cast<RXYInstruction*>(instr);
4283 int r1 = rxyInstr->R1Value();
4284 int x2 = rxyInstr->X2Value();
4285 int b2 = rxyInstr->B2Value();
4286 int d2 = rxyInstr->D2Value();
4287 int32_t r1_val = get_low_register<int32_t>(r1);
4288 int64_t x2_val = (x2 == 0) ? 0 : get_register(x2);
4289 int64_t b2_val = (b2 == 0) ? 0 : get_register(b2);
4290 intptr_t mem_addr = b2_val + x2_val + d2;
4291
4292 if (op == LRVH) {
4293 int16_t mem_val = ReadH(mem_addr, instr);
4294 int32_t result = ByteReverse(mem_val) & 0x0000ffff;
4295 result |= r1_val & 0xffff0000;
4296 set_low_register(r1, result);
4297 } else if (op == LRV) {
4298 int32_t mem_val = ReadW(mem_addr, instr);
4299 set_low_register(r1, ByteReverse(mem_val));
4300 } else if (op == STRVH) {
4301 int16_t result = static_cast<int16_t>(r1_val >> 16);
4302 WriteH(mem_addr, ByteReverse(result), instr);
4303 } else if (op == STRV) {
4304 WriteW(mem_addr, ByteReverse(r1_val), instr);
4305 }
4306
4307 break;
4308 }
4309 case AHIK:
4310 case AGHIK: {
4311 // Non-clobbering Add Halfword Immediate
4312 RIEInstruction* rieInst = reinterpret_cast<RIEInstruction*>(instr);
4313 int r1 = rieInst->R1Value();
4314 int r2 = rieInst->R2Value();
4315 bool isOF = false;
4316 if (AHIK == op) {
4317 // 32-bit Add
4318 int32_t r2_val = get_low_register<int32_t>(r2);
4319 int32_t imm = rieInst->I6Value();
4320 isOF = CheckOverflowForIntAdd(r2_val, imm);
4321 set_low_register(r1, r2_val + imm);
4322 SetS390ConditionCode<int32_t>(r2_val + imm, 0);
4323 } else if (AGHIK == op) {
4324 // 64-bit Add
4325 int64_t r2_val = get_register(r2);
4326 int64_t imm = static_cast<int64_t>(rieInst->I6Value());
4327 isOF = CheckOverflowForIntAdd(r2_val, imm);
4328 set_register(r1, r2_val + imm);
4329 SetS390ConditionCode<int64_t>(r2_val + imm, 0);
4330 }
4331 SetS390OverflowCode(isOF);
4332 break;
4333 }
4334 case ALFI:
4335 case SLFI: {
4336 RILInstruction* rilInstr = reinterpret_cast<RILInstruction*>(instr);
4337 int r1 = rilInstr->R1Value();
4338 uint32_t imm = rilInstr->I2UnsignedValue();
4339 uint32_t alu_out = get_low_register<uint32_t>(r1);
4340 if (op == ALFI) {
4341 alu_out += imm;
4342 } else if (op == SLFI) {
4343 alu_out -= imm;
4344 }
4345 SetS390ConditionCode<uint32_t>(alu_out, 0);
4346 set_low_register(r1, alu_out);
4347 break;
4348 }
4349 case ML: {
4350 UNIMPLEMENTED();
4351 break;
4352 }
4353 case AY:
4354 case SY:
4355 case NY:
4356 case OY:
4357 case XY:
4358 case CY: {
4359 RXYInstruction* rxyInstr = reinterpret_cast<RXYInstruction*>(instr);
4360 int r1 = rxyInstr->R1Value();
4361 int x2 = rxyInstr->X2Value();
4362 int b2 = rxyInstr->B2Value();
4363 int d2 = rxyInstr->D2Value();
4364 int64_t x2_val = (x2 == 0) ? 0 : get_register(x2);
4365 int64_t b2_val = (b2 == 0) ? 0 : get_register(b2);
4366 int32_t alu_out = get_low_register<int32_t>(r1);
4367 int32_t mem_val = ReadW(b2_val + x2_val + d2, instr);
4368 bool isOF = false;
4369 if (op == AY) {
4370 isOF = CheckOverflowForIntAdd(alu_out, mem_val);
4371 alu_out += mem_val;
4372 SetS390ConditionCode<int32_t>(alu_out, 0);
4373 SetS390OverflowCode(isOF);
4374 } else if (op == SY) {
4375 isOF = CheckOverflowForIntSub(alu_out, mem_val);
4376 alu_out -= mem_val;
4377 SetS390ConditionCode<int32_t>(alu_out, 0);
4378 SetS390OverflowCode(isOF);
4379 } else if (op == NY) {
4380 alu_out &= mem_val;
4381 SetS390BitWiseConditionCode<uint32_t>(alu_out);
4382 } else if (op == OY) {
4383 alu_out |= mem_val;
4384 SetS390BitWiseConditionCode<uint32_t>(alu_out);
4385 } else if (op == XY) {
4386 alu_out ^= mem_val;
4387 SetS390BitWiseConditionCode<uint32_t>(alu_out);
4388 } else if (op == CY) {
4389 SetS390ConditionCode<int32_t>(alu_out, mem_val);
4390 }
4391 if (op != CY) {
4392 set_low_register(r1, alu_out);
4393 }
4394 break;
4395 }
4396 case AHY:
4397 case SHY: {
4398 RXYInstruction* rxyInstr = reinterpret_cast<RXYInstruction*>(instr);
4399 int32_t r1_val = get_low_register<int32_t>(rxyInstr->R1Value());
4400 int b2 = rxyInstr->B2Value();
4401 int x2 = rxyInstr->X2Value();
4402 int64_t b2_val = (b2 == 0) ? 0 : get_register(b2);
4403 int64_t x2_val = (x2 == 0) ? 0 : get_register(x2);
4404 intptr_t d2_val = rxyInstr->D2Value();
4405 int16_t mem_val = ReadH(b2_val + d2_val + x2_val, instr);
4406 int32_t alu_out = 0;
4407 bool isOF = false;
4408 switch (op) {
4409 case AHY:
4410 alu_out = r1_val + mem_val;
4411 isOF = CheckOverflowForIntAdd(r1_val, mem_val);
4412 break;
4413 case SHY:
4414 alu_out = r1_val - mem_val;
4415 isOF = CheckOverflowForIntSub(r1_val, mem_val);
4416 break;
4417 default:
4418 UNREACHABLE();
4419 break;
4420 }
4421 set_low_register(r1, alu_out);
4422 SetS390ConditionCode<int32_t>(alu_out, 0);
4423 SetS390OverflowCode(isOF);
4424 break;
4425 }
4426 case AG:
4427 case SG:
4428 case NG:
4429 case OG:
4430 case XG:
4431 case CG:
4432 case CLG: {
4433 RXYInstruction* rxyInstr = reinterpret_cast<RXYInstruction*>(instr);
4434 int r1 = rxyInstr->R1Value();
4435 int x2 = rxyInstr->X2Value();
4436 int b2 = rxyInstr->B2Value();
4437 int d2 = rxyInstr->D2Value();
4438 int64_t x2_val = (x2 == 0) ? 0 : get_register(x2);
4439 int64_t b2_val = (b2 == 0) ? 0 : get_register(b2);
4440 int64_t alu_out = get_register(r1);
4441 int64_t mem_val = ReadDW(b2_val + x2_val + d2);
4442
4443 switch (op) {
4444 case AG: {
4445 alu_out += mem_val;
4446 SetS390ConditionCode<int32_t>(alu_out, 0);
4447 break;
4448 }
4449 case SG: {
4450 alu_out -= mem_val;
4451 SetS390ConditionCode<int32_t>(alu_out, 0);
4452 break;
4453 }
4454 case NG: {
4455 alu_out &= mem_val;
4456 SetS390BitWiseConditionCode<uint32_t>(alu_out);
4457 break;
4458 }
4459 case OG: {
4460 alu_out |= mem_val;
4461 SetS390BitWiseConditionCode<uint32_t>(alu_out);
4462 break;
4463 }
4464 case XG: {
4465 alu_out ^= mem_val;
4466 SetS390BitWiseConditionCode<uint32_t>(alu_out);
4467 break;
4468 }
4469 case CG: {
4470 SetS390ConditionCode<int64_t>(alu_out, mem_val);
4471 break;
4472 }
4473 case CLG: {
4474 SetS390ConditionCode<uint64_t>(alu_out, mem_val);
4475 break;
4476 }
4477 default: {
4478 DCHECK(false);
4479 break;
4480 }
4481 }
4482
4483 if (op != CG) {
4484 set_register(r1, alu_out);
4485 }
4486 break;
4487 }
4488 case ALY:
4489 case SLY:
4490 case CLY: {
4491 RXYInstruction* rxyInstr = reinterpret_cast<RXYInstruction*>(instr);
4492 int r1 = rxyInstr->R1Value();
4493 int x2 = rxyInstr->X2Value();
4494 int b2 = rxyInstr->B2Value();
4495 int d2 = rxyInstr->D2Value();
4496 int64_t x2_val = (x2 == 0) ? 0 : get_register(x2);
4497 int64_t b2_val = (b2 == 0) ? 0 : get_register(b2);
4498 uint32_t alu_out = get_low_register<uint32_t>(r1);
4499 uint32_t mem_val = ReadWU(b2_val + x2_val + d2, instr);
4500
4501 if (op == ALY) {
4502 alu_out += mem_val;
4503 set_low_register(r1, alu_out);
4504 SetS390ConditionCode<uint32_t>(alu_out, 0);
4505 } else if (op == SLY) {
4506 alu_out -= mem_val;
4507 set_low_register(r1, alu_out);
4508 SetS390ConditionCode<uint32_t>(alu_out, 0);
4509 } else if (op == CLY) {
4510 SetS390ConditionCode<uint32_t>(alu_out, mem_val);
4511 }
4512 break;
4513 }
4514 case AGFI:
4515 case AFI: {
4516 // Clobbering Add Word Immediate
4517 RILInstruction* rilInstr = reinterpret_cast<RILInstruction*>(instr);
4518 int r1 = rilInstr->R1Value();
4519 int i2 = rilInstr->I2Value();
4520 bool isOF = false;
4521 if (AFI == op) {
4522 // 32-bit Add (Register + 32-bit Immediate)
4523 int32_t r1_val = get_low_register<int32_t>(r1);
4524 isOF = CheckOverflowForIntAdd(r1_val, i2);
4525 int32_t alu_out = r1_val + i2;
4526 set_low_register(r1, alu_out);
4527 SetS390ConditionCode<int32_t>(alu_out, 0);
4528 } else if (AGFI == op) {
4529 // 64-bit Add (Register + 32-bit Imm)
4530 int64_t r1_val = get_register(r1);
4531 isOF = CheckOverflowForIntAdd(r1_val, i2);
4532 int64_t alu_out = r1_val + i2;
4533 set_register(r1, alu_out);
4534 SetS390ConditionCode<int64_t>(alu_out, 0);
4535 }
4536 SetS390OverflowCode(isOF);
4537 break;
4538 }
4539 case ASI: {
4540 int8_t i2 = static_cast<int8_t>(siyInstr->I2Value());
4541 int b1 = siyInstr->B1Value();
4542 intptr_t b1_val = (b1 == 0) ? 0 : get_register(b1);
4543
4544 int d1_val = siyInstr->D1Value();
4545 intptr_t addr = b1_val + d1_val;
4546
4547 int32_t mem_val = ReadW(addr, instr);
4548 bool isOF = CheckOverflowForIntAdd(mem_val, i2);
4549 int32_t alu_out = mem_val + i2;
4550 SetS390ConditionCode<int32_t>(alu_out, 0);
4551 SetS390OverflowCode(isOF);
4552 WriteW(addr, alu_out, instr);
4553 break;
4554 }
4555 case AGSI: {
4556 int8_t i2 = static_cast<int8_t>(siyInstr->I2Value());
4557 int b1 = siyInstr->B1Value();
4558 intptr_t b1_val = (b1 == 0) ? 0 : get_register(b1);
4559
4560 int d1_val = siyInstr->D1Value();
4561 intptr_t addr = b1_val + d1_val;
4562
4563 int64_t mem_val = ReadDW(addr);
4564 int isOF = CheckOverflowForIntAdd(mem_val, i2);
4565 int64_t alu_out = mem_val + i2;
4566 SetS390ConditionCode<uint64_t>(alu_out, 0);
4567 SetS390OverflowCode(isOF);
4568 WriteDW(addr, alu_out);
4569 break;
4570 }
4571 case AGF:
4572 case SGF:
4573 case ALG:
4574 case SLG: {
4575 #ifndef V8_TARGET_ARCH_S390X
4576 DCHECK(false);
4577 #endif
4578 RXYInstruction* rxyInstr = reinterpret_cast<RXYInstruction*>(instr);
4579 int r1 = rxyInstr->R1Value();
4580 uint64_t r1_val = get_register(rxyInstr->R1Value());
4581 int b2 = rxyInstr->B2Value();
4582 int x2 = rxyInstr->X2Value();
4583 int64_t b2_val = (b2 == 0) ? 0 : get_register(b2);
4584 int64_t x2_val = (x2 == 0) ? 0 : get_register(x2);
4585 intptr_t d2_val = rxyInstr->D2Value();
4586 uint64_t alu_out = r1_val;
4587 if (op == ALG) {
4588 uint64_t mem_val =
4589 static_cast<uint64_t>(ReadDW(b2_val + d2_val + x2_val));
4590 alu_out += mem_val;
4591 SetS390ConditionCode<uint64_t>(alu_out, 0);
4592 } else if (op == SLG) {
4593 uint64_t mem_val =
4594 static_cast<uint64_t>(ReadDW(b2_val + d2_val + x2_val));
4595 alu_out -= mem_val;
4596 SetS390ConditionCode<uint64_t>(alu_out, 0);
4597 } else if (op == AGF) {
4598 uint32_t mem_val = ReadW(b2_val + d2_val + x2_val, instr);
4599 alu_out += mem_val;
4600 SetS390ConditionCode<int64_t>(alu_out, 0);
4601 } else if (op == SGF) {
4602 uint32_t mem_val = ReadW(b2_val + d2_val + x2_val, instr);
4603 alu_out -= mem_val;
4604 SetS390ConditionCode<int64_t>(alu_out, 0);
4605 } else {
4606 DCHECK(false);
4607 }
4608 set_register(r1, alu_out);
4609 break;
4610 }
4611 case ALGFI:
4612 case SLGFI: {
4613 #ifndef V8_TARGET_ARCH_S390X
4614 // should only be called on 64bit
4615 DCHECK(false);
4616 #endif
4617 RILInstruction* rilInstr = reinterpret_cast<RILInstruction*>(instr);
4618 int r1 = rilInstr->R1Value();
4619 uint32_t i2 = rilInstr->I2UnsignedValue();
4620 uint64_t r1_val = (uint64_t)(get_register(r1));
4621 uint64_t alu_out;
4622 if (op == ALGFI)
4623 alu_out = r1_val + i2;
4624 else
4625 alu_out = r1_val - i2;
4626 set_register(r1, (intptr_t)alu_out);
4627 SetS390ConditionCode<uint64_t>(alu_out, 0);
4628 break;
4629 }
4630 case MSY:
4631 case MSG: {
4632 RXYInstruction* rxyInstr = reinterpret_cast<RXYInstruction*>(instr);
4633 int r1 = rxyInstr->R1Value();
4634 int b2 = rxyInstr->B2Value();
4635 int x2 = rxyInstr->X2Value();
4636 int64_t b2_val = (b2 == 0) ? 0 : get_register(b2);
4637 int64_t x2_val = (x2 == 0) ? 0 : get_register(x2);
4638 intptr_t d2_val = rxyInstr->D2Value();
4639 if (op == MSY) {
4640 int32_t mem_val = ReadW(b2_val + d2_val + x2_val, instr);
4641 int32_t r1_val = get_low_register<int32_t>(r1);
4642 set_low_register(r1, mem_val * r1_val);
4643 } else if (op == MSG) {
4644 int64_t mem_val = ReadDW(b2_val + d2_val + x2_val);
4645 int64_t r1_val = get_register(r1);
4646 set_register(r1, mem_val * r1_val);
4647 } else {
4648 UNREACHABLE();
4649 }
4650 break;
4651 }
4652 case MSFI:
4653 case MSGFI: {
4654 RILInstruction* rilinst = reinterpret_cast<RILInstruction*>(instr);
4655 int r1 = rilinst->R1Value();
4656 int32_t i2 = rilinst->I2Value();
4657 if (op == MSFI) {
4658 int32_t alu_out = get_low_register<int32_t>(r1);
4659 alu_out = alu_out * i2;
4660 set_low_register(r1, alu_out);
4661 } else if (op == MSGFI) {
4662 int64_t alu_out = get_register(r1);
4663 alu_out = alu_out * i2;
4664 set_register(r1, alu_out);
4665 } else {
4666 UNREACHABLE();
4667 }
4668 break;
4669 }
4670 default:
4671 UNREACHABLE();
4672 return false;
4673 }
4674 return true;
4675 }
4676
4677 int16_t Simulator::ByteReverse(int16_t hword) {
4678 return (hword << 8) | ((hword >> 8) & 0x00ff);
4679 }
4680
4681 int32_t Simulator::ByteReverse(int32_t word) {
4682 int32_t result = word << 24;
4683 result |= (word << 8) & 0x00ff0000;
4684 result |= (word >> 8) & 0x0000ff00;
4685 result |= (word >> 24) & 0x00000ff;
4686 return result;
4687 }
4688
4689 // Executes the current instruction.
4690 void Simulator::ExecuteInstruction(Instruction* instr, bool auto_incr_pc) {
4691 if (v8::internal::FLAG_check_icache) {
4692 CheckICache(isolate_->simulator_i_cache(), instr);
4693 }
4694 pc_modified_ = false;
4695 if (::v8::internal::FLAG_trace_sim) {
4696 disasm::NameConverter converter;
4697 disasm::Disassembler dasm(converter);
4698 // use a reasonably large buffer
4699 v8::internal::EmbeddedVector<char, 256> buffer;
4700 dasm.InstructionDecode(buffer, reinterpret_cast<byte*>(instr));
4701 #ifdef V8_TARGET_ARCH_S390X
4702 PrintF("%05ld %08" V8PRIxPTR " %s\n", icount_,
4703 reinterpret_cast<intptr_t>(instr), buffer.start());
4704 #else
4705 PrintF("%05lld %08" V8PRIxPTR " %s\n", icount_,
4706 reinterpret_cast<intptr_t>(instr), buffer.start());
4707 #endif
4708 // Flush stdout to prevent incomplete file output during abnormal exits
4709 // This is caused by the output being buffered before being written to file
4710 fflush(stdout);
4711 }
4712
4713 // Try to simulate as S390 Instruction first.
4714 bool processed = true;
4715
4716 int instrLength = instr->InstructionLength();
4717 if (instrLength == 2)
4718 processed = DecodeTwoByte(instr);
4719 else if (instrLength == 4)
4720 processed = DecodeFourByte(instr);
4721 else if (instrLength == 6)
4722 processed = DecodeSixByte(instr);
4723
4724 if (processed) {
4725 if (!pc_modified_ && auto_incr_pc) {
4726 set_pc(reinterpret_cast<intptr_t>(instr) + instrLength);
4727 }
4728 return;
4729 }
4730 }
4731
4732 void Simulator::DebugStart() {
4733 S390Debugger dbg(this);
4734 dbg.Debug();
4735 }
4736
4737 void Simulator::Execute() {
4738 // Get the PC to simulate. Cannot use the accessor here as we need the
4739 // raw PC value and not the one used as input to arithmetic instructions.
4740 intptr_t program_counter = get_pc();
4741
4742 if (::v8::internal::FLAG_stop_sim_at == 0) {
4743 // Fast version of the dispatch loop without checking whether the simulator
4744 // should be stopping at a particular executed instruction.
4745 while (program_counter != end_sim_pc) {
4746 Instruction* instr = reinterpret_cast<Instruction*>(program_counter);
4747 icount_++;
4748 ExecuteInstruction(instr);
4749 program_counter = get_pc();
4750 }
4751 } else {
4752 // FLAG_stop_sim_at is at the non-default value. Stop in the debugger when
4753 // we reach the particular instuction count.
4754 while (program_counter != end_sim_pc) {
4755 Instruction* instr = reinterpret_cast<Instruction*>(program_counter);
4756 icount_++;
4757 if (icount_ == ::v8::internal::FLAG_stop_sim_at) {
4758 S390Debugger dbg(this);
4759 dbg.Debug();
4760 } else {
4761 ExecuteInstruction(instr);
4762 }
4763 program_counter = get_pc();
4764 }
4765 }
4766 }
4767
4768 void Simulator::CallInternal(byte* entry, int reg_arg_count) {
4769 // Prepare to execute the code at entry
4770 if (ABI_USES_FUNCTION_DESCRIPTORS) {
4771 // entry is the function descriptor
4772 set_pc(*(reinterpret_cast<intptr_t*>(entry)));
4773 } else {
4774 // entry is the instruction address
4775 set_pc(reinterpret_cast<intptr_t>(entry));
4776 }
4777 // Remember the values of non-volatile registers.
4778 int64_t r6_val = get_register(r6);
4779 int64_t r7_val = get_register(r7);
4780 int64_t r8_val = get_register(r8);
4781 int64_t r9_val = get_register(r9);
4782 int64_t r10_val = get_register(r10);
4783 int64_t r11_val = get_register(r11);
4784 int64_t r12_val = get_register(r12);
4785 int64_t r13_val = get_register(r13);
4786
4787 if (ABI_CALL_VIA_IP) {
4788 // Put target address in ip (for JS prologue).
4789 set_register(ip, get_pc());
4790 }
4791
4792 // Put down marker for end of simulation. The simulator will stop simulation
4793 // when the PC reaches this value. By saving the "end simulation" value into
4794 // the LR the simulation stops when returning to this call point.
4795 registers_[14] = end_sim_pc;
4796
4797 // Set up the non-volatile registers with a known value. To be able to check
4798 // that they are preserved properly across JS execution.
4799 intptr_t callee_saved_value = icount_;
4800 if (reg_arg_count < 5) {
4801 set_register(r6, callee_saved_value + 6);
4802 }
4803 set_register(r7, callee_saved_value + 7);
4804 set_register(r8, callee_saved_value + 8);
4805 set_register(r9, callee_saved_value + 9);
4806 set_register(r10, callee_saved_value + 10);
4807 set_register(r11, callee_saved_value + 11);
4808 set_register(r12, callee_saved_value + 12);
4809 set_register(r13, callee_saved_value + 13);
4810
4811 // Start the simulation
4812 Execute();
4813
4814 // Check that the non-volatile registers have been preserved.
4815 #ifndef V8_TARGET_ARCH_S390X
4816 if (reg_arg_count < 5) {
4817 DCHECK_EQ(callee_saved_value + 6, get_low_register<int32_t>(r6));
4818 }
4819 DCHECK_EQ(callee_saved_value + 7, get_low_register<int32_t>(r7));
4820 DCHECK_EQ(callee_saved_value + 8, get_low_register<int32_t>(r8));
4821 DCHECK_EQ(callee_saved_value + 9, get_low_register<int32_t>(r9));
4822 DCHECK_EQ(callee_saved_value + 10, get_low_register<int32_t>(r10));
4823 DCHECK_EQ(callee_saved_value + 11, get_low_register<int32_t>(r11));
4824 DCHECK_EQ(callee_saved_value + 12, get_low_register<int32_t>(r12));
4825 DCHECK_EQ(callee_saved_value + 13, get_low_register<int32_t>(r13));
4826 #else
4827 if (reg_arg_count < 5) {
4828 DCHECK_EQ(callee_saved_value + 6, get_register(r6));
4829 }
4830 DCHECK_EQ(callee_saved_value + 7, get_register(r7));
4831 DCHECK_EQ(callee_saved_value + 8, get_register(r8));
4832 DCHECK_EQ(callee_saved_value + 9, get_register(r9));
4833 DCHECK_EQ(callee_saved_value + 10, get_register(r10));
4834 DCHECK_EQ(callee_saved_value + 11, get_register(r11));
4835 DCHECK_EQ(callee_saved_value + 12, get_register(r12));
4836 DCHECK_EQ(callee_saved_value + 13, get_register(r13));
4837 #endif
4838
4839 // Restore non-volatile registers with the original value.
4840 set_register(r6, r6_val);
4841 set_register(r7, r7_val);
4842 set_register(r8, r8_val);
4843 set_register(r9, r9_val);
4844 set_register(r10, r10_val);
4845 set_register(r11, r11_val);
4846 set_register(r12, r12_val);
4847 set_register(r13, r13_val);
4848 }
4849
4850 intptr_t Simulator::Call(byte* entry, int argument_count, ...) {
4851 // Remember the values of non-volatile registers.
4852 int64_t r6_val = get_register(r6);
4853 int64_t r7_val = get_register(r7);
4854 int64_t r8_val = get_register(r8);
4855 int64_t r9_val = get_register(r9);
4856 int64_t r10_val = get_register(r10);
4857 int64_t r11_val = get_register(r11);
4858 int64_t r12_val = get_register(r12);
4859 int64_t r13_val = get_register(r13);
4860
4861 va_list parameters;
4862 va_start(parameters, argument_count);
4863 // Set up arguments
4864
4865 // First 5 arguments passed in registers r2-r6.
4866 int reg_arg_count = (argument_count > 5) ? 5 : argument_count;
4867 int stack_arg_count = argument_count - reg_arg_count;
4868 for (int i = 0; i < reg_arg_count; i++) {
4869 intptr_t value = va_arg(parameters, intptr_t);
4870 set_register(i + 2, value);
4871 }
4872
4873 // Remaining arguments passed on stack.
4874 int64_t original_stack = get_register(sp);
4875 // Compute position of stack on entry to generated code.
4876 intptr_t entry_stack =
4877 (original_stack -
4878 (kCalleeRegisterSaveAreaSize + stack_arg_count * sizeof(intptr_t)));
4879 if (base::OS::ActivationFrameAlignment() != 0) {
4880 entry_stack &= -base::OS::ActivationFrameAlignment();
4881 }
4882
4883 // Store remaining arguments on stack, from low to high memory.
4884 intptr_t* stack_argument =
4885 reinterpret_cast<intptr_t*>(entry_stack + kCalleeRegisterSaveAreaSize);
4886 for (int i = 0; i < stack_arg_count; i++) {
4887 intptr_t value = va_arg(parameters, intptr_t);
4888 stack_argument[i] = value;
4889 }
4890 va_end(parameters);
4891 set_register(sp, entry_stack);
4892
4893 // Prepare to execute the code at entry
4894 #if ABI_USES_FUNCTION_DESCRIPTORS
4895 // entry is the function descriptor
4896 set_pc(*(reinterpret_cast<intptr_t*>(entry)));
4897 #else
4898 // entry is the instruction address
4899 set_pc(reinterpret_cast<intptr_t>(entry));
4900 #endif
4901
4902 // Put target address in ip (for JS prologue).
4903 set_register(r12, get_pc());
4904
4905 // Put down marker for end of simulation. The simulator will stop simulation
4906 // when the PC reaches this value. By saving the "end simulation" value into
4907 // the LR the simulation stops when returning to this call point.
4908 registers_[14] = end_sim_pc;
4909
4910 // Set up the non-volatile registers with a known value. To be able to check
4911 // that they are preserved properly across JS execution.
4912 intptr_t callee_saved_value = icount_;
4913 if (reg_arg_count < 5) {
4914 set_register(r6, callee_saved_value + 6);
4915 }
4916 set_register(r7, callee_saved_value + 7);
4917 set_register(r8, callee_saved_value + 8);
4918 set_register(r9, callee_saved_value + 9);
4919 set_register(r10, callee_saved_value + 10);
4920 set_register(r11, callee_saved_value + 11);
4921 set_register(r12, callee_saved_value + 12);
4922 set_register(r13, callee_saved_value + 13);
4923
4924 // Start the simulation
4925 Execute();
4926
4927 // Check that the non-volatile registers have been preserved.
4928 #ifndef V8_TARGET_ARCH_S390X
4929 if (reg_arg_count < 5) {
4930 DCHECK_EQ(callee_saved_value + 6, get_low_register<int32_t>(r6));
4931 }
4932 DCHECK_EQ(callee_saved_value + 7, get_low_register<int32_t>(r7));
4933 DCHECK_EQ(callee_saved_value + 8, get_low_register<int32_t>(r8));
4934 DCHECK_EQ(callee_saved_value + 9, get_low_register<int32_t>(r9));
4935 DCHECK_EQ(callee_saved_value + 10, get_low_register<int32_t>(r10));
4936 DCHECK_EQ(callee_saved_value + 11, get_low_register<int32_t>(r11));
4937 DCHECK_EQ(callee_saved_value + 12, get_low_register<int32_t>(r12));
4938 DCHECK_EQ(callee_saved_value + 13, get_low_register<int32_t>(r13));
4939 #else
4940 if (reg_arg_count < 5) {
4941 DCHECK_EQ(callee_saved_value + 6, get_register(r6));
4942 }
4943 DCHECK_EQ(callee_saved_value + 7, get_register(r7));
4944 DCHECK_EQ(callee_saved_value + 8, get_register(r8));
4945 DCHECK_EQ(callee_saved_value + 9, get_register(r9));
4946 DCHECK_EQ(callee_saved_value + 10, get_register(r10));
4947 DCHECK_EQ(callee_saved_value + 11, get_register(r11));
4948 DCHECK_EQ(callee_saved_value + 12, get_register(r12));
4949 DCHECK_EQ(callee_saved_value + 13, get_register(r13));
4950 #endif
4951
4952 // Restore non-volatile registers with the original value.
4953 set_register(r6, r6_val);
4954 set_register(r7, r7_val);
4955 set_register(r8, r8_val);
4956 set_register(r9, r9_val);
4957 set_register(r10, r10_val);
4958 set_register(r11, r11_val);
4959 set_register(r12, r12_val);
4960 set_register(r13, r13_val);
4961 // Pop stack passed arguments.
4962
4963 #ifndef V8_TARGET_ARCH_S390X
4964 DCHECK_EQ(entry_stack, get_low_register<int32_t>(sp));
4965 #else
4966 DCHECK_EQ(entry_stack, get_register(sp));
4967 #endif
4968 set_register(sp, original_stack);
4969
4970 // Return value register
4971 intptr_t result = get_register(r2);
4972 return result;
4973 }
4974
4975 void Simulator::CallFP(byte* entry, double d0, double d1) {
4976 set_d_register_from_double(0, d0);
4977 set_d_register_from_double(1, d1);
4978 CallInternal(entry);
4979 }
4980
4981 int32_t Simulator::CallFPReturnsInt(byte* entry, double d0, double d1) {
4982 CallFP(entry, d0, d1);
4983 int32_t result = get_register(r2);
4984 return result;
4985 }
4986
4987 double Simulator::CallFPReturnsDouble(byte* entry, double d0, double d1) {
4988 CallFP(entry, d0, d1);
4989 return get_double_from_d_register(0);
4990 }
4991
4992 uintptr_t Simulator::PushAddress(uintptr_t address) {
4993 uintptr_t new_sp = get_register(sp) - sizeof(uintptr_t);
4994 uintptr_t* stack_slot = reinterpret_cast<uintptr_t*>(new_sp);
4995 *stack_slot = address;
4996 set_register(sp, new_sp);
4997 return new_sp;
4998 }
4999
5000 uintptr_t Simulator::PopAddress() {
5001 uintptr_t current_sp = get_register(sp);
5002 uintptr_t* stack_slot = reinterpret_cast<uintptr_t*>(current_sp);
5003 uintptr_t address = *stack_slot;
5004 set_register(sp, current_sp + sizeof(uintptr_t));
5005 return address;
5006 }
5007
5008 } // namespace internal
5009 } // namespace v8
5010
5011 #endif // USE_SIMULATOR
5012 #endif // V8_TARGET_ARCH_S390
OLDNEW
« src/s390/assembler-s390.h ('K') | « src/s390/simulator-s390.h ('k') | tools/gyp/v8.gyp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698