Index: lib/Target/AArch64/AArch64RegisterInfo.td =================================================================== --- lib/Target/AArch64/AArch64RegisterInfo.td +++ lib/Target/AArch64/AArch64RegisterInfo.td @@ -859,6 +859,22 @@ def ZPR64 : ZPRRegOp<"d", ZPRAsmOp64, ZPR>; def ZPR128 : ZPRRegOp<"q", ZPRAsmOp128, ZPR>; +class FPRasZPR : AsmOperandClass{ + let Name = "FPR" # Width # "asZPR"; + let PredicateMethod = "isFPRasZPR"; + let RenderMethod = "addFPRasZPRRegOperands<" # Width # ">"; +} + +class FPRasZPROperand : RegisterOperand { + let ParserMatchClass = FPRasZPR; + let PrintMethod = "printZPRasFPR<" # Width # ">"; +} + +def FPR8asZPR : FPRasZPROperand<8>; +def FPR16asZPR : FPRasZPROperand<16>; +def FPR32asZPR : FPRasZPROperand<32>; +def FPR64asZPR : FPRasZPROperand<64>; +def FPR128asZPR : FPRasZPROperand<128>; let Namespace = "AArch64" in { def zsub0 : SubRegIndex<128, -1>; Index: lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp =================================================================== --- lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp +++ lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp @@ -934,6 +934,11 @@ AArch64MCRegisterClasses[Class].contains(getReg()); } + template bool isFPRasZPR() const { + return Kind == k_Register && Reg.Kind == RegKind::Scalar && + AArch64MCRegisterClasses[Class].contains(getReg()); + } + template DiagnosticPredicate isSVEPredicateVectorRegOfWidth() const { if (Kind != k_Register || Reg.Kind != RegKind::SVEPredicateVector) @@ -1269,6 +1274,21 @@ Inst.addOperand(MCOperand::createReg(Reg)); } + template + void addFPRasZPRRegOperands(MCInst &Inst, unsigned N) const { + unsigned Base; + switch (Width) { + case 8: Base = AArch64::B0; break; + case 16: Base = AArch64::H0; break; + case 32: Base = AArch64::S0; break; + case 64: Base = AArch64::D0; break; + case 128: Base = AArch64::Q0; break; + default: + llvm_unreachable("Unsupported width"); + } + Inst.addOperand(MCOperand::createReg(AArch64::Z0 + getReg() - Base)); + } + void addVectorReg64Operands(MCInst &Inst, unsigned N) const { assert(N == 1 && "Invalid number of operands!"); assert( Index: lib/Target/AArch64/InstPrinter/AArch64InstPrinter.h =================================================================== --- lib/Target/AArch64/InstPrinter/AArch64InstPrinter.h +++ lib/Target/AArch64/InstPrinter/AArch64InstPrinter.h @@ -180,6 +180,9 @@ template void printSVERegOp(const MCInst *MI, unsigned OpNum, const MCSubtargetInfo &STI, raw_ostream &O); + template + void printZPRasFPR(const MCInst *MI, unsigned OpNum, + const MCSubtargetInfo &STI, raw_ostream &O); }; class AArch64AppleInstPrinter : public AArch64InstPrinter { Index: lib/Target/AArch64/InstPrinter/AArch64InstPrinter.cpp =================================================================== --- lib/Target/AArch64/InstPrinter/AArch64InstPrinter.cpp +++ lib/Target/AArch64/InstPrinter/AArch64InstPrinter.cpp @@ -1499,3 +1499,21 @@ else O << '#' << formatHex((uint64_t)PrintVal); } + +template +void AArch64InstPrinter::printZPRasFPR(const MCInst *MI, unsigned OpNum, + const MCSubtargetInfo &STI, + raw_ostream &O) { + unsigned Base; + switch (Width) { + case 8: Base = AArch64::B0; break; + case 16: Base = AArch64::H0; break; + case 32: Base = AArch64::S0; break; + case 64: Base = AArch64::D0; break; + case 128: Base = AArch64::Q0; break; + default: + llvm_unreachable("Unsupported width"); + } + unsigned Reg = MI->getOperand(OpNum).getReg(); + O << getRegisterName(Reg - AArch64::Z0 + Base); +} Index: lib/Target/AArch64/SVEInstrFormats.td =================================================================== --- lib/Target/AArch64/SVEInstrFormats.td +++ lib/Target/AArch64/SVEInstrFormats.td @@ -334,6 +334,16 @@ (!cast(NAME # _D) ZPR64:$Zd, ZPR64:$Zn, sve_elm_idx_extdup_d:$idx), 1>; def : InstAlias<"mov $Zd, $Zn$idx", (!cast(NAME # _Q) ZPR128:$Zd, ZPR128:$Zn, sve_elm_idx_extdup_q:$idx), 1>; + def : InstAlias<"mov $Zd, $Bn", + (!cast(NAME # _B) ZPR8:$Zd, FPR8asZPR:$Bn, 0), 2>; + def : InstAlias<"mov $Zd, $Hn", + (!cast(NAME # _H) ZPR16:$Zd, FPR16asZPR:$Hn, 0), 2>; + def : InstAlias<"mov $Zd, $Sn", + (!cast(NAME # _S) ZPR32:$Zd, FPR32asZPR:$Sn, 0), 2>; + def : InstAlias<"mov $Zd, $Dn", + (!cast(NAME # _D) ZPR64:$Zd, FPR64asZPR:$Dn, 0), 2>; + def : InstAlias<"mov $Zd, $Qn", + (!cast(NAME # _Q) ZPR128:$Zd, FPR128asZPR:$Qn, 0), 2>; } //===----------------------------------------------------------------------===// Index: test/MC/AArch64/SVE/dup-diagnostics.s =================================================================== --- test/MC/AArch64/SVE/dup-diagnostics.s +++ test/MC/AArch64/SVE/dup-diagnostics.s @@ -141,6 +141,31 @@ // --------------------------------------------------------------------------// // Immediate not compatible with encode/decode function. +dup z0.b, b0 +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid operand for instruction +// CHECK-NEXT: dup z0.b, b0 +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +dup z0.h, h0 +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid operand for instruction +// CHECK-NEXT: dup z0.h, h0 +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +dup z0.s, s0 +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid operand for instruction +// CHECK-NEXT: dup z0.s, s0 +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +dup z0.d, d0 +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid operand for instruction +// CHECK-NEXT: dup z0.d, d0 +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +dup z0.q, q0 +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid operand for instruction +// CHECK-NEXT: dup z0.q, q0 +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + dup z24.b, z17.b[-1] // CHECK: [[@LINE-1]]:{{[0-9]+}}: error: vector lane must be an integer in range [0, 63]. // CHECK-NEXT: dup z24.b, z17.b[-1] Index: test/MC/AArch64/SVE/dup.s =================================================================== --- test/MC/AArch64/SVE/dup.s +++ test/MC/AArch64/SVE/dup.s @@ -182,31 +182,31 @@ // CHECK-UNKNOWN: f5 ef f8 25 dup z0.b, z0.b[0] -// CHECK-INST: mov z0.b, z0.b[0] +// CHECK-INST: mov z0.b, b0 // CHECK-ENCODING: [0x00,0x20,0x21,0x05] // CHECK-ERROR: instruction requires: sve // CHECK-UNKNOWN: 00 20 21 05 dup z0.h, z0.h[0] -// CHECK-INST: mov z0.h, z0.h[0] +// CHECK-INST: mov z0.h, h0 // CHECK-ENCODING: [0x00,0x20,0x22,0x05] // CHECK-ERROR: instruction requires: sve // CHECK-UNKNOWN: 00 20 22 05 dup z0.s, z0.s[0] -// CHECK-INST: mov z0.s, z0.s[0] +// CHECK-INST: mov z0.s, s0 // CHECK-ENCODING: [0x00,0x20,0x24,0x05] // CHECK-ERROR: instruction requires: sve // CHECK-UNKNOWN: 00 20 24 05 dup z0.d, z0.d[0] -// CHECK-INST: mov z0.d, z0.d[0] +// CHECK-INST: mov z0.d, d0 // CHECK-ENCODING: [0x00,0x20,0x28,0x05] // CHECK-ERROR: instruction requires: sve // CHECK-UNKNOWN: 00 20 28 05 dup z0.q, z0.q[0] -// CHECK-INST: mov z0.q, z0.q[0] +// CHECK-INST: mov z0.q, q0 // CHECK-ENCODING: [0x00,0x20,0x30,0x05] // CHECK-ERROR: instruction requires: sve // CHECK-UNKNOWN: 00 20 30 05 Index: test/MC/AArch64/SVE/mov.s =================================================================== --- test/MC/AArch64/SVE/mov.s +++ test/MC/AArch64/SVE/mov.s @@ -406,31 +406,61 @@ // Tests for indexed variant mov z0.b, z0.b[0] -// CHECK-INST: mov z0.b, z0.b[0] +// CHECK-INST: mov z0.b, b0 // CHECK-ENCODING: [0x00,0x20,0x21,0x05] // CHECK-ERROR: instruction requires: sve // CHECK-UNKNOWN: 00 20 21 05 mov z0.h, z0.h[0] -// CHECK-INST: mov z0.h, z0.h[0] +// CHECK-INST: mov z0.h, h0 // CHECK-ENCODING: [0x00,0x20,0x22,0x05] // CHECK-ERROR: instruction requires: sve // CHECK-UNKNOWN: 00 20 22 05 mov z0.s, z0.s[0] -// CHECK-INST: mov z0.s, z0.s[0] +// CHECK-INST: mov z0.s, s0 // CHECK-ENCODING: [0x00,0x20,0x24,0x05] // CHECK-ERROR: instruction requires: sve // CHECK-UNKNOWN: 00 20 24 05 mov z0.d, z0.d[0] -// CHECK-INST: mov z0.d, z0.d[0] +// CHECK-INST: mov z0.d, d0 // CHECK-ENCODING: [0x00,0x20,0x28,0x05] // CHECK-ERROR: instruction requires: sve // CHECK-UNKNOWN: 00 20 28 05 mov z0.q, z0.q[0] -// CHECK-INST: mov z0.q, z0.q[0] +// CHECK-INST: mov z0.q, q0 +// CHECK-ENCODING: [0x00,0x20,0x30,0x05] +// CHECK-ERROR: instruction requires: sve +// CHECK-UNKNOWN: 00 20 30 05 + +mov z0.b, b0 +// CHECK-INST: mov z0.b, b0 +// CHECK-ENCODING: [0x00,0x20,0x21,0x05] +// CHECK-ERROR: instruction requires: sve +// CHECK-UNKNOWN: 00 20 21 05 + +mov z0.h, h0 +// CHECK-INST: mov z0.h, h0 +// CHECK-ENCODING: [0x00,0x20,0x22,0x05] +// CHECK-ERROR: instruction requires: sve +// CHECK-UNKNOWN: 00 20 22 05 + +mov z0.s, s0 +// CHECK-INST: mov z0.s, s0 +// CHECK-ENCODING: [0x00,0x20,0x24,0x05] +// CHECK-ERROR: instruction requires: sve +// CHECK-UNKNOWN: 00 20 24 05 + +mov z0.d, d0 +// CHECK-INST: mov z0.d, d0 +// CHECK-ENCODING: [0x00,0x20,0x28,0x05] +// CHECK-ERROR: instruction requires: sve +// CHECK-UNKNOWN: 00 20 28 05 + +mov z0.q, q0 +// CHECK-INST: mov z0.q, q0 // CHECK-ENCODING: [0x00,0x20,0x30,0x05] // CHECK-ERROR: instruction requires: sve // CHECK-UNKNOWN: 00 20 30 05