diff --git a/src/s390/simulator-s390.cc b/src/s390/simulator-s390.cc index ec1f66c0b3..75ed0fd2c6 100644 --- a/src/s390/simulator-s390.cc +++ b/src/s390/simulator-s390.cc @@ -1150,8 +1150,9 @@ bool Simulator::BorrowFrom(int32_t left, int32_t right) { } // Calculate V flag value for additions and subtractions. -bool Simulator::OverflowFrom(int32_t alu_out, int32_t left, int32_t right, - bool addition) { +template +bool Simulator::OverflowFromSigned(T1 alu_out, T1 left, T1 right, + bool addition) { bool overflow; if (addition) { // operands have the same sign @@ -1640,12 +1641,11 @@ void Simulator::PrintStopInfo(uint32_t code) { // (2) Test the result and one of the operands have opposite sign // (a) No overflow if they don't have opposite sign // (b) Overflow if opposite -#define CheckOverflowForIntAdd(src1, src2) \ - (((src1) ^ (src2)) < 0 ? false : ((((src1) + (src2)) ^ (src1)) < 0)) +#define CheckOverflowForIntAdd(src1, src2, type) \ + OverflowFromSigned(src1 + src2, src1, src2, true); -// Method for checking overflow on signed subtraction: -#define CheckOverflowForIntSub(src1, src2) \ - (((src1 - src2) < src1) != (src2 > 0)) +#define CheckOverflowForIntSub(src1, src2, type) \ + OverflowFromSigned(src1 - src2, src1, src2, false); // Method for checking overflow on unsigned addtion #define CheckOverflowForUIntAdd(src1, src2) \ @@ -1686,13 +1686,13 @@ bool Simulator::DecodeTwoByte(Instruction* instr) { bool isOF = false; switch (op) { case AR: - isOF = CheckOverflowForIntAdd(r1_val, r2_val); + isOF = CheckOverflowForIntAdd(r1_val, r2_val, int32_t); r1_val += r2_val; SetS390ConditionCode(r1_val, 0); SetS390OverflowCode(isOF); break; case SR: - isOF = CheckOverflowForIntSub(r1_val, r2_val); + isOF = CheckOverflowForIntSub(r1_val, r2_val, int32_t); r1_val -= r2_val; SetS390ConditionCode(r1_val, 0); SetS390OverflowCode(isOF); @@ -2461,13 +2461,13 @@ bool Simulator::DecodeFourByteArithmetic(Instruction* instr) { bool isOF = false; switch (op) { case AGR: - isOF = CheckOverflowForIntAdd(r1_val, r2_val); + isOF = CheckOverflowForIntAdd(r1_val, r2_val, int64_t); r1_val += r2_val; SetS390ConditionCode(r1_val, 0); SetS390OverflowCode(isOF); break; case SGR: - isOF = CheckOverflowForIntSub(r1_val, r2_val); + isOF = CheckOverflowForIntSub(r1_val, r2_val, int64_t); r1_val -= r2_val; SetS390ConditionCode(r1_val, 0); SetS390OverflowCode(isOF); @@ -2497,7 +2497,7 @@ bool Simulator::DecodeFourByteArithmetic(Instruction* instr) { int r2 = rreInst->R2Value(); int64_t r1_val = get_register(r1); int64_t r2_val = static_cast(get_low_register(r2)); - bool isOF = CheckOverflowForIntAdd(r1_val, r2_val); + bool isOF = CheckOverflowForIntAdd(r1_val, r2_val, int64_t); r1_val += r2_val; SetS390ConditionCode(r1_val, 0); SetS390OverflowCode(isOF); @@ -2511,7 +2511,7 @@ bool Simulator::DecodeFourByteArithmetic(Instruction* instr) { int64_t r1_val = get_register(r1); int64_t r2_val = static_cast(get_low_register(r2)); bool isOF = false; - isOF = CheckOverflowForIntSub(r1_val, r2_val); + isOF = CheckOverflowForIntSub(r1_val, r2_val, int64_t); r1_val -= r2_val; SetS390ConditionCode(r1_val, 0); SetS390OverflowCode(isOF); @@ -2530,12 +2530,12 @@ bool Simulator::DecodeFourByteArithmetic(Instruction* instr) { int32_t r2_val = get_low_register(r2); int32_t r3_val = get_low_register(r3); if (ARK == op) { - bool isOF = CheckOverflowForIntAdd(r2_val, r3_val); + bool isOF = CheckOverflowForIntAdd(r2_val, r3_val, int32_t); SetS390ConditionCode(r2_val + r3_val, 0); SetS390OverflowCode(isOF); set_low_register(r1, r2_val + r3_val); } else if (SRK == op) { - bool isOF = CheckOverflowForIntSub(r2_val, r3_val); + bool isOF = CheckOverflowForIntSub(r2_val, r3_val, int32_t); SetS390ConditionCode(r2_val - r3_val, 0); SetS390OverflowCode(isOF); set_low_register(r1, r2_val - r3_val); @@ -2587,12 +2587,12 @@ bool Simulator::DecodeFourByteArithmetic(Instruction* instr) { int64_t r2_val = get_register(r2); int64_t r3_val = get_register(r3); if (AGRK == op) { - bool isOF = CheckOverflowForIntAdd(r2_val, r3_val); + bool isOF = CheckOverflowForIntAdd(r2_val, r3_val, int64_t); SetS390ConditionCode(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); + bool isOF = CheckOverflowForIntSub(r2_val, r3_val, int64_t); SetS390ConditionCode(r2_val - r3_val, 0); SetS390OverflowCode(isOF); set_register(r1, r2_val - r3_val); @@ -2635,13 +2635,13 @@ bool Simulator::DecodeFourByteArithmetic(Instruction* instr) { case AHI: case MHI: { RIInstruction* riinst = reinterpret_cast(instr); - int r1 = riinst->R1Value(); - int i = riinst->I2Value(); + int32_t r1 = riinst->R1Value(); + int32_t i = riinst->I2Value(); int32_t r1_val = get_low_register(r1); bool isOF = false; switch (op) { case AHI: - isOF = CheckOverflowForIntAdd(r1_val, i); + isOF = CheckOverflowForIntAdd(r1_val, i, int32_t); r1_val += i; break; case MHI: @@ -2659,13 +2659,13 @@ bool Simulator::DecodeFourByteArithmetic(Instruction* instr) { case AGHI: case MGHI: { RIInstruction* riinst = reinterpret_cast(instr); - int r1 = riinst->R1Value(); + int32_t r1 = riinst->R1Value(); int64_t i = static_cast(riinst->I2Value()); int64_t r1_val = get_register(r1); bool isOF = false; switch (op) { case AGHI: - isOF = CheckOverflowForIntAdd(r1_val, i); + isOF = CheckOverflowForIntAdd(r1_val, i, int64_t); r1_val += i; break; case MGHI: @@ -2752,13 +2752,13 @@ bool Simulator::DecodeFourByteArithmetic(Instruction* instr) { bool isOF = false; switch (op) { case A: - isOF = CheckOverflowForIntAdd(r1_val, mem_val); + isOF = CheckOverflowForIntAdd(r1_val, mem_val, int32_t); alu_out = r1_val + mem_val; SetS390ConditionCode(alu_out, 0); SetS390OverflowCode(isOF); break; case S: - isOF = CheckOverflowForIntSub(r1_val, mem_val); + isOF = CheckOverflowForIntSub(r1_val, mem_val, int32_t); alu_out = r1_val - mem_val; SetS390ConditionCode(alu_out, 0); SetS390OverflowCode(isOF); @@ -2836,14 +2836,14 @@ bool Simulator::DecodeFourByteArithmetic(Instruction* instr) { 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; - int16_t mem_val = ReadH(addr, instr); + int32_t mem_val = static_cast(ReadH(addr, instr)); int32_t alu_out = 0; bool isOF = false; if (AH == op) { - isOF = CheckOverflowForIntAdd(r1_val, mem_val); + isOF = CheckOverflowForIntAdd(r1_val, mem_val, int32_t); alu_out = r1_val + mem_val; } else if (SH == op) { - isOF = CheckOverflowForIntSub(r1_val, mem_val); + isOF = CheckOverflowForIntSub(r1_val, mem_val, int32_t); alu_out = r1_val - mem_val; } else if (MH == op) { alu_out = r1_val * mem_val; @@ -4322,14 +4322,14 @@ bool Simulator::DecodeSixByteArithmetic(Instruction* instr) { // 32-bit Add int32_t r2_val = get_low_register(r2); int32_t imm = rieInst->I6Value(); - isOF = CheckOverflowForIntAdd(r2_val, imm); + isOF = CheckOverflowForIntAdd(r2_val, imm, int32_t); set_low_register(r1, r2_val + imm); SetS390ConditionCode(r2_val + imm, 0); } else if (AGHIK == op) { // 64-bit Add int64_t r2_val = get_register(r2); int64_t imm = static_cast(rieInst->I6Value()); - isOF = CheckOverflowForIntAdd(r2_val, imm); + isOF = CheckOverflowForIntAdd(r2_val, imm, int64_t); set_register(r1, r2_val + imm); SetS390ConditionCode(r2_val + imm, 0); } @@ -4372,12 +4372,12 @@ bool Simulator::DecodeSixByteArithmetic(Instruction* instr) { int32_t mem_val = ReadW(b2_val + x2_val + d2, instr); bool isOF = false; if (op == AY) { - isOF = CheckOverflowForIntAdd(alu_out, mem_val); + isOF = CheckOverflowForIntAdd(alu_out, mem_val, int32_t); alu_out += mem_val; SetS390ConditionCode(alu_out, 0); SetS390OverflowCode(isOF); } else if (op == SY) { - isOF = CheckOverflowForIntSub(alu_out, mem_val); + isOF = CheckOverflowForIntSub(alu_out, mem_val, int32_t); alu_out -= mem_val; SetS390ConditionCode(alu_out, 0); SetS390OverflowCode(isOF); @@ -4407,17 +4407,18 @@ bool Simulator::DecodeSixByteArithmetic(Instruction* instr) { int64_t b2_val = (b2 == 0) ? 0 : get_register(b2); int64_t x2_val = (x2 == 0) ? 0 : get_register(x2); intptr_t d2_val = rxyInstr->D2Value(); - int16_t mem_val = ReadH(b2_val + d2_val + x2_val, instr); + int32_t mem_val = + static_cast(ReadH(b2_val + d2_val + x2_val, instr)); int32_t alu_out = 0; bool isOF = false; switch (op) { case AHY: alu_out = r1_val + mem_val; - isOF = CheckOverflowForIntAdd(r1_val, mem_val); + isOF = CheckOverflowForIntAdd(r1_val, mem_val, int32_t); break; case SHY: alu_out = r1_val - mem_val; - isOF = CheckOverflowForIntSub(r1_val, mem_val); + isOF = CheckOverflowForIntSub(r1_val, mem_val, int64_t); break; default: UNREACHABLE(); @@ -4520,20 +4521,21 @@ bool Simulator::DecodeSixByteArithmetic(Instruction* instr) { case AFI: { // Clobbering Add Word Immediate RILInstruction* rilInstr = reinterpret_cast(instr); - int r1 = rilInstr->R1Value(); - int i2 = rilInstr->I2Value(); + int32_t r1 = rilInstr->R1Value(); bool isOF = false; if (AFI == op) { // 32-bit Add (Register + 32-bit Immediate) int32_t r1_val = get_low_register(r1); - isOF = CheckOverflowForIntAdd(r1_val, i2); + int32_t i2 = rilInstr->I2Value(); + isOF = CheckOverflowForIntAdd(r1_val, i2, int32_t); int32_t alu_out = r1_val + i2; set_low_register(r1, alu_out); SetS390ConditionCode(alu_out, 0); } else if (AGFI == op) { // 64-bit Add (Register + 32-bit Imm) int64_t r1_val = get_register(r1); - isOF = CheckOverflowForIntAdd(r1_val, i2); + int64_t i2 = static_cast(rilInstr->I2Value()); + isOF = CheckOverflowForIntAdd(r1_val, i2, int64_t); int64_t alu_out = r1_val + i2; set_register(r1, alu_out); SetS390ConditionCode(alu_out, 0); @@ -4542,7 +4544,12 @@ bool Simulator::DecodeSixByteArithmetic(Instruction* instr) { break; } case ASI: { - int8_t i2 = static_cast(siyInstr->I2Value()); + // TODO(bcleung): Change all fooInstr->I2Value() to template functions. + // The below static cast to 8 bit and then to 32 bit is necessary + // because siyInstr->I2Value() returns a uint8_t, which a direct + // cast to int32_t could incorrectly interpret. + int8_t i2_8bit = static_cast(siyInstr->I2Value()); + int32_t i2 = static_cast(i2_8bit); int b1 = siyInstr->B1Value(); intptr_t b1_val = (b1 == 0) ? 0 : get_register(b1); @@ -4550,7 +4557,7 @@ bool Simulator::DecodeSixByteArithmetic(Instruction* instr) { intptr_t addr = b1_val + d1_val; int32_t mem_val = ReadW(addr, instr); - bool isOF = CheckOverflowForIntAdd(mem_val, i2); + bool isOF = CheckOverflowForIntAdd(mem_val, i2, int32_t); int32_t alu_out = mem_val + i2; SetS390ConditionCode(alu_out, 0); SetS390OverflowCode(isOF); @@ -4558,7 +4565,12 @@ bool Simulator::DecodeSixByteArithmetic(Instruction* instr) { break; } case AGSI: { - int8_t i2 = static_cast(siyInstr->I2Value()); + // TODO(bcleung): Change all fooInstr->I2Value() to template functions. + // The below static cast to 8 bit and then to 32 bit is necessary + // because siyInstr->I2Value() returns a uint8_t, which a direct + // cast to int32_t could incorrectly interpret. + int8_t i2_8bit = static_cast(siyInstr->I2Value()); + int64_t i2 = static_cast(i2_8bit); int b1 = siyInstr->B1Value(); intptr_t b1_val = (b1 == 0) ? 0 : get_register(b1); @@ -4566,7 +4578,7 @@ bool Simulator::DecodeSixByteArithmetic(Instruction* instr) { intptr_t addr = b1_val + d1_val; int64_t mem_val = ReadDW(addr); - int isOF = CheckOverflowForIntAdd(mem_val, i2); + int isOF = CheckOverflowForIntAdd(mem_val, i2, int64_t); int64_t alu_out = mem_val + i2; SetS390ConditionCode(alu_out, 0); SetS390OverflowCode(isOF); diff --git a/src/s390/simulator-s390.h b/src/s390/simulator-s390.h index 1bdcf0b957..8fee5145e6 100644 --- a/src/s390/simulator-s390.h +++ b/src/s390/simulator-s390.h @@ -258,8 +258,8 @@ class Simulator { // Helper functions to set the conditional flags in the architecture state. bool CarryFrom(int32_t left, int32_t right, int32_t carry = 0); bool BorrowFrom(int32_t left, int32_t right); - bool OverflowFrom(int32_t alu_out, int32_t left, int32_t right, - bool addition); + template + inline bool OverflowFromSigned(T1 alu_out, T1 left, T1 right, bool addition); // Helper functions to decode common "addressing" modes int32_t GetShiftRm(Instruction* instr, bool* carry_out);