| //==- SystemZInstrFormats.td - SystemZ Instruction Formats --*- tablegen -*-==// |
| // |
| // The LLVM Compiler Infrastructure |
| // |
| // This file is distributed under the University of Illinois Open Source |
| // License. See LICENSE.TXT for details. |
| // |
| //===----------------------------------------------------------------------===// |
| |
| //===----------------------------------------------------------------------===// |
| // Basic SystemZ instruction definition |
| //===----------------------------------------------------------------------===// |
| |
| class InstSystemZ<int size, dag outs, dag ins, string asmstr, |
| list<dag> pattern> : Instruction { |
| let Namespace = "SystemZ"; |
| |
| dag OutOperandList = outs; |
| dag InOperandList = ins; |
| let Size = size; |
| let Pattern = pattern; |
| let AsmString = asmstr; |
| |
| // Used to identify a group of related instructions, such as ST and STY. |
| string Function = ""; |
| |
| // "12" for an instruction that has a ...Y equivalent, "20" for that |
| // ...Y equivalent. |
| string PairType = "none"; |
| |
| // True if this instruction is a simple D(X,B) load of a register |
| // (with no sign or zero extension). |
| bit SimpleBDXLoad = 0; |
| |
| // True if this instruction is a simple D(X,B) store of a register |
| // (with no truncation). |
| bit SimpleBDXStore = 0; |
| |
| // True if this instruction has a 20-bit displacement field. |
| bit Has20BitOffset = 0; |
| |
| // True if addresses in this instruction have an index register. |
| bit HasIndex = 0; |
| |
| // True if this is a 128-bit pseudo instruction that combines two 64-bit |
| // operations. |
| bit Is128Bit = 0; |
| |
| let TSFlags{0} = SimpleBDXLoad; |
| let TSFlags{1} = SimpleBDXStore; |
| let TSFlags{2} = Has20BitOffset; |
| let TSFlags{3} = HasIndex; |
| let TSFlags{4} = Is128Bit; |
| } |
| |
| //===----------------------------------------------------------------------===// |
| // Mappings between instructions |
| //===----------------------------------------------------------------------===// |
| |
| // Return the version of an instruction that has an unsigned 12-bit |
| // displacement. |
| def getDisp12Opcode : InstrMapping { |
| let FilterClass = "InstSystemZ"; |
| let RowFields = ["Function"]; |
| let ColFields = ["PairType"]; |
| let KeyCol = ["20"]; |
| let ValueCols = [["12"]]; |
| } |
| |
| // Return the version of an instruction that has a signed 20-bit displacement. |
| def getDisp20Opcode : InstrMapping { |
| let FilterClass = "InstSystemZ"; |
| let RowFields = ["Function"]; |
| let ColFields = ["PairType"]; |
| let KeyCol = ["12"]; |
| let ValueCols = [["20"]]; |
| } |
| |
| //===----------------------------------------------------------------------===// |
| // Instruction formats |
| //===----------------------------------------------------------------------===// |
| // |
| // Formats are specified using operand field declarations of the form: |
| // |
| // bits<4> Rn : register input or output for operand n |
| // bits<m> In : immediate value of width m for operand n |
| // bits<4> Bn : base register for address operand n |
| // bits<m> Dn : displacement value of width m for address operand n |
| // bits<4> Xn : index register for address operand n |
| // bits<4> Mn : mode value for operand n |
| // |
| // The operand numbers ("n" in the list above) follow the architecture manual, |
| // but the fields are always declared in assembly order, so there are some |
| // cases where operand "2" comes after operand "3". For address operands, |
| // the base register field is declared first, followed by the displacement, |
| // followed by the index (if any). This matches the bdaddr* and bdxaddr* |
| // orders. |
| // |
| //===----------------------------------------------------------------------===// |
| |
| class InstRI<bits<12> op, dag outs, dag ins, string asmstr, list<dag> pattern> |
| : InstSystemZ<4, outs, ins, asmstr, pattern> { |
| field bits<32> Inst; |
| |
| bits<4> R1; |
| bits<16> I2; |
| |
| let Inst{31-24} = op{11-4}; |
| let Inst{23-20} = R1; |
| let Inst{19-16} = op{3-0}; |
| let Inst{15-0} = I2; |
| } |
| |
| class InstRIEf<bits<16> op, dag outs, dag ins, string asmstr, list<dag> pattern> |
| : InstSystemZ<6, outs, ins, asmstr, pattern> { |
| field bits<48> Inst; |
| |
| bits<4> R1; |
| bits<4> R2; |
| bits<8> I3; |
| bits<8> I4; |
| bits<8> I5; |
| |
| let Inst{47-40} = op{15-8}; |
| let Inst{39-36} = R1; |
| let Inst{35-32} = R2; |
| let Inst{31-24} = I3; |
| let Inst{23-16} = I4; |
| let Inst{15-8} = I5; |
| let Inst{7-0} = op{7-0}; |
| } |
| |
| class InstRIL<bits<12> op, dag outs, dag ins, string asmstr, list<dag> pattern> |
| : InstSystemZ<6, outs, ins, asmstr, pattern> { |
| field bits<48> Inst; |
| |
| bits<4> R1; |
| bits<32> I2; |
| |
| let Inst{47-40} = op{11-4}; |
| let Inst{39-36} = R1; |
| let Inst{35-32} = op{3-0}; |
| let Inst{31-0} = I2; |
| } |
| |
| class InstRR<bits<8> op, dag outs, dag ins, string asmstr, list<dag> pattern> |
| : InstSystemZ<2, outs, ins, asmstr, pattern> { |
| field bits<16> Inst; |
| |
| bits<4> R1; |
| bits<4> R2; |
| |
| let Inst{15-8} = op; |
| let Inst{7-4} = R1; |
| let Inst{3-0} = R2; |
| } |
| |
| class InstRRD<bits<16> op, dag outs, dag ins, string asmstr, list<dag> pattern> |
| : InstSystemZ<4, outs, ins, asmstr, pattern> { |
| field bits<32> Inst; |
| |
| bits<4> R1; |
| bits<4> R3; |
| bits<4> R2; |
| |
| let Inst{31-16} = op; |
| let Inst{15-12} = R1; |
| let Inst{11-8} = 0; |
| let Inst{7-4} = R3; |
| let Inst{3-0} = R2; |
| } |
| |
| class InstRRE<bits<16> op, dag outs, dag ins, string asmstr, list<dag> pattern> |
| : InstSystemZ<4, outs, ins, asmstr, pattern> { |
| field bits<32> Inst; |
| |
| bits<4> R1; |
| bits<4> R2; |
| |
| let Inst{31-16} = op; |
| let Inst{15-8} = 0; |
| let Inst{7-4} = R1; |
| let Inst{3-0} = R2; |
| } |
| |
| class InstRRF<bits<16> op, dag outs, dag ins, string asmstr, list<dag> pattern> |
| : InstSystemZ<4, outs, ins, asmstr, pattern> { |
| field bits<32> Inst; |
| |
| bits<4> R1; |
| bits<4> R2; |
| bits<4> R3; |
| |
| let Inst{31-16} = op; |
| let Inst{15-12} = R3; |
| let Inst{11-8} = 0; |
| let Inst{7-4} = R1; |
| let Inst{3-0} = R2; |
| } |
| |
| class InstRX<bits<8> op, dag outs, dag ins, string asmstr, list<dag> pattern> |
| : InstSystemZ<4, outs, ins, asmstr, pattern> { |
| field bits<32> Inst; |
| |
| bits<4> R1; |
| bits<4> B2; |
| bits<12> D2; |
| bits<4> X2; |
| |
| let Inst{31-24} = op; |
| let Inst{23-20} = R1; |
| let Inst{19-16} = X2; |
| let Inst{15-12} = B2; |
| let Inst{11-0} = D2; |
| |
| let HasIndex = 1; |
| } |
| |
| class InstRXE<bits<16> op, dag outs, dag ins, string asmstr, list<dag> pattern> |
| : InstSystemZ<6, outs, ins, asmstr, pattern> { |
| field bits<48> Inst; |
| |
| bits<4> R1; |
| bits<4> B2; |
| bits<12> D2; |
| bits<4> X2; |
| |
| let Inst{47-40} = op{15-8}; |
| let Inst{39-36} = R1; |
| let Inst{35-32} = X2; |
| let Inst{31-28} = B2; |
| let Inst{27-16} = D2; |
| let Inst{15-8} = 0; |
| let Inst{7-0} = op{7-0}; |
| |
| let HasIndex = 1; |
| } |
| |
| class InstRXF<bits<16> op, dag outs, dag ins, string asmstr, list<dag> pattern> |
| : InstSystemZ<6, outs, ins, asmstr, pattern> { |
| field bits<48> Inst; |
| |
| bits<4> R1; |
| bits<4> R3; |
| bits<4> B2; |
| bits<12> D2; |
| bits<4> X2; |
| |
| let Inst{47-40} = op{15-8}; |
| let Inst{39-36} = R3; |
| let Inst{35-32} = X2; |
| let Inst{31-28} = B2; |
| let Inst{27-16} = D2; |
| let Inst{15-12} = R1; |
| let Inst{11-8} = 0; |
| let Inst{7-0} = op{7-0}; |
| |
| let HasIndex = 1; |
| } |
| |
| class InstRXY<bits<16> op, dag outs, dag ins, string asmstr, list<dag> pattern> |
| : InstSystemZ<6, outs, ins, asmstr, pattern> { |
| field bits<48> Inst; |
| |
| bits<4> R1; |
| bits<4> B2; |
| bits<20> D2; |
| bits<4> X2; |
| |
| let Inst{47-40} = op{15-8}; |
| let Inst{39-36} = R1; |
| let Inst{35-32} = X2; |
| let Inst{31-28} = B2; |
| let Inst{27-16} = D2{11-0}; |
| let Inst{15-8} = D2{19-12}; |
| let Inst{7-0} = op{7-0}; |
| |
| let Has20BitOffset = 1; |
| let HasIndex = 1; |
| } |
| |
| class InstRS<bits<8> op, dag outs, dag ins, string asmstr, list<dag> pattern> |
| : InstSystemZ<4, outs, ins, asmstr, pattern> { |
| field bits<32> Inst; |
| |
| bits<4> R1; |
| bits<4> R3; |
| bits<4> B2; |
| bits<12> D2; |
| |
| let Inst{31-24} = op; |
| let Inst{23-20} = R1; |
| let Inst{19-16} = R3; |
| let Inst{15-12} = B2; |
| let Inst{11-0} = D2; |
| } |
| |
| class InstRSY<bits<16> op, dag outs, dag ins, string asmstr, list<dag> pattern> |
| : InstSystemZ<6, outs, ins, asmstr, pattern> { |
| field bits<48> Inst; |
| |
| bits<4> R1; |
| bits<4> R3; |
| bits<4> B2; |
| bits<20> D2; |
| |
| let Inst{47-40} = op{15-8}; |
| let Inst{39-36} = R1; |
| let Inst{35-32} = R3; |
| let Inst{31-28} = B2; |
| let Inst{27-16} = D2{11-0}; |
| let Inst{15-8} = D2{19-12}; |
| let Inst{7-0} = op{7-0}; |
| |
| let Has20BitOffset = 1; |
| } |
| |
| class InstSI<bits<8> op, dag outs, dag ins, string asmstr, list<dag> pattern> |
| : InstSystemZ<4, outs, ins, asmstr, pattern> { |
| field bits<32> Inst; |
| |
| bits<4> B1; |
| bits<12> D1; |
| bits<8> I2; |
| |
| let Inst{31-24} = op; |
| let Inst{23-16} = I2; |
| let Inst{15-12} = B1; |
| let Inst{11-0} = D1; |
| } |
| |
| class InstSIL<bits<16> op, dag outs, dag ins, string asmstr, list<dag> pattern> |
| : InstSystemZ<6, outs, ins, asmstr, pattern> { |
| field bits<48> Inst; |
| |
| bits<4> B1; |
| bits<12> D1; |
| bits<16> I2; |
| |
| let Inst{47-32} = op; |
| let Inst{31-28} = B1; |
| let Inst{27-16} = D1; |
| let Inst{15-0} = I2; |
| } |
| |
| class InstSIY<bits<16> op, dag outs, dag ins, string asmstr, list<dag> pattern> |
| : InstSystemZ<6, outs, ins, asmstr, pattern> { |
| field bits<48> Inst; |
| |
| bits<4> B1; |
| bits<20> D1; |
| bits<8> I2; |
| |
| let Inst{47-40} = op{15-8}; |
| let Inst{39-32} = I2; |
| let Inst{31-28} = B1; |
| let Inst{27-16} = D1{11-0}; |
| let Inst{15-8} = D1{19-12}; |
| let Inst{7-0} = op{7-0}; |
| |
| let Has20BitOffset = 1; |
| } |
| |
| //===----------------------------------------------------------------------===// |
| // Instruction definitions with semantics |
| //===----------------------------------------------------------------------===// |
| // |
| // These classes have the form <Category><Format>, where <Format> is one |
| // of the formats defined above and where <Category> describes the inputs |
| // and outputs. <Category> can be one of: |
| // |
| // Inherent: |
| // One register output operand and no input operands. |
| // |
| // Store: |
| // One register or immediate input operand and one address input operand. |
| // The instruction stores the first operand to the address. |
| // |
| // This category is used for both pure and truncating stores. |
| // |
| // LoadMultiple: |
| // One address input operand and two explicit output operands. |
| // The instruction loads a range of registers from the address, |
| // with the explicit operands giving the first and last register |
| // to load. Other loaded registers are added as implicit definitions. |
| // |
| // StoreMultiple: |
| // Two explicit input register operands and an address operand. |
| // The instruction stores a range of registers to the address, |
| // with the explicit operands giving the first and last register |
| // to store. Other stored registers are added as implicit uses. |
| // |
| // Unary: |
| // One register output operand and one input operand. The input |
| // operand may be a register, immediate or memory. |
| // |
| // Binary: |
| // One register output operand and two input operands. The first |
| // input operand is always a register and he second may be a register, |
| // immediate or memory. |
| // |
| // Shift: |
| // One register output operand and two input operands. The first |
| // input operand is a register and the second has the same form as |
| // an address (although it isn't actually used to address memory). |
| // |
| // Compare: |
| // Two input operands. The first operand is always a register, |
| // the second may be a register, immediate or memory. |
| // |
| // Ternary: |
| // One register output operand and three register input operands. |
| // |
| // CmpSwap: |
| // One output operand and three input operands. The first two |
| // operands are registers and the third is an address. The instruction |
| // both reads from and writes to the address. |
| // |
| // RotateSelect: |
| // One output operand and five input operands. The first two operands |
| // are registers and the other three are immediates. |
| // |
| // The format determines which input operands are tied to output operands, |
| // and also determines the shape of any address operand. |
| // |
| // Multiclasses of the form <Category><Format>Pair define two instructions, |
| // one with <Category><Format> and one with <Category><Format>Y. The name |
| // of the first instruction has no suffix, the name of the second has |
| // an extra "y". |
| // |
| //===----------------------------------------------------------------------===// |
| |
| class InherentRRE<string mnemonic, bits<16> opcode, RegisterOperand cls, |
| dag src> |
| : InstRRE<opcode, (outs cls:$dst), (ins), |
| mnemonic#"\t$dst", |
| [(set cls:$dst, src)]> { |
| let R2 = 0; |
| } |
| |
| class LoadMultipleRSY<string mnemonic, bits<16> opcode, RegisterOperand cls> |
| : InstRSY<opcode, (outs cls:$dst1, cls:$dst2), (ins bdaddr20only:$addr), |
| mnemonic#"\t$dst1, $dst2, $addr", []> { |
| let mayLoad = 1; |
| } |
| |
| class StoreRILPC<string mnemonic, bits<12> opcode, SDPatternOperator operator, |
| RegisterOperand cls> |
| : InstRIL<opcode, (outs), (ins cls:$src, pcrel32:$addr), |
| mnemonic#"\t$src, $addr", |
| [(operator cls:$src, pcrel32:$addr)]> { |
| let mayStore = 1; |
| // We want PC-relative addresses to be tried ahead of BD and BDX addresses. |
| // However, BDXs have two extra operands and are therefore 6 units more |
| // complex. |
| let AddedComplexity = 7; |
| } |
| |
| class StoreRX<string mnemonic, bits<8> opcode, SDPatternOperator operator, |
| RegisterOperand cls, AddressingMode mode = bdxaddr12only> |
| : InstRX<opcode, (outs), (ins cls:$src, mode:$addr), |
| mnemonic#"\t$src, $addr", |
| [(operator cls:$src, mode:$addr)]> { |
| let mayStore = 1; |
| } |
| |
| class StoreRXY<string mnemonic, bits<16> opcode, SDPatternOperator operator, |
| RegisterOperand cls, AddressingMode mode = bdxaddr20only> |
| : InstRXY<opcode, (outs), (ins cls:$src, mode:$addr), |
| mnemonic#"\t$src, $addr", |
| [(operator cls:$src, mode:$addr)]> { |
| let mayStore = 1; |
| } |
| |
| multiclass StoreRXPair<string mnemonic, bits<8> rxOpcode, bits<16> rxyOpcode, |
| SDPatternOperator operator, RegisterOperand cls> { |
| let Function = mnemonic ## #cls in { |
| let PairType = "12" in |
| def "" : StoreRX<mnemonic, rxOpcode, operator, cls, bdxaddr12pair>; |
| let PairType = "20" in |
| def Y : StoreRXY<mnemonic#"y", rxyOpcode, operator, cls, bdxaddr20pair>; |
| } |
| } |
| |
| class StoreMultipleRSY<string mnemonic, bits<16> opcode, RegisterOperand cls> |
| : InstRSY<opcode, (outs), (ins cls:$from, cls:$to, bdaddr20only:$addr), |
| mnemonic#"\t$from, $to, $addr", []> { |
| let mayStore = 1; |
| } |
| |
| class StoreSI<string mnemonic, bits<8> opcode, SDPatternOperator operator, |
| Immediate imm, AddressingMode mode = bdaddr12only> |
| : InstSI<opcode, (outs), (ins mode:$addr, imm:$src), |
| mnemonic#"\t$addr, $src", |
| [(operator imm:$src, mode:$addr)]> { |
| let mayStore = 1; |
| } |
| |
| class StoreSIY<string mnemonic, bits<16> opcode, SDPatternOperator operator, |
| Immediate imm, AddressingMode mode = bdaddr20only> |
| : InstSIY<opcode, (outs), (ins mode:$addr, imm:$src), |
| mnemonic#"\t$addr, $src", |
| [(operator imm:$src, mode:$addr)]> { |
| let mayStore = 1; |
| } |
| |
| class StoreSIL<string mnemonic, bits<16> opcode, SDPatternOperator operator, |
| Immediate imm> |
| : InstSIL<opcode, (outs), (ins bdaddr12only:$addr, imm:$src), |
| mnemonic#"\t$addr, $src", |
| [(operator imm:$src, bdaddr12only:$addr)]> { |
| let mayStore = 1; |
| } |
| |
| multiclass StoreSIPair<string mnemonic, bits<8> siOpcode, bits<16> siyOpcode, |
| SDPatternOperator operator, Immediate imm> { |
| let Function = mnemonic in { |
| let PairType = "12" in |
| def "" : StoreSI<mnemonic, siOpcode, operator, imm, bdaddr12pair>; |
| let PairType = "20" in |
| def Y : StoreSIY<mnemonic#"y", siyOpcode, operator, imm, bdaddr20pair>; |
| } |
| } |
| |
| class UnaryRR<string mnemonic, bits<8> opcode, SDPatternOperator operator, |
| RegisterOperand cls1, RegisterOperand cls2> |
| : InstRR<opcode, (outs cls1:$dst), (ins cls2:$src), |
| mnemonic#"\t$dst, $src", |
| [(set cls1:$dst, (operator cls2:$src))]>; |
| |
| class UnaryRRE<string mnemonic, bits<16> opcode, SDPatternOperator operator, |
| RegisterOperand cls1, RegisterOperand cls2> |
| : InstRRE<opcode, (outs cls1:$dst), (ins cls2:$src), |
| mnemonic#"\t$dst, $src", |
| [(set cls1:$dst, (operator cls2:$src))]>; |
| |
| class UnaryRRF<string mnemonic, bits<16> opcode, RegisterOperand cls1, |
| RegisterOperand cls2> |
| : InstRRF<opcode, (outs cls1:$dst), (ins cls2:$src, uimm8zx4:$mode), |
| mnemonic#"\t$dst, $mode, $src", []>; |
| |
| class UnaryRI<string mnemonic, bits<12> opcode, SDPatternOperator operator, |
| RegisterOperand cls, Immediate imm> |
| : InstRI<opcode, (outs cls:$dst), (ins imm:$src), |
| mnemonic#"\t$dst, $src", |
| [(set cls:$dst, (operator imm:$src))]>; |
| |
| class UnaryRIL<string mnemonic, bits<12> opcode, SDPatternOperator operator, |
| RegisterOperand cls, Immediate imm> |
| : InstRIL<opcode, (outs cls:$dst), (ins imm:$src), |
| mnemonic#"\t$dst, $src", |
| [(set cls:$dst, (operator imm:$src))]>; |
| |
| class UnaryRILPC<string mnemonic, bits<12> opcode, SDPatternOperator operator, |
| RegisterOperand cls> |
| : InstRIL<opcode, (outs cls:$dst), (ins pcrel32:$addr), |
| mnemonic#"\t$dst, $addr", |
| [(set cls:$dst, (operator pcrel32:$addr))]> { |
| let mayLoad = 1; |
| // We want PC-relative addresses to be tried ahead of BD and BDX addresses. |
| // However, BDXs have two extra operands and are therefore 6 units more |
| // complex. |
| let AddedComplexity = 7; |
| } |
| |
| class UnaryRX<string mnemonic, bits<8> opcode, SDPatternOperator operator, |
| RegisterOperand cls, AddressingMode mode = bdxaddr12only> |
| : InstRX<opcode, (outs cls:$dst), (ins mode:$addr), |
| mnemonic#"\t$dst, $addr", |
| [(set cls:$dst, (operator mode:$addr))]> { |
| let mayLoad = 1; |
| } |
| |
| class UnaryRXE<string mnemonic, bits<16> opcode, SDPatternOperator operator, |
| RegisterOperand cls> |
| : InstRXE<opcode, (outs cls:$dst), (ins bdxaddr12only:$addr), |
| mnemonic#"\t$dst, $addr", |
| [(set cls:$dst, (operator bdxaddr12only:$addr))]> { |
| let mayLoad = 1; |
| } |
| |
| class UnaryRXY<string mnemonic, bits<16> opcode, SDPatternOperator operator, |
| RegisterOperand cls, AddressingMode mode = bdxaddr20only> |
| : InstRXY<opcode, (outs cls:$dst), (ins mode:$addr), |
| mnemonic#"\t$dst, $addr", |
| [(set cls:$dst, (operator mode:$addr))]> { |
| let mayLoad = 1; |
| } |
| |
| multiclass UnaryRXPair<string mnemonic, bits<8> rxOpcode, bits<16> rxyOpcode, |
| SDPatternOperator operator, RegisterOperand cls> { |
| let Function = mnemonic ## #cls in { |
| let PairType = "12" in |
| def "" : UnaryRX<mnemonic, rxOpcode, operator, cls, bdxaddr12pair>; |
| let PairType = "20" in |
| def Y : UnaryRXY<mnemonic#"y", rxyOpcode, operator, cls, bdxaddr20pair>; |
| } |
| } |
| |
| class BinaryRR<string mnemonic, bits<8> opcode, SDPatternOperator operator, |
| RegisterOperand cls1, RegisterOperand cls2> |
| : InstRR<opcode, (outs cls1:$dst), (ins cls1:$src1, cls2:$src2), |
| mnemonic#"\t$dst, $src2", |
| [(set cls1:$dst, (operator cls1:$src1, cls2:$src2))]> { |
| let Constraints = "$src1 = $dst"; |
| let DisableEncoding = "$src1"; |
| } |
| |
| class BinaryRRE<string mnemonic, bits<16> opcode, SDPatternOperator operator, |
| RegisterOperand cls1, RegisterOperand cls2> |
| : InstRRE<opcode, (outs cls1:$dst), (ins cls1:$src1, cls2:$src2), |
| mnemonic#"\t$dst, $src2", |
| [(set cls1:$dst, (operator cls1:$src1, cls2:$src2))]> { |
| let Constraints = "$src1 = $dst"; |
| let DisableEncoding = "$src1"; |
| } |
| |
| // Here the assembly and dag operands are in natural order, |
| // but the first input operand maps to R3 and the second to R2. |
| // This is used for "CPSDR R1, R3, R2", which is equivalent to |
| // R1 = copysign (R3, R2). |
| // |
| // Direct uses of the instruction must pass operands in encoding order -- |
| // R1, R2, R3 -- so they must pass the source operands in reverse order. |
| class BinaryRevRRF<string mnemonic, bits<16> opcode, SDPatternOperator operator, |
| RegisterOperand cls1, RegisterOperand cls2> |
| : InstRRF<opcode, (outs cls1:$dst), (ins cls2:$src2, cls1:$src1), |
| mnemonic#"\t$dst, $src1, $src2", |
| [(set cls1:$dst, (operator cls1:$src1, cls2:$src2))]>; |
| |
| class BinaryRI<string mnemonic, bits<12> opcode, SDPatternOperator operator, |
| RegisterOperand cls, Immediate imm> |
| : InstRI<opcode, (outs cls:$dst), (ins cls:$src1, imm:$src2), |
| mnemonic#"\t$dst, $src2", |
| [(set cls:$dst, (operator cls:$src1, imm:$src2))]> { |
| let Constraints = "$src1 = $dst"; |
| let DisableEncoding = "$src1"; |
| } |
| |
| class BinaryRIL<string mnemonic, bits<12> opcode, SDPatternOperator operator, |
| RegisterOperand cls, Immediate imm> |
| : InstRIL<opcode, (outs cls:$dst), (ins cls:$src1, imm:$src2), |
| mnemonic#"\t$dst, $src2", |
| [(set cls:$dst, (operator cls:$src1, imm:$src2))]> { |
| let Constraints = "$src1 = $dst"; |
| let DisableEncoding = "$src1"; |
| } |
| |
| class BinaryRX<string mnemonic, bits<8> opcode, SDPatternOperator operator, |
| RegisterOperand cls, SDPatternOperator load, |
| AddressingMode mode = bdxaddr12only> |
| : InstRX<opcode, (outs cls:$dst), (ins cls:$src1, mode:$src2), |
| mnemonic#"\t$dst, $src2", |
| [(set cls:$dst, (operator cls:$src1, (load mode:$src2)))]> { |
| let Constraints = "$src1 = $dst"; |
| let DisableEncoding = "$src1"; |
| let mayLoad = 1; |
| } |
| |
| class BinaryRXE<string mnemonic, bits<16> opcode, SDPatternOperator operator, |
| RegisterOperand cls, SDPatternOperator load> |
| : InstRXE<opcode, (outs cls:$dst), (ins cls:$src1, bdxaddr12only:$src2), |
| mnemonic#"\t$dst, $src2", |
| [(set cls:$dst, (operator cls:$src1, |
| (load bdxaddr12only:$src2)))]> { |
| let Constraints = "$src1 = $dst"; |
| let DisableEncoding = "$src1"; |
| let mayLoad = 1; |
| } |
| |
| class BinaryRXY<string mnemonic, bits<16> opcode, SDPatternOperator operator, |
| RegisterOperand cls, SDPatternOperator load, |
| AddressingMode mode = bdxaddr20only> |
| : InstRXY<opcode, (outs cls:$dst), (ins cls:$src1, mode:$src2), |
| mnemonic#"\t$dst, $src2", |
| [(set cls:$dst, (operator cls:$src1, (load mode:$src2)))]> { |
| let Constraints = "$src1 = $dst"; |
| let DisableEncoding = "$src1"; |
| let mayLoad = 1; |
| } |
| |
| multiclass BinaryRXPair<string mnemonic, bits<8> rxOpcode, bits<16> rxyOpcode, |
| SDPatternOperator operator, RegisterOperand cls, |
| SDPatternOperator load> { |
| let Function = mnemonic ## #cls in { |
| let PairType = "12" in |
| def "" : BinaryRX<mnemonic, rxOpcode, operator, cls, load, bdxaddr12pair>; |
| let PairType = "20" in |
| def Y : BinaryRXY<mnemonic#"y", rxyOpcode, operator, cls, load, |
| bdxaddr20pair>; |
| } |
| } |
| |
| class BinarySI<string mnemonic, bits<8> opcode, SDPatternOperator operator, |
| Operand imm, AddressingMode mode = bdaddr12only> |
| : InstSI<opcode, (outs), (ins mode:$addr, imm:$src), |
| mnemonic#"\t$addr, $src", |
| [(store (operator (load mode:$addr), imm:$src), mode:$addr)]> { |
| let mayLoad = 1; |
| let mayStore = 1; |
| } |
| |
| class BinarySIY<string mnemonic, bits<16> opcode, SDPatternOperator operator, |
| Operand imm, AddressingMode mode = bdaddr20only> |
| : InstSIY<opcode, (outs), (ins mode:$addr, imm:$src), |
| mnemonic#"\t$addr, $src", |
| [(store (operator (load mode:$addr), imm:$src), mode:$addr)]> { |
| let mayLoad = 1; |
| let mayStore = 1; |
| } |
| |
| multiclass BinarySIPair<string mnemonic, bits<8> siOpcode, |
| bits<16> siyOpcode, SDPatternOperator operator, |
| Operand imm> { |
| let Function = mnemonic ## #cls in { |
| let PairType = "12" in |
| def "" : BinarySI<mnemonic, siOpcode, operator, imm, bdaddr12pair>; |
| let PairType = "20" in |
| def Y : BinarySIY<mnemonic#"y", siyOpcode, operator, imm, bdaddr20pair>; |
| } |
| } |
| |
| class ShiftRS<string mnemonic, bits<8> opcode, SDPatternOperator operator, |
| RegisterOperand cls, AddressingMode mode> |
| : InstRS<opcode, (outs cls:$dst), (ins cls:$src1, mode:$src2), |
| mnemonic#"\t$dst, $src2", |
| [(set cls:$dst, (operator cls:$src1, mode:$src2))]> { |
| let R3 = 0; |
| let Constraints = "$src1 = $dst"; |
| let DisableEncoding = "$src1"; |
| } |
| |
| class ShiftRSY<string mnemonic, bits<16> opcode, SDPatternOperator operator, |
| RegisterOperand cls, AddressingMode mode> |
| : InstRSY<opcode, (outs cls:$dst), (ins cls:$src1, mode:$src2), |
| mnemonic#"\t$dst, $src1, $src2", |
| [(set cls:$dst, (operator cls:$src1, mode:$src2))]>; |
| |
| class CompareRR<string mnemonic, bits<8> opcode, SDPatternOperator operator, |
| RegisterOperand cls1, RegisterOperand cls2> |
| : InstRR<opcode, (outs), (ins cls1:$src1, cls2:$src2), |
| mnemonic#"\t$src1, $src2", |
| [(operator cls1:$src1, cls2:$src2)]>; |
| |
| class CompareRRE<string mnemonic, bits<16> opcode, SDPatternOperator operator, |
| RegisterOperand cls1, RegisterOperand cls2> |
| : InstRRE<opcode, (outs), (ins cls1:$src1, cls2:$src2), |
| mnemonic#"\t$src1, $src2", |
| [(operator cls1:$src1, cls2:$src2)]>; |
| |
| class CompareRI<string mnemonic, bits<12> opcode, SDPatternOperator operator, |
| RegisterOperand cls, Immediate imm> |
| : InstRI<opcode, (outs), (ins cls:$src1, imm:$src2), |
| mnemonic#"\t$src1, $src2", |
| [(operator cls:$src1, imm:$src2)]>; |
| |
| class CompareRIL<string mnemonic, bits<12> opcode, SDPatternOperator operator, |
| RegisterOperand cls, Immediate imm> |
| : InstRIL<opcode, (outs), (ins cls:$src1, imm:$src2), |
| mnemonic#"\t$src1, $src2", |
| [(operator cls:$src1, imm:$src2)]>; |
| |
| class CompareRILPC<string mnemonic, bits<12> opcode, SDPatternOperator operator, |
| RegisterOperand cls, SDPatternOperator load> |
| : InstRIL<opcode, (outs), (ins cls:$src1, pcrel32:$src2), |
| mnemonic#"\t$src1, $src2", |
| [(operator cls:$src1, (load pcrel32:$src2))]> { |
| let mayLoad = 1; |
| // We want PC-relative addresses to be tried ahead of BD and BDX addresses. |
| // However, BDXs have two extra operands and are therefore 6 units more |
| // complex. |
| let AddedComplexity = 7; |
| } |
| |
| class CompareRX<string mnemonic, bits<8> opcode, SDPatternOperator operator, |
| RegisterOperand cls, SDPatternOperator load, |
| AddressingMode mode = bdxaddr12only> |
| : InstRX<opcode, (outs), (ins cls:$src1, mode:$src2), |
| mnemonic#"\t$src1, $src2", |
| [(operator cls:$src1, (load mode:$src2))]> { |
| let mayLoad = 1; |
| } |
| |
| class CompareRXE<string mnemonic, bits<16> opcode, SDPatternOperator operator, |
| RegisterOperand cls, SDPatternOperator load> |
| : InstRXE<opcode, (outs), (ins cls:$src1, bdxaddr12only:$src2), |
| mnemonic#"\t$src1, $src2", |
| [(operator cls:$src1, (load bdxaddr12only:$src2))]> { |
| let mayLoad = 1; |
| } |
| |
| class CompareRXY<string mnemonic, bits<16> opcode, SDPatternOperator operator, |
| RegisterOperand cls, SDPatternOperator load, |
| AddressingMode mode = bdxaddr20only> |
| : InstRXY<opcode, (outs), (ins cls:$src1, mode:$src2), |
| mnemonic#"\t$src1, $src2", |
| [(operator cls:$src1, (load mode:$src2))]> { |
| let mayLoad = 1; |
| } |
| |
| multiclass CompareRXPair<string mnemonic, bits<8> rxOpcode, bits<16> rxyOpcode, |
| SDPatternOperator operator, RegisterOperand cls, |
| SDPatternOperator load> { |
| let Function = mnemonic ## #cls in { |
| let PairType = "12" in |
| def "" : CompareRX<mnemonic, rxOpcode, operator, cls, |
| load, bdxaddr12pair>; |
| let PairType = "20" in |
| def Y : CompareRXY<mnemonic#"y", rxyOpcode, operator, cls, |
| load, bdxaddr20pair>; |
| } |
| } |
| |
| class CompareSI<string mnemonic, bits<8> opcode, SDPatternOperator operator, |
| SDPatternOperator load, Immediate imm, |
| AddressingMode mode = bdaddr12only> |
| : InstSI<opcode, (outs), (ins mode:$addr, imm:$src), |
| mnemonic#"\t$addr, $src", |
| [(operator (load mode:$addr), imm:$src)]> { |
| let mayLoad = 1; |
| } |
| |
| class CompareSIL<string mnemonic, bits<16> opcode, SDPatternOperator operator, |
| SDPatternOperator load, Immediate imm> |
| : InstSIL<opcode, (outs), (ins bdaddr12only:$addr, imm:$src), |
| mnemonic#"\t$addr, $src", |
| [(operator (load bdaddr12only:$addr), imm:$src)]> { |
| let mayLoad = 1; |
| } |
| |
| class CompareSIY<string mnemonic, bits<16> opcode, SDPatternOperator operator, |
| SDPatternOperator load, Immediate imm, |
| AddressingMode mode = bdaddr20only> |
| : InstSIY<opcode, (outs), (ins mode:$addr, imm:$src), |
| mnemonic#"\t$addr, $src", |
| [(operator (load mode:$addr), imm:$src)]> { |
| let mayLoad = 1; |
| } |
| |
| multiclass CompareSIPair<string mnemonic, bits<8> siOpcode, bits<16> siyOpcode, |
| SDPatternOperator operator, SDPatternOperator load, |
| Immediate imm> { |
| let Function = mnemonic in { |
| let PairType = "12" in |
| def "" : CompareSI<mnemonic, siOpcode, operator, load, imm, bdaddr12pair>; |
| let PairType = "20" in |
| def Y : CompareSIY<mnemonic#"y", siyOpcode, operator, load, imm, |
| bdaddr20pair>; |
| } |
| } |
| |
| class TernaryRRD<string mnemonic, bits<16> opcode, |
| SDPatternOperator operator, RegisterOperand cls> |
| : InstRRD<opcode, (outs cls:$dst), (ins cls:$src1, cls:$src2, cls:$src3), |
| mnemonic#"\t$dst, $src2, $src3", |
| [(set cls:$dst, (operator cls:$src1, cls:$src2, cls:$src3))]> { |
| let Constraints = "$src1 = $dst"; |
| let DisableEncoding = "$src1"; |
| } |
| |
| class TernaryRXF<string mnemonic, bits<16> opcode, SDPatternOperator operator, |
| RegisterOperand cls, SDPatternOperator load> |
| : InstRXF<opcode, (outs cls:$dst), |
| (ins cls:$src1, cls:$src2, bdxaddr12only:$src3), |
| mnemonic#"\t$dst, $src2, $src3", |
| [(set cls:$dst, (operator cls:$src1, cls:$src2, |
| (load bdxaddr12only:$src3)))]> { |
| let Constraints = "$src1 = $dst"; |
| let DisableEncoding = "$src1"; |
| let mayLoad = 1; |
| } |
| |
| class CmpSwapRS<string mnemonic, bits<8> opcode, SDPatternOperator operator, |
| RegisterOperand cls, AddressingMode mode = bdaddr12only> |
| : InstRS<opcode, (outs cls:$dst), (ins cls:$old, cls:$new, mode:$ptr), |
| mnemonic#"\t$dst, $new, $ptr", |
| [(set cls:$dst, (operator mode:$ptr, cls:$old, cls:$new))]> { |
| let Constraints = "$old = $dst"; |
| let DisableEncoding = "$old"; |
| let mayLoad = 1; |
| let mayStore = 1; |
| } |
| |
| class CmpSwapRSY<string mnemonic, bits<16> opcode, SDPatternOperator operator, |
| RegisterOperand cls, AddressingMode mode = bdaddr20only> |
| : InstRSY<opcode, (outs cls:$dst), (ins cls:$old, cls:$new, mode:$ptr), |
| mnemonic#"\t$dst, $new, $ptr", |
| [(set cls:$dst, (operator mode:$ptr, cls:$old, cls:$new))]> { |
| let Constraints = "$old = $dst"; |
| let DisableEncoding = "$old"; |
| let mayLoad = 1; |
| let mayStore = 1; |
| } |
| |
| multiclass CmpSwapRSPair<string mnemonic, bits<8> rsOpcode, bits<16> rsyOpcode, |
| SDPatternOperator operator, RegisterOperand cls> { |
| let Function = mnemonic ## #cls in { |
| let PairType = "12" in |
| def "" : CmpSwapRS<mnemonic, rsOpcode, operator, cls, bdaddr12pair>; |
| let PairType = "20" in |
| def Y : CmpSwapRSY<mnemonic#"y", rsyOpcode, operator, cls, bdaddr20pair>; |
| } |
| } |
| |
| class RotateSelectRIEf<string mnemonic, bits<16> opcode, RegisterOperand cls1, |
| RegisterOperand cls2> |
| : InstRIEf<opcode, (outs cls1:$dst), |
| (ins cls1:$src1, cls2:$src2, |
| uimm8zx6:$imm1, uimm8zx6:$imm2, uimm8zx6:$imm3), |
| mnemonic#"\t$dst, $src2, $imm1, $imm2, $imm3", []> { |
| let Constraints = "$src1 = $dst"; |
| let DisableEncoding = "$src1"; |
| } |
| |
| //===----------------------------------------------------------------------===// |
| // Pseudo instructions |
| //===----------------------------------------------------------------------===// |
| // |
| // Convenience instructions that get lowered to real instructions |
| // by either SystemZTargetLowering::EmitInstrWithCustomInserter() |
| // or SystemZInstrInfo::expandPostRAPseudo(). |
| // |
| //===----------------------------------------------------------------------===// |
| |
| class Pseudo<dag outs, dag ins, list<dag> pattern> |
| : InstSystemZ<0, outs, ins, "", pattern> { |
| let isPseudo = 1; |
| let isCodeGenOnly = 1; |
| } |
| |
| // Implements "$dst = $cc & (8 >> CC) ? $src1 : $src2", where CC is |
| // the value of the PSW's 2-bit condition code field. |
| class SelectWrapper<RegisterOperand cls> |
| : Pseudo<(outs cls:$dst), (ins cls:$src1, cls:$src2, i8imm:$cc), |
| [(set cls:$dst, (z_select_ccmask cls:$src1, cls:$src2, imm:$cc))]> { |
| let usesCustomInserter = 1; |
| // Although the instructions used by these nodes do not in themselves |
| // change the PSW, the insertion requires new blocks, and the PSW cannot |
| // be live across them. |
| let Defs = [PSW]; |
| let Uses = [PSW]; |
| } |
| |
| // OPERATOR is ATOMIC_SWAP or an ATOMIC_LOAD_* operation. PAT and OPERAND |
| // describe the second (non-memory) operand. |
| class AtomicLoadBinary<SDPatternOperator operator, RegisterOperand cls, |
| dag pat, DAGOperand operand> |
| : Pseudo<(outs cls:$dst), (ins bdaddr20only:$ptr, operand:$src2), |
| [(set cls:$dst, (operator bdaddr20only:$ptr, pat))]> { |
| let Defs = [PSW]; |
| let Has20BitOffset = 1; |
| let mayLoad = 1; |
| let mayStore = 1; |
| let usesCustomInserter = 1; |
| } |
| |
| // Specializations of AtomicLoadWBinary. |
| class AtomicLoadBinaryReg32<SDPatternOperator operator> |
| : AtomicLoadBinary<operator, GR32, (i32 GR32:$src2), GR32>; |
| class AtomicLoadBinaryImm32<SDPatternOperator operator, Immediate imm> |
| : AtomicLoadBinary<operator, GR32, (i32 imm:$src2), imm>; |
| class AtomicLoadBinaryReg64<SDPatternOperator operator> |
| : AtomicLoadBinary<operator, GR64, (i64 GR64:$src2), GR64>; |
| class AtomicLoadBinaryImm64<SDPatternOperator operator, Immediate imm> |
| : AtomicLoadBinary<operator, GR64, (i64 imm:$src2), imm>; |
| |
| // OPERATOR is ATOMIC_SWAPW or an ATOMIC_LOADW_* operation. PAT and OPERAND |
| // describe the second (non-memory) operand. |
| class AtomicLoadWBinary<SDPatternOperator operator, dag pat, |
| DAGOperand operand> |
| : Pseudo<(outs GR32:$dst), |
| (ins bdaddr20only:$ptr, operand:$src2, ADDR32:$bitshift, |
| ADDR32:$negbitshift, uimm32:$bitsize), |
| [(set GR32:$dst, (operator bdaddr20only:$ptr, pat, ADDR32:$bitshift, |
| ADDR32:$negbitshift, uimm32:$bitsize))]> { |
| let Defs = [PSW]; |
| let Has20BitOffset = 1; |
| let mayLoad = 1; |
| let mayStore = 1; |
| let usesCustomInserter = 1; |
| } |
| |
| // Specializations of AtomicLoadWBinary. |
| class AtomicLoadWBinaryReg<SDPatternOperator operator> |
| : AtomicLoadWBinary<operator, (i32 GR32:$src2), GR32>; |
| class AtomicLoadWBinaryImm<SDPatternOperator operator, Immediate imm> |
| : AtomicLoadWBinary<operator, (i32 imm:$src2), imm>; |