diff --git a/lib/Target/ARM/ARMCodeEmitter.cpp b/lib/Target/ARM/ARMCodeEmitter.cpp index 945a259e062..fcda30f83af 100644 --- a/lib/Target/ARM/ARMCodeEmitter.cpp +++ b/lib/Target/ARM/ARMCodeEmitter.cpp @@ -69,6 +69,8 @@ namespace { void emitConstPoolInstruction(const MachineInstr &MI); + void emitMOVi2piecesInstruction(const MachineInstr &MI); + void addPCLabel(unsigned LabelID); void emitPseudoInstruction(const MachineInstr &MI); @@ -78,9 +80,7 @@ namespace { const MachineOperand &MO, unsigned OpIdx); - unsigned getMachineSoImmOpValue(const MachineInstr &MI, - const TargetInstrDesc &TID, - const MachineOperand &MO); + unsigned getMachineSoImmOpValue(unsigned SoImm); unsigned getAddrModeSBit(const MachineInstr &MI, const TargetInstrDesc &TID) const; @@ -344,6 +344,47 @@ void ARMCodeEmitter::emitConstPoolInstruction(const MachineInstr &MI) { } } +void ARMCodeEmitter::emitMOVi2piecesInstruction(const MachineInstr &MI) { + const MachineOperand &MO0 = MI.getOperand(0); + const MachineOperand &MO1 = MI.getOperand(1); + assert(MO1.isImm() && "Not a valid so_imm value!"); + unsigned V1 = ARM_AM::getSOImmTwoPartFirst(MO1.getImm()); + unsigned V2 = ARM_AM::getSOImmTwoPartSecond(MO1.getImm()); + + // Emit the 'mov' instruction. + unsigned Binary = 0xd << 21; // mov: Insts{24-21} = 0b1101 + + // Set the conditional execution predicate. + Binary |= II->getPredicate(&MI) << 28; + + // Encode Rd. + Binary |= getMachineOpValue(MI, MO0) << ARMII::RegRdShift; + + // Encode so_imm. + // Set bit I(25) to identify this is the immediate form of + Binary |= 1 << ARMII::I_BitShift; + Binary |= getMachineSoImmOpValue(ARM_AM::getSOImmVal(V1)); + emitWordLE(Binary); + + // Now the 'orr' instruction. + Binary = 0xc << 21; // orr: Insts{24-21} = 0b1100 + + // Set the conditional execution predicate. + Binary |= II->getPredicate(&MI) << 28; + + // Encode Rd. + Binary |= getMachineOpValue(MI, MO0) << ARMII::RegRdShift; + + // Encode Rn. + Binary |= getMachineOpValue(MI, MO0) << ARMII::RegRnShift; + + // Encode so_imm. + // Set bit I(25) to identify this is the immediate form of + Binary |= 1 << ARMII::I_BitShift; + Binary |= getMachineSoImmOpValue(ARM_AM::getSOImmVal(V2)); + emitWordLE(Binary); +} + void ARMCodeEmitter::addPCLabel(unsigned LabelID) { DOUT << "\t** LPC" << LabelID << " @ " << (void*)MCE.getCurrentPCValue() << '\n'; @@ -385,6 +426,10 @@ void ARMCodeEmitter::emitPseudoInstruction(const MachineInstr &MI) { emitMiscLoadStoreInstruction(MI, ARM::PC); break; } + case ARM::MOVi2pieces: + // Two instructions to materialize a constant. + emitMOVi2piecesInstruction(MI); + break; } } @@ -447,14 +492,11 @@ unsigned ARMCodeEmitter::getMachineSoRegOpValue(const MachineInstr &MI, return Binary | ARM_AM::getSORegOffset(MO2.getImm()) << 7; } -unsigned ARMCodeEmitter::getMachineSoImmOpValue(const MachineInstr &MI, - const TargetInstrDesc &TID, - const MachineOperand &MO) { - unsigned SoImm = MO.getImm(); +unsigned ARMCodeEmitter::getMachineSoImmOpValue(unsigned SoImm) { // Encode rotate_imm. - unsigned Binary = ARM_AM::getSOImmValRot(SoImm) << ARMII::RotImmShift; + unsigned Binary = (ARM_AM::getSOImmValRot(SoImm) >> 1) << ARMII::RotImmShift; // Encode immed_8. - Binary |= ARM_AM::getSOImmVal(SoImm); + Binary |= ARM_AM::getSOImmValImm(SoImm); return Binary; } @@ -471,8 +513,6 @@ unsigned ARMCodeEmitter::getAddrModeSBit(const MachineInstr &MI, void ARMCodeEmitter::emitDataProcessingInstruction(const MachineInstr &MI, unsigned ImplicitRn) { const TargetInstrDesc &TID = MI.getDesc(); - if (TID.getOpcode() == ARM::MOVi2pieces) - abort(); // FIXME // Part of binary is determined by TableGn. unsigned Binary = getBinaryCodeForInstr(MI); @@ -521,7 +561,7 @@ void ARMCodeEmitter::emitDataProcessingInstruction(const MachineInstr &MI, // Encode so_imm. // Set bit I(25) to identify this is the immediate form of Binary |= 1 << ARMII::I_BitShift; - Binary |= getMachineSoImmOpValue(MI, TID, MO); + Binary |= getMachineSoImmOpValue(MO.getImm()); emitWordLE(Binary); } diff --git a/lib/Target/ARM/ARMInstrInfo.td b/lib/Target/ARM/ARMInstrInfo.td index e57b5d93b88..a10f9383619 100644 --- a/lib/Target/ARM/ARMInstrInfo.td +++ b/lib/Target/ARM/ARMInstrInfo.td @@ -1195,9 +1195,9 @@ def : ARMPat<(ARMWrapperJT tjumptable:$dst, imm:$id), // Two piece so_imms. let isReMaterializable = 1 in -def MOVi2pieces : AI1x2<0x0, (outs GPR:$dst), (ins so_imm2part:$src), DPFrm, +def MOVi2pieces : AI1x2<0x0, (outs GPR:$dst), (ins so_imm2part:$src), Pseudo, "mov", " $dst, $src", - [(set GPR:$dst, so_imm2part:$src)]>, UnaryDP; + [(set GPR:$dst, so_imm2part:$src)]>; def : ARMPat<(or GPR:$LHS, so_imm2part:$RHS), (ORRri (ORRri GPR:$LHS, (so_imm2part_1 imm:$RHS)), diff --git a/lib/Target/ARM/AsmPrinter/ARMAsmPrinter.cpp b/lib/Target/ARM/AsmPrinter/ARMAsmPrinter.cpp index 5c6312420c0..3eec5622783 100644 --- a/lib/Target/ARM/AsmPrinter/ARMAsmPrinter.cpp +++ b/lib/Target/ARM/AsmPrinter/ARMAsmPrinter.cpp @@ -363,8 +363,8 @@ void ARMAsmPrinter::printSOImmOperand(const MachineInstr *MI, int OpNum) { printSOImm(O, MO.getImm(), TAI); } -/// printSOImm2PartOperand - SOImm is broken into two pieces using a mov -/// followed by a or to materialize. +/// printSOImm2PartOperand - SOImm is broken into two pieces using a 'mov' +/// followed by an 'orr' to materialize. void ARMAsmPrinter::printSOImm2PartOperand(const MachineInstr *MI, int OpNum) { const MachineOperand &MO = MI->getOperand(OpNum); assert(MO.isImm() && "Not a valid so_imm value!");