X-Git-Url: http://demsky.eecs.uci.edu/git/?a=blobdiff_plain;f=lib%2FTarget%2FARM%2FARMCodeEmitter.cpp;h=c27fc5f1eafff4d3edf52f82d3a539030c8a57f0;hb=9036d80d7b696daec0eb4738848b18a2a6e4fe1f;hp=b39ab7f833d8c4e5343d8c0584735e0ee9dbf399;hpb=96581d3633edf702b14a60472a1ec5354f327c18;p=oota-llvm.git diff --git a/lib/Target/ARM/ARMCodeEmitter.cpp b/lib/Target/ARM/ARMCodeEmitter.cpp index b39ab7f833d..c27fc5f1eaf 100644 --- a/lib/Target/ARM/ARMCodeEmitter.cpp +++ b/lib/Target/ARM/ARMCodeEmitter.cpp @@ -75,12 +75,16 @@ namespace { void emitWordLE(unsigned Binary); + void emitDWordLE(uint64_t Binary); + void emitConstPoolInstruction(const MachineInstr &MI); void emitMOVi2piecesInstruction(const MachineInstr &MI); void emitLEApcrelJTInstruction(const MachineInstr &MI); + void emitPseudoMoveInstruction(const MachineInstr &MI); + void addPCLabel(unsigned LabelID); void emitPseudoInstruction(const MachineInstr &MI); @@ -122,6 +126,14 @@ namespace { void emitVFPArithInstruction(const MachineInstr &MI); + void emitVFPConversionInstruction(const MachineInstr &MI); + + void emitVFPLoadStoreInstruction(const MachineInstr &MI); + + void emitVFPLoadStoreMultipleInstruction(const MachineInstr &MI); + + void emitMiscInstruction(const MachineInstr &MI); + /// getBinaryCodeForInstr - This function, generated by the /// CodeEmitterGenerator using TableGen, produces the binary encoding for /// machine instructions. @@ -212,9 +224,13 @@ unsigned ARMCodeEmitter::getMachineOpValue(const MachineInstr &MI, emitGlobalAddress(MO.getGlobal(), ARM::reloc_arm_branch, true); else if (MO.isSymbol()) emitExternalSymbolAddress(MO.getSymbolName(), ARM::reloc_arm_branch); - else if (MO.isCPI()) - emitConstPoolAddress(MO.getIndex(), ARM::reloc_arm_cp_entry); - else if (MO.isJTI()) + else if (MO.isCPI()) { + const TargetInstrDesc &TID = MI.getDesc(); + // For VFP load, the immediate offset is multiplied by 4. + unsigned Reloc = ((TID.TSFlags & ARMII::FormMask) == ARMII::VFPLdStFrm) + ? ARM::reloc_arm_vfp_cp_entry : ARM::reloc_arm_cp_entry; + emitConstPoolAddress(MO.getIndex(), Reloc); + } else if (MO.isJTI()) emitJumpTableAddress(MO.getIndex(), ARM::reloc_arm_relative); else if (MO.isMBB()) emitMachineBasicBlock(MO.getMBB(), ARM::reloc_arm_branch); @@ -273,14 +289,25 @@ void ARMCodeEmitter::emitWordLE(unsigned Binary) { MCE.emitWordLE(Binary); } +void ARMCodeEmitter::emitDWordLE(uint64_t Binary) { +#ifndef NDEBUG + DOUT << " 0x" << std::hex << std::setw(8) << std::setfill('0') + << (unsigned)Binary << std::dec << "\n"; + DOUT << " 0x" << std::hex << std::setw(8) << std::setfill('0') + << (unsigned)(Binary >> 32) << std::dec << "\n"; +#endif + MCE.emitDWordLE(Binary); +} + void ARMCodeEmitter::emitInstruction(const MachineInstr &MI) { DOUT << "JIT: " << (void*)MCE.getCurrentPCValue() << ":\t" << MI; NumEmitted++; // Keep track of the # of mi's emitted switch (MI.getDesc().TSFlags & ARMII::FormMask) { - default: + default: { assert(0 && "Unhandled instruction encoding format!"); break; + } case ARMII::Pseudo: emitPseudoInstruction(MI); break; @@ -296,8 +323,7 @@ void ARMCodeEmitter::emitInstruction(const MachineInstr &MI) { case ARMII::StMiscFrm: emitMiscLoadStoreInstruction(MI); break; - case ARMII::LdMulFrm: - case ARMII::StMulFrm: + case ARMII::LdStMulFrm: emitLoadStoreMultipleInstruction(MI); break; case ARMII::MulFrm: @@ -320,6 +346,22 @@ void ARMCodeEmitter::emitInstruction(const MachineInstr &MI) { case ARMII::VFPBinaryFrm: emitVFPArithInstruction(MI); break; + case ARMII::VFPConv1Frm: + case ARMII::VFPConv2Frm: + case ARMII::VFPConv3Frm: + case ARMII::VFPConv4Frm: + case ARMII::VFPConv5Frm: + emitVFPConversionInstruction(MI); + break; + case ARMII::VFPLdStFrm: + emitVFPLoadStoreInstruction(MI); + break; + case ARMII::VFPLdStMulFrm: + emitVFPLoadStoreMultipleInstruction(MI); + break; + case ARMII::VFPMiscFrm: + emitMiscInstruction(MI); + break; } } @@ -349,7 +391,7 @@ void ARMCodeEmitter::emitConstPoolInstruction(const MachineInstr &MI) { (intptr_t)ACPV, false)); else emitGlobalAddress(GV, ARM::reloc_arm_machine_cp_entry, - ACPV->isStub(), (intptr_t)ACPV); + ACPV->isStub() || isa(GV), (intptr_t)ACPV); } else { assert(!ACPV->isNonLazyPointer() && "Don't know how to deal this yet!"); emitExternalSymbolAddress(ACPV->getSymbol(), ARM::reloc_arm_absolute); @@ -358,18 +400,34 @@ void ARMCodeEmitter::emitConstPoolInstruction(const MachineInstr &MI) { } else { Constant *CV = MCPE.Val.ConstVal; +#ifndef NDEBUG DOUT << " ** Constant pool #" << CPI << " @ " - << (void*)MCE.getCurrentPCValue() << " " << *CV << '\n'; + << (void*)MCE.getCurrentPCValue() << " "; + if (const Function *F = dyn_cast(CV)) + DOUT << F->getName(); + else + DOUT << *CV; + DOUT << '\n'; +#endif if (GlobalValue *GV = dyn_cast(CV)) { - emitGlobalAddress(GV, ARM::reloc_arm_absolute, false); + emitGlobalAddress(GV, ARM::reloc_arm_absolute, isa(GV)); emitWordLE(0); - } else { - assert(CV->getType()->isInteger() && - "Not expecting non-integer constpool entries yet!"); - const ConstantInt *CI = dyn_cast(CV); + } else if (const ConstantInt *CI = dyn_cast(CV)) { uint32_t Val = *(uint32_t*)CI->getValue().getRawData(); emitWordLE(Val); + } else if (const ConstantFP *CFP = dyn_cast(CV)) { + if (CFP->getType() == Type::FloatTy) + emitWordLE(CFP->getValueAPF().bitcastToAPInt().getZExtValue()); + else if (CFP->getType() == Type::DoubleTy) + emitDWordLE(CFP->getValueAPF().bitcastToAPInt().getZExtValue()); + else { + assert(0 && "Unable to handle this constantpool entry!"); + abort(); + } + } else { + assert(0 && "Unable to handle this constantpool entry!"); + abort(); } } } @@ -443,6 +501,45 @@ void ARMCodeEmitter::emitLEApcrelJTInstruction(const MachineInstr &MI) { emitWordLE(Binary); } +void ARMCodeEmitter::emitPseudoMoveInstruction(const MachineInstr &MI) { + unsigned Opcode = MI.getDesc().Opcode; + + // Part of binary is determined by TableGn. + unsigned Binary = getBinaryCodeForInstr(MI); + + // Set the conditional execution predicate + Binary |= II->getPredicate(&MI) << ARMII::CondShift; + + // Encode S bit if MI modifies CPSR. + if (Opcode == ARM::MOVsrl_flag || Opcode == ARM::MOVsra_flag) + Binary |= 1 << ARMII::S_BitShift; + + // Encode register def if there is one. + Binary |= getMachineOpValue(MI, 0) << ARMII::RegRdShift; + + // Encode the shift operation. + switch (Opcode) { + default: break; + case ARM::MOVrx: + // rrx + Binary |= 0x6 << 4; + break; + case ARM::MOVsrl_flag: + // lsr #1 + Binary |= (0x2 << 4) | (1 << 7); + break; + case ARM::MOVsra_flag: + // asr #1 + Binary |= (0x4 << 4) | (1 << 7); + break; + } + + // Encode register Rm. + Binary |= getMachineOpValue(MI, 1); + + emitWordLE(Binary); +} + void ARMCodeEmitter::addPCLabel(unsigned LabelID) { DOUT << " ** LPC" << LabelID << " @ " << (void*)MCE.getCurrentPCValue() << '\n'; @@ -454,6 +551,24 @@ void ARMCodeEmitter::emitPseudoInstruction(const MachineInstr &MI) { switch (Opcode) { default: abort(); // FIXME: + case TargetInstrInfo::INLINEASM: { + // We allow inline assembler nodes with empty bodies - they can + // implicitly define registers, which is ok for JIT. + if (MI.getOperand(0).getSymbolName()[0]) { + assert(0 && "JIT does not support inline asm!\n"); + abort(); + } + break; + } + case TargetInstrInfo::DBG_LABEL: + case TargetInstrInfo::EH_LABEL: + MCE.emitLabel(MI.getOperand(0).getImm()); + break; + case TargetInstrInfo::IMPLICIT_DEF: + case TargetInstrInfo::DECLARE: + case ARM::DWARF_LOC: + // Do nothing. + break; case ARM::CONSTPOOL_ENTRY: emitConstPoolInstruction(MI); break; @@ -492,6 +607,11 @@ void ARMCodeEmitter::emitPseudoInstruction(const MachineInstr &MI) { // Materialize jumptable address. emitLEApcrelJTInstruction(MI); break; + case ARM::MOVrx: + case ARM::MOVsrl_flag: + case ARM::MOVsra_flag: + emitPseudoMoveInstruction(MI); + break; } } @@ -641,6 +761,8 @@ void ARMCodeEmitter::emitLoadStoreInstruction(const MachineInstr &MI, unsigned ImplicitRd, unsigned ImplicitRn) { const TargetInstrDesc &TID = MI.getDesc(); + unsigned Form = TID.TSFlags & ARMII::FormMask; + bool IsPrePost = (TID.TSFlags & ARMII::IndexModeMask) != 0; // Part of binary is determined by TableGn. unsigned Binary = getBinaryCodeForInstr(MI); @@ -648,8 +770,17 @@ void ARMCodeEmitter::emitLoadStoreInstruction(const MachineInstr &MI, // Set the conditional execution predicate Binary |= II->getPredicate(&MI) << ARMII::CondShift; - // Set first operand unsigned OpIdx = 0; + + // Operand 0 of a pre- and post-indexed store is the address base + // writeback. Skip it. + bool Skipped = false; + if (IsPrePost && Form == ARMII::StFrm) { + ++OpIdx; + Skipped = true; + } + + // Set first operand if (ImplicitRd) // Special handling for implicit use (e.g. PC). Binary |= (ARMRegisterInfo::getRegisterNumbering(ImplicitRd) @@ -666,7 +797,7 @@ void ARMCodeEmitter::emitLoadStoreInstruction(const MachineInstr &MI, Binary |= getMachineOpValue(MI, OpIdx++) << ARMII::RegRnShift; // If this is a two-address operand, skip it. e.g. LDR_PRE. - if (TID.getOperandConstraint(OpIdx, TOI::TIED_TO) != -1) + if (!Skipped && TID.getOperandConstraint(OpIdx, TOI::TIED_TO) != -1) ++OpIdx; const MachineOperand &MO2 = MI.getOperand(OpIdx); @@ -690,11 +821,11 @@ void ARMCodeEmitter::emitLoadStoreInstruction(const MachineInstr &MI, // Set bit[3:0] to the corresponding Rm register Binary |= ARMRegisterInfo::getRegisterNumbering(MO2.getReg()); - // if this instr is in scaled register offset/index instruction, set + // If this instr is in scaled register offset/index instruction, set // shift_immed(bit[11:7]) and shift(bit[6:5]) fields. if (unsigned ShImm = ARM_AM::getAM2Offset(AM2Opc)) { - Binary |= getShiftOp(AM2Opc) << 5; // shift - Binary |= ShImm << 7; // shift_immed + Binary |= getShiftOp(AM2Opc) << ARMII::ShiftImmShift; // shift + Binary |= ShImm << ARMII::ShiftShift; // shift_immed } emitWordLE(Binary); @@ -703,6 +834,8 @@ void ARMCodeEmitter::emitLoadStoreInstruction(const MachineInstr &MI, void ARMCodeEmitter::emitMiscLoadStoreInstruction(const MachineInstr &MI, unsigned ImplicitRn) { const TargetInstrDesc &TID = MI.getDesc(); + unsigned Form = TID.TSFlags & ARMII::FormMask; + bool IsPrePost = (TID.TSFlags & ARMII::IndexModeMask) != 0; // Part of binary is determined by TableGn. unsigned Binary = getBinaryCodeForInstr(MI); @@ -710,11 +843,20 @@ void ARMCodeEmitter::emitMiscLoadStoreInstruction(const MachineInstr &MI, // Set the conditional execution predicate Binary |= II->getPredicate(&MI) << ARMII::CondShift; + unsigned OpIdx = 0; + + // Operand 0 of a pre- and post-indexed store is the address base + // writeback. Skip it. + bool Skipped = false; + if (IsPrePost && Form == ARMII::StMiscFrm) { + ++OpIdx; + Skipped = true; + } + // Set first operand - Binary |= getMachineOpValue(MI, 0) << ARMII::RegRdShift; + Binary |= getMachineOpValue(MI, OpIdx++) << ARMII::RegRdShift; // Set second operand - unsigned OpIdx = 1; if (ImplicitRn) // Special handling for implicit use (e.g. PC). Binary |= (ARMRegisterInfo::getRegisterNumbering(ImplicitRn) @@ -723,7 +865,7 @@ void ARMCodeEmitter::emitMiscLoadStoreInstruction(const MachineInstr &MI, Binary |= getMachineOpValue(MI, OpIdx++) << ARMII::RegRnShift; // If this is a two-address operand, skip it. e.g. LDRH_POST. - if (TID.getOperandConstraint(OpIdx, TOI::TIED_TO) != -1) + if (!Skipped && TID.getOperandConstraint(OpIdx, TOI::TIED_TO) != -1) ++OpIdx; const MachineOperand &MO2 = MI.getOperand(OpIdx); @@ -746,30 +888,21 @@ void ARMCodeEmitter::emitMiscLoadStoreInstruction(const MachineInstr &MI, Binary |= 1 << ARMII::AM3_I_BitShift; if (unsigned ImmOffs = ARM_AM::getAM3Offset(AM3Opc)) { // Set operands - Binary |= (ImmOffs >> 4) << 8; // immedH - Binary |= (ImmOffs & ~0xF); // immedL + Binary |= (ImmOffs >> 4) << ARMII::ImmHiShift; // immedH + Binary |= (ImmOffs & 0xF); // immedL } emitWordLE(Binary); } -void ARMCodeEmitter::emitLoadStoreMultipleInstruction(const MachineInstr &MI) { - // Part of binary is determined by TableGn. - unsigned Binary = getBinaryCodeForInstr(MI); - - // Set the conditional execution predicate - Binary |= II->getPredicate(&MI) << ARMII::CondShift; - - // Set first operand - Binary |= getMachineOpValue(MI, 0) << ARMII::RegRnShift; +static unsigned getAddrModeUPBits(unsigned Mode) { + unsigned Binary = 0; // Set addressing mode by modifying bits U(23) and P(24) // IA - Increment after - bit U = 1 and bit P = 0 // IB - Increment before - bit U = 1 and bit P = 1 // DA - Decrement after - bit U = 0 and bit P = 0 // DB - Decrement before - bit U = 0 and bit P = 1 - const MachineOperand &MO = MI.getOperand(1); - ARM_AM::AMSubMode Mode = ARM_AM::getAM4SubMode(MO.getImm()); switch (Mode) { default: assert(0 && "Unknown addressing sub-mode!"); case ARM_AM::da: break; @@ -778,6 +911,23 @@ void ARMCodeEmitter::emitLoadStoreMultipleInstruction(const MachineInstr &MI) { case ARM_AM::ib: Binary |= 0x3 << ARMII::U_BitShift; break; } + return Binary; +} + +void ARMCodeEmitter::emitLoadStoreMultipleInstruction(const MachineInstr &MI) { + // Part of binary is determined by TableGn. + unsigned Binary = getBinaryCodeForInstr(MI); + + // Set the conditional execution predicate + Binary |= II->getPredicate(&MI) << ARMII::CondShift; + + // Set base address operand + Binary |= getMachineOpValue(MI, 0) << ARMII::RegRnShift; + + // Set addressing mode by modifying bits U(23) and P(24) + const MachineOperand &MO = MI.getOperand(1); + Binary |= getAddrModeUPBits(ARM_AM::getAM4SubMode(MO.getImm())); + // Set bit W(21) if (ARM_AM::getAM4WBFlag(MO.getImm())) Binary |= 0x1 << ARMII::W_BitShift; @@ -785,8 +935,8 @@ void ARMCodeEmitter::emitLoadStoreMultipleInstruction(const MachineInstr &MI) { // Set registers for (unsigned i = 4, e = MI.getNumOperands(); i != e; ++i) { const MachineOperand &MO = MI.getOperand(i); - if (MO.isReg() && MO.isImplicit()) - continue; + if (!MO.isReg() || MO.isImplicit()) + break; unsigned RegNum = ARMRegisterInfo::getRegisterNumbering(MO.getReg()); assert(TargetRegisterInfo::isPhysicalRegister(MO.getReg()) && RegNum < 16); @@ -928,7 +1078,7 @@ void ARMCodeEmitter::emitBranchInstruction(const MachineInstr &MI) { void ARMCodeEmitter::emitInlineJumpTable(unsigned JTIndex) { // Remember the base address of the inline jump table. - intptr_t JTBase = MCE.getCurrentPCValue(); + uintptr_t JTBase = MCE.getCurrentPCValue(); JTI->addJumpTableBaseAddr(JTIndex, JTBase); DOUT << " ** Jump Table #" << JTIndex << " @ " << (void*)JTBase << '\n'; @@ -983,6 +1133,48 @@ void ARMCodeEmitter::emitMiscBranchInstruction(const MachineInstr &MI) { emitWordLE(Binary); } +static unsigned encodeVFPRd(const MachineInstr &MI, unsigned OpIdx) { + unsigned RegD = MI.getOperand(OpIdx).getReg(); + unsigned Binary = 0; + bool isSPVFP = false; + RegD = ARMRegisterInfo::getRegisterNumbering(RegD, isSPVFP); + if (!isSPVFP) + Binary |= RegD << ARMII::RegRdShift; + else { + Binary |= ((RegD & 0x1E) >> 1) << ARMII::RegRdShift; + Binary |= (RegD & 0x01) << ARMII::D_BitShift; + } + return Binary; +} + +static unsigned encodeVFPRn(const MachineInstr &MI, unsigned OpIdx) { + unsigned RegN = MI.getOperand(OpIdx).getReg(); + unsigned Binary = 0; + bool isSPVFP = false; + RegN = ARMRegisterInfo::getRegisterNumbering(RegN, isSPVFP); + if (!isSPVFP) + Binary |= RegN << ARMII::RegRnShift; + else { + Binary |= ((RegN & 0x1E) >> 1) << ARMII::RegRnShift; + Binary |= (RegN & 0x01) << ARMII::N_BitShift; + } + return Binary; +} + +static unsigned encodeVFPRm(const MachineInstr &MI, unsigned OpIdx) { + unsigned RegM = MI.getOperand(OpIdx).getReg(); + unsigned Binary = 0; + bool isSPVFP = false; + RegM = ARMRegisterInfo::getRegisterNumbering(RegM, isSPVFP); + if (!isSPVFP) + Binary |= RegM; + else { + Binary |= ((RegM & 0x1E) >> 1); + Binary |= (RegM & 0x01) << ARMII::M_BitShift; + } + return Binary; +} + void ARMCodeEmitter::emitVFPArithInstruction(const MachineInstr &MI) { const TargetInstrDesc &TID = MI.getDesc(); @@ -998,27 +1190,163 @@ void ARMCodeEmitter::emitVFPArithInstruction(const MachineInstr &MI) { (Binary & ARMII::M_BitShift) == 0 && "VFP encoding bug!"); // Encode Dd / Sd. - unsigned RegD = getMachineOpValue(MI, OpIdx++); - Binary |= (RegD & 0x0f) << ARMII::RegFdShift; - Binary |= (RegD & 0x10) << ARMII::D_BitShift; + Binary |= encodeVFPRd(MI, OpIdx++); // If this is a two-address operand, skip it, e.g. FMACD. if (TID.getOperandConstraint(OpIdx, TOI::TIED_TO) != -1) ++OpIdx; // Encode Dn / Sn. - if ((TID.TSFlags & ARMII::FormMask) == ARMII::VFPBinaryFrm) { - unsigned RegN = getMachineOpValue(MI, OpIdx++); - Binary |= (RegN & 0x0f); - Binary |= (RegN & 0x10) << ARMII::N_BitShift; + if ((TID.TSFlags & ARMII::FormMask) == ARMII::VFPBinaryFrm) + Binary |= encodeVFPRn(MI, OpIdx++); + + if (OpIdx == TID.getNumOperands() || + TID.OpInfo[OpIdx].isPredicate() || + TID.OpInfo[OpIdx].isOptionalDef()) { + // FCMPEZD etc. has only one operand. + emitWordLE(Binary); + return; } // Encode Dm / Sm. - unsigned RegM = getMachineOpValue(MI, OpIdx++); - Binary |= (RegM & 0x0f); - Binary |= (RegM & 0x10) << ARMII::M_BitShift; + Binary |= encodeVFPRm(MI, OpIdx); emitWordLE(Binary); } +void ARMCodeEmitter::emitVFPConversionInstruction(const MachineInstr &MI) { + const TargetInstrDesc &TID = MI.getDesc(); + unsigned Form = TID.TSFlags & ARMII::FormMask; + + // Part of binary is determined by TableGn. + unsigned Binary = getBinaryCodeForInstr(MI); + + // Set the conditional execution predicate + Binary |= II->getPredicate(&MI) << ARMII::CondShift; + + switch (Form) { + default: break; + case ARMII::VFPConv1Frm: + case ARMII::VFPConv2Frm: + case ARMII::VFPConv3Frm: + // Encode Dd / Sd. + Binary |= encodeVFPRd(MI, 0); + break; + case ARMII::VFPConv4Frm: + // Encode Dn / Sn. + Binary |= encodeVFPRn(MI, 0); + break; + case ARMII::VFPConv5Frm: + // Encode Dm / Sm. + Binary |= encodeVFPRm(MI, 0); + break; + } + + switch (Form) { + default: break; + case ARMII::VFPConv1Frm: + // Encode Dm / Sm. + Binary |= encodeVFPRm(MI, 1); + break; + case ARMII::VFPConv2Frm: + case ARMII::VFPConv3Frm: + // Encode Dn / Sn. + Binary |= encodeVFPRn(MI, 1); + break; + case ARMII::VFPConv4Frm: + case ARMII::VFPConv5Frm: + // Encode Dd / Sd. + Binary |= encodeVFPRd(MI, 1); + break; + } + + if (Form == ARMII::VFPConv5Frm) + // Encode Dn / Sn. + Binary |= encodeVFPRn(MI, 2); + else if (Form == ARMII::VFPConv3Frm) + // Encode Dm / Sm. + Binary |= encodeVFPRm(MI, 2); + + emitWordLE(Binary); +} + +void ARMCodeEmitter::emitVFPLoadStoreInstruction(const MachineInstr &MI) { + // Part of binary is determined by TableGn. + unsigned Binary = getBinaryCodeForInstr(MI); + + // Set the conditional execution predicate + Binary |= II->getPredicate(&MI) << ARMII::CondShift; + + unsigned OpIdx = 0; + + // Encode Dd / Sd. + Binary |= encodeVFPRd(MI, OpIdx++); + + // Encode address base. + const MachineOperand &Base = MI.getOperand(OpIdx++); + Binary |= getMachineOpValue(MI, Base) << ARMII::RegRnShift; + + // If there is a non-zero immediate offset, encode it. + if (Base.isReg()) { + const MachineOperand &Offset = MI.getOperand(OpIdx); + if (unsigned ImmOffs = ARM_AM::getAM5Offset(Offset.getImm())) { + if (ARM_AM::getAM5Op(Offset.getImm()) == ARM_AM::add) + Binary |= 1 << ARMII::U_BitShift; + Binary |= ImmOffs; + emitWordLE(Binary); + return; + } + } + + // If immediate offset is omitted, default to +0. + Binary |= 1 << ARMII::U_BitShift; + + emitWordLE(Binary); +} + +void +ARMCodeEmitter::emitVFPLoadStoreMultipleInstruction(const MachineInstr &MI) { + // Part of binary is determined by TableGn. + unsigned Binary = getBinaryCodeForInstr(MI); + + // Set the conditional execution predicate + Binary |= II->getPredicate(&MI) << ARMII::CondShift; + + // Set base address operand + Binary |= getMachineOpValue(MI, 0) << ARMII::RegRnShift; + + // Set addressing mode by modifying bits U(23) and P(24) + const MachineOperand &MO = MI.getOperand(1); + Binary |= getAddrModeUPBits(ARM_AM::getAM5SubMode(MO.getImm())); + + // Set bit W(21) + if (ARM_AM::getAM5WBFlag(MO.getImm())) + Binary |= 0x1 << ARMII::W_BitShift; + + // First register is encoded in Dd. + Binary |= encodeVFPRd(MI, 4); + + // Number of registers are encoded in offset field. + unsigned NumRegs = 1; + for (unsigned i = 5, e = MI.getNumOperands(); i != e; ++i) { + const MachineOperand &MO = MI.getOperand(i); + if (!MO.isReg() || MO.isImplicit()) + break; + ++NumRegs; + } + Binary |= NumRegs * 2; + + emitWordLE(Binary); +} + +void ARMCodeEmitter::emitMiscInstruction(const MachineInstr &MI) { + // Part of binary is determined by TableGn. + unsigned Binary = getBinaryCodeForInstr(MI); + + // Set the conditional execution predicate + Binary |= II->getPredicate(&MI) << ARMII::CondShift; + + emitWordLE(Binary); +} + #include "ARMGenCodeEmitter.inc"