[PowerPC] Support asm parsing for bc[l][a][+-] mnemonics

PowerPC assembly code in the wild, so it seems, has things like this:

  bc+     12, 28, .L9

This is a bit odd because the '+' here becomes part of the BO field, and the BO
field is otherwise the first operand. Nevertheless, the ISA specification does
clearly say that the +- hint syntax applies to all conditional-branch mnemonics
(that test either CTR or a condition register, although not the forms which
check both), both basic and extended, so this is supposed to be valid.

This introduces some asm-parser-only definitions which take only the upper
three bits from the specified BO value, and the lower two bits are implied by
the +- suffix (via some associated aliases).

Fixes PR23646.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@280571 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Hal Finkel 2016-09-03 02:31:44 +00:00
parent 0d65f1da0e
commit f86e7eec65
6 changed files with 111 additions and 0 deletions

View File

@ -545,6 +545,7 @@ public:
&& isUInt<5>(getImm())); }
bool isCRBitMask() const { return Kind == Immediate && isUInt<8>(getImm()) &&
isPowerOf2_32(getImm()); }
bool isATBitsAsHint() const { return false; }
bool isMem() const override { return false; }
bool isReg() const override { return false; }

View File

@ -258,6 +258,15 @@ void PPCInstPrinter::printPredicateOperand(const MCInst *MI, unsigned OpNo,
printOperand(MI, OpNo+1, O);
}
void PPCInstPrinter::printATBitsAsHint(const MCInst *MI, unsigned OpNo,
raw_ostream &O) {
unsigned Code = MI->getOperand(OpNo).getImm();
if (Code == 2)
O << "-";
else if (Code == 3)
O << "+";
}
void PPCInstPrinter::printU1ImmOperand(const MCInst *MI, unsigned OpNo,
raw_ostream &O) {
unsigned int Value = MI->getOperand(OpNo).getImm();

View File

@ -45,6 +45,7 @@ public:
void printOperand(const MCInst *MI, unsigned OpNo, raw_ostream &O);
void printPredicateOperand(const MCInst *MI, unsigned OpNo,
raw_ostream &O, const char *Modifier = nullptr);
void printATBitsAsHint(const MCInst *MI, unsigned OpNo, raw_ostream &O);
void printU1ImmOperand(const MCInst *MI, unsigned OpNo, raw_ostream &O);
void printU2ImmOperand(const MCInst *MI, unsigned OpNo, raw_ostream &O);

View File

@ -163,6 +163,22 @@ class BForm_3<bits<6> opcode, bit aa, bit lk,
let Inst{31} = lk;
}
class BForm_3_at<bits<6> opcode, bit aa, bit lk,
dag OOL, dag IOL, string asmstr>
: I<opcode, OOL, IOL, asmstr, IIC_BrB> {
bits<5> BO;
bits<2> at;
bits<5> BI;
bits<14> BD;
let Inst{6-8} = BO{4-2};
let Inst{9-10} = at;
let Inst{11-15} = BI;
let Inst{16-29} = BD;
let Inst{30} = aa;
let Inst{31} = lk;
}
class BForm_4<bits<6> opcode, bits<5> bo, bit aa, bit lk,
dag OOL, dag IOL, string asmstr>
: I<opcode, OOL, IOL, asmstr, IIC_BrB> {

View File

@ -478,6 +478,15 @@ def u2imm : Operand<i32> {
let ParserMatchClass = PPCU2ImmAsmOperand;
}
def PPCATBitsAsHintAsmOperand : AsmOperandClass {
let Name = "ATBitsAsHint"; let PredicateMethod = "isATBitsAsHint";
let RenderMethod = "addImmOperands"; // Irrelevant, predicate always fails.
}
def atimm : Operand<i32> {
let PrintMethod = "printATBitsAsHint";
let ParserMatchClass = PPCATBitsAsHintAsmOperand;
}
def PPCU3ImmAsmOperand : AsmOperandClass {
let Name = "U3Imm"; let PredicateMethod = "isU3Imm";
let RenderMethod = "addImmOperands";
@ -4134,6 +4143,16 @@ let PPC970_Unit = 7 in {
def gBCA : BForm_3<16, 1, 0, (outs),
(ins u5imm:$bo, crbitrc:$bi, abscondbrtarget:$dst),
"bca $bo, $bi, $dst">;
let isAsmParserOnly = 1 in {
def gBCat : BForm_3_at<16, 0, 0, (outs),
(ins u5imm:$bo, atimm:$at, crbitrc:$bi,
condbrtarget:$dst),
"bc$at $bo, $bi, $dst">;
def gBCAat : BForm_3_at<16, 1, 0, (outs),
(ins u5imm:$bo, atimm:$at, crbitrc:$bi,
abscondbrtarget:$dst),
"bca$at $bo, $bi, $dst">;
} // isAsmParserOnly = 1
}
let Defs = [LR, CTR], Uses = [CTR, RM] in {
def gBCL : BForm_3<16, 0, 1, (outs),
@ -4142,6 +4161,16 @@ let PPC970_Unit = 7 in {
def gBCLA : BForm_3<16, 1, 1, (outs),
(ins u5imm:$bo, crbitrc:$bi, abscondbrtarget:$dst),
"bcla $bo, $bi, $dst">;
let isAsmParserOnly = 1 in {
def gBCLat : BForm_3_at<16, 0, 1, (outs),
(ins u5imm:$bo, atimm:$at, crbitrc:$bi,
condbrtarget:$dst),
"bcl$at $bo, $bi, $dst">;
def gBCLAat : BForm_3_at<16, 1, 1, (outs),
(ins u5imm:$bo, atimm:$at, crbitrc:$bi,
abscondbrtarget:$dst),
"bcla$at $bo, $bi, $dst">;
} // // isAsmParserOnly = 1
}
let Defs = [CTR], Uses = [CTR, LR, RM] in
def gBCLR : XLForm_2<19, 16, 0, (outs),
@ -4160,6 +4189,20 @@ let PPC970_Unit = 7 in {
(ins u5imm:$bo, crbitrc:$bi, i32imm:$bh),
"bcctrl $bo, $bi, $bh", IIC_BrB, []>;
}
multiclass BranchSimpleMnemonicAT<string pm, int at> {
def : InstAlias<"bc"#pm#" $bo, $bi, $dst", (gBCat u5imm:$bo, at, crbitrc:$bi,
condbrtarget:$dst)>;
def : InstAlias<"bca"#pm#" $bo, $bi, $dst", (gBCAat u5imm:$bo, at, crbitrc:$bi,
condbrtarget:$dst)>;
def : InstAlias<"bcl"#pm#" $bo, $bi, $dst", (gBCLat u5imm:$bo, at, crbitrc:$bi,
condbrtarget:$dst)>;
def : InstAlias<"bcla"#pm#" $bo, $bi, $dst", (gBCLAat u5imm:$bo, at, crbitrc:$bi,
condbrtarget:$dst)>;
}
defm : BranchSimpleMnemonicAT<"+", 3>;
defm : BranchSimpleMnemonicAT<"-", 2>;
def : InstAlias<"bclr $bo, $bi", (gBCLR u5imm:$bo, crbitrc:$bi, 0)>;
def : InstAlias<"bclrl $bo, $bi", (gBCLRL u5imm:$bo, crbitrc:$bi, 0)>;
def : InstAlias<"bcctr $bo, $bi", (gBCCTR u5imm:$bo, crbitrc:$bi, 0)>;

View File

@ -48,6 +48,47 @@
# CHECK-LE-NEXT: # fixup A - offset: 0, value: target, kind: fixup_ppc_brcond14abs
bcla 4, 10, target
# CHECK-BE: bc+ 12, 28, target # encoding: [0x41,0xfc,A,0bAAAAAA00]
# CHECK-LE: bc+ 12, 28, target # encoding: [0bAAAAAA00,A,0xfc,0x41]
# CHECK-BE-NEXT: # fixup A - offset: 0, value: target, kind: fixup_ppc_brcond14
# CHECK-LE-NEXT: # fixup A - offset: 0, value: target, kind: fixup_ppc_brcond14
bc+ 12, 28, target
# CHECK-BE: bc- 12, 28, target # encoding: [0x41,0xdc,A,0bAAAAAA00]
# CHECK-LE: bc- 12, 28, target # encoding: [0bAAAAAA00,A,0xdc,0x41]
# CHECK-BE-NEXT: # fixup A - offset: 0, value: target, kind: fixup_ppc_brcond14
# CHECK-LE-NEXT: # fixup A - offset: 0, value: target, kind: fixup_ppc_brcond14
bc- 12, 28, target
# CHECK-BE: bca+ 12, 28, target # encoding: [0x41,0xfc,A,0bAAAAAA10]
# CHECK-LE: bca+ 12, 28, target # encoding: [0bAAAAAA10,A,0xfc,0x41]
# CHECK-BE-NEXT: # fixup A - offset: 0, value: target, kind: fixup_ppc_brcond14abs
# CHECK-LE-NEXT: # fixup A - offset: 0, value: target, kind: fixup_ppc_brcond14abs
bca+ 12, 28, target
# CHECK-BE: bca- 12, 28, target # encoding: [0x41,0xdc,A,0bAAAAAA10]
# CHECK-LE: bca- 12, 28, target # encoding: [0bAAAAAA10,A,0xdc,0x41]
# CHECK-BE-NEXT: # fixup A - offset: 0, value: target, kind: fixup_ppc_brcond14abs
# CHECK-LE-NEXT: # fixup A - offset: 0, value: target, kind: fixup_ppc_brcond14abs
bca- 12, 28, target
# CHECK-BE: bcl+ 12, 28, target # encoding: [0x41,0xfc,A,0bAAAAAA01]
# CHECK-LE: bcl+ 12, 28, target # encoding: [0bAAAAAA01,A,0xfc,0x41]
# CHECK-BE-NEXT: # fixup A - offset: 0, value: target, kind: fixup_ppc_brcond14
# CHECK-LE-NEXT: # fixup A - offset: 0, value: target, kind: fixup_ppc_brcond14
bcl+ 12, 28, target
# CHECK-BE: bcl- 12, 28, target # encoding: [0x41,0xdc,A,0bAAAAAA01]
# CHECK-LE: bcl- 12, 28, target # encoding: [0bAAAAAA01,A,0xdc,0x41]
# CHECK-BE-NEXT: # fixup A - offset: 0, value: target, kind: fixup_ppc_brcond14
# CHECK-LE-NEXT: # fixup A - offset: 0, value: target, kind: fixup_ppc_brcond14
bcl- 12, 28, target
# CHECK-BE: bcla+ 12, 28, target # encoding: [0x41,0xfc,A,0bAAAAAA11]
# CHECK-LE: bcla+ 12, 28, target # encoding: [0bAAAAAA11,A,0xfc,0x41]
# CHECK-BE-NEXT: # fixup A - offset: 0, value: target, kind: fixup_ppc_brcond14abs
# CHECK-LE-NEXT: # fixup A - offset: 0, value: target, kind: fixup_ppc_brcond14abs
bcla+ 12, 28, target
# CHECK-BE: bcla- 12, 28, target # encoding: [0x41,0xdc,A,0bAAAAAA11]
# CHECK-LE: bcla- 12, 28, target # encoding: [0bAAAAAA11,A,0xdc,0x41]
# CHECK-BE-NEXT: # fixup A - offset: 0, value: target, kind: fixup_ppc_brcond14abs
# CHECK-LE-NEXT: # fixup A - offset: 0, value: target, kind: fixup_ppc_brcond14abs
bcla- 12, 28, target
# CHECK-BE: bclr 4, 10, 3 # encoding: [0x4c,0x8a,0x18,0x20]
# CHECK-LE: bclr 4, 10, 3 # encoding: [0x20,0x18,0x8a,0x4c]
bclr 4, 10, 3