| Index: src/s390/simulator-s390.cc
|
| diff --git a/src/s390/simulator-s390.cc b/src/s390/simulator-s390.cc
|
| index ec1f66c0b3a02d6df823bb815826295c0b404a2f..75ed0fd2c6b742a18329f1e697e5213f536c96d9 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 <typename T1>
|
| +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<type>(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<type>(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<int32_t>(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<int32_t>(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<int64_t>(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<int64_t>(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<int64_t>(get_low_register<int32_t>(r2));
|
| - bool isOF = CheckOverflowForIntAdd(r1_val, r2_val);
|
| + bool isOF = CheckOverflowForIntAdd(r1_val, r2_val, int64_t);
|
| r1_val += r2_val;
|
| SetS390ConditionCode<int64_t>(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<int64_t>(get_low_register<int32_t>(r2));
|
| bool isOF = false;
|
| - isOF = CheckOverflowForIntSub(r1_val, r2_val);
|
| + isOF = CheckOverflowForIntSub(r1_val, r2_val, int64_t);
|
| r1_val -= r2_val;
|
| SetS390ConditionCode<int64_t>(r1_val, 0);
|
| SetS390OverflowCode(isOF);
|
| @@ -2530,12 +2530,12 @@ bool Simulator::DecodeFourByteArithmetic(Instruction* instr) {
|
| int32_t r2_val = get_low_register<int32_t>(r2);
|
| int32_t r3_val = get_low_register<int32_t>(r3);
|
| if (ARK == op) {
|
| - bool isOF = CheckOverflowForIntAdd(r2_val, r3_val);
|
| + bool isOF = CheckOverflowForIntAdd(r2_val, r3_val, int32_t);
|
| SetS390ConditionCode<int32_t>(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<int32_t>(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<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);
|
| + 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);
|
| @@ -2635,13 +2635,13 @@ bool Simulator::DecodeFourByteArithmetic(Instruction* instr) {
|
| case AHI:
|
| case MHI: {
|
| RIInstruction* riinst = reinterpret_cast<RIInstruction*>(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<int32_t>(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<RIInstruction*>(instr);
|
| - int r1 = riinst->R1Value();
|
| + 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);
|
| + 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<int32_t>(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<int32_t>(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<int32_t>(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<int32_t>(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<int32_t>(r2_val + imm, 0);
|
| } else if (AGHIK == op) {
|
| // 64-bit Add
|
| int64_t r2_val = get_register(r2);
|
| int64_t imm = static_cast<int64_t>(rieInst->I6Value());
|
| - isOF = CheckOverflowForIntAdd(r2_val, imm);
|
| + isOF = CheckOverflowForIntAdd(r2_val, imm, int64_t);
|
| set_register(r1, r2_val + imm);
|
| SetS390ConditionCode<int64_t>(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<int32_t>(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<int32_t>(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<int32_t>(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<RILInstruction*>(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<int32_t>(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<int32_t>(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<int64_t>(rilInstr->I2Value());
|
| + 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);
|
| @@ -4542,7 +4544,12 @@ bool Simulator::DecodeSixByteArithmetic(Instruction* instr) {
|
| break;
|
| }
|
| case ASI: {
|
| - int8_t i2 = static_cast<int8_t>(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<int8_t>(siyInstr->I2Value());
|
| + int32_t i2 = static_cast<int32_t>(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<int32_t>(alu_out, 0);
|
| SetS390OverflowCode(isOF);
|
| @@ -4558,7 +4565,12 @@ bool Simulator::DecodeSixByteArithmetic(Instruction* instr) {
|
| break;
|
| }
|
| case AGSI: {
|
| - int8_t i2 = static_cast<int8_t>(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<int8_t>(siyInstr->I2Value());
|
| + int64_t i2 = static_cast<int64_t>(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<uint64_t>(alu_out, 0);
|
| SetS390OverflowCode(isOF);
|
|
|