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 { ...@@ -27,6 +27,8 @@ class PPCOperandConverter final : public InstructionOperandConverter {
PPCOperandConverter(CodeGenerator* gen, Instruction* instr) PPCOperandConverter(CodeGenerator* gen, Instruction* instr)
: InstructionOperandConverter(gen, instr) {} : InstructionOperandConverter(gen, instr) {}
size_t OutputCount() { return instr_->OutputCount(); }
RCBit OutputRCBit() const { RCBit OutputRCBit() const {
switch (instr_->flags_mode()) { switch (instr_->flags_mode()) {
case kFlags_branch: case kFlags_branch:
...@@ -1157,14 +1159,32 @@ void CodeGenerator::AssembleArchInstruction(Instruction* instr) { ...@@ -1157,14 +1159,32 @@ void CodeGenerator::AssembleArchInstruction(Instruction* instr) {
break; break;
case kPPC_DoubleToInt32: case kPPC_DoubleToInt32:
case kPPC_DoubleToUint32: 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), __ ConvertDoubleToInt64(i.InputDoubleRegister(0),
#if !V8_TARGET_ARCH_PPC64 #if !V8_TARGET_ARCH_PPC64
kScratchReg, kScratchReg,
#endif #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()); DCHECK_EQ(LeaveRC, i.OutputRCBit());
break; break;
}
#if V8_TARGET_ARCH_PPC64 #if V8_TARGET_ARCH_PPC64
case kPPC_DoubleToUint64: case kPPC_DoubleToUint64:
__ ConvertDoubleToUnsignedInt64(i.InputDoubleRegister(0), __ ConvertDoubleToUnsignedInt64(i.InputDoubleRegister(0),
......
...@@ -933,11 +933,19 @@ void InstructionSelector::VisitTruncateFloat32ToInt64(Node* node) { ...@@ -933,11 +933,19 @@ void InstructionSelector::VisitTruncateFloat32ToInt64(Node* node) {
void InstructionSelector::VisitTryTruncateFloat64ToInt64(Node* node) { void InstructionSelector::VisitTryTruncateFloat64ToInt64(Node* node) {
if (NodeProperties::FindProjection(node, 1)) { PPCOperandGenerator g(this);
// TODO(ppc): implement the second return value.
UNIMPLEMENTED(); 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) { ...@@ -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); emit(EXT4 | MCRFS | bf * B23 | bfa * B18);
} }
...@@ -2219,6 +2222,20 @@ void Assembler::fneg(const DoubleRegister frt, const DoubleRegister frb, ...@@ -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) { void Assembler::mtfsfi(int bf, int immediate, RCBit rc) {
emit(EXT4 | MTFSFI | bf * B23 | immediate * B12 | rc); emit(EXT4 | MTFSFI | bf * B23 | immediate * B12 | rc);
} }
......
...@@ -984,7 +984,7 @@ class Assembler : public AssemblerBase { ...@@ -984,7 +984,7 @@ class Assembler : public AssemblerBase {
void mtlr(Register src); void mtlr(Register src);
void mtctr(Register src); void mtctr(Register src);
void mtxer(Register src); void mtxer(Register src);
void mcrfs(int bf, int bfa); void mcrfs(CRegister cr, FPSCRBit bit);
void mfcr(Register dst); void mfcr(Register dst);
#if V8_TARGET_ARCH_PPC64 #if V8_TARGET_ARCH_PPC64
void mffprd(Register dst, DoubleRegister src); void mffprd(Register dst, DoubleRegister src);
...@@ -1071,6 +1071,8 @@ class Assembler : public AssemblerBase { ...@@ -1071,6 +1071,8 @@ class Assembler : public AssemblerBase {
RCBit rc = LeaveRC); RCBit rc = LeaveRC);
void fneg(const DoubleRegister frt, const DoubleRegister frb, void fneg(const DoubleRegister frt, const DoubleRegister frb,
RCBit rc = LeaveRC); 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 mtfsfi(int bf, int immediate, RCBit rc = LeaveRC);
void mffs(const DoubleRegister frt, 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, void mtfsf(const DoubleRegister frb, bool L = 1, int FLM = 0, bool W = 0,
......
...@@ -279,8 +279,10 @@ enum OpcodeExt4 { ...@@ -279,8 +279,10 @@ enum OpcodeExt4 {
FRSP = 12 << 1, // Floating-Point Rounding FRSP = 12 << 1, // Floating-Point Rounding
FCTIW = 14 << 1, // Floating Convert to Integer Word X-form FCTIW = 14 << 1, // Floating Convert to Integer Word X-form
FCTIWZ = 15 << 1, // Floating Convert to Integer Word with Round to Zero 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 FNEG = 40 << 1, // Floating Negate
MCRFS = 64 << 1, // Move to Condition Register from FPSCR MCRFS = 64 << 1, // Move to Condition Register from FPSCR
MTFSB0 = 70 << 1, // Move to FPSCR Bit 0
FMR = 72 << 1, // Floating Move Register FMR = 72 << 1, // Floating Move Register
MTFSFI = 134 << 1, // Move to FPSCR Field Immediate MTFSFI = 134 << 1, // Move to FPSCR Field Immediate
FABS = 264 << 1, // Floating Absolute Value 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 }; ...@@ -402,6 +404,13 @@ enum CRBit { CR_LT = 0, CR_GT = 1, CR_EQ = 2, CR_SO = 3, CR_FU = 3 };
#define CRWIDTH 4 #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. // Supervisor Call (svc) specific support.
......
...@@ -1017,6 +1017,18 @@ void Decoder::DecodeExt4(Instruction* instr) { ...@@ -1017,6 +1017,18 @@ void Decoder::DecodeExt4(Instruction* instr) {
Format(instr, "fneg'. 'Dt, 'Db"); Format(instr, "fneg'. 'Dt, 'Db");
break; break;
} }
case MCRFS: {
Format(instr, "mcrfs ?,?");
break;
}
case MTFSB0: {
Format(instr, "mtfsb0'. ?");
break;
}
case MTFSB1: {
Format(instr, "mtfsb1'. ?");
break;
}
default: { default: {
Unknown(instr); // not used by V8 Unknown(instr); // not used by V8
} }
......
...@@ -2916,11 +2916,14 @@ void Simulator::ExecuteExt4(Instruction* instr) { ...@@ -2916,11 +2916,14 @@ void Simulator::ExecuteExt4(Instruction* instr) {
int64_t one = 1; // work-around gcc int64_t one = 1; // work-around gcc
int64_t kMinLongLong = (one << 63); int64_t kMinLongLong = (one << 63);
int64_t kMaxLongLong = kMinLongLong - 1; int64_t kMaxLongLong = kMinLongLong - 1;
bool invalid_convert = false;
if (frb_val > kMaxLongLong) { if (std::isnan(frb_val) || frb_val < kMinLongLong) {
frt_val = kMaxLongLong;
} else if (frb_val < kMinLongLong) {
frt_val = kMinLongLong; frt_val = kMinLongLong;
invalid_convert = true;
} else if (frb_val > kMaxLongLong) {
frt_val = kMaxLongLong;
invalid_convert = true;
} else { } else {
switch (fp_condition_reg_ & kFPRoundingModeMask) { switch (fp_condition_reg_ & kFPRoundingModeMask) {
case kRoundToZero: case kRoundToZero:
...@@ -2939,6 +2942,7 @@ void Simulator::ExecuteExt4(Instruction* instr) { ...@@ -2939,6 +2942,7 @@ void Simulator::ExecuteExt4(Instruction* instr) {
} }
} }
set_d_register(frt, frt_val); set_d_register(frt, frt_val);
if (invalid_convert) SetFPSCR(VXCVI);
return; return;
} }
case FCTIDZ: { case FCTIDZ: {
...@@ -2949,15 +2953,19 @@ void Simulator::ExecuteExt4(Instruction* instr) { ...@@ -2949,15 +2953,19 @@ void Simulator::ExecuteExt4(Instruction* instr) {
int64_t one = 1; // work-around gcc int64_t one = 1; // work-around gcc
int64_t kMinLongLong = (one << 63); int64_t kMinLongLong = (one << 63);
int64_t kMaxLongLong = kMinLongLong - 1; int64_t kMaxLongLong = kMinLongLong - 1;
bool invalid_convert = false;
if (frb_val > kMaxLongLong) { if (std::isnan(frb_val) || frb_val < kMinLongLong) {
frt_val = kMaxLongLong;
} else if (frb_val < kMinLongLong) {
frt_val = kMinLongLong; frt_val = kMinLongLong;
invalid_convert = true;
} else if (frb_val > kMaxLongLong) {
frt_val = kMaxLongLong;
invalid_convert = true;
} else { } else {
frt_val = (int64_t)frb_val; frt_val = (int64_t)frb_val;
} }
set_d_register(frt, frt_val); set_d_register(frt, frt_val);
if (invalid_convert) SetFPSCR(VXCVI);
return; return;
} }
case FCTIDU: { case FCTIDU: {
...@@ -2967,11 +2975,14 @@ void Simulator::ExecuteExt4(Instruction* instr) { ...@@ -2967,11 +2975,14 @@ void Simulator::ExecuteExt4(Instruction* instr) {
uint64_t frt_val; uint64_t frt_val;
uint64_t kMinLongLong = 0; uint64_t kMinLongLong = 0;
uint64_t kMaxLongLong = kMinLongLong - 1; uint64_t kMaxLongLong = kMinLongLong - 1;
bool invalid_convert = false;
if (frb_val > kMaxLongLong) { if (std::isnan(frb_val) || frb_val < kMinLongLong) {
frt_val = kMaxLongLong;
} else if (frb_val < kMinLongLong) {
frt_val = kMinLongLong; frt_val = kMinLongLong;
invalid_convert = true;
} else if (frb_val > kMaxLongLong) {
frt_val = kMaxLongLong;
invalid_convert = true;
} else { } else {
switch (fp_condition_reg_ & kFPRoundingModeMask) { switch (fp_condition_reg_ & kFPRoundingModeMask) {
case kRoundToZero: case kRoundToZero:
...@@ -2990,6 +3001,7 @@ void Simulator::ExecuteExt4(Instruction* instr) { ...@@ -2990,6 +3001,7 @@ void Simulator::ExecuteExt4(Instruction* instr) {
} }
} }
set_d_register(frt, frt_val); set_d_register(frt, frt_val);
if (invalid_convert) SetFPSCR(VXCVI);
return; return;
} }
case FCTIDUZ: { case FCTIDUZ: {
...@@ -2999,15 +3011,19 @@ void Simulator::ExecuteExt4(Instruction* instr) { ...@@ -2999,15 +3011,19 @@ void Simulator::ExecuteExt4(Instruction* instr) {
uint64_t frt_val; uint64_t frt_val;
uint64_t kMinLongLong = 0; uint64_t kMinLongLong = 0;
uint64_t kMaxLongLong = kMinLongLong - 1; uint64_t kMaxLongLong = kMinLongLong - 1;
bool invalid_convert = false;
if (frb_val > kMaxLongLong) { if (std::isnan(frb_val) || frb_val < kMinLongLong) {
frt_val = kMaxLongLong;
} else if (frb_val < kMinLongLong) {
frt_val = kMinLongLong; frt_val = kMinLongLong;
invalid_convert = true;
} else if (frb_val > kMaxLongLong) {
frt_val = kMaxLongLong;
invalid_convert = true;
} else { } else {
frt_val = (uint64_t)frb_val; frt_val = (uint64_t)frb_val;
} }
set_d_register(frt, frt_val); set_d_register(frt, frt_val);
if (invalid_convert) SetFPSCR(VXCVI);
return; return;
} }
case FCTIW: case FCTIW:
...@@ -3104,6 +3120,43 @@ void Simulator::ExecuteExt4(Instruction* instr) { ...@@ -3104,6 +3120,43 @@ void Simulator::ExecuteExt4(Instruction* instr) {
set_d_register(frt, lval); set_d_register(frt, lval);
return; 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: { case FABS: {
int frt = instr->RTValue(); int frt = instr->RTValue();
int frb = instr->RBValue(); int frb = instr->RBValue();
......
...@@ -323,6 +323,9 @@ class Simulator { ...@@ -323,6 +323,9 @@ class Simulator {
#endif #endif
void ExecuteGeneric(Instruction* instr); 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. // Executes one instruction.
void ExecuteInstruction(Instruction* instr); 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