Commit 2fdc0ae3 authored by bryleun's avatar bryleun Committed by Commit bot

S390: Fixed condition code handling on FP->INT and FP rounding in simulator.

The below instructions were fixed so that the produced condition
codes in simulator matched behaviour in native s390 CPUs:

CFDBR
CGDBR
CGEBR
CFEBR
CLFDBR
CLGDBR
CLGEBR

Also implemented the CLFEBR instruction in s390 simulator.

(Copypaste of 1763663003, which was pointing at wrong branch - should be master, not lkgr)

R=danno@chromium.org,jkummerow@chromium.org,jochen@chromium.org,joransiu@ca.ibm.com,michael_dawson@ca.ibm.com,mbrandy@us.ibm.com,jyan@ca.ibm.com

BUG=

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

Cr-Commit-Position: refs/heads/master@{#34598}
parent 4ea11ca9
......@@ -2975,7 +2975,8 @@ void Simulator::DecodeFourByteFloatingPointIntConversion(Instruction* instr) {
case CLFDBR:
case CLGDBR:
case CELFBR:
case CLGEBR: {
case CLGEBR:
case CLFEBR: {
RREInstruction* rreInstr = reinterpret_cast<RREInstruction*>(instr);
int r1 = rreInstr->R1Value();
int r2 = rreInstr->R2Value();
......@@ -2999,17 +3000,22 @@ void Simulator::DecodeFourByteFloatingPointIntConversion(Instruction* instr) {
double r2_val = get_double_from_d_register(r2);
uint32_t r1_val = static_cast<uint32_t>(r2_val);
set_low_register(r1, r1_val);
SetS390ConditionCode<double>(r2_val, 0);
SetS390ConvertConditionCode<double>(r2_val, r1_val, UINT32_MAX);
} else if (op == CLFEBR) {
float r2_val = get_float32_from_d_register(r2);
uint32_t r1_val = static_cast<uint32_t>(r2_val);
set_low_register(r1, r1_val);
SetS390ConvertConditionCode<double>(r2_val, r1_val, UINT32_MAX);
} else if (op == CLGDBR) {
double r2_val = get_double_from_d_register(r2);
uint64_t r1_val = static_cast<uint64_t>(r2_val);
set_register(r1, r1_val);
SetS390ConditionCode<double>(r2_val, 0);
SetS390ConvertConditionCode<double>(r2_val, r1_val, UINT64_MAX);
} else if (op == CLGEBR) {
float r2_val = get_float32_from_d_register(r2);
uint64_t r1_val = static_cast<uint64_t>(r2_val);
set_register(r1, r1_val);
SetS390ConditionCode<double>(r2_val, 0);
SetS390ConvertConditionCode<double>(r2_val, r1_val, UINT64_MAX);
}
break;
}
......@@ -3031,14 +3037,7 @@ void Simulator::DecodeFourByteFloatingPointRound(Instruction* instr) {
int mask_val = rreInstr->M3Value();
int32_t r1_val = 0;
if (r2_val == 0.0)
condition_reg_ = 8;
else if (r2_val < 0.0)
condition_reg_ = 4;
else if (r2_val > 0.0)
condition_reg_ = 2;
else
condition_reg_ = 1;
SetS390RoundConditionCode(r2_val, INT32_MAX, INT32_MIN);
switch (mask_val) {
case CURRENT_ROUNDING_MODE:
......@@ -3119,14 +3118,7 @@ void Simulator::DecodeFourByteFloatingPointRound(Instruction* instr) {
int mask_val = rreInstr->M3Value();
int64_t r1_val = 0;
if (r2_val == 0.0)
condition_reg_ = 8;
else if (r2_val < 0.0)
condition_reg_ = 4;
else if (r2_val > 0.0)
condition_reg_ = 2;
else
condition_reg_ = 1;
SetS390RoundConditionCode(r2_val, INT64_MAX, INT64_MIN);
switch (mask_val) {
case CURRENT_ROUNDING_MODE:
......@@ -3175,14 +3167,7 @@ void Simulator::DecodeFourByteFloatingPointRound(Instruction* instr) {
int mask_val = rreInstr->M3Value();
int64_t r1_val = 0;
if (r2_fval == 0.0)
condition_reg_ = 8;
else if (r2_fval < 0.0)
condition_reg_ = 4;
else if (r2_fval > 0.0)
condition_reg_ = 2;
else
condition_reg_ = 1;
SetS390RoundConditionCode(r2_fval, INT64_MAX, INT64_MIN);
switch (mask_val) {
case CURRENT_ROUNDING_MODE:
......@@ -3231,14 +3216,7 @@ void Simulator::DecodeFourByteFloatingPointRound(Instruction* instr) {
int mask_val = rreInstr->M3Value();
int32_t r1_val = 0;
if (r2_fval == 0.0)
condition_reg_ = 8;
else if (r2_fval < 0.0)
condition_reg_ = 4;
else if (r2_fval > 0.0)
condition_reg_ = 2;
else
condition_reg_ = 1;
SetS390RoundConditionCode(r2_fval, INT32_MAX, INT32_MIN);
switch (mask_val) {
case CURRENT_ROUNDING_MODE:
......@@ -3487,7 +3465,8 @@ bool Simulator::DecodeFourByteFloatingPoint(Instruction* instr) {
case CLFDBR:
case CELFBR:
case CLGDBR:
case CLGEBR: {
case CLGEBR:
case CLFEBR: {
DecodeFourByteFloatingPointIntConversion(instr);
break;
}
......
......@@ -317,6 +317,66 @@ class Simulator {
bool DecodeSixByteArithmetic(Instruction* instr);
bool S390InstructionDecode(Instruction* instr);
// Used by the CL**BR instructions.
template <typename T1, typename T2>
void SetS390RoundConditionCode(T1 r2_val, T2 max, T2 min) {
condition_reg_ = 0;
double r2_dval = static_cast<double>(r2_val);
double dbl_min = static_cast<double>(min);
double dbl_max = static_cast<double>(max);
if (r2_dval == 0.0)
condition_reg_ = 8;
else if (r2_dval < 0.0 && r2_dval >= dbl_min && std::isfinite(r2_dval))
condition_reg_ = 4;
else if (r2_dval > 0.0 && r2_dval <= dbl_max && std::isfinite(r2_dval))
condition_reg_ = 2;
else
condition_reg_ = 1;
}
template <typename T1>
void SetS390RoundConditionCode(T1 r2_val, int64_t max, int64_t min) {
condition_reg_ = 0;
double r2_dval = static_cast<double>(r2_val);
double dbl_min = static_cast<double>(min);
double dbl_max = static_cast<double>(max);
// Note that the IEEE 754 floating-point representations (both 32 and
// 64 bit) cannot exactly represent INT64_MAX. The closest it can get
// is INT64_max + 1. IEEE 754 FP can, though, represent INT64_MIN
// exactly.
// This is not an issue for INT32, as IEEE754 64-bit can represent
// INT32_MAX and INT32_MIN with exact precision.
if (r2_dval == 0.0)
condition_reg_ = 8;
else if (r2_dval < 0.0 && r2_dval >= dbl_min && std::isfinite(r2_dval))
condition_reg_ = 4;
else if (r2_dval > 0.0 && r2_dval < dbl_max && std::isfinite(r2_dval))
condition_reg_ = 2;
else
condition_reg_ = 1;
}
// Used by the CL**BR instructions.
template <typename T1, typename T2, typename T3>
void SetS390ConvertConditionCode(T1 src, T2 dst, T3 max) {
condition_reg_ = 0;
if (src == static_cast<T1>(0.0)) {
condition_reg_ |= 8;
} else if (src < static_cast<T1>(0.0) && static_cast<T2>(src) == 0 &&
std::isfinite(src)) {
condition_reg_ |= 4;
} else if (src > static_cast<T1>(0.0) && std::isfinite(src) &&
src < static_cast<T1>(max)) {
condition_reg_ |= 2;
} else {
condition_reg_ |= 1;
}
}
template <typename T>
void SetS390ConditionCode(T lhs, T rhs) {
condition_reg_ = 0;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment