mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2024-12-12 13:30:51 +00:00
Use TableGen'erated pseudo lowering for ARM.
Hook up the TableGen lowering for simple pseudo instructions for ARM and use it for a subset of the many pseudos the backend has as proof of concept. More conversions to come. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@134705 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
86f9adb8be
commit
53e3fc463e
@ -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) {
|
||||
// Do any auto-generated pseudo lowerings.
|
||||
if (emitPseudoExpansionLowering(OutStreamer, MI))
|
||||
return;
|
||||
|
||||
// Check for manual lowerings.
|
||||
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);
|
||||
return;
|
||||
}
|
||||
|
||||
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,19 +1121,6 @@ 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:
|
||||
@ -1912,31 +1861,6 @@ void ARMAsmPrinter::EmitInstruction(const MachineInstr *MI) {
|
||||
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;
|
||||
|
@ -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;
|
||||
|
@ -314,6 +314,25 @@ class t2PseudoInst<dag oops, dag iops, SizeFlagVal sz, InstrItinClass itin,
|
||||
let SZ = sz;
|
||||
list<Predicate> Predicates = [IsThumb2];
|
||||
}
|
||||
|
||||
class ARMPseudoExpand<dag oops, dag iops, SizeFlagVal sz,
|
||||
InstrItinClass itin, list<dag> pattern,
|
||||
dag Result>
|
||||
: ARMPseudoInst<oops, iops, sz, itin, pattern>,
|
||||
PseudoInstExpansion<Result>;
|
||||
|
||||
class tPseudoExpand<dag oops, dag iops, SizeFlagVal sz,
|
||||
InstrItinClass itin, list<dag> pattern,
|
||||
dag Result>
|
||||
: tPseudoInst<oops, iops, sz, itin, pattern>,
|
||||
PseudoInstExpansion<Result>;
|
||||
|
||||
class t2PseudoExpand<dag oops, dag iops, SizeFlagVal 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,
|
||||
IndexMode im, Format f, InstrItinClass itin,
|
||||
|
@ -1363,14 +1363,6 @@ let isBranch = 1, isTerminator = 1, isBarrier = 1, isIndirectBranch = 1 in {
|
||||
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
|
||||
@ -1526,13 +1518,23 @@ let isCall = 1, isTerminator = 1, isReturn = 1, isBarrier = 1 in {
|
||||
}
|
||||
|
||||
let isBranch = 1, isTerminator = 1 in {
|
||||
// B is "predicable" since it's just a Bcc with an 'always' condition.
|
||||
// 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 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), Size4Bytes, IIC_Br,
|
||||
[(br bb:$target)], (Bcc br_target:$target, (ops 14, zero_reg))>;
|
||||
|
||||
let isNotDuplicable = 1, isIndirectBranch = 1 in {
|
||||
def BR_JTr : ARMPseudoInst<(outs),
|
||||
@ -1554,14 +1556,6 @@ let isBranch = 1, isTerminator = 1 in {
|
||||
} // 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
|
||||
@ -2030,9 +2024,10 @@ def : MnemonicAlias<"stm", "stmia">;
|
||||
// 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,
|
||||
def LDMIA_RET : ARMPseudoExpand<(outs GPR:$wb), (ins GPR:$Rn, pred:$p,
|
||||
reglist:$regs, variable_ops),
|
||||
Size4Bytes, IIC_iLoad_mBr, []>,
|
||||
Size4Bytes, IIC_iLoad_mBr, [],
|
||||
(LDMIA_UPD GPR:$wb, GPR:$Rn, pred:$p, reglist:$regs)>,
|
||||
RegConstraint<"$Rn = $wb">;
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
@ -2690,28 +2685,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))]>,
|
||||
def MULv5: ARMPseudoExpand<(outs GPR:$Rd), (ins GPR:$Rn, GPR:$Rm,
|
||||
pred:$p, cc_out:$s),
|
||||
Size4Bytes, 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))]>,
|
||||
@ -2720,6 +2713,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),
|
||||
Size4Bytes, 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)))]>,
|
||||
@ -2735,21 +2736,8 @@ 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,
|
||||
"smull", "\t$RdLo, $RdHi, $Rn, $Rm", []>,
|
||||
@ -2759,25 +2747,23 @@ def UMULL : AsMul1I64<0b0000100, (outs GPR:$RdLo, GPR:$RdHi),
|
||||
(ins GPR:$Rn, GPR:$Rm), IIC_iMUL64,
|
||||
"umull", "\t$RdLo, $RdHi, $Rn, $Rm", []>,
|
||||
Requires<[IsARM, HasV6]>;
|
||||
|
||||
let Constraints = "@earlyclobber $RdLo,@earlyclobber $RdHi" in {
|
||||
def SMULLv5 : ARMPseudoExpand<(outs GPR:$RdLo, GPR:$RdHi),
|
||||
(ins GPR:$Rn, GPR:$Rm, pred:$p, cc_out:$s),
|
||||
Size4Bytes, IIC_iMUL64, [],
|
||||
(SMULL GPR:$RdLo, GPR:$RdHi, GPR:$Rn, GPR:$Rm, pred:$p, cc_out:$s)>,
|
||||
Requires<[IsARM, NoV6]>;
|
||||
|
||||
def UMULLv5 : ARMPseudoExpand<(outs GPR:$RdLo, GPR:$RdHi),
|
||||
(ins GPR:$Rn, GPR:$Rm, pred:$p, cc_out:$s),
|
||||
Size4Bytes, IIC_iMUL64, [],
|
||||
(UMULL GPR:$RdLo, GPR:$RdHi, GPR:$Rn, GPR:$Rm, pred:$p, cc_out:$s)>,
|
||||
Requires<[IsARM, NoV6]>;
|
||||
}
|
||||
}
|
||||
|
||||
// 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),
|
||||
(ins GPR:$Rn, GPR:$Rm, pred:$p, cc_out:$s),
|
||||
Size4Bytes, IIC_iMAC64, []>,
|
||||
Requires<[IsARM, NoV6]>;
|
||||
def UMAALv5 : ARMPseudoInst<(outs GPR:$RdLo, GPR:$RdHi),
|
||||
(ins GPR:$Rn, GPR:$Rm, pred:$p, cc_out:$s),
|
||||
Size4Bytes, IIC_iMAC64, []>,
|
||||
Requires<[IsARM, NoV6]>;
|
||||
|
||||
}
|
||||
|
||||
def SMLAL : AsMul1I64<0b0000111, (outs GPR:$RdLo, GPR:$RdHi),
|
||||
(ins GPR:$Rn, GPR:$Rm), IIC_iMAC64,
|
||||
"smlal", "\t$RdLo, $RdHi, $Rn, $Rm", []>,
|
||||
@ -2800,6 +2786,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),
|
||||
Size4Bytes, 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),
|
||||
Size4Bytes, 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),
|
||||
Size4Bytes, IIC_iMAC64, [],
|
||||
(UMAAL GPR:$RdLo, GPR:$RdHi, GPR:$Rn, GPR:$Rm, pred:$p)>,
|
||||
Requires<[IsARM, NoV6]>;
|
||||
}
|
||||
|
||||
} // neverHasSideEffects
|
||||
|
||||
// Most significant word multiply
|
||||
@ -3838,6 +3843,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),
|
||||
Size4Bytes, 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.
|
||||
|
@ -405,12 +405,6 @@ let isBranch = 1, isTerminator = 1, isBarrier = 1, isIndirectBranch = 1 in {
|
||||
}
|
||||
}
|
||||
|
||||
// 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, []>;
|
||||
|
||||
// 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
|
||||
// potentially appearing dead.
|
||||
@ -528,8 +522,8 @@ 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),
|
||||
Size4Bytes, IIC_Br, [], (tBL t_bltarget:$target)>;
|
||||
|
||||
def tBR_JTr : tPseudoInst<(outs),
|
||||
(ins tGPR:$target, i32imm:$jt, i32imm:$id),
|
||||
@ -1477,3 +1471,12 @@ 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),
|
||||
Size2Bytes, IIC_iPop_Br, [],
|
||||
(tPOP pred:$p, reglist:$regs)>;
|
||||
|
||||
|
@ -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, []>,
|
||||
Size4Bytes, IIC_iLoad_mBr, [],
|
||||
(t2LDMIA_UPD GPR:$wb, GPR:$Rn, pred:$p, reglist:$regs)>,
|
||||
RegConstraint<"$Rn = $wb">;
|
||||
|
||||
let isBranch = 1, isTerminator = 1, isBarrier = 1 in {
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
if (AP.lowerOperand(MO, MCOp))
|
||||
OutMI.addOperand(MCOp);
|
||||
}
|
||||
}
|
||||
|
@ -17,7 +17,8 @@ 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 MCTargetDesc
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user