diff --git a/lib/Target/ARM/ARMCodeEmitter.cpp b/lib/Target/ARM/ARMCodeEmitter.cpp index 29a8f31a514..2288ad1d37c 100644 --- a/lib/Target/ARM/ARMCodeEmitter.cpp +++ b/lib/Target/ARM/ARMCodeEmitter.cpp @@ -124,6 +124,12 @@ namespace { 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. @@ -326,6 +332,15 @@ void ARMCodeEmitter::emitInstruction(const MachineInstr &MI) { case ARMII::VFPConv2Frm: emitVFPConversionInstruction(MI); break; + case ARMII::VFPLdStFrm: + emitVFPLoadStoreInstruction(MI); + break; + case ARMII::VFPLdStMulFrm: + emitVFPLoadStoreMultipleInstruction(MI); + break; + case ARMII::VFPMiscFrm: + emitMiscInstruction(MI); + break; } } @@ -759,23 +774,14 @@ void ARMCodeEmitter::emitMiscLoadStoreInstruction(const MachineInstr &MI, 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; @@ -784,6 +790,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; @@ -791,8 +814,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); @@ -1064,4 +1087,87 @@ void ARMCodeEmitter::emitVFPConversionInstruction(const MachineInstr &MI) { 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. + unsigned RegD = getMachineOpValue(MI, OpIdx++); + Binary |= (RegD & 0x0f) << ARMII::RegRdShift; + Binary |= (RegD & 0x10) << ARMII::D_BitShift; + + // 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; + // Immediate offset is multiplied by 4. + Binary |= ImmOffs >> 2; + 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. + unsigned FirstReg = MI.getOperand(4).getReg(); + Binary |= ARMRegisterInfo::getRegisterNumbering(FirstReg)<< ARMII::RegRdShift; + + // 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" diff --git a/lib/Target/ARM/ARMInstrFormats.td b/lib/Target/ARM/ARMInstrFormats.td index 5efa76db8e1..b59af13cd9e 100644 --- a/lib/Target/ARM/ARMInstrFormats.td +++ b/lib/Target/ARM/ARMInstrFormats.td @@ -19,29 +19,33 @@ class Format val> { bits<5> Value = val; } -def Pseudo : Format<1>; -def MulFrm : Format<2>; -def BrFrm : Format<3>; -def BrMiscFrm : Format<4>; +def Pseudo : Format<1>; +def MulFrm : Format<2>; +def BrFrm : Format<3>; +def BrMiscFrm : Format<4>; -def DPFrm : Format<5>; -def DPSoRegFrm : Format<6>; +def DPFrm : Format<5>; +def DPSoRegFrm : Format<6>; -def LdFrm : Format<7>; -def StFrm : Format<8>; -def LdMiscFrm : Format<9>; -def StMiscFrm : Format<10>; -def LdMulFrm : Format<11>; -def StMulFrm : Format<12>; +def LdFrm : Format<7>; +def StFrm : Format<8>; +def LdMiscFrm : Format<9>; +def StMiscFrm : Format<10>; +def LdMulFrm : Format<11>; +def StMulFrm : Format<12>; -def ArithMiscFrm: Format<13>; -def ExtFrm : Format<14>; -def VFPFrm : Format<15>; -def VFPUnaryFrm : Format<16>; -def VFPBinaryFrm: Format<17>; -def VFPConv1Frm : Format<18>; -def VFPConv2Frm : Format<19>; -def ThumbFrm : Format<20>; +def ArithMiscFrm : Format<13>; +def ExtFrm : Format<14>; + +def VFPUnaryFrm : Format<15>; +def VFPBinaryFrm : Format<16>; +def VFPConv1Frm : Format<17>; +def VFPConv2Frm : Format<18>; +def VFPLdStFrm : Format<19>; +def VFPLdStMulFrm : Format<20>; +def VFPMiscFrm : Format<21>; + +def ThumbFrm : Format<22>; // Misc flag for data processing instructions that indicates whether // the instruction has a Rn register operand. @@ -738,30 +742,45 @@ class TJTI pattern> // ARM VFP Instruction templates. // -// ARM Float Instruction -class ASI pattern> - : AI { - // TODO: Mark the instructions with the appropriate subtarget info. -} - -class ASI5 pattern> +// ARM VFP addrmode5 loads and stores +class ADI5 opcod1, bits<2> opcod2, dag oops, dag iops, + string opc, string asm, list pattern> : I { + VFPLdStFrm, opc, asm, "", pattern> { // TODO: Mark the instructions with the appropriate subtarget info. + let Inst{27-24} = opcod1; + let Inst{21-20} = opcod2; + let Inst{11-8} = 0b1011; } -// ARM Double Instruction -class ADI pattern> - : AI { - // TODO: Mark the instructions with the appropriate subtarget info. -} - -class ADI5 pattern> +class ASI5 opcod1, bits<2> opcod2, dag oops, dag iops, + string opc, string asm, list pattern> : I { + VFPLdStFrm, opc, asm, "", pattern> { // TODO: Mark the instructions with the appropriate subtarget info. + let Inst{27-24} = opcod1; + let Inst{21-20} = opcod2; + let Inst{11-8} = 0b1010; } +// Load / store multiple +class AXSI5 pattern> + : XI { + // TODO: Mark the instructions with the appropriate subtarget info. + let Inst{27-25} = 0b110; + let Inst{11-8} = 0b1011; +} + +class AXDI5 pattern> + : XI { + // TODO: Mark the instructions with the appropriate subtarget info. + let Inst{27-25} = 0b110; + let Inst{11-8} = 0b1010; +} + + // Double precision, unary class ADuI opcod1, bits<4> opcod2, bits<4> opcod3, dag oops, dag iops, string opc, string asm, list pattern> @@ -817,32 +836,6 @@ class AVConv2I opcod1, bits<4> opcod2, bits<4> opcod3, let Inst{6} = 1; } -// Special cases. -class AXSI pattern> - : XI { - // TODO: Mark the instructions with the appropriate subtarget info. -} - -class AXSI5 pattern> - : XI { - // TODO: Mark the instructions with the appropriate subtarget info. -} - -class AXDI pattern> - : XI { - // TODO: Mark the instructions with the appropriate subtarget info. -} - -class AXDI5 pattern> - : XI { - // TODO: Mark the instructions with the appropriate subtarget info. -} - - //===----------------------------------------------------------------------===// diff --git a/lib/Target/ARM/ARMInstrInfo.h b/lib/Target/ARM/ARMInstrInfo.h index ccaeac56a12..c77a6288f6f 100644 --- a/lib/Target/ARM/ARMInstrInfo.h +++ b/lib/Target/ARM/ARMInstrInfo.h @@ -69,46 +69,48 @@ namespace ARMII { //===------------------------------------------------------------------===// // Instruction encoding formats. // - FormShift = 10, - FormMask = 0x1f << FormShift, + FormShift = 10, + FormMask = 0x1f << FormShift, // Pseudo instructions - Pseudo = 1 << FormShift, + Pseudo = 1 << FormShift, // Multiply instructions - MulFrm = 2 << FormShift, + MulFrm = 2 << FormShift, // Branch instructions - BrFrm = 3 << FormShift, - BrMiscFrm = 4 << FormShift, + BrFrm = 3 << FormShift, + BrMiscFrm = 4 << FormShift, // Data Processing instructions - DPFrm = 5 << FormShift, - DPSoRegFrm = 6 << FormShift, + DPFrm = 5 << FormShift, + DPSoRegFrm = 6 << FormShift, // Load and Store - LdFrm = 7 << FormShift, - StFrm = 8 << FormShift, - LdMiscFrm = 9 << FormShift, - StMiscFrm = 10 << FormShift, - LdMulFrm = 11 << FormShift, - StMulFrm = 12 << FormShift, + LdFrm = 7 << FormShift, + StFrm = 8 << FormShift, + LdMiscFrm = 9 << FormShift, + StMiscFrm = 10 << FormShift, + LdMulFrm = 11 << FormShift, + StMulFrm = 12 << FormShift, // Miscellaneous arithmetic instructions - ArithMiscFrm= 13 << FormShift, + ArithMiscFrm = 13 << FormShift, // Extend instructions - ExtFrm = 14 << FormShift, + ExtFrm = 14 << FormShift, // VFP formats - VPFFrm = 15 << FormShift, - VFPUnaryFrm = 16 << FormShift, - VFPBinaryFrm = 17 << FormShift, - VFPConv1Frm = 18 << FormShift, - VFPConv2Frm = 19 << FormShift, + VFPUnaryFrm = 15 << FormShift, + VFPBinaryFrm = 16 << FormShift, + VFPConv1Frm = 17 << FormShift, + VFPConv2Frm = 18 << FormShift, + VFPLdStFrm = 19 << FormShift, + VFPLdStMulFrm = 20 << FormShift, + VFPMiscFrm = 21 << FormShift, // Thumb format - ThumbFrm = 20 << FormShift, + ThumbFrm = 22 << FormShift, //===------------------------------------------------------------------===// // Field shifts - such shifts are used to set field while generating diff --git a/lib/Target/ARM/ARMInstrVFP.td b/lib/Target/ARM/ARMInstrVFP.td index 2dc3f0bacf8..442c12abcb9 100644 --- a/lib/Target/ARM/ARMInstrVFP.td +++ b/lib/Target/ARM/ARMInstrVFP.td @@ -35,20 +35,20 @@ def arm_fmdrr : SDNode<"ARMISD::FMDRR", SDT_FMDRR>; // let isSimpleLoad = 1 in { -def FLDD : ADI5<(outs DPR:$dst), (ins addrmode5:$addr), +def FLDD : ADI5<0b1101, 0b01, (outs DPR:$dst), (ins addrmode5:$addr), "fldd", " $dst, $addr", [(set DPR:$dst, (load addrmode5:$addr))]>; -def FLDS : ASI5<(outs SPR:$dst), (ins addrmode5:$addr), +def FLDS : ASI5<0b1101, 0b01, (outs SPR:$dst), (ins addrmode5:$addr), "flds", " $dst, $addr", [(set SPR:$dst, (load addrmode5:$addr))]>; } // isSimpleLoad -def FSTD : ADI5<(outs), (ins DPR:$src, addrmode5:$addr), +def FSTD : ADI5<0b1101, 0b00, (outs), (ins DPR:$src, addrmode5:$addr), "fstd", " $src, $addr", [(store DPR:$src, addrmode5:$addr)]>; -def FSTS : ASI5<(outs), (ins SPR:$src, addrmode5:$addr), +def FSTS : ASI5<0b1101, 0b00, (outs), (ins SPR:$src, addrmode5:$addr), "fsts", " $src, $addr", [(store SPR:$src, addrmode5:$addr)]>; @@ -60,24 +60,32 @@ let mayLoad = 1 in { def FLDMD : AXDI5<(outs), (ins addrmode5:$addr, pred:$p, reglist:$dst1, variable_ops), "fldm${addr:submode}d${p} ${addr:base}, $dst1", - []>; + []> { + let Inst{20} = 1; +} def FLDMS : AXSI5<(outs), (ins addrmode5:$addr, pred:$p, reglist:$dst1, variable_ops), "fldm${addr:submode}s${p} ${addr:base}, $dst1", - []>; + []> { + let Inst{20} = 1; +} } let mayStore = 1 in { def FSTMD : AXDI5<(outs), (ins addrmode5:$addr, pred:$p, reglist:$src1, variable_ops), "fstm${addr:submode}d${p} ${addr:base}, $src1", - []>; + []> { + let Inst{20} = 0; +} def FSTMS : AXSI5<(outs), (ins addrmode5:$addr, pred:$p, reglist:$src1, variable_ops), "fstm${addr:submode}s${p} ${addr:base}, $src1", - []>; + []> { + let Inst{20} = 0; +} } // mayStore // FLDMX, FSTMX - mixing S/D registers for pre-armv6 cores @@ -384,4 +392,11 @@ def FNEGScc : ASuI<0b11101011, 0b0001, 0b0100, // let Defs = [CPSR] in -def FMSTAT : ASI<(outs), (ins), "fmstat", "", [(arm_fmstat)]>; +def FMSTAT : AI<(outs), (ins), VFPMiscFrm, "fmstat", "", [(arm_fmstat)]> { + let Inst{27-20} = 0b11101111; + let Inst{19-16} = 0b0001; + let Inst{15-12} = 0b1111; + let Inst{11-8} = 0b1010; + let Inst{7} = 0; + let Inst{4} = 1; +}