mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2024-12-14 11:32:34 +00:00
Thumb unconditional branches are allowed in IT blocks, and therefore should have a predicate operand, unlike conditional branches.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@139415 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
13d8baa3fc
commit
51f6a7abf2
@ -963,6 +963,8 @@ void ARMAsmPrinter::EmitJump2Table(const MachineInstr *MI) {
|
||||
MCInst BrInst;
|
||||
BrInst.setOpcode(ARM::t2B);
|
||||
BrInst.addOperand(MCOperand::CreateExpr(MBBSymbolExpr));
|
||||
BrInst.addOperand(MCOperand::CreateImm(ARMCC::AL));
|
||||
BrInst.addOperand(MCOperand::CreateReg(0));
|
||||
OutStreamer.EmitInstruction(BrInst);
|
||||
continue;
|
||||
}
|
||||
@ -1677,6 +1679,8 @@ void ARMAsmPrinter::EmitInstruction(const MachineInstr *MI) {
|
||||
MCInst TmpInst;
|
||||
TmpInst.setOpcode(ARM::tB);
|
||||
TmpInst.addOperand(MCOperand::CreateExpr(SymbolExpr));
|
||||
TmpInst.addOperand(MCOperand::CreateImm(ARMCC::AL));
|
||||
TmpInst.addOperand(MCOperand::CreateReg(0));
|
||||
OutStreamer.EmitInstruction(TmpInst);
|
||||
}
|
||||
{
|
||||
|
@ -404,7 +404,8 @@ ARMBaseInstrInfo::InsertBranch(MachineBasicBlock &MBB, MachineBasicBlock *TBB,
|
||||
? ARM::B : (AFI->isThumb2Function() ? ARM::t2B : ARM::tB);
|
||||
int BccOpc = !AFI->isThumbFunction()
|
||||
? ARM::Bcc : (AFI->isThumb2Function() ? ARM::t2Bcc : ARM::tBcc);
|
||||
|
||||
bool isThumb = AFI->isThumbFunction() || AFI->isThumb2Function();
|
||||
|
||||
// Shouldn't be a fall through.
|
||||
assert(TBB && "InsertBranch must not be told to insert a fallthrough");
|
||||
assert((Cond.size() == 2 || Cond.size() == 0) &&
|
||||
@ -412,7 +413,10 @@ ARMBaseInstrInfo::InsertBranch(MachineBasicBlock &MBB, MachineBasicBlock *TBB,
|
||||
|
||||
if (FBB == 0) {
|
||||
if (Cond.empty()) // Unconditional branch?
|
||||
BuildMI(&MBB, DL, get(BOpc)).addMBB(TBB);
|
||||
if (isThumb)
|
||||
BuildMI(&MBB, DL, get(BOpc)).addMBB(TBB).addImm(ARMCC::AL).addReg(0);
|
||||
else
|
||||
BuildMI(&MBB, DL, get(BOpc)).addMBB(TBB);
|
||||
else
|
||||
BuildMI(&MBB, DL, get(BccOpc)).addMBB(TBB)
|
||||
.addImm(Cond[0].getImm()).addReg(Cond[1].getReg());
|
||||
@ -422,7 +426,10 @@ ARMBaseInstrInfo::InsertBranch(MachineBasicBlock &MBB, MachineBasicBlock *TBB,
|
||||
// Two-way conditional branch.
|
||||
BuildMI(&MBB, DL, get(BccOpc)).addMBB(TBB)
|
||||
.addImm(Cond[0].getImm()).addReg(Cond[1].getReg());
|
||||
BuildMI(&MBB, DL, get(BOpc)).addMBB(FBB);
|
||||
if (isThumb)
|
||||
BuildMI(&MBB, DL, get(BOpc)).addMBB(FBB).addImm(ARMCC::AL).addReg(0);
|
||||
else
|
||||
BuildMI(&MBB, DL, get(BOpc)).addMBB(FBB);
|
||||
return 2;
|
||||
}
|
||||
|
||||
|
@ -739,7 +739,11 @@ MachineBasicBlock *ARMConstantIslands::SplitBlockBeforeInstr(MachineInstr *MI) {
|
||||
// There doesn't seem to be meaningful DebugInfo available; this doesn't
|
||||
// correspond to anything in the source.
|
||||
unsigned Opc = isThumb ? (isThumb2 ? ARM::t2B : ARM::tB) : ARM::B;
|
||||
BuildMI(OrigBB, DebugLoc(), TII->get(Opc)).addMBB(NewBB);
|
||||
if (!isThumb)
|
||||
BuildMI(OrigBB, DebugLoc(), TII->get(Opc)).addMBB(NewBB);
|
||||
else
|
||||
BuildMI(OrigBB, DebugLoc(), TII->get(Opc)).addMBB(NewBB)
|
||||
.addImm(ARMCC::AL).addReg(0);
|
||||
++NumSplit;
|
||||
|
||||
// Update the CFG. All succs of OrigBB are now succs of NewBB.
|
||||
@ -1151,7 +1155,11 @@ void ARMConstantIslands::CreateNewWater(unsigned CPUserIndex,
|
||||
// targets will be exchanged, and the altered branch may be out of
|
||||
// range, so the machinery has to know about it.
|
||||
int UncondBr = isThumb ? ((isThumb2) ? ARM::t2B : ARM::tB) : ARM::B;
|
||||
BuildMI(UserMBB, DebugLoc(), TII->get(UncondBr)).addMBB(NewMBB);
|
||||
if (!isThumb)
|
||||
BuildMI(UserMBB, DebugLoc(), TII->get(UncondBr)).addMBB(NewMBB);
|
||||
else
|
||||
BuildMI(UserMBB, DebugLoc(), TII->get(UncondBr)).addMBB(NewMBB)
|
||||
.addImm(ARMCC::AL).addReg(0);
|
||||
unsigned MaxDisp = getUnconditionalBrDisp(UncondBr);
|
||||
ImmBranches.push_back(ImmBranch(&UserMBB->back(),
|
||||
MaxDisp, false, UncondBr));
|
||||
@ -1893,7 +1901,8 @@ AdjustJTTargetBlockForward(MachineBasicBlock *BB, MachineBasicBlock *JTBB)
|
||||
// There doesn't seem to be meaningful DebugInfo available; this doesn't
|
||||
// correspond directly to anything in the source.
|
||||
assert (isThumb2 && "Adjusting for TB[BH] but not in Thumb2?");
|
||||
BuildMI(NewBB, DebugLoc(), TII->get(ARM::t2B)).addMBB(BB);
|
||||
BuildMI(NewBB, DebugLoc(), TII->get(ARM::t2B)).addMBB(BB)
|
||||
.addImm(ARMCC::AL).addReg(0);
|
||||
|
||||
// Update internal data structures to account for the newly inserted MBB.
|
||||
MF.RenumberBlocks(NewBB);
|
||||
|
@ -414,6 +414,9 @@ void ARMFrameLowering::emitEpilogue(MachineFunction &MF,
|
||||
MIB.addExternalSymbol(JumpTarget.getSymbolName(),
|
||||
JumpTarget.getTargetFlags());
|
||||
}
|
||||
|
||||
// Add the default predicate in Thumb mode.
|
||||
if (STI.isThumb()) MIB.addImm(ARMCC::AL).addReg(0);
|
||||
} else if (RetOpcode == ARM::TCRETURNri) {
|
||||
BuildMI(MBB, MBBI, dl,
|
||||
TII.get(STI.isThumb() ? ARM::tTAILJMPr : ARM::TAILJMPr)).
|
||||
|
@ -5713,8 +5713,10 @@ ARMTargetLowering::EmitInstrWithCustomInserter(MachineInstr *MI,
|
||||
|
||||
BuildMI(BB, dl, TII->get(isThumb2 ? ARM::t2Bcc : ARM::Bcc))
|
||||
.addMBB(destMBB).addImm(ARMCC::EQ).addReg(ARM::CPSR);
|
||||
BuildMI(BB, dl, TII->get(isThumb2 ? ARM::t2B : ARM::B))
|
||||
.addMBB(exitMBB);
|
||||
if (isThumb2)
|
||||
AddDefaultPred(BuildMI(BB, dl, TII->get(ARM::t2B)).addMBB(exitMBB));
|
||||
else
|
||||
BuildMI(BB, dl, TII->get(ARM::B)) .addMBB(exitMBB);
|
||||
|
||||
MI->eraseFromParent(); // The pseudo instruction is gone now.
|
||||
return BB;
|
||||
|
@ -487,8 +487,8 @@ let isCall = 1,
|
||||
|
||||
let isBranch = 1, isTerminator = 1, isBarrier = 1 in {
|
||||
let isPredicable = 1 in
|
||||
def tB : T1I<(outs), (ins t_brtarget:$target), IIC_Br,
|
||||
"b\t$target", [(br bb:$target)]>,
|
||||
def tB : T1pI<(outs), (ins t_brtarget:$target), IIC_Br,
|
||||
"b", "\t$target", [(br bb:$target)]>,
|
||||
T1Encoding<{1,1,1,0,0,?}> {
|
||||
bits<11> target;
|
||||
let Inst{10-0} = target;
|
||||
@ -537,9 +537,10 @@ let isCall = 1, isTerminator = 1, isReturn = 1, isBarrier = 1 in {
|
||||
// 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),
|
||||
def tTAILJMPdND : tPseudoExpand<(outs),
|
||||
(ins t_brtarget:$dst, pred:$p, variable_ops),
|
||||
4, IIC_Br, [],
|
||||
(tB t_brtarget:$dst)>,
|
||||
(tB t_brtarget:$dst, pred:$p)>,
|
||||
Requires<[IsThumb, IsNotDarwin]>;
|
||||
def tTAILJMPrND : tPseudoExpand<(outs), (ins tcGPR:$dst, variable_ops),
|
||||
4, IIC_Br, [],
|
||||
|
@ -3004,8 +3004,8 @@ def t2LDMIA_RET: t2PseudoExpand<(outs GPR:$wb), (ins GPR:$Rn, pred:$p,
|
||||
|
||||
let isBranch = 1, isTerminator = 1, isBarrier = 1 in {
|
||||
let isPredicable = 1 in
|
||||
def t2B : T2XI<(outs), (ins uncondbrtarget:$target), IIC_Br,
|
||||
"b.w\t$target",
|
||||
def t2B : T2I<(outs), (ins uncondbrtarget:$target), IIC_Br,
|
||||
"b", ".w\t$target",
|
||||
[(br bb:$target)]> {
|
||||
let Inst{31-27} = 0b11110;
|
||||
let Inst{15-14} = 0b10;
|
||||
@ -3060,7 +3060,7 @@ def t2TBH : T2I<(outs), (ins GPR:$Rn, GPR:$Rm), IIC_Br,
|
||||
} // isBranch, isTerminator, isBarrier
|
||||
|
||||
// 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. :(
|
||||
// a two-value operand where a dag node expects ", "two operands. :(
|
||||
let isBranch = 1, isTerminator = 1 in
|
||||
def t2Bcc : T2I<(outs), (ins brtarget:$target), IIC_Br,
|
||||
"b", ".w\t$target",
|
||||
@ -3088,9 +3088,10 @@ 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),
|
||||
def tTAILJMPd: tPseudoExpand<(outs),
|
||||
(ins uncondbrtarget:$dst, pred:$p, variable_ops),
|
||||
4, IIC_Br, [],
|
||||
(t2B uncondbrtarget:$dst)>,
|
||||
(t2B uncondbrtarget:$dst, pred:$p)>,
|
||||
Requires<[IsThumb2, IsDarwin]>;
|
||||
}
|
||||
|
||||
|
@ -3567,8 +3567,8 @@ validateInstruction(MCInst &Inst,
|
||||
// Check for non-'al' condition codes outside of the IT block.
|
||||
} else if (isThumbTwo() && MCID.isPredicable() &&
|
||||
Inst.getOperand(MCID.findFirstPredOperandIdx()).getImm() !=
|
||||
ARMCC::AL && Inst.getOpcode() != ARM::tBcc &&
|
||||
Inst.getOpcode() != ARM::t2Bcc)
|
||||
ARMCC::AL && Inst.getOpcode() != ARM::tB &&
|
||||
Inst.getOpcode() != ARM::t2B)
|
||||
return Error(Loc, "predicated instructions must be in IT block");
|
||||
|
||||
switch (Inst.getOpcode()) {
|
||||
@ -3721,6 +3721,16 @@ processInstruction(MCInst &Inst,
|
||||
if (Inst.getOperand(3).getImm() < 8 && Operands.size() == 6)
|
||||
Inst.setOpcode(ARM::tADDi3);
|
||||
break;
|
||||
case ARM::tB:
|
||||
// A Thumb conditional branch outside of an IT block is a tBcc.
|
||||
if (Inst.getOperand(1).getImm() != ARMCC::AL && !inITBlock())
|
||||
Inst.setOpcode(ARM::tBcc);
|
||||
break;
|
||||
case ARM::t2B:
|
||||
// A Thumb2 conditional branch outside of an IT block is a t2Bcc.
|
||||
if (Inst.getOperand(1).getImm() != ARMCC::AL && !inITBlock())
|
||||
Inst.setOpcode(ARM::t2Bcc);
|
||||
break;
|
||||
case ARM::t2Bcc:
|
||||
// If the conditional is AL or we're in an IT block, we really want t2B.
|
||||
if (Inst.getOperand(1).getImm() == ARMCC::AL || inITBlock())
|
||||
|
@ -426,6 +426,8 @@ static void AddThumb1SBit(MCInst &MI, bool InITBlock) {
|
||||
// post-pass.
|
||||
MCDisassembler::DecodeStatus
|
||||
ThumbDisassembler::AddThumbPredicate(MCInst &MI) const {
|
||||
MCDisassembler::DecodeStatus S = Success;
|
||||
|
||||
// A few instructions actually have predicates encoded in them. Don't
|
||||
// try to overwrite it if we're seeing one of those.
|
||||
switch (MI.getOpcode()) {
|
||||
@ -436,8 +438,16 @@ ThumbDisassembler::AddThumbPredicate(MCInst &MI) const {
|
||||
// Some instructions (mostly conditional branches) are not
|
||||
// allowed in IT blocks.
|
||||
if (!ITBlock.empty())
|
||||
return SoftFail;
|
||||
return Success;
|
||||
S = SoftFail;
|
||||
else
|
||||
return Success;
|
||||
break;
|
||||
case ARM::tB:
|
||||
case ARM::t2B:
|
||||
// Some instructions (mostly unconditional branches) can
|
||||
// only appears at the end of, or outside of, an IT.
|
||||
if (ITBlock.size() > 1)
|
||||
S = SoftFail;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
@ -466,7 +476,7 @@ ThumbDisassembler::AddThumbPredicate(MCInst &MI) const {
|
||||
MI.insert(I, MCOperand::CreateReg(0));
|
||||
else
|
||||
MI.insert(I, MCOperand::CreateReg(ARM::CPSR));
|
||||
return Success;
|
||||
return S;
|
||||
}
|
||||
}
|
||||
|
||||
@ -477,7 +487,7 @@ ThumbDisassembler::AddThumbPredicate(MCInst &MI) const {
|
||||
else
|
||||
MI.insert(I, MCOperand::CreateReg(ARM::CPSR));
|
||||
|
||||
return Success;
|
||||
return S;
|
||||
}
|
||||
|
||||
// Thumb VFP instructions are a special case. Because we share their
|
||||
|
@ -188,7 +188,7 @@ _func:
|
||||
@ CHECK: beq.w _bar @ encoding: [A,0xf0'A',A,0x80'A']
|
||||
@ fixup A - offset: 0, value: _bar, kind: fixup_t2_condbranch
|
||||
@ CHECK: it eq @ encoding: [0x08,0xbf]
|
||||
@ CHECK: b.w _bar @ encoding: [A,0xf0'A',A,0x90'A']
|
||||
@ CHECK: beq.w _bar @ encoding: [A,0xf0'A',A,0x90'A']
|
||||
@ fixup A - offset: 0, value: _bar, kind: fixup_t2_uncondbranch
|
||||
@ CHECK: bmi.w #-183396 @ encoding: [0x13,0xf5,0xce,0xa9]
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user