| Index: src/s390/simulator-s390.cc
|
| diff --git a/src/s390/simulator-s390.cc b/src/s390/simulator-s390.cc
|
| index f611d24cb7b5b188a0410894bb7fc27a82daece0..e819556048d7652b7a02dacd9decfd1a750ff4a9 100644
|
| --- a/src/s390/simulator-s390.cc
|
| +++ b/src/s390/simulator-s390.cc
|
| @@ -5900,6 +5900,16 @@ uintptr_t Simulator::PopAddress() {
|
|
|
| #define AS(type) reinterpret_cast<type*>(instr)
|
|
|
| +#define DECODE_RIL_A_INSTRUCTION(r1, i2) \
|
| + int r1 = AS(RILInstruction)->R1Value(); \
|
| + uint32_t i2 = AS(RILInstruction)->I2UnsignedValue(); \
|
| + int length = 6;
|
| +
|
| +#define DECODE_RIL_B_INSTRUCTION(r1, i2) \
|
| + int r1 = AS(RILInstruction)->R1Value(); \
|
| + int32_t i2 = AS(RILInstruction)->I2Value(); \
|
| + int length = 6;
|
| +
|
| #define DECODE_RIL_C_INSTRUCTION(m1, ri2) \
|
| Condition m1 = static_cast<Condition>(AS(RILInstruction)->R1Value()); \
|
| uint64_t ri2 = AS(RILInstruction)->I2Value(); \
|
| @@ -5912,6 +5922,32 @@ uintptr_t Simulator::PopAddress() {
|
| int d2 = AS(RXYInstruction)->D2Value(); \
|
| int length = 6;
|
|
|
| +#define DECODE_RX_A_INSTRUCTION(x2, b2, r1, d2_val) \
|
| + int x2 = AS(RXInstruction)->X2Value(); \
|
| + int b2 = AS(RXInstruction)->B2Value(); \
|
| + int r1 = AS(RXInstruction)->R1Value(); \
|
| + intptr_t d2_val = AS(RXInstruction)->D2Value(); \
|
| + int length = 4;
|
| +
|
| +#define DECODE_RS_A_INSTRUCTION(r1, r3, b2, d2) \
|
| + int r3 = AS(RSInstruction)->R3Value(); \
|
| + int b2 = AS(RSInstruction)->B2Value(); \
|
| + int r1 = AS(RSInstruction)->R1Value(); \
|
| + intptr_t d2 = AS(RSInstruction)->D2Value(); \
|
| + int length = 4;
|
| +
|
| +#define DECODE_RS_A_INSTRUCTION_NO_R3(r1, b2, d2) \
|
| + int b2 = AS(RSInstruction)->B2Value(); \
|
| + int r1 = AS(RSInstruction)->R1Value(); \
|
| + int d2 = AS(RSInstruction)->D2Value(); \
|
| + int length = 4;
|
| +
|
| +#define DECODE_SI_INSTRUCTION_I_UINT8(b1, d1_val, imm_val) \
|
| + int b1 = AS(SIInstruction)->B1Value(); \
|
| + intptr_t d1_val = AS(SIInstruction)->D1Value(); \
|
| + uint8_t imm_val = AS(SIInstruction)->I2Value(); \
|
| + int length = 4;
|
| +
|
| #define DECODE_RRE_INSTRUCTION(r1, r2) \
|
| int r1 = AS(RREInstruction)->R1Value(); \
|
| int r2 = AS(RREInstruction)->R2Value(); \
|
| @@ -5948,6 +5984,11 @@ uintptr_t Simulator::PopAddress() {
|
| int16_t i2 = AS(RIInstruction)->I2Value(); \
|
| int length = 4;
|
|
|
| +#define DECODE_RI_B_INSTRUCTION(instr, r1, i2) \
|
| + int32_t r1 = AS(RILInstruction)->R1Value(); \
|
| + int16_t i2 = AS(RILInstruction)->I2Value(); \
|
| + int length = 4;
|
| +
|
| #define DECODE_RI_C_INSTRUCTION(instr, m1, i2) \
|
| Condition m1 = static_cast<Condition>(AS(RIInstruction)->R1Value()); \
|
| int16_t i2 = AS(RIInstruction)->I2Value(); \
|
| @@ -5993,14 +6034,9 @@ EVALUATE(AR) {
|
|
|
| EVALUATE(L) {
|
| DCHECK_OPCODE(L);
|
| - RXInstruction* rxinst = reinterpret_cast<RXInstruction*>(instr);
|
| - int b2 = rxinst->B2Value();
|
| - int x2 = rxinst->X2Value();
|
| - int32_t r1 = rxinst->R1Value();
|
| - int length = 4;
|
| + DECODE_RX_A_INSTRUCTION(x2, b2, r1, d2_val);
|
| int64_t b2_val = (b2 == 0) ? 0 : get_register(b2);
|
| int64_t x2_val = (x2 == 0) ? 0 : get_register(x2);
|
| - intptr_t d2_val = rxinst->D2Value();
|
| intptr_t addr = b2_val + x2_val + d2_val;
|
| int32_t mem_val = ReadW(addr, instr);
|
| set_low_register(r1, mem_val);
|
| @@ -6056,20 +6092,14 @@ EVALUATE(BRCL) {
|
|
|
| EVALUATE(IIHF) {
|
| DCHECK_OPCODE(IIHF);
|
| - RILInstruction* rilInstr = reinterpret_cast<RILInstruction*>(instr);
|
| - int r1 = rilInstr->R1Value();
|
| - uint32_t imm = rilInstr->I2UnsignedValue();
|
| - int length = 6;
|
| + DECODE_RIL_A_INSTRUCTION(r1, imm);
|
| set_high_register(r1, imm);
|
| return length;
|
| }
|
|
|
| EVALUATE(IILF) {
|
| DCHECK_OPCODE(IILF);
|
| - RILInstruction* rilInstr = reinterpret_cast<RILInstruction*>(instr);
|
| - int r1 = rilInstr->R1Value();
|
| - uint32_t imm = rilInstr->I2UnsignedValue();
|
| - int length = 6;
|
| + DECODE_RIL_A_INSTRUCTION(r1, imm);
|
| set_low_register(r1, imm);
|
| return length;
|
| }
|
| @@ -6164,14 +6194,10 @@ EVALUATE(LGF) {
|
|
|
| EVALUATE(ST) {
|
| DCHECK_OPCODE(ST);
|
| - RXInstruction* rxinst = reinterpret_cast<RXInstruction*>(instr);
|
| - int b2 = rxinst->B2Value();
|
| - int x2 = rxinst->X2Value();
|
| - int length = 4;
|
| - int32_t r1_val = get_low_register<int32_t>(rxinst->R1Value());
|
| + DECODE_RX_A_INSTRUCTION(x2, b2, r1, d2_val);
|
| + int32_t r1_val = get_low_register<int32_t>(r1);
|
| int64_t b2_val = (b2 == 0) ? 0 : get_register(b2);
|
| int64_t x2_val = (x2 == 0) ? 0 : get_register(x2);
|
| - intptr_t d2_val = rxinst->D2Value();
|
| intptr_t addr = b2_val + x2_val + d2_val;
|
| WriteW(addr, r1_val, instr);
|
| return length;
|
| @@ -6299,7 +6325,14 @@ EVALUATE(AGHIK) {
|
| return length;
|
| }
|
|
|
| -EVALUATE(BKPT) { return DecodeInstructionOriginal(instr); }
|
| +EVALUATE(BKPT) {
|
| + DCHECK_OPCODE(BKPT);
|
| + set_pc(get_pc() + 2);
|
| + S390Debugger dbg(this);
|
| + dbg.Debug();
|
| + int length = 2;
|
| + return length;
|
| +}
|
|
|
| EVALUATE(SPM) { return DecodeInstructionOriginal(instr); }
|
|
|
| @@ -6307,7 +6340,22 @@ EVALUATE(BALR) { return DecodeInstructionOriginal(instr); }
|
|
|
| EVALUATE(BCTR) { return DecodeInstructionOriginal(instr); }
|
|
|
| -EVALUATE(BCR) { return DecodeInstructionOriginal(instr); }
|
| +EVALUATE(BCR) {
|
| + DCHECK_OPCODE(BCR);
|
| + DECODE_RR_INSTRUCTION(r1, r2);
|
| + if (TestConditionCode(Condition(r1))) {
|
| + intptr_t r2_val = get_register(r2);
|
| +#if (!V8_TARGET_ARCH_S390X && V8_HOST_ARCH_S390)
|
| + // On 31-bit, the top most bit may be 0 or 1, but is ignored by the
|
| + // hardware. Cleanse the top bit before jumping to it, unless it's one
|
| + // of the special PCs
|
| + if (r2_val != bad_lr && r2_val != end_sim_pc) r2_val &= 0x7FFFFFFF;
|
| +#endif
|
| + set_pc(r2_val);
|
| + }
|
| +
|
| + return length;
|
| +}
|
|
|
| EVALUATE(SVC) { return DecodeInstructionOriginal(instr); }
|
|
|
| @@ -6315,7 +6363,24 @@ EVALUATE(BSM) { return DecodeInstructionOriginal(instr); }
|
|
|
| EVALUATE(BASSM) { return DecodeInstructionOriginal(instr); }
|
|
|
| -EVALUATE(BASR) { return DecodeInstructionOriginal(instr); }
|
| +EVALUATE(BASR) {
|
| + DCHECK_OPCODE(BASR);
|
| + DECODE_RR_INSTRUCTION(r1, r2);
|
| + intptr_t link_addr = get_pc() + 2;
|
| + // If R2 is zero, the BASR does not branch.
|
| + int64_t r2_val = (r2 == 0) ? link_addr : get_register(r2);
|
| +#if (!V8_TARGET_ARCH_S390X && V8_HOST_ARCH_S390)
|
| + // On 31-bit, the top most bit may be 0 or 1, which can cause issues
|
| + // for stackwalker. The top bit should either be cleanse before being
|
| + // pushed onto the stack, or during stack walking when dereferenced.
|
| + // For simulator, we'll take the worst case scenario and always tag
|
| + // the high bit, to flush out more problems.
|
| + link_addr |= 0x80000000;
|
| +#endif
|
| + set_register(r1, link_addr);
|
| + set_pc(r2_val);
|
| + return length;
|
| +}
|
|
|
| EVALUATE(MVCL) { return DecodeInstructionOriginal(instr); }
|
|
|
| @@ -6323,45 +6388,239 @@ EVALUATE(CLCL) { return DecodeInstructionOriginal(instr); }
|
|
|
| EVALUATE(LPR) { return DecodeInstructionOriginal(instr); }
|
|
|
| -EVALUATE(LNR) { return DecodeInstructionOriginal(instr); }
|
| +EVALUATE(LNR) {
|
| + DCHECK_OPCODE(LNR);
|
| + // Load Negative (32)
|
| + DECODE_RR_INSTRUCTION(r1, r2);
|
| + int32_t r2_val = get_low_register<int32_t>(r2);
|
| + r2_val = (r2_val >= 0) ? -r2_val : r2_val; // If pos, then negate it.
|
| + set_low_register(r1, r2_val);
|
| + condition_reg_ = (r2_val == 0) ? CC_EQ : CC_LT; // CC0 - result is zero
|
| + // CC1 - result is negative
|
| + return length;
|
| +}
|
|
|
| -EVALUATE(LTR) { return DecodeInstructionOriginal(instr); }
|
| +EVALUATE(LTR) {
|
| + DCHECK_OPCODE(LTR);
|
| + DECODE_RR_INSTRUCTION(r1, r2);
|
| + int32_t r2_val = get_low_register<int32_t>(r2);
|
| + SetS390ConditionCode<int32_t>(r2_val, 0);
|
| + set_low_register(r1, r2_val);
|
| + return length;
|
| +}
|
|
|
| -EVALUATE(LCR) { return DecodeInstructionOriginal(instr); }
|
| +EVALUATE(LCR) {
|
| + DCHECK_OPCODE(LCR);
|
| + DECODE_RR_INSTRUCTION(r1, r2);
|
| + int32_t r2_val = get_low_register<int32_t>(r2);
|
| + int32_t original_r2_val = r2_val;
|
| + r2_val = ~r2_val;
|
| + r2_val = r2_val + 1;
|
| + set_low_register(r1, r2_val);
|
| + SetS390ConditionCode<int32_t>(r2_val, 0);
|
| + // Checks for overflow where r2_val = -2147483648.
|
| + // Cannot do int comparison due to GCC 4.8 bug on x86.
|
| + // Detect INT_MIN alternatively, as it is the only value where both
|
| + // original and result are negative due to overflow.
|
| + if (r2_val < 0 && original_r2_val < 0) {
|
| + SetS390OverflowCode(true);
|
| + }
|
| + return length;
|
| +}
|
|
|
| -EVALUATE(NR) { return DecodeInstructionOriginal(instr); }
|
| +EVALUATE(NR) {
|
| + DCHECK_OPCODE(NR);
|
| + DECODE_RR_INSTRUCTION(r1, r2);
|
| + int32_t r1_val = get_low_register<int32_t>(r1);
|
| + int32_t r2_val = get_low_register<int32_t>(r2);
|
| + r1_val &= r2_val;
|
| + SetS390BitWiseConditionCode<uint32_t>(r1_val);
|
| + set_low_register(r1, r1_val);
|
| + return length;
|
| +}
|
|
|
| -EVALUATE(OR) { return DecodeInstructionOriginal(instr); }
|
| +EVALUATE(OR) {
|
| + DCHECK_OPCODE(OR);
|
| + DECODE_RR_INSTRUCTION(r1, r2);
|
| + int32_t r1_val = get_low_register<int32_t>(r1);
|
| + int32_t r2_val = get_low_register<int32_t>(r2);
|
| + r1_val |= r2_val;
|
| + SetS390BitWiseConditionCode<uint32_t>(r1_val);
|
| + set_low_register(r1, r1_val);
|
| + return length;
|
| +}
|
|
|
| -EVALUATE(XR) { return DecodeInstructionOriginal(instr); }
|
| +EVALUATE(XR) {
|
| + DCHECK_OPCODE(XR);
|
| + DECODE_RR_INSTRUCTION(r1, r2);
|
| + int32_t r1_val = get_low_register<int32_t>(r1);
|
| + int32_t r2_val = get_low_register<int32_t>(r2);
|
| + r1_val ^= r2_val;
|
| + SetS390BitWiseConditionCode<uint32_t>(r1_val);
|
| + set_low_register(r1, r1_val);
|
| + return length;
|
| +}
|
|
|
| -EVALUATE(CR) { return DecodeInstructionOriginal(instr); }
|
| +EVALUATE(CR) {
|
| + DCHECK_OPCODE(CR);
|
| + DECODE_RR_INSTRUCTION(r1, r2);
|
| + int32_t r1_val = get_low_register<int32_t>(r1);
|
| + int32_t r2_val = get_low_register<int32_t>(r2);
|
| + SetS390ConditionCode<int32_t>(r1_val, r2_val);
|
| + return length;
|
| +}
|
|
|
| -EVALUATE(SR) { return DecodeInstructionOriginal(instr); }
|
| +EVALUATE(SR) {
|
| + DCHECK_OPCODE(SR);
|
| + DECODE_RR_INSTRUCTION(r1, r2);
|
| + int32_t r1_val = get_low_register<int32_t>(r1);
|
| + int32_t r2_val = get_low_register<int32_t>(r2);
|
| + bool isOF = false;
|
| + isOF = CheckOverflowForIntSub(r1_val, r2_val, int32_t);
|
| + r1_val -= r2_val;
|
| + SetS390ConditionCode<int32_t>(r1_val, 0);
|
| + SetS390OverflowCode(isOF);
|
| + set_low_register(r1, r1_val);
|
| + return length;
|
| +}
|
|
|
| -EVALUATE(MR) { return DecodeInstructionOriginal(instr); }
|
| +EVALUATE(MR) {
|
| + DCHECK_OPCODE(MR);
|
| + DECODE_RR_INSTRUCTION(r1, r2);
|
| + int32_t r1_val = get_low_register<int32_t>(r1);
|
| + int32_t r2_val = get_low_register<int32_t>(r2);
|
| + DCHECK(r1 % 2 == 0);
|
| + r1_val = get_low_register<int32_t>(r1 + 1);
|
| + int64_t product = static_cast<int64_t>(r1_val) * static_cast<int64_t>(r2_val);
|
| + int32_t high_bits = product >> 32;
|
| + r1_val = high_bits;
|
| + int32_t low_bits = product & 0x00000000FFFFFFFF;
|
| + set_low_register(r1, high_bits);
|
| + set_low_register(r1 + 1, low_bits);
|
| + set_low_register(r1, r1_val);
|
| + return length;
|
| +}
|
|
|
| -EVALUATE(DR) { return DecodeInstructionOriginal(instr); }
|
| +EVALUATE(DR) {
|
| + DCHECK_OPCODE(DR);
|
| + DECODE_RR_INSTRUCTION(r1, r2);
|
| + int32_t r1_val = get_low_register<int32_t>(r1);
|
| + int32_t r2_val = get_low_register<int32_t>(r2);
|
| + // reg-reg pair should be even-odd pair, assert r1 is an even register
|
| + DCHECK(r1 % 2 == 0);
|
| + // leftmost 32 bits of the dividend are in r1
|
| + // rightmost 32 bits of the dividend are in r1+1
|
| + // get the signed value from r1
|
| + int64_t dividend = static_cast<int64_t>(r1_val) << 32;
|
| + // get unsigned value from r1+1
|
| + // avoid addition with sign-extended r1+1 value
|
| + dividend += get_low_register<uint32_t>(r1 + 1);
|
| + int32_t remainder = dividend % r2_val;
|
| + int32_t quotient = dividend / r2_val;
|
| + r1_val = remainder;
|
| + set_low_register(r1, remainder);
|
| + set_low_register(r1 + 1, quotient);
|
| + set_low_register(r1, r1_val);
|
| + return length;
|
| +}
|
|
|
| -EVALUATE(ALR) { return DecodeInstructionOriginal(instr); }
|
| +EVALUATE(ALR) {
|
| + DCHECK_OPCODE(ALR);
|
| + DECODE_RR_INSTRUCTION(r1, r2);
|
| + uint32_t r1_val = get_low_register<uint32_t>(r1);
|
| + uint32_t r2_val = get_low_register<uint32_t>(r2);
|
| + uint32_t alu_out = 0;
|
| + bool isOF = false;
|
| + alu_out = r1_val + r2_val;
|
| + isOF = CheckOverflowForUIntAdd(r1_val, r2_val);
|
| + set_low_register(r1, alu_out);
|
| + SetS390ConditionCodeCarry<uint32_t>(alu_out, isOF);
|
| + return length;
|
| +}
|
|
|
| -EVALUATE(SLR) { return DecodeInstructionOriginal(instr); }
|
| +EVALUATE(SLR) {
|
| + DCHECK_OPCODE(SLR);
|
| + DECODE_RR_INSTRUCTION(r1, r2);
|
| + uint32_t r1_val = get_low_register<uint32_t>(r1);
|
| + uint32_t r2_val = get_low_register<uint32_t>(r2);
|
| + uint32_t alu_out = 0;
|
| + bool isOF = false;
|
| + alu_out = r1_val - r2_val;
|
| + isOF = CheckOverflowForUIntSub(r1_val, r2_val);
|
| + set_low_register(r1, alu_out);
|
| + SetS390ConditionCodeCarry<uint32_t>(alu_out, isOF);
|
| + return length;
|
| +}
|
|
|
| -EVALUATE(LDR) { return DecodeInstructionOriginal(instr); }
|
| +EVALUATE(LDR) {
|
| + DCHECK_OPCODE(LDR);
|
| + DECODE_RR_INSTRUCTION(r1, r2);
|
| + int64_t r2_val = get_d_register(r2);
|
| + set_d_register(r1, r2_val);
|
| + return length;
|
| +}
|
|
|
| EVALUATE(CDR) { return DecodeInstructionOriginal(instr); }
|
|
|
| EVALUATE(LER) { return DecodeInstructionOriginal(instr); }
|
|
|
| -EVALUATE(STH) { return DecodeInstructionOriginal(instr); }
|
| +EVALUATE(STH) {
|
| + DCHECK_OPCODE(STH);
|
| + DECODE_RX_A_INSTRUCTION(x2, b2, r1, d2_val);
|
| + int16_t r1_val = get_low_register<int32_t>(r1);
|
| + int64_t b2_val = (b2 == 0) ? 0 : get_register(b2);
|
| + int64_t x2_val = (x2 == 0) ? 0 : get_register(x2);
|
| + intptr_t mem_addr = b2_val + x2_val + d2_val;
|
| + WriteH(mem_addr, r1_val, instr);
|
|
|
| -EVALUATE(LA) { return DecodeInstructionOriginal(instr); }
|
| + return length;
|
| +}
|
|
|
| -EVALUATE(STC) { return DecodeInstructionOriginal(instr); }
|
| +EVALUATE(LA) {
|
| + DCHECK_OPCODE(LA);
|
| + DECODE_RX_A_INSTRUCTION(x2, b2, r1, d2_val);
|
| + int64_t b2_val = (b2 == 0) ? 0 : get_register(b2);
|
| + int64_t x2_val = (x2 == 0) ? 0 : get_register(x2);
|
| + intptr_t addr = b2_val + x2_val + d2_val;
|
| + set_register(r1, addr);
|
| + return length;
|
| +}
|
| +
|
| +EVALUATE(STC) {
|
| + DCHECK_OPCODE(STC);
|
| + // Store Character/Byte
|
| + DECODE_RX_A_INSTRUCTION(x2, b2, r1, d2_val);
|
| + uint8_t r1_val = get_low_register<int32_t>(r1);
|
| + int64_t b2_val = (b2 == 0) ? 0 : get_register(b2);
|
| + int64_t x2_val = (x2 == 0) ? 0 : get_register(x2);
|
| + intptr_t mem_addr = b2_val + x2_val + d2_val;
|
| + WriteB(mem_addr, r1_val);
|
| + return length;
|
| +}
|
|
|
| EVALUATE(IC_z) { return DecodeInstructionOriginal(instr); }
|
|
|
| -EVALUATE(EX) { return DecodeInstructionOriginal(instr); }
|
| +EVALUATE(EX) {
|
| + DCHECK_OPCODE(EX);
|
| + DECODE_RX_A_INSTRUCTION(x2, b2, r1, d2_val);
|
| + int64_t b2_val = (b2 == 0) ? 0 : get_register(b2);
|
| + int64_t x2_val = (x2 == 0) ? 0 : get_register(x2);
|
| + int32_t r1_val = get_low_register<int32_t>(r1);
|
| +
|
| + SixByteInstr the_instr = Instruction::InstructionBits(
|
| + reinterpret_cast<const byte*>(b2_val + x2_val + d2_val));
|
| + int inst_length = Instruction::InstructionLength(
|
| + reinterpret_cast<const byte*>(b2_val + x2_val + d2_val));
|
| +
|
| + char new_instr_buf[8];
|
| + char* addr = reinterpret_cast<char*>(&new_instr_buf[0]);
|
| + the_instr |= static_cast<SixByteInstr>(r1_val & 0xff)
|
| + << (8 * inst_length - 16);
|
| + Instruction::SetInstructionBits<SixByteInstr>(
|
| + reinterpret_cast<byte*>(addr), static_cast<SixByteInstr>(the_instr));
|
| + ExecuteInstruction(reinterpret_cast<Instruction*>(addr), false);
|
| + return length;
|
| +}
|
|
|
| EVALUATE(BAL) { return DecodeInstructionOriginal(instr); }
|
|
|
| @@ -6369,15 +6628,72 @@ EVALUATE(BCT) { return DecodeInstructionOriginal(instr); }
|
|
|
| EVALUATE(BC) { return DecodeInstructionOriginal(instr); }
|
|
|
| -EVALUATE(LH) { return DecodeInstructionOriginal(instr); }
|
| +EVALUATE(LH) {
|
| + DCHECK_OPCODE(LH);
|
| + // Load Halfword
|
| + DECODE_RX_A_INSTRUCTION(x2, b2, r1, d2_val);
|
| +
|
| + int64_t x2_val = (x2 == 0) ? 0 : get_register(x2);
|
| + int64_t b2_val = (b2 == 0) ? 0 : get_register(b2);
|
| + intptr_t mem_addr = x2_val + b2_val + d2_val;
|
| +
|
| + int32_t result = static_cast<int32_t>(ReadH(mem_addr, instr));
|
| + set_low_register(r1, result);
|
| + return length;
|
| +}
|
|
|
| EVALUATE(CH) { return DecodeInstructionOriginal(instr); }
|
|
|
| -EVALUATE(AH) { return DecodeInstructionOriginal(instr); }
|
| +EVALUATE(AH) {
|
| + DCHECK_OPCODE(AH);
|
| + DECODE_RX_A_INSTRUCTION(x2, b2, r1, d2_val);
|
| + int32_t r1_val = get_low_register<int32_t>(r1);
|
| + int64_t b2_val = (b2 == 0) ? 0 : get_register(b2);
|
| + int64_t x2_val = (x2 == 0) ? 0 : get_register(x2);
|
| + intptr_t addr = b2_val + x2_val + d2_val;
|
| + int32_t mem_val = static_cast<int32_t>(ReadH(addr, instr));
|
| + int32_t alu_out = 0;
|
| + bool isOF = false;
|
| + isOF = CheckOverflowForIntAdd(r1_val, mem_val, int32_t);
|
| + alu_out = r1_val + mem_val;
|
| + set_low_register(r1, alu_out);
|
| + SetS390ConditionCode<int32_t>(alu_out, 0);
|
| + SetS390OverflowCode(isOF);
|
| +
|
| + return length;
|
| +}
|
|
|
| -EVALUATE(SH) { return DecodeInstructionOriginal(instr); }
|
| +EVALUATE(SH) {
|
| + DCHECK_OPCODE(SH);
|
| + DECODE_RX_A_INSTRUCTION(x2, b2, r1, d2_val);
|
| + int32_t r1_val = get_low_register<int32_t>(r1);
|
| + int64_t b2_val = (b2 == 0) ? 0 : get_register(b2);
|
| + int64_t x2_val = (x2 == 0) ? 0 : get_register(x2);
|
| + intptr_t addr = b2_val + x2_val + d2_val;
|
| + int32_t mem_val = static_cast<int32_t>(ReadH(addr, instr));
|
| + int32_t alu_out = 0;
|
| + bool isOF = false;
|
| + isOF = CheckOverflowForIntSub(r1_val, mem_val, int32_t);
|
| + alu_out = r1_val - mem_val;
|
| + SetS390ConditionCode<int32_t>(alu_out, 0);
|
| + SetS390OverflowCode(isOF);
|
|
|
| -EVALUATE(MH) { return DecodeInstructionOriginal(instr); }
|
| + return length;
|
| +}
|
| +
|
| +EVALUATE(MH) {
|
| + DCHECK_OPCODE(MH);
|
| + DECODE_RX_A_INSTRUCTION(x2, b2, r1, d2_val);
|
| + int32_t r1_val = get_low_register<int32_t>(r1);
|
| + int64_t b2_val = (b2 == 0) ? 0 : get_register(b2);
|
| + int64_t x2_val = (x2 == 0) ? 0 : get_register(x2);
|
| + intptr_t addr = b2_val + x2_val + d2_val;
|
| + int32_t mem_val = static_cast<int32_t>(ReadH(addr, instr));
|
| + int32_t alu_out = 0;
|
| + alu_out = r1_val * mem_val;
|
| + set_low_register(r1, alu_out);
|
| + return length;
|
| +}
|
|
|
| EVALUATE(BAS) { return DecodeInstructionOriginal(instr); }
|
|
|
| @@ -6387,19 +6703,110 @@ EVALUATE(CVB) { return DecodeInstructionOriginal(instr); }
|
|
|
| EVALUATE(LAE) { return DecodeInstructionOriginal(instr); }
|
|
|
| -EVALUATE(N) { return DecodeInstructionOriginal(instr); }
|
| +EVALUATE(N) {
|
| + DCHECK_OPCODE(N);
|
| + // 32-bit Reg-Mem instructions
|
| + DECODE_RX_A_INSTRUCTION(x2, b2, r1, d2_val);
|
| + int32_t r1_val = get_low_register<int32_t>(r1);
|
| + int64_t b2_val = (b2 == 0) ? 0 : get_register(b2);
|
| + int64_t x2_val = (x2 == 0) ? 0 : get_register(x2);
|
| + int32_t mem_val = ReadW(b2_val + x2_val + d2_val, instr);
|
| + int32_t alu_out = 0;
|
| + alu_out = r1_val & mem_val;
|
| + SetS390BitWiseConditionCode<uint32_t>(alu_out);
|
| + set_low_register(r1, alu_out);
|
| + return length;
|
| +}
|
|
|
| -EVALUATE(CL) { return DecodeInstructionOriginal(instr); }
|
| +EVALUATE(CL) {
|
| + DCHECK_OPCODE(CL);
|
| + DECODE_RX_A_INSTRUCTION(x2, b2, r1, d2_val);
|
| + int32_t r1_val = get_low_register<int32_t>(r1);
|
| + int64_t b2_val = (b2 == 0) ? 0 : get_register(b2);
|
| + int64_t x2_val = (x2 == 0) ? 0 : get_register(x2);
|
| + intptr_t addr = b2_val + x2_val + d2_val;
|
| + int32_t mem_val = ReadW(addr, instr);
|
| + SetS390ConditionCode<uint32_t>(r1_val, mem_val);
|
| + return length;
|
| +}
|
|
|
| -EVALUATE(O) { return DecodeInstructionOriginal(instr); }
|
| +EVALUATE(O) {
|
| + DCHECK_OPCODE(O);
|
| + // 32-bit Reg-Mem instructions
|
| + DECODE_RX_A_INSTRUCTION(x2, b2, r1, d2_val);
|
| + int32_t r1_val = get_low_register<int32_t>(r1);
|
| + int64_t b2_val = (b2 == 0) ? 0 : get_register(b2);
|
| + int64_t x2_val = (x2 == 0) ? 0 : get_register(x2);
|
| + int32_t mem_val = ReadW(b2_val + x2_val + d2_val, instr);
|
| + int32_t alu_out = 0;
|
| + alu_out = r1_val | mem_val;
|
| + SetS390BitWiseConditionCode<uint32_t>(alu_out);
|
| + set_low_register(r1, alu_out);
|
| + return length;
|
| +}
|
|
|
| -EVALUATE(X) { return DecodeInstructionOriginal(instr); }
|
| +EVALUATE(X) {
|
| + DCHECK_OPCODE(X);
|
| + // 32-bit Reg-Mem instructions
|
| + DECODE_RX_A_INSTRUCTION(x2, b2, r1, d2_val);
|
| + int32_t r1_val = get_low_register<int32_t>(r1);
|
| + int64_t b2_val = (b2 == 0) ? 0 : get_register(b2);
|
| + int64_t x2_val = (x2 == 0) ? 0 : get_register(x2);
|
| + int32_t mem_val = ReadW(b2_val + x2_val + d2_val, instr);
|
| + int32_t alu_out = 0;
|
| + alu_out = r1_val ^ mem_val;
|
| + SetS390BitWiseConditionCode<uint32_t>(alu_out);
|
| + set_low_register(r1, alu_out);
|
| + return length;
|
| +}
|
|
|
| -EVALUATE(C) { return DecodeInstructionOriginal(instr); }
|
| +EVALUATE(C) {
|
| + DCHECK_OPCODE(C);
|
| + DECODE_RX_A_INSTRUCTION(x2, b2, r1, d2_val);
|
| + int32_t r1_val = get_low_register<int32_t>(r1);
|
| + int64_t b2_val = (b2 == 0) ? 0 : get_register(b2);
|
| + int64_t x2_val = (x2 == 0) ? 0 : get_register(x2);
|
| + intptr_t addr = b2_val + x2_val + d2_val;
|
| + int32_t mem_val = ReadW(addr, instr);
|
| + SetS390ConditionCode<int32_t>(r1_val, mem_val);
|
| + return length;
|
| +}
|
|
|
| -EVALUATE(A) { return DecodeInstructionOriginal(instr); }
|
| +EVALUATE(A) {
|
| + DCHECK_OPCODE(A);
|
| + // 32-bit Reg-Mem instructions
|
| + DECODE_RX_A_INSTRUCTION(x2, b2, r1, d2_val);
|
| + int32_t r1_val = get_low_register<int32_t>(r1);
|
| + int64_t b2_val = (b2 == 0) ? 0 : get_register(b2);
|
| + int64_t x2_val = (x2 == 0) ? 0 : get_register(x2);
|
| + int32_t mem_val = ReadW(b2_val + x2_val + d2_val, instr);
|
| + int32_t alu_out = 0;
|
| + bool isOF = false;
|
| + isOF = CheckOverflowForIntAdd(r1_val, mem_val, int32_t);
|
| + alu_out = r1_val + mem_val;
|
| + SetS390ConditionCode<int32_t>(alu_out, 0);
|
| + SetS390OverflowCode(isOF);
|
| + set_low_register(r1, alu_out);
|
| + return length;
|
| +}
|
|
|
| -EVALUATE(S) { return DecodeInstructionOriginal(instr); }
|
| +EVALUATE(S) {
|
| + DCHECK_OPCODE(S);
|
| + // 32-bit Reg-Mem instructions
|
| + DECODE_RX_A_INSTRUCTION(x2, b2, r1, d2_val);
|
| + int32_t r1_val = get_low_register<int32_t>(r1);
|
| + int64_t b2_val = (b2 == 0) ? 0 : get_register(b2);
|
| + int64_t x2_val = (x2 == 0) ? 0 : get_register(x2);
|
| + int32_t mem_val = ReadW(b2_val + x2_val + d2_val, instr);
|
| + int32_t alu_out = 0;
|
| + bool isOF = false;
|
| + isOF = CheckOverflowForIntSub(r1_val, mem_val, int32_t);
|
| + alu_out = r1_val - mem_val;
|
| + SetS390ConditionCode<int32_t>(alu_out, 0);
|
| + SetS390OverflowCode(isOF);
|
| + set_low_register(r1, alu_out);
|
| + return length;
|
| +}
|
|
|
| EVALUATE(M) { return DecodeInstructionOriginal(instr); }
|
|
|
| @@ -6409,45 +6816,250 @@ EVALUATE(AL) { return DecodeInstructionOriginal(instr); }
|
|
|
| EVALUATE(SL) { return DecodeInstructionOriginal(instr); }
|
|
|
| -EVALUATE(STD) { return DecodeInstructionOriginal(instr); }
|
| +EVALUATE(STD) {
|
| + DCHECK_OPCODE(STD);
|
| + DECODE_RX_A_INSTRUCTION(x2, b2, r1, d2_val);
|
| + int64_t b2_val = (b2 == 0) ? 0 : get_register(b2);
|
| + int64_t x2_val = (x2 == 0) ? 0 : get_register(x2);
|
| + intptr_t addr = b2_val + x2_val + d2_val;
|
| + int64_t frs_val = get_d_register(r1);
|
| + WriteDW(addr, frs_val);
|
| + return length;
|
| +}
|
|
|
| -EVALUATE(LD) { return DecodeInstructionOriginal(instr); }
|
| +EVALUATE(LD) {
|
| + DCHECK_OPCODE(LD);
|
| + DECODE_RX_A_INSTRUCTION(x2, b2, r1, d2_val);
|
| + int64_t b2_val = (b2 == 0) ? 0 : get_register(b2);
|
| + int64_t x2_val = (x2 == 0) ? 0 : get_register(x2);
|
| + intptr_t addr = b2_val + x2_val + d2_val;
|
| + int64_t dbl_val = *reinterpret_cast<int64_t*>(addr);
|
| + set_d_register(r1, dbl_val);
|
| + return length;
|
| +}
|
|
|
| EVALUATE(CD) { return DecodeInstructionOriginal(instr); }
|
|
|
| -EVALUATE(STE) { return DecodeInstructionOriginal(instr); }
|
| +EVALUATE(STE) {
|
| + DCHECK_OPCODE(STE);
|
| + DECODE_RX_A_INSTRUCTION(x2, b2, r1, d2_val);
|
| + int64_t b2_val = (b2 == 0) ? 0 : get_register(b2);
|
| + int64_t x2_val = (x2 == 0) ? 0 : get_register(x2);
|
| + intptr_t addr = b2_val + x2_val + d2_val;
|
| + int64_t frs_val = get_d_register(r1) >> 32;
|
| + WriteW(addr, static_cast<int32_t>(frs_val), instr);
|
| + return length;
|
| +}
|
|
|
| -EVALUATE(MS) { return DecodeInstructionOriginal(instr); }
|
| +EVALUATE(MS) {
|
| + DCHECK_OPCODE(MS);
|
| + DECODE_RX_A_INSTRUCTION(x2, b2, r1, d2_val);
|
| + int64_t x2_val = (x2 == 0) ? 0 : get_register(x2);
|
| + int64_t b2_val = (b2 == 0) ? 0 : get_register(b2);
|
| + int32_t mem_val = ReadW(b2_val + x2_val + d2_val, instr);
|
| + int32_t r1_val = get_low_register<int32_t>(r1);
|
| + set_low_register(r1, r1_val * mem_val);
|
| + return length;
|
| +}
|
|
|
| -EVALUATE(LE) { return DecodeInstructionOriginal(instr); }
|
| +EVALUATE(LE) {
|
| + DCHECK_OPCODE(LE);
|
| + DECODE_RX_A_INSTRUCTION(x2, b2, r1, d2_val);
|
| + int64_t b2_val = (b2 == 0) ? 0 : get_register(b2);
|
| + int64_t x2_val = (x2 == 0) ? 0 : get_register(x2);
|
| + intptr_t addr = b2_val + x2_val + d2_val;
|
| + float float_val = *reinterpret_cast<float*>(addr);
|
| + set_d_register_from_float32(r1, float_val);
|
| + return length;
|
| +}
|
|
|
| EVALUATE(BRXH) { return DecodeInstructionOriginal(instr); }
|
|
|
| EVALUATE(BRXLE) { return DecodeInstructionOriginal(instr); }
|
|
|
| -EVALUATE(BXH) { return DecodeInstructionOriginal(instr); }
|
| +EVALUATE(BXH) {
|
| + DCHECK_OPCODE(BXH);
|
| + DECODE_RS_A_INSTRUCTION(r1, r3, b2, d2);
|
| +
|
| + // r1_val is the first operand, r3_val is the increment
|
| + int32_t r1_val = r1 == 0 ? 0 : get_register(r1);
|
| + int32_t r3_val = r2 == 0 ? 0 : get_register(r3);
|
| + intptr_t b2_val = b2 == 0 ? 0 : get_register(b2);
|
| + intptr_t branch_address = b2_val + d2;
|
| + // increment r1_val
|
| + r1_val += r3_val;
|
| +
|
| + // if the increment is even, then it designates a pair of registers
|
| + // and the contents of the even and odd registers of the pair are used as
|
| + // the increment and compare value respectively. If the increment is odd,
|
| + // the increment itself is used as both the increment and compare value
|
| + int32_t compare_val = r3 % 2 == 0 ? get_register(r3 + 1) : r3_val;
|
| + if (r1_val > compare_val) {
|
| + // branch to address if r1_val is greater than compare value
|
| + set_pc(branch_address);
|
| + }
|
| +
|
| + // update contents of register in r1 with the new incremented value
|
| + set_register(r1, r1_val);
|
| +
|
| + return length;
|
| +}
|
|
|
| EVALUATE(BXLE) { return DecodeInstructionOriginal(instr); }
|
|
|
| -EVALUATE(SRL) { return DecodeInstructionOriginal(instr); }
|
| +EVALUATE(SRL) {
|
| + DCHECK_OPCODE(SRL);
|
| + DECODE_RS_A_INSTRUCTION_NO_R3(r1, b2, d2);
|
| + // only takes rightmost 6bits
|
| + int64_t b2_val = b2 == 0 ? 0 : get_register(b2);
|
| + int shiftBits = (b2_val + d2) & 0x3F;
|
| + uint32_t r1_val = get_low_register<uint32_t>(r1);
|
| + uint32_t alu_out = 0;
|
| + alu_out = r1_val >> shiftBits;
|
| + set_low_register(r1, alu_out);
|
| + return length;
|
| +}
|
|
|
| -EVALUATE(SLL) { return DecodeInstructionOriginal(instr); }
|
| +EVALUATE(SLL) {
|
| + DCHECK_OPCODE(SLL);
|
| + DECODE_RS_A_INSTRUCTION_NO_R3(r1, b2, d2)
|
| + // only takes rightmost 6bits
|
| + int64_t b2_val = b2 == 0 ? 0 : get_register(b2);
|
| + int shiftBits = (b2_val + d2) & 0x3F;
|
| + uint32_t r1_val = get_low_register<uint32_t>(r1);
|
| + uint32_t alu_out = 0;
|
| + alu_out = r1_val << shiftBits;
|
| + set_low_register(r1, alu_out);
|
| + return length;
|
| +}
|
|
|
| -EVALUATE(SRA) { return DecodeInstructionOriginal(instr); }
|
| +EVALUATE(SRA) {
|
| + DCHECK_OPCODE(SRA);
|
| + DECODE_RS_A_INSTRUCTION_NO_R3(r1, b2, d2);
|
| + // only takes rightmost 6bits
|
| + int64_t b2_val = b2 == 0 ? 0 : get_register(b2);
|
| + int shiftBits = (b2_val + d2) & 0x3F;
|
| + int32_t r1_val = get_low_register<int32_t>(r1);
|
| + int32_t alu_out = 0;
|
| + bool isOF = false;
|
| + alu_out = r1_val >> shiftBits;
|
| + set_low_register(r1, alu_out);
|
| + SetS390ConditionCode<int32_t>(alu_out, 0);
|
| + SetS390OverflowCode(isOF);
|
| + return length;
|
| +}
|
|
|
| -EVALUATE(SLA) { return DecodeInstructionOriginal(instr); }
|
| +EVALUATE(SLA) {
|
| + DCHECK_OPCODE(SLA);
|
| + DECODE_RS_A_INSTRUCTION_NO_R3(r1, b2, d2);
|
| + // only takes rightmost 6bits
|
| + int64_t b2_val = b2 == 0 ? 0 : get_register(b2);
|
| + int shiftBits = (b2_val + d2) & 0x3F;
|
| + int32_t r1_val = get_low_register<int32_t>(r1);
|
| + int32_t alu_out = 0;
|
| + bool isOF = false;
|
| + isOF = CheckOverflowForShiftLeft(r1_val, shiftBits);
|
| + alu_out = r1_val << shiftBits;
|
| + set_low_register(r1, alu_out);
|
| + SetS390ConditionCode<int32_t>(alu_out, 0);
|
| + SetS390OverflowCode(isOF);
|
| + return length;
|
| +}
|
|
|
| -EVALUATE(SRDL) { return DecodeInstructionOriginal(instr); }
|
| +EVALUATE(SRDL) {
|
| + DCHECK_OPCODE(SRDL);
|
| + DECODE_RS_A_INSTRUCTION_NO_R3(r1, b2, d2);
|
| + DCHECK(r1 % 2 == 0); // must be a reg pair
|
| + // only takes rightmost 6bits
|
| + int64_t b2_val = b2 == 0 ? 0 : get_register(b2);
|
| + int shiftBits = (b2_val + d2) & 0x3F;
|
| + uint64_t opnd1 = static_cast<uint64_t>(get_low_register<uint32_t>(r1)) << 32;
|
| + uint64_t opnd2 = static_cast<uint64_t>(get_low_register<uint32_t>(r1 + 1));
|
| + uint64_t r1_val = opnd1 | opnd2;
|
| + uint64_t alu_out = r1_val >> shiftBits;
|
| + set_low_register(r1, alu_out >> 32);
|
| + set_low_register(r1 + 1, alu_out & 0x00000000FFFFFFFF);
|
| + SetS390ConditionCode<int32_t>(alu_out, 0);
|
| + return length;
|
| +}
|
|
|
| -EVALUATE(SLDL) { return DecodeInstructionOriginal(instr); }
|
| +EVALUATE(SLDL) {
|
| + DCHECK_OPCODE(SLDL);
|
| + DECODE_RS_A_INSTRUCTION_NO_R3(r1, b2, d2);
|
| + // only takes rightmost 6bits
|
| + int64_t b2_val = b2 == 0 ? 0 : get_register(b2);
|
| + int shiftBits = (b2_val + d2) & 0x3F;
|
|
|
| -EVALUATE(SRDA) { return DecodeInstructionOriginal(instr); }
|
| + DCHECK(r1 % 2 == 0);
|
| + uint32_t r1_val = get_low_register<uint32_t>(r1);
|
| + uint32_t r1_next_val = get_low_register<uint32_t>(r1 + 1);
|
| + uint64_t alu_out = (static_cast<uint64_t>(r1_val) << 32) |
|
| + (static_cast<uint64_t>(r1_next_val));
|
| + alu_out <<= shiftBits;
|
| + set_low_register(r1 + 1, static_cast<uint32_t>(alu_out));
|
| + set_low_register(r1, static_cast<uint32_t>(alu_out >> 32));
|
| + return length;
|
| +}
|
| +
|
| +EVALUATE(SRDA) {
|
| + DCHECK_OPCODE(SRDA);
|
| + DECODE_RS_A_INSTRUCTION_NO_R3(r1, b2, d2);
|
| + DCHECK(r1 % 2 == 0); // must be a reg pair
|
| + // only takes rightmost 6bits
|
| + int64_t b2_val = b2 == 0 ? 0 : get_register(b2);
|
| + int shiftBits = (b2_val + d2) & 0x3F;
|
| + int64_t opnd1 = static_cast<int64_t>(get_low_register<int32_t>(r1)) << 32;
|
| + int64_t opnd2 = static_cast<uint64_t>(get_low_register<uint32_t>(r1 + 1));
|
| + int64_t r1_val = opnd1 + opnd2;
|
| + int64_t alu_out = r1_val >> shiftBits;
|
| + set_low_register(r1, alu_out >> 32);
|
| + set_low_register(r1 + 1, alu_out & 0x00000000FFFFFFFF);
|
| + SetS390ConditionCode<int32_t>(alu_out, 0);
|
| + return length;
|
| +}
|
|
|
| EVALUATE(SLDA) { return DecodeInstructionOriginal(instr); }
|
|
|
| -EVALUATE(STM) { return DecodeInstructionOriginal(instr); }
|
| +EVALUATE(STM) {
|
| + DCHECK_OPCODE(STM);
|
| + DECODE_RS_A_INSTRUCTION(r1, r3, rb, d2);
|
| + // Store Multiple 32-bits.
|
| + int offset = d2;
|
| + // Regs roll around if r3 is less than r1.
|
| + // Artifically increase r3 by 16 so we can calculate
|
| + // the number of regs stored properly.
|
| + if (r3 < r1) r3 += 16;
|
| +
|
| + int32_t rb_val = (rb == 0) ? 0 : get_low_register<int32_t>(rb);
|
| +
|
| + // Store each register in ascending order.
|
| + for (int i = 0; i <= r3 - r1; i++) {
|
| + int32_t value = get_low_register<int32_t>((r1 + i) % 16);
|
| + WriteW(rb_val + offset + 4 * i, value, instr);
|
| + }
|
| + return length;
|
| +}
|
|
|
| -EVALUATE(TM) { return DecodeInstructionOriginal(instr); }
|
| +EVALUATE(TM) {
|
| + DCHECK_OPCODE(TM);
|
| + // Test Under Mask (Mem - Imm) (8)
|
| + DECODE_SI_INSTRUCTION_I_UINT8(b1, d1_val, imm_val)
|
| + int64_t b1_val = (b1 == 0) ? 0 : get_register(b1);
|
| + intptr_t addr = b1_val + d1_val;
|
| + uint8_t mem_val = ReadB(addr);
|
| + uint8_t selected_bits = mem_val & imm_val;
|
| + // CC0: Selected bits are zero
|
| + // CC1: Selected bits mixed zeros and ones
|
| + // CC3: Selected bits all ones
|
| + if (0 == selected_bits) {
|
| + condition_reg_ = CC_EQ; // CC0
|
| + } else if (selected_bits == imm_val) {
|
| + condition_reg_ = 0x1; // CC3
|
| + } else {
|
| + condition_reg_ = 0x4; // CC1
|
| + }
|
| + return length;
|
| +}
|
|
|
| EVALUATE(MVI) { return DecodeInstructionOriginal(instr); }
|
|
|
| @@ -6455,13 +7067,40 @@ EVALUATE(TS) { return DecodeInstructionOriginal(instr); }
|
|
|
| EVALUATE(NI) { return DecodeInstructionOriginal(instr); }
|
|
|
| -EVALUATE(CLI) { return DecodeInstructionOriginal(instr); }
|
| +EVALUATE(CLI) {
|
| + DCHECK_OPCODE(CLI);
|
| + // Compare Immediate (Mem - Imm) (8)
|
| + DECODE_SI_INSTRUCTION_I_UINT8(b1, d1_val, imm_val)
|
| + int64_t b1_val = (b1 == 0) ? 0 : get_register(b1);
|
| + intptr_t addr = b1_val + d1_val;
|
| + uint8_t mem_val = ReadB(addr);
|
| + SetS390ConditionCode<uint8_t>(mem_val, imm_val);
|
| + return length;
|
| +}
|
|
|
| EVALUATE(OI) { return DecodeInstructionOriginal(instr); }
|
|
|
| EVALUATE(XI) { return DecodeInstructionOriginal(instr); }
|
|
|
| -EVALUATE(LM) { return DecodeInstructionOriginal(instr); }
|
| +EVALUATE(LM) {
|
| + DCHECK_OPCODE(LM);
|
| + DECODE_RS_A_INSTRUCTION(r1, r3, rb, d2);
|
| + // Store Multiple 32-bits.
|
| + int offset = d2;
|
| + // Regs roll around if r3 is less than r1.
|
| + // Artifically increase r3 by 16 so we can calculate
|
| + // the number of regs stored properly.
|
| + if (r3 < r1) r3 += 16;
|
| +
|
| + int32_t rb_val = (rb == 0) ? 0 : get_low_register<int32_t>(rb);
|
| +
|
| + // Store each register in ascending order.
|
| + for (int i = 0; i <= r3 - r1; i++) {
|
| + int32_t value = ReadW(rb_val + offset + 4 * i, instr);
|
| + set_low_register((r1 + i) % 16, value);
|
| + }
|
| + return length;
|
| +}
|
|
|
| EVALUATE(MVCLE) { return DecodeInstructionOriginal(instr); }
|
|
|
| @@ -6483,7 +7122,26 @@ EVALUATE(TRTR) { return DecodeInstructionOriginal(instr); }
|
|
|
| EVALUATE(MVN) { return DecodeInstructionOriginal(instr); }
|
|
|
| -EVALUATE(MVC) { return DecodeInstructionOriginal(instr); }
|
| +EVALUATE(MVC) {
|
| + DCHECK_OPCODE(MVC);
|
| + // Move Character
|
| + SSInstruction* ssInstr = reinterpret_cast<SSInstruction*>(instr);
|
| + int b1 = ssInstr->B1Value();
|
| + intptr_t d1 = ssInstr->D1Value();
|
| + int b2 = ssInstr->B2Value();
|
| + intptr_t d2 = ssInstr->D2Value();
|
| + int length = ssInstr->Length();
|
| + int64_t b1_val = (b1 == 0) ? 0 : get_register(b1);
|
| + int64_t b2_val = (b2 == 0) ? 0 : get_register(b2);
|
| + intptr_t src_addr = b2_val + d2;
|
| + intptr_t dst_addr = b1_val + d1;
|
| + // remember that the length is the actual length - 1
|
| + for (int i = 0; i < length + 1; ++i) {
|
| + WriteB(dst_addr++, ReadB(src_addr++));
|
| + }
|
| + length = 6;
|
| + return length;
|
| +}
|
|
|
| EVALUATE(MVZ) { return DecodeInstructionOriginal(instr); }
|
|
|
| @@ -6553,17 +7211,52 @@ EVALUATE(NIHH) { return DecodeInstructionOriginal(instr); }
|
|
|
| EVALUATE(NIHL) { return DecodeInstructionOriginal(instr); }
|
|
|
| -EVALUATE(NILH) { return DecodeInstructionOriginal(instr); }
|
| +EVALUATE(NILH) {
|
| + DCHECK_OPCODE(NILH);
|
| + DECODE_RI_A_INSTRUCTION(instr, r1, i);
|
| + int32_t r1_val = get_low_register<int32_t>(r1);
|
| + // CC is set based on the 16 bits that are AND'd
|
| + SetS390BitWiseConditionCode<uint16_t>((r1_val >> 16) & i);
|
| + i = (i << 16) | 0x0000FFFF;
|
| + set_low_register(r1, r1_val & i);
|
| + return length;
|
| +}
|
|
|
| -EVALUATE(NILL) { return DecodeInstructionOriginal(instr); }
|
| +EVALUATE(NILL) {
|
| + DCHECK_OPCODE(NILL);
|
| + DECODE_RI_A_INSTRUCTION(instr, r1, i);
|
| + int32_t r1_val = get_low_register<int32_t>(r1);
|
| + // CC is set based on the 16 bits that are AND'd
|
| + SetS390BitWiseConditionCode<uint16_t>(r1_val & i);
|
| + i |= 0xFFFF0000;
|
| + set_low_register(r1, r1_val & i);
|
| + return length;
|
| +}
|
|
|
| EVALUATE(OIHH) { return DecodeInstructionOriginal(instr); }
|
|
|
| EVALUATE(OIHL) { return DecodeInstructionOriginal(instr); }
|
|
|
| -EVALUATE(OILH) { return DecodeInstructionOriginal(instr); }
|
| +EVALUATE(OILH) {
|
| + DCHECK_OPCODE(OILH);
|
| + DECODE_RI_A_INSTRUCTION(instr, r1, i);
|
| + int32_t r1_val = get_low_register<int32_t>(r1);
|
| + // CC is set based on the 16 bits that are AND'd
|
| + SetS390BitWiseConditionCode<uint16_t>((r1_val >> 16) | i);
|
| + i = i << 16;
|
| + set_low_register(r1, r1_val | i);
|
| + return length;
|
| +}
|
|
|
| -EVALUATE(OILL) { return DecodeInstructionOriginal(instr); }
|
| +EVALUATE(OILL) {
|
| + DCHECK_OPCODE(OILL);
|
| + DECODE_RI_A_INSTRUCTION(instr, r1, i);
|
| + int32_t r1_val = get_low_register<int32_t>(r1);
|
| + // CC is set based on the 16 bits that are AND'd
|
| + SetS390BitWiseConditionCode<uint16_t>(r1_val | i);
|
| + set_low_register(r1, r1_val | i);
|
| + return length;
|
| +}
|
|
|
| EVALUATE(LLIHH) { return DecodeInstructionOriginal(instr); }
|
|
|
| @@ -6575,75 +7268,405 @@ EVALUATE(LLILL) { return DecodeInstructionOriginal(instr); }
|
|
|
| EVALUATE(TMLH) { return DecodeInstructionOriginal(instr); }
|
|
|
| -EVALUATE(TMLL) { return DecodeInstructionOriginal(instr); }
|
| +EVALUATE(TMLL) {
|
| + DCHECK_OPCODE(TMLL);
|
| + DECODE_RI_A_INSTRUCTION(instr, r1, i2);
|
| + int mask = i2 & 0x0000FFFF;
|
| + if (mask == 0) {
|
| + condition_reg_ = 0x0;
|
| + return length;
|
| + }
|
| + uint32_t r1_val = get_low_register<uint32_t>(r1);
|
| + r1_val = r1_val & 0x0000FFFF; // uses only the last 16bits
|
| +
|
| + // Test if all selected bits are Zero
|
| + bool allSelectedBitsAreZeros = true;
|
| + for (int i = 0; i < 15; i++) {
|
| + if (mask & (1 << i)) {
|
| + if (r1_val & (1 << i)) {
|
| + allSelectedBitsAreZeros = false;
|
| + break;
|
| + }
|
| + }
|
| + }
|
| + if (allSelectedBitsAreZeros) {
|
| + condition_reg_ = 0x8;
|
| + return length; // Done!
|
| + }
|
| +
|
| + // Test if all selected bits are one
|
| + bool allSelectedBitsAreOnes = true;
|
| + for (int i = 0; i < 15; i++) {
|
| + if (mask & (1 << i)) {
|
| + if (!(r1_val & (1 << i))) {
|
| + allSelectedBitsAreOnes = false;
|
| + break;
|
| + }
|
| + }
|
| + }
|
| + if (allSelectedBitsAreOnes) {
|
| + condition_reg_ = 0x1;
|
| + return length; // Done!
|
| + }
|
| +
|
| + // Now we know selected bits mixed zeros and ones
|
| + // Test if the leftmost bit is zero or one
|
| + for (int i = 14; i >= 0; i--) {
|
| + if (mask & (1 << i)) {
|
| + if (r1_val & (1 << i)) {
|
| + // leftmost bit is one
|
| + condition_reg_ = 0x2;
|
| + } else {
|
| + // leftmost bit is zero
|
| + condition_reg_ = 0x4;
|
| + }
|
| + return length; // Done!
|
| + }
|
| + }
|
| + return length;
|
| +}
|
|
|
| EVALUATE(TMHH) { return DecodeInstructionOriginal(instr); }
|
|
|
| EVALUATE(TMHL) { return DecodeInstructionOriginal(instr); }
|
|
|
| -EVALUATE(BRAS) { return DecodeInstructionOriginal(instr); }
|
| +EVALUATE(BRAS) {
|
| + DCHECK_OPCODE(BRAS);
|
| + // Branch Relative and Save
|
| + DECODE_RI_B_INSTRUCTION(instr, r1, d2)
|
| + intptr_t pc = get_pc();
|
| + // Set PC of next instruction to register
|
| + set_register(r1, pc + sizeof(FourByteInstr));
|
| + // Update PC to branch target
|
| + set_pc(pc + d2 * 2);
|
| + return length;
|
| +}
|
|
|
| -EVALUATE(BRCT) { return DecodeInstructionOriginal(instr); }
|
| +EVALUATE(BRCT) {
|
| + DCHECK_OPCODE(BRCT);
|
| + // Branch On Count (32/64).
|
| + DECODE_RI_A_INSTRUCTION(instr, r1, i2);
|
| + int64_t value = get_low_register<int32_t>(r1);
|
| + set_low_register(r1, --value);
|
| + // Branch if value != 0
|
| + if (value != 0) {
|
| + intptr_t offset = i2 * 2;
|
| + set_pc(get_pc() + offset);
|
| + }
|
| + return length;
|
| +}
|
|
|
| -EVALUATE(BRCTG) { return DecodeInstructionOriginal(instr); }
|
| +EVALUATE(BRCTG) {
|
| + DCHECK_OPCODE(BRCTG);
|
| + // Branch On Count (32/64).
|
| + DECODE_RI_A_INSTRUCTION(instr, r1, i2);
|
| + int64_t value = get_register(r1);
|
| + set_register(r1, --value);
|
| + // Branch if value != 0
|
| + if (value != 0) {
|
| + intptr_t offset = i2 * 2;
|
| + set_pc(get_pc() + offset);
|
| + }
|
| + return length;
|
| +}
|
|
|
| -EVALUATE(LHI) { return DecodeInstructionOriginal(instr); }
|
| +EVALUATE(LHI) {
|
| + DCHECK_OPCODE(LHI);
|
| + DECODE_RI_A_INSTRUCTION(instr, r1, i);
|
| + set_low_register(r1, i);
|
| + return length;
|
| +}
|
|
|
| -EVALUATE(LGHI) { return DecodeInstructionOriginal(instr); }
|
| +EVALUATE(LGHI) {
|
| + DCHECK_OPCODE(LGHI);
|
| + DECODE_RI_A_INSTRUCTION(instr, r1, i2);
|
| + int64_t i = static_cast<int64_t>(i2);
|
| + set_register(r1, i);
|
| + return length;
|
| +}
|
|
|
| -EVALUATE(MHI) { return DecodeInstructionOriginal(instr); }
|
| +EVALUATE(MHI) {
|
| + DCHECK_OPCODE(MHI);
|
| + DECODE_RI_A_INSTRUCTION(instr, r1, i);
|
| + int32_t r1_val = get_low_register<int32_t>(r1);
|
| + bool isOF = false;
|
| + isOF = CheckOverflowForMul(r1_val, i);
|
| + r1_val *= i;
|
| + set_low_register(r1, r1_val);
|
| + SetS390ConditionCode<int32_t>(r1_val, 0);
|
| + SetS390OverflowCode(isOF);
|
| + return length;
|
| +}
|
|
|
| -EVALUATE(MGHI) { return DecodeInstructionOriginal(instr); }
|
| +EVALUATE(MGHI) {
|
| + DCHECK_OPCODE(MGHI);
|
| + DECODE_RI_A_INSTRUCTION(instr, r1, i2);
|
| + int64_t i = static_cast<int64_t>(i2);
|
| + int64_t r1_val = get_register(r1);
|
| + bool isOF = false;
|
| + isOF = CheckOverflowForMul(r1_val, i);
|
| + r1_val *= i;
|
| + set_register(r1, r1_val);
|
| + SetS390ConditionCode<int32_t>(r1_val, 0);
|
| + SetS390OverflowCode(isOF);
|
| + return length;
|
| +}
|
|
|
| -EVALUATE(CHI) { return DecodeInstructionOriginal(instr); }
|
| +EVALUATE(CHI) {
|
| + DCHECK_OPCODE(CHI);
|
| + DECODE_RI_A_INSTRUCTION(instr, r1, i);
|
| + int32_t r1_val = get_low_register<int32_t>(r1);
|
| + SetS390ConditionCode<int32_t>(r1_val, i);
|
| + return length;
|
| +}
|
|
|
| -EVALUATE(CGHI) { return DecodeInstructionOriginal(instr); }
|
| +EVALUATE(CGHI) {
|
| + DCHECK_OPCODE(CGHI);
|
| + DECODE_RI_A_INSTRUCTION(instr, r1, i2);
|
| + int64_t i = static_cast<int64_t>(i2);
|
| + int64_t r1_val = get_register(r1);
|
| + SetS390ConditionCode<int64_t>(r1_val, i);
|
| + return length;
|
| +}
|
|
|
| -EVALUATE(LARL) { return DecodeInstructionOriginal(instr); }
|
| +EVALUATE(LARL) {
|
| + DCHECK_OPCODE(LARL);
|
| + DECODE_RIL_B_INSTRUCTION(r1, i2);
|
| + intptr_t offset = i2 * 2;
|
| + set_register(r1, get_pc() + offset);
|
| + return length;
|
| +}
|
|
|
| EVALUATE(LGFI) { return DecodeInstructionOriginal(instr); }
|
|
|
| -EVALUATE(BRASL) { return DecodeInstructionOriginal(instr); }
|
| +EVALUATE(BRASL) {
|
| + DCHECK_OPCODE(BRASL);
|
| + // Branch and Save Relative Long
|
| + DECODE_RIL_B_INSTRUCTION(r1, i2);
|
| + intptr_t d2 = i2;
|
| + intptr_t pc = get_pc();
|
| + set_register(r1, pc + 6); // save next instruction to register
|
| + set_pc(pc + d2 * 2); // update register
|
| + return length;
|
| +}
|
|
|
| -EVALUATE(XIHF) { return DecodeInstructionOriginal(instr); }
|
| +EVALUATE(XIHF) {
|
| + DCHECK_OPCODE(XIHF);
|
| + DECODE_RIL_A_INSTRUCTION(r1, imm);
|
| + uint32_t alu_out = 0;
|
| + alu_out = get_high_register<uint32_t>(r1);
|
| + alu_out = alu_out ^ imm;
|
| + set_high_register(r1, alu_out);
|
| + SetS390BitWiseConditionCode<uint32_t>(alu_out);
|
| + return length;
|
| +}
|
| +
|
| +EVALUATE(XILF) {
|
| + DCHECK_OPCODE(XILF);
|
| + DECODE_RIL_A_INSTRUCTION(r1, imm);
|
| + uint32_t alu_out = 0;
|
| + alu_out = get_low_register<uint32_t>(r1);
|
| + alu_out = alu_out ^ imm;
|
| + set_low_register(r1, alu_out);
|
| + SetS390BitWiseConditionCode<uint32_t>(alu_out);
|
| + return length;
|
| +}
|
|
|
| -EVALUATE(XILF) { return DecodeInstructionOriginal(instr); }
|
| +EVALUATE(NIHF) {
|
| + DCHECK_OPCODE(NIHF);
|
| + // Bitwise Op on upper 32-bits
|
| + DECODE_RIL_A_INSTRUCTION(r1, imm);
|
| + uint32_t alu_out = get_high_register<uint32_t>(r1);
|
| + alu_out &= imm;
|
| + SetS390BitWiseConditionCode<uint32_t>(alu_out);
|
| + set_high_register(r1, alu_out);
|
| + return length;
|
| +}
|
|
|
| -EVALUATE(NIHF) { return DecodeInstructionOriginal(instr); }
|
| +EVALUATE(NILF) {
|
| + DCHECK_OPCODE(NILF);
|
| + // Bitwise Op on lower 32-bits
|
| + DECODE_RIL_A_INSTRUCTION(r1, imm);
|
| + uint32_t alu_out = get_low_register<uint32_t>(r1);
|
| + alu_out &= imm;
|
| + SetS390BitWiseConditionCode<uint32_t>(alu_out);
|
| + set_low_register(r1, alu_out);
|
| + return length;
|
| +}
|
|
|
| -EVALUATE(NILF) { return DecodeInstructionOriginal(instr); }
|
| +EVALUATE(OIHF) {
|
| + DCHECK_OPCODE(OIHF);
|
| + // Bitwise Op on upper 32-bits
|
| + DECODE_RIL_B_INSTRUCTION(r1, imm);
|
| + uint32_t alu_out = get_high_register<uint32_t>(r1);
|
| + alu_out |= imm;
|
| + SetS390BitWiseConditionCode<uint32_t>(alu_out);
|
| + set_high_register(r1, alu_out);
|
| + return length;
|
| +}
|
|
|
| -EVALUATE(OIHF) { return DecodeInstructionOriginal(instr); }
|
| +EVALUATE(OILF) {
|
| + DCHECK_OPCODE(OILF);
|
| + // Bitwise Op on lower 32-bits
|
| + DECODE_RIL_B_INSTRUCTION(r1, imm);
|
| + uint32_t alu_out = get_low_register<uint32_t>(r1);
|
| + alu_out |= imm;
|
| + SetS390BitWiseConditionCode<uint32_t>(alu_out);
|
| + set_low_register(r1, alu_out);
|
| + return length;
|
| +}
|
|
|
| -EVALUATE(OILF) { return DecodeInstructionOriginal(instr); }
|
| +EVALUATE(LLIHF) {
|
| + DCHECK_OPCODE(LLIHF);
|
| + // Load Logical Immediate into high word
|
| + DECODE_RIL_A_INSTRUCTION(r1, i2);
|
| + uint64_t imm = static_cast<uint64_t>(i2);
|
| + set_register(r1, imm << 32);
|
| + return length;
|
| +}
|
|
|
| -EVALUATE(LLIHF) { return DecodeInstructionOriginal(instr); }
|
| +EVALUATE(LLILF) {
|
| + DCHECK_OPCODE(LLILF);
|
| + // Load Logical into lower 32-bits (zero extend upper 32-bits)
|
| + DECODE_RIL_A_INSTRUCTION(r1, i2);
|
| + uint64_t imm = static_cast<uint64_t>(i2);
|
| + set_register(r1, imm);
|
| + return length;
|
| +}
|
|
|
| -EVALUATE(LLILF) { return DecodeInstructionOriginal(instr); }
|
| +EVALUATE(MSGFI) {
|
| + DCHECK_OPCODE(MSGFI);
|
| + DECODE_RIL_B_INSTRUCTION(r1, i2);
|
| + int64_t alu_out = get_register(r1);
|
| + alu_out = alu_out * i2;
|
| + set_register(r1, alu_out);
|
| + return length;
|
| +}
|
|
|
| -EVALUATE(MSGFI) { return DecodeInstructionOriginal(instr); }
|
| +EVALUATE(MSFI) {
|
| + DCHECK_OPCODE(MSFI);
|
| + DECODE_RIL_B_INSTRUCTION(r1, i2);
|
| + int32_t alu_out = get_low_register<int32_t>(r1);
|
| + alu_out = alu_out * i2;
|
| + set_low_register(r1, alu_out);
|
| + return length;
|
| +}
|
|
|
| -EVALUATE(MSFI) { return DecodeInstructionOriginal(instr); }
|
| +EVALUATE(SLGFI) {
|
| + DCHECK_OPCODE(SLGFI);
|
| +#ifndef V8_TARGET_ARCH_S390X
|
| + // should only be called on 64bit
|
| + DCHECK(false);
|
| +#endif
|
| + DECODE_RIL_A_INSTRUCTION(r1, i2);
|
| + uint64_t r1_val = (uint64_t)(get_register(r1));
|
| + uint64_t alu_out;
|
| + alu_out = r1_val - i2;
|
| + set_register(r1, (intptr_t)alu_out);
|
| + SetS390ConditionCode<uint64_t>(alu_out, 0);
|
| + return length;
|
| +}
|
|
|
| -EVALUATE(SLGFI) { return DecodeInstructionOriginal(instr); }
|
| +EVALUATE(SLFI) {
|
| + DCHECK_OPCODE(SLFI);
|
| + DECODE_RIL_A_INSTRUCTION(r1, imm);
|
| + uint32_t alu_out = get_low_register<uint32_t>(r1);
|
| + alu_out -= imm;
|
| + SetS390ConditionCode<uint32_t>(alu_out, 0);
|
| + set_low_register(r1, alu_out);
|
| + return length;
|
| +}
|
|
|
| -EVALUATE(SLFI) { return DecodeInstructionOriginal(instr); }
|
| +EVALUATE(AGFI) {
|
| + DCHECK_OPCODE(AGFI);
|
| + // Clobbering Add Word Immediate
|
| + DECODE_RIL_B_INSTRUCTION(r1, i2_val);
|
| + bool isOF = false;
|
| + // 64-bit Add (Register + 32-bit Imm)
|
| + int64_t r1_val = get_register(r1);
|
| + int64_t i2 = static_cast<int64_t>(i2_val);
|
| + isOF = CheckOverflowForIntAdd(r1_val, i2, int64_t);
|
| + int64_t alu_out = r1_val + i2;
|
| + set_register(r1, alu_out);
|
| + SetS390ConditionCode<int64_t>(alu_out, 0);
|
| + SetS390OverflowCode(isOF);
|
| + return length;
|
| +}
|
|
|
| -EVALUATE(AGFI) { return DecodeInstructionOriginal(instr); }
|
| +EVALUATE(AFI) {
|
| + DCHECK_OPCODE(AFI);
|
| + // Clobbering Add Word Immediate
|
| + DECODE_RIL_B_INSTRUCTION(r1, i2);
|
| + bool isOF = false;
|
| + // 32-bit Add (Register + 32-bit Immediate)
|
| + int32_t r1_val = get_low_register<int32_t>(r1);
|
| + isOF = CheckOverflowForIntAdd(r1_val, i2, int32_t);
|
| + int32_t alu_out = r1_val + i2;
|
| + set_low_register(r1, alu_out);
|
| + SetS390ConditionCode<int32_t>(alu_out, 0);
|
| + SetS390OverflowCode(isOF);
|
| + return length;
|
| +}
|
|
|
| -EVALUATE(AFI) { return DecodeInstructionOriginal(instr); }
|
| +EVALUATE(ALGFI) {
|
| + DCHECK_OPCODE(ALGFI);
|
| +#ifndef V8_TARGET_ARCH_S390X
|
| + // should only be called on 64bit
|
| + DCHECK(false);
|
| +#endif
|
| + DECODE_RIL_A_INSTRUCTION(r1, i2);
|
| + uint64_t r1_val = (uint64_t)(get_register(r1));
|
| + uint64_t alu_out;
|
| + alu_out = r1_val + i2;
|
| + set_register(r1, (intptr_t)alu_out);
|
| + SetS390ConditionCode<uint64_t>(alu_out, 0);
|
|
|
| -EVALUATE(ALGFI) { return DecodeInstructionOriginal(instr); }
|
| + return length;
|
| +}
|
|
|
| -EVALUATE(ALFI) { return DecodeInstructionOriginal(instr); }
|
| +EVALUATE(ALFI) {
|
| + DCHECK_OPCODE(ALFI);
|
| + DECODE_RIL_A_INSTRUCTION(r1, imm);
|
| + uint32_t alu_out = get_low_register<uint32_t>(r1);
|
| + alu_out += imm;
|
| + SetS390ConditionCode<uint32_t>(alu_out, 0);
|
| + set_low_register(r1, alu_out);
|
| + return length;
|
| +}
|
|
|
| -EVALUATE(CGFI) { return DecodeInstructionOriginal(instr); }
|
| +EVALUATE(CGFI) {
|
| + DCHECK_OPCODE(CGFI);
|
| + // Compare with Immediate (64)
|
| + DECODE_RIL_B_INSTRUCTION(r1, i2);
|
| + int64_t imm = static_cast<int64_t>(i2);
|
| + SetS390ConditionCode<int64_t>(get_register(r1), imm);
|
| + return length;
|
| +}
|
|
|
| -EVALUATE(CFI) { return DecodeInstructionOriginal(instr); }
|
| +EVALUATE(CFI) {
|
| + DCHECK_OPCODE(CFI);
|
| + // Compare with Immediate (32)
|
| + DECODE_RIL_B_INSTRUCTION(r1, imm);
|
| + SetS390ConditionCode<int32_t>(get_low_register<int32_t>(r1), imm);
|
| + return length;
|
| +}
|
|
|
| -EVALUATE(CLGFI) { return DecodeInstructionOriginal(instr); }
|
| +EVALUATE(CLGFI) {
|
| + DCHECK_OPCODE(CLGFI);
|
| + // Compare Logical with Immediate (64)
|
| + DECODE_RIL_A_INSTRUCTION(r1, i2);
|
| + uint64_t imm = static_cast<uint64_t>(i2);
|
| + SetS390ConditionCode<uint64_t>(get_register(r1), imm);
|
| + return length;
|
| +}
|
|
|
| -EVALUATE(CLFI) { return DecodeInstructionOriginal(instr); }
|
| +EVALUATE(CLFI) {
|
| + DCHECK_OPCODE(CLFI);
|
| + // Compare Logical with Immediate (32)
|
| + DECODE_RIL_A_INSTRUCTION(r1, imm);
|
| + SetS390ConditionCode<uint32_t>(get_low_register<uint32_t>(r1), imm);
|
| + return length;
|
| +}
|
|
|
| EVALUATE(LLHRL) { return DecodeInstructionOriginal(instr); }
|
|
|
| @@ -6733,7 +7756,14 @@ EVALUATE(SAR) { return DecodeInstructionOriginal(instr); }
|
|
|
| EVALUATE(EAR) { return DecodeInstructionOriginal(instr); }
|
|
|
| -EVALUATE(MSR) { return DecodeInstructionOriginal(instr); }
|
| +EVALUATE(MSR) {
|
| + DCHECK_OPCODE(MSR);
|
| + DECODE_RRE_INSTRUCTION(r1, r2);
|
| + int32_t r1_val = get_low_register<int32_t>(r1);
|
| + int32_t r2_val = get_low_register<int32_t>(r2);
|
| + set_low_register(r1, r1_val * r2_val);
|
| + return length;
|
| +}
|
|
|
| EVALUATE(MVST) { return DecodeInstructionOriginal(instr); }
|
|
|
| @@ -6779,15 +7809,46 @@ EVALUATE(TABORT) { return DecodeInstructionOriginal(instr); }
|
|
|
| EVALUATE(TRAP4) { return DecodeInstructionOriginal(instr); }
|
|
|
| -EVALUATE(LPEBR) { return DecodeInstructionOriginal(instr); }
|
| +EVALUATE(LPEBR) {
|
| + DCHECK_OPCODE(LPEBR);
|
| + DECODE_RRE_INSTRUCTION(r1, r2);
|
| + float fr1_val = get_float32_from_d_register(r1);
|
| + float fr2_val = get_float32_from_d_register(r2);
|
| + fr1_val = std::fabs(fr2_val);
|
| + set_d_register_from_float32(r1, fr1_val);
|
| + if (fr2_val != fr2_val) { // input is NaN
|
| + condition_reg_ = CC_OF;
|
| + } else if (fr2_val == 0) {
|
| + condition_reg_ = CC_EQ;
|
| + } else {
|
| + condition_reg_ = CC_GT;
|
| + }
|
| +
|
| + return length;
|
| +}
|
|
|
| EVALUATE(LNEBR) { return DecodeInstructionOriginal(instr); }
|
|
|
| -EVALUATE(LTEBR) { return DecodeInstructionOriginal(instr); }
|
| +EVALUATE(LTEBR) {
|
| + DCHECK_OPCODE(LTEBR);
|
| + DECODE_RRE_INSTRUCTION(r1, r2);
|
| + int64_t r2_val = get_d_register(r2);
|
| + float fr2_val = get_float32_from_d_register(r2);
|
| + SetS390ConditionCode<float>(fr2_val, 0.0);
|
| + set_d_register(r1, r2_val);
|
| + return length;
|
| +}
|
|
|
| EVALUATE(LCEBR) { return DecodeInstructionOriginal(instr); }
|
|
|
| -EVALUATE(LDEBR) { return DecodeInstructionOriginal(instr); }
|
| +EVALUATE(LDEBR) {
|
| + DCHECK_OPCODE(LDEBR);
|
| + DECODE_RRE_INSTRUCTION(r1, r2);
|
| + float fp_val = get_float32_from_d_register(r2);
|
| + double db_val = static_cast<double>(fp_val);
|
| + set_d_register_from_double(r1, db_val);
|
| + return length;
|
| +}
|
|
|
| EVALUATE(LXDBR) { return DecodeInstructionOriginal(instr); }
|
|
|
| @@ -6797,27 +7858,108 @@ EVALUATE(MXDBR) { return DecodeInstructionOriginal(instr); }
|
|
|
| EVALUATE(KEBR) { return DecodeInstructionOriginal(instr); }
|
|
|
| -EVALUATE(CEBR) { return DecodeInstructionOriginal(instr); }
|
| +EVALUATE(CEBR) {
|
| + DCHECK_OPCODE(CEBR);
|
| + DECODE_RRE_INSTRUCTION(r1, r2);
|
| + float fr1_val = get_float32_from_d_register(r1);
|
| + float fr2_val = get_float32_from_d_register(r2);
|
| + if (isNaN(fr1_val) || isNaN(fr2_val)) {
|
| + condition_reg_ = CC_OF;
|
| + } else {
|
| + SetS390ConditionCode<float>(fr1_val, fr2_val);
|
| + }
|
| +
|
| + return length;
|
| +}
|
|
|
| -EVALUATE(AEBR) { return DecodeInstructionOriginal(instr); }
|
| +EVALUATE(AEBR) {
|
| + DCHECK_OPCODE(AEBR);
|
| + DECODE_RRE_INSTRUCTION(r1, r2);
|
| + float fr1_val = get_float32_from_d_register(r1);
|
| + float fr2_val = get_float32_from_d_register(r2);
|
| + fr1_val += fr2_val;
|
| + set_d_register_from_float32(r1, fr1_val);
|
| + SetS390ConditionCode<float>(fr1_val, 0);
|
|
|
| -EVALUATE(SEBR) { return DecodeInstructionOriginal(instr); }
|
| + return length;
|
| +}
|
| +
|
| +EVALUATE(SEBR) {
|
| + DCHECK_OPCODE(SEBR);
|
| + DECODE_RRE_INSTRUCTION(r1, r2);
|
| + float fr1_val = get_float32_from_d_register(r1);
|
| + float fr2_val = get_float32_from_d_register(r2);
|
| + fr1_val -= fr2_val;
|
| + set_d_register_from_float32(r1, fr1_val);
|
| + SetS390ConditionCode<float>(fr1_val, 0);
|
| +
|
| + return length;
|
| +}
|
|
|
| EVALUATE(MDEBR) { return DecodeInstructionOriginal(instr); }
|
|
|
| -EVALUATE(DEBR) { return DecodeInstructionOriginal(instr); }
|
| +EVALUATE(DEBR) {
|
| + DCHECK_OPCODE(DEBR);
|
| + DECODE_RRE_INSTRUCTION(r1, r2);
|
| + float fr1_val = get_float32_from_d_register(r1);
|
| + float fr2_val = get_float32_from_d_register(r2);
|
| + fr1_val /= fr2_val;
|
| + set_d_register_from_float32(r1, fr1_val);
|
| + SetS390ConditionCode<float>(fr1_val, 0);
|
| +
|
| + return length;
|
| +}
|
|
|
| EVALUATE(MAEBR) { return DecodeInstructionOriginal(instr); }
|
|
|
| EVALUATE(MSEBR) { return DecodeInstructionOriginal(instr); }
|
|
|
| -EVALUATE(LPDBR) { return DecodeInstructionOriginal(instr); }
|
| +EVALUATE(LPDBR) {
|
| + DCHECK_OPCODE(LPDBR);
|
| + DECODE_RRE_INSTRUCTION(r1, r2);
|
| + double r1_val = get_double_from_d_register(r1);
|
| + double r2_val = get_double_from_d_register(r2);
|
| + r1_val = std::fabs(r2_val);
|
| + set_d_register_from_double(r1, r1_val);
|
| + if (r2_val != r2_val) { // input is NaN
|
| + condition_reg_ = CC_OF;
|
| + } else if (r2_val == 0) {
|
| + condition_reg_ = CC_EQ;
|
| + } else {
|
| + condition_reg_ = CC_GT;
|
| + }
|
| + return length;
|
| +}
|
|
|
| EVALUATE(LNDBR) { return DecodeInstructionOriginal(instr); }
|
|
|
| -EVALUATE(LTDBR) { return DecodeInstructionOriginal(instr); }
|
| +EVALUATE(LTDBR) {
|
| + DCHECK_OPCODE(LTDBR);
|
| + DECODE_RRE_INSTRUCTION(r1, r2);
|
| + int64_t r2_val = get_d_register(r2);
|
| + SetS390ConditionCode<double>(bit_cast<double, int64_t>(r2_val), 0.0);
|
| + set_d_register(r1, r2_val);
|
| + return length;
|
| +}
|
|
|
| -EVALUATE(LCDBR) { return DecodeInstructionOriginal(instr); }
|
| +EVALUATE(LCDBR) {
|
| + DCHECK_OPCODE(LCDBR);
|
| + DECODE_RRE_INSTRUCTION(r1, r2);
|
| + double r1_val = get_double_from_d_register(r1);
|
| + double r2_val = get_double_from_d_register(r2);
|
| + r1_val = -r2_val;
|
| + set_d_register_from_double(r1, r1_val);
|
| + if (r2_val != r2_val) { // input is NaN
|
| + condition_reg_ = CC_OF;
|
| + } else if (r2_val == 0) {
|
| + condition_reg_ = CC_EQ;
|
| + } else if (r2_val < 0) {
|
| + condition_reg_ = CC_LT;
|
| + } else if (r2_val > 0) {
|
| + condition_reg_ = CC_GT;
|
| + }
|
| + return length;
|
| +}
|
|
|
| EVALUATE(SQEBR) { return DecodeInstructionOriginal(instr); }
|
|
|
|
|