S390: Implemented ALCR in S390 simulator.

This CL implements the ALCR, add logical 32-bit integer with carry, instruction in the s390 simulator.

Some 64-bit operations in the 4-byte arithmetic section of the s390 simulator have been refactored into a separate function to stay below 500 lines.

R=michael_dawson@ca.ibm.com,jyan@ca.ibm.com,mbrandy@us.ibm.com,joransiu@ca.ibm.com,

BUG=

Review URL: https://codereview.chromium.org/1846673003

Cr-Commit-Position: refs/heads/master@{#35184}
This commit is contained in:
bryleun 2016-03-31 17:41:40 -07:00 committed by Commit bot
parent 86357d5235
commit 8760b602b7
2 changed files with 150 additions and 73 deletions

View File

@ -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;

View File

@ -309,6 +309,7 @@ class Simulator {
bool DecodeTwoByte(Instruction* instr);
bool DecodeFourByte(Instruction* instr);
bool DecodeFourByteArithmetic(Instruction* instr);
bool DecodeFourByteArithmetic64Bit(Instruction* instr);
bool DecodeFourByteFloatingPoint(Instruction* instr);
void DecodeFourByteFloatingPointIntConversion(Instruction* instr);
void DecodeFourByteFloatingPointRound(Instruction* instr);
@ -395,6 +396,23 @@ class Simulator {
if (condition_reg_ == 0) condition_reg_ = unordered;
}
// Used by arithmetic operations that use carry.
template <typename T>
void SetS390ConditionCodeCarry(T result, bool overflow) {
condition_reg_ = 0;
bool zero_result = (result == static_cast<T>(0));
if (zero_result && !overflow) {
condition_reg_ |= 8;
} else if (!zero_result && !overflow) {
condition_reg_ |= 4;
} else if (zero_result && overflow) {
condition_reg_ |= 2;
} else if (!zero_result && overflow) {
condition_reg_ |= 1;
}
if (condition_reg_ == 0) UNREACHABLE();
}
bool isNaN(double value) { return (value != value); }
// Set the condition code for bitwise operations