diff --git a/lib/Target/ARM64/ARM64ISelDAGToDAG.cpp b/lib/Target/ARM64/ARM64ISelDAGToDAG.cpp index ce4203f321c..8fec6f02b76 100644 --- a/lib/Target/ARM64/ARM64ISelDAGToDAG.cpp +++ b/lib/Target/ARM64/ARM64ISelDAGToDAG.cpp @@ -111,27 +111,18 @@ public: return SelectAddrModeUnscaled(N, 16, Base, OffImm); } - bool SelectAddrModeRO8(SDValue N, SDValue &Base, SDValue &Offset, - SDValue &Imm) { - return SelectAddrModeRO(N, 1, Base, Offset, Imm); + template + bool SelectAddrModeWRO(SDValue N, SDValue &Base, SDValue &Offset, + SDValue &SignExtend, SDValue &DoShift) { + return SelectAddrModeWRO(N, Width / 8, Base, Offset, SignExtend, DoShift); } - bool SelectAddrModeRO16(SDValue N, SDValue &Base, SDValue &Offset, - SDValue &Imm) { - return SelectAddrModeRO(N, 2, Base, Offset, Imm); + + template + bool SelectAddrModeXRO(SDValue N, SDValue &Base, SDValue &Offset, + SDValue &SignExtend, SDValue &DoShift) { + return SelectAddrModeXRO(N, Width / 8, Base, Offset, SignExtend, DoShift); } - bool SelectAddrModeRO32(SDValue N, SDValue &Base, SDValue &Offset, - SDValue &Imm) { - return SelectAddrModeRO(N, 4, Base, Offset, Imm); - } - bool SelectAddrModeRO64(SDValue N, SDValue &Base, SDValue &Offset, - SDValue &Imm) { - return SelectAddrModeRO(N, 8, Base, Offset, Imm); - } - bool SelectAddrModeRO128(SDValue N, SDValue &Base, SDValue &Offset, - SDValue &Imm) { - return SelectAddrModeRO(N, 16, Base, Offset, Imm); - } - bool SelectAddrModeNoIndex(SDValue N, SDValue &Val); + /// Form sequences of consecutive 64/128-bit registers for use in NEON /// instructions making use of a vector-list (e.g. ldN, tbl). Vecs must have @@ -179,11 +170,15 @@ private: SDValue &OffImm); bool SelectAddrModeUnscaled(SDValue N, unsigned Size, SDValue &Base, SDValue &OffImm); - bool SelectAddrModeRO(SDValue N, unsigned Size, SDValue &Base, - SDValue &Offset, SDValue &Imm); + bool SelectAddrModeWRO(SDValue N, unsigned Size, SDValue &Base, + SDValue &Offset, SDValue &SignExtend, + SDValue &DoShift); + bool SelectAddrModeXRO(SDValue N, unsigned Size, SDValue &Base, + SDValue &Offset, SDValue &SignExtend, + SDValue &DoShift); bool isWorthFolding(SDValue V) const; - bool SelectExtendedSHL(SDValue N, unsigned Size, SDValue &Offset, - SDValue &Imm); + bool SelectExtendedSHL(SDValue N, unsigned Size, bool WantExtend, + SDValue &Offset, SDValue &SignExtend); template bool SelectCVTFixedPosOperand(SDValue N, SDValue &FixedPos) { @@ -219,14 +214,6 @@ static bool isOpcWithIntImmediate(const SDNode *N, unsigned Opc, isIntImmediate(N->getOperand(1).getNode(), Imm); } -bool ARM64DAGToDAGISel::SelectAddrModeNoIndex(SDValue N, SDValue &Val) { - EVT ValTy = N.getValueType(); - if (ValTy != MVT::i64) - return false; - Val = N; - return true; -} - bool ARM64DAGToDAGISel::SelectInlineAsmMemoryOperand( const SDValue &Op, char ConstraintCode, std::vector &OutOps) { assert(ConstraintCode == 'm' && "unexpected asm memory constraint"); @@ -563,8 +550,8 @@ bool ARM64DAGToDAGISel::SelectArithExtendedRegister(SDValue N, SDValue &Reg, // if we're folding a (sext i8), we need the RHS to be a GPR32, even though // there might not be an actual 32-bit value in the program. We can // (harmlessly) synthesize one by injected an EXTRACT_SUBREG here. - if (Reg.getValueType() == MVT::i64 && Ext != ARM64_AM::UXTX && - Ext != ARM64_AM::SXTX) { + assert(Ext != ARM64_AM::UXTX && Ext != ARM64_AM::SXTX); + if (Reg.getValueType() == MVT::i64) { SDValue SubReg = CurDAG->getTargetConstant(ARM64::sub_32, MVT::i32); MachineSDNode *Node = CurDAG->getMachineNode( TargetOpcode::EXTRACT_SUBREG, SDLoc(N), MVT::i32, Reg, SubReg); @@ -675,47 +662,44 @@ static SDValue Widen(SelectionDAG *CurDAG, SDValue N) { return SDValue(Node, 0); } -static SDValue WidenIfNeeded(SelectionDAG *CurDAG, SDValue N) { - if (N.getValueType() == MVT::i32) { - return Widen(CurDAG, N); - } - - return N; -} - /// \brief Check if the given SHL node (\p N), can be used to form an /// extended register for an addressing mode. bool ARM64DAGToDAGISel::SelectExtendedSHL(SDValue N, unsigned Size, - SDValue &Offset, SDValue &Imm) { + bool WantExtend, SDValue &Offset, + SDValue &SignExtend) { assert(N.getOpcode() == ISD::SHL && "Invalid opcode."); ConstantSDNode *CSD = dyn_cast(N.getOperand(1)); - if (CSD && (CSD->getZExtValue() & 0x7) == CSD->getZExtValue()) { + if (!CSD || (CSD->getZExtValue() & 0x7) != CSD->getZExtValue()) + return false; + if (WantExtend) { ARM64_AM::ShiftExtendType Ext = getExtendTypeForNode(N.getOperand(0), true); - if (Ext == ARM64_AM::InvalidShiftExtend) { - Ext = ARM64_AM::UXTX; - Offset = WidenIfNeeded(CurDAG, N.getOperand(0)); - } else { - Offset = WidenIfNeeded(CurDAG, N.getOperand(0).getOperand(0)); - } - - unsigned LegalShiftVal = Log2_32(Size); - unsigned ShiftVal = CSD->getZExtValue(); - - if (ShiftVal != 0 && ShiftVal != LegalShiftVal) + if (Ext == ARM64_AM::InvalidShiftExtend) return false; - Imm = CurDAG->getTargetConstant( - ARM64_AM::getMemExtendImm(Ext, ShiftVal != 0), MVT::i32); - if (isWorthFolding(N)) - return true; + Offset = N.getOperand(0).getOperand(0); + SignExtend = CurDAG->getTargetConstant(Ext == ARM64_AM::SXTW, MVT::i32); + } else { + Offset = N.getOperand(0); + SignExtend = CurDAG->getTargetConstant(0, MVT::i32); } + + unsigned LegalShiftVal = Log2_32(Size); + unsigned ShiftVal = CSD->getZExtValue(); + + if (ShiftVal != 0 && ShiftVal != LegalShiftVal) + return false; + + if (isWorthFolding(N)) + return true; + return false; } -bool ARM64DAGToDAGISel::SelectAddrModeRO(SDValue N, unsigned Size, +bool ARM64DAGToDAGISel::SelectAddrModeWRO(SDValue N, unsigned Size, SDValue &Base, SDValue &Offset, - SDValue &Imm) { + SDValue &SignExtend, + SDValue &DoShift) { if (N.getOpcode() != ISD::ADD) return false; SDValue LHS = N.getOperand(0); @@ -740,26 +724,30 @@ bool ARM64DAGToDAGISel::SelectAddrModeRO(SDValue N, unsigned Size, // Try to match a shifted extend on the RHS. if (IsExtendedRegisterWorthFolding && RHS.getOpcode() == ISD::SHL && - SelectExtendedSHL(RHS, Size, Offset, Imm)) { + SelectExtendedSHL(RHS, Size, true, Offset, SignExtend)) { Base = LHS; + DoShift = CurDAG->getTargetConstant(true, MVT::i32); return true; } // Try to match a shifted extend on the LHS. if (IsExtendedRegisterWorthFolding && LHS.getOpcode() == ISD::SHL && - SelectExtendedSHL(LHS, Size, Offset, Imm)) { + SelectExtendedSHL(LHS, Size, true, Offset, SignExtend)) { Base = RHS; + DoShift = CurDAG->getTargetConstant(true, MVT::i32); return true; } - ARM64_AM::ShiftExtendType Ext = ARM64_AM::UXTX; + // There was no shift, whatever else we find. + DoShift = CurDAG->getTargetConstant(false, MVT::i32); + + ARM64_AM::ShiftExtendType Ext = ARM64_AM::InvalidShiftExtend; // Try to match an unshifted extend on the LHS. if (IsExtendedRegisterWorthFolding && (Ext = getExtendTypeForNode(LHS, true)) != ARM64_AM::InvalidShiftExtend) { Base = RHS; - Offset = WidenIfNeeded(CurDAG, LHS.getOperand(0)); - Imm = CurDAG->getTargetConstant(ARM64_AM::getMemExtendImm(Ext, false), - MVT::i32); + Offset = LHS.getOperand(0); + SignExtend = CurDAG->getTargetConstant(Ext == ARM64_AM::SXTW, MVT::i32); if (isWorthFolding(LHS)) return true; } @@ -768,19 +756,62 @@ bool ARM64DAGToDAGISel::SelectAddrModeRO(SDValue N, unsigned Size, if (IsExtendedRegisterWorthFolding && (Ext = getExtendTypeForNode(RHS, true)) != ARM64_AM::InvalidShiftExtend) { Base = LHS; - Offset = WidenIfNeeded(CurDAG, RHS.getOperand(0)); - Imm = CurDAG->getTargetConstant(ARM64_AM::getMemExtendImm(Ext, false), - MVT::i32); + Offset = RHS.getOperand(0); + SignExtend = CurDAG->getTargetConstant(Ext == ARM64_AM::SXTW, MVT::i32); if (isWorthFolding(RHS)) return true; } + return false; +} + +bool ARM64DAGToDAGISel::SelectAddrModeXRO(SDValue N, unsigned Size, + SDValue &Base, SDValue &Offset, + SDValue &SignExtend, + SDValue &DoShift) { + if (N.getOpcode() != ISD::ADD) + return false; + SDValue LHS = N.getOperand(0); + SDValue RHS = N.getOperand(1); + + // We don't want to match immediate adds here, because they are better lowered + // to the register-immediate addressing modes. + if (isa(LHS) || isa(RHS)) + return false; + + // Check if this particular node is reused in any non-memory related + // operation. If yes, do not try to fold this node into the address + // computation, since the computation will be kept. + const SDNode *Node = N.getNode(); + for (SDNode *UI : Node->uses()) { + if (!isa(*UI)) + return false; + } + + // Remember if it is worth folding N when it produces extended register. + bool IsExtendedRegisterWorthFolding = isWorthFolding(N); + + // Try to match a shifted extend on the RHS. + if (IsExtendedRegisterWorthFolding && RHS.getOpcode() == ISD::SHL && + SelectExtendedSHL(RHS, Size, false, Offset, SignExtend)) { + Base = LHS; + DoShift = CurDAG->getTargetConstant(true, MVT::i32); + return true; + } + + // Try to match a shifted extend on the LHS. + if (IsExtendedRegisterWorthFolding && LHS.getOpcode() == ISD::SHL && + SelectExtendedSHL(LHS, Size, false, Offset, SignExtend)) { + Base = RHS; + DoShift = CurDAG->getTargetConstant(true, MVT::i32); + return true; + } + // Match any non-shifted, non-extend, non-immediate add expression. Base = LHS; - Offset = WidenIfNeeded(CurDAG, RHS); - Ext = ARM64_AM::UXTX; - Imm = CurDAG->getTargetConstant(ARM64_AM::getMemExtendImm(Ext, false), - MVT::i32); + Offset = RHS; + SignExtend = CurDAG->getTargetConstant(false, MVT::i32); + DoShift = CurDAG->getTargetConstant(false, MVT::i32); // Reg1 + Reg2 is free: no check needed. return true; } diff --git a/lib/Target/ARM64/ARM64InstrAtomics.td b/lib/Target/ARM64/ARM64InstrAtomics.td index 989e7a2e74a..1d1483ac126 100644 --- a/lib/Target/ARM64/ARM64InstrAtomics.td +++ b/lib/Target/ARM64/ARM64InstrAtomics.td @@ -43,39 +43,63 @@ class relaxed_load // 8-bit loads def : Pat<(acquiring_load GPR64sp:$ptr), (LDARB GPR64sp:$ptr)>; -def : Pat<(relaxed_load ro_indexed8:$addr), - (LDRBBro ro_indexed8:$addr)>; -def : Pat<(relaxed_load am_indexed8:$addr), - (LDRBBui am_indexed8:$addr)>; -def : Pat<(relaxed_load am_unscaled8:$addr), - (LDURBBi am_unscaled8:$addr)>; +def : Pat<(relaxed_load (ro_Windexed8 GPR64sp:$Rn, GPR32:$Rm, + ro_Wextend8:$offset)), + (LDRBBroW GPR64sp:$Rn, GPR32:$Rm, ro_Wextend8:$offset)>; +def : Pat<(relaxed_load (ro_Xindexed8 GPR64sp:$Rn, GPR64:$Rm, + ro_Xextend8:$offset)), + (LDRBBroX GPR64sp:$Rn, GPR64:$Rm, ro_Xextend8:$offset)>; +def : Pat<(relaxed_load (am_indexed8 GPR64sp:$Rn, + uimm12s1:$offset)), + (LDRBBui GPR64sp:$Rn, uimm12s1:$offset)>; +def : Pat<(relaxed_load + (am_unscaled8 GPR64sp:$Rn, simm9:$offset)), + (LDURBBi GPR64sp:$Rn, simm9:$offset)>; // 16-bit loads def : Pat<(acquiring_load GPR64sp:$ptr), (LDARH GPR64sp:$ptr)>; -def : Pat<(relaxed_load ro_indexed16:$addr), - (LDRHHro ro_indexed16:$addr)>; -def : Pat<(relaxed_load am_indexed16:$addr), - (LDRHHui am_indexed16:$addr)>; -def : Pat<(relaxed_load am_unscaled16:$addr), - (LDURHHi am_unscaled16:$addr)>; +def : Pat<(relaxed_load (ro_Windexed16 GPR64sp:$Rn, GPR32:$Rm, + ro_Wextend16:$extend)), + (LDRHHroW GPR64sp:$Rn, GPR32:$Rm, ro_Wextend16:$extend)>; +def : Pat<(relaxed_load (ro_Xindexed16 GPR64sp:$Rn, GPR64:$Rm, + ro_Xextend16:$extend)), + (LDRHHroX GPR64sp:$Rn, GPR64:$Rm, ro_Xextend16:$extend)>; +def : Pat<(relaxed_load (am_indexed16 GPR64sp:$Rn, + uimm12s2:$offset)), + (LDRHHui GPR64sp:$Rn, uimm12s2:$offset)>; +def : Pat<(relaxed_load + (am_unscaled16 GPR64sp:$Rn, simm9:$offset)), + (LDURHHi GPR64sp:$Rn, simm9:$offset)>; // 32-bit loads def : Pat<(acquiring_load GPR64sp:$ptr), (LDARW GPR64sp:$ptr)>; -def : Pat<(relaxed_load ro_indexed32:$addr), - (LDRWro ro_indexed32:$addr)>; -def : Pat<(relaxed_load am_indexed32:$addr), - (LDRWui am_indexed32:$addr)>; -def : Pat<(relaxed_load am_unscaled32:$addr), - (LDURWi am_unscaled32:$addr)>; +def : Pat<(relaxed_load (ro_Windexed32 GPR64sp:$Rn, GPR32:$Rm, + ro_Wextend32:$extend)), + (LDRWroW GPR64sp:$Rn, GPR32:$Rm, ro_Wextend32:$extend)>; +def : Pat<(relaxed_load (ro_Xindexed32 GPR64sp:$Rn, GPR64:$Rm, + ro_Xextend32:$extend)), + (LDRWroX GPR64sp:$Rn, GPR64:$Rm, ro_Xextend32:$extend)>; +def : Pat<(relaxed_load (am_indexed32 GPR64sp:$Rn, + uimm12s4:$offset)), + (LDRWui GPR64sp:$Rn, uimm12s4:$offset)>; +def : Pat<(relaxed_load + (am_unscaled32 GPR64sp:$Rn, simm9:$offset)), + (LDURWi GPR64sp:$Rn, simm9:$offset)>; // 64-bit loads def : Pat<(acquiring_load GPR64sp:$ptr), (LDARX GPR64sp:$ptr)>; -def : Pat<(relaxed_load ro_indexed64:$addr), - (LDRXro ro_indexed64:$addr)>; -def : Pat<(relaxed_load am_indexed64:$addr), - (LDRXui am_indexed64:$addr)>; -def : Pat<(relaxed_load am_unscaled64:$addr), - (LDURXi am_unscaled64:$addr)>; +def : Pat<(relaxed_load (ro_Windexed64 GPR64sp:$Rn, GPR32:$Rm, + ro_Wextend64:$extend)), + (LDRXroW GPR64sp:$Rn, GPR32:$Rm, ro_Wextend64:$extend)>; +def : Pat<(relaxed_load (ro_Xindexed64 GPR64sp:$Rn, GPR64:$Rm, + ro_Xextend64:$extend)), + (LDRXroX GPR64sp:$Rn, GPR64:$Rm, ro_Xextend64:$extend)>; +def : Pat<(relaxed_load (am_indexed64 GPR64sp:$Rn, + uimm12s8:$offset)), + (LDRXui GPR64sp:$Rn, uimm12s8:$offset)>; +def : Pat<(relaxed_load + (am_unscaled64 GPR64sp:$Rn, simm9:$offset)), + (LDURXi GPR64sp:$Rn, simm9:$offset)>; //===---------------------------------- // Atomic stores @@ -103,42 +127,74 @@ class relaxed_store // 8-bit stores def : Pat<(releasing_store GPR64sp:$ptr, GPR32:$val), (STLRB GPR32:$val, GPR64sp:$ptr)>; -def : Pat<(relaxed_store ro_indexed8:$ptr, GPR32:$val), - (STRBBro GPR32:$val, ro_indexed8:$ptr)>; -def : Pat<(relaxed_store am_indexed8:$ptr, GPR32:$val), - (STRBBui GPR32:$val, am_indexed8:$ptr)>; -def : Pat<(relaxed_store am_unscaled8:$ptr, GPR32:$val), - (STURBBi GPR32:$val, am_unscaled8:$ptr)>; +def : Pat<(relaxed_store + (ro_Windexed8 GPR64sp:$Rn, GPR32:$Rm, ro_Wextend8:$extend), + GPR32:$val), + (STRBBroW GPR32:$val, GPR64sp:$Rn, GPR32:$Rm, ro_Wextend8:$extend)>; +def : Pat<(relaxed_store + (ro_Xindexed8 GPR64sp:$Rn, GPR64:$Rm, ro_Xextend8:$extend), + GPR32:$val), + (STRBBroX GPR32:$val, GPR64sp:$Rn, GPR64:$Rm, ro_Xextend8:$extend)>; +def : Pat<(relaxed_store + (am_indexed8 GPR64sp:$Rn, uimm12s1:$offset), GPR32:$val), + (STRBBui GPR32:$val, GPR64sp:$Rn, uimm12s1:$offset)>; +def : Pat<(relaxed_store + (am_unscaled8 GPR64sp:$Rn, simm9:$offset), GPR32:$val), + (STURBBi GPR32:$val, GPR64sp:$Rn, simm9:$offset)>; // 16-bit stores def : Pat<(releasing_store GPR64sp:$ptr, GPR32:$val), (STLRH GPR32:$val, GPR64sp:$ptr)>; -def : Pat<(relaxed_store ro_indexed16:$ptr, GPR32:$val), - (STRHHro GPR32:$val, ro_indexed16:$ptr)>; -def : Pat<(relaxed_store am_indexed16:$ptr, GPR32:$val), - (STRHHui GPR32:$val, am_indexed16:$ptr)>; -def : Pat<(relaxed_store am_unscaled16:$ptr, GPR32:$val), - (STURHHi GPR32:$val, am_unscaled16:$ptr)>; +def : Pat<(relaxed_store (ro_Windexed16 GPR64sp:$Rn, GPR32:$Rm, + ro_Wextend16:$extend), + GPR32:$val), + (STRHHroW GPR32:$val, GPR64sp:$Rn, GPR32:$Rm, ro_Wextend16:$extend)>; +def : Pat<(relaxed_store (ro_Xindexed16 GPR64sp:$Rn, GPR64:$Rm, + ro_Xextend16:$extend), + GPR32:$val), + (STRHHroX GPR32:$val, GPR64sp:$Rn, GPR64:$Rm, ro_Xextend16:$extend)>; +def : Pat<(relaxed_store + (am_indexed16 GPR64sp:$Rn, uimm12s2:$offset), GPR32:$val), + (STRHHui GPR32:$val, GPR64sp:$Rn, uimm12s2:$offset)>; +def : Pat<(relaxed_store + (am_unscaled16 GPR64sp:$Rn, simm9:$offset), GPR32:$val), + (STURHHi GPR32:$val, GPR64sp:$Rn, simm9:$offset)>; // 32-bit stores def : Pat<(releasing_store GPR64sp:$ptr, GPR32:$val), (STLRW GPR32:$val, GPR64sp:$ptr)>; -def : Pat<(relaxed_store ro_indexed32:$ptr, GPR32:$val), - (STRWro GPR32:$val, ro_indexed32:$ptr)>; -def : Pat<(relaxed_store am_indexed32:$ptr, GPR32:$val), - (STRWui GPR32:$val, am_indexed32:$ptr)>; -def : Pat<(relaxed_store am_unscaled32:$ptr, GPR32:$val), - (STURWi GPR32:$val, am_unscaled32:$ptr)>; +def : Pat<(relaxed_store (ro_Windexed32 GPR64sp:$Rn, GPR32:$Rm, + ro_Wextend32:$extend), + GPR32:$val), + (STRWroW GPR32:$val, GPR64sp:$Rn, GPR32:$Rm, ro_Wextend32:$extend)>; +def : Pat<(relaxed_store (ro_Xindexed32 GPR64sp:$Rn, GPR64:$Rm, + ro_Xextend32:$extend), + GPR32:$val), + (STRWroX GPR32:$val, GPR64sp:$Rn, GPR64:$Rm, ro_Xextend32:$extend)>; +def : Pat<(relaxed_store + (am_indexed32 GPR64sp:$Rn, uimm12s4:$offset), GPR32:$val), + (STRWui GPR32:$val, GPR64sp:$Rn, uimm12s4:$offset)>; +def : Pat<(relaxed_store + (am_unscaled32 GPR64sp:$Rn, simm9:$offset), GPR32:$val), + (STURWi GPR32:$val, GPR64sp:$Rn, simm9:$offset)>; // 64-bit stores def : Pat<(releasing_store GPR64sp:$ptr, GPR64:$val), (STLRX GPR64:$val, GPR64sp:$ptr)>; -def : Pat<(relaxed_store ro_indexed64:$ptr, GPR64:$val), - (STRXro GPR64:$val, ro_indexed64:$ptr)>; -def : Pat<(relaxed_store am_indexed64:$ptr, GPR64:$val), - (STRXui GPR64:$val, am_indexed64:$ptr)>; -def : Pat<(relaxed_store am_unscaled64:$ptr, GPR64:$val), - (STURXi GPR64:$val, am_unscaled64:$ptr)>; +def : Pat<(relaxed_store (ro_Windexed64 GPR64sp:$Rn, GPR32:$Rm, + ro_Wextend16:$extend), + GPR64:$val), + (STRXroW GPR64:$val, GPR64sp:$Rn, GPR32:$Rm, ro_Wextend64:$extend)>; +def : Pat<(relaxed_store (ro_Xindexed64 GPR64sp:$Rn, GPR64:$Rm, + ro_Xextend16:$extend), + GPR64:$val), + (STRXroX GPR64:$val, GPR64sp:$Rn, GPR64:$Rm, ro_Xextend64:$extend)>; +def : Pat<(relaxed_store + (am_indexed64 GPR64sp:$Rn, uimm12s8:$offset), GPR64:$val), + (STRXui GPR64:$val, GPR64sp:$Rn, uimm12s8:$offset)>; +def : Pat<(relaxed_store + (am_unscaled64 GPR64sp:$Rn, simm9:$offset), GPR64:$val), + (STURXi GPR64:$val, GPR64sp:$Rn, simm9:$offset)>; //===---------------------------------- // Low-level exclusive operations @@ -162,20 +218,20 @@ def ldxr_8 : PatFrag<(ops node:$ptr), (int_arm64_ldxr node:$ptr), [{ return cast(N)->getMemoryVT() == MVT::i64; }]>; -def : Pat<(ldxr_1 am_noindex:$addr), - (SUBREG_TO_REG (i64 0), (LDXRB am_noindex:$addr), sub_32)>; -def : Pat<(ldxr_2 am_noindex:$addr), - (SUBREG_TO_REG (i64 0), (LDXRH am_noindex:$addr), sub_32)>; -def : Pat<(ldxr_4 am_noindex:$addr), - (SUBREG_TO_REG (i64 0), (LDXRW am_noindex:$addr), sub_32)>; -def : Pat<(ldxr_8 am_noindex:$addr), (LDXRX am_noindex:$addr)>; +def : Pat<(ldxr_1 GPR64sp:$addr), + (SUBREG_TO_REG (i64 0), (LDXRB GPR64sp:$addr), sub_32)>; +def : Pat<(ldxr_2 GPR64sp:$addr), + (SUBREG_TO_REG (i64 0), (LDXRH GPR64sp:$addr), sub_32)>; +def : Pat<(ldxr_4 GPR64sp:$addr), + (SUBREG_TO_REG (i64 0), (LDXRW GPR64sp:$addr), sub_32)>; +def : Pat<(ldxr_8 GPR64sp:$addr), (LDXRX GPR64sp:$addr)>; -def : Pat<(and (ldxr_1 am_noindex:$addr), 0xff), - (SUBREG_TO_REG (i64 0), (LDXRB am_noindex:$addr), sub_32)>; -def : Pat<(and (ldxr_2 am_noindex:$addr), 0xffff), - (SUBREG_TO_REG (i64 0), (LDXRH am_noindex:$addr), sub_32)>; -def : Pat<(and (ldxr_4 am_noindex:$addr), 0xffffffff), - (SUBREG_TO_REG (i64 0), (LDXRW am_noindex:$addr), sub_32)>; +def : Pat<(and (ldxr_1 GPR64sp:$addr), 0xff), + (SUBREG_TO_REG (i64 0), (LDXRB GPR64sp:$addr), sub_32)>; +def : Pat<(and (ldxr_2 GPR64sp:$addr), 0xffff), + (SUBREG_TO_REG (i64 0), (LDXRH GPR64sp:$addr), sub_32)>; +def : Pat<(and (ldxr_4 GPR64sp:$addr), 0xffffffff), + (SUBREG_TO_REG (i64 0), (LDXRW GPR64sp:$addr), sub_32)>; // Load-exclusives. @@ -195,20 +251,20 @@ def ldaxr_8 : PatFrag<(ops node:$ptr), (int_arm64_ldaxr node:$ptr), [{ return cast(N)->getMemoryVT() == MVT::i64; }]>; -def : Pat<(ldaxr_1 am_noindex:$addr), - (SUBREG_TO_REG (i64 0), (LDAXRB am_noindex:$addr), sub_32)>; -def : Pat<(ldaxr_2 am_noindex:$addr), - (SUBREG_TO_REG (i64 0), (LDAXRH am_noindex:$addr), sub_32)>; -def : Pat<(ldaxr_4 am_noindex:$addr), - (SUBREG_TO_REG (i64 0), (LDAXRW am_noindex:$addr), sub_32)>; -def : Pat<(ldaxr_8 am_noindex:$addr), (LDAXRX am_noindex:$addr)>; +def : Pat<(ldaxr_1 GPR64sp:$addr), + (SUBREG_TO_REG (i64 0), (LDAXRB GPR64sp:$addr), sub_32)>; +def : Pat<(ldaxr_2 GPR64sp:$addr), + (SUBREG_TO_REG (i64 0), (LDAXRH GPR64sp:$addr), sub_32)>; +def : Pat<(ldaxr_4 GPR64sp:$addr), + (SUBREG_TO_REG (i64 0), (LDAXRW GPR64sp:$addr), sub_32)>; +def : Pat<(ldaxr_8 GPR64sp:$addr), (LDAXRX GPR64sp:$addr)>; -def : Pat<(and (ldaxr_1 am_noindex:$addr), 0xff), - (SUBREG_TO_REG (i64 0), (LDAXRB am_noindex:$addr), sub_32)>; -def : Pat<(and (ldaxr_2 am_noindex:$addr), 0xffff), - (SUBREG_TO_REG (i64 0), (LDAXRH am_noindex:$addr), sub_32)>; -def : Pat<(and (ldaxr_4 am_noindex:$addr), 0xffffffff), - (SUBREG_TO_REG (i64 0), (LDAXRW am_noindex:$addr), sub_32)>; +def : Pat<(and (ldaxr_1 GPR64sp:$addr), 0xff), + (SUBREG_TO_REG (i64 0), (LDAXRB GPR64sp:$addr), sub_32)>; +def : Pat<(and (ldaxr_2 GPR64sp:$addr), 0xffff), + (SUBREG_TO_REG (i64 0), (LDAXRH GPR64sp:$addr), sub_32)>; +def : Pat<(and (ldaxr_4 GPR64sp:$addr), 0xffffffff), + (SUBREG_TO_REG (i64 0), (LDAXRW GPR64sp:$addr), sub_32)>; // Store-exclusives. @@ -233,28 +289,28 @@ def stxr_8 : PatFrag<(ops node:$val, node:$ptr), }]>; -def : Pat<(stxr_1 GPR64:$val, am_noindex:$addr), - (STXRB (EXTRACT_SUBREG GPR64:$val, sub_32), am_noindex:$addr)>; -def : Pat<(stxr_2 GPR64:$val, am_noindex:$addr), - (STXRH (EXTRACT_SUBREG GPR64:$val, sub_32), am_noindex:$addr)>; -def : Pat<(stxr_4 GPR64:$val, am_noindex:$addr), - (STXRW (EXTRACT_SUBREG GPR64:$val, sub_32), am_noindex:$addr)>; -def : Pat<(stxr_8 GPR64:$val, am_noindex:$addr), - (STXRX GPR64:$val, am_noindex:$addr)>; +def : Pat<(stxr_1 GPR64:$val, GPR64sp:$addr), + (STXRB (EXTRACT_SUBREG GPR64:$val, sub_32), GPR64sp:$addr)>; +def : Pat<(stxr_2 GPR64:$val, GPR64sp:$addr), + (STXRH (EXTRACT_SUBREG GPR64:$val, sub_32), GPR64sp:$addr)>; +def : Pat<(stxr_4 GPR64:$val, GPR64sp:$addr), + (STXRW (EXTRACT_SUBREG GPR64:$val, sub_32), GPR64sp:$addr)>; +def : Pat<(stxr_8 GPR64:$val, GPR64sp:$addr), + (STXRX GPR64:$val, GPR64sp:$addr)>; -def : Pat<(stxr_1 (zext (and GPR32:$val, 0xff)), am_noindex:$addr), - (STXRB GPR32:$val, am_noindex:$addr)>; -def : Pat<(stxr_2 (zext (and GPR32:$val, 0xffff)), am_noindex:$addr), - (STXRH GPR32:$val, am_noindex:$addr)>; -def : Pat<(stxr_4 (zext GPR32:$val), am_noindex:$addr), - (STXRW GPR32:$val, am_noindex:$addr)>; +def : Pat<(stxr_1 (zext (and GPR32:$val, 0xff)), GPR64sp:$addr), + (STXRB GPR32:$val, GPR64sp:$addr)>; +def : Pat<(stxr_2 (zext (and GPR32:$val, 0xffff)), GPR64sp:$addr), + (STXRH GPR32:$val, GPR64sp:$addr)>; +def : Pat<(stxr_4 (zext GPR32:$val), GPR64sp:$addr), + (STXRW GPR32:$val, GPR64sp:$addr)>; -def : Pat<(stxr_1 (and GPR64:$val, 0xff), am_noindex:$addr), - (STXRB (EXTRACT_SUBREG GPR64:$val, sub_32), am_noindex:$addr)>; -def : Pat<(stxr_2 (and GPR64:$val, 0xffff), am_noindex:$addr), - (STXRH (EXTRACT_SUBREG GPR64:$val, sub_32), am_noindex:$addr)>; -def : Pat<(stxr_4 (and GPR64:$val, 0xffffffff), am_noindex:$addr), - (STXRW (EXTRACT_SUBREG GPR64:$val, sub_32), am_noindex:$addr)>; +def : Pat<(stxr_1 (and GPR64:$val, 0xff), GPR64sp:$addr), + (STXRB (EXTRACT_SUBREG GPR64:$val, sub_32), GPR64sp:$addr)>; +def : Pat<(stxr_2 (and GPR64:$val, 0xffff), GPR64sp:$addr), + (STXRH (EXTRACT_SUBREG GPR64:$val, sub_32), GPR64sp:$addr)>; +def : Pat<(stxr_4 (and GPR64:$val, 0xffffffff), GPR64sp:$addr), + (STXRW (EXTRACT_SUBREG GPR64:$val, sub_32), GPR64sp:$addr)>; // Store-release-exclusives. @@ -279,28 +335,28 @@ def stlxr_8 : PatFrag<(ops node:$val, node:$ptr), }]>; -def : Pat<(stlxr_1 GPR64:$val, am_noindex:$addr), - (STLXRB (EXTRACT_SUBREG GPR64:$val, sub_32), am_noindex:$addr)>; -def : Pat<(stlxr_2 GPR64:$val, am_noindex:$addr), - (STLXRH (EXTRACT_SUBREG GPR64:$val, sub_32), am_noindex:$addr)>; -def : Pat<(stlxr_4 GPR64:$val, am_noindex:$addr), - (STLXRW (EXTRACT_SUBREG GPR64:$val, sub_32), am_noindex:$addr)>; -def : Pat<(stlxr_8 GPR64:$val, am_noindex:$addr), - (STLXRX GPR64:$val, am_noindex:$addr)>; +def : Pat<(stlxr_1 GPR64:$val, GPR64sp:$addr), + (STLXRB (EXTRACT_SUBREG GPR64:$val, sub_32), GPR64sp:$addr)>; +def : Pat<(stlxr_2 GPR64:$val, GPR64sp:$addr), + (STLXRH (EXTRACT_SUBREG GPR64:$val, sub_32), GPR64sp:$addr)>; +def : Pat<(stlxr_4 GPR64:$val, GPR64sp:$addr), + (STLXRW (EXTRACT_SUBREG GPR64:$val, sub_32), GPR64sp:$addr)>; +def : Pat<(stlxr_8 GPR64:$val, GPR64sp:$addr), + (STLXRX GPR64:$val, GPR64sp:$addr)>; -def : Pat<(stlxr_1 (zext (and GPR32:$val, 0xff)), am_noindex:$addr), - (STLXRB GPR32:$val, am_noindex:$addr)>; -def : Pat<(stlxr_2 (zext (and GPR32:$val, 0xffff)), am_noindex:$addr), - (STLXRH GPR32:$val, am_noindex:$addr)>; -def : Pat<(stlxr_4 (zext GPR32:$val), am_noindex:$addr), - (STLXRW GPR32:$val, am_noindex:$addr)>; +def : Pat<(stlxr_1 (zext (and GPR32:$val, 0xff)), GPR64sp:$addr), + (STLXRB GPR32:$val, GPR64sp:$addr)>; +def : Pat<(stlxr_2 (zext (and GPR32:$val, 0xffff)), GPR64sp:$addr), + (STLXRH GPR32:$val, GPR64sp:$addr)>; +def : Pat<(stlxr_4 (zext GPR32:$val), GPR64sp:$addr), + (STLXRW GPR32:$val, GPR64sp:$addr)>; -def : Pat<(stlxr_1 (and GPR64:$val, 0xff), am_noindex:$addr), - (STLXRB (EXTRACT_SUBREG GPR64:$val, sub_32), am_noindex:$addr)>; -def : Pat<(stlxr_2 (and GPR64:$val, 0xffff), am_noindex:$addr), - (STLXRH (EXTRACT_SUBREG GPR64:$val, sub_32), am_noindex:$addr)>; -def : Pat<(stlxr_4 (and GPR64:$val, 0xffffffff), am_noindex:$addr), - (STLXRW (EXTRACT_SUBREG GPR64:$val, sub_32), am_noindex:$addr)>; +def : Pat<(stlxr_1 (and GPR64:$val, 0xff), GPR64sp:$addr), + (STLXRB (EXTRACT_SUBREG GPR64:$val, sub_32), GPR64sp:$addr)>; +def : Pat<(stlxr_2 (and GPR64:$val, 0xffff), GPR64sp:$addr), + (STLXRH (EXTRACT_SUBREG GPR64:$val, sub_32), GPR64sp:$addr)>; +def : Pat<(stlxr_4 (and GPR64:$val, 0xffffffff), GPR64sp:$addr), + (STLXRW (EXTRACT_SUBREG GPR64:$val, sub_32), GPR64sp:$addr)>; // And clear exclusive. diff --git a/lib/Target/ARM64/ARM64InstrFormats.td b/lib/Target/ARM64/ARM64InstrFormats.td index 0ac27e09358..bf9fa2992b7 100644 --- a/lib/Target/ARM64/ARM64InstrFormats.td +++ b/lib/Target/ARM64/ARM64InstrFormats.td @@ -222,34 +222,27 @@ def simm9 : Operand, ImmLeaf= -256 && Imm < 256; }]> { let ParserMatchClass = SImm9Operand; } -// simm7s4 predicate - True if the immediate is a multiple of 4 in the range -// [-256, 252]. -def SImm7s4Operand : AsmOperandClass { - let Name = "SImm7s4"; - let DiagnosticType = "InvalidMemoryIndexed32SImm7"; +// simm7sN predicate - True if the immediate is a multiple of N in the range +// [-64 * N, 63 * N]. +class SImm7Scaled : AsmOperandClass { + let Name = "SImm7s" # Scale; + let DiagnosticType = "InvalidMemoryIndexed" # Scale # "SImm7"; } + +def SImm7s4Operand : SImm7Scaled<4>; +def SImm7s8Operand : SImm7Scaled<8>; +def SImm7s16Operand : SImm7Scaled<16>; + def simm7s4 : Operand { let ParserMatchClass = SImm7s4Operand; let PrintMethod = "printImmScale<4>"; } -// simm7s8 predicate - True if the immediate is a multiple of 8 in the range -// [-512, 504]. -def SImm7s8Operand : AsmOperandClass { - let Name = "SImm7s8"; - let DiagnosticType = "InvalidMemoryIndexed64SImm7"; -} def simm7s8 : Operand { let ParserMatchClass = SImm7s8Operand; let PrintMethod = "printImmScale<8>"; } -// simm7s16 predicate - True if the immediate is a multiple of 16 in the range -// [-1024, 1008]. -def SImm7s16Operand : AsmOperandClass { - let Name = "SImm7s16"; - let DiagnosticType = "InvalidMemoryIndexed64SImm7"; -} def simm7s16 : Operand { let ParserMatchClass = SImm7s16Operand; let PrintMethod = "printImmScale<16>"; @@ -639,17 +632,17 @@ def neg_addsub_shifted_imm64 : neg_addsub_shifted_imm; // {5-3} - extend type // {2-0} - imm3 def arith_extend : Operand { - let PrintMethod = "printExtend"; + let PrintMethod = "printArithExtend"; let ParserMatchClass = ExtendOperand; } def arith_extend64 : Operand { - let PrintMethod = "printExtend"; + let PrintMethod = "printArithExtend"; let ParserMatchClass = ExtendOperand64; } // 'extend' that's a lsl of a 64-bit register. def arith_extendlsl64 : Operand { - let PrintMethod = "printExtend"; + let PrintMethod = "printArithExtend"; let ParserMatchClass = ExtendOperandLSL64; } @@ -2178,96 +2171,46 @@ def maski16_or_more : Operand, // (unsigned immediate) // Indexed for 8-bit registers. offset is in range [0,4095]. -def MemoryIndexed8Operand : AsmOperandClass { - let Name = "MemoryIndexed8"; - let DiagnosticType = "InvalidMemoryIndexed8"; -} -def am_indexed8 : Operand, - ComplexPattern { - let PrintMethod = "printAMIndexed<8>"; - let EncoderMethod - = "getAMIndexed8OpValue"; - let ParserMatchClass = MemoryIndexed8Operand; - let MIOperandInfo = (ops GPR64sp:$base, i64imm:$offset); +def am_indexed8 : ComplexPattern; +def am_indexed16 : ComplexPattern; +def am_indexed32 : ComplexPattern; +def am_indexed64 : ComplexPattern; +def am_indexed128 : ComplexPattern; + +class UImm12OffsetOperand : AsmOperandClass { + let Name = "UImm12Offset" # Scale; + let RenderMethod = "addUImm12OffsetOperands<" # Scale # ">"; + let PredicateMethod = "isUImm12Offset<" # Scale # ">"; + let DiagnosticType = "InvalidMemoryIndexed" # Scale; } -// Indexed for 16-bit registers. offset is multiple of 2 in range [0,8190], -// stored as immval/2 (the 12-bit literal that encodes directly into the insn). -def MemoryIndexed16Operand : AsmOperandClass { - let Name = "MemoryIndexed16"; - let DiagnosticType = "InvalidMemoryIndexed16"; -} -def am_indexed16 : Operand, - ComplexPattern { - let PrintMethod = "printAMIndexed<16>"; +def UImm12OffsetScale1Operand : UImm12OffsetOperand<1>; +def UImm12OffsetScale2Operand : UImm12OffsetOperand<2>; +def UImm12OffsetScale4Operand : UImm12OffsetOperand<4>; +def UImm12OffsetScale8Operand : UImm12OffsetOperand<8>; +def UImm12OffsetScale16Operand : UImm12OffsetOperand<16>; + +class uimm12_scaled : Operand { + let ParserMatchClass + = !cast("UImm12OffsetScale" # Scale # "Operand"); let EncoderMethod - = "getAMIndexed8OpValue"; - let ParserMatchClass = MemoryIndexed16Operand; - let MIOperandInfo = (ops GPR64sp:$base, i64imm:$offset); + = "getLdStUImm12OpValue"; + let PrintMethod = "printUImm12Offset<" # Scale # ">"; } -// Indexed for 32-bit registers. offset is multiple of 4 in range [0,16380], -// stored as immval/4 (the 12-bit literal that encodes directly into the insn). -def MemoryIndexed32Operand : AsmOperandClass { - let Name = "MemoryIndexed32"; - let DiagnosticType = "InvalidMemoryIndexed32"; -} -def am_indexed32 : Operand, - ComplexPattern { - let PrintMethod = "printAMIndexed<32>"; - let EncoderMethod - = "getAMIndexed8OpValue"; - let ParserMatchClass = MemoryIndexed32Operand; - let MIOperandInfo = (ops GPR64sp:$base, i64imm:$offset); -} - -// Indexed for 64-bit registers. offset is multiple of 8 in range [0,32760], -// stored as immval/8 (the 12-bit literal that encodes directly into the insn). -def MemoryIndexed64Operand : AsmOperandClass { - let Name = "MemoryIndexed64"; - let DiagnosticType = "InvalidMemoryIndexed64"; -} -def am_indexed64 : Operand, - ComplexPattern { - let PrintMethod = "printAMIndexed<64>"; - let EncoderMethod - = "getAMIndexed8OpValue"; - let ParserMatchClass = MemoryIndexed64Operand; - let MIOperandInfo = (ops GPR64sp:$base, i64imm:$offset); -} - -// Indexed for 128-bit registers. offset is multiple of 16 in range [0,65520], -// stored as immval/16 (the 12-bit literal that encodes directly into the insn). -def MemoryIndexed128Operand : AsmOperandClass { - let Name = "MemoryIndexed128"; - let DiagnosticType = "InvalidMemoryIndexed128"; -} -def am_indexed128 : Operand, - ComplexPattern { - let PrintMethod = "printAMIndexed<128>"; - let EncoderMethod - = "getAMIndexed8OpValue"; - let ParserMatchClass = MemoryIndexed128Operand; - let MIOperandInfo = (ops GPR64sp:$base, i64imm:$offset); -} - -// No offset. -def MemoryNoIndexOperand : AsmOperandClass { let Name = "MemoryNoIndex"; } -def am_noindex : Operand, - ComplexPattern { - let PrintMethod = "printAMNoIndex"; - let ParserMatchClass = MemoryNoIndexOperand; - let MIOperandInfo = (ops GPR64sp:$base); -} +def uimm12s1 : uimm12_scaled<1>; +def uimm12s2 : uimm12_scaled<2>; +def uimm12s4 : uimm12_scaled<4>; +def uimm12s8 : uimm12_scaled<8>; +def uimm12s16 : uimm12_scaled<16>; class BaseLoadStoreUI sz, bit V, bits<2> opc, dag oops, dag iops, string asm, list pattern> - : I { - bits<5> dst; + : I { + bits<5> Rt; - bits<17> addr; - bits<5> base = addr{4-0}; - bits<12> offset = addr{16-5}; + bits<5> Rn; + bits<12> offset; let Inst{31-30} = sz; let Inst{29-27} = 0b111; @@ -2275,25 +2218,35 @@ class BaseLoadStoreUI sz, bit V, bits<2> opc, dag oops, dag iops, let Inst{25-24} = 0b01; let Inst{23-22} = opc; let Inst{21-10} = offset; - let Inst{9-5} = base; - let Inst{4-0} = dst; + let Inst{9-5} = Rn; + let Inst{4-0} = Rt; let DecoderMethod = "DecodeUnsignedLdStInstruction"; } -let mayLoad = 1, mayStore = 0, hasSideEffects = 0 in -class LoadUI sz, bit V, bits<2> opc, RegisterClass regtype, - Operand indextype, string asm, list pattern> - : BaseLoadStoreUI, - Sched<[WriteLD]>; +multiclass LoadUI sz, bit V, bits<2> opc, RegisterClass regtype, + Operand indextype, string asm, list pattern> { + let AddedComplexity = 10, mayLoad = 1, mayStore = 0, hasSideEffects = 0 in + def ui : BaseLoadStoreUI, + Sched<[WriteLD]>; -let mayLoad = 0, mayStore = 1, hasSideEffects = 0 in -class StoreUI sz, bit V, bits<2> opc, RegisterClass regtype, - Operand indextype, string asm, list pattern> - : BaseLoadStoreUI, - Sched<[WriteST]>; + def : InstAlias(NAME # "ui") regtype:$Rt, GPR64sp:$Rn, 0)>; +} + +multiclass StoreUI sz, bit V, bits<2> opc, RegisterClass regtype, + Operand indextype, string asm, list pattern> { + let AddedComplexity = 10, mayLoad = 0, mayStore = 1, hasSideEffects = 0 in + def ui : BaseLoadStoreUI, + Sched<[WriteST]>; + + def : InstAlias(NAME # "ui") regtype:$Rt, GPR64sp:$Rn, 0)>; +} def PrefetchOperand : AsmOperandClass { let Name = "Prefetch"; @@ -2307,7 +2260,8 @@ def prfop : Operand { let mayLoad = 0, mayStore = 0, hasSideEffects = 1 in class PrefetchUI sz, bit V, bits<2> opc, string asm, list pat> : BaseLoadStoreUI, + (outs), (ins prfop:$Rt, GPR64sp:$Rn, uimm12s8:$offset), + asm, pat>, Sched<[WriteLD]>; //--- @@ -2357,317 +2311,511 @@ class PrefetchLiteral opc, bit V, string asm, list pat> // Load/store register offset //--- -class MemROAsmOperand : AsmOperandClass { - let Name = "MemoryRegisterOffset"#sz; - let DiagnosticType = "InvalidMemoryIndexed"; +def ro_Xindexed8 : ComplexPattern", []>; +def ro_Xindexed16 : ComplexPattern", []>; +def ro_Xindexed32 : ComplexPattern", []>; +def ro_Xindexed64 : ComplexPattern", []>; +def ro_Xindexed128 : ComplexPattern", []>; + +def ro_Windexed8 : ComplexPattern", []>; +def ro_Windexed16 : ComplexPattern", []>; +def ro_Windexed32 : ComplexPattern", []>; +def ro_Windexed64 : ComplexPattern", []>; +def ro_Windexed128 : ComplexPattern", []>; + +class MemExtendOperand : AsmOperandClass { + let Name = "Mem" # Reg # "Extend" # Width; + let PredicateMethod = "isMem" # Reg # "Extend<" # Width # ">"; + let RenderMethod = "addMemExtendOperands"; + let DiagnosticType = "InvalidMemory" # Reg # "Extend" # Width; } -def MemROAsmOperand8 : MemROAsmOperand<8>; -def MemROAsmOperand16 : MemROAsmOperand<16>; -def MemROAsmOperand32 : MemROAsmOperand<32>; -def MemROAsmOperand64 : MemROAsmOperand<64>; -def MemROAsmOperand128 : MemROAsmOperand<128>; +def MemWExtend8Operand : MemExtendOperand<"W", 8> { + // The address "[x0, x1, lsl #0]" actually maps to the variant which performs + // the trivial shift. + let RenderMethod = "addMemExtend8Operands"; +} +def MemWExtend16Operand : MemExtendOperand<"W", 16>; +def MemWExtend32Operand : MemExtendOperand<"W", 32>; +def MemWExtend64Operand : MemExtendOperand<"W", 64>; +def MemWExtend128Operand : MemExtendOperand<"W", 128>; -class ro_indexed : Operand { // ComplexPattern<...> - let PrintMethod = "printMemoryRegOffset<" # sz # ">"; - let MIOperandInfo = (ops GPR64sp:$base, GPR64:$offset, i32imm:$extend); +def MemXExtend8Operand : MemExtendOperand<"X", 8> { + // The address "[x0, x1, lsl #0]" actually maps to the variant which performs + // the trivial shift. + let RenderMethod = "addMemExtend8Operands"; +} +def MemXExtend16Operand : MemExtendOperand<"X", 16>; +def MemXExtend32Operand : MemExtendOperand<"X", 32>; +def MemXExtend64Operand : MemExtendOperand<"X", 64>; +def MemXExtend128Operand : MemExtendOperand<"X", 128>; + +class ro_extend + : Operand { + let ParserMatchClass = ParserClass; + let PrintMethod = "printMemExtend<'" # Reg # "', " # Width # ">"; + let DecoderMethod = "DecodeMemExtend"; + let EncoderMethod = "getMemExtendOpValue"; + let MIOperandInfo = (ops i32imm:$signed, i32imm:$doshift); } -def ro_indexed8 : ro_indexed<8>, ComplexPattern { - let ParserMatchClass = MemROAsmOperand8; +def ro_Wextend8 : ro_extend; +def ro_Wextend16 : ro_extend; +def ro_Wextend32 : ro_extend; +def ro_Wextend64 : ro_extend; +def ro_Wextend128 : ro_extend; + +def ro_Xextend8 : ro_extend; +def ro_Xextend16 : ro_extend; +def ro_Xextend32 : ro_extend; +def ro_Xextend64 : ro_extend; +def ro_Xextend128 : ro_extend; + +class ROAddrMode { + // CodeGen-level pattern covering the entire addressing mode. + ComplexPattern Wpat = windex; + ComplexPattern Xpat = xindex; + + // Asm-level Operand covering the valid "uxtw #3" style syntax. + Operand Wext = wextend; + Operand Xext = xextend; } -def ro_indexed16 : ro_indexed<16>, ComplexPattern { - let ParserMatchClass = MemROAsmOperand16; -} - -def ro_indexed32 : ro_indexed<32>, ComplexPattern { - let ParserMatchClass = MemROAsmOperand32; -} - -def ro_indexed64 : ro_indexed<64>, ComplexPattern { - let ParserMatchClass = MemROAsmOperand64; -} - -def ro_indexed128 : ro_indexed<128>, ComplexPattern { - let ParserMatchClass = MemROAsmOperand128; -} +def ro8 : ROAddrMode; +def ro16 : ROAddrMode; +def ro32 : ROAddrMode; +def ro64 : ROAddrMode; +def ro128 : ROAddrMode; class LoadStore8RO sz, bit V, bits<2> opc, RegisterClass regtype, string asm, dag ins, dag outs, list pat> - : I { - // The operands are in order to match the 'addr' MI operands, so we - // don't need an encoder method and by-name matching. Just use the default - // in-order handling. Since we're using by-order, make sure the names - // do not match. - bits<5> dst; - bits<5> base; - bits<5> offset; - bits<4> extend; + : I { + bits<5> Rt; + bits<5> Rn; + bits<5> Rm; + bits<2> extend; let Inst{31-30} = sz; let Inst{29-27} = 0b111; let Inst{26} = V; let Inst{25-24} = 0b00; let Inst{23-22} = opc; let Inst{21} = 1; - let Inst{20-16} = offset; - let Inst{15-13} = extend{3-1}; - - let Inst{12} = extend{0}; + let Inst{20-16} = Rm; + let Inst{15} = extend{1}; // sign extend Rm? + let Inst{14} = 1; + let Inst{12} = extend{0}; // do shift? let Inst{11-10} = 0b10; - let Inst{9-5} = base; - let Inst{4-0} = dst; - - let DecoderMethod = "DecodeRegOffsetLdStInstruction"; + let Inst{9-5} = Rn; + let Inst{4-0} = Rt; } -class Load8RO sz, bit V, bits<2> opc, RegisterClass regtype, - string asm, list pat> - : LoadStore8RO, - Sched<[WriteLDIdx, ReadAdrBase]>; +class ROInstAlias + : InstAlias; -class Store8RO sz, bit V, bits<2> opc, RegisterClass regtype, - string asm, list pat> - : LoadStore8RO, - Sched<[WriteSTIdx, ReadAdrBase]>; +multiclass Load8RO sz, bit V, bits<2> opc, RegisterClass regtype, + string asm, ValueType Ty, SDPatternOperator loadop> { + let AddedComplexity = 10 in + def roW : LoadStore8RO, + Sched<[WriteLDIdx, ReadAdrBase]> { + let Inst{13} = 0b0; + } + + let AddedComplexity = 10 in + def roX : LoadStore8RO, + Sched<[WriteLDIdx, ReadAdrBase]> { + let Inst{13} = 0b1; + } + + def : ROInstAlias(NAME # "roX")>; +} + +multiclass Store8RO sz, bit V, bits<2> opc, RegisterClass regtype, + string asm, ValueType Ty, SDPatternOperator storeop> { + let AddedComplexity = 10 in + def roW : LoadStore8RO, + Sched<[WriteSTIdx, ReadAdrBase]> { + let Inst{13} = 0b0; + } + + let AddedComplexity = 10 in + def roX : LoadStore8RO, + Sched<[WriteSTIdx, ReadAdrBase]> { + let Inst{13} = 0b1; + } + + def : ROInstAlias(NAME # "roX")>; +} class LoadStore16RO sz, bit V, bits<2> opc, RegisterClass regtype, string asm, dag ins, dag outs, list pat> - : I { - // The operands are in order to match the 'addr' MI operands, so we - // don't need an encoder method and by-name matching. Just use the default - // in-order handling. Since we're using by-order, make sure the names - // do not match. - bits<5> dst; - bits<5> base; - bits<5> offset; - bits<4> extend; + : I { + bits<5> Rt; + bits<5> Rn; + bits<5> Rm; + bits<2> extend; let Inst{31-30} = sz; let Inst{29-27} = 0b111; let Inst{26} = V; let Inst{25-24} = 0b00; let Inst{23-22} = opc; let Inst{21} = 1; - let Inst{20-16} = offset; - let Inst{15-13} = extend{3-1}; - - let Inst{12} = extend{0}; + let Inst{20-16} = Rm; + let Inst{15} = extend{1}; // sign extend Rm? + let Inst{14} = 1; + let Inst{12} = extend{0}; // do shift? let Inst{11-10} = 0b10; - let Inst{9-5} = base; - let Inst{4-0} = dst; - - let DecoderMethod = "DecodeRegOffsetLdStInstruction"; + let Inst{9-5} = Rn; + let Inst{4-0} = Rt; } -class Load16RO sz, bit V, bits<2> opc, RegisterClass regtype, - string asm, list pat> - : LoadStore16RO, - Sched<[WriteLDIdx, ReadAdrBase]>; +multiclass Load16RO sz, bit V, bits<2> opc, RegisterClass regtype, + string asm, ValueType Ty, SDPatternOperator loadop> { + let AddedComplexity = 10 in + def roW : LoadStore16RO, + Sched<[WriteLDIdx, ReadAdrBase]> { + let Inst{13} = 0b0; + } -class Store16RO sz, bit V, bits<2> opc, RegisterClass regtype, - string asm, list pat> - : LoadStore16RO, - Sched<[WriteSTIdx, ReadAdrBase]>; + let AddedComplexity = 10 in + def roX : LoadStore16RO, + Sched<[WriteLDIdx, ReadAdrBase]> { + let Inst{13} = 0b1; + } + + def : ROInstAlias(NAME # "roX")>; +} + +multiclass Store16RO sz, bit V, bits<2> opc, RegisterClass regtype, + string asm, ValueType Ty, SDPatternOperator storeop> { + let AddedComplexity = 10 in + def roW : LoadStore16RO, + Sched<[WriteSTIdx, ReadAdrBase]> { + let Inst{13} = 0b0; + } + + let AddedComplexity = 10 in + def roX : LoadStore16RO, + Sched<[WriteSTIdx, ReadAdrBase]> { + let Inst{13} = 0b1; + } + + def : ROInstAlias(NAME # "roX")>; +} class LoadStore32RO sz, bit V, bits<2> opc, RegisterClass regtype, string asm, dag ins, dag outs, list pat> - : I { - // The operands are in order to match the 'addr' MI operands, so we - // don't need an encoder method and by-name matching. Just use the default - // in-order handling. Since we're using by-order, make sure the names - // do not match. - bits<5> dst; - bits<5> base; - bits<5> offset; - bits<4> extend; + : I { + bits<5> Rt; + bits<5> Rn; + bits<5> Rm; + bits<2> extend; let Inst{31-30} = sz; let Inst{29-27} = 0b111; let Inst{26} = V; let Inst{25-24} = 0b00; let Inst{23-22} = opc; let Inst{21} = 1; - let Inst{20-16} = offset; - let Inst{15-13} = extend{3-1}; - - let Inst{12} = extend{0}; + let Inst{20-16} = Rm; + let Inst{15} = extend{1}; // sign extend Rm? + let Inst{14} = 1; + let Inst{12} = extend{0}; // do shift? let Inst{11-10} = 0b10; - let Inst{9-5} = base; - let Inst{4-0} = dst; - - let DecoderMethod = "DecodeRegOffsetLdStInstruction"; + let Inst{9-5} = Rn; + let Inst{4-0} = Rt; } -class Load32RO sz, bit V, bits<2> opc, RegisterClass regtype, - string asm, list pat> - : LoadStore32RO, - Sched<[WriteLDIdx, ReadAdrBase]>; +multiclass Load32RO sz, bit V, bits<2> opc, RegisterClass regtype, + string asm, ValueType Ty, SDPatternOperator loadop> { + let AddedComplexity = 10 in + def roW : LoadStore32RO, + Sched<[WriteLDIdx, ReadAdrBase]> { + let Inst{13} = 0b0; + } -class Store32RO sz, bit V, bits<2> opc, RegisterClass regtype, - string asm, list pat> - : LoadStore32RO, - Sched<[WriteSTIdx, ReadAdrBase]>; + let AddedComplexity = 10 in + def roX : LoadStore32RO, + Sched<[WriteLDIdx, ReadAdrBase]> { + let Inst{13} = 0b1; + } + + def : ROInstAlias(NAME # "roX")>; +} + +multiclass Store32RO sz, bit V, bits<2> opc, RegisterClass regtype, + string asm, ValueType Ty, SDPatternOperator storeop> { + let AddedComplexity = 10 in + def roW : LoadStore32RO, + Sched<[WriteSTIdx, ReadAdrBase]> { + let Inst{13} = 0b0; + } + + let AddedComplexity = 10 in + def roX : LoadStore32RO, + Sched<[WriteSTIdx, ReadAdrBase]> { + let Inst{13} = 0b1; + } + + def : ROInstAlias(NAME # "roX")>; +} class LoadStore64RO sz, bit V, bits<2> opc, RegisterClass regtype, string asm, dag ins, dag outs, list pat> - : I { - // The operands are in order to match the 'addr' MI operands, so we - // don't need an encoder method and by-name matching. Just use the default - // in-order handling. Since we're using by-order, make sure the names - // do not match. - bits<5> dst; - bits<5> base; - bits<5> offset; - bits<4> extend; + : I { + bits<5> Rt; + bits<5> Rn; + bits<5> Rm; + bits<2> extend; let Inst{31-30} = sz; let Inst{29-27} = 0b111; let Inst{26} = V; let Inst{25-24} = 0b00; let Inst{23-22} = opc; let Inst{21} = 1; - let Inst{20-16} = offset; - let Inst{15-13} = extend{3-1}; - - let Inst{12} = extend{0}; + let Inst{20-16} = Rm; + let Inst{15} = extend{1}; // sign extend Rm? + let Inst{14} = 1; + let Inst{12} = extend{0}; // do shift? let Inst{11-10} = 0b10; - let Inst{9-5} = base; - let Inst{4-0} = dst; - - let DecoderMethod = "DecodeRegOffsetLdStInstruction"; + let Inst{9-5} = Rn; + let Inst{4-0} = Rt; } -let mayLoad = 1, mayStore = 0, hasSideEffects = 0 in -class Load64RO sz, bit V, bits<2> opc, RegisterClass regtype, - string asm, list pat> - : LoadStore64RO, - Sched<[WriteLDIdx, ReadAdrBase]>; +multiclass Load64RO sz, bit V, bits<2> opc, RegisterClass regtype, + string asm, ValueType Ty, SDPatternOperator loadop> { + let AddedComplexity = 10, mayLoad = 1, mayStore = 0, hasSideEffects = 0 in + def roW : LoadStore64RO, + Sched<[WriteLDIdx, ReadAdrBase]> { + let Inst{13} = 0b0; + } -let mayLoad = 0, mayStore = 1, hasSideEffects = 0 in -class Store64RO sz, bit V, bits<2> opc, RegisterClass regtype, - string asm, list pat> - : LoadStore64RO, - Sched<[WriteSTIdx, ReadAdrBase]>; + let AddedComplexity = 10, mayLoad = 1, mayStore = 0, hasSideEffects = 0 in + def roX : LoadStore64RO, + Sched<[WriteLDIdx, ReadAdrBase]> { + let Inst{13} = 0b1; + } + def : ROInstAlias(NAME # "roX")>; +} + +multiclass Store64RO sz, bit V, bits<2> opc, RegisterClass regtype, + string asm, ValueType Ty, SDPatternOperator storeop> { + let AddedComplexity = 10, mayLoad = 0, mayStore = 1, hasSideEffects = 0 in + def roW : LoadStore64RO, + Sched<[WriteSTIdx, ReadAdrBase]> { + let Inst{13} = 0b0; + } + + let AddedComplexity = 10, mayLoad = 0, mayStore = 1, hasSideEffects = 0 in + def roX : LoadStore64RO, + Sched<[WriteSTIdx, ReadAdrBase]> { + let Inst{13} = 0b1; + } + + def : ROInstAlias(NAME # "roX")>; +} class LoadStore128RO sz, bit V, bits<2> opc, RegisterClass regtype, string asm, dag ins, dag outs, list pat> - : I { - // The operands are in order to match the 'addr' MI operands, so we - // don't need an encoder method and by-name matching. Just use the default - // in-order handling. Since we're using by-order, make sure the names - // do not match. - bits<5> dst; - bits<5> base; - bits<5> offset; - bits<4> extend; + : I { + bits<5> Rt; + bits<5> Rn; + bits<5> Rm; + bits<2> extend; let Inst{31-30} = sz; let Inst{29-27} = 0b111; let Inst{26} = V; let Inst{25-24} = 0b00; let Inst{23-22} = opc; let Inst{21} = 1; - let Inst{20-16} = offset; - let Inst{15-13} = extend{3-1}; - - let Inst{12} = extend{0}; + let Inst{20-16} = Rm; + let Inst{15} = extend{1}; // sign extend Rm? + let Inst{14} = 1; + let Inst{12} = extend{0}; // do shift? let Inst{11-10} = 0b10; - let Inst{9-5} = base; - let Inst{4-0} = dst; - - let DecoderMethod = "DecodeRegOffsetLdStInstruction"; + let Inst{9-5} = Rn; + let Inst{4-0} = Rt; } -let mayLoad = 1, mayStore = 0, hasSideEffects = 0 in -class Load128RO sz, bit V, bits<2> opc, RegisterClass regtype, - string asm, list pat> - : LoadStore128RO, - Sched<[WriteLDIdx, ReadAdrBase]>; +multiclass Load128RO sz, bit V, bits<2> opc, RegisterClass regtype, + string asm, ValueType Ty, SDPatternOperator loadop> { + let AddedComplexity = 10, mayLoad = 1, mayStore = 0, hasSideEffects = 0 in + def roW : LoadStore128RO, + Sched<[WriteLDIdx, ReadAdrBase]> { + let Inst{13} = 0b0; + } -let mayLoad = 0, mayStore = 1, hasSideEffects = 0 in -class Store128RO sz, bit V, bits<2> opc, RegisterClass regtype, - string asm, list pat> - : LoadStore128RO, - Sched<[WriteSTIdx, ReadAdrBase]>; + let AddedComplexity = 10, mayLoad = 1, mayStore = 0, hasSideEffects = 0 in + def roX : LoadStore128RO, + Sched<[WriteLDIdx, ReadAdrBase]> { + let Inst{13} = 0b1; + } + + def : ROInstAlias(NAME # "roX")>; +} + +multiclass Store128RO sz, bit V, bits<2> opc, RegisterClass regtype, + string asm, ValueType Ty, SDPatternOperator storeop> { + let AddedComplexity = 10, mayLoad = 0, mayStore = 1, hasSideEffects = 0 in + def roW : LoadStore128RO, + Sched<[WriteSTIdx, ReadAdrBase]> { + let Inst{13} = 0b0; + } + + let AddedComplexity = 10, mayLoad = 0, mayStore = 1, hasSideEffects = 0 in + def roX : LoadStore128RO, + Sched<[WriteSTIdx, ReadAdrBase]> { + let Inst{13} = 0b1; + } + + def : ROInstAlias(NAME # "roX")>; +} let mayLoad = 0, mayStore = 0, hasSideEffects = 1 in -class PrefetchRO sz, bit V, bits<2> opc, string asm, list pat> - : I<(outs), (ins prfop:$Rt, ro_indexed64:$addr), asm, - "\t$Rt, $addr", "", pat>, +class BasePrefetchRO sz, bit V, bits<2> opc, dag outs, dag ins, + string asm, list pat> + : I, Sched<[WriteLD]> { - // The operands are in order to match the 'addr' MI operands, so we - // don't need an encoder method and by-name matching. Just use the default - // in-order handling. Since we're using by-order, make sure the names - // do not match. - bits<5> dst; - bits<5> base; - bits<5> offset; - bits<4> extend; + bits<5> Rt; + bits<5> Rn; + bits<5> Rm; + bits<2> extend; let Inst{31-30} = sz; let Inst{29-27} = 0b111; let Inst{26} = V; let Inst{25-24} = 0b00; let Inst{23-22} = opc; let Inst{21} = 1; - let Inst{20-16} = offset; - let Inst{15-13} = extend{3-1}; - - let Inst{12} = extend{0}; + let Inst{20-16} = Rm; + let Inst{15} = extend{1}; // sign extend Rm? + let Inst{14} = 1; + let Inst{12} = extend{0}; // do shift? let Inst{11-10} = 0b10; - let Inst{9-5} = base; - let Inst{4-0} = dst; + let Inst{9-5} = Rn; + let Inst{4-0} = Rt; +} - let DecoderMethod = "DecodeRegOffsetLdStInstruction"; +multiclass PrefetchRO sz, bit V, bits<2> opc, string asm> { + def roW : BasePrefetchRO { + let Inst{13} = 0b0; + } + + def roX : BasePrefetchRO { + let Inst{13} = 0b1; + } + + def : InstAlias<"prfm $Rt, [$Rn, $Rm]", + (!cast(NAME # "roX") prfop:$Rt, + GPR64sp:$Rn, GPR64:$Rm, 0, 0)>; } //--- // Load/store unscaled immediate //--- -def MemoryUnscaledOperand : AsmOperandClass { - let Name = "MemoryUnscaled"; - let DiagnosticType = "InvalidMemoryIndexedSImm9"; -} -class am_unscaled_operand : Operand { - let PrintMethod = "printAMIndexed<8>"; - let ParserMatchClass = MemoryUnscaledOperand; - let MIOperandInfo = (ops GPR64sp:$base, i64imm:$offset); -} -class am_unscaled_wb_operand : Operand { - let PrintMethod = "printAMIndexedWB<8>"; - let ParserMatchClass = MemoryUnscaledOperand; - let MIOperandInfo = (ops GPR64sp:$base, i64imm:$offset); -} -def am_unscaled : am_unscaled_operand; -def am_unscaled_wb: am_unscaled_wb_operand; -def am_unscaled8 : am_unscaled_operand, - ComplexPattern; -def am_unscaled16 : am_unscaled_operand, - ComplexPattern; -def am_unscaled32 : am_unscaled_operand, - ComplexPattern; -def am_unscaled64 : am_unscaled_operand, - ComplexPattern; -def am_unscaled128 : am_unscaled_operand, - ComplexPattern; +def am_unscaled8 : ComplexPattern; +def am_unscaled16 : ComplexPattern; +def am_unscaled32 : ComplexPattern; +def am_unscaled64 : ComplexPattern; +def am_unscaled128 :ComplexPattern; class BaseLoadStoreUnscale sz, bit V, bits<2> opc, dag oops, dag iops, string asm, list pattern> - : I { - // The operands are in order to match the 'addr' MI operands, so we - // don't need an encoder method and by-name matching. Just use the default - // in-order handling. Since we're using by-order, make sure the names - // do not match. - bits<5> dst; - bits<5> base; + : I { + bits<5> Rt; + bits<5> Rn; bits<9> offset; let Inst{31-30} = sz; let Inst{29-27} = 0b111; @@ -2677,31 +2825,46 @@ class BaseLoadStoreUnscale sz, bit V, bits<2> opc, dag oops, dag iops, let Inst{21} = 0; let Inst{20-12} = offset; let Inst{11-10} = 0b00; - let Inst{9-5} = base; - let Inst{4-0} = dst; + let Inst{9-5} = Rn; + let Inst{4-0} = Rt; let DecoderMethod = "DecodeSignedLdStInstruction"; } -let AddedComplexity = 1 in // try this before LoadUI -class LoadUnscaled sz, bit V, bits<2> opc, RegisterClass regtype, - Operand amtype, string asm, list pattern> - : BaseLoadStoreUnscale, - Sched<[WriteLD]>; +multiclass LoadUnscaled sz, bit V, bits<2> opc, RegisterClass regtype, + string asm, list pattern> { + let AddedComplexity = 1 in // try this before LoadUI + def i : BaseLoadStoreUnscale, + Sched<[WriteLD]>; -let AddedComplexity = 1 in // try this before StoreUI -class StoreUnscaled sz, bit V, bits<2> opc, RegisterClass regtype, - Operand amtype, string asm, list pattern> - : BaseLoadStoreUnscale, - Sched<[WriteST]>; + def : InstAlias(NAME # "i") regtype:$Rt, GPR64sp:$Rn, 0)>; +} -let mayLoad = 0, mayStore = 0, hasSideEffects = 1 in -class PrefetchUnscaled sz, bit V, bits<2> opc, string asm, list pat> - : BaseLoadStoreUnscale, - Sched<[WriteLD]>; +multiclass StoreUnscaled sz, bit V, bits<2> opc, RegisterClass regtype, + string asm, list pattern> { + let AddedComplexity = 1 in // try this before StoreUI + def i : BaseLoadStoreUnscale, + Sched<[WriteST]>; + + def : InstAlias(NAME # "i") regtype:$Rt, GPR64sp:$Rn, 0)>; +} + +multiclass PrefetchUnscaled sz, bit V, bits<2> opc, string asm, + list pat> { + let mayLoad = 0, mayStore = 0, hasSideEffects = 1 in + def i : BaseLoadStoreUnscale, + Sched<[WriteLD]>; + + def : InstAlias(NAME # "i") prfop:$Rt, GPR64sp:$Rn, 0)>; +} //--- // Load/store unscaled immediate, unprivileged @@ -2709,13 +2872,9 @@ class PrefetchUnscaled sz, bit V, bits<2> opc, string asm, list pat class BaseLoadStoreUnprivileged sz, bit V, bits<2> opc, dag oops, dag iops, string asm> - : I { - // The operands are in order to match the 'addr' MI operands, so we - // don't need an encoder method and by-name matching. Just use the default - // in-order handling. Since we're using by-order, make sure the names - // do not match. - bits<5> dst; - bits<5> base; + : I { + bits<5> Rt; + bits<5> Rn; bits<9> offset; let Inst{31-30} = sz; let Inst{29-27} = 0b111; @@ -2725,26 +2884,33 @@ class BaseLoadStoreUnprivileged sz, bit V, bits<2> opc, let Inst{21} = 0; let Inst{20-12} = offset; let Inst{11-10} = 0b10; - let Inst{9-5} = base; - let Inst{4-0} = dst; + let Inst{9-5} = Rn; + let Inst{4-0} = Rt; let DecoderMethod = "DecodeSignedLdStInstruction"; } -let mayStore = 0, mayLoad = 1, hasSideEffects = 0 in { -class LoadUnprivileged sz, bit V, bits<2> opc, RegisterClass regtype, - string asm> - : BaseLoadStoreUnprivileged, - Sched<[WriteLD]>; +multiclass LoadUnprivileged sz, bit V, bits<2> opc, + RegisterClass regtype, string asm> { + let mayStore = 0, mayLoad = 1, hasSideEffects = 0 in + def i : BaseLoadStoreUnprivileged, + Sched<[WriteLD]>; + + def : InstAlias(NAME # "i") regtype:$Rt, GPR64sp:$Rn, 0)>; } -let mayStore = 1, mayLoad = 0, hasSideEffects = 0 in { -class StoreUnprivileged sz, bit V, bits<2> opc, RegisterClass regtype, - string asm> - : BaseLoadStoreUnprivileged, - Sched<[WriteST]>; +multiclass StoreUnprivileged sz, bit V, bits<2> opc, + RegisterClass regtype, string asm> { + let mayStore = 1, mayLoad = 0, hasSideEffects = 0 in + def i : BaseLoadStoreUnprivileged, + Sched<[WriteST]>; + + def : InstAlias(NAME # "i") regtype:$Rt, GPR64sp:$Rn, 0)>; } //--- @@ -2753,12 +2919,9 @@ class StoreUnprivileged sz, bit V, bits<2> opc, RegisterClass regtype, class BaseLoadStorePreIdx sz, bit V, bits<2> opc, dag oops, dag iops, string asm, string cstr> - : I { - // The operands are in order to match the 'addr' MI operands, so we - // don't need an encoder method and by-name matching. Just use the default - // in-order handling. - bits<5> dst; - bits<5> base; + : I { + bits<5> Rt; + bits<5> Rn; bits<9> offset; let Inst{31-30} = sz; let Inst{29-27} = 0b111; @@ -2768,24 +2931,26 @@ class BaseLoadStorePreIdx sz, bit V, bits<2> opc, dag oops, dag iops, let Inst{21} = 0; let Inst{20-12} = offset; let Inst{11-10} = 0b11; - let Inst{9-5} = base; - let Inst{4-0} = dst; + let Inst{9-5} = Rn; + let Inst{4-0} = Rt; let DecoderMethod = "DecodeSignedLdStInstruction"; } let hasSideEffects = 0 in { let mayStore = 0, mayLoad = 1 in -// FIXME: Modeling the write-back of these instructions for isel is tricky. -// we need the complex addressing mode for the memory reference, but -// we also need the write-back specified as a tied operand to the -// base register. That combination does not play nicely with -// the asm matcher and friends. +// FIXME: Modeling the write-back of these instructions for isel used +// to be tricky. we need the complex addressing mode for the memory +// reference, but we also need the write-back specified as a tied +// operand to the base register. It should work now, but needs to be +// done as a separate patch. This would allow us to be rid of the +// codegenonly pseudoinstructions below too. class LoadPreIdx sz, bit V, bits<2> opc, RegisterClass regtype, string asm> : BaseLoadStorePreIdx, + (ins GPR64sp:$Rn, simm9:$offset), asm, + ""/*"$Rn = $wback"*/>, Sched<[WriteLD, WriteAdr]>; let mayStore = 1, mayLoad = 0 in @@ -2793,8 +2958,8 @@ class StorePreIdx sz, bit V, bits<2> opc, RegisterClass regtype, string asm> : BaseLoadStorePreIdx, + (ins regtype:$Rt, GPR64sp:$Rn, simm9:$offset), + asm, ""/*"$Rn = $wback"*/>, Sched<[WriteAdr, WriteST]>; } // hasSideEffects = 0 @@ -2812,25 +2977,25 @@ class StorePreIdx sz, bit V, bits<2> opc, RegisterClass regtype, let mayStore = 0, mayLoad = 1, hasSideEffects = 0 in { class LoadPreIdxPseudo : Pseudo<(outs regtype:$Rt, GPR64sp:$wback), - (ins am_noindex:$addr, simm9:$offset), [], - "$addr.base = $wback,@earlyclobber $wback">, + (ins GPR64sp:$addr, simm9:$offset), [], + "$addr = $wback,@earlyclobber $wback">, Sched<[WriteLD, WriteAdr]>; class LoadPostIdxPseudo : Pseudo<(outs regtype:$Rt, GPR64sp:$wback), - (ins am_noindex:$addr, simm9:$offset), [], - "$addr.base = $wback,@earlyclobber $wback">, + (ins GPR64sp:$addr, simm9:$offset), [], + "$addr = $wback,@earlyclobber $wback">, Sched<[WriteLD, WriteI]>; } multiclass StorePreIdxPseudo { let mayStore = 1, mayLoad = 0, hasSideEffects = 0 in def _isel: Pseudo<(outs GPR64sp:$wback), - (ins regtype:$Rt, am_noindex:$addr, simm9:$offset), [], - "$addr.base = $wback,@earlyclobber $wback">, + (ins regtype:$Rt, GPR64sp:$addr, simm9:$offset), [], + "$addr = $wback,@earlyclobber $wback">, Sched<[WriteAdr, WriteST]>; - def : Pat<(OpNode (Ty regtype:$Rt), am_noindex:$addr, simm9:$offset), - (!cast(NAME#_isel) regtype:$Rt, am_noindex:$addr, + def : Pat<(OpNode (Ty regtype:$Rt), GPR64sp:$addr, simm9:$offset), + (!cast(NAME#_isel) regtype:$Rt, GPR64sp:$addr, simm9:$offset)>; } @@ -2841,12 +3006,9 @@ multiclass StorePreIdxPseudo sz, bit V, bits<2> opc, dag oops, dag iops, string asm, string cstr> - : I { - // The operands are in order to match the 'addr' MI operands, so we - // don't need an encoder method and by-name matching. Just use the default - // in-order handling. - bits<5> dst; - bits<5> base; + : I { + bits<5> Rt; + bits<5> Rn; bits<9> offset; let Inst{31-30} = sz; let Inst{29-27} = 0b111; @@ -2856,24 +3018,25 @@ class BaseLoadStorePostIdx sz, bit V, bits<2> opc, dag oops, dag iops, let Inst{21} = 0b0; let Inst{20-12} = offset; let Inst{11-10} = 0b01; - let Inst{9-5} = base; - let Inst{4-0} = dst; + let Inst{9-5} = Rn; + let Inst{4-0} = Rt; let DecoderMethod = "DecodeSignedLdStInstruction"; } let hasSideEffects = 0 in { let mayStore = 0, mayLoad = 1 in -// FIXME: Modeling the write-back of these instructions for isel is tricky. -// we need the complex addressing mode for the memory reference, but -// we also need the write-back specified as a tied operand to the -// base register. That combination does not play nicely with -// the asm matcher and friends. +// FIXME: Modeling the write-back of these instructions for isel used +// to be tricky. we need the complex addressing mode for the memory +// reference, but we also need the write-back specified as a tied +// operand to the base register. It should work now, but needs to be +// done as a separate patch. This would allow us to be rid of the +// codegenonly pseudoinstructions below too. class LoadPostIdx sz, bit V, bits<2> opc, RegisterClass regtype, string asm> : BaseLoadStorePostIdx, Sched<[WriteLD, WriteI]>; @@ -2882,7 +3045,7 @@ class StorePostIdx sz, bit V, bits<2> opc, RegisterClass regtype, string asm> : BaseLoadStorePostIdx, Sched<[WriteAdr, WriteST, ReadAdrBase]>; } // hasSideEffects = 0 @@ -2899,13 +3062,13 @@ multiclass StorePostIdxPseudo { let mayStore = 1, mayLoad = 0, hasSideEffects = 0 in def _isel: Pseudo<(outs GPR64sp:$wback), - (ins regtype:$Rt, am_noindex:$addr, simm9:$idx), [], - "$addr.base = $wback,@earlyclobber $wback">, - PseudoInstExpansion<(Insn regtype:$Rt, am_noindex:$addr, simm9:$idx)>, + (ins regtype:$Rt, GPR64sp:$Rn, simm9:$idx), [], + "$Rn = $wback,@earlyclobber $wback">, + PseudoInstExpansion<(Insn regtype:$Rt, GPR64sp:$Rn, simm9:$idx)>, Sched<[WriteAdr, WriteST, ReadAdrBase]>; - def : Pat<(OpNode (Ty regtype:$Rt), am_noindex:$addr, simm9:$idx), - (!cast(NAME#_isel) regtype:$Rt, am_noindex:$addr, + def : Pat<(OpNode (Ty regtype:$Rt), GPR64sp:$Rn, simm9:$idx), + (!cast(NAME#_isel) regtype:$Rt, GPR64sp:$Rn, simm9:$idx)>; } @@ -2917,14 +3080,10 @@ multiclass StorePostIdxPseudo opc, bit V, bit L, dag oops, dag iops, string asm> - : I { - // The operands are in order to match the 'addr' MI operands, so we - // don't need an encoder method and by-name matching. Just use the default - // in-order handling. Since we're using by-order, make sure the names - // do not match. - bits<5> dst; - bits<5> dst2; - bits<5> base; + : I { + bits<5> Rt; + bits<5> Rt2; + bits<5> Rn; bits<7> offset; let Inst{31-30} = opc; let Inst{29-27} = 0b101; @@ -2932,88 +3091,48 @@ class BaseLoadStorePairOffset opc, bit V, bit L, dag oops, dag iops, let Inst{25-23} = 0b010; let Inst{22} = L; let Inst{21-15} = offset; - let Inst{14-10} = dst2; - let Inst{9-5} = base; - let Inst{4-0} = dst; + let Inst{14-10} = Rt2; + let Inst{9-5} = Rn; + let Inst{4-0} = Rt; let DecoderMethod = "DecodePairLdStInstruction"; } -let hasSideEffects = 0 in { -let mayStore = 0, mayLoad = 1 in -class LoadPairOffset opc, bit V, RegisterClass regtype, - Operand indextype, string asm> - : BaseLoadStorePairOffset, - Sched<[WriteLD, WriteLDHi]>; +multiclass LoadPairOffset opc, bit V, RegisterClass regtype, + Operand indextype, string asm> { + let hasSideEffects = 0, mayStore = 0, mayLoad = 1 in + def i : BaseLoadStorePairOffset, + Sched<[WriteLD, WriteLDHi]>; -let mayLoad = 0, mayStore = 1 in -class StorePairOffset opc, bit V, RegisterClass regtype, - Operand indextype, string asm> - : BaseLoadStorePairOffset, - Sched<[WriteSTP]>; -} // hasSideEffects = 0 + def : InstAlias(NAME # "i") regtype:$Rt, regtype:$Rt2, + GPR64sp:$Rn, 0)>; +} + + +multiclass StorePairOffset opc, bit V, RegisterClass regtype, + Operand indextype, string asm> { + let hasSideEffects = 0, mayLoad = 0, mayStore = 1 in + def i : BaseLoadStorePairOffset, + Sched<[WriteSTP]>; + + def : InstAlias(NAME # "i") regtype:$Rt, regtype:$Rt2, + GPR64sp:$Rn, 0)>; +} // (pre-indexed) - -def MemoryIndexed32SImm7 : AsmOperandClass { - let Name = "MemoryIndexed32SImm7"; - let DiagnosticType = "InvalidMemoryIndexed32SImm7"; -} -def am_indexed32simm7 : Operand { // ComplexPattern<...> - let PrintMethod = "printAMIndexed<32>"; - let ParserMatchClass = MemoryIndexed32SImm7; - let MIOperandInfo = (ops GPR64sp:$base, i32imm:$offset); -} -def am_indexed32simm7_wb : Operand { // ComplexPattern<...> - let PrintMethod = "printAMIndexedWB<32>"; - let ParserMatchClass = MemoryIndexed32SImm7; - let MIOperandInfo = (ops GPR64sp:$base, i32imm:$offset); -} - -def MemoryIndexed64SImm7 : AsmOperandClass { - let Name = "MemoryIndexed64SImm7"; - let DiagnosticType = "InvalidMemoryIndexed64SImm7"; -} -def am_indexed64simm7 : Operand { // ComplexPattern<...> - let PrintMethod = "printAMIndexed<64>"; - let ParserMatchClass = MemoryIndexed64SImm7; - let MIOperandInfo = (ops GPR64sp:$base, i32imm:$offset); -} -def am_indexed64simm7_wb : Operand { // ComplexPattern<...> - let PrintMethod = "printAMIndexedWB<64>"; - let ParserMatchClass = MemoryIndexed64SImm7; - let MIOperandInfo = (ops GPR64sp:$base, i32imm:$offset); -} - -def MemoryIndexed128SImm7 : AsmOperandClass { - let Name = "MemoryIndexed128SImm7"; - let DiagnosticType = "InvalidMemoryIndexed128SImm7"; -} -def am_indexed128simm7 : Operand { // ComplexPattern<...> - let PrintMethod = "printAMIndexed<128>"; - let ParserMatchClass = MemoryIndexed128SImm7; - let MIOperandInfo = (ops GPR64sp:$base, i32imm:$offset); -} -def am_indexed128simm7_wb : Operand { // ComplexPattern<...> - let PrintMethod = "printAMIndexedWB<128>"; - let ParserMatchClass = MemoryIndexed128SImm7; - let MIOperandInfo = (ops GPR64sp:$base, i32imm:$offset); -} - class BaseLoadStorePairPreIdx opc, bit V, bit L, dag oops, dag iops, string asm> - : I { - // The operands are in order to match the 'addr' MI operands, so we - // don't need an encoder method and by-name matching. Just use the default - // in-order handling. Since we're using by-order, make sure the names - // do not match. - bits<5> dst; - bits<5> dst2; - bits<5> base; + : I { + bits<5> Rt; + bits<5> Rt2; + bits<5> Rn; bits<7> offset; let Inst{31-30} = opc; let Inst{29-27} = 0b101; @@ -3021,9 +3140,9 @@ class BaseLoadStorePairPreIdx opc, bit V, bit L, dag oops, dag iops, let Inst{25-23} = 0b011; let Inst{22} = L; let Inst{21-15} = offset; - let Inst{14-10} = dst2; - let Inst{9-5} = base; - let Inst{4-0} = dst; + let Inst{14-10} = Rt2; + let Inst{9-5} = Rn; + let Inst{4-0} = Rt; let DecoderMethod = "DecodePairLdStInstruction"; } @@ -3031,17 +3150,18 @@ class BaseLoadStorePairPreIdx opc, bit V, bit L, dag oops, dag iops, let hasSideEffects = 0 in { let mayStore = 0, mayLoad = 1 in class LoadPairPreIdx opc, bit V, RegisterClass regtype, - Operand addrmode, string asm> + Operand indextype, string asm> : BaseLoadStorePairPreIdx, + (ins GPR64sp:$Rn, indextype:$offset), asm>, Sched<[WriteLD, WriteLDHi, WriteAdr]>; let mayStore = 1, mayLoad = 0 in class StorePairPreIdx opc, bit V, RegisterClass regtype, - Operand addrmode, string asm> + Operand indextype, string asm> : BaseLoadStorePairPreIdx, Sched<[WriteAdr, WriteSTP]>; } // hasSideEffects = 0 @@ -3050,14 +3170,10 @@ class StorePairPreIdx opc, bit V, RegisterClass regtype, class BaseLoadStorePairPostIdx opc, bit V, bit L, dag oops, dag iops, string asm> - : I { - // The operands are in order to match the 'addr' MI operands, so we - // don't need an encoder method and by-name matching. Just use the default - // in-order handling. Since we're using by-order, make sure the names - // do not match. - bits<5> dst; - bits<5> dst2; - bits<5> base; + : I { + bits<5> Rt; + bits<5> Rt2; + bits<5> Rn; bits<7> offset; let Inst{31-30} = opc; let Inst{29-27} = 0b101; @@ -3065,9 +3181,9 @@ class BaseLoadStorePairPostIdx opc, bit V, bit L, dag oops, dag iops, let Inst{25-23} = 0b001; let Inst{22} = L; let Inst{21-15} = offset; - let Inst{14-10} = dst2; - let Inst{9-5} = base; - let Inst{4-0} = dst; + let Inst{14-10} = Rt2; + let Inst{9-5} = Rn; + let Inst{4-0} = Rt; let DecoderMethod = "DecodePairLdStInstruction"; } @@ -3078,7 +3194,7 @@ class LoadPairPostIdx opc, bit V, RegisterClass regtype, Operand idxtype, string asm> : BaseLoadStorePairPostIdx, + (ins GPR64sp:$Rn, idxtype:$offset), asm>, Sched<[WriteLD, WriteLDHi, WriteAdr]>; let mayStore = 1, mayLoad = 0 in @@ -3086,7 +3202,7 @@ class StorePairPostIdx opc, bit V, RegisterClass regtype, Operand idxtype, string asm> : BaseLoadStorePairPostIdx, Sched<[WriteAdr, WriteSTP]>; } // hasSideEffects = 0 @@ -3095,14 +3211,10 @@ class StorePairPostIdx opc, bit V, RegisterClass regtype, class BaseLoadStorePairNoAlloc opc, bit V, bit L, dag oops, dag iops, string asm> - : I { - // The operands are in order to match the 'addr' MI operands, so we - // don't need an encoder method and by-name matching. Just use the default - // in-order handling. Since we're using by-order, make sure the names - // do not match. - bits<5> dst; - bits<5> dst2; - bits<5> base; + : I { + bits<5> Rt; + bits<5> Rt2; + bits<5> Rn; bits<7> offset; let Inst{31-30} = opc; let Inst{29-27} = 0b101; @@ -3110,30 +3222,40 @@ class BaseLoadStorePairNoAlloc opc, bit V, bit L, dag oops, dag iops, let Inst{25-23} = 0b000; let Inst{22} = L; let Inst{21-15} = offset; - let Inst{14-10} = dst2; - let Inst{9-5} = base; - let Inst{4-0} = dst; + let Inst{14-10} = Rt2; + let Inst{9-5} = Rn; + let Inst{4-0} = Rt; let DecoderMethod = "DecodePairLdStInstruction"; } -let hasSideEffects = 0 in { -let mayStore = 0, mayLoad = 1 in -class LoadPairNoAlloc opc, bit V, RegisterClass regtype, - Operand indextype, string asm> - : BaseLoadStorePairNoAlloc, - Sched<[WriteLD, WriteLDHi]>; +multiclass LoadPairNoAlloc opc, bit V, RegisterClass regtype, + Operand indextype, string asm> { + let hasSideEffects = 0, mayStore = 0, mayLoad = 1 in + def i : BaseLoadStorePairNoAlloc, + Sched<[WriteLD, WriteLDHi]>; -let mayStore = 1, mayLoad = 0 in -class StorePairNoAlloc opc, bit V, RegisterClass regtype, - Operand indextype, string asm> - : BaseLoadStorePairNoAlloc, - Sched<[WriteSTP]>; -} // hasSideEffects = 0 + + def : InstAlias(NAME # "i") regtype:$Rt, regtype:$Rt2, + GPR64sp:$Rn, 0)>; +} + +multiclass StorePairNoAlloc opc, bit V, RegisterClass regtype, + Operand indextype, string asm> { + let hasSideEffects = 0, mayStore = 1, mayLoad = 0 in + def i : BaseLoadStorePairNoAlloc, + Sched<[WriteSTP]>; + + def : InstAlias(NAME # "i") regtype:$Rt, regtype:$Rt2, + GPR64sp:$Rn, 0)>; +} //--- // Load/store exclusive @@ -3172,10 +3294,10 @@ class BaseLoadStoreExclusive sz, bit o2, bit L, bit o1, bit o0, class LoadStoreExclusiveSimple sz, bit o2, bit L, bit o1, bit o0, dag oops, dag iops, string asm, string operands> : BaseLoadStoreExclusive { - bits<5> reg; - bits<5> base; - let Inst{9-5} = base; - let Inst{4-0} = reg; + bits<5> Rt; + bits<5> Rn; + let Inst{9-5} = Rn; + let Inst{4-0} = Rt; let PostEncoderMethod = "fixLoadStoreExclusive<0,0>"; } @@ -3185,28 +3307,28 @@ let mayLoad = 1, mayStore = 0 in class LoadAcquire sz, bit o2, bit L, bit o1, bit o0, RegisterClass regtype, string asm> : LoadStoreExclusiveSimple, + (ins GPR64sp0:$Rn), asm, "\t$Rt, [$Rn]">, Sched<[WriteLD]>; class LoadExclusive sz, bit o2, bit L, bit o1, bit o0, RegisterClass regtype, string asm> : LoadStoreExclusiveSimple, + (ins GPR64sp0:$Rn), asm, "\t$Rt, [$Rn]">, Sched<[WriteLD]>; class LoadExclusivePair sz, bit o2, bit L, bit o1, bit o0, RegisterClass regtype, string asm> : BaseLoadStoreExclusive, + (ins GPR64sp0:$Rn), asm, + "\t$Rt, $Rt2, [$Rn]">, Sched<[WriteLD, WriteLDHi]> { - bits<5> dst1; - bits<5> dst2; - bits<5> base; - let Inst{14-10} = dst2; - let Inst{9-5} = base; - let Inst{4-0} = dst1; + bits<5> Rt; + bits<5> Rt2; + bits<5> Rn; + let Inst{14-10} = Rt2; + let Inst{9-5} = Rn; + let Inst{4-0} = Rt; let PostEncoderMethod = "fixLoadStoreExclusive<0,1>"; } @@ -3216,23 +3338,23 @@ let mayLoad = 0, mayStore = 1 in class StoreRelease sz, bit o2, bit L, bit o1, bit o0, RegisterClass regtype, string asm> : LoadStoreExclusiveSimple, + (ins regtype:$Rt, GPR64sp0:$Rn), + asm, "\t$Rt, [$Rn]">, Sched<[WriteST]>; let mayLoad = 1, mayStore = 1 in class StoreExclusive sz, bit o2, bit L, bit o1, bit o0, RegisterClass regtype, string asm> : BaseLoadStoreExclusive, + (ins regtype:$Rt, GPR64sp0:$Rn), + asm, "\t$Ws, $Rt, [$Rn]">, Sched<[WriteSTX]> { - bits<5> status; - bits<5> reg; - bits<5> base; - let Inst{20-16} = status; - let Inst{9-5} = base; - let Inst{4-0} = reg; + bits<5> Ws; + bits<5> Rt; + bits<5> Rn; + let Inst{20-16} = Ws; + let Inst{9-5} = Rn; + let Inst{4-0} = Rt; let Constraints = "@earlyclobber $Ws"; let PostEncoderMethod = "fixLoadStoreExclusive<1,0>"; @@ -3242,17 +3364,17 @@ class StoreExclusivePair sz, bit o2, bit L, bit o1, bit o0, RegisterClass regtype, string asm> : BaseLoadStoreExclusive, + (ins regtype:$Rt, regtype:$Rt2, GPR64sp0:$Rn), + asm, "\t$Ws, $Rt, $Rt2, [$Rn]">, Sched<[WriteSTX]> { - bits<5> status; - bits<5> dst1; - bits<5> dst2; - bits<5> base; - let Inst{20-16} = status; - let Inst{14-10} = dst2; - let Inst{9-5} = base; - let Inst{4-0} = dst1; + bits<5> Ws; + bits<5> Rt; + bits<5> Rt2; + bits<5> Rn; + let Inst{20-16} = Ws; + let Inst{14-10} = Rt2; + let Inst{9-5} = Rn; + let Inst{4-0} = Rt; let Constraints = "@earlyclobber $Ws"; } @@ -3916,18 +4038,6 @@ multiclass FPMoveImmediate { // AdvSIMD //---------------------------------------------------------------------------- -def MemorySIMDNoIndexOperand : AsmOperandClass { - let Name = "MemorySIMDNoIndex"; - let ParserMethod = "tryParseNoIndexMemory"; -} -def am_simdnoindex : Operand, - ComplexPattern { - let PrintMethod = "printAMNoIndex"; - let ParserMatchClass = MemorySIMDNoIndexOperand; - let MIOperandInfo = (ops GPR64sp:$base); - let DecoderMethod = "DecodeGPR64spRegisterClass"; -} - let Predicates = [HasNEON] in { //---------------------------------------------------------------------------- @@ -7573,13 +7683,13 @@ multiclass SIMDVectorLShiftLongBHSD opc, string asm, // SIMD ldX/stX no-index memory references don't allow the optional // ", #0" constant and handle post-indexing explicitly, so we use // a more specialized parse method for them. Otherwise, it's the same as -// the general am_noindex handling. +// the general GPR64sp handling. class BaseSIMDLdSt opcode, bits<2> size, string asm, dag oops, dag iops, list pattern> - : I { + : I { bits<5> Vt; - bits<5> vaddr; + bits<5> Rn; let Inst{31} = 0; let Inst{30} = Q; let Inst{29-23} = 0b0011000; @@ -7587,15 +7697,15 @@ class BaseSIMDLdSt opcode, bits<2> size, let Inst{21-16} = 0b000000; let Inst{15-12} = opcode; let Inst{11-10} = size; - let Inst{9-5} = vaddr; + let Inst{9-5} = Rn; let Inst{4-0} = Vt; } class BaseSIMDLdStPost opcode, bits<2> size, string asm, dag oops, dag iops> - : I { + : I { bits<5> Vt; - bits<5> vaddr; + bits<5> Rn; bits<5> Xm; let Inst{31} = 0; let Inst{30} = Q; @@ -7605,7 +7715,7 @@ class BaseSIMDLdStPost opcode, bits<2> size, let Inst{20-16} = Xm; let Inst{15-12} = opcode; let Inst{11-10} = size; - let Inst{9-5} = vaddr; + let Inst{9-5} = Rn; let Inst{4-0} = Vt; } @@ -7614,41 +7724,41 @@ class BaseSIMDLdStPost opcode, bits<2> size, multiclass SIMDLdStAliases { // E.g. "ld1 { v0.8b, v1.8b }, [x1], #16" - // "ld1\t$Vt, $vaddr, #16" + // "ld1\t$Vt, [$Rn], #16" // may get mapped to - // (LD1Twov8b_POST VecListTwo8b:$Vt, am_simdnoindex:$vaddr, XZR) - def : InstAlias(NAME # Count # "v" # layout # "_POST") - am_simdnoindex:$vaddr, + GPR64sp:$Rn, !cast("VecList" # Count # layout):$Vt, XZR), 1>; // E.g. "ld1.8b { v0, v1 }, [x1], #16" - // "ld1.8b\t$Vt, $vaddr, #16" + // "ld1.8b\t$Vt, [$Rn], #16" // may get mapped to - // (LD1Twov8b_POST VecListTwo64:$Vt, am_simdnoindex:$vaddr, XZR) - def : InstAlias(NAME # Count # "v" # layout # "_POST") - am_simdnoindex:$vaddr, + GPR64sp:$Rn, !cast("VecList" # Count # Size):$Vt, XZR), 0>; // E.g. "ld1.8b { v0, v1 }, [x1]" - // "ld1\t$Vt, $vaddr" + // "ld1\t$Vt, [$Rn]" // may get mapped to - // (LD1Twov8b VecListTwo64:$Vt, am_simdnoindex:$vaddr) - def : InstAlias(NAME # Count # "v" # layout) !cast("VecList" # Count # Size):$Vt, - am_simdnoindex:$vaddr), 0>; + GPR64sp:$Rn), 0>; // E.g. "ld1.8b { v0, v1 }, [x1], x2" - // "ld1\t$Vt, $vaddr, $Xm" + // "ld1\t$Vt, [$Rn], $Xm" // may get mapped to - // (LD1Twov8b_POST VecListTwo64:$Vt, am_simdnoindex:$vaddr, GPR64pi8:$Xm) - def : InstAlias(NAME # Count # "v" # layout # "_POST") - am_simdnoindex:$vaddr, + GPR64sp:$Rn, !cast("VecList" # Count # Size):$Vt, !cast("GPR64pi" # Offset):$Xm), 0>; } @@ -7658,61 +7768,61 @@ multiclass BaseSIMDLdN(veclist # "16b"):$Vt), - (ins am_simdnoindex:$vaddr), []>; + (ins GPR64sp:$Rn), []>; def v8h : BaseSIMDLdSt<1, 1, opcode, 0b01, asm, (outs !cast(veclist # "8h"):$Vt), - (ins am_simdnoindex:$vaddr), []>; + (ins GPR64sp:$Rn), []>; def v4s : BaseSIMDLdSt<1, 1, opcode, 0b10, asm, (outs !cast(veclist # "4s"):$Vt), - (ins am_simdnoindex:$vaddr), []>; + (ins GPR64sp:$Rn), []>; def v2d : BaseSIMDLdSt<1, 1, opcode, 0b11, asm, (outs !cast(veclist # "2d"):$Vt), - (ins am_simdnoindex:$vaddr), []>; + (ins GPR64sp:$Rn), []>; def v8b : BaseSIMDLdSt<0, 1, opcode, 0b00, asm, (outs !cast(veclist # "8b"):$Vt), - (ins am_simdnoindex:$vaddr), []>; + (ins GPR64sp:$Rn), []>; def v4h : BaseSIMDLdSt<0, 1, opcode, 0b01, asm, (outs !cast(veclist # "4h"):$Vt), - (ins am_simdnoindex:$vaddr), []>; + (ins GPR64sp:$Rn), []>; def v2s : BaseSIMDLdSt<0, 1, opcode, 0b10, asm, (outs !cast(veclist # "2s"):$Vt), - (ins am_simdnoindex:$vaddr), []>; + (ins GPR64sp:$Rn), []>; def v16b_POST: BaseSIMDLdStPost<1, 1, opcode, 0b00, asm, - (outs am_simdnoindex:$wback, + (outs GPR64sp:$wback, !cast(veclist # "16b"):$Vt), - (ins am_simdnoindex:$vaddr, + (ins GPR64sp:$Rn, !cast("GPR64pi" # Offset128):$Xm)>; def v8h_POST : BaseSIMDLdStPost<1, 1, opcode, 0b01, asm, - (outs am_simdnoindex:$wback, + (outs GPR64sp:$wback, !cast(veclist # "8h"):$Vt), - (ins am_simdnoindex:$vaddr, + (ins GPR64sp:$Rn, !cast("GPR64pi" # Offset128):$Xm)>; def v4s_POST : BaseSIMDLdStPost<1, 1, opcode, 0b10, asm, - (outs am_simdnoindex:$wback, + (outs GPR64sp:$wback, !cast(veclist # "4s"):$Vt), - (ins am_simdnoindex:$vaddr, + (ins GPR64sp:$Rn, !cast("GPR64pi" # Offset128):$Xm)>; def v2d_POST : BaseSIMDLdStPost<1, 1, opcode, 0b11, asm, - (outs am_simdnoindex:$wback, + (outs GPR64sp:$wback, !cast(veclist # "2d"):$Vt), - (ins am_simdnoindex:$vaddr, + (ins GPR64sp:$Rn, !cast("GPR64pi" # Offset128):$Xm)>; def v8b_POST : BaseSIMDLdStPost<0, 1, opcode, 0b00, asm, - (outs am_simdnoindex:$wback, + (outs GPR64sp:$wback, !cast(veclist # "8b"):$Vt), - (ins am_simdnoindex:$vaddr, + (ins GPR64sp:$Rn, !cast("GPR64pi" # Offset64):$Xm)>; def v4h_POST : BaseSIMDLdStPost<0, 1, opcode, 0b01, asm, - (outs am_simdnoindex:$wback, + (outs GPR64sp:$wback, !cast(veclist # "4h"):$Vt), - (ins am_simdnoindex:$vaddr, + (ins GPR64sp:$Rn, !cast("GPR64pi" # Offset64):$Xm)>; def v2s_POST : BaseSIMDLdStPost<0, 1, opcode, 0b10, asm, - (outs am_simdnoindex:$wback, + (outs GPR64sp:$wback, !cast(veclist # "2s"):$Vt), - (ins am_simdnoindex:$vaddr, + (ins GPR64sp:$Rn, !cast("GPR64pi" # Offset64):$Xm)>; } @@ -7731,60 +7841,60 @@ multiclass BaseSIMDStN(veclist # "16b"):$Vt, - am_simdnoindex:$vaddr), []>; + GPR64sp:$Rn), []>; def v8h : BaseSIMDLdSt<1, 0, opcode, 0b01, asm, (outs), (ins !cast(veclist # "8h"):$Vt, - am_simdnoindex:$vaddr), []>; + GPR64sp:$Rn), []>; def v4s : BaseSIMDLdSt<1, 0, opcode, 0b10, asm, (outs), (ins !cast(veclist # "4s"):$Vt, - am_simdnoindex:$vaddr), []>; + GPR64sp:$Rn), []>; def v2d : BaseSIMDLdSt<1, 0, opcode, 0b11, asm, (outs), (ins !cast(veclist # "2d"):$Vt, - am_simdnoindex:$vaddr), []>; + GPR64sp:$Rn), []>; def v8b : BaseSIMDLdSt<0, 0, opcode, 0b00, asm, (outs), (ins !cast(veclist # "8b"):$Vt, - am_simdnoindex:$vaddr), []>; + GPR64sp:$Rn), []>; def v4h : BaseSIMDLdSt<0, 0, opcode, 0b01, asm, (outs), (ins !cast(veclist # "4h"):$Vt, - am_simdnoindex:$vaddr), []>; + GPR64sp:$Rn), []>; def v2s : BaseSIMDLdSt<0, 0, opcode, 0b10, asm, (outs), (ins !cast(veclist # "2s"):$Vt, - am_simdnoindex:$vaddr), []>; + GPR64sp:$Rn), []>; def v16b_POST : BaseSIMDLdStPost<1, 0, opcode, 0b00, asm, - (outs am_simdnoindex:$wback), + (outs GPR64sp:$wback), (ins !cast(veclist # "16b"):$Vt, - am_simdnoindex:$vaddr, + GPR64sp:$Rn, !cast("GPR64pi" # Offset128):$Xm)>; def v8h_POST : BaseSIMDLdStPost<1, 0, opcode, 0b01, asm, - (outs am_simdnoindex:$wback), + (outs GPR64sp:$wback), (ins !cast(veclist # "8h"):$Vt, - am_simdnoindex:$vaddr, + GPR64sp:$Rn, !cast("GPR64pi" # Offset128):$Xm)>; def v4s_POST : BaseSIMDLdStPost<1, 0, opcode, 0b10, asm, - (outs am_simdnoindex:$wback), + (outs GPR64sp:$wback), (ins !cast(veclist # "4s"):$Vt, - am_simdnoindex:$vaddr, + GPR64sp:$Rn, !cast("GPR64pi" # Offset128):$Xm)>; def v2d_POST : BaseSIMDLdStPost<1, 0, opcode, 0b11, asm, - (outs am_simdnoindex:$wback), + (outs GPR64sp:$wback), (ins !cast(veclist # "2d"):$Vt, - am_simdnoindex:$vaddr, + GPR64sp:$Rn, !cast("GPR64pi" # Offset128):$Xm)>; def v8b_POST : BaseSIMDLdStPost<0, 0, opcode, 0b00, asm, - (outs am_simdnoindex:$wback), + (outs GPR64sp:$wback), (ins !cast(veclist # "8b"):$Vt, - am_simdnoindex:$vaddr, + GPR64sp:$Rn, !cast("GPR64pi" # Offset64):$Xm)>; def v4h_POST : BaseSIMDLdStPost<0, 0, opcode, 0b01, asm, - (outs am_simdnoindex:$wback), + (outs GPR64sp:$wback), (ins !cast(veclist # "4h"):$Vt, - am_simdnoindex:$vaddr, + GPR64sp:$Rn, !cast("GPR64pi" # Offset64):$Xm)>; def v2s_POST : BaseSIMDLdStPost<0, 0, opcode, 0b10, asm, - (outs am_simdnoindex:$wback), + (outs GPR64sp:$wback), (ins !cast(veclist # "2s"):$Vt, - am_simdnoindex:$vaddr, + GPR64sp:$Rn, !cast("GPR64pi" # Offset64):$Xm)>; } @@ -7805,12 +7915,12 @@ multiclass BaseSIMDLd1(veclist # "1d"):$Vt), - (ins am_simdnoindex:$vaddr), []>; + (ins GPR64sp:$Rn), []>; def v1d_POST : BaseSIMDLdStPost<0, 1, opcode, 0b11, asm, - (outs am_simdnoindex:$wback, + (outs GPR64sp:$wback, !cast(veclist # "1d"):$Vt), - (ins am_simdnoindex:$vaddr, + (ins GPR64sp:$Rn, !cast("GPR64pi" # Offset64):$Xm)>; } @@ -7825,12 +7935,12 @@ multiclass BaseSIMDSt1(veclist # "1d"):$Vt, - am_simdnoindex:$vaddr), []>; + GPR64sp:$Rn), []>; def v1d_POST : BaseSIMDLdStPost<0, 0, opcode, 0b11, asm, - (outs am_simdnoindex:$wback), + (outs GPR64sp:$wback), (ins !cast(veclist # "1d"):$Vt, - am_simdnoindex:$vaddr, + GPR64sp:$Rn, !cast("GPR64pi" # Offset64):$Xm)>; } @@ -7884,13 +7994,13 @@ class BaseSIMDLdStSingle opcode, dag oops, dag iops, list pattern> : I { bits<5> Vt; - bits<5> vaddr; + bits<5> Rn; let Inst{31} = 0; let Inst{29-24} = 0b001101; let Inst{22} = L; let Inst{21} = R; let Inst{15-13} = opcode; - let Inst{9-5} = vaddr; + let Inst{9-5} = Rn; let Inst{4-0} = Vt; } @@ -7899,13 +8009,13 @@ class BaseSIMDLdStSingleTied opcode, dag oops, dag iops, list pattern> : I { bits<5> Vt; - bits<5> vaddr; + bits<5> Rn; let Inst{31} = 0; let Inst{29-24} = 0b001101; let Inst{22} = L; let Inst{21} = R; let Inst{15-13} = opcode; - let Inst{9-5} = vaddr; + let Inst{9-5} = Rn; let Inst{4-0} = Vt; } @@ -7913,8 +8023,8 @@ class BaseSIMDLdStSingleTied opcode, let mayLoad = 1, mayStore = 0, hasSideEffects = 0 in class BaseSIMDLdR opcode, bit S, bits<2> size, string asm, Operand listtype> - : BaseSIMDLdStSingle<1, R, opcode, asm, "\t$Vt, $vaddr", "", - (outs listtype:$Vt), (ins am_simdnoindex:$vaddr), + : BaseSIMDLdStSingle<1, R, opcode, asm, "\t$Vt, [$Rn]", "", + (outs listtype:$Vt), (ins GPR64sp:$Rn), []> { let Inst{30} = Q; let Inst{23} = 0; @@ -7925,10 +8035,10 @@ class BaseSIMDLdR opcode, bit S, bits<2> size, string asm, let mayLoad = 1, mayStore = 0, hasSideEffects = 0 in class BaseSIMDLdRPost opcode, bit S, bits<2> size, string asm, Operand listtype, Operand GPR64pi> - : BaseSIMDLdStSingle<1, R, opcode, asm, "\t$Vt, $vaddr, $Xm", - "$vaddr = $wback", - (outs am_simdnoindex:$wback, listtype:$Vt), - (ins am_simdnoindex:$vaddr, GPR64pi:$Xm), []> { + : BaseSIMDLdStSingle<1, R, opcode, asm, "\t$Vt, [$Rn], $Xm", + "$Rn = $wback", + (outs GPR64sp:$wback, listtype:$Vt), + (ins GPR64sp:$Rn, GPR64pi:$Xm), []> { bits<5> Xm; let Inst{30} = Q; let Inst{23} = 1; @@ -7940,41 +8050,41 @@ class BaseSIMDLdRPost opcode, bit S, bits<2> size, multiclass SIMDLdrAliases { // E.g. "ld1r { v0.8b }, [x1], #1" - // "ld1r.8b\t$Vt, $vaddr, #1" + // "ld1r.8b\t$Vt, [$Rn], #1" // may get mapped to - // (LD1Rv8b_POST VecListOne8b:$Vt, am_simdnoindex:$vaddr, XZR) - def : InstAlias(NAME # "v" # layout # "_POST") - am_simdnoindex:$vaddr, + GPR64sp:$Rn, !cast("VecList" # Count # layout):$Vt, XZR), 1>; // E.g. "ld1r.8b { v0 }, [x1], #1" - // "ld1r.8b\t$Vt, $vaddr, #1" + // "ld1r.8b\t$Vt, [$Rn], #1" // may get mapped to - // (LD1Rv8b_POST VecListOne64:$Vt, am_simdnoindex:$vaddr, XZR) - def : InstAlias(NAME # "v" # layout # "_POST") - am_simdnoindex:$vaddr, + GPR64sp:$Rn, !cast("VecList" # Count # Size):$Vt, XZR), 0>; // E.g. "ld1r.8b { v0 }, [x1]" - // "ld1r.8b\t$Vt, $vaddr" + // "ld1r.8b\t$Vt, [$Rn]" // may get mapped to - // (LD1Rv8b VecListOne64:$Vt, am_simdnoindex:$vaddr) - def : InstAlias(NAME # "v" # layout) !cast("VecList" # Count # Size):$Vt, - am_simdnoindex:$vaddr), 0>; + GPR64sp:$Rn), 0>; // E.g. "ld1r.8b { v0 }, [x1], x2" - // "ld1r.8b\t$Vt, $vaddr, $Xm" + // "ld1r.8b\t$Vt, [$Rn], $Xm" // may get mapped to - // (LD1Rv8b_POST VecListOne64:$Vt, am_simdnoindex:$vaddr, GPR64pi1:$Xm) - def : InstAlias(NAME # "v" # layout # "_POST") - am_simdnoindex:$vaddr, + GPR64sp:$Rn, !cast("VecList" # Count # Size):$Vt, !cast("GPR64pi" # Offset):$Xm), 0>; } @@ -8035,7 +8145,7 @@ multiclass SIMDLdR opcode, bit S, string asm, string Count, class SIMDLdStSingleB opcode, string asm, dag oops, dag iops, list pattern> - : BaseSIMDLdStSingle { // idx encoded in Q:S:size fields. bits<4> idx; @@ -8047,7 +8157,7 @@ class SIMDLdStSingleB opcode, string asm, } class SIMDLdStSingleBTied opcode, string asm, dag oops, dag iops, list pattern> - : BaseSIMDLdStSingleTied { // idx encoded in Q:S:size fields. bits<4> idx; @@ -8059,8 +8169,8 @@ class SIMDLdStSingleBTied opcode, string asm, } class SIMDLdStSingleBPost opcode, string asm, dag oops, dag iops> - : BaseSIMDLdStSingle { + : BaseSIMDLdStSingle { // idx encoded in Q:S:size fields. bits<4> idx; bits<5> Xm; @@ -8072,8 +8182,8 @@ class SIMDLdStSingleBPost opcode, string asm, } class SIMDLdStSingleBTiedPost opcode, string asm, dag oops, dag iops> - : BaseSIMDLdStSingleTied { + : BaseSIMDLdStSingleTied { // idx encoded in Q:S:size fields. bits<4> idx; bits<5> Xm; @@ -8086,7 +8196,7 @@ class SIMDLdStSingleBTiedPost opcode, string asm, class SIMDLdStSingleH opcode, bit size, string asm, dag oops, dag iops, list pattern> - : BaseSIMDLdStSingle { // idx encoded in Q:S:size<1> fields. bits<3> idx; @@ -8099,7 +8209,7 @@ class SIMDLdStSingleH opcode, bit size, string asm, } class SIMDLdStSingleHTied opcode, bit size, string asm, dag oops, dag iops, list pattern> - : BaseSIMDLdStSingleTied { // idx encoded in Q:S:size<1> fields. bits<3> idx; @@ -8113,8 +8223,8 @@ class SIMDLdStSingleHTied opcode, bit size, string asm, class SIMDLdStSingleHPost opcode, bit size, string asm, dag oops, dag iops> - : BaseSIMDLdStSingle { + : BaseSIMDLdStSingle { // idx encoded in Q:S:size<1> fields. bits<3> idx; bits<5> Xm; @@ -8127,8 +8237,8 @@ class SIMDLdStSingleHPost opcode, bit size, string asm, } class SIMDLdStSingleHTiedPost opcode, bit size, string asm, dag oops, dag iops> - : BaseSIMDLdStSingleTied { + : BaseSIMDLdStSingleTied { // idx encoded in Q:S:size<1> fields. bits<3> idx; bits<5> Xm; @@ -8141,7 +8251,7 @@ class SIMDLdStSingleHTiedPost opcode, bit size, string asm } class SIMDLdStSingleS opcode, bits<2> size, string asm, dag oops, dag iops, list pattern> - : BaseSIMDLdStSingle { // idx encoded in Q:S fields. bits<2> idx; @@ -8153,7 +8263,7 @@ class SIMDLdStSingleS opcode, bits<2> size, string asm, } class SIMDLdStSingleSTied opcode, bits<2> size, string asm, dag oops, dag iops, list pattern> - : BaseSIMDLdStSingleTied { // idx encoded in Q:S fields. bits<2> idx; @@ -8165,8 +8275,8 @@ class SIMDLdStSingleSTied opcode, bits<2> size, string asm } class SIMDLdStSingleSPost opcode, bits<2> size, string asm, dag oops, dag iops> - : BaseSIMDLdStSingle { + : BaseSIMDLdStSingle { // idx encoded in Q:S fields. bits<2> idx; bits<5> Xm; @@ -8178,8 +8288,8 @@ class SIMDLdStSingleSPost opcode, bits<2> size, } class SIMDLdStSingleSTiedPost opcode, bits<2> size, string asm, dag oops, dag iops> - : BaseSIMDLdStSingleTied { + : BaseSIMDLdStSingleTied { // idx encoded in Q:S fields. bits<2> idx; bits<5> Xm; @@ -8191,7 +8301,7 @@ class SIMDLdStSingleSTiedPost opcode, bits<2> size, } class SIMDLdStSingleD opcode, bits<2> size, string asm, dag oops, dag iops, list pattern> - : BaseSIMDLdStSingle { // idx encoded in Q field. bits<1> idx; @@ -8203,7 +8313,7 @@ class SIMDLdStSingleD opcode, bits<2> size, string asm, } class SIMDLdStSingleDTied opcode, bits<2> size, string asm, dag oops, dag iops, list pattern> - : BaseSIMDLdStSingleTied { // idx encoded in Q field. bits<1> idx; @@ -8215,8 +8325,8 @@ class SIMDLdStSingleDTied opcode, bits<2> size, string asm } class SIMDLdStSingleDPost opcode, bits<2> size, string asm, dag oops, dag iops> - : BaseSIMDLdStSingle { + : BaseSIMDLdStSingle { // idx encoded in Q field. bits<1> idx; bits<5> Xm; @@ -8228,8 +8338,8 @@ class SIMDLdStSingleDPost opcode, bits<2> size, } class SIMDLdStSingleDTiedPost opcode, bits<2> size, string asm, dag oops, dag iops> - : BaseSIMDLdStSingleTied { + : BaseSIMDLdStSingleTied { // idx encoded in Q field. bits<1> idx; bits<5> Xm; @@ -8247,12 +8357,12 @@ multiclass SIMDLdSingleBTied opcode, string asm, def i8 : SIMDLdStSingleBTied<1, R, opcode, asm, (outs listtype:$dst), (ins listtype:$Vt, VectorIndexB:$idx, - am_simdnoindex:$vaddr), []>; + GPR64sp:$Rn), []>; def i8_POST : SIMDLdStSingleBTiedPost<1, R, opcode, asm, - (outs am_simdnoindex:$wback, listtype:$dst), + (outs GPR64sp:$wback, listtype:$dst), (ins listtype:$Vt, VectorIndexB:$idx, - am_simdnoindex:$vaddr, GPR64pi:$Xm)>; + GPR64sp:$Rn, GPR64pi:$Xm)>; } let mayLoad = 1, mayStore = 0, hasSideEffects = 0 in multiclass SIMDLdSingleHTied opcode, bit size, string asm, @@ -8261,12 +8371,12 @@ multiclass SIMDLdSingleHTied opcode, bit size, string asm, def i16 : SIMDLdStSingleHTied<1, R, opcode, size, asm, (outs listtype:$dst), (ins listtype:$Vt, VectorIndexH:$idx, - am_simdnoindex:$vaddr), []>; + GPR64sp:$Rn), []>; def i16_POST : SIMDLdStSingleHTiedPost<1, R, opcode, size, asm, - (outs am_simdnoindex:$wback, listtype:$dst), + (outs GPR64sp:$wback, listtype:$dst), (ins listtype:$Vt, VectorIndexH:$idx, - am_simdnoindex:$vaddr, GPR64pi:$Xm)>; + GPR64sp:$Rn, GPR64pi:$Xm)>; } let mayLoad = 1, mayStore = 0, hasSideEffects = 0 in multiclass SIMDLdSingleSTied opcode, bits<2> size,string asm, @@ -8275,12 +8385,12 @@ multiclass SIMDLdSingleSTied opcode, bits<2> size,string asm, def i32 : SIMDLdStSingleSTied<1, R, opcode, size, asm, (outs listtype:$dst), (ins listtype:$Vt, VectorIndexS:$idx, - am_simdnoindex:$vaddr), []>; + GPR64sp:$Rn), []>; def i32_POST : SIMDLdStSingleSTiedPost<1, R, opcode, size, asm, - (outs am_simdnoindex:$wback, listtype:$dst), + (outs GPR64sp:$wback, listtype:$dst), (ins listtype:$Vt, VectorIndexS:$idx, - am_simdnoindex:$vaddr, GPR64pi:$Xm)>; + GPR64sp:$Rn, GPR64pi:$Xm)>; } let mayLoad = 1, mayStore = 0, hasSideEffects = 0 in multiclass SIMDLdSingleDTied opcode, bits<2> size, string asm, @@ -8288,100 +8398,100 @@ multiclass SIMDLdSingleDTied opcode, bits<2> size, string asm, def i64 : SIMDLdStSingleDTied<1, R, opcode, size, asm, (outs listtype:$dst), (ins listtype:$Vt, VectorIndexD:$idx, - am_simdnoindex:$vaddr), []>; + GPR64sp:$Rn), []>; def i64_POST : SIMDLdStSingleDTiedPost<1, R, opcode, size, asm, - (outs am_simdnoindex:$wback, listtype:$dst), + (outs GPR64sp:$wback, listtype:$dst), (ins listtype:$Vt, VectorIndexD:$idx, - am_simdnoindex:$vaddr, GPR64pi:$Xm)>; + GPR64sp:$Rn, GPR64pi:$Xm)>; } let mayLoad = 0, mayStore = 1, hasSideEffects = 0 in multiclass SIMDStSingleB opcode, string asm, RegisterOperand listtype, RegisterOperand GPR64pi> { def i8 : SIMDLdStSingleB<0, R, opcode, asm, (outs), (ins listtype:$Vt, VectorIndexB:$idx, - am_simdnoindex:$vaddr), []>; + GPR64sp:$Rn), []>; def i8_POST : SIMDLdStSingleBPost<0, R, opcode, asm, - (outs am_simdnoindex:$wback), + (outs GPR64sp:$wback), (ins listtype:$Vt, VectorIndexB:$idx, - am_simdnoindex:$vaddr, GPR64pi:$Xm)>; + GPR64sp:$Rn, GPR64pi:$Xm)>; } let mayLoad = 0, mayStore = 1, hasSideEffects = 0 in multiclass SIMDStSingleH opcode, bit size, string asm, RegisterOperand listtype, RegisterOperand GPR64pi> { def i16 : SIMDLdStSingleH<0, R, opcode, size, asm, (outs), (ins listtype:$Vt, VectorIndexH:$idx, - am_simdnoindex:$vaddr), []>; + GPR64sp:$Rn), []>; def i16_POST : SIMDLdStSingleHPost<0, R, opcode, size, asm, - (outs am_simdnoindex:$wback), + (outs GPR64sp:$wback), (ins listtype:$Vt, VectorIndexH:$idx, - am_simdnoindex:$vaddr, GPR64pi:$Xm)>; + GPR64sp:$Rn, GPR64pi:$Xm)>; } let mayLoad = 0, mayStore = 1, hasSideEffects = 0 in multiclass SIMDStSingleS opcode, bits<2> size,string asm, RegisterOperand listtype, RegisterOperand GPR64pi> { def i32 : SIMDLdStSingleS<0, R, opcode, size, asm, (outs), (ins listtype:$Vt, VectorIndexS:$idx, - am_simdnoindex:$vaddr), []>; + GPR64sp:$Rn), []>; def i32_POST : SIMDLdStSingleSPost<0, R, opcode, size, asm, - (outs am_simdnoindex:$wback), + (outs GPR64sp:$wback), (ins listtype:$Vt, VectorIndexS:$idx, - am_simdnoindex:$vaddr, GPR64pi:$Xm)>; + GPR64sp:$Rn, GPR64pi:$Xm)>; } let mayLoad = 0, mayStore = 1, hasSideEffects = 0 in multiclass SIMDStSingleD opcode, bits<2> size, string asm, RegisterOperand listtype, RegisterOperand GPR64pi> { def i64 : SIMDLdStSingleD<0, R, opcode, size, asm, (outs), (ins listtype:$Vt, VectorIndexD:$idx, - am_simdnoindex:$vaddr), []>; + GPR64sp:$Rn), []>; def i64_POST : SIMDLdStSingleDPost<0, R, opcode, size, asm, - (outs am_simdnoindex:$wback), + (outs GPR64sp:$wback), (ins listtype:$Vt, VectorIndexD:$idx, - am_simdnoindex:$vaddr, GPR64pi:$Xm)>; + GPR64sp:$Rn, GPR64pi:$Xm)>; } multiclass SIMDLdStSingleAliases { // E.g. "ld1 { v0.8b }[0], [x1], #1" - // "ld1\t$Vt, $vaddr, #1" + // "ld1\t$Vt, [$Rn], #1" // may get mapped to - // (LD1Rv8b_POST VecListOne8b:$Vt, am_simdnoindex:$vaddr, XZR) - def : InstAlias(NAME # Type # "_POST") - am_simdnoindex:$vaddr, + GPR64sp:$Rn, !cast("VecList" # Count # layout):$Vt, idxtype:$idx, XZR), 1>; // E.g. "ld1.8b { v0 }[0], [x1], #1" - // "ld1.8b\t$Vt, $vaddr, #1" + // "ld1.8b\t$Vt, [$Rn], #1" // may get mapped to - // (LD1Rv8b_POST VecListOne64:$Vt, am_simdnoindex:$vaddr, XZR) - def : InstAlias(NAME # Type # "_POST") - am_simdnoindex:$vaddr, + GPR64sp:$Rn, !cast("VecList" # Count # "128"):$Vt, idxtype:$idx, XZR), 0>; // E.g. "ld1.8b { v0 }[0], [x1]" - // "ld1.8b\t$Vt, $vaddr" + // "ld1.8b\t$Vt, [$Rn]" // may get mapped to - // (LD1Rv8b VecListOne64:$Vt, am_simdnoindex:$vaddr) - def : InstAlias(NAME # Type) !cast("VecList" # Count # "128"):$Vt, - idxtype:$idx, am_simdnoindex:$vaddr), 0>; + idxtype:$idx, GPR64sp:$Rn), 0>; // E.g. "ld1.8b { v0 }[0], [x1], x2" - // "ld1.8b\t$Vt, $vaddr, $Xm" + // "ld1.8b\t$Vt, [$Rn], $Xm" // may get mapped to - // (LD1Rv8b_POST VecListOne64:$Vt, am_simdnoindex:$vaddr, GPR64pi1:$Xm) - def : InstAlias(NAME # Type # "_POST") - am_simdnoindex:$vaddr, + GPR64sp:$Rn, !cast("VecList" # Count # "128"):$Vt, idxtype:$idx, !cast("GPR64pi" # Offset):$Xm), 0>; diff --git a/lib/Target/ARM64/ARM64InstrInfo.cpp b/lib/Target/ARM64/ARM64InstrInfo.cpp index 5643fb0ce2c..e1f9667841c 100644 --- a/lib/Target/ARM64/ARM64InstrInfo.cpp +++ b/lib/Target/ARM64/ARM64InstrInfo.cpp @@ -1039,29 +1039,53 @@ bool ARM64InstrInfo::isScaledAddr(const MachineInstr *MI) const { switch (MI->getOpcode()) { default: break; - case ARM64::LDRBBro: - case ARM64::LDRBro: - case ARM64::LDRDro: - case ARM64::LDRHHro: - case ARM64::LDRHro: - case ARM64::LDRQro: - case ARM64::LDRSBWro: - case ARM64::LDRSBXro: - case ARM64::LDRSHWro: - case ARM64::LDRSHXro: - case ARM64::LDRSWro: - case ARM64::LDRSro: - case ARM64::LDRWro: - case ARM64::LDRXro: - case ARM64::STRBBro: - case ARM64::STRBro: - case ARM64::STRDro: - case ARM64::STRHHro: - case ARM64::STRHro: - case ARM64::STRQro: - case ARM64::STRSro: - case ARM64::STRWro: - case ARM64::STRXro: + case ARM64::LDRBBroW: + case ARM64::LDRBroW: + case ARM64::LDRDroW: + case ARM64::LDRHHroW: + case ARM64::LDRHroW: + case ARM64::LDRQroW: + case ARM64::LDRSBWroW: + case ARM64::LDRSBXroW: + case ARM64::LDRSHWroW: + case ARM64::LDRSHXroW: + case ARM64::LDRSWroW: + case ARM64::LDRSroW: + case ARM64::LDRWroW: + case ARM64::LDRXroW: + case ARM64::STRBBroW: + case ARM64::STRBroW: + case ARM64::STRDroW: + case ARM64::STRHHroW: + case ARM64::STRHroW: + case ARM64::STRQroW: + case ARM64::STRSroW: + case ARM64::STRWroW: + case ARM64::STRXroW: + case ARM64::LDRBBroX: + case ARM64::LDRBroX: + case ARM64::LDRDroX: + case ARM64::LDRHHroX: + case ARM64::LDRHroX: + case ARM64::LDRQroX: + case ARM64::LDRSBWroX: + case ARM64::LDRSBXroX: + case ARM64::LDRSHWroX: + case ARM64::LDRSHXroX: + case ARM64::LDRSWroX: + case ARM64::LDRSroX: + case ARM64::LDRWroX: + case ARM64::LDRXroX: + case ARM64::STRBBroX: + case ARM64::STRBroX: + case ARM64::STRDroX: + case ARM64::STRHHroX: + case ARM64::STRHroX: + case ARM64::STRQroX: + case ARM64::STRSroX: + case ARM64::STRWroX: + case ARM64::STRXroX: + unsigned Val = MI->getOperand(3).getImm(); ARM64_AM::ShiftExtendType ExtType = ARM64_AM::getMemExtendType(Val); return (ExtType != ARM64_AM::UXTX) || ARM64_AM::getMemDoShift(Val); diff --git a/lib/Target/ARM64/ARM64InstrInfo.td b/lib/Target/ARM64/ARM64InstrInfo.td index 4c735c057a2..94a39c11122 100644 --- a/lib/Target/ARM64/ARM64InstrInfo.td +++ b/lib/Target/ARM64/ARM64InstrInfo.td @@ -1064,22 +1064,22 @@ def : InstAlias<"dcps3", (DCPS3 0)>; //===----------------------------------------------------------------------===// // Pair (indexed, offset) -def LDPWi : LoadPairOffset<0b00, 0, GPR32, am_indexed32simm7, "ldp">; -def LDPXi : LoadPairOffset<0b10, 0, GPR64, am_indexed64simm7, "ldp">; -def LDPSi : LoadPairOffset<0b00, 1, FPR32, am_indexed32simm7, "ldp">; -def LDPDi : LoadPairOffset<0b01, 1, FPR64, am_indexed64simm7, "ldp">; -def LDPQi : LoadPairOffset<0b10, 1, FPR128, am_indexed128simm7, "ldp">; +defm LDPW : LoadPairOffset<0b00, 0, GPR32, simm7s4, "ldp">; +defm LDPX : LoadPairOffset<0b10, 0, GPR64, simm7s8, "ldp">; +defm LDPS : LoadPairOffset<0b00, 1, FPR32, simm7s4, "ldp">; +defm LDPD : LoadPairOffset<0b01, 1, FPR64, simm7s8, "ldp">; +defm LDPQ : LoadPairOffset<0b10, 1, FPR128, simm7s16, "ldp">; -def LDPSWi : LoadPairOffset<0b01, 0, GPR64, am_indexed32simm7, "ldpsw">; +defm LDPSW : LoadPairOffset<0b01, 0, GPR64, simm7s4, "ldpsw">; // Pair (pre-indexed) -def LDPWpre : LoadPairPreIdx<0b00, 0, GPR32, am_indexed32simm7_wb, "ldp">; -def LDPXpre : LoadPairPreIdx<0b10, 0, GPR64, am_indexed64simm7_wb, "ldp">; -def LDPSpre : LoadPairPreIdx<0b00, 1, FPR32, am_indexed32simm7_wb, "ldp">; -def LDPDpre : LoadPairPreIdx<0b01, 1, FPR64, am_indexed64simm7_wb, "ldp">; -def LDPQpre : LoadPairPreIdx<0b10, 1, FPR128, am_indexed128simm7_wb, "ldp">; +def LDPWpre : LoadPairPreIdx<0b00, 0, GPR32, simm7s4, "ldp">; +def LDPXpre : LoadPairPreIdx<0b10, 0, GPR64, simm7s8, "ldp">; +def LDPSpre : LoadPairPreIdx<0b00, 1, FPR32, simm7s4, "ldp">; +def LDPDpre : LoadPairPreIdx<0b01, 1, FPR64, simm7s8, "ldp">; +def LDPQpre : LoadPairPreIdx<0b10, 1, FPR128, simm7s16, "ldp">; -def LDPSWpre : LoadPairPreIdx<0b01, 0, GPR64, am_indexed32simm7_wb, "ldpsw">; +def LDPSWpre : LoadPairPreIdx<0b01, 0, GPR64, simm7s4, "ldpsw">; // Pair (post-indexed) def LDPWpost : LoadPairPostIdx<0b00, 0, GPR32, simm7s4, "ldp">; @@ -1092,259 +1092,351 @@ def LDPSWpost : LoadPairPostIdx<0b01, 0, GPR64, simm7s4, "ldpsw">; // Pair (no allocate) -def LDNPWi : LoadPairNoAlloc<0b00, 0, GPR32, am_indexed32simm7, "ldnp">; -def LDNPXi : LoadPairNoAlloc<0b10, 0, GPR64, am_indexed64simm7, "ldnp">; -def LDNPSi : LoadPairNoAlloc<0b00, 1, FPR32, am_indexed32simm7, "ldnp">; -def LDNPDi : LoadPairNoAlloc<0b01, 1, FPR64, am_indexed64simm7, "ldnp">; -def LDNPQi : LoadPairNoAlloc<0b10, 1, FPR128, am_indexed128simm7, "ldnp">; +defm LDNPW : LoadPairNoAlloc<0b00, 0, GPR32, simm7s4, "ldnp">; +defm LDNPX : LoadPairNoAlloc<0b10, 0, GPR64, simm7s8, "ldnp">; +defm LDNPS : LoadPairNoAlloc<0b00, 1, FPR32, simm7s4, "ldnp">; +defm LDNPD : LoadPairNoAlloc<0b01, 1, FPR64, simm7s8, "ldnp">; +defm LDNPQ : LoadPairNoAlloc<0b10, 1, FPR128, simm7s16, "ldnp">; //--- // (register offset) //--- -let AddedComplexity = 10 in { // Integer -def LDRBBro : Load8RO<0b00, 0, 0b01, GPR32, "ldrb", - [(set GPR32:$Rt, (zextloadi8 ro_indexed8:$addr))]>; -def LDRHHro : Load16RO<0b01, 0, 0b01, GPR32, "ldrh", - [(set GPR32:$Rt, (zextloadi16 ro_indexed16:$addr))]>; -def LDRWro : Load32RO<0b10, 0, 0b01, GPR32, "ldr", - [(set GPR32:$Rt, (load ro_indexed32:$addr))]>; -def LDRXro : Load64RO<0b11, 0, 0b01, GPR64, "ldr", - [(set GPR64:$Rt, (load ro_indexed64:$addr))]>; +defm LDRBB : Load8RO<0b00, 0, 0b01, GPR32, "ldrb", i32, zextloadi8>; +defm LDRHH : Load16RO<0b01, 0, 0b01, GPR32, "ldrh", i32, zextloadi16>; +defm LDRW : Load32RO<0b10, 0, 0b01, GPR32, "ldr", i32, load>; +defm LDRX : Load64RO<0b11, 0, 0b01, GPR64, "ldr", i64, load>; // Floating-point -def LDRBro : Load8RO<0b00, 1, 0b01, FPR8, "ldr", - [(set FPR8:$Rt, (load ro_indexed8:$addr))]>; -def LDRHro : Load16RO<0b01, 1, 0b01, FPR16, "ldr", - [(set (f16 FPR16:$Rt), (load ro_indexed16:$addr))]>; -def LDRSro : Load32RO<0b10, 1, 0b01, FPR32, "ldr", - [(set (f32 FPR32:$Rt), (load ro_indexed32:$addr))]>; -def LDRDro : Load64RO<0b11, 1, 0b01, FPR64, "ldr", - [(set (f64 FPR64:$Rt), (load ro_indexed64:$addr))]>; -def LDRQro : Load128RO<0b00, 1, 0b11, FPR128, "ldr", []> { - let mayLoad = 1; -} +defm LDRB : Load8RO<0b00, 1, 0b01, FPR8, "ldr", untyped, load>; +defm LDRH : Load16RO<0b01, 1, 0b01, FPR16, "ldr", f16, load>; +defm LDRS : Load32RO<0b10, 1, 0b01, FPR32, "ldr", f32, load>; +defm LDRD : Load64RO<0b11, 1, 0b01, FPR64, "ldr", f64, load>; +defm LDRQ : Load128RO<0b00, 1, 0b11, FPR128, "ldr", f128, load>; + +// Load sign-extended half-word +defm LDRSHW : Load16RO<0b01, 0, 0b11, GPR32, "ldrsh", i32, sextloadi16>; +defm LDRSHX : Load16RO<0b01, 0, 0b10, GPR64, "ldrsh", i64, sextloadi16>; + +// Load sign-extended byte +defm LDRSBW : Load8RO<0b00, 0, 0b11, GPR32, "ldrsb", i32, sextloadi8>; +defm LDRSBX : Load8RO<0b00, 0, 0b10, GPR64, "ldrsb", i64, sextloadi8>; + +// Load sign-extended word +defm LDRSW : Load32RO<0b10, 0, 0b10, GPR64, "ldrsw", i64, sextloadi32>; + +// Pre-fetch. +defm PRFM : PrefetchRO<0b11, 0, 0b10, "prfm">; // For regular load, we do not have any alignment requirement. // Thus, it is safe to directly map the vector loads with interesting // addressing modes. // FIXME: We could do the same for bitconvert to floating point vectors. -def : Pat <(v8i8 (scalar_to_vector (i32 (extloadi8 ro_indexed8:$addr)))), - (INSERT_SUBREG (v8i8 (IMPLICIT_DEF)), - (LDRBro ro_indexed8:$addr), bsub)>; -def : Pat <(v16i8 (scalar_to_vector (i32 (extloadi8 ro_indexed8:$addr)))), - (INSERT_SUBREG (v16i8 (IMPLICIT_DEF)), - (LDRBro ro_indexed8:$addr), bsub)>; -def : Pat <(v4i16 (scalar_to_vector (i32 (extloadi16 ro_indexed16:$addr)))), - (INSERT_SUBREG (v4i16 (IMPLICIT_DEF)), - (LDRHro ro_indexed16:$addr), hsub)>; -def : Pat <(v8i16 (scalar_to_vector (i32 (extloadi16 ro_indexed16:$addr)))), - (INSERT_SUBREG (v8i16 (IMPLICIT_DEF)), - (LDRHro ro_indexed16:$addr), hsub)>; -def : Pat <(v2i32 (scalar_to_vector (i32 (load ro_indexed32:$addr)))), - (INSERT_SUBREG (v2i32 (IMPLICIT_DEF)), - (LDRSro ro_indexed32:$addr), ssub)>; -def : Pat <(v4i32 (scalar_to_vector (i32 (load ro_indexed32:$addr)))), - (INSERT_SUBREG (v4i32 (IMPLICIT_DEF)), - (LDRSro ro_indexed32:$addr), ssub)>; -def : Pat <(v1i64 (scalar_to_vector (i64 (load ro_indexed64:$addr)))), - (LDRDro ro_indexed64:$addr)>; -def : Pat <(v2i64 (scalar_to_vector (i64 (load ro_indexed64:$addr)))), - (INSERT_SUBREG (v2i64 (IMPLICIT_DEF)), - (LDRDro ro_indexed64:$addr), dsub)>; +multiclass ScalToVecROLoadPat { + def : Pat<(VecTy (scalar_to_vector (ScalTy + (loadop (ro.Wpat GPR64sp:$Rn, GPR32:$Rm, ro.Wext:$offset))))), + (INSERT_SUBREG (VecTy (IMPLICIT_DEF)), + (LOADW GPR64sp:$Rn, GPR32:$Rm, ro.Wext:$offset), + sub)>; + + def : Pat<(VecTy (scalar_to_vector (ScalTy + (loadop (ro.Xpat GPR64sp:$Rn, GPR64:$Rm, ro.Xext:$offset))))), + (INSERT_SUBREG (VecTy (IMPLICIT_DEF)), + (LOADX GPR64sp:$Rn, GPR64:$Rm, ro.Xext:$offset), + sub)>; +} + +let AddedComplexity = 10 in { +defm : ScalToVecROLoadPat; +defm : ScalToVecROLoadPat; + +defm : ScalToVecROLoadPat; +defm : ScalToVecROLoadPat; + +defm : ScalToVecROLoadPat; +defm : ScalToVecROLoadPat; + +defm : ScalToVecROLoadPat; +defm : ScalToVecROLoadPat; + +defm : ScalToVecROLoadPat; + +defm : ScalToVecROLoadPat; + + +def : Pat <(v1i64 (scalar_to_vector (i64 + (load (ro_Windexed64 GPR64sp:$Rn, GPR32:$Rm, + ro_Wextend64:$extend))))), + (LDRDroW GPR64sp:$Rn, GPR32:$Rm, ro_Wextend64:$extend)>; + +def : Pat <(v1i64 (scalar_to_vector (i64 + (load (ro_Xindexed64 GPR64sp:$Rn, GPR64:$Rm, + ro_Xextend64:$extend))))), + (LDRDroX GPR64sp:$Rn, GPR64:$Rm, ro_Xextend64:$extend)>; +} // Match all load 64 bits width whose type is compatible with FPR64 +multiclass VecROLoadPat { + + def : Pat<(VecTy (load (ro.Wpat GPR64sp:$Rn, GPR32:$Rm, ro.Wext:$extend))), + (LOADW GPR64sp:$Rn, GPR32:$Rm, ro.Wext:$extend)>; + + def : Pat<(VecTy (load (ro.Xpat GPR64sp:$Rn, GPR64:$Rm, ro.Xext:$extend))), + (LOADX GPR64sp:$Rn, GPR64:$Rm, ro.Xext:$extend)>; +} + +let AddedComplexity = 10 in { let Predicates = [IsLE] in { // We must do vector loads with LD1 in big-endian. - def : Pat<(v2f32 (load ro_indexed64:$addr)), (LDRDro ro_indexed64:$addr)>; - def : Pat<(v8i8 (load ro_indexed64:$addr)), (LDRDro ro_indexed64:$addr)>; - def : Pat<(v4i16 (load ro_indexed64:$addr)), (LDRDro ro_indexed64:$addr)>; - def : Pat<(v2i32 (load ro_indexed64:$addr)), (LDRDro ro_indexed64:$addr)>; + defm : VecROLoadPat; + defm : VecROLoadPat; + defm : VecROLoadPat; + defm : VecROLoadPat; } -def : Pat<(v1f64 (load ro_indexed64:$addr)), (LDRDro ro_indexed64:$addr)>; -def : Pat<(v1i64 (load ro_indexed64:$addr)), (LDRDro ro_indexed64:$addr)>; + +defm : VecROLoadPat; +defm : VecROLoadPat; // Match all load 128 bits width whose type is compatible with FPR128 let Predicates = [IsLE] in { // We must do vector loads with LD1 in big-endian. - def : Pat<(v4f32 (load ro_indexed128:$addr)), (LDRQro ro_indexed128:$addr)>; - def : Pat<(v2f64 (load ro_indexed128:$addr)), (LDRQro ro_indexed128:$addr)>; - def : Pat<(v16i8 (load ro_indexed128:$addr)), (LDRQro ro_indexed128:$addr)>; - def : Pat<(v8i16 (load ro_indexed128:$addr)), (LDRQro ro_indexed128:$addr)>; - def : Pat<(v4i32 (load ro_indexed128:$addr)), (LDRQro ro_indexed128:$addr)>; - def : Pat<(v2i64 (load ro_indexed128:$addr)), (LDRQro ro_indexed128:$addr)>; + defm : VecROLoadPat; + defm : VecROLoadPat; + defm : VecROLoadPat; + defm : VecROLoadPat; + defm : VecROLoadPat; + defm : VecROLoadPat; } -def : Pat<(f128 (load ro_indexed128:$addr)), (LDRQro ro_indexed128:$addr)>; - -// Load sign-extended half-word -def LDRSHWro : Load16RO<0b01, 0, 0b11, GPR32, "ldrsh", - [(set GPR32:$Rt, (sextloadi16 ro_indexed16:$addr))]>; -def LDRSHXro : Load16RO<0b01, 0, 0b10, GPR64, "ldrsh", - [(set GPR64:$Rt, (sextloadi16 ro_indexed16:$addr))]>; - -// Load sign-extended byte -def LDRSBWro : Load8RO<0b00, 0, 0b11, GPR32, "ldrsb", - [(set GPR32:$Rt, (sextloadi8 ro_indexed8:$addr))]>; -def LDRSBXro : Load8RO<0b00, 0, 0b10, GPR64, "ldrsb", - [(set GPR64:$Rt, (sextloadi8 ro_indexed8:$addr))]>; - -// Load sign-extended word -def LDRSWro : Load32RO<0b10, 0, 0b10, GPR64, "ldrsw", - [(set GPR64:$Rt, (sextloadi32 ro_indexed32:$addr))]>; - -// Pre-fetch. -def PRFMro : PrefetchRO<0b11, 0, 0b10, "prfm", - [(ARM64Prefetch imm:$Rt, ro_indexed64:$addr)]>; +} // AddedComplexity = 10 // zextload -> i64 -def : Pat<(i64 (zextloadi8 ro_indexed8:$addr)), - (SUBREG_TO_REG (i64 0), (LDRBBro ro_indexed8:$addr), sub_32)>; -def : Pat<(i64 (zextloadi16 ro_indexed16:$addr)), - (SUBREG_TO_REG (i64 0), (LDRHHro ro_indexed16:$addr), sub_32)>; -def : Pat<(i64 (zextloadi32 ro_indexed32:$addr)), - (SUBREG_TO_REG (i64 0), (LDRWro ro_indexed32:$addr), sub_32)>; +multiclass ExtLoadTo64ROPat { + def : Pat<(i64 (loadop (ro.Wpat GPR64sp:$Rn, GPR32:$Rm, ro.Wext:$extend))), + (SUBREG_TO_REG (i64 0), + (INSTW GPR64sp:$Rn, GPR32:$Rm, ro.Wext:$extend), + sub_32)>; -// zextloadi1 -> zextloadi8 -def : Pat<(i32 (zextloadi1 ro_indexed8:$addr)), (LDRBBro ro_indexed8:$addr)>; -def : Pat<(i64 (zextloadi1 ro_indexed8:$addr)), - (SUBREG_TO_REG (i64 0), (LDRBBro ro_indexed8:$addr), sub_32)>; + def : Pat<(i64 (loadop (ro.Xpat GPR64sp:$Rn, GPR64:$Rm, ro.Xext:$extend))), + (SUBREG_TO_REG (i64 0), + (INSTX GPR64sp:$Rn, GPR64:$Rm, ro.Xext:$extend), + sub_32)>; +} -// extload -> zextload -def : Pat<(i32 (extloadi16 ro_indexed16:$addr)), (LDRHHro ro_indexed16:$addr)>; -def : Pat<(i32 (extloadi8 ro_indexed8:$addr)), (LDRBBro ro_indexed8:$addr)>; -def : Pat<(i32 (extloadi1 ro_indexed8:$addr)), (LDRBBro ro_indexed8:$addr)>; -def : Pat<(i64 (extloadi32 ro_indexed32:$addr)), - (SUBREG_TO_REG (i64 0), (LDRWro ro_indexed32:$addr), sub_32)>; -def : Pat<(i64 (extloadi16 ro_indexed16:$addr)), - (SUBREG_TO_REG (i64 0), (LDRHHro ro_indexed16:$addr), sub_32)>; -def : Pat<(i64 (extloadi8 ro_indexed8:$addr)), - (SUBREG_TO_REG (i64 0), (LDRBBro ro_indexed8:$addr), sub_32)>; -def : Pat<(i64 (extloadi1 ro_indexed8:$addr)), - (SUBREG_TO_REG (i64 0), (LDRBBro ro_indexed8:$addr), sub_32)>; +let AddedComplexity = 10 in { + defm : ExtLoadTo64ROPat; + defm : ExtLoadTo64ROPat; + defm : ExtLoadTo64ROPat; -} // AddedComplexity = 10 + // zextloadi1 -> zextloadi8 + defm : ExtLoadTo64ROPat; + + // extload -> zextload + defm : ExtLoadTo64ROPat; + defm : ExtLoadTo64ROPat; + defm : ExtLoadTo64ROPat; + + // extloadi1 -> zextloadi8 + defm : ExtLoadTo64ROPat; +} + + +// zextload -> i64 +multiclass ExtLoadTo32ROPat { + def : Pat<(i32 (loadop (ro.Wpat GPR64sp:$Rn, GPR32:$Rm, ro.Wext:$extend))), + (INSTW GPR64sp:$Rn, GPR32:$Rm, ro.Wext:$extend)>; + + def : Pat<(i32 (loadop (ro.Xpat GPR64sp:$Rn, GPR64:$Rm, ro.Xext:$extend))), + (INSTX GPR64sp:$Rn, GPR64:$Rm, ro.Xext:$extend)>; + +} + +let AddedComplexity = 10 in { + // extload -> zextload + defm : ExtLoadTo32ROPat; + defm : ExtLoadTo32ROPat; + defm : ExtLoadTo32ROPat; + + // zextloadi1 -> zextloadi8 + defm : ExtLoadTo32ROPat; +} //--- // (unsigned immediate) //--- -def LDRXui : LoadUI<0b11, 0, 0b01, GPR64, am_indexed64, "ldr", - [(set GPR64:$Rt, (load am_indexed64:$addr))]>; -def LDRWui : LoadUI<0b10, 0, 0b01, GPR32, am_indexed32, "ldr", - [(set GPR32:$Rt, (load am_indexed32:$addr))]>; -def LDRBui : LoadUI<0b00, 1, 0b01, FPR8, am_indexed8, "ldr", - [(set FPR8:$Rt, (load am_indexed8:$addr))]>; -def LDRHui : LoadUI<0b01, 1, 0b01, FPR16, am_indexed16, "ldr", - [(set (f16 FPR16:$Rt), (load am_indexed16:$addr))]>; -def LDRSui : LoadUI<0b10, 1, 0b01, FPR32, am_indexed32, "ldr", - [(set (f32 FPR32:$Rt), (load am_indexed32:$addr))]>; -def LDRDui : LoadUI<0b11, 1, 0b01, FPR64, am_indexed64, "ldr", - [(set (f64 FPR64:$Rt), (load am_indexed64:$addr))]>; -def LDRQui : LoadUI<0b00, 1, 0b11, FPR128, am_indexed128, "ldr", - [(set (f128 FPR128:$Rt), (load am_indexed128:$addr))]>; +defm LDRX : LoadUI<0b11, 0, 0b01, GPR64, uimm12s8, "ldr", + [(set GPR64:$Rt, + (load (am_indexed64 GPR64sp:$Rn, uimm12s8:$offset)))]>; +defm LDRW : LoadUI<0b10, 0, 0b01, GPR32, uimm12s4, "ldr", + [(set GPR32:$Rt, + (load (am_indexed32 GPR64sp:$Rn, uimm12s4:$offset)))]>; +defm LDRB : LoadUI<0b00, 1, 0b01, FPR8, uimm12s1, "ldr", + [(set FPR8:$Rt, + (load (am_indexed8 GPR64sp:$Rn, uimm12s1:$offset)))]>; +defm LDRH : LoadUI<0b01, 1, 0b01, FPR16, uimm12s2, "ldr", + [(set (f16 FPR16:$Rt), + (load (am_indexed16 GPR64sp:$Rn, uimm12s2:$offset)))]>; +defm LDRS : LoadUI<0b10, 1, 0b01, FPR32, uimm12s4, "ldr", + [(set (f32 FPR32:$Rt), + (load (am_indexed32 GPR64sp:$Rn, uimm12s4:$offset)))]>; +defm LDRD : LoadUI<0b11, 1, 0b01, FPR64, uimm12s8, "ldr", + [(set (f64 FPR64:$Rt), + (load (am_indexed64 GPR64sp:$Rn, uimm12s8:$offset)))]>; +defm LDRQ : LoadUI<0b00, 1, 0b11, FPR128, uimm12s16, "ldr", + [(set (f128 FPR128:$Rt), + (load (am_indexed128 GPR64sp:$Rn, uimm12s16:$offset)))]>; // For regular load, we do not have any alignment requirement. // Thus, it is safe to directly map the vector loads with interesting // addressing modes. // FIXME: We could do the same for bitconvert to floating point vectors. -def : Pat <(v8i8 (scalar_to_vector (i32 (extloadi8 am_indexed8:$addr)))), +def : Pat <(v8i8 (scalar_to_vector (i32 + (extloadi8 (am_indexed8 GPR64sp:$Rn, uimm12s1:$offset))))), (INSERT_SUBREG (v8i8 (IMPLICIT_DEF)), - (LDRBui am_indexed8:$addr), bsub)>; -def : Pat <(v16i8 (scalar_to_vector (i32 (extloadi8 am_indexed8:$addr)))), + (LDRBui GPR64sp:$Rn, uimm12s1:$offset), bsub)>; +def : Pat <(v16i8 (scalar_to_vector (i32 + (extloadi8 (am_indexed8 GPR64sp:$Rn, uimm12s1:$offset))))), (INSERT_SUBREG (v16i8 (IMPLICIT_DEF)), - (LDRBui am_indexed8:$addr), bsub)>; -def : Pat <(v4i16 (scalar_to_vector (i32 (extloadi16 am_indexed16:$addr)))), + (LDRBui GPR64sp:$Rn, uimm12s1:$offset), bsub)>; +def : Pat <(v4i16 (scalar_to_vector (i32 + (extloadi16 (am_indexed16 GPR64sp:$Rn, uimm12s2:$offset))))), (INSERT_SUBREG (v4i16 (IMPLICIT_DEF)), - (LDRHui am_indexed16:$addr), hsub)>; -def : Pat <(v8i16 (scalar_to_vector (i32 (extloadi16 am_indexed16:$addr)))), + (LDRHui GPR64sp:$Rn, uimm12s2:$offset), hsub)>; +def : Pat <(v8i16 (scalar_to_vector (i32 + (extloadi16 (am_indexed16 GPR64sp:$Rn, uimm12s2:$offset))))), (INSERT_SUBREG (v8i16 (IMPLICIT_DEF)), - (LDRHui am_indexed16:$addr), hsub)>; -def : Pat <(v2i32 (scalar_to_vector (i32 (load am_indexed32:$addr)))), + (LDRHui GPR64sp:$Rn, uimm12s2:$offset), hsub)>; +def : Pat <(v2i32 (scalar_to_vector (i32 + (load (am_indexed32 GPR64sp:$Rn, uimm12s4:$offset))))), (INSERT_SUBREG (v2i32 (IMPLICIT_DEF)), - (LDRSui am_indexed32:$addr), ssub)>; -def : Pat <(v4i32 (scalar_to_vector (i32 (load am_indexed32:$addr)))), + (LDRSui GPR64sp:$Rn, uimm12s4:$offset), ssub)>; +def : Pat <(v4i32 (scalar_to_vector (i32 + (load (am_indexed32 GPR64sp:$Rn, uimm12s4:$offset))))), (INSERT_SUBREG (v4i32 (IMPLICIT_DEF)), - (LDRSui am_indexed32:$addr), ssub)>; -def : Pat <(v1i64 (scalar_to_vector (i64 (load am_indexed64:$addr)))), - (LDRDui am_indexed64:$addr)>; -def : Pat <(v2i64 (scalar_to_vector (i64 (load am_indexed64:$addr)))), + (LDRSui GPR64sp:$Rn, uimm12s4:$offset), ssub)>; +def : Pat <(v1i64 (scalar_to_vector (i64 + (load (am_indexed64 GPR64sp:$Rn, uimm12s8:$offset))))), + (LDRDui GPR64sp:$Rn, uimm12s8:$offset)>; +def : Pat <(v2i64 (scalar_to_vector (i64 + (load (am_indexed64 GPR64sp:$Rn, uimm12s8:$offset))))), (INSERT_SUBREG (v2i64 (IMPLICIT_DEF)), - (LDRDui am_indexed64:$addr), dsub)>; + (LDRDui GPR64sp:$Rn, uimm12s8:$offset), dsub)>; // Match all load 64 bits width whose type is compatible with FPR64 let Predicates = [IsLE] in { // We must use LD1 to perform vector loads in big-endian. - def : Pat<(v2f32 (load am_indexed64:$addr)), (LDRDui am_indexed64:$addr)>; - def : Pat<(v8i8 (load am_indexed64:$addr)), (LDRDui am_indexed64:$addr)>; - def : Pat<(v4i16 (load am_indexed64:$addr)), (LDRDui am_indexed64:$addr)>; - def : Pat<(v2i32 (load am_indexed64:$addr)), (LDRDui am_indexed64:$addr)>; + def : Pat<(v2f32 (load (am_indexed64 GPR64sp:$Rn, uimm12s8:$offset))), + (LDRDui GPR64sp:$Rn, uimm12s8:$offset)>; + def : Pat<(v8i8 (load (am_indexed64 GPR64sp:$Rn, uimm12s8:$offset))), + (LDRDui GPR64sp:$Rn, uimm12s8:$offset)>; + def : Pat<(v4i16 (load (am_indexed64 GPR64sp:$Rn, uimm12s8:$offset))), + (LDRDui GPR64sp:$Rn, uimm12s8:$offset)>; + def : Pat<(v2i32 (load (am_indexed64 GPR64sp:$Rn, uimm12s8:$offset))), + (LDRDui GPR64sp:$Rn, uimm12s8:$offset)>; } -def : Pat<(v1f64 (load am_indexed64:$addr)), (LDRDui am_indexed64:$addr)>; -def : Pat<(v1i64 (load am_indexed64:$addr)), (LDRDui am_indexed64:$addr)>; +def : Pat<(v1f64 (load (am_indexed64 GPR64sp:$Rn, uimm12s8:$offset))), + (LDRDui GPR64sp:$Rn, uimm12s8:$offset)>; +def : Pat<(v1i64 (load (am_indexed64 GPR64sp:$Rn, uimm12s8:$offset))), + (LDRDui GPR64sp:$Rn, uimm12s8:$offset)>; // Match all load 128 bits width whose type is compatible with FPR128 let Predicates = [IsLE] in { // We must use LD1 to perform vector loads in big-endian. - def : Pat<(v4f32 (load am_indexed128:$addr)), (LDRQui am_indexed128:$addr)>; - def : Pat<(v2f64 (load am_indexed128:$addr)), (LDRQui am_indexed128:$addr)>; - def : Pat<(v16i8 (load am_indexed128:$addr)), (LDRQui am_indexed128:$addr)>; - def : Pat<(v8i16 (load am_indexed128:$addr)), (LDRQui am_indexed128:$addr)>; - def : Pat<(v4i32 (load am_indexed128:$addr)), (LDRQui am_indexed128:$addr)>; - def : Pat<(v2i64 (load am_indexed128:$addr)), (LDRQui am_indexed128:$addr)>; + def : Pat<(v4f32 (load (am_indexed128 GPR64sp:$Rn, uimm12s16:$offset))), + (LDRQui GPR64sp:$Rn, uimm12s16:$offset)>; + def : Pat<(v2f64 (load (am_indexed128 GPR64sp:$Rn, uimm12s16:$offset))), + (LDRQui GPR64sp:$Rn, uimm12s16:$offset)>; + def : Pat<(v16i8 (load (am_indexed128 GPR64sp:$Rn, uimm12s16:$offset))), + (LDRQui GPR64sp:$Rn, uimm12s16:$offset)>; + def : Pat<(v8i16 (load (am_indexed128 GPR64sp:$Rn, uimm12s16:$offset))), + (LDRQui GPR64sp:$Rn, uimm12s16:$offset)>; + def : Pat<(v4i32 (load (am_indexed128 GPR64sp:$Rn, uimm12s16:$offset))), + (LDRQui GPR64sp:$Rn, uimm12s16:$offset)>; + def : Pat<(v2i64 (load (am_indexed128 GPR64sp:$Rn, uimm12s16:$offset))), + (LDRQui GPR64sp:$Rn, uimm12s16:$offset)>; } -def : Pat<(f128 (load am_indexed128:$addr)), (LDRQui am_indexed128:$addr)>; +def : Pat<(f128 (load (am_indexed128 GPR64sp:$Rn, uimm12s16:$offset))), + (LDRQui GPR64sp:$Rn, uimm12s16:$offset)>; -def LDRHHui : LoadUI<0b01, 0, 0b01, GPR32, am_indexed16, "ldrh", - [(set GPR32:$Rt, (zextloadi16 am_indexed16:$addr))]>; -def LDRBBui : LoadUI<0b00, 0, 0b01, GPR32, am_indexed8, "ldrb", - [(set GPR32:$Rt, (zextloadi8 am_indexed8:$addr))]>; +defm LDRHH : LoadUI<0b01, 0, 0b01, GPR32, uimm12s2, "ldrh", + [(set GPR32:$Rt, + (zextloadi16 (am_indexed16 GPR64sp:$Rn, + uimm12s2:$offset)))]>; +defm LDRBB : LoadUI<0b00, 0, 0b01, GPR32, uimm12s1, "ldrb", + [(set GPR32:$Rt, + (zextloadi8 (am_indexed8 GPR64sp:$Rn, + uimm12s1:$offset)))]>; // zextload -> i64 -def : Pat<(i64 (zextloadi8 am_indexed8:$addr)), - (SUBREG_TO_REG (i64 0), (LDRBBui am_indexed8:$addr), sub_32)>; -def : Pat<(i64 (zextloadi16 am_indexed16:$addr)), - (SUBREG_TO_REG (i64 0), (LDRHHui am_indexed16:$addr), sub_32)>; +def : Pat<(i64 (zextloadi8 (am_indexed8 GPR64sp:$Rn, uimm12s1:$offset))), + (SUBREG_TO_REG (i64 0), (LDRBBui GPR64sp:$Rn, uimm12s1:$offset), sub_32)>; +def : Pat<(i64 (zextloadi16 (am_indexed16 GPR64sp:$Rn, uimm12s2:$offset))), + (SUBREG_TO_REG (i64 0), (LDRHHui GPR64sp:$Rn, uimm12s2:$offset), sub_32)>; // zextloadi1 -> zextloadi8 -def : Pat<(i32 (zextloadi1 am_indexed8:$addr)), (LDRBBui am_indexed8:$addr)>; -def : Pat<(i64 (zextloadi1 am_indexed8:$addr)), - (SUBREG_TO_REG (i64 0), (LDRBBui am_indexed8:$addr), sub_32)>; +def : Pat<(i32 (zextloadi1 (am_indexed8 GPR64sp:$Rn, uimm12s1:$offset))), + (LDRBBui GPR64sp:$Rn, uimm12s1:$offset)>; +def : Pat<(i64 (zextloadi1 (am_indexed8 GPR64sp:$Rn, uimm12s1:$offset))), + (SUBREG_TO_REG (i64 0), (LDRBBui GPR64sp:$Rn, uimm12s1:$offset), sub_32)>; // extload -> zextload -def : Pat<(i32 (extloadi16 am_indexed16:$addr)), (LDRHHui am_indexed16:$addr)>; -def : Pat<(i32 (extloadi8 am_indexed8:$addr)), (LDRBBui am_indexed8:$addr)>; -def : Pat<(i32 (extloadi1 am_indexed8:$addr)), (LDRBBui am_indexed8:$addr)>; -def : Pat<(i64 (extloadi32 am_indexed32:$addr)), - (SUBREG_TO_REG (i64 0), (LDRWui am_indexed32:$addr), sub_32)>; -def : Pat<(i64 (extloadi16 am_indexed16:$addr)), - (SUBREG_TO_REG (i64 0), (LDRHHui am_indexed16:$addr), sub_32)>; -def : Pat<(i64 (extloadi8 am_indexed8:$addr)), - (SUBREG_TO_REG (i64 0), (LDRBBui am_indexed8:$addr), sub_32)>; -def : Pat<(i64 (extloadi1 am_indexed8:$addr)), - (SUBREG_TO_REG (i64 0), (LDRBBui am_indexed8:$addr), sub_32)>; +def : Pat<(i32 (extloadi16 (am_indexed16 GPR64sp:$Rn, uimm12s2:$offset))), + (LDRHHui GPR64sp:$Rn, uimm12s2:$offset)>; +def : Pat<(i32 (extloadi8 (am_indexed8 GPR64sp:$Rn, uimm12s1:$offset))), + (LDRBBui GPR64sp:$Rn, uimm12s1:$offset)>; +def : Pat<(i32 (extloadi1 (am_indexed8 GPR64sp:$Rn, uimm12s1:$offset))), + (LDRBBui GPR64sp:$Rn, uimm12s1:$offset)>; +def : Pat<(i64 (extloadi32 (am_indexed32 GPR64sp:$Rn, uimm12s4:$offset))), + (SUBREG_TO_REG (i64 0), (LDRWui GPR64sp:$Rn, uimm12s4:$offset), sub_32)>; +def : Pat<(i64 (extloadi16 (am_indexed16 GPR64sp:$Rn, uimm12s2:$offset))), + (SUBREG_TO_REG (i64 0), (LDRHHui GPR64sp:$Rn, uimm12s2:$offset), sub_32)>; +def : Pat<(i64 (extloadi8 (am_indexed8 GPR64sp:$Rn, uimm12s1:$offset))), + (SUBREG_TO_REG (i64 0), (LDRBBui GPR64sp:$Rn, uimm12s1:$offset), sub_32)>; +def : Pat<(i64 (extloadi1 (am_indexed8 GPR64sp:$Rn, uimm12s1:$offset))), + (SUBREG_TO_REG (i64 0), (LDRBBui GPR64sp:$Rn, uimm12s1:$offset), sub_32)>; // load sign-extended half-word -def LDRSHWui : LoadUI<0b01, 0, 0b11, GPR32, am_indexed16, "ldrsh", - [(set GPR32:$Rt, (sextloadi16 am_indexed16:$addr))]>; -def LDRSHXui : LoadUI<0b01, 0, 0b10, GPR64, am_indexed16, "ldrsh", - [(set GPR64:$Rt, (sextloadi16 am_indexed16:$addr))]>; +defm LDRSHW : LoadUI<0b01, 0, 0b11, GPR32, uimm12s2, "ldrsh", + [(set GPR32:$Rt, + (sextloadi16 (am_indexed16 GPR64sp:$Rn, + uimm12s2:$offset)))]>; +defm LDRSHX : LoadUI<0b01, 0, 0b10, GPR64, uimm12s2, "ldrsh", + [(set GPR64:$Rt, + (sextloadi16 (am_indexed16 GPR64sp:$Rn, + uimm12s2:$offset)))]>; // load sign-extended byte -def LDRSBWui : LoadUI<0b00, 0, 0b11, GPR32, am_indexed8, "ldrsb", - [(set GPR32:$Rt, (sextloadi8 am_indexed8:$addr))]>; -def LDRSBXui : LoadUI<0b00, 0, 0b10, GPR64, am_indexed8, "ldrsb", - [(set GPR64:$Rt, (sextloadi8 am_indexed8:$addr))]>; +defm LDRSBW : LoadUI<0b00, 0, 0b11, GPR32, uimm12s1, "ldrsb", + [(set GPR32:$Rt, + (sextloadi8 (am_indexed8 GPR64sp:$Rn, + uimm12s1:$offset)))]>; +defm LDRSBX : LoadUI<0b00, 0, 0b10, GPR64, uimm12s1, "ldrsb", + [(set GPR64:$Rt, + (sextloadi8 (am_indexed8 GPR64sp:$Rn, + uimm12s1:$offset)))]>; // load sign-extended word -def LDRSWui : LoadUI<0b10, 0, 0b10, GPR64, am_indexed32, "ldrsw", - [(set GPR64:$Rt, (sextloadi32 am_indexed32:$addr))]>; +defm LDRSW : LoadUI<0b10, 0, 0b10, GPR64, uimm12s4, "ldrsw", + [(set GPR64:$Rt, + (sextloadi32 (am_indexed32 GPR64sp:$Rn, + uimm12s4:$offset)))]>; // load zero-extended word -def : Pat<(i64 (zextloadi32 am_indexed32:$addr)), - (SUBREG_TO_REG (i64 0), (LDRWui am_indexed32:$addr), sub_32)>; +def : Pat<(i64 (zextloadi32 (am_indexed32 GPR64sp:$Rn, uimm12s4:$offset))), + (SUBREG_TO_REG (i64 0), (LDRWui GPR64sp:$Rn, uimm12s4:$offset), sub_32)>; // Pre-fetch. def PRFMui : PrefetchUI<0b11, 0, 0b10, "prfm", - [(ARM64Prefetch imm:$Rt, am_indexed64:$addr)]>; + [(ARM64Prefetch imm:$Rt, + (am_indexed64 GPR64sp:$Rn, + uimm12s8:$offset))]>; + +def : InstAlias<"prfm $Rt, [$Rn]", (PRFMui prfop:$Rt, GPR64sp:$Rn, 0)>; //--- // (literal) @@ -1363,76 +1455,99 @@ def PRFMl : PrefetchLiteral<0b11, 0, "prfm", []>; //--- // (unscaled immediate) -def LDURXi : LoadUnscaled<0b11, 0, 0b01, GPR64, am_unscaled64, "ldur", - [(set GPR64:$Rt, (load am_unscaled64:$addr))]>; -def LDURWi : LoadUnscaled<0b10, 0, 0b01, GPR32, am_unscaled32, "ldur", - [(set GPR32:$Rt, (load am_unscaled32:$addr))]>; -def LDURBi : LoadUnscaled<0b00, 1, 0b01, FPR8, am_unscaled8, "ldur", - [(set FPR8:$Rt, (load am_unscaled8:$addr))]>; -def LDURHi : LoadUnscaled<0b01, 1, 0b01, FPR16, am_unscaled16, "ldur", - [(set (f16 FPR16:$Rt), (load am_unscaled16:$addr))]>; -def LDURSi : LoadUnscaled<0b10, 1, 0b01, FPR32, am_unscaled32, "ldur", - [(set (f32 FPR32:$Rt), (load am_unscaled32:$addr))]>; -def LDURDi : LoadUnscaled<0b11, 1, 0b01, FPR64, am_unscaled64, "ldur", - [(set (f64 FPR64:$Rt), (load am_unscaled64:$addr))]>; -def LDURQi : LoadUnscaled<0b00, 1, 0b11, FPR128, am_unscaled128, "ldur", - [(set (f128 FPR128:$Rt), (load am_unscaled128:$addr))]>; +defm LDURX : LoadUnscaled<0b11, 0, 0b01, GPR64, "ldur", + [(set GPR64:$Rt, + (load (am_unscaled64 GPR64sp:$Rn, simm9:$offset)))]>; +defm LDURW : LoadUnscaled<0b10, 0, 0b01, GPR32, "ldur", + [(set GPR32:$Rt, + (load (am_unscaled32 GPR64sp:$Rn, simm9:$offset)))]>; +defm LDURB : LoadUnscaled<0b00, 1, 0b01, FPR8, "ldur", + [(set FPR8:$Rt, + (load (am_unscaled8 GPR64sp:$Rn, simm9:$offset)))]>; +defm LDURH : LoadUnscaled<0b01, 1, 0b01, FPR16, "ldur", + [(set FPR16:$Rt, + (load (am_unscaled16 GPR64sp:$Rn, simm9:$offset)))]>; +defm LDURS : LoadUnscaled<0b10, 1, 0b01, FPR32, "ldur", + [(set (f32 FPR32:$Rt), + (load (am_unscaled32 GPR64sp:$Rn, simm9:$offset)))]>; +defm LDURD : LoadUnscaled<0b11, 1, 0b01, FPR64, "ldur", + [(set (f64 FPR64:$Rt), + (load (am_unscaled64 GPR64sp:$Rn, simm9:$offset)))]>; +defm LDURQ : LoadUnscaled<0b00, 1, 0b11, FPR128, "ldur", + [(set (f128 FPR128:$Rt), + (load (am_unscaled128 GPR64sp:$Rn, simm9:$offset)))]>; -def LDURHHi - : LoadUnscaled<0b01, 0, 0b01, GPR32, am_unscaled16, "ldurh", - [(set GPR32:$Rt, (zextloadi16 am_unscaled16:$addr))]>; -def LDURBBi - : LoadUnscaled<0b00, 0, 0b01, GPR32, am_unscaled8, "ldurb", - [(set GPR32:$Rt, (zextloadi8 am_unscaled8:$addr))]>; +defm LDURHH + : LoadUnscaled<0b01, 0, 0b01, GPR32, "ldurh", + [(set GPR32:$Rt, + (zextloadi16 (am_unscaled16 GPR64sp:$Rn, simm9:$offset)))]>; +defm LDURBB + : LoadUnscaled<0b00, 0, 0b01, GPR32, "ldurb", + [(set GPR32:$Rt, + (zextloadi8 (am_unscaled16 GPR64sp:$Rn, simm9:$offset)))]>; // Match all load 64 bits width whose type is compatible with FPR64 let Predicates = [IsLE] in { - def : Pat<(v2f32 (load am_unscaled64:$addr)), (LDURDi am_unscaled64:$addr)>; - def : Pat<(v8i8 (load am_unscaled64:$addr)), (LDURDi am_unscaled64:$addr)>; - def : Pat<(v4i16 (load am_unscaled64:$addr)), (LDURDi am_unscaled64:$addr)>; - def : Pat<(v2i32 (load am_unscaled64:$addr)), (LDURDi am_unscaled64:$addr)>; + def : Pat<(v2f32 (load (am_unscaled64 GPR64sp:$Rn, simm9:$offset))), + (LDURDi GPR64sp:$Rn, simm9:$offset)>; + def : Pat<(v2i32 (load (am_unscaled64 GPR64sp:$Rn, simm9:$offset))), + (LDURDi GPR64sp:$Rn, simm9:$offset)>; + def : Pat<(v4i16 (load (am_unscaled64 GPR64sp:$Rn, simm9:$offset))), + (LDURDi GPR64sp:$Rn, simm9:$offset)>; + def : Pat<(v8i8 (load (am_unscaled64 GPR64sp:$Rn, simm9:$offset))), + (LDURDi GPR64sp:$Rn, simm9:$offset)>; } -def : Pat<(v1f64 (load am_unscaled64:$addr)), (LDURDi am_unscaled64:$addr)>; -def : Pat<(v1i64 (load am_unscaled64:$addr)), (LDURDi am_unscaled64:$addr)>; +def : Pat<(v1f64 (load (am_unscaled64 GPR64sp:$Rn, simm9:$offset))), + (LDURDi GPR64sp:$Rn, simm9:$offset)>; +def : Pat<(v1i64 (load (am_unscaled64 GPR64sp:$Rn, simm9:$offset))), + (LDURDi GPR64sp:$Rn, simm9:$offset)>; // Match all load 128 bits width whose type is compatible with FPR128 let Predicates = [IsLE] in { - def : Pat<(v4f32 (load am_unscaled128:$addr)), (LDURQi am_unscaled128:$addr)>; - def : Pat<(v2f64 (load am_unscaled128:$addr)), (LDURQi am_unscaled128:$addr)>; - def : Pat<(v16i8 (load am_unscaled128:$addr)), (LDURQi am_unscaled128:$addr)>; - def : Pat<(v8i16 (load am_unscaled128:$addr)), (LDURQi am_unscaled128:$addr)>; - def : Pat<(v4i32 (load am_unscaled128:$addr)), (LDURQi am_unscaled128:$addr)>; - def : Pat<(v2i64 (load am_unscaled128:$addr)), (LDURQi am_unscaled128:$addr)>; - def : Pat<(v2f64 (load am_unscaled128:$addr)), (LDURQi am_unscaled128:$addr)>; + def : Pat<(v2f64 (load (am_unscaled128 GPR64sp:$Rn, simm9:$offset))), + (LDURQi GPR64sp:$Rn, simm9:$offset)>; + def : Pat<(v2i64 (load (am_unscaled128 GPR64sp:$Rn, simm9:$offset))), + (LDURQi GPR64sp:$Rn, simm9:$offset)>; + def : Pat<(v4f32 (load (am_unscaled128 GPR64sp:$Rn, simm9:$offset))), + (LDURQi GPR64sp:$Rn, simm9:$offset)>; + def : Pat<(v4i32 (load (am_unscaled128 GPR64sp:$Rn, simm9:$offset))), + (LDURQi GPR64sp:$Rn, simm9:$offset)>; + def : Pat<(v8i16 (load (am_unscaled128 GPR64sp:$Rn, simm9:$offset))), + (LDURQi GPR64sp:$Rn, simm9:$offset)>; + def : Pat<(v16i8 (load (am_unscaled128 GPR64sp:$Rn, simm9:$offset))), + (LDURQi GPR64sp:$Rn, simm9:$offset)>; } // anyext -> zext -def : Pat<(i32 (extloadi16 am_unscaled16:$addr)), (LDURHHi am_unscaled16:$addr)>; -def : Pat<(i32 (extloadi8 am_unscaled8:$addr)), (LDURBBi am_unscaled8:$addr)>; -def : Pat<(i32 (extloadi1 am_unscaled8:$addr)), (LDURBBi am_unscaled8:$addr)>; -def : Pat<(i64 (extloadi32 am_unscaled32:$addr)), - (SUBREG_TO_REG (i64 0), (LDURWi am_unscaled32:$addr), sub_32)>; -def : Pat<(i64 (extloadi16 am_unscaled16:$addr)), - (SUBREG_TO_REG (i64 0), (LDURHHi am_unscaled16:$addr), sub_32)>; -def : Pat<(i64 (extloadi8 am_unscaled8:$addr)), - (SUBREG_TO_REG (i64 0), (LDURBBi am_unscaled8:$addr), sub_32)>; -def : Pat<(i64 (extloadi1 am_unscaled8:$addr)), - (SUBREG_TO_REG (i64 0), (LDURBBi am_unscaled8:$addr), sub_32)>; +def : Pat<(i32 (extloadi16 (am_unscaled16 GPR64sp:$Rn, simm9:$offset))), + (LDURHHi GPR64sp:$Rn, simm9:$offset)>; +def : Pat<(i32 (extloadi8 (am_unscaled8 GPR64sp:$Rn, simm9:$offset))), + (LDURBBi GPR64sp:$Rn, simm9:$offset)>; +def : Pat<(i32 (extloadi1 (am_unscaled8 GPR64sp:$Rn, simm9:$offset))), + (LDURBBi GPR64sp:$Rn, simm9:$offset)>; +def : Pat<(i64 (extloadi32 (am_unscaled32 GPR64sp:$Rn, simm9:$offset))), + (SUBREG_TO_REG (i64 0), (LDURWi GPR64sp:$Rn, simm9:$offset), sub_32)>; +def : Pat<(i64 (extloadi16 (am_unscaled16 GPR64sp:$Rn, simm9:$offset))), + (SUBREG_TO_REG (i64 0), (LDURHHi GPR64sp:$Rn, simm9:$offset), sub_32)>; +def : Pat<(i64 (extloadi8 (am_unscaled8 GPR64sp:$Rn, simm9:$offset))), + (SUBREG_TO_REG (i64 0), (LDURBBi GPR64sp:$Rn, simm9:$offset), sub_32)>; +def : Pat<(i64 (extloadi1 (am_unscaled8 GPR64sp:$Rn, simm9:$offset))), + (SUBREG_TO_REG (i64 0), (LDURBBi GPR64sp:$Rn, simm9:$offset), sub_32)>; // unscaled zext -def : Pat<(i32 (zextloadi16 am_unscaled16:$addr)), - (LDURHHi am_unscaled16:$addr)>; -def : Pat<(i32 (zextloadi8 am_unscaled8:$addr)), - (LDURBBi am_unscaled8:$addr)>; -def : Pat<(i32 (zextloadi1 am_unscaled8:$addr)), - (LDURBBi am_unscaled8:$addr)>; -def : Pat<(i64 (zextloadi32 am_unscaled32:$addr)), - (SUBREG_TO_REG (i64 0), (LDURWi am_unscaled32:$addr), sub_32)>; -def : Pat<(i64 (zextloadi16 am_unscaled16:$addr)), - (SUBREG_TO_REG (i64 0), (LDURHHi am_unscaled16:$addr), sub_32)>; -def : Pat<(i64 (zextloadi8 am_unscaled8:$addr)), - (SUBREG_TO_REG (i64 0), (LDURBBi am_unscaled8:$addr), sub_32)>; -def : Pat<(i64 (zextloadi1 am_unscaled8:$addr)), - (SUBREG_TO_REG (i64 0), (LDURBBi am_unscaled8:$addr), sub_32)>; +def : Pat<(i32 (zextloadi16 (am_unscaled16 GPR64sp:$Rn, simm9:$offset))), + (LDURHHi GPR64sp:$Rn, simm9:$offset)>; +def : Pat<(i32 (zextloadi8 (am_unscaled8 GPR64sp:$Rn, simm9:$offset))), + (LDURBBi GPR64sp:$Rn, simm9:$offset)>; +def : Pat<(i32 (zextloadi1 (am_unscaled8 GPR64sp:$Rn, simm9:$offset))), + (LDURBBi GPR64sp:$Rn, simm9:$offset)>; +def : Pat<(i64 (zextloadi32 (am_unscaled32 GPR64sp:$Rn, simm9:$offset))), + (SUBREG_TO_REG (i64 0), (LDURWi GPR64sp:$Rn, simm9:$offset), sub_32)>; +def : Pat<(i64 (zextloadi16 (am_unscaled16 GPR64sp:$Rn, simm9:$offset))), + (SUBREG_TO_REG (i64 0), (LDURHHi GPR64sp:$Rn, simm9:$offset), sub_32)>; +def : Pat<(i64 (zextloadi8 (am_unscaled8 GPR64sp:$Rn, simm9:$offset))), + (SUBREG_TO_REG (i64 0), (LDURBBi GPR64sp:$Rn, simm9:$offset), sub_32)>; +def : Pat<(i64 (zextloadi1 (am_unscaled8 GPR64sp:$Rn, simm9:$offset))), + (SUBREG_TO_REG (i64 0), (LDURBBi GPR64sp:$Rn, simm9:$offset), sub_32)>; //--- @@ -1442,119 +1557,122 @@ def : Pat<(i64 (zextloadi1 am_unscaled8:$addr)), // the don't otherwise match the scaled addressing mode for LDR/STR. Don't // associate a DiagnosticType either, as we want the diagnostic for the // canonical form (the scaled operand) to take precedence. -def MemoryUnscaledFB8Operand : AsmOperandClass { - let Name = "MemoryUnscaledFB8"; - let RenderMethod = "addMemoryUnscaledOperands"; +class SImm9OffsetOperand : AsmOperandClass { + let Name = "SImm9OffsetFB" # Width; + let PredicateMethod = "isSImm9OffsetFB<" # Width # ">"; + let RenderMethod = "addImmOperands"; } -def MemoryUnscaledFB16Operand : AsmOperandClass { - let Name = "MemoryUnscaledFB16"; - let RenderMethod = "addMemoryUnscaledOperands"; + +def SImm9OffsetFB8Operand : SImm9OffsetOperand<8>; +def SImm9OffsetFB16Operand : SImm9OffsetOperand<16>; +def SImm9OffsetFB32Operand : SImm9OffsetOperand<32>; +def SImm9OffsetFB64Operand : SImm9OffsetOperand<64>; +def SImm9OffsetFB128Operand : SImm9OffsetOperand<128>; + +def simm9_offset_fb8 : Operand { + let ParserMatchClass = SImm9OffsetFB8Operand; } -def MemoryUnscaledFB32Operand : AsmOperandClass { - let Name = "MemoryUnscaledFB32"; - let RenderMethod = "addMemoryUnscaledOperands"; +def simm9_offset_fb16 : Operand { + let ParserMatchClass = SImm9OffsetFB16Operand; } -def MemoryUnscaledFB64Operand : AsmOperandClass { - let Name = "MemoryUnscaledFB64"; - let RenderMethod = "addMemoryUnscaledOperands"; +def simm9_offset_fb32 : Operand { + let ParserMatchClass = SImm9OffsetFB32Operand; } -def MemoryUnscaledFB128Operand : AsmOperandClass { - let Name = "MemoryUnscaledFB128"; - let RenderMethod = "addMemoryUnscaledOperands"; +def simm9_offset_fb64 : Operand { + let ParserMatchClass = SImm9OffsetFB64Operand; } -def am_unscaled_fb8 : Operand { - let ParserMatchClass = MemoryUnscaledFB8Operand; - let MIOperandInfo = (ops GPR64sp:$base, i64imm:$offset); +def simm9_offset_fb128 : Operand { + let ParserMatchClass = SImm9OffsetFB128Operand; } -def am_unscaled_fb16 : Operand { - let ParserMatchClass = MemoryUnscaledFB16Operand; - let MIOperandInfo = (ops GPR64sp:$base, i64imm:$offset); -} -def am_unscaled_fb32 : Operand { - let ParserMatchClass = MemoryUnscaledFB32Operand; - let MIOperandInfo = (ops GPR64sp:$base, i64imm:$offset); -} -def am_unscaled_fb64 : Operand { - let ParserMatchClass = MemoryUnscaledFB64Operand; - let MIOperandInfo = (ops GPR64sp:$base, i64imm:$offset); -} -def am_unscaled_fb128 : Operand { - let ParserMatchClass = MemoryUnscaledFB128Operand; - let MIOperandInfo = (ops GPR64sp:$base, i64imm:$offset); -} -def : InstAlias<"ldr $Rt, $addr", (LDURXi GPR64:$Rt, am_unscaled_fb64:$addr), 0>; -def : InstAlias<"ldr $Rt, $addr", (LDURWi GPR32:$Rt, am_unscaled_fb32:$addr), 0>; -def : InstAlias<"ldr $Rt, $addr", (LDURBi FPR8:$Rt, am_unscaled_fb8:$addr), 0>; -def : InstAlias<"ldr $Rt, $addr", (LDURHi FPR16:$Rt, am_unscaled_fb16:$addr), 0>; -def : InstAlias<"ldr $Rt, $addr", (LDURSi FPR32:$Rt, am_unscaled_fb32:$addr), 0>; -def : InstAlias<"ldr $Rt, $addr", (LDURDi FPR64:$Rt, am_unscaled_fb64:$addr), 0>; -def : InstAlias<"ldr $Rt, $addr", (LDURQi FPR128:$Rt, am_unscaled_fb128:$addr), 0>; + +// FIXME: these don't work +def : InstAlias<"ldr $Rt, [$Rn, $offset]", + (LDURXi GPR64:$Rt, GPR64sp:$Rn, simm9_offset_fb64:$offset), 0>; +def : InstAlias<"ldr $Rt, [$Rn, $offset]", + (LDURWi GPR32:$Rt, GPR64sp:$Rn, simm9_offset_fb32:$offset), 0>; +def : InstAlias<"ldr $Rt, [$Rn, $offset]", + (LDURBi FPR8:$Rt, GPR64sp:$Rn, simm9_offset_fb8:$offset), 0>; +def : InstAlias<"ldr $Rt, [$Rn, $offset]", + (LDURHi FPR16:$Rt, GPR64sp:$Rn, simm9_offset_fb16:$offset), 0>; +def : InstAlias<"ldr $Rt, [$Rn, $offset]", + (LDURSi FPR32:$Rt, GPR64sp:$Rn, simm9_offset_fb32:$offset), 0>; +def : InstAlias<"ldr $Rt, [$Rn, $offset]", + (LDURDi FPR64:$Rt, GPR64sp:$Rn, simm9_offset_fb64:$offset), 0>; +def : InstAlias<"ldr $Rt, [$Rn, $offset]", + (LDURQi FPR128:$Rt, GPR64sp:$Rn, simm9_offset_fb128:$offset), 0>; // zextload -> i64 -def : Pat<(i64 (zextloadi8 am_unscaled8:$addr)), - (SUBREG_TO_REG (i64 0), (LDURBBi am_unscaled8:$addr), sub_32)>; -def : Pat<(i64 (zextloadi16 am_unscaled16:$addr)), - (SUBREG_TO_REG (i64 0), (LDURHHi am_unscaled16:$addr), sub_32)>; +def : Pat<(i64 (zextloadi8 (am_unscaled8 GPR64sp:$Rn, simm9:$offset))), + (SUBREG_TO_REG (i64 0), (LDURBBi GPR64sp:$Rn, simm9:$offset), sub_32)>; +def : Pat<(i64 (zextloadi16 (am_unscaled16 GPR64sp:$Rn, simm9:$offset))), + (SUBREG_TO_REG (i64 0), (LDURHHi GPR64sp:$Rn, simm9:$offset), sub_32)>; // load sign-extended half-word -def LDURSHWi - : LoadUnscaled<0b01, 0, 0b11, GPR32, am_unscaled16, "ldursh", - [(set GPR32:$Rt, (sextloadi16 am_unscaled16:$addr))]>; -def LDURSHXi - : LoadUnscaled<0b01, 0, 0b10, GPR64, am_unscaled16, "ldursh", - [(set GPR64:$Rt, (sextloadi16 am_unscaled16:$addr))]>; +defm LDURSHW + : LoadUnscaled<0b01, 0, 0b11, GPR32, "ldursh", + [(set GPR32:$Rt, + (sextloadi16 (am_unscaled16 GPR64sp:$Rn, simm9:$offset)))]>; +defm LDURSHX + : LoadUnscaled<0b01, 0, 0b10, GPR64, "ldursh", + [(set GPR64:$Rt, + (sextloadi16 (am_unscaled16 GPR64sp:$Rn, simm9:$offset)))]>; // load sign-extended byte -def LDURSBWi - : LoadUnscaled<0b00, 0, 0b11, GPR32, am_unscaled8, "ldursb", - [(set GPR32:$Rt, (sextloadi8 am_unscaled8:$addr))]>; -def LDURSBXi - : LoadUnscaled<0b00, 0, 0b10, GPR64, am_unscaled8, "ldursb", - [(set GPR64:$Rt, (sextloadi8 am_unscaled8:$addr))]>; +defm LDURSBW + : LoadUnscaled<0b00, 0, 0b11, GPR32, "ldursb", + [(set GPR32:$Rt, + (sextloadi8 (am_unscaled8 GPR64sp:$Rn, simm9:$offset)))]>; +defm LDURSBX + : LoadUnscaled<0b00, 0, 0b10, GPR64, "ldursb", + [(set GPR64:$Rt, + (sextloadi8 (am_unscaled8 GPR64sp:$Rn, simm9:$offset)))]>; // load sign-extended word -def LDURSWi - : LoadUnscaled<0b10, 0, 0b10, GPR64, am_unscaled32, "ldursw", - [(set GPR64:$Rt, (sextloadi32 am_unscaled32:$addr))]>; +defm LDURSW + : LoadUnscaled<0b10, 0, 0b10, GPR64, "ldursw", + [(set GPR64:$Rt, + (sextloadi32 (am_unscaled32 GPR64sp:$Rn, simm9:$offset)))]>; // zero and sign extending aliases from generic LDR* mnemonics to LDUR*. -def : InstAlias<"ldrb $Rt, $addr", - (LDURBBi GPR32:$Rt, am_unscaled_fb8:$addr), 0>; -def : InstAlias<"ldrh $Rt, $addr", - (LDURHHi GPR32:$Rt, am_unscaled_fb16:$addr), 0>; -def : InstAlias<"ldrsb $Rt, $addr", - (LDURSBWi GPR32:$Rt, am_unscaled_fb8:$addr), 0>; -def : InstAlias<"ldrsb $Rt, $addr", - (LDURSBXi GPR64:$Rt, am_unscaled_fb8:$addr), 0>; -def : InstAlias<"ldrsh $Rt, $addr", - (LDURSHWi GPR32:$Rt, am_unscaled_fb16:$addr), 0>; -def : InstAlias<"ldrsh $Rt, $addr", - (LDURSHXi GPR64:$Rt, am_unscaled_fb16:$addr), 0>; -def : InstAlias<"ldrsw $Rt, $addr", - (LDURSWi GPR64:$Rt, am_unscaled_fb32:$addr), 0>; +// FIXME: these don't work now +def : InstAlias<"ldrb $Rt, [$Rn, $offset]", + (LDURBBi GPR32:$Rt, GPR64sp:$Rn, simm9_offset_fb8:$offset), 0>; +def : InstAlias<"ldrh $Rt, [$Rn, $offset]", + (LDURHHi GPR32:$Rt, GPR64sp:$Rn, simm9_offset_fb16:$offset), 0>; +def : InstAlias<"ldrsb $Rt, [$Rn, $offset]", + (LDURSBWi GPR32:$Rt, GPR64sp:$Rn, simm9_offset_fb8:$offset), 0>; +def : InstAlias<"ldrsb $Rt, [$Rn, $offset]", + (LDURSBXi GPR64:$Rt, GPR64sp:$Rn, simm9_offset_fb8:$offset), 0>; +def : InstAlias<"ldrsh $Rt, [$Rn, $offset]", + (LDURSHWi GPR32:$Rt, GPR64sp:$Rn, simm9_offset_fb16:$offset), 0>; +def : InstAlias<"ldrsh $Rt, [$Rn, $offset]", + (LDURSHXi GPR64:$Rt, GPR64sp:$Rn, simm9_offset_fb16:$offset), 0>; +def : InstAlias<"ldrsw $Rt, [$Rn, $offset]", + (LDURSWi GPR64:$Rt, GPR64sp:$Rn, simm9_offset_fb32:$offset), 0>; // Pre-fetch. -def PRFUMi : PrefetchUnscaled<0b11, 0, 0b10, "prfum", - [(ARM64Prefetch imm:$Rt, am_unscaled64:$addr)]>; +defm PRFUM : PrefetchUnscaled<0b11, 0, 0b10, "prfum", + [(ARM64Prefetch imm:$Rt, + (am_unscaled64 GPR64sp:$Rn, simm9:$offset))]>; //--- // (unscaled immediate, unprivileged) -def LDTRXi : LoadUnprivileged<0b11, 0, 0b01, GPR64, "ldtr">; -def LDTRWi : LoadUnprivileged<0b10, 0, 0b01, GPR32, "ldtr">; +defm LDTRX : LoadUnprivileged<0b11, 0, 0b01, GPR64, "ldtr">; +defm LDTRW : LoadUnprivileged<0b10, 0, 0b01, GPR32, "ldtr">; -def LDTRHi : LoadUnprivileged<0b01, 0, 0b01, GPR32, "ldtrh">; -def LDTRBi : LoadUnprivileged<0b00, 0, 0b01, GPR32, "ldtrb">; +defm LDTRH : LoadUnprivileged<0b01, 0, 0b01, GPR32, "ldtrh">; +defm LDTRB : LoadUnprivileged<0b00, 0, 0b01, GPR32, "ldtrb">; // load sign-extended half-word -def LDTRSHWi : LoadUnprivileged<0b01, 0, 0b11, GPR32, "ldtrsh">; -def LDTRSHXi : LoadUnprivileged<0b01, 0, 0b10, GPR64, "ldtrsh">; +defm LDTRSHW : LoadUnprivileged<0b01, 0, 0b11, GPR32, "ldtrsh">; +defm LDTRSHX : LoadUnprivileged<0b01, 0, 0b10, GPR64, "ldtrsh">; // load sign-extended byte -def LDTRSBWi : LoadUnprivileged<0b00, 0, 0b11, GPR32, "ldtrsb">; -def LDTRSBXi : LoadUnprivileged<0b00, 0, 0b10, GPR64, "ldtrsb">; +defm LDTRSBW : LoadUnprivileged<0b00, 0, 0b11, GPR32, "ldtrsb">; +defm LDTRSBX : LoadUnprivileged<0b00, 0, 0b10, GPR64, "ldtrsb">; // load sign-extended word -def LDTRSWi : LoadUnprivileged<0b10, 0, 0b10, GPR64, "ldtrsw">; +defm LDTRSW : LoadUnprivileged<0b10, 0, 0b10, GPR64, "ldtrsw">; //--- // (immediate pre-indexed) @@ -1642,18 +1760,18 @@ def LDRSBXpost_isel : LoadPostIdxPseudo; // Pair (indexed, offset) // FIXME: Use dedicated range-checked addressing mode operand here. -def STPWi : StorePairOffset<0b00, 0, GPR32, am_indexed32simm7, "stp">; -def STPXi : StorePairOffset<0b10, 0, GPR64, am_indexed64simm7, "stp">; -def STPSi : StorePairOffset<0b00, 1, FPR32, am_indexed32simm7, "stp">; -def STPDi : StorePairOffset<0b01, 1, FPR64, am_indexed64simm7, "stp">; -def STPQi : StorePairOffset<0b10, 1, FPR128, am_indexed128simm7, "stp">; +defm STPW : StorePairOffset<0b00, 0, GPR32, simm7s4, "stp">; +defm STPX : StorePairOffset<0b10, 0, GPR64, simm7s8, "stp">; +defm STPS : StorePairOffset<0b00, 1, FPR32, simm7s4, "stp">; +defm STPD : StorePairOffset<0b01, 1, FPR64, simm7s8, "stp">; +defm STPQ : StorePairOffset<0b10, 1, FPR128, simm7s16, "stp">; // Pair (pre-indexed) -def STPWpre : StorePairPreIdx<0b00, 0, GPR32, am_indexed32simm7_wb, "stp">; -def STPXpre : StorePairPreIdx<0b10, 0, GPR64, am_indexed64simm7_wb, "stp">; -def STPSpre : StorePairPreIdx<0b00, 1, FPR32, am_indexed32simm7_wb, "stp">; -def STPDpre : StorePairPreIdx<0b01, 1, FPR64, am_indexed64simm7_wb, "stp">; -def STPQpre : StorePairPreIdx<0b10, 1, FPR128, am_indexed128simm7_wb, "stp">; +def STPWpre : StorePairPreIdx<0b00, 0, GPR32, simm7s4, "stp">; +def STPXpre : StorePairPreIdx<0b10, 0, GPR64, simm7s8, "stp">; +def STPSpre : StorePairPreIdx<0b00, 1, FPR32, simm7s4, "stp">; +def STPDpre : StorePairPreIdx<0b01, 1, FPR64, simm7s8, "stp">; +def STPQpre : StorePairPreIdx<0b10, 1, FPR128, simm7s16, "stp">; // Pair (pre-indexed) def STPWpost : StorePairPostIdx<0b00, 0, GPR32, simm7s4, "stp">; @@ -1663,248 +1781,294 @@ def STPDpost : StorePairPostIdx<0b01, 1, FPR64, simm7s8, "stp">; def STPQpost : StorePairPostIdx<0b10, 1, FPR128, simm7s16, "stp">; // Pair (no allocate) -def STNPWi : StorePairNoAlloc<0b00, 0, GPR32, am_indexed32simm7, "stnp">; -def STNPXi : StorePairNoAlloc<0b10, 0, GPR64, am_indexed64simm7, "stnp">; -def STNPSi : StorePairNoAlloc<0b00, 1, FPR32, am_indexed32simm7, "stnp">; -def STNPDi : StorePairNoAlloc<0b01, 1, FPR64, am_indexed64simm7, "stnp">; -def STNPQi : StorePairNoAlloc<0b10, 1, FPR128, am_indexed128simm7, "stnp">; +defm STNPW : StorePairNoAlloc<0b00, 0, GPR32, simm7s4, "stnp">; +defm STNPX : StorePairNoAlloc<0b10, 0, GPR64, simm7s8, "stnp">; +defm STNPS : StorePairNoAlloc<0b00, 1, FPR32, simm7s4, "stnp">; +defm STNPD : StorePairNoAlloc<0b01, 1, FPR64, simm7s8, "stnp">; +defm STNPQ : StorePairNoAlloc<0b10, 1, FPR128, simm7s16, "stnp">; //--- // (Register offset) -let AddedComplexity = 10 in { - // Integer -def STRHHro : Store16RO<0b01, 0, 0b00, GPR32, "strh", - [(truncstorei16 GPR32:$Rt, ro_indexed16:$addr)]>; -def STRBBro : Store8RO<0b00, 0, 0b00, GPR32, "strb", - [(truncstorei8 GPR32:$Rt, ro_indexed8:$addr)]>; -def STRWro : Store32RO<0b10, 0, 0b00, GPR32, "str", - [(store GPR32:$Rt, ro_indexed32:$addr)]>; -def STRXro : Store64RO<0b11, 0, 0b00, GPR64, "str", - [(store GPR64:$Rt, ro_indexed64:$addr)]>; - -// truncstore i64 -def : Pat<(truncstorei8 GPR64:$Rt, ro_indexed8:$addr), - (STRBBro (EXTRACT_SUBREG GPR64:$Rt, sub_32), ro_indexed8:$addr)>; -def : Pat<(truncstorei16 GPR64:$Rt, ro_indexed16:$addr), - (STRHHro (EXTRACT_SUBREG GPR64:$Rt, sub_32), ro_indexed16:$addr)>; -def : Pat<(truncstorei32 GPR64:$Rt, ro_indexed32:$addr), - (STRWro (EXTRACT_SUBREG GPR64:$Rt, sub_32), ro_indexed32:$addr)>; +defm STRBB : Store8RO< 0b00, 0, 0b00, GPR32, "strb", i32, truncstorei8>; +defm STRHH : Store16RO<0b01, 0, 0b00, GPR32, "strh", i32, truncstorei16>; +defm STRW : Store32RO<0b10, 0, 0b00, GPR32, "str", i32, store>; +defm STRX : Store64RO<0b11, 0, 0b00, GPR64, "str", i64, store>; // Floating-point -def STRBro : Store8RO<0b00, 1, 0b00, FPR8, "str", - [(store FPR8:$Rt, ro_indexed8:$addr)]>; -def STRHro : Store16RO<0b01, 1, 0b00, FPR16, "str", - [(store (f16 FPR16:$Rt), ro_indexed16:$addr)]>; -def STRSro : Store32RO<0b10, 1, 0b00, FPR32, "str", - [(store (f32 FPR32:$Rt), ro_indexed32:$addr)]>; -def STRDro : Store64RO<0b11, 1, 0b00, FPR64, "str", - [(store (f64 FPR64:$Rt), ro_indexed64:$addr)]>; -def STRQro : Store128RO<0b00, 1, 0b10, FPR128, "str", []> { - let mayStore = 1; +defm STRB : Store8RO< 0b00, 1, 0b00, FPR8, "str", untyped, store>; +defm STRH : Store16RO<0b01, 1, 0b00, FPR16, "str", f16, store>; +defm STRS : Store32RO<0b10, 1, 0b00, FPR32, "str", f32, store>; +defm STRD : Store64RO<0b11, 1, 0b00, FPR64, "str", f64, store>; +defm STRQ : Store128RO<0b00, 1, 0b10, FPR128, "str", f128, store>; + +multiclass TruncStoreFrom64ROPat { + + def : Pat<(storeop GPR64:$Rt, + (ro.Wpat GPR64sp:$Rn, GPR32:$Rm, ro.Wext:$extend)), + (STRW (EXTRACT_SUBREG GPR64:$Rt, sub_32), + GPR64sp:$Rn, GPR32:$Rm, ro.Wext:$extend)>; + + def : Pat<(storeop GPR64:$Rt, + (ro.Xpat GPR64sp:$Rn, GPR64:$Rm, ro.Xext:$extend)), + (STRX (EXTRACT_SUBREG GPR64:$Rt, sub_32), + GPR64sp:$Rn, GPR64:$Rm, ro.Xext:$extend)>; } +let AddedComplexity = 10 in { + // truncstore i64 + defm : TruncStoreFrom64ROPat; + defm : TruncStoreFrom64ROPat; + defm : TruncStoreFrom64ROPat; +} + +multiclass VecROStorePat { + def : Pat<(store (VecTy FPR:$Rt), + (ro.Wpat GPR64sp:$Rn, GPR32:$Rm, ro.Wext:$extend)), + (STRW FPR:$Rt, GPR64sp:$Rn, GPR32:$Rm, ro.Wext:$extend)>; + + def : Pat<(store (VecTy FPR:$Rt), + (ro.Xpat GPR64sp:$Rn, GPR64:$Rm, ro.Xext:$extend)), + (STRX FPR:$Rt, GPR64sp:$Rn, GPR64:$Rm, ro.Xext:$extend)>; +} + +let AddedComplexity = 10 in { // Match all store 64 bits width whose type is compatible with FPR64 let Predicates = [IsLE] in { // We must use ST1 to store vectors in big-endian. - def : Pat<(store (v2f32 FPR64:$Rn), ro_indexed64:$addr), - (STRDro FPR64:$Rn, ro_indexed64:$addr)>; - def : Pat<(store (v8i8 FPR64:$Rn), ro_indexed64:$addr), - (STRDro FPR64:$Rn, ro_indexed64:$addr)>; - def : Pat<(store (v4i16 FPR64:$Rn), ro_indexed64:$addr), - (STRDro FPR64:$Rn, ro_indexed64:$addr)>; - def : Pat<(store (v2i32 FPR64:$Rn), ro_indexed64:$addr), - (STRDro FPR64:$Rn, ro_indexed64:$addr)>; + defm : VecROStorePat; + defm : VecROStorePat; + defm : VecROStorePat; + defm : VecROStorePat; } -def : Pat<(store (v1f64 FPR64:$Rn), ro_indexed64:$addr), - (STRDro FPR64:$Rn, ro_indexed64:$addr)>; -def : Pat<(store (v1i64 FPR64:$Rn), ro_indexed64:$addr), - (STRDro FPR64:$Rn, ro_indexed64:$addr)>; + +defm : VecROStorePat; +defm : VecROStorePat; // Match all store 128 bits width whose type is compatible with FPR128 let Predicates = [IsLE] in { // We must use ST1 to store vectors in big-endian. - def : Pat<(store (v4f32 FPR128:$Rn), ro_indexed128:$addr), - (STRQro FPR128:$Rn, ro_indexed128:$addr)>; - def : Pat<(store (v2f64 FPR128:$Rn), ro_indexed128:$addr), - (STRQro FPR128:$Rn, ro_indexed128:$addr)>; - def : Pat<(store (v16i8 FPR128:$Rn), ro_indexed128:$addr), - (STRQro FPR128:$Rn, ro_indexed128:$addr)>; - def : Pat<(store (v8i16 FPR128:$Rn), ro_indexed128:$addr), - (STRQro FPR128:$Rn, ro_indexed128:$addr)>; - def : Pat<(store (v4i32 FPR128:$Rn), ro_indexed128:$addr), - (STRQro FPR128:$Rn, ro_indexed128:$addr)>; - def : Pat<(store (v2i64 FPR128:$Rn), ro_indexed128:$addr), - (STRQro FPR128:$Rn, ro_indexed128:$addr)>; + defm : VecROStorePat; + defm : VecROStorePat; + defm : VecROStorePat; + defm : VecROStorePat; + defm : VecROStorePat; + defm : VecROStorePat; } -def : Pat<(store (f128 FPR128:$Rn), ro_indexed128:$addr), - (STRQro FPR128:$Rn, ro_indexed128:$addr)>; +} // AddedComplexity = 10 //--- // (unsigned immediate) -def STRXui : StoreUI<0b11, 0, 0b00, GPR64, am_indexed64, "str", - [(store GPR64:$Rt, am_indexed64:$addr)]>; -def STRWui : StoreUI<0b10, 0, 0b00, GPR32, am_indexed32, "str", - [(store GPR32:$Rt, am_indexed32:$addr)]>; -def STRBui : StoreUI<0b00, 1, 0b00, FPR8, am_indexed8, "str", - [(store FPR8:$Rt, am_indexed8:$addr)]>; -def STRHui : StoreUI<0b01, 1, 0b00, FPR16, am_indexed16, "str", - [(store (f16 FPR16:$Rt), am_indexed16:$addr)]>; -def STRSui : StoreUI<0b10, 1, 0b00, FPR32, am_indexed32, "str", - [(store (f32 FPR32:$Rt), am_indexed32:$addr)]>; -def STRDui : StoreUI<0b11, 1, 0b00, FPR64, am_indexed64, "str", - [(store (f64 FPR64:$Rt), am_indexed64:$addr)]>; -def STRQui : StoreUI<0b00, 1, 0b10, FPR128, am_indexed128, "str", []> { - let mayStore = 1; -} +defm STRX : StoreUI<0b11, 0, 0b00, GPR64, uimm12s8, "str", + [(store GPR64:$Rt, + (am_indexed64 GPR64sp:$Rn, uimm12s8:$offset))]>; +defm STRW : StoreUI<0b10, 0, 0b00, GPR32, uimm12s4, "str", + [(store GPR32:$Rt, + (am_indexed32 GPR64sp:$Rn, uimm12s4:$offset))]>; +defm STRB : StoreUI<0b00, 1, 0b00, FPR8, uimm12s1, "str", + [(store FPR8:$Rt, + (am_indexed8 GPR64sp:$Rn, uimm12s1:$offset))]>; +defm STRH : StoreUI<0b01, 1, 0b00, FPR16, uimm12s2, "str", + [(store (f16 FPR16:$Rt), + (am_indexed16 GPR64sp:$Rn, uimm12s2:$offset))]>; +defm STRS : StoreUI<0b10, 1, 0b00, FPR32, uimm12s4, "str", + [(store (f32 FPR32:$Rt), + (am_indexed32 GPR64sp:$Rn, uimm12s4:$offset))]>; +defm STRD : StoreUI<0b11, 1, 0b00, FPR64, uimm12s8, "str", + [(store (f64 FPR64:$Rt), + (am_indexed64 GPR64sp:$Rn, uimm12s8:$offset))]>; +defm STRQ : StoreUI<0b00, 1, 0b10, FPR128, uimm12s16, "str", []>; + +defm STRHH : StoreUI<0b01, 0, 0b00, GPR32, uimm12s2, "strh", + [(truncstorei16 GPR32:$Rt, + (am_indexed16 GPR64sp:$Rn, + uimm12s2:$offset))]>; +defm STRBB : StoreUI<0b00, 0, 0b00, GPR32, uimm12s1, "strb", + [(truncstorei8 GPR32:$Rt, + (am_indexed8 GPR64sp:$Rn, + uimm12s1:$offset))]>; // Match all store 64 bits width whose type is compatible with FPR64 +let AddedComplexity = 10 in { let Predicates = [IsLE] in { // We must use ST1 to store vectors in big-endian. - def : Pat<(store (v2f32 FPR64:$Rn), am_indexed64:$addr), - (STRDui FPR64:$Rn, am_indexed64:$addr)>; - def : Pat<(store (v8i8 FPR64:$Rn), am_indexed64:$addr), - (STRDui FPR64:$Rn, am_indexed64:$addr)>; - def : Pat<(store (v4i16 FPR64:$Rn), am_indexed64:$addr), - (STRDui FPR64:$Rn, am_indexed64:$addr)>; - def : Pat<(store (v2i32 FPR64:$Rn), am_indexed64:$addr), - (STRDui FPR64:$Rn, am_indexed64:$addr)>; + def : Pat<(store (v2f32 FPR64:$Rt), + (am_indexed64 GPR64sp:$Rn, uimm12s8:$offset)), + (STRDui FPR64:$Rt, GPR64sp:$Rn, uimm12s8:$offset)>; + def : Pat<(store (v8i8 FPR64:$Rt), + (am_indexed64 GPR64sp:$Rn, uimm12s8:$offset)), + (STRDui FPR64:$Rt, GPR64sp:$Rn, uimm12s8:$offset)>; + def : Pat<(store (v4i16 FPR64:$Rt), + (am_indexed64 GPR64sp:$Rn, uimm12s8:$offset)), + (STRDui FPR64:$Rt, GPR64sp:$Rn, uimm12s8:$offset)>; + def : Pat<(store (v2i32 FPR64:$Rt), + (am_indexed64 GPR64sp:$Rn, uimm12s8:$offset)), + (STRDui FPR64:$Rt, GPR64sp:$Rn, uimm12s8:$offset)>; } -def : Pat<(store (v1f64 FPR64:$Rn), am_indexed64:$addr), - (STRDui FPR64:$Rn, am_indexed64:$addr)>; -def : Pat<(store (v1i64 FPR64:$Rn), am_indexed64:$addr), - (STRDui FPR64:$Rn, am_indexed64:$addr)>; +def : Pat<(store (v1f64 FPR64:$Rt), + (am_indexed64 GPR64sp:$Rn, uimm12s8:$offset)), + (STRDui FPR64:$Rt, GPR64sp:$Rn, uimm12s8:$offset)>; +def : Pat<(store (v1i64 FPR64:$Rt), + (am_indexed64 GPR64sp:$Rn, uimm12s8:$offset)), + (STRDui FPR64:$Rt, GPR64sp:$Rn, uimm12s8:$offset)>; // Match all store 128 bits width whose type is compatible with FPR128 let Predicates = [IsLE] in { // We must use ST1 to store vectors in big-endian. - def : Pat<(store (v4f32 FPR128:$Rn), am_indexed128:$addr), - (STRQui FPR128:$Rn, am_indexed128:$addr)>; - def : Pat<(store (v2f64 FPR128:$Rn), am_indexed128:$addr), - (STRQui FPR128:$Rn, am_indexed128:$addr)>; - def : Pat<(store (v16i8 FPR128:$Rn), am_indexed128:$addr), - (STRQui FPR128:$Rn, am_indexed128:$addr)>; - def : Pat<(store (v8i16 FPR128:$Rn), am_indexed128:$addr), - (STRQui FPR128:$Rn, am_indexed128:$addr)>; - def : Pat<(store (v4i32 FPR128:$Rn), am_indexed128:$addr), - (STRQui FPR128:$Rn, am_indexed128:$addr)>; - def : Pat<(store (v2i64 FPR128:$Rn), am_indexed128:$addr), - (STRQui FPR128:$Rn, am_indexed128:$addr)>; + def : Pat<(store (v4f32 FPR128:$Rt), + (am_indexed128 GPR64sp:$Rn, uimm12s16:$offset)), + (STRQui FPR128:$Rt, GPR64sp:$Rn, uimm12s16:$offset)>; + def : Pat<(store (v2f64 FPR128:$Rt), + (am_indexed128 GPR64sp:$Rn, uimm12s16:$offset)), + (STRQui FPR128:$Rt, GPR64sp:$Rn, uimm12s16:$offset)>; + def : Pat<(store (v16i8 FPR128:$Rt), + (am_indexed128 GPR64sp:$Rn, uimm12s16:$offset)), + (STRQui FPR128:$Rt, GPR64sp:$Rn, uimm12s16:$offset)>; + def : Pat<(store (v8i16 FPR128:$Rt), + (am_indexed128 GPR64sp:$Rn, uimm12s16:$offset)), + (STRQui FPR128:$Rt, GPR64sp:$Rn, uimm12s16:$offset)>; + def : Pat<(store (v4i32 FPR128:$Rt), + (am_indexed128 GPR64sp:$Rn, uimm12s16:$offset)), + (STRQui FPR128:$Rt, GPR64sp:$Rn, uimm12s16:$offset)>; + def : Pat<(store (v2i64 FPR128:$Rt), + (am_indexed128 GPR64sp:$Rn, uimm12s16:$offset)), + (STRQui FPR128:$Rt, GPR64sp:$Rn, uimm12s16:$offset)>; } -def : Pat<(store (f128 FPR128:$Rn), am_indexed128:$addr), - (STRQui FPR128:$Rn, am_indexed128:$addr)>; - -def STRHHui : StoreUI<0b01, 0, 0b00, GPR32, am_indexed16, "strh", - [(truncstorei16 GPR32:$Rt, am_indexed16:$addr)]>; -def STRBBui : StoreUI<0b00, 0, 0b00, GPR32, am_indexed8, "strb", - [(truncstorei8 GPR32:$Rt, am_indexed8:$addr)]>; +def : Pat<(store (f128 FPR128:$Rt), + (am_indexed128 GPR64sp:$Rn, uimm12s16:$offset)), + (STRQui FPR128:$Rt, GPR64sp:$Rn, uimm12s16:$offset)>; // truncstore i64 -def : Pat<(truncstorei32 GPR64:$Rt, am_indexed32:$addr), - (STRWui (EXTRACT_SUBREG GPR64:$Rt, sub_32), am_indexed32:$addr)>; -def : Pat<(truncstorei16 GPR64:$Rt, am_indexed16:$addr), - (STRHHui (EXTRACT_SUBREG GPR64:$Rt, sub_32), am_indexed16:$addr)>; -def : Pat<(truncstorei8 GPR64:$Rt, am_indexed8:$addr), - (STRBBui (EXTRACT_SUBREG GPR64:$Rt, sub_32), am_indexed8:$addr)>; +def : Pat<(truncstorei32 GPR64:$Rt, + (am_indexed32 GPR64sp:$Rn, uimm12s4:$offset)), + (STRWui (EXTRACT_SUBREG GPR64:$Rt, sub_32), GPR64sp:$Rn, uimm12s4:$offset)>; +def : Pat<(truncstorei16 GPR64:$Rt, + (am_indexed16 GPR64sp:$Rn, uimm12s2:$offset)), + (STRHHui (EXTRACT_SUBREG GPR64:$Rt, sub_32), GPR64sp:$Rn, uimm12s2:$offset)>; +def : Pat<(truncstorei8 GPR64:$Rt, (am_indexed8 GPR64sp:$Rn, uimm12s1:$offset)), + (STRBBui (EXTRACT_SUBREG GPR64:$Rt, sub_32), GPR64sp:$Rn, uimm12s1:$offset)>; } // AddedComplexity = 10 //--- // (unscaled immediate) -def STURXi : StoreUnscaled<0b11, 0, 0b00, GPR64, am_unscaled64, "stur", - [(store GPR64:$Rt, am_unscaled64:$addr)]>; -def STURWi : StoreUnscaled<0b10, 0, 0b00, GPR32, am_unscaled32, "stur", - [(store GPR32:$Rt, am_unscaled32:$addr)]>; -def STURBi : StoreUnscaled<0b00, 1, 0b00, FPR8, am_unscaled8, "stur", - [(store FPR8:$Rt, am_unscaled8:$addr)]>; -def STURHi : StoreUnscaled<0b01, 1, 0b00, FPR16, am_unscaled16, "stur", - [(store (f16 FPR16:$Rt), am_unscaled16:$addr)]>; -def STURSi : StoreUnscaled<0b10, 1, 0b00, FPR32, am_unscaled32, "stur", - [(store (f32 FPR32:$Rt), am_unscaled32:$addr)]>; -def STURDi : StoreUnscaled<0b11, 1, 0b00, FPR64, am_unscaled64, "stur", - [(store (f64 FPR64:$Rt), am_unscaled64:$addr)]>; -def STURQi : StoreUnscaled<0b00, 1, 0b10, FPR128, am_unscaled128, "stur", - [(store (f128 FPR128:$Rt), am_unscaled128:$addr)]>; -def STURHHi : StoreUnscaled<0b01, 0, 0b00, GPR32, am_unscaled16, "sturh", - [(truncstorei16 GPR32:$Rt, am_unscaled16:$addr)]>; -def STURBBi : StoreUnscaled<0b00, 0, 0b00, GPR32, am_unscaled8, "sturb", - [(truncstorei8 GPR32:$Rt, am_unscaled8:$addr)]>; +defm STURX : StoreUnscaled<0b11, 0, 0b00, GPR64, "stur", + [(store GPR64:$Rt, + (am_unscaled64 GPR64sp:$Rn, simm9:$offset))]>; +defm STURW : StoreUnscaled<0b10, 0, 0b00, GPR32, "stur", + [(store GPR32:$Rt, + (am_unscaled32 GPR64sp:$Rn, simm9:$offset))]>; +defm STURB : StoreUnscaled<0b00, 1, 0b00, FPR8, "stur", + [(store FPR8:$Rt, + (am_unscaled8 GPR64sp:$Rn, simm9:$offset))]>; +defm STURH : StoreUnscaled<0b01, 1, 0b00, FPR16, "stur", + [(store (f16 FPR16:$Rt), + (am_unscaled16 GPR64sp:$Rn, simm9:$offset))]>; +defm STURS : StoreUnscaled<0b10, 1, 0b00, FPR32, "stur", + [(store (f32 FPR32:$Rt), + (am_unscaled32 GPR64sp:$Rn, simm9:$offset))]>; +defm STURD : StoreUnscaled<0b11, 1, 0b00, FPR64, "stur", + [(store (f64 FPR64:$Rt), + (am_unscaled64 GPR64sp:$Rn, simm9:$offset))]>; +defm STURQ : StoreUnscaled<0b00, 1, 0b10, FPR128, "stur", + [(store (f128 FPR128:$Rt), + (am_unscaled128 GPR64sp:$Rn, simm9:$offset))]>; +defm STURHH : StoreUnscaled<0b01, 0, 0b00, GPR32, "sturh", + [(truncstorei16 GPR32:$Rt, + (am_unscaled16 GPR64sp:$Rn, simm9:$offset))]>; +defm STURBB : StoreUnscaled<0b00, 0, 0b00, GPR32, "sturb", + [(truncstorei8 GPR32:$Rt, + (am_unscaled8 GPR64sp:$Rn, simm9:$offset))]>; // Match all store 64 bits width whose type is compatible with FPR64 let Predicates = [IsLE] in { // We must use ST1 to store vectors in big-endian. - def : Pat<(store (v2f32 FPR64:$Rn), am_unscaled64:$addr), - (STURDi FPR64:$Rn, am_unscaled64:$addr)>; - def : Pat<(store (v8i8 FPR64:$Rn), am_unscaled64:$addr), - (STURDi FPR64:$Rn, am_unscaled64:$addr)>; - def : Pat<(store (v4i16 FPR64:$Rn), am_unscaled64:$addr), - (STURDi FPR64:$Rn, am_unscaled64:$addr)>; - def : Pat<(store (v2i32 FPR64:$Rn), am_unscaled64:$addr), - (STURDi FPR64:$Rn, am_unscaled64:$addr)>; + def : Pat<(store (v2f32 FPR64:$Rt), + (am_unscaled64 GPR64sp:$Rn, simm9:$offset)), + (STURDi FPR64:$Rt, GPR64sp:$Rn, simm9:$offset)>; + def : Pat<(store (v8i8 FPR64:$Rt), + (am_unscaled64 GPR64sp:$Rn, simm9:$offset)), + (STURDi FPR64:$Rt, GPR64sp:$Rn, simm9:$offset)>; + def : Pat<(store (v4i16 FPR64:$Rt), + (am_unscaled64 GPR64sp:$Rn, simm9:$offset)), + (STURDi FPR64:$Rt, GPR64sp:$Rn, simm9:$offset)>; + def : Pat<(store (v2i32 FPR64:$Rt), + (am_unscaled64 GPR64sp:$Rn, simm9:$offset)), + (STURDi FPR64:$Rt, GPR64sp:$Rn, simm9:$offset)>; } -def : Pat<(store (v1f64 FPR64:$Rn), am_unscaled64:$addr), - (STURDi FPR64:$Rn, am_unscaled64:$addr)>; -def : Pat<(store (v1i64 FPR64:$Rn), am_unscaled64:$addr), - (STURDi FPR64:$Rn, am_unscaled64:$addr)>; +def : Pat<(store (v1f64 FPR64:$Rt), (am_unscaled64 GPR64sp:$Rn, simm9:$offset)), + (STURDi FPR64:$Rt, GPR64sp:$Rn, simm9:$offset)>; +def : Pat<(store (v1i64 FPR64:$Rt), (am_unscaled64 GPR64sp:$Rn, simm9:$offset)), + (STURDi FPR64:$Rt, GPR64sp:$Rn, simm9:$offset)>; // Match all store 128 bits width whose type is compatible with FPR128 let Predicates = [IsLE] in { // We must use ST1 to store vectors in big-endian. - def : Pat<(store (v4f32 FPR128:$Rn), am_unscaled128:$addr), - (STURQi FPR128:$Rn, am_unscaled128:$addr)>; - def : Pat<(store (v2f64 FPR128:$Rn), am_unscaled128:$addr), - (STURQi FPR128:$Rn, am_unscaled128:$addr)>; - def : Pat<(store (v16i8 FPR128:$Rn), am_unscaled128:$addr), - (STURQi FPR128:$Rn, am_unscaled128:$addr)>; - def : Pat<(store (v8i16 FPR128:$Rn), am_unscaled128:$addr), - (STURQi FPR128:$Rn, am_unscaled128:$addr)>; - def : Pat<(store (v4i32 FPR128:$Rn), am_unscaled128:$addr), - (STURQi FPR128:$Rn, am_unscaled128:$addr)>; - def : Pat<(store (v2i64 FPR128:$Rn), am_unscaled128:$addr), - (STURQi FPR128:$Rn, am_unscaled128:$addr)>; - def : Pat<(store (v2f64 FPR128:$Rn), am_unscaled128:$addr), - (STURQi FPR128:$Rn, am_unscaled128:$addr)>; + def : Pat<(store (v4f32 FPR128:$Rt), + (am_unscaled128 GPR64sp:$Rn, simm9:$offset)), + (STURQi FPR128:$Rt, GPR64sp:$Rn, simm9:$offset)>; + def : Pat<(store (v2f64 FPR128:$Rt), + (am_unscaled128 GPR64sp:$Rn, simm9:$offset)), + (STURQi FPR128:$Rt, GPR64sp:$Rn, simm9:$offset)>; + def : Pat<(store (v16i8 FPR128:$Rt), + (am_unscaled128 GPR64sp:$Rn, simm9:$offset)), + (STURQi FPR128:$Rt, GPR64sp:$Rn, simm9:$offset)>; + def : Pat<(store (v8i16 FPR128:$Rt), + (am_unscaled128 GPR64sp:$Rn, simm9:$offset)), + (STURQi FPR128:$Rt, GPR64sp:$Rn, simm9:$offset)>; + def : Pat<(store (v4i32 FPR128:$Rt), + (am_unscaled128 GPR64sp:$Rn, simm9:$offset)), + (STURQi FPR128:$Rt, GPR64sp:$Rn, simm9:$offset)>; + def : Pat<(store (v2i64 FPR128:$Rt), + (am_unscaled128 GPR64sp:$Rn, simm9:$offset)), + (STURQi FPR128:$Rt, GPR64sp:$Rn, simm9:$offset)>; + def : Pat<(store (v2f64 FPR128:$Rt), + (am_unscaled128 GPR64sp:$Rn, simm9:$offset)), + (STURQi FPR128:$Rt, GPR64sp:$Rn, simm9:$offset)>; } // unscaled i64 truncating stores -def : Pat<(truncstorei32 GPR64:$Rt, am_unscaled32:$addr), - (STURWi (EXTRACT_SUBREG GPR64:$Rt, sub_32), am_unscaled32:$addr)>; -def : Pat<(truncstorei16 GPR64:$Rt, am_unscaled16:$addr), - (STURHHi (EXTRACT_SUBREG GPR64:$Rt, sub_32), am_unscaled16:$addr)>; -def : Pat<(truncstorei8 GPR64:$Rt, am_unscaled8:$addr), - (STURBBi (EXTRACT_SUBREG GPR64:$Rt, sub_32), am_unscaled8:$addr)>; +def : Pat<(truncstorei32 GPR64:$Rt, (am_unscaled32 GPR64sp:$Rn, simm9:$offset)), + (STURWi (EXTRACT_SUBREG GPR64:$Rt, sub_32), GPR64sp:$Rn, simm9:$offset)>; +def : Pat<(truncstorei16 GPR64:$Rt, (am_unscaled16 GPR64sp:$Rn, simm9:$offset)), + (STURHHi (EXTRACT_SUBREG GPR64:$Rt, sub_32), GPR64sp:$Rn, simm9:$offset)>; +def : Pat<(truncstorei8 GPR64:$Rt, (am_unscaled8 GPR64sp:$Rn, simm9:$offset)), + (STURBBi (EXTRACT_SUBREG GPR64:$Rt, sub_32), GPR64sp:$Rn, simm9:$offset)>; //--- // STR mnemonics fall back to STUR for negative or unaligned offsets. -def : InstAlias<"str $Rt, $addr", - (STURXi GPR64:$Rt, am_unscaled_fb64:$addr), 0>; -def : InstAlias<"str $Rt, $addr", - (STURWi GPR32:$Rt, am_unscaled_fb32:$addr), 0>; -def : InstAlias<"str $Rt, $addr", - (STURBi FPR8:$Rt, am_unscaled_fb8:$addr), 0>; -def : InstAlias<"str $Rt, $addr", - (STURHi FPR16:$Rt, am_unscaled_fb16:$addr), 0>; -def : InstAlias<"str $Rt, $addr", - (STURSi FPR32:$Rt, am_unscaled_fb32:$addr), 0>; -def : InstAlias<"str $Rt, $addr", - (STURDi FPR64:$Rt, am_unscaled_fb64:$addr), 0>; -def : InstAlias<"str $Rt, $addr", - (STURQi FPR128:$Rt, am_unscaled_fb128:$addr), 0>; +// FIXME: these don't work now. +def : InstAlias<"str $Rt, [$Rn, $offset]", + (STURXi GPR64:$Rt, GPR64sp:$Rn, simm9_offset_fb64:$offset), 0>; +def : InstAlias<"str $Rt, [$Rn, $offset]", + (STURWi GPR32:$Rt, GPR64sp:$Rn, simm9_offset_fb32:$offset), 0>; +def : InstAlias<"str $Rt, [$Rn, $offset]", + (STURBi FPR8:$Rt, GPR64sp:$Rn, simm9_offset_fb8:$offset), 0>; +def : InstAlias<"str $Rt, [$Rn, $offset]", + (STURHi FPR16:$Rt, GPR64sp:$Rn, simm9_offset_fb16:$offset), 0>; +def : InstAlias<"str $Rt, [$Rn, $offset]", + (STURSi FPR32:$Rt, GPR64sp:$Rn, simm9_offset_fb32:$offset), 0>; +def : InstAlias<"str $Rt, [$Rn, $offset]", + (STURDi FPR64:$Rt, GPR64sp:$Rn, simm9_offset_fb64:$offset), 0>; +def : InstAlias<"str $Rt, [$Rn, $offset]", + (STURQi FPR128:$Rt, GPR64sp:$Rn, simm9_offset_fb128:$offset), 0>; -def : InstAlias<"strb $Rt, $addr", - (STURBBi GPR32:$Rt, am_unscaled_fb8:$addr), 0>; -def : InstAlias<"strh $Rt, $addr", - (STURHHi GPR32:$Rt, am_unscaled_fb16:$addr), 0>; +def : InstAlias<"strb $Rt, [$Rn, $offset]", + (STURBBi GPR32:$Rt, GPR64sp:$Rn, simm9_offset_fb8:$offset), 0>; +def : InstAlias<"strh $Rt, [$Rn, $offset]", + (STURHHi GPR32:$Rt, GPR64sp:$Rn, simm9_offset_fb16:$offset), 0>; //--- // (unscaled immediate, unprivileged) -def STTRWi : StoreUnprivileged<0b10, 0, 0b00, GPR32, "sttr">; -def STTRXi : StoreUnprivileged<0b11, 0, 0b00, GPR64, "sttr">; +defm STTRW : StoreUnprivileged<0b10, 0, 0b00, GPR32, "sttr">; +defm STTRX : StoreUnprivileged<0b11, 0, 0b00, GPR64, "sttr">; -def STTRHi : StoreUnprivileged<0b01, 0, 0b00, GPR32, "sttrh">; -def STTRBi : StoreUnprivileged<0b00, 0, 0b00, GPR32, "sttrb">; +defm STTRH : StoreUnprivileged<0b01, 0, 0b00, GPR32, "sttrh">; +defm STTRB : StoreUnprivileged<0b00, 0, 0b00, GPR32, "sttrb">; //--- // (immediate pre-indexed) @@ -1928,41 +2092,41 @@ defm STRWpre : StorePreIdxPseudo; defm STRHHpre : StorePreIdxPseudo; defm STRBBpre : StorePreIdxPseudo; // truncstore i64 -def : Pat<(pre_truncsti32 GPR64:$Rt, am_noindex:$addr, simm9:$off), - (STRWpre_isel (EXTRACT_SUBREG GPR64:$Rt, sub_32), am_noindex:$addr, +def : Pat<(pre_truncsti32 GPR64:$Rt, GPR64sp:$addr, simm9:$off), + (STRWpre_isel (EXTRACT_SUBREG GPR64:$Rt, sub_32), GPR64sp:$addr, simm9:$off)>; -def : Pat<(pre_truncsti16 GPR64:$Rt, am_noindex:$addr, simm9:$off), - (STRHHpre_isel (EXTRACT_SUBREG GPR64:$Rt, sub_32), am_noindex:$addr, +def : Pat<(pre_truncsti16 GPR64:$Rt, GPR64sp:$addr, simm9:$off), + (STRHHpre_isel (EXTRACT_SUBREG GPR64:$Rt, sub_32), GPR64sp:$addr, simm9:$off)>; -def : Pat<(pre_truncsti8 GPR64:$Rt, am_noindex:$addr, simm9:$off), - (STRBBpre_isel (EXTRACT_SUBREG GPR64:$Rt, sub_32), am_noindex:$addr, +def : Pat<(pre_truncsti8 GPR64:$Rt, GPR64sp:$addr, simm9:$off), + (STRBBpre_isel (EXTRACT_SUBREG GPR64:$Rt, sub_32), GPR64sp:$addr, simm9:$off)>; -def : Pat<(pre_store (v8i8 FPR64:$Rt), am_noindex:$addr, simm9:$off), - (STRDpre_isel FPR64:$Rt, am_noindex:$addr, simm9:$off)>; -def : Pat<(pre_store (v4i16 FPR64:$Rt), am_noindex:$addr, simm9:$off), - (STRDpre_isel FPR64:$Rt, am_noindex:$addr, simm9:$off)>; -def : Pat<(pre_store (v2i32 FPR64:$Rt), am_noindex:$addr, simm9:$off), - (STRDpre_isel FPR64:$Rt, am_noindex:$addr, simm9:$off)>; -def : Pat<(pre_store (v2f32 FPR64:$Rt), am_noindex:$addr, simm9:$off), - (STRDpre_isel FPR64:$Rt, am_noindex:$addr, simm9:$off)>; -def : Pat<(pre_store (v1i64 FPR64:$Rt), am_noindex:$addr, simm9:$off), - (STRDpre_isel FPR64:$Rt, am_noindex:$addr, simm9:$off)>; -def : Pat<(pre_store (v1f64 FPR64:$Rt), am_noindex:$addr, simm9:$off), - (STRDpre_isel FPR64:$Rt, am_noindex:$addr, simm9:$off)>; +def : Pat<(pre_store (v8i8 FPR64:$Rt), GPR64sp:$addr, simm9:$off), + (STRDpre_isel FPR64:$Rt, GPR64sp:$addr, simm9:$off)>; +def : Pat<(pre_store (v4i16 FPR64:$Rt), GPR64sp:$addr, simm9:$off), + (STRDpre_isel FPR64:$Rt, GPR64sp:$addr, simm9:$off)>; +def : Pat<(pre_store (v2i32 FPR64:$Rt), GPR64sp:$addr, simm9:$off), + (STRDpre_isel FPR64:$Rt, GPR64sp:$addr, simm9:$off)>; +def : Pat<(pre_store (v2f32 FPR64:$Rt), GPR64sp:$addr, simm9:$off), + (STRDpre_isel FPR64:$Rt, GPR64sp:$addr, simm9:$off)>; +def : Pat<(pre_store (v1i64 FPR64:$Rt), GPR64sp:$addr, simm9:$off), + (STRDpre_isel FPR64:$Rt, GPR64sp:$addr, simm9:$off)>; +def : Pat<(pre_store (v1f64 FPR64:$Rt), GPR64sp:$addr, simm9:$off), + (STRDpre_isel FPR64:$Rt, GPR64sp:$addr, simm9:$off)>; -def : Pat<(pre_store (v16i8 FPR128:$Rt), am_noindex:$addr, simm9:$off), - (STRQpre_isel FPR128:$Rt, am_noindex:$addr, simm9:$off)>; -def : Pat<(pre_store (v8i16 FPR128:$Rt), am_noindex:$addr, simm9:$off), - (STRQpre_isel FPR128:$Rt, am_noindex:$addr, simm9:$off)>; -def : Pat<(pre_store (v4i32 FPR128:$Rt), am_noindex:$addr, simm9:$off), - (STRQpre_isel FPR128:$Rt, am_noindex:$addr, simm9:$off)>; -def : Pat<(pre_store (v4f32 FPR128:$Rt), am_noindex:$addr, simm9:$off), - (STRQpre_isel FPR128:$Rt, am_noindex:$addr, simm9:$off)>; -def : Pat<(pre_store (v2i64 FPR128:$Rt), am_noindex:$addr, simm9:$off), - (STRQpre_isel FPR128:$Rt, am_noindex:$addr, simm9:$off)>; -def : Pat<(pre_store (v2f64 FPR128:$Rt), am_noindex:$addr, simm9:$off), - (STRQpre_isel FPR128:$Rt, am_noindex:$addr, simm9:$off)>; +def : Pat<(pre_store (v16i8 FPR128:$Rt), GPR64sp:$addr, simm9:$off), + (STRQpre_isel FPR128:$Rt, GPR64sp:$addr, simm9:$off)>; +def : Pat<(pre_store (v8i16 FPR128:$Rt), GPR64sp:$addr, simm9:$off), + (STRQpre_isel FPR128:$Rt, GPR64sp:$addr, simm9:$off)>; +def : Pat<(pre_store (v4i32 FPR128:$Rt), GPR64sp:$addr, simm9:$off), + (STRQpre_isel FPR128:$Rt, GPR64sp:$addr, simm9:$off)>; +def : Pat<(pre_store (v4f32 FPR128:$Rt), GPR64sp:$addr, simm9:$off), + (STRQpre_isel FPR128:$Rt, GPR64sp:$addr, simm9:$off)>; +def : Pat<(pre_store (v2i64 FPR128:$Rt), GPR64sp:$addr, simm9:$off), + (STRQpre_isel FPR128:$Rt, GPR64sp:$addr, simm9:$off)>; +def : Pat<(pre_store (v2f64 FPR128:$Rt), GPR64sp:$addr, simm9:$off), + (STRQpre_isel FPR128:$Rt, GPR64sp:$addr, simm9:$off)>; //--- // (immediate post-indexed) @@ -1986,41 +2150,41 @@ defm STRWpost : StorePostIdxPseudo; defm STRHHpost : StorePostIdxPseudo; defm STRBBpost : StorePostIdxPseudo; // truncstore i64 -def : Pat<(post_truncsti32 GPR64:$Rt, am_noindex:$addr, simm9:$off), - (STRWpost_isel (EXTRACT_SUBREG GPR64:$Rt, sub_32), am_noindex:$addr, +def : Pat<(post_truncsti32 GPR64:$Rt, GPR64sp:$addr, simm9:$off), + (STRWpost_isel (EXTRACT_SUBREG GPR64:$Rt, sub_32), GPR64sp:$addr, simm9:$off)>; -def : Pat<(post_truncsti16 GPR64:$Rt, am_noindex:$addr, simm9:$off), - (STRHHpost_isel (EXTRACT_SUBREG GPR64:$Rt, sub_32), am_noindex:$addr, +def : Pat<(post_truncsti16 GPR64:$Rt, GPR64sp:$addr, simm9:$off), + (STRHHpost_isel (EXTRACT_SUBREG GPR64:$Rt, sub_32), GPR64sp:$addr, simm9:$off)>; -def : Pat<(post_truncsti8 GPR64:$Rt, am_noindex:$addr, simm9:$off), - (STRBBpost_isel (EXTRACT_SUBREG GPR64:$Rt, sub_32), am_noindex:$addr, +def : Pat<(post_truncsti8 GPR64:$Rt, GPR64sp:$addr, simm9:$off), + (STRBBpost_isel (EXTRACT_SUBREG GPR64:$Rt, sub_32), GPR64sp:$addr, simm9:$off)>; -def : Pat<(post_store (v8i8 FPR64:$Rt), am_noindex:$addr, simm9:$off), - (STRDpost_isel FPR64:$Rt, am_noindex:$addr, simm9:$off)>; -def : Pat<(post_store (v4i16 FPR64:$Rt), am_noindex:$addr, simm9:$off), - (STRDpost_isel FPR64:$Rt, am_noindex:$addr, simm9:$off)>; -def : Pat<(post_store (v2i32 FPR64:$Rt), am_noindex:$addr, simm9:$off), - (STRDpost_isel FPR64:$Rt, am_noindex:$addr, simm9:$off)>; -def : Pat<(post_store (v2f32 FPR64:$Rt), am_noindex:$addr, simm9:$off), - (STRDpost_isel FPR64:$Rt, am_noindex:$addr, simm9:$off)>; -def : Pat<(post_store (v1i64 FPR64:$Rt), am_noindex:$addr, simm9:$off), - (STRDpost_isel FPR64:$Rt, am_noindex:$addr, simm9:$off)>; -def : Pat<(post_store (v1f64 FPR64:$Rt), am_noindex:$addr, simm9:$off), - (STRDpost_isel FPR64:$Rt, am_noindex:$addr, simm9:$off)>; +def : Pat<(post_store (v8i8 FPR64:$Rt), GPR64sp:$addr, simm9:$off), + (STRDpost_isel FPR64:$Rt, GPR64sp:$addr, simm9:$off)>; +def : Pat<(post_store (v4i16 FPR64:$Rt), GPR64sp:$addr, simm9:$off), + (STRDpost_isel FPR64:$Rt, GPR64sp:$addr, simm9:$off)>; +def : Pat<(post_store (v2i32 FPR64:$Rt), GPR64sp:$addr, simm9:$off), + (STRDpost_isel FPR64:$Rt, GPR64sp:$addr, simm9:$off)>; +def : Pat<(post_store (v2f32 FPR64:$Rt), GPR64sp:$addr, simm9:$off), + (STRDpost_isel FPR64:$Rt, GPR64sp:$addr, simm9:$off)>; +def : Pat<(post_store (v1i64 FPR64:$Rt), GPR64sp:$addr, simm9:$off), + (STRDpost_isel FPR64:$Rt, GPR64sp:$addr, simm9:$off)>; +def : Pat<(post_store (v1f64 FPR64:$Rt), GPR64sp:$addr, simm9:$off), + (STRDpost_isel FPR64:$Rt, GPR64sp:$addr, simm9:$off)>; -def : Pat<(post_store (v16i8 FPR128:$Rt), am_noindex:$addr, simm9:$off), - (STRQpost_isel FPR128:$Rt, am_noindex:$addr, simm9:$off)>; -def : Pat<(post_store (v8i16 FPR128:$Rt), am_noindex:$addr, simm9:$off), - (STRQpost_isel FPR128:$Rt, am_noindex:$addr, simm9:$off)>; -def : Pat<(post_store (v4i32 FPR128:$Rt), am_noindex:$addr, simm9:$off), - (STRQpost_isel FPR128:$Rt, am_noindex:$addr, simm9:$off)>; -def : Pat<(post_store (v4f32 FPR128:$Rt), am_noindex:$addr, simm9:$off), - (STRQpost_isel FPR128:$Rt, am_noindex:$addr, simm9:$off)>; -def : Pat<(post_store (v2i64 FPR128:$Rt), am_noindex:$addr, simm9:$off), - (STRQpost_isel FPR128:$Rt, am_noindex:$addr, simm9:$off)>; -def : Pat<(post_store (v2f64 FPR128:$Rt), am_noindex:$addr, simm9:$off), - (STRQpost_isel FPR128:$Rt, am_noindex:$addr, simm9:$off)>; +def : Pat<(post_store (v16i8 FPR128:$Rt), GPR64sp:$addr, simm9:$off), + (STRQpost_isel FPR128:$Rt, GPR64sp:$addr, simm9:$off)>; +def : Pat<(post_store (v8i16 FPR128:$Rt), GPR64sp:$addr, simm9:$off), + (STRQpost_isel FPR128:$Rt, GPR64sp:$addr, simm9:$off)>; +def : Pat<(post_store (v4i32 FPR128:$Rt), GPR64sp:$addr, simm9:$off), + (STRQpost_isel FPR128:$Rt, GPR64sp:$addr, simm9:$off)>; +def : Pat<(post_store (v4f32 FPR128:$Rt), GPR64sp:$addr, simm9:$off), + (STRQpost_isel FPR128:$Rt, GPR64sp:$addr, simm9:$off)>; +def : Pat<(post_store (v2i64 FPR128:$Rt), GPR64sp:$addr, simm9:$off), + (STRQpost_isel FPR128:$Rt, GPR64sp:$addr, simm9:$off)>; +def : Pat<(post_store (v2f64 FPR128:$Rt), GPR64sp:$addr, simm9:$off), + (STRQpost_isel FPR128:$Rt, GPR64sp:$addr, simm9:$off)>; //===----------------------------------------------------------------------===// // Load/store exclusive instructions. @@ -2845,25 +3009,46 @@ def : Pat<(v1f64 (int_arm64_neon_frsqrte (v1f64 FPR64:$Rn))), // just load it on the floating point unit. // Here are the patterns for 8 and 16-bits to float. // 8-bits -> float. -def : Pat <(f32 (uint_to_fp (i32 (zextloadi8 ro_indexed8:$addr)))), +multiclass UIntToFPROLoadPat { + def : Pat<(DstTy (uint_to_fp (SrcTy + (loadop (ro.Wpat GPR64sp:$Rn, GPR32:$Rm, + ro.Wext:$extend))))), + (UCVTF (INSERT_SUBREG (DstTy (IMPLICIT_DEF)), + (LDRW GPR64sp:$Rn, GPR32:$Rm, ro.Wext:$extend), + sub))>; + + def : Pat<(DstTy (uint_to_fp (SrcTy + (loadop (ro.Xpat GPR64sp:$Rn, GPR64:$Rm, + ro.Wext:$extend))))), + (UCVTF (INSERT_SUBREG (DstTy (IMPLICIT_DEF)), + (LDRX GPR64sp:$Rn, GPR64:$Rm, ro.Xext:$extend), + sub))>; +} + +defm : UIntToFPROLoadPat; +def : Pat <(f32 (uint_to_fp (i32 + (zextloadi8 (am_indexed8 GPR64sp:$Rn, uimm12s1:$offset))))), (UCVTFv1i32 (INSERT_SUBREG (f32 (IMPLICIT_DEF)), - (LDRBro ro_indexed8:$addr), bsub))>; -def : Pat <(f32 (uint_to_fp (i32 (zextloadi8 am_indexed8:$addr)))), + (LDRBui GPR64sp:$Rn, uimm12s1:$offset), bsub))>; +def : Pat <(f32 (uint_to_fp (i32 + (zextloadi8 (am_unscaled8 GPR64sp:$Rn, simm9:$offset))))), (UCVTFv1i32 (INSERT_SUBREG (f32 (IMPLICIT_DEF)), - (LDRBui am_indexed8:$addr), bsub))>; -def : Pat <(f32 (uint_to_fp (i32 (zextloadi8 am_unscaled8:$addr)))), - (UCVTFv1i32 (INSERT_SUBREG (f32 (IMPLICIT_DEF)), - (LDURBi am_unscaled8:$addr), bsub))>; + (LDURBi GPR64sp:$Rn, simm9:$offset), bsub))>; // 16-bits -> float. -def : Pat <(f32 (uint_to_fp (i32 (zextloadi16 ro_indexed16:$addr)))), +defm : UIntToFPROLoadPat; +def : Pat <(f32 (uint_to_fp (i32 + (zextloadi16 (am_indexed16 GPR64sp:$Rn, uimm12s2:$offset))))), (UCVTFv1i32 (INSERT_SUBREG (f32 (IMPLICIT_DEF)), - (LDRHro ro_indexed16:$addr), hsub))>; -def : Pat <(f32 (uint_to_fp (i32 (zextloadi16 am_indexed16:$addr)))), + (LDRHui GPR64sp:$Rn, uimm12s2:$offset), hsub))>; +def : Pat <(f32 (uint_to_fp (i32 + (zextloadi16 (am_unscaled16 GPR64sp:$Rn, simm9:$offset))))), (UCVTFv1i32 (INSERT_SUBREG (f32 (IMPLICIT_DEF)), - (LDRHui am_indexed16:$addr), hsub))>; -def : Pat <(f32 (uint_to_fp (i32 (zextloadi16 am_unscaled16:$addr)))), - (UCVTFv1i32 (INSERT_SUBREG (f32 (IMPLICIT_DEF)), - (LDURHi am_unscaled16:$addr), hsub))>; + (LDURHi GPR64sp:$Rn, simm9:$offset), hsub))>; // 32-bits are handled in target specific dag combine: // performIntToFpCombine. // 64-bits integer to 32-bits floating point, not possible with @@ -2872,35 +3057,38 @@ def : Pat <(f32 (uint_to_fp (i32 (zextloadi16 am_unscaled16:$addr)))), // Here are the patterns for 8, 16, 32, and 64-bits to double. // 8-bits -> double. -def : Pat <(f64 (uint_to_fp (i32 (zextloadi8 ro_indexed8:$addr)))), +defm : UIntToFPROLoadPat; +def : Pat <(f64 (uint_to_fp (i32 + (zextloadi8 (am_indexed8 GPR64sp:$Rn, uimm12s1:$offset))))), (UCVTFv1i64 (INSERT_SUBREG (f64 (IMPLICIT_DEF)), - (LDRBro ro_indexed8:$addr), bsub))>; -def : Pat <(f64 (uint_to_fp (i32 (zextloadi8 am_indexed8:$addr)))), + (LDRBui GPR64sp:$Rn, uimm12s1:$offset), bsub))>; +def : Pat <(f64 (uint_to_fp (i32 + (zextloadi8 (am_unscaled8 GPR64sp:$Rn, simm9:$offset))))), (UCVTFv1i64 (INSERT_SUBREG (f64 (IMPLICIT_DEF)), - (LDRBui am_indexed8:$addr), bsub))>; -def : Pat <(f64 (uint_to_fp (i32 (zextloadi8 am_unscaled8:$addr)))), - (UCVTFv1i64 (INSERT_SUBREG (f64 (IMPLICIT_DEF)), - (LDURBi am_unscaled8:$addr), bsub))>; + (LDURBi GPR64sp:$Rn, simm9:$offset), bsub))>; // 16-bits -> double. -def : Pat <(f64 (uint_to_fp (i32 (zextloadi16 ro_indexed16:$addr)))), +defm : UIntToFPROLoadPat; +def : Pat <(f64 (uint_to_fp (i32 + (zextloadi16 (am_indexed16 GPR64sp:$Rn, uimm12s2:$offset))))), (UCVTFv1i64 (INSERT_SUBREG (f64 (IMPLICIT_DEF)), - (LDRHro ro_indexed16:$addr), hsub))>; -def : Pat <(f64 (uint_to_fp (i32 (zextloadi16 am_indexed16:$addr)))), + (LDRHui GPR64sp:$Rn, uimm12s2:$offset), hsub))>; +def : Pat <(f64 (uint_to_fp (i32 + (zextloadi16 (am_unscaled16 GPR64sp:$Rn, simm9:$offset))))), (UCVTFv1i64 (INSERT_SUBREG (f64 (IMPLICIT_DEF)), - (LDRHui am_indexed16:$addr), hsub))>; -def : Pat <(f64 (uint_to_fp (i32 (zextloadi16 am_unscaled16:$addr)))), - (UCVTFv1i64 (INSERT_SUBREG (f64 (IMPLICIT_DEF)), - (LDURHi am_unscaled16:$addr), hsub))>; + (LDURHi GPR64sp:$Rn, simm9:$offset), hsub))>; // 32-bits -> double. -def : Pat <(f64 (uint_to_fp (i32 (load ro_indexed32:$addr)))), +defm : UIntToFPROLoadPat; +def : Pat <(f64 (uint_to_fp (i32 + (load (am_indexed32 GPR64sp:$Rn, uimm12s4:$offset))))), (UCVTFv1i64 (INSERT_SUBREG (f64 (IMPLICIT_DEF)), - (LDRSro ro_indexed32:$addr), ssub))>; -def : Pat <(f64 (uint_to_fp (i32 (load am_indexed32:$addr)))), + (LDRSui GPR64sp:$Rn, uimm12s4:$offset), ssub))>; +def : Pat <(f64 (uint_to_fp (i32 + (load (am_unscaled32 GPR64sp:$Rn, simm9:$offset))))), (UCVTFv1i64 (INSERT_SUBREG (f64 (IMPLICIT_DEF)), - (LDRSui am_indexed32:$addr), ssub))>; -def : Pat <(f64 (uint_to_fp (i32 (load am_unscaled32:$addr)))), - (UCVTFv1i64 (INSERT_SUBREG (f64 (IMPLICIT_DEF)), - (LDURSi am_unscaled32:$addr), ssub))>; + (LDURSi GPR64sp:$Rn, simm9:$offset), ssub))>; // 64-bits -> double are handled in target specific dag combine: // performIntToFpCombine. @@ -4226,70 +4414,50 @@ def : InstAlias<"uxtl2 $dst.2d, $src1.4s", // and still being faster. // However, this is not good for code size. // 8-bits -> float. 2 sizes step-up. -def : Pat <(f32 (sint_to_fp (i32 (sextloadi8 ro_indexed8:$addr)))), - (SCVTFv1i32 (f32 (EXTRACT_SUBREG - (SSHLLv4i16_shift - (f64 - (EXTRACT_SUBREG - (SSHLLv8i8_shift - (INSERT_SUBREG (f64 (IMPLICIT_DEF)), - (LDRBro ro_indexed8:$addr), - bsub), - 0), - dsub)), +class SExtLoadi8CVTf32Pat + : Pat<(f32 (sint_to_fp (i32 (sextloadi8 addrmode)))), + (SCVTFv1i32 (f32 (EXTRACT_SUBREG + (SSHLLv4i16_shift + (f64 + (EXTRACT_SUBREG + (SSHLLv8i8_shift + (INSERT_SUBREG (f64 (IMPLICIT_DEF)), + INST, + bsub), + 0), + dsub)), 0), - ssub)))>, Requires<[NotForCodeSize]>; -def : Pat <(f32 (sint_to_fp (i32 (sextloadi8 am_indexed8:$addr)))), - (SCVTFv1i32 (f32 (EXTRACT_SUBREG - (SSHLLv4i16_shift - (f64 - (EXTRACT_SUBREG - (SSHLLv8i8_shift - (INSERT_SUBREG (f64 (IMPLICIT_DEF)), - (LDRBui am_indexed8:$addr), - bsub), - 0), - dsub)), - 0), - ssub)))>, Requires<[NotForCodeSize]>; -def : Pat <(f32 (sint_to_fp (i32 (sextloadi8 am_unscaled8:$addr)))), - (SCVTFv1i32 (f32 (EXTRACT_SUBREG - (SSHLLv4i16_shift - (f64 - (EXTRACT_SUBREG - (SSHLLv8i8_shift - (INSERT_SUBREG (f64 (IMPLICIT_DEF)), - (LDURBi am_unscaled8:$addr), - bsub), - 0), - dsub)), - 0), - ssub)))>, Requires<[NotForCodeSize]>; + ssub)))>, Requires<[NotForCodeSize]>; + +def : SExtLoadi8CVTf32Pat<(ro8.Wpat GPR64sp:$Rn, GPR32:$Rm, ro8.Wext:$ext), + (LDRBroW GPR64sp:$Rn, GPR32:$Rm, ro8.Wext:$ext)>; +def : SExtLoadi8CVTf32Pat<(ro8.Xpat GPR64sp:$Rn, GPR64:$Rm, ro8.Xext:$ext), + (LDRBroX GPR64sp:$Rn, GPR64:$Rm, ro8.Xext:$ext)>; +def : SExtLoadi8CVTf32Pat<(am_indexed8 GPR64sp:$Rn, uimm12s1:$offset), + (LDRBui GPR64sp:$Rn, uimm12s1:$offset)>; +def : SExtLoadi8CVTf32Pat<(am_unscaled8 GPR64sp:$Rn, simm9:$offset), + (LDURBi GPR64sp:$Rn, simm9:$offset)>; + // 16-bits -> float. 1 size step-up. -def : Pat <(f32 (sint_to_fp (i32 (sextloadi16 ro_indexed16:$addr)))), - (SCVTFv1i32 (f32 (EXTRACT_SUBREG - (SSHLLv4i16_shift +class SExtLoadi16CVTf32Pat + : Pat<(f32 (sint_to_fp (i32 (sextloadi16 addrmode)))), + (SCVTFv1i32 (f32 (EXTRACT_SUBREG + (SSHLLv4i16_shift (INSERT_SUBREG (f64 (IMPLICIT_DEF)), - (LDRHro ro_indexed16:$addr), - hsub), - 0), - ssub)))>, Requires<[NotForCodeSize]>; -def : Pat <(f32 (sint_to_fp (i32 (sextloadi16 am_indexed16:$addr)))), - (SCVTFv1i32 (f32 (EXTRACT_SUBREG - (SSHLLv4i16_shift - (INSERT_SUBREG (f64 (IMPLICIT_DEF)), - (LDRHui am_indexed16:$addr), - hsub), - 0), - ssub)))>, Requires<[NotForCodeSize]>; -def : Pat <(f32 (sint_to_fp (i32 (sextloadi16 am_unscaled16:$addr)))), - (SCVTFv1i32 (f32 (EXTRACT_SUBREG - (SSHLLv4i16_shift - (INSERT_SUBREG (f64 (IMPLICIT_DEF)), - (LDURHi am_unscaled16:$addr), - hsub), - 0), - ssub)))>, Requires<[NotForCodeSize]>; + INST, + hsub), + 0), + ssub)))>, Requires<[NotForCodeSize]>; + +def : SExtLoadi16CVTf32Pat<(ro16.Wpat GPR64sp:$Rn, GPR32:$Rm, ro16.Wext:$ext), + (LDRHroW GPR64sp:$Rn, GPR32:$Rm, ro16.Wext:$ext)>; +def : SExtLoadi16CVTf32Pat<(ro16.Xpat GPR64sp:$Rn, GPR64:$Rm, ro16.Xext:$ext), + (LDRHroX GPR64sp:$Rn, GPR64:$Rm, ro16.Xext:$ext)>; +def : SExtLoadi16CVTf32Pat<(am_indexed16 GPR64sp:$Rn, uimm12s2:$offset), + (LDRHui GPR64sp:$Rn, uimm12s2:$offset)>; +def : SExtLoadi16CVTf32Pat<(am_unscaled16 GPR64sp:$Rn, simm9:$offset), + (LDURHi GPR64sp:$Rn, simm9:$offset)>; + // 32-bits to 32-bits are handled in target specific dag combine: // performIntToFpCombine. // 64-bits integer to 32-bits floating point, not possible with @@ -4299,70 +4467,49 @@ def : Pat <(f32 (sint_to_fp (i32 (sextloadi16 am_unscaled16:$addr)))), // Here are the patterns for 8, 16, 32, and 64-bits to double. // 8-bits -> double. 3 size step-up: give up. // 16-bits -> double. 2 size step. -def : Pat <(f64 (sint_to_fp (i32 (sextloadi16 ro_indexed16:$addr)))), +class SExtLoadi16CVTf64Pat + : Pat <(f64 (sint_to_fp (i32 (sextloadi16 addrmode)))), (SCVTFv1i64 (f64 (EXTRACT_SUBREG (SSHLLv2i32_shift (f64 (EXTRACT_SUBREG (SSHLLv4i16_shift (INSERT_SUBREG (f64 (IMPLICIT_DEF)), - (LDRHro ro_indexed16:$addr), - hsub), + INST, + hsub), 0), dsub)), 0), dsub)))>, Requires<[NotForCodeSize]>; -def : Pat <(f64 (sint_to_fp (i32 (sextloadi16 am_indexed16:$addr)))), - (SCVTFv1i64 (f64 (EXTRACT_SUBREG - (SSHLLv2i32_shift - (f64 - (EXTRACT_SUBREG - (SSHLLv4i16_shift - (INSERT_SUBREG (f64 (IMPLICIT_DEF)), - (LDRHui am_indexed16:$addr), - hsub), - 0), - dsub)), - 0), - dsub)))>, Requires<[NotForCodeSize]>; -def : Pat <(f64 (sint_to_fp (i32 (sextloadi16 am_unscaled16:$addr)))), - (SCVTFv1i64 (f64 (EXTRACT_SUBREG - (SSHLLv2i32_shift - (f64 - (EXTRACT_SUBREG - (SSHLLv4i16_shift - (INSERT_SUBREG (f64 (IMPLICIT_DEF)), - (LDURHi am_unscaled16:$addr), - hsub), - 0), - dsub)), - 0), - dsub)))>, Requires<[NotForCodeSize]>; + +def : SExtLoadi16CVTf64Pat<(ro16.Wpat GPR64sp:$Rn, GPR32:$Rm, ro16.Wext:$ext), + (LDRHroW GPR64sp:$Rn, GPR32:$Rm, ro16.Wext:$ext)>; +def : SExtLoadi16CVTf64Pat<(ro16.Xpat GPR64sp:$Rn, GPR64:$Rm, ro16.Xext:$ext), + (LDRHroX GPR64sp:$Rn, GPR64:$Rm, ro16.Xext:$ext)>; +def : SExtLoadi16CVTf64Pat<(am_indexed16 GPR64sp:$Rn, uimm12s2:$offset), + (LDRHui GPR64sp:$Rn, uimm12s2:$offset)>; +def : SExtLoadi16CVTf64Pat<(am_unscaled16 GPR64sp:$Rn, simm9:$offset), + (LDURHi GPR64sp:$Rn, simm9:$offset)>; // 32-bits -> double. 1 size step-up. -def : Pat <(f64 (sint_to_fp (i32 (load ro_indexed32:$addr)))), +class SExtLoadi32CVTf64Pat + : Pat <(f64 (sint_to_fp (i32 (load addrmode)))), (SCVTFv1i64 (f64 (EXTRACT_SUBREG (SSHLLv2i32_shift (INSERT_SUBREG (f64 (IMPLICIT_DEF)), - (LDRSro ro_indexed32:$addr), - ssub), - 0), - dsub)))>, Requires<[NotForCodeSize]>; -def : Pat <(f64 (sint_to_fp (i32 (load am_indexed32:$addr)))), - (SCVTFv1i64 (f64 (EXTRACT_SUBREG - (SSHLLv2i32_shift - (INSERT_SUBREG (f64 (IMPLICIT_DEF)), - (LDRSui am_indexed32:$addr), - ssub), - 0), - dsub)))>, Requires<[NotForCodeSize]>; -def : Pat <(f64 (sint_to_fp (i32 (load am_unscaled32:$addr)))), - (SCVTFv1i64 (f64 (EXTRACT_SUBREG - (SSHLLv2i32_shift - (INSERT_SUBREG (f64 (IMPLICIT_DEF)), - (LDURSi am_unscaled32:$addr), - ssub), + INST, + ssub), 0), dsub)))>, Requires<[NotForCodeSize]>; + +def : SExtLoadi32CVTf64Pat<(ro32.Wpat GPR64sp:$Rn, GPR32:$Rm, ro32.Wext:$ext), + (LDRSroW GPR64sp:$Rn, GPR32:$Rm, ro32.Wext:$ext)>; +def : SExtLoadi32CVTf64Pat<(ro32.Xpat GPR64sp:$Rn, GPR64:$Rm, ro32.Xext:$ext), + (LDRSroX GPR64sp:$Rn, GPR64:$Rm, ro32.Xext:$ext)>; +def : SExtLoadi32CVTf64Pat<(am_indexed32 GPR64sp:$Rn, uimm12s4:$offset), + (LDRSui GPR64sp:$Rn, uimm12s4:$offset)>; +def : SExtLoadi32CVTf64Pat<(am_unscaled32 GPR64sp:$Rn, simm9:$offset), + (LDURSi GPR64sp:$Rn, simm9:$offset)>; + // 64-bits -> double are handled in target specific dag combine: // performIntToFpCombine. @@ -4381,7 +4528,7 @@ defm ST3 : SIMDSt3Multiple<"st3">; defm ST4 : SIMDSt4Multiple<"st4">; class Ld1Pat - : Pat<(ty (load am_simdnoindex:$vaddr)), (INST am_simdnoindex:$vaddr)>; + : Pat<(ty (load GPR64sp:$Rn)), (INST GPR64sp:$Rn)>; def : Ld1Pat; def : Ld1Pat; @@ -4393,8 +4540,8 @@ def : Ld1Pat; def : Ld1Pat; class St1Pat - : Pat<(store ty:$Vt, am_simdnoindex:$vaddr), - (INST ty:$Vt, am_simdnoindex:$vaddr)>; + : Pat<(store ty:$Vt, GPR64sp:$Rn), + (INST ty:$Vt, GPR64sp:$Rn)>; def : St1Pat; def : St1Pat; @@ -4432,37 +4579,37 @@ defm LD4 : SIMDLdSingleSTied<1, 0b101, 0b00, "ld4", VecListFours, GPR64pi16>; defm LD4 : SIMDLdSingleDTied<1, 0b101, 0b01, "ld4", VecListFourd, GPR64pi32>; } -def : Pat<(v8i8 (ARM64dup (i32 (extloadi8 am_simdnoindex:$vaddr)))), - (LD1Rv8b am_simdnoindex:$vaddr)>; -def : Pat<(v16i8 (ARM64dup (i32 (extloadi8 am_simdnoindex:$vaddr)))), - (LD1Rv16b am_simdnoindex:$vaddr)>; -def : Pat<(v4i16 (ARM64dup (i32 (extloadi16 am_simdnoindex:$vaddr)))), - (LD1Rv4h am_simdnoindex:$vaddr)>; -def : Pat<(v8i16 (ARM64dup (i32 (extloadi16 am_simdnoindex:$vaddr)))), - (LD1Rv8h am_simdnoindex:$vaddr)>; -def : Pat<(v2i32 (ARM64dup (i32 (load am_simdnoindex:$vaddr)))), - (LD1Rv2s am_simdnoindex:$vaddr)>; -def : Pat<(v4i32 (ARM64dup (i32 (load am_simdnoindex:$vaddr)))), - (LD1Rv4s am_simdnoindex:$vaddr)>; -def : Pat<(v2i64 (ARM64dup (i64 (load am_simdnoindex:$vaddr)))), - (LD1Rv2d am_simdnoindex:$vaddr)>; -def : Pat<(v1i64 (ARM64dup (i64 (load am_simdnoindex:$vaddr)))), - (LD1Rv1d am_simdnoindex:$vaddr)>; +def : Pat<(v8i8 (ARM64dup (i32 (extloadi8 GPR64sp:$Rn)))), + (LD1Rv8b GPR64sp:$Rn)>; +def : Pat<(v16i8 (ARM64dup (i32 (extloadi8 GPR64sp:$Rn)))), + (LD1Rv16b GPR64sp:$Rn)>; +def : Pat<(v4i16 (ARM64dup (i32 (extloadi16 GPR64sp:$Rn)))), + (LD1Rv4h GPR64sp:$Rn)>; +def : Pat<(v8i16 (ARM64dup (i32 (extloadi16 GPR64sp:$Rn)))), + (LD1Rv8h GPR64sp:$Rn)>; +def : Pat<(v2i32 (ARM64dup (i32 (load GPR64sp:$Rn)))), + (LD1Rv2s GPR64sp:$Rn)>; +def : Pat<(v4i32 (ARM64dup (i32 (load GPR64sp:$Rn)))), + (LD1Rv4s GPR64sp:$Rn)>; +def : Pat<(v2i64 (ARM64dup (i64 (load GPR64sp:$Rn)))), + (LD1Rv2d GPR64sp:$Rn)>; +def : Pat<(v1i64 (ARM64dup (i64 (load GPR64sp:$Rn)))), + (LD1Rv1d GPR64sp:$Rn)>; // Grab the floating point version too -def : Pat<(v2f32 (ARM64dup (f32 (load am_simdnoindex:$vaddr)))), - (LD1Rv2s am_simdnoindex:$vaddr)>; -def : Pat<(v4f32 (ARM64dup (f32 (load am_simdnoindex:$vaddr)))), - (LD1Rv4s am_simdnoindex:$vaddr)>; -def : Pat<(v2f64 (ARM64dup (f64 (load am_simdnoindex:$vaddr)))), - (LD1Rv2d am_simdnoindex:$vaddr)>; -def : Pat<(v1f64 (ARM64dup (f64 (load am_simdnoindex:$vaddr)))), - (LD1Rv1d am_simdnoindex:$vaddr)>; +def : Pat<(v2f32 (ARM64dup (f32 (load GPR64sp:$Rn)))), + (LD1Rv2s GPR64sp:$Rn)>; +def : Pat<(v4f32 (ARM64dup (f32 (load GPR64sp:$Rn)))), + (LD1Rv4s GPR64sp:$Rn)>; +def : Pat<(v2f64 (ARM64dup (f64 (load GPR64sp:$Rn)))), + (LD1Rv2d GPR64sp:$Rn)>; +def : Pat<(v1f64 (ARM64dup (f64 (load GPR64sp:$Rn)))), + (LD1Rv1d GPR64sp:$Rn)>; class Ld1Lane128Pat : Pat<(vector_insert (VTy VecListOne128:$Rd), - (STy (scalar_load am_simdnoindex:$vaddr)), VecIndex:$idx), - (LD1 VecListOne128:$Rd, VecIndex:$idx, am_simdnoindex:$vaddr)>; + (STy (scalar_load GPR64sp:$Rn)), VecIndex:$idx), + (LD1 VecListOne128:$Rd, VecIndex:$idx, GPR64sp:$Rn)>; def : Ld1Lane128Pat; def : Ld1Lane128Pat; @@ -4474,10 +4621,10 @@ def : Ld1Lane128Pat; class Ld1Lane64Pat : Pat<(vector_insert (VTy VecListOne64:$Rd), - (STy (scalar_load am_simdnoindex:$vaddr)), VecIndex:$idx), + (STy (scalar_load GPR64sp:$Rn)), VecIndex:$idx), (EXTRACT_SUBREG (LD1 (SUBREG_TO_REG (i32 0), VecListOne64:$Rd, dsub), - VecIndex:$idx, am_simdnoindex:$vaddr), + VecIndex:$idx, GPR64sp:$Rn), dsub)>; def : Ld1Lane64Pat; @@ -4497,13 +4644,13 @@ defm ST1 : SIMDStSingleH<0, 0b010, 0, "st1", VecListOneh, GPR64pi2>; defm ST1 : SIMDStSingleS<0, 0b100, 0b00, "st1", VecListOnes, GPR64pi4>; defm ST1 : SIMDStSingleD<0, 0b100, 0b01, "st1", VecListOned, GPR64pi8>; -let AddedComplexity = 8 in +let AddedComplexity = 15 in class St1Lane128Pat : Pat<(scalar_store (STy (vector_extract (VTy VecListOne128:$Vt), VecIndex:$idx)), - am_simdnoindex:$vaddr), - (ST1 VecListOne128:$Vt, VecIndex:$idx, am_simdnoindex:$vaddr)>; + GPR64sp:$Rn), + (ST1 VecListOne128:$Vt, VecIndex:$idx, GPR64sp:$Rn)>; def : St1Lane128Pat; def : St1Lane128Pat; @@ -4512,14 +4659,14 @@ def : St1Lane128Pat; def : St1Lane128Pat; def : St1Lane128Pat; -let AddedComplexity = 8 in +let AddedComplexity = 15 in class St1Lane64Pat : Pat<(scalar_store (STy (vector_extract (VTy VecListOne64:$Vt), VecIndex:$idx)), - am_simdnoindex:$vaddr), + GPR64sp:$Rn), (ST1 (SUBREG_TO_REG (i32 0), VecListOne64:$Vt, dsub), - VecIndex:$idx, am_simdnoindex:$vaddr)>; + VecIndex:$idx, GPR64sp:$Rn)>; def : St1Lane64Pat; def : St1Lane64Pat; @@ -4531,15 +4678,15 @@ multiclass St1LanePost64Pat { def : Pat<(scalar_store (STy (vector_extract (VTy VecListOne64:$Vt), VecIndex:$idx)), - am_simdnoindex:$vaddr, offset), + GPR64sp:$Rn, offset), (ST1 (SUBREG_TO_REG (i32 0), VecListOne64:$Vt, dsub), - VecIndex:$idx, am_simdnoindex:$vaddr, XZR)>; + VecIndex:$idx, GPR64sp:$Rn, XZR)>; def : Pat<(scalar_store (STy (vector_extract (VTy VecListOne64:$Vt), VecIndex:$idx)), - am_simdnoindex:$vaddr, GPR64:$Rm), + GPR64sp:$Rn, GPR64:$Rm), (ST1 (SUBREG_TO_REG (i32 0), VecListOne64:$Vt, dsub), - VecIndex:$idx, am_simdnoindex:$vaddr, $Rm)>; + VecIndex:$idx, GPR64sp:$Rn, $Rm)>; } defm : St1LanePost64Pat; @@ -4555,13 +4702,13 @@ multiclass St1LanePost128Pat { def : Pat<(scalar_store (STy (vector_extract (VTy VecListOne128:$Vt), VecIndex:$idx)), - am_simdnoindex:$vaddr, offset), - (ST1 VecListOne128:$Vt, VecIndex:$idx, am_simdnoindex:$vaddr, XZR)>; + GPR64sp:$Rn, offset), + (ST1 VecListOne128:$Vt, VecIndex:$idx, GPR64sp:$Rn, XZR)>; def : Pat<(scalar_store (STy (vector_extract (VTy VecListOne128:$Vt), VecIndex:$idx)), - am_simdnoindex:$vaddr, GPR64:$Rm), - (ST1 VecListOne128:$Vt, VecIndex:$idx, am_simdnoindex:$vaddr, $Rm)>; + GPR64sp:$Rn, GPR64:$Rm), + (ST1 VecListOne128:$Vt, VecIndex:$idx, GPR64sp:$Rn, $Rm)>; } defm : St1LanePost128Pat { def GPR32sponly : RegisterClass<"ARM64", [i32], 32, (add WSP)>; def GPR64sponly : RegisterClass<"ARM64", [i64], 64, (add SP)>; +def GPR64spPlus0Operand : AsmOperandClass { + let Name = "GPR64sp0"; + let RenderMethod = "addRegOperands"; + let ParserMethod = "tryParseGPR64sp0Operand"; +} + +def GPR64sp0 : RegisterOperand { + let ParserMatchClass = GPR64spPlus0Operand; +} + // GPR register classes which include WZR/XZR AND SP/WSP. This is not a // constraint used by any instructions, it is used as a common super-class. def GPR32all : RegisterClass<"ARM64", [i32], 32, (add GPR32common, WZR, WSP)>; diff --git a/lib/Target/ARM64/AsmParser/ARM64AsmParser.cpp b/lib/Target/ARM64/AsmParser/ARM64AsmParser.cpp index cc301f60ede..982690fe86c 100644 --- a/lib/Target/ARM64/AsmParser/ARM64AsmParser.cpp +++ b/lib/Target/ARM64/AsmParser/ARM64AsmParser.cpp @@ -57,7 +57,6 @@ private: int tryParseRegister(); int tryMatchVectorRegister(StringRef &Kind, bool expected); bool parseRegister(OperandVector &Operands); - bool parseMemory(OperandVector &Operands); bool parseSymbolicImmVal(const MCExpr *&ImmVal); bool parseVectorList(OperandVector &Operands); bool parseOperand(OperandVector &Operands, bool isCondCode, @@ -86,7 +85,6 @@ private: /// } OperandMatchResultTy tryParseOptionalShiftExtend(OperandVector &Operands); - OperandMatchResultTy tryParseNoIndexMemory(OperandVector &Operands); OperandMatchResultTy tryParseBarrierOperand(OperandVector &Operands); OperandMatchResultTy tryParseMRSSystemRegister(OperandVector &Operands); OperandMatchResultTy tryParseSysReg(OperandVector &Operands); @@ -96,6 +94,7 @@ private: OperandMatchResultTy tryParseAdrLabel(OperandVector &Operands); OperandMatchResultTy tryParseFPImm(OperandVector &Operands); OperandMatchResultTy tryParseAddSubImm(OperandVector &Operands); + OperandMatchResultTy tryParseGPR64sp0Operand(OperandVector &Operands); bool tryParseVectorRegister(OperandVector &Operands); public: @@ -133,18 +132,11 @@ namespace { /// ARM64Operand - Instances of this class represent a parsed ARM64 machine /// instruction. class ARM64Operand : public MCParsedAsmOperand { -public: - enum MemIdxKindTy { - ImmediateOffset, // pre-indexed, no writeback - RegisterOffset // register offset, with optional extend - }; - private: enum KindTy { k_Immediate, k_ShiftedImm, k_CondCode, - k_Memory, k_Register, k_VectorList, k_VectorIndex, @@ -157,7 +149,7 @@ private: k_Barrier } Kind; - SMLoc StartLoc, EndLoc, OffsetLoc; + SMLoc StartLoc, EndLoc; struct TokOp { const char *Data; @@ -221,22 +213,13 @@ private: struct ShiftExtendOp { ARM64_AM::ShiftExtendType Type; unsigned Amount; + bool HasExplicitAmount; }; struct ExtendOp { unsigned Val; }; - // This is for all forms of ARM64 address expressions - struct MemOp { - unsigned BaseRegNum, OffsetRegNum; - ARM64_AM::ShiftExtendType ExtType; - unsigned ShiftVal; - bool ExplicitShift; - const MCExpr *OffsetImm; - MemIdxKindTy Mode; - }; - union { struct TokOp Tok; struct RegOp Reg; @@ -251,7 +234,6 @@ private: struct SysCRImmOp SysCRImm; struct PrefetchOp Prefetch; struct ShiftExtendOp ShiftExtend; - struct MemOp Mem; }; // Keep the MCContext around as the MCExprs may need manipulated during @@ -303,9 +285,6 @@ public: case k_Prefetch: Prefetch = o.Prefetch; break; - case k_Memory: - Mem = o.Mem; - break; case k_ShiftExtend: ShiftExtend = o.ShiftExtend; break; @@ -316,8 +295,6 @@ public: SMLoc getStartLoc() const override { return StartLoc; } /// getEndLoc - Get the location of the last token of this operand. SMLoc getEndLoc() const override { return EndLoc; } - /// getOffsetLoc - Get the location of the offset of this memory operand. - SMLoc getOffsetLoc() const { return OffsetLoc; } StringRef getToken() const { assert(Kind == k_Token && "Invalid access!"); @@ -409,7 +386,13 @@ public: return ShiftExtend.Amount; } + bool hasShiftExtendAmount() const { + assert(Kind == k_ShiftExtend && "Invalid access!"); + return ShiftExtend.HasExplicitAmount; + } + bool isImm() const override { return Kind == k_Immediate; } + bool isMem() const override { return false; } bool isSImm9() const { if (!isImm()) return false; @@ -446,6 +429,52 @@ public: int64_t Val = MCE->getValue(); return (Val >= -1024 && Val <= 1008 && (Val & 15) == 0); } + + bool isSymbolicUImm12Offset(const MCExpr *Expr, unsigned Scale) const { + ARM64MCExpr::VariantKind ELFRefKind; + MCSymbolRefExpr::VariantKind DarwinRefKind; + int64_t Addend; + if (!ARM64AsmParser::classifySymbolRef(Expr, ELFRefKind, DarwinRefKind, + Addend)) { + // If we don't understand the expression, assume the best and + // let the fixup and relocation code deal with it. + return true; + } + + if (DarwinRefKind == MCSymbolRefExpr::VK_PAGEOFF || + ELFRefKind == ARM64MCExpr::VK_LO12 || + ELFRefKind == ARM64MCExpr::VK_GOT_LO12 || + ELFRefKind == ARM64MCExpr::VK_DTPREL_LO12 || + ELFRefKind == ARM64MCExpr::VK_DTPREL_LO12_NC || + ELFRefKind == ARM64MCExpr::VK_TPREL_LO12 || + ELFRefKind == ARM64MCExpr::VK_TPREL_LO12_NC || + ELFRefKind == ARM64MCExpr::VK_GOTTPREL_LO12_NC || + ELFRefKind == ARM64MCExpr::VK_TLSDESC_LO12) { + // Note that we don't range-check the addend. It's adjusted modulo page + // size when converted, so there is no "out of range" condition when using + // @pageoff. + return Addend >= 0 && (Addend % Scale) == 0; + } else if (DarwinRefKind == MCSymbolRefExpr::VK_GOTPAGEOFF || + DarwinRefKind == MCSymbolRefExpr::VK_TLVPPAGEOFF) { + // @gotpageoff/@tlvppageoff can only be used directly, not with an addend. + return Addend == 0; + } + + return false; + } + + template bool isUImm12Offset() const { + if (!isImm()) + return false; + + const MCConstantExpr *MCE = dyn_cast(getImm()); + if (!MCE) + return isSymbolicUImm12Offset(getImm(), Scale); + + int64_t Val = MCE->getValue(); + return (Val % Scale) == 0 && Val >= 0 && (Val / Scale) < 0x1000; + } + bool isImm0_7() const { if (!isImm()) return false; @@ -826,6 +855,11 @@ public: ARM64MCRegisterClasses[ARM64::GPR64RegClassID].contains(Reg.RegNum); } + bool isGPR64sp0() const { + return Kind == k_Register && !Reg.isVector && + ARM64MCRegisterClasses[ARM64::GPR64spRegClassID].contains(Reg.RegNum); + } + /// Is this a vector list with the type implicit (presumably attached to the /// instruction itself)? template bool isImplicitlyTypedVectorList() const { @@ -863,7 +897,6 @@ public: bool isTokenEqual(StringRef Str) const { return Kind == k_Token && getToken() == Str; } - bool isMem() const override { return Kind == k_Memory; } bool isSysCR() const { return Kind == k_SysCR; } bool isPrefetch() const { return Kind == k_Prefetch; } bool isShiftExtend() const { return Kind == k_ShiftExtend; } @@ -903,6 +936,24 @@ public: getShiftExtendAmount() <= 4; } + template bool isMemXExtend() const { + if (!isExtend()) + return false; + ARM64_AM::ShiftExtendType ET = getShiftExtendType(); + return (ET == ARM64_AM::LSL || ET == ARM64_AM::SXTX) && + (getShiftExtendAmount() == Log2_32(Width / 8) || + getShiftExtendAmount() == 0); + } + + template bool isMemWExtend() const { + if (!isExtend()) + return false; + ARM64_AM::ShiftExtendType ET = getShiftExtendType(); + return (ET == ARM64_AM::UXTW || ET == ARM64_AM::SXTW) && + (getShiftExtendAmount() == Log2_32(Width / 8) || + getShiftExtendAmount() == 0); + } + template bool isArithmeticShifter() const { if (!isShifter()) @@ -978,180 +1029,14 @@ public: return getShiftExtendType() == ARM64_AM::MSL && (Shift == 8 || Shift == 16); } - bool isMemoryRegisterOffset8() const { - return isMem() && Mem.Mode == RegisterOffset && Mem.ShiftVal == 0; - } - - bool isMemoryRegisterOffset16() const { - return isMem() && Mem.Mode == RegisterOffset && - (Mem.ShiftVal == 0 || Mem.ShiftVal == 1); - } - - bool isMemoryRegisterOffset32() const { - return isMem() && Mem.Mode == RegisterOffset && - (Mem.ShiftVal == 0 || Mem.ShiftVal == 2); - } - - bool isMemoryRegisterOffset64() const { - return isMem() && Mem.Mode == RegisterOffset && - (Mem.ShiftVal == 0 || Mem.ShiftVal == 3); - } - - bool isMemoryRegisterOffset128() const { - return isMem() && Mem.Mode == RegisterOffset && - (Mem.ShiftVal == 0 || Mem.ShiftVal == 4); - } - - bool isMemoryUnscaled() const { - if (!isMem()) - return false; - if (Mem.Mode != ImmediateOffset) - return false; - if (!Mem.OffsetImm) - return true; - // Make sure the immediate value is valid. - const MCConstantExpr *CE = dyn_cast(Mem.OffsetImm); - if (!CE) - return false; - // The offset must fit in a signed 9-bit unscaled immediate. - int64_t Value = CE->getValue(); - return (Value >= -256 && Value < 256); - } // Fallback unscaled operands are for aliases of LDR/STR that fall back // to LDUR/STUR when the offset is not legal for the former but is for // the latter. As such, in addition to checking for being a legal unscaled // address, also check that it is not a legal scaled address. This avoids // ambiguity in the matcher. - bool isMemoryUnscaledFB8() const { - return isMemoryUnscaled() && !isMemoryIndexed8(); - } - bool isMemoryUnscaledFB16() const { - return isMemoryUnscaled() && !isMemoryIndexed16(); - } - bool isMemoryUnscaledFB32() const { - return isMemoryUnscaled() && !isMemoryIndexed32(); - } - bool isMemoryUnscaledFB64() const { - return isMemoryUnscaled() && !isMemoryIndexed64(); - } - bool isMemoryUnscaledFB128() const { - return isMemoryUnscaled() && !isMemoryIndexed128(); - } - bool isMemoryIndexed(unsigned Scale) const { - if (!isMem()) - return false; - if (Mem.Mode != ImmediateOffset) - return false; - if (!Mem.OffsetImm) - return true; - // Make sure the immediate value is valid. - const MCConstantExpr *CE = dyn_cast(Mem.OffsetImm); - - if (CE) { - // The offset must be a positive multiple of the scale and in range of - // encoding with a 12-bit immediate. - int64_t Value = CE->getValue(); - return (Value >= 0 && (Value % Scale) == 0 && Value <= (4095 * Scale)); - } - - // If it's not a constant, check for some expressions we know. - const MCExpr *Expr = Mem.OffsetImm; - ARM64MCExpr::VariantKind ELFRefKind; - MCSymbolRefExpr::VariantKind DarwinRefKind; - int64_t Addend; - if (!ARM64AsmParser::classifySymbolRef(Expr, ELFRefKind, DarwinRefKind, - Addend)) { - // If we don't understand the expression, assume the best and - // let the fixup and relocation code deal with it. - return true; - } - - if (DarwinRefKind == MCSymbolRefExpr::VK_PAGEOFF || - ELFRefKind == ARM64MCExpr::VK_LO12 || - ELFRefKind == ARM64MCExpr::VK_GOT_LO12 || - ELFRefKind == ARM64MCExpr::VK_DTPREL_LO12 || - ELFRefKind == ARM64MCExpr::VK_DTPREL_LO12_NC || - ELFRefKind == ARM64MCExpr::VK_TPREL_LO12 || - ELFRefKind == ARM64MCExpr::VK_TPREL_LO12_NC || - ELFRefKind == ARM64MCExpr::VK_GOTTPREL_LO12_NC || - ELFRefKind == ARM64MCExpr::VK_TLSDESC_LO12) { - // Note that we don't range-check the addend. It's adjusted modulo page - // size when converted, so there is no "out of range" condition when using - // @pageoff. - return Addend >= 0 && (Addend % Scale) == 0; - } else if (DarwinRefKind == MCSymbolRefExpr::VK_GOTPAGEOFF || - DarwinRefKind == MCSymbolRefExpr::VK_TLVPPAGEOFF) { - // @gotpageoff/@tlvppageoff can only be used directly, not with an addend. - return Addend == 0; - } - - return false; - } - bool isMemoryIndexed128() const { return isMemoryIndexed(16); } - bool isMemoryIndexed64() const { return isMemoryIndexed(8); } - bool isMemoryIndexed32() const { return isMemoryIndexed(4); } - bool isMemoryIndexed16() const { return isMemoryIndexed(2); } - bool isMemoryIndexed8() const { return isMemoryIndexed(1); } - bool isMemoryNoIndex() const { - if (!isMem()) - return false; - if (Mem.Mode != ImmediateOffset) - return false; - if (!Mem.OffsetImm) - return true; - - // Make sure the immediate value is valid. Only zero is allowed. - const MCConstantExpr *CE = dyn_cast(Mem.OffsetImm); - if (!CE || CE->getValue() != 0) - return false; - return true; - } - bool isMemorySIMDNoIndex() const { - if (!isMem()) - return false; - if (Mem.Mode != ImmediateOffset) - return false; - return Mem.OffsetImm == nullptr; - } - bool isMemoryIndexedSImm9() const { - if (!isMem() || Mem.Mode != ImmediateOffset) - return false; - if (!Mem.OffsetImm) - return true; - const MCConstantExpr *CE = dyn_cast(Mem.OffsetImm); - assert(CE && "Non-constant pre-indexed offset!"); - int64_t Value = CE->getValue(); - return Value >= -256 && Value <= 255; - } - bool isMemoryIndexed32SImm7() const { - if (!isMem() || Mem.Mode != ImmediateOffset) - return false; - if (!Mem.OffsetImm) - return true; - const MCConstantExpr *CE = dyn_cast(Mem.OffsetImm); - assert(CE && "Non-constant pre-indexed offset!"); - int64_t Value = CE->getValue(); - return ((Value % 4) == 0) && Value >= -256 && Value <= 252; - } - bool isMemoryIndexed64SImm7() const { - if (!isMem() || Mem.Mode != ImmediateOffset) - return false; - if (!Mem.OffsetImm) - return true; - const MCConstantExpr *CE = dyn_cast(Mem.OffsetImm); - assert(CE && "Non-constant pre-indexed offset!"); - int64_t Value = CE->getValue(); - return ((Value % 8) == 0) && Value >= -512 && Value <= 504; - } - bool isMemoryIndexed128SImm7() const { - if (!isMem() || Mem.Mode != ImmediateOffset) - return false; - if (!Mem.OffsetImm) - return true; - const MCConstantExpr *CE = dyn_cast(Mem.OffsetImm); - assert(CE && "Non-constant pre-indexed offset!"); - int64_t Value = CE->getValue(); - return ((Value % 16) == 0) && Value >= -1024 && Value <= 1008; + template + bool isSImm9OffsetFB() const { + return isSImm9() && !isUImm12Offset(); } bool isAdrpLabel() const { @@ -1313,6 +1198,18 @@ public: addImmOperands(Inst, N); } + template + void addUImm12OffsetOperands(MCInst &Inst, unsigned N) const { + assert(N == 1 && "Invalid number of operands!"); + const MCConstantExpr *MCE = dyn_cast(getImm()); + + if (!MCE) { + Inst.addOperand(MCOperand::CreateExpr(getImm())); + return; + } + Inst.addOperand(MCOperand::CreateImm(MCE->getValue() / Scale)); + } + void addSImm9Operands(MCInst &Inst, unsigned N) const { assert(N == 1 && "Invalid number of operands!"); const MCConstantExpr *MCE = dyn_cast(getImm()); @@ -1577,6 +1474,26 @@ public: Inst.addOperand(MCOperand::CreateImm(Imm)); } + void addMemExtendOperands(MCInst &Inst, unsigned N) const { + assert(N == 2 && "Invalid number of operands!"); + ARM64_AM::ShiftExtendType ET = getShiftExtendType(); + bool IsSigned = ET == ARM64_AM::SXTW || ET == ARM64_AM::SXTX; + Inst.addOperand(MCOperand::CreateImm(IsSigned)); + Inst.addOperand(MCOperand::CreateImm(getShiftExtendAmount() != 0)); + } + + // For 8-bit load/store instructions with a register offset, both the + // "DoShift" and "NoShift" variants have a shift of 0. Because of this, + // they're disambiguated by whether the shift was explicit or implicit rather + // than its size. + void addMemExtend8Operands(MCInst &Inst, unsigned N) const { + assert(N == 2 && "Invalid number of operands!"); + ARM64_AM::ShiftExtendType ET = getShiftExtendType(); + bool IsSigned = ET == ARM64_AM::SXTW || ET == ARM64_AM::SXTX; + Inst.addOperand(MCOperand::CreateImm(IsSigned)); + Inst.addOperand(MCOperand::CreateImm(hasShiftExtendAmount())); + } + template void addMOVZMovAliasOperands(MCInst &Inst, unsigned N) const { assert(N == 1 && "Invalid number of operands!"); @@ -1595,168 +1512,6 @@ public: Inst.addOperand(MCOperand::CreateImm((~Value >> Shift) & 0xffff)); } - void addMemoryRegisterOffsetOperands(MCInst &Inst, unsigned N, bool DoShift) { - assert(N == 3 && "Invalid number of operands!"); - - Inst.addOperand(MCOperand::CreateReg(Mem.BaseRegNum)); - Inst.addOperand(MCOperand::CreateReg(getXRegFromWReg(Mem.OffsetRegNum))); - unsigned ExtendImm = ARM64_AM::getMemExtendImm(Mem.ExtType, DoShift); - Inst.addOperand(MCOperand::CreateImm(ExtendImm)); - } - - void addMemoryRegisterOffset8Operands(MCInst &Inst, unsigned N) { - addMemoryRegisterOffsetOperands(Inst, N, Mem.ExplicitShift); - } - - void addMemoryRegisterOffset16Operands(MCInst &Inst, unsigned N) { - addMemoryRegisterOffsetOperands(Inst, N, Mem.ShiftVal == 1); - } - - void addMemoryRegisterOffset32Operands(MCInst &Inst, unsigned N) { - addMemoryRegisterOffsetOperands(Inst, N, Mem.ShiftVal == 2); - } - - void addMemoryRegisterOffset64Operands(MCInst &Inst, unsigned N) { - addMemoryRegisterOffsetOperands(Inst, N, Mem.ShiftVal == 3); - } - - void addMemoryRegisterOffset128Operands(MCInst &Inst, unsigned N) { - addMemoryRegisterOffsetOperands(Inst, N, Mem.ShiftVal == 4); - } - - void addMemoryIndexedOperands(MCInst &Inst, unsigned N, - unsigned Scale) const { - // Add the base register operand. - Inst.addOperand(MCOperand::CreateReg(Mem.BaseRegNum)); - - if (!Mem.OffsetImm) { - // There isn't an offset. - Inst.addOperand(MCOperand::CreateImm(0)); - return; - } - - // Add the offset operand. - if (const MCConstantExpr *CE = dyn_cast(Mem.OffsetImm)) { - assert(CE->getValue() % Scale == 0 && - "Offset operand must be multiple of the scale!"); - - // The MCInst offset operand doesn't include the low bits (like the - // instruction encoding). - Inst.addOperand(MCOperand::CreateImm(CE->getValue() / Scale)); - } - - // If this is a pageoff symrefexpr with an addend, the linker will - // do the scaling of the addend. - // - // Otherwise we don't know what this is, so just add the scaling divide to - // the expression and let the MC fixup evaluation code deal with it. - const MCExpr *Expr = Mem.OffsetImm; - ARM64MCExpr::VariantKind ELFRefKind; - MCSymbolRefExpr::VariantKind DarwinRefKind; - int64_t Addend; - if (Scale > 1 && - (!ARM64AsmParser::classifySymbolRef(Expr, ELFRefKind, DarwinRefKind, - Addend) || - (Addend != 0 && DarwinRefKind != MCSymbolRefExpr::VK_PAGEOFF))) { - Expr = MCBinaryExpr::CreateDiv(Expr, MCConstantExpr::Create(Scale, Ctx), - Ctx); - } - - Inst.addOperand(MCOperand::CreateExpr(Expr)); - } - - void addMemoryUnscaledOperands(MCInst &Inst, unsigned N) const { - assert(N == 2 && isMemoryUnscaled() && "Invalid number of operands!"); - // Add the base register operand. - Inst.addOperand(MCOperand::CreateReg(Mem.BaseRegNum)); - - // Add the offset operand. - if (!Mem.OffsetImm) - Inst.addOperand(MCOperand::CreateImm(0)); - else { - // Only constant offsets supported. - const MCConstantExpr *CE = cast(Mem.OffsetImm); - Inst.addOperand(MCOperand::CreateImm(CE->getValue())); - } - } - - void addMemoryIndexed128Operands(MCInst &Inst, unsigned N) const { - assert(N == 2 && isMemoryIndexed128() && "Invalid number of operands!"); - addMemoryIndexedOperands(Inst, N, 16); - } - - void addMemoryIndexed64Operands(MCInst &Inst, unsigned N) const { - assert(N == 2 && isMemoryIndexed64() && "Invalid number of operands!"); - addMemoryIndexedOperands(Inst, N, 8); - } - - void addMemoryIndexed32Operands(MCInst &Inst, unsigned N) const { - assert(N == 2 && isMemoryIndexed32() && "Invalid number of operands!"); - addMemoryIndexedOperands(Inst, N, 4); - } - - void addMemoryIndexed16Operands(MCInst &Inst, unsigned N) const { - assert(N == 2 && isMemoryIndexed16() && "Invalid number of operands!"); - addMemoryIndexedOperands(Inst, N, 2); - } - - void addMemoryIndexed8Operands(MCInst &Inst, unsigned N) const { - assert(N == 2 && isMemoryIndexed8() && "Invalid number of operands!"); - addMemoryIndexedOperands(Inst, N, 1); - } - - void addMemoryNoIndexOperands(MCInst &Inst, unsigned N) const { - assert(N == 1 && isMemoryNoIndex() && "Invalid number of operands!"); - // Add the base register operand (the offset is always zero, so ignore it). - Inst.addOperand(MCOperand::CreateReg(Mem.BaseRegNum)); - } - - void addMemorySIMDNoIndexOperands(MCInst &Inst, unsigned N) const { - assert(N == 1 && isMemorySIMDNoIndex() && "Invalid number of operands!"); - // Add the base register operand (the offset is always zero, so ignore it). - Inst.addOperand(MCOperand::CreateReg(Mem.BaseRegNum)); - } - - void addMemoryWritebackIndexedOperands(MCInst &Inst, unsigned N, - unsigned Scale) const { - assert(N == 2 && "Invalid number of operands!"); - - // Add the base register operand. - Inst.addOperand(MCOperand::CreateReg(Mem.BaseRegNum)); - - // Add the offset operand. - int64_t Offset = 0; - if (Mem.OffsetImm) { - const MCConstantExpr *CE = dyn_cast(Mem.OffsetImm); - assert(CE && "Non-constant indexed offset operand!"); - Offset = CE->getValue(); - } - - if (Scale != 1) { - assert(Offset % Scale == 0 && - "Offset operand must be a multiple of the scale!"); - Offset /= Scale; - } - - Inst.addOperand(MCOperand::CreateImm(Offset)); - } - - void addMemoryIndexedSImm9Operands(MCInst &Inst, unsigned N) const { - addMemoryWritebackIndexedOperands(Inst, N, 1); - } - - void addMemoryIndexed32SImm7Operands(MCInst &Inst, unsigned N) const { - addMemoryWritebackIndexedOperands(Inst, N, 4); - } - - void addMemoryIndexed64SImm7Operands(MCInst &Inst, unsigned N) const { - addMemoryWritebackIndexedOperands(Inst, N, 8); - } - - void addMemoryIndexed128SImm7Operands(MCInst &Inst, unsigned N) const { - addMemoryWritebackIndexedOperands(Inst, N, 16); - } - void print(raw_ostream &OS) const override; static ARM64Operand *CreateToken(StringRef Str, bool IsSuffix, SMLoc S, @@ -1857,40 +1612,6 @@ public: return Op; } - static ARM64Operand *CreateMem(unsigned BaseRegNum, const MCExpr *Off, - SMLoc S, SMLoc E, SMLoc OffsetLoc, - MCContext &Ctx) { - ARM64Operand *Op = new ARM64Operand(k_Memory, Ctx); - Op->Mem.BaseRegNum = BaseRegNum; - Op->Mem.OffsetRegNum = 0; - Op->Mem.OffsetImm = Off; - Op->Mem.ExtType = ARM64_AM::UXTX; - Op->Mem.ShiftVal = 0; - Op->Mem.ExplicitShift = false; - Op->Mem.Mode = ImmediateOffset; - Op->OffsetLoc = OffsetLoc; - Op->StartLoc = S; - Op->EndLoc = E; - return Op; - } - - static ARM64Operand *CreateRegOffsetMem(unsigned BaseReg, unsigned OffsetReg, - ARM64_AM::ShiftExtendType ExtType, - unsigned ShiftVal, bool ExplicitShift, - SMLoc S, SMLoc E, MCContext &Ctx) { - ARM64Operand *Op = new ARM64Operand(k_Memory, Ctx); - Op->Mem.BaseRegNum = BaseReg; - Op->Mem.OffsetRegNum = OffsetReg; - Op->Mem.OffsetImm = nullptr; - Op->Mem.ExtType = ExtType; - Op->Mem.ShiftVal = ShiftVal; - Op->Mem.ExplicitShift = ExplicitShift; - Op->Mem.Mode = RegisterOffset; - Op->StartLoc = S; - Op->EndLoc = E; - return Op; - } - static ARM64Operand *CreateSysCR(unsigned Val, SMLoc S, SMLoc E, MCContext &Ctx) { ARM64Operand *Op = new ARM64Operand(k_SysCR, Ctx); @@ -1908,11 +1629,13 @@ public: return Op; } - static ARM64Operand *CreateShiftExtend(ARM64_AM::ShiftExtendType ShOp, unsigned Val, + static ARM64Operand *CreateShiftExtend(ARM64_AM::ShiftExtendType ShOp, + unsigned Val, bool HasExplicitAmount, SMLoc S, SMLoc E, MCContext &Ctx) { ARM64Operand *Op = new ARM64Operand(k_ShiftExtend, Ctx); Op->ShiftExtend.Type = ShOp; Op->ShiftExtend.Amount = Val; + Op->ShiftExtend.HasExplicitAmount = HasExplicitAmount; Op->StartLoc = S; Op->EndLoc = E; return Op; @@ -1949,9 +1672,6 @@ void ARM64Operand::print(raw_ostream &OS) const { case k_CondCode: OS << ""; break; - case k_Memory: - OS << ""; - break; case k_Register: OS << ""; break; @@ -1986,7 +1706,10 @@ void ARM64Operand::print(raw_ostream &OS) const { } case k_ShiftExtend: { OS << "<" << ARM64_AM::getShiftExtendName(getShiftExtendType()) << " #" - << getShiftExtendAmount() << ">"; + << getShiftExtendAmount(); + if (!hasShiftExtendAmount()) + OS << ""; + OS << '>'; break; } } @@ -2498,7 +2221,7 @@ ARM64AsmParser::tryParseOptionalShiftExtend(OperandVector &Operands) { // "extend" type operatoins don't need an immediate, #0 is implicit. SMLoc E = SMLoc::getFromPointer(getLoc().getPointer() - 1); Operands.push_back( - ARM64Operand::CreateShiftExtend(ShOp, 0, S, E, getContext())); + ARM64Operand::CreateShiftExtend(ShOp, 0, false, S, E, getContext())); return MatchOperand_Success; } @@ -2523,8 +2246,8 @@ ARM64AsmParser::tryParseOptionalShiftExtend(OperandVector &Operands) { } SMLoc E = SMLoc::getFromPointer(getLoc().getPointer() - 1); - Operands.push_back(ARM64Operand::CreateShiftExtend(ShOp, MCE->getValue(), S, - E, getContext())); + Operands.push_back(ARM64Operand::CreateShiftExtend(ShOp, MCE->getValue(), + true, S, E, getContext())); return MatchOperand_Success; } @@ -2931,213 +2654,6 @@ bool ARM64AsmParser::parseRegister(OperandVector &Operands) { return false; } -/// tryParseNoIndexMemory - Custom parser method for memory operands that -/// do not allow base regisrer writeback modes, -/// or those that handle writeback separately from -/// the memory operand (like the AdvSIMD ldX/stX -/// instructions. -ARM64AsmParser::OperandMatchResultTy -ARM64AsmParser::tryParseNoIndexMemory(OperandVector &Operands) { - if (Parser.getTok().isNot(AsmToken::LBrac)) - return MatchOperand_NoMatch; - SMLoc S = getLoc(); - Parser.Lex(); // Eat left bracket token. - - const AsmToken &BaseRegTok = Parser.getTok(); - if (BaseRegTok.isNot(AsmToken::Identifier)) { - Error(BaseRegTok.getLoc(), "register expected"); - return MatchOperand_ParseFail; - } - - int64_t Reg = tryParseRegister(); - if (Reg == -1) { - Error(BaseRegTok.getLoc(), "register expected"); - return MatchOperand_ParseFail; - } - - SMLoc E = getLoc(); - if (Parser.getTok().isNot(AsmToken::RBrac)) { - Error(E, "']' expected"); - return MatchOperand_ParseFail; - } - - Parser.Lex(); // Eat right bracket token. - - Operands.push_back(ARM64Operand::CreateMem(Reg, nullptr, S, E, E, getContext())); - return MatchOperand_Success; -} - -/// parseMemory - Parse a memory operand for a basic load/store instruction. -bool ARM64AsmParser::parseMemory(OperandVector &Operands) { - assert(Parser.getTok().is(AsmToken::LBrac) && "Token is not a Left Bracket"); - SMLoc S = getLoc(); - Parser.Lex(); // Eat left bracket token. - - const AsmToken &BaseRegTok = Parser.getTok(); - SMLoc BaseRegLoc = BaseRegTok.getLoc(); - if (BaseRegTok.isNot(AsmToken::Identifier)) - return Error(BaseRegLoc, "register expected"); - - int64_t Reg = tryParseRegister(); - if (Reg == -1) - return Error(BaseRegLoc, "register expected"); - - if (!ARM64MCRegisterClasses[ARM64::GPR64spRegClassID].contains(Reg)) - return Error(BaseRegLoc, "invalid operand for instruction"); - - // If there is an offset expression, parse it. - const MCExpr *OffsetExpr = nullptr; - SMLoc OffsetLoc; - if (Parser.getTok().is(AsmToken::Comma)) { - Parser.Lex(); // Eat the comma. - OffsetLoc = getLoc(); - - // Register offset - const AsmToken &OffsetRegTok = Parser.getTok(); - int Reg2 = OffsetRegTok.is(AsmToken::Identifier) ? tryParseRegister() : -1; - if (Reg2 != -1) { - // Default shift is LSL, with an omitted shift. We use the third bit of - // the extend value to indicate presence/omission of the immediate offset. - ARM64_AM::ShiftExtendType ExtOp = ARM64_AM::UXTX; - int64_t ShiftVal = 0; - bool ExplicitShift = false; - - if (Parser.getTok().is(AsmToken::Comma)) { - // Embedded extend operand. - Parser.Lex(); // Eat the comma - - SMLoc ExtLoc = getLoc(); - const AsmToken &Tok = Parser.getTok(); - ExtOp = StringSwitch(Tok.getString().lower()) - .Case("uxtw", ARM64_AM::UXTW) - .Case("lsl", ARM64_AM::UXTX) // Alias for UXTX - .Case("sxtw", ARM64_AM::SXTW) - .Case("sxtx", ARM64_AM::SXTX) - .Default(ARM64_AM::InvalidShiftExtend); - if (ExtOp == ARM64_AM::InvalidShiftExtend) - return Error(ExtLoc, "expected valid extend operation"); - - Parser.Lex(); // Eat the extend op. - - // A 32-bit offset register is only valid for [SU]/XTW extend - // operators. - if (ARM64MCRegisterClasses[ARM64::GPR32allRegClassID].contains(Reg2)) { - if (ExtOp != ARM64_AM::UXTW && - ExtOp != ARM64_AM::SXTW) - return Error(ExtLoc, "32-bit general purpose offset register " - "requires sxtw or uxtw extend"); - } else if (!ARM64MCRegisterClasses[ARM64::GPR64allRegClassID].contains( - Reg2)) - return Error(OffsetLoc, - "64-bit general purpose offset register expected"); - - bool Hash = getLexer().is(AsmToken::Hash); - if (getLexer().is(AsmToken::RBrac)) { - // No immediate operand. - if (ExtOp == ARM64_AM::UXTX) - return Error(ExtLoc, "LSL extend requires immediate operand"); - } else if (Hash || getLexer().is(AsmToken::Integer)) { - // Immediate operand. - if (Hash) - Parser.Lex(); // Eat the '#' - const MCExpr *ImmVal; - SMLoc ExprLoc = getLoc(); - if (getParser().parseExpression(ImmVal)) - return true; - const MCConstantExpr *MCE = dyn_cast(ImmVal); - if (!MCE) - return TokError("immediate value expected for extend operand"); - - ExplicitShift = true; - ShiftVal = MCE->getValue(); - if (ShiftVal < 0 || ShiftVal > 4) - return Error(ExprLoc, "immediate operand out of range"); - } else - return Error(getLoc(), "expected immediate operand"); - } - - if (Parser.getTok().isNot(AsmToken::RBrac)) - return Error(getLoc(), "']' expected"); - - Parser.Lex(); // Eat right bracket token. - - SMLoc E = getLoc(); - Operands.push_back(ARM64Operand::CreateRegOffsetMem( - Reg, Reg2, ExtOp, ShiftVal, ExplicitShift, S, E, getContext())); - return false; - - // Immediate expressions. - } else if (Parser.getTok().is(AsmToken::Hash) || - Parser.getTok().is(AsmToken::Colon) || - Parser.getTok().is(AsmToken::Integer)) { - if (Parser.getTok().is(AsmToken::Hash)) - Parser.Lex(); // Eat hash token. - - if (parseSymbolicImmVal(OffsetExpr)) - return true; - } else { - // FIXME: We really should make sure that we're dealing with a LDR/STR - // instruction that can legally have a symbolic expression here. - // Symbol reference. - if (Parser.getTok().isNot(AsmToken::Identifier) && - Parser.getTok().isNot(AsmToken::String)) - return Error(getLoc(), "identifier or immediate expression expected"); - if (getParser().parseExpression(OffsetExpr)) - return true; - // If this is a plain ref, Make sure a legal variant kind was specified. - // Otherwise, it's a more complicated expression and we have to just - // assume it's OK and let the relocation stuff puke if it's not. - ARM64MCExpr::VariantKind ELFRefKind; - MCSymbolRefExpr::VariantKind DarwinRefKind; - int64_t Addend; - if (classifySymbolRef(OffsetExpr, ELFRefKind, DarwinRefKind, Addend) && - Addend == 0) { - assert(ELFRefKind == ARM64MCExpr::VK_INVALID && - "ELF symbol modifiers not supported here yet"); - - switch (DarwinRefKind) { - default: - return Error(getLoc(), "expected @pageoff or @gotpageoff modifier"); - case MCSymbolRefExpr::VK_GOTPAGEOFF: - case MCSymbolRefExpr::VK_PAGEOFF: - case MCSymbolRefExpr::VK_TLVPPAGEOFF: - // These are what we're expecting. - break; - } - } - } - } - - SMLoc E = getLoc(); - if (Parser.getTok().isNot(AsmToken::RBrac)) - return Error(E, "']' expected"); - - Parser.Lex(); // Eat right bracket token. - - // Create the memory operand. - Operands.push_back( - ARM64Operand::CreateMem(Reg, OffsetExpr, S, E, OffsetLoc, getContext())); - - // Check for a '!', indicating pre-indexed addressing with writeback. - if (Parser.getTok().is(AsmToken::Exclaim)) { - // There needs to have been an immediate or wback doesn't make sense. - if (!OffsetExpr) - return Error(E, "missing offset for pre-indexed addressing"); - // Pre-indexed with writeback must have a constant expression for the - // offset. FIXME: Theoretically, we'd like to allow fixups so long - // as they don't require a relocation. - if (!isa(OffsetExpr)) - return Error(OffsetLoc, "constant immediate expression expected"); - - // Create the Token operand for the '!'. - Operands.push_back(ARM64Operand::CreateToken( - "!", false, Parser.getTok().getLoc(), getContext())); - Parser.Lex(); // Eat the '!' token. - } - - return false; -} - bool ARM64AsmParser::parseSymbolicImmVal(const MCExpr *&ImmVal) { bool HasELFModifier = false; ARM64MCExpr::VariantKind RefKind; @@ -3313,6 +2829,47 @@ bool ARM64AsmParser::parseVectorList(OperandVector &Operands) { return false; } +ARM64AsmParser::OperandMatchResultTy +ARM64AsmParser::tryParseGPR64sp0Operand(OperandVector &Operands) { + const AsmToken &Tok = Parser.getTok(); + if (!Tok.is(AsmToken::Identifier)) + return MatchOperand_NoMatch; + + unsigned RegNum = MatchRegisterName(Tok.getString().lower()); + + MCContext &Ctx = getContext(); + const MCRegisterInfo *RI = Ctx.getRegisterInfo(); + if (!RI->getRegClass(ARM64::GPR64spRegClassID).contains(RegNum)) + return MatchOperand_NoMatch; + + SMLoc S = getLoc(); + Parser.Lex(); // Eat register + + if (Parser.getTok().isNot(AsmToken::Comma)) { + Operands.push_back(ARM64Operand::CreateReg(RegNum, false, S, getLoc(), Ctx)); + return MatchOperand_Success; + } + Parser.Lex(); // Eat comma. + + if (Parser.getTok().is(AsmToken::Hash)) + Parser.Lex(); // Eat hash + + if (Parser.getTok().isNot(AsmToken::Integer)) { + Error(getLoc(), "index must be absent or #0"); + return MatchOperand_ParseFail; + } + + const MCExpr *ImmVal; + if (Parser.parseExpression(ImmVal) || !isa(ImmVal) || + cast(ImmVal)->getValue() != 0) { + Error(getLoc(), "index must be absent or #0"); + return MatchOperand_ParseFail; + } + + Operands.push_back(ARM64Operand::CreateReg(RegNum, false, S, getLoc(), Ctx)); + return MatchOperand_Success; +} + /// parseOperand - Parse a arm instruction operand. For now this parses the /// operand regardless of the mnemonic. bool ARM64AsmParser::parseOperand(OperandVector &Operands, bool isCondCode, @@ -3341,8 +2898,16 @@ bool ARM64AsmParser::parseOperand(OperandVector &Operands, bool isCondCode, Operands.push_back(ARM64Operand::CreateImm(Expr, S, E, getContext())); return false; } - case AsmToken::LBrac: - return parseMemory(Operands); + case AsmToken::LBrac: { + SMLoc Loc = Parser.getTok().getLoc(); + Operands.push_back(ARM64Operand::CreateToken("[", false, Loc, + getContext())); + Parser.Lex(); // Eat '[' + + // There's no comma after a '[', so we can parse the next operand + // immediately. + return parseOperand(Operands, false, false); + } case AsmToken::LCurly: return parseVectorList(Operands); case AsmToken::Identifier: { @@ -3530,6 +3095,28 @@ bool ARM64AsmParser::ParseInstruction(ParseInstructionInfo &Info, return true; } + // After successfully parsing some operands there are two special cases to + // consider (i.e. notional operands not separated by commas). Both are due + // to memory specifiers: + // + An RBrac will end an address for load/store/prefetch + // + An '!' will indicate a pre-indexed operation. + // + // It's someone else's responsibility to make sure these tokens are sane + // in the given context! + if (Parser.getTok().is(AsmToken::RBrac)) { + SMLoc Loc = Parser.getTok().getLoc(); + Operands.push_back(ARM64Operand::CreateToken("]", false, Loc, + getContext())); + Parser.Lex(); + } + + if (Parser.getTok().is(AsmToken::Exclaim)) { + SMLoc Loc = Parser.getTok().getLoc(); + Operands.push_back(ARM64Operand::CreateToken("!", false, Loc, + getContext())); + Parser.Lex(); + } + ++N; } } @@ -3749,23 +3336,51 @@ bool ARM64AsmParser::showMatchError(SMLoc Loc, unsigned ErrCode) { "expected compatible register or floating-point constant"); case Match_InvalidMemoryIndexedSImm9: return Error(Loc, "index must be an integer in range [-256, 255]."); - case Match_InvalidMemoryIndexed32SImm7: + case Match_InvalidMemoryIndexed4SImm7: return Error(Loc, "index must be a multiple of 4 in range [-256, 252]."); - case Match_InvalidMemoryIndexed64SImm7: + case Match_InvalidMemoryIndexed8SImm7: return Error(Loc, "index must be a multiple of 8 in range [-512, 504]."); - case Match_InvalidMemoryIndexed128SImm7: + case Match_InvalidMemoryIndexed16SImm7: return Error(Loc, "index must be a multiple of 16 in range [-1024, 1008]."); - case Match_InvalidMemoryIndexed: - return Error(Loc, "invalid offset in memory address."); - case Match_InvalidMemoryIndexed8: + case Match_InvalidMemoryWExtend8: + return Error(Loc, + "expected 'uxtw' or 'sxtw' with optional shift of #0"); + case Match_InvalidMemoryWExtend16: + return Error(Loc, + "expected 'uxtw' or 'sxtw' with optional shift of #0 or #1"); + case Match_InvalidMemoryWExtend32: + return Error(Loc, + "expected 'uxtw' or 'sxtw' with optional shift of #0 or #2"); + case Match_InvalidMemoryWExtend64: + return Error(Loc, + "expected 'uxtw' or 'sxtw' with optional shift of #0 or #3"); + case Match_InvalidMemoryWExtend128: + return Error(Loc, + "expected 'uxtw' or 'sxtw' with optional shift of #0 or #4"); + case Match_InvalidMemoryXExtend8: + return Error(Loc, + "expected 'lsl' or 'sxtx' with optional shift of #0"); + case Match_InvalidMemoryXExtend16: + return Error(Loc, + "expected 'lsl' or 'sxtx' with optional shift of #0 or #1"); + case Match_InvalidMemoryXExtend32: + return Error(Loc, + "expected 'lsl' or 'sxtx' with optional shift of #0 or #2"); + case Match_InvalidMemoryXExtend64: + return Error(Loc, + "expected 'lsl' or 'sxtx' with optional shift of #0 or #3"); + case Match_InvalidMemoryXExtend128: + return Error(Loc, + "expected 'lsl' or 'sxtx' with optional shift of #0 or #4"); + case Match_InvalidMemoryIndexed1: return Error(Loc, "index must be an integer in range [0, 4095]."); - case Match_InvalidMemoryIndexed16: + case Match_InvalidMemoryIndexed2: return Error(Loc, "index must be a multiple of 2 in range [0, 8190]."); - case Match_InvalidMemoryIndexed32: + case Match_InvalidMemoryIndexed4: return Error(Loc, "index must be a multiple of 4 in range [0, 16380]."); - case Match_InvalidMemoryIndexed64: + case Match_InvalidMemoryIndexed8: return Error(Loc, "index must be a multiple of 8 in range [0, 32760]."); - case Match_InvalidMemoryIndexed128: + case Match_InvalidMemoryIndexed16: return Error(Loc, "index must be a multiple of 16 in range [0, 65520]."); case Match_InvalidImm0_7: return Error(Loc, "immediate must be an integer in range [0, 7]."); @@ -4109,39 +3724,11 @@ bool ARM64AsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode, return showMatchError(ErrorLoc, MatchResult); } - case Match_InvalidMemoryIndexedSImm9: { - // If there is not a '!' after the memory operand that failed, we really - // want the diagnostic for the non-pre-indexed instruction variant instead. - // Be careful to check for the post-indexed variant as well, which also - // uses this match diagnostic. Also exclude the explicitly unscaled - // mnemonics, as they want the unscaled diagnostic as well. - if (Operands.size() == ErrorInfo + 1 && - !((ARM64Operand *)Operands[ErrorInfo])->isImm() && - !Tok.startswith("stur") && !Tok.startswith("ldur")) { - // FIXME: Here we use a vague diagnostic for memory operand in many - // instructions of various formats. This diagnostic can be more accurate - // if splitting memory operand into many smaller operands to help - // diagnose. - MatchResult = Match_InvalidMemoryIndexed; - } - else if(Operands.size() == 3 && Operands.size() == ErrorInfo + 1 && - ((ARM64Operand *)Operands[ErrorInfo])->isImm()) { - MatchResult = Match_InvalidLabel; - } - SMLoc ErrorLoc = ((ARM64Operand *)Operands[ErrorInfo])->getStartLoc(); - if (ErrorLoc == SMLoc()) - ErrorLoc = IDLoc; - return showMatchError(ErrorLoc, MatchResult); - } - case Match_InvalidMemoryIndexed32: - case Match_InvalidMemoryIndexed64: - case Match_InvalidMemoryIndexed128: - // If there is a '!' after the memory operand that failed, we really - // want the diagnostic for the pre-indexed instruction variant instead. - if (Operands.size() > ErrorInfo + 1 && - ((ARM64Operand *)Operands[ErrorInfo + 1])->isTokenEqual("!")) - MatchResult = Match_InvalidMemoryIndexedSImm9; - // FALL THROUGH + case Match_InvalidMemoryIndexed1: + case Match_InvalidMemoryIndexed2: + case Match_InvalidMemoryIndexed4: + case Match_InvalidMemoryIndexed8: + case Match_InvalidMemoryIndexed16: case Match_InvalidCondCode: case Match_AddSubRegExtendSmall: case Match_AddSubRegExtendLarge: @@ -4152,12 +3739,20 @@ bool ARM64AsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode, case Match_InvalidMovImm32Shift: case Match_InvalidMovImm64Shift: case Match_InvalidFPImm: - case Match_InvalidMemoryIndexed: - case Match_InvalidMemoryIndexed8: - case Match_InvalidMemoryIndexed16: - case Match_InvalidMemoryIndexed32SImm7: - case Match_InvalidMemoryIndexed64SImm7: - case Match_InvalidMemoryIndexed128SImm7: + case Match_InvalidMemoryWExtend8: + case Match_InvalidMemoryWExtend16: + case Match_InvalidMemoryWExtend32: + case Match_InvalidMemoryWExtend64: + case Match_InvalidMemoryWExtend128: + case Match_InvalidMemoryXExtend8: + case Match_InvalidMemoryXExtend16: + case Match_InvalidMemoryXExtend32: + case Match_InvalidMemoryXExtend64: + case Match_InvalidMemoryXExtend128: + case Match_InvalidMemoryIndexed4SImm7: + case Match_InvalidMemoryIndexed8SImm7: + case Match_InvalidMemoryIndexed16SImm7: + case Match_InvalidMemoryIndexedSImm9: case Match_InvalidImm0_7: case Match_InvalidImm0_15: case Match_InvalidImm0_31: @@ -4179,10 +3774,6 @@ bool ARM64AsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode, // Any time we get here, there's nothing fancy to do. Just get the // operand SMLoc and display the diagnostic. SMLoc ErrorLoc = ((ARM64Operand *)Operands[ErrorInfo])->getStartLoc(); - // If it's a memory operand, the error is with the offset immediate, - // so get that location instead. - if (((ARM64Operand *)Operands[ErrorInfo])->isMem()) - ErrorLoc = ((ARM64Operand *)Operands[ErrorInfo])->getOffsetLoc(); if (ErrorLoc == SMLoc()) ErrorLoc = IDLoc; return showMatchError(ErrorLoc, MatchResult); diff --git a/lib/Target/ARM64/Disassembler/ARM64Disassembler.cpp b/lib/Target/ARM64/Disassembler/ARM64Disassembler.cpp index 92eabcf2b4e..20bcb366bf5 100644 --- a/lib/Target/ARM64/Disassembler/ARM64Disassembler.cpp +++ b/lib/Target/ARM64/Disassembler/ARM64Disassembler.cpp @@ -89,6 +89,8 @@ static DecodeStatus DecodeFixedPointScaleImm64(llvm::MCInst &Inst, unsigned Imm, const void *Decoder); static DecodeStatus DecodePCRelLabel19(llvm::MCInst &Inst, unsigned Imm, uint64_t Address, const void *Decoder); +static DecodeStatus DecodeMemExtend(llvm::MCInst &Inst, unsigned Imm, + uint64_t Address, const void *Decoder); static DecodeStatus DecodeMRSSystemRegister(llvm::MCInst &Inst, unsigned Imm, uint64_t Address, const void *Decoder); static DecodeStatus DecodeMSRSystemRegister(llvm::MCInst &Inst, unsigned Imm, @@ -114,10 +116,6 @@ static DecodeStatus DecodeExclusiveLdStInstruction(llvm::MCInst &Inst, static DecodeStatus DecodePairLdStInstruction(llvm::MCInst &Inst, uint32_t insn, uint64_t Address, const void *Decoder); -static DecodeStatus DecodeRegOffsetLdStInstruction(llvm::MCInst &Inst, - uint32_t insn, - uint64_t Address, - const void *Decoder); static DecodeStatus DecodeAddSubERegInstruction(llvm::MCInst &Inst, uint32_t insn, uint64_t Address, const void *Decoder); @@ -605,6 +603,13 @@ static DecodeStatus DecodePCRelLabel19(llvm::MCInst &Inst, unsigned Imm, return Success; } +static DecodeStatus DecodeMemExtend(llvm::MCInst &Inst, unsigned Imm, + uint64_t Address, const void *Decoder) { + Inst.addOperand(MCOperand::CreateImm((Imm >> 1) & 1)); + Inst.addOperand(MCOperand::CreateImm(Imm & 1)); + return Success; +} + static DecodeStatus DecodeMRSSystemRegister(llvm::MCInst &Inst, unsigned Imm, uint64_t Address, const void *Decoder) { @@ -1189,81 +1194,6 @@ static DecodeStatus DecodePairLdStInstruction(llvm::MCInst &Inst, uint32_t insn, return Success; } -static DecodeStatus DecodeRegOffsetLdStInstruction(llvm::MCInst &Inst, - uint32_t insn, uint64_t Addr, - const void *Decoder) { - unsigned Rt = fieldFromInstruction(insn, 0, 5); - unsigned Rn = fieldFromInstruction(insn, 5, 5); - unsigned Rm = fieldFromInstruction(insn, 16, 5); - unsigned extendHi = fieldFromInstruction(insn, 13, 3); - unsigned extendLo = fieldFromInstruction(insn, 12, 1); - unsigned extend = (extendHi << 1) | extendLo; - - // All RO load-store instructions are undefined if option == 00x or 10x. - if (extend >> 2 == 0x0 || extend >> 2 == 0x2) - return Fail; - - switch (Inst.getOpcode()) { - default: - return Fail; - case ARM64::LDRSWro: - DecodeGPR64RegisterClass(Inst, Rt, Addr, Decoder); - break; - case ARM64::LDRXro: - case ARM64::STRXro: - DecodeGPR64RegisterClass(Inst, Rt, Addr, Decoder); - break; - case ARM64::LDRWro: - case ARM64::STRWro: - DecodeGPR32RegisterClass(Inst, Rt, Addr, Decoder); - break; - case ARM64::LDRQro: - case ARM64::STRQro: - DecodeFPR128RegisterClass(Inst, Rt, Addr, Decoder); - break; - case ARM64::LDRDro: - case ARM64::STRDro: - DecodeFPR64RegisterClass(Inst, Rt, Addr, Decoder); - break; - case ARM64::LDRSro: - case ARM64::STRSro: - DecodeFPR32RegisterClass(Inst, Rt, Addr, Decoder); - break; - case ARM64::LDRHro: - case ARM64::STRHro: - DecodeFPR16RegisterClass(Inst, Rt, Addr, Decoder); - break; - case ARM64::LDRBro: - case ARM64::STRBro: - DecodeFPR8RegisterClass(Inst, Rt, Addr, Decoder); - break; - case ARM64::LDRBBro: - case ARM64::STRBBro: - case ARM64::LDRSBWro: - DecodeGPR32RegisterClass(Inst, Rt, Addr, Decoder); - break; - case ARM64::LDRHHro: - case ARM64::STRHHro: - case ARM64::LDRSHWro: - DecodeGPR32RegisterClass(Inst, Rt, Addr, Decoder); - break; - case ARM64::LDRSHXro: - DecodeGPR64RegisterClass(Inst, Rt, Addr, Decoder); - break; - case ARM64::LDRSBXro: - DecodeGPR64RegisterClass(Inst, Rt, Addr, Decoder); - break; - case ARM64::PRFMro: - Inst.addOperand(MCOperand::CreateImm(Rt)); - } - - DecodeGPR64spRegisterClass(Inst, Rn, Addr, Decoder); - DecodeGPR64RegisterClass(Inst, Rm, Addr, Decoder); - - Inst.addOperand(MCOperand::CreateImm(extend)); - return Success; -} - static DecodeStatus DecodeAddSubERegInstruction(llvm::MCInst &Inst, uint32_t insn, uint64_t Addr, const void *Decoder) { diff --git a/lib/Target/ARM64/InstPrinter/ARM64InstPrinter.cpp b/lib/Target/ARM64/InstPrinter/ARM64InstPrinter.cpp index adfcb46ac40..48fba37146e 100644 --- a/lib/Target/ARM64/InstPrinter/ARM64InstPrinter.cpp +++ b/lib/Target/ARM64/InstPrinter/ARM64InstPrinter.cpp @@ -990,11 +990,11 @@ void ARM64InstPrinter::printShiftedRegister(const MCInst *MI, unsigned OpNum, void ARM64InstPrinter::printExtendedRegister(const MCInst *MI, unsigned OpNum, raw_ostream &O) { O << getRegisterName(MI->getOperand(OpNum).getReg()); - printExtend(MI, OpNum + 1, O); + printArithExtend(MI, OpNum + 1, O); } -void ARM64InstPrinter::printExtend(const MCInst *MI, unsigned OpNum, - raw_ostream &O) { +void ARM64InstPrinter::printArithExtend(const MCInst *MI, unsigned OpNum, + raw_ostream &O) { unsigned Val = MI->getOperand(OpNum).getImm(); ARM64_AM::ShiftExtendType ExtType = ARM64_AM::getArithExtendType(Val); unsigned ShiftVal = ARM64_AM::getArithShiftValue(Val); @@ -1019,6 +1019,23 @@ void ARM64InstPrinter::printExtend(const MCInst *MI, unsigned OpNum, O << " #" << ShiftVal; } +void ARM64InstPrinter::printMemExtend(const MCInst *MI, unsigned OpNum, + raw_ostream &O, char SrcRegKind, + unsigned Width) { + unsigned SignExtend = MI->getOperand(OpNum).getImm(); + unsigned DoShift = MI->getOperand(OpNum + 1).getImm(); + + // sxtw, sxtx, uxtw or lsl (== uxtx) + bool IsLSL = !SignExtend && SrcRegKind == 'x'; + if (IsLSL) + O << "lsl"; + else + O << (SignExtend ? 's' : 'u') << "xt" << SrcRegKind; + + if (DoShift || IsLSL) + O << " #" << Log2_32(Width / 8); +} + void ARM64InstPrinter::printCondCode(const MCInst *MI, unsigned OpNum, raw_ostream &O) { ARM64CC::CondCode CC = (ARM64CC::CondCode)MI->getOperand(OpNum).getImm(); @@ -1042,18 +1059,15 @@ void ARM64InstPrinter::printImmScale(const MCInst *MI, unsigned OpNum, O << '#' << Scale * MI->getOperand(OpNum).getImm(); } -void ARM64InstPrinter::printAMIndexed(const MCInst *MI, unsigned OpNum, - unsigned Scale, raw_ostream &O) { - const MCOperand MO1 = MI->getOperand(OpNum + 1); - O << '[' << getRegisterName(MI->getOperand(OpNum).getReg()); - if (MO1.isImm()) { - if (MO1.getImm() != 0) - O << ", #" << (MO1.getImm() * Scale); +void ARM64InstPrinter::printUImm12Offset(const MCInst *MI, unsigned OpNum, + unsigned Scale, raw_ostream &O) { + const MCOperand MO = MI->getOperand(OpNum); + if (MO.isImm()) { + O << "#" << (MO.getImm() * Scale); } else { - assert(MO1.isExpr() && "Unexpected operand type!"); - O << ", " << *MO1.getExpr(); + assert(MO.isExpr() && "Unexpected operand type!"); + O << *MO.getExpr(); } - O << ']'; } void ARM64InstPrinter::printAMIndexedWB(const MCInst *MI, unsigned OpNum, @@ -1080,37 +1094,6 @@ void ARM64InstPrinter::printPrefetchOp(const MCInst *MI, unsigned OpNum, O << '#' << prfop; } -void ARM64InstPrinter::printMemoryPostIndexed(const MCInst *MI, unsigned OpNum, - raw_ostream &O, unsigned Scale) { - O << '[' << getRegisterName(MI->getOperand(OpNum).getReg()) << ']' << ", #" - << Scale * MI->getOperand(OpNum + 1).getImm(); -} - -void ARM64InstPrinter::printMemoryRegOffset(const MCInst *MI, unsigned OpNum, - raw_ostream &O, int Scale) { - unsigned Val = MI->getOperand(OpNum + 2).getImm(); - ARM64_AM::ShiftExtendType ExtType = ARM64_AM::getMemExtendType(Val); - - O << '[' << getRegisterName(MI->getOperand(OpNum).getReg()) << ", "; - if (ExtType == ARM64_AM::UXTW || ExtType == ARM64_AM::SXTW) - O << getRegisterName(getWRegFromXReg(MI->getOperand(OpNum + 1).getReg())); - else - O << getRegisterName(MI->getOperand(OpNum + 1).getReg()); - - bool DoShift = ARM64_AM::getMemDoShift(Val); - - if (ExtType == ARM64_AM::UXTX) { - if (DoShift) - O << ", lsl"; - } else - O << ", " << ARM64_AM::getShiftExtendName(ExtType); - - if (DoShift) - O << " #" << Log2_32(Scale); - - O << "]"; -} - void ARM64InstPrinter::printFPImmOperand(const MCInst *MI, unsigned OpNum, raw_ostream &O) { const MCOperand &MO = MI->getOperand(OpNum); diff --git a/lib/Target/ARM64/InstPrinter/ARM64InstPrinter.h b/lib/Target/ARM64/InstPrinter/ARM64InstPrinter.h index 31818dff980..0fd6f100712 100644 --- a/lib/Target/ARM64/InstPrinter/ARM64InstPrinter.h +++ b/lib/Target/ARM64/InstPrinter/ARM64InstPrinter.h @@ -62,18 +62,26 @@ protected: void printShifter(const MCInst *MI, unsigned OpNum, raw_ostream &O); void printShiftedRegister(const MCInst *MI, unsigned OpNum, raw_ostream &O); void printExtendedRegister(const MCInst *MI, unsigned OpNum, raw_ostream &O); - void printExtend(const MCInst *MI, unsigned OpNum, raw_ostream &O); + void printArithExtend(const MCInst *MI, unsigned OpNum, raw_ostream &O); + + void printMemExtend(const MCInst *MI, unsigned OpNum, raw_ostream &O, + char SrcRegKind, unsigned Width); + template + void printMemExtend(const MCInst *MI, unsigned OpNum, raw_ostream &O) { + printMemExtend(MI, OpNum, O, SrcRegKind, Width); + } + void printCondCode(const MCInst *MI, unsigned OpNum, raw_ostream &O); void printInverseCondCode(const MCInst *MI, unsigned OpNum, raw_ostream &O); void printAlignedLabel(const MCInst *MI, unsigned OpNum, raw_ostream &O); - void printAMIndexed(const MCInst *MI, unsigned OpNum, unsigned Scale, - raw_ostream &O); + void printUImm12Offset(const MCInst *MI, unsigned OpNum, unsigned Scale, + raw_ostream &O); void printAMIndexedWB(const MCInst *MI, unsigned OpNum, unsigned Scale, raw_ostream &O); - template - void printAMIndexed(const MCInst *MI, unsigned OpNum, raw_ostream &O) { - printAMIndexed(MI, OpNum, BitWidth / 8, O); + template + void printUImm12Offset(const MCInst *MI, unsigned OpNum, raw_ostream &O) { + printUImm12Offset(MI, OpNum, Scale, O); } template @@ -88,21 +96,6 @@ protected: void printPrefetchOp(const MCInst *MI, unsigned OpNum, raw_ostream &O); - void printMemoryPostIndexed(const MCInst *MI, unsigned OpNum, raw_ostream &O, - unsigned Scale); - template - void printMemoryPostIndexed(const MCInst *MI, unsigned OpNum, - raw_ostream &O) { - printMemoryPostIndexed(MI, OpNum, O, BitWidth / 8); - } - - void printMemoryRegOffset(const MCInst *MI, unsigned OpNum, raw_ostream &O, - int LegalShiftAmt); - template - void printMemoryRegOffset(const MCInst *MI, unsigned OpNum, raw_ostream &O) { - printMemoryRegOffset(MI, OpNum, O, BitWidth / 8); - } - void printFPImmOperand(const MCInst *MI, unsigned OpNum, raw_ostream &O); void printVectorList(const MCInst *MI, unsigned OpNum, raw_ostream &O, diff --git a/lib/Target/ARM64/MCTargetDesc/ARM64MCCodeEmitter.cpp b/lib/Target/ARM64/MCTargetDesc/ARM64MCCodeEmitter.cpp index 3c6dbc85b13..0db08f422e4 100644 --- a/lib/Target/ARM64/MCTargetDesc/ARM64MCCodeEmitter.cpp +++ b/lib/Target/ARM64/MCTargetDesc/ARM64MCCodeEmitter.cpp @@ -56,12 +56,11 @@ public: SmallVectorImpl &Fixups, const MCSubtargetInfo &STI) const; - /// getAMIndexed8OpValue - Return encoding info for base register - /// and 12-bit unsigned immediate attached to a load, store or prfm - /// instruction. If operand requires a relocation, record it and - /// return zero in that part of the encoding. + /// getLdStUImm12OpValue - Return encoding info for 12-bit unsigned immediate + /// attached to a load, store or prfm instruction. If operand requires a + /// relocation, record it and return zero in that part of the encoding. template - uint32_t getAMIndexed8OpValue(const MCInst &MI, unsigned OpIdx, + uint32_t getLdStUImm12OpValue(const MCInst &MI, unsigned OpIdx, SmallVectorImpl &Fixups, const MCSubtargetInfo &STI) const; @@ -89,6 +88,13 @@ public: SmallVectorImpl &Fixups, const MCSubtargetInfo &STI) const; + /// getMemExtendOpValue - Return the encoded value for a reg-extend load/store + /// instruction: bit 0 is whether a shift is present, bit 1 is whether the + /// operation is a sign extend (as opposed to a zero extend). + uint32_t getMemExtendOpValue(const MCInst &MI, unsigned OpIdx, + SmallVectorImpl &Fixups, + const MCSubtargetInfo &STI) const; + /// getTestBranchTargetOpValue - Return the encoded value for a test-bit-and- /// branch target. uint32_t getTestBranchTargetOpValue(const MCInst &MI, unsigned OpIdx, @@ -221,15 +227,11 @@ ARM64MCCodeEmitter::getMachineOpValue(const MCInst &MI, const MCOperand &MO, return 0; } -template -uint32_t -ARM64MCCodeEmitter::getAMIndexed8OpValue(const MCInst &MI, unsigned OpIdx, +template uint32_t +ARM64MCCodeEmitter::getLdStUImm12OpValue(const MCInst &MI, unsigned OpIdx, SmallVectorImpl &Fixups, const MCSubtargetInfo &STI) const { - unsigned BaseReg = MI.getOperand(OpIdx).getReg(); - BaseReg = Ctx.getRegisterInfo()->getEncodingValue(BaseReg); - - const MCOperand &MO = MI.getOperand(OpIdx + 1); + const MCOperand &MO = MI.getOperand(OpIdx); uint32_t ImmVal = 0; if (MO.isImm()) @@ -241,7 +243,7 @@ ARM64MCCodeEmitter::getAMIndexed8OpValue(const MCInst &MI, unsigned OpIdx, ++MCNumFixups; } - return BaseReg | (ImmVal << 5); + return ImmVal; } /// getAdrLabelOpValue - Return encoding info for 21-bit immediate ADR label @@ -255,7 +257,7 @@ ARM64MCCodeEmitter::getAdrLabelOpValue(const MCInst &MI, unsigned OpIdx, // If the destination is an immediate, we have nothing to do. if (MO.isImm()) return MO.getImm(); - assert(MO.isExpr() && "Unexpected ADR target type!"); + assert(MO.isExpr() && "Unexpected target type!"); const MCExpr *Expr = MO.getExpr(); MCFixupKind Kind = MI.getOpcode() == ARM64::ADR @@ -341,6 +343,15 @@ ARM64MCCodeEmitter::getLoadLiteralOpValue(const MCInst &MI, unsigned OpIdx, return 0; } +uint32_t +ARM64MCCodeEmitter::getMemExtendOpValue(const MCInst &MI, unsigned OpIdx, + SmallVectorImpl &Fixups, + const MCSubtargetInfo &STI) const { + unsigned SignExtend = MI.getOperand(OpIdx).getImm(); + unsigned DoShift = MI.getOperand(OpIdx + 1).getImm(); + return (SignExtend << 1) | DoShift; +} + uint32_t ARM64MCCodeEmitter::getMoveWideImmOpValue(const MCInst &MI, unsigned OpIdx, SmallVectorImpl &Fixups, diff --git a/test/MC/AArch64/basic-a64-diagnostics.s b/test/MC/AArch64/basic-a64-diagnostics.s index 42493a2ef7a..213dc00f0a6 100644 --- a/test/MC/AArch64/basic-a64-diagnostics.s +++ b/test/MC/AArch64/basic-a64-diagnostics.s @@ -1803,7 +1803,7 @@ stxrb w2, w3, [x4, #20] stlxrh w10, w11, [w2] // CHECK-ERROR-AARCH64: error: expected '#0' -// CHECK-ERROR-ARM64: error: invalid operand for instruction +// CHECK-ERROR-ARM64: error: index must be absent or #0 // CHECK-ERROR-NEXT: stxrb w2, w3, [x4, #20] // CHECK-ERROR-NEXT: ^ // CHECK-ERROR: error: invalid operand for instruction @@ -1887,7 +1887,8 @@ //------------------------------------------------------------------------------ ldr x3, [x4, #25], #0 ldr x4, [x9, #0], #4 -// CHECK-ERROR: error: {{expected symbolic reference or integer|index must be a multiple of 8}} in range [0, 32760] +// CHECK-ERROR-AARCH64: error: {{expected symbolic reference or integer|index must be a multiple of 8}} in range [0, 32760] +// CHECK-ERROR-ARM64: error: invalid operand for instruction // CHECK-ERROR-NEXT: ldr x3, [x4, #25], #0 // CHECK-ERROR-NEXT: ^ // CHECK-ERROR-AARCH64-NEXT: error: invalid operand for instruction @@ -2083,22 +2084,19 @@ strh w9, [sp, #-257]! str w1, [x19, #256]! str w9, [sp, #-257]! -// CHECK-ERROR-AARCH64: error: invalid operand for instruction -// CHECK-ERROR-ARM64: error: invalid offset in memory address +// CHECK-ERROR: error: invalid operand for instruction // CHECK-ERROR-NEXT: strb w1, [x19, #256]! // CHECK-ERROR-NEXT: ^ // CHECK-ERROR-NEXT: error: {{expected|index must be an}} integer in range [-256, 255] // CHECK-ERROR-NEXT: strb w9, [sp, #-257]! // CHECK-ERROR-NEXT: ^ -// CHECK-ERROR-AARCH64-NEXT: error: invalid operand for instruction -// CHECK-ERROR-ARM64-NEXT: error: invalid offset in memory address +// CHECK-ERROR-NEXT: error: invalid operand for instruction // CHECK-ERROR-NEXT: strh w1, [x19, #256]! // CHECK-ERROR-NEXT: ^ // CHECK-ERROR-NEXT: error: {{expected|index must be an}} integer in range [-256, 255] // CHECK-ERROR-NEXT: strh w9, [sp, #-257]! // CHECK-ERROR-NEXT: ^ -// CHECK-ERROR-AARCH64-NEXT: error: invalid operand for instruction -// CHECK-ERROR-ARM64-NEXT: error: invalid offset in memory address +// CHECK-ERROR-NEXT: error: invalid operand for instruction // CHECK-ERROR-NEXT: str w1, [x19, #256]! // CHECK-ERROR-NEXT: ^ // CHECK-ERROR-NEXT: error: {{expected|index must be an}} integer in range [-256, 255] @@ -2111,22 +2109,19 @@ ldrh w9, [sp, #-257]! ldr w1, [x19, #256]! ldr w9, [sp, #-257]! -// CHECK-ERROR-AARCH64: error: invalid operand for instruction -// CHECK-ERROR-ARM64: error: invalid offset in memory address +// CHECK-ERROR: error: invalid operand for instruction // CHECK-ERROR-NEXT: ldrb w1, [x19, #256]! // CHECK-ERROR-NEXT: ^ // CHECK-ERROR-NEXT: error: {{expected|index must be an}} integer in range [-256, 255] // CHECK-ERROR-NEXT: ldrb w9, [sp, #-257]! // CHECK-ERROR-NEXT: ^ -// CHECK-ERROR-AARCH64-NEXT: error: invalid operand for instruction -// CHECK-ERROR-ARM64-NEXT: error: invalid offset in memory address +// CHECK-ERROR-NEXT: error: invalid operand for instruction // CHECK-ERROR-NEXT: ldrh w1, [x19, #256]! // CHECK-ERROR-NEXT: ^ // CHECK-ERROR-NEXT: error: {{expected|index must be an}} integer in range [-256, 255] // CHECK-ERROR-NEXT: ldrh w9, [sp, #-257]! // CHECK-ERROR-NEXT: ^ -// CHECK-ERROR-AARCH64-NEXT: error: invalid operand for instruction -// CHECK-ERROR-ARM64-NEXT: error: invalid offset in memory address +// CHECK-ERROR-NEXT: error: invalid operand for instruction // CHECK-ERROR-NEXT: ldr w1, [x19, #256]! // CHECK-ERROR-NEXT: ^ // CHECK-ERROR-NEXT: error: {{expected|index must be an}} integer in range [-256, 255] @@ -2139,22 +2134,19 @@ ldrsh x22, [x13, #-257]! ldrsw x2, [x3, #256]! ldrsw x22, [x13, #-257]! -// CHECK-ERROR-AARCH64: error: invalid operand for instruction -// CHECK-ERROR-ARM64: error: invalid offset in memory address +// CHECK-ERROR: error: invalid operand for instruction // CHECK-ERROR-NEXT: ldrsb x2, [x3, #256]! // CHECK-ERROR-NEXT: ^ // CHECK-ERROR-NEXT: error: {{expected|index must be an}} integer in range [-256, 255] // CHECK-ERROR-NEXT: ldrsb x22, [x13, #-257]! // CHECK-ERROR-NEXT: ^ -// CHECK-ERROR-AARCH64-NEXT: error: invalid operand for instruction -// CHECK-ERROR-ARM64-NEXT: error: invalid offset in memory address +// CHECK-ERROR-NEXT: error: invalid operand for instruction // CHECK-ERROR-NEXT: ldrsh x2, [x3, #256]! // CHECK-ERROR-NEXT: ^ // CHECK-ERROR-NEXT: error: {{expected|index must be an}} integer in range [-256, 255] // CHECK-ERROR-NEXT: ldrsh x22, [x13, #-257]! // CHECK-ERROR-NEXT: ^ -// CHECK-ERROR-AARCH64-NEXT: error: invalid operand for instruction -// CHECK-ERROR-ARM64-NEXT: error: invalid offset in memory address +// CHECK-ERROR-NEXT: error: invalid operand for instruction // CHECK-ERROR-NEXT: ldrsw x2, [x3, #256]! // CHECK-ERROR-NEXT: ^ // CHECK-ERROR-NEXT: error: {{expected|index must be an}} integer in range [-256, 255] @@ -2165,15 +2157,13 @@ ldrsb w22, [x13, #-257]! ldrsh w2, [x3, #256]! ldrsh w22, [x13, #-257]! -// CHECK-ERROR-AARCH64: error: invalid operand for instruction -// CHECK-ERROR-ARM64: error: invalid offset in memory address +// CHECK-ERROR: error: invalid operand for instruction // CHECK-ERROR-NEXT: ldrsb w2, [x3, #256]! // CHECK-ERROR-NEXT: ^ // CHECK-ERROR-NEXT: error: {{expected|index must be an}} integer in range [-256, 255] // CHECK-ERROR-NEXT: ldrsb w22, [x13, #-257]! // CHECK-ERROR-NEXT: ^ -// CHECK-ERROR-AARCH64-NEXT: error: invalid operand for instruction -// CHECK-ERROR-ARM64-NEXT: error: invalid offset in memory address +// CHECK-ERROR-NEXT: error: invalid operand for instruction // CHECK-ERROR-NEXT: ldrsh w2, [x3, #256]! // CHECK-ERROR-NEXT: ^ // CHECK-ERROR-NEXT: error: {{expected|index must be an}} integer in range [-256, 255] @@ -2188,29 +2178,25 @@ str s3, [x13, #-257]! str d3, [x3, #256]! str d3, [x13, #-257]! -// CHECK-ERROR-AARCH64: error: invalid operand for instruction -// CHECK-ERROR-ARM64: error: invalid offset in memory address +// CHECK-ERROR: error: invalid operand for instruction // CHECK-ERROR-NEXT: str b3, [x3, #256]! // CHECK-ERROR-NEXT: ^ // CHECK-ERROR-NEXT: error: {{expected|index must be an}} integer in range [-256, 255] // CHECK-ERROR-NEXT: str b3, [x13, #-257]! // CHECK-ERROR-NEXT: ^ -// CHECK-ERROR-AARCH64-NEXT: error: invalid operand for instruction -// CHECK-ERROR-ARM64-NEXT: error: invalid offset in memory address +// CHECK-ERROR-NEXT: error: invalid operand for instruction // CHECK-ERROR-NEXT: str h3, [x3, #256]! // CHECK-ERROR-NEXT: ^ // CHECK-ERROR-NEXT: error: {{expected|index must be an}} integer in range [-256, 255] // CHECK-ERROR-NEXT: str h3, [x13, #-257]! // CHECK-ERROR-NEXT: ^ -// CHECK-ERROR-AARCH64-NEXT: error: invalid operand for instruction -// CHECK-ERROR-ARM64-NEXT: error: invalid offset in memory address +// CHECK-ERROR-NEXT: error: invalid operand for instruction // CHECK-ERROR-NEXT: str s3, [x3, #256]! // CHECK-ERROR-NEXT: ^ // CHECK-ERROR-NEXT: error: {{expected|index must be an}} integer in range [-256, 255] // CHECK-ERROR-NEXT: str s3, [x13, #-257]! // CHECK-ERROR-NEXT: ^ -// CHECK-ERROR-AARCH64-NEXT: error: invalid operand for instruction -// CHECK-ERROR-ARM64-NEXT: error: invalid offset in memory address +// CHECK-ERROR-NEXT: error: invalid operand for instruction // CHECK-ERROR-NEXT: str d3, [x3, #256]! // CHECK-ERROR-NEXT: ^ // CHECK-ERROR-NEXT: error: {{expected|index must be an}} integer in range [-256, 255] @@ -2225,29 +2211,25 @@ ldr s3, [x13, #-257]! ldr d3, [x3, #256]! ldr d3, [x13, #-257]! -// CHECK-ERROR-AARCH64: error: invalid operand for instruction -// CHECK-ERROR-ARM64: error: invalid offset in memory address +// CHECK-ERROR: error: invalid operand for instruction // CHECK-ERROR-NEXT: ldr b3, [x3, #256]! // CHECK-ERROR-NEXT: ^ // CHECK-ERROR-NEXT: error: {{expected|index must be an}} integer in range [-256, 255] // CHECK-ERROR-NEXT: ldr b3, [x13, #-257]! // CHECK-ERROR-NEXT: ^ -// CHECK-ERROR-AARCH64-NEXT: error: invalid operand for instruction -// CHECK-ERROR-ARM64-NEXT: error: invalid offset in memory address +// CHECK-ERROR-NEXT: error: invalid operand for instruction // CHECK-ERROR-NEXT: ldr h3, [x3, #256]! // CHECK-ERROR-NEXT: ^ // CHECK-ERROR-NEXT: error: {{expected|index must be an}} integer in range [-256, 255] // CHECK-ERROR-NEXT: ldr h3, [x13, #-257]! // CHECK-ERROR-NEXT: ^ -// CHECK-ERROR-AARCH64-NEXT: error: invalid operand for instruction -// CHECK-ERROR-ARM64-NEXT: error: invalid offset in memory address +// CHECK-ERROR-NEXT: error: invalid operand for instruction // CHECK-ERROR-NEXT: ldr s3, [x3, #256]! // CHECK-ERROR-NEXT: ^ // CHECK-ERROR-NEXT: error: {{expected|index must be an}} integer in range [-256, 255] // CHECK-ERROR-NEXT: ldr s3, [x13, #-257]! // CHECK-ERROR-NEXT: ^ -// CHECK-ERROR-AARCH64-NEXT: error: invalid operand for instruction -// CHECK-ERROR-ARM64-NEXT: error: invalid offset in memory address +// CHECK-ERROR-NEXT: error: invalid operand for instruction // CHECK-ERROR-NEXT: ldr d3, [x3, #256]! // CHECK-ERROR-NEXT: ^ // CHECK-ERROR-NEXT: error: {{expected|index must be an}} integer in range [-256, 255] @@ -2262,20 +2244,16 @@ sttrh w17, [x1, #256] ldtrsw x20, [x1, #256] ldtr x12, [sp, #256] -// CHECK-ERROR-AARCH64: error: expected integer in range [-256, 255] -// CHECK-ERROR-ARM64: error: invalid offset in memory address +// CHECK-ERROR: error: {{expected|index must be an}} integer in range [-256, 255] // CHECK-ERROR-NEXT: ldtrb w2, [sp, #256] // CHECK-ERROR-NEXT: ^ -// CHECK-ERROR-AARCH64-NEXT: error: {{expected|index must be an}} integer in range [-256, 255] -// CHECK-ERROR-ARM64-NEXT: error: invalid offset in memory address +// CHECK-ERROR-NEXT: error: {{expected|index must be an}} integer in range [-256, 255] // CHECK-ERROR-NEXT: sttrh w17, [x1, #256] // CHECK-ERROR-NEXT: ^ -// CHECK-ERROR-AARCH64-NEXT: error: {{expected|index must be an}} integer in range [-256, 255] -// CHECK-ERROR-ARM64-NEXT: error: invalid offset in memory address +// CHECK-ERROR-NEXT: error: {{expected|index must be an}} integer in range [-256, 255] // CHECK-ERROR-NEXT: ldtrsw x20, [x1, #256] // CHECK-ERROR-NEXT: ^ -// CHECK-ERROR-AARCH64-NEXT: error: {{expected|index must be an}} integer in range [-256, 255] -// CHECK-ERROR-ARM64-NEXT: error: invalid offset in memory address +// CHECK-ERROR-NEXT: error: {{expected|index must be an}} integer in range [-256, 255] // CHECK-ERROR-NEXT: ldtr x12, [sp, #256] // CHECK-ERROR-NEXT: ^ @@ -2290,12 +2268,10 @@ // CHECK-ERROR-NEXT: error: invalid operand for instruction // CHECK-ERROR-NEXT: sttr b2, [x2, #-257] // CHECK-ERROR-NEXT: ^ -// CHECK-ERROR-AARCH64-NEXT: error: {{expected|index must be an}} integer in range [-256, 255] -// CHECK-ERROR-ARM64-NEXT: error: invalid offset in memory address +// CHECK-ERROR-NEXT: error: {{expected|index must be an}} integer in range [-256, 255] // CHECK-ERROR-NEXT: ldtrsb x9, [sp, #-257] // CHECK-ERROR-NEXT: ^ -// CHECK-ERROR-AARCH64-NEXT: error: {{expected|index must be an}} integer in range [-256, 255] -// CHECK-ERROR-ARM64-NEXT: error: invalid offset in memory address +// CHECK-ERROR-NEXT: error: {{expected|index must be an}} integer in range [-256, 255] // CHECK-ERROR-NEXT: ldtr w2, [x30, #-257] // CHECK-ERROR-NEXT: ^ // CHECK-ERROR-NEXT: error: invalid operand for instruction @@ -2313,24 +2289,19 @@ ldr w0, [x4, #16384] ldrh w2, [x21, #8192] ldrb w3, [x12, #4096] -// CHECK-ERROR-AARCH64: error: {{expected|index must be an}} integer in range [-256, 255] -// CHECK-ERROR-ARM64: error: invalid offset in memory address +// CHECK-ERROR: error: {{expected|index must be an}} integer in range [-256, 255] // CHECK-ERROR-NEXT: ldr q0, [x11, #65536] // CHECK-ERROR-NEXT: ^ -// CHECK-ERROR-AARCH64-NEXT: error: {{expected|index must be an}} integer in range [-256, 255] -// CHECK-ERROR-ARM64-NEXT: error: invalid offset in memory address +// CHECK-ERROR-NEXT: error: {{expected|index must be an}} integer in range [-256, 255] // CHECK-ERROR-NEXT: ldr x0, [sp, #32768] // CHECK-ERROR-NEXT: ^ -// CHECK-ERROR-AARCH64-NEXT: error: {{expected|index must be an}} integer in range [-256, 255] -// CHECK-ERROR-ARM64-NEXT: error: invalid offset in memory address +// CHECK-ERROR-NEXT: error: {{expected|index must be an}} integer in range [-256, 255] // CHECK-ERROR-NEXT: ldr w0, [x4, #16384] // CHECK-ERROR-NEXT: ^ -// CHECK-ERROR-AARCH64-NEXT: error: {{expected|index must be an}} integer in range [-256, 255] -// CHECK-ERROR-ARM64-NEXT: error: invalid offset in memory address +// CHECK-ERROR-NEXT: error: {{expected|index must be an}} integer in range [-256, 255] // CHECK-ERROR-NEXT: ldrh w2, [x21, #8192] // CHECK-ERROR-NEXT: ^ -// CHECK-ERROR-AARCH64-NEXT: error: {{expected|index must be an}} integer in range [-256, 255] -// CHECK-ERROR-ARM64-NEXT: error: invalid offset in memory address +// CHECK-ERROR-NEXT: error: {{expected|index must be an}} integer in range [-256, 255] // CHECK-ERROR-NEXT: ldrb w3, [x12, #4096] // CHECK-ERROR-NEXT: ^ @@ -2372,8 +2343,7 @@ // CHECK-ERROR-AARCH64-NEXT: error: too few operands for instruction // CHECK-ERROR-AARCH64-NEXT: str x5, [x22, #12] // CHECK-ERROR-AARCH64-NEXT: ^ -// CHECK-ERROR-AARCH64-NEXT: error: {{expected|index must be an}} integer in range [-256, 255] -// CHECK-ERROR-ARM64-NEXT: error: invalid offset in memory address +// CHECK-ERROR-NEXT: error: {{expected|index must be an}} integer in range [-256, 255] // CHECK-ERROR-NEXT: str w7, [x12, #16384] // CHECK-ERROR-NEXT: ^ @@ -2411,92 +2381,78 @@ // CHECK-ERROR-NEXT: error: invalid operand for instruction // CHECK-ERROR-NEXT: ldr w3, [xzr, x3] // CHECK-ERROR-NEXT: ^ -// CHECK-ERROR-AARCH64-NEXT: error: expected #imm after shift specifier -// CHECK-ERROR-ARM64-NEXT: error: LSL extend requires immediate operand +// CHECK-ERROR-NEXT: error: expected #imm after shift specifier // CHECK-ERROR-NEXT: ldr w4, [x0, x4, lsl] // CHECK-ERROR-NEXT: ^ -// CHECK-ERROR-AARCH64-NEXT: error: expected 'lsl' or 'sxtx' with optional shift of #0 or #2 -// CHECK-ERROR-AARCH64-NEXT: ldr w9, [x5, x5, uxtw] -// CHECK-ERROR-AARCH64-NEXT: ^ -// CHECK-ERROR-AARCH64-NEXT: error: expected 'lsl' or 'sxtx' with optional shift of #0 or #2 -// CHECK-ERROR-AARCH64-NEXT: ldr w10, [x6, x9, sxtw #2] -// CHECK-ERROR-AARCH64-NEXT: ^ -// CHECK-ERROR-AARCH64-NEXT: error: expected 'uxtw' or 'sxtw' with optional shift of #0 or #2 -// CHECK-ERROR-ARM64-NEXT: error: 32-bit general purpose offset register requires sxtw or uxtw extend +// CHECK-ERROR-NEXT: error: expected 'lsl' or 'sxtx' with optional shift of #0 or #2 +// CHECK-ERROR-NEXT: ldr w9, [x5, x5, uxtw] +// CHECK-ERROR-NEXT: ^ +// CHECK-ERROR-NEXT: error: expected 'lsl' or 'sxtx' with optional shift of #0 or #2 +// CHECK-ERROR-NEXT: ldr w10, [x6, x9, sxtw #2] +// CHECK-ERROR-NEXT: ^ +// CHECK-ERROR-NEXT: error: expected 'uxtw' or 'sxtw' with optional shift of #0 or #2 // CHECK-ERROR-NEXT: ldr w11, [x7, w2, lsl #2] // CHECK-ERROR-NEXT: ^ -// CHECK-ERROR-AARCH64-NEXT: error: expected 'uxtw' or 'sxtw' with optional shift of #0 or #2 -// CHECK-ERROR-ARM64-NEXT: error: 32-bit general purpose offset register requires sxtw or uxtw extend +// CHECK-ERROR-NEXT: error: expected 'uxtw' or 'sxtw' with optional shift of #0 or #2 // CHECK-ERROR-NEXT: ldr w12, [x8, w1, sxtx] // CHECK-ERROR-NEXT: ^ ldrsb w9, [x4, x2, lsl #-1] strb w9, [x4, x2, lsl #1] -// CHECK-ERROR-AARCH64-NEXT: error: expected integer shift amount -// CHECK-ERROR-ARM64-NEXT: error: immediate operand out of range +// CHECK-ERROR-NEXT: error: expected integer shift amount // CHECK-ERROR-NEXT: ldrsb w9, [x4, x2, lsl #-1] // CHECK-ERROR-NEXT: ^ -// CHECK-ERROR-AARCH64-NEXT: error: expected 'lsl' or 'sxtx' with optional shift of #0 -// CHECK-ERROR-ARM64-NEXT: error: invalid offset in memory address +// CHECK-ERROR-NEXT: error: expected 'lsl' or 'sxtx' with optional shift of #0 // CHECK-ERROR-NEXT: strb w9, [x4, x2, lsl #1] // CHECK-ERROR-NEXT: ^ ldrsh w9, [x4, x2, lsl #-1] ldr h13, [x4, w2, uxtw #2] -// CHECK-ERROR-AARCH64-NEXT: error: expected integer shift amount -// CHECK-ERROR-ARM64-NEXT: error: immediate operand out of range +// CHECK-ERROR-NEXT: error: expected integer shift amount // CHECK-ERROR-NEXT: ldrsh w9, [x4, x2, lsl #-1] // CHECK-ERROR-NEXT: ^ -// CHECK-ERROR-AARCH64-NEXT: error: expected 'uxtw' or 'sxtw' with optional shift of #0 or #1 -// CHECK-ERROR-ARM64-NEXT: error: invalid offset in memory address +// CHECK-ERROR-NEXT: error: expected 'uxtw' or 'sxtw' with optional shift of #0 or #1 // CHECK-ERROR-NEXT: ldr h13, [x4, w2, uxtw #2] // CHECK-ERROR-NEXT: ^ str w9, [x5, w9, sxtw #-1] str s3, [sp, w9, uxtw #1] ldrsw x9, [x15, x4, sxtx #3] -// CHECK-ERROR-AARCH64-NEXT: error: expected integer shift amount -// CHECK-ERROR-ARM64-NEXT: error: immediate operand out of range +// CHECK-ERROR-NEXT: error: expected integer shift amount // CHECK-ERROR-NEXT: str w9, [x5, w9, sxtw #-1] // CHECK-ERROR-NEXT: ^ -// CHECK-ERROR-AARCH64-NEXT: error: expected 'uxtw' or 'sxtw' with optional shift of #0 or #2 -// CHECK-ERROR-ARM64-NEXT: error: invalid offset in memory address +// CHECK-ERROR-NEXT: error: expected 'uxtw' or 'sxtw' with optional shift of #0 or #2 // CHECK-ERROR-NEXT: str s3, [sp, w9, uxtw #1] // CHECK-ERROR-NEXT: ^ -// CHECK-ERROR-AARCH64-NEXT: error: expected 'lsl' or 'sxtx' with optional shift of #0 or #2 -// CHECK-ERROR-ARM64-NEXT: error: invalid offset in memory address +// CHECK-ERROR-NEXT: error: expected 'lsl' or 'sxtx' with optional shift of #0 or #2 // CHECK-ERROR-NEXT: ldrsw x9, [x15, x4, sxtx #3] // CHECK-ERROR-NEXT: ^ str xzr, [x5, x9, sxtx #-1] prfm pldl3keep, [sp, x20, lsl #2] ldr d3, [x20, wzr, uxtw #4] -// CHECK-ERROR-AARCH64-NEXT: error: expected integer shift amount -// CHECK-ERROR-ARM64-NEXT: error: immediate operand out of range +// CHECK-ERROR-NEXT: error: expected integer shift amount // CHECK-ERROR-NEXT: str xzr, [x5, x9, sxtx #-1] // CHECK-ERROR-NEXT: ^ -// CHECK-ERROR-AARCH64-NEXT: error: expected 'lsl' or 'sxtx' with optional shift of #0 or #3 -// CHECK-ERROR-ARM64-NEXT: error: expected label or encodable integer pc offset +// CHECK-ERROR-NEXT: error: expected 'lsl' or 'sxtx' with optional shift of #0 or #3 // CHECK-ERROR-NEXT: prfm pldl3keep, [sp, x20, lsl #2] // CHECK-ERROR-NEXT: ^ -// CHECK-ERROR-AARCH64-NEXT: error: expected 'uxtw' or 'sxtw' with optional shift of #0 or #3 -// CHECK-ERROR-ARM64-NEXT: error: invalid offset in memory address +// CHECK-ERROR-NEXT: error: expected 'uxtw' or 'sxtw' with optional shift of #0 or #3 // CHECK-ERROR-NEXT: ldr d3, [x20, wzr, uxtw #4] // CHECK-ERROR-NEXT: ^ ldr q5, [sp, x2, lsl #-1] ldr q10, [x20, w4, uxtw #2] str q21, [x20, w4, uxtw #5] -// CHECK-ERROR-AARCH64-NEXT: error: expected integer shift amount -// CHECK-ERROR-ARM64-NEXT: error: immediate operand out of range +// CHECK-ERROR-NEXT: error: expected integer shift amount // CHECK-ERROR-NEXT: ldr q5, [sp, x2, lsl #-1] // CHECK-ERROR-NEXT: ^ // CHECK-ERROR-AARCH64-NEXT: error: expected 'lsl' or 'sxtw' with optional shift of #0 or #4 -// CHECK-ERROR-ARM64-NEXT: error: invalid offset in memory address +// CHECK-ERROR-ARM64-NEXT: error: expected 'uxtw' or 'sxtw' with optional shift of #0 or #4 // CHECK-ERROR-NEXT: ldr q10, [x20, w4, uxtw #2] // CHECK-ERROR-NEXT: ^ // CHECK-ERROR-AARCH64-NEXT: error: expected 'lsl' or 'sxtw' with optional shift of #0 or #4 -// CHECK-ERROR-ARM64-NEXT: error: immediate operand out of range +// CHECK-ERROR-ARM64-NEXT: error: expected 'uxtw' or 'sxtw' with optional shift of #0 or #4 // CHECK-ERROR-NEXT: str q21, [x20, w4, uxtw #5] // CHECK-ERROR-NEXT: ^ @@ -2695,16 +2651,13 @@ // CHECK-ERROR: error: invalid operand for instruction // CHECK-ERROR-NEXT: ldp d3, q2, [sp], #0 // CHECK-ERROR-NEXT: ^ -// CHECK-ERROR-AARCH64-NEXT: error: {{expected integer|index must be a}} multiple of 16 in range [-1024, 1008] -// CHECK-ERROR-ARM64-NEXT: error: {{expected integer|index must be a}} multiple of 8 in range [-512, 504] +// CHECK-ERROR-NEXT: error: {{expected integer|index must be a}} multiple of 16 in range [-1024, 1008] // CHECK-ERROR-NEXT: ldp q3, q5, [sp], #8 // CHECK-ERROR-NEXT: ^ -// CHECK-ERROR-AARCH64-NEXT: error: {{expected integer|index must be a}} multiple of 16 in range [-1024, 1008] -// CHECK-ERROR-ARM64-NEXT: error: {{expected integer|index must be a}} multiple of 8 in range [-512, 504] +// CHECK-ERROR-NEXT: error: {{expected integer|index must be a}} multiple of 16 in range [-1024, 1008] // CHECK-ERROR-NEXT: stp q20, q25, [x5], #1024 // CHECK-ERROR-NEXT: ^ -// CHECK-ERROR-AARCH64-NEXT: error: {{expected integer|index must be a}} multiple of 16 in range [-1024, 1008] -// CHECK-ERROR-ARM64-NEXT: error: {{expected integer|index must be a}} multiple of 8 in range [-512, 504] +// CHECK-ERROR-NEXT: error: {{expected integer|index must be a}} multiple of 16 in range [-1024, 1008] // CHECK-ERROR-NEXT: ldp q30, q15, [x23], #-1040 // CHECK-ERROR-NEXT: ^ diff --git a/test/MC/AArch64/neon-diagnostics.s b/test/MC/AArch64/neon-diagnostics.s index 03c678f28f7..10fdde46028 100644 --- a/test/MC/AArch64/neon-diagnostics.s +++ b/test/MC/AArch64/neon-diagnostics.s @@ -4080,8 +4080,7 @@ // CHECK-ARM64-ERROR: error: vector register expected // CHECK-ERROR: ld1 {v32.16b}, [x0] // CHECK-ERROR: ^ -// CHECK-AARCH64-ERROR: error: invalid operand for instruction -// CHECK-ARM64-ERROR: error: register expected +// CHECK-ERROR: error: invalid operand for instruction // CHECK-ERROR: ld1 {v15.8h}, [x32] // CHECK-ERROR: ^ @@ -4130,8 +4129,7 @@ // CHECK-ARM64-ERROR: error: registers must be sequential // CHECK-ERROR: ld2 {v0.8b, v2.8b}, [x0] // CHECK-ERROR: ^ -// CHECK-AARCH64-ERROR: error: invalid operand for instruction -// CHECK-ARM64-ERROR: error: register expected +// CHECK-AARCH64: error: invalid operand for instruction // CHECK-ERROR: ld2 {v15.4h, v16.4h, v17.4h}, [x32] // CHECK-ERROR: ^ // CHECK-AARCH64-ERROR: error: expected the same vector layout @@ -4207,8 +4205,7 @@ // CHECK-ARM64-ERROR: error: vector register expected // CHECK-ERROR: st1 {v32.16b}, [x0] // CHECK-ERROR: ^ -// CHECK-AARCH64-ERROR: error: invalid operand for instruction -// CHECK-ARM64-ERROR: error: register expected +// CHECK-ERROR: error: invalid operand for instruction // CHECK-ERROR: st1 {v15.8h}, [x32] // CHECK-ERROR: ^ @@ -4434,8 +4431,7 @@ // CHECK-ARM64-ERROR: vector lane must be an integer in range // CHECK-ERROR: st1 {v0.d}[16], [x0] // CHECK-ERROR: ^ -// CHECK-AARCH64-ERROR: error: invalid operand for instruction -// CHECK-ARM64-ERROR: error: register expected +// CHECK-ERROR: error: invalid operand for instruction // CHECK-ERROR: st2 {v31.s, v0.s}[3], [8] // CHECK-ERROR: ^ // CHECK-AARCH64-ERROR: error: expected lane number diff --git a/test/MC/ARM64/diags.s b/test/MC/ARM64/diags.s index edbdfe98c2e..3ff2b54998f 100644 --- a/test/MC/ARM64/diags.s +++ b/test/MC/ARM64/diags.s @@ -9,7 +9,7 @@ foo: ldr x3, [foo + 4] ; CHECK: ldr x3, foo+4 ; encoding: [0bAAA00011,A,A,0x58] ; CHECK: ; fixup A - offset: 0, value: foo+4, kind: fixup_arm64_ldr_pcrel_imm19 -; CHECK-ERRORS: error: register expected +; CHECK-ERRORS: error: invalid operand for instruction ; The last argument should be flagged as an error. rdar://9576009 ld4.8b {v0, v1, v2, v3}, [x0], #33 @@ -33,10 +33,10 @@ foo: ldur x0, [x1, #-257] -; CHECK-ERRORS: error: invalid offset in memory address. +; CHECK-ERRORS: error: index must be an integer in range [-256, 255]. ; CHECK-ERRORS: ldr x0, [x0, #804] ; CHECK-ERRORS: ^ -; CHECK-ERRORS: error: invalid offset in memory address. +; CHECK-ERRORS: error: index must be an integer in range [-256, 255]. ; CHECK-ERRORS: ldr w0, [x0, #802] ; CHECK-ERRORS: ^ ; CHECK-ERRORS: error: index must be an integer in range [-256, 255]. @@ -66,7 +66,7 @@ foo: ; CHECK-ERRORS: error: index must be a multiple of 8 in range [-512, 504]. ; CHECK-ERRORS: ldp x3, x4, [x5], #12 ; CHECK-ERRORS: ^ -; CHECK-ERRORS: error: index must be a multiple of 8 in range [-512, 504]. +; CHECK-ERRORS: error: index must be a multiple of 16 in range [-1024, 1008]. ; CHECK-ERRORS: ldp q3, q4, [x5], #12 ; CHECK-ERRORS: ^ ; CHECK-ERRORS: error: index must be an integer in range [-256, 255]. @@ -84,31 +84,31 @@ ldr s1, [x3, w3, sxtw #4] ldr d1, [x3, w3, sxtw #4] ldr q1, [x3, w3, sxtw #1] -; CHECK-ERRORS: error: invalid offset in memory address. +; CHECK-ERRORS: error: expected 'uxtw' or 'sxtw' with optional shift of #0 ; CHECK-ERRORS:ldrb w1, [x3, w3, sxtw #4] ; CHECK-ERRORS: ^ -; CHECK-ERRORS: error: invalid offset in memory address. +; CHECK-ERRORS: error: expected 'uxtw' or 'sxtw' with optional shift of #0 or #1 ; CHECK-ERRORS:ldrh w1, [x3, w3, sxtw #4] ; CHECK-ERRORS: ^ -; CHECK-ERRORS: error: invalid offset in memory address. +; CHECK-ERRORS: error: expected 'uxtw' or 'sxtw' with optional shift of #0 or #2 ; CHECK-ERRORS:ldr w1, [x3, w3, sxtw #4] ; CHECK-ERRORS: ^ -; CHECK-ERRORS: error: invalid offset in memory address. +; CHECK-ERRORS: error: expected 'uxtw' or 'sxtw' with optional shift of #0 or #3 ; CHECK-ERRORS:ldr x1, [x3, w3, sxtw #4] ; CHECK-ERRORS: ^ -; CHECK-ERRORS: error: invalid offset in memory address. +; CHECK-ERRORS: error: expected 'uxtw' or 'sxtw' with optional shift of #0 ; CHECK-ERRORS:ldr b1, [x3, w3, sxtw #4] ; CHECK-ERRORS: ^ -; CHECK-ERRORS: invalid offset in memory address. +; CHECK-ERRORS: error: expected 'uxtw' or 'sxtw' with optional shift of #0 or #1 ; CHECK-ERRORS:ldr h1, [x3, w3, sxtw #4] ; CHECK-ERRORS: ^ -; CHECK-ERRORS: invalid offset in memory address. +; CHECK-ERRORS: error: expected 'uxtw' or 'sxtw' with optional shift of #0 or #2 ; CHECK-ERRORS:ldr s1, [x3, w3, sxtw #4] ; CHECK-ERRORS: ^ -; CHECK-ERRORS: invalid offset in memory address. +; CHECK-ERRORS: error: expected 'uxtw' or 'sxtw' with optional shift of #0 or #3 ; CHECK-ERRORS:ldr d1, [x3, w3, sxtw #4] ; CHECK-ERRORS: ^ -; CHECK-ERRORS: invalid offset in memory address. +; CHECK-ERRORS: error: expected 'uxtw' or 'sxtw' with optional shift of #0 or #4 ; CHECK-ERRORS:ldr q1, [x3, w3, sxtw #1] ; CHECK-ERRORS: ^ @@ -118,10 +118,10 @@ ldr q1, [x3, w3, sxtw #1] str d1, [x3, w3, sxtx #3] ldr s1, [x3, d3, sxtx #2] -; CHECK-ERRORS: 32-bit general purpose offset register requires sxtw or uxtw extend +; CHECK-ERRORS: error: expected 'uxtw' or 'sxtw' with optional shift of #0 or #3 ; CHECK-ERRORS: str d1, [x3, w3, sxtx #3] ; CHECK-ERRORS: ^ -; CHECK-ERRORS: error: 64-bit general purpose offset register expected +; CHECK-ERRORS: error: index must be an integer in range [-256, 255]. ; CHECK-ERRORS: ldr s1, [x3, d3, sxtx #2] ; CHECK-ERRORS: ^ diff --git a/utils/TableGen/CodeGenDAGPatterns.cpp b/utils/TableGen/CodeGenDAGPatterns.cpp index 1636fb42339..00bc9a5bbb9 100644 --- a/utils/TableGen/CodeGenDAGPatterns.cpp +++ b/utils/TableGen/CodeGenDAGPatterns.cpp @@ -1718,9 +1718,9 @@ bool TreePatternNode::ApplyTypeConstraints(TreePattern &TP, bool NotRegisters) { DagInit *MIOpInfo = OperandNode->getValueAsDag("MIOperandInfo"); if (unsigned NumArgs = MIOpInfo->getNumArgs()) { // But don't do that if the whole operand is being provided by - // a single ComplexPattern. - const ComplexPattern *AM = Child->getComplexPatternInfo(CDP); - if (!AM || AM->getNumOperands() < NumArgs) { + // a single ComplexPattern-related Operand. + + if (Child->getNumMIResults(CDP) < NumArgs) { // Match first sub-operand against the child we already have. Record *SubRec = cast(MIOpInfo->getArg(0))->getDef(); MadeChange |=