aboutsummaryrefslogtreecommitdiffstats
path: root/lib/Target/ARM
diff options
context:
space:
mode:
Diffstat (limited to 'lib/Target/ARM')
-rw-r--r--lib/Target/ARM/ARM.h17
-rw-r--r--lib/Target/ARM/ARM.td156
-rw-r--r--lib/Target/ARM/ARMAsmPrinter.cpp161
-rw-r--r--lib/Target/ARM/ARMAsmPrinter.h12
-rw-r--r--lib/Target/ARM/ARMBaseInfo.h12
-rw-r--r--lib/Target/ARM/ARMBaseInstrInfo.cpp63
-rw-r--r--lib/Target/ARM/ARMBaseInstrInfo.h26
-rw-r--r--lib/Target/ARM/ARMBaseRegisterInfo.cpp1
-rw-r--r--lib/Target/ARM/ARMConstantIslandPass.cpp5
-rw-r--r--lib/Target/ARM/ARMExpandPseudoInsts.cpp15
-rw-r--r--lib/Target/ARM/ARMFrameLowering.cpp46
-rw-r--r--lib/Target/ARM/ARMGlobalMerge.cpp10
-rw-r--r--lib/Target/ARM/ARMISelLowering.cpp76
-rw-r--r--lib/Target/ARM/ARMISelLowering.h1
-rw-r--r--lib/Target/ARM/ARMInstrFormats.td241
-rw-r--r--lib/Target/ARM/ARMInstrInfo.td549
-rw-r--r--lib/Target/ARM/ARMInstrNEON.td30
-rw-r--r--lib/Target/ARM/ARMInstrThumb.td212
-rw-r--r--lib/Target/ARM/ARMInstrThumb2.td164
-rw-r--r--lib/Target/ARM/ARMInstrVFP.td6
-rw-r--r--lib/Target/ARM/ARMMCCodeEmitter.cpp75
-rw-r--r--lib/Target/ARM/ARMMCInstLower.cpp118
-rw-r--r--lib/Target/ARM/ARMSubtarget.cpp110
-rw-r--r--lib/Target/ARM/ARMSubtarget.h74
-rw-r--r--lib/Target/ARM/ARMTargetMachine.cpp25
-rw-r--r--lib/Target/ARM/ARMTargetMachine.h3
-rw-r--r--lib/Target/ARM/AsmParser/ARMAsmParser.cpp312
-rw-r--r--lib/Target/ARM/CMakeLists.txt3
-rw-r--r--lib/Target/ARM/Disassembler/ARMDisassemblerCore.cpp14
-rw-r--r--lib/Target/ARM/InstPrinter/ARMInstPrinter.cpp34
-rw-r--r--lib/Target/ARM/InstPrinter/ARMInstPrinter.h5
-rw-r--r--lib/Target/ARM/MCTargetDesc/ARMMCAsmInfo.cpp (renamed from lib/Target/ARM/ARMMCAsmInfo.cpp)0
-rw-r--r--lib/Target/ARM/MCTargetDesc/ARMMCAsmInfo.h (renamed from lib/Target/ARM/ARMMCAsmInfo.h)0
-rw-r--r--lib/Target/ARM/MCTargetDesc/ARMMCTargetDesc.cpp144
-rw-r--r--lib/Target/ARM/MCTargetDesc/ARMMCTargetDesc.h52
-rw-r--r--lib/Target/ARM/MCTargetDesc/CMakeLists.txt7
-rw-r--r--lib/Target/ARM/MCTargetDesc/Makefile16
-rw-r--r--lib/Target/ARM/Makefile5
-rw-r--r--lib/Target/ARM/NEONMoveFix.cpp5
-rw-r--r--lib/Target/ARM/README.txt18
-rw-r--r--lib/Target/ARM/Thumb1FrameLowering.cpp4
41 files changed, 1580 insertions, 1247 deletions
diff --git a/lib/Target/ARM/ARM.h b/lib/Target/ARM/ARM.h
index 8f77b04..08dc340 100644
--- a/lib/Target/ARM/ARM.h
+++ b/lib/Target/ARM/ARM.h
@@ -16,6 +16,7 @@
#define TARGET_ARM_H
#include "ARMBaseInfo.h"
+#include "MCTargetDesc/ARMMCTargetDesc.h"
#include "llvm/Support/DataTypes.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Target/TargetMachine.h"
@@ -23,19 +24,21 @@
namespace llvm {
+class ARMAsmPrinter;
class ARMBaseTargetMachine;
class FunctionPass;
class JITCodeEmitter;
-class formatted_raw_ostream;
+class MachineInstr;
class MCCodeEmitter;
+class MCInst;
+class MCInstrInfo;
class MCObjectWriter;
+class MCSubtargetInfo;
class TargetAsmBackend;
-class MachineInstr;
-class ARMAsmPrinter;
-class MCInst;
+class formatted_raw_ostream;
-MCCodeEmitter *createARMMCCodeEmitter(const Target &,
- TargetMachine &TM,
+MCCodeEmitter *createARMMCCodeEmitter(const MCInstrInfo &MCII,
+ const MCSubtargetInfo &STI,
MCContext &Ctx);
TargetAsmBackend *createARMAsmBackend(const Target &, const std::string &);
@@ -55,8 +58,6 @@ FunctionPass *createMLxExpansionPass();
FunctionPass *createThumb2ITBlockPass();
FunctionPass *createThumb2SizeReductionPass();
-extern Target TheARMTarget, TheThumbTarget;
-
void LowerARMMachineInstrToMCInst(const MachineInstr *MI, MCInst &OutMI,
ARMAsmPrinter &AP);
diff --git a/lib/Target/ARM/ARM.td b/lib/Target/ARM/ARM.td
index 39a3528..cf333cc 100644
--- a/lib/Target/ARM/ARM.td
+++ b/lib/Target/ARM/ARM.td
@@ -16,18 +16,26 @@
include "llvm/Target/Target.td"
+//===----------------------------------------------------------------------===//
+// ARM Subtarget state.
+//
+
+def ModeThumb : SubtargetFeature<"thumb-mode", "InThumbMode", "true",
+ "Thumb mode">;
//===----------------------------------------------------------------------===//
// ARM Subtarget features.
//
-def FeatureVFP2 : SubtargetFeature<"vfp2", "ARMFPUType", "VFPv2",
+def FeatureVFP2 : SubtargetFeature<"vfp2", "HasVFPv2", "true",
"Enable VFP2 instructions">;
-def FeatureVFP3 : SubtargetFeature<"vfp3", "ARMFPUType", "VFPv3",
- "Enable VFP3 instructions">;
-def FeatureNEON : SubtargetFeature<"neon", "ARMFPUType", "NEON",
- "Enable NEON instructions">;
-def FeatureThumb2 : SubtargetFeature<"thumb2", "ThumbMode", "Thumb2",
+def FeatureVFP3 : SubtargetFeature<"vfp3", "HasVFPv3", "true",
+ "Enable VFP3 instructions",
+ [FeatureVFP2]>;
+def FeatureNEON : SubtargetFeature<"neon", "HasNEON", "true",
+ "Enable NEON instructions",
+ [FeatureVFP3]>;
+def FeatureThumb2 : SubtargetFeature<"thumb2", "HasThumb2", "true",
"Enable Thumb2 instructions">;
def FeatureNoARM : SubtargetFeature<"noarm", "NoARM", "true",
"Does not support ARM mode execution">;
@@ -83,34 +91,24 @@ def FeatureDSPThumb2 : SubtargetFeature<"t2dsp", "Thumb2DSP", "true",
def FeatureMP : SubtargetFeature<"mp", "HasMPExtension", "true",
"Supports Multiprocessing extension">;
-// ARM architectures.
-def ArchV4T : SubtargetFeature<"v4t", "ARMArchVersion", "V4T",
- "ARM v4T">;
-def ArchV5T : SubtargetFeature<"v5t", "ARMArchVersion", "V5T",
- "ARM v5T">;
-def ArchV5TE : SubtargetFeature<"v5te", "ARMArchVersion", "V5TE",
- "ARM v5TE, v5TEj, v5TExp">;
-def ArchV6 : SubtargetFeature<"v6", "ARMArchVersion", "V6",
- "ARM v6">;
-def ArchV6M : SubtargetFeature<"v6m", "ARMArchVersion", "V6M",
- "ARM v6m",
- [FeatureNoARM, FeatureDB]>;
-def ArchV6T2 : SubtargetFeature<"v6t2", "ARMArchVersion", "V6T2",
- "ARM v6t2",
- [FeatureThumb2, FeatureDSPThumb2]>;
-def ArchV7A : SubtargetFeature<"v7a", "ARMArchVersion", "V7A",
- "ARM v7A",
- [FeatureThumb2, FeatureNEON, FeatureDB,
- FeatureDSPThumb2]>;
-def ArchV7M : SubtargetFeature<"v7m", "ARMArchVersion", "V7M",
- "ARM v7M",
- [FeatureThumb2, FeatureNoARM, FeatureDB,
- FeatureHWDiv]>;
-def ArchV7EM : SubtargetFeature<"v7em", "ARMArchVersion", "V7EM",
- "ARM v7E-M",
- [FeatureThumb2, FeatureNoARM, FeatureDB,
- FeatureHWDiv, FeatureDSPThumb2,
- FeatureT2XtPk]>;
+// ARM ISAs.
+def HasV4TOps : SubtargetFeature<"v4t", "HasV4TOps", "true",
+ "Support ARM v4T instructions">;
+def HasV5TOps : SubtargetFeature<"v5t", "HasV5TOps", "true",
+ "Support ARM v5T instructions",
+ [HasV4TOps]>;
+def HasV5TEOps : SubtargetFeature<"v5te", "HasV5TEOps", "true",
+ "Support ARM v5TE, v5TEj, and v5TExp instructions",
+ [HasV5TOps]>;
+def HasV6Ops : SubtargetFeature<"v6", "HasV6Ops", "true",
+ "Support ARM v6 instructions",
+ [HasV5TEOps]>;
+def HasV6T2Ops : SubtargetFeature<"v6t2", "HasV6T2Ops", "true",
+ "Support ARM v6t2 instructions",
+ [HasV6Ops, FeatureThumb2, FeatureDSPThumb2]>;
+def HasV7Ops : SubtargetFeature<"v7", "HasV7Ops", "true",
+ "Support ARM v7 instructions",
+ [HasV6T2Ops]>;
//===----------------------------------------------------------------------===//
// ARM Processors supported.
@@ -119,8 +117,6 @@ def ArchV7EM : SubtargetFeature<"v7em", "ARMArchVersion", "V7EM",
include "ARMSchedule.td"
// ARM processor families.
-def ProcOthers : SubtargetFeature<"others", "ARMProcFamily", "Others",
- "One of the other ARM processor families">;
def ProcA8 : SubtargetFeature<"a8", "ARMProcFamily", "CortexA8",
"Cortex-A8 ARM processors",
[FeatureSlowFPBrcc, FeatureNEONForFP,
@@ -145,64 +141,76 @@ def : ProcNoItin<"strongarm1100", []>;
def : ProcNoItin<"strongarm1110", []>;
// V4T Processors.
-def : ProcNoItin<"arm7tdmi", [ArchV4T]>;
-def : ProcNoItin<"arm7tdmi-s", [ArchV4T]>;
-def : ProcNoItin<"arm710t", [ArchV4T]>;
-def : ProcNoItin<"arm720t", [ArchV4T]>;
-def : ProcNoItin<"arm9", [ArchV4T]>;
-def : ProcNoItin<"arm9tdmi", [ArchV4T]>;
-def : ProcNoItin<"arm920", [ArchV4T]>;
-def : ProcNoItin<"arm920t", [ArchV4T]>;
-def : ProcNoItin<"arm922t", [ArchV4T]>;
-def : ProcNoItin<"arm940t", [ArchV4T]>;
-def : ProcNoItin<"ep9312", [ArchV4T]>;
+def : ProcNoItin<"arm7tdmi", [HasV4TOps]>;
+def : ProcNoItin<"arm7tdmi-s", [HasV4TOps]>;
+def : ProcNoItin<"arm710t", [HasV4TOps]>;
+def : ProcNoItin<"arm720t", [HasV4TOps]>;
+def : ProcNoItin<"arm9", [HasV4TOps]>;
+def : ProcNoItin<"arm9tdmi", [HasV4TOps]>;
+def : ProcNoItin<"arm920", [HasV4TOps]>;
+def : ProcNoItin<"arm920t", [HasV4TOps]>;
+def : ProcNoItin<"arm922t", [HasV4TOps]>;
+def : ProcNoItin<"arm940t", [HasV4TOps]>;
+def : ProcNoItin<"ep9312", [HasV4TOps]>;
// V5T Processors.
-def : ProcNoItin<"arm10tdmi", [ArchV5T]>;
-def : ProcNoItin<"arm1020t", [ArchV5T]>;
+def : ProcNoItin<"arm10tdmi", [HasV5TOps]>;
+def : ProcNoItin<"arm1020t", [HasV5TOps]>;
// V5TE Processors.
-def : ProcNoItin<"arm9e", [ArchV5TE]>;
-def : ProcNoItin<"arm926ej-s", [ArchV5TE]>;
-def : ProcNoItin<"arm946e-s", [ArchV5TE]>;
-def : ProcNoItin<"arm966e-s", [ArchV5TE]>;
-def : ProcNoItin<"arm968e-s", [ArchV5TE]>;
-def : ProcNoItin<"arm10e", [ArchV5TE]>;
-def : ProcNoItin<"arm1020e", [ArchV5TE]>;
-def : ProcNoItin<"arm1022e", [ArchV5TE]>;
-def : ProcNoItin<"xscale", [ArchV5TE]>;
-def : ProcNoItin<"iwmmxt", [ArchV5TE]>;
+def : ProcNoItin<"arm9e", [HasV5TEOps]>;
+def : ProcNoItin<"arm926ej-s", [HasV5TEOps]>;
+def : ProcNoItin<"arm946e-s", [HasV5TEOps]>;
+def : ProcNoItin<"arm966e-s", [HasV5TEOps]>;
+def : ProcNoItin<"arm968e-s", [HasV5TEOps]>;
+def : ProcNoItin<"arm10e", [HasV5TEOps]>;
+def : ProcNoItin<"arm1020e", [HasV5TEOps]>;
+def : ProcNoItin<"arm1022e", [HasV5TEOps]>;
+def : ProcNoItin<"xscale", [HasV5TEOps]>;
+def : ProcNoItin<"iwmmxt", [HasV5TEOps]>;
// V6 Processors.
-def : Processor<"arm1136j-s", ARMV6Itineraries, [ArchV6]>;
-def : Processor<"arm1136jf-s", ARMV6Itineraries, [ArchV6, FeatureVFP2,
+def : Processor<"arm1136j-s", ARMV6Itineraries, [HasV6Ops]>;
+def : Processor<"arm1136jf-s", ARMV6Itineraries, [HasV6Ops, FeatureVFP2,
FeatureHasSlowFPVMLx]>;
-def : Processor<"arm1176jz-s", ARMV6Itineraries, [ArchV6]>;
-def : Processor<"arm1176jzf-s", ARMV6Itineraries, [ArchV6, FeatureVFP2,
+def : Processor<"arm1176jz-s", ARMV6Itineraries, [HasV6Ops]>;
+def : Processor<"arm1176jzf-s", ARMV6Itineraries, [HasV6Ops, FeatureVFP2,
FeatureHasSlowFPVMLx]>;
-def : Processor<"mpcorenovfp", ARMV6Itineraries, [ArchV6]>;
-def : Processor<"mpcore", ARMV6Itineraries, [ArchV6, FeatureVFP2,
+def : Processor<"mpcorenovfp", ARMV6Itineraries, [HasV6Ops]>;
+def : Processor<"mpcore", ARMV6Itineraries, [HasV6Ops, FeatureVFP2,
FeatureHasSlowFPVMLx]>;
// V6M Processors.
-def : Processor<"cortex-m0", ARMV6Itineraries, [ArchV6M]>;
+def : Processor<"cortex-m0", ARMV6Itineraries, [HasV6Ops, FeatureNoARM,
+ FeatureDB]>;
// V6T2 Processors.
-def : Processor<"arm1156t2-s", ARMV6Itineraries, [ArchV6T2]>;
-def : Processor<"arm1156t2f-s", ARMV6Itineraries, [ArchV6T2, FeatureVFP2,
+def : Processor<"arm1156t2-s", ARMV6Itineraries, [HasV6T2Ops]>;
+def : Processor<"arm1156t2f-s", ARMV6Itineraries, [HasV6T2Ops, FeatureVFP2,
FeatureHasSlowFPVMLx]>;
-// V7 Processors.
+// V7a Processors.
def : Processor<"cortex-a8", CortexA8Itineraries,
- [ArchV7A, ProcA8]>;
+ [ProcA8, HasV7Ops, FeatureNEON, FeatureDB,
+ FeatureDSPThumb2]>;
def : Processor<"cortex-a9", CortexA9Itineraries,
- [ArchV7A, ProcA9]>;
+ [ProcA9, HasV7Ops, FeatureNEON, FeatureDB,
+ FeatureDSPThumb2]>;
def : Processor<"cortex-a9-mp", CortexA9Itineraries,
- [ArchV7A, ProcA9, FeatureMP]>;
+ [ProcA9, HasV7Ops, FeatureNEON, FeatureDB,
+ FeatureDSPThumb2, FeatureMP]>;
// V7M Processors.
-def : ProcNoItin<"cortex-m3", [ArchV7M]>;
-def : ProcNoItin<"cortex-m4", [ArchV7EM, FeatureVFP2, FeatureVFPOnlySP]>;
+def : ProcNoItin<"cortex-m3", [HasV7Ops,
+ FeatureThumb2, FeatureNoARM, FeatureDB,
+ FeatureHWDiv]>;
+
+// V7EM Processors.
+def : ProcNoItin<"cortex-m4", [HasV7Ops,
+ FeatureThumb2, FeatureNoARM, FeatureDB,
+ FeatureHWDiv, FeatureDSPThumb2,
+ FeatureT2XtPk, FeatureVFP2,
+ FeatureVFPOnlySP]>;
//===----------------------------------------------------------------------===//
// Register File Description
diff --git a/lib/Target/ARM/ARMAsmPrinter.cpp b/lib/Target/ARM/ARMAsmPrinter.cpp
index 7240837..dbc3ee4 100644
--- a/lib/Target/ARM/ARMAsmPrinter.cpp
+++ b/lib/Target/ARM/ARMAsmPrinter.cpp
@@ -654,7 +654,7 @@ void ARMAsmPrinter::emitAttributes() {
}
/* TODO: ARMBuildAttrs::Allowed is not completely accurate,
- * since NEON can have 1 (allowed) or 2 (fused MAC operations) */
+ * since NEON can have 1 (allowed) or 2 (MAC operations) */
if (Subtarget->hasNEON()) {
AttrEmitter->EmitAttribute(ARMBuildAttrs::Advanced_SIMD_arch,
ARMBuildAttrs::Allowed);
@@ -1069,48 +1069,18 @@ void ARMAsmPrinter::EmitUnwindingInstruction(const MachineInstr *MI) {
extern cl::opt<bool> EnableARMEHABI;
+// Simple pseudo-instructions have their lowering (with expansion to real
+// instructions) auto-generated.
+#include "ARMGenMCPseudoLowering.inc"
+
void ARMAsmPrinter::EmitInstruction(const MachineInstr *MI) {
- unsigned Opc = MI->getOpcode();
- switch (Opc) {
- default: break;
- case ARM::B: {
- // B is just a Bcc with an 'always' predicate.
- MCInst TmpInst;
- LowerARMMachineInstrToMCInst(MI, TmpInst, *this);
- TmpInst.setOpcode(ARM::Bcc);
- // Add predicate operands.
- TmpInst.addOperand(MCOperand::CreateImm(ARMCC::AL));
- TmpInst.addOperand(MCOperand::CreateReg(0));
- OutStreamer.EmitInstruction(TmpInst);
- return;
- }
- case ARM::LDMIA_RET: {
- // LDMIA_RET is just a normal LDMIA_UPD instruction that targets PC and as
- // such has additional code-gen properties and scheduling information.
- // To emit it, we just construct as normal and set the opcode to LDMIA_UPD.
- MCInst TmpInst;
- LowerARMMachineInstrToMCInst(MI, TmpInst, *this);
- TmpInst.setOpcode(ARM::LDMIA_UPD);
- OutStreamer.EmitInstruction(TmpInst);
- return;
- }
- case ARM::t2LDMIA_RET: {
- // As above for LDMIA_RET. Map to the tPOP instruction.
- MCInst TmpInst;
- LowerARMMachineInstrToMCInst(MI, TmpInst, *this);
- TmpInst.setOpcode(ARM::t2LDMIA_UPD);
- OutStreamer.EmitInstruction(TmpInst);
- return;
- }
- case ARM::tPOP_RET: {
- // As above for LDMIA_RET. Map to the tPOP instruction.
- MCInst TmpInst;
- LowerARMMachineInstrToMCInst(MI, TmpInst, *this);
- TmpInst.setOpcode(ARM::tPOP);
- OutStreamer.EmitInstruction(TmpInst);
+ // Do any auto-generated pseudo lowerings.
+ if (emitPseudoExpansionLowering(OutStreamer, MI))
return;
- }
+ // Check for manual lowerings.
+ unsigned Opc = MI->getOpcode();
+ switch (Opc) {
case ARM::t2MOVi32imm: assert(0 && "Should be lowered by thumb2it pass");
case ARM::DBG_VALUE: {
if (isVerbose() && OutStreamer.hasRawTextSupport()) {
@@ -1121,14 +1091,6 @@ void ARMAsmPrinter::EmitInstruction(const MachineInstr *MI) {
}
return;
}
- case ARM::tBfar: {
- MCInst TmpInst;
- TmpInst.setOpcode(ARM::tBL);
- TmpInst.addOperand(MCOperand::CreateExpr(MCSymbolRefExpr::Create(
- MI->getOperand(0).getMBB()->getSymbol(), OutContext)));
- OutStreamer.EmitInstruction(TmpInst);
- return;
- }
case ARM::LEApcrel:
case ARM::tLEApcrel:
case ARM::t2LEApcrel: {
@@ -1159,39 +1121,8 @@ void ARMAsmPrinter::EmitInstruction(const MachineInstr *MI) {
OutStreamer.EmitInstruction(TmpInst);
return;
}
- case ARM::MOVPCRX: {
- MCInst TmpInst;
- TmpInst.setOpcode(ARM::MOVr);
- TmpInst.addOperand(MCOperand::CreateReg(ARM::PC));
- TmpInst.addOperand(MCOperand::CreateReg(MI->getOperand(0).getReg()));
- // Add predicate operands.
- TmpInst.addOperand(MCOperand::CreateImm(ARMCC::AL));
- TmpInst.addOperand(MCOperand::CreateReg(0));
- // Add 's' bit operand (always reg0 for this)
- TmpInst.addOperand(MCOperand::CreateReg(0));
- OutStreamer.EmitInstruction(TmpInst);
- return;
- }
// Darwin call instructions are just normal call instructions with different
// clobber semantics (they clobber R9).
- case ARM::BLr9:
- case ARM::BLr9_pred:
- case ARM::BLXr9:
- case ARM::BLXr9_pred: {
- unsigned newOpc;
- switch (Opc) {
- default: assert(0);
- case ARM::BLr9: newOpc = ARM::BL; break;
- case ARM::BLr9_pred: newOpc = ARM::BL_pred; break;
- case ARM::BLXr9: newOpc = ARM::BLX; break;
- case ARM::BLXr9_pred: newOpc = ARM::BLX_pred; break;
- }
- MCInst TmpInst;
- LowerARMMachineInstrToMCInst(MI, TmpInst, *this);
- TmpInst.setOpcode(newOpc);
- OutStreamer.EmitInstruction(TmpInst);
- return;
- }
case ARM::BXr9_CALL:
case ARM::BX_CALL: {
{
@@ -1868,75 +1799,6 @@ void ARMAsmPrinter::EmitInstruction(const MachineInstr *MI) {
}
return;
}
- // Tail jump branches are really just branch instructions with additional
- // code-gen attributes. Convert them to the canonical form here.
- case ARM::TAILJMPd:
- case ARM::TAILJMPdND: {
- MCInst TmpInst, TmpInst2;
- // Lower the instruction as-is to get the operands properly converted.
- LowerARMMachineInstrToMCInst(MI, TmpInst2, *this);
- TmpInst.setOpcode(ARM::Bcc);
- TmpInst.addOperand(TmpInst2.getOperand(0));
- // Add predicate operands.
- TmpInst.addOperand(MCOperand::CreateImm(ARMCC::AL));
- TmpInst.addOperand(MCOperand::CreateReg(0));
- OutStreamer.AddComment("TAILCALL");
- OutStreamer.EmitInstruction(TmpInst);
- return;
- }
- case ARM::tTAILJMPd:
- case ARM::tTAILJMPdND: {
- MCInst TmpInst, TmpInst2;
- LowerARMMachineInstrToMCInst(MI, TmpInst2, *this);
- // The Darwin toolchain doesn't support tail call relocations of 16-bit
- // branches.
- TmpInst.setOpcode(Opc == ARM::tTAILJMPd ? ARM::t2B : ARM::tB);
- TmpInst.addOperand(TmpInst2.getOperand(0));
- OutStreamer.AddComment("TAILCALL");
- OutStreamer.EmitInstruction(TmpInst);
- return;
- }
- case ARM::TAILJMPrND:
- case ARM::tTAILJMPrND:
- case ARM::TAILJMPr:
- case ARM::tTAILJMPr: {
- unsigned newOpc = (Opc == ARM::TAILJMPr || Opc == ARM::TAILJMPrND)
- ? ARM::BX : ARM::tBX;
- MCInst TmpInst;
- TmpInst.setOpcode(newOpc);
- TmpInst.addOperand(MCOperand::CreateReg(MI->getOperand(0).getReg()));
- // Predicate.
- TmpInst.addOperand(MCOperand::CreateImm(ARMCC::AL));
- TmpInst.addOperand(MCOperand::CreateReg(0));
- OutStreamer.AddComment("TAILCALL");
- OutStreamer.EmitInstruction(TmpInst);
- return;
- }
-
- // These are the pseudos created to comply with stricter operand restrictions
- // on ARMv5. Lower them now to "normal" instructions, since all the
- // restrictions are already satisfied.
- case ARM::MULv5:
- EmitPatchedInstruction(MI, ARM::MUL);
- return;
- case ARM::MLAv5:
- EmitPatchedInstruction(MI, ARM::MLA);
- return;
- case ARM::SMULLv5:
- EmitPatchedInstruction(MI, ARM::SMULL);
- return;
- case ARM::UMULLv5:
- EmitPatchedInstruction(MI, ARM::UMULL);
- return;
- case ARM::SMLALv5:
- EmitPatchedInstruction(MI, ARM::SMLAL);
- return;
- case ARM::UMLALv5:
- EmitPatchedInstruction(MI, ARM::UMLAL);
- return;
- case ARM::UMAALv5:
- EmitPatchedInstruction(MI, ARM::UMAAL);
- return;
}
MCInst TmpInst;
@@ -1954,11 +1816,10 @@ void ARMAsmPrinter::EmitInstruction(const MachineInstr *MI) {
//===----------------------------------------------------------------------===//
static MCInstPrinter *createARMMCInstPrinter(const Target &T,
- TargetMachine &TM,
unsigned SyntaxVariant,
const MCAsmInfo &MAI) {
if (SyntaxVariant == 0)
- return new ARMInstPrinter(TM, MAI);
+ return new ARMInstPrinter(MAI);
return 0;
}
diff --git a/lib/Target/ARM/ARMAsmPrinter.h b/lib/Target/ARM/ARMAsmPrinter.h
index 5f9169e..7741fc4 100644
--- a/lib/Target/ARM/ARMAsmPrinter.h
+++ b/lib/Target/ARM/ARMAsmPrinter.h
@@ -21,6 +21,8 @@
namespace llvm {
+class MCOperand;
+
namespace ARM {
enum DW_ISA {
DW_ISA_ARM_thumb = 1,
@@ -72,6 +74,9 @@ public:
void EmitStartOfAsmFile(Module &M);
void EmitEndOfAsmFile(Module &M);
+ // lowerOperand - Convert a MachineOperand into the equivalent MCOperand.
+ bool lowerOperand(const MachineOperand &MO, MCOperand &MCOp);
+
private:
// Helpers for EmitStartOfAsmFile() and EmitEndOfAsmFile()
void emitAttributes();
@@ -84,6 +89,10 @@ private:
void EmitUnwindingInstruction(const MachineInstr *MI);
+ // emitPseudoExpansionLowering - tblgen'erated.
+ bool emitPseudoExpansionLowering(MCStreamer &OutStreamer,
+ const MachineInstr *MI);
+
public:
void PrintDebugValueComment(const MachineInstr *MI, raw_ostream &OS);
@@ -100,6 +109,7 @@ public:
llvm::ARM::DW_ISA_ARM_thumb : llvm::ARM::DW_ISA_ARM_arm;
}
+ MCOperand GetSymbolRef(const MachineOperand &MO, const MCSymbol *Symbol);
MCSymbol *GetARMSetPICJumpTableLabel2(unsigned uid, unsigned uid2,
const MachineBasicBlock *MBB) const;
MCSymbol *GetARMJTIPICJumpTableLabel2(unsigned uid, unsigned uid2) const;
@@ -107,7 +117,7 @@ public:
MCSymbol *GetARMSJLJEHLabel(void) const;
MCSymbol *GetARMGVSymbol(const GlobalValue *GV);
-
+
/// EmitMachineConstantPoolValue - Print a machine constantpool value to
/// the .s file.
virtual void EmitMachineConstantPoolValue(MachineConstantPoolValue *MCPV);
diff --git a/lib/Target/ARM/ARMBaseInfo.h b/lib/Target/ARM/ARMBaseInfo.h
index 4c9ecdf..458f7dd 100644
--- a/lib/Target/ARM/ARMBaseInfo.h
+++ b/lib/Target/ARM/ARMBaseInfo.h
@@ -17,22 +17,12 @@
#ifndef ARMBASEINFO_H
#define ARMBASEINFO_H
+#include "MCTargetDesc/ARMMCTargetDesc.h"
#include "llvm/Support/ErrorHandling.h"
// Note that the following auto-generated files only defined enum types, and
// so are safe to include here.
-// Defines symbolic names for ARM registers. This defines a mapping from
-// register name to register number.
-//
-#define GET_REGINFO_ENUM
-#include "ARMGenRegisterInfo.inc"
-
-// Defines symbolic names for the ARM instructions.
-//
-#define GET_INSTRINFO_ENUM
-#include "ARMGenInstrInfo.inc"
-
namespace llvm {
// Enums corresponding to ARM condition codes
diff --git a/lib/Target/ARM/ARMBaseInstrInfo.cpp b/lib/Target/ARM/ARMBaseInstrInfo.cpp
index 32e9372..649bd7d 100644
--- a/lib/Target/ARM/ARMBaseInstrInfo.cpp
+++ b/lib/Target/ARM/ARMBaseInstrInfo.cpp
@@ -30,12 +30,12 @@
#include "llvm/CodeGen/MachineRegisterInfo.h"
#include "llvm/CodeGen/PseudoSourceValue.h"
#include "llvm/MC/MCAsmInfo.h"
+#include "llvm/Support/BranchProbability.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/ADT/STLExtras.h"
-#define GET_INSTRINFO_MC_DESC
#define GET_INSTRINFO_CTOR
#include "ARMGenInstrInfo.inc"
@@ -528,35 +528,23 @@ unsigned ARMBaseInstrInfo::GetInstSizeInBytes(const MachineInstr *MI) const {
const MachineFunction *MF = MBB.getParent();
const MCAsmInfo *MAI = MF->getTarget().getMCAsmInfo();
- // Basic size info comes from the TSFlags field.
const MCInstrDesc &MCID = MI->getDesc();
- uint64_t TSFlags = MCID.TSFlags;
+ if (MCID.getSize())
+ return MCID.getSize();
- unsigned Opc = MI->getOpcode();
- switch ((TSFlags & ARMII::SizeMask) >> ARMII::SizeShift) {
- default: {
// If this machine instr is an inline asm, measure it.
if (MI->getOpcode() == ARM::INLINEASM)
return getInlineAsmLength(MI->getOperand(0).getSymbolName(), *MAI);
if (MI->isLabel())
return 0;
+ unsigned Opc = MI->getOpcode();
switch (Opc) {
- default:
- llvm_unreachable("Unknown or unset size field for instr!");
case TargetOpcode::IMPLICIT_DEF:
case TargetOpcode::KILL:
case TargetOpcode::PROLOG_LABEL:
case TargetOpcode::EH_LABEL:
case TargetOpcode::DBG_VALUE:
return 0;
- }
- break;
- }
- case ARMII::Size8Bytes: return 8; // ARM instruction x 2.
- case ARMII::Size4Bytes: return 4; // ARM / Thumb2 instruction.
- case ARMII::Size2Bytes: return 2; // Thumb1 instruction.
- case ARMII::SizeSpecial: {
- switch (Opc) {
case ARM::MOVi16_ga_pcrel:
case ARM::MOVTi16_ga_pcrel:
case ARM::t2MOVi16_ga_pcrel:
@@ -620,8 +608,6 @@ unsigned ARMBaseInstrInfo::GetInstSizeInBytes(const MachineInstr *MI) const {
// Otherwise, pseudo-instruction sizes are zero.
return 0;
}
- }
- }
return 0; // Not reached
}
@@ -651,7 +637,7 @@ void ARMBaseInstrInfo::copyPhysReg(MachineBasicBlock &MBB,
else if (ARM::DPRRegClass.contains(DestReg, SrcReg))
Opc = ARM::VMOVD;
else if (ARM::QPRRegClass.contains(DestReg, SrcReg))
- Opc = ARM::VMOVQ;
+ Opc = ARM::VORRq;
else if (ARM::QQPRRegClass.contains(DestReg, SrcReg))
Opc = ARM::VMOVQQ;
else if (ARM::QQQQPRRegClass.contains(DestReg, SrcReg))
@@ -661,6 +647,8 @@ void ARMBaseInstrInfo::copyPhysReg(MachineBasicBlock &MBB,
MachineInstrBuilder MIB = BuildMI(MBB, I, DL, get(Opc), DestReg);
MIB.addReg(SrcReg, getKillRegState(KillSrc));
+ if (Opc == ARM::VORRq)
+ MIB.addReg(SrcReg, getKillRegState(KillSrc));
if (Opc != ARM::VMOVQQ && Opc != ARM::VMOVQQQQ)
AddDefaultPred(MIB);
}
@@ -1273,20 +1261,20 @@ bool ARMBaseInstrInfo::isSchedulingBoundary(const MachineInstr *MI,
return false;
}
-bool ARMBaseInstrInfo::isProfitableToIfCvt(MachineBasicBlock &MBB,
- unsigned NumCycles,
- unsigned ExtraPredCycles,
- float Probability,
- float Confidence) const {
+bool ARMBaseInstrInfo::
+isProfitableToIfCvt(MachineBasicBlock &MBB,
+ unsigned NumCycles, unsigned ExtraPredCycles,
+ const BranchProbability &Probability) const {
if (!NumCycles)
return false;
// Attempt to estimate the relative costs of predication versus branching.
- float UnpredCost = Probability * NumCycles;
- UnpredCost += 1.0; // The branch itself
- UnpredCost += (1.0 - Confidence) * Subtarget.getMispredictionPenalty();
+ unsigned UnpredCost = Probability.getNumerator() * NumCycles;
+ UnpredCost /= Probability.getDenominator();
+ UnpredCost += 1; // The branch itself
+ UnpredCost += Subtarget.getMispredictionPenalty() / 10;
- return (float)(NumCycles + ExtraPredCycles) < UnpredCost;
+ return (NumCycles + ExtraPredCycles) <= UnpredCost;
}
bool ARMBaseInstrInfo::
@@ -1294,16 +1282,23 @@ isProfitableToIfCvt(MachineBasicBlock &TMBB,
unsigned TCycles, unsigned TExtra,
MachineBasicBlock &FMBB,
unsigned FCycles, unsigned FExtra,
- float Probability, float Confidence) const {
+ const BranchProbability &Probability) const {
if (!TCycles || !FCycles)
return false;
// Attempt to estimate the relative costs of predication versus branching.
- float UnpredCost = Probability * TCycles + (1.0 - Probability) * FCycles;
- UnpredCost += 1.0; // The branch itself
- UnpredCost += (1.0 - Confidence) * Subtarget.getMispredictionPenalty();
-
- return (float)(TCycles + FCycles + TExtra + FExtra) < UnpredCost;
+ unsigned TUnpredCost = Probability.getNumerator() * TCycles;
+ TUnpredCost /= Probability.getDenominator();
+
+ uint32_t Comp = Probability.getDenominator() - Probability.getNumerator();
+ unsigned FUnpredCost = Comp * FCycles;
+ FUnpredCost /= Probability.getDenominator();
+
+ unsigned UnpredCost = TUnpredCost + FUnpredCost;
+ UnpredCost += 1; // The branch itself
+ UnpredCost += Subtarget.getMispredictionPenalty() / 10;
+
+ return (TCycles + FCycles + TExtra + FExtra) <= UnpredCost;
}
/// getInstrPredicate - If instruction is predicated, returns its predicate
diff --git a/lib/Target/ARM/ARMBaseInstrInfo.h b/lib/Target/ARM/ARMBaseInstrInfo.h
index f95adc4..507e897 100644
--- a/lib/Target/ARM/ARMBaseInstrInfo.h
+++ b/lib/Target/ARM/ARMBaseInstrInfo.h
@@ -39,24 +39,16 @@ namespace ARMII {
// This four-bit field describes the addressing mode used.
AddrModeMask = 0x1f, // The AddrMode enums are declared in ARMBaseInfo.h
- // Size* - Flags to keep track of the size of an instruction.
- SizeShift = 5,
- SizeMask = 7 << SizeShift,
- SizeSpecial = 1, // 0 byte pseudo or special case.
- Size8Bytes = 2,
- Size4Bytes = 3,
- Size2Bytes = 4,
-
// IndexMode - Unindex, pre-indexed, or post-indexed are valid for load
// and store ops only. Generic "updating" flag is used for ld/st multiple.
// The index mode enums are declared in ARMBaseInfo.h
- IndexModeShift = 8,
+ IndexModeShift = 5,
IndexModeMask = 3 << IndexModeShift,
//===------------------------------------------------------------------===//
// Instruction encoding formats.
//
- FormShift = 10,
+ FormShift = 7,
FormMask = 0x3f << FormShift,
// Pseudo instructions
@@ -129,15 +121,15 @@ namespace ARMII {
// UnaryDP - Indicates this is a unary data processing instruction, i.e.
// it doesn't have a Rn operand.
- UnaryDP = 1 << 16,
+ UnaryDP = 1 << 13,
// Xform16Bit - Indicates this Thumb2 instruction may be transformed into
// a 16-bit Thumb instruction if certain conditions are met.
- Xform16Bit = 1 << 17,
+ Xform16Bit = 1 << 14,
//===------------------------------------------------------------------===//
// Code domain.
- DomainShift = 18,
+ DomainShift = 15,
DomainMask = 7 << DomainShift,
DomainGeneral = 0 << DomainShift,
DomainVFP = 1 << DomainShift,
@@ -311,18 +303,18 @@ public:
virtual bool isProfitableToIfCvt(MachineBasicBlock &MBB,
unsigned NumCycles, unsigned ExtraPredCycles,
- float Prob, float Confidence) const;
+ const BranchProbability &Probability) const;
virtual bool isProfitableToIfCvt(MachineBasicBlock &TMBB,
unsigned NumT, unsigned ExtraT,
MachineBasicBlock &FMBB,
unsigned NumF, unsigned ExtraF,
- float Probability, float Confidence) const;
+ const BranchProbability &Probability) const;
virtual bool isProfitableToDupForIfCvt(MachineBasicBlock &MBB,
unsigned NumCycles,
- float Probability,
- float Confidence) const {
+ const BranchProbability
+ &Probability) const {
return NumCycles == 1;
}
diff --git a/lib/Target/ARM/ARMBaseRegisterInfo.cpp b/lib/Target/ARM/ARMBaseRegisterInfo.cpp
index e46082d..ba42295 100644
--- a/lib/Target/ARM/ARMBaseRegisterInfo.cpp
+++ b/lib/Target/ARM/ARMBaseRegisterInfo.cpp
@@ -40,7 +40,6 @@
#include "llvm/ADT/SmallVector.h"
#include "llvm/Support/CommandLine.h"
-#define GET_REGINFO_MC_DESC
#define GET_REGINFO_TARGET_DESC
#include "ARMGenRegisterInfo.inc"
diff --git a/lib/Target/ARM/ARMConstantIslandPass.cpp b/lib/Target/ARM/ARMConstantIslandPass.cpp
index 309caee..f45ebdc 100644
--- a/lib/Target/ARM/ARMConstantIslandPass.cpp
+++ b/lib/Target/ARM/ARMConstantIslandPass.cpp
@@ -1538,7 +1538,10 @@ bool ARMConstantIslands::UndoLRSpillRestore() {
if (MI->getOpcode() == ARM::tPOP_RET &&
MI->getOperand(2).getReg() == ARM::PC &&
MI->getNumExplicitOperands() == 3) {
- BuildMI(MI->getParent(), MI->getDebugLoc(), TII->get(ARM::tBX_RET));
+ // Create the new insn and copy the predicate from the old.
+ BuildMI(MI->getParent(), MI->getDebugLoc(), TII->get(ARM::tBX_RET))
+ .addOperand(MI->getOperand(0))
+ .addOperand(MI->getOperand(1));
MI->eraseFromParent();
MadeChange = true;
}
diff --git a/lib/Target/ARM/ARMExpandPseudoInsts.cpp b/lib/Target/ARM/ARMExpandPseudoInsts.cpp
index 619c603..94b72fd 100644
--- a/lib/Target/ARM/ARMExpandPseudoInsts.cpp
+++ b/lib/Target/ARM/ARMExpandPseudoInsts.cpp
@@ -841,8 +841,9 @@ bool ARMExpandPseudo::ExpandMI(MachineBasicBlock &MBB,
MI.getOperand(0).getReg())
.addOperand(MI.getOperand(1))
.addReg(0)
- .addImm(ARM_AM::getSORegOpc((Opcode == ARM::MOVsrl_flag ? ARM_AM::lsr
- : ARM_AM::asr), 1)))
+ .addImm(ARM_AM::getSORegOpc((Opcode == ARM::MOVsrl_flag ?
+ ARM_AM::lsr : ARM_AM::asr),
+ 1)))
.addReg(ARM::CPSR, RegState::Define);
MI.eraseFromParent();
return true;
@@ -905,10 +906,10 @@ bool ARMExpandPseudo::ExpandMI(MachineBasicBlock &MBB,
const MachineOperand &MO1 = MI.getOperand(1);
const GlobalValue *GV = MO1.getGlobal();
unsigned TF = MO1.getTargetFlags();
- bool isARM = (Opcode != ARM::t2MOV_ga_pcrel && Opcode != ARM::t2MOV_ga_dyn);
+ bool isARM = (Opcode != ARM::t2MOV_ga_pcrel && Opcode!=ARM::t2MOV_ga_dyn);
bool isPIC = (Opcode != ARM::MOV_ga_dyn && Opcode != ARM::t2MOV_ga_dyn);
unsigned LO16Opc = isARM ? ARM::MOVi16_ga_pcrel : ARM::t2MOVi16_ga_pcrel;
- unsigned HI16Opc = isARM ? ARM::MOVTi16_ga_pcrel : ARM::t2MOVTi16_ga_pcrel;
+ unsigned HI16Opc = isARM ? ARM::MOVTi16_ga_pcrel :ARM::t2MOVTi16_ga_pcrel;
unsigned LO16TF = isPIC
? ARMII::MO_LO16_NONLAZY_PIC : ARMII::MO_LO16_NONLAZY;
unsigned HI16TF = isPIC
@@ -963,15 +964,17 @@ bool ARMExpandPseudo::ExpandMI(MachineBasicBlock &MBB,
unsigned OddSrc = TRI->getSubReg(SrcReg, ARM::qsub_1);
MachineInstrBuilder Even =
AddDefaultPred(BuildMI(MBB, MBBI, MI.getDebugLoc(),
- TII->get(ARM::VMOVQ))
+ TII->get(ARM::VORRq))
.addReg(EvenDst,
RegState::Define | getDeadRegState(DstIsDead))
+ .addReg(EvenSrc, getKillRegState(SrcIsKill))
.addReg(EvenSrc, getKillRegState(SrcIsKill)));
MachineInstrBuilder Odd =
AddDefaultPred(BuildMI(MBB, MBBI, MI.getDebugLoc(),
- TII->get(ARM::VMOVQ))
+ TII->get(ARM::VORRq))
.addReg(OddDst,
RegState::Define | getDeadRegState(DstIsDead))
+ .addReg(OddSrc, getKillRegState(SrcIsKill))
.addReg(OddSrc, getKillRegState(SrcIsKill)));
TransferImpOps(MI, Even, Odd);
MI.eraseFromParent();
diff --git a/lib/Target/ARM/ARMFrameLowering.cpp b/lib/Target/ARM/ARMFrameLowering.cpp
index 9e943e4..381b404 100644
--- a/lib/Target/ARM/ARMFrameLowering.cpp
+++ b/lib/Target/ARM/ARMFrameLowering.cpp
@@ -739,20 +739,52 @@ static unsigned GetFunctionSizeInBytes(const MachineFunction &MF,
/// estimateStackSize - Estimate and return the size of the frame.
/// FIXME: Make generic?
static unsigned estimateStackSize(MachineFunction &MF) {
- const MachineFrameInfo *FFI = MF.getFrameInfo();
+ const MachineFrameInfo *MFI = MF.getFrameInfo();
+ const TargetFrameLowering *TFI = MF.getTarget().getFrameLowering();
+ const TargetRegisterInfo *RegInfo = MF.getTarget().getRegisterInfo();
+ unsigned MaxAlign = MFI->getMaxAlignment();
int Offset = 0;
- for (int i = FFI->getObjectIndexBegin(); i != 0; ++i) {
- int FixedOff = -FFI->getObjectOffset(i);
+
+ // This code is very, very similar to PEI::calculateFrameObjectOffsets().
+ // It really should be refactored to share code. Until then, changes
+ // should keep in mind that there's tight coupling between the two.
+
+ for (int i = MFI->getObjectIndexBegin(); i != 0; ++i) {
+ int FixedOff = -MFI->getObjectOffset(i);
if (FixedOff > Offset) Offset = FixedOff;
}
- for (unsigned i = 0, e = FFI->getObjectIndexEnd(); i != e; ++i) {
- if (FFI->isDeadObjectIndex(i))
+ for (unsigned i = 0, e = MFI->getObjectIndexEnd(); i != e; ++i) {
+ if (MFI->isDeadObjectIndex(i))
continue;
- Offset += FFI->getObjectSize(i);
- unsigned Align = FFI->getObjectAlignment(i);
+ Offset += MFI->getObjectSize(i);
+ unsigned Align = MFI->getObjectAlignment(i);
// Adjust to alignment boundary
Offset = (Offset+Align-1)/Align*Align;
+
+ MaxAlign = std::max(Align, MaxAlign);
}
+
+ if (MFI->adjustsStack() && TFI->hasReservedCallFrame(MF))
+ Offset += MFI->getMaxCallFrameSize();
+
+ // Round up the size to a multiple of the alignment. If the function has
+ // any calls or alloca's, align to the target's StackAlignment value to
+ // ensure that the callee's frame or the alloca data is suitably aligned;
+ // otherwise, for leaf functions, align to the TransientStackAlignment
+ // value.
+ unsigned StackAlign;
+ if (MFI->adjustsStack() || MFI->hasVarSizedObjects() ||
+ (RegInfo->needsStackRealignment(MF) && MFI->getObjectIndexEnd() != 0))
+ StackAlign = TFI->getStackAlignment();
+ else
+ StackAlign = TFI->getTransientStackAlignment();
+
+ // If the frame pointer is eliminated, all frame offsets will be relative to
+ // SP not FP. Align to MaxAlign so this works.
+ StackAlign = std::max(StackAlign, MaxAlign);
+ unsigned AlignMask = StackAlign - 1;
+ Offset = (Offset + AlignMask) & ~uint64_t(AlignMask);
+
return (unsigned)Offset;
}
diff --git a/lib/Target/ARM/ARMGlobalMerge.cpp b/lib/Target/ARM/ARMGlobalMerge.cpp
index 4bdd4f1..8d77b2d 100644
--- a/lib/Target/ARM/ARMGlobalMerge.cpp
+++ b/lib/Target/ARM/ARMGlobalMerge.cpp
@@ -128,10 +128,10 @@ bool ARMGlobalMerge::doMerge(SmallVectorImpl<GlobalVariable*> &Globals,
for (size_t i = 0, e = Globals.size(); i != e; ) {
size_t j = 0;
uint64_t MergedSize = 0;
- std::vector<const Type*> Tys;
+ std::vector<Type*> Tys;
std::vector<Constant*> Inits;
for (j = i; j != e; ++j) {
- const Type *Ty = Globals[j]->getType()->getElementType();
+ Type *Ty = Globals[j]->getType()->getElementType();
MergedSize += TD->getTypeAllocSize(Ty);
if (MergedSize > MaxOffset) {
break;
@@ -176,8 +176,8 @@ bool ARMGlobalMerge::doInitialization(Module &M) {
// Ignore fancy-aligned globals for now.
unsigned Alignment = I->getAlignment();
- unsigned AllocSize = TD->getTypeAllocSize(I->getType()->getElementType());
- if (Alignment > AllocSize)
+ const Type *Ty = I->getType()->getElementType();
+ if (Alignment > TD->getABITypeAlignment(Ty))
continue;
// Ignore all 'special' globals.
@@ -185,7 +185,7 @@ bool ARMGlobalMerge::doInitialization(Module &M) {
I->getName().startswith(".llvm."))
continue;
- if (AllocSize < MaxOffset) {
+ if (TD->getTypeAllocSize(Ty) < MaxOffset) {
const TargetLoweringObjectFile &TLOF = TLI->getObjFileLowering();
if (TLOF.getKindForGlobal(I, TLI->getTargetMachine()).isBSSLocal())
BSSGlobals.push_back(I);
diff --git a/lib/Target/ARM/ARMISelLowering.cpp b/lib/Target/ARM/ARMISelLowering.cpp
index 8cd9aa2..cf8c5ba 100644
--- a/lib/Target/ARM/ARMISelLowering.cpp
+++ b/lib/Target/ARM/ARMISelLowering.cpp
@@ -708,6 +708,9 @@ ARMTargetLowering::ARMTargetLowering(TargetMachine &TM)
setOperationAction(ISD::FPOW, MVT::f64, Expand);
setOperationAction(ISD::FPOW, MVT::f32, Expand);
+ setOperationAction(ISD::FMA, MVT::f64, Expand);
+ setOperationAction(ISD::FMA, MVT::f32, Expand);
+
// Various VFP goodness
if (!UseSoftFloat && !Subtarget->isThumb1Only()) {
// int <-> fp are custom expanded into bit_convert + ARMISD ops.
@@ -1637,7 +1640,11 @@ ARMTargetLowering::IsEligibleForTailCallOptimization(SDValue Callee,
return false;
// FIXME: Completely disable sibcall for Thumb1 since Thumb1RegisterInfo::
- // emitEpilogue is not ready for them.
+ // emitEpilogue is not ready for them. Thumb tail calls also use t2B, as
+ // the Thumb1 16-bit unconditional branch doesn't have sufficient relocation
+ // support in the assembler and linker to be used. This would need to be
+ // fixed to fully support tail calls in Thumb1.
+ //
// Doing this is tricky, since the LDM/POP instruction on Thumb doesn't take
// LR. This means if we need to reload LR, it takes an extra instructions,
// which outweighs the value of the tail call; but here we don't know yet
@@ -2747,7 +2754,7 @@ SDValue ARMTargetLowering::LowerSELECT_CC(SDValue Op, SelectionDAG &DAG) const {
SDValue ARMcc;
SDValue CCR = DAG.getRegister(ARM::CPSR, MVT::i32);
SDValue Cmp = getARMCmp(LHS, RHS, CC, ARMcc, DAG, dl);
- return DAG.getNode(ARMISD::CMOV, dl, VT, FalseVal, TrueVal, ARMcc, CCR,Cmp);
+ return DAG.getNode(ARMISD::CMOV, dl, VT, FalseVal, TrueVal, ARMcc, CCR, Cmp);
}
ARMCC::CondCodes CondCode, CondCode2;
@@ -6953,6 +6960,70 @@ static SDValue PerformSELECT_CCCombine(SDNode *N, SelectionDAG &DAG,
return DAG.getNode(Opcode, N->getDebugLoc(), N->getValueType(0), LHS, RHS);
}
+/// PerformCMOVCombine - Target-specific DAG combining for ARMISD::CMOV.
+SDValue
+ARMTargetLowering::PerformCMOVCombine(SDNode *N, SelectionDAG &DAG) const {
+ SDValue Cmp = N->getOperand(4);
+ if (Cmp.getOpcode() != ARMISD::CMPZ)
+ // Only looking at EQ and NE cases.
+ return SDValue();
+
+ EVT VT = N->getValueType(0);
+ DebugLoc dl = N->getDebugLoc();
+ SDValue LHS = Cmp.getOperand(0);
+ SDValue RHS = Cmp.getOperand(1);
+ SDValue FalseVal = N->getOperand(0);
+ SDValue TrueVal = N->getOperand(1);
+ SDValue ARMcc = N->getOperand(2);
+ ARMCC::CondCodes CC = (ARMCC::CondCodes)cast<ConstantSDNode>(ARMcc)->getZExtValue();
+
+ // Simplify
+ // mov r1, r0
+ // cmp r1, x
+ // mov r0, y
+ // moveq r0, x
+ // to
+ // cmp r0, x
+ // movne r0, y
+ //
+ // mov r1, r0
+ // cmp r1, x
+ // mov r0, x
+ // movne r0, y
+ // to
+ // cmp r0, x
+ // movne r0, y
+ /// FIXME: Turn this into a target neutral optimization?
+ SDValue Res;
+ if (CC == ARMCC::NE && FalseVal == RHS) {
+ Res = DAG.getNode(ARMISD::CMOV, dl, VT, LHS, TrueVal, ARMcc,
+ N->getOperand(3), Cmp);
+ } else if (CC == ARMCC::EQ && TrueVal == RHS) {
+ SDValue ARMcc;
+ SDValue NewCmp = getARMCmp(LHS, RHS, ISD::SETNE, ARMcc, DAG, dl);
+ Res = DAG.getNode(ARMISD::CMOV, dl, VT, LHS, FalseVal, ARMcc,
+ N->getOperand(3), NewCmp);
+ }
+
+ if (Res.getNode()) {
+ APInt KnownZero, KnownOne;
+ APInt Mask = APInt::getAllOnesValue(VT.getScalarType().getSizeInBits());
+ DAG.ComputeMaskedBits(SDValue(N,0), Mask, KnownZero, KnownOne);
+ // Capture demanded bits information that would be otherwise lost.
+ if (KnownZero == 0xfffffffe)
+ Res = DAG.getNode(ISD::AssertZext, dl, MVT::i32, Res,
+ DAG.getValueType(MVT::i1));
+ else if (KnownZero == 0xffffff00)
+ Res = DAG.getNode(ISD::AssertZext, dl, MVT::i32, Res,
+ DAG.getValueType(MVT::i8));
+ else if (KnownZero == 0xffff0000)
+ Res = DAG.getNode(ISD::AssertZext, dl, MVT::i32, Res,
+ DAG.getValueType(MVT::i16));
+ }
+
+ return Res;
+}
+
SDValue ARMTargetLowering::PerformDAGCombine(SDNode *N,
DAGCombinerInfo &DCI) const {
switch (N->getOpcode()) {
@@ -6981,6 +7052,7 @@ SDValue ARMTargetLowering::PerformDAGCombine(SDNode *N,
case ISD::ZERO_EXTEND:
case ISD::ANY_EXTEND: return PerformExtendCombine(N, DCI.DAG, Subtarget);
case ISD::SELECT_CC: return PerformSELECT_CCCombine(N, DCI.DAG, Subtarget);
+ case ARMISD::CMOV: return PerformCMOVCombine(N, DCI.DAG);
case ARMISD::VLD2DUP:
case ARMISD::VLD3DUP:
case ARMISD::VLD4DUP:
diff --git a/lib/Target/ARM/ARMISelLowering.h b/lib/Target/ARM/ARMISelLowering.h
index dd9df0e..980fb40 100644
--- a/lib/Target/ARM/ARMISelLowering.h
+++ b/lib/Target/ARM/ARMISelLowering.h
@@ -244,6 +244,7 @@ namespace llvm {
EmitInstrWithCustomInserter(MachineInstr *MI,
MachineBasicBlock *MBB) const;
+ SDValue PerformCMOVCombine(SDNode *N, SelectionDAG &DAG) const;
virtual SDValue PerformDAGCombine(SDNode *N, DAGCombinerInfo &DCI) const;
bool isDesirableToTransformToIntegerOp(unsigned Opc, EVT VT) const;
diff --git a/lib/Target/ARM/ARMInstrFormats.td b/lib/Target/ARM/ARMInstrFormats.td
index 897d8a5..3ccf22f 100644
--- a/lib/Target/ARM/ARMInstrFormats.td
+++ b/lib/Target/ARM/ARMInstrFormats.td
@@ -107,16 +107,6 @@ def AddrModeT2_pc : AddrMode<14>;
def AddrModeT2_i8s4 : AddrMode<15>;
def AddrMode_i12 : AddrMode<16>;
-// Instruction size.
-class SizeFlagVal<bits<3> val> {
- bits<3> Value = val;
-}
-def SizeInvalid : SizeFlagVal<0>; // Unset.
-def SizeSpecial : SizeFlagVal<1>; // Pseudo or special.
-def Size8Bytes : SizeFlagVal<2>;
-def Size4Bytes : SizeFlagVal<3>;
-def Size2Bytes : SizeFlagVal<4>;
-
// Load / store index mode.
class IndexMode<bits<2> val> {
bits<2> Value = val;
@@ -236,13 +226,13 @@ def shr_imm64 : Operand<i32> {
// ARM Instruction templates.
//
-class InstTemplate<AddrMode am, SizeFlagVal sz, IndexMode im,
+class InstTemplate<AddrMode am, int sz, IndexMode im,
Format f, Domain d, string cstr, InstrItinClass itin>
: Instruction {
let Namespace = "ARM";
AddrMode AM = am;
- SizeFlagVal SZ = sz;
+ int Size = sz;
IndexMode IM = im;
bits<2> IndexModeBits = IM.Value;
Format F = f;
@@ -256,12 +246,11 @@ class InstTemplate<AddrMode am, SizeFlagVal sz, IndexMode im,
// The layout of TSFlags should be kept in sync with ARMBaseInstrInfo.h.
let TSFlags{4-0} = AM.Value;
- let TSFlags{7-5} = SZ.Value;
- let TSFlags{9-8} = IndexModeBits;
- let TSFlags{15-10} = Form;
- let TSFlags{16} = isUnaryDataProc;
- let TSFlags{17} = canXformTo16Bit;
- let TSFlags{20-18} = D.Value;
+ let TSFlags{6-5} = IndexModeBits;
+ let TSFlags{12-7} = Form;
+ let TSFlags{13} = isUnaryDataProc;
+ let TSFlags{14} = canXformTo16Bit;
+ let TSFlags{17-15} = D.Value;
let Constraints = cstr;
let Itinerary = itin;
@@ -271,53 +260,70 @@ class Encoding {
field bits<32> Inst;
}
-class InstARM<AddrMode am, SizeFlagVal sz, IndexMode im,
+class InstARM<AddrMode am, int sz, IndexMode im,
Format f, Domain d, string cstr, InstrItinClass itin>
: InstTemplate<am, sz, im, f, d, cstr, itin>, Encoding;
// This Encoding-less class is used by Thumb1 to specify the encoding bits later
// on by adding flavors to specific instructions.
-class InstThumb<AddrMode am, SizeFlagVal sz, IndexMode im,
+class InstThumb<AddrMode am, int sz, IndexMode im,
Format f, Domain d, string cstr, InstrItinClass itin>
: InstTemplate<am, sz, im, f, d, cstr, itin>;
class PseudoInst<dag oops, dag iops, InstrItinClass itin, list<dag> pattern>
- // FIXME: This really should derive from InstTemplate instead, as pseudos
- // don't need encoding information. TableGen doesn't like that
- // currently. Need to figure out why and fix it.
- : InstARM<AddrModeNone, SizeSpecial, IndexModeNone, Pseudo, GenericDomain,
- "", itin> {
+ : InstTemplate<AddrModeNone, 0, IndexModeNone, Pseudo,
+ GenericDomain, "", itin> {
let OutOperandList = oops;
let InOperandList = iops;
let Pattern = pattern;
let isCodeGenOnly = 1;
+ let isPseudo = 1;
}
// PseudoInst that's ARM-mode only.
-class ARMPseudoInst<dag oops, dag iops, SizeFlagVal sz, InstrItinClass itin,
+class ARMPseudoInst<dag oops, dag iops, int sz, InstrItinClass itin,
list<dag> pattern>
: PseudoInst<oops, iops, itin, pattern> {
- let SZ = sz;
+ let Size = sz;
list<Predicate> Predicates = [IsARM];
}
// PseudoInst that's Thumb-mode only.
-class tPseudoInst<dag oops, dag iops, SizeFlagVal sz, InstrItinClass itin,
+class tPseudoInst<dag oops, dag iops, int sz, InstrItinClass itin,
list<dag> pattern>
: PseudoInst<oops, iops, itin, pattern> {
- let SZ = sz;
+ let Size = sz;
list<Predicate> Predicates = [IsThumb];
}
// PseudoInst that's Thumb2-mode only.
-class t2PseudoInst<dag oops, dag iops, SizeFlagVal sz, InstrItinClass itin,
+class t2PseudoInst<dag oops, dag iops, int sz, InstrItinClass itin,
list<dag> pattern>
: PseudoInst<oops, iops, itin, pattern> {
- let SZ = sz;
+ let Size = sz;
list<Predicate> Predicates = [IsThumb2];
}
+
+class ARMPseudoExpand<dag oops, dag iops, int sz,
+ InstrItinClass itin, list<dag> pattern,
+ dag Result>
+ : ARMPseudoInst<oops, iops, sz, itin, pattern>,
+ PseudoInstExpansion<Result>;
+
+class tPseudoExpand<dag oops, dag iops, int sz,
+ InstrItinClass itin, list<dag> pattern,
+ dag Result>
+ : tPseudoInst<oops, iops, sz, itin, pattern>,
+ PseudoInstExpansion<Result>;
+
+class t2PseudoExpand<dag oops, dag iops, int sz,
+ InstrItinClass itin, list<dag> pattern,
+ dag Result>
+ : t2PseudoInst<oops, iops, sz, itin, pattern>,
+ PseudoInstExpansion<Result>;
+
// Almost all ARM instructions are predicable.
-class I<dag oops, dag iops, AddrMode am, SizeFlagVal sz,
+class I<dag oops, dag iops, AddrMode am, int sz,
IndexMode im, Format f, InstrItinClass itin,
string opc, string asm, string cstr,
list<dag> pattern>
@@ -332,7 +338,7 @@ class I<dag oops, dag iops, AddrMode am, SizeFlagVal sz,
}
// A few are not predicable
-class InoP<dag oops, dag iops, AddrMode am, SizeFlagVal sz,
+class InoP<dag oops, dag iops, AddrMode am, int sz,
IndexMode im, Format f, InstrItinClass itin,
string opc, string asm, string cstr,
list<dag> pattern>
@@ -348,7 +354,7 @@ class InoP<dag oops, dag iops, AddrMode am, SizeFlagVal sz,
// Same as I except it can optionally modify CPSR. Note it's modeled as an input
// operand since by default it's a zero register. It will become an implicit def
// once it's "flipped".
-class sI<dag oops, dag iops, AddrMode am, SizeFlagVal sz,
+class sI<dag oops, dag iops, AddrMode am, int sz,
IndexMode im, Format f, InstrItinClass itin,
string opc, string asm, string cstr,
list<dag> pattern>
@@ -366,7 +372,7 @@ class sI<dag oops, dag iops, AddrMode am, SizeFlagVal sz,
}
// Special cases
-class XI<dag oops, dag iops, AddrMode am, SizeFlagVal sz,
+class XI<dag oops, dag iops, AddrMode am, int sz,
IndexMode im, Format f, InstrItinClass itin,
string asm, string cstr, list<dag> pattern>
: InstARM<am, sz, im, f, GenericDomain, cstr, itin> {
@@ -379,31 +385,31 @@ class XI<dag oops, dag iops, AddrMode am, SizeFlagVal sz,
class AI<dag oops, dag iops, Format f, InstrItinClass itin,
string opc, string asm, list<dag> pattern>
- : I<oops, iops, AddrModeNone, Size4Bytes, IndexModeNone, f, itin,
+ : I<oops, iops, AddrModeNone, 4, IndexModeNone, f, itin,
opc, asm, "", pattern>;
class AsI<dag oops, dag iops, Format f, InstrItinClass itin,
string opc, string asm, list<dag> pattern>
- : sI<oops, iops, AddrModeNone, Size4Bytes, IndexModeNone, f, itin,
+ : sI<oops, iops, AddrModeNone, 4, IndexModeNone, f, itin,
opc, asm, "", pattern>;
class AXI<dag oops, dag iops, Format f, InstrItinClass itin,
string asm, list<dag> pattern>
- : XI<oops, iops, AddrModeNone, Size4Bytes, IndexModeNone, f, itin,
+ : XI<oops, iops, AddrModeNone, 4, IndexModeNone, f, itin,
asm, "", pattern>;
class AInoP<dag oops, dag iops, Format f, InstrItinClass itin,
string opc, string asm, list<dag> pattern>
- : InoP<oops, iops, AddrModeNone, Size4Bytes, IndexModeNone, f, itin,
+ : InoP<oops, iops, AddrModeNone, 4, IndexModeNone, f, itin,
opc, asm, "", pattern>;
// Ctrl flow instructions
class ABI<bits<4> opcod, dag oops, dag iops, InstrItinClass itin,
string opc, string asm, list<dag> pattern>
- : I<oops, iops, AddrModeNone, Size4Bytes, IndexModeNone, BrFrm, itin,
+ : I<oops, iops, AddrModeNone, 4, IndexModeNone, BrFrm, itin,
opc, asm, "", pattern> {
let Inst{27-24} = opcod;
}
class ABXI<bits<4> opcod, dag oops, dag iops, InstrItinClass itin,
string asm, list<dag> pattern>
- : XI<oops, iops, AddrModeNone, Size4Bytes, IndexModeNone, BrFrm, itin,
+ : XI<oops, iops, AddrModeNone, 4, IndexModeNone, BrFrm, itin,
asm, "", pattern> {
let Inst{27-24} = opcod;
}
@@ -411,13 +417,13 @@ class ABXI<bits<4> opcod, dag oops, dag iops, InstrItinClass itin,
// BR_JT instructions
class JTI<dag oops, dag iops, InstrItinClass itin,
string asm, list<dag> pattern>
- : XI<oops, iops, AddrModeNone, SizeSpecial, IndexModeNone, BrMiscFrm, itin,
+ : XI<oops, iops, AddrModeNone, 0, IndexModeNone, BrMiscFrm, itin,
asm, "", pattern>;
// Atomic load/store instructions
class AIldrex<bits<2> opcod, dag oops, dag iops, InstrItinClass itin,
string opc, string asm, list<dag> pattern>
- : I<oops, iops, AddrModeNone, Size4Bytes, IndexModeNone, LdStExFrm, itin,
+ : I<oops, iops, AddrModeNone, 4, IndexModeNone, LdStExFrm, itin,
opc, asm, "", pattern> {
bits<4> Rt;
bits<4> Rn;
@@ -430,7 +436,7 @@ class AIldrex<bits<2> opcod, dag oops, dag iops, InstrItinClass itin,
}
class AIstrex<bits<2> opcod, dag oops, dag iops, InstrItinClass itin,
string opc, string asm, list<dag> pattern>
- : I<oops, iops, AddrModeNone, Size4Bytes, IndexModeNone, LdStExFrm, itin,
+ : I<oops, iops, AddrModeNone, 4, IndexModeNone, LdStExFrm, itin,
opc, asm, "", pattern> {
bits<4> Rd;
bits<4> Rt;
@@ -460,21 +466,21 @@ class AIswp<bit b, dag oops, dag iops, string opc, list<dag> pattern>
// addrmode1 instructions
class AI1<bits<4> opcod, dag oops, dag iops, Format f, InstrItinClass itin,
string opc, string asm, list<dag> pattern>
- : I<oops, iops, AddrMode1, Size4Bytes, IndexModeNone, f, itin,
+ : I<oops, iops, AddrMode1, 4, IndexModeNone, f, itin,
opc, asm, "", pattern> {
let Inst{24-21} = opcod;
let Inst{27-26} = 0b00;
}
class AsI1<bits<4> opcod, dag oops, dag iops, Format f, InstrItinClass itin,
string opc, string asm, list<dag> pattern>
- : sI<oops, iops, AddrMode1, Size4Bytes, IndexModeNone, f, itin,
+ : sI<oops, iops, AddrMode1, 4, IndexModeNone, f, itin,
opc, asm, "", pattern> {
let Inst{24-21} = opcod;
let Inst{27-26} = 0b00;
}
class AXI1<bits<4> opcod, dag oops, dag iops, Format f, InstrItinClass itin,
string asm, list<dag> pattern>
- : XI<oops, iops, AddrMode1, Size4Bytes, IndexModeNone, f, itin,
+ : XI<oops, iops, AddrMode1, 4, IndexModeNone, f, itin,
asm, "", pattern> {
let Inst{24-21} = opcod;
let Inst{27-26} = 0b00;
@@ -486,7 +492,7 @@ class AXI1<bits<4> opcod, dag oops, dag iops, Format f, InstrItinClass itin,
class AI2ldst<bits<3> op, bit isLd, bit isByte, dag oops, dag iops, AddrMode am,
Format f, InstrItinClass itin, string opc, string asm,
list<dag> pattern>
- : I<oops, iops, am, Size4Bytes, IndexModeNone, f, itin, opc, asm,
+ : I<oops, iops, am, 4, IndexModeNone, f, itin, opc, asm,
"", pattern> {
let Inst{27-25} = op;
let Inst{24} = 1; // 24 == P
@@ -499,7 +505,7 @@ class AI2ldst<bits<3> op, bit isLd, bit isByte, dag oops, dag iops, AddrMode am,
class AI2ldstidx<bit isLd, bit isByte, bit isPre, dag oops, dag iops,
IndexMode im, Format f, InstrItinClass itin, string opc,
string asm, string cstr, list<dag> pattern>
- : I<oops, iops, AddrMode2, Size4Bytes, im, f, itin,
+ : I<oops, iops, AddrMode2, 4, im, f, itin,
opc, asm, cstr, pattern> {
bits<4> Rt;
let Inst{27-26} = 0b01;
@@ -547,7 +553,7 @@ class AI2stridxT<bit isByte, bit isPre, dag oops, dag iops,
// addrmode3 instructions
class AI3ld<bits<4> op, bit op20, dag oops, dag iops, Format f,
InstrItinClass itin, string opc, string asm, list<dag> pattern>
- : I<oops, iops, AddrMode3, Size4Bytes, IndexModeNone, f, itin,
+ : I<oops, iops, AddrMode3, 4, IndexModeNone, f, itin,
opc, asm, "", pattern> {
bits<14> addr;
bits<4> Rt;
@@ -567,7 +573,7 @@ class AI3ld<bits<4> op, bit op20, dag oops, dag iops, Format f,
class AI3ldstidx<bits<4> op, bit op20, bit isLd, bit isPre, dag oops, dag iops,
IndexMode im, Format f, InstrItinClass itin, string opc,
string asm, string cstr, list<dag> pattern>
- : I<oops, iops, AddrMode3, Size4Bytes, im, f, itin,
+ : I<oops, iops, AddrMode3, 4, im, f, itin,
opc, asm, cstr, pattern> {
bits<4> Rt;
let Inst{27-25} = 0b000;
@@ -583,7 +589,7 @@ class AI3ldstidx<bits<4> op, bit op20, bit isLd, bit isPre, dag oops, dag iops,
class AI3ldstidxT<bits<4> op, bit op20, bit isLd, bit isPre, dag oops, dag iops,
IndexMode im, Format f, InstrItinClass itin, string opc,
string asm, string cstr, list<dag> pattern>
- : I<oops, iops, AddrMode3, Size4Bytes, im, f, itin,
+ : I<oops, iops, AddrMode3, 4, im, f, itin,
opc, asm, cstr, pattern> {
// {13} 1 == imm8, 0 == Rm
// {12-9} Rn
@@ -627,7 +633,7 @@ class AI3stridx<bits<4> op, bit isByte, bit isPre, dag oops, dag iops,
// stores
class AI3str<bits<4> op, dag oops, dag iops, Format f, InstrItinClass itin,
string opc, string asm, list<dag> pattern>
- : I<oops, iops, AddrMode3, Size4Bytes, IndexModeNone, f, itin,
+ : I<oops, iops, AddrMode3, 4, IndexModeNone, f, itin,
opc, asm, "", pattern> {
bits<14> addr;
bits<4> Rt;
@@ -647,7 +653,7 @@ class AI3str<bits<4> op, dag oops, dag iops, Format f, InstrItinClass itin,
// Pre-indexed stores
class AI3sthpr<dag oops, dag iops, Format f, InstrItinClass itin,
string opc, string asm, string cstr, list<dag> pattern>
- : I<oops, iops, AddrMode3, Size4Bytes, IndexModePre, f, itin,
+ : I<oops, iops, AddrMode3, 4, IndexModePre, f, itin,
opc, asm, cstr, pattern> {
let Inst{4} = 1;
let Inst{5} = 1; // H bit
@@ -660,7 +666,7 @@ class AI3sthpr<dag oops, dag iops, Format f, InstrItinClass itin,
}
class AI3stdpr<dag oops, dag iops, Format f, InstrItinClass itin,
string opc, string asm, string cstr, list<dag> pattern>
- : I<oops, iops, AddrMode3, Size4Bytes, IndexModePre, f, itin,
+ : I<oops, iops, AddrMode3, 4, IndexModePre, f, itin,
opc, asm, cstr, pattern> {
let Inst{4} = 1;
let Inst{5} = 1; // H bit
@@ -675,7 +681,7 @@ class AI3stdpr<dag oops, dag iops, Format f, InstrItinClass itin,
// Post-indexed stores
class AI3sthpo<dag oops, dag iops, Format f, InstrItinClass itin,
string opc, string asm, string cstr, list<dag> pattern>
- : I<oops, iops, AddrMode3, Size4Bytes, IndexModePost, f, itin,
+ : I<oops, iops, AddrMode3, 4, IndexModePost, f, itin,
opc, asm, cstr,pattern> {
// {13} 1 == imm8, 0 == Rm
// {12-9} Rn
@@ -701,7 +707,7 @@ class AI3sthpo<dag oops, dag iops, Format f, InstrItinClass itin,
}
class AI3stdpo<dag oops, dag iops, Format f, InstrItinClass itin,
string opc, string asm, string cstr, list<dag> pattern>
- : I<oops, iops, AddrMode3, Size4Bytes, IndexModePost, f, itin,
+ : I<oops, iops, AddrMode3, 4, IndexModePost, f, itin,
opc, asm, cstr, pattern> {
let Inst{4} = 1;
let Inst{5} = 1; // H bit
@@ -716,7 +722,7 @@ class AI3stdpo<dag oops, dag iops, Format f, InstrItinClass itin,
// addrmode4 instructions
class AXI4<dag oops, dag iops, IndexMode im, Format f, InstrItinClass itin,
string asm, string cstr, list<dag> pattern>
- : XI<oops, iops, AddrMode4, Size4Bytes, im, f, itin, asm, cstr, pattern> {
+ : XI<oops, iops, AddrMode4, 4, im, f, itin, asm, cstr, pattern> {
bits<4> p;
bits<16> regs;
bits<4> Rn;
@@ -730,7 +736,7 @@ class AXI4<dag oops, dag iops, IndexMode im, Format f, InstrItinClass itin,
// Unsigned multiply, multiply-accumulate instructions.
class AMul1I<bits<7> opcod, dag oops, dag iops, InstrItinClass itin,
string opc, string asm, list<dag> pattern>
- : I<oops, iops, AddrModeNone, Size4Bytes, IndexModeNone, MulFrm, itin,
+ : I<oops, iops, AddrModeNone, 4, IndexModeNone, MulFrm, itin,
opc, asm, "", pattern> {
let Inst{7-4} = 0b1001;
let Inst{20} = 0; // S bit
@@ -738,7 +744,7 @@ class AMul1I<bits<7> opcod, dag oops, dag iops, InstrItinClass itin,
}
class AsMul1I<bits<7> opcod, dag oops, dag iops, InstrItinClass itin,
string opc, string asm, list<dag> pattern>
- : sI<oops, iops, AddrModeNone, Size4Bytes, IndexModeNone, MulFrm, itin,
+ : sI<oops, iops, AddrModeNone, 4, IndexModeNone, MulFrm, itin,
opc, asm, "", pattern> {
let Inst{7-4} = 0b1001;
let Inst{27-21} = opcod;
@@ -747,7 +753,7 @@ class AsMul1I<bits<7> opcod, dag oops, dag iops, InstrItinClass itin,
// Most significant word multiply
class AMul2I<bits<7> opcod, bits<4> opc7_4, dag oops, dag iops,
InstrItinClass itin, string opc, string asm, list<dag> pattern>
- : I<oops, iops, AddrModeNone, Size4Bytes, IndexModeNone, MulFrm, itin,
+ : I<oops, iops, AddrModeNone, 4, IndexModeNone, MulFrm, itin,
opc, asm, "", pattern> {
bits<4> Rd;
bits<4> Rn;
@@ -770,7 +776,7 @@ class AMul2Ia<bits<7> opcod, bits<4> opc7_4, dag oops, dag iops,
// SMUL<x><y> / SMULW<y> / SMLA<x><y> / SMLAW<x><y>
class AMulxyIbase<bits<7> opcod, bits<2> bit6_5, dag oops, dag iops,
InstrItinClass itin, string opc, string asm, list<dag> pattern>
- : I<oops, iops, AddrModeNone, Size4Bytes, IndexModeNone, MulFrm, itin,
+ : I<oops, iops, AddrModeNone, 4, IndexModeNone, MulFrm, itin,
opc, asm, "", pattern> {
bits<4> Rn;
bits<4> Rm;
@@ -809,7 +815,7 @@ class AMulxyI64<bits<7> opcod, bits<2> bit6_5, dag oops, dag iops,
// Extend instructions.
class AExtI<bits<8> opcod, dag oops, dag iops, InstrItinClass itin,
string opc, string asm, list<dag> pattern>
- : I<oops, iops, AddrModeNone, Size4Bytes, IndexModeNone, ExtFrm, itin,
+ : I<oops, iops, AddrModeNone, 4, IndexModeNone, ExtFrm, itin,
opc, asm, "", pattern> {
// All AExtI instructions have Rd and Rm register operands.
bits<4> Rd;
@@ -824,7 +830,7 @@ class AExtI<bits<8> opcod, dag oops, dag iops, InstrItinClass itin,
// Misc Arithmetic instructions.
class AMiscA1I<bits<8> opcod, bits<4> opc7_4, dag oops, dag iops,
InstrItinClass itin, string opc, string asm, list<dag> pattern>
- : I<oops, iops, AddrModeNone, Size4Bytes, IndexModeNone, ArithMiscFrm, itin,
+ : I<oops, iops, AddrModeNone, 4, IndexModeNone, ArithMiscFrm, itin,
opc, asm, "", pattern> {
bits<4> Rd;
bits<4> Rm;
@@ -839,7 +845,7 @@ class AMiscA1I<bits<8> opcod, bits<4> opc7_4, dag oops, dag iops,
// PKH instructions
class APKHI<bits<8> opcod, bit tb, dag oops, dag iops, InstrItinClass itin,
string opc, string asm, list<dag> pattern>
- : I<oops, iops, AddrModeNone, Size4Bytes, IndexModeNone, ArithMiscFrm, itin,
+ : I<oops, iops, AddrModeNone, 4, IndexModeNone, ArithMiscFrm, itin,
opc, asm, "", pattern> {
bits<4> Rd;
bits<4> Rn;
@@ -874,7 +880,7 @@ class ARMV6Pat<dag pattern, dag result> : Pat<pattern, result> {
// Thumb Instruction Format Definitions.
//
-class ThumbI<dag oops, dag iops, AddrMode am, SizeFlagVal sz,
+class ThumbI<dag oops, dag iops, AddrMode am, int sz,
InstrItinClass itin, string asm, string cstr, list<dag> pattern>
: InstThumb<am, sz, IndexModeNone, ThumbFrm, GenericDomain, cstr, itin> {
let OutOperandList = oops;
@@ -886,39 +892,32 @@ class ThumbI<dag oops, dag iops, AddrMode am, SizeFlagVal sz,
// TI - Thumb instruction.
class TI<dag oops, dag iops, InstrItinClass itin, string asm, list<dag> pattern>
- : ThumbI<oops, iops, AddrModeNone, Size2Bytes, itin, asm, "", pattern>;
+ : ThumbI<oops, iops, AddrModeNone, 2, itin, asm, "", pattern>;
// Two-address instructions
class TIt<dag oops, dag iops, InstrItinClass itin, string asm,
list<dag> pattern>
- : ThumbI<oops, iops, AddrModeNone, Size2Bytes, itin, asm, "$lhs = $dst",
+ : ThumbI<oops, iops, AddrModeNone, 2, itin, asm, "$lhs = $dst",
pattern>;
// tBL, tBX 32-bit instructions
class TIx2<bits<5> opcod1, bits<2> opcod2, bit opcod3,
dag oops, dag iops, InstrItinClass itin, string asm,
list<dag> pattern>
- : ThumbI<oops, iops, AddrModeNone, Size4Bytes, itin, asm, "", pattern>,
+ : ThumbI<oops, iops, AddrModeNone, 4, itin, asm, "", pattern>,
Encoding {
let Inst{31-27} = opcod1;
let Inst{15-14} = opcod2;
let Inst{12} = opcod3;
}
-// Move to/from coprocessor instructions
-class T1Cop<dag oops, dag iops, string asm, list<dag> pattern>
- : ThumbI<oops, iops, AddrModeNone, Size4Bytes, NoItinerary, asm, "", pattern>,
- Encoding, Requires<[IsThumb, HasV6]> {
- let Inst{31-28} = 0b1110;
-}
-
// BR_JT instructions
class TJTI<dag oops, dag iops, InstrItinClass itin, string asm,
list<dag> pattern>
- : ThumbI<oops, iops, AddrModeNone, SizeSpecial, itin, asm, "", pattern>;
+ : ThumbI<oops, iops, AddrModeNone, 0, itin, asm, "", pattern>;
// Thumb1 only
-class Thumb1I<dag oops, dag iops, AddrMode am, SizeFlagVal sz,
+class Thumb1I<dag oops, dag iops, AddrMode am, int sz,
InstrItinClass itin, string asm, string cstr, list<dag> pattern>
: InstThumb<am, sz, IndexModeNone, ThumbFrm, GenericDomain, cstr, itin> {
let OutOperandList = oops;
@@ -930,19 +929,19 @@ class Thumb1I<dag oops, dag iops, AddrMode am, SizeFlagVal sz,
class T1I<dag oops, dag iops, InstrItinClass itin,
string asm, list<dag> pattern>
- : Thumb1I<oops, iops, AddrModeNone, Size2Bytes, itin, asm, "", pattern>;
+ : Thumb1I<oops, iops, AddrModeNone, 2, itin, asm, "", pattern>;
class T1Ix2<dag oops, dag iops, InstrItinClass itin,
string asm, list<dag> pattern>
- : Thumb1I<oops, iops, AddrModeNone, Size4Bytes, itin, asm, "", pattern>;
+ : Thumb1I<oops, iops, AddrModeNone, 4, itin, asm, "", pattern>;
// Two-address instructions
class T1It<dag oops, dag iops, InstrItinClass itin,
string asm, string cstr, list<dag> pattern>
- : Thumb1I<oops, iops, AddrModeNone, Size2Bytes, itin,
+ : Thumb1I<oops, iops, AddrModeNone, 2, itin,
asm, cstr, pattern>;
// Thumb1 instruction that can either be predicated or set CPSR.
-class Thumb1sI<dag oops, dag iops, AddrMode am, SizeFlagVal sz,
+class Thumb1sI<dag oops, dag iops, AddrMode am, int sz,
InstrItinClass itin,
string opc, string asm, string cstr, list<dag> pattern>
: InstThumb<am, sz, IndexModeNone, ThumbFrm, GenericDomain, cstr, itin> {
@@ -955,16 +954,16 @@ class Thumb1sI<dag oops, dag iops, AddrMode am, SizeFlagVal sz,
class T1sI<dag oops, dag iops, InstrItinClass itin,
string opc, string asm, list<dag> pattern>
- : Thumb1sI<oops, iops, AddrModeNone, Size2Bytes, itin, opc, asm, "", pattern>;
+ : Thumb1sI<oops, iops, AddrModeNone, 2, itin, opc, asm, "", pattern>;
// Two-address instructions
class T1sIt<dag oops, dag iops, InstrItinClass itin,
string opc, string asm, list<dag> pattern>
- : Thumb1sI<oops, iops, AddrModeNone, Size2Bytes, itin, opc, asm,
+ : Thumb1sI<oops, iops, AddrModeNone, 2, itin, opc, asm,
"$Rn = $Rdn", pattern>;
// Thumb1 instruction that can be predicated.
-class Thumb1pI<dag oops, dag iops, AddrMode am, SizeFlagVal sz,
+class Thumb1pI<dag oops, dag iops, AddrMode am, int sz,
InstrItinClass itin,
string opc, string asm, string cstr, list<dag> pattern>
: InstThumb<am, sz, IndexModeNone, ThumbFrm, GenericDomain, cstr, itin> {
@@ -977,17 +976,17 @@ class Thumb1pI<dag oops, dag iops, AddrMode am, SizeFlagVal sz,
class T1pI<dag oops, dag iops, InstrItinClass itin,
string opc, string asm, list<dag> pattern>
- : Thumb1pI<oops, iops, AddrModeNone, Size2Bytes, itin, opc, asm, "", pattern>;
+ : Thumb1pI<oops, iops, AddrModeNone, 2, itin, opc, asm, "", pattern>;
// Two-address instructions
class T1pIt<dag oops, dag iops, InstrItinClass itin,
string opc, string asm, list<dag> pattern>
- : Thumb1pI<oops, iops, AddrModeNone, Size2Bytes, itin, opc, asm,
+ : Thumb1pI<oops, iops, AddrModeNone, 2, itin, opc, asm,
"$Rn = $Rdn", pattern>;
class T1pIs<dag oops, dag iops,
InstrItinClass itin, string opc, string asm, list<dag> pattern>
- : Thumb1pI<oops, iops, AddrModeT1_s, Size2Bytes, itin, opc, asm, "", pattern>;
+ : Thumb1pI<oops, iops, AddrModeT1_s, 2, itin, opc, asm, "", pattern>;
class Encoding16 : Encoding {
let Inst{31-16} = 0x0000;
@@ -1036,7 +1035,7 @@ class T1BranchCond<bits<4> opcode> : Encoding16 {
class T1pILdStEncode<bits<3> opcode, dag oops, dag iops, AddrMode am,
InstrItinClass itin, string opc, string asm,
list<dag> pattern>
- : Thumb1pI<oops, iops, am, Size2Bytes, itin, opc, asm, "", pattern>,
+ : Thumb1pI<oops, iops, am, 2, itin, opc, asm, "", pattern>,
T1LoadStore<0b0101, opcode> {
bits<3> Rt;
bits<8> addr;
@@ -1047,7 +1046,7 @@ class T1pILdStEncode<bits<3> opcode, dag oops, dag iops, AddrMode am,
class T1pILdStEncodeImm<bits<4> opA, bit opB, dag oops, dag iops, AddrMode am,
InstrItinClass itin, string opc, string asm,
list<dag> pattern>
- : Thumb1pI<oops, iops, am, Size2Bytes, itin, opc, asm, "", pattern>,
+ : Thumb1pI<oops, iops, am, 2, itin, opc, asm, "", pattern>,
T1LoadStore<opA, {opB,?,?}> {
bits<3> Rt;
bits<8> addr;
@@ -1063,7 +1062,7 @@ class T1Misc<bits<7> opcode> : Encoding16 {
}
// Thumb2I - Thumb2 instruction. Almost all Thumb2 instructions are predicable.
-class Thumb2I<dag oops, dag iops, AddrMode am, SizeFlagVal sz,
+class Thumb2I<dag oops, dag iops, AddrMode am, int sz,
InstrItinClass itin,
string opc, string asm, string cstr, list<dag> pattern>
: InstARM<am, sz, IndexModeNone, ThumbFrm, GenericDomain, cstr, itin> {
@@ -1080,7 +1079,7 @@ class Thumb2I<dag oops, dag iops, AddrMode am, SizeFlagVal sz,
//
// FIXME: This uses unified syntax so {s} comes before {p}. We should make it
// more consistent.
-class Thumb2sI<dag oops, dag iops, AddrMode am, SizeFlagVal sz,
+class Thumb2sI<dag oops, dag iops, AddrMode am, int sz,
InstrItinClass itin,
string opc, string asm, string cstr, list<dag> pattern>
: InstARM<am, sz, IndexModeNone, ThumbFrm, GenericDomain, cstr, itin> {
@@ -1095,7 +1094,7 @@ class Thumb2sI<dag oops, dag iops, AddrMode am, SizeFlagVal sz,
}
// Special cases
-class Thumb2XI<dag oops, dag iops, AddrMode am, SizeFlagVal sz,
+class Thumb2XI<dag oops, dag iops, AddrMode am, int sz,
InstrItinClass itin,
string asm, string cstr, list<dag> pattern>
: InstARM<am, sz, IndexModeNone, ThumbFrm, GenericDomain, cstr, itin> {
@@ -1106,7 +1105,7 @@ class Thumb2XI<dag oops, dag iops, AddrMode am, SizeFlagVal sz,
list<Predicate> Predicates = [IsThumb2];
}
-class ThumbXI<dag oops, dag iops, AddrMode am, SizeFlagVal sz,
+class ThumbXI<dag oops, dag iops, AddrMode am, int sz,
InstrItinClass itin,
string asm, string cstr, list<dag> pattern>
: InstARM<am, sz, IndexModeNone, ThumbFrm, GenericDomain, cstr, itin> {
@@ -1119,22 +1118,22 @@ class ThumbXI<dag oops, dag iops, AddrMode am, SizeFlagVal sz,
class T2I<dag oops, dag iops, InstrItinClass itin,
string opc, string asm, list<dag> pattern>
- : Thumb2I<oops, iops, AddrModeNone, Size4Bytes, itin, opc, asm, "", pattern>;
+ : Thumb2I<oops, iops, AddrModeNone, 4, itin, opc, asm, "", pattern>;
class T2Ii12<dag oops, dag iops, InstrItinClass itin,
string opc, string asm, list<dag> pattern>
- : Thumb2I<oops, iops, AddrModeT2_i12, Size4Bytes, itin, opc, asm, "",pattern>;
+ : Thumb2I<oops, iops, AddrModeT2_i12, 4, itin, opc, asm, "",pattern>;
class T2Ii8<dag oops, dag iops, InstrItinClass itin,
string opc, string asm, list<dag> pattern>
- : Thumb2I<oops, iops, AddrModeT2_i8, Size4Bytes, itin, opc, asm, "", pattern>;
+ : Thumb2I<oops, iops, AddrModeT2_i8, 4, itin, opc, asm, "", pattern>;
class T2Iso<dag oops, dag iops, InstrItinClass itin,
string opc, string asm, list<dag> pattern>
- : Thumb2I<oops, iops, AddrModeT2_so, Size4Bytes, itin, opc, asm, "", pattern>;
+ : Thumb2I<oops, iops, AddrModeT2_so, 4, itin, opc, asm, "", pattern>;
class T2Ipc<dag oops, dag iops, InstrItinClass itin,
string opc, string asm, list<dag> pattern>
- : Thumb2I<oops, iops, AddrModeT2_pc, Size4Bytes, itin, opc, asm, "", pattern>;
+ : Thumb2I<oops, iops, AddrModeT2_pc, 4, itin, opc, asm, "", pattern>;
class T2Ii8s4<bit P, bit W, bit isLoad, dag oops, dag iops, InstrItinClass itin,
string opc, string asm, list<dag> pattern>
- : Thumb2I<oops, iops, AddrModeT2_i8s4, Size4Bytes, itin, opc, asm, "",
+ : Thumb2I<oops, iops, AddrModeT2_i8s4, 4, itin, opc, asm, "",
pattern> {
bits<4> Rt;
bits<4> Rt2;
@@ -1153,32 +1152,32 @@ class T2Ii8s4<bit P, bit W, bit isLoad, dag oops, dag iops, InstrItinClass itin,
class T2sI<dag oops, dag iops, InstrItinClass itin,
string opc, string asm, list<dag> pattern>
- : Thumb2sI<oops, iops, AddrModeNone, Size4Bytes, itin, opc, asm, "", pattern>;
+ : Thumb2sI<oops, iops, AddrModeNone, 4, itin, opc, asm, "", pattern>;
class T2XI<dag oops, dag iops, InstrItinClass itin,
string asm, list<dag> pattern>
- : Thumb2XI<oops, iops, AddrModeNone, Size4Bytes, itin, asm, "", pattern>;
+ : Thumb2XI<oops, iops, AddrModeNone, 4, itin, asm, "", pattern>;
class T2JTI<dag oops, dag iops, InstrItinClass itin,
string asm, list<dag> pattern>
- : Thumb2XI<oops, iops, AddrModeNone, SizeSpecial, itin, asm, "", pattern>;
+ : Thumb2XI<oops, iops, AddrModeNone, 0, itin, asm, "", pattern>;
// Move to/from coprocessor instructions
-class T2Cop<dag oops, dag iops, string asm, list<dag> pattern>
- : T2XI<oops, iops, NoItinerary, asm, pattern>, Requires<[IsThumb2, HasV6]> {
- let Inst{31-28} = 0b1111;
+class T2Cop<bits<4> opc, dag oops, dag iops, string asm, list<dag> pattern>
+ : T2XI <oops, iops, NoItinerary, asm, pattern>, Requires<[IsThumb2]> {
+ let Inst{31-28} = opc;
}
// Two-address instructions
class T2XIt<dag oops, dag iops, InstrItinClass itin,
string asm, string cstr, list<dag> pattern>
- : Thumb2XI<oops, iops, AddrModeNone, Size4Bytes, itin, asm, cstr, pattern>;
+ : Thumb2XI<oops, iops, AddrModeNone, 4, itin, asm, cstr, pattern>;
// T2Iidxldst - Thumb2 indexed load / store instructions.
class T2Iidxldst<bit signed, bits<2> opcod, bit load, bit pre,
dag oops, dag iops,
AddrMode am, IndexMode im, InstrItinClass itin,
string opc, string asm, string cstr, list<dag> pattern>
- : InstARM<am, Size4Bytes, im, ThumbFrm, GenericDomain, cstr, itin> {
+ : InstARM<am, 4, im, ThumbFrm, GenericDomain, cstr, itin> {
let OutOperandList = oops;
let InOperandList = !con(iops, (ins pred:$p));
let AsmString = !strconcat(opc, "${p}", asm);
@@ -1232,7 +1231,7 @@ class T2Pat<dag pattern, dag result> : Pat<pattern, result> {
//
// Almost all VFP instructions are predicable.
-class VFPI<dag oops, dag iops, AddrMode am, SizeFlagVal sz,
+class VFPI<dag oops, dag iops, AddrMode am, int sz,
IndexMode im, Format f, InstrItinClass itin,
string opc, string asm, string cstr, list<dag> pattern>
: InstARM<am, sz, im, f, VFPDomain, cstr, itin> {
@@ -1247,7 +1246,7 @@ class VFPI<dag oops, dag iops, AddrMode am, SizeFlagVal sz,
}
// Special cases
-class VFPXI<dag oops, dag iops, AddrMode am, SizeFlagVal sz,
+class VFPXI<dag oops, dag iops, AddrMode am, int sz,
IndexMode im, Format f, InstrItinClass itin,
string asm, string cstr, list<dag> pattern>
: InstARM<am, sz, im, f, VFPDomain, cstr, itin> {
@@ -1263,7 +1262,7 @@ class VFPXI<dag oops, dag iops, AddrMode am, SizeFlagVal sz,
class VFPAI<dag oops, dag iops, Format f, InstrItinClass itin,
string opc, string asm, list<dag> pattern>
- : VFPI<oops, iops, AddrModeNone, Size4Bytes, IndexModeNone, f, itin,
+ : VFPI<oops, iops, AddrModeNone, 4, IndexModeNone, f, itin,
opc, asm, "", pattern> {
let PostEncoderMethod = "VFPThumb2PostEncoder";
}
@@ -1272,7 +1271,7 @@ class VFPAI<dag oops, dag iops, Format f, InstrItinClass itin,
class ADI5<bits<4> opcod1, bits<2> opcod2, dag oops, dag iops,
InstrItinClass itin,
string opc, string asm, list<dag> pattern>
- : VFPI<oops, iops, AddrMode5, Size4Bytes, IndexModeNone,
+ : VFPI<oops, iops, AddrMode5, 4, IndexModeNone,
VFPLdStFrm, itin, opc, asm, "", pattern> {
// Instruction operands.
bits<5> Dd;
@@ -1298,7 +1297,7 @@ class ADI5<bits<4> opcod1, bits<2> opcod2, dag oops, dag iops,
class ASI5<bits<4> opcod1, bits<2> opcod2, dag oops, dag iops,
InstrItinClass itin,
string opc, string asm, list<dag> pattern>
- : VFPI<oops, iops, AddrMode5, Size4Bytes, IndexModeNone,
+ : VFPI<oops, iops, AddrMode5, 4, IndexModeNone,
VFPLdStFrm, itin, opc, asm, "", pattern> {
// Instruction operands.
bits<5> Sd;
@@ -1324,7 +1323,7 @@ class ASI5<bits<4> opcod1, bits<2> opcod2, dag oops, dag iops,
// VFP Load / store multiple pseudo instructions.
class PseudoVFPLdStM<dag oops, dag iops, InstrItinClass itin, string cstr,
list<dag> pattern>
- : InstARM<AddrMode4, Size4Bytes, IndexModeNone, Pseudo, VFPNeonDomain,
+ : InstARM<AddrMode4, 4, IndexModeNone, Pseudo, VFPNeonDomain,
cstr, itin> {
let OutOperandList = oops;
let InOperandList = !con(iops, (ins pred:$p));
@@ -1335,7 +1334,7 @@ class PseudoVFPLdStM<dag oops, dag iops, InstrItinClass itin, string cstr,
// Load / store multiple
class AXDI4<dag oops, dag iops, IndexMode im, InstrItinClass itin,
string asm, string cstr, list<dag> pattern>
- : VFPXI<oops, iops, AddrMode4, Size4Bytes, im,
+ : VFPXI<oops, iops, AddrMode4, 4, im,
VFPLdStMulFrm, itin, asm, cstr, pattern> {
// Instruction operands.
bits<4> Rn;
@@ -1355,7 +1354,7 @@ class AXDI4<dag oops, dag iops, IndexMode im, InstrItinClass itin,
class AXSI4<dag oops, dag iops, IndexMode im, InstrItinClass itin,
string asm, string cstr, list<dag> pattern>
- : VFPXI<oops, iops, AddrMode4, Size4Bytes, im,
+ : VFPXI<oops, iops, AddrMode4, 4, im,
VFPLdStMulFrm, itin, asm, cstr, pattern> {
// Instruction operands.
bits<4> Rn;
@@ -1569,7 +1568,7 @@ class AVConv5I<bits<8> opcod1, bits<4> opcod2, dag oops, dag iops,
class NeonI<dag oops, dag iops, AddrMode am, IndexMode im, Format f,
InstrItinClass itin, string opc, string dt, string asm, string cstr,
list<dag> pattern>
- : InstARM<am, Size4Bytes, im, f, NeonDomain, cstr, itin> {
+ : InstARM<am, 4, im, f, NeonDomain, cstr, itin> {
let OutOperandList = oops;
let InOperandList = !con(iops, (ins pred:$p));
let AsmString = !strconcat(opc, "${p}", ".", dt, "\t", asm);
@@ -1581,7 +1580,7 @@ class NeonI<dag oops, dag iops, AddrMode am, IndexMode im, Format f,
class NeonXI<dag oops, dag iops, AddrMode am, IndexMode im, Format f,
InstrItinClass itin, string opc, string asm, string cstr,
list<dag> pattern>
- : InstARM<am, Size4Bytes, im, f, NeonDomain, cstr, itin> {
+ : InstARM<am, 4, im, f, NeonDomain, cstr, itin> {
let OutOperandList = oops;
let InOperandList = !con(iops, (ins pred:$p));
let AsmString = !strconcat(opc, "${p}", "\t", asm);
@@ -1621,7 +1620,7 @@ class NLdStLn<bit op23, bits<2> op21_20, bits<4> op11_8, bits<4> op7_4,
}
class PseudoNLdSt<dag oops, dag iops, InstrItinClass itin, string cstr>
- : InstARM<AddrMode6, Size4Bytes, IndexModeNone, Pseudo, NeonDomain, cstr,
+ : InstARM<AddrMode6, 4, IndexModeNone, Pseudo, NeonDomain, cstr,
itin> {
let OutOperandList = oops;
let InOperandList = !con(iops, (ins pred:$p));
@@ -1630,7 +1629,7 @@ class PseudoNLdSt<dag oops, dag iops, InstrItinClass itin, string cstr>
class PseudoNeonI<dag oops, dag iops, InstrItinClass itin, string cstr,
list<dag> pattern>
- : InstARM<AddrModeNone, Size4Bytes, IndexModeNone, Pseudo, NeonDomain, cstr,
+ : InstARM<AddrModeNone, 4, IndexModeNone, Pseudo, NeonDomain, cstr,
itin> {
let OutOperandList = oops;
let InOperandList = !con(iops, (ins pred:$p));
@@ -1859,7 +1858,7 @@ class N3VX<bit op24, bit op23, bits<2> op21_20, bits<4> op11_8, bit op6,
class NVLaneOp<bits<8> opcod1, bits<4> opcod2, bits<2> opcod3,
dag oops, dag iops, Format f, InstrItinClass itin,
string opc, string dt, string asm, list<dag> pattern>
- : InstARM<AddrModeNone, Size4Bytes, IndexModeNone, f, NeonDomain,
+ : InstARM<AddrModeNone, 4, IndexModeNone, f, NeonDomain,
"", itin> {
let Inst{27-20} = opcod1;
let Inst{11-8} = opcod2;
diff --git a/lib/Target/ARM/ARMInstrInfo.td b/lib/Target/ARM/ARMInstrInfo.td
index ed979e7..a42dd1a 100644
--- a/lib/Target/ARM/ARMInstrInfo.td
+++ b/lib/Target/ARM/ARMInstrInfo.td
@@ -147,35 +147,48 @@ def ARMbfi : SDNode<"ARMISD::BFI", SDT_ARMBFI>;
//===----------------------------------------------------------------------===//
// ARM Instruction Predicate Definitions.
//
-def HasV4T : Predicate<"Subtarget->hasV4TOps()">, AssemblerPredicate;
+def HasV4T : Predicate<"Subtarget->hasV4TOps()">,
+ AssemblerPredicate<"HasV4TOps">;
def NoV4T : Predicate<"!Subtarget->hasV4TOps()">;
def HasV5T : Predicate<"Subtarget->hasV5TOps()">;
-def HasV5TE : Predicate<"Subtarget->hasV5TEOps()">, AssemblerPredicate;
-def HasV6 : Predicate<"Subtarget->hasV6Ops()">, AssemblerPredicate;
+def HasV5TE : Predicate<"Subtarget->hasV5TEOps()">,
+ AssemblerPredicate<"HasV5TEOps">;
+def HasV6 : Predicate<"Subtarget->hasV6Ops()">,
+ AssemblerPredicate<"HasV6Ops">;
def NoV6 : Predicate<"!Subtarget->hasV6Ops()">;
-def HasV6T2 : Predicate<"Subtarget->hasV6T2Ops()">, AssemblerPredicate;
+def HasV6T2 : Predicate<"Subtarget->hasV6T2Ops()">,
+ AssemblerPredicate<"HasV6T2Ops">;
def NoV6T2 : Predicate<"!Subtarget->hasV6T2Ops()">;
-def HasV7 : Predicate<"Subtarget->hasV7Ops()">, AssemblerPredicate;
+def HasV7 : Predicate<"Subtarget->hasV7Ops()">,
+ AssemblerPredicate<"HasV7Ops">;
def NoVFP : Predicate<"!Subtarget->hasVFP2()">;
-def HasVFP2 : Predicate<"Subtarget->hasVFP2()">, AssemblerPredicate;
-def HasVFP3 : Predicate<"Subtarget->hasVFP3()">, AssemblerPredicate;
-def HasNEON : Predicate<"Subtarget->hasNEON()">, AssemblerPredicate;
-def HasFP16 : Predicate<"Subtarget->hasFP16()">, AssemblerPredicate;
-def HasDivide : Predicate<"Subtarget->hasDivide()">, AssemblerPredicate;
+def HasVFP2 : Predicate<"Subtarget->hasVFP2()">,
+ AssemblerPredicate<"FeatureVFP2">;
+def HasVFP3 : Predicate<"Subtarget->hasVFP3()">,
+ AssemblerPredicate<"FeatureVFP3">;
+def HasNEON : Predicate<"Subtarget->hasNEON()">,
+ AssemblerPredicate<"FeatureNEON">;
+def HasFP16 : Predicate<"Subtarget->hasFP16()">,
+ AssemblerPredicate<"FeatureFP16">;
+def HasDivide : Predicate<"Subtarget->hasDivide()">,
+ AssemblerPredicate<"FeatureHWDiv">;
def HasT2ExtractPack : Predicate<"Subtarget->hasT2ExtractPack()">,
- AssemblerPredicate;
+ AssemblerPredicate<"FeatureT2XtPk">;
def HasThumb2DSP : Predicate<"Subtarget->hasThumb2DSP()">,
- AssemblerPredicate;
+ AssemblerPredicate<"FeatureDSPThumb2">;
def HasDB : Predicate<"Subtarget->hasDataBarrier()">,
- AssemblerPredicate;
+ AssemblerPredicate<"FeatureDB">;
def HasMP : Predicate<"Subtarget->hasMPExtension()">,
- AssemblerPredicate;
+ AssemblerPredicate<"FeatureMP">;
def UseNEONForFP : Predicate<"Subtarget->useNEONForSinglePrecisionFP()">;
def DontUseNEONForFP : Predicate<"!Subtarget->useNEONForSinglePrecisionFP()">;
-def IsThumb : Predicate<"Subtarget->isThumb()">, AssemblerPredicate;
+def IsThumb : Predicate<"Subtarget->isThumb()">,
+ AssemblerPredicate<"ModeThumb">;
def IsThumb1Only : Predicate<"Subtarget->isThumb1Only()">;
-def IsThumb2 : Predicate<"Subtarget->isThumb2()">, AssemblerPredicate;
-def IsARM : Predicate<"!Subtarget->isThumb()">, AssemblerPredicate;
+def IsThumb2 : Predicate<"Subtarget->isThumb2()">,
+ AssemblerPredicate<"ModeThumb,FeatureThumb2">;
+def IsARM : Predicate<"!Subtarget->isThumb()">,
+ AssemblerPredicate<"!ModeThumb">;
def IsDarwin : Predicate<"Subtarget->isTargetDarwin()">;
def IsNotDarwin : Predicate<"!Subtarget->isTargetDarwin()">;
@@ -242,11 +255,13 @@ def lo16AllZero : PatLeaf<(i32 imm), [{
return (((uint32_t)N->getZExtValue()) & 0xFFFFUL) == 0;
}], hi16>;
-/// imm0_65535 predicate - True if the 32-bit immediate is in the range
-/// [0.65535].
-def imm0_65535 : ImmLeaf<i32, [{
+/// imm0_65535 - An immediate is in the range [0.65535].
+def Imm0_65535AsmOperand: AsmOperandClass { let Name = "Imm0_65535"; }
+def imm0_65535 : Operand<i32>, ImmLeaf<i32, [{
return Imm >= 0 && Imm < 65536;
-}]>;
+}]> {
+ let ParserMatchClass = Imm0_65535AsmOperand;
+}
class BinOpFrag<dag res> : PatFrag<(ops node:$LHS, node:$RHS), res>;
class UnOpFrag <dag res> : PatFrag<(ops node:$Src), res>;
@@ -299,16 +314,19 @@ def fsub_mlx : PatFrag<(ops node:$lhs, node:$rhs),(fsub node:$lhs, node:$rhs),[{
// FIXME: rename brtarget to t2_brtarget
def brtarget : Operand<OtherVT> {
let EncoderMethod = "getBranchTargetOpValue";
+ let OperandType = "OPERAND_PCREL";
}
// FIXME: get rid of this one?
def uncondbrtarget : Operand<OtherVT> {
let EncoderMethod = "getUnconditionalBranchTargetOpValue";
+ let OperandType = "OPERAND_PCREL";
}
// Branch target for ARM. Handles conditional/unconditional
def br_target : Operand<OtherVT> {
let EncoderMethod = "getARMBranchTargetOpValue";
+ let OperandType = "OPERAND_PCREL";
}
// Call target.
@@ -316,6 +334,7 @@ def br_target : Operand<OtherVT> {
def bltarget : Operand<i32> {
// Encoded the same as branch targets.
let EncoderMethod = "getBranchTargetOpValue";
+ let OperandType = "OPERAND_PCREL";
}
// Call target for ARM. Handles conditional/unconditional
@@ -323,6 +342,7 @@ def bltarget : Operand<i32> {
def bl_target : Operand<i32> {
// Encoded the same as branch targets.
let EncoderMethod = "getARMBranchTargetOpValue";
+ let OperandType = "OPERAND_PCREL";
}
@@ -399,14 +419,20 @@ def shift_imm : Operand<i32> {
let ParserMatchClass = ShifterAsmOperand;
}
+def ShiftedRegAsmOperand : AsmOperandClass {
+ let Name = "ShiftedReg";
+}
+
// shifter_operand operands: so_reg and so_imm.
def so_reg : Operand<i32>, // reg reg imm
ComplexPattern<i32, 3, "SelectShifterOperandReg",
[shl,srl,sra,rotr]> {
let EncoderMethod = "getSORegOpValue";
let PrintMethod = "printSORegOperand";
+ let ParserMatchClass = ShiftedRegAsmOperand;
let MIOperandInfo = (ops GPR, GPR, shift_imm);
}
+// FIXME: Does this need to be distinct from so_reg?
def shift_so_reg : Operand<i32>, // reg reg imm
ComplexPattern<i32, 3, "SelectShiftShifterOperandReg",
[shl,srl,sra,rotr]> {
@@ -421,7 +447,6 @@ def so_imm : Operand<i32>, ImmLeaf<i32, [{
return ARM_AM::getSOImmVal(Imm) != -1;
}]> {
let EncoderMethod = "getSOImmOpValue";
- let PrintMethod = "printSOImmOperand";
}
// Break so_imm's up into two pieces. This handles immediates with up to 16
@@ -439,6 +464,22 @@ def arm_i32imm : PatLeaf<(imm), [{
return ARM_AM::isSOImmTwoPartVal((unsigned)N->getZExtValue());
}]>;
+/// imm0_7 predicate - Immediate in the range [0,31].
+def Imm0_7AsmOperand: AsmOperandClass { let Name = "Imm0_7"; }
+def imm0_7 : Operand<i32>, ImmLeaf<i32, [{
+ return Imm >= 0 && Imm < 8;
+}]> {
+ let ParserMatchClass = Imm0_7AsmOperand;
+}
+
+/// imm0_15 predicate - Immediate in the range [0,31].
+def Imm0_15AsmOperand: AsmOperandClass { let Name = "Imm0_15"; }
+def imm0_15 : Operand<i32>, ImmLeaf<i32, [{
+ return Imm >= 0 && Imm < 16;
+}]> {
+ let ParserMatchClass = Imm0_15AsmOperand;
+}
+
/// imm0_31 predicate - True if the 32-bit immediate is in the range [0,31].
def imm0_31 : Operand<i32>, ImmLeaf<i32, [{
return Imm >= 0 && Imm < 32;
@@ -932,9 +973,9 @@ multiclass AI_exta_rrot_np<bits<8> opcod, string opc> {
}
/// AI1_adde_sube_irs - Define instructions and patterns for adde and sube.
-let Uses = [CPSR] in {
multiclass AI1_adde_sube_irs<bits<4> opcod, string opc, PatFrag opnode,
- bit Commutable = 0> {
+ string baseOpc, bit Commutable = 0> {
+ let Uses = [CPSR] in {
def ri : AsI1<opcod, (outs GPR:$Rd), (ins GPR:$Rn, so_imm:$imm),
DPFrm, IIC_iALUi, opc, "\t$Rd, $Rn, $imm",
[(set GPR:$Rd, (opnode GPR:$Rn, so_imm:$imm))]>,
@@ -973,7 +1014,24 @@ multiclass AI1_adde_sube_irs<bits<4> opcod, string opc, PatFrag opnode,
let Inst{15-12} = Rd;
let Inst{19-16} = Rn;
}
-}
+ }
+ // Assembly aliases for optional destination operand when it's the same
+ // as the source operand.
+ def : InstAlias<!strconcat(opc, "${s}${p} $Rdn, $imm"),
+ (!cast<Instruction>(!strconcat(baseOpc, "ri")) GPR:$Rdn, GPR:$Rdn,
+ so_imm:$imm, pred:$p,
+ cc_out:$s)>,
+ Requires<[IsARM]>;
+ def : InstAlias<!strconcat(opc, "${s}${p} $Rdn, $Rm"),
+ (!cast<Instruction>(!strconcat(baseOpc, "rr")) GPR:$Rdn, GPR:$Rdn,
+ GPR:$Rm, pred:$p,
+ cc_out:$s)>,
+ Requires<[IsARM]>;
+ def : InstAlias<!strconcat(opc, "${s}${p} $Rdn, $shift"),
+ (!cast<Instruction>(!strconcat(baseOpc, "rs")) GPR:$Rdn, GPR:$Rdn,
+ so_reg:$shift, pred:$p,
+ cc_out:$s)>,
+ Requires<[IsARM]>;
}
// Carry setting variants
@@ -981,15 +1039,15 @@ multiclass AI1_adde_sube_irs<bits<4> opcod, string opc, PatFrag opnode,
let usesCustomInserter = 1 in {
multiclass AI1_adde_sube_s_irs<PatFrag opnode, bit Commutable = 0> {
def ri : ARMPseudoInst<(outs GPR:$Rd), (ins GPR:$Rn, so_imm:$imm),
- Size4Bytes, IIC_iALUi,
+ 4, IIC_iALUi,
[(set GPR:$Rd, (opnode GPR:$Rn, so_imm:$imm))]>;
def rr : ARMPseudoInst<(outs GPR:$Rd), (ins GPR:$Rn, GPR:$Rm),
- Size4Bytes, IIC_iALUr,
+ 4, IIC_iALUr,
[(set GPR:$Rd, (opnode GPR:$Rn, GPR:$Rm))]> {
let isCommutable = Commutable;
}
def rs : ARMPseudoInst<(outs GPR:$Rd), (ins GPR:$Rn, so_reg:$shift),
- Size4Bytes, IIC_iALUsr,
+ 4, IIC_iALUsr,
[(set GPR:$Rd, (opnode GPR:$Rn, so_reg:$shift))]>;
}
}
@@ -1139,9 +1197,8 @@ def SEV : AI<(outs), (ins), MiscFrm, NoItinerary, "sev", "",
// The i32imm operand $val can be used by a debugger to store more information
// about the breakpoint.
-def BKPT : AI<(outs), (ins i32imm:$val), MiscFrm, NoItinerary, "bkpt", "\t$val",
- [/* For disassembly only; pattern left blank */]>,
- Requires<[IsARM]> {
+def BKPT : AI<(outs), (ins imm0_65535:$val), MiscFrm, NoItinerary,
+ "bkpt", "\t$val", []>, Requires<[IsARM]> {
bits<16> val;
let Inst{3-0} = val{3-0};
let Inst{19-8} = val{15-4};
@@ -1231,9 +1288,8 @@ def SETEND : AXI<(outs),(ins setend_op:$end), MiscFrm, NoItinerary,
let Inst{8-0} = 0;
}
-def DBG : AI<(outs), (ins i32imm:$opt), MiscFrm, NoItinerary, "dbg", "\t$opt",
- [/* For disassembly only; pattern left blank */]>,
- Requires<[IsARM, HasV7]> {
+def DBG : AI<(outs), (ins imm0_15:$opt), MiscFrm, NoItinerary, "dbg", "\t$opt",
+ []>, Requires<[IsARM, HasV7]> {
bits<4> opt;
let Inst{27-4} = 0b001100100000111100001111;
let Inst{3-0} = opt;
@@ -1250,40 +1306,40 @@ def TRAP : AXI<(outs), (ins), MiscFrm, NoItinerary,
// Address computation and loads and stores in PIC mode.
let isNotDuplicable = 1 in {
def PICADD : ARMPseudoInst<(outs GPR:$dst), (ins GPR:$a, pclabel:$cp, pred:$p),
- Size4Bytes, IIC_iALUr,
+ 4, IIC_iALUr,
[(set GPR:$dst, (ARMpic_add GPR:$a, imm:$cp))]>;
let AddedComplexity = 10 in {
def PICLDR : ARMPseudoInst<(outs GPR:$dst), (ins addrmodepc:$addr, pred:$p),
- Size4Bytes, IIC_iLoad_r,
+ 4, IIC_iLoad_r,
[(set GPR:$dst, (load addrmodepc:$addr))]>;
def PICLDRH : ARMPseudoInst<(outs GPR:$Rt), (ins addrmodepc:$addr, pred:$p),
- Size4Bytes, IIC_iLoad_bh_r,
+ 4, IIC_iLoad_bh_r,
[(set GPR:$Rt, (zextloadi16 addrmodepc:$addr))]>;
def PICLDRB : ARMPseudoInst<(outs GPR:$Rt), (ins addrmodepc:$addr, pred:$p),
- Size4Bytes, IIC_iLoad_bh_r,
+ 4, IIC_iLoad_bh_r,
[(set GPR:$Rt, (zextloadi8 addrmodepc:$addr))]>;
def PICLDRSH : ARMPseudoInst<(outs GPR:$Rt), (ins addrmodepc:$addr, pred:$p),
- Size4Bytes, IIC_iLoad_bh_r,
+ 4, IIC_iLoad_bh_r,
[(set GPR:$Rt, (sextloadi16 addrmodepc:$addr))]>;
def PICLDRSB : ARMPseudoInst<(outs GPR:$Rt), (ins addrmodepc:$addr, pred:$p),
- Size4Bytes, IIC_iLoad_bh_r,
+ 4, IIC_iLoad_bh_r,
[(set GPR:$Rt, (sextloadi8 addrmodepc:$addr))]>;
}
let AddedComplexity = 10 in {
def PICSTR : ARMPseudoInst<(outs), (ins GPR:$src, addrmodepc:$addr, pred:$p),
- Size4Bytes, IIC_iStore_r, [(store GPR:$src, addrmodepc:$addr)]>;
+ 4, IIC_iStore_r, [(store GPR:$src, addrmodepc:$addr)]>;
def PICSTRH : ARMPseudoInst<(outs), (ins GPR:$src, addrmodepc:$addr, pred:$p),
- Size4Bytes, IIC_iStore_bh_r, [(truncstorei16 GPR:$src,
+ 4, IIC_iStore_bh_r, [(truncstorei16 GPR:$src,
addrmodepc:$addr)]>;
def PICSTRB : ARMPseudoInst<(outs), (ins GPR:$src, addrmodepc:$addr, pred:$p),
- Size4Bytes, IIC_iStore_bh_r, [(truncstorei8 GPR:$src, addrmodepc:$addr)]>;
+ 4, IIC_iStore_bh_r, [(truncstorei8 GPR:$src, addrmodepc:$addr)]>;
}
} // isNotDuplicable = 1
@@ -1305,11 +1361,11 @@ def ADR : AI1<{0,?,?,0}, (outs GPR:$Rd), (ins adrlabel:$label),
let Inst{11-0} = label;
}
def LEApcrel : ARMPseudoInst<(outs GPR:$Rd), (ins i32imm:$label, pred:$p),
- Size4Bytes, IIC_iALUi, []>;
+ 4, IIC_iALUi, []>;
def LEApcrelJT : ARMPseudoInst<(outs GPR:$Rd),
(ins i32imm:$label, nohash_imm:$id, pred:$p),
- Size4Bytes, IIC_iALUi, []>;
+ 4, IIC_iALUi, []>;
//===----------------------------------------------------------------------===//
// Control Flow Instructions.
@@ -1342,22 +1398,13 @@ let isBranch = 1, isTerminator = 1, isBarrier = 1, isIndirectBranch = 1 in {
let Inst{3-0} = dst;
}
- // For disassembly only.
- def BX_pred : AXI<(outs), (ins GPR:$dst, pred:$p), BrMiscFrm, IIC_Br,
- "bx$p\t$dst", [/* pattern left blank */]>,
+ def BX_pred : AI<(outs), (ins GPR:$dst), BrMiscFrm, IIC_Br,
+ "bx", "\t$dst", [/* pattern left blank */]>,
Requires<[IsARM, HasV4T]> {
bits<4> dst;
let Inst{27-4} = 0b000100101111111111110001;
let Inst{3-0} = dst;
}
-
- // ARMV4 only
- // FIXME: We would really like to define this as a vanilla ARMPat like:
- // ARMPat<(brind GPR:$dst), (MOVr PC, GPR:$dst)>
- // With that, however, we can't set isBranch, isTerminator, etc..
- def MOVPCRX : ARMPseudoInst<(outs), (ins GPR:$dst),
- Size4Bytes, IIC_Br, [(brind GPR:$dst)]>,
- Requires<[IsARM, NoV4T]>;
}
// All calls clobber the non-callee saved registers. SP is marked as
@@ -1409,12 +1456,12 @@ let isCall = 1,
// ARMv4T
// Note: Restrict $func to the tGPR regclass to prevent it being in LR.
def BX_CALL : ARMPseudoInst<(outs), (ins tGPR:$func, variable_ops),
- Size8Bytes, IIC_Br, [(ARMcall_nolink tGPR:$func)]>,
+ 8, IIC_Br, [(ARMcall_nolink tGPR:$func)]>,
Requires<[IsARM, HasV4T, IsNotDarwin]>;
// ARMv4
def BMOVPCRX_CALL : ARMPseudoInst<(outs), (ins tGPR:$func, variable_ops),
- Size8Bytes, IIC_Br, [(ARMcall_nolink tGPR:$func)]>,
+ 8, IIC_Br, [(ARMcall_nolink tGPR:$func)]>,
Requires<[IsARM, NoV4T, IsNotDarwin]>;
}
@@ -1424,131 +1471,82 @@ let isCall = 1,
// moved above / below calls.
Defs = [R0, R1, R2, R3, R9, R12, LR, QQQQ0, QQQQ2, QQQQ3, CPSR, FPSCR],
Uses = [R7, SP] in {
- def BLr9 : ARMPseudoInst<(outs), (ins bltarget:$func, variable_ops),
- Size4Bytes, IIC_Br,
- [(ARMcall tglobaladdr:$func)]>, Requires<[IsARM, IsDarwin]>;
-
- def BLr9_pred : ARMPseudoInst<(outs),
- (ins bltarget:$func, pred:$p, variable_ops),
- Size4Bytes, IIC_Br,
- [(ARMcall_pred tglobaladdr:$func)]>,
+ def BLr9 : ARMPseudoExpand<(outs), (ins bl_target:$func, variable_ops),
+ 4, IIC_Br,
+ [(ARMcall tglobaladdr:$func)], (BL bl_target:$func)>,
+ Requires<[IsARM, IsDarwin]>;
+
+ def BLr9_pred : ARMPseudoExpand<(outs),
+ (ins bl_target:$func, pred:$p, variable_ops),
+ 4, IIC_Br,
+ [(ARMcall_pred tglobaladdr:$func)],
+ (BL_pred bl_target:$func, pred:$p)>,
Requires<[IsARM, IsDarwin]>;
// ARMv5T and above
- def BLXr9 : ARMPseudoInst<(outs), (ins GPR:$func, variable_ops),
- Size4Bytes, IIC_Br,
- [(ARMcall GPR:$func)]>, Requires<[IsARM, HasV5T, IsDarwin]>;
-
- def BLXr9_pred: ARMPseudoInst<(outs), (ins GPR:$func, pred:$p, variable_ops),
- Size4Bytes, IIC_Br,
- [(ARMcall_pred GPR:$func)]>,
+ def BLXr9 : ARMPseudoExpand<(outs), (ins GPR:$func, variable_ops),
+ 4, IIC_Br,
+ [(ARMcall GPR:$func)],
+ (BLX GPR:$func)>,
+ Requires<[IsARM, HasV5T, IsDarwin]>;
+
+ def BLXr9_pred: ARMPseudoExpand<(outs), (ins GPR:$func, pred:$p,variable_ops),
+ 4, IIC_Br,
+ [(ARMcall_pred GPR:$func)],
+ (BLX_pred GPR:$func, pred:$p)>,
Requires<[IsARM, HasV5T, IsDarwin]>;
// ARMv4T
// Note: Restrict $func to the tGPR regclass to prevent it being in LR.
def BXr9_CALL : ARMPseudoInst<(outs), (ins tGPR:$func, variable_ops),
- Size8Bytes, IIC_Br, [(ARMcall_nolink tGPR:$func)]>,
+ 8, IIC_Br, [(ARMcall_nolink tGPR:$func)]>,
Requires<[IsARM, HasV4T, IsDarwin]>;
// ARMv4
def BMOVPCRXr9_CALL : ARMPseudoInst<(outs), (ins tGPR:$func, variable_ops),
- Size8Bytes, IIC_Br, [(ARMcall_nolink tGPR:$func)]>,
+ 8, IIC_Br, [(ARMcall_nolink tGPR:$func)]>,
Requires<[IsARM, NoV4T, IsDarwin]>;
}
-// Tail calls.
-
-// FIXME: The Thumb versions of these should live in ARMInstrThumb.td
-let isCall = 1, isTerminator = 1, isReturn = 1, isBarrier = 1 in {
- // Darwin versions.
- let Defs = [R0, R1, R2, R3, R9, R12, QQQQ0, QQQQ2, QQQQ3, PC],
- Uses = [SP] in {
- def TCRETURNdi : PseudoInst<(outs), (ins i32imm:$dst, variable_ops),
- IIC_Br, []>, Requires<[IsDarwin]>;
-
- def TCRETURNri : PseudoInst<(outs), (ins tcGPR:$dst, variable_ops),
- IIC_Br, []>, Requires<[IsDarwin]>;
-
- def TAILJMPd : ARMPseudoInst<(outs), (ins brtarget:$dst, variable_ops),
- Size4Bytes, IIC_Br,
- []>, Requires<[IsARM, IsDarwin]>;
-
- def tTAILJMPd: tPseudoInst<(outs), (ins brtarget:$dst, variable_ops),
- Size4Bytes, IIC_Br,
- []>, Requires<[IsThumb, IsDarwin]>;
-
- def TAILJMPr : ARMPseudoInst<(outs), (ins tcGPR:$dst, variable_ops),
- Size4Bytes, IIC_Br,
- []>, Requires<[IsARM, IsDarwin]>;
-
- def tTAILJMPr : tPseudoInst<(outs), (ins tcGPR:$dst, variable_ops),
- Size4Bytes, IIC_Br,
- []>, Requires<[IsThumb, IsDarwin]>;
- }
-
- // Non-Darwin versions (the difference is R9).
- let Defs = [R0, R1, R2, R3, R12, QQQQ0, QQQQ2, QQQQ3, PC],
- Uses = [SP] in {
- def TCRETURNdiND : PseudoInst<(outs), (ins i32imm:$dst, variable_ops),
- IIC_Br, []>, Requires<[IsNotDarwin]>;
-
- def TCRETURNriND : PseudoInst<(outs), (ins tcGPR:$dst, variable_ops),
- IIC_Br, []>, Requires<[IsNotDarwin]>;
-
- def TAILJMPdND : ARMPseudoInst<(outs), (ins brtarget:$dst, variable_ops),
- Size4Bytes, IIC_Br,
- []>, Requires<[IsARM, IsNotDarwin]>;
-
- def tTAILJMPdND : tPseudoInst<(outs), (ins brtarget:$dst, variable_ops),
- Size4Bytes, IIC_Br,
- []>, Requires<[IsThumb, IsNotDarwin]>;
-
- def TAILJMPrND : ARMPseudoInst<(outs), (ins tcGPR:$dst, variable_ops),
- Size4Bytes, IIC_Br,
- []>, Requires<[IsARM, IsNotDarwin]>;
- def tTAILJMPrND : tPseudoInst<(outs), (ins tcGPR:$dst, variable_ops),
- Size4Bytes, IIC_Br,
- []>, Requires<[IsThumb, IsNotDarwin]>;
+let isBranch = 1, isTerminator = 1 in {
+ // FIXME: should be able to write a pattern for ARMBrcond, but can't use
+ // a two-value operand where a dag node expects two operands. :(
+ def Bcc : ABI<0b1010, (outs), (ins br_target:$target),
+ IIC_Br, "b", "\t$target",
+ [/*(ARMbrcond bb:$target, imm:$cc, CCR:$ccr)*/]> {
+ bits<24> target;
+ let Inst{23-0} = target;
}
-}
-let isBranch = 1, isTerminator = 1 in {
- // B is "predicable" since it's just a Bcc with an 'always' condition.
let isBarrier = 1 in {
+ // B is "predicable" since it's just a Bcc with an 'always' condition.
let isPredicable = 1 in
// FIXME: We shouldn't need this pseudo at all. Just using Bcc directly
// should be sufficient.
- def B : ARMPseudoInst<(outs), (ins brtarget:$target), Size4Bytes, IIC_Br,
- [(br bb:$target)]>;
+ // FIXME: Is B really a Barrier? That doesn't seem right.
+ def B : ARMPseudoExpand<(outs), (ins br_target:$target), 4, IIC_Br,
+ [(br bb:$target)], (Bcc br_target:$target, (ops 14, zero_reg))>;
let isNotDuplicable = 1, isIndirectBranch = 1 in {
def BR_JTr : ARMPseudoInst<(outs),
(ins GPR:$target, i32imm:$jt, i32imm:$id),
- SizeSpecial, IIC_Br,
+ 0, IIC_Br,
[(ARMbrjt GPR:$target, tjumptable:$jt, imm:$id)]>;
// FIXME: This shouldn't use the generic "addrmode2," but rather be split
// into i12 and rs suffixed versions.
def BR_JTm : ARMPseudoInst<(outs),
(ins addrmode2:$target, i32imm:$jt, i32imm:$id),
- SizeSpecial, IIC_Br,
+ 0, IIC_Br,
[(ARMbrjt (i32 (load addrmode2:$target)), tjumptable:$jt,
imm:$id)]>;
def BR_JTadd : ARMPseudoInst<(outs),
(ins GPR:$target, GPR:$idx, i32imm:$jt, i32imm:$id),
- SizeSpecial, IIC_Br,
+ 0, IIC_Br,
[(ARMbrjt (add GPR:$target, GPR:$idx), tjumptable:$jt,
imm:$id)]>;
} // isNotDuplicable = 1, isIndirectBranch = 1
} // isBarrier = 1
- // FIXME: should be able to write a pattern for ARMBrcond, but can't use
- // a two-value operand where a dag node expects two operands. :(
- def Bcc : ABI<0b1010, (outs), (ins br_target:$target),
- IIC_Br, "b", "\t$target",
- [/*(ARMbrcond bb:$target, imm:$cc, CCR:$ccr)*/]> {
- bits<24> target;
- let Inst{23-0} = target;
- }
}
// BLX (immediate) -- for disassembly only
@@ -1561,14 +1559,65 @@ def BLXi : AXI<(outs), (ins br_target:$target), BrMiscFrm, NoItinerary,
let Inst{24} = target{0};
}
-// Branch and Exchange Jazelle -- for disassembly only
+// Branch and Exchange Jazelle
def BXJ : ABI<0b0001, (outs), (ins GPR:$func), NoItinerary, "bxj", "\t$func",
- [/* For disassembly only; pattern left blank */]> {
+ [/* pattern left blank */]> {
+ bits<4> func;
let Inst{23-20} = 0b0010;
- //let Inst{19-8} = 0xfff;
+ let Inst{19-8} = 0xfff;
let Inst{7-4} = 0b0010;
+ let Inst{3-0} = func;
+}
+
+// Tail calls.
+
+let isCall = 1, isTerminator = 1, isReturn = 1, isBarrier = 1 in {
+ // Darwin versions.
+ let Defs = [R0, R1, R2, R3, R9, R12, QQQQ0, QQQQ2, QQQQ3, PC],
+ Uses = [SP] in {
+ def TCRETURNdi : PseudoInst<(outs), (ins i32imm:$dst, variable_ops),
+ IIC_Br, []>, Requires<[IsDarwin]>;
+
+ def TCRETURNri : PseudoInst<(outs), (ins tcGPR:$dst, variable_ops),
+ IIC_Br, []>, Requires<[IsDarwin]>;
+
+ def TAILJMPd : ARMPseudoExpand<(outs), (ins br_target:$dst, variable_ops),
+ 4, IIC_Br, [],
+ (Bcc br_target:$dst, (ops 14, zero_reg))>,
+ Requires<[IsARM, IsDarwin]>;
+
+ def TAILJMPr : ARMPseudoExpand<(outs), (ins tcGPR:$dst, variable_ops),
+ 4, IIC_Br, [],
+ (BX GPR:$dst)>,
+ Requires<[IsARM, IsDarwin]>;
+
+ }
+
+ // Non-Darwin versions (the difference is R9).
+ let Defs = [R0, R1, R2, R3, R12, QQQQ0, QQQQ2, QQQQ3, PC],
+ Uses = [SP] in {
+ def TCRETURNdiND : PseudoInst<(outs), (ins i32imm:$dst, variable_ops),
+ IIC_Br, []>, Requires<[IsNotDarwin]>;
+
+ def TCRETURNriND : PseudoInst<(outs), (ins tcGPR:$dst, variable_ops),
+ IIC_Br, []>, Requires<[IsNotDarwin]>;
+
+ def TAILJMPdND : ARMPseudoExpand<(outs), (ins brtarget:$dst, variable_ops),
+ 4, IIC_Br, [],
+ (Bcc br_target:$dst, (ops 14, zero_reg))>,
+ Requires<[IsARM, IsNotDarwin]>;
+
+ def TAILJMPrND : ARMPseudoExpand<(outs), (ins tcGPR:$dst, variable_ops),
+ 4, IIC_Br, [],
+ (BX GPR:$dst)>,
+ Requires<[IsARM, IsNotDarwin]>;
+ }
}
+
+
+
+
// Secure Monitor Call is a system instruction -- for disassembly only
def SMC : ABI<0b0001, (outs), (ins i32imm:$opt), NoItinerary, "smc", "\t$opt",
[/* For disassembly only; pattern left blank */]> {
@@ -1585,7 +1634,6 @@ def SVC : ABI<0b1111, (outs), (ins i32imm:$svc), IIC_Br, "svc", "\t$svc",
let Inst{23-0} = svc;
}
}
-def : MnemonicAlias<"swi", "svc">;
// Store Return State is a system instruction -- for disassembly only
let isCodeGenOnly = 1 in { // FIXME: This should not use submode!
@@ -1931,10 +1979,12 @@ def STRHT: AI3sthpo<(outs GPR:$base_wb), (ins GPR:$Rt, addrmode3:$addr),
multiclass arm_ldst_mult<string asm, bit L_bit, Format f,
InstrItinClass itin, InstrItinClass itin_upd> {
+ // IA is the default, so no need for an explicit suffix on the
+ // mnemonic here. Without it is the cannonical spelling.
def IA :
AXI4<(outs), (ins GPR:$Rn, pred:$p, reglist:$regs, variable_ops),
IndexModeNone, f, itin,
- !strconcat(asm, "ia${p}\t$Rn, $regs"), "", []> {
+ !strconcat(asm, "${p}\t$Rn, $regs"), "", []> {
let Inst{24-23} = 0b01; // Increment After
let Inst{21} = 0; // No writeback
let Inst{20} = L_bit;
@@ -1942,7 +1992,7 @@ multiclass arm_ldst_mult<string asm, bit L_bit, Format f,
def IA_UPD :
AXI4<(outs GPR:$wb), (ins GPR:$Rn, pred:$p, reglist:$regs, variable_ops),
IndexModeUpd, f, itin_upd,
- !strconcat(asm, "ia${p}\t$Rn!, $regs"), "$Rn = $wb", []> {
+ !strconcat(asm, "${p}\t$Rn!, $regs"), "$Rn = $wb", []> {
let Inst{24-23} = 0b01; // Increment After
let Inst{21} = 1; // Writeback
let Inst{20} = L_bit;
@@ -2007,19 +2057,14 @@ defm STM : arm_ldst_mult<"stm", 0, LdStMulFrm, IIC_iStore_m, IIC_iStore_mu>;
} // neverHasSideEffects
-// Load / Store Multiple Mnemonic Aliases
-def : MnemonicAlias<"ldmfd", "ldmia">;
-def : MnemonicAlias<"stmfd", "stmdb">;
-def : MnemonicAlias<"ldm", "ldmia">;
-def : MnemonicAlias<"stm", "stmia">;
-
// FIXME: remove when we have a way to marking a MI with these properties.
// FIXME: Should pc be an implicit operand like PICADD, etc?
let isReturn = 1, isTerminator = 1, isBarrier = 1, mayLoad = 1,
hasExtraDefRegAllocReq = 1, isCodeGenOnly = 1 in
-def LDMIA_RET : ARMPseudoInst<(outs GPR:$wb), (ins GPR:$Rn, pred:$p,
- reglist:$regs, variable_ops),
- Size4Bytes, IIC_iLoad_mBr, []>,
+def LDMIA_RET : ARMPseudoExpand<(outs GPR:$wb), (ins GPR:$Rn, pred:$p,
+ reglist:$regs, variable_ops),
+ 4, IIC_iLoad_mBr, [],
+ (LDMIA_UPD GPR:$wb, GPR:$Rn, pred:$p, reglist:$regs)>,
RegConstraint<"$Rn = $wb">;
//===----------------------------------------------------------------------===//
@@ -2189,7 +2234,7 @@ defm UXTAB16 : AI_exta_rrot_np<0b01101100, "uxtab16">;
def SBFX : I<(outs GPR:$Rd),
(ins GPR:$Rn, imm0_31:$lsb, imm0_31_m1:$width),
- AddrMode1, Size4Bytes, IndexModeNone, DPFrm, IIC_iUNAsi,
+ AddrMode1, 4, IndexModeNone, DPFrm, IIC_iUNAsi,
"sbfx", "\t$Rd, $Rn, $lsb, $width", "", []>,
Requires<[IsARM, HasV6T2]> {
bits<4> Rd;
@@ -2206,7 +2251,7 @@ def SBFX : I<(outs GPR:$Rd),
def UBFX : I<(outs GPR:$Rd),
(ins GPR:$Rn, imm0_31:$lsb, imm0_31_m1:$width),
- AddrMode1, Size4Bytes, IndexModeNone, DPFrm, IIC_iUNAsi,
+ AddrMode1, 4, IndexModeNone, DPFrm, IIC_iUNAsi,
"ubfx", "\t$Rd, $Rn, $lsb, $width", "", []>,
Requires<[IsARM, HasV6T2]> {
bits<4> Rd;
@@ -2241,9 +2286,11 @@ defm SUBS : AI1_bin_s_irs<0b0010, "subs",
BinOpFrag<(subc node:$LHS, node:$RHS)>>;
defm ADC : AI1_adde_sube_irs<0b0101, "adc",
- BinOpFrag<(adde_dead_carry node:$LHS, node:$RHS)>, 1>;
+ BinOpFrag<(adde_dead_carry node:$LHS, node:$RHS)>,
+ "ADC", 1>;
defm SBC : AI1_adde_sube_irs<0b0110, "sbc",
- BinOpFrag<(sube_dead_carry node:$LHS, node:$RHS)>>;
+ BinOpFrag<(sube_dead_carry node:$LHS, node:$RHS)>,
+ "SBC">;
// ADC and SUBC with 's' bit set.
let usesCustomInserter = 1 in {
@@ -2296,13 +2343,13 @@ def RSBrs : AsI1<0b0011, (outs GPR:$Rd), (ins GPR:$Rn, so_reg:$shift),
// NOTE: CPSR def omitted because it will be handled by the custom inserter.
let usesCustomInserter = 1 in {
def RSBSri : ARMPseudoInst<(outs GPR:$Rd), (ins GPR:$Rn, so_imm:$imm),
- Size4Bytes, IIC_iALUi,
+ 4, IIC_iALUi,
[(set GPR:$Rd, (subc so_imm:$imm, GPR:$Rn))]>;
def RSBSrr : ARMPseudoInst<(outs GPR:$Rd), (ins GPR:$Rn, GPR:$Rm),
- Size4Bytes, IIC_iALUr,
+ 4, IIC_iALUr,
[/* For disassembly only; pattern left blank */]>;
def RSBSrs : ARMPseudoInst<(outs GPR:$Rd), (ins GPR:$Rn, so_reg:$shift),
- Size4Bytes, IIC_iALUsr,
+ 4, IIC_iALUsr,
[(set GPR:$Rd, (subc so_reg:$shift, GPR:$Rn))]>;
}
@@ -2350,10 +2397,10 @@ def RSCrs : AsI1<0b0111, (outs GPR:$Rd), (ins GPR:$Rn, so_reg:$shift),
// NOTE: CPSR def omitted because it will be handled by the custom inserter.
let usesCustomInserter = 1, Uses = [CPSR] in {
def RSCSri : ARMPseudoInst<(outs GPR:$Rd), (ins GPR:$Rn, so_imm:$imm),
- Size4Bytes, IIC_iALUi,
+ 4, IIC_iALUi,
[(set GPR:$Rd, (sube_dead_carry so_imm:$imm, GPR:$Rn))]>;
def RSCSrs : ARMPseudoInst<(outs GPR:$Rd), (ins GPR:$Rn, so_reg:$shift),
- Size4Bytes, IIC_iALUsr,
+ 4, IIC_iALUsr,
[(set GPR:$Rd, (sube_dead_carry so_reg:$shift, GPR:$Rn))]>;
}
@@ -2565,7 +2612,7 @@ defm BIC : AsI1_bin_irs<0b1110, "bic",
BinOpFrag<(and node:$LHS, (not node:$RHS))>, "BIC">;
def BFC : I<(outs GPR:$Rd), (ins GPR:$src, bf_inv_mask_imm:$imm),
- AddrMode1, Size4Bytes, IndexModeNone, DPFrm, IIC_iUNAsi,
+ AddrMode1, 4, IndexModeNone, DPFrm, IIC_iUNAsi,
"bfc", "\t$Rd, $imm", "$src = $Rd",
[(set GPR:$Rd, (and GPR:$src, bf_inv_mask_imm:$imm))]>,
Requires<[IsARM, HasV6T2]> {
@@ -2580,7 +2627,7 @@ def BFC : I<(outs GPR:$Rd), (ins GPR:$src, bf_inv_mask_imm:$imm),
// A8.6.18 BFI - Bitfield insert (Encoding A1)
def BFI : I<(outs GPR:$Rd), (ins GPR:$src, GPR:$Rn, bf_inv_mask_imm:$imm),
- AddrMode1, Size4Bytes, IndexModeNone, DPFrm, IIC_iUNAsi,
+ AddrMode1, 4, IndexModeNone, DPFrm, IIC_iUNAsi,
"bfi", "\t$Rd, $Rn, $imm", "$src = $Rd",
[(set GPR:$Rd, (ARMbfi GPR:$src, GPR:$Rn,
bf_inv_mask_imm:$imm))]>,
@@ -2600,7 +2647,7 @@ def BFI : I<(outs GPR:$Rd), (ins GPR:$src, GPR:$Rn, bf_inv_mask_imm:$imm),
let isAsmParserOnly = 1 in
def BFI4p : I<(outs GPR:$Rd), (ins GPR:$src, GPR:$Rn,
lsb_pos_imm:$lsb, width_imm:$width),
- AddrMode1, Size4Bytes, IndexModeNone, DPFrm, IIC_iUNAsi,
+ AddrMode1, 4, IndexModeNone, DPFrm, IIC_iUNAsi,
"bfi", "\t$Rd, $Rn, $lsb, $width", "$src = $Rd",
[]>, Requires<[IsARM, HasV6T2]> {
bits<4> Rd;
@@ -2677,31 +2724,26 @@ class AsMul1I64<bits<7> opcod, dag oops, dag iops, InstrItinClass itin,
let Inst{3-0} = Rn;
}
+// FIXME: The v5 pseudos are only necessary for the additional Constraint
+// property. Remove them when it's possible to add those properties
+// on an individual MachineInstr, not just an instuction description.
let isCommutable = 1 in {
-let Constraints = "@earlyclobber $Rd" in
-def MULv5: ARMPseudoInst<(outs GPR:$Rd), (ins GPR:$Rn, GPR:$Rm,
- pred:$p, cc_out:$s),
- Size4Bytes, IIC_iMUL32,
- [(set GPR:$Rd, (mul GPR:$Rn, GPR:$Rm))]>,
- Requires<[IsARM, NoV6]>;
-
def MUL : AsMul1I32<0b0000000, (outs GPR:$Rd), (ins GPR:$Rn, GPR:$Rm),
IIC_iMUL32, "mul", "\t$Rd, $Rn, $Rm",
[(set GPR:$Rd, (mul GPR:$Rn, GPR:$Rm))]>,
Requires<[IsARM, HasV6]> {
let Inst{15-12} = 0b0000;
}
-}
let Constraints = "@earlyclobber $Rd" in
-def MLAv5: ARMPseudoInst<(outs GPR:$Rd),
- (ins GPR:$Rn, GPR:$Rm, GPR:$Ra, pred:$p, cc_out:$s),
- Size4Bytes, IIC_iMAC32,
- [(set GPR:$Rd, (add (mul GPR:$Rn, GPR:$Rm), GPR:$Ra))]>,
- Requires<[IsARM, NoV6]> {
- bits<4> Ra;
- let Inst{15-12} = Ra;
+def MULv5: ARMPseudoExpand<(outs GPR:$Rd), (ins GPR:$Rn, GPR:$Rm,
+ pred:$p, cc_out:$s),
+ 4, IIC_iMUL32,
+ [(set GPR:$Rd, (mul GPR:$Rn, GPR:$Rm))],
+ (MUL GPR:$Rd, GPR:$Rn, GPR:$Rm, pred:$p, cc_out:$s)>,
+ Requires<[IsARM, NoV6]>;
}
+
def MLA : AsMul1I32<0b0000001, (outs GPR:$Rd), (ins GPR:$Rn, GPR:$Rm, GPR:$Ra),
IIC_iMAC32, "mla", "\t$Rd, $Rn, $Rm, $Ra",
[(set GPR:$Rd, (add (mul GPR:$Rn, GPR:$Rm), GPR:$Ra))]>,
@@ -2710,6 +2752,14 @@ def MLA : AsMul1I32<0b0000001, (outs GPR:$Rd), (ins GPR:$Rn, GPR:$Rm, GPR:$Ra),
let Inst{15-12} = Ra;
}
+let Constraints = "@earlyclobber $Rd" in
+def MLAv5: ARMPseudoExpand<(outs GPR:$Rd),
+ (ins GPR:$Rn, GPR:$Rm, GPR:$Ra, pred:$p, cc_out:$s),
+ 4, IIC_iMAC32,
+ [(set GPR:$Rd, (add (mul GPR:$Rn, GPR:$Rm), GPR:$Ra))],
+ (MLA GPR:$Rd, GPR:$Rn, GPR:$Rm, GPR:$Ra, pred:$p, cc_out:$s)>,
+ Requires<[IsARM, NoV6]>;
+
def MLS : AMul1I<0b0000011, (outs GPR:$Rd), (ins GPR:$Rn, GPR:$Rm, GPR:$Ra),
IIC_iMAC32, "mls", "\t$Rd, $Rn, $Rm, $Ra",
[(set GPR:$Rd, (sub GPR:$Ra, (mul GPR:$Rn, GPR:$Rm)))]>,
@@ -2725,49 +2775,34 @@ def MLS : AMul1I<0b0000011, (outs GPR:$Rd), (ins GPR:$Rn, GPR:$Rm, GPR:$Ra),
}
// Extra precision multiplies with low / high results
-
let neverHasSideEffects = 1 in {
let isCommutable = 1 in {
-let Constraints = "@earlyclobber $RdLo,@earlyclobber $RdHi" in {
-def SMULLv5 : ARMPseudoInst<(outs GPR:$RdLo, GPR:$RdHi),
- (ins GPR:$Rn, GPR:$Rm, pred:$p, cc_out:$s),
- Size4Bytes, IIC_iMUL64, []>,
- Requires<[IsARM, NoV6]>;
-
-def UMULLv5 : ARMPseudoInst<(outs GPR:$RdLo, GPR:$RdHi),
- (ins GPR:$Rn, GPR:$Rm, pred:$p, cc_out:$s),
- Size4Bytes, IIC_iMUL64, []>,
- Requires<[IsARM, NoV6]>;
-}
-
def SMULL : AsMul1I64<0b0000110, (outs GPR:$RdLo, GPR:$RdHi),
- (ins GPR:$Rn, GPR:$Rm), IIC_iMUL64,
+ (ins GPR:$Rn, GPR:$Rm), IIC_iMUL64,
"smull", "\t$RdLo, $RdHi, $Rn, $Rm", []>,
Requires<[IsARM, HasV6]>;
def UMULL : AsMul1I64<0b0000100, (outs GPR:$RdLo, GPR:$RdHi),
- (ins GPR:$Rn, GPR:$Rm), IIC_iMUL64,
+ (ins GPR:$Rn, GPR:$Rm), IIC_iMUL64,
"umull", "\t$RdLo, $RdHi, $Rn, $Rm", []>,
Requires<[IsARM, HasV6]>;
-}
-// Multiply + accumulate
let Constraints = "@earlyclobber $RdLo,@earlyclobber $RdHi" in {
-def SMLALv5 : ARMPseudoInst<(outs GPR:$RdLo, GPR:$RdHi),
- (ins GPR:$Rn, GPR:$Rm, pred:$p, cc_out:$s),
- Size4Bytes, IIC_iMAC64, []>,
- Requires<[IsARM, NoV6]>;
-def UMLALv5 : ARMPseudoInst<(outs GPR:$RdLo, GPR:$RdHi),
+def SMULLv5 : ARMPseudoExpand<(outs GPR:$RdLo, GPR:$RdHi),
(ins GPR:$Rn, GPR:$Rm, pred:$p, cc_out:$s),
- Size4Bytes, IIC_iMAC64, []>,
+ 4, IIC_iMUL64, [],
+ (SMULL GPR:$RdLo, GPR:$RdHi, GPR:$Rn, GPR:$Rm, pred:$p, cc_out:$s)>,
Requires<[IsARM, NoV6]>;
-def UMAALv5 : ARMPseudoInst<(outs GPR:$RdLo, GPR:$RdHi),
+
+def UMULLv5 : ARMPseudoExpand<(outs GPR:$RdLo, GPR:$RdHi),
(ins GPR:$Rn, GPR:$Rm, pred:$p, cc_out:$s),
- Size4Bytes, IIC_iMAC64, []>,
+ 4, IIC_iMUL64, [],
+ (UMULL GPR:$RdLo, GPR:$RdHi, GPR:$Rn, GPR:$Rm, pred:$p, cc_out:$s)>,
Requires<[IsARM, NoV6]>;
-
+}
}
+// Multiply + accumulate
def SMLAL : AsMul1I64<0b0000111, (outs GPR:$RdLo, GPR:$RdHi),
(ins GPR:$Rn, GPR:$Rm), IIC_iMAC64,
"smlal", "\t$RdLo, $RdHi, $Rn, $Rm", []>,
@@ -2790,6 +2825,25 @@ def UMAAL : AMul1I <0b0000010, (outs GPR:$RdLo, GPR:$RdHi),
let Inst{11-8} = Rm;
let Inst{3-0} = Rn;
}
+
+let Constraints = "@earlyclobber $RdLo,@earlyclobber $RdHi" in {
+def SMLALv5 : ARMPseudoExpand<(outs GPR:$RdLo, GPR:$RdHi),
+ (ins GPR:$Rn, GPR:$Rm, pred:$p, cc_out:$s),
+ 4, IIC_iMAC64, [],
+ (SMLAL GPR:$RdLo, GPR:$RdHi, GPR:$Rn, GPR:$Rm, pred:$p, cc_out:$s)>,
+ Requires<[IsARM, NoV6]>;
+def UMLALv5 : ARMPseudoExpand<(outs GPR:$RdLo, GPR:$RdHi),
+ (ins GPR:$Rn, GPR:$Rm, pred:$p, cc_out:$s),
+ 4, IIC_iMAC64, [],
+ (UMLAL GPR:$RdLo, GPR:$RdHi, GPR:$Rn, GPR:$Rm, pred:$p, cc_out:$s)>,
+ Requires<[IsARM, NoV6]>;
+def UMAALv5 : ARMPseudoExpand<(outs GPR:$RdLo, GPR:$RdHi),
+ (ins GPR:$Rn, GPR:$Rm, pred:$p),
+ 4, IIC_iMAC64, [],
+ (UMAAL GPR:$RdLo, GPR:$RdHi, GPR:$Rn, GPR:$Rm, pred:$p)>,
+ Requires<[IsARM, NoV6]>;
+}
+
} // neverHasSideEffects
// Most significant word multiply
@@ -3193,26 +3247,26 @@ def BCCZi64 : PseudoInst<(outs),
// a two-value operand where a dag node expects two operands. :(
let neverHasSideEffects = 1 in {
def MOVCCr : ARMPseudoInst<(outs GPR:$Rd), (ins GPR:$false, GPR:$Rm, pred:$p),
- Size4Bytes, IIC_iCMOVr,
+ 4, IIC_iCMOVr,
[/*(set GPR:$Rd, (ARMcmov GPR:$false, GPR:$Rm, imm:$cc, CCR:$ccr))*/]>,
RegConstraint<"$false = $Rd">;
def MOVCCs : ARMPseudoInst<(outs GPR:$Rd),
(ins GPR:$false, so_reg:$shift, pred:$p),
- Size4Bytes, IIC_iCMOVsr,
+ 4, IIC_iCMOVsr,
[/*(set GPR:$Rd, (ARMcmov GPR:$false, so_reg:$shift, imm:$cc, CCR:$ccr))*/]>,
RegConstraint<"$false = $Rd">;
let isMoveImm = 1 in
def MOVCCi16 : ARMPseudoInst<(outs GPR:$Rd),
(ins GPR:$false, i32imm_hilo16:$imm, pred:$p),
- Size4Bytes, IIC_iMOVi,
+ 4, IIC_iMOVi,
[]>,
RegConstraint<"$false = $Rd">, Requires<[IsARM, HasV6T2]>;
let isMoveImm = 1 in
def MOVCCi : ARMPseudoInst<(outs GPR:$Rd),
(ins GPR:$false, so_imm:$imm, pred:$p),
- Size4Bytes, IIC_iCMOVi,
+ 4, IIC_iCMOVi,
[/*(set GPR:$Rd, (ARMcmov GPR:$false, so_imm:$imm, imm:$cc, CCR:$ccr))*/]>,
RegConstraint<"$false = $Rd">;
@@ -3220,12 +3274,12 @@ def MOVCCi : ARMPseudoInst<(outs GPR:$Rd),
let isMoveImm = 1 in
def MOVCCi32imm : ARMPseudoInst<(outs GPR:$Rd),
(ins GPR:$false, i32imm:$src, pred:$p),
- Size8Bytes, IIC_iCMOVix2, []>, RegConstraint<"$false = $Rd">;
+ 8, IIC_iCMOVix2, []>, RegConstraint<"$false = $Rd">;
let isMoveImm = 1 in
def MVNCCi : ARMPseudoInst<(outs GPR:$Rd),
(ins GPR:$false, so_imm:$imm, pred:$p),
- Size4Bytes, IIC_iCMOVi,
+ 4, IIC_iCMOVi,
[/*(set GPR:$Rd, (ARMcmov GPR:$false, so_imm_not:$imm, imm:$cc, CCR:$ccr))*/]>,
RegConstraint<"$false = $Rd">;
} // neverHasSideEffects
@@ -3251,19 +3305,20 @@ def DMB : AInoP<(outs), (ins memb_opt:$opt), MiscFrm, NoItinerary,
}
def DSB : AInoP<(outs), (ins memb_opt:$opt), MiscFrm, NoItinerary,
- "dsb", "\t$opt",
- [/* For disassembly only; pattern left blank */]>,
+ "dsb", "\t$opt", []>,
Requires<[IsARM, HasDB]> {
bits<4> opt;
let Inst{31-4} = 0xf57ff04;
let Inst{3-0} = opt;
}
-// ISB has only full system option -- for disassembly only
-def ISB : AInoP<(outs), (ins), MiscFrm, NoItinerary, "isb", "", []>,
+// ISB has only full system option
+def ISB : AInoP<(outs), (ins memb_opt:$opt), MiscFrm, NoItinerary,
+ "isb", "\t$opt", []>,
Requires<[IsARM, HasDB]> {
+ bits<4> opt;
let Inst{31-4} = 0xf57ff06;
- let Inst{3-0} = 0b1111;
+ let Inst{3-0} = opt;
}
let usesCustomInserter = 1 in {
@@ -3426,8 +3481,8 @@ def SWPB : AIswp<1, (outs GPR:$Rt), (ins GPR:$Rt2, GPR:$Rn), "swpb",
// Coprocessor Instructions.
//
-def CDP : ABI<0b1110, (outs), (ins p_imm:$cop, i32imm:$opc1,
- c_imm:$CRd, c_imm:$CRn, c_imm:$CRm, i32imm:$opc2),
+def CDP : ABI<0b1110, (outs), (ins p_imm:$cop, imm0_15:$opc1,
+ c_imm:$CRd, c_imm:$CRn, c_imm:$CRm, imm0_7:$opc2),
NoItinerary, "cdp", "\t$cop, $opc1, $CRd, $CRn, $CRm, $opc2",
[(int_arm_cdp imm:$cop, imm:$opc1, imm:$CRd, imm:$CRn,
imm:$CRm, imm:$opc2)]> {
@@ -3447,8 +3502,8 @@ def CDP : ABI<0b1110, (outs), (ins p_imm:$cop, i32imm:$opc1,
let Inst{23-20} = opc1;
}
-def CDP2 : ABXI<0b1110, (outs), (ins p_imm:$cop, i32imm:$opc1,
- c_imm:$CRd, c_imm:$CRn, c_imm:$CRm, i32imm:$opc2),
+def CDP2 : ABXI<0b1110, (outs), (ins p_imm:$cop, imm0_15:$opc1,
+ c_imm:$CRd, c_imm:$CRn, c_imm:$CRm, imm0_7:$opc2),
NoItinerary, "cdp2\t$cop, $opc1, $CRd, $CRn, $CRm, $opc2",
[(int_arm_cdp2 imm:$cop, imm:$opc1, imm:$CRd, imm:$CRn,
imm:$CRm, imm:$opc2)]> {
@@ -3471,7 +3526,7 @@ def CDP2 : ABXI<0b1110, (outs), (ins p_imm:$cop, i32imm:$opc1,
class ACI<dag oops, dag iops, string opc, string asm,
IndexMode im = IndexModeNone>
- : InoP<oops, iops, AddrModeNone, Size4Bytes, im, BrFrm, NoItinerary,
+ : InoP<oops, iops, AddrModeNone, 4, im, BrFrm, NoItinerary,
opc, asm, "", [/* For disassembly only; pattern left blank */]> {
let Inst{27-25} = 0b110;
}
@@ -3599,8 +3654,8 @@ class MovRCopro<string opc, bit direction, dag oops, dag iops,
def MCR : MovRCopro<"mcr", 0 /* from ARM core register to coprocessor */,
(outs),
- (ins p_imm:$cop, i32imm:$opc1, GPR:$Rt, c_imm:$CRn,
- c_imm:$CRm, i32imm:$opc2),
+ (ins p_imm:$cop, imm0_7:$opc1, GPR:$Rt, c_imm:$CRn,
+ c_imm:$CRm, imm0_7:$opc2),
[(int_arm_mcr imm:$cop, imm:$opc1, GPR:$Rt, imm:$CRn,
imm:$CRm, imm:$opc2)]>;
def MRC : MovRCopro<"mrc", 1 /* from coprocessor to ARM core register */,
@@ -3636,8 +3691,8 @@ class MovRCopro2<string opc, bit direction, dag oops, dag iops,
def MCR2 : MovRCopro2<"mcr2", 0 /* from ARM core register to coprocessor */,
(outs),
- (ins p_imm:$cop, i32imm:$opc1, GPR:$Rt, c_imm:$CRn,
- c_imm:$CRm, i32imm:$opc2),
+ (ins p_imm:$cop, imm0_7:$opc1, GPR:$Rt, c_imm:$CRn,
+ c_imm:$CRm, imm0_7:$opc2),
[(int_arm_mcr2 imm:$cop, imm:$opc1, GPR:$Rt, imm:$CRn,
imm:$CRm, imm:$opc2)]>;
def MRC2 : MovRCopro2<"mrc2", 1 /* from coprocessor to ARM core register */,
@@ -3651,7 +3706,7 @@ def : ARMV5TPat<(int_arm_mrc2 imm:$cop, imm:$opc1, imm:$CRn,
class MovRRCopro<string opc, bit direction,
list<dag> pattern = [/* For disassembly only */]>
- : ABI<0b1100, (outs), (ins p_imm:$cop, i32imm:$opc1,
+ : ABI<0b1100, (outs), (ins p_imm:$cop, imm0_15:$opc1,
GPR:$Rt, GPR:$Rt2, c_imm:$CRm),
NoItinerary, opc, "\t$cop, $opc1, $Rt, $Rt2, $CRm", pattern> {
let Inst{23-21} = 0b010;
@@ -3677,7 +3732,7 @@ def MRRC : MovRRCopro<"mrrc", 1 /* from coprocessor to ARM core register */>;
class MovRRCopro2<string opc, bit direction,
list<dag> pattern = [/* For disassembly only */]>
- : ABXI<0b1100, (outs), (ins p_imm:$cop, i32imm:$opc1,
+ : ABXI<0b1100, (outs), (ins p_imm:$cop, imm0_15:$opc1,
GPR:$Rt, GPR:$Rt2, c_imm:$CRm), NoItinerary,
!strconcat(opc, "\t$cop, $opc1, $Rt, $Rt2, $CRm"), pattern> {
let Inst{31-28} = 0b1111;
@@ -3828,6 +3883,13 @@ def Int_eh_sjlj_dispatchsetup :
// Non-Instruction Patterns
//
+// ARMv4 indirect branch using (MOVr PC, dst)
+let isBranch = 1, isTerminator = 1, isBarrier = 1, isIndirectBranch = 1 in
+ def MOVPCRX : ARMPseudoExpand<(outs), (ins GPR:$dst),
+ 4, IIC_Br, [(brind GPR:$dst)],
+ (MOVr PC, GPR:$dst, (ops 14, zero_reg), zero_reg)>,
+ Requires<[IsARM, NoV4T]>;
+
// Large immediate handling.
// 32-bit immediate using two piece so_imms or movw + movt.
@@ -3993,3 +4055,22 @@ include "ARMInstrVFP.td"
include "ARMInstrNEON.td"
+//===----------------------------------------------------------------------===//
+// Assembler aliases
+//
+
+// Memory barriers
+def : InstAlias<"dmb", (DMB 0xf)>, Requires<[IsARM, HasDB]>;
+def : InstAlias<"dsb", (DSB 0xf)>, Requires<[IsARM, HasDB]>;
+def : InstAlias<"isb", (ISB 0xf)>, Requires<[IsARM, HasDB]>;
+
+// System instructions
+def : MnemonicAlias<"swi", "svc">;
+
+// Load / Store Multiple
+def : MnemonicAlias<"ldmfd", "ldm">;
+def : MnemonicAlias<"ldmia", "ldm">;
+def : MnemonicAlias<"stmfd", "stmdb">;
+def : MnemonicAlias<"stmia", "stm">;
+def : MnemonicAlias<"stmea", "stm">;
+
diff --git a/lib/Target/ARM/ARMInstrNEON.td b/lib/Target/ARM/ARMInstrNEON.td
index 977139f..0df62f4 100644
--- a/lib/Target/ARM/ARMInstrNEON.td
+++ b/lib/Target/ARM/ARMInstrNEON.td
@@ -4214,17 +4214,12 @@ def VSWPq : N2VX<0b11, 0b11, 0b00, 0b10, 0b00000, 1, 0,
// Vector Move Operations.
// VMOV : Vector Move (Register)
+def : InstAlias<"vmov${p} $Vd, $Vm",
+ (VORRd DPR:$Vd, DPR:$Vm, DPR:$Vm, pred:$p)>;
+def : InstAlias<"vmov${p} $Vd, $Vm",
+ (VORRq QPR:$Vd, QPR:$Vm, QPR:$Vm, pred:$p)>;
let neverHasSideEffects = 1 in {
-def VMOVDneon: N3VX<0, 0, 0b10, 0b0001, 0, 1, (outs DPR:$Vd), (ins DPR:$Vm),
- N3RegFrm, IIC_VMOV, "vmov", "$Vd, $Vm", "", []> {
- let Vn{4-0} = Vm{4-0};
-}
-def VMOVQ : N3VX<0, 0, 0b10, 0b0001, 1, 1, (outs QPR:$Vd), (ins QPR:$Vm),
- N3RegFrm, IIC_VMOV, "vmov", "$Vd, $Vm", "", []> {
- let Vn{4-0} = Vm{4-0};
-}
-
// Pseudo vector move instructions for QQ and QQQQ registers. This should
// be expanded after register allocation is completed.
def VMOVQQ : PseudoInst<(outs QQPR:$dst), (ins QQPR:$src),
@@ -4704,11 +4699,10 @@ def VEXTd32 : VEXTd<"vext", "32", v2i32> {
let Inst{11-10} = index{1-0};
let Inst{9-8} = 0b00;
}
-def VEXTdf : VEXTd<"vext", "32", v2f32> {
- let Inst{11-10} = index{1-0};
- let Inst{9-8} = 0b00;
-
-}
+def : Pat<(v2f32 (NEONvext (v2f32 DPR:$Vn),
+ (v2f32 DPR:$Vm),
+ (i32 imm:$index))),
+ (VEXTd32 DPR:$Vn, DPR:$Vm, imm:$index)>;
def VEXTq8 : VEXTq<"vext", "8", v16i8> {
let Inst{11-8} = index{3-0};
@@ -4721,10 +4715,10 @@ def VEXTq32 : VEXTq<"vext", "32", v4i32> {
let Inst{11-10} = index{1-0};
let Inst{9-8} = 0b00;
}
-def VEXTqf : VEXTq<"vext", "32", v4f32> {
- let Inst{11-10} = index{1-0};
- let Inst{9-8} = 0b00;
-}
+def : Pat<(v4f32 (NEONvext (v4f32 QPR:$Vn),
+ (v4f32 QPR:$Vm),
+ (i32 imm:$index))),
+ (VEXTq32 QPR:$Vn, QPR:$Vm, imm:$index)>;
// VTRN : Vector Transpose
diff --git a/lib/Target/ARM/ARMInstrThumb.td b/lib/Target/ARM/ARMInstrThumb.td
index 4efe171..bfe83ec 100644
--- a/lib/Target/ARM/ARMInstrThumb.td
+++ b/lib/Target/ARM/ARMInstrThumb.td
@@ -26,10 +26,6 @@ def imm_comp_XFORM : SDNodeXForm<imm, [{
return CurDAG->getTargetConstant(~((uint32_t)N->getZExtValue()), MVT::i32);
}]>;
-/// imm0_7 predicate - True if the 32-bit immediate is in the range [0,7].
-def imm0_7 : ImmLeaf<i32, [{
- return Imm >= 0 && Imm < 8;
-}]>;
def imm0_7_neg : PatLeaf<(i32 imm), [{
return (uint32_t)-N->getZExtValue() < 8;
}], imm_neg_XFORM>;
@@ -75,10 +71,12 @@ def t_adrlabel : Operand<i32> {
// Scaled 4 immediate.
def t_imm_s4 : Operand<i32> {
let PrintMethod = "printThumbS4ImmOperand";
+ let OperandType = "OPERAND_IMMEDIATE";
}
// Define Thumb specific addressing modes.
+let OperandType = "OPERAND_PCREL" in {
def t_brtarget : Operand<OtherVT> {
let EncoderMethod = "getThumbBRTargetOpValue";
}
@@ -98,6 +96,7 @@ def t_bltarget : Operand<i32> {
def t_blxtarget : Operand<i32> {
let EncoderMethod = "getThumbBLXTargetOpValue";
}
+}
def MemModeRegThumbAsmOperand : AsmOperandClass {
let Name = "MemModeRegThumb";
@@ -361,27 +360,6 @@ def tADDspr : TIt<(outs GPR:$dst), (ins GPR:$lhs, GPR:$rhs), IIC_iALUr,
// Control Flow Instructions.
//
-let isReturn = 1, isTerminator = 1, isBarrier = 1 in {
- def tBX_RET : TI<(outs), (ins), IIC_Br, "bx\tlr",
- [(ARMretflag)]>,
- T1Special<{1,1,0,?}> {
- // A6.2.3 & A8.6.25
- let Inst{6-3} = 0b1110; // Rm = lr
- let Inst{2-0} = 0b000;
- }
-
- // Alternative return instruction used by vararg functions.
- def tBX_RET_vararg : TI<(outs), (ins tGPR:$Rm),
- IIC_Br, "bx\t$Rm",
- []>,
- T1Special<{1,1,0,?}> {
- // A6.2.3 & A8.6.25
- bits<4> Rm;
- let Inst{6-3} = Rm;
- let Inst{2-0} = 0b000;
- }
-}
-
// Indirect branches
let isBranch = 1, isTerminator = 1, isBarrier = 1, isIndirectBranch = 1 in {
def tBX : TI<(outs), (ins GPR:$Rm, pred:$p), IIC_Br, "bx${p}\t$Rm", []>,
@@ -391,25 +369,17 @@ let isBranch = 1, isTerminator = 1, isBarrier = 1, isIndirectBranch = 1 in {
let Inst{6-3} = Rm;
let Inst{2-0} = 0b000;
}
-
- def tBRIND : TI<(outs), (ins GPR:$Rm),
- IIC_Br,
- "mov\tpc, $Rm",
- [(brind GPR:$Rm)]>,
- T1Special<{1,0,?,?}> {
- // A8.6.97
- bits<4> Rm;
- let Inst{7} = 1; // <Rd> = Inst{7:2-0} = pc
- let Inst{6-3} = Rm;
- let Inst{2-0} = 0b111;
- }
}
-// FIXME: remove when we have a way to marking a MI with these properties.
-let isReturn = 1, isTerminator = 1, isBarrier = 1, mayLoad = 1,
- hasExtraDefRegAllocReq = 1 in
-def tPOP_RET : tPseudoInst<(outs), (ins pred:$p, reglist:$regs, variable_ops),
- Size2Bytes, IIC_iPop_Br, []>;
+let isReturn = 1, isTerminator = 1, isBarrier = 1 in {
+ def tBX_RET : tPseudoExpand<(outs), (ins pred:$p), 2, IIC_Br,
+ [(ARMretflag)], (tBX LR, pred:$p)>;
+
+ // Alternative return instruction used by vararg functions.
+ def tBX_RET_vararg : tPseudoExpand<(outs), (ins tGPR:$Rm, pred:$p),
+ 2, IIC_Br, [],
+ (tBX GPR:$Rm, pred:$p)>;
+}
// All calls clobber the non-callee saved registers. SP is marked as a use to
// prevent stack-pointer assignments that appear immediately before calls from
@@ -458,7 +428,7 @@ let isCall = 1,
// ARMv4T
def tBX_CALL : tPseudoInst<(outs), (ins tGPR:$func, variable_ops),
- Size4Bytes, IIC_Br,
+ 4, IIC_Br,
[(ARMcall_nolink tGPR:$func)]>,
Requires<[IsThumb, IsThumb1Only, IsNotDarwin]>;
}
@@ -510,7 +480,7 @@ let isCall = 1,
// ARMv4T
def tBXr9_CALL : tPseudoInst<(outs), (ins tGPR:$func, variable_ops),
- Size4Bytes, IIC_Br,
+ 4, IIC_Br,
[(ARMcall_nolink tGPR:$func)]>,
Requires<[IsThumb, IsThumb1Only, IsDarwin]>;
}
@@ -528,12 +498,12 @@ let isBranch = 1, isTerminator = 1, isBarrier = 1 in {
// Just a pseudo for a tBL instruction. Needed to let regalloc know about
// the clobber of LR.
let Defs = [LR] in
- def tBfar : tPseudoInst<(outs), (ins t_bltarget:$target),
- Size4Bytes, IIC_Br, []>;
+ def tBfar : tPseudoExpand<(outs), (ins t_bltarget:$target),
+ 4, IIC_Br, [], (tBL t_bltarget:$target)>;
def tBR_JTr : tPseudoInst<(outs),
(ins tGPR:$target, i32imm:$jt, i32imm:$id),
- SizeSpecial, IIC_Br,
+ 0, IIC_Br,
[(ARMbrjt tGPR:$target, tjumptable:$jt, imm:$id)]> {
list<Predicate> Predicates = [IsThumb, IsThumb1Only];
}
@@ -577,6 +547,33 @@ let isBranch = 1, isTerminator = 1 in {
}
}
+// Tail calls
+let isCall = 1, isTerminator = 1, isReturn = 1, isBarrier = 1 in {
+ // Darwin versions.
+ let Defs = [R0, R1, R2, R3, R9, R12, QQQQ0, QQQQ2, QQQQ3, PC],
+ Uses = [SP] in {
+ // tTAILJMPd: Darwin version uses a Thumb2 branch (no Thumb1 tail calls
+ // on Darwin), so it's in ARMInstrThumb2.td.
+ def tTAILJMPr : tPseudoExpand<(outs), (ins tcGPR:$dst, variable_ops),
+ 4, IIC_Br, [],
+ (tBX GPR:$dst, (ops 14, zero_reg))>,
+ Requires<[IsThumb, IsDarwin]>;
+ }
+ // Non-Darwin versions (the difference is R9).
+ let Defs = [R0, R1, R2, R3, R12, QQQQ0, QQQQ2, QQQQ3, PC],
+ Uses = [SP] in {
+ def tTAILJMPdND : tPseudoExpand<(outs), (ins t_brtarget:$dst, variable_ops),
+ 4, IIC_Br, [],
+ (tB t_brtarget:$dst)>,
+ Requires<[IsThumb, IsNotDarwin]>;
+ def tTAILJMPrND : tPseudoExpand<(outs), (ins tcGPR:$dst, variable_ops),
+ 4, IIC_Br, [],
+ (tBX GPR:$dst, (ops 14, zero_reg))>,
+ Requires<[IsThumb, IsNotDarwin]>;
+ }
+}
+
+
// A8.6.218 Supervisor Call (Software Interrupt) -- for disassembly only
// A8.6.16 B: Encoding T1
// If Inst{11-8} == 0b1111 then SEE SVC
@@ -1055,7 +1052,7 @@ def tMOVi8 : T1sI<(outs tGPR:$Rd), (ins imm0_255:$imm8), IIC_iMOVi,
let neverHasSideEffects = 1 in {
def tMOVr : Thumb1pI<(outs GPR:$Rd), (ins GPR:$Rm), AddrModeNone,
- Size2Bytes, IIC_iMOVr,
+ 2, IIC_iMOVr,
"mov", "\t$Rd, $Rm", "", []>,
T1Special<{1,0,?,?}> {
// A8.6.97
@@ -1229,105 +1226,11 @@ def tADR : T1I<(outs tGPR:$Rd), (ins t_adrlabel:$addr, pred:$p),
let neverHasSideEffects = 1, isReMaterializable = 1 in
def tLEApcrel : tPseudoInst<(outs tGPR:$Rd), (ins i32imm:$label, pred:$p),
- Size2Bytes, IIC_iALUi, []>;
+ 2, IIC_iALUi, []>;
def tLEApcrelJT : tPseudoInst<(outs tGPR:$Rd),
(ins i32imm:$label, nohash_imm:$id, pred:$p),
- Size2Bytes, IIC_iALUi, []>;
-
-//===----------------------------------------------------------------------===//
-// Move between coprocessor and ARM core register -- for disassembly only
-//
-
-class tMovRCopro<string opc, bit direction, dag oops, dag iops,
- list<dag> pattern>
- : T1Cop<oops, iops, !strconcat(opc, "\t$cop, $opc1, $Rt, $CRn, $CRm, $opc2"),
- pattern> {
- let Inst{27-24} = 0b1110;
- let Inst{20} = direction;
- let Inst{4} = 1;
-
- bits<4> Rt;
- bits<4> cop;
- bits<3> opc1;
- bits<3> opc2;
- bits<4> CRm;
- bits<4> CRn;
-
- let Inst{15-12} = Rt;
- let Inst{11-8} = cop;
- let Inst{23-21} = opc1;
- let Inst{7-5} = opc2;
- let Inst{3-0} = CRm;
- let Inst{19-16} = CRn;
-}
-
-def tMCR : tMovRCopro<"mcr", 0 /* from ARM core register to coprocessor */,
- (outs),
- (ins p_imm:$cop, i32imm:$opc1, GPR:$Rt, c_imm:$CRn,
- c_imm:$CRm, i32imm:$opc2),
- [(int_arm_mcr imm:$cop, imm:$opc1, GPR:$Rt, imm:$CRn,
- imm:$CRm, imm:$opc2)]>;
-def tMRC : tMovRCopro<"mrc", 1 /* from coprocessor to ARM core register */,
- (outs GPR:$Rt),
- (ins p_imm:$cop, i32imm:$opc1, c_imm:$CRn, c_imm:$CRm, i32imm:$opc2),
- []>;
-
-def : Pat<(int_arm_mrc imm:$cop, imm:$opc1, imm:$CRn, imm:$CRm, imm:$opc2),
- (tMRC imm:$cop, imm:$opc1, imm:$CRn, imm:$CRm, imm:$opc2)>,
- Requires<[IsThumb, HasV6T2]>;
-
-class tMovRRCopro<string opc, bit direction,
- list<dag> pattern = [/* For disassembly only */]>
- : T1Cop<(outs), (ins p_imm:$cop, i32imm:$opc1, GPR:$Rt, GPR:$Rt2, c_imm:$CRm),
- !strconcat(opc, "\t$cop, $opc1, $Rt, $Rt2, $CRm"), pattern> {
- let Inst{27-24} = 0b1100;
- let Inst{23-21} = 0b010;
- let Inst{20} = direction;
-
- bits<4> Rt;
- bits<4> Rt2;
- bits<4> cop;
- bits<4> opc1;
- bits<4> CRm;
-
- let Inst{15-12} = Rt;
- let Inst{19-16} = Rt2;
- let Inst{11-8} = cop;
- let Inst{7-4} = opc1;
- let Inst{3-0} = CRm;
-}
-
-def tMCRR : tMovRRCopro<"mcrr", 0 /* from ARM core register to coprocessor */,
- [(int_arm_mcrr imm:$cop, imm:$opc1, GPR:$Rt, GPR:$Rt2,
- imm:$CRm)]>;
-def tMRRC : tMovRRCopro<"mrrc", 1 /* from coprocessor to ARM core register */>;
-
-//===----------------------------------------------------------------------===//
-// Other Coprocessor Instructions. For disassembly only.
-//
-def tCDP : T1Cop<(outs), (ins p_imm:$cop, i32imm:$opc1,
- c_imm:$CRd, c_imm:$CRn, c_imm:$CRm, i32imm:$opc2),
- "cdp\t$cop, $opc1, $CRd, $CRn, $CRm, $opc2",
- [(int_arm_cdp imm:$cop, imm:$opc1, imm:$CRd, imm:$CRn,
- imm:$CRm, imm:$opc2)]> {
- let Inst{27-24} = 0b1110;
-
- bits<4> opc1;
- bits<4> CRn;
- bits<4> CRd;
- bits<4> cop;
- bits<3> opc2;
- bits<4> CRm;
-
- let Inst{3-0} = CRm;
- let Inst{4} = 0;
- let Inst{7-5} = opc2;
- let Inst{11-8} = cop;
- let Inst{15-12} = CRd;
- let Inst{19-16} = CRn;
- let Inst{23-20} = opc1;
-}
+ 2, IIC_iALUi, []>;
//===----------------------------------------------------------------------===//
// TLS Instructions
@@ -1337,7 +1240,7 @@ def tCDP : T1Cop<(outs), (ins p_imm:$cop, i32imm:$opc1,
// This is a pseudo inst so that we can get the encoding right,
// complete with fixup for the aeabi_read_tp function.
let isCall = 1, Defs = [R0, R12, LR, CPSR], Uses = [SP] in
-def tTPsoft : tPseudoInst<(outs), (ins), Size4Bytes, IIC_Br,
+def tTPsoft : tPseudoInst<(outs), (ins), 4, IIC_Br,
[(set R0, ARMthread_pointer)]>;
//===----------------------------------------------------------------------===//
@@ -1357,14 +1260,14 @@ def tTPsoft : tPseudoInst<(outs), (ins), Size4Bytes, IIC_Br,
let Defs = [ R0, R1, R2, R3, R4, R5, R6, R7, R12, CPSR ],
hasSideEffects = 1, isBarrier = 1, isCodeGenOnly = 1 in
def tInt_eh_sjlj_setjmp : ThumbXI<(outs),(ins tGPR:$src, tGPR:$val),
- AddrModeNone, SizeSpecial, NoItinerary, "","",
+ AddrModeNone, 0, NoItinerary, "","",
[(set R0, (ARMeh_sjlj_setjmp tGPR:$src, tGPR:$val))]>;
// FIXME: Non-Darwin version(s)
let isBarrier = 1, hasSideEffects = 1, isTerminator = 1, isCodeGenOnly = 1,
Defs = [ R7, LR, SP ] in
def tInt_eh_sjlj_longjmp : XI<(outs), (ins GPR:$src, GPR:$scratch),
- AddrModeNone, SizeSpecial, IndexModeNone,
+ AddrModeNone, 0, IndexModeNone,
Pseudo, NoItinerary, "", "",
[(ARMeh_sjlj_longjmp GPR:$src, GPR:$scratch)]>,
Requires<[IsThumb, IsDarwin]>;
@@ -1477,3 +1380,18 @@ def tLDRpci_pic : PseudoInst<(outs GPR:$dst), (ins i32imm:$addr, pclabel:$cp),
[(set GPR:$dst, (ARMpic_add (load (ARMWrapper tconstpool:$addr)),
imm:$cp))]>,
Requires<[IsThumb, IsThumb1Only]>;
+
+// Pseudo-instruction for merged POP and return.
+// FIXME: remove when we have a way to marking a MI with these properties.
+let isReturn = 1, isTerminator = 1, isBarrier = 1, mayLoad = 1,
+ hasExtraDefRegAllocReq = 1 in
+def tPOP_RET : tPseudoExpand<(outs), (ins pred:$p, reglist:$regs, variable_ops),
+ 2, IIC_iPop_Br, [],
+ (tPOP pred:$p, reglist:$regs)>;
+
+// Indirect branch using "mov pc, $Rm"
+let isBranch = 1, isTerminator = 1, isBarrier = 1, isIndirectBranch = 1 in {
+ def tBRIND : tPseudoExpand<(outs), (ins GPR:$Rm, pred:$p),
+ 2, IIC_Br, [(brind GPR:$Rm)],
+ (tMOVr PC, GPR:$Rm, pred:$p)>;
+}
diff --git a/lib/Target/ARM/ARMInstrThumb2.td b/lib/Target/ARM/ARMInstrThumb2.td
index eb533f8..c2c6cbc 100644
--- a/lib/Target/ARM/ARMInstrThumb2.td
+++ b/lib/Target/ARM/ARMInstrThumb2.td
@@ -716,18 +716,18 @@ let usesCustomInserter = 1 in {
multiclass T2I_adde_sube_s_irs<PatFrag opnode, bit Commutable = 0> {
// shifted imm
def ri : t2PseudoInst<(outs rGPR:$Rd), (ins rGPR:$Rn, t2_so_imm:$imm),
- Size4Bytes, IIC_iALUi,
+ 4, IIC_iALUi,
[(set rGPR:$Rd, (opnode rGPR:$Rn, t2_so_imm:$imm))]>;
// register
def rr : t2PseudoInst<(outs rGPR:$Rd), (ins rGPR:$Rn, rGPR:$Rm),
- Size4Bytes, IIC_iALUr,
+ 4, IIC_iALUr,
[(set rGPR:$Rd, (opnode rGPR:$Rn, rGPR:$Rm))]> {
let isCommutable = Commutable;
}
// shifted register
def rs : t2PseudoInst<
(outs rGPR:$Rd), (ins rGPR:$Rn, t2_so_reg:$ShiftedRm),
- Size4Bytes, IIC_iALUsi,
+ 4, IIC_iALUsi,
[(set rGPR:$Rd, (opnode rGPR:$Rn, t2_so_reg:$ShiftedRm))]>;
}
}
@@ -1164,10 +1164,10 @@ def t2ADR : T2PCOneRegImm<(outs rGPR:$Rd),
let neverHasSideEffects = 1, isReMaterializable = 1 in
def t2LEApcrel : t2PseudoInst<(outs rGPR:$Rd), (ins i32imm:$label, pred:$p),
- Size4Bytes, IIC_iALUi, []>;
+ 4, IIC_iALUi, []>;
def t2LEApcrelJT : t2PseudoInst<(outs rGPR:$Rd),
(ins i32imm:$label, nohash_imm:$id, pred:$p),
- Size4Bytes, IIC_iALUi,
+ 4, IIC_iALUi,
[]>;
@@ -2709,14 +2709,14 @@ defm t2TEQ : T2I_cmp_irs<0b0100, "teq",
let neverHasSideEffects = 1 in {
def t2MOVCCr : t2PseudoInst<(outs rGPR:$Rd),
(ins rGPR:$false, rGPR:$Rm, pred:$p),
- Size4Bytes, IIC_iCMOVr,
+ 4, IIC_iCMOVr,
[/*(set rGPR:$Rd, (ARMcmov rGPR:$false, rGPR:$Rm, imm:$cc, CCR:$ccr))*/]>,
RegConstraint<"$false = $Rd">;
let isMoveImm = 1 in
def t2MOVCCi : t2PseudoInst<(outs rGPR:$Rd),
(ins rGPR:$false, t2_so_imm:$imm, pred:$p),
- Size4Bytes, IIC_iCMOVi,
+ 4, IIC_iCMOVi,
[/*(set rGPR:$Rd,(ARMcmov rGPR:$false,t2_so_imm:$imm, imm:$cc, CCR:$ccr))*/]>,
RegConstraint<"$false = $Rd">;
@@ -2823,7 +2823,7 @@ def t2ISB : AInoP<(outs), (ins), ThumbFrm, NoItinerary, "isb", "",
let Inst{3-0} = 0b1111;
}
-class T2I_ldrex<bits<2> opcod, dag oops, dag iops, AddrMode am, SizeFlagVal sz,
+class T2I_ldrex<bits<2> opcod, dag oops, dag iops, AddrMode am, int sz,
InstrItinClass itin, string opc, string asm, string cstr,
list<dag> pattern, bits<4> rt2 = 0b1111>
: Thumb2I<oops, iops, am, sz, itin, opc, asm, cstr, pattern> {
@@ -2839,7 +2839,7 @@ class T2I_ldrex<bits<2> opcod, dag oops, dag iops, AddrMode am, SizeFlagVal sz,
let Inst{19-16} = addr;
let Inst{15-12} = Rt;
}
-class T2I_strex<bits<2> opcod, dag oops, dag iops, AddrMode am, SizeFlagVal sz,
+class T2I_strex<bits<2> opcod, dag oops, dag iops, AddrMode am, int sz,
InstrItinClass itin, string opc, string asm, string cstr,
list<dag> pattern, bits<4> rt2 = 0b1111>
: Thumb2I<oops, iops, am, sz, itin, opc, asm, cstr, pattern> {
@@ -2859,13 +2859,13 @@ class T2I_strex<bits<2> opcod, dag oops, dag iops, AddrMode am, SizeFlagVal sz,
let mayLoad = 1 in {
def t2LDREXB : T2I_ldrex<0b00, (outs rGPR:$Rt), (ins t2addrmode_reg:$addr),
- AddrModeNone, Size4Bytes, NoItinerary,
+ AddrModeNone, 4, NoItinerary,
"ldrexb", "\t$Rt, $addr", "", []>;
def t2LDREXH : T2I_ldrex<0b01, (outs rGPR:$Rt), (ins t2addrmode_reg:$addr),
- AddrModeNone, Size4Bytes, NoItinerary,
+ AddrModeNone, 4, NoItinerary,
"ldrexh", "\t$Rt, $addr", "", []>;
def t2LDREX : Thumb2I<(outs rGPR:$Rt), (ins t2addrmode_reg:$addr),
- AddrModeNone, Size4Bytes, NoItinerary,
+ AddrModeNone, 4, NoItinerary,
"ldrex", "\t$Rt, $addr", "", []> {
let Inst{31-27} = 0b11101;
let Inst{26-20} = 0b0000101;
@@ -2880,7 +2880,7 @@ def t2LDREX : Thumb2I<(outs rGPR:$Rt), (ins t2addrmode_reg:$addr),
let hasExtraDefRegAllocReq = 1 in
def t2LDREXD : T2I_ldrex<0b11, (outs rGPR:$Rt, rGPR:$Rt2),
(ins t2addrmode_reg:$addr),
- AddrModeNone, Size4Bytes, NoItinerary,
+ AddrModeNone, 4, NoItinerary,
"ldrexd", "\t$Rt, $Rt2, $addr", "",
[], {?, ?, ?, ?}> {
bits<4> Rt2;
@@ -2891,14 +2891,14 @@ def t2LDREXD : T2I_ldrex<0b11, (outs rGPR:$Rt, rGPR:$Rt2),
let mayStore = 1, Constraints = "@earlyclobber $Rd" in {
def t2STREXB : T2I_strex<0b00, (outs rGPR:$Rd),
(ins rGPR:$Rt, t2addrmode_reg:$addr),
- AddrModeNone, Size4Bytes, NoItinerary,
+ AddrModeNone, 4, NoItinerary,
"strexb", "\t$Rd, $Rt, $addr", "", []>;
def t2STREXH : T2I_strex<0b01, (outs rGPR:$Rd),
(ins rGPR:$Rt, t2addrmode_reg:$addr),
- AddrModeNone, Size4Bytes, NoItinerary,
+ AddrModeNone, 4, NoItinerary,
"strexh", "\t$Rd, $Rt, $addr", "", []>;
def t2STREX : Thumb2I<(outs rGPR:$Rd), (ins rGPR:$Rt, t2addrmode_reg:$addr),
- AddrModeNone, Size4Bytes, NoItinerary,
+ AddrModeNone, 4, NoItinerary,
"strex", "\t$Rd, $Rt, $addr", "",
[]> {
let Inst{31-27} = 0b11101;
@@ -2917,7 +2917,7 @@ def t2STREX : Thumb2I<(outs rGPR:$Rd), (ins rGPR:$Rt, t2addrmode_reg:$addr),
let hasExtraSrcRegAllocReq = 1, Constraints = "@earlyclobber $Rd" in
def t2STREXD : T2I_strex<0b11, (outs rGPR:$Rd),
(ins rGPR:$Rt, rGPR:$Rt2, t2addrmode_reg:$addr),
- AddrModeNone, Size4Bytes, NoItinerary,
+ AddrModeNone, 4, NoItinerary,
"strexd", "\t$Rd, $Rt, $Rt2, $addr", "", [],
{?, ?, ?, ?}> {
bits<4> Rt2;
@@ -2955,7 +2955,7 @@ let Defs =
QQQQ0, QQQQ1, QQQQ2, QQQQ3 ],
hasSideEffects = 1, isBarrier = 1, isCodeGenOnly = 1 in {
def t2Int_eh_sjlj_setjmp : Thumb2XI<(outs), (ins tGPR:$src, tGPR:$val),
- AddrModeNone, SizeSpecial, NoItinerary, "", "",
+ AddrModeNone, 0, NoItinerary, "", "",
[(set R0, (ARMeh_sjlj_setjmp tGPR:$src, tGPR:$val))]>,
Requires<[IsThumb2, HasVFP2]>;
}
@@ -2964,7 +2964,7 @@ let Defs =
[ R0, R1, R2, R3, R4, R5, R6, R7, R8, R9, R10, R11, R12, LR, CPSR ],
hasSideEffects = 1, isBarrier = 1, isCodeGenOnly = 1 in {
def t2Int_eh_sjlj_setjmp_nofp : Thumb2XI<(outs), (ins tGPR:$src, tGPR:$val),
- AddrModeNone, SizeSpecial, NoItinerary, "", "",
+ AddrModeNone, 0, NoItinerary, "", "",
[(set R0, (ARMeh_sjlj_setjmp tGPR:$src, tGPR:$val))]>,
Requires<[IsThumb2, NoVFP]>;
}
@@ -2978,9 +2978,10 @@ let Defs =
// FIXME: Should pc be an implicit operand like PICADD, etc?
let isReturn = 1, isTerminator = 1, isBarrier = 1, mayLoad = 1,
hasExtraDefRegAllocReq = 1, isCodeGenOnly = 1 in
-def t2LDMIA_RET: t2PseudoInst<(outs GPR:$wb), (ins GPR:$Rn, pred:$p,
+def t2LDMIA_RET: t2PseudoExpand<(outs GPR:$wb), (ins GPR:$Rn, pred:$p,
reglist:$regs, variable_ops),
- Size4Bytes, IIC_iLoad_mBr, []>,
+ 4, IIC_iLoad_mBr, [],
+ (t2LDMIA_UPD GPR:$wb, GPR:$Rn, pred:$p, reglist:$regs)>,
RegConstraint<"$Rn = $wb">;
let isBranch = 1, isTerminator = 1, isBarrier = 1 in {
@@ -3003,17 +3004,17 @@ def t2B : T2XI<(outs), (ins uncondbrtarget:$target), IIC_Br,
let isNotDuplicable = 1, isIndirectBranch = 1 in {
def t2BR_JT : t2PseudoInst<(outs),
(ins GPR:$target, GPR:$index, i32imm:$jt, i32imm:$id),
- SizeSpecial, IIC_Br,
+ 0, IIC_Br,
[(ARMbr2jt GPR:$target, GPR:$index, tjumptable:$jt, imm:$id)]>;
// FIXME: Add a non-pc based case that can be predicated.
def t2TBB_JT : t2PseudoInst<(outs),
(ins GPR:$index, i32imm:$jt, i32imm:$id),
- SizeSpecial, IIC_Br, []>;
+ 0, IIC_Br, []>;
def t2TBH_JT : t2PseudoInst<(outs),
(ins GPR:$index, i32imm:$jt, i32imm:$id),
- SizeSpecial, IIC_Br, []>;
+ 0, IIC_Br, []>;
def t2TBB : T2I<(outs), (ins GPR:$Rn, GPR:$Rm), IIC_Br,
"tbb", "\t[$Rn, $Rm]", []> {
@@ -3061,11 +3062,22 @@ def t2Bcc : T2I<(outs), (ins brtarget:$target), IIC_Br,
let Inst{10-0} = target{11-1};
}
+// Tail calls. The Darwin version of thumb tail calls uses a t2 branch, so
+// it goes here.
+let isCall = 1, isTerminator = 1, isReturn = 1, isBarrier = 1 in {
+ // Darwin version.
+ let Defs = [R0, R1, R2, R3, R9, R12, QQQQ0, QQQQ2, QQQQ3, PC],
+ Uses = [SP] in
+ def tTAILJMPd: tPseudoExpand<(outs), (ins uncondbrtarget:$dst, variable_ops),
+ 4, IIC_Br, [],
+ (t2B uncondbrtarget:$dst)>,
+ Requires<[IsThumb2, IsDarwin]>;
+}
// IT block
let Defs = [ITSTATE] in
def t2IT : Thumb2XI<(outs), (ins it_pred:$cc, it_mask:$mask),
- AddrModeNone, Size2Bytes, IIC_iALUx,
+ AddrModeNone, 2, IIC_iALUx,
"it$mask\t$cc", "", []> {
// 16-bit instruction.
let Inst{31-16} = 0x0000;
@@ -3145,8 +3157,7 @@ def t2WFE : T2I_hint<0b00000010, "wfe", ".w">;
def t2WFI : T2I_hint<0b00000011, "wfi", ".w">;
def t2SEV : T2I_hint<0b00000100, "sev", ".w">;
-def t2DBG : T2I<(outs),(ins i32imm:$opt), NoItinerary, "dbg", "\t$opt",
- [/* For disassembly only; pattern left blank */]> {
+def t2DBG : T2I<(outs), (ins imm0_15:$opt), NoItinerary, "dbg", "\t$opt", []> {
let Inst{31-20} = 0xf3a;
let Inst{15-14} = 0b10;
let Inst{12} = 0;
@@ -3314,12 +3325,13 @@ def t2MSR : T2SpecialReg<0b111100111000 /* op31-20 */, 0b10 /* op15-14 */,
}
//===----------------------------------------------------------------------===//
-// Move between coprocessor and ARM core register -- for disassembly only
+// Move between coprocessor and ARM core register
//
-class t2MovRCopro<string opc, bit direction, dag oops, dag iops,
+class t2MovRCopro<bits<4> Op, string opc, bit direction, dag oops, dag iops,
list<dag> pattern>
- : T2Cop<oops, iops, !strconcat(opc, "\t$cop, $opc1, $Rt, $CRn, $CRm, $opc2"),
+ : T2Cop<Op, oops, iops,
+ !strconcat(opc, "\t$cop, $opc1, $Rt, $CRn, $CRm, $opc2"),
pattern> {
let Inst{27-24} = 0b1110;
let Inst{20} = direction;
@@ -3340,22 +3352,10 @@ class t2MovRCopro<string opc, bit direction, dag oops, dag iops,
let Inst{19-16} = CRn;
}
-def t2MCR2 : t2MovRCopro<"mcr2", 0 /* from ARM core register to coprocessor */,
- (outs), (ins p_imm:$cop, i32imm:$opc1, GPR:$Rt, c_imm:$CRn,
- c_imm:$CRm, i32imm:$opc2),
- [(int_arm_mcr2 imm:$cop, imm:$opc1, GPR:$Rt, imm:$CRn,
- imm:$CRm, imm:$opc2)]>;
-def t2MRC2 : t2MovRCopro<"mrc2", 1 /* from coprocessor to ARM core register */,
- (outs GPR:$Rt), (ins p_imm:$cop, i32imm:$opc1, c_imm:$CRn,
- c_imm:$CRm, i32imm:$opc2), []>;
-
-def : T2v6Pat<(int_arm_mrc2 imm:$cop, imm:$opc1, imm:$CRn,
- imm:$CRm, imm:$opc2),
- (t2MRC2 imm:$cop, imm:$opc1, imm:$CRn, imm:$CRm, imm:$opc2)>;
-
-class t2MovRRCopro<string opc, bit direction,
- list<dag> pattern = [/* For disassembly only */]>
- : T2Cop<(outs), (ins p_imm:$cop, i32imm:$opc1, GPR:$Rt, GPR:$Rt2, c_imm:$CRm),
+class t2MovRRCopro<bits<4> Op, string opc, bit direction,
+ list<dag> pattern = []>
+ : T2Cop<Op, (outs),
+ (ins p_imm:$cop, imm0_15:$opc1, GPR:$Rt, GPR:$Rt2, c_imm:$CRm),
!strconcat(opc, "\t$cop, $opc1, $Rt, $Rt2, $CRm"), pattern> {
let Inst{27-24} = 0b1100;
let Inst{23-21} = 0b010;
@@ -3374,19 +3374,77 @@ class t2MovRRCopro<string opc, bit direction,
let Inst{3-0} = CRm;
}
-def t2MCRR2 : t2MovRRCopro<"mcrr2",
- 0 /* from ARM core register to coprocessor */,
+/* from ARM core register to coprocessor */
+def t2MCR : t2MovRCopro<0b1110, "mcr", 0,
+ (outs),
+ (ins p_imm:$cop, imm0_7:$opc1, GPR:$Rt, c_imm:$CRn,
+ c_imm:$CRm, imm0_7:$opc2),
+ [(int_arm_mcr imm:$cop, imm:$opc1, GPR:$Rt, imm:$CRn,
+ imm:$CRm, imm:$opc2)]>;
+def t2MCR2 : t2MovRCopro<0b1111, "mcr2", 0,
+ (outs), (ins p_imm:$cop, imm0_7:$opc1, GPR:$Rt, c_imm:$CRn,
+ c_imm:$CRm, imm0_7:$opc2),
+ [(int_arm_mcr2 imm:$cop, imm:$opc1, GPR:$Rt, imm:$CRn,
+ imm:$CRm, imm:$opc2)]>;
+
+/* from coprocessor to ARM core register */
+def t2MRC : t2MovRCopro<0b1110, "mrc", 1,
+ (outs GPR:$Rt),
+ (ins p_imm:$cop, i32imm:$opc1, c_imm:$CRn, c_imm:$CRm, i32imm:$opc2),
+ []>;
+
+def t2MRC2 : t2MovRCopro<0b1111, "mrc2", 1,
+ (outs GPR:$Rt), (ins p_imm:$cop, i32imm:$opc1, c_imm:$CRn,
+ c_imm:$CRm, i32imm:$opc2), []>;
+
+def : T2v6Pat<(int_arm_mrc imm:$cop, imm:$opc1, imm:$CRn, imm:$CRm, imm:$opc2),
+ (t2MRC imm:$cop, imm:$opc1, imm:$CRn, imm:$CRm, imm:$opc2)>;
+
+def : T2v6Pat<(int_arm_mrc2 imm:$cop, imm:$opc1, imm:$CRn, imm:$CRm, imm:$opc2),
+ (t2MRC2 imm:$cop, imm:$opc1, imm:$CRn, imm:$CRm, imm:$opc2)>;
+
+
+/* from ARM core register to coprocessor */
+def t2MCRR : t2MovRRCopro<0b1110, "mcrr", 0,
+ [(int_arm_mcrr imm:$cop, imm:$opc1, GPR:$Rt, GPR:$Rt2,
+ imm:$CRm)]>;
+def t2MCRR2 : t2MovRRCopro<0b1111, "mcrr2", 0,
[(int_arm_mcrr2 imm:$cop, imm:$opc1, GPR:$Rt,
GPR:$Rt2, imm:$CRm)]>;
-def t2MRRC2 : t2MovRRCopro<"mrrc2",
- 1 /* from coprocessor to ARM core register */>;
+/* from coprocessor to ARM core register */
+def t2MRRC : t2MovRRCopro<0b1110, "mrrc", 1>;
+
+def t2MRRC2 : t2MovRRCopro<0b1111, "mrrc2", 1>;
//===----------------------------------------------------------------------===//
-// Other Coprocessor Instructions. For disassembly only.
+// Other Coprocessor Instructions.
//
-def t2CDP2 : T2Cop<(outs), (ins p_imm:$cop, i32imm:$opc1,
- c_imm:$CRd, c_imm:$CRn, c_imm:$CRm, i32imm:$opc2),
+def tCDP : T2Cop<0b1110, (outs), (ins p_imm:$cop, imm0_15:$opc1,
+ c_imm:$CRd, c_imm:$CRn, c_imm:$CRm, imm0_7:$opc2),
+ "cdp\t$cop, $opc1, $CRd, $CRn, $CRm, $opc2",
+ [(int_arm_cdp imm:$cop, imm:$opc1, imm:$CRd, imm:$CRn,
+ imm:$CRm, imm:$opc2)]> {
+ let Inst{27-24} = 0b1110;
+
+ bits<4> opc1;
+ bits<4> CRn;
+ bits<4> CRd;
+ bits<4> cop;
+ bits<3> opc2;
+ bits<4> CRm;
+
+ let Inst{3-0} = CRm;
+ let Inst{4} = 0;
+ let Inst{7-5} = opc2;
+ let Inst{11-8} = cop;
+ let Inst{15-12} = CRd;
+ let Inst{19-16} = CRn;
+ let Inst{23-20} = opc1;
+}
+
+def t2CDP2 : T2Cop<0b1111, (outs), (ins p_imm:$cop, imm0_15:$opc1,
+ c_imm:$CRd, c_imm:$CRn, c_imm:$CRm, imm0_7:$opc2),
"cdp2\t$cop, $opc1, $CRd, $CRn, $CRm, $opc2",
[(int_arm_cdp2 imm:$cop, imm:$opc1, imm:$CRd, imm:$CRn,
imm:$CRm, imm:$opc2)]> {
diff --git a/lib/Target/ARM/ARMInstrVFP.td b/lib/Target/ARM/ARMInstrVFP.td
index d2aaa97..f1f3cb9 100644
--- a/lib/Target/ARM/ARMInstrVFP.td
+++ b/lib/Target/ARM/ARMInstrVFP.td
@@ -873,7 +873,7 @@ def VULTOD : AVConv1XI<0b11101, 0b11, 0b1011, 0b1011, 1,
} // End of 'let Constraints = "$a = $dst", isCodeGenOnly = 1 in'
//===----------------------------------------------------------------------===//
-// FP FMA Operations.
+// FP Multiply-Accumulate Operations.
//
def VMLAD : ADbI<0b11100, 0b00, 0, 0,
@@ -990,12 +990,12 @@ def : Pat<(fsub_mlx (fmul_su SPR:$a, SPR:$b), SPR:$dstin),
let neverHasSideEffects = 1 in {
def VMOVDcc : ARMPseudoInst<(outs DPR:$Dd), (ins DPR:$Dn, DPR:$Dm, pred:$p),
- Size4Bytes, IIC_fpUNA64,
+ 4, IIC_fpUNA64,
[/*(set DPR:$Dd, (ARMcmov DPR:$Dn, DPR:$Dm, imm:$cc))*/]>,
RegConstraint<"$Dn = $Dd">;
def VMOVScc : ARMPseudoInst<(outs SPR:$Sd), (ins SPR:$Sn, SPR:$Sm, pred:$p),
- Size4Bytes, IIC_fpUNA32,
+ 4, IIC_fpUNA32,
[/*(set SPR:$Sd, (ARMcmov SPR:$Sn, SPR:$Sm, imm:$cc))*/]>,
RegConstraint<"$Sn = $Sd">;
} // neverHasSideEffects
diff --git a/lib/Target/ARM/ARMMCCodeEmitter.cpp b/lib/Target/ARM/ARMMCCodeEmitter.cpp
index 4fcba11..39be3f0 100644
--- a/lib/Target/ARM/ARMMCCodeEmitter.cpp
+++ b/lib/Target/ARM/ARMMCCodeEmitter.cpp
@@ -21,8 +21,11 @@
#include "llvm/MC/MCCodeEmitter.h"
#include "llvm/MC/MCExpr.h"
#include "llvm/MC/MCInst.h"
+#include "llvm/MC/MCInstrInfo.h"
+#include "llvm/MC/MCSubtargetInfo.h"
#include "llvm/ADT/Statistic.h"
#include "llvm/Support/raw_ostream.h"
+
using namespace llvm;
STATISTIC(MCNumEmitted, "Number of MC instructions emitted.");
@@ -32,19 +35,30 @@ namespace {
class ARMMCCodeEmitter : public MCCodeEmitter {
ARMMCCodeEmitter(const ARMMCCodeEmitter &); // DO NOT IMPLEMENT
void operator=(const ARMMCCodeEmitter &); // DO NOT IMPLEMENT
- const TargetMachine &TM;
- const TargetInstrInfo &TII;
- const ARMSubtarget *Subtarget;
- MCContext &Ctx;
+ const MCInstrInfo &MCII;
+ const MCSubtargetInfo &STI;
public:
- ARMMCCodeEmitter(TargetMachine &tm, MCContext &ctx)
- : TM(tm), TII(*TM.getInstrInfo()),
- Subtarget(&TM.getSubtarget<ARMSubtarget>()), Ctx(ctx) {
+ ARMMCCodeEmitter(const MCInstrInfo &mcii, const MCSubtargetInfo &sti,
+ MCContext &ctx)
+ : MCII(mcii), STI(sti) {
}
~ARMMCCodeEmitter() {}
+ bool isThumb() const {
+ // FIXME: Can tablegen auto-generate this?
+ return (STI.getFeatureBits() & ARM::ModeThumb) != 0;
+ }
+ bool isThumb2() const {
+ return isThumb() && (STI.getFeatureBits() & ARM::FeatureThumb2) != 0;
+ }
+ bool isTargetDarwin() const {
+ Triple TT(STI.getTargetTriple());
+ Triple::OSType OS = TT.getOS();
+ return OS == Triple::Darwin || OS == Triple::MacOSX || OS == Triple::IOS;
+ }
+
unsigned getMachineSoImmOpValue(unsigned SoImm) const;
// getBinaryCodeForInstr - TableGen'erated function for getting the
@@ -320,9 +334,10 @@ public:
} // end anonymous namespace
-MCCodeEmitter *llvm::createARMMCCodeEmitter(const Target &, TargetMachine &TM,
+MCCodeEmitter *llvm::createARMMCCodeEmitter(const MCInstrInfo &MCII,
+ const MCSubtargetInfo &STI,
MCContext &Ctx) {
- return new ARMMCCodeEmitter(TM, Ctx);
+ return new ARMMCCodeEmitter(MCII, STI, Ctx);
}
/// NEONThumb2DataIPostEncoder - Post-process encoded NEON data-processing
@@ -330,7 +345,7 @@ MCCodeEmitter *llvm::createARMMCCodeEmitter(const Target &, TargetMachine &TM,
/// Thumb2 mode.
unsigned ARMMCCodeEmitter::NEONThumb2DataIPostEncoder(const MCInst &MI,
unsigned EncodedValue) const {
- if (Subtarget->isThumb2()) {
+ if (isThumb2()) {
// NEON Thumb2 data-processsing encodings are very simple: bit 24 is moved
// to bit 12 of the high half-word (i.e. bit 28), and bits 27-24 are
// set to 1111.
@@ -349,7 +364,7 @@ unsigned ARMMCCodeEmitter::NEONThumb2DataIPostEncoder(const MCInst &MI,
/// Thumb2 mode.
unsigned ARMMCCodeEmitter::NEONThumb2LoadStorePostEncoder(const MCInst &MI,
unsigned EncodedValue) const {
- if (Subtarget->isThumb2()) {
+ if (isThumb2()) {
EncodedValue &= 0xF0FFFFFF;
EncodedValue |= 0x09000000;
}
@@ -362,7 +377,7 @@ unsigned ARMMCCodeEmitter::NEONThumb2LoadStorePostEncoder(const MCInst &MI,
/// Thumb2 mode.
unsigned ARMMCCodeEmitter::NEONThumb2DupPostEncoder(const MCInst &MI,
unsigned EncodedValue) const {
- if (Subtarget->isThumb2()) {
+ if (isThumb2()) {
EncodedValue &= 0x00FFFFFF;
EncodedValue |= 0xEE000000;
}
@@ -374,7 +389,7 @@ unsigned ARMMCCodeEmitter::NEONThumb2DupPostEncoder(const MCInst &MI,
/// them to their Thumb2 form if we are currently in Thumb2 mode.
unsigned ARMMCCodeEmitter::
VFPThumb2PostEncoder(const MCInst &MI, unsigned EncodedValue) const {
- if (Subtarget->isThumb2()) {
+ if (isThumb2()) {
EncodedValue &= 0x0FFFFFFF;
EncodedValue |= 0xE0000000;
}
@@ -515,7 +530,7 @@ getBranchTargetOpValue(const MCInst &MI, unsigned OpIdx,
SmallVectorImpl<MCFixup> &Fixups) const {
// FIXME: This really, really shouldn't use TargetMachine. We don't want
// coupling between MC and TM anywhere we can help it.
- if (Subtarget->isThumb2())
+ if (isThumb2())
return
::getBranchTargetOpValue(MI, OpIdx, ARM::fixup_t2_condbranch, Fixups);
return getARMBranchTargetOpValue(MI, OpIdx, Fixups);
@@ -624,7 +639,7 @@ getAddrModeImm12OpValue(const MCInst &MI, unsigned OpIdx,
const MCExpr *Expr = MO.getExpr();
MCFixupKind Kind;
- if (Subtarget->isThumb2())
+ if (isThumb2())
Kind = MCFixupKind(ARM::fixup_t2_ldst_pcrel_12);
else
Kind = MCFixupKind(ARM::fixup_arm_ldst_pcrel_12);
@@ -709,22 +724,22 @@ ARMMCCodeEmitter::getHiLo16ImmOpValue(const MCInst &MI, unsigned OpIdx,
switch (ARM16Expr->getKind()) {
default: assert(0 && "Unsupported ARMFixup");
case ARMMCExpr::VK_ARM_HI16:
- if (!Subtarget->isTargetDarwin() && EvaluateAsPCRel(E))
- Kind = MCFixupKind(Subtarget->isThumb2()
+ if (!isTargetDarwin() && EvaluateAsPCRel(E))
+ Kind = MCFixupKind(isThumb2()
? ARM::fixup_t2_movt_hi16_pcrel
: ARM::fixup_arm_movt_hi16_pcrel);
else
- Kind = MCFixupKind(Subtarget->isThumb2()
+ Kind = MCFixupKind(isThumb2()
? ARM::fixup_t2_movt_hi16
: ARM::fixup_arm_movt_hi16);
break;
case ARMMCExpr::VK_ARM_LO16:
- if (!Subtarget->isTargetDarwin() && EvaluateAsPCRel(E))
- Kind = MCFixupKind(Subtarget->isThumb2()
+ if (!isTargetDarwin() && EvaluateAsPCRel(E))
+ Kind = MCFixupKind(isThumb2()
? ARM::fixup_t2_movw_lo16_pcrel
: ARM::fixup_arm_movw_lo16_pcrel);
else
- Kind = MCFixupKind(Subtarget->isThumb2()
+ Kind = MCFixupKind(isThumb2()
? ARM::fixup_t2_movw_lo16
: ARM::fixup_arm_movw_lo16);
break;
@@ -898,7 +913,7 @@ getAddrMode5OpValue(const MCInst &MI, unsigned OpIdx,
assert(MO.isExpr() && "Unexpected machine operand type!");
const MCExpr *Expr = MO.getExpr();
MCFixupKind Kind;
- if (Subtarget->isThumb2())
+ if (isThumb2())
Kind = MCFixupKind(ARM::fixup_t2_pcrel_10);
else
Kind = MCFixupKind(ARM::fixup_arm_pcrel_10);
@@ -1274,21 +1289,21 @@ void ARMMCCodeEmitter::
EncodeInstruction(const MCInst &MI, raw_ostream &OS,
SmallVectorImpl<MCFixup> &Fixups) const {
// Pseudo instructions don't get encoded.
- const MCInstrDesc &Desc = TII.get(MI.getOpcode());
+ const MCInstrDesc &Desc = MCII.get(MI.getOpcode());
uint64_t TSFlags = Desc.TSFlags;
if ((TSFlags & ARMII::FormMask) == ARMII::Pseudo)
return;
+
int Size;
- // Basic size info comes from the TSFlags field.
- switch ((TSFlags & ARMII::SizeMask) >> ARMII::SizeShift) {
- default: llvm_unreachable("Unexpected instruction size!");
- case ARMII::Size2Bytes: Size = 2; break;
- case ARMII::Size4Bytes: Size = 4; break;
- }
+ if (Desc.getSize() == 2 || Desc.getSize() == 4)
+ Size = Desc.getSize();
+ else
+ llvm_unreachable("Unexpected instruction size!");
+
uint32_t Binary = getBinaryCodeForInstr(MI, Fixups);
// Thumb 32-bit wide instructions need to emit the high order halfword
// first.
- if (Subtarget->isThumb() && Size == 4) {
+ if (isThumb() && Size == 4) {
EmitConstant(Binary >> 16, 2, OS);
EmitConstant(Binary & 0xffff, 2, OS);
} else
diff --git a/lib/Target/ARM/ARMMCInstLower.cpp b/lib/Target/ARM/ARMMCInstLower.cpp
index 59d6050..7411b59 100644
--- a/lib/Target/ARM/ARMMCInstLower.cpp
+++ b/lib/Target/ARM/ARMMCInstLower.cpp
@@ -23,43 +23,94 @@
using namespace llvm;
-static MCOperand GetSymbolRef(const MachineOperand &MO, const MCSymbol *Symbol,
- ARMAsmPrinter &Printer) {
- MCContext &Ctx = Printer.OutContext;
+MCOperand ARMAsmPrinter::GetSymbolRef(const MachineOperand &MO,
+ const MCSymbol *Symbol) {
const MCExpr *Expr;
switch (MO.getTargetFlags()) {
default: {
- Expr = MCSymbolRefExpr::Create(Symbol, MCSymbolRefExpr::VK_None, Ctx);
+ Expr = MCSymbolRefExpr::Create(Symbol, MCSymbolRefExpr::VK_None,
+ OutContext);
switch (MO.getTargetFlags()) {
default:
assert(0 && "Unknown target flag on symbol operand");
case 0:
break;
case ARMII::MO_LO16:
- Expr = MCSymbolRefExpr::Create(Symbol, MCSymbolRefExpr::VK_None, Ctx);
- Expr = ARMMCExpr::CreateLower16(Expr, Ctx);
+ Expr = MCSymbolRefExpr::Create(Symbol, MCSymbolRefExpr::VK_None,
+ OutContext);
+ Expr = ARMMCExpr::CreateLower16(Expr, OutContext);
break;
case ARMII::MO_HI16:
- Expr = MCSymbolRefExpr::Create(Symbol, MCSymbolRefExpr::VK_None, Ctx);
- Expr = ARMMCExpr::CreateUpper16(Expr, Ctx);
+ Expr = MCSymbolRefExpr::Create(Symbol, MCSymbolRefExpr::VK_None,
+ OutContext);
+ Expr = ARMMCExpr::CreateUpper16(Expr, OutContext);
break;
}
break;
}
case ARMII::MO_PLT:
- Expr = MCSymbolRefExpr::Create(Symbol, MCSymbolRefExpr::VK_ARM_PLT, Ctx);
+ Expr = MCSymbolRefExpr::Create(Symbol, MCSymbolRefExpr::VK_ARM_PLT,
+ OutContext);
break;
}
if (!MO.isJTI() && MO.getOffset())
Expr = MCBinaryExpr::CreateAdd(Expr,
- MCConstantExpr::Create(MO.getOffset(), Ctx),
- Ctx);
+ MCConstantExpr::Create(MO.getOffset(),
+ OutContext),
+ OutContext);
return MCOperand::CreateExpr(Expr);
}
+bool ARMAsmPrinter::lowerOperand(const MachineOperand &MO,
+ MCOperand &MCOp) {
+ switch (MO.getType()) {
+ default:
+ assert(0 && "unknown operand type");
+ return false;
+ case MachineOperand::MO_Register:
+ // Ignore all non-CPSR implicit register operands.
+ if (MO.isImplicit() && MO.getReg() != ARM::CPSR)
+ return false;
+ assert(!MO.getSubReg() && "Subregs should be eliminated!");
+ MCOp = MCOperand::CreateReg(MO.getReg());
+ break;
+ case MachineOperand::MO_Immediate:
+ MCOp = MCOperand::CreateImm(MO.getImm());
+ break;
+ case MachineOperand::MO_MachineBasicBlock:
+ MCOp = MCOperand::CreateExpr(MCSymbolRefExpr::Create(
+ MO.getMBB()->getSymbol(), OutContext));
+ break;
+ case MachineOperand::MO_GlobalAddress:
+ MCOp = GetSymbolRef(MO, Mang->getSymbol(MO.getGlobal()));
+ break;
+ case MachineOperand::MO_ExternalSymbol:
+ MCOp = GetSymbolRef(MO,
+ GetExternalSymbolSymbol(MO.getSymbolName()));
+ break;
+ case MachineOperand::MO_JumpTableIndex:
+ MCOp = GetSymbolRef(MO, GetJTISymbol(MO.getIndex()));
+ break;
+ case MachineOperand::MO_ConstantPoolIndex:
+ MCOp = GetSymbolRef(MO, GetCPISymbol(MO.getIndex()));
+ break;
+ case MachineOperand::MO_BlockAddress:
+ MCOp = GetSymbolRef(MO, GetBlockAddressSymbol(MO.getBlockAddress()));
+ break;
+ case MachineOperand::MO_FPImmediate: {
+ APFloat Val = MO.getFPImm()->getValueAPF();
+ bool ignored;
+ Val.convert(APFloat::IEEEdouble, APFloat::rmTowardZero, &ignored);
+ MCOp = MCOperand::CreateFPImm(Val.convertToDouble());
+ break;
+ }
+ }
+ return true;
+}
+
void llvm::LowerARMMachineInstrToMCInst(const MachineInstr *MI, MCInst &OutMI,
ARMAsmPrinter &AP) {
OutMI.setOpcode(MI->getOpcode());
@@ -68,48 +119,7 @@ void llvm::LowerARMMachineInstrToMCInst(const MachineInstr *MI, MCInst &OutMI,
const MachineOperand &MO = MI->getOperand(i);
MCOperand MCOp;
- switch (MO.getType()) {
- default:
- MI->dump();
- assert(0 && "unknown operand type");
- case MachineOperand::MO_Register:
- // Ignore all non-CPSR implicit register operands.
- if (MO.isImplicit() && MO.getReg() != ARM::CPSR) continue;
- assert(!MO.getSubReg() && "Subregs should be eliminated!");
- MCOp = MCOperand::CreateReg(MO.getReg());
- break;
- case MachineOperand::MO_Immediate:
- MCOp = MCOperand::CreateImm(MO.getImm());
- break;
- case MachineOperand::MO_MachineBasicBlock:
- MCOp = MCOperand::CreateExpr(MCSymbolRefExpr::Create(
- MO.getMBB()->getSymbol(), AP.OutContext));
- break;
- case MachineOperand::MO_GlobalAddress:
- MCOp = GetSymbolRef(MO, AP.Mang->getSymbol(MO.getGlobal()), AP);
- break;
- case MachineOperand::MO_ExternalSymbol:
- MCOp = GetSymbolRef(MO,
- AP.GetExternalSymbolSymbol(MO.getSymbolName()), AP);
- break;
- case MachineOperand::MO_JumpTableIndex:
- MCOp = GetSymbolRef(MO, AP.GetJTISymbol(MO.getIndex()), AP);
- break;
- case MachineOperand::MO_ConstantPoolIndex:
- MCOp = GetSymbolRef(MO, AP.GetCPISymbol(MO.getIndex()), AP);
- break;
- case MachineOperand::MO_BlockAddress:
- MCOp = GetSymbolRef(MO,AP.GetBlockAddressSymbol(MO.getBlockAddress()),AP);
- break;
- case MachineOperand::MO_FPImmediate: {
- APFloat Val = MO.getFPImm()->getValueAPF();
- bool ignored;
- Val.convert(APFloat::IEEEdouble, APFloat::rmTowardZero, &ignored);
- MCOp = MCOperand::CreateFPImm(Val.convertToDouble());
- break;
- }
- }
-
- OutMI.addOperand(MCOp);
+ if (AP.lowerOperand(MO, MCOp))
+ OutMI.addOperand(MCOp);
}
}
diff --git a/lib/Target/ARM/ARMSubtarget.cpp b/lib/Target/ARM/ARMSubtarget.cpp
index a7010c5..1cab9e4 100644
--- a/lib/Target/ARM/ARMSubtarget.cpp
+++ b/lib/Target/ARM/ARMSubtarget.cpp
@@ -18,9 +18,8 @@
#include "llvm/Support/CommandLine.h"
#include "llvm/ADT/SmallVector.h"
-#define GET_SUBTARGETINFO_CTOR
-#define GET_SUBTARGETINFO_MC_DESC
#define GET_SUBTARGETINFO_TARGET_DESC
+#define GET_SUBTARGETINFO_CTOR
#include "ARMGenSubtargetInfo.inc"
using namespace llvm;
@@ -37,17 +36,24 @@ StrictAlign("arm-strict-align", cl::Hidden,
cl::desc("Disallow all unaligned memory accesses"));
ARMSubtarget::ARMSubtarget(const std::string &TT, const std::string &CPU,
- const std::string &FS, bool isT)
- : ARMGenSubtargetInfo()
- , ARMArchVersion(V4)
+ const std::string &FS)
+ : ARMGenSubtargetInfo(TT, CPU, FS)
, ARMProcFamily(Others)
- , ARMFPUType(None)
+ , HasV4TOps(false)
+ , HasV5TOps(false)
+ , HasV5TEOps(false)
+ , HasV6Ops(false)
+ , HasV6T2Ops(false)
+ , HasV7Ops(false)
+ , HasVFPv2(false)
+ , HasVFPv3(false)
+ , HasNEON(false)
, UseNEONForSinglePrecisionFP(false)
, SlowFPVMLx(false)
, HasVMLxForwarding(false)
, SlowFPBrcc(false)
- , IsThumb(isT)
- , ThumbMode(Thumb1)
+ , InThumbMode(false)
+ , HasThumb2(false)
, NoARM(false)
, PostRAScheduler(false)
, IsR9Reserved(ReserveR9)
@@ -68,78 +74,25 @@ ARMSubtarget::ARMSubtarget(const std::string &TT, const std::string &CPU,
, TargetTriple(TT)
, TargetABI(ARM_ABI_APCS) {
// Determine default and user specified characteristics
-
- // When no arch is specified either by CPU or by attributes, make the default
- // ARMv4T.
- const char *ARMArchFeature = "";
if (CPUString.empty())
CPUString = "generic";
- if (CPUString == "generic" && (FS.empty() || FS == "generic")) {
- ARMArchVersion = V4T;
- ARMArchFeature = "+v4t";
- }
-
- // Set the boolean corresponding to the current target triple, or the default
- // if one cannot be determined, to true.
- unsigned Len = TT.length();
- unsigned Idx = 0;
-
- if (Len >= 5 && TT.substr(0, 4) == "armv")
- Idx = 4;
- else if (Len >= 6 && TT.substr(0, 5) == "thumb") {
- IsThumb = true;
- if (Len >= 7 && TT[5] == 'v')
- Idx = 6;
- }
- if (Idx) {
- unsigned SubVer = TT[Idx];
- if (SubVer >= '7' && SubVer <= '9') {
- ARMArchVersion = V7A;
- ARMArchFeature = "+v7a";
- if (Len >= Idx+2 && TT[Idx+1] == 'm') {
- ARMArchVersion = V7M;
- ARMArchFeature = "+v7m";
- } else if (Len >= Idx+3 && TT[Idx+1] == 'e'&& TT[Idx+2] == 'm') {
- ARMArchVersion = V7EM;
- ARMArchFeature = "+v7em";
- }
- } else if (SubVer == '6') {
- ARMArchVersion = V6;
- ARMArchFeature = "+v6";
- if (Len >= Idx+3 && TT[Idx+1] == 't' && TT[Idx+2] == '2') {
- ARMArchVersion = V6T2;
- ARMArchFeature = "+v6t2";
- }
- } else if (SubVer == '5') {
- ARMArchVersion = V5T;
- ARMArchFeature = "+v5t";
- if (Len >= Idx+3 && TT[Idx+1] == 't' && TT[Idx+2] == 'e') {
- ARMArchVersion = V5TE;
- ARMArchFeature = "+v5te";
- }
- } else if (SubVer == '4') {
- if (Len >= Idx+2 && TT[Idx+1] == 't') {
- ARMArchVersion = V4T;
- ARMArchFeature = "+v4t";
- } else {
- ARMArchVersion = V4;
- ARMArchFeature = "";
- }
- }
- }
-
- if (TT.find("eabi") != std::string::npos)
- TargetABI = ARM_ABI_AAPCS;
// Insert the architecture feature derived from the target triple into the
// feature string. This is important for setting features that are implied
// based on the architecture version.
- std::string FSWithArch = std::string(ARMArchFeature);
- if (FSWithArch.empty())
- FSWithArch = FS;
- else if (!FS.empty())
- FSWithArch = FSWithArch + "," + FS;
- ParseSubtargetFeatures(FSWithArch, CPUString);
+ std::string ArchFS = ARM_MC::ParseARMTriple(TT);
+ if (!FS.empty()) {
+ if (!ArchFS.empty())
+ ArchFS = ArchFS + "," + FS;
+ else
+ ArchFS = FS;
+ }
+ ParseSubtargetFeatures(CPUString, ArchFS);
+
+ // Thumb2 implies at least V6T2. FIXME: Fix tests to explicitly specify a
+ // ARM version or CPU and then remove this.
+ if (!HasV6T2Ops && hasThumb2())
+ HasV4TOps = HasV5TOps = HasV5TEOps = HasV6Ops = HasV6T2Ops = true;
// Initialize scheduling itinerary for the specified CPU.
InstrItins = getInstrItineraryForCPU(CPUString);
@@ -147,11 +100,8 @@ ARMSubtarget::ARMSubtarget(const std::string &TT, const std::string &CPU,
// After parsing Itineraries, set ItinData.IssueWidth.
computeIssueWidth();
- // Thumb2 implies at least V6T2.
- if (ARMArchVersion >= V6T2)
- ThumbMode = Thumb2;
- else if (ThumbMode >= Thumb2)
- ARMArchVersion = V6T2;
+ if (TT.find("eabi") != std::string::npos)
+ TargetABI = ARM_ABI_AAPCS;
if (isAAPCS_ABI())
stackAlignment = 8;
@@ -159,7 +109,7 @@ ARMSubtarget::ARMSubtarget(const std::string &TT, const std::string &CPU,
if (!isTargetDarwin())
UseMovt = hasV6T2Ops();
else {
- IsR9Reserved = ReserveR9 | (ARMArchVersion < V6);
+ IsR9Reserved = ReserveR9 | !HasV6Ops;
UseMovt = DarwinUseMOVT && hasV6T2Ops();
}
diff --git a/lib/Target/ARM/ARMSubtarget.h b/lib/Target/ARM/ARMSubtarget.h
index 66e4426..c650872 100644
--- a/lib/Target/ARM/ARMSubtarget.h
+++ b/lib/Target/ARM/ARMSubtarget.h
@@ -14,6 +14,7 @@
#ifndef ARMSUBTARGET_H
#define ARMSUBTARGET_H
+#include "MCTargetDesc/ARMMCTargetDesc.h"
#include "llvm/Target/TargetSubtargetInfo.h"
#include "llvm/MC/MCInstrItineraries.h"
#include "llvm/ADT/Triple.h"
@@ -24,35 +25,31 @@
namespace llvm {
class GlobalValue;
+class StringRef;
class ARMSubtarget : public ARMGenSubtargetInfo {
protected:
- enum ARMArchEnum {
- V4, V4T, V5T, V5TE, V6, V6M, V6T2, V7A, V7M, V7EM
- };
-
enum ARMProcFamilyEnum {
Others, CortexA8, CortexA9
};
- enum ARMFPEnum {
- None, VFPv2, VFPv3, NEON
- };
-
- enum ThumbTypeEnum {
- Thumb1,
- Thumb2
- };
-
- /// ARMArchVersion - ARM architecture version: V4, V4T (base), V5T, V5TE,
- /// V6, V6T2, V7A, V7M, V7EM.
- ARMArchEnum ARMArchVersion;
-
/// ARMProcFamily - ARM processor family: Cortex-A8, Cortex-A9, and others.
ARMProcFamilyEnum ARMProcFamily;
- /// ARMFPUType - Floating Point Unit type.
- ARMFPEnum ARMFPUType;
+ /// HasV4TOps, HasV5TOps, HasV5TEOps, HasV6Ops, HasV6T2Ops, HasV7Ops -
+ /// Specify whether target support specific ARM ISA variants.
+ bool HasV4TOps;
+ bool HasV5TOps;
+ bool HasV5TEOps;
+ bool HasV6Ops;
+ bool HasV6T2Ops;
+ bool HasV7Ops;
+
+ /// HasVFPv2, HasVFPv3, HasNEON - Specify what floating point ISAs are
+ /// supported.
+ bool HasVFPv2;
+ bool HasVFPv3;
+ bool HasNEON;
/// UseNEONForSinglePrecisionFP - if the NEONFP attribute has been
/// specified. Use the method useNEONForSinglePrecisionFP() to
@@ -70,11 +67,11 @@ protected:
/// SlowFPBrcc - True if floating point compare + branch is slow.
bool SlowFPBrcc;
- /// IsThumb - True if we are in thumb mode, false if in ARM mode.
- bool IsThumb;
+ /// InThumbMode - True if compiling for Thumb, false for ARM.
+ bool InThumbMode;
- /// ThumbMode - Indicates supported Thumb version.
- ThumbTypeEnum ThumbMode;
+ /// HasThumb2 - True if Thumb2 instructions are supported.
+ bool HasThumb2;
/// NoARM - True if subtarget does not support ARM mode execution.
bool NoARM;
@@ -161,7 +158,7 @@ protected:
/// of the specified triple.
///
ARMSubtarget(const std::string &TT, const std::string &CPU,
- const std::string &FS, bool isThumb);
+ const std::string &FS);
/// getMaxInlineSizeThreshold - Returns the maximum memset / memcpy size
/// that still makes it profitable to inline the call.
@@ -172,27 +169,28 @@ protected:
}
/// ParseSubtargetFeatures - Parses features string setting specified
/// subtarget options. Definition of function is auto generated by tblgen.
- void ParseSubtargetFeatures(const std::string &FS, const std::string &CPU);
+ void ParseSubtargetFeatures(StringRef CPU, StringRef FS);
void computeIssueWidth();
- bool hasV4TOps() const { return ARMArchVersion >= V4T; }
- bool hasV5TOps() const { return ARMArchVersion >= V5T; }
- bool hasV5TEOps() const { return ARMArchVersion >= V5TE; }
- bool hasV6Ops() const { return ARMArchVersion >= V6; }
- bool hasV6T2Ops() const { return ARMArchVersion >= V6T2; }
- bool hasV7Ops() const { return ARMArchVersion >= V7A; }
+ bool hasV4TOps() const { return HasV4TOps; }
+ bool hasV5TOps() const { return HasV5TOps; }
+ bool hasV5TEOps() const { return HasV5TEOps; }
+ bool hasV6Ops() const { return HasV6Ops; }
+ bool hasV6T2Ops() const { return HasV6T2Ops; }
+ bool hasV7Ops() const { return HasV7Ops; }
bool isCortexA8() const { return ARMProcFamily == CortexA8; }
bool isCortexA9() const { return ARMProcFamily == CortexA9; }
bool hasARMOps() const { return !NoARM; }
- bool hasVFP2() const { return ARMFPUType >= VFPv2; }
- bool hasVFP3() const { return ARMFPUType >= VFPv3; }
- bool hasNEON() const { return ARMFPUType >= NEON; }
+ bool hasVFP2() const { return HasVFPv2; }
+ bool hasVFP3() const { return HasVFPv3; }
+ bool hasNEON() const { return HasNEON; }
bool useNEONForSinglePrecisionFP() const {
return hasNEON() && UseNEONForSinglePrecisionFP; }
+
bool hasDivide() const { return HasHardwareDivide; }
bool hasT2ExtractPack() const { return HasT2ExtractPack; }
bool hasDataBarrier() const { return HasDataBarrier; }
@@ -216,10 +214,10 @@ protected:
bool isAPCS_ABI() const { return TargetABI == ARM_ABI_APCS; }
bool isAAPCS_ABI() const { return TargetABI == ARM_ABI_AAPCS; }
- bool isThumb() const { return IsThumb; }
- bool isThumb1Only() const { return IsThumb && (ThumbMode == Thumb1); }
- bool isThumb2() const { return IsThumb && (ThumbMode == Thumb2); }
- bool hasThumb2() const { return ThumbMode >= Thumb2; }
+ bool isThumb() const { return InThumbMode; }
+ bool isThumb1Only() const { return InThumbMode && !HasThumb2; }
+ bool isThumb2() const { return InThumbMode && HasThumb2; }
+ bool hasThumb2() const { return HasThumb2; }
bool isR9Reserved() const { return IsR9Reserved; }
diff --git a/lib/Target/ARM/ARMTargetMachine.cpp b/lib/Target/ARM/ARMTargetMachine.cpp
index 80e7d55..f0b176a 100644
--- a/lib/Target/ARM/ARMTargetMachine.cpp
+++ b/lib/Target/ARM/ARMTargetMachine.cpp
@@ -11,7 +11,6 @@
//===----------------------------------------------------------------------===//
#include "ARMTargetMachine.h"
-#include "ARMMCAsmInfo.h"
#include "ARMFrameLowering.h"
#include "ARM.h"
#include "llvm/PassManager.h"
@@ -22,15 +21,6 @@
#include "llvm/Target/TargetRegistry.h"
using namespace llvm;
-static MCAsmInfo *createMCAsmInfo(const Target &T, StringRef TT) {
- Triple TheTriple(TT);
-
- if (TheTriple.isOSDarwin())
- return new ARMMCAsmInfoDarwin();
-
- return new ARMELFMCAsmInfo();
-}
-
// This is duplicated code. Refactor this.
static MCStreamer *createMCStreamer(const Target &T, const std::string &TT,
MCContext &Ctx, TargetAsmBackend &TAB,
@@ -56,10 +46,6 @@ extern "C" void LLVMInitializeARMTarget() {
RegisterTargetMachine<ARMTargetMachine> X(TheARMTarget);
RegisterTargetMachine<ThumbTargetMachine> Y(TheThumbTarget);
- // Register the target asm info.
- RegisterAsmInfoFn A(TheARMTarget, createMCAsmInfo);
- RegisterAsmInfoFn B(TheThumbTarget, createMCAsmInfo);
-
// Register the MC Code Emitter
TargetRegistry::RegisterCodeEmitter(TheARMTarget, createARMMCCodeEmitter);
TargetRegistry::RegisterCodeEmitter(TheThumbTarget, createARMMCCodeEmitter);
@@ -79,10 +65,9 @@ extern "C" void LLVMInitializeARMTarget() {
ARMBaseTargetMachine::ARMBaseTargetMachine(const Target &T,
const std::string &TT,
const std::string &CPU,
- const std::string &FS,
- bool isThumb)
- : LLVMTargetMachine(T, TT),
- Subtarget(TT, CPU, FS, isThumb),
+ const std::string &FS)
+ : LLVMTargetMachine(T, TT, CPU, FS),
+ Subtarget(TT, CPU, FS),
JITInfo(),
InstrItins(Subtarget.getInstrItineraryData()) {
DefRelocModel = getRelocationModel();
@@ -95,7 +80,7 @@ ARMBaseTargetMachine::ARMBaseTargetMachine(const Target &T,
ARMTargetMachine::ARMTargetMachine(const Target &T, const std::string &TT,
const std::string &CPU,
const std::string &FS)
- : ARMBaseTargetMachine(T, TT, CPU, FS, false), InstrInfo(Subtarget),
+ : ARMBaseTargetMachine(T, TT, CPU, FS), InstrInfo(Subtarget),
DataLayout(Subtarget.isAPCS_ABI() ?
std::string("e-p:32:32-f64:32:64-i64:32:64-"
"v128:32:128-v64:32:64-n32") :
@@ -113,7 +98,7 @@ ARMTargetMachine::ARMTargetMachine(const Target &T, const std::string &TT,
ThumbTargetMachine::ThumbTargetMachine(const Target &T, const std::string &TT,
const std::string &CPU,
const std::string &FS)
- : ARMBaseTargetMachine(T, TT, CPU, FS, true),
+ : ARMBaseTargetMachine(T, TT, CPU, FS),
InstrInfo(Subtarget.hasThumb2()
? ((ARMBaseInstrInfo*)new Thumb2InstrInfo(Subtarget))
: ((ARMBaseInstrInfo*)new Thumb1InstrInfo(Subtarget))),
diff --git a/lib/Target/ARM/ARMTargetMachine.h b/lib/Target/ARM/ARMTargetMachine.h
index a4a7927..bc3d46a 100644
--- a/lib/Target/ARM/ARMTargetMachine.h
+++ b/lib/Target/ARM/ARMTargetMachine.h
@@ -41,8 +41,7 @@ private:
public:
ARMBaseTargetMachine(const Target &T, const std::string &TT,
- const std::string &CPU, const std::string &FS,
- bool isThumb);
+ const std::string &CPU, const std::string &FS);
virtual ARMJITInfo *getJITInfo() { return &JITInfo; }
virtual const ARMSubtarget *getSubtargetImpl() const { return &Subtarget; }
diff --git a/lib/Target/ARM/AsmParser/ARMAsmParser.cpp b/lib/Target/ARM/AsmParser/ARMAsmParser.cpp
index 6952c38..a474127 100644
--- a/lib/Target/ARM/AsmParser/ARMAsmParser.cpp
+++ b/lib/Target/ARM/AsmParser/ARMAsmParser.cpp
@@ -20,14 +20,17 @@
#include "llvm/MC/MCStreamer.h"
#include "llvm/MC/MCExpr.h"
#include "llvm/MC/MCInst.h"
+#include "llvm/MC/MCSubtargetInfo.h"
#include "llvm/Target/TargetRegistry.h"
#include "llvm/Target/TargetAsmParser.h"
#include "llvm/Support/SourceMgr.h"
#include "llvm/Support/raw_ostream.h"
+#include "llvm/ADT/OwningPtr.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/ADT/StringSwitch.h"
#include "llvm/ADT/Twine.h"
+
using namespace llvm;
namespace {
@@ -35,8 +38,8 @@ namespace {
class ARMOperand;
class ARMAsmParser : public TargetAsmParser {
+ MCSubtargetInfo &STI;
MCAsmParser &Parser;
- TargetMachine &TM;
MCAsmParser &getParser() const { return Parser; }
MCAsmLexer &getLexer() const { return Parser.getLexer(); }
@@ -47,7 +50,7 @@ class ARMAsmParser : public TargetAsmParser {
int TryParseRegister();
virtual bool ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc);
bool TryParseRegisterWithWriteBack(SmallVectorImpl<MCParsedAsmOperand*> &);
- bool TryParseShiftRegister(SmallVectorImpl<MCParsedAsmOperand*> &);
+ int TryParseShiftRegister(SmallVectorImpl<MCParsedAsmOperand*> &);
bool ParseRegisterList(SmallVectorImpl<MCParsedAsmOperand*> &);
bool ParseMemory(SmallVectorImpl<MCParsedAsmOperand*> &,
ARMII::AddrMode AddrMode);
@@ -79,6 +82,18 @@ class ARMAsmParser : public TargetAsmParser {
void GetMnemonicAcceptInfo(StringRef Mnemonic, bool &CanAcceptCarrySet,
bool &CanAcceptPredicationCode);
+ bool isThumb() const {
+ // FIXME: Can tablegen auto-generate this?
+ return (STI.getFeatureBits() & ARM::ModeThumb) != 0;
+ }
+ bool isThumbOne() const {
+ return isThumb() && (STI.getFeatureBits() & ARM::FeatureThumb2) == 0;
+ }
+ void SwitchMode() {
+ unsigned FB = ComputeAvailableFeatures(STI.ToggleFeature(ARM::ModeThumb));
+ setAvailableFeatures(FB);
+ }
+
/// @name Auto-generated Match Functions
/// {
@@ -113,13 +128,13 @@ class ARMAsmParser : public TargetAsmParser {
const SmallVectorImpl<MCParsedAsmOperand*> &);
public:
- ARMAsmParser(const Target &T, MCAsmParser &_Parser, TargetMachine &_TM)
- : TargetAsmParser(T), Parser(_Parser), TM(_TM) {
- MCAsmParserExtension::Initialize(_Parser);
- // Initialize the set of available features.
- setAvailableFeatures(ComputeAvailableFeatures(
- &TM.getSubtarget<ARMSubtarget>()));
- }
+ ARMAsmParser(MCSubtargetInfo &_STI, MCAsmParser &_Parser)
+ : TargetAsmParser(), STI(_STI), Parser(_Parser) {
+ MCAsmParserExtension::Initialize(_Parser);
+
+ // Initialize the set of available features.
+ setAvailableFeatures(ComputeAvailableFeatures(STI.getFeatureBits()));
+ }
virtual bool ParseInstruction(StringRef Name, SMLoc NameLoc,
SmallVectorImpl<MCParsedAsmOperand*> &Operands);
@@ -146,6 +161,7 @@ class ARMOperand : public MCParsedAsmOperand {
RegisterList,
DPRRegisterList,
SPRRegisterList,
+ ShiftedRegister,
Shifter,
Token
} Kind;
@@ -207,8 +223,14 @@ class ARMOperand : public MCParsedAsmOperand {
struct {
ARM_AM::ShiftOpc ShiftTy;
- unsigned RegNum;
+ unsigned Imm;
} Shift;
+ struct {
+ ARM_AM::ShiftOpc ShiftTy;
+ unsigned SrcReg;
+ unsigned ShiftReg;
+ unsigned ShiftImm;
+ } ShiftedReg;
};
ARMOperand(KindTy K) : MCParsedAsmOperand(), Kind(K) {}
@@ -255,6 +277,9 @@ public:
case Shifter:
Shift = o.Shift;
break;
+ case ShiftedRegister:
+ ShiftedReg = o.ShiftedReg;
+ break;
}
}
@@ -358,6 +383,30 @@ public:
int64_t Value = CE->getValue();
return Value >= 0 && Value < 256;
}
+ bool isImm0_7() const {
+ if (Kind != Immediate)
+ return false;
+ const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
+ if (!CE) return false;
+ int64_t Value = CE->getValue();
+ return Value >= 0 && Value < 8;
+ }
+ bool isImm0_15() const {
+ if (Kind != Immediate)
+ return false;
+ const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
+ if (!CE) return false;
+ int64_t Value = CE->getValue();
+ return Value >= 0 && Value < 16;
+ }
+ bool isImm0_65535() const {
+ if (Kind != Immediate)
+ return false;
+ const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
+ if (!CE) return false;
+ int64_t Value = CE->getValue();
+ return Value >= 0 && Value < 65536;
+ }
bool isT2SOImm() const {
if (Kind != Immediate)
return false;
@@ -374,6 +423,7 @@ public:
bool isMemBarrierOpt() const { return Kind == MemBarrierOpt; }
bool isMemory() const { return Kind == Memory; }
bool isShifter() const { return Kind == Shifter; }
+ bool isShiftedReg() const { return Kind == ShiftedRegister; }
bool isMemMode2() const {
if (getMemAddrMode() != ARMII::AddrMode2)
return false;
@@ -504,6 +554,18 @@ public:
Inst.addOperand(MCOperand::CreateReg(getReg()));
}
+ void addShiftedRegOperands(MCInst &Inst, unsigned N) const {
+ assert(N == 3 && "Invalid number of operands!");
+ assert(isShiftedReg() && "addShiftedRegOperands() on non ShiftedReg!");
+ assert((ShiftedReg.ShiftReg == 0 ||
+ ARM_AM::getSORegOffset(ShiftedReg.ShiftImm) == 0) &&
+ "Invalid shifted register operand!");
+ Inst.addOperand(MCOperand::CreateReg(ShiftedReg.SrcReg));
+ Inst.addOperand(MCOperand::CreateReg(ShiftedReg.ShiftReg));
+ Inst.addOperand(MCOperand::CreateImm(
+ ARM_AM::getSORegOpc(ShiftedReg.ShiftTy, ShiftedReg.ShiftImm)));
+ }
+
void addShifterOperands(MCInst &Inst, unsigned N) const {
assert(N == 1 && "Invalid number of operands!");
Inst.addOperand(MCOperand::CreateImm(
@@ -536,6 +598,21 @@ public:
addExpr(Inst, getImm());
}
+ void addImm0_7Operands(MCInst &Inst, unsigned N) const {
+ assert(N == 1 && "Invalid number of operands!");
+ addExpr(Inst, getImm());
+ }
+
+ void addImm0_15Operands(MCInst &Inst, unsigned N) const {
+ assert(N == 1 && "Invalid number of operands!");
+ addExpr(Inst, getImm());
+ }
+
+ void addImm0_65535Operands(MCInst &Inst, unsigned N) const {
+ assert(N == 1 && "Invalid number of operands!");
+ addExpr(Inst, getImm());
+ }
+
void addT2SOImmOperands(MCInst &Inst, unsigned N) const {
assert(N == 1 && "Invalid number of operands!");
addExpr(Inst, getImm());
@@ -674,7 +751,7 @@ public:
Inst.addOperand(MCOperand::CreateImm(unsigned(getProcIFlags())));
}
- virtual void dump(raw_ostream &OS) const;
+ virtual void print(raw_ostream &OS) const;
static ARMOperand *CreateCondCode(ARMCC::CondCodes CC, SMLoc S) {
ARMOperand *Op = new ARMOperand(CondCode);
@@ -725,6 +802,21 @@ public:
return Op;
}
+ static ARMOperand *CreateShiftedRegister(ARM_AM::ShiftOpc ShTy,
+ unsigned SrcReg,
+ unsigned ShiftReg,
+ unsigned ShiftImm,
+ SMLoc S, SMLoc E) {
+ ARMOperand *Op = new ARMOperand(ShiftedRegister);
+ Op->ShiftedReg.ShiftTy = ShTy;
+ Op->ShiftedReg.SrcReg = SrcReg;
+ Op->ShiftedReg.ShiftReg = ShiftReg;
+ Op->ShiftedReg.ShiftImm = ShiftImm;
+ Op->StartLoc = S;
+ Op->EndLoc = E;
+ return Op;
+ }
+
static ARMOperand *CreateShifter(ARM_AM::ShiftOpc ShTy,
SMLoc S, SMLoc E) {
ARMOperand *Op = new ARMOperand(Shifter);
@@ -828,7 +920,7 @@ public:
} // end anonymous namespace.
-void ARMOperand::dump(raw_ostream &OS) const {
+void ARMOperand::print(raw_ostream &OS) const {
switch (Kind) {
case CondCode:
OS << "<ARMCC::" << ARMCondCodeToString(getCondCode()) << ">";
@@ -889,7 +981,15 @@ void ARMOperand::dump(raw_ostream &OS) const {
OS << "<register " << getReg() << ">";
break;
case Shifter:
- OS << "<shifter " << getShiftOpcStr(Shift.ShiftTy) << ">";
+ OS << "<shifter " << ARM_AM::getShiftOpcStr(Shift.ShiftTy) << ">";
+ break;
+ case ShiftedRegister:
+ OS << "<so_reg"
+ << ShiftedReg.SrcReg
+ << ARM_AM::getShiftOpcStr(ARM_AM::getSORegShOp(ShiftedReg.ShiftImm))
+ << ", " << ShiftedReg.ShiftReg << ", "
+ << ARM_AM::getSORegOffset(ShiftedReg.ShiftImm)
+ << ">";
break;
case RegisterList:
case DPRRegisterList:
@@ -953,11 +1053,12 @@ int ARMAsmParser::TryParseRegister() {
return RegNum;
}
-/// Try to parse a register name. The token must be an Identifier when called,
-/// and if it is a register name the token is eaten and the register number is
-/// returned. Otherwise return -1.
-///
-bool ARMAsmParser::TryParseShiftRegister(
+// Try to parse a shifter (e.g., "lsl <amt>"). On success, return 0.
+// If a recoverable error occurs, return 1. If an irrecoverable error
+// occurs, return -1. An irrecoverable error is one where tokens have been
+// consumed in the process of trying to parse the shifter (i.e., when it is
+// indeed a shifter operand, but malformed).
+int ARMAsmParser::TryParseShiftRegister(
SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
SMLoc S = Parser.getTok().getLoc();
const AsmToken &Tok = Parser.getTok();
@@ -974,18 +1075,69 @@ bool ARMAsmParser::TryParseShiftRegister(
.Default(ARM_AM::no_shift);
if (ShiftTy == ARM_AM::no_shift)
- return true;
-
- Parser.Lex(); // Eat shift-type operand;
- int RegNum = TryParseRegister();
- if (RegNum == -1)
- return Error(Parser.getTok().getLoc(), "register expected");
+ return 1;
+
+ Parser.Lex(); // Eat the operator.
+
+ // The source register for the shift has already been added to the
+ // operand list, so we need to pop it off and combine it into the shifted
+ // register operand instead.
+ OwningPtr<ARMOperand> PrevOp((ARMOperand*)Operands.pop_back_val());
+ if (!PrevOp->isReg())
+ return Error(PrevOp->getStartLoc(), "shift must be of a register");
+ int SrcReg = PrevOp->getReg();
+ int64_t Imm = 0;
+ int ShiftReg = 0;
+ if (ShiftTy == ARM_AM::rrx) {
+ // RRX Doesn't have an explicit shift amount. The encoder expects
+ // the shift register to be the same as the source register. Seems odd,
+ // but OK.
+ ShiftReg = SrcReg;
+ } else {
+ // Figure out if this is shifted by a constant or a register (for non-RRX).
+ if (Parser.getTok().is(AsmToken::Hash)) {
+ Parser.Lex(); // Eat hash.
+ SMLoc ImmLoc = Parser.getTok().getLoc();
+ const MCExpr *ShiftExpr = 0;
+ if (getParser().ParseExpression(ShiftExpr)) {
+ Error(ImmLoc, "invalid immediate shift value");
+ return -1;
+ }
+ // The expression must be evaluatable as an immediate.
+ const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ShiftExpr);
+ if (!CE) {
+ Error(ImmLoc, "invalid immediate shift value");
+ return -1;
+ }
+ // Range check the immediate.
+ // lsl, ror: 0 <= imm <= 31
+ // lsr, asr: 0 <= imm <= 32
+ Imm = CE->getValue();
+ if (Imm < 0 ||
+ ((ShiftTy == ARM_AM::lsl || ShiftTy == ARM_AM::ror) && Imm > 31) ||
+ ((ShiftTy == ARM_AM::lsr || ShiftTy == ARM_AM::asr) && Imm > 32)) {
+ Error(ImmLoc, "immediate shift value out of range");
+ return -1;
+ }
+ } else if (Parser.getTok().is(AsmToken::Identifier)) {
+ ShiftReg = TryParseRegister();
+ SMLoc L = Parser.getTok().getLoc();
+ if (ShiftReg == -1) {
+ Error (L, "expected immediate or register in shift operand");
+ return -1;
+ }
+ } else {
+ Error (Parser.getTok().getLoc(),
+ "expected immediate or register in shift operand");
+ return -1;
+ }
+ }
- Operands.push_back(ARMOperand::CreateReg(RegNum,S, Parser.getTok().getLoc()));
- Operands.push_back(ARMOperand::CreateShifter(ShiftTy,
+ Operands.push_back(ARMOperand::CreateShiftedRegister(ShiftTy, SrcReg,
+ ShiftReg, Imm,
S, Parser.getTok().getLoc()));
- return false;
+ return 0;
}
@@ -1188,10 +1340,14 @@ tryParseMemBarrierOptOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
unsigned Opt = StringSwitch<unsigned>(OptStr.slice(0, OptStr.size()))
.Case("sy", ARM_MB::SY)
.Case("st", ARM_MB::ST)
+ .Case("sh", ARM_MB::ISH)
.Case("ish", ARM_MB::ISH)
+ .Case("shst", ARM_MB::ISHST)
.Case("ishst", ARM_MB::ISHST)
.Case("nsh", ARM_MB::NSH)
+ .Case("un", ARM_MB::NSH)
.Case("nshst", ARM_MB::NSHST)
+ .Case("unst", ARM_MB::NSHST)
.Case("osh", ARM_MB::OSH)
.Case("oshst", ARM_MB::OSHST)
.Default(~0U);
@@ -1630,15 +1786,18 @@ bool ARMAsmParser::ParseOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands,
default:
Error(Parser.getTok().getLoc(), "unexpected token in operand");
return true;
- case AsmToken::Identifier:
+ case AsmToken::Identifier: {
if (!TryParseRegisterWithWriteBack(Operands))
return false;
- if (!TryParseShiftRegister(Operands))
+ int Res = TryParseShiftRegister(Operands);
+ if (Res == 0) // success
return false;
-
+ else if (Res == -1) // irrecoverable error
+ return true;
// Fall though for the Identifier case that is not a register or a
// special name.
+ }
case AsmToken::Integer: // things like 1f and 2b as a branch targets
case AsmToken::Dot: { // . as a branch target
// This was not a register so parse other operands that start with an
@@ -1790,29 +1949,32 @@ static StringRef SplitMnemonic(StringRef Mnemonic,
Mnemonic == "vqdmlal" || Mnemonic == "bics"))
return Mnemonic;
- // First, split out any predication code.
- unsigned CC = StringSwitch<unsigned>(Mnemonic.substr(Mnemonic.size()-2))
- .Case("eq", ARMCC::EQ)
- .Case("ne", ARMCC::NE)
- .Case("hs", ARMCC::HS)
- .Case("cs", ARMCC::HS)
- .Case("lo", ARMCC::LO)
- .Case("cc", ARMCC::LO)
- .Case("mi", ARMCC::MI)
- .Case("pl", ARMCC::PL)
- .Case("vs", ARMCC::VS)
- .Case("vc", ARMCC::VC)
- .Case("hi", ARMCC::HI)
- .Case("ls", ARMCC::LS)
- .Case("ge", ARMCC::GE)
- .Case("lt", ARMCC::LT)
- .Case("gt", ARMCC::GT)
- .Case("le", ARMCC::LE)
- .Case("al", ARMCC::AL)
- .Default(~0U);
- if (CC != ~0U) {
- Mnemonic = Mnemonic.slice(0, Mnemonic.size() - 2);
- PredicationCode = CC;
+ // First, split out any predication code. Ignore mnemonics we know aren't
+ // predicated but do have a carry-set and so weren't caught above.
+ if (Mnemonic != "adcs") {
+ unsigned CC = StringSwitch<unsigned>(Mnemonic.substr(Mnemonic.size()-2))
+ .Case("eq", ARMCC::EQ)
+ .Case("ne", ARMCC::NE)
+ .Case("hs", ARMCC::HS)
+ .Case("cs", ARMCC::HS)
+ .Case("lo", ARMCC::LO)
+ .Case("cc", ARMCC::LO)
+ .Case("mi", ARMCC::MI)
+ .Case("pl", ARMCC::PL)
+ .Case("vs", ARMCC::VS)
+ .Case("vc", ARMCC::VC)
+ .Case("hi", ARMCC::HI)
+ .Case("ls", ARMCC::LS)
+ .Case("ge", ARMCC::GE)
+ .Case("lt", ARMCC::LT)
+ .Case("gt", ARMCC::GT)
+ .Case("le", ARMCC::LE)
+ .Case("al", ARMCC::AL)
+ .Default(~0U);
+ if (CC != ~0U) {
+ Mnemonic = Mnemonic.slice(0, Mnemonic.size() - 2);
+ PredicationCode = CC;
+ }
}
// Next, determine if we have a carry setting bit. We explicitly ignore all
@@ -1852,9 +2014,6 @@ static StringRef SplitMnemonic(StringRef Mnemonic,
void ARMAsmParser::
GetMnemonicAcceptInfo(StringRef Mnemonic, bool &CanAcceptCarrySet,
bool &CanAcceptPredicationCode) {
- bool isThumbOne = TM.getSubtarget<ARMSubtarget>().isThumb1Only();
- bool isThumb = TM.getSubtarget<ARMSubtarget>().isThumb();
-
if (Mnemonic == "and" || Mnemonic == "lsl" || Mnemonic == "lsr" ||
Mnemonic == "rrx" || Mnemonic == "ror" || Mnemonic == "sub" ||
Mnemonic == "smull" || Mnemonic == "add" || Mnemonic == "adc" ||
@@ -1863,7 +2022,7 @@ GetMnemonicAcceptInfo(StringRef Mnemonic, bool &CanAcceptCarrySet,
Mnemonic == "rsb" || Mnemonic == "rsc" || Mnemonic == "orn" ||
Mnemonic == "sbc" || Mnemonic == "mla" || Mnemonic == "umull" ||
Mnemonic == "eor" || Mnemonic == "smlal" ||
- (Mnemonic == "mov" && !isThumbOne)) {
+ (Mnemonic == "mov" && !isThumbOne())) {
CanAcceptCarrySet = true;
} else {
CanAcceptCarrySet = false;
@@ -1880,7 +2039,7 @@ GetMnemonicAcceptInfo(StringRef Mnemonic, bool &CanAcceptCarrySet,
CanAcceptPredicationCode = true;
}
- if (isThumb)
+ if (isThumb())
if (Mnemonic == "bkpt" || Mnemonic == "mcr" || Mnemonic == "mcrr" ||
Mnemonic == "mrc" || Mnemonic == "mrrc" || Mnemonic == "cdp")
CanAcceptPredicationCode = false;
@@ -1912,20 +2071,22 @@ bool ARMAsmParser::ParseInstruction(StringRef Name, SMLoc NameLoc,
bool CanAcceptCarrySet, CanAcceptPredicationCode;
GetMnemonicAcceptInfo(Head, CanAcceptCarrySet, CanAcceptPredicationCode);
+ // If we had a carry-set on an instruction that can't do that, issue an
+ // error.
+ if (!CanAcceptCarrySet && CarrySetting) {
+ Parser.EatToEndOfStatement();
+ return Error(NameLoc, "instruction '" + Head +
+ "' can not set flags, but 's' suffix specified");
+ }
+
// Add the carry setting operand, if necessary.
//
// FIXME: It would be awesome if we could somehow invent a location such that
// match errors on this operand would print a nice diagnostic about how the
// 's' character in the mnemonic resulted in a CCOut operand.
- if (CanAcceptCarrySet) {
+ if (CanAcceptCarrySet)
Operands.push_back(ARMOperand::CreateCCOut(CarrySetting ? ARM::CPSR : 0,
NameLoc));
- } else {
- // This mnemonic can't ever accept a carry set, but the user wrote one (or
- // misspelled another mnemonic).
-
- // FIXME: Issue a nice error.
- }
// Add the predication code operand, if necessary.
if (CanAcceptPredicationCode) {
@@ -2016,7 +2177,7 @@ MatchAndEmitInstruction(SMLoc IDLoc,
// that updates the condition codes if it ends in 's'. So see if the
// mnemonic ends in 's' and if so try removing the 's' and adding a CCOut
// operand with a value of CPSR.
- else if(MatchResult == Match_MnemonicFail) {
+ else if (MatchResult == Match_MnemonicFail) {
// Get the instruction mnemonic, which is the first token.
StringRef Mnemonic = ((ARMOperand*)Operands[0])->getToken();
if (Mnemonic.substr(Mnemonic.size()-1) == "s") {
@@ -2202,20 +2363,15 @@ bool ARMAsmParser::ParseDirectiveCode(SMLoc L) {
return Error(Parser.getTok().getLoc(), "unexpected token in directive");
Parser.Lex();
- // FIXME: We need to be able switch subtargets at this point so that
- // MatchInstructionImpl() will work when it gets the AvailableFeatures which
- // includes Feature_IsThumb or not to match the right instructions. This is
- // blocked on the FIXME in llvm-mc.cpp when creating the TargetMachine.
- if (Val == 16){
- assert(TM.getSubtarget<ARMSubtarget>().isThumb() &&
- "switching between arm/thumb not yet suppported via .code 16)");
+ if (Val == 16) {
+ if (!isThumb())
+ SwitchMode();
getParser().getStreamer().EmitAssemblerFlag(MCAF_Code16);
- }
- else{
- assert(!TM.getSubtarget<ARMSubtarget>().isThumb() &&
- "switching between thumb/arm not yet suppported via .code 32)");
+ } else {
+ if (isThumb())
+ SwitchMode();
getParser().getStreamer().EmitAssemblerFlag(MCAF_Code32);
- }
+ }
return false;
}
diff --git a/lib/Target/ARM/CMakeLists.txt b/lib/Target/ARM/CMakeLists.txt
index a261ca0..21608d0 100644
--- a/lib/Target/ARM/CMakeLists.txt
+++ b/lib/Target/ARM/CMakeLists.txt
@@ -4,6 +4,7 @@ tablegen(ARMGenRegisterInfo.inc -gen-register-info)
tablegen(ARMGenInstrInfo.inc -gen-instr-info)
tablegen(ARMGenCodeEmitter.inc -gen-emitter)
tablegen(ARMGenMCCodeEmitter.inc -gen-emitter -mc-emitter)
+tablegen(ARMGenMCPseudoLowering.inc -gen-pseudo-lowering)
tablegen(ARMGenAsmWriter.inc -gen-asm-writer)
tablegen(ARMGenAsmMatcher.inc -gen-asm-matcher)
tablegen(ARMGenDAGISel.inc -gen-dag-isel)
@@ -35,7 +36,6 @@ add_llvm_target(ARMCodeGen
ARMMCCodeEmitter.cpp
ARMMCExpr.cpp
ARMLoadStoreOptimizer.cpp
- ARMMCAsmInfo.cpp
ARMMCInstLower.cpp
ARMRegisterInfo.cpp
ARMSelectionDAGInfo.cpp
@@ -65,3 +65,4 @@ add_subdirectory(TargetInfo)
add_subdirectory(AsmParser)
add_subdirectory(Disassembler)
add_subdirectory(InstPrinter)
+add_subdirectory(MCTargetDesc)
diff --git a/lib/Target/ARM/Disassembler/ARMDisassemblerCore.cpp b/lib/Target/ARM/Disassembler/ARMDisassemblerCore.cpp
index fe165b0..d89c80a 100644
--- a/lib/Target/ARM/Disassembler/ARMDisassemblerCore.cpp
+++ b/lib/Target/ARM/Disassembler/ARMDisassemblerCore.cpp
@@ -70,9 +70,10 @@
///
/// { ARM::CCRRegClassID, 0|(1<<MCOI::OptionalDef), 0 }
///
-/// And this maps to one MCOperand with the regsiter kind of ARM::CPSR.
-#define GET_INSTRINFO_MC_DESC
-#include "ARMGenInstrInfo.inc"
+
+namespace llvm {
+extern MCInstrDesc ARMInsts[];
+}
using namespace llvm;
@@ -3092,11 +3093,6 @@ static bool DisassembleNVdVnVmOptImm(MCInst &MI, unsigned Opcode, uint32_t insn,
: decodeNEONRm(insn))));
++OpIdx;
- // Special case handling for VMOVDneon and VMOVQ because they are marked as
- // N3RegFrm.
- if (Opcode == ARM::VMOVDneon || Opcode == ARM::VMOVQ)
- return true;
-
// Dm = Inst{5:3-0} => NEON Rm
// or
// Dm is restricted to D0-D7 if size is 16, D0-D15 otherwise
@@ -3380,7 +3376,7 @@ static bool DisassemblePreLoadFrm(MCInst &MI, unsigned Opcode, uint32_t insn,
static bool DisassembleMiscFrm(MCInst &MI, unsigned Opcode, uint32_t insn,
unsigned short NumOps, unsigned &NumOpsAdded, BO B) {
- if (Opcode == ARM::DMB || Opcode == ARM::DSB) {
+ if (Opcode == ARM::DMB || Opcode == ARM::DSB || Opcode == ARM::ISB) {
// Inst{3-0} encodes the memory barrier option for the variants.
unsigned opt = slice(insn, 3, 0);
switch (opt) {
diff --git a/lib/Target/ARM/InstPrinter/ARMInstPrinter.cpp b/lib/Target/ARM/InstPrinter/ARMInstPrinter.cpp
index 8ae87f8..78d3e47 100644
--- a/lib/Target/ARM/InstPrinter/ARMInstPrinter.cpp
+++ b/lib/Target/ARM/InstPrinter/ARMInstPrinter.cpp
@@ -126,38 +126,6 @@ void ARMInstPrinter::printOperand(const MCInst *MI, unsigned OpNo,
}
}
-static void printSOImm(raw_ostream &O, int64_t V, raw_ostream *CommentStream,
- const MCAsmInfo *MAI) {
- // Break it up into two parts that make up a shifter immediate.
- V = ARM_AM::getSOImmVal(V);
- assert(V != -1 && "Not a valid so_imm value!");
-
- unsigned Imm = ARM_AM::getSOImmValImm(V);
- unsigned Rot = ARM_AM::getSOImmValRot(V);
-
- // Print low-level immediate formation info, per
- // A5.2.3: Data-processing (immediate), and
- // A5.2.4: Modified immediate constants in ARM instructions
- if (Rot) {
- O << "#" << Imm << ", #" << Rot;
- // Pretty printed version.
- if (CommentStream)
- *CommentStream << (int)ARM_AM::rotr32(Imm, Rot) << "\n";
- } else {
- O << "#" << Imm;
- }
-}
-
-
-/// printSOImmOperand - SOImm is 4-bit rotate amount in bits 8-11 with 8-bit
-/// immediate in bits 0-7.
-void ARMInstPrinter::printSOImmOperand(const MCInst *MI, unsigned OpNum,
- raw_ostream &O) {
- const MCOperand &MO = MI->getOperand(OpNum);
- assert(MO.isImm() && "Not a valid so_imm value!");
- printSOImm(O, MO.getImm(), CommentStream, &MAI);
-}
-
// so_reg is a 4-operand unit corresponding to register forms of the A5.1
// "Addressing Mode 1 - Data-processing operands" forms. This includes:
// REG 0 0 - e.g. R5
@@ -174,6 +142,8 @@ void ARMInstPrinter::printSORegOperand(const MCInst *MI, unsigned OpNum,
// Print the shift opc.
ARM_AM::ShiftOpc ShOpc = ARM_AM::getSORegShOp(MO3.getImm());
O << ", " << ARM_AM::getShiftOpcStr(ShOpc);
+ if (ShOpc == ARM_AM::rrx)
+ return;
if (MO2.getReg()) {
O << ' ' << getRegisterName(MO2.getReg());
assert(ARM_AM::getSORegOffset(MO3.getImm()) == 0);
diff --git a/lib/Target/ARM/InstPrinter/ARMInstPrinter.h b/lib/Target/ARM/InstPrinter/ARMInstPrinter.h
index bde0eb9..d5f238b 100644
--- a/lib/Target/ARM/InstPrinter/ARMInstPrinter.h
+++ b/lib/Target/ARM/InstPrinter/ARMInstPrinter.h
@@ -19,11 +19,10 @@
namespace llvm {
class MCOperand;
-class TargetMachine;
class ARMInstPrinter : public MCInstPrinter {
public:
- ARMInstPrinter(TargetMachine &TM, const MCAsmInfo &MAI)
+ ARMInstPrinter(const MCAsmInfo &MAI)
: MCInstPrinter(MAI) {}
virtual void printInst(const MCInst *MI, raw_ostream &O);
@@ -39,8 +38,6 @@ public:
void printOperand(const MCInst *MI, unsigned OpNo, raw_ostream &O);
- void printSOImmOperand(const MCInst *MI, unsigned OpNum, raw_ostream &O);
-
void printSORegOperand(const MCInst *MI, unsigned OpNum, raw_ostream &O);
void printAddrMode2Operand(const MCInst *MI, unsigned OpNum, raw_ostream &O);
diff --git a/lib/Target/ARM/ARMMCAsmInfo.cpp b/lib/Target/ARM/MCTargetDesc/ARMMCAsmInfo.cpp
index 53b4c95..53b4c95 100644
--- a/lib/Target/ARM/ARMMCAsmInfo.cpp
+++ b/lib/Target/ARM/MCTargetDesc/ARMMCAsmInfo.cpp
diff --git a/lib/Target/ARM/ARMMCAsmInfo.h b/lib/Target/ARM/MCTargetDesc/ARMMCAsmInfo.h
index 90f7822..90f7822 100644
--- a/lib/Target/ARM/ARMMCAsmInfo.h
+++ b/lib/Target/ARM/MCTargetDesc/ARMMCAsmInfo.h
diff --git a/lib/Target/ARM/MCTargetDesc/ARMMCTargetDesc.cpp b/lib/Target/ARM/MCTargetDesc/ARMMCTargetDesc.cpp
new file mode 100644
index 0000000..f8fcf2b
--- /dev/null
+++ b/lib/Target/ARM/MCTargetDesc/ARMMCTargetDesc.cpp
@@ -0,0 +1,144 @@
+//===-- ARMMCTargetDesc.cpp - ARM Target Descriptions -----------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file provides ARM specific target descriptions.
+//
+//===----------------------------------------------------------------------===//
+
+#include "ARMMCTargetDesc.h"
+#include "ARMMCAsmInfo.h"
+#include "llvm/MC/MCInstrInfo.h"
+#include "llvm/MC/MCRegisterInfo.h"
+#include "llvm/MC/MCSubtargetInfo.h"
+#include "llvm/Target/TargetRegistry.h"
+
+#define GET_REGINFO_MC_DESC
+#include "ARMGenRegisterInfo.inc"
+
+#define GET_INSTRINFO_MC_DESC
+#include "ARMGenInstrInfo.inc"
+
+#define GET_SUBTARGETINFO_MC_DESC
+#include "ARMGenSubtargetInfo.inc"
+
+using namespace llvm;
+
+std::string ARM_MC::ParseARMTriple(StringRef TT) {
+ // Set the boolean corresponding to the current target triple, or the default
+ // if one cannot be determined, to true.
+ unsigned Len = TT.size();
+ unsigned Idx = 0;
+
+ // FIXME: Enahnce Triple helper class to extract ARM version.
+ bool isThumb = false;
+ if (Len >= 5 && TT.substr(0, 4) == "armv")
+ Idx = 4;
+ else if (Len >= 6 && TT.substr(0, 5) == "thumb") {
+ isThumb = true;
+ if (Len >= 7 && TT[5] == 'v')
+ Idx = 6;
+ }
+
+ std::string ARMArchFeature;
+ if (Idx) {
+ unsigned SubVer = TT[Idx];
+ if (SubVer >= '7' && SubVer <= '9') {
+ if (Len >= Idx+2 && TT[Idx+1] == 'm') {
+ // v7m: FeatureNoARM, FeatureDB, FeatureHWDiv
+ ARMArchFeature = "+v7,+noarm,+db,+hwdiv";
+ } else if (Len >= Idx+3 && TT[Idx+1] == 'e'&& TT[Idx+2] == 'm') {
+ // v7em: FeatureNoARM, FeatureDB, FeatureHWDiv, FeatureDSPThumb2,
+ // FeatureT2XtPk
+ ARMArchFeature = "+v7,+noarm,+db,+hwdiv,+t2dsp,t2xtpk";
+ } else
+ // v7a: FeatureNEON, FeatureDB, FeatureDSPThumb2
+ ARMArchFeature = "+v7,+neon,+db,+t2dsp";
+ } else if (SubVer == '6') {
+ if (Len >= Idx+3 && TT[Idx+1] == 't' && TT[Idx+2] == '2')
+ ARMArchFeature = "+v6t2";
+ else
+ ARMArchFeature = "+v6";
+ } else if (SubVer == '5') {
+ if (Len >= Idx+3 && TT[Idx+1] == 't' && TT[Idx+2] == 'e')
+ ARMArchFeature = "+v5te";
+ else
+ ARMArchFeature = "+v5t";
+ } else if (SubVer == '4' && Len >= Idx+2 && TT[Idx+1] == 't')
+ ARMArchFeature = "+v4t";
+ }
+
+ if (isThumb) {
+ if (ARMArchFeature.empty())
+ ARMArchFeature = "+thumb-mode";
+ else
+ ARMArchFeature += ",+thumb-mode";
+ }
+
+ return ARMArchFeature;
+}
+
+MCSubtargetInfo *ARM_MC::createARMMCSubtargetInfo(StringRef TT, StringRef CPU,
+ StringRef FS) {
+ std::string ArchFS = ARM_MC::ParseARMTriple(TT);
+ if (!FS.empty()) {
+ if (!ArchFS.empty())
+ ArchFS = ArchFS + "," + FS.str();
+ else
+ ArchFS = FS;
+ }
+
+ MCSubtargetInfo *X = new MCSubtargetInfo();
+ InitARMMCSubtargetInfo(X, TT, CPU, ArchFS);
+ return X;
+}
+
+// Force static initialization.
+extern "C" void LLVMInitializeARMMCSubtargetInfo() {
+ TargetRegistry::RegisterMCSubtargetInfo(TheARMTarget,
+ ARM_MC::createARMMCSubtargetInfo);
+ TargetRegistry::RegisterMCSubtargetInfo(TheThumbTarget,
+ ARM_MC::createARMMCSubtargetInfo);
+}
+
+static MCInstrInfo *createARMMCInstrInfo() {
+ MCInstrInfo *X = new MCInstrInfo();
+ InitARMMCInstrInfo(X);
+ return X;
+}
+
+extern "C" void LLVMInitializeARMMCInstrInfo() {
+ TargetRegistry::RegisterMCInstrInfo(TheARMTarget, createARMMCInstrInfo);
+ TargetRegistry::RegisterMCInstrInfo(TheThumbTarget, createARMMCInstrInfo);
+}
+
+static MCRegisterInfo *createARMMCRegisterInfo() {
+ MCRegisterInfo *X = new MCRegisterInfo();
+ InitARMMCRegisterInfo(X);
+ return X;
+}
+
+extern "C" void LLVMInitializeARMMCRegInfo() {
+ TargetRegistry::RegisterMCRegInfo(TheARMTarget, createARMMCRegisterInfo);
+ TargetRegistry::RegisterMCRegInfo(TheThumbTarget, createARMMCRegisterInfo);
+}
+
+static MCAsmInfo *createARMMCAsmInfo(const Target &T, StringRef TT) {
+ Triple TheTriple(TT);
+
+ if (TheTriple.isOSDarwin())
+ return new ARMMCAsmInfoDarwin();
+
+ return new ARMELFMCAsmInfo();
+}
+
+extern "C" void LLVMInitializeARMMCAsmInfo() {
+ // Register the target asm info.
+ RegisterMCAsmInfoFn A(TheARMTarget, createARMMCAsmInfo);
+ RegisterMCAsmInfoFn B(TheThumbTarget, createARMMCAsmInfo);
+}
diff --git a/lib/Target/ARM/MCTargetDesc/ARMMCTargetDesc.h b/lib/Target/ARM/MCTargetDesc/ARMMCTargetDesc.h
new file mode 100644
index 0000000..74701e3
--- /dev/null
+++ b/lib/Target/ARM/MCTargetDesc/ARMMCTargetDesc.h
@@ -0,0 +1,52 @@
+//===-- ARMMCTargetDesc.h - ARM Target Descriptions -------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file provides ARM specific target descriptions.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef ARMMCTARGETDESC_H
+#define ARMMCTARGETDESC_H
+
+#include <string>
+
+namespace llvm {
+class MCSubtargetInfo;
+class Target;
+class StringRef;
+
+extern Target TheARMTarget, TheThumbTarget;
+
+namespace ARM_MC {
+ std::string ParseARMTriple(StringRef TT);
+
+ /// createARMMCSubtargetInfo - Create a ARM MCSubtargetInfo instance.
+ /// This is exposed so Asm parser, etc. do not need to go through
+ /// TargetRegistry.
+ MCSubtargetInfo *createARMMCSubtargetInfo(StringRef TT, StringRef CPU,
+ StringRef FS);
+}
+
+} // End llvm namespace
+
+// Defines symbolic names for ARM registers. This defines a mapping from
+// register name to register number.
+//
+#define GET_REGINFO_ENUM
+#include "ARMGenRegisterInfo.inc"
+
+// Defines symbolic names for the ARM instructions.
+//
+#define GET_INSTRINFO_ENUM
+#include "ARMGenInstrInfo.inc"
+
+#define GET_SUBTARGETINFO_ENUM
+#include "ARMGenSubtargetInfo.inc"
+
+#endif
diff --git a/lib/Target/ARM/MCTargetDesc/CMakeLists.txt b/lib/Target/ARM/MCTargetDesc/CMakeLists.txt
new file mode 100644
index 0000000..68daf42
--- /dev/null
+++ b/lib/Target/ARM/MCTargetDesc/CMakeLists.txt
@@ -0,0 +1,7 @@
+add_llvm_library(LLVMARMDesc
+ ARMMCTargetDesc.cpp
+ ARMMCAsmInfo.cpp
+ )
+
+# Hack: we need to include 'main' target directory to grab private headers
+include_directories(${CMAKE_CURRENT_SOURCE_DIR}/.. ${CMAKE_CURRENT_BINARY_DIR}/..)
diff --git a/lib/Target/ARM/MCTargetDesc/Makefile b/lib/Target/ARM/MCTargetDesc/Makefile
new file mode 100644
index 0000000..448ed9d
--- /dev/null
+++ b/lib/Target/ARM/MCTargetDesc/Makefile
@@ -0,0 +1,16 @@
+##===- lib/Target/ARM/TargetDesc/Makefile ------------------*- Makefile -*-===##
+#
+# The LLVM Compiler Infrastructure
+#
+# This file is distributed under the University of Illinois Open Source
+# License. See LICENSE.TXT for details.
+#
+##===----------------------------------------------------------------------===##
+
+LEVEL = ../../../..
+LIBRARYNAME = LLVMARMDesc
+
+# Hack: we need to include 'main' target directory to grab private headers
+CPP.Flags += -I$(PROJ_OBJ_DIR)/.. -I$(PROJ_SRC_DIR)/..
+
+include $(LEVEL)/Makefile.common
diff --git a/lib/Target/ARM/Makefile b/lib/Target/ARM/Makefile
index 51a8ac4..eb8c603 100644
--- a/lib/Target/ARM/Makefile
+++ b/lib/Target/ARM/Makefile
@@ -17,8 +17,9 @@ BUILT_SOURCES = ARMGenRegisterInfo.inc ARMGenInstrInfo.inc \
ARMGenDAGISel.inc ARMGenSubtargetInfo.inc \
ARMGenCodeEmitter.inc ARMGenCallingConv.inc \
ARMGenDecoderTables.inc ARMGenEDInfo.inc \
- ARMGenFastISel.inc ARMGenMCCodeEmitter.inc
+ ARMGenFastISel.inc ARMGenMCCodeEmitter.inc \
+ ARMGenMCPseudoLowering.inc
-DIRS = InstPrinter AsmParser Disassembler TargetInfo
+DIRS = InstPrinter AsmParser Disassembler TargetInfo MCTargetDesc
include $(LEVEL)/Makefile.common
diff --git a/lib/Target/ARM/NEONMoveFix.cpp b/lib/Target/ARM/NEONMoveFix.cpp
index 965665c..c85d1e9 100644
--- a/lib/Target/ARM/NEONMoveFix.cpp
+++ b/lib/Target/ARM/NEONMoveFix.cpp
@@ -77,7 +77,7 @@ bool NEONMoveFixPass::InsertMoves(MachineBasicBlock &MBB) {
}
if (inNEONDomain(Domain, isA8)) {
- // Convert VMOVD to VMOVDneon
+ // Convert VMOVD to VORRd
unsigned DestReg = MI->getOperand(0).getReg();
DEBUG({errs() << "vmov convert: "; MI->dump();});
@@ -88,7 +88,8 @@ bool NEONMoveFixPass::InsertMoves(MachineBasicBlock &MBB) {
// - The imp-defs / imp-uses are superregs only, we don't care about
// them.
AddDefaultPred(BuildMI(MBB, *MI, MI->getDebugLoc(),
- TII->get(ARM::VMOVDneon), DestReg).addReg(SrcReg));
+ TII->get(ARM::VORRd), DestReg)
+ .addReg(SrcReg).addReg(SrcReg));
MBB.erase(MI);
MachineBasicBlock::iterator I = prior(NextMII);
MI = &*I;
diff --git a/lib/Target/ARM/README.txt b/lib/Target/ARM/README.txt
index 8ba9a27..2f6842e 100644
--- a/lib/Target/ARM/README.txt
+++ b/lib/Target/ARM/README.txt
@@ -681,3 +681,21 @@ is compiled and optimized to:
str r1, [r0]
//===---------------------------------------------------------------------===//
+
+Improve codegen for select's:
+if (x != 0) x = 1
+if (x == 1) x = 1
+
+ARM codegen used to look like this:
+ mov r1, r0
+ cmp r1, #1
+ mov r0, #0
+ moveq r0, #1
+
+The naive lowering select between two different values. It should recognize the
+test is equality test so it's more a conditional move rather than a select:
+ cmp r0, #1
+ movne r0, #0
+
+Currently this is a ARM specific dag combine. We probably should make it into a
+target-neutral one.
diff --git a/lib/Target/ARM/Thumb1FrameLowering.cpp b/lib/Target/ARM/Thumb1FrameLowering.cpp
index 48211d8..c258870 100644
--- a/lib/Target/ARM/Thumb1FrameLowering.cpp
+++ b/lib/Target/ARM/Thumb1FrameLowering.cpp
@@ -273,8 +273,8 @@ void Thumb1FrameLowering::emitEpilogue(MachineFunction &MF,
emitSPUpdate(MBB, MBBI, TII, dl, *RegInfo, VARegSaveSize);
- BuildMI(MBB, MBBI, dl, TII.get(ARM::tBX_RET_vararg))
- .addReg(ARM::R3, RegState::Kill);
+ AddDefaultPred(BuildMI(MBB, MBBI, dl, TII.get(ARM::tBX_RET_vararg))
+ .addReg(ARM::R3, RegState::Kill));
// erase the old tBX_RET instruction
MBB.erase(MBBI);
}