From edda31c412d524531ee6cd3f2d21c2ef85b6afb0 Mon Sep 17 00:00:00 2001 From: Evan Cheng Date: Wed, 5 Nov 2008 18:35:52 +0000 Subject: [PATCH] Restructure ARM code emitter to use instruction formats instead of addressing modes to determine how to encode instructions. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@58764 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Target/ARM/ARM.td | 4 +- lib/Target/ARM/ARMCodeEmitter.cpp | 260 ++++++++++++++++-------------- lib/Target/ARM/ARMInstrFormats.td | 77 ++++----- lib/Target/ARM/ARMInstrInfo.h | 74 ++++----- lib/Target/ARM/ARMInstrInfo.td | 172 ++++++++++---------- 5 files changed, 302 insertions(+), 285 deletions(-) diff --git a/lib/Target/ARM/ARM.td b/lib/Target/ARM/ARM.td index 290f8ff3999..3ce8baaab4a 100644 --- a/lib/Target/ARM/ARM.td +++ b/lib/Target/ARM/ARM.td @@ -102,12 +102,14 @@ def ARMInstrInfo : InstrInfo { "SizeFlag", "IndexModeBits", "Opcode", + "isUnaryDataProc", "Form"]; let TSFlagsShifts = [0, 4, 7, 9, - 13]; + 13, + 14]; } //===----------------------------------------------------------------------===// diff --git a/lib/Target/ARM/ARMCodeEmitter.cpp b/lib/Target/ARM/ARMCodeEmitter.cpp index 47aa22b7d9d..193df988dc1 100644 --- a/lib/Target/ARM/ARMCodeEmitter.cpp +++ b/lib/Target/ARM/ARMCodeEmitter.cpp @@ -69,10 +69,6 @@ namespace { void emitPseudoInstruction(const MachineInstr &MI); - unsigned getAddrModeNoneInstrBinary(const MachineInstr &MI, - const TargetInstrDesc &TID, - unsigned Binary); - unsigned getMachineSoRegOpValue(const MachineInstr &MI, const TargetInstrDesc &TID, const MachineOperand &MO, @@ -85,25 +81,19 @@ namespace { unsigned getAddrModeSBit(const MachineInstr &MI, const TargetInstrDesc &TID) const; - unsigned getAddrMode1InstrBinary(const MachineInstr &MI, - const TargetInstrDesc &TID, - unsigned Binary); - unsigned getAddrMode2InstrBinary(const MachineInstr &MI, - const TargetInstrDesc &TID, - unsigned Binary); - unsigned getAddrMode3InstrBinary(const MachineInstr &MI, - const TargetInstrDesc &TID, - unsigned Binary); - unsigned getAddrMode4InstrBinary(const MachineInstr &MI, - const TargetInstrDesc &TID, - unsigned Binary); - unsigned getAddrMode6InstrBinary(const MachineInstr &MI, - const TargetInstrDesc &TID, - unsigned Binary); - - /// getInstrBinary - Return binary encoding for the specified - /// machine instruction. - unsigned getInstrBinary(const MachineInstr &MI); + void emitDataProcessingInstruction(const MachineInstr &MI); + + void emitLoadStoreInstruction(const MachineInstr &MI); + + void emitMiscLoadStoreInstruction(const MachineInstr &MI); + + void emitLoadStoreMultipleInstruction(const MachineInstr &MI); + + void emitMulFrm1Instruction(const MachineInstr &MI); + + void emitBranchInstruction(const MachineInstr &MI); + + void emitMiscBranchInstruction(const MachineInstr &MI); /// getBinaryCodeForInstr - This function, generated by the /// CodeEmitterGenerator using TableGen, produces the binary encoding for @@ -260,10 +250,39 @@ void ARMCodeEmitter::emitInstruction(const MachineInstr &MI) { DOUT << "JIT: " << (void*)MCE.getCurrentPCValue() << ":\t" << MI; NumEmitted++; // Keep track of the # of mi's emitted - if ((MI.getDesc().TSFlags & ARMII::FormMask) == ARMII::Pseudo) + switch (MI.getDesc().TSFlags & ARMII::FormMask) { + default: + assert(0 && "Unhandled instruction encoding format!"); + break; + case ARMII::Pseudo: emitPseudoInstruction(MI); - else - MCE.emitWordLE(getInstrBinary(MI)); + break; + case ARMII::DPFrm: + case ARMII::DPSoRegFrm: + emitDataProcessingInstruction(MI); + break; + case ARMII::LdFrm: + case ARMII::StFrm: + emitLoadStoreInstruction(MI); + break; + case ARMII::LdMiscFrm: + case ARMII::StMiscFrm: + emitMiscLoadStoreInstruction(MI); + break; + case ARMII::LdMulFrm: + case ARMII::StMulFrm: + emitLoadStoreMultipleInstruction(MI); + break; + case ARMII::MulFrm1: + emitMulFrm1Instruction(MI); + break; + case ARMII::Branch: + emitBranchInstruction(MI); + break; + case ARMII::BranchMisc: + emitMiscBranchInstruction(MI); + break; + } } void ARMCodeEmitter::emitConstPoolInstruction(const MachineInstr &MI) { @@ -329,51 +348,13 @@ void ARMCodeEmitter::emitPseudoInstruction(const MachineInstr &MI) { JTI->addPCLabelAddr(MO2.getImm(), MCE.getCurrentPCValue()); // PICADD is just an add instruction that implicitly read pc. - unsigned Binary = getBinaryCodeForInstr(MI); - const TargetInstrDesc &TID = MI.getDesc(); - MCE.emitWordLE(getAddrMode1InstrBinary(MI, TID, Binary)); + emitDataProcessingInstruction(MI); break; } } } -unsigned ARMCodeEmitter::getAddrModeNoneInstrBinary(const MachineInstr &MI, - const TargetInstrDesc &TID, - unsigned Binary) { - // Set the conditional execution predicate - Binary |= II->getPredicate(&MI) << 28; - - switch (TID.TSFlags & ARMII::FormMask) { - default: - assert(0 && "Unknown instruction subtype!"); - break; - case ARMII::Branch: { - // Set signed_immed_24 field - Binary |= getMachineOpValue(MI, 0); - - // if it is a conditional branch, set cond field - if (TID.Opcode == ARM::Bcc) { - Binary &= 0x0FFFFFFF; // clear conditional field - Binary |= getMachineOpValue(MI, 1) << 28; // set conditional field - } - break; - } - case ARMII::BranchMisc: { - if (TID.Opcode == ARM::BX) - abort(); // FIXME - if (TID.Opcode == ARM::BX_RET) - Binary |= 0xe; // the return register is LR - else - // otherwise, set the return register - Binary |= getMachineOpValue(MI, 0); - break; - } - } - - return Binary; -} - unsigned ARMCodeEmitter::getMachineSoRegOpValue(const MachineInstr &MI, const TargetInstrDesc &TID, const MachineOperand &MO, @@ -453,9 +434,14 @@ unsigned ARMCodeEmitter::getAddrModeSBit(const MachineInstr &MI, return 0; } -unsigned ARMCodeEmitter::getAddrMode1InstrBinary(const MachineInstr &MI, - const TargetInstrDesc &TID, - unsigned Binary) { +void ARMCodeEmitter::emitDataProcessingInstruction(const MachineInstr &MI) { + const TargetInstrDesc &TID = MI.getDesc(); + if (TID.getOpcode() == ARM::MOVi2pieces) + abort(); // FIXME + + // Part of binary is determined by TableGn. + unsigned Binary = getBinaryCodeForInstr(MI); + // Set the conditional execution predicate Binary |= II->getPredicate(&MI) << 28; @@ -471,16 +457,12 @@ unsigned ARMCodeEmitter::getAddrMode1InstrBinary(const MachineInstr &MI, } // Encode first non-shifter register operand if there is one. - unsigned Format = TID.TSFlags & ARMII::FormMask; - bool HasRnReg = !(Format == ARMII::DPRdMisc || - Format == ARMII::DPRdIm || - Format == ARMII::DPRdReg || - Format == ARMII::DPRdSoReg); - if (HasRnReg) { + bool isUnary = TID.TSFlags & ARMII::UnaryDP; + if (!isUnary) { if (TID.getOpcode() == ARM::PICADD) - // Special handling for PICADD. It implicitly use add. - Binary |= - ARMRegisterInfo::getRegisterNumbering(ARM::PC) << ARMII::RegRnShift; + // Special handling for PICADD. It implicitly uses PC register. + Binary |= (ARMRegisterInfo::getRegisterNumbering(ARM::PC) + << ARMII::RegRnShift); else { Binary |= getMachineOpValue(MI, OpIdx) << ARMII::RegRnShift; ++OpIdx; @@ -488,30 +470,33 @@ unsigned ARMCodeEmitter::getAddrMode1InstrBinary(const MachineInstr &MI, } // Encode shifter operand. - bool HasSoReg = (Format == ARMII::DPRdSoReg || - Format == ARMII::DPRnSoReg || - Format == ARMII::DPRSoReg || - Format == ARMII::DPRSoRegS); - const MachineOperand &MO = MI.getOperand(OpIdx); - if (HasSoReg) + if ((TID.TSFlags & ARMII::FormMask) == ARMII::DPSoRegFrm) { // Encode SoReg. - return Binary | getMachineSoRegOpValue(MI, TID, MO, OpIdx); + MCE.emitWordLE(Binary | getMachineSoRegOpValue(MI, TID, MO, OpIdx)); + return; + } - if (MO.isReg()) + if (MO.isReg()) { // Encode register Rm. - return Binary | ARMRegisterInfo::getRegisterNumbering(MO.getReg()); + MCE.emitWordLE(Binary | ARMRegisterInfo::getRegisterNumbering(MO.getReg())); + return; + } // 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); - return Binary; + + MCE.emitWordLE(Binary); } -unsigned ARMCodeEmitter::getAddrMode2InstrBinary(const MachineInstr &MI, - const TargetInstrDesc &TID, - unsigned Binary) { +void ARMCodeEmitter::emitLoadStoreInstruction(const MachineInstr &MI) { + const TargetInstrDesc &TID = MI.getDesc(); + + // Part of binary is determined by TableGn. + unsigned Binary = getBinaryCodeForInstr(MI); + // Set the conditional execution predicate Binary |= II->getPredicate(&MI) << 28; @@ -531,7 +516,8 @@ unsigned ARMCodeEmitter::getAddrMode2InstrBinary(const MachineInstr &MI, if (ARM_AM::getAM2Offset(MO3.getImm())) // Set the value of offset_12 field Binary |= ARM_AM::getAM2Offset(MO3.getImm()); - return Binary; + MCE.emitWordLE(Binary); + return; } // Set bit I(25), because this is not in immediate enconding. @@ -547,12 +533,15 @@ unsigned ARMCodeEmitter::getAddrMode2InstrBinary(const MachineInstr &MI, Binary |= ShImm << 7; // shift_immed } - return Binary; + MCE.emitWordLE(Binary); } -unsigned ARMCodeEmitter::getAddrMode3InstrBinary(const MachineInstr &MI, - const TargetInstrDesc &TID, - unsigned Binary) { +void ARMCodeEmitter::emitMiscLoadStoreInstruction(const MachineInstr &MI) { + const TargetInstrDesc &TID = MI.getDesc(); + + // Part of binary is determined by TableGn. + unsigned Binary = getBinaryCodeForInstr(MI); + // Set the conditional execution predicate Binary |= II->getPredicate(&MI) << 28; @@ -573,7 +562,8 @@ unsigned ARMCodeEmitter::getAddrMode3InstrBinary(const MachineInstr &MI, // to the corresponding Rm register. if (MO2.getReg()) { Binary |= ARMRegisterInfo::getRegisterNumbering(MO2.getReg()); - return Binary; + MCE.emitWordLE(Binary); + return; } // if this instr is in immediate offset/index encoding, set bit 22 to 1 @@ -584,12 +574,15 @@ unsigned ARMCodeEmitter::getAddrMode3InstrBinary(const MachineInstr &MI, Binary |= (ImmOffs & ~0xF); // immedL } - return Binary; + MCE.emitWordLE(Binary); } -unsigned ARMCodeEmitter::getAddrMode4InstrBinary(const MachineInstr &MI, - const TargetInstrDesc &TID, - unsigned Binary) { +void ARMCodeEmitter::emitLoadStoreMultipleInstruction(const MachineInstr &MI) { + const TargetInstrDesc &TID = MI.getDesc(); + + // Part of binary is determined by TableGn. + unsigned Binary = getBinaryCodeForInstr(MI); + // Set the conditional execution predicate Binary |= II->getPredicate(&MI) << 28; @@ -626,12 +619,15 @@ unsigned ARMCodeEmitter::getAddrMode4InstrBinary(const MachineInstr &MI, Binary |= 0x1 << RegNum; } - return Binary; + MCE.emitWordLE(Binary); } -unsigned ARMCodeEmitter::getAddrMode6InstrBinary(const MachineInstr &MI, - const TargetInstrDesc &TID, - unsigned Binary) { +void ARMCodeEmitter::emitMulFrm1Instruction(const MachineInstr &MI) { + const TargetInstrDesc &TID = MI.getDesc(); + + // Part of binary is determined by TableGn. + unsigned Binary = getBinaryCodeForInstr(MI); + // Set the conditional execution predicate Binary |= II->getPredicate(&MI) << 28; @@ -653,33 +649,49 @@ unsigned ARMCodeEmitter::getAddrMode6InstrBinary(const MachineInstr &MI, // Encode Rs Binary |= getMachineOpValue(MI, OpIdx++) << ARMII::RegRsShift; - return Binary; + MCE.emitWordLE(Binary); } -/// getInstrBinary - Return binary encoding for the specified -/// machine instruction. -unsigned ARMCodeEmitter::getInstrBinary(const MachineInstr &MI) { +void ARMCodeEmitter::emitBranchInstruction(const MachineInstr &MI) { + const TargetInstrDesc &TID = MI.getDesc(); + // Part of binary is determined by TableGn. unsigned Binary = getBinaryCodeForInstr(MI); - const TargetInstrDesc &TID = MI.getDesc(); - switch (TID.TSFlags & ARMII::AddrModeMask) { - case ARMII::AddrModeNone: - return getAddrModeNoneInstrBinary(MI, TID, Binary); - case ARMII::AddrMode1: - return getAddrMode1InstrBinary(MI, TID, Binary); - case ARMII::AddrMode2: - return getAddrMode2InstrBinary(MI, TID, Binary); - case ARMII::AddrMode3: - return getAddrMode3InstrBinary(MI, TID, Binary); - case ARMII::AddrMode4: - return getAddrMode4InstrBinary(MI, TID, Binary); - case ARMII::AddrMode6: - return getAddrMode6InstrBinary(MI, TID, Binary); + // Set the conditional execution predicate + Binary |= II->getPredicate(&MI) << 28; + + // Set signed_immed_24 field + Binary |= getMachineOpValue(MI, 0); + + // if it is a conditional branch, set cond field + if (TID.Opcode == ARM::Bcc) { + Binary &= 0x0FFFFFFF; // clear conditional field + Binary |= getMachineOpValue(MI, 1) << 28; // set conditional field } - abort(); - return 0; + MCE.emitWordLE(Binary); +} + +void ARMCodeEmitter::emitMiscBranchInstruction(const MachineInstr &MI) { + const TargetInstrDesc &TID = MI.getDesc(); + if (TID.Opcode == ARM::BX) + abort(); // FIXME + + // Part of binary is determined by TableGn. + unsigned Binary = getBinaryCodeForInstr(MI); + + // Set the conditional execution predicate + Binary |= II->getPredicate(&MI) << 28; + + if (TID.Opcode == ARM::BX_RET) + // The return register is LR. + Binary |= ARMRegisterInfo::getRegisterNumbering(ARM::LR); + else + // otherwise, set the return register + Binary |= getMachineOpValue(MI, 0); + + MCE.emitWordLE(Binary); } #include "ARMGenCodeEmitter.inc" diff --git a/lib/Target/ARM/ARMInstrFormats.td b/lib/Target/ARM/ARMInstrFormats.td index e64247763e6..d284cd0dd5b 100644 --- a/lib/Target/ARM/ARMInstrFormats.td +++ b/lib/Target/ARM/ARMInstrFormats.td @@ -20,35 +20,32 @@ class Format val> { } def Pseudo : Format<1>; -def MulFrm : Format<2>; -def MulSMLAW : Format<3>; -def MulSMULW : Format<4>; -def MulSMLA : Format<5>; -def MulSMUL : Format<6>; -def Branch : Format<7>; -def BranchMisc : Format<8>; - -def DPRdIm : Format<9>; -def DPRdReg : Format<10>; -def DPRdSoReg : Format<11>; -def DPRdMisc : Format<12>; -def DPRnIm : Format<13>; -def DPRnReg : Format<14>; -def DPRnSoReg : Format<15>; -def DPRIm : Format<16>; -def DPRReg : Format<17>; -def DPRSoReg : Format<18>; -def DPRImS : Format<19>; -def DPRRegS : Format<20>; -def DPRSoRegS : Format<21>; - -def LdFrm : Format<22>; -def StFrm : Format<23>; - -def ArithMisc : Format<24>; -def ThumbFrm : Format<25>; -def VFPFrm : Format<26>; - +def MulFrm1 : Format<2>; +def MulFrm2 : Format<3>; +def MulSMLAW : Format<4>; +def MulSMULW : Format<5>; +def MulSMLA : Format<6>; +def MulSMUL : Format<7>; +def Branch : Format<8>; +def BranchMisc : Format<9>; + +def DPFrm : Format<10>; +def DPSoRegFrm : Format<11>; + +def LdFrm : Format<12>; +def StFrm : Format<13>; +def LdMiscFrm : Format<14>; +def StMiscFrm : Format<15>; +def LdMulFrm : Format<16>; +def StMulFrm : Format<17>; + +def ArithMisc : Format<18>; +def ThumbFrm : Format<19>; +def VFPFrm : Format<20>; + +// Misc flag for data processing instructions that indicates whether +// the instruction has a Rn register operand. +class UnaryDP { bit isUnaryDataProc = 1; } //===----------------------------------------------------------------------===// @@ -63,6 +60,8 @@ class InstARM opcod, AddrMode am, SizeFlagVal sz, IndexMode im, let Namespace = "ARM"; bits<4> Opcode = opcod; + + // TSFlagsFields AddrMode AM = am; bits<4> AddrModeBits = AM.Value; @@ -74,6 +73,11 @@ class InstARM opcod, AddrMode am, SizeFlagVal sz, IndexMode im, Format F = f; bits<5> Form = F.Value; + + // + // Attributes specific to ARM instructions... + // + bit isUnaryDataProc = 0; let Constraints = cstr; } @@ -658,23 +662,20 @@ class AXI4st opcod, dag oops, dag iops, Format f, string asm, let Inst{27-25} = 0b100; } -// addrmode6 // Unsigned multiply, multiply-accumulate instructions. -class AI6 opcod, dag oops, dag iops, Format f, string opc, +class AMul1I opcod, dag oops, dag iops, string opc, string asm, list pattern> - : I -{ + : I { // FIXME: bits 7-4 should be a sub-mode (for SMLAxx, SMLAWy, ...) let Inst{7-4} = 0b1001; let Inst{27-24} = 0b0000; let Inst{23-20} = opcod; } -class AsI6 opcod, dag oops, dag iops, Format f, string opc, +class AsMul1I opcod, dag oops, dag iops, string opc, string asm, list pattern> - : sI -{ + : sI { // FIXME: bits 7-4 should be a sub-mode (for SMLAxx, SMLAWy, ...) let Inst{7-4} = 0b1001; let Inst{27-24} = 0b0000; diff --git a/lib/Target/ARM/ARMInstrInfo.h b/lib/Target/ARM/ARMInstrInfo.h index eb6109ebf3a..6f1bf3831dd 100644 --- a/lib/Target/ARM/ARMInstrInfo.h +++ b/lib/Target/ARM/ARMInstrInfo.h @@ -39,11 +39,10 @@ namespace ARMII { AddrMode3 = 3, AddrMode4 = 4, AddrMode5 = 5, - AddrMode6 = 6, - AddrModeT1 = 7, - AddrModeT2 = 8, - AddrModeT4 = 9, - AddrModeTs = 10, // i8 * 4 for pc and sp relative data + AddrModeT1 = 6, + AddrModeT2 = 7, + AddrModeT4 = 8, + AddrModeTs = 9, // i8 * 4 for pc and sp relative data // Size* - Flags to keep track of the size of an instruction. SizeShift = 4, @@ -63,56 +62,57 @@ namespace ARMII { // Opcode OpcodeShift = 9, OpcodeMask = 0xf << OpcodeShift, - - // Format - FormShift = 13, - FormMask = 31 << FormShift, + + //===------------------------------------------------------------------===// + // Misc flags. + + // UnaryDP - Indicates this is a unary data processing instruction, i.e. + // it doesn't have a Rn operand. + UnaryDP = 1 << 13, + + //===------------------------------------------------------------------===// + // Instruction encoding formats. + // + FormShift = 14, + FormMask = 0x1f << FormShift, // Pseudo instructions Pseudo = 1 << FormShift, // Multiply instructions - MulFrm = 2 << FormShift, - MulSMLAW = 3 << FormShift, - MulSMULW = 4 << FormShift, - MulSMLA = 5 << FormShift, - MulSMUL = 6 << FormShift, + MulFrm1 = 2 << FormShift, + MulFrm2 = 3 << FormShift, + MulSMLAW = 4 << FormShift, + MulSMULW = 5 << FormShift, + MulSMLA = 6 << FormShift, + MulSMUL = 7 << FormShift, // Branch instructions - Branch = 7 << FormShift, - BranchMisc = 8 << FormShift, + Branch = 8 << FormShift, + BranchMisc = 9 << FormShift, // Data Processing instructions - DPRdIm = 9 << FormShift, - DPRdReg = 10 << FormShift, - DPRdSoReg = 11 << FormShift, - DPRdMisc = 12 << FormShift, - - DPRnIm = 13 << FormShift, - DPRnReg = 14 << FormShift, - DPRnSoReg = 15 << FormShift, - - DPRIm = 16 << FormShift, - DPRReg = 17 << FormShift, - DPRSoReg = 18 << FormShift, - - DPRImS = 19 << FormShift, - DPRRegS = 20 << FormShift, - DPRSoRegS = 21 << FormShift, + DPFrm = 10 << FormShift, + DPSoRegFrm = 11 << FormShift, // Load and Store - LdFrm = 22 << FormShift, - StFrm = 23 << FormShift, + LdFrm = 12 << FormShift, + StFrm = 13 << FormShift, + LdMiscFrm = 14 << FormShift, + StMiscFrm = 15 << FormShift, + LdMulFrm = 16 << FormShift, + StMulFrm = 17 << FormShift, // Miscellaneous arithmetic instructions - ArithMisc = 24 << FormShift, + ArithMisc = 18 << FormShift, // Thumb format - ThumbFrm = 25 << FormShift, + ThumbFrm = 19 << FormShift, // VFP format - VPFFrm = 26 << FormShift, + VPFFrm = 20 << FormShift, + //===------------------------------------------------------------------===// // Field shifts - such shifts are used to set field while generating // machine instructions. RotImmShift = 8, diff --git a/lib/Target/ARM/ARMInstrInfo.td b/lib/Target/ARM/ARMInstrInfo.td index d2ea2b1088a..07119a2edb9 100644 --- a/lib/Target/ARM/ARMInstrInfo.td +++ b/lib/Target/ARM/ARMInstrInfo.td @@ -310,11 +310,10 @@ def AddrMode2 : AddrMode<2>; def AddrMode3 : AddrMode<3>; def AddrMode4 : AddrMode<4>; def AddrMode5 : AddrMode<5>; -def AddrMode6 : AddrMode<6>; -def AddrModeT1 : AddrMode<7>; -def AddrModeT2 : AddrMode<8>; -def AddrModeT4 : AddrMode<9>; -def AddrModeTs : AddrMode<10>; +def AddrModeT1 : AddrMode<6>; +def AddrModeT2 : AddrMode<7>; +def AddrModeT4 : AddrMode<8>; +def AddrModeTs : AddrMode<9>; // Instruction size. class SizeFlagVal val> { @@ -345,13 +344,13 @@ include "ARMInstrFormats.td" /// AsI1_bin_irs - Defines a set of (op r, {so_imm|r|so_reg}) patterns for a /// binop that produces a value. multiclass AsI1_bin_irs opcod, string opc, PatFrag opnode> { - def ri : AsI1; - def rr : AsI1; - def rs : AsI1; } @@ -360,13 +359,13 @@ multiclass AsI1_bin_irs opcod, string opc, PatFrag opnode> { /// instruction modifies the CSPR register. let Defs = [CPSR] in { multiclass ASI1_bin_s_irs opcod, string opc, PatFrag opnode> { - def ri : AI1; - def rr : AI1; - def rs : AI1; } @@ -377,13 +376,13 @@ multiclass ASI1_bin_s_irs opcod, string opc, PatFrag opnode> { /// a explicit result, only implicitly set CPSR. let Defs = [CPSR] in { multiclass AI1_cmp_irs opcod, string opc, PatFrag opnode> { - def ri : AI1; - def rr : AI1; - def rs : AI1; } @@ -420,13 +419,13 @@ multiclass AI_bin_rrot opcod, string opc, PatFrag opnode> { let Uses = [CPSR] in { multiclass AsXI1_bin_c_irs opcod, string opc, PatFrag opnode> { def ri : AXI1; def rr : AXI1; def rs : AXI1; } } @@ -533,7 +532,7 @@ let isReturn = 1, isTerminator = 1 in let isReturn = 1, isTerminator = 1 in def LDM_RET : AXI4ldpc<0x0, (outs), (ins addrmode4:$addr, pred:$p, reglist:$dst1, variable_ops), - LdFrm, "ldm${p}${addr:submode} $addr, $dst1", + LdMulFrm, "ldm${p}${addr:submode} $addr, $dst1", []>; let isCall = 1, @@ -610,7 +609,7 @@ def LDRcp : AI2ldw<0x0, (outs GPR:$dst), (ins addrmode2:$addr), LdFrm, "ldr", " $dst, $addr", []>; // Loads with zero extension -def LDRH : AI3ldh<0xB, (outs GPR:$dst), (ins addrmode3:$addr), LdFrm, +def LDRH : AI3ldh<0xB, (outs GPR:$dst), (ins addrmode3:$addr), LdMiscFrm, "ldr", "h $dst, $addr", [(set GPR:$dst, (zextloadi16 addrmode3:$addr))]>; @@ -619,17 +618,17 @@ def LDRB : AI2ldb<0x1, (outs GPR:$dst), (ins addrmode2:$addr), LdFrm, [(set GPR:$dst, (zextloadi8 addrmode2:$addr))]>; // Loads with sign extension -def LDRSH : AI3ldsh<0xE, (outs GPR:$dst), (ins addrmode3:$addr), LdFrm, +def LDRSH : AI3ldsh<0xE, (outs GPR:$dst), (ins addrmode3:$addr), LdMiscFrm, "ldr", "sh $dst, $addr", [(set GPR:$dst, (sextloadi16 addrmode3:$addr))]>; -def LDRSB : AI3ldsb<0xD, (outs GPR:$dst), (ins addrmode3:$addr), LdFrm, +def LDRSB : AI3ldsb<0xD, (outs GPR:$dst), (ins addrmode3:$addr), LdMiscFrm, "ldr", "sb $dst, $addr", [(set GPR:$dst, (sextloadi8 addrmode3:$addr))]>; let mayLoad = 1 in { // Load doubleword -def LDRD : AI3ldd<0xD, (outs GPR:$dst), (ins addrmode3:$addr), LdFrm, +def LDRD : AI3ldd<0xD, (outs GPR:$dst), (ins addrmode3:$addr), LdMiscFrm, "ldr", "d $dst, $addr", []>, Requires<[IsARM, HasV5T]>; @@ -643,11 +642,11 @@ def LDR_POST : AI2ldwpo<0x0, (outs GPR:$dst, GPR:$base_wb), "ldr", " $dst, [$base], $offset", "$base = $base_wb", []>; def LDRH_PRE : AI3ldhpr<0xB, (outs GPR:$dst, GPR:$base_wb), - (ins addrmode3:$addr), LdFrm, + (ins addrmode3:$addr), LdMiscFrm, "ldr", "h $dst, $addr!", "$addr.base = $base_wb", []>; def LDRH_POST : AI3ldhpo<0xB, (outs GPR:$dst, GPR:$base_wb), - (ins GPR:$base,am3offset:$offset), LdFrm, + (ins GPR:$base,am3offset:$offset), LdMiscFrm, "ldr", "h $dst, [$base], $offset", "$base = $base_wb", []>; def LDRB_PRE : AI2ldbpr<0x1, (outs GPR:$dst, GPR:$base_wb), @@ -659,19 +658,19 @@ def LDRB_POST : AI2ldbpo<0x1, (outs GPR:$dst, GPR:$base_wb), "ldr", "b $dst, [$base], $offset", "$base = $base_wb", []>; def LDRSH_PRE : AI3ldshpr<0xE, (outs GPR:$dst, GPR:$base_wb), - (ins addrmode3:$addr), LdFrm, + (ins addrmode3:$addr), LdMiscFrm, "ldr", "sh $dst, $addr!", "$addr.base = $base_wb", []>; def LDRSH_POST: AI3ldshpo<0xE, (outs GPR:$dst, GPR:$base_wb), - (ins GPR:$base,am3offset:$offset), LdFrm, + (ins GPR:$base,am3offset:$offset), LdMiscFrm, "ldr", "sh $dst, [$base], $offset", "$base = $base_wb", []>; def LDRSB_PRE : AI3ldsbpr<0xD, (outs GPR:$dst, GPR:$base_wb), - (ins addrmode3:$addr), LdFrm, + (ins addrmode3:$addr), LdMiscFrm, "ldr", "sb $dst, $addr!", "$addr.base = $base_wb", []>; def LDRSB_POST: AI3ldsbpo<0xD, (outs GPR:$dst, GPR:$base_wb), - (ins GPR:$base,am3offset:$offset), LdFrm, + (ins GPR:$base,am3offset:$offset), LdMiscFrm, "ldr", "sb $dst, [$base], $offset", "$base = $base_wb", []>; } @@ -681,7 +680,7 @@ def STR : AI2stw<0x0, (outs), (ins GPR:$src, addrmode2:$addr), StFrm, [(store GPR:$src, addrmode2:$addr)]>; // Stores with truncate -def STRH : AI3sth<0xB, (outs), (ins GPR:$src, addrmode3:$addr), StFrm, +def STRH : AI3sth<0xB, (outs), (ins GPR:$src, addrmode3:$addr), StMiscFrm, "str", "h $src, $addr", [(truncstorei16 GPR:$src, addrmode3:$addr)]>; @@ -691,7 +690,7 @@ def STRB : AI2stb<0x1, (outs), (ins GPR:$src, addrmode2:$addr), StFrm, // Store doubleword let mayStore = 1 in -def STRD : AI3std<0xF, (outs), (ins GPR:$src, addrmode3:$addr), StFrm, +def STRD : AI3std<0xF, (outs), (ins GPR:$src, addrmode3:$addr), StMiscFrm, "str", "d $src, $addr", []>, Requires<[IsARM, HasV5T]>; @@ -709,13 +708,13 @@ def STR_POST : AI2stwpo<0x0, (outs GPR:$base_wb), (post_store GPR:$src, GPR:$base, am2offset:$offset))]>; def STRH_PRE : AI3sthpr<0xB, (outs GPR:$base_wb), - (ins GPR:$src, GPR:$base,am3offset:$offset), StFrm, + (ins GPR:$src, GPR:$base,am3offset:$offset), StMiscFrm, "str", "h $src, [$base, $offset]!", "$base = $base_wb", [(set GPR:$base_wb, (pre_truncsti16 GPR:$src, GPR:$base,am3offset:$offset))]>; def STRH_POST: AI3sthpo<0xB, (outs GPR:$base_wb), - (ins GPR:$src, GPR:$base,am3offset:$offset), StFrm, + (ins GPR:$src, GPR:$base,am3offset:$offset), StMiscFrm, "str", "h $src, [$base], $offset", "$base = $base_wb", [(set GPR:$base_wb, (post_truncsti16 GPR:$src, GPR:$base, am3offset:$offset))]>; @@ -740,42 +739,42 @@ def STRB_POST: AI2stbpo<0x1, (outs GPR:$base_wb), let mayLoad = 1 in def LDM : AXI4ld<0x0, (outs), (ins addrmode4:$addr, pred:$p, reglist:$dst1, variable_ops), - LdFrm, "ldm${p}${addr:submode} $addr, $dst1", + LdMulFrm, "ldm${p}${addr:submode} $addr, $dst1", []>; let mayStore = 1 in def STM : AXI4st<0x0, (outs), (ins addrmode4:$addr, pred:$p, reglist:$src1, variable_ops), - StFrm, "stm${p}${addr:submode} $addr, $src1", + StMulFrm, "stm${p}${addr:submode} $addr, $src1", []>; //===----------------------------------------------------------------------===// // Move Instructions. // -def MOVr : AsI1<0b1101, (outs GPR:$dst), (ins GPR:$src), DPRdReg, - "mov", " $dst, $src", []>; -def MOVs : AsI1<0b1101, (outs GPR:$dst), (ins so_reg:$src), DPRdSoReg, - "mov", " $dst, $src", [(set GPR:$dst, so_reg:$src)]>; +def MOVr : AsI1<0b1101, (outs GPR:$dst), (ins GPR:$src), DPFrm, + "mov", " $dst, $src", []>, UnaryDP; +def MOVs : AsI1<0b1101, (outs GPR:$dst), (ins so_reg:$src), DPSoRegFrm, + "mov", " $dst, $src", [(set GPR:$dst, so_reg:$src)]>, UnaryDP; let isReMaterializable = 1 in -def MOVi : AsI1<0b1101, (outs GPR:$dst), (ins so_imm:$src), DPRdIm, - "mov", " $dst, $src", [(set GPR:$dst, so_imm:$src)]>; +def MOVi : AsI1<0b1101, (outs GPR:$dst), (ins so_imm:$src), DPFrm, + "mov", " $dst, $src", [(set GPR:$dst, so_imm:$src)]>, UnaryDP; -def MOVrx : AsI1<0b1101, (outs GPR:$dst), (ins GPR:$src), DPRdMisc, +def MOVrx : AsI1<0b1101, (outs GPR:$dst), (ins GPR:$src), DPFrm, "mov", " $dst, $src, rrx", - [(set GPR:$dst, (ARMrrx GPR:$src))]>; + [(set GPR:$dst, (ARMrrx GPR:$src))]>, UnaryDP; // These aren't really mov instructions, but we have to define them this way // due to flag operands. let Defs = [CPSR] in { -def MOVsrl_flag : AI1<0b1101, (outs GPR:$dst), (ins GPR:$src), DPRdMisc, +def MOVsrl_flag : AI1<0b1101, (outs GPR:$dst), (ins GPR:$src), DPFrm, "mov", "s $dst, $src, lsr #1", - [(set GPR:$dst, (ARMsrl_flag GPR:$src))]>; -def MOVsra_flag : AI1<0b1101, (outs GPR:$dst), (ins GPR:$src), DPRdMisc, + [(set GPR:$dst, (ARMsrl_flag GPR:$src))]>, UnaryDP; +def MOVsra_flag : AI1<0b1101, (outs GPR:$dst), (ins GPR:$src), DPFrm, "mov", "s $dst, $src, asr #1", - [(set GPR:$dst, (ARMsra_flag GPR:$src))]>; + [(set GPR:$dst, (ARMsra_flag GPR:$src))]>, UnaryDP; } //===----------------------------------------------------------------------===// @@ -839,20 +838,20 @@ defm SBC : AsXI1_bin_c_irs<0b0110, "sbc", BinOpFrag<(sube node:$LHS, node:$RHS)>>; // These don't define reg/reg forms, because they are handled above. -def RSBri : AsI1<0b0011, (outs GPR:$dst), (ins GPR:$a, so_imm:$b), DPRIm, +def RSBri : AsI1<0b0011, (outs GPR:$dst), (ins GPR:$a, so_imm:$b), DPFrm, "rsb", " $dst, $a, $b", [(set GPR:$dst, (sub so_imm:$b, GPR:$a))]>; -def RSBrs : AsI1<0b0011, (outs GPR:$dst), (ins GPR:$a, so_reg:$b), DPRSoReg, +def RSBrs : AsI1<0b0011, (outs GPR:$dst), (ins GPR:$a, so_reg:$b), DPSoRegFrm, "rsb", " $dst, $a, $b", [(set GPR:$dst, (sub so_reg:$b, GPR:$a))]>; // RSB with 's' bit set. let Defs = [CPSR] in { -def RSBSri : AI1<0b0011, (outs GPR:$dst), (ins GPR:$a, so_imm:$b), DPRIm, +def RSBSri : AI1<0b0011, (outs GPR:$dst), (ins GPR:$a, so_imm:$b), DPFrm, "rsb", "s $dst, $a, $b", [(set GPR:$dst, (subc so_imm:$b, GPR:$a))]>; -def RSBSrs : AI1<0b0011, (outs GPR:$dst), (ins GPR:$a, so_reg:$b), DPRSoReg, +def RSBSrs : AI1<0b0011, (outs GPR:$dst), (ins GPR:$a, so_reg:$b), DPSoRegFrm, "rsb", "s $dst, $a, $b", [(set GPR:$dst, (subc so_reg:$b, GPR:$a))]>; } @@ -860,10 +859,10 @@ def RSBSrs : AI1<0b0011, (outs GPR:$dst), (ins GPR:$a, so_reg:$b), DPRSoReg, // FIXME: Do not allow RSC to be predicated for now. But they can set CPSR. let Uses = [CPSR] in { def RSCri : AXI1<0b0111, (outs GPR:$dst), (ins GPR:$a, so_imm:$b, cc_out:$s), - DPRIm, "rsc${s} $dst, $a, $b", + DPFrm, "rsc${s} $dst, $a, $b", [(set GPR:$dst, (sube so_imm:$b, GPR:$a))]>; def RSCrs : AXI1<0b0111, (outs GPR:$dst), (ins GPR:$a, so_reg:$b, cc_out:$s), - DPRSoReg, "rsc${s} $dst, $a, $b", + DPSoRegFrm, "rsc${s} $dst, $a, $b", [(set GPR:$dst, (sube so_reg:$b, GPR:$a))]>; } @@ -896,13 +895,16 @@ defm EOR : AsI1_bin_irs<0b0001, "eor", defm BIC : AsI1_bin_irs<0b1110, "bic", BinOpFrag<(and node:$LHS, (not node:$RHS))>>; -def MVNr : AsI1<0b1111, (outs GPR:$dst), (ins GPR:$src), DPRdReg, - "mvn", " $dst, $src", [(set GPR:$dst, (not GPR:$src))]>; -def MVNs : AsI1<0b1111, (outs GPR:$dst), (ins so_reg:$src), DPRdSoReg, - "mvn", " $dst, $src", [(set GPR:$dst, (not so_reg:$src))]>; +def MVNr : AsI1<0b1111, (outs GPR:$dst), (ins GPR:$src), DPFrm, + "mvn", " $dst, $src", + [(set GPR:$dst, (not GPR:$src))]>, UnaryDP; +def MVNs : AsI1<0b1111, (outs GPR:$dst), (ins so_reg:$src), DPSoRegFrm, + "mvn", " $dst, $src", + [(set GPR:$dst, (not so_reg:$src))]>, UnaryDP; let isReMaterializable = 1 in -def MVNi : AsI1<0b1111, (outs GPR:$dst), (ins so_imm:$imm), DPRdIm, - "mvn", " $dst, $imm", [(set GPR:$dst, so_imm_not:$imm)]>; +def MVNi : AsI1<0b1111, (outs GPR:$dst), (ins so_imm:$imm), DPFrm, + "mvn", " $dst, $imm", + [(set GPR:$dst, so_imm_not:$imm)]>,UnaryDP; def : ARMPat<(and GPR:$src, so_imm_not:$imm), (BICri GPR:$src, so_imm_not:$imm)>; @@ -911,48 +913,48 @@ def : ARMPat<(and GPR:$src, so_imm_not:$imm), // Multiply Instructions. // -def MUL : AsI6<0b0000, (outs GPR:$dst), (ins GPR:$a, GPR:$b), MulFrm, +def MUL : AsMul1I<0b0000, (outs GPR:$dst), (ins GPR:$a, GPR:$b), "mul", " $dst, $a, $b", [(set GPR:$dst, (mul GPR:$a, GPR:$b))]>; -def MLA : AsI6<0b0010, (outs GPR:$dst), (ins GPR:$a, GPR:$b, GPR:$c), - MulFrm, "mla", " $dst, $a, $b, $c", +def MLA : AsMul1I<0b0010, (outs GPR:$dst), (ins GPR:$a, GPR:$b, GPR:$c), + "mla", " $dst, $a, $b, $c", [(set GPR:$dst, (add (mul GPR:$a, GPR:$b), GPR:$c))]>; // Extra precision multiplies with low / high results -def SMULL : AsI6<0b1100, (outs GPR:$ldst, GPR:$hdst), (ins GPR:$a, GPR:$b), - MulFrm, "smull", " $ldst, $hdst, $a, $b", []>; +def SMULL : AsMul1I<0b1100, (outs GPR:$ldst, GPR:$hdst), (ins GPR:$a, GPR:$b), + "smull", " $ldst, $hdst, $a, $b", []>; -def UMULL : AsI6<0b1000, (outs GPR:$ldst, GPR:$hdst), (ins GPR:$a, GPR:$b), - MulFrm, "umull", " $ldst, $hdst, $a, $b", []>; +def UMULL : AsMul1I<0b1000, (outs GPR:$ldst, GPR:$hdst), (ins GPR:$a, GPR:$b), + "umull", " $ldst, $hdst, $a, $b", []>; // Multiply + accumulate -def SMLAL : AsI6<0b1110, (outs GPR:$ldst, GPR:$hdst), (ins GPR:$a, GPR:$b), - MulFrm, "smlal", " $ldst, $hdst, $a, $b", []>; +def SMLAL : AsMul1I<0b1110, (outs GPR:$ldst, GPR:$hdst), (ins GPR:$a, GPR:$b), + "smlal", " $ldst, $hdst, $a, $b", []>; -def UMLAL : AsI6<0b1010, (outs GPR:$ldst, GPR:$hdst), (ins GPR:$a, GPR:$b), - MulFrm, "umlal", " $ldst, $hdst, $a, $b", []>; +def UMLAL : AsMul1I<0b1010, (outs GPR:$ldst, GPR:$hdst), (ins GPR:$a, GPR:$b), + "umlal", " $ldst, $hdst, $a, $b", []>; -def UMAAL : AI6 <0b0000, (outs GPR:$ldst, GPR:$hdst), (ins GPR:$a, GPR:$b), - MulFrm, "umaal", " $ldst, $hdst, $a, $b", []>, - Requires<[IsARM, HasV6]>; +def UMAAL : AMul1I<0b0000, (outs GPR:$ldst, GPR:$hdst), (ins GPR:$a, GPR:$b), + "umaal", " $ldst, $hdst, $a, $b", []>, + Requires<[IsARM, HasV6]>; // Most significant word multiply // FIXME: encoding -def SMMUL : AI<0x0, (outs GPR:$dst), (ins GPR:$a, GPR:$b), MulFrm, +def SMMUL : AI<0x0, (outs GPR:$dst), (ins GPR:$a, GPR:$b), MulFrm2, "smmul", " $dst, $a, $b", [(set GPR:$dst, (mulhs GPR:$a, GPR:$b))]>, Requires<[IsARM, HasV6]>; // FIXME: encoding -def SMMLA : AI<0x0, (outs GPR:$dst), (ins GPR:$a, GPR:$b, GPR:$c), MulFrm, +def SMMLA : AI<0x0, (outs GPR:$dst), (ins GPR:$a, GPR:$b, GPR:$c), MulFrm2, "smmla", " $dst, $a, $b, $c", [(set GPR:$dst, (add (mulhs GPR:$a, GPR:$b), GPR:$c))]>, Requires<[IsARM, HasV6]>; // FIXME: encoding -def SMMLS : AI<0x0, (outs GPR:$dst), (ins GPR:$a, GPR:$b, GPR:$c), MulFrm, +def SMMLS : AI<0x0, (outs GPR:$dst), (ins GPR:$a, GPR:$b, GPR:$c), MulFrm2, "smmls", " $dst, $a, $b, $c", [(set GPR:$dst, (sub GPR:$c, (mulhs GPR:$a, GPR:$b)))]>, Requires<[IsARM, HasV6]>; @@ -1133,20 +1135,20 @@ def : ARMPat<(ARMcmpNZ GPR:$src, so_imm_neg:$imm), // Conditional moves // FIXME: should be able to write a pattern for ARMcmov, but can't use // a two-value operand where a dag node expects two operands. :( -def MOVCCr : AI<0xD, (outs GPR:$dst), (ins GPR:$false, GPR:$true), - DPRdReg, "mov", " $dst, $true", +def MOVCCr : AI<0xD, (outs GPR:$dst), (ins GPR:$false, GPR:$true), DPFrm, + "mov", " $dst, $true", [/*(set GPR:$dst, (ARMcmov GPR:$false, GPR:$true, imm:$cc, CCR:$ccr))*/]>, RegConstraint<"$false = $dst">; -def MOVCCs : AI<0xD, (outs GPR:$dst), (ins GPR:$false, so_reg:$true), - DPRdSoReg, "mov", " $dst, $true", +def MOVCCs : AI<0xD, (outs GPR:$dst), (ins GPR:$false, so_reg:$true), DPSoRegFrm, + "mov", " $dst, $true", [/*(set GPR:$dst, (ARMcmov GPR:$false, so_reg:$true, imm:$cc, CCR:$ccr))*/]>, - RegConstraint<"$false = $dst">; + RegConstraint<"$false = $dst">, UnaryDP; -def MOVCCi : AI<0xD, (outs GPR:$dst), (ins GPR:$false, so_imm:$true), - DPRdIm, "mov", " $dst, $true", +def MOVCCi : AI<0xD, (outs GPR:$dst), (ins GPR:$false, so_imm:$true), DPFrm, + "mov", " $dst, $true", [/*(set GPR:$dst, (ARMcmov GPR:$false, so_imm:$true, imm:$cc, CCR:$ccr))*/]>, - RegConstraint<"$false = $dst">; + RegConstraint<"$false = $dst">, UnaryDP; // LEApcrel - Load a pc-relative address into a register without offending the @@ -1192,9 +1194,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), DPRdMisc, +def MOVi2pieces : AI1x2<0x0, (outs GPR:$dst), (ins so_imm2part:$src), DPFrm, "mov", " $dst, $src", - [(set GPR:$dst, so_imm2part:$src)]>; + [(set GPR:$dst, so_imm2part:$src)]>, UnaryDP; def : ARMPat<(or GPR:$LHS, so_imm2part:$RHS), (ORRri (ORRri GPR:$LHS, (so_imm2part_1 imm:$RHS)), -- 2.34.1