Commit b9f92c15 authored by mbrandy's avatar mbrandy Committed by Commit bot

PPC64: [turbofan] Changed TruncateFloat64ToInt64 to TryTruncateFloat64ToInt64.

Port 95844d94

Original commit message:
    The new operator provides a second output which indicates whether the
    conversion from float64 to int64 was successful or not. The second
    output returns 0 if the conversion fails. If the conversion succeeds,
    then the second output is differs from 0.

    The second output can be ignored, which means that the operator can be
    used the same way as the original operator.

R=ahaas@chromium.org, joransiu@ca.ibm.com, jyan@ca.ibm.com, michael_dawson@ca.ibm.com
BUG=

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

Cr-Commit-Position: refs/heads/master@{#32724}
parent e94f07aa
......@@ -27,6 +27,8 @@ class PPCOperandConverter final : public InstructionOperandConverter {
PPCOperandConverter(CodeGenerator* gen, Instruction* instr)
: InstructionOperandConverter(gen, instr) {}
size_t OutputCount() { return instr_->OutputCount(); }
RCBit OutputRCBit() const {
switch (instr_->flags_mode()) {
case kFlags_branch:
......@@ -1157,14 +1159,32 @@ void CodeGenerator::AssembleArchInstruction(Instruction* instr) {
break;
case kPPC_DoubleToInt32:
case kPPC_DoubleToUint32:
case kPPC_DoubleToInt64:
case kPPC_DoubleToInt64: {
#if V8_TARGET_ARCH_PPC64
bool check_conversion =
(opcode == kPPC_DoubleToInt64 && i.OutputCount() > 1);
if (check_conversion) {
__ mtfsb0(VXCVI); // clear FPSCR:VXCVI bit
}
#endif
__ ConvertDoubleToInt64(i.InputDoubleRegister(0),
#if !V8_TARGET_ARCH_PPC64
kScratchReg,
#endif
i.OutputRegister(), kScratchDoubleReg);
i.OutputRegister(0), kScratchDoubleReg);
#if V8_TARGET_ARCH_PPC64
if (check_conversion) {
// Set 2nd output to zero if conversion fails.
CRBit crbit = static_cast<CRBit>(VXCVI % CRWIDTH);
__ mcrfs(cr7, VXCVI); // extract FPSCR field containing VXCVI into cr7
__ li(i.OutputRegister(1), Operand(1));
__ isel(i.OutputRegister(1), r0, i.OutputRegister(1),
v8::internal::Assembler::encode_crbit(cr7, crbit));
}
#endif
DCHECK_EQ(LeaveRC, i.OutputRCBit());
break;
}
#if V8_TARGET_ARCH_PPC64
case kPPC_DoubleToUint64:
__ ConvertDoubleToUnsignedInt64(i.InputDoubleRegister(0),
......
......@@ -933,11 +933,19 @@ void InstructionSelector::VisitTruncateFloat32ToInt64(Node* node) {
void InstructionSelector::VisitTryTruncateFloat64ToInt64(Node* node) {
if (NodeProperties::FindProjection(node, 1)) {
// TODO(ppc): implement the second return value.
UNIMPLEMENTED();
PPCOperandGenerator g(this);
InstructionOperand inputs[] = {g.UseRegister(node->InputAt(0))};
InstructionOperand outputs[2];
size_t output_count = 0;
outputs[output_count++] = g.DefineAsRegister(node);
Node* success_output = NodeProperties::FindProjection(node, 1);
if (success_output) {
outputs[output_count++] = g.DefineAsRegister(success_output);
}
VisitRR(this, kPPC_DoubleToInt64, node);
Emit(kPPC_DoubleToInt64, output_count, outputs, 1, inputs);
}
......
......@@ -1844,7 +1844,10 @@ void Assembler::mtxer(Register src) {
}
void Assembler::mcrfs(int bf, int bfa) {
void Assembler::mcrfs(CRegister cr, FPSCRBit bit) {
DCHECK(static_cast<int>(bit) < 32);
int bf = cr.code();
int bfa = bit / CRWIDTH;
emit(EXT4 | MCRFS | bf * B23 | bfa * B18);
}
......@@ -2219,6 +2222,20 @@ void Assembler::fneg(const DoubleRegister frt, const DoubleRegister frb,
}
void Assembler::mtfsb0(FPSCRBit bit, RCBit rc) {
DCHECK(static_cast<int>(bit) < 32);
int bt = bit;
emit(EXT4 | MTFSB0 | bt * B21 | rc);
}
void Assembler::mtfsb1(FPSCRBit bit, RCBit rc) {
DCHECK(static_cast<int>(bit) < 32);
int bt = bit;
emit(EXT4 | MTFSB1 | bt * B21 | rc);
}
void Assembler::mtfsfi(int bf, int immediate, RCBit rc) {
emit(EXT4 | MTFSFI | bf * B23 | immediate * B12 | rc);
}
......
......@@ -984,7 +984,7 @@ class Assembler : public AssemblerBase {
void mtlr(Register src);
void mtctr(Register src);
void mtxer(Register src);
void mcrfs(int bf, int bfa);
void mcrfs(CRegister cr, FPSCRBit bit);
void mfcr(Register dst);
#if V8_TARGET_ARCH_PPC64
void mffprd(Register dst, DoubleRegister src);
......@@ -1071,6 +1071,8 @@ class Assembler : public AssemblerBase {
RCBit rc = LeaveRC);
void fneg(const DoubleRegister frt, const DoubleRegister frb,
RCBit rc = LeaveRC);
void mtfsb0(FPSCRBit bit, RCBit rc = LeaveRC);
void mtfsb1(FPSCRBit bit, RCBit rc = LeaveRC);
void mtfsfi(int bf, int immediate, RCBit rc = LeaveRC);
void mffs(const DoubleRegister frt, RCBit rc = LeaveRC);
void mtfsf(const DoubleRegister frb, bool L = 1, int FLM = 0, bool W = 0,
......
......@@ -279,8 +279,10 @@ enum OpcodeExt4 {
FRSP = 12 << 1, // Floating-Point Rounding
FCTIW = 14 << 1, // Floating Convert to Integer Word X-form
FCTIWZ = 15 << 1, // Floating Convert to Integer Word with Round to Zero
MTFSB1 = 38 << 1, // Move to FPSCR Bit 1
FNEG = 40 << 1, // Floating Negate
MCRFS = 64 << 1, // Move to Condition Register from FPSCR
MTFSB0 = 70 << 1, // Move to FPSCR Bit 0
FMR = 72 << 1, // Floating Move Register
MTFSFI = 134 << 1, // Move to FPSCR Field Immediate
FABS = 264 << 1, // Floating Absolute Value
......@@ -402,6 +404,13 @@ enum CRBit { CR_LT = 0, CR_GT = 1, CR_EQ = 2, CR_SO = 3, CR_FU = 3 };
#define CRWIDTH 4
// These are the documented bit positions biased down by 32
enum FPSCRBit {
VXSOFT = 21, // 53: Software-Defined Condition
VXSQRT = 22, // 54: Invalid Square Root
VXCVI = 23 // 55: Invalid Integer Convert
};
// -----------------------------------------------------------------------------
// Supervisor Call (svc) specific support.
......
......@@ -1017,6 +1017,18 @@ void Decoder::DecodeExt4(Instruction* instr) {
Format(instr, "fneg'. 'Dt, 'Db");
break;
}
case MCRFS: {
Format(instr, "mcrfs ?,?");
break;
}
case MTFSB0: {
Format(instr, "mtfsb0'. ?");
break;
}
case MTFSB1: {
Format(instr, "mtfsb1'. ?");
break;
}
default: {
Unknown(instr); // not used by V8
}
......
......@@ -2916,11 +2916,14 @@ void Simulator::ExecuteExt4(Instruction* instr) {
int64_t one = 1; // work-around gcc
int64_t kMinLongLong = (one << 63);
int64_t kMaxLongLong = kMinLongLong - 1;
bool invalid_convert = false;
if (frb_val > kMaxLongLong) {
frt_val = kMaxLongLong;
} else if (frb_val < kMinLongLong) {
if (std::isnan(frb_val) || frb_val < kMinLongLong) {
frt_val = kMinLongLong;
invalid_convert = true;
} else if (frb_val > kMaxLongLong) {
frt_val = kMaxLongLong;
invalid_convert = true;
} else {
switch (fp_condition_reg_ & kFPRoundingModeMask) {
case kRoundToZero:
......@@ -2939,6 +2942,7 @@ void Simulator::ExecuteExt4(Instruction* instr) {
}
}
set_d_register(frt, frt_val);
if (invalid_convert) SetFPSCR(VXCVI);
return;
}
case FCTIDZ: {
......@@ -2949,15 +2953,19 @@ void Simulator::ExecuteExt4(Instruction* instr) {
int64_t one = 1; // work-around gcc
int64_t kMinLongLong = (one << 63);
int64_t kMaxLongLong = kMinLongLong - 1;
bool invalid_convert = false;
if (frb_val > kMaxLongLong) {
frt_val = kMaxLongLong;
} else if (frb_val < kMinLongLong) {
if (std::isnan(frb_val) || frb_val < kMinLongLong) {
frt_val = kMinLongLong;
invalid_convert = true;
} else if (frb_val > kMaxLongLong) {
frt_val = kMaxLongLong;
invalid_convert = true;
} else {
frt_val = (int64_t)frb_val;
}
set_d_register(frt, frt_val);
if (invalid_convert) SetFPSCR(VXCVI);
return;
}
case FCTIDU: {
......@@ -2967,11 +2975,14 @@ void Simulator::ExecuteExt4(Instruction* instr) {
uint64_t frt_val;
uint64_t kMinLongLong = 0;
uint64_t kMaxLongLong = kMinLongLong - 1;
bool invalid_convert = false;
if (frb_val > kMaxLongLong) {
frt_val = kMaxLongLong;
} else if (frb_val < kMinLongLong) {
if (std::isnan(frb_val) || frb_val < kMinLongLong) {
frt_val = kMinLongLong;
invalid_convert = true;
} else if (frb_val > kMaxLongLong) {
frt_val = kMaxLongLong;
invalid_convert = true;
} else {
switch (fp_condition_reg_ & kFPRoundingModeMask) {
case kRoundToZero:
......@@ -2990,6 +3001,7 @@ void Simulator::ExecuteExt4(Instruction* instr) {
}
}
set_d_register(frt, frt_val);
if (invalid_convert) SetFPSCR(VXCVI);
return;
}
case FCTIDUZ: {
......@@ -2999,15 +3011,19 @@ void Simulator::ExecuteExt4(Instruction* instr) {
uint64_t frt_val;
uint64_t kMinLongLong = 0;
uint64_t kMaxLongLong = kMinLongLong - 1;
bool invalid_convert = false;
if (frb_val > kMaxLongLong) {
frt_val = kMaxLongLong;
} else if (frb_val < kMinLongLong) {
if (std::isnan(frb_val) || frb_val < kMinLongLong) {
frt_val = kMinLongLong;
invalid_convert = true;
} else if (frb_val > kMaxLongLong) {
frt_val = kMaxLongLong;
invalid_convert = true;
} else {
frt_val = (uint64_t)frb_val;
}
set_d_register(frt, frt_val);
if (invalid_convert) SetFPSCR(VXCVI);
return;
}
case FCTIW:
......@@ -3104,6 +3120,43 @@ void Simulator::ExecuteExt4(Instruction* instr) {
set_d_register(frt, lval);
return;
}
case MCRFS: {
int bf = instr->Bits(25, 23);
int bfa = instr->Bits(20, 18);
int cr_shift = (7 - bf) * CRWIDTH;
int fp_shift = (7 - bfa) * CRWIDTH;
int field_val = (fp_condition_reg_ >> fp_shift) & 0xf;
condition_reg_ &= ~(0x0f << cr_shift);
condition_reg_ |= (field_val << cr_shift);
// Clear copied exception bits
switch (bfa) {
case 5:
ClearFPSCR(VXSOFT);
ClearFPSCR(VXSQRT);
ClearFPSCR(VXCVI);
break;
default:
UNIMPLEMENTED();
break;
}
return;
}
case MTFSB0: {
int bt = instr->Bits(25, 21);
ClearFPSCR(bt);
if (instr->Bit(0)) { // RC bit set
UNIMPLEMENTED();
}
return;
}
case MTFSB1: {
int bt = instr->Bits(25, 21);
SetFPSCR(bt);
if (instr->Bit(0)) { // RC bit set
UNIMPLEMENTED();
}
return;
}
case FABS: {
int frt = instr->RTValue();
int frb = instr->RBValue();
......
......@@ -323,6 +323,9 @@ class Simulator {
#endif
void ExecuteGeneric(Instruction* instr);
void SetFPSCR(int bit) { fp_condition_reg_ |= (1 << (31 - bit)); }
void ClearFPSCR(int bit) { fp_condition_reg_ &= ~(1 << (31 - bit)); }
// Executes one instruction.
void ExecuteInstruction(Instruction* instr);
......
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