From 0f35ee7851a146f94ae6b3d7d851e45652abaaad Mon Sep 17 00:00:00 2001 From: Milad Farazmand Date: Thu, 23 Jul 2020 17:45:11 +0000 Subject: [PATCH] PPC/s390x: Use INT32_MIN s an overflow indicator To match the behaviour of other architectures, Float32ToInt32 needs to return INT32_MIN as an overflow indicator instead of 0. Change-Id: I68140daf06f8575fc38fb857033b5c56fec6bb2f Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2316398 Reviewed-by: Junliang Yan Commit-Queue: Milad Farazmand Cr-Commit-Position: refs/heads/master@{#69030} --- src/compiler/backend/ppc/code-generator-ppc.cc | 14 ++++++++++++++ src/compiler/backend/ppc/instruction-codes-ppc.h | 1 + .../backend/ppc/instruction-scheduler-ppc.cc | 1 + .../backend/ppc/instruction-selector-ppc.cc | 2 +- src/compiler/backend/s390/code-generator-s390.cc | 4 +++- src/execution/ppc/simulator-ppc.cc | 4 ++++ src/execution/s390/simulator-s390.cc | 8 +++++--- 7 files changed, 29 insertions(+), 5 deletions(-) diff --git a/src/compiler/backend/ppc/code-generator-ppc.cc b/src/compiler/backend/ppc/code-generator-ppc.cc index a6350e96fb..b065060704 100644 --- a/src/compiler/backend/ppc/code-generator-ppc.cc +++ b/src/compiler/backend/ppc/code-generator-ppc.cc @@ -1851,6 +1851,20 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction( i.OutputDoubleRegister()); DCHECK_EQ(LeaveRC, i.OutputRCBit()); break; + case kPPC_Float32ToInt32: { + __ mtfsb0(VXCVI); // clear FPSCR:VXCVI bit + __ fctiwz(kScratchDoubleReg, i.InputDoubleRegister(0)); + __ MovDoubleLowToInt(i.OutputRegister(), kScratchDoubleReg); + // Use INT32_MIN s an overflow indicator because it allows for easier + // out-of-bounds detection. + CRegister cr = cr7; + int crbit = v8::internal::Assembler::encode_crbit( + cr, static_cast(VXCVI % CRWIDTH)); + __ mcrfs(cr, VXCVI); // extract FPSCR field containing VXCVI into cr7 + __ lis(kScratchReg, Operand(static_cast(0x8000))); + __ isel(i.OutputRegister(0), kScratchReg, i.OutputRegister(0), crbit); + break; + } case kPPC_DoubleToInt32: case kPPC_DoubleToUint32: case kPPC_DoubleToInt64: { diff --git a/src/compiler/backend/ppc/instruction-codes-ppc.h b/src/compiler/backend/ppc/instruction-codes-ppc.h index 184d7f88f1..4d1fed2758 100644 --- a/src/compiler/backend/ppc/instruction-codes-ppc.h +++ b/src/compiler/backend/ppc/instruction-codes-ppc.h @@ -95,6 +95,7 @@ namespace compiler { V(PPC_Int32ToFloat32) \ V(PPC_Int32ToDouble) \ V(PPC_Uint32ToFloat32) \ + V(PPC_Float32ToInt32) \ V(PPC_Uint32ToDouble) \ V(PPC_Float32ToDouble) \ V(PPC_Float64SilenceNaN) \ diff --git a/src/compiler/backend/ppc/instruction-scheduler-ppc.cc b/src/compiler/backend/ppc/instruction-scheduler-ppc.cc index b1fe8cc575..bd10b36e5d 100644 --- a/src/compiler/backend/ppc/instruction-scheduler-ppc.cc +++ b/src/compiler/backend/ppc/instruction-scheduler-ppc.cc @@ -92,6 +92,7 @@ int InstructionScheduler::GetTargetInstructionFlags( case kPPC_Int32ToDouble: case kPPC_Uint32ToFloat32: case kPPC_Uint32ToDouble: + case kPPC_Float32ToInt32: case kPPC_Float32ToDouble: case kPPC_Float64SilenceNaN: case kPPC_DoubleToInt32: diff --git a/src/compiler/backend/ppc/instruction-selector-ppc.cc b/src/compiler/backend/ppc/instruction-selector-ppc.cc index f19b633dd0..fd73b27208 100644 --- a/src/compiler/backend/ppc/instruction-selector-ppc.cc +++ b/src/compiler/backend/ppc/instruction-selector-ppc.cc @@ -1227,7 +1227,7 @@ void InstructionSelector::VisitRoundFloat64ToInt32(Node* node) { } void InstructionSelector::VisitTruncateFloat32ToInt32(Node* node) { - VisitRR(this, kPPC_DoubleToInt32, node); + VisitRR(this, kPPC_Float32ToInt32, node); } void InstructionSelector::VisitTruncateFloat32ToUint32(Node* node) { diff --git a/src/compiler/backend/s390/code-generator-s390.cc b/src/compiler/backend/s390/code-generator-s390.cc index 24591b89b8..690eac56c5 100644 --- a/src/compiler/backend/s390/code-generator-s390.cc +++ b/src/compiler/backend/s390/code-generator-s390.cc @@ -2421,7 +2421,9 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction( __ ConvertFloat32ToInt32(i.OutputRegister(0), i.InputDoubleRegister(0), kRoundToZero); __ b(Condition(0xE), &done, Label::kNear); // normal case - __ lghi(i.OutputRegister(0), Operand::Zero()); + // Use INT32_MIN s an overflow indicator because it allows for easier + // out-of-bounds detection. + __ llilh(i.OutputRegister(0), Operand(0x8000)); __ bind(&done); break; } diff --git a/src/execution/ppc/simulator-ppc.cc b/src/execution/ppc/simulator-ppc.cc index a0da6dd634..1134469134 100644 --- a/src/execution/ppc/simulator-ppc.cc +++ b/src/execution/ppc/simulator-ppc.cc @@ -3331,6 +3331,7 @@ void Simulator::ExecuteGeneric(Instruction* instr) { int64_t frt_val; int64_t kMinVal = kMinInt; int64_t kMaxVal = kMaxInt; + bool invalid_convert = false; if (std::isnan(frb_val)) { frt_val = kMinVal; @@ -3360,13 +3361,16 @@ void Simulator::ExecuteGeneric(Instruction* instr) { } if (frb_val < kMinVal) { frt_val = kMinVal; + invalid_convert = true; } else if (frb_val > kMaxVal) { frt_val = kMaxVal; + invalid_convert = true; } else { frt_val = (int64_t)frb_val; } } set_d_register(frt, frt_val); + if (invalid_convert) SetFPSCR(VXCVI); return; } case FNEG: { diff --git a/src/execution/s390/simulator-s390.cc b/src/execution/s390/simulator-s390.cc index 455f325f36..9ace63a009 100644 --- a/src/execution/s390/simulator-s390.cc +++ b/src/execution/s390/simulator-s390.cc @@ -5956,9 +5956,11 @@ EVALUATE(LLIHL) { } EVALUATE(LLILH) { - UNIMPLEMENTED(); - USE(instr); - return 0; + DCHECK_OPCODE(LLILH); + DECODE_RI_A_INSTRUCTION(instr, r1, i2); + uint64_t imm = static_cast(i2); + set_register(r1, (imm << 48) >> 32); + return length; } EVALUATE(LLILL) {