Index: src/s390/simulator-s390.cc |
diff --git a/src/s390/simulator-s390.cc b/src/s390/simulator-s390.cc |
index 5d50b615a11627ffde1b8a611d90210759b0fc8d..b7f4e3dd0ac1a72f7f4341721b5790cc340d77fe 100644 |
--- a/src/s390/simulator-s390.cc |
+++ b/src/s390/simulator-s390.cc |
@@ -1822,8 +1822,7 @@ bool Simulator::DecodeTwoByte(Instruction* instr) { |
UNREACHABLE(); |
} |
set_low_register(r1, alu_out); |
- SetS390ConditionCode<uint32_t>(alu_out, 0); |
- SetS390OverflowCode(isOF); |
+ SetS390ConditionCodeCarry<uint32_t>(alu_out, isOF); |
break; |
} |
case LNR: { |
@@ -2457,13 +2456,9 @@ bool Simulator::DecodeFourByte(Instruction* instr) { |
return true; |
} |
-/** |
- * Decodes and simulates four byte arithmetic instructions |
- */ |
-bool Simulator::DecodeFourByteArithmetic(Instruction* instr) { |
+bool Simulator::DecodeFourByteArithmetic64Bit(Instruction* instr) { |
Opcode op = instr->S390OpcodeValue(); |
- // Pre-cast instruction to various types |
RRFInstruction* rrfInst = reinterpret_cast<RRFInstruction*>(instr); |
RREInstruction* rreInst = reinterpret_cast<RREInstruction*>(instr); |
@@ -2537,6 +2532,112 @@ bool Simulator::DecodeFourByteArithmetic(Instruction* instr) { |
set_register(r1, r1_val); |
break; |
} |
+ case AGRK: |
+ case SGRK: |
+ case NGRK: |
+ case OGRK: |
+ case XGRK: { |
+ // 64-bit Non-clobbering arithmetics / bitwise ops. |
+ int r1 = rrfInst->R1Value(); |
+ int r2 = rrfInst->R2Value(); |
+ int r3 = rrfInst->R3Value(); |
+ int64_t r2_val = get_register(r2); |
+ int64_t r3_val = get_register(r3); |
+ if (AGRK == op) { |
+ bool isOF = CheckOverflowForIntAdd(r2_val, r3_val, int64_t); |
+ SetS390ConditionCode<int64_t>(r2_val + r3_val, 0); |
+ SetS390OverflowCode(isOF); |
+ set_register(r1, r2_val + r3_val); |
+ } else if (SGRK == op) { |
+ bool isOF = CheckOverflowForIntSub(r2_val, r3_val, int64_t); |
+ SetS390ConditionCode<int64_t>(r2_val - r3_val, 0); |
+ SetS390OverflowCode(isOF); |
+ set_register(r1, r2_val - r3_val); |
+ } else { |
+ // Assume bitwise operation here |
+ uint64_t bitwise_result = 0; |
+ if (NGRK == op) { |
+ bitwise_result = r2_val & r3_val; |
+ } else if (OGRK == op) { |
+ bitwise_result = r2_val | r3_val; |
+ } else if (XGRK == op) { |
+ bitwise_result = r2_val ^ r3_val; |
+ } |
+ SetS390BitWiseConditionCode<uint64_t>(bitwise_result); |
+ set_register(r1, bitwise_result); |
+ } |
+ break; |
+ } |
+ case ALGRK: |
+ case SLGRK: { |
+ // 64-bit Non-clobbering unsigned arithmetics |
+ int r1 = rrfInst->R1Value(); |
+ int r2 = rrfInst->R2Value(); |
+ int r3 = rrfInst->R3Value(); |
+ uint64_t r2_val = get_register(r2); |
+ uint64_t r3_val = get_register(r3); |
+ if (ALGRK == op) { |
+ bool isOF = CheckOverflowForUIntAdd(r2_val, r3_val); |
+ SetS390ConditionCode<uint64_t>(r2_val + r3_val, 0); |
+ SetS390OverflowCode(isOF); |
+ set_register(r1, r2_val + r3_val); |
+ } else if (SLGRK == op) { |
+ bool isOF = CheckOverflowForUIntSub(r2_val, r3_val); |
+ SetS390ConditionCode<uint64_t>(r2_val - r3_val, 0); |
+ SetS390OverflowCode(isOF); |
+ set_register(r1, r2_val - r3_val); |
+ } |
+ } |
+ case AGHI: |
+ case MGHI: { |
+ RIInstruction* riinst = reinterpret_cast<RIInstruction*>(instr); |
+ int32_t r1 = riinst->R1Value(); |
+ int64_t i = static_cast<int64_t>(riinst->I2Value()); |
+ int64_t r1_val = get_register(r1); |
+ bool isOF = false; |
+ switch (op) { |
+ case AGHI: |
+ isOF = CheckOverflowForIntAdd(r1_val, i, int64_t); |
+ r1_val += i; |
+ break; |
+ case MGHI: |
+ isOF = CheckOverflowForMul(r1_val, i); |
+ r1_val *= i; |
+ break; // no overflow indication is given |
+ default: |
+ break; |
+ } |
+ set_register(r1, r1_val); |
+ SetS390ConditionCode<int32_t>(r1_val, 0); |
+ SetS390OverflowCode(isOF); |
+ break; |
+ } |
+ default: |
+ UNREACHABLE(); |
+ } |
+ return true; |
+} |
+ |
+/** |
+ * Decodes and simulates four byte arithmetic instructions |
+ */ |
+bool Simulator::DecodeFourByteArithmetic(Instruction* instr) { |
+ Opcode op = instr->S390OpcodeValue(); |
+ |
+ // Pre-cast instruction to various types |
+ RRFInstruction* rrfInst = reinterpret_cast<RRFInstruction*>(instr); |
+ |
+ switch (op) { |
+ case AGR: |
+ case SGR: |
+ case OGR: |
+ case NGR: |
+ case XGR: |
+ case AGFR: |
+ case SGFR: { |
+ DecodeFourByteArithmetic64Bit(instr); |
+ break; |
+ } |
case ARK: |
case SRK: |
case NRK: |
@@ -2599,56 +2700,12 @@ bool Simulator::DecodeFourByteArithmetic(Instruction* instr) { |
case NGRK: |
case OGRK: |
case XGRK: { |
- // 64-bit Non-clobbering arithmetics / bitwise ops. |
- int r1 = rrfInst->R1Value(); |
- int r2 = rrfInst->R2Value(); |
- int r3 = rrfInst->R3Value(); |
- int64_t r2_val = get_register(r2); |
- int64_t r3_val = get_register(r3); |
- if (AGRK == op) { |
- bool isOF = CheckOverflowForIntAdd(r2_val, r3_val, int64_t); |
- SetS390ConditionCode<int64_t>(r2_val + r3_val, 0); |
- SetS390OverflowCode(isOF); |
- set_register(r1, r2_val + r3_val); |
- } else if (SGRK == op) { |
- bool isOF = CheckOverflowForIntSub(r2_val, r3_val, int64_t); |
- SetS390ConditionCode<int64_t>(r2_val - r3_val, 0); |
- SetS390OverflowCode(isOF); |
- set_register(r1, r2_val - r3_val); |
- } else { |
- // Assume bitwise operation here |
- uint64_t bitwise_result = 0; |
- if (NGRK == op) { |
- bitwise_result = r2_val & r3_val; |
- } else if (OGRK == op) { |
- bitwise_result = r2_val | r3_val; |
- } else if (XGRK == op) { |
- bitwise_result = r2_val ^ r3_val; |
- } |
- SetS390BitWiseConditionCode<uint64_t>(bitwise_result); |
- set_register(r1, bitwise_result); |
- } |
+ DecodeFourByteArithmetic64Bit(instr); |
break; |
} |
case ALGRK: |
case SLGRK: { |
- // 64-bit Non-clobbering unsigned arithmetics |
- int r1 = rrfInst->R1Value(); |
- int r2 = rrfInst->R2Value(); |
- int r3 = rrfInst->R3Value(); |
- uint64_t r2_val = get_register(r2); |
- uint64_t r3_val = get_register(r3); |
- if (ALGRK == op) { |
- bool isOF = CheckOverflowForUIntAdd(r2_val, r3_val); |
- SetS390ConditionCode<uint64_t>(r2_val + r3_val, 0); |
- SetS390OverflowCode(isOF); |
- set_register(r1, r2_val + r3_val); |
- } else if (SLGRK == op) { |
- bool isOF = CheckOverflowForUIntSub(r2_val, r3_val); |
- SetS390ConditionCode<uint64_t>(r2_val - r3_val, 0); |
- SetS390OverflowCode(isOF); |
- set_register(r1, r2_val - r3_val); |
- } |
+ DecodeFourByteArithmetic64Bit(instr); |
break; |
} |
case AHI: |
@@ -2677,26 +2734,7 @@ bool Simulator::DecodeFourByteArithmetic(Instruction* instr) { |
} |
case AGHI: |
case MGHI: { |
- RIInstruction* riinst = reinterpret_cast<RIInstruction*>(instr); |
- int32_t r1 = riinst->R1Value(); |
- int64_t i = static_cast<int64_t>(riinst->I2Value()); |
- int64_t r1_val = get_register(r1); |
- bool isOF = false; |
- switch (op) { |
- case AGHI: |
- isOF = CheckOverflowForIntAdd(r1_val, i, int64_t); |
- r1_val += i; |
- break; |
- case MGHI: |
- isOF = CheckOverflowForMul(r1_val, i); |
- r1_val *= i; |
- break; // no overflow indication is given |
- default: |
- break; |
- } |
- set_register(r1, r1_val); |
- SetS390ConditionCode<int32_t>(r1_val, 0); |
- SetS390OverflowCode(isOF); |
+ DecodeFourByteArithmetic64Bit(instr); |
break; |
} |
case MLR: { |
@@ -2980,6 +3018,27 @@ bool Simulator::DecodeFourByteArithmetic(Instruction* instr) { |
#endif |
break; |
} |
+ case ALCR: { |
+ RREInstruction* rrinst = reinterpret_cast<RREInstruction*>(instr); |
+ int r1 = rrinst->R1Value(); |
+ int r2 = rrinst->R2Value(); |
+ 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; |
+ bool isOF_original = CheckOverflowForUIntAdd(r1_val, r2_val); |
+ if (TestConditionCode((Condition)2) || TestConditionCode((Condition)3)) { |
+ alu_out = alu_out + 1; |
+ isOF = isOF_original || CheckOverflowForUIntAdd(alu_out, 1); |
+ } else { |
+ isOF = isOF_original; |
+ } |
+ set_low_register(r1, alu_out); |
+ SetS390ConditionCodeCarry<uint32_t>(alu_out, isOF); |
+ break; |
+ } |
default: { return DecodeFourByteFloatingPoint(instr); } |
} |
return true; |