llvm.org GIT mirror llvm / 5c025f2
Fix for PR18921, "vmov" part. Added support for bytes replication feature, so it could be GAS compatible. E.g. instructions below: "vmov.i32 d0, 0xffffffff" "vmvn.i32 d0, 0xabababab" "vmov.i32 d0, 0xabababab" "vmov.i16 d0, 0xabab" are incorrect, but we could deal with such cases. For first one we should emit: "vmov.i8 d0, 0xff" For second one ("vmvn"): "vmov.i8 d0, 0x54" For last two instructions it should emit: "vmov.i8 d0, 0xab" P.S.: In ARMAsmParser.cpp I have also fixed few nearby style issues in old code. Just for keeping method bodies in harmony with themselves. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@207080 91177308-0d34-0410-b5e6-96231b3b80d8 Stepan Dyatkovskiy 6 years ago
5 changed file(s) with 237 addition(s) and 5 deletion(s). Raw diff Collapse all Expand all
3838 let PrintMethod = "printNEONModImmOperand";
3939 let ParserMatchClass = nImmVMOVI32AsmOperand;
4040 }
41
42 def nImmVMOVI16AsmOperandByteReplicate :
43 AsmOperandClass {
44 let Name = "NEONi16vmovByteReplicate";
45 let PredicateMethod = "isNEONi16ByteReplicate";
46 let RenderMethod = "addNEONvmovByteReplicateOperands";
47 }
48 def nImmVMOVI32AsmOperandByteReplicate :
49 AsmOperandClass {
50 let Name = "NEONi32vmovByteReplicate";
51 let PredicateMethod = "isNEONi32ByteReplicate";
52 let RenderMethod = "addNEONvmovByteReplicateOperands";
53 }
54 def nImmVMVNI16AsmOperandByteReplicate :
55 AsmOperandClass {
56 let Name = "NEONi16invByteReplicate";
57 let PredicateMethod = "isNEONi16ByteReplicate";
58 let RenderMethod = "addNEONinvByteReplicateOperands";
59 }
60 def nImmVMVNI32AsmOperandByteReplicate :
61 AsmOperandClass {
62 let Name = "NEONi32invByteReplicate";
63 let PredicateMethod = "isNEONi32ByteReplicate";
64 let RenderMethod = "addNEONinvByteReplicateOperands";
65 }
66
67 def nImmVMOVI16ByteReplicate : Operand {
68 let PrintMethod = "printNEONModImmOperand";
69 let ParserMatchClass = nImmVMOVI16AsmOperandByteReplicate;
70 }
71 def nImmVMOVI32ByteReplicate : Operand {
72 let PrintMethod = "printNEONModImmOperand";
73 let ParserMatchClass = nImmVMOVI32AsmOperandByteReplicate;
74 }
75 def nImmVMVNI16ByteReplicate : Operand {
76 let PrintMethod = "printNEONModImmOperand";
77 let ParserMatchClass = nImmVMVNI16AsmOperandByteReplicate;
78 }
79 def nImmVMVNI32ByteReplicate : Operand {
80 let PrintMethod = "printNEONModImmOperand";
81 let ParserMatchClass = nImmVMVNI32AsmOperandByteReplicate;
82 }
83
4184 def nImmVMOVI32NegAsmOperand : AsmOperandClass { let Name = "NEONi32vmovNeg"; }
4285 def nImmVMOVI32Neg : Operand {
4386 let PrintMethod = "printNEONModImmOperand";
53005343 [(set QPR:$Vd, (v4f32 (NEONvmovFPImm timm:$SIMM)))]>;
53015344 } // isReMaterializable
53025345
5346 // Add support for bytes replication feature, so it could be GAS compatible.
5347 // E.g. instructions below:
5348 // "vmov.i32 d0, 0xffffffff"
5349 // "vmov.i32 d0, 0xabababab"
5350 // "vmov.i16 d0, 0xabab"
5351 // are incorrect, but we could deal with such cases.
5352 // For last two instructions, for example, it should emit:
5353 // "vmov.i8 d0, 0xab"
5354 def : NEONInstAlias<"vmov${p}.i16 $Vd, $Vm",
5355 (VMOVv8i8 DPR:$Vd, nImmVMOVI16ByteReplicate:$Vm, pred:$p)>;
5356 def : NEONInstAlias<"vmov${p}.i32 $Vd, $Vm",
5357 (VMOVv8i8 DPR:$Vd, nImmVMOVI32ByteReplicate:$Vm, pred:$p)>;
5358 def : NEONInstAlias<"vmov${p}.i16 $Vd, $Vm",
5359 (VMOVv16i8 QPR:$Vd, nImmVMOVI16ByteReplicate:$Vm, pred:$p)>;
5360 def : NEONInstAlias<"vmov${p}.i32 $Vd, $Vm",
5361 (VMOVv16i8 QPR:$Vd, nImmVMOVI32ByteReplicate:$Vm, pred:$p)>;
5362
5363 // Also add same support for VMVN instructions. So instruction:
5364 // "vmvn.i32 d0, 0xabababab"
5365 // actually means:
5366 // "vmov.i8 d0, 0x54"
5367 def : NEONInstAlias<"vmvn${p}.i16 $Vd, $Vm",
5368 (VMOVv8i8 DPR:$Vd, nImmVMVNI16ByteReplicate:$Vm, pred:$p)>;
5369 def : NEONInstAlias<"vmvn${p}.i32 $Vd, $Vm",
5370 (VMOVv8i8 DPR:$Vd, nImmVMVNI32ByteReplicate:$Vm, pred:$p)>;
5371 def : NEONInstAlias<"vmvn${p}.i16 $Vd, $Vm",
5372 (VMOVv16i8 QPR:$Vd, nImmVMVNI16ByteReplicate:$Vm, pred:$p)>;
5373 def : NEONInstAlias<"vmvn${p}.i32 $Vd, $Vm",
5374 (VMOVv16i8 QPR:$Vd, nImmVMVNI32ByteReplicate:$Vm, pred:$p)>;
53035375
53045376 // On some CPUs the two instructions "vmov.i32 dD, #0" and "vmov.i32 qD, #0"
53055377 // require zero cycles to execute so they should be used wherever possible for
16091609 }
16101610
16111611 bool isNEONi16splat() const {
1612 if (!isImm()) return false;
1612 if (isNEONByteReplicate(2))
1613 return false; // Leave that for bytes replication and forbid by default.
1614 if (!isImm())
1615 return false;
16131616 const MCConstantExpr *CE = dyn_cast(getImm());
16141617 // Must be a constant.
16151618 if (!CE) return false;
16191622 }
16201623
16211624 bool isNEONi32splat() const {
1622 if (!isImm()) return false;
1625 if (isNEONByteReplicate(4))
1626 return false; // Leave that for bytes replication and forbid by default.
1627 if (!isImm())
1628 return false;
16231629 const MCConstantExpr *CE = dyn_cast(getImm());
16241630 // Must be a constant.
16251631 if (!CE) return false;
16311637 (Value >= 0x01000000 && Value <= 0xff000000);
16321638 }
16331639
1634 bool isNEONi32vmov() const {
1635 if (!isImm()) return false;
1640 bool isNEONByteReplicate(unsigned NumBytes) const {
1641 if (!isImm())
1642 return false;
16361643 const MCConstantExpr *CE = dyn_cast(getImm());
16371644 // Must be a constant.
1638 if (!CE) return false;
1645 if (!CE)
1646 return false;
1647 int64_t Value = CE->getValue();
1648 if (!Value)
1649 return false; // Don't bother with zero.
1650
1651 unsigned char B = Value & 0xff;
1652 for (unsigned i = 1; i < NumBytes; ++i) {
1653 Value >>= 8;
1654 if ((Value & 0xff) != B)
1655 return false;
1656 }
1657 return true;
1658 }
1659 bool isNEONi16ByteReplicate() const { return isNEONByteReplicate(2); }
1660 bool isNEONi32ByteReplicate() const { return isNEONByteReplicate(4); }
1661 bool isNEONi32vmov() const {
1662 if (isNEONByteReplicate(4))
1663 return false; // Let it to be classified as byte-replicate case.
1664 if (!isImm())
1665 return false;
1666 const MCConstantExpr *CE = dyn_cast(getImm());
1667 // Must be a constant.
1668 if (!CE)
1669 return false;
16391670 int64_t Value = CE->getValue();
16401671 // i32 value with set bits only in one byte X000, 0X00, 00X0, or 000X,
16411672 // for VMOV/VMVN only, 00Xf or 0Xff are also accepted.
23832414 Inst.addOperand(MCOperand::CreateImm(Value));
23842415 }
23852416
2417 void addNEONinvByteReplicateOperands(MCInst &Inst, unsigned N) const {
2418 assert(N == 1 && "Invalid number of operands!");
2419 // The immediate encodes the type of constant as well as the value.
2420 const MCConstantExpr *CE = dyn_cast(getImm());
2421 unsigned Value = CE->getValue();
2422 assert((Inst.getOpcode() == ARM::VMOVv8i8 ||
2423 Inst.getOpcode() == ARM::VMOVv16i8) &&
2424 "All vmvn instructions that wants to replicate non-zero byte "
2425 "always must be replaced with VMOVv8i8 or VMOVv16i8.");
2426 unsigned B = ((~Value) & 0xff);
2427 B |= 0xe00; // cmode = 0b1110
2428 Inst.addOperand(MCOperand::CreateImm(B));
2429 }
23862430 void addNEONi32vmovOperands(MCInst &Inst, unsigned N) const {
23872431 assert(N == 1 && "Invalid number of operands!");
23882432 // The immediate encodes the type of constant as well as the value.
23972441 Inst.addOperand(MCOperand::CreateImm(Value));
23982442 }
23992443
2444 void addNEONvmovByteReplicateOperands(MCInst &Inst, unsigned N) const {
2445 assert(N == 1 && "Invalid number of operands!");
2446 // The immediate encodes the type of constant as well as the value.
2447 const MCConstantExpr *CE = dyn_cast(getImm());
2448 unsigned Value = CE->getValue();
2449 assert((Inst.getOpcode() == ARM::VMOVv8i8 ||
2450 Inst.getOpcode() == ARM::VMOVv16i8) &&
2451 "All instructions that wants to replicate non-zero byte "
2452 "always must be replaced with VMOVv8i8 or VMOVv16i8.");
2453 unsigned B = Value & 0xff;
2454 B |= 0xe00; // cmode = 0b1110
2455 Inst.addOperand(MCOperand::CreateImm(B));
2456 }
24002457 void addNEONi32vmovNegOperands(MCInst &Inst, unsigned N) const {
24012458 assert(N == 1 && "Invalid number of operands!");
24022459 // The immediate encodes the type of constant as well as the value.
0 @ PR18921, "vmov" part.
1 @ RUN: llvm-mc -triple=armv7-linux-gnueabi -show-encoding < %s | FileCheck %s
2 .text
3
4 @ CHECK: vmov.i8 d2, #0xff @ encoding: [0x1f,0x2e,0x87,0xf3]
5 @ CHECK: vmov.i8 q2, #0xff @ encoding: [0x5f,0x4e,0x87,0xf3]
6 @ CHECK: vmov.i8 d2, #0xab @ encoding: [0x1b,0x2e,0x82,0xf3]
7 @ CHECK: vmov.i8 q2, #0xab @ encoding: [0x5b,0x4e,0x82,0xf3]
8 @ CHECK: vmov.i8 q2, #0xab @ encoding: [0x5b,0x4e,0x82,0xf3]
9 @ CHECK: vmov.i8 q2, #0xab @ encoding: [0x5b,0x4e,0x82,0xf3]
10
11 @ CHECK: vmov.i8 d2, #0x0 @ encoding: [0x10,0x2e,0x80,0xf2]
12 @ CHECK: vmov.i8 q2, #0x0 @ encoding: [0x50,0x4e,0x80,0xf2]
13 @ CHECK: vmov.i8 d2, #0x54 @ encoding: [0x14,0x2e,0x85,0xf2]
14 @ CHECK: vmov.i8 q2, #0x54 @ encoding: [0x54,0x4e,0x85,0xf2]
15 @ CHECK: vmov.i8 d2, #0x54 @ encoding: [0x14,0x2e,0x85,0xf2]
16 @ CHECK: vmov.i8 q2, #0x54 @ encoding: [0x54,0x4e,0x85,0xf2]
17
18 vmov.i32 d2, #0xffffffff
19 vmov.i32 q2, #0xffffffff
20 vmov.i32 d2, #0xabababab
21 vmov.i32 q2, #0xabababab
22 vmov.i16 q2, #0xabab
23 vmov.i16 q2, #0xabab
24
25 vmvn.i32 d2, #0xffffffff
26 vmvn.i32 q2, #0xffffffff
27 vmvn.i32 d2, #0xabababab
28 vmvn.i32 q2, #0xabababab
29 vmvn.i16 d2, #0xabab
30 vmvn.i16 q2, #0xabab
0 @ RUN: not llvm-mc -triple=armv7-linux-gnueabi %s 2>&1 | FileCheck %s
1 .text
2
3 @ CHECK: error: invalid operand for instruction
4 @ CHECK: vmov.i32 d2, #0xffffffab
5 @ CHECK: error: invalid operand for instruction
6 @ CHECK: vmov.i32 q2, #0xffffffab
7 @ CHECK: error: invalid operand for instruction
8 @ CHECK: vmov.i16 q2, #0xffab
9 @ CHECK: error: invalid operand for instruction
10 @ CHECK: vmov.i16 q2, #0xffab
11
12 @ CHECK: error: invalid operand for instruction
13 @ CHECK: vmvn.i32 d2, #0xffffffab
14 @ CHECK: error: invalid operand for instruction
15 @ CHECK: vmvn.i32 q2, #0xffffffab
16 @ CHECK: error: invalid operand for instruction
17 @ CHECK: vmvn.i16 q2, #0xffab
18 @ CHECK: error: invalid operand for instruction
19 @ CHECK: vmvn.i16 q2, #0xffab
20
21 vmov.i32 d2, #0xffffffab
22 vmov.i32 q2, #0xffffffab
23 vmov.i16 q2, #0xffab
24 vmov.i16 q2, #0xffab
25
26 vmvn.i32 d2, #0xffffffab
27 vmvn.i32 q2, #0xffffffab
28 vmvn.i16 q2, #0xffab
29 vmvn.i16 q2, #0xffab
0 @ RUN: not llvm-mc -triple=armv7-linux-gnueabi %s 2>&1 | FileCheck %s
1 .text
2
3 @ CHECK: error: invalid operand for instruction
4 @ CHECK: vorr.i32 d2, #0xffffffff
5 @ CHECK: error: invalid operand for instruction
6 @ CHECK: vorr.i32 q2, #0xffffffff
7 @ CHECK: error: invalid operand for instruction
8 @ CHECK: vorr.i32 d2, #0xabababab
9 @ CHECK: error: invalid operand for instruction
10 @ CHECK: vorr.i32 q2, #0xabababab
11 @ CHECK: error: invalid operand for instruction
12 @ CHECK: vorr.i16 q2, #0xabab
13 @ CHECK: error: invalid operand for instruction
14 @ CHECK: vorr.i16 q2, #0xabab
15
16 @ CHECK: error: invalid operand for instruction
17 @ CHECK: vbic.i32 d2, #0xffffffff
18 @ CHECK: error: invalid operand for instruction
19 @ CHECK: vbic.i32 q2, #0xffffffff
20 @ CHECK: error: invalid operand for instruction
21 @ CHECK: vbic.i32 d2, #0xabababab
22 @ CHECK: error: invalid operand for instruction
23 @ CHECK: vbic.i32 q2, #0xabababab
24 @ CHECK: error: invalid operand for instruction
25 @ CHECK: vbic.i16 d2, #0xabab
26 @ CHECK: error: invalid operand for instruction
27 @ CHECK: vbic.i16 q2, #0xabab
28
29 vorr.i32 d2, #0xffffffff
30 vorr.i32 q2, #0xffffffff
31 vorr.i32 d2, #0xabababab
32 vorr.i32 q2, #0xabababab
33 vorr.i16 q2, #0xabab
34 vorr.i16 q2, #0xabab
35
36 vbic.i32 d2, #0xffffffff
37 vbic.i32 q2, #0xffffffff
38 vbic.i32 d2, #0xabababab
39 vbic.i32 q2, #0xabababab
40 vbic.i16 d2, #0xabab
41 vbic.i16 q2, #0xabab