llvm.org GIT mirror llvm / a9af055
[AArch64] Add logical alias instructions to MC AsmParser This patch teaches the AsmParser to accept some logical+immediate instructions and convert them as shown: bic Rd, Rn, #imm -> and Rd, Rn, #~imm bics Rd, Rn, #imm -> ands Rd, Rn, #~imm orn Rd, Rn, #imm -> orr Rd, Rn, #~imm eon Rd, Rn, #imm -> eor Rd, Rn, #~imm Those instructions are an alternate syntax available to assembly coders, and are needed in order to support code already compiling with some other assemblers. For example, the bic construct is used by the linux kernel. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@212722 91177308-0d34-0410-b5e6-96231b3b80d8 Arnaud A. de Grandmaison 6 years ago
5 changed file(s) with 126 addition(s) and 19 deletion(s). Raw diff Collapse all Expand all
447447 return CurDAG->getTargetConstant(enc, MVT::i32);
448448 }]>;
449449
450 def LogicalImm32Operand : AsmOperandClass {
451 let Name = "LogicalImm32";
452 let DiagnosticType = "LogicalSecondSource";
453 }
454 def LogicalImm64Operand : AsmOperandClass {
455 let Name = "LogicalImm64";
456 let DiagnosticType = "LogicalSecondSource";
450 let DiagnosticType = "LogicalSecondSource" in {
451 def LogicalImm32Operand : AsmOperandClass {
452 let Name = "LogicalImm32";
453 }
454 def LogicalImm64Operand : AsmOperandClass {
455 let Name = "LogicalImm64";
456 }
457 def LogicalImm32NotOperand : AsmOperandClass {
458 let Name = "LogicalImm32Not";
459 }
460 def LogicalImm64NotOperand : AsmOperandClass {
461 let Name = "LogicalImm64Not";
462 }
457463 }
458464 def logical_imm32 : Operand, PatLeaf<(imm), [{
459465 return AArch64_AM::isLogicalImmediate(N->getZExtValue(), 32);
466472 }], logical_imm64_XFORM> {
467473 let PrintMethod = "printLogicalImm64";
468474 let ParserMatchClass = LogicalImm64Operand;
475 }
476 def logical_imm32_not : Operand {
477 let ParserMatchClass = LogicalImm32NotOperand;
478 }
479 def logical_imm64_not : Operand {
480 let ParserMatchClass = LogicalImm64NotOperand;
469481 }
470482
471483 // imm0_65535 predicate - True if the immediate is in the range [0,65535].
19341946 : InstAlias
19351947 (inst regtype:$dst, regtype:$src1, regtype:$src2, 0)>;
19361948
1937 let AddedComplexity = 6 in
1938 multiclass LogicalImm opc, string mnemonic, SDNode OpNode> {
1949 multiclass LogicalImm opc, string mnemonic, SDNode OpNode,
1950 string Alias> {
1951 let AddedComplexity = 6 in
19391952 def Wri : BaseLogicalImm
19401953 [(set GPR32sp:$Rd, (OpNode GPR32:$Rn,
19411954 logical_imm32:$imm))]> {
19421955 let Inst{31} = 0;
19431956 let Inst{22} = 0; // 64-bit version has an additional bit of immediate.
19441957 }
1958 let AddedComplexity = 6 in
19451959 def Xri : BaseLogicalImm
19461960 [(set GPR64sp:$Rd, (OpNode GPR64:$Rn,
19471961 logical_imm64:$imm))]> {
19481962 let Inst{31} = 1;
19491963 }
1950 }
1951
1952 multiclass LogicalImmS opc, string mnemonic, SDNode OpNode> {
1964
1965 def : InstAlias
1966 (!cast(NAME # "Wri") GPR32sp:$Rd, GPR32:$Rn,
1967 logical_imm32_not:$imm), 0>;
1968 def : InstAlias
1969 (!cast(NAME # "Xri") GPR64sp:$Rd, GPR64:$Rn,
1970 logical_imm64_not:$imm), 0>;
1971 }
1972
1973 multiclass LogicalImmS opc, string mnemonic, SDNode OpNode,
1974 string Alias> {
19531975 let isCompare = 1, Defs = [NZCV] in {
19541976 def Wri : BaseLogicalImm
19551977 [(set GPR32:$Rd, (OpNode GPR32:$Rn, logical_imm32:$imm))]> {
19611983 let Inst{31} = 1;
19621984 }
19631985 } // end Defs = [NZCV]
1986
1987 def : InstAlias
1988 (!cast(NAME # "Wri") GPR32:$Rd, GPR32:$Rn,
1989 logical_imm32_not:$imm), 0>;
1990 def : InstAlias
1991 (!cast(NAME # "Xri") GPR64:$Rd, GPR64:$Rn,
1992 logical_imm64_not:$imm), 0>;
19641993 }
19651994
19661995 class BaseLogicalRegPseudo
670670 //===----------------------------------------------------------------------===//
671671
672672 // (immediate)
673 defm ANDS : LogicalImmS<0b11, "ands", AArch64and_flag>;
674 defm AND : LogicalImm<0b00, "and", and>;
675 defm EOR : LogicalImm<0b10, "eor", xor>;
676 defm ORR : LogicalImm<0b01, "orr", or>;
673 defm ANDS : LogicalImmS<0b11, "ands", AArch64and_flag, "bics">;
674 defm AND : LogicalImm<0b00, "and", and, "bic">;
675 defm EOR : LogicalImm<0b10, "eor", xor, "eon">;
676 defm ORR : LogicalImm<0b01, "orr", or, "orn">;
677677
678678 // FIXME: these aliases *are* canonical sometimes (when movz can't be
679679 // used). Actually, it seems to be working right now, but putting logical_immXX
632632 return false;
633633 return AArch64_AM::isLogicalImmediate(MCE->getValue(), 64);
634634 }
635 bool isLogicalImm32Not() const {
636 if (!isImm())
637 return false;
638 const MCConstantExpr *MCE = dyn_cast(getImm());
639 if (!MCE)
640 return false;
641 int64_t Val = ~MCE->getValue() & 0xFFFFFFFF;
642 return AArch64_AM::isLogicalImmediate(Val, 32);
643 }
644 bool isLogicalImm64Not() const {
645 if (!isImm())
646 return false;
647 const MCConstantExpr *MCE = dyn_cast(getImm());
648 if (!MCE)
649 return false;
650 return AArch64_AM::isLogicalImmediate(~MCE->getValue(), 64);
651 }
635652 bool isShiftedImm() const { return Kind == k_ShiftedImm; }
636653 bool isAddSubImm() const {
637654 if (!isShiftedImm() && !isImm())
13731390 const MCConstantExpr *MCE = dyn_cast(getImm());
13741391 assert(MCE && "Invalid logical immediate operand!");
13751392 uint64_t encoding = AArch64_AM::encodeLogicalImmediate(MCE->getValue(), 64);
1393 Inst.addOperand(MCOperand::CreateImm(encoding));
1394 }
1395
1396 void addLogicalImm32NotOperands(MCInst &Inst, unsigned N) const {
1397 assert(N == 1 && "Invalid number of operands!");
1398 const MCConstantExpr *MCE = cast(getImm());
1399 int64_t Val = ~MCE->getValue() & 0xFFFFFFFF;
1400 uint64_t encoding = AArch64_AM::encodeLogicalImmediate(Val, 32);
1401 Inst.addOperand(MCOperand::CreateImm(encoding));
1402 }
1403
1404 void addLogicalImm64NotOperands(MCInst &Inst, unsigned N) const {
1405 assert(N == 1 && "Invalid number of operands!");
1406 const MCConstantExpr *MCE = cast(getImm());
1407 uint64_t encoding =
1408 AArch64_AM::encodeLogicalImmediate(~MCE->getValue(), 64);
13761409 Inst.addOperand(MCOperand::CreateImm(encoding));
13771410 }
13781411
0 // RUN: llvm-mc -triple=aarch64-none-linux-gnu < %s | FileCheck %s
1
2 // CHECK: and x0, x1, #0xfffffffffffffffd
3 // CHECK: and x0, x1, #0xfffffffffffffffd
4 and x0, x1, #~2
5 bic x0, x1, #2
6
7 // CHECK: and w0, w1, #0xfffffffd
8 // CHECK: and w0, w1, #0xfffffffd
9 and w0, w1, #~2
10 bic w0, w1, #2
11
12 // CHECK: ands x0, x1, #0xfffffffffffffffd
13 // CHECK: ands x0, x1, #0xfffffffffffffffd
14 ands x0, x1, #~2
15 bics x0, x1, #2
16
17 // CHECK: ands w0, w1, #0xfffffffd
18 // CHECK: ands w0, w1, #0xfffffffd
19 ands w0, w1, #~2
20 bics w0, w1, #2
21
22 // CHECK: orr x0, x1, #0xfffffffffffffffd
23 // CHECK: orr x0, x1, #0xfffffffffffffffd
24 orr x0, x1, #~2
25 orn x0, x1, #2
26
27 // CHECK: orr w2, w1, #0xfffffffc
28 // CHECK: orr w2, w1, #0xfffffffc
29 orr w2, w1, #~3
30 orn w2, w1, #3
31
32 // CHECK: eor x0, x1, #0xfffffffffffffffd
33 // CHECK: eor x0, x1, #0xfffffffffffffffd
34 eor x0, x1, #~2
35 eon x0, x1, #2
36
37 // CHECK: eor w2, w1, #0xfffffffc
38 // CHECK: eor w2, w1, #0xfffffffc
39 eor w2, w1, #~3
40 eon w2, w1, #3
29842984 orn wsp, w3, w5
29852985 bics x20, sp, x9, lsr #0
29862986 orn x2, x6, sp, lsl #3
2987 // CHECK-ERROR: error: invalid operand for instruction
2987 // FIXME: the diagnostic we get for 'orn wsp, w3, w5' is from the orn alias,
2988 // which is a better match than the genuine ORNWri, whereas it would be better
2989 // to get the ORNWri diagnostic when the alias did not match, i.e. the
2990 // alias' diagnostics should have a lower priority.
2991 // CHECK-ERROR: error: expected compatible register or logical immediate
29882992 // CHECK-ERROR-NEXT: orn wsp, w3, w5
2989 // CHECK-ERROR-NEXT: ^
2993 // CHECK-ERROR-NEXT: ^
29902994 // CHECK-ERROR-NEXT: error: invalid operand for instruction
29912995 // CHECK-ERROR-NEXT: bics x20, sp, x9, lsr #0
29922996 // CHECK-ERROR-NEXT: ^
2993 // CHECK-ERROR-NEXT: error: invalid operand for instruction
2997 // CHECK-ERROR-NEXT: error: expected compatible register or logical immediate
29942998 // CHECK-ERROR-NEXT: orn x2, x6, sp, lsl #3
29952999 // CHECK-ERROR-NEXT: ^
29963000