| OLD | NEW |
| 1 // Copyright 2014 the V8 project authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include <stdarg.h> | 5 #include <stdarg.h> |
| 6 #include <stdlib.h> | 6 #include <stdlib.h> |
| 7 #include <cmath> | 7 #include <cmath> |
| 8 | 8 |
| 9 #if V8_TARGET_ARCH_S390 | 9 #if V8_TARGET_ARCH_S390 |
| 10 | 10 |
| (...skipping 2394 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2405 #define CheckOverflowForMul(src1, src2) (((src1) * (src2)) / (src2) != (src1)) | 2405 #define CheckOverflowForMul(src1, src2) (((src1) * (src2)) / (src2) != (src1)) |
| 2406 | 2406 |
| 2407 // Method for checking overflow on shift right | 2407 // Method for checking overflow on shift right |
| 2408 #define CheckOverflowForShiftRight(src1, src2) \ | 2408 #define CheckOverflowForShiftRight(src1, src2) \ |
| 2409 (((src1) >> (src2)) << (src2) != (src1)) | 2409 (((src1) >> (src2)) << (src2) != (src1)) |
| 2410 | 2410 |
| 2411 // Method for checking overflow on shift left | 2411 // Method for checking overflow on shift left |
| 2412 #define CheckOverflowForShiftLeft(src1, src2) \ | 2412 #define CheckOverflowForShiftLeft(src1, src2) \ |
| 2413 (((src1) << (src2)) >> (src2) != (src1)) | 2413 (((src1) << (src2)) >> (src2) != (src1)) |
| 2414 | 2414 |
| 2415 // S390 Decode and simulate helpers | |
| 2416 bool Simulator::DecodeTwoByte(Instruction* instr) { | |
| 2417 Opcode op = instr->S390OpcodeValue(); | |
| 2418 | |
| 2419 switch (op) { | |
| 2420 // RR format instructions | |
| 2421 case AR: | |
| 2422 case SR: | |
| 2423 case MR: | |
| 2424 case DR: | |
| 2425 case OR: | |
| 2426 case NR: | |
| 2427 case XR: { | |
| 2428 RRInstruction* rrinst = reinterpret_cast<RRInstruction*>(instr); | |
| 2429 int r1 = rrinst->R1Value(); | |
| 2430 int r2 = rrinst->R2Value(); | |
| 2431 int32_t r1_val = get_low_register<int32_t>(r1); | |
| 2432 int32_t r2_val = get_low_register<int32_t>(r2); | |
| 2433 bool isOF = false; | |
| 2434 switch (op) { | |
| 2435 case AR: | |
| 2436 isOF = CheckOverflowForIntAdd(r1_val, r2_val, int32_t); | |
| 2437 r1_val += r2_val; | |
| 2438 SetS390ConditionCode<int32_t>(r1_val, 0); | |
| 2439 SetS390OverflowCode(isOF); | |
| 2440 break; | |
| 2441 case SR: | |
| 2442 isOF = CheckOverflowForIntSub(r1_val, r2_val, int32_t); | |
| 2443 r1_val -= r2_val; | |
| 2444 SetS390ConditionCode<int32_t>(r1_val, 0); | |
| 2445 SetS390OverflowCode(isOF); | |
| 2446 break; | |
| 2447 case OR: | |
| 2448 r1_val |= r2_val; | |
| 2449 SetS390BitWiseConditionCode<uint32_t>(r1_val); | |
| 2450 break; | |
| 2451 case NR: | |
| 2452 r1_val &= r2_val; | |
| 2453 SetS390BitWiseConditionCode<uint32_t>(r1_val); | |
| 2454 break; | |
| 2455 case XR: | |
| 2456 r1_val ^= r2_val; | |
| 2457 SetS390BitWiseConditionCode<uint32_t>(r1_val); | |
| 2458 break; | |
| 2459 case MR: { | |
| 2460 DCHECK(r1 % 2 == 0); | |
| 2461 r1_val = get_low_register<int32_t>(r1 + 1); | |
| 2462 int64_t product = | |
| 2463 static_cast<int64_t>(r1_val) * static_cast<int64_t>(r2_val); | |
| 2464 int32_t high_bits = product >> 32; | |
| 2465 r1_val = high_bits; | |
| 2466 int32_t low_bits = product & 0x00000000FFFFFFFF; | |
| 2467 set_low_register(r1, high_bits); | |
| 2468 set_low_register(r1 + 1, low_bits); | |
| 2469 break; | |
| 2470 } | |
| 2471 case DR: { | |
| 2472 // reg-reg pair should be even-odd pair, assert r1 is an even register | |
| 2473 DCHECK(r1 % 2 == 0); | |
| 2474 // leftmost 32 bits of the dividend are in r1 | |
| 2475 // rightmost 32 bits of the dividend are in r1+1 | |
| 2476 // get the signed value from r1 | |
| 2477 int64_t dividend = static_cast<int64_t>(r1_val) << 32; | |
| 2478 // get unsigned value from r1+1 | |
| 2479 // avoid addition with sign-extended r1+1 value | |
| 2480 dividend += get_low_register<uint32_t>(r1 + 1); | |
| 2481 int32_t remainder = dividend % r2_val; | |
| 2482 int32_t quotient = dividend / r2_val; | |
| 2483 r1_val = remainder; | |
| 2484 set_low_register(r1, remainder); | |
| 2485 set_low_register(r1 + 1, quotient); | |
| 2486 break; // reg pair | |
| 2487 } | |
| 2488 default: | |
| 2489 UNREACHABLE(); | |
| 2490 break; | |
| 2491 } | |
| 2492 set_low_register(r1, r1_val); | |
| 2493 break; | |
| 2494 } | |
| 2495 case LR: { | |
| 2496 RRInstruction* rrinst = reinterpret_cast<RRInstruction*>(instr); | |
| 2497 int r1 = rrinst->R1Value(); | |
| 2498 int r2 = rrinst->R2Value(); | |
| 2499 set_low_register(r1, get_low_register<int32_t>(r2)); | |
| 2500 break; | |
| 2501 } | |
| 2502 case LDR: { | |
| 2503 RRInstruction* rrinst = reinterpret_cast<RRInstruction*>(instr); | |
| 2504 int r1 = rrinst->R1Value(); | |
| 2505 int r2 = rrinst->R2Value(); | |
| 2506 int64_t r2_val = get_d_register(r2); | |
| 2507 set_d_register(r1, r2_val); | |
| 2508 break; | |
| 2509 } | |
| 2510 case CR: { | |
| 2511 RRInstruction* rrinst = reinterpret_cast<RRInstruction*>(instr); | |
| 2512 int r1 = rrinst->R1Value(); | |
| 2513 int r2 = rrinst->R2Value(); | |
| 2514 int32_t r1_val = get_low_register<int32_t>(r1); | |
| 2515 int32_t r2_val = get_low_register<int32_t>(r2); | |
| 2516 SetS390ConditionCode<int32_t>(r1_val, r2_val); | |
| 2517 break; | |
| 2518 } | |
| 2519 case CLR: { | |
| 2520 RRInstruction* rrinst = reinterpret_cast<RRInstruction*>(instr); | |
| 2521 int r1 = rrinst->R1Value(); | |
| 2522 int r2 = rrinst->R2Value(); | |
| 2523 uint32_t r1_val = get_low_register<uint32_t>(r1); | |
| 2524 uint32_t r2_val = get_low_register<uint32_t>(r2); | |
| 2525 SetS390ConditionCode<uint32_t>(r1_val, r2_val); | |
| 2526 break; | |
| 2527 } | |
| 2528 case BCR: { | |
| 2529 RRInstruction* rrinst = reinterpret_cast<RRInstruction*>(instr); | |
| 2530 int r1 = rrinst->R1Value(); | |
| 2531 int r2 = rrinst->R2Value(); | |
| 2532 if (TestConditionCode(Condition(r1))) { | |
| 2533 intptr_t r2_val = get_register(r2); | |
| 2534 #if (!V8_TARGET_ARCH_S390X && V8_HOST_ARCH_S390) | |
| 2535 // On 31-bit, the top most bit may be 0 or 1, but is ignored by the | |
| 2536 // hardware. Cleanse the top bit before jumping to it, unless it's one | |
| 2537 // of the special PCs | |
| 2538 if (r2_val != bad_lr && r2_val != end_sim_pc) r2_val &= 0x7FFFFFFF; | |
| 2539 #endif | |
| 2540 set_pc(r2_val); | |
| 2541 } | |
| 2542 break; | |
| 2543 } | |
| 2544 case LTR: { | |
| 2545 RRInstruction* rrinst = reinterpret_cast<RRInstruction*>(instr); | |
| 2546 int r1 = rrinst->R1Value(); | |
| 2547 int r2 = rrinst->R2Value(); | |
| 2548 int32_t r2_val = get_low_register<int32_t>(r2); | |
| 2549 SetS390ConditionCode<int32_t>(r2_val, 0); | |
| 2550 set_low_register(r1, r2_val); | |
| 2551 break; | |
| 2552 } | |
| 2553 case ALR: | |
| 2554 case SLR: { | |
| 2555 RRInstruction* rrinst = reinterpret_cast<RRInstruction*>(instr); | |
| 2556 int r1 = rrinst->R1Value(); | |
| 2557 int r2 = rrinst->R2Value(); | |
| 2558 uint32_t r1_val = get_low_register<uint32_t>(r1); | |
| 2559 uint32_t r2_val = get_low_register<uint32_t>(r2); | |
| 2560 uint32_t alu_out = 0; | |
| 2561 bool isOF = false; | |
| 2562 if (ALR == op) { | |
| 2563 alu_out = r1_val + r2_val; | |
| 2564 isOF = CheckOverflowForUIntAdd(r1_val, r2_val); | |
| 2565 } else if (SLR == op) { | |
| 2566 alu_out = r1_val - r2_val; | |
| 2567 isOF = CheckOverflowForUIntSub(r1_val, r2_val); | |
| 2568 } else { | |
| 2569 UNREACHABLE(); | |
| 2570 } | |
| 2571 set_low_register(r1, alu_out); | |
| 2572 SetS390ConditionCodeCarry<uint32_t>(alu_out, isOF); | |
| 2573 break; | |
| 2574 } | |
| 2575 case LNR: { | |
| 2576 // Load Negative (32) | |
| 2577 RRInstruction* rrinst = reinterpret_cast<RRInstruction*>(instr); | |
| 2578 int r1 = rrinst->R1Value(); | |
| 2579 int r2 = rrinst->R2Value(); | |
| 2580 int32_t r2_val = get_low_register<int32_t>(r2); | |
| 2581 r2_val = (r2_val >= 0) ? -r2_val : r2_val; // If pos, then negate it. | |
| 2582 set_low_register(r1, r2_val); | |
| 2583 condition_reg_ = (r2_val == 0) ? CC_EQ : CC_LT; // CC0 - result is zero | |
| 2584 // CC1 - result is negative | |
| 2585 break; | |
| 2586 } | |
| 2587 case BASR: { | |
| 2588 RRInstruction* rrinst = reinterpret_cast<RRInstruction*>(instr); | |
| 2589 int r1 = rrinst->R1Value(); | |
| 2590 int r2 = rrinst->R2Value(); | |
| 2591 intptr_t link_addr = get_pc() + 2; | |
| 2592 // If R2 is zero, the BASR does not branch. | |
| 2593 int64_t r2_val = (r2 == 0) ? link_addr : get_register(r2); | |
| 2594 #if (!V8_TARGET_ARCH_S390X && V8_HOST_ARCH_S390) | |
| 2595 // On 31-bit, the top most bit may be 0 or 1, which can cause issues | |
| 2596 // for stackwalker. The top bit should either be cleanse before being | |
| 2597 // pushed onto the stack, or during stack walking when dereferenced. | |
| 2598 // For simulator, we'll take the worst case scenario and always tag | |
| 2599 // the high bit, to flush out more problems. | |
| 2600 link_addr |= 0x80000000; | |
| 2601 #endif | |
| 2602 set_register(r1, link_addr); | |
| 2603 set_pc(r2_val); | |
| 2604 break; | |
| 2605 } | |
| 2606 case LCR: { | |
| 2607 RRInstruction* rrinst = reinterpret_cast<RRInstruction*>(instr); | |
| 2608 int r1 = rrinst->R1Value(); | |
| 2609 int r2 = rrinst->R2Value(); | |
| 2610 int32_t r2_val = get_low_register<int32_t>(r2); | |
| 2611 int32_t original_r2_val = r2_val; | |
| 2612 r2_val = ~r2_val; | |
| 2613 r2_val = r2_val + 1; | |
| 2614 set_low_register(r1, r2_val); | |
| 2615 SetS390ConditionCode<int32_t>(r2_val, 0); | |
| 2616 // Checks for overflow where r2_val = -2147483648. | |
| 2617 // Cannot do int comparison due to GCC 4.8 bug on x86. | |
| 2618 // Detect INT_MIN alternatively, as it is the only value where both | |
| 2619 // original and result are negative due to overflow. | |
| 2620 if (r2_val < 0 && original_r2_val < 0) { | |
| 2621 SetS390OverflowCode(true); | |
| 2622 } | |
| 2623 break; | |
| 2624 } | |
| 2625 case BKPT: { | |
| 2626 set_pc(get_pc() + 2); | |
| 2627 S390Debugger dbg(this); | |
| 2628 dbg.Debug(); | |
| 2629 break; | |
| 2630 } | |
| 2631 default: | |
| 2632 UNREACHABLE(); | |
| 2633 return false; | |
| 2634 break; | |
| 2635 } | |
| 2636 return true; | |
| 2637 } | |
| 2638 | |
| 2639 // Decode routine for four-byte instructions | |
| 2640 bool Simulator::DecodeFourByte(Instruction* instr) { | |
| 2641 Opcode op = instr->S390OpcodeValue(); | |
| 2642 | |
| 2643 // Pre-cast instruction to various types | |
| 2644 RREInstruction* rreInst = reinterpret_cast<RREInstruction*>(instr); | |
| 2645 SIInstruction* siInstr = reinterpret_cast<SIInstruction*>(instr); | |
| 2646 | |
| 2647 switch (op) { | |
| 2648 case POPCNT_Z: { | |
| 2649 int r1 = rreInst->R1Value(); | |
| 2650 int r2 = rreInst->R2Value(); | |
| 2651 int64_t r2_val = get_register(r2); | |
| 2652 int64_t r1_val = 0; | |
| 2653 | |
| 2654 uint8_t* r2_val_ptr = reinterpret_cast<uint8_t*>(&r2_val); | |
| 2655 uint8_t* r1_val_ptr = reinterpret_cast<uint8_t*>(&r1_val); | |
| 2656 for (int i = 0; i < 8; i++) { | |
| 2657 uint32_t x = static_cast<uint32_t>(r2_val_ptr[i]); | |
| 2658 #if defined(__GNUC__) | |
| 2659 r1_val_ptr[i] = __builtin_popcount(x); | |
| 2660 #else | |
| 2661 #error unsupport __builtin_popcount | |
| 2662 #endif | |
| 2663 } | |
| 2664 | |
| 2665 set_register(r1, static_cast<uint64_t>(r1_val)); | |
| 2666 break; | |
| 2667 } | |
| 2668 case LLGFR: { | |
| 2669 int r1 = rreInst->R1Value(); | |
| 2670 int r2 = rreInst->R2Value(); | |
| 2671 int32_t r2_val = get_low_register<int32_t>(r2); | |
| 2672 uint64_t r2_finalval = | |
| 2673 (static_cast<uint64_t>(r2_val) & 0x00000000ffffffff); | |
| 2674 set_register(r1, r2_finalval); | |
| 2675 break; | |
| 2676 } | |
| 2677 case EX: { | |
| 2678 RXInstruction* rxinst = reinterpret_cast<RXInstruction*>(instr); | |
| 2679 int r1 = rxinst->R1Value(); | |
| 2680 int b2 = rxinst->B2Value(); | |
| 2681 int x2 = rxinst->X2Value(); | |
| 2682 int64_t b2_val = (b2 == 0) ? 0 : get_register(b2); | |
| 2683 int64_t x2_val = (x2 == 0) ? 0 : get_register(x2); | |
| 2684 intptr_t d2_val = rxinst->D2Value(); | |
| 2685 int32_t r1_val = get_low_register<int32_t>(r1); | |
| 2686 | |
| 2687 SixByteInstr the_instr = Instruction::InstructionBits( | |
| 2688 reinterpret_cast<const byte*>(b2_val + x2_val + d2_val)); | |
| 2689 int length = Instruction::InstructionLength( | |
| 2690 reinterpret_cast<const byte*>(b2_val + x2_val + d2_val)); | |
| 2691 | |
| 2692 char new_instr_buf[8]; | |
| 2693 char* addr = reinterpret_cast<char*>(&new_instr_buf[0]); | |
| 2694 the_instr |= static_cast<SixByteInstr>(r1_val & 0xff) | |
| 2695 << (8 * length - 16); | |
| 2696 Instruction::SetInstructionBits<SixByteInstr>( | |
| 2697 reinterpret_cast<byte*>(addr), static_cast<SixByteInstr>(the_instr)); | |
| 2698 ExecuteInstruction(reinterpret_cast<Instruction*>(addr), false); | |
| 2699 break; | |
| 2700 } | |
| 2701 case LGR: { | |
| 2702 // Load Register (64) | |
| 2703 int r1 = rreInst->R1Value(); | |
| 2704 int r2 = rreInst->R2Value(); | |
| 2705 set_register(r1, get_register(r2)); | |
| 2706 break; | |
| 2707 } | |
| 2708 case LDGR: { | |
| 2709 // Load FPR from GPR (L <- 64) | |
| 2710 uint64_t int_val = get_register(rreInst->R2Value()); | |
| 2711 // double double_val = bit_cast<double, uint64_t>(int_val); | |
| 2712 // set_d_register_from_double(rreInst->R1Value(), double_val); | |
| 2713 set_d_register(rreInst->R1Value(), int_val); | |
| 2714 break; | |
| 2715 } | |
| 2716 case LGDR: { | |
| 2717 // Load GPR from FPR (64 <- L) | |
| 2718 int64_t double_val = get_d_register(rreInst->R2Value()); | |
| 2719 set_register(rreInst->R1Value(), double_val); | |
| 2720 break; | |
| 2721 } | |
| 2722 case LTGR: { | |
| 2723 // Load Register (64) | |
| 2724 int r1 = rreInst->R1Value(); | |
| 2725 int r2 = rreInst->R2Value(); | |
| 2726 int64_t r2_val = get_register(r2); | |
| 2727 SetS390ConditionCode<int64_t>(r2_val, 0); | |
| 2728 set_register(r1, get_register(r2)); | |
| 2729 break; | |
| 2730 } | |
| 2731 case LZDR: { | |
| 2732 int r1 = rreInst->R1Value(); | |
| 2733 set_d_register_from_double(r1, 0.0); | |
| 2734 break; | |
| 2735 } | |
| 2736 case LTEBR: { | |
| 2737 RREInstruction* rreinst = reinterpret_cast<RREInstruction*>(instr); | |
| 2738 int r1 = rreinst->R1Value(); | |
| 2739 int r2 = rreinst->R2Value(); | |
| 2740 int64_t r2_val = get_d_register(r2); | |
| 2741 float fr2_val = get_float32_from_d_register(r2); | |
| 2742 SetS390ConditionCode<float>(fr2_val, 0.0); | |
| 2743 set_d_register(r1, r2_val); | |
| 2744 break; | |
| 2745 } | |
| 2746 case LTDBR: { | |
| 2747 RREInstruction* rreinst = reinterpret_cast<RREInstruction*>(instr); | |
| 2748 int r1 = rreinst->R1Value(); | |
| 2749 int r2 = rreinst->R2Value(); | |
| 2750 int64_t r2_val = get_d_register(r2); | |
| 2751 SetS390ConditionCode<double>(bit_cast<double, int64_t>(r2_val), 0.0); | |
| 2752 set_d_register(r1, r2_val); | |
| 2753 break; | |
| 2754 } | |
| 2755 case CGR: { | |
| 2756 // Compare (64) | |
| 2757 int64_t r1_val = get_register(rreInst->R1Value()); | |
| 2758 int64_t r2_val = get_register(rreInst->R2Value()); | |
| 2759 SetS390ConditionCode<int64_t>(r1_val, r2_val); | |
| 2760 break; | |
| 2761 } | |
| 2762 case CLGR: { | |
| 2763 // Compare Logical (64) | |
| 2764 uint64_t r1_val = static_cast<uint64_t>(get_register(rreInst->R1Value())); | |
| 2765 uint64_t r2_val = static_cast<uint64_t>(get_register(rreInst->R2Value())); | |
| 2766 SetS390ConditionCode<uint64_t>(r1_val, r2_val); | |
| 2767 break; | |
| 2768 } | |
| 2769 case LH: { | |
| 2770 // Load Halfword | |
| 2771 RXInstruction* rxinst = reinterpret_cast<RXInstruction*>(instr); | |
| 2772 int r1 = rxinst->R1Value(); | |
| 2773 int x2 = rxinst->X2Value(); | |
| 2774 int b2 = rxinst->B2Value(); | |
| 2775 | |
| 2776 int64_t x2_val = (x2 == 0) ? 0 : get_register(x2); | |
| 2777 int64_t b2_val = (b2 == 0) ? 0 : get_register(b2); | |
| 2778 intptr_t d2_val = rxinst->D2Value(); | |
| 2779 intptr_t mem_addr = x2_val + b2_val + d2_val; | |
| 2780 | |
| 2781 int32_t result = static_cast<int32_t>(ReadH(mem_addr, instr)); | |
| 2782 set_low_register(r1, result); | |
| 2783 break; | |
| 2784 } | |
| 2785 case LHI: { | |
| 2786 RIInstruction* riinst = reinterpret_cast<RIInstruction*>(instr); | |
| 2787 int r1 = riinst->R1Value(); | |
| 2788 int i = riinst->I2Value(); | |
| 2789 set_low_register(r1, i); | |
| 2790 break; | |
| 2791 } | |
| 2792 case LGHI: { | |
| 2793 RIInstruction* riinst = reinterpret_cast<RIInstruction*>(instr); | |
| 2794 int r1 = riinst->R1Value(); | |
| 2795 int64_t i = riinst->I2Value(); | |
| 2796 set_register(r1, i); | |
| 2797 break; | |
| 2798 } | |
| 2799 case CHI: { | |
| 2800 RIInstruction* riinst = reinterpret_cast<RIInstruction*>(instr); | |
| 2801 int r1 = riinst->R1Value(); | |
| 2802 int16_t i = riinst->I2Value(); | |
| 2803 int32_t r1_val = get_low_register<int32_t>(r1); | |
| 2804 SetS390ConditionCode<int32_t>(r1_val, i); | |
| 2805 break; | |
| 2806 } | |
| 2807 case CGHI: { | |
| 2808 RIInstruction* riinst = reinterpret_cast<RIInstruction*>(instr); | |
| 2809 int r1 = riinst->R1Value(); | |
| 2810 int64_t i = static_cast<int64_t>(riinst->I2Value()); | |
| 2811 int64_t r1_val = get_register(r1); | |
| 2812 SetS390ConditionCode<int64_t>(r1_val, i); | |
| 2813 break; | |
| 2814 } | |
| 2815 case BRAS: { | |
| 2816 // Branch Relative and Save | |
| 2817 RILInstruction* rilInstr = reinterpret_cast<RILInstruction*>(instr); | |
| 2818 int r1 = rilInstr->R1Value(); | |
| 2819 intptr_t d2 = rilInstr->I2Value(); | |
| 2820 intptr_t pc = get_pc(); | |
| 2821 // Set PC of next instruction to register | |
| 2822 set_register(r1, pc + sizeof(FourByteInstr)); | |
| 2823 // Update PC to branch target | |
| 2824 set_pc(pc + d2 * 2); | |
| 2825 break; | |
| 2826 } | |
| 2827 case BRC: { | |
| 2828 // Branch Relative on Condition | |
| 2829 RIInstruction* riinst = reinterpret_cast<RIInstruction*>(instr); | |
| 2830 int m1 = riinst->M1Value(); | |
| 2831 if (TestConditionCode((Condition)m1)) { | |
| 2832 intptr_t offset = riinst->I2Value() * 2; | |
| 2833 set_pc(get_pc() + offset); | |
| 2834 } | |
| 2835 break; | |
| 2836 } | |
| 2837 case BRCT: | |
| 2838 case BRCTG: { | |
| 2839 // Branch On Count (32/64). | |
| 2840 RIInstruction* riinst = reinterpret_cast<RIInstruction*>(instr); | |
| 2841 int r1 = riinst->R1Value(); | |
| 2842 int64_t value = | |
| 2843 (op == BRCT) ? get_low_register<int32_t>(r1) : get_register(r1); | |
| 2844 if (BRCT == op) | |
| 2845 set_low_register(r1, --value); | |
| 2846 else | |
| 2847 set_register(r1, --value); | |
| 2848 // Branch if value != 0 | |
| 2849 if (value != 0) { | |
| 2850 intptr_t offset = riinst->I2Value() * 2; | |
| 2851 set_pc(get_pc() + offset); | |
| 2852 } | |
| 2853 break; | |
| 2854 } | |
| 2855 case BXH: { | |
| 2856 RSInstruction* rsinst = reinterpret_cast<RSInstruction*>(instr); | |
| 2857 int r1 = rsinst->R1Value(); | |
| 2858 int r3 = rsinst->R3Value(); | |
| 2859 int b2 = rsinst->B2Value(); | |
| 2860 int d2 = rsinst->D2Value(); | |
| 2861 | |
| 2862 // r1_val is the first operand, r3_val is the increment | |
| 2863 int32_t r1_val = r1 == 0 ? 0 : get_register(r1); | |
| 2864 int32_t r3_val = r2 == 0 ? 0 : get_register(r3); | |
| 2865 intptr_t b2_val = b2 == 0 ? 0 : get_register(b2); | |
| 2866 intptr_t branch_address = b2_val + d2; | |
| 2867 // increment r1_val | |
| 2868 r1_val += r3_val; | |
| 2869 | |
| 2870 // if the increment is even, then it designates a pair of registers | |
| 2871 // and the contents of the even and odd registers of the pair are used as | |
| 2872 // the increment and compare value respectively. If the increment is odd, | |
| 2873 // the increment itself is used as both the increment and compare value | |
| 2874 int32_t compare_val = r3 % 2 == 0 ? get_register(r3 + 1) : r3_val; | |
| 2875 if (r1_val > compare_val) { | |
| 2876 // branch to address if r1_val is greater than compare value | |
| 2877 set_pc(branch_address); | |
| 2878 } | |
| 2879 | |
| 2880 // update contents of register in r1 with the new incremented value | |
| 2881 set_register(r1, r1_val); | |
| 2882 break; | |
| 2883 } | |
| 2884 case IIHH: | |
| 2885 case IIHL: | |
| 2886 case IILH: | |
| 2887 case IILL: { | |
| 2888 UNIMPLEMENTED(); | |
| 2889 break; | |
| 2890 } | |
| 2891 case STM: | |
| 2892 case LM: { | |
| 2893 // Store Multiple 32-bits. | |
| 2894 RSInstruction* rsinstr = reinterpret_cast<RSInstruction*>(instr); | |
| 2895 int r1 = rsinstr->R1Value(); | |
| 2896 int r3 = rsinstr->R3Value(); | |
| 2897 int rb = rsinstr->B2Value(); | |
| 2898 int offset = rsinstr->D2Value(); | |
| 2899 | |
| 2900 // Regs roll around if r3 is less than r1. | |
| 2901 // Artifically increase r3 by 16 so we can calculate | |
| 2902 // the number of regs stored properly. | |
| 2903 if (r3 < r1) r3 += 16; | |
| 2904 | |
| 2905 int32_t rb_val = (rb == 0) ? 0 : get_low_register<int32_t>(rb); | |
| 2906 | |
| 2907 // Store each register in ascending order. | |
| 2908 for (int i = 0; i <= r3 - r1; i++) { | |
| 2909 if (op == STM) { | |
| 2910 int32_t value = get_low_register<int32_t>((r1 + i) % 16); | |
| 2911 WriteW(rb_val + offset + 4 * i, value, instr); | |
| 2912 } else if (op == LM) { | |
| 2913 int32_t value = ReadW(rb_val + offset + 4 * i, instr); | |
| 2914 set_low_register((r1 + i) % 16, value); | |
| 2915 } | |
| 2916 } | |
| 2917 break; | |
| 2918 } | |
| 2919 case SLL: | |
| 2920 case SRL: { | |
| 2921 RSInstruction* rsInstr = reinterpret_cast<RSInstruction*>(instr); | |
| 2922 int r1 = rsInstr->R1Value(); | |
| 2923 int b2 = rsInstr->B2Value(); | |
| 2924 intptr_t d2 = rsInstr->D2Value(); | |
| 2925 // only takes rightmost 6bits | |
| 2926 int64_t b2_val = b2 == 0 ? 0 : get_register(b2); | |
| 2927 int shiftBits = (b2_val + d2) & 0x3F; | |
| 2928 uint32_t r1_val = get_low_register<uint32_t>(r1); | |
| 2929 uint32_t alu_out = 0; | |
| 2930 if (SLL == op) { | |
| 2931 alu_out = r1_val << shiftBits; | |
| 2932 } else if (SRL == op) { | |
| 2933 alu_out = r1_val >> shiftBits; | |
| 2934 } else { | |
| 2935 UNREACHABLE(); | |
| 2936 } | |
| 2937 set_low_register(r1, alu_out); | |
| 2938 break; | |
| 2939 } | |
| 2940 case SLDL: { | |
| 2941 RSInstruction* rsInstr = reinterpret_cast<RSInstruction*>(instr); | |
| 2942 int r1 = rsInstr->R1Value(); | |
| 2943 int b2 = rsInstr->B2Value(); | |
| 2944 intptr_t d2 = rsInstr->D2Value(); | |
| 2945 // only takes rightmost 6bits | |
| 2946 int64_t b2_val = b2 == 0 ? 0 : get_register(b2); | |
| 2947 int shiftBits = (b2_val + d2) & 0x3F; | |
| 2948 | |
| 2949 DCHECK(r1 % 2 == 0); | |
| 2950 uint32_t r1_val = get_low_register<uint32_t>(r1); | |
| 2951 uint32_t r1_next_val = get_low_register<uint32_t>(r1 + 1); | |
| 2952 uint64_t alu_out = (static_cast<uint64_t>(r1_val) << 32) | | |
| 2953 (static_cast<uint64_t>(r1_next_val)); | |
| 2954 alu_out <<= shiftBits; | |
| 2955 set_low_register(r1 + 1, static_cast<uint32_t>(alu_out)); | |
| 2956 set_low_register(r1, static_cast<uint32_t>(alu_out >> 32)); | |
| 2957 break; | |
| 2958 } | |
| 2959 case SLA: | |
| 2960 case SRA: { | |
| 2961 RSInstruction* rsInstr = reinterpret_cast<RSInstruction*>(instr); | |
| 2962 int r1 = rsInstr->R1Value(); | |
| 2963 int b2 = rsInstr->B2Value(); | |
| 2964 intptr_t d2 = rsInstr->D2Value(); | |
| 2965 // only takes rightmost 6bits | |
| 2966 int64_t b2_val = b2 == 0 ? 0 : get_register(b2); | |
| 2967 int shiftBits = (b2_val + d2) & 0x3F; | |
| 2968 int32_t r1_val = get_low_register<int32_t>(r1); | |
| 2969 int32_t alu_out = 0; | |
| 2970 bool isOF = false; | |
| 2971 if (op == SLA) { | |
| 2972 isOF = CheckOverflowForShiftLeft(r1_val, shiftBits); | |
| 2973 alu_out = r1_val << shiftBits; | |
| 2974 } else if (op == SRA) { | |
| 2975 alu_out = r1_val >> shiftBits; | |
| 2976 } | |
| 2977 set_low_register(r1, alu_out); | |
| 2978 SetS390ConditionCode<int32_t>(alu_out, 0); | |
| 2979 SetS390OverflowCode(isOF); | |
| 2980 break; | |
| 2981 } | |
| 2982 case LLHR: { | |
| 2983 UNIMPLEMENTED(); | |
| 2984 break; | |
| 2985 } | |
| 2986 case LLGHR: { | |
| 2987 UNIMPLEMENTED(); | |
| 2988 break; | |
| 2989 } | |
| 2990 case L: | |
| 2991 case LA: | |
| 2992 case LD: | |
| 2993 case LE: { | |
| 2994 RXInstruction* rxinst = reinterpret_cast<RXInstruction*>(instr); | |
| 2995 int b2 = rxinst->B2Value(); | |
| 2996 int x2 = rxinst->X2Value(); | |
| 2997 int32_t r1 = rxinst->R1Value(); | |
| 2998 int64_t b2_val = (b2 == 0) ? 0 : get_register(b2); | |
| 2999 int64_t x2_val = (x2 == 0) ? 0 : get_register(x2); | |
| 3000 intptr_t d2_val = rxinst->D2Value(); | |
| 3001 intptr_t addr = b2_val + x2_val + d2_val; | |
| 3002 if (op == L) { | |
| 3003 int32_t mem_val = ReadW(addr, instr); | |
| 3004 set_low_register(r1, mem_val); | |
| 3005 } else if (op == LA) { | |
| 3006 set_register(r1, addr); | |
| 3007 } else if (op == LD) { | |
| 3008 int64_t dbl_val = *reinterpret_cast<int64_t*>(addr); | |
| 3009 set_d_register(r1, dbl_val); | |
| 3010 } else if (op == LE) { | |
| 3011 float float_val = *reinterpret_cast<float*>(addr); | |
| 3012 set_d_register_from_float32(r1, float_val); | |
| 3013 } | |
| 3014 break; | |
| 3015 } | |
| 3016 case C: | |
| 3017 case CL: { | |
| 3018 RXInstruction* rxinst = reinterpret_cast<RXInstruction*>(instr); | |
| 3019 int b2 = rxinst->B2Value(); | |
| 3020 int x2 = rxinst->X2Value(); | |
| 3021 int32_t r1_val = get_low_register<int32_t>(rxinst->R1Value()); | |
| 3022 int64_t b2_val = (b2 == 0) ? 0 : get_register(b2); | |
| 3023 int64_t x2_val = (x2 == 0) ? 0 : get_register(x2); | |
| 3024 intptr_t d2_val = rxinst->D2Value(); | |
| 3025 intptr_t addr = b2_val + x2_val + d2_val; | |
| 3026 int32_t mem_val = ReadW(addr, instr); | |
| 3027 if (C == op) | |
| 3028 SetS390ConditionCode<int32_t>(r1_val, mem_val); | |
| 3029 else if (CL == op) | |
| 3030 SetS390ConditionCode<uint32_t>(r1_val, mem_val); | |
| 3031 break; | |
| 3032 } | |
| 3033 case CLI: { | |
| 3034 // Compare Immediate (Mem - Imm) (8) | |
| 3035 int b1 = siInstr->B1Value(); | |
| 3036 int64_t b1_val = (b1 == 0) ? 0 : get_register(b1); | |
| 3037 intptr_t d1_val = siInstr->D1Value(); | |
| 3038 intptr_t addr = b1_val + d1_val; | |
| 3039 uint8_t mem_val = ReadB(addr); | |
| 3040 uint8_t imm_val = siInstr->I2Value(); | |
| 3041 SetS390ConditionCode<uint8_t>(mem_val, imm_val); | |
| 3042 break; | |
| 3043 } | |
| 3044 case TM: { | |
| 3045 // Test Under Mask (Mem - Imm) (8) | |
| 3046 int b1 = siInstr->B1Value(); | |
| 3047 int64_t b1_val = (b1 == 0) ? 0 : get_register(b1); | |
| 3048 intptr_t d1_val = siInstr->D1Value(); | |
| 3049 intptr_t addr = b1_val + d1_val; | |
| 3050 uint8_t mem_val = ReadB(addr); | |
| 3051 uint8_t imm_val = siInstr->I2Value(); | |
| 3052 uint8_t selected_bits = mem_val & imm_val; | |
| 3053 // CC0: Selected bits are zero | |
| 3054 // CC1: Selected bits mixed zeros and ones | |
| 3055 // CC3: Selected bits all ones | |
| 3056 if (0 == selected_bits) { | |
| 3057 condition_reg_ = CC_EQ; // CC0 | |
| 3058 } else if (selected_bits == imm_val) { | |
| 3059 condition_reg_ = 0x1; // CC3 | |
| 3060 } else { | |
| 3061 condition_reg_ = 0x4; // CC1 | |
| 3062 } | |
| 3063 break; | |
| 3064 } | |
| 3065 case ST: | |
| 3066 case STE: | |
| 3067 case STD: { | |
| 3068 RXInstruction* rxinst = reinterpret_cast<RXInstruction*>(instr); | |
| 3069 int b2 = rxinst->B2Value(); | |
| 3070 int x2 = rxinst->X2Value(); | |
| 3071 int32_t r1_val = get_low_register<int32_t>(rxinst->R1Value()); | |
| 3072 int64_t b2_val = (b2 == 0) ? 0 : get_register(b2); | |
| 3073 int64_t x2_val = (x2 == 0) ? 0 : get_register(x2); | |
| 3074 intptr_t d2_val = rxinst->D2Value(); | |
| 3075 intptr_t addr = b2_val + x2_val + d2_val; | |
| 3076 if (op == ST) { | |
| 3077 WriteW(addr, r1_val, instr); | |
| 3078 } else if (op == STD) { | |
| 3079 int64_t frs_val = get_d_register(rxinst->R1Value()); | |
| 3080 WriteDW(addr, frs_val); | |
| 3081 } else if (op == STE) { | |
| 3082 int64_t frs_val = get_d_register(rxinst->R1Value()) >> 32; | |
| 3083 WriteW(addr, static_cast<int32_t>(frs_val), instr); | |
| 3084 } | |
| 3085 break; | |
| 3086 } | |
| 3087 case LTGFR: | |
| 3088 case LGFR: { | |
| 3089 // Load and Test Register (64 <- 32) (Sign Extends 32-bit val) | |
| 3090 // Load Register (64 <- 32) (Sign Extends 32-bit val) | |
| 3091 RREInstruction* rreInstr = reinterpret_cast<RREInstruction*>(instr); | |
| 3092 int r1 = rreInstr->R1Value(); | |
| 3093 int r2 = rreInstr->R2Value(); | |
| 3094 int32_t r2_val = get_low_register<int32_t>(r2); | |
| 3095 int64_t result = static_cast<int64_t>(r2_val); | |
| 3096 set_register(r1, result); | |
| 3097 | |
| 3098 if (LTGFR == op) SetS390ConditionCode<int64_t>(result, 0); | |
| 3099 break; | |
| 3100 } | |
| 3101 case LNGR: { | |
| 3102 // Load Negative (64) | |
| 3103 int r1 = rreInst->R1Value(); | |
| 3104 int r2 = rreInst->R2Value(); | |
| 3105 int64_t r2_val = get_register(r2); | |
| 3106 r2_val = (r2_val >= 0) ? -r2_val : r2_val; // If pos, then negate it. | |
| 3107 set_register(r1, r2_val); | |
| 3108 condition_reg_ = (r2_val == 0) ? CC_EQ : CC_LT; // CC0 - result is zero | |
| 3109 // CC1 - result is negative | |
| 3110 break; | |
| 3111 } | |
| 3112 case TRAP4: { | |
| 3113 // whack the space of the caller allocated stack | |
| 3114 int64_t sp_addr = get_register(sp); | |
| 3115 for (int i = 0; i < kCalleeRegisterSaveAreaSize / kPointerSize; ++i) { | |
| 3116 // we dont want to whack the RA (r14) | |
| 3117 if (i != 14) (reinterpret_cast<intptr_t*>(sp_addr))[i] = 0xdeadbabe; | |
| 3118 } | |
| 3119 SoftwareInterrupt(instr); | |
| 3120 break; | |
| 3121 } | |
| 3122 case STC: { | |
| 3123 // Store Character/Byte | |
| 3124 RXInstruction* rxinst = reinterpret_cast<RXInstruction*>(instr); | |
| 3125 int b2 = rxinst->B2Value(); | |
| 3126 int x2 = rxinst->X2Value(); | |
| 3127 uint8_t r1_val = get_low_register<int32_t>(rxinst->R1Value()); | |
| 3128 int64_t b2_val = (b2 == 0) ? 0 : get_register(b2); | |
| 3129 int64_t x2_val = (x2 == 0) ? 0 : get_register(x2); | |
| 3130 intptr_t d2_val = rxinst->D2Value(); | |
| 3131 intptr_t mem_addr = b2_val + x2_val + d2_val; | |
| 3132 WriteB(mem_addr, r1_val); | |
| 3133 break; | |
| 3134 } | |
| 3135 case STH: { | |
| 3136 RXInstruction* rxinst = reinterpret_cast<RXInstruction*>(instr); | |
| 3137 int b2 = rxinst->B2Value(); | |
| 3138 int x2 = rxinst->X2Value(); | |
| 3139 int16_t r1_val = get_low_register<int32_t>(rxinst->R1Value()); | |
| 3140 int64_t b2_val = (b2 == 0) ? 0 : get_register(b2); | |
| 3141 int64_t x2_val = (x2 == 0) ? 0 : get_register(x2); | |
| 3142 intptr_t d2_val = rxinst->D2Value(); | |
| 3143 intptr_t mem_addr = b2_val + x2_val + d2_val; | |
| 3144 WriteH(mem_addr, r1_val, instr); | |
| 3145 break; | |
| 3146 } | |
| 3147 #if V8_TARGET_ARCH_S390X | |
| 3148 case LCGR: { | |
| 3149 int r1 = rreInst->R1Value(); | |
| 3150 int r2 = rreInst->R2Value(); | |
| 3151 int64_t r2_val = get_register(r2); | |
| 3152 r2_val = ~r2_val; | |
| 3153 r2_val = r2_val + 1; | |
| 3154 set_register(r1, r2_val); | |
| 3155 SetS390ConditionCode<int64_t>(r2_val, 0); | |
| 3156 // if the input is INT_MIN, loading its compliment would be overflowing | |
| 3157 if (r2_val < 0 && (r2_val + 1) > 0) { | |
| 3158 SetS390OverflowCode(true); | |
| 3159 } | |
| 3160 break; | |
| 3161 } | |
| 3162 #endif | |
| 3163 case SRDA: { | |
| 3164 RSInstruction* rsInstr = reinterpret_cast<RSInstruction*>(instr); | |
| 3165 int r1 = rsInstr->R1Value(); | |
| 3166 DCHECK(r1 % 2 == 0); // must be a reg pair | |
| 3167 int b2 = rsInstr->B2Value(); | |
| 3168 intptr_t d2 = rsInstr->D2Value(); | |
| 3169 // only takes rightmost 6bits | |
| 3170 int64_t b2_val = b2 == 0 ? 0 : get_register(b2); | |
| 3171 int shiftBits = (b2_val + d2) & 0x3F; | |
| 3172 int64_t opnd1 = static_cast<int64_t>(get_low_register<int32_t>(r1)) << 32; | |
| 3173 int64_t opnd2 = static_cast<uint64_t>(get_low_register<uint32_t>(r1 + 1)); | |
| 3174 int64_t r1_val = opnd1 + opnd2; | |
| 3175 int64_t alu_out = r1_val >> shiftBits; | |
| 3176 set_low_register(r1, alu_out >> 32); | |
| 3177 set_low_register(r1 + 1, alu_out & 0x00000000FFFFFFFF); | |
| 3178 SetS390ConditionCode<int32_t>(alu_out, 0); | |
| 3179 break; | |
| 3180 } | |
| 3181 case SRDL: { | |
| 3182 RSInstruction* rsInstr = reinterpret_cast<RSInstruction*>(instr); | |
| 3183 int r1 = rsInstr->R1Value(); | |
| 3184 DCHECK(r1 % 2 == 0); // must be a reg pair | |
| 3185 int b2 = rsInstr->B2Value(); | |
| 3186 intptr_t d2 = rsInstr->D2Value(); | |
| 3187 // only takes rightmost 6bits | |
| 3188 int64_t b2_val = b2 == 0 ? 0 : get_register(b2); | |
| 3189 int shiftBits = (b2_val + d2) & 0x3F; | |
| 3190 uint64_t opnd1 = static_cast<uint64_t>(get_low_register<uint32_t>(r1)) | |
| 3191 << 32; | |
| 3192 uint64_t opnd2 = | |
| 3193 static_cast<uint64_t>(get_low_register<uint32_t>(r1 + 1)); | |
| 3194 uint64_t r1_val = opnd1 | opnd2; | |
| 3195 uint64_t alu_out = r1_val >> shiftBits; | |
| 3196 set_low_register(r1, alu_out >> 32); | |
| 3197 set_low_register(r1 + 1, alu_out & 0x00000000FFFFFFFF); | |
| 3198 SetS390ConditionCode<int32_t>(alu_out, 0); | |
| 3199 break; | |
| 3200 } | |
| 3201 default: { return DecodeFourByteArithmetic(instr); } | |
| 3202 } | |
| 3203 return true; | |
| 3204 } | |
| 3205 | |
| 3206 bool Simulator::DecodeFourByteArithmetic64Bit(Instruction* instr) { | |
| 3207 Opcode op = instr->S390OpcodeValue(); | |
| 3208 | |
| 3209 RRFInstruction* rrfInst = reinterpret_cast<RRFInstruction*>(instr); | |
| 3210 RREInstruction* rreInst = reinterpret_cast<RREInstruction*>(instr); | |
| 3211 | |
| 3212 switch (op) { | |
| 3213 case AGR: | |
| 3214 case SGR: | |
| 3215 case OGR: | |
| 3216 case NGR: | |
| 3217 case XGR: { | |
| 3218 int r1 = rreInst->R1Value(); | |
| 3219 int r2 = rreInst->R2Value(); | |
| 3220 int64_t r1_val = get_register(r1); | |
| 3221 int64_t r2_val = get_register(r2); | |
| 3222 bool isOF = false; | |
| 3223 switch (op) { | |
| 3224 case AGR: | |
| 3225 isOF = CheckOverflowForIntAdd(r1_val, r2_val, int64_t); | |
| 3226 r1_val += r2_val; | |
| 3227 SetS390ConditionCode<int64_t>(r1_val, 0); | |
| 3228 SetS390OverflowCode(isOF); | |
| 3229 break; | |
| 3230 case SGR: | |
| 3231 isOF = CheckOverflowForIntSub(r1_val, r2_val, int64_t); | |
| 3232 r1_val -= r2_val; | |
| 3233 SetS390ConditionCode<int64_t>(r1_val, 0); | |
| 3234 SetS390OverflowCode(isOF); | |
| 3235 break; | |
| 3236 case OGR: | |
| 3237 r1_val |= r2_val; | |
| 3238 SetS390BitWiseConditionCode<uint64_t>(r1_val); | |
| 3239 break; | |
| 3240 case NGR: | |
| 3241 r1_val &= r2_val; | |
| 3242 SetS390BitWiseConditionCode<uint64_t>(r1_val); | |
| 3243 break; | |
| 3244 case XGR: | |
| 3245 r1_val ^= r2_val; | |
| 3246 SetS390BitWiseConditionCode<uint64_t>(r1_val); | |
| 3247 break; | |
| 3248 default: | |
| 3249 UNREACHABLE(); | |
| 3250 break; | |
| 3251 } | |
| 3252 set_register(r1, r1_val); | |
| 3253 break; | |
| 3254 } | |
| 3255 case AGFR: { | |
| 3256 // Add Register (64 <- 32) (Sign Extends 32-bit val) | |
| 3257 int r1 = rreInst->R1Value(); | |
| 3258 int r2 = rreInst->R2Value(); | |
| 3259 int64_t r1_val = get_register(r1); | |
| 3260 int64_t r2_val = static_cast<int64_t>(get_low_register<int32_t>(r2)); | |
| 3261 bool isOF = CheckOverflowForIntAdd(r1_val, r2_val, int64_t); | |
| 3262 r1_val += r2_val; | |
| 3263 SetS390ConditionCode<int64_t>(r1_val, 0); | |
| 3264 SetS390OverflowCode(isOF); | |
| 3265 set_register(r1, r1_val); | |
| 3266 break; | |
| 3267 } | |
| 3268 case SGFR: { | |
| 3269 // Sub Reg (64 <- 32) | |
| 3270 int r1 = rreInst->R1Value(); | |
| 3271 int r2 = rreInst->R2Value(); | |
| 3272 int64_t r1_val = get_register(r1); | |
| 3273 int64_t r2_val = static_cast<int64_t>(get_low_register<int32_t>(r2)); | |
| 3274 bool isOF = false; | |
| 3275 isOF = CheckOverflowForIntSub(r1_val, r2_val, int64_t); | |
| 3276 r1_val -= r2_val; | |
| 3277 SetS390ConditionCode<int64_t>(r1_val, 0); | |
| 3278 SetS390OverflowCode(isOF); | |
| 3279 set_register(r1, r1_val); | |
| 3280 break; | |
| 3281 } | |
| 3282 case AGRK: | |
| 3283 case SGRK: | |
| 3284 case NGRK: | |
| 3285 case OGRK: | |
| 3286 case XGRK: { | |
| 3287 // 64-bit Non-clobbering arithmetics / bitwise ops. | |
| 3288 int r1 = rrfInst->R1Value(); | |
| 3289 int r2 = rrfInst->R2Value(); | |
| 3290 int r3 = rrfInst->R3Value(); | |
| 3291 int64_t r2_val = get_register(r2); | |
| 3292 int64_t r3_val = get_register(r3); | |
| 3293 if (AGRK == op) { | |
| 3294 bool isOF = CheckOverflowForIntAdd(r2_val, r3_val, int64_t); | |
| 3295 SetS390ConditionCode<int64_t>(r2_val + r3_val, 0); | |
| 3296 SetS390OverflowCode(isOF); | |
| 3297 set_register(r1, r2_val + r3_val); | |
| 3298 } else if (SGRK == op) { | |
| 3299 bool isOF = CheckOverflowForIntSub(r2_val, r3_val, int64_t); | |
| 3300 SetS390ConditionCode<int64_t>(r2_val - r3_val, 0); | |
| 3301 SetS390OverflowCode(isOF); | |
| 3302 set_register(r1, r2_val - r3_val); | |
| 3303 } else { | |
| 3304 // Assume bitwise operation here | |
| 3305 uint64_t bitwise_result = 0; | |
| 3306 if (NGRK == op) { | |
| 3307 bitwise_result = r2_val & r3_val; | |
| 3308 } else if (OGRK == op) { | |
| 3309 bitwise_result = r2_val | r3_val; | |
| 3310 } else if (XGRK == op) { | |
| 3311 bitwise_result = r2_val ^ r3_val; | |
| 3312 } | |
| 3313 SetS390BitWiseConditionCode<uint64_t>(bitwise_result); | |
| 3314 set_register(r1, bitwise_result); | |
| 3315 } | |
| 3316 break; | |
| 3317 } | |
| 3318 case ALGRK: | |
| 3319 case SLGRK: { | |
| 3320 // 64-bit Non-clobbering unsigned arithmetics | |
| 3321 int r1 = rrfInst->R1Value(); | |
| 3322 int r2 = rrfInst->R2Value(); | |
| 3323 int r3 = rrfInst->R3Value(); | |
| 3324 uint64_t r2_val = get_register(r2); | |
| 3325 uint64_t r3_val = get_register(r3); | |
| 3326 if (ALGRK == op) { | |
| 3327 bool isOF = CheckOverflowForUIntAdd(r2_val, r3_val); | |
| 3328 SetS390ConditionCode<uint64_t>(r2_val + r3_val, 0); | |
| 3329 SetS390OverflowCode(isOF); | |
| 3330 set_register(r1, r2_val + r3_val); | |
| 3331 } else if (SLGRK == op) { | |
| 3332 bool isOF = CheckOverflowForUIntSub(r2_val, r3_val); | |
| 3333 SetS390ConditionCode<uint64_t>(r2_val - r3_val, 0); | |
| 3334 SetS390OverflowCode(isOF); | |
| 3335 set_register(r1, r2_val - r3_val); | |
| 3336 } | |
| 3337 break; | |
| 3338 } | |
| 3339 case AGHI: | |
| 3340 case MGHI: { | |
| 3341 RIInstruction* riinst = reinterpret_cast<RIInstruction*>(instr); | |
| 3342 int32_t r1 = riinst->R1Value(); | |
| 3343 int64_t i = static_cast<int64_t>(riinst->I2Value()); | |
| 3344 int64_t r1_val = get_register(r1); | |
| 3345 bool isOF = false; | |
| 3346 switch (op) { | |
| 3347 case AGHI: | |
| 3348 isOF = CheckOverflowForIntAdd(r1_val, i, int64_t); | |
| 3349 r1_val += i; | |
| 3350 break; | |
| 3351 case MGHI: | |
| 3352 isOF = CheckOverflowForMul(r1_val, i); | |
| 3353 r1_val *= i; | |
| 3354 break; // no overflow indication is given | |
| 3355 default: | |
| 3356 break; | |
| 3357 } | |
| 3358 set_register(r1, r1_val); | |
| 3359 SetS390ConditionCode<int32_t>(r1_val, 0); | |
| 3360 SetS390OverflowCode(isOF); | |
| 3361 break; | |
| 3362 } | |
| 3363 default: | |
| 3364 UNREACHABLE(); | |
| 3365 } | |
| 3366 return true; | |
| 3367 } | |
| 3368 | |
| 3369 /** | |
| 3370 * Decodes and simulates four byte arithmetic instructions | |
| 3371 */ | |
| 3372 bool Simulator::DecodeFourByteArithmetic(Instruction* instr) { | |
| 3373 Opcode op = instr->S390OpcodeValue(); | |
| 3374 | |
| 3375 // Pre-cast instruction to various types | |
| 3376 RRFInstruction* rrfInst = reinterpret_cast<RRFInstruction*>(instr); | |
| 3377 | |
| 3378 switch (op) { | |
| 3379 case AGR: | |
| 3380 case SGR: | |
| 3381 case OGR: | |
| 3382 case NGR: | |
| 3383 case XGR: | |
| 3384 case AGFR: | |
| 3385 case SGFR: { | |
| 3386 DecodeFourByteArithmetic64Bit(instr); | |
| 3387 break; | |
| 3388 } | |
| 3389 case ARK: | |
| 3390 case SRK: | |
| 3391 case NRK: | |
| 3392 case ORK: | |
| 3393 case XRK: { | |
| 3394 // 32-bit Non-clobbering arithmetics / bitwise ops | |
| 3395 int r1 = rrfInst->R1Value(); | |
| 3396 int r2 = rrfInst->R2Value(); | |
| 3397 int r3 = rrfInst->R3Value(); | |
| 3398 int32_t r2_val = get_low_register<int32_t>(r2); | |
| 3399 int32_t r3_val = get_low_register<int32_t>(r3); | |
| 3400 if (ARK == op) { | |
| 3401 bool isOF = CheckOverflowForIntAdd(r2_val, r3_val, int32_t); | |
| 3402 SetS390ConditionCode<int32_t>(r2_val + r3_val, 0); | |
| 3403 SetS390OverflowCode(isOF); | |
| 3404 set_low_register(r1, r2_val + r3_val); | |
| 3405 } else if (SRK == op) { | |
| 3406 bool isOF = CheckOverflowForIntSub(r2_val, r3_val, int32_t); | |
| 3407 SetS390ConditionCode<int32_t>(r2_val - r3_val, 0); | |
| 3408 SetS390OverflowCode(isOF); | |
| 3409 set_low_register(r1, r2_val - r3_val); | |
| 3410 } else { | |
| 3411 // Assume bitwise operation here | |
| 3412 uint32_t bitwise_result = 0; | |
| 3413 if (NRK == op) { | |
| 3414 bitwise_result = r2_val & r3_val; | |
| 3415 } else if (ORK == op) { | |
| 3416 bitwise_result = r2_val | r3_val; | |
| 3417 } else if (XRK == op) { | |
| 3418 bitwise_result = r2_val ^ r3_val; | |
| 3419 } | |
| 3420 SetS390BitWiseConditionCode<uint32_t>(bitwise_result); | |
| 3421 set_low_register(r1, bitwise_result); | |
| 3422 } | |
| 3423 break; | |
| 3424 } | |
| 3425 case ALRK: | |
| 3426 case SLRK: { | |
| 3427 // 32-bit Non-clobbering unsigned arithmetics | |
| 3428 int r1 = rrfInst->R1Value(); | |
| 3429 int r2 = rrfInst->R2Value(); | |
| 3430 int r3 = rrfInst->R3Value(); | |
| 3431 uint32_t r2_val = get_low_register<uint32_t>(r2); | |
| 3432 uint32_t r3_val = get_low_register<uint32_t>(r3); | |
| 3433 if (ALRK == op) { | |
| 3434 bool isOF = CheckOverflowForUIntAdd(r2_val, r3_val); | |
| 3435 SetS390ConditionCode<uint32_t>(r2_val + r3_val, 0); | |
| 3436 SetS390OverflowCode(isOF); | |
| 3437 set_low_register(r1, r2_val + r3_val); | |
| 3438 } else if (SLRK == op) { | |
| 3439 bool isOF = CheckOverflowForUIntSub(r2_val, r3_val); | |
| 3440 SetS390ConditionCode<uint32_t>(r2_val - r3_val, 0); | |
| 3441 SetS390OverflowCode(isOF); | |
| 3442 set_low_register(r1, r2_val - r3_val); | |
| 3443 } | |
| 3444 break; | |
| 3445 } | |
| 3446 case AGRK: | |
| 3447 case SGRK: | |
| 3448 case NGRK: | |
| 3449 case OGRK: | |
| 3450 case XGRK: { | |
| 3451 DecodeFourByteArithmetic64Bit(instr); | |
| 3452 break; | |
| 3453 } | |
| 3454 case ALGRK: | |
| 3455 case SLGRK: { | |
| 3456 DecodeFourByteArithmetic64Bit(instr); | |
| 3457 break; | |
| 3458 } | |
| 3459 case AHI: | |
| 3460 case MHI: { | |
| 3461 RIInstruction* riinst = reinterpret_cast<RIInstruction*>(instr); | |
| 3462 int32_t r1 = riinst->R1Value(); | |
| 3463 int32_t i = riinst->I2Value(); | |
| 3464 int32_t r1_val = get_low_register<int32_t>(r1); | |
| 3465 bool isOF = false; | |
| 3466 switch (op) { | |
| 3467 case AHI: | |
| 3468 isOF = CheckOverflowForIntAdd(r1_val, i, int32_t); | |
| 3469 r1_val += i; | |
| 3470 break; | |
| 3471 case MHI: | |
| 3472 isOF = CheckOverflowForMul(r1_val, i); | |
| 3473 r1_val *= i; | |
| 3474 break; // no overflow indication is given | |
| 3475 default: | |
| 3476 break; | |
| 3477 } | |
| 3478 set_low_register(r1, r1_val); | |
| 3479 SetS390ConditionCode<int32_t>(r1_val, 0); | |
| 3480 SetS390OverflowCode(isOF); | |
| 3481 break; | |
| 3482 } | |
| 3483 case AGHI: | |
| 3484 case MGHI: { | |
| 3485 DecodeFourByteArithmetic64Bit(instr); | |
| 3486 break; | |
| 3487 } | |
| 3488 case MLR: { | |
| 3489 RREInstruction* rreinst = reinterpret_cast<RREInstruction*>(instr); | |
| 3490 int r1 = rreinst->R1Value(); | |
| 3491 int r2 = rreinst->R2Value(); | |
| 3492 DCHECK(r1 % 2 == 0); | |
| 3493 | |
| 3494 uint32_t r1_val = get_low_register<uint32_t>(r1 + 1); | |
| 3495 uint32_t r2_val = get_low_register<uint32_t>(r2); | |
| 3496 uint64_t product = | |
| 3497 static_cast<uint64_t>(r1_val) * static_cast<uint64_t>(r2_val); | |
| 3498 int32_t high_bits = product >> 32; | |
| 3499 int32_t low_bits = product & 0x00000000FFFFFFFF; | |
| 3500 set_low_register(r1, high_bits); | |
| 3501 set_low_register(r1 + 1, low_bits); | |
| 3502 break; | |
| 3503 } | |
| 3504 case DLGR: { | |
| 3505 #ifdef V8_TARGET_ARCH_S390X | |
| 3506 RREInstruction* rreinst = reinterpret_cast<RREInstruction*>(instr); | |
| 3507 int r1 = rreinst->R1Value(); | |
| 3508 int r2 = rreinst->R2Value(); | |
| 3509 uint64_t r1_val = get_register(r1); | |
| 3510 uint64_t r2_val = get_register(r2); | |
| 3511 DCHECK(r1 % 2 == 0); | |
| 3512 unsigned __int128 dividend = static_cast<unsigned __int128>(r1_val) << 64; | |
| 3513 dividend += get_register(r1 + 1); | |
| 3514 uint64_t remainder = dividend % r2_val; | |
| 3515 uint64_t quotient = dividend / r2_val; | |
| 3516 r1_val = remainder; | |
| 3517 set_register(r1, remainder); | |
| 3518 set_register(r1 + 1, quotient); | |
| 3519 #else | |
| 3520 UNREACHABLE(); | |
| 3521 #endif | |
| 3522 break; | |
| 3523 } | |
| 3524 case DLR: { | |
| 3525 RREInstruction* rreinst = reinterpret_cast<RREInstruction*>(instr); | |
| 3526 int r1 = rreinst->R1Value(); | |
| 3527 int r2 = rreinst->R2Value(); | |
| 3528 uint32_t r1_val = get_low_register<uint32_t>(r1); | |
| 3529 uint32_t r2_val = get_low_register<uint32_t>(r2); | |
| 3530 DCHECK(r1 % 2 == 0); | |
| 3531 uint64_t dividend = static_cast<uint64_t>(r1_val) << 32; | |
| 3532 dividend += get_low_register<uint32_t>(r1 + 1); | |
| 3533 uint32_t remainder = dividend % r2_val; | |
| 3534 uint32_t quotient = dividend / r2_val; | |
| 3535 r1_val = remainder; | |
| 3536 set_low_register(r1, remainder); | |
| 3537 set_low_register(r1 + 1, quotient); | |
| 3538 break; | |
| 3539 } | |
| 3540 case A: | |
| 3541 case S: | |
| 3542 case M: | |
| 3543 case D: | |
| 3544 case O: | |
| 3545 case N: | |
| 3546 case X: { | |
| 3547 // 32-bit Reg-Mem instructions | |
| 3548 RXInstruction* rxinst = reinterpret_cast<RXInstruction*>(instr); | |
| 3549 int b2 = rxinst->B2Value(); | |
| 3550 int x2 = rxinst->X2Value(); | |
| 3551 int32_t r1_val = get_low_register<int32_t>(rxinst->R1Value()); | |
| 3552 int64_t b2_val = (b2 == 0) ? 0 : get_register(b2); | |
| 3553 int64_t x2_val = (x2 == 0) ? 0 : get_register(x2); | |
| 3554 intptr_t d2_val = rxinst->D2Value(); | |
| 3555 int32_t mem_val = ReadW(b2_val + x2_val + d2_val, instr); | |
| 3556 int32_t alu_out = 0; | |
| 3557 bool isOF = false; | |
| 3558 switch (op) { | |
| 3559 case A: | |
| 3560 isOF = CheckOverflowForIntAdd(r1_val, mem_val, int32_t); | |
| 3561 alu_out = r1_val + mem_val; | |
| 3562 SetS390ConditionCode<int32_t>(alu_out, 0); | |
| 3563 SetS390OverflowCode(isOF); | |
| 3564 break; | |
| 3565 case S: | |
| 3566 isOF = CheckOverflowForIntSub(r1_val, mem_val, int32_t); | |
| 3567 alu_out = r1_val - mem_val; | |
| 3568 SetS390ConditionCode<int32_t>(alu_out, 0); | |
| 3569 SetS390OverflowCode(isOF); | |
| 3570 break; | |
| 3571 case M: | |
| 3572 case D: | |
| 3573 UNIMPLEMENTED(); | |
| 3574 break; | |
| 3575 case O: | |
| 3576 alu_out = r1_val | mem_val; | |
| 3577 SetS390BitWiseConditionCode<uint32_t>(alu_out); | |
| 3578 break; | |
| 3579 case N: | |
| 3580 alu_out = r1_val & mem_val; | |
| 3581 SetS390BitWiseConditionCode<uint32_t>(alu_out); | |
| 3582 break; | |
| 3583 case X: | |
| 3584 alu_out = r1_val ^ mem_val; | |
| 3585 SetS390BitWiseConditionCode<uint32_t>(alu_out); | |
| 3586 break; | |
| 3587 default: | |
| 3588 UNREACHABLE(); | |
| 3589 break; | |
| 3590 } | |
| 3591 set_low_register(r1, alu_out); | |
| 3592 break; | |
| 3593 } | |
| 3594 case OILL: | |
| 3595 case OIHL: { | |
| 3596 RIInstruction* riInst = reinterpret_cast<RIInstruction*>(instr); | |
| 3597 int r1 = riInst->R1Value(); | |
| 3598 int i = riInst->I2Value(); | |
| 3599 int32_t r1_val = get_low_register<int32_t>(r1); | |
| 3600 if (OILL == op) { | |
| 3601 // CC is set based on the 16 bits that are AND'd | |
| 3602 SetS390BitWiseConditionCode<uint16_t>(r1_val | i); | |
| 3603 } else if (OILH == op) { | |
| 3604 // CC is set based on the 16 bits that are AND'd | |
| 3605 SetS390BitWiseConditionCode<uint16_t>((r1_val >> 16) | i); | |
| 3606 i = i << 16; | |
| 3607 } else { | |
| 3608 UNIMPLEMENTED(); | |
| 3609 } | |
| 3610 set_low_register(r1, r1_val | i); | |
| 3611 break; | |
| 3612 } | |
| 3613 case NILL: | |
| 3614 case NILH: { | |
| 3615 RIInstruction* riInst = reinterpret_cast<RIInstruction*>(instr); | |
| 3616 int r1 = riInst->R1Value(); | |
| 3617 int i = riInst->I2Value(); | |
| 3618 int32_t r1_val = get_low_register<int32_t>(r1); | |
| 3619 if (NILL == op) { | |
| 3620 // CC is set based on the 16 bits that are AND'd | |
| 3621 SetS390BitWiseConditionCode<uint16_t>(r1_val & i); | |
| 3622 i |= 0xFFFF0000; | |
| 3623 } else if (NILH == op) { | |
| 3624 // CC is set based on the 16 bits that are AND'd | |
| 3625 SetS390BitWiseConditionCode<uint16_t>((r1_val >> 16) & i); | |
| 3626 i = (i << 16) | 0x0000FFFF; | |
| 3627 } else { | |
| 3628 UNIMPLEMENTED(); | |
| 3629 } | |
| 3630 set_low_register(r1, r1_val & i); | |
| 3631 break; | |
| 3632 } | |
| 3633 case AH: | |
| 3634 case SH: | |
| 3635 case MH: { | |
| 3636 RXInstruction* rxinst = reinterpret_cast<RXInstruction*>(instr); | |
| 3637 int b2 = rxinst->B2Value(); | |
| 3638 int x2 = rxinst->X2Value(); | |
| 3639 int32_t r1_val = get_low_register<int32_t>(rxinst->R1Value()); | |
| 3640 int64_t b2_val = (b2 == 0) ? 0 : get_register(b2); | |
| 3641 int64_t x2_val = (x2 == 0) ? 0 : get_register(x2); | |
| 3642 intptr_t d2_val = rxinst->D2Value(); | |
| 3643 intptr_t addr = b2_val + x2_val + d2_val; | |
| 3644 int32_t mem_val = static_cast<int32_t>(ReadH(addr, instr)); | |
| 3645 int32_t alu_out = 0; | |
| 3646 bool isOF = false; | |
| 3647 if (AH == op) { | |
| 3648 isOF = CheckOverflowForIntAdd(r1_val, mem_val, int32_t); | |
| 3649 alu_out = r1_val + mem_val; | |
| 3650 } else if (SH == op) { | |
| 3651 isOF = CheckOverflowForIntSub(r1_val, mem_val, int32_t); | |
| 3652 alu_out = r1_val - mem_val; | |
| 3653 } else if (MH == op) { | |
| 3654 alu_out = r1_val * mem_val; | |
| 3655 } else { | |
| 3656 UNREACHABLE(); | |
| 3657 } | |
| 3658 set_low_register(r1, alu_out); | |
| 3659 if (MH != op) { // MH does not change condition code | |
| 3660 SetS390ConditionCode<int32_t>(alu_out, 0); | |
| 3661 SetS390OverflowCode(isOF); | |
| 3662 } | |
| 3663 break; | |
| 3664 } | |
| 3665 case DSGR: { | |
| 3666 RREInstruction* rreInst = reinterpret_cast<RREInstruction*>(instr); | |
| 3667 int r1 = rreInst->R1Value(); | |
| 3668 int r2 = rreInst->R2Value(); | |
| 3669 | |
| 3670 DCHECK(r1 % 2 == 0); | |
| 3671 | |
| 3672 int64_t dividend = get_register(r1 + 1); | |
| 3673 int64_t divisor = get_register(r2); | |
| 3674 set_register(r1, dividend % divisor); | |
| 3675 set_register(r1 + 1, dividend / divisor); | |
| 3676 | |
| 3677 break; | |
| 3678 } | |
| 3679 case FLOGR: { | |
| 3680 RREInstruction* rreInst = reinterpret_cast<RREInstruction*>(instr); | |
| 3681 int r1 = rreInst->R1Value(); | |
| 3682 int r2 = rreInst->R2Value(); | |
| 3683 | |
| 3684 DCHECK(r1 % 2 == 0); | |
| 3685 | |
| 3686 int64_t r2_val = get_register(r2); | |
| 3687 | |
| 3688 int i = 0; | |
| 3689 for (; i < 64; i++) { | |
| 3690 if (r2_val < 0) break; | |
| 3691 r2_val <<= 1; | |
| 3692 } | |
| 3693 | |
| 3694 r2_val = get_register(r2); | |
| 3695 | |
| 3696 int64_t mask = ~(1 << (63 - i)); | |
| 3697 set_register(r1, i); | |
| 3698 set_register(r1 + 1, r2_val & mask); | |
| 3699 | |
| 3700 break; | |
| 3701 } | |
| 3702 case MSR: | |
| 3703 case MSGR: { // they do not set overflow code | |
| 3704 RREInstruction* rreInst = reinterpret_cast<RREInstruction*>(instr); | |
| 3705 int r1 = rreInst->R1Value(); | |
| 3706 int r2 = rreInst->R2Value(); | |
| 3707 if (op == MSR) { | |
| 3708 int32_t r1_val = get_low_register<int32_t>(r1); | |
| 3709 int32_t r2_val = get_low_register<int32_t>(r2); | |
| 3710 set_low_register(r1, r1_val * r2_val); | |
| 3711 } else if (op == MSGR) { | |
| 3712 int64_t r1_val = get_register(r1); | |
| 3713 int64_t r2_val = get_register(r2); | |
| 3714 set_register(r1, r1_val * r2_val); | |
| 3715 } else { | |
| 3716 UNREACHABLE(); | |
| 3717 } | |
| 3718 break; | |
| 3719 } | |
| 3720 case MS: { | |
| 3721 RXInstruction* rxinst = reinterpret_cast<RXInstruction*>(instr); | |
| 3722 int r1 = rxinst->R1Value(); | |
| 3723 int b2 = rxinst->B2Value(); | |
| 3724 int x2 = rxinst->X2Value(); | |
| 3725 int64_t x2_val = (x2 == 0) ? 0 : get_register(x2); | |
| 3726 int64_t b2_val = (b2 == 0) ? 0 : get_register(b2); | |
| 3727 intptr_t d2_val = rxinst->D2Value(); | |
| 3728 int32_t mem_val = ReadW(b2_val + x2_val + d2_val, instr); | |
| 3729 int32_t r1_val = get_low_register<int32_t>(r1); | |
| 3730 set_low_register(r1, r1_val * mem_val); | |
| 3731 break; | |
| 3732 } | |
| 3733 case LGBR: | |
| 3734 case LBR: { | |
| 3735 RREInstruction* rrinst = reinterpret_cast<RREInstruction*>(instr); | |
| 3736 int r1 = rrinst->R1Value(); | |
| 3737 int r2 = rrinst->R2Value(); | |
| 3738 if (op == LGBR) { | |
| 3739 int64_t r2_val = get_low_register<int64_t>(r2); | |
| 3740 r2_val <<= 56; | |
| 3741 r2_val >>= 56; | |
| 3742 set_register(r1, r2_val); | |
| 3743 } else if (op == LBR) { | |
| 3744 int32_t r2_val = get_low_register<int32_t>(r2); | |
| 3745 r2_val <<= 24; | |
| 3746 r2_val >>= 24; | |
| 3747 set_low_register(r1, r2_val); | |
| 3748 } else { | |
| 3749 UNREACHABLE(); | |
| 3750 } | |
| 3751 break; | |
| 3752 } | |
| 3753 case LGHR: | |
| 3754 case LHR: { | |
| 3755 RREInstruction* rrinst = reinterpret_cast<RREInstruction*>(instr); | |
| 3756 int r1 = rrinst->R1Value(); | |
| 3757 int r2 = rrinst->R2Value(); | |
| 3758 if (op == LGHR) { | |
| 3759 int64_t r2_val = get_low_register<int64_t>(r2); | |
| 3760 r2_val <<= 48; | |
| 3761 r2_val >>= 48; | |
| 3762 set_register(r1, r2_val); | |
| 3763 } else if (op == LHR) { | |
| 3764 int32_t r2_val = get_low_register<int32_t>(r2); | |
| 3765 r2_val <<= 16; | |
| 3766 r2_val >>= 16; | |
| 3767 set_low_register(r1, r2_val); | |
| 3768 } else { | |
| 3769 UNREACHABLE(); | |
| 3770 } | |
| 3771 break; | |
| 3772 } | |
| 3773 case ALCR: { | |
| 3774 RREInstruction* rrinst = reinterpret_cast<RREInstruction*>(instr); | |
| 3775 int r1 = rrinst->R1Value(); | |
| 3776 int r2 = rrinst->R2Value(); | |
| 3777 uint32_t r1_val = get_low_register<uint32_t>(r1); | |
| 3778 uint32_t r2_val = get_low_register<uint32_t>(r2); | |
| 3779 uint32_t alu_out = 0; | |
| 3780 bool isOF = false; | |
| 3781 | |
| 3782 alu_out = r1_val + r2_val; | |
| 3783 bool isOF_original = CheckOverflowForUIntAdd(r1_val, r2_val); | |
| 3784 if (TestConditionCode((Condition)2) || TestConditionCode((Condition)3)) { | |
| 3785 alu_out = alu_out + 1; | |
| 3786 isOF = isOF_original || CheckOverflowForUIntAdd(alu_out, 1); | |
| 3787 } else { | |
| 3788 isOF = isOF_original; | |
| 3789 } | |
| 3790 set_low_register(r1, alu_out); | |
| 3791 SetS390ConditionCodeCarry<uint32_t>(alu_out, isOF); | |
| 3792 break; | |
| 3793 } | |
| 3794 case SLBR: { | |
| 3795 RREInstruction* rrinst = reinterpret_cast<RREInstruction*>(instr); | |
| 3796 int r1 = rrinst->R1Value(); | |
| 3797 int r2 = rrinst->R2Value(); | |
| 3798 uint32_t r1_val = get_low_register<uint32_t>(r1); | |
| 3799 uint32_t r2_val = get_low_register<uint32_t>(r2); | |
| 3800 uint32_t alu_out = 0; | |
| 3801 bool isOF = false; | |
| 3802 | |
| 3803 alu_out = r1_val - r2_val; | |
| 3804 bool isOF_original = CheckOverflowForUIntSub(r1_val, r2_val); | |
| 3805 if (TestConditionCode((Condition)2) || TestConditionCode((Condition)3)) { | |
| 3806 alu_out = alu_out - 1; | |
| 3807 isOF = isOF_original || CheckOverflowForUIntSub(alu_out, 1); | |
| 3808 } else { | |
| 3809 isOF = isOF_original; | |
| 3810 } | |
| 3811 set_low_register(r1, alu_out); | |
| 3812 SetS390ConditionCodeCarry<uint32_t>(alu_out, isOF); | |
| 3813 break; | |
| 3814 } | |
| 3815 default: { return DecodeFourByteFloatingPoint(instr); } | |
| 3816 } | |
| 3817 return true; | |
| 3818 } | |
| 3819 | |
| 3820 void Simulator::DecodeFourByteFloatingPointIntConversion(Instruction* instr) { | |
| 3821 Opcode op = instr->S390OpcodeValue(); | |
| 3822 switch (op) { | |
| 3823 case CDLFBR: | |
| 3824 case CDLGBR: | |
| 3825 case CELGBR: | |
| 3826 case CLFDBR: | |
| 3827 case CLGDBR: | |
| 3828 case CELFBR: | |
| 3829 case CLGEBR: | |
| 3830 case CLFEBR: { | |
| 3831 RREInstruction* rreInstr = reinterpret_cast<RREInstruction*>(instr); | |
| 3832 int r1 = rreInstr->R1Value(); | |
| 3833 int r2 = rreInstr->R2Value(); | |
| 3834 if (op == CDLFBR) { | |
| 3835 uint32_t r2_val = get_low_register<uint32_t>(r2); | |
| 3836 double r1_val = static_cast<double>(r2_val); | |
| 3837 set_d_register_from_double(r1, r1_val); | |
| 3838 } else if (op == CELFBR) { | |
| 3839 uint32_t r2_val = get_low_register<uint32_t>(r2); | |
| 3840 float r1_val = static_cast<float>(r2_val); | |
| 3841 set_d_register_from_float32(r1, r1_val); | |
| 3842 } else if (op == CDLGBR) { | |
| 3843 uint64_t r2_val = get_register(r2); | |
| 3844 double r1_val = static_cast<double>(r2_val); | |
| 3845 set_d_register_from_double(r1, r1_val); | |
| 3846 } else if (op == CELGBR) { | |
| 3847 uint64_t r2_val = get_register(r2); | |
| 3848 float r1_val = static_cast<float>(r2_val); | |
| 3849 set_d_register_from_float32(r1, r1_val); | |
| 3850 } else if (op == CLFDBR) { | |
| 3851 double r2_val = get_double_from_d_register(r2); | |
| 3852 uint32_t r1_val = static_cast<uint32_t>(r2_val); | |
| 3853 set_low_register(r1, r1_val); | |
| 3854 SetS390ConvertConditionCode<double>(r2_val, r1_val, UINT32_MAX); | |
| 3855 } else if (op == CLFEBR) { | |
| 3856 float r2_val = get_float32_from_d_register(r2); | |
| 3857 uint32_t r1_val = static_cast<uint32_t>(r2_val); | |
| 3858 set_low_register(r1, r1_val); | |
| 3859 SetS390ConvertConditionCode<double>(r2_val, r1_val, UINT32_MAX); | |
| 3860 } else if (op == CLGDBR) { | |
| 3861 double r2_val = get_double_from_d_register(r2); | |
| 3862 uint64_t r1_val = static_cast<uint64_t>(r2_val); | |
| 3863 set_register(r1, r1_val); | |
| 3864 SetS390ConvertConditionCode<double>(r2_val, r1_val, UINT64_MAX); | |
| 3865 } else if (op == CLGEBR) { | |
| 3866 float r2_val = get_float32_from_d_register(r2); | |
| 3867 uint64_t r1_val = static_cast<uint64_t>(r2_val); | |
| 3868 set_register(r1, r1_val); | |
| 3869 SetS390ConvertConditionCode<double>(r2_val, r1_val, UINT64_MAX); | |
| 3870 } | |
| 3871 break; | |
| 3872 } | |
| 3873 default: | |
| 3874 UNREACHABLE(); | |
| 3875 } | |
| 3876 } | |
| 3877 | |
| 3878 void Simulator::DecodeFourByteFloatingPointRound(Instruction* instr) { | |
| 3879 Opcode op = instr->S390OpcodeValue(); | |
| 3880 RREInstruction* rreInstr = reinterpret_cast<RREInstruction*>(instr); | |
| 3881 int r1 = rreInstr->R1Value(); | |
| 3882 int r2 = rreInstr->R2Value(); | |
| 3883 double r2_val = get_double_from_d_register(r2); | |
| 3884 float r2_fval = get_float32_from_d_register(r2); | |
| 3885 | |
| 3886 switch (op) { | |
| 3887 case CFDBR: { | |
| 3888 int mask_val = rreInstr->M3Value(); | |
| 3889 int32_t r1_val = 0; | |
| 3890 | |
| 3891 SetS390RoundConditionCode(r2_val, INT32_MAX, INT32_MIN); | |
| 3892 | |
| 3893 switch (mask_val) { | |
| 3894 case CURRENT_ROUNDING_MODE: | |
| 3895 case ROUND_TO_PREPARE_FOR_SHORTER_PRECISION: { | |
| 3896 r1_val = static_cast<int32_t>(r2_val); | |
| 3897 break; | |
| 3898 } | |
| 3899 case ROUND_TO_NEAREST_WITH_TIES_AWAY_FROM_0: { | |
| 3900 double ceil_val = std::ceil(r2_val); | |
| 3901 double floor_val = std::floor(r2_val); | |
| 3902 double sub_val1 = std::fabs(r2_val - floor_val); | |
| 3903 double sub_val2 = std::fabs(r2_val - ceil_val); | |
| 3904 if (sub_val1 > sub_val2) { | |
| 3905 r1_val = static_cast<int32_t>(ceil_val); | |
| 3906 } else if (sub_val1 < sub_val2) { | |
| 3907 r1_val = static_cast<int32_t>(floor_val); | |
| 3908 } else { // round away from zero: | |
| 3909 if (r2_val > 0.0) { | |
| 3910 r1_val = static_cast<int32_t>(ceil_val); | |
| 3911 } else { | |
| 3912 r1_val = static_cast<int32_t>(floor_val); | |
| 3913 } | |
| 3914 } | |
| 3915 break; | |
| 3916 } | |
| 3917 case ROUND_TO_NEAREST_WITH_TIES_TO_EVEN: { | |
| 3918 double ceil_val = std::ceil(r2_val); | |
| 3919 double floor_val = std::floor(r2_val); | |
| 3920 double sub_val1 = std::fabs(r2_val - floor_val); | |
| 3921 double sub_val2 = std::fabs(r2_val - ceil_val); | |
| 3922 if (sub_val1 > sub_val2) { | |
| 3923 r1_val = static_cast<int32_t>(ceil_val); | |
| 3924 } else if (sub_val1 < sub_val2) { | |
| 3925 r1_val = static_cast<int32_t>(floor_val); | |
| 3926 } else { // check which one is even: | |
| 3927 int32_t c_v = static_cast<int32_t>(ceil_val); | |
| 3928 int32_t f_v = static_cast<int32_t>(floor_val); | |
| 3929 if (f_v % 2 == 0) | |
| 3930 r1_val = f_v; | |
| 3931 else | |
| 3932 r1_val = c_v; | |
| 3933 } | |
| 3934 break; | |
| 3935 } | |
| 3936 case ROUND_TOWARD_0: { | |
| 3937 // check for overflow, cast r2_val to 64bit integer | |
| 3938 // then check value within the range of INT_MIN and INT_MAX | |
| 3939 // and set condition code accordingly | |
| 3940 int64_t temp = static_cast<int64_t>(r2_val); | |
| 3941 if (temp < INT_MIN || temp > INT_MAX) { | |
| 3942 condition_reg_ = CC_OF; | |
| 3943 } | |
| 3944 r1_val = static_cast<int32_t>(r2_val); | |
| 3945 break; | |
| 3946 } | |
| 3947 case ROUND_TOWARD_PLUS_INFINITE: { | |
| 3948 r1_val = static_cast<int32_t>(std::ceil(r2_val)); | |
| 3949 break; | |
| 3950 } | |
| 3951 case ROUND_TOWARD_MINUS_INFINITE: { | |
| 3952 // check for overflow, cast r2_val to 64bit integer | |
| 3953 // then check value within the range of INT_MIN and INT_MAX | |
| 3954 // and set condition code accordingly | |
| 3955 int64_t temp = static_cast<int64_t>(std::floor(r2_val)); | |
| 3956 if (temp < INT_MIN || temp > INT_MAX) { | |
| 3957 condition_reg_ = CC_OF; | |
| 3958 } | |
| 3959 r1_val = static_cast<int32_t>(std::floor(r2_val)); | |
| 3960 break; | |
| 3961 } | |
| 3962 default: | |
| 3963 UNREACHABLE(); | |
| 3964 } | |
| 3965 set_low_register(r1, r1_val); | |
| 3966 break; | |
| 3967 } | |
| 3968 case CGDBR: { | |
| 3969 int mask_val = rreInstr->M3Value(); | |
| 3970 int64_t r1_val = 0; | |
| 3971 | |
| 3972 SetS390RoundConditionCode(r2_val, INT64_MAX, INT64_MIN); | |
| 3973 | |
| 3974 switch (mask_val) { | |
| 3975 case CURRENT_ROUNDING_MODE: | |
| 3976 case ROUND_TO_NEAREST_WITH_TIES_AWAY_FROM_0: | |
| 3977 case ROUND_TO_PREPARE_FOR_SHORTER_PRECISION: { | |
| 3978 UNIMPLEMENTED(); | |
| 3979 break; | |
| 3980 } | |
| 3981 case ROUND_TO_NEAREST_WITH_TIES_TO_EVEN: { | |
| 3982 double ceil_val = std::ceil(r2_val); | |
| 3983 double floor_val = std::floor(r2_val); | |
| 3984 if (std::abs(r2_val - floor_val) > std::abs(r2_val - ceil_val)) { | |
| 3985 r1_val = static_cast<int64_t>(ceil_val); | |
| 3986 } else if (std::abs(r2_val - floor_val) < | |
| 3987 std::abs(r2_val - ceil_val)) { | |
| 3988 r1_val = static_cast<int64_t>(floor_val); | |
| 3989 } else { // check which one is even: | |
| 3990 int64_t c_v = static_cast<int64_t>(ceil_val); | |
| 3991 int64_t f_v = static_cast<int64_t>(floor_val); | |
| 3992 if (f_v % 2 == 0) | |
| 3993 r1_val = f_v; | |
| 3994 else | |
| 3995 r1_val = c_v; | |
| 3996 } | |
| 3997 break; | |
| 3998 } | |
| 3999 case ROUND_TOWARD_0: { | |
| 4000 r1_val = static_cast<int64_t>(r2_val); | |
| 4001 break; | |
| 4002 } | |
| 4003 case ROUND_TOWARD_PLUS_INFINITE: { | |
| 4004 r1_val = static_cast<int64_t>(std::ceil(r2_val)); | |
| 4005 break; | |
| 4006 } | |
| 4007 case ROUND_TOWARD_MINUS_INFINITE: { | |
| 4008 r1_val = static_cast<int64_t>(std::floor(r2_val)); | |
| 4009 break; | |
| 4010 } | |
| 4011 default: | |
| 4012 UNREACHABLE(); | |
| 4013 } | |
| 4014 set_register(r1, r1_val); | |
| 4015 break; | |
| 4016 } | |
| 4017 case CGEBR: { | |
| 4018 int mask_val = rreInstr->M3Value(); | |
| 4019 int64_t r1_val = 0; | |
| 4020 | |
| 4021 SetS390RoundConditionCode(r2_fval, INT64_MAX, INT64_MIN); | |
| 4022 | |
| 4023 switch (mask_val) { | |
| 4024 case CURRENT_ROUNDING_MODE: | |
| 4025 case ROUND_TO_NEAREST_WITH_TIES_AWAY_FROM_0: | |
| 4026 case ROUND_TO_PREPARE_FOR_SHORTER_PRECISION: { | |
| 4027 UNIMPLEMENTED(); | |
| 4028 break; | |
| 4029 } | |
| 4030 case ROUND_TO_NEAREST_WITH_TIES_TO_EVEN: { | |
| 4031 float ceil_val = std::ceil(r2_fval); | |
| 4032 float floor_val = std::floor(r2_fval); | |
| 4033 if (std::abs(r2_fval - floor_val) > std::abs(r2_fval - ceil_val)) { | |
| 4034 r1_val = static_cast<int64_t>(ceil_val); | |
| 4035 } else if (std::abs(r2_fval - floor_val) < | |
| 4036 std::abs(r2_fval - ceil_val)) { | |
| 4037 r1_val = static_cast<int64_t>(floor_val); | |
| 4038 } else { // check which one is even: | |
| 4039 int64_t c_v = static_cast<int64_t>(ceil_val); | |
| 4040 int64_t f_v = static_cast<int64_t>(floor_val); | |
| 4041 if (f_v % 2 == 0) | |
| 4042 r1_val = f_v; | |
| 4043 else | |
| 4044 r1_val = c_v; | |
| 4045 } | |
| 4046 break; | |
| 4047 } | |
| 4048 case ROUND_TOWARD_0: { | |
| 4049 r1_val = static_cast<int64_t>(r2_fval); | |
| 4050 break; | |
| 4051 } | |
| 4052 case ROUND_TOWARD_PLUS_INFINITE: { | |
| 4053 r1_val = static_cast<int64_t>(std::ceil(r2_fval)); | |
| 4054 break; | |
| 4055 } | |
| 4056 case ROUND_TOWARD_MINUS_INFINITE: { | |
| 4057 r1_val = static_cast<int64_t>(std::floor(r2_fval)); | |
| 4058 break; | |
| 4059 } | |
| 4060 default: | |
| 4061 UNREACHABLE(); | |
| 4062 } | |
| 4063 set_register(r1, r1_val); | |
| 4064 break; | |
| 4065 } | |
| 4066 case CFEBR: { | |
| 4067 int mask_val = rreInstr->M3Value(); | |
| 4068 int32_t r1_val = 0; | |
| 4069 | |
| 4070 SetS390RoundConditionCode(r2_fval, INT32_MAX, INT32_MIN); | |
| 4071 | |
| 4072 switch (mask_val) { | |
| 4073 case CURRENT_ROUNDING_MODE: | |
| 4074 case ROUND_TO_PREPARE_FOR_SHORTER_PRECISION: { | |
| 4075 r1_val = static_cast<int32_t>(r2_fval); | |
| 4076 break; | |
| 4077 } | |
| 4078 case ROUND_TO_NEAREST_WITH_TIES_AWAY_FROM_0: { | |
| 4079 float ceil_val = std::ceil(r2_fval); | |
| 4080 float floor_val = std::floor(r2_fval); | |
| 4081 float sub_val1 = std::fabs(r2_fval - floor_val); | |
| 4082 float sub_val2 = std::fabs(r2_fval - ceil_val); | |
| 4083 if (sub_val1 > sub_val2) { | |
| 4084 r1_val = static_cast<int32_t>(ceil_val); | |
| 4085 } else if (sub_val1 < sub_val2) { | |
| 4086 r1_val = static_cast<int32_t>(floor_val); | |
| 4087 } else { // round away from zero: | |
| 4088 if (r2_fval > 0.0) { | |
| 4089 r1_val = static_cast<int32_t>(ceil_val); | |
| 4090 } else { | |
| 4091 r1_val = static_cast<int32_t>(floor_val); | |
| 4092 } | |
| 4093 } | |
| 4094 break; | |
| 4095 } | |
| 4096 case ROUND_TO_NEAREST_WITH_TIES_TO_EVEN: { | |
| 4097 float ceil_val = std::ceil(r2_fval); | |
| 4098 float floor_val = std::floor(r2_fval); | |
| 4099 float sub_val1 = std::fabs(r2_fval - floor_val); | |
| 4100 float sub_val2 = std::fabs(r2_fval - ceil_val); | |
| 4101 if (sub_val1 > sub_val2) { | |
| 4102 r1_val = static_cast<int32_t>(ceil_val); | |
| 4103 } else if (sub_val1 < sub_val2) { | |
| 4104 r1_val = static_cast<int32_t>(floor_val); | |
| 4105 } else { // check which one is even: | |
| 4106 int32_t c_v = static_cast<int32_t>(ceil_val); | |
| 4107 int32_t f_v = static_cast<int32_t>(floor_val); | |
| 4108 if (f_v % 2 == 0) | |
| 4109 r1_val = f_v; | |
| 4110 else | |
| 4111 r1_val = c_v; | |
| 4112 } | |
| 4113 break; | |
| 4114 } | |
| 4115 case ROUND_TOWARD_0: { | |
| 4116 // check for overflow, cast r2_fval to 64bit integer | |
| 4117 // then check value within the range of INT_MIN and INT_MAX | |
| 4118 // and set condition code accordingly | |
| 4119 int64_t temp = static_cast<int64_t>(r2_fval); | |
| 4120 if (temp < INT_MIN || temp > INT_MAX) { | |
| 4121 condition_reg_ = CC_OF; | |
| 4122 } | |
| 4123 r1_val = static_cast<int32_t>(r2_fval); | |
| 4124 break; | |
| 4125 } | |
| 4126 case ROUND_TOWARD_PLUS_INFINITE: { | |
| 4127 r1_val = static_cast<int32_t>(std::ceil(r2_fval)); | |
| 4128 break; | |
| 4129 } | |
| 4130 case ROUND_TOWARD_MINUS_INFINITE: { | |
| 4131 // check for overflow, cast r2_fval to 64bit integer | |
| 4132 // then check value within the range of INT_MIN and INT_MAX | |
| 4133 // and set condition code accordingly | |
| 4134 int64_t temp = static_cast<int64_t>(std::floor(r2_fval)); | |
| 4135 if (temp < INT_MIN || temp > INT_MAX) { | |
| 4136 condition_reg_ = CC_OF; | |
| 4137 } | |
| 4138 r1_val = static_cast<int32_t>(std::floor(r2_fval)); | |
| 4139 break; | |
| 4140 } | |
| 4141 default: | |
| 4142 UNREACHABLE(); | |
| 4143 } | |
| 4144 set_low_register(r1, r1_val); | |
| 4145 | |
| 4146 break; | |
| 4147 } | |
| 4148 default: | |
| 4149 UNREACHABLE(); | |
| 4150 } | |
| 4151 } | |
| 4152 | |
| 4153 /** | |
| 4154 * Decodes and simulates four byte floating point instructions | |
| 4155 */ | |
| 4156 bool Simulator::DecodeFourByteFloatingPoint(Instruction* instr) { | |
| 4157 Opcode op = instr->S390OpcodeValue(); | |
| 4158 | |
| 4159 switch (op) { | |
| 4160 case ADBR: | |
| 4161 case AEBR: | |
| 4162 case SDBR: | |
| 4163 case SEBR: | |
| 4164 case MDBR: | |
| 4165 case MEEBR: | |
| 4166 case MADBR: | |
| 4167 case DDBR: | |
| 4168 case DEBR: | |
| 4169 case CDBR: | |
| 4170 case CEBR: | |
| 4171 case CDFBR: | |
| 4172 case CDGBR: | |
| 4173 case CEGBR: | |
| 4174 case CGEBR: | |
| 4175 case CFDBR: | |
| 4176 case CGDBR: | |
| 4177 case SQDBR: | |
| 4178 case SQEBR: | |
| 4179 case CFEBR: | |
| 4180 case CEFBR: | |
| 4181 case LCDBR: | |
| 4182 case LCEBR: | |
| 4183 case LPDBR: | |
| 4184 case LPEBR: { | |
| 4185 RREInstruction* rreInstr = reinterpret_cast<RREInstruction*>(instr); | |
| 4186 int r1 = rreInstr->R1Value(); | |
| 4187 int r2 = rreInstr->R2Value(); | |
| 4188 double r1_val = get_double_from_d_register(r1); | |
| 4189 double r2_val = get_double_from_d_register(r2); | |
| 4190 float fr1_val = get_float32_from_d_register(r1); | |
| 4191 float fr2_val = get_float32_from_d_register(r2); | |
| 4192 if (op == ADBR) { | |
| 4193 r1_val += r2_val; | |
| 4194 set_d_register_from_double(r1, r1_val); | |
| 4195 SetS390ConditionCode<double>(r1_val, 0); | |
| 4196 } else if (op == AEBR) { | |
| 4197 fr1_val += fr2_val; | |
| 4198 set_d_register_from_float32(r1, fr1_val); | |
| 4199 SetS390ConditionCode<float>(fr1_val, 0); | |
| 4200 } else if (op == SDBR) { | |
| 4201 r1_val -= r2_val; | |
| 4202 set_d_register_from_double(r1, r1_val); | |
| 4203 SetS390ConditionCode<double>(r1_val, 0); | |
| 4204 } else if (op == SEBR) { | |
| 4205 fr1_val -= fr2_val; | |
| 4206 set_d_register_from_float32(r1, fr1_val); | |
| 4207 SetS390ConditionCode<float>(fr1_val, 0); | |
| 4208 } else if (op == MDBR) { | |
| 4209 r1_val *= r2_val; | |
| 4210 set_d_register_from_double(r1, r1_val); | |
| 4211 SetS390ConditionCode<double>(r1_val, 0); | |
| 4212 } else if (op == MEEBR) { | |
| 4213 fr1_val *= fr2_val; | |
| 4214 set_d_register_from_float32(r1, fr1_val); | |
| 4215 SetS390ConditionCode<float>(fr1_val, 0); | |
| 4216 } else if (op == MADBR) { | |
| 4217 RRDInstruction* rrdInstr = reinterpret_cast<RRDInstruction*>(instr); | |
| 4218 int r1 = rrdInstr->R1Value(); | |
| 4219 int r2 = rrdInstr->R2Value(); | |
| 4220 int r3 = rrdInstr->R3Value(); | |
| 4221 double r1_val = get_double_from_d_register(r1); | |
| 4222 double r2_val = get_double_from_d_register(r2); | |
| 4223 double r3_val = get_double_from_d_register(r3); | |
| 4224 r1_val += r2_val * r3_val; | |
| 4225 set_d_register_from_double(r1, r1_val); | |
| 4226 SetS390ConditionCode<double>(r1_val, 0); | |
| 4227 } else if (op == DDBR) { | |
| 4228 r1_val /= r2_val; | |
| 4229 set_d_register_from_double(r1, r1_val); | |
| 4230 SetS390ConditionCode<double>(r1_val, 0); | |
| 4231 } else if (op == DEBR) { | |
| 4232 fr1_val /= fr2_val; | |
| 4233 set_d_register_from_float32(r1, fr1_val); | |
| 4234 SetS390ConditionCode<float>(fr1_val, 0); | |
| 4235 } else if (op == CDBR) { | |
| 4236 if (isNaN(r1_val) || isNaN(r2_val)) { | |
| 4237 condition_reg_ = CC_OF; | |
| 4238 } else { | |
| 4239 SetS390ConditionCode<double>(r1_val, r2_val); | |
| 4240 } | |
| 4241 } else if (op == CEBR) { | |
| 4242 if (isNaN(fr1_val) || isNaN(fr2_val)) { | |
| 4243 condition_reg_ = CC_OF; | |
| 4244 } else { | |
| 4245 SetS390ConditionCode<float>(fr1_val, fr2_val); | |
| 4246 } | |
| 4247 } else if (op == CDGBR) { | |
| 4248 int64_t r2_val = get_register(r2); | |
| 4249 double r1_val = static_cast<double>(r2_val); | |
| 4250 set_d_register_from_double(r1, r1_val); | |
| 4251 } else if (op == CEGBR) { | |
| 4252 int64_t fr2_val = get_register(r2); | |
| 4253 float fr1_val = static_cast<float>(fr2_val); | |
| 4254 set_d_register_from_float32(r1, fr1_val); | |
| 4255 } else if (op == CDFBR) { | |
| 4256 int32_t r2_val = get_low_register<int32_t>(r2); | |
| 4257 double r1_val = static_cast<double>(r2_val); | |
| 4258 set_d_register_from_double(r1, r1_val); | |
| 4259 } else if (op == CEFBR) { | |
| 4260 int32_t fr2_val = get_low_register<int32_t>(r2); | |
| 4261 float fr1_val = static_cast<float>(fr2_val); | |
| 4262 set_d_register_from_float32(r1, fr1_val); | |
| 4263 } else if (op == CFDBR) { | |
| 4264 DecodeFourByteFloatingPointRound(instr); | |
| 4265 } else if (op == CGDBR) { | |
| 4266 DecodeFourByteFloatingPointRound(instr); | |
| 4267 } else if (op == CGEBR) { | |
| 4268 DecodeFourByteFloatingPointRound(instr); | |
| 4269 } else if (op == SQDBR) { | |
| 4270 r1_val = std::sqrt(r2_val); | |
| 4271 set_d_register_from_double(r1, r1_val); | |
| 4272 } else if (op == SQEBR) { | |
| 4273 fr1_val = std::sqrt(fr2_val); | |
| 4274 set_d_register_from_float32(r1, fr1_val); | |
| 4275 } else if (op == CFEBR) { | |
| 4276 DecodeFourByteFloatingPointRound(instr); | |
| 4277 } else if (op == LCDBR) { | |
| 4278 r1_val = -r2_val; | |
| 4279 set_d_register_from_double(r1, r1_val); | |
| 4280 if (r2_val != r2_val) { // input is NaN | |
| 4281 condition_reg_ = CC_OF; | |
| 4282 } else if (r2_val == 0) { | |
| 4283 condition_reg_ = CC_EQ; | |
| 4284 } else if (r2_val < 0) { | |
| 4285 condition_reg_ = CC_LT; | |
| 4286 } else if (r2_val > 0) { | |
| 4287 condition_reg_ = CC_GT; | |
| 4288 } | |
| 4289 } else if (op == LCEBR) { | |
| 4290 fr1_val = -fr2_val; | |
| 4291 set_d_register_from_float32(r1, fr1_val); | |
| 4292 if (fr2_val != fr2_val) { // input is NaN | |
| 4293 condition_reg_ = CC_OF; | |
| 4294 } else if (fr2_val == 0) { | |
| 4295 condition_reg_ = CC_EQ; | |
| 4296 } else if (fr2_val < 0) { | |
| 4297 condition_reg_ = CC_LT; | |
| 4298 } else if (fr2_val > 0) { | |
| 4299 condition_reg_ = CC_GT; | |
| 4300 } | |
| 4301 } else if (op == LPDBR) { | |
| 4302 r1_val = std::fabs(r2_val); | |
| 4303 set_d_register_from_double(r1, r1_val); | |
| 4304 if (r2_val != r2_val) { // input is NaN | |
| 4305 condition_reg_ = CC_OF; | |
| 4306 } else if (r2_val == 0) { | |
| 4307 condition_reg_ = CC_EQ; | |
| 4308 } else { | |
| 4309 condition_reg_ = CC_GT; | |
| 4310 } | |
| 4311 } else if (op == LPEBR) { | |
| 4312 fr1_val = std::fabs(fr2_val); | |
| 4313 set_d_register_from_float32(r1, fr1_val); | |
| 4314 if (fr2_val != fr2_val) { // input is NaN | |
| 4315 condition_reg_ = CC_OF; | |
| 4316 } else if (fr2_val == 0) { | |
| 4317 condition_reg_ = CC_EQ; | |
| 4318 } else { | |
| 4319 condition_reg_ = CC_GT; | |
| 4320 } | |
| 4321 } else { | |
| 4322 UNREACHABLE(); | |
| 4323 } | |
| 4324 break; | |
| 4325 } | |
| 4326 case CDLFBR: | |
| 4327 case CDLGBR: | |
| 4328 case CELGBR: | |
| 4329 case CLFDBR: | |
| 4330 case CELFBR: | |
| 4331 case CLGDBR: | |
| 4332 case CLGEBR: | |
| 4333 case CLFEBR: { | |
| 4334 DecodeFourByteFloatingPointIntConversion(instr); | |
| 4335 break; | |
| 4336 } | |
| 4337 case TMLL: { | |
| 4338 RIInstruction* riinst = reinterpret_cast<RIInstruction*>(instr); | |
| 4339 int r1 = riinst->R1Value(); | |
| 4340 int mask = riinst->I2Value() & 0x0000FFFF; | |
| 4341 if (mask == 0) { | |
| 4342 condition_reg_ = 0x0; | |
| 4343 break; | |
| 4344 } | |
| 4345 uint32_t r1_val = get_low_register<uint32_t>(r1); | |
| 4346 r1_val = r1_val & 0x0000FFFF; // uses only the last 16bits | |
| 4347 | |
| 4348 // Test if all selected bits are Zero | |
| 4349 bool allSelectedBitsAreZeros = true; | |
| 4350 for (int i = 0; i < 15; i++) { | |
| 4351 if (mask & (1 << i)) { | |
| 4352 if (r1_val & (1 << i)) { | |
| 4353 allSelectedBitsAreZeros = false; | |
| 4354 break; | |
| 4355 } | |
| 4356 } | |
| 4357 } | |
| 4358 if (allSelectedBitsAreZeros) { | |
| 4359 condition_reg_ = 0x8; | |
| 4360 break; // Done! | |
| 4361 } | |
| 4362 | |
| 4363 // Test if all selected bits are one | |
| 4364 bool allSelectedBitsAreOnes = true; | |
| 4365 for (int i = 0; i < 15; i++) { | |
| 4366 if (mask & (1 << i)) { | |
| 4367 if (!(r1_val & (1 << i))) { | |
| 4368 allSelectedBitsAreOnes = false; | |
| 4369 break; | |
| 4370 } | |
| 4371 } | |
| 4372 } | |
| 4373 if (allSelectedBitsAreOnes) { | |
| 4374 condition_reg_ = 0x1; | |
| 4375 break; // Done! | |
| 4376 } | |
| 4377 | |
| 4378 // Now we know selected bits mixed zeros and ones | |
| 4379 // Test if the leftmost bit is zero or one | |
| 4380 for (int i = 14; i >= 0; i--) { | |
| 4381 if (mask & (1 << i)) { | |
| 4382 if (r1_val & (1 << i)) { | |
| 4383 // leftmost bit is one | |
| 4384 condition_reg_ = 0x2; | |
| 4385 } else { | |
| 4386 // leftmost bit is zero | |
| 4387 condition_reg_ = 0x4; | |
| 4388 } | |
| 4389 break; // Done! | |
| 4390 } | |
| 4391 } | |
| 4392 break; | |
| 4393 } | |
| 4394 case LEDBR: { | |
| 4395 RREInstruction* rreInst = reinterpret_cast<RREInstruction*>(instr); | |
| 4396 int r1 = rreInst->R1Value(); | |
| 4397 int r2 = rreInst->R2Value(); | |
| 4398 double r2_val = get_double_from_d_register(r2); | |
| 4399 set_d_register_from_float32(r1, static_cast<float>(r2_val)); | |
| 4400 break; | |
| 4401 } | |
| 4402 case FIDBRA: { | |
| 4403 RRFInstruction* rrfInst = reinterpret_cast<RRFInstruction*>(instr); | |
| 4404 int r1 = rrfInst->R1Value(); | |
| 4405 int r2 = rrfInst->R2Value(); | |
| 4406 int m3 = rrfInst->M3Value(); | |
| 4407 double r2_val = get_double_from_d_register(r2); | |
| 4408 DCHECK(rrfInst->M4Value() == 0); | |
| 4409 switch (m3) { | |
| 4410 case Assembler::FIDBRA_ROUND_TO_NEAREST_AWAY_FROM_0: | |
| 4411 set_d_register_from_double(r1, round(r2_val)); | |
| 4412 break; | |
| 4413 case Assembler::FIDBRA_ROUND_TOWARD_0: | |
| 4414 set_d_register_from_double(r1, trunc(r2_val)); | |
| 4415 break; | |
| 4416 case Assembler::FIDBRA_ROUND_TOWARD_POS_INF: | |
| 4417 set_d_register_from_double(r1, std::ceil(r2_val)); | |
| 4418 break; | |
| 4419 case Assembler::FIDBRA_ROUND_TOWARD_NEG_INF: | |
| 4420 set_d_register_from_double(r1, std::floor(r2_val)); | |
| 4421 break; | |
| 4422 default: | |
| 4423 UNIMPLEMENTED(); | |
| 4424 break; | |
| 4425 } | |
| 4426 break; | |
| 4427 } | |
| 4428 case FIEBRA: { | |
| 4429 RRFInstruction* rrfInst = reinterpret_cast<RRFInstruction*>(instr); | |
| 4430 int r1 = rrfInst->R1Value(); | |
| 4431 int r2 = rrfInst->R2Value(); | |
| 4432 int m3 = rrfInst->M3Value(); | |
| 4433 float r2_val = get_float32_from_d_register(r2); | |
| 4434 DCHECK(rrfInst->M4Value() == 0); | |
| 4435 switch (m3) { | |
| 4436 case Assembler::FIDBRA_ROUND_TO_NEAREST_AWAY_FROM_0: | |
| 4437 set_d_register_from_float32(r1, round(r2_val)); | |
| 4438 break; | |
| 4439 case Assembler::FIDBRA_ROUND_TOWARD_0: | |
| 4440 set_d_register_from_float32(r1, trunc(r2_val)); | |
| 4441 break; | |
| 4442 case Assembler::FIDBRA_ROUND_TOWARD_POS_INF: | |
| 4443 set_d_register_from_float32(r1, std::ceil(r2_val)); | |
| 4444 break; | |
| 4445 case Assembler::FIDBRA_ROUND_TOWARD_NEG_INF: | |
| 4446 set_d_register_from_float32(r1, std::floor(r2_val)); | |
| 4447 break; | |
| 4448 default: | |
| 4449 UNIMPLEMENTED(); | |
| 4450 break; | |
| 4451 } | |
| 4452 break; | |
| 4453 } | |
| 4454 case MSDBR: { | |
| 4455 UNIMPLEMENTED(); | |
| 4456 break; | |
| 4457 } | |
| 4458 case LDEBR: { | |
| 4459 RREInstruction* rreInstr = reinterpret_cast<RREInstruction*>(instr); | |
| 4460 int r1 = rreInstr->R1Value(); | |
| 4461 int r2 = rreInstr->R2Value(); | |
| 4462 float fp_val = get_float32_from_d_register(r2); | |
| 4463 double db_val = static_cast<double>(fp_val); | |
| 4464 set_d_register_from_double(r1, db_val); | |
| 4465 break; | |
| 4466 } | |
| 4467 default: { | |
| 4468 UNREACHABLE(); | |
| 4469 return false; | |
| 4470 } | |
| 4471 } | |
| 4472 return true; | |
| 4473 } | |
| 4474 | |
| 4475 // Decode routine for six-byte instructions | |
| 4476 bool Simulator::DecodeSixByte(Instruction* instr) { | |
| 4477 Opcode op = instr->S390OpcodeValue(); | |
| 4478 | |
| 4479 // Pre-cast instruction to various types | |
| 4480 RIEInstruction* rieInstr = reinterpret_cast<RIEInstruction*>(instr); | |
| 4481 RILInstruction* rilInstr = reinterpret_cast<RILInstruction*>(instr); | |
| 4482 RSYInstruction* rsyInstr = reinterpret_cast<RSYInstruction*>(instr); | |
| 4483 RXEInstruction* rxeInstr = reinterpret_cast<RXEInstruction*>(instr); | |
| 4484 RXYInstruction* rxyInstr = reinterpret_cast<RXYInstruction*>(instr); | |
| 4485 SIYInstruction* siyInstr = reinterpret_cast<SIYInstruction*>(instr); | |
| 4486 SILInstruction* silInstr = reinterpret_cast<SILInstruction*>(instr); | |
| 4487 SSInstruction* ssInstr = reinterpret_cast<SSInstruction*>(instr); | |
| 4488 | |
| 4489 switch (op) { | |
| 4490 case CLIY: { | |
| 4491 // Compare Immediate (Mem - Imm) (8) | |
| 4492 int b1 = siyInstr->B1Value(); | |
| 4493 int64_t b1_val = (b1 == 0) ? 0 : get_register(b1); | |
| 4494 intptr_t d1_val = siyInstr->D1Value(); | |
| 4495 intptr_t addr = b1_val + d1_val; | |
| 4496 uint8_t mem_val = ReadB(addr); | |
| 4497 uint8_t imm_val = siyInstr->I2Value(); | |
| 4498 SetS390ConditionCode<uint8_t>(mem_val, imm_val); | |
| 4499 break; | |
| 4500 } | |
| 4501 case TMY: { | |
| 4502 // Test Under Mask (Mem - Imm) (8) | |
| 4503 int b1 = siyInstr->B1Value(); | |
| 4504 int64_t b1_val = (b1 == 0) ? 0 : get_register(b1); | |
| 4505 intptr_t d1_val = siyInstr->D1Value(); | |
| 4506 intptr_t addr = b1_val + d1_val; | |
| 4507 uint8_t mem_val = ReadB(addr); | |
| 4508 uint8_t imm_val = siyInstr->I2Value(); | |
| 4509 uint8_t selected_bits = mem_val & imm_val; | |
| 4510 // CC0: Selected bits are zero | |
| 4511 // CC1: Selected bits mixed zeros and ones | |
| 4512 // CC3: Selected bits all ones | |
| 4513 if (0 == selected_bits) { | |
| 4514 condition_reg_ = CC_EQ; // CC0 | |
| 4515 } else if (selected_bits == imm_val) { | |
| 4516 condition_reg_ = 0x1; // CC3 | |
| 4517 } else { | |
| 4518 condition_reg_ = 0x4; // CC1 | |
| 4519 } | |
| 4520 break; | |
| 4521 } | |
| 4522 case LDEB: { | |
| 4523 // Load Float | |
| 4524 int r1 = rxeInstr->R1Value(); | |
| 4525 int rb = rxeInstr->B2Value(); | |
| 4526 int rx = rxeInstr->X2Value(); | |
| 4527 int offset = rxeInstr->D2Value(); | |
| 4528 int64_t rb_val = (rb == 0) ? 0 : get_register(rb); | |
| 4529 int64_t rx_val = (rx == 0) ? 0 : get_register(rx); | |
| 4530 double ret = static_cast<double>( | |
| 4531 *reinterpret_cast<float*>(rx_val + rb_val + offset)); | |
| 4532 set_d_register_from_double(r1, ret); | |
| 4533 break; | |
| 4534 } | |
| 4535 case LAY: { | |
| 4536 // Load Address | |
| 4537 int r1 = rxyInstr->R1Value(); | |
| 4538 int rb = rxyInstr->B2Value(); | |
| 4539 int rx = rxyInstr->X2Value(); | |
| 4540 int offset = rxyInstr->D2Value(); | |
| 4541 int64_t rb_val = (rb == 0) ? 0 : get_register(rb); | |
| 4542 int64_t rx_val = (rx == 0) ? 0 : get_register(rx); | |
| 4543 set_register(r1, rx_val + rb_val + offset); | |
| 4544 break; | |
| 4545 } | |
| 4546 case LARL: { | |
| 4547 // Load Addresss Relative Long | |
| 4548 int r1 = rilInstr->R1Value(); | |
| 4549 intptr_t offset = rilInstr->I2Value() * 2; | |
| 4550 set_register(r1, get_pc() + offset); | |
| 4551 break; | |
| 4552 } | |
| 4553 case LLILF: { | |
| 4554 // Load Logical into lower 32-bits (zero extend upper 32-bits) | |
| 4555 int r1 = rilInstr->R1Value(); | |
| 4556 uint64_t imm = static_cast<uint64_t>(rilInstr->I2UnsignedValue()); | |
| 4557 set_register(r1, imm); | |
| 4558 break; | |
| 4559 } | |
| 4560 case LLIHF: { | |
| 4561 // Load Logical Immediate into high word | |
| 4562 int r1 = rilInstr->R1Value(); | |
| 4563 uint64_t imm = static_cast<uint64_t>(rilInstr->I2UnsignedValue()); | |
| 4564 set_register(r1, imm << 32); | |
| 4565 break; | |
| 4566 } | |
| 4567 case OILF: | |
| 4568 case NILF: | |
| 4569 case IILF: { | |
| 4570 // Bitwise Op on lower 32-bits | |
| 4571 int r1 = rilInstr->R1Value(); | |
| 4572 uint32_t imm = rilInstr->I2UnsignedValue(); | |
| 4573 uint32_t alu_out = get_low_register<uint32_t>(r1); | |
| 4574 if (NILF == op) { | |
| 4575 alu_out &= imm; | |
| 4576 SetS390BitWiseConditionCode<uint32_t>(alu_out); | |
| 4577 } else if (OILF == op) { | |
| 4578 alu_out |= imm; | |
| 4579 SetS390BitWiseConditionCode<uint32_t>(alu_out); | |
| 4580 } else if (op == IILF) { | |
| 4581 alu_out = imm; | |
| 4582 } else { | |
| 4583 DCHECK(false); | |
| 4584 } | |
| 4585 set_low_register(r1, alu_out); | |
| 4586 break; | |
| 4587 } | |
| 4588 case OIHF: | |
| 4589 case NIHF: | |
| 4590 case IIHF: { | |
| 4591 // Bitwise Op on upper 32-bits | |
| 4592 int r1 = rilInstr->R1Value(); | |
| 4593 uint32_t imm = rilInstr->I2Value(); | |
| 4594 uint32_t alu_out = get_high_register<uint32_t>(r1); | |
| 4595 if (op == NIHF) { | |
| 4596 alu_out &= imm; | |
| 4597 SetS390BitWiseConditionCode<uint32_t>(alu_out); | |
| 4598 } else if (op == OIHF) { | |
| 4599 alu_out |= imm; | |
| 4600 SetS390BitWiseConditionCode<uint32_t>(alu_out); | |
| 4601 } else if (op == IIHF) { | |
| 4602 alu_out = imm; | |
| 4603 } else { | |
| 4604 DCHECK(false); | |
| 4605 } | |
| 4606 set_high_register(r1, alu_out); | |
| 4607 break; | |
| 4608 } | |
| 4609 case CLFI: { | |
| 4610 // Compare Logical with Immediate (32) | |
| 4611 int r1 = rilInstr->R1Value(); | |
| 4612 uint32_t imm = rilInstr->I2UnsignedValue(); | |
| 4613 SetS390ConditionCode<uint32_t>(get_low_register<uint32_t>(r1), imm); | |
| 4614 break; | |
| 4615 } | |
| 4616 case CFI: { | |
| 4617 // Compare with Immediate (32) | |
| 4618 int r1 = rilInstr->R1Value(); | |
| 4619 int32_t imm = rilInstr->I2Value(); | |
| 4620 SetS390ConditionCode<int32_t>(get_low_register<int32_t>(r1), imm); | |
| 4621 break; | |
| 4622 } | |
| 4623 case CLGFI: { | |
| 4624 // Compare Logical with Immediate (64) | |
| 4625 int r1 = rilInstr->R1Value(); | |
| 4626 uint64_t imm = static_cast<uint64_t>(rilInstr->I2UnsignedValue()); | |
| 4627 SetS390ConditionCode<uint64_t>(get_register(r1), imm); | |
| 4628 break; | |
| 4629 } | |
| 4630 case CGFI: { | |
| 4631 // Compare with Immediate (64) | |
| 4632 int r1 = rilInstr->R1Value(); | |
| 4633 int64_t imm = static_cast<int64_t>(rilInstr->I2Value()); | |
| 4634 SetS390ConditionCode<int64_t>(get_register(r1), imm); | |
| 4635 break; | |
| 4636 } | |
| 4637 case BRASL: { | |
| 4638 // Branch and Save Relative Long | |
| 4639 int r1 = rilInstr->R1Value(); | |
| 4640 intptr_t d2 = rilInstr->I2Value(); | |
| 4641 intptr_t pc = get_pc(); | |
| 4642 set_register(r1, pc + 6); // save next instruction to register | |
| 4643 set_pc(pc + d2 * 2); // update register | |
| 4644 break; | |
| 4645 } | |
| 4646 case BRCL: { | |
| 4647 // Branch on Condition Relative Long | |
| 4648 Condition m1 = (Condition)rilInstr->R1Value(); | |
| 4649 if (TestConditionCode((Condition)m1)) { | |
| 4650 intptr_t offset = rilInstr->I2Value() * 2; | |
| 4651 set_pc(get_pc() + offset); | |
| 4652 } | |
| 4653 break; | |
| 4654 } | |
| 4655 case LMG: | |
| 4656 case STMG: { | |
| 4657 // Store Multiple 64-bits. | |
| 4658 int r1 = rsyInstr->R1Value(); | |
| 4659 int r3 = rsyInstr->R3Value(); | |
| 4660 int rb = rsyInstr->B2Value(); | |
| 4661 int offset = rsyInstr->D2Value(); | |
| 4662 | |
| 4663 // Regs roll around if r3 is less than r1. | |
| 4664 // Artifically increase r3 by 16 so we can calculate | |
| 4665 // the number of regs stored properly. | |
| 4666 if (r3 < r1) r3 += 16; | |
| 4667 | |
| 4668 int64_t rb_val = (rb == 0) ? 0 : get_register(rb); | |
| 4669 | |
| 4670 // Store each register in ascending order. | |
| 4671 for (int i = 0; i <= r3 - r1; i++) { | |
| 4672 if (op == LMG) { | |
| 4673 int64_t value = ReadDW(rb_val + offset + 8 * i); | |
| 4674 set_register((r1 + i) % 16, value); | |
| 4675 } else if (op == STMG) { | |
| 4676 int64_t value = get_register((r1 + i) % 16); | |
| 4677 WriteDW(rb_val + offset + 8 * i, value); | |
| 4678 } else { | |
| 4679 DCHECK(false); | |
| 4680 } | |
| 4681 } | |
| 4682 break; | |
| 4683 } | |
| 4684 case SLLK: | |
| 4685 case RLL: | |
| 4686 case SRLK: | |
| 4687 case SLLG: | |
| 4688 case RLLG: | |
| 4689 case SRLG: { | |
| 4690 DecodeSixByteBitShift(instr); | |
| 4691 break; | |
| 4692 } | |
| 4693 case SLAK: | |
| 4694 case SRAK: { | |
| 4695 // 32-bit non-clobbering shift-left/right arithmetic | |
| 4696 int r1 = rsyInstr->R1Value(); | |
| 4697 int r3 = rsyInstr->R3Value(); | |
| 4698 int b2 = rsyInstr->B2Value(); | |
| 4699 intptr_t d2 = rsyInstr->D2Value(); | |
| 4700 // only takes rightmost 6 bits | |
| 4701 int64_t b2_val = (b2 == 0) ? 0 : get_register(b2); | |
| 4702 int shiftBits = (b2_val + d2) & 0x3F; | |
| 4703 int32_t r3_val = get_low_register<int32_t>(r3); | |
| 4704 int32_t alu_out = 0; | |
| 4705 bool isOF = false; | |
| 4706 if (op == SLAK) { | |
| 4707 isOF = CheckOverflowForShiftLeft(r3_val, shiftBits); | |
| 4708 alu_out = r3_val << shiftBits; | |
| 4709 } else if (op == SRAK) { | |
| 4710 alu_out = r3_val >> shiftBits; | |
| 4711 } | |
| 4712 set_low_register(r1, alu_out); | |
| 4713 SetS390ConditionCode<int32_t>(alu_out, 0); | |
| 4714 SetS390OverflowCode(isOF); | |
| 4715 break; | |
| 4716 } | |
| 4717 case SLAG: | |
| 4718 case SRAG: { | |
| 4719 // 64-bit non-clobbering shift-left/right arithmetic | |
| 4720 int r1 = rsyInstr->R1Value(); | |
| 4721 int r3 = rsyInstr->R3Value(); | |
| 4722 int b2 = rsyInstr->B2Value(); | |
| 4723 intptr_t d2 = rsyInstr->D2Value(); | |
| 4724 // only takes rightmost 6 bits | |
| 4725 int64_t b2_val = (b2 == 0) ? 0 : get_register(b2); | |
| 4726 int shiftBits = (b2_val + d2) & 0x3F; | |
| 4727 int64_t r3_val = get_register(r3); | |
| 4728 intptr_t alu_out = 0; | |
| 4729 bool isOF = false; | |
| 4730 if (op == SLAG) { | |
| 4731 isOF = CheckOverflowForShiftLeft(r3_val, shiftBits); | |
| 4732 alu_out = r3_val << shiftBits; | |
| 4733 } else if (op == SRAG) { | |
| 4734 alu_out = r3_val >> shiftBits; | |
| 4735 } | |
| 4736 set_register(r1, alu_out); | |
| 4737 SetS390ConditionCode<intptr_t>(alu_out, 0); | |
| 4738 SetS390OverflowCode(isOF); | |
| 4739 break; | |
| 4740 } | |
| 4741 case LMY: | |
| 4742 case STMY: { | |
| 4743 RSYInstruction* rsyInstr = reinterpret_cast<RSYInstruction*>(instr); | |
| 4744 // Load/Store Multiple (32) | |
| 4745 int r1 = rsyInstr->R1Value(); | |
| 4746 int r3 = rsyInstr->R3Value(); | |
| 4747 int b2 = rsyInstr->B2Value(); | |
| 4748 int offset = rsyInstr->D2Value(); | |
| 4749 | |
| 4750 // Regs roll around if r3 is less than r1. | |
| 4751 // Artifically increase r3 by 16 so we can calculate | |
| 4752 // the number of regs stored properly. | |
| 4753 if (r3 < r1) r3 += 16; | |
| 4754 | |
| 4755 int32_t b2_val = (b2 == 0) ? 0 : get_low_register<int32_t>(b2); | |
| 4756 | |
| 4757 // Store each register in ascending order. | |
| 4758 for (int i = 0; i <= r3 - r1; i++) { | |
| 4759 if (op == LMY) { | |
| 4760 int32_t value = ReadW(b2_val + offset + 4 * i, instr); | |
| 4761 set_low_register((r1 + i) % 16, value); | |
| 4762 } else { | |
| 4763 int32_t value = get_low_register<int32_t>((r1 + i) % 16); | |
| 4764 WriteW(b2_val + offset + 4 * i, value, instr); | |
| 4765 } | |
| 4766 } | |
| 4767 break; | |
| 4768 } | |
| 4769 case LT: | |
| 4770 case LTG: { | |
| 4771 // Load and Test (32/64) | |
| 4772 int r1 = rxyInstr->R1Value(); | |
| 4773 int x2 = rxyInstr->X2Value(); | |
| 4774 int b2 = rxyInstr->B2Value(); | |
| 4775 int d2 = rxyInstr->D2Value(); | |
| 4776 | |
| 4777 int64_t x2_val = (x2 == 0) ? 0 : get_register(x2); | |
| 4778 int64_t b2_val = (b2 == 0) ? 0 : get_register(b2); | |
| 4779 intptr_t addr = x2_val + b2_val + d2; | |
| 4780 | |
| 4781 if (op == LT) { | |
| 4782 int32_t value = ReadW(addr, instr); | |
| 4783 set_low_register(r1, value); | |
| 4784 SetS390ConditionCode<int32_t>(value, 0); | |
| 4785 } else if (op == LTG) { | |
| 4786 int64_t value = ReadDW(addr); | |
| 4787 set_register(r1, value); | |
| 4788 SetS390ConditionCode<int64_t>(value, 0); | |
| 4789 } | |
| 4790 break; | |
| 4791 } | |
| 4792 case LY: | |
| 4793 case LB: | |
| 4794 case LGB: | |
| 4795 case LG: | |
| 4796 case LGF: | |
| 4797 case LGH: | |
| 4798 case LLGF: | |
| 4799 case STG: | |
| 4800 case STY: | |
| 4801 case STCY: | |
| 4802 case STHY: | |
| 4803 case STEY: | |
| 4804 case LDY: | |
| 4805 case LHY: | |
| 4806 case STDY: | |
| 4807 case LEY: { | |
| 4808 // Miscellaneous Loads and Stores | |
| 4809 int r1 = rxyInstr->R1Value(); | |
| 4810 int x2 = rxyInstr->X2Value(); | |
| 4811 int b2 = rxyInstr->B2Value(); | |
| 4812 int d2 = rxyInstr->D2Value(); | |
| 4813 int64_t x2_val = (x2 == 0) ? 0 : get_register(x2); | |
| 4814 int64_t b2_val = (b2 == 0) ? 0 : get_register(b2); | |
| 4815 intptr_t addr = x2_val + b2_val + d2; | |
| 4816 if (op == LY) { | |
| 4817 uint32_t mem_val = ReadWU(addr, instr); | |
| 4818 set_low_register(r1, mem_val); | |
| 4819 } else if (op == LB) { | |
| 4820 int32_t mem_val = ReadB(addr); | |
| 4821 set_low_register(r1, mem_val); | |
| 4822 } else if (op == LGB) { | |
| 4823 int64_t mem_val = ReadB(addr); | |
| 4824 set_register(r1, mem_val); | |
| 4825 } else if (op == LG) { | |
| 4826 int64_t mem_val = ReadDW(addr); | |
| 4827 set_register(r1, mem_val); | |
| 4828 } else if (op == LGF) { | |
| 4829 int64_t mem_val = static_cast<int64_t>(ReadW(addr, instr)); | |
| 4830 set_register(r1, mem_val); | |
| 4831 } else if (op == LGH) { | |
| 4832 int64_t mem_val = static_cast<int64_t>(ReadH(addr, instr)); | |
| 4833 set_register(r1, mem_val); | |
| 4834 } else if (op == LLGF) { | |
| 4835 // int r1 = rreInst->R1Value(); | |
| 4836 // int r2 = rreInst->R2Value(); | |
| 4837 // int32_t r2_val = get_low_register<int32_t>(r2); | |
| 4838 // uint64_t r2_finalval = (static_cast<uint64_t>(r2_val) | |
| 4839 // & 0x00000000ffffffff); | |
| 4840 // set_register(r1, r2_finalval); | |
| 4841 // break; | |
| 4842 uint64_t mem_val = static_cast<uint64_t>(ReadWU(addr, instr)); | |
| 4843 set_register(r1, mem_val); | |
| 4844 } else if (op == LDY) { | |
| 4845 uint64_t dbl_val = *reinterpret_cast<uint64_t*>(addr); | |
| 4846 set_d_register(r1, dbl_val); | |
| 4847 } else if (op == STEY) { | |
| 4848 int64_t frs_val = get_d_register(r1) >> 32; | |
| 4849 WriteW(addr, static_cast<int32_t>(frs_val), instr); | |
| 4850 } else if (op == LEY) { | |
| 4851 float float_val = *reinterpret_cast<float*>(addr); | |
| 4852 set_d_register_from_float32(r1, float_val); | |
| 4853 } else if (op == STY) { | |
| 4854 uint32_t value = get_low_register<uint32_t>(r1); | |
| 4855 WriteW(addr, value, instr); | |
| 4856 } else if (op == STG) { | |
| 4857 uint64_t value = get_register(r1); | |
| 4858 WriteDW(addr, value); | |
| 4859 } else if (op == STDY) { | |
| 4860 int64_t frs_val = get_d_register(r1); | |
| 4861 WriteDW(addr, frs_val); | |
| 4862 } else if (op == STCY) { | |
| 4863 uint8_t value = get_low_register<uint32_t>(r1); | |
| 4864 WriteB(addr, value); | |
| 4865 } else if (op == STHY) { | |
| 4866 uint16_t value = get_low_register<uint32_t>(r1); | |
| 4867 WriteH(addr, value, instr); | |
| 4868 } else if (op == LHY) { | |
| 4869 int32_t result = static_cast<int32_t>(ReadH(addr, instr)); | |
| 4870 set_low_register(r1, result); | |
| 4871 } | |
| 4872 break; | |
| 4873 } | |
| 4874 case MVC: { | |
| 4875 // Move Character | |
| 4876 int b1 = ssInstr->B1Value(); | |
| 4877 intptr_t d1 = ssInstr->D1Value(); | |
| 4878 int b2 = ssInstr->B2Value(); | |
| 4879 intptr_t d2 = ssInstr->D2Value(); | |
| 4880 int length = ssInstr->Length(); | |
| 4881 int64_t b1_val = (b1 == 0) ? 0 : get_register(b1); | |
| 4882 int64_t b2_val = (b2 == 0) ? 0 : get_register(b2); | |
| 4883 intptr_t src_addr = b2_val + d2; | |
| 4884 intptr_t dst_addr = b1_val + d1; | |
| 4885 // remember that the length is the actual length - 1 | |
| 4886 for (int i = 0; i < length + 1; ++i) { | |
| 4887 WriteB(dst_addr++, ReadB(src_addr++)); | |
| 4888 } | |
| 4889 break; | |
| 4890 } | |
| 4891 case MVHI: { | |
| 4892 // Move Integer (32) | |
| 4893 int b1 = silInstr->B1Value(); | |
| 4894 intptr_t d1 = silInstr->D1Value(); | |
| 4895 int16_t i2 = silInstr->I2Value(); | |
| 4896 int64_t b1_val = (b1 == 0) ? 0 : get_register(b1); | |
| 4897 intptr_t src_addr = b1_val + d1; | |
| 4898 WriteW(src_addr, i2, instr); | |
| 4899 break; | |
| 4900 } | |
| 4901 case MVGHI: { | |
| 4902 // Move Integer (64) | |
| 4903 int b1 = silInstr->B1Value(); | |
| 4904 intptr_t d1 = silInstr->D1Value(); | |
| 4905 int16_t i2 = silInstr->I2Value(); | |
| 4906 int64_t b1_val = (b1 == 0) ? 0 : get_register(b1); | |
| 4907 intptr_t src_addr = b1_val + d1; | |
| 4908 WriteDW(src_addr, i2); | |
| 4909 break; | |
| 4910 } | |
| 4911 case LLH: | |
| 4912 case LLGH: { | |
| 4913 // Load Logical Halfworld | |
| 4914 int r1 = rxyInstr->R1Value(); | |
| 4915 int b2 = rxyInstr->B2Value(); | |
| 4916 int x2 = rxyInstr->X2Value(); | |
| 4917 int64_t b2_val = (b2 == 0) ? 0 : get_register(b2); | |
| 4918 int64_t x2_val = (x2 == 0) ? 0 : get_register(x2); | |
| 4919 intptr_t d2_val = rxyInstr->D2Value(); | |
| 4920 uint16_t mem_val = ReadHU(b2_val + d2_val + x2_val, instr); | |
| 4921 if (op == LLH) { | |
| 4922 set_low_register(r1, mem_val); | |
| 4923 } else if (op == LLGH) { | |
| 4924 set_register(r1, mem_val); | |
| 4925 } else { | |
| 4926 UNREACHABLE(); | |
| 4927 } | |
| 4928 break; | |
| 4929 } | |
| 4930 case LLC: | |
| 4931 case LLGC: { | |
| 4932 // Load Logical Character - loads a byte and zero extends. | |
| 4933 int r1 = rxyInstr->R1Value(); | |
| 4934 int b2 = rxyInstr->B2Value(); | |
| 4935 int x2 = rxyInstr->X2Value(); | |
| 4936 int64_t b2_val = (b2 == 0) ? 0 : get_register(b2); | |
| 4937 int64_t x2_val = (x2 == 0) ? 0 : get_register(x2); | |
| 4938 intptr_t d2_val = rxyInstr->D2Value(); | |
| 4939 uint8_t mem_val = ReadBU(b2_val + d2_val + x2_val); | |
| 4940 if (op == LLC) { | |
| 4941 set_low_register(r1, static_cast<uint32_t>(mem_val)); | |
| 4942 } else if (op == LLGC) { | |
| 4943 set_register(r1, static_cast<uint64_t>(mem_val)); | |
| 4944 } else { | |
| 4945 UNREACHABLE(); | |
| 4946 } | |
| 4947 break; | |
| 4948 } | |
| 4949 case XIHF: | |
| 4950 case XILF: { | |
| 4951 int r1 = rilInstr->R1Value(); | |
| 4952 uint32_t imm = rilInstr->I2UnsignedValue(); | |
| 4953 uint32_t alu_out = 0; | |
| 4954 if (op == XILF) { | |
| 4955 alu_out = get_low_register<uint32_t>(r1); | |
| 4956 alu_out = alu_out ^ imm; | |
| 4957 set_low_register(r1, alu_out); | |
| 4958 } else if (op == XIHF) { | |
| 4959 alu_out = get_high_register<uint32_t>(r1); | |
| 4960 alu_out = alu_out ^ imm; | |
| 4961 set_high_register(r1, alu_out); | |
| 4962 } else { | |
| 4963 UNREACHABLE(); | |
| 4964 } | |
| 4965 SetS390BitWiseConditionCode<uint32_t>(alu_out); | |
| 4966 break; | |
| 4967 } | |
| 4968 case RISBG: { | |
| 4969 // Rotate then insert selected bits | |
| 4970 int r1 = rieInstr->R1Value(); | |
| 4971 int r2 = rieInstr->R2Value(); | |
| 4972 // Starting Bit Position is Bits 2-7 of I3 field | |
| 4973 uint32_t start_bit = rieInstr->I3Value() & 0x3F; | |
| 4974 // Ending Bit Position is Bits 2-7 of I4 field | |
| 4975 uint32_t end_bit = rieInstr->I4Value() & 0x3F; | |
| 4976 // Shift Amount is Bits 2-7 of I5 field | |
| 4977 uint32_t shift_amount = rieInstr->I5Value() & 0x3F; | |
| 4978 // Zero out Remaining (unslected) bits if Bit 0 of I4 is 1. | |
| 4979 bool zero_remaining = (0 != (rieInstr->I4Value() & 0x80)); | |
| 4980 | |
| 4981 uint64_t src_val = get_register(r2); | |
| 4982 | |
| 4983 // Rotate Left by Shift Amount first | |
| 4984 uint64_t rotated_val = | |
| 4985 (src_val << shift_amount) | (src_val >> (64 - shift_amount)); | |
| 4986 int32_t width = end_bit - start_bit + 1; | |
| 4987 | |
| 4988 uint64_t selection_mask = 0; | |
| 4989 if (width < 64) { | |
| 4990 selection_mask = (static_cast<uint64_t>(1) << width) - 1; | |
| 4991 } else { | |
| 4992 selection_mask = static_cast<uint64_t>(static_cast<int64_t>(-1)); | |
| 4993 } | |
| 4994 selection_mask = selection_mask << (63 - end_bit); | |
| 4995 | |
| 4996 uint64_t selected_val = rotated_val & selection_mask; | |
| 4997 | |
| 4998 if (!zero_remaining) { | |
| 4999 // Merged the unselected bits from the original value | |
| 5000 selected_val = (src_val & ~selection_mask) | selected_val; | |
| 5001 } | |
| 5002 | |
| 5003 // Condition code is set by treating result as 64-bit signed int | |
| 5004 SetS390ConditionCode<int64_t>(selected_val, 0); | |
| 5005 set_register(r1, selected_val); | |
| 5006 break; | |
| 5007 } | |
| 5008 default: | |
| 5009 return DecodeSixByteArithmetic(instr); | |
| 5010 } | |
| 5011 return true; | |
| 5012 } | |
| 5013 | |
| 5014 void Simulator::DecodeSixByteBitShift(Instruction* instr) { | |
| 5015 Opcode op = instr->S390OpcodeValue(); | |
| 5016 | |
| 5017 // Pre-cast instruction to various types | |
| 5018 | |
| 5019 RSYInstruction* rsyInstr = reinterpret_cast<RSYInstruction*>(instr); | |
| 5020 | |
| 5021 switch (op) { | |
| 5022 case SLLK: | |
| 5023 case RLL: | |
| 5024 case SRLK: { | |
| 5025 // For SLLK/SRLL, the 32-bit third operand is shifted the number | |
| 5026 // of bits specified by the second-operand address, and the result is | |
| 5027 // placed at the first-operand location. Except for when the R1 and R3 | |
| 5028 // fields designate the same register, the third operand remains | |
| 5029 // unchanged in general register R3. | |
| 5030 int r1 = rsyInstr->R1Value(); | |
| 5031 int r3 = rsyInstr->R3Value(); | |
| 5032 int b2 = rsyInstr->B2Value(); | |
| 5033 intptr_t d2 = rsyInstr->D2Value(); | |
| 5034 // only takes rightmost 6 bits | |
| 5035 int64_t b2_val = (b2 == 0) ? 0 : get_register(b2); | |
| 5036 int shiftBits = (b2_val + d2) & 0x3F; | |
| 5037 // unsigned | |
| 5038 uint32_t r3_val = get_low_register<uint32_t>(r3); | |
| 5039 uint32_t alu_out = 0; | |
| 5040 if (SLLK == op) { | |
| 5041 alu_out = r3_val << shiftBits; | |
| 5042 } else if (SRLK == op) { | |
| 5043 alu_out = r3_val >> shiftBits; | |
| 5044 } else if (RLL == op) { | |
| 5045 uint32_t rotateBits = r3_val >> (32 - shiftBits); | |
| 5046 alu_out = (r3_val << shiftBits) | (rotateBits); | |
| 5047 } else { | |
| 5048 UNREACHABLE(); | |
| 5049 } | |
| 5050 set_low_register(r1, alu_out); | |
| 5051 break; | |
| 5052 } | |
| 5053 case SLLG: | |
| 5054 case RLLG: | |
| 5055 case SRLG: { | |
| 5056 // For SLLG/SRLG, the 64-bit third operand is shifted the number | |
| 5057 // of bits specified by the second-operand address, and the result is | |
| 5058 // placed at the first-operand location. Except for when the R1 and R3 | |
| 5059 // fields designate the same register, the third operand remains | |
| 5060 // unchanged in general register R3. | |
| 5061 int r1 = rsyInstr->R1Value(); | |
| 5062 int r3 = rsyInstr->R3Value(); | |
| 5063 int b2 = rsyInstr->B2Value(); | |
| 5064 intptr_t d2 = rsyInstr->D2Value(); | |
| 5065 // only takes rightmost 6 bits | |
| 5066 int64_t b2_val = (b2 == 0) ? 0 : get_register(b2); | |
| 5067 int shiftBits = (b2_val + d2) & 0x3F; | |
| 5068 // unsigned | |
| 5069 uint64_t r3_val = get_register(r3); | |
| 5070 uint64_t alu_out = 0; | |
| 5071 if (op == SLLG) { | |
| 5072 alu_out = r3_val << shiftBits; | |
| 5073 } else if (op == SRLG) { | |
| 5074 alu_out = r3_val >> shiftBits; | |
| 5075 } else if (op == RLLG) { | |
| 5076 uint64_t rotateBits = r3_val >> (64 - shiftBits); | |
| 5077 alu_out = (r3_val << shiftBits) | (rotateBits); | |
| 5078 } else { | |
| 5079 UNREACHABLE(); | |
| 5080 } | |
| 5081 set_register(r1, alu_out); | |
| 5082 break; | |
| 5083 } | |
| 5084 default: | |
| 5085 UNREACHABLE(); | |
| 5086 } | |
| 5087 } | |
| 5088 | |
| 5089 /** | |
| 5090 * Decodes and simulates six byte arithmetic instructions | |
| 5091 */ | |
| 5092 bool Simulator::DecodeSixByteArithmetic(Instruction* instr) { | |
| 5093 Opcode op = instr->S390OpcodeValue(); | |
| 5094 | |
| 5095 // Pre-cast instruction to various types | |
| 5096 SIYInstruction* siyInstr = reinterpret_cast<SIYInstruction*>(instr); | |
| 5097 | |
| 5098 switch (op) { | |
| 5099 case CDB: | |
| 5100 case ADB: | |
| 5101 case SDB: | |
| 5102 case MDB: | |
| 5103 case DDB: | |
| 5104 case SQDB: { | |
| 5105 RXEInstruction* rxeInstr = reinterpret_cast<RXEInstruction*>(instr); | |
| 5106 int b2 = rxeInstr->B2Value(); | |
| 5107 int x2 = rxeInstr->X2Value(); | |
| 5108 int64_t b2_val = (b2 == 0) ? 0 : get_register(b2); | |
| 5109 int64_t x2_val = (x2 == 0) ? 0 : get_register(x2); | |
| 5110 intptr_t d2_val = rxeInstr->D2Value(); | |
| 5111 double r1_val = get_double_from_d_register(rxeInstr->R1Value()); | |
| 5112 double dbl_val = ReadDouble(b2_val + x2_val + d2_val); | |
| 5113 | |
| 5114 switch (op) { | |
| 5115 case CDB: | |
| 5116 SetS390ConditionCode<double>(r1_val, dbl_val); | |
| 5117 break; | |
| 5118 case ADB: | |
| 5119 r1_val += dbl_val; | |
| 5120 set_d_register_from_double(r1, r1_val); | |
| 5121 SetS390ConditionCode<double>(r1_val, 0); | |
| 5122 break; | |
| 5123 case SDB: | |
| 5124 r1_val -= dbl_val; | |
| 5125 set_d_register_from_double(r1, r1_val); | |
| 5126 SetS390ConditionCode<double>(r1_val, 0); | |
| 5127 break; | |
| 5128 case MDB: | |
| 5129 r1_val *= dbl_val; | |
| 5130 set_d_register_from_double(r1, r1_val); | |
| 5131 SetS390ConditionCode<double>(r1_val, 0); | |
| 5132 break; | |
| 5133 case DDB: | |
| 5134 r1_val /= dbl_val; | |
| 5135 set_d_register_from_double(r1, r1_val); | |
| 5136 SetS390ConditionCode<double>(r1_val, 0); | |
| 5137 break; | |
| 5138 case SQDB: | |
| 5139 r1_val = std::sqrt(dbl_val); | |
| 5140 set_d_register_from_double(r1, r1_val); | |
| 5141 default: | |
| 5142 UNREACHABLE(); | |
| 5143 break; | |
| 5144 } | |
| 5145 break; | |
| 5146 } | |
| 5147 case LRV: | |
| 5148 case LRVH: | |
| 5149 case STRV: | |
| 5150 case STRVH: { | |
| 5151 RXYInstruction* rxyInstr = reinterpret_cast<RXYInstruction*>(instr); | |
| 5152 int r1 = rxyInstr->R1Value(); | |
| 5153 int x2 = rxyInstr->X2Value(); | |
| 5154 int b2 = rxyInstr->B2Value(); | |
| 5155 int d2 = rxyInstr->D2Value(); | |
| 5156 int32_t r1_val = get_low_register<int32_t>(r1); | |
| 5157 int64_t x2_val = (x2 == 0) ? 0 : get_register(x2); | |
| 5158 int64_t b2_val = (b2 == 0) ? 0 : get_register(b2); | |
| 5159 intptr_t mem_addr = b2_val + x2_val + d2; | |
| 5160 | |
| 5161 if (op == LRVH) { | |
| 5162 int16_t mem_val = ReadH(mem_addr, instr); | |
| 5163 int32_t result = ByteReverse(mem_val) & 0x0000ffff; | |
| 5164 result |= r1_val & 0xffff0000; | |
| 5165 set_low_register(r1, result); | |
| 5166 } else if (op == LRV) { | |
| 5167 int32_t mem_val = ReadW(mem_addr, instr); | |
| 5168 set_low_register(r1, ByteReverse(mem_val)); | |
| 5169 } else if (op == STRVH) { | |
| 5170 int16_t result = static_cast<int16_t>(r1_val >> 16); | |
| 5171 WriteH(mem_addr, ByteReverse(result), instr); | |
| 5172 } else if (op == STRV) { | |
| 5173 WriteW(mem_addr, ByteReverse(r1_val), instr); | |
| 5174 } | |
| 5175 | |
| 5176 break; | |
| 5177 } | |
| 5178 case AHIK: | |
| 5179 case AGHIK: { | |
| 5180 // Non-clobbering Add Halfword Immediate | |
| 5181 RIEInstruction* rieInst = reinterpret_cast<RIEInstruction*>(instr); | |
| 5182 int r1 = rieInst->R1Value(); | |
| 5183 int r2 = rieInst->R2Value(); | |
| 5184 bool isOF = false; | |
| 5185 if (AHIK == op) { | |
| 5186 // 32-bit Add | |
| 5187 int32_t r2_val = get_low_register<int32_t>(r2); | |
| 5188 int32_t imm = rieInst->I6Value(); | |
| 5189 isOF = CheckOverflowForIntAdd(r2_val, imm, int32_t); | |
| 5190 set_low_register(r1, r2_val + imm); | |
| 5191 SetS390ConditionCode<int32_t>(r2_val + imm, 0); | |
| 5192 } else if (AGHIK == op) { | |
| 5193 // 64-bit Add | |
| 5194 int64_t r2_val = get_register(r2); | |
| 5195 int64_t imm = static_cast<int64_t>(rieInst->I6Value()); | |
| 5196 isOF = CheckOverflowForIntAdd(r2_val, imm, int64_t); | |
| 5197 set_register(r1, r2_val + imm); | |
| 5198 SetS390ConditionCode<int64_t>(r2_val + imm, 0); | |
| 5199 } | |
| 5200 SetS390OverflowCode(isOF); | |
| 5201 break; | |
| 5202 } | |
| 5203 case ALFI: | |
| 5204 case SLFI: { | |
| 5205 RILInstruction* rilInstr = reinterpret_cast<RILInstruction*>(instr); | |
| 5206 int r1 = rilInstr->R1Value(); | |
| 5207 uint32_t imm = rilInstr->I2UnsignedValue(); | |
| 5208 uint32_t alu_out = get_low_register<uint32_t>(r1); | |
| 5209 if (op == ALFI) { | |
| 5210 alu_out += imm; | |
| 5211 } else if (op == SLFI) { | |
| 5212 alu_out -= imm; | |
| 5213 } | |
| 5214 SetS390ConditionCode<uint32_t>(alu_out, 0); | |
| 5215 set_low_register(r1, alu_out); | |
| 5216 break; | |
| 5217 } | |
| 5218 case ML: { | |
| 5219 UNIMPLEMENTED(); | |
| 5220 break; | |
| 5221 } | |
| 5222 case AY: | |
| 5223 case SY: | |
| 5224 case NY: | |
| 5225 case OY: | |
| 5226 case XY: | |
| 5227 case CY: { | |
| 5228 RXYInstruction* rxyInstr = reinterpret_cast<RXYInstruction*>(instr); | |
| 5229 int r1 = rxyInstr->R1Value(); | |
| 5230 int x2 = rxyInstr->X2Value(); | |
| 5231 int b2 = rxyInstr->B2Value(); | |
| 5232 int d2 = rxyInstr->D2Value(); | |
| 5233 int64_t x2_val = (x2 == 0) ? 0 : get_register(x2); | |
| 5234 int64_t b2_val = (b2 == 0) ? 0 : get_register(b2); | |
| 5235 int32_t alu_out = get_low_register<int32_t>(r1); | |
| 5236 int32_t mem_val = ReadW(b2_val + x2_val + d2, instr); | |
| 5237 bool isOF = false; | |
| 5238 if (op == AY) { | |
| 5239 isOF = CheckOverflowForIntAdd(alu_out, mem_val, int32_t); | |
| 5240 alu_out += mem_val; | |
| 5241 SetS390ConditionCode<int32_t>(alu_out, 0); | |
| 5242 SetS390OverflowCode(isOF); | |
| 5243 } else if (op == SY) { | |
| 5244 isOF = CheckOverflowForIntSub(alu_out, mem_val, int32_t); | |
| 5245 alu_out -= mem_val; | |
| 5246 SetS390ConditionCode<int32_t>(alu_out, 0); | |
| 5247 SetS390OverflowCode(isOF); | |
| 5248 } else if (op == NY) { | |
| 5249 alu_out &= mem_val; | |
| 5250 SetS390BitWiseConditionCode<uint32_t>(alu_out); | |
| 5251 } else if (op == OY) { | |
| 5252 alu_out |= mem_val; | |
| 5253 SetS390BitWiseConditionCode<uint32_t>(alu_out); | |
| 5254 } else if (op == XY) { | |
| 5255 alu_out ^= mem_val; | |
| 5256 SetS390BitWiseConditionCode<uint32_t>(alu_out); | |
| 5257 } else if (op == CY) { | |
| 5258 SetS390ConditionCode<int32_t>(alu_out, mem_val); | |
| 5259 } | |
| 5260 if (op != CY) { | |
| 5261 set_low_register(r1, alu_out); | |
| 5262 } | |
| 5263 break; | |
| 5264 } | |
| 5265 case AHY: | |
| 5266 case SHY: { | |
| 5267 RXYInstruction* rxyInstr = reinterpret_cast<RXYInstruction*>(instr); | |
| 5268 int32_t r1_val = get_low_register<int32_t>(rxyInstr->R1Value()); | |
| 5269 int b2 = rxyInstr->B2Value(); | |
| 5270 int x2 = rxyInstr->X2Value(); | |
| 5271 int64_t b2_val = (b2 == 0) ? 0 : get_register(b2); | |
| 5272 int64_t x2_val = (x2 == 0) ? 0 : get_register(x2); | |
| 5273 intptr_t d2_val = rxyInstr->D2Value(); | |
| 5274 int32_t mem_val = | |
| 5275 static_cast<int32_t>(ReadH(b2_val + d2_val + x2_val, instr)); | |
| 5276 int32_t alu_out = 0; | |
| 5277 bool isOF = false; | |
| 5278 switch (op) { | |
| 5279 case AHY: | |
| 5280 alu_out = r1_val + mem_val; | |
| 5281 isOF = CheckOverflowForIntAdd(r1_val, mem_val, int32_t); | |
| 5282 break; | |
| 5283 case SHY: | |
| 5284 alu_out = r1_val - mem_val; | |
| 5285 isOF = CheckOverflowForIntSub(r1_val, mem_val, int64_t); | |
| 5286 break; | |
| 5287 default: | |
| 5288 UNREACHABLE(); | |
| 5289 break; | |
| 5290 } | |
| 5291 set_low_register(r1, alu_out); | |
| 5292 SetS390ConditionCode<int32_t>(alu_out, 0); | |
| 5293 SetS390OverflowCode(isOF); | |
| 5294 break; | |
| 5295 } | |
| 5296 case AG: | |
| 5297 case SG: | |
| 5298 case NG: | |
| 5299 case OG: | |
| 5300 case XG: | |
| 5301 case CG: | |
| 5302 case CLG: { | |
| 5303 RXYInstruction* rxyInstr = reinterpret_cast<RXYInstruction*>(instr); | |
| 5304 int r1 = rxyInstr->R1Value(); | |
| 5305 int x2 = rxyInstr->X2Value(); | |
| 5306 int b2 = rxyInstr->B2Value(); | |
| 5307 int d2 = rxyInstr->D2Value(); | |
| 5308 int64_t x2_val = (x2 == 0) ? 0 : get_register(x2); | |
| 5309 int64_t b2_val = (b2 == 0) ? 0 : get_register(b2); | |
| 5310 int64_t alu_out = get_register(r1); | |
| 5311 int64_t mem_val = ReadDW(b2_val + x2_val + d2); | |
| 5312 | |
| 5313 switch (op) { | |
| 5314 case AG: { | |
| 5315 alu_out += mem_val; | |
| 5316 SetS390ConditionCode<int32_t>(alu_out, 0); | |
| 5317 break; | |
| 5318 } | |
| 5319 case SG: { | |
| 5320 alu_out -= mem_val; | |
| 5321 SetS390ConditionCode<int32_t>(alu_out, 0); | |
| 5322 break; | |
| 5323 } | |
| 5324 case NG: { | |
| 5325 alu_out &= mem_val; | |
| 5326 SetS390BitWiseConditionCode<uint32_t>(alu_out); | |
| 5327 break; | |
| 5328 } | |
| 5329 case OG: { | |
| 5330 alu_out |= mem_val; | |
| 5331 SetS390BitWiseConditionCode<uint32_t>(alu_out); | |
| 5332 break; | |
| 5333 } | |
| 5334 case XG: { | |
| 5335 alu_out ^= mem_val; | |
| 5336 SetS390BitWiseConditionCode<uint32_t>(alu_out); | |
| 5337 break; | |
| 5338 } | |
| 5339 case CG: { | |
| 5340 SetS390ConditionCode<int64_t>(alu_out, mem_val); | |
| 5341 break; | |
| 5342 } | |
| 5343 case CLG: { | |
| 5344 SetS390ConditionCode<uint64_t>(alu_out, mem_val); | |
| 5345 break; | |
| 5346 } | |
| 5347 default: { | |
| 5348 DCHECK(false); | |
| 5349 break; | |
| 5350 } | |
| 5351 } | |
| 5352 | |
| 5353 if (op != CG) { | |
| 5354 set_register(r1, alu_out); | |
| 5355 } | |
| 5356 break; | |
| 5357 } | |
| 5358 case ALY: | |
| 5359 case SLY: | |
| 5360 case CLY: { | |
| 5361 RXYInstruction* rxyInstr = reinterpret_cast<RXYInstruction*>(instr); | |
| 5362 int r1 = rxyInstr->R1Value(); | |
| 5363 int x2 = rxyInstr->X2Value(); | |
| 5364 int b2 = rxyInstr->B2Value(); | |
| 5365 int d2 = rxyInstr->D2Value(); | |
| 5366 int64_t x2_val = (x2 == 0) ? 0 : get_register(x2); | |
| 5367 int64_t b2_val = (b2 == 0) ? 0 : get_register(b2); | |
| 5368 uint32_t alu_out = get_low_register<uint32_t>(r1); | |
| 5369 uint32_t mem_val = ReadWU(b2_val + x2_val + d2, instr); | |
| 5370 | |
| 5371 if (op == ALY) { | |
| 5372 alu_out += mem_val; | |
| 5373 set_low_register(r1, alu_out); | |
| 5374 SetS390ConditionCode<uint32_t>(alu_out, 0); | |
| 5375 } else if (op == SLY) { | |
| 5376 alu_out -= mem_val; | |
| 5377 set_low_register(r1, alu_out); | |
| 5378 SetS390ConditionCode<uint32_t>(alu_out, 0); | |
| 5379 } else if (op == CLY) { | |
| 5380 SetS390ConditionCode<uint32_t>(alu_out, mem_val); | |
| 5381 } | |
| 5382 break; | |
| 5383 } | |
| 5384 case AGFI: | |
| 5385 case AFI: { | |
| 5386 // Clobbering Add Word Immediate | |
| 5387 RILInstruction* rilInstr = reinterpret_cast<RILInstruction*>(instr); | |
| 5388 int32_t r1 = rilInstr->R1Value(); | |
| 5389 bool isOF = false; | |
| 5390 if (AFI == op) { | |
| 5391 // 32-bit Add (Register + 32-bit Immediate) | |
| 5392 int32_t r1_val = get_low_register<int32_t>(r1); | |
| 5393 int32_t i2 = rilInstr->I2Value(); | |
| 5394 isOF = CheckOverflowForIntAdd(r1_val, i2, int32_t); | |
| 5395 int32_t alu_out = r1_val + i2; | |
| 5396 set_low_register(r1, alu_out); | |
| 5397 SetS390ConditionCode<int32_t>(alu_out, 0); | |
| 5398 } else if (AGFI == op) { | |
| 5399 // 64-bit Add (Register + 32-bit Imm) | |
| 5400 int64_t r1_val = get_register(r1); | |
| 5401 int64_t i2 = static_cast<int64_t>(rilInstr->I2Value()); | |
| 5402 isOF = CheckOverflowForIntAdd(r1_val, i2, int64_t); | |
| 5403 int64_t alu_out = r1_val + i2; | |
| 5404 set_register(r1, alu_out); | |
| 5405 SetS390ConditionCode<int64_t>(alu_out, 0); | |
| 5406 } | |
| 5407 SetS390OverflowCode(isOF); | |
| 5408 break; | |
| 5409 } | |
| 5410 case ASI: { | |
| 5411 // TODO(bcleung): Change all fooInstr->I2Value() to template functions. | |
| 5412 // The below static cast to 8 bit and then to 32 bit is necessary | |
| 5413 // because siyInstr->I2Value() returns a uint8_t, which a direct | |
| 5414 // cast to int32_t could incorrectly interpret. | |
| 5415 int8_t i2_8bit = static_cast<int8_t>(siyInstr->I2Value()); | |
| 5416 int32_t i2 = static_cast<int32_t>(i2_8bit); | |
| 5417 int b1 = siyInstr->B1Value(); | |
| 5418 intptr_t b1_val = (b1 == 0) ? 0 : get_register(b1); | |
| 5419 | |
| 5420 int d1_val = siyInstr->D1Value(); | |
| 5421 intptr_t addr = b1_val + d1_val; | |
| 5422 | |
| 5423 int32_t mem_val = ReadW(addr, instr); | |
| 5424 bool isOF = CheckOverflowForIntAdd(mem_val, i2, int32_t); | |
| 5425 int32_t alu_out = mem_val + i2; | |
| 5426 SetS390ConditionCode<int32_t>(alu_out, 0); | |
| 5427 SetS390OverflowCode(isOF); | |
| 5428 WriteW(addr, alu_out, instr); | |
| 5429 break; | |
| 5430 } | |
| 5431 case AGSI: { | |
| 5432 // TODO(bcleung): Change all fooInstr->I2Value() to template functions. | |
| 5433 // The below static cast to 8 bit and then to 32 bit is necessary | |
| 5434 // because siyInstr->I2Value() returns a uint8_t, which a direct | |
| 5435 // cast to int32_t could incorrectly interpret. | |
| 5436 int8_t i2_8bit = static_cast<int8_t>(siyInstr->I2Value()); | |
| 5437 int64_t i2 = static_cast<int64_t>(i2_8bit); | |
| 5438 int b1 = siyInstr->B1Value(); | |
| 5439 intptr_t b1_val = (b1 == 0) ? 0 : get_register(b1); | |
| 5440 | |
| 5441 int d1_val = siyInstr->D1Value(); | |
| 5442 intptr_t addr = b1_val + d1_val; | |
| 5443 | |
| 5444 int64_t mem_val = ReadDW(addr); | |
| 5445 int isOF = CheckOverflowForIntAdd(mem_val, i2, int64_t); | |
| 5446 int64_t alu_out = mem_val + i2; | |
| 5447 SetS390ConditionCode<uint64_t>(alu_out, 0); | |
| 5448 SetS390OverflowCode(isOF); | |
| 5449 WriteDW(addr, alu_out); | |
| 5450 break; | |
| 5451 } | |
| 5452 case AGF: | |
| 5453 case SGF: | |
| 5454 case ALG: | |
| 5455 case SLG: { | |
| 5456 #ifndef V8_TARGET_ARCH_S390X | |
| 5457 DCHECK(false); | |
| 5458 #endif | |
| 5459 RXYInstruction* rxyInstr = reinterpret_cast<RXYInstruction*>(instr); | |
| 5460 int r1 = rxyInstr->R1Value(); | |
| 5461 uint64_t r1_val = get_register(rxyInstr->R1Value()); | |
| 5462 int b2 = rxyInstr->B2Value(); | |
| 5463 int x2 = rxyInstr->X2Value(); | |
| 5464 int64_t b2_val = (b2 == 0) ? 0 : get_register(b2); | |
| 5465 int64_t x2_val = (x2 == 0) ? 0 : get_register(x2); | |
| 5466 intptr_t d2_val = rxyInstr->D2Value(); | |
| 5467 uint64_t alu_out = r1_val; | |
| 5468 if (op == ALG) { | |
| 5469 uint64_t mem_val = | |
| 5470 static_cast<uint64_t>(ReadDW(b2_val + d2_val + x2_val)); | |
| 5471 alu_out += mem_val; | |
| 5472 SetS390ConditionCode<uint64_t>(alu_out, 0); | |
| 5473 } else if (op == SLG) { | |
| 5474 uint64_t mem_val = | |
| 5475 static_cast<uint64_t>(ReadDW(b2_val + d2_val + x2_val)); | |
| 5476 alu_out -= mem_val; | |
| 5477 SetS390ConditionCode<uint64_t>(alu_out, 0); | |
| 5478 } else if (op == AGF) { | |
| 5479 uint32_t mem_val = ReadW(b2_val + d2_val + x2_val, instr); | |
| 5480 alu_out += mem_val; | |
| 5481 SetS390ConditionCode<int64_t>(alu_out, 0); | |
| 5482 } else if (op == SGF) { | |
| 5483 uint32_t mem_val = ReadW(b2_val + d2_val + x2_val, instr); | |
| 5484 alu_out -= mem_val; | |
| 5485 SetS390ConditionCode<int64_t>(alu_out, 0); | |
| 5486 } else { | |
| 5487 DCHECK(false); | |
| 5488 } | |
| 5489 set_register(r1, alu_out); | |
| 5490 break; | |
| 5491 } | |
| 5492 case ALGFI: | |
| 5493 case SLGFI: { | |
| 5494 #ifndef V8_TARGET_ARCH_S390X | |
| 5495 // should only be called on 64bit | |
| 5496 DCHECK(false); | |
| 5497 #endif | |
| 5498 RILInstruction* rilInstr = reinterpret_cast<RILInstruction*>(instr); | |
| 5499 int r1 = rilInstr->R1Value(); | |
| 5500 uint32_t i2 = rilInstr->I2UnsignedValue(); | |
| 5501 uint64_t r1_val = (uint64_t)(get_register(r1)); | |
| 5502 uint64_t alu_out; | |
| 5503 if (op == ALGFI) | |
| 5504 alu_out = r1_val + i2; | |
| 5505 else | |
| 5506 alu_out = r1_val - i2; | |
| 5507 set_register(r1, (intptr_t)alu_out); | |
| 5508 SetS390ConditionCode<uint64_t>(alu_out, 0); | |
| 5509 break; | |
| 5510 } | |
| 5511 case MSY: | |
| 5512 case MSG: { | |
| 5513 RXYInstruction* rxyInstr = reinterpret_cast<RXYInstruction*>(instr); | |
| 5514 int r1 = rxyInstr->R1Value(); | |
| 5515 int b2 = rxyInstr->B2Value(); | |
| 5516 int x2 = rxyInstr->X2Value(); | |
| 5517 int64_t b2_val = (b2 == 0) ? 0 : get_register(b2); | |
| 5518 int64_t x2_val = (x2 == 0) ? 0 : get_register(x2); | |
| 5519 intptr_t d2_val = rxyInstr->D2Value(); | |
| 5520 if (op == MSY) { | |
| 5521 int32_t mem_val = ReadW(b2_val + d2_val + x2_val, instr); | |
| 5522 int32_t r1_val = get_low_register<int32_t>(r1); | |
| 5523 set_low_register(r1, mem_val * r1_val); | |
| 5524 } else if (op == MSG) { | |
| 5525 int64_t mem_val = ReadDW(b2_val + d2_val + x2_val); | |
| 5526 int64_t r1_val = get_register(r1); | |
| 5527 set_register(r1, mem_val * r1_val); | |
| 5528 } else { | |
| 5529 UNREACHABLE(); | |
| 5530 } | |
| 5531 break; | |
| 5532 } | |
| 5533 case MSFI: | |
| 5534 case MSGFI: { | |
| 5535 RILInstruction* rilinst = reinterpret_cast<RILInstruction*>(instr); | |
| 5536 int r1 = rilinst->R1Value(); | |
| 5537 int32_t i2 = rilinst->I2Value(); | |
| 5538 if (op == MSFI) { | |
| 5539 int32_t alu_out = get_low_register<int32_t>(r1); | |
| 5540 alu_out = alu_out * i2; | |
| 5541 set_low_register(r1, alu_out); | |
| 5542 } else if (op == MSGFI) { | |
| 5543 int64_t alu_out = get_register(r1); | |
| 5544 alu_out = alu_out * i2; | |
| 5545 set_register(r1, alu_out); | |
| 5546 } else { | |
| 5547 UNREACHABLE(); | |
| 5548 } | |
| 5549 break; | |
| 5550 } | |
| 5551 default: | |
| 5552 UNREACHABLE(); | |
| 5553 return false; | |
| 5554 } | |
| 5555 return true; | |
| 5556 } | |
| 5557 | |
| 5558 int16_t Simulator::ByteReverse(int16_t hword) { | 2415 int16_t Simulator::ByteReverse(int16_t hword) { |
| 5559 #if defined(__GNUC__) | 2416 #if defined(__GNUC__) |
| 5560 return __builtin_bswap16(hword); | 2417 return __builtin_bswap16(hword); |
| 5561 #else | 2418 #else |
| 5562 return (hword << 8) | ((hword >> 8) & 0x00ff); | 2419 return (hword << 8) | ((hword >> 8) & 0x00ff); |
| 5563 #endif | 2420 #endif |
| 5564 } | 2421 } |
| 5565 | 2422 |
| 5566 int32_t Simulator::ByteReverse(int32_t word) { | 2423 int32_t Simulator::ByteReverse(int32_t word) { |
| 5567 #if defined(__GNUC__) | 2424 #if defined(__GNUC__) |
| 5568 return __builtin_bswap32(word); | 2425 return __builtin_bswap32(word); |
| 5569 #else | 2426 #else |
| 5570 int32_t result = word << 24; | 2427 int32_t result = word << 24; |
| 5571 result |= (word << 8) & 0x00ff0000; | 2428 result |= (word << 8) & 0x00ff0000; |
| 5572 result |= (word >> 8) & 0x0000ff00; | 2429 result |= (word >> 8) & 0x0000ff00; |
| 5573 result |= (word >> 24) & 0x00000ff; | 2430 result |= (word >> 24) & 0x00000ff; |
| 5574 return result; | 2431 return result; |
| 5575 #endif | 2432 #endif |
| 5576 } | 2433 } |
| 5577 | 2434 |
| 5578 int64_t Simulator::ByteReverse(int64_t dword) { | 2435 int64_t Simulator::ByteReverse(int64_t dword) { |
| 5579 #if defined(__GNUC__) | 2436 #if defined(__GNUC__) |
| 5580 return __builtin_bswap64(dword); | 2437 return __builtin_bswap64(dword); |
| 5581 #else | 2438 #else |
| 5582 #error unsupport __builtin_bswap64 | 2439 #error unsupport __builtin_bswap64 |
| 5583 #endif | 2440 #endif |
| 5584 } | 2441 } |
| 5585 | 2442 |
| 5586 int Simulator::DecodeInstructionOriginal(Instruction* instr) { | |
| 5587 int instrLength = instr->InstructionLength(); | |
| 5588 bool processed = true; | |
| 5589 if (instrLength == 2) | |
| 5590 processed = DecodeTwoByte(instr); | |
| 5591 else if (instrLength == 4) | |
| 5592 processed = DecodeFourByte(instr); | |
| 5593 else if (instrLength == 6) | |
| 5594 processed = DecodeSixByte(instr); | |
| 5595 return instrLength; | |
| 5596 } | |
| 5597 | |
| 5598 int Simulator::DecodeInstruction(Instruction* instr) { | 2443 int Simulator::DecodeInstruction(Instruction* instr) { |
| 5599 Opcode op = instr->S390OpcodeValue(); | 2444 Opcode op = instr->S390OpcodeValue(); |
| 5600 DCHECK(EvalTable[op] != NULL); | 2445 DCHECK(EvalTable[op] != NULL); |
| 5601 return (this->*EvalTable[op])(instr); | 2446 return (this->*EvalTable[op])(instr); |
| 5602 } | 2447 } |
| 5603 | 2448 |
| 5604 // Executes the current instruction. | 2449 // Executes the current instruction. |
| 5605 void Simulator::ExecuteInstruction(Instruction* instr, bool auto_incr_pc) { | 2450 void Simulator::ExecuteInstruction(Instruction* instr, bool auto_incr_pc) { |
| 5606 icount_++; | 2451 icount_++; |
| 5607 | 2452 |
| (...skipping 7361 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 12969 return 0; | 9814 return 0; |
| 12970 } | 9815 } |
| 12971 | 9816 |
| 12972 #undef EVALUATE | 9817 #undef EVALUATE |
| 12973 | 9818 |
| 12974 } // namespace internal | 9819 } // namespace internal |
| 12975 } // namespace v8 | 9820 } // namespace v8 |
| 12976 | 9821 |
| 12977 #endif // USE_SIMULATOR | 9822 #endif // USE_SIMULATOR |
| 12978 #endif // V8_TARGET_ARCH_S390 | 9823 #endif // V8_TARGET_ARCH_S390 |
| OLD | NEW |