diff --git a/src/compiler/ppc/code-generator-ppc.cc b/src/compiler/ppc/code-generator-ppc.cc index 6bf0a7e80a..4beb382c0b 100644 --- a/src/compiler/ppc/code-generator-ppc.cc +++ b/src/compiler/ppc/code-generator-ppc.cc @@ -928,6 +928,19 @@ void CodeGenerator::AssembleArchInstruction(Instruction* instr) { case kPPC_ShiftRightAlg64: ASSEMBLE_BINOP_INT_RC(srad, sradi); break; +#endif +#if !V8_TARGET_ARCH_PPC64 + case kPPC_PairShiftLeft: + if (instr->InputAt(2)->IsImmediate()) { + __ PairShiftLeft(i.OutputRegister(0), i.OutputRegister(1), + i.InputRegister(0), i.InputRegister(1), + i.InputInt32(2)); + } else { + __ PairShiftLeft(i.OutputRegister(0), i.OutputRegister(1), + i.InputRegister(0), i.InputRegister(1), kScratchReg, + i.InputRegister(2)); + } + break; #endif case kPPC_RotRight32: if (HasRegisterInput(instr, 1)) { diff --git a/src/compiler/ppc/instruction-codes-ppc.h b/src/compiler/ppc/instruction-codes-ppc.h index 877ebb5c12..f548eb87c5 100644 --- a/src/compiler/ppc/instruction-codes-ppc.h +++ b/src/compiler/ppc/instruction-codes-ppc.h @@ -23,6 +23,7 @@ namespace compiler { V(PPC_ShiftRight64) \ V(PPC_ShiftRightAlg32) \ V(PPC_ShiftRightAlg64) \ + V(PPC_PairShiftLeft) \ V(PPC_RotRight32) \ V(PPC_RotRight64) \ V(PPC_Not) \ diff --git a/src/compiler/ppc/instruction-scheduler-ppc.cc b/src/compiler/ppc/instruction-scheduler-ppc.cc index fd1df6a495..b830425d56 100644 --- a/src/compiler/ppc/instruction-scheduler-ppc.cc +++ b/src/compiler/ppc/instruction-scheduler-ppc.cc @@ -25,6 +25,7 @@ int InstructionScheduler::GetTargetInstructionFlags( case kPPC_ShiftRight64: case kPPC_ShiftRightAlg32: case kPPC_ShiftRightAlg64: + case kPPC_PairShiftLeft: case kPPC_RotRight32: case kPPC_RotRight64: case kPPC_Not: diff --git a/src/compiler/ppc/instruction-selector-ppc.cc b/src/compiler/ppc/instruction-selector-ppc.cc index e895062624..6d5aa72ca8 100644 --- a/src/compiler/ppc/instruction-selector-ppc.cc +++ b/src/compiler/ppc/instruction-selector-ppc.cc @@ -787,6 +787,28 @@ void InstructionSelector::VisitWord32Sar(Node* node) { VisitRRO(this, kPPC_ShiftRightAlg32, node, kShift32Imm); } +#if !V8_TARGET_ARCH_PPC64 +void InstructionSelector::VisitWord32PairShl(Node* node) { + PPCOperandGenerator g(this); + Int32Matcher m(node->InputAt(2)); + InstructionOperand shift_operand; + if (m.HasValue()) { + shift_operand = g.UseImmediate(m.node()); + } else { + shift_operand = g.UseUniqueRegister(m.node()); + } + + InstructionOperand inputs[] = {g.UseRegister(node->InputAt(0)), + g.UseRegister(node->InputAt(1)), + shift_operand}; + + InstructionOperand outputs[] = { + g.DefineSameAsFirst(node), + g.DefineAsRegister(NodeProperties::FindProjection(node, 1))}; + + Emit(kPPC_PairShiftLeft, 2, outputs, 3, inputs); +} +#endif #if V8_TARGET_ARCH_PPC64 void InstructionSelector::VisitWord64Sar(Node* node) { diff --git a/src/ppc/macro-assembler-ppc.cc b/src/ppc/macro-assembler-ppc.cc index 3f8640a408..2e3fafa09d 100644 --- a/src/ppc/macro-assembler-ppc.cc +++ b/src/ppc/macro-assembler-ppc.cc @@ -803,6 +803,52 @@ void MacroAssembler::ConvertDoubleToUnsignedInt64( } #endif +#if !V8_TARGET_ARCH_PPC64 +void MacroAssembler::PairShiftLeft(Register dst_low, Register dst_high, + Register src_low, Register src_high, + Register scratch, Register shift) { + DCHECK(!AreAliased(dst_low, src_high, shift)); + DCHECK(!AreAliased(dst_high, src_low, shift)); + Label less_than_32; + Label done; + cmpi(shift, Operand(32)); + blt(&less_than_32); + // If shift >= 32 + andi(scratch, shift, Operand(0x1f)); + slw(dst_high, src_low, scratch); + li(dst_low, Operand::Zero()); + b(&done); + bind(&less_than_32); + // If shift < 32 + subfic(scratch, shift, Operand(32)); + slw(dst_high, src_high, shift); + srw(scratch, src_low, scratch); + orx(dst_high, dst_high, scratch); + slw(dst_low, src_low, shift); + bind(&done); +} + +void MacroAssembler::PairShiftLeft(Register dst_low, Register dst_high, + Register src_low, Register src_high, + uint32_t shift) { + DCHECK(!AreAliased(dst_low, src_high)); + DCHECK(!AreAliased(dst_high, src_low)); + Label less_than_32; + Label done; + if (shift >= 32) { + shift &= 0x1f; + slwi(dst_high, src_low, Operand(shift)); + li(dst_low, Operand::Zero()); + } else if (shift == 0) { + Move(dst_low, src_low); + Move(dst_high, src_high); + } else { + slwi(dst_high, src_high, Operand(shift)); + rlwimi(dst_high, src_low, shift, 32 - shift, 31); + slwi(dst_low, src_low, Operand(shift)); + } +} +#endif void MacroAssembler::LoadConstantPoolPointerRegisterFromCodeTargetAddress( Register code_target_address) { diff --git a/src/ppc/macro-assembler-ppc.h b/src/ppc/macro-assembler-ppc.h index 8cd9cf8c20..4a3215c841 100644 --- a/src/ppc/macro-assembler-ppc.h +++ b/src/ppc/macro-assembler-ppc.h @@ -410,6 +410,13 @@ class MacroAssembler : public Assembler { FPRoundingMode rounding_mode = kRoundToZero); #endif +#if !V8_TARGET_ARCH_PPC64 + void PairShiftLeft(Register dst_low, Register dst_high, Register src_low, + Register src_high, Register scratch, Register shift); + void PairShiftLeft(Register dst_low, Register dst_high, Register src_low, + Register src_high, uint32_t shift); +#endif + // Generates function and stub prologue code. void StubPrologue(Register base = no_reg, int prologue_offset = 0); void Prologue(bool code_pre_aging, Register base, int prologue_offset = 0);