mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-12-13 22:58:50 +00:00
AArch64: add BFC alias for the BFI/BFM instructions.
Unlike 32-bit ARM, AArch64 can use wzr/xzr to implement this without the need for a separate instruction. rdar://18679590 llvm-svn: 236245
This commit is contained in:
parent
f16b28762e
commit
db249b5492
@ -3644,6 +3644,60 @@ bool AArch64AsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
|
||||
Op3.getEndLoc(), getContext());
|
||||
}
|
||||
}
|
||||
} else if (NumOperands == 4 && Tok == "bfc") {
|
||||
// FIXME: Horrible hack to handle BFC->BFM alias.
|
||||
AArch64Operand &Op1 = static_cast<AArch64Operand &>(*Operands[1]);
|
||||
AArch64Operand LSBOp = static_cast<AArch64Operand &>(*Operands[2]);
|
||||
AArch64Operand WidthOp = static_cast<AArch64Operand &>(*Operands[3]);
|
||||
|
||||
if (Op1.isReg() && LSBOp.isImm() && WidthOp.isImm()) {
|
||||
const MCConstantExpr *LSBCE = dyn_cast<MCConstantExpr>(LSBOp.getImm());
|
||||
const MCConstantExpr *WidthCE = dyn_cast<MCConstantExpr>(WidthOp.getImm());
|
||||
|
||||
if (LSBCE && WidthCE) {
|
||||
uint64_t LSB = LSBCE->getValue();
|
||||
uint64_t Width = WidthCE->getValue();
|
||||
|
||||
uint64_t RegWidth = 0;
|
||||
if (AArch64MCRegisterClasses[AArch64::GPR64allRegClassID].contains(
|
||||
Op1.getReg()))
|
||||
RegWidth = 64;
|
||||
else
|
||||
RegWidth = 32;
|
||||
|
||||
if (LSB >= RegWidth)
|
||||
return Error(LSBOp.getStartLoc(),
|
||||
"expected integer in range [0, 31]");
|
||||
if (Width < 1 || Width > RegWidth)
|
||||
return Error(WidthOp.getStartLoc(),
|
||||
"expected integer in range [1, 32]");
|
||||
|
||||
uint64_t ImmR = 0;
|
||||
if (RegWidth == 32)
|
||||
ImmR = (32 - LSB) & 0x1f;
|
||||
else
|
||||
ImmR = (64 - LSB) & 0x3f;
|
||||
|
||||
uint64_t ImmS = Width - 1;
|
||||
|
||||
if (ImmR != 0 && ImmS >= ImmR)
|
||||
return Error(WidthOp.getStartLoc(),
|
||||
"requested insert overflows register");
|
||||
|
||||
const MCExpr *ImmRExpr = MCConstantExpr::Create(ImmR, getContext());
|
||||
const MCExpr *ImmSExpr = MCConstantExpr::Create(ImmS, getContext());
|
||||
Operands[0] = AArch64Operand::CreateToken(
|
||||
"bfm", false, Op.getStartLoc(), getContext());
|
||||
Operands[2] = AArch64Operand::CreateReg(
|
||||
RegWidth == 32 ? AArch64::WZR : AArch64::XZR, false, SMLoc(),
|
||||
SMLoc(), getContext());
|
||||
Operands[3] = AArch64Operand::CreateImm(
|
||||
ImmRExpr, LSBOp.getStartLoc(), LSBOp.getEndLoc(), getContext());
|
||||
Operands.emplace_back(
|
||||
AArch64Operand::CreateImm(ImmSExpr, WidthOp.getStartLoc(),
|
||||
WidthOp.getEndLoc(), getContext()));
|
||||
}
|
||||
}
|
||||
} else if (NumOperands == 5) {
|
||||
// FIXME: Horrible hack to handle the BFI -> BFM, SBFIZ->SBFM, and
|
||||
// UBFIZ -> UBFM aliases.
|
||||
@ -3675,8 +3729,7 @@ bool AArch64AsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
|
||||
"expected integer in range [1, 32]");
|
||||
|
||||
uint64_t NewOp3Val = 0;
|
||||
if (AArch64MCRegisterClasses[AArch64::GPR32allRegClassID].contains(
|
||||
Op1.getReg()))
|
||||
if (RegWidth == 32)
|
||||
NewOp3Val = (32 - Op3Val) & 0x1f;
|
||||
else
|
||||
NewOp3Val = (64 - Op3Val) & 0x3f;
|
||||
|
@ -162,11 +162,23 @@ void AArch64InstPrinter::printInst(const MCInst *MI, raw_ostream &O,
|
||||
int ImmR = MI->getOperand(3).getImm();
|
||||
int ImmS = MI->getOperand(4).getImm();
|
||||
|
||||
// BFI alias
|
||||
if (ImmS < ImmR) {
|
||||
if ((Op2.getReg() == AArch64::WZR || Op2.getReg() == AArch64::XZR) &&
|
||||
(ImmR == 0 || ImmS < ImmR)) {
|
||||
// BFC takes precedence over its entire range, sligtly differently to BFI.
|
||||
int BitWidth = Opcode == AArch64::BFMXri ? 64 : 32;
|
||||
int LSB = (BitWidth - ImmR) % BitWidth;
|
||||
int Width = ImmS + 1;
|
||||
|
||||
O << "\tbfc\t" << getRegisterName(Op0.getReg())
|
||||
<< ", #" << LSB << ", #" << Width;
|
||||
printAnnotation(O, Annot);
|
||||
return;
|
||||
} else if (ImmS < ImmR) {
|
||||
// BFI alias
|
||||
int BitWidth = Opcode == AArch64::BFMXri ? 64 : 32;
|
||||
int LSB = (BitWidth - ImmR) % BitWidth;
|
||||
int Width = ImmS + 1;
|
||||
|
||||
O << "\tbfi\t" << getRegisterName(Op0.getReg()) << ", "
|
||||
<< getRegisterName(Op2.getReg()) << ", #" << LSB << ", #" << Width;
|
||||
printAnnotation(O, Annot);
|
||||
|
@ -1088,6 +1088,23 @@
|
||||
// CHECK-ERROR-NEXT: ubfx w3, wsp, #10, #8
|
||||
// CHECK-ERROR-NEXT: ^
|
||||
|
||||
bfc wsp, #3, #6
|
||||
bfc w4, #2, #31
|
||||
bfc sp, #0, #1
|
||||
bfc x6, #0, #0
|
||||
// CHECK-ERROR: error: invalid operand for instruction
|
||||
// CHECK-ERROR-NEXT: bfc wsp, #3, #6
|
||||
// CHECK-ERROR-NEXT: ^
|
||||
// CHECK-ERROR-NEXT: error: requested insert overflows register
|
||||
// CHECK-ERROR-NEXT: bfc w4, #2, #31
|
||||
// CHECK-ERROR-NEXT: ^
|
||||
// CHECK-ERROR-NEXT: error: invalid operand for instruction
|
||||
// CHECK-ERROR-NEXT: bfc sp, #0, #1
|
||||
// CHECK-ERROR-NEXT: ^
|
||||
// CHECK-ERROR-NEXT: error: expected integer in range [1, 32]
|
||||
// CHECK-ERROR-NEXT: bfc x6, #0, #0
|
||||
// CHECK-ERROR-NEXT: ^
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Compare & branch (immediate)
|
||||
//------------------------------------------------------------------------------
|
||||
|
@ -978,7 +978,7 @@ _func:
|
||||
bfm x5, x6, #12, #63
|
||||
// CHECK: bfi x4, x5, #52, #11 // encoding: [0xa4,0x28,0x4c,0xb3]
|
||||
// CHECK: bfxil xzr, x4, #0, #1 // encoding: [0x9f,0x00,0x40,0xb3]
|
||||
// CHECK: bfi x4, xzr, #1, #6 // encoding: [0xe4,0x17,0x7f,0xb3]
|
||||
// CHECK: bfc x4, #1, #6 // encoding: [0xe4,0x17,0x7f,0xb3]
|
||||
// CHECK: bfxil x5, x6, #12, #52 // encoding: [0xc5,0xfc,0x4c,0xb3]
|
||||
|
||||
sxtb w1, w2
|
||||
@ -1078,7 +1078,7 @@ _func:
|
||||
// CHECK: bfxil w9, w10, #0, #32 // encoding: [0x49,0x7d,0x00,0x33]
|
||||
// CHECK: bfi w11, w12, #31, #1 // encoding: [0x8b,0x01,0x01,0x33]
|
||||
// CHECK: bfi w13, w14, #29, #3 // encoding: [0xcd,0x09,0x03,0x33]
|
||||
// CHECK: bfi xzr, xzr, #10, #11 // encoding: [0xff,0x2b,0x76,0xb3]
|
||||
// CHECK: bfc xzr, #10, #11 // encoding: [0xff,0x2b,0x76,0xb3]
|
||||
|
||||
bfxil w9, w10, #0, #1
|
||||
bfxil x2, x3, #63, #1
|
||||
@ -1132,6 +1132,16 @@ _func:
|
||||
// CHECK: lsr w11, w12, #31 // encoding: [0x8b,0x7d,0x1f,0x53]
|
||||
// CHECK: lsr w13, w14, #29 // encoding: [0xcd,0x7d,0x1d,0x53]
|
||||
// CHECK: ubfx xzr, xzr, #10, #11 // encoding: [0xff,0x53,0x4a,0xd3]
|
||||
|
||||
bfc w3, #0, #32
|
||||
bfc wzr, #31, #1
|
||||
bfc x0, #5, #9
|
||||
bfc xzr, #63, #1
|
||||
// CHECK: bfc w3, #0, #32 // encoding: [0xe3,0x7f,0x00,0x33]
|
||||
// CHECK: bfc wzr, #31, #1 // encoding: [0xff,0x03,0x01,0x33]
|
||||
// CHECK: bfc x0, #5, #9 // encoding: [0xe0,0x23,0x7b,0xb3]
|
||||
// CHECK: bfc xzr, #63, #1 // encoding: [0xff,0x03,0x41,0xb3]
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Compare & branch (immediate)
|
||||
//------------------------------------------------------------------------------
|
||||
|
@ -622,7 +622,7 @@
|
||||
|
||||
# CHECK: bfi x4, x5, #52, #11
|
||||
# CHECK: bfxil xzr, x4, #0, #1
|
||||
# CHECK: bfi x4, xzr, #1, #6
|
||||
# CHECK: bfc x4, #1, #6
|
||||
# CHECK: bfxil x5, x6, #12, #52
|
||||
0xa4 0x28 0x4c 0xb3
|
||||
0x9f 0x0 0x40 0xb3
|
||||
@ -715,7 +715,7 @@
|
||||
# CHECK: bfxil w9, w10, #0, #32
|
||||
# CHECK: bfi w11, w12, #31, #1
|
||||
# CHECK: bfi w13, w14, #29, #3
|
||||
# CHECK: bfi xzr, xzr, #10, #11
|
||||
# CHECK: bfc xzr, #10, #11
|
||||
0x49 0x1 0x0 0x33
|
||||
0x62 0x0 0x41 0xb3
|
||||
0x93 0xfe 0x40 0xb3
|
||||
|
Loading…
Reference in New Issue
Block a user