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:
parent
86357d5235
commit
8760b602b7
@ -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;
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user