X-Git-Url: http://plrg.eecs.uci.edu/git/?a=blobdiff_plain;f=lib%2FTarget%2FARM%2FARMCodeEmitter.cpp;h=089d1c51598f41c9ccfa6b2e4db36abbfc9596f3;hb=9ccaf53ada99c63737547c0235baeb8454b04e80;hp=49e83c3f8a9632ed0f1ea55ea7a5327949e894de;hpb=52e4a0a074b758ad3dbf6841b249aaf3baf08f28;p=oota-llvm.git diff --git a/lib/Target/ARM/ARMCodeEmitter.cpp b/lib/Target/ARM/ARMCodeEmitter.cpp index 49e83c3f8a9..089d1c51598 100644 --- a/lib/Target/ARM/ARMCodeEmitter.cpp +++ b/lib/Target/ARM/ARMCodeEmitter.cpp @@ -55,6 +55,7 @@ namespace { const std::vector *MCPEs; const std::vector *MJTEs; bool IsPIC; + bool IsThumb; void getAnalysisUsage(AnalysisUsage &AU) const { AU.addRequired(); @@ -64,11 +65,11 @@ namespace { static char ID; public: ARMCodeEmitter(TargetMachine &tm, JITCodeEmitter &mce) - : MachineFunctionPass(&ID), JTI(0), + : MachineFunctionPass(ID), JTI(0), II((const ARMInstrInfo *)tm.getInstrInfo()), TD(tm.getTargetData()), TM(tm), - MCE(mce), MCPEs(0), MJTEs(0), - IsPIC(TM.getRelocationModel() == Reloc::PIC_) {} + MCE(mce), MCPEs(0), MJTEs(0), + IsPIC(TM.getRelocationModel() == Reloc::PIC_), IsThumb(false) {} /// getBinaryCodeForInstr - This function, generated by the /// CodeEmitterGenerator using TableGen, produces the binary encoding for @@ -139,7 +140,8 @@ namespace { void emitMiscInstruction(const MachineInstr &MI); - void emitNEONGetLaneInstruction(const MachineInstr &MI); + void emitNEONLaneInstruction(const MachineInstr &MI); + void emitNEONDupInstruction(const MachineInstr &MI); void emitNEON1RegModImmInstruction(const MachineInstr &MI); void emitNEON2RegInstruction(const MachineInstr &MI); void emitNEON3RegInstruction(const MachineInstr &MI); @@ -199,6 +201,7 @@ bool ARMCodeEmitter::runOnMachineFunction(MachineFunction &MF) { MJTEs = 0; if (MF.getJumpTableInfo()) MJTEs = &MF.getJumpTableInfo()->getJumpTables(); IsPIC = TM.getRelocationModel() == Reloc::PIC_; + IsThumb = MF.getInfo()->isThumbFunction(); JTI->Initialize(MF, IsPIC); MMI = &getAnalysis(); MCE.setModuleInfo(MMI); @@ -415,7 +418,11 @@ void ARMCodeEmitter::emitInstruction(const MachineInstr &MI) { break; // NEON instructions. case ARMII::NGetLnFrm: - emitNEONGetLaneInstruction(MI); + case ARMII::NSetLnFrm: + emitNEONLaneInstruction(MI); + break; + case ARMII::NDupFrm: + emitNEONDupInstruction(MI); break; case ARMII::N1RegModImmFrm: emitNEON1RegModImmInstruction(MI); @@ -647,6 +654,19 @@ void ARMCodeEmitter::emitPseudoInstruction(const MachineInstr &MI) { switch (Opcode) { default: llvm_unreachable("ARMCodeEmitter::emitPseudoInstruction"); + case ARM::BX: + case ARM::BMOVPCRX: + case ARM::BXr9: + case ARM::BMOVPCRXr9: { + // First emit mov lr, pc + unsigned Binary = 0x01a0e00f; + Binary |= II->getPredicate(&MI) << ARMII::CondShift; + emitWordLE(Binary); + + // and then emit the branch. + emitMiscBranchInstruction(MI); + break; + } case TargetOpcode::INLINEASM: { // We allow inline assembler nodes with empty bodies - they can // implicitly define registers, which is ok for JIT. @@ -655,7 +675,7 @@ void ARMCodeEmitter::emitPseudoInstruction(const MachineInstr &MI) { } break; } - case TargetOpcode::DBG_LABEL: + case TargetOpcode::PROLOG_LABEL: case TargetOpcode::EH_LABEL: MCE.emitLabel(MI.getOperand(0).getMCSymbol()); break; @@ -1585,16 +1605,37 @@ static unsigned encodeNEONRm(const MachineInstr &MI, unsigned OpIdx) { return Binary; } -void ARMCodeEmitter::emitNEONGetLaneInstruction(const MachineInstr &MI) { +/// convertNEONDataProcToThumb - Convert the ARM mode encoding for a NEON +/// data-processing instruction to the corresponding Thumb encoding. +static unsigned convertNEONDataProcToThumb(unsigned Binary) { + assert((Binary & 0xfe000000) == 0xf2000000 && + "not an ARM NEON data-processing instruction"); + unsigned UBit = (Binary >> 24) & 1; + return 0xef000000 | (UBit << 28) | (Binary & 0xffffff); +} + +void ARMCodeEmitter::emitNEONLaneInstruction(const MachineInstr &MI) { unsigned Binary = getBinaryCodeForInstr(MI); + unsigned RegTOpIdx, RegNOpIdx, LnOpIdx; + const TargetInstrDesc &TID = MI.getDesc(); + if ((TID.TSFlags & ARMII::FormMask) == ARMII::NGetLnFrm) { + RegTOpIdx = 0; + RegNOpIdx = 1; + LnOpIdx = 2; + } else { // ARMII::NSetLnFrm + RegTOpIdx = 2; + RegNOpIdx = 0; + LnOpIdx = 3; + } + // Set the conditional execution predicate - Binary |= II->getPredicate(&MI) << ARMII::CondShift; + Binary |= (IsThumb ? ARMCC::AL : II->getPredicate(&MI)) << ARMII::CondShift; - unsigned RegT = MI.getOperand(0).getReg(); + unsigned RegT = MI.getOperand(RegTOpIdx).getReg(); RegT = ARMRegisterInfo::getRegisterNumbering(RegT); Binary |= (RegT << ARMII::RegRdShift); - Binary |= encodeNEONRn(MI, 1); + Binary |= encodeNEONRn(MI, RegNOpIdx); unsigned LaneShift; if ((Binary & (1 << 22)) != 0) @@ -1604,7 +1645,7 @@ void ARMCodeEmitter::emitNEONGetLaneInstruction(const MachineInstr &MI) { else LaneShift = 2; // 32-bit elements - unsigned Lane = MI.getOperand(2).getImm() << LaneShift; + unsigned Lane = MI.getOperand(LnOpIdx).getImm() << LaneShift; unsigned Opc1 = Lane >> 2; unsigned Opc2 = Lane & 3; assert((Opc1 & 3) == 0 && "out-of-range lane number operand"); @@ -1614,6 +1655,19 @@ void ARMCodeEmitter::emitNEONGetLaneInstruction(const MachineInstr &MI) { emitWordLE(Binary); } +void ARMCodeEmitter::emitNEONDupInstruction(const MachineInstr &MI) { + unsigned Binary = getBinaryCodeForInstr(MI); + + // Set the conditional execution predicate + Binary |= (IsThumb ? ARMCC::AL : II->getPredicate(&MI)) << ARMII::CondShift; + + unsigned RegT = MI.getOperand(1).getReg(); + RegT = ARMRegisterInfo::getRegisterNumbering(RegT); + Binary |= (RegT << ARMII::RegRdShift); + Binary |= encodeNEONRn(MI, 0); + emitWordLE(Binary); +} + void ARMCodeEmitter::emitNEON1RegModImmInstruction(const MachineInstr &MI) { unsigned Binary = getBinaryCodeForInstr(MI); // Destination register is encoded in Dd. @@ -1621,15 +1675,13 @@ void ARMCodeEmitter::emitNEON1RegModImmInstruction(const MachineInstr &MI) { // Immediate fields: Op, Cmode, I, Imm3, Imm4 unsigned Imm = MI.getOperand(1).getImm(); unsigned Op = (Imm >> 12) & 1; - Binary |= (Op << 5); unsigned Cmode = (Imm >> 8) & 0xf; - Binary |= (Cmode << 8); unsigned I = (Imm >> 7) & 1; - Binary |= (I << 24); unsigned Imm3 = (Imm >> 4) & 0x7; - Binary |= (Imm3 << 16); unsigned Imm4 = Imm & 0xf; - Binary |= Imm4; + Binary |= (I << 24) | (Imm3 << 16) | (Cmode << 8) | (Op << 5) | Imm4; + if (IsThumb) + Binary = convertNEONDataProcToThumb(Binary); emitWordLE(Binary); } @@ -1642,6 +1694,8 @@ void ARMCodeEmitter::emitNEON2RegInstruction(const MachineInstr &MI) { if (TID.getOperandConstraint(OpIdx, TOI::TIED_TO) != -1) ++OpIdx; Binary |= encodeNEONRm(MI, OpIdx); + if (IsThumb) + Binary = convertNEONDataProcToThumb(Binary); // FIXME: This does not handle VDUPfdf or VDUPfqf. emitWordLE(Binary); } @@ -1658,6 +1712,8 @@ void ARMCodeEmitter::emitNEON3RegInstruction(const MachineInstr &MI) { if (TID.getOperandConstraint(OpIdx, TOI::TIED_TO) != -1) ++OpIdx; Binary |= encodeNEONRm(MI, OpIdx); + if (IsThumb) + Binary = convertNEONDataProcToThumb(Binary); // FIXME: This does not handle VMOVDneon or VMOVQ. emitWordLE(Binary); }