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 |