//===-- VEInstrInfo.td - Target Description for VE Target -----------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // // This file describes the VE instructions in TableGen format. // //===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===// // Instruction format superclass //===----------------------------------------------------------------------===// include "VEInstrFormats.td" //===----------------------------------------------------------------------===// // Feature predicates. //===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===// // Instruction Pattern Stuff //===----------------------------------------------------------------------===// def simm7 : PatLeaf<(imm), [{ return isInt<7>(N->getSExtValue()); }]>; def simm32 : PatLeaf<(imm), [{ return isInt<32>(N->getSExtValue()); }]>; def uimm6 : PatLeaf<(imm), [{ return isUInt<6>(N->getZExtValue()); }]>; // ASX format of memory address def MEMri : Operand { let PrintMethod = "printMemASXOperand"; let MIOperandInfo = (ops ptr_rc, i64imm); } // AS format of memory address def MEMASri : Operand { let PrintMethod = "printMemASOperand"; let MIOperandInfo = (ops ptr_rc, i64imm); } // Branch targets have OtherVT type. def brtarget32 : Operand { let EncoderMethod = "getBranchTarget32OpValue"; } def simm7Op64 : Operand { let DecoderMethod = "DecodeSIMM7"; } def simm32Op64 : Operand { let DecoderMethod = "DecodeSIMM32"; } def uimm6Op64 : Operand { let DecoderMethod = "DecodeUIMM6"; } // Operand for printing out a condition code. let PrintMethod = "printCCOperand" in def CCOp : Operand; // These are target-independent nodes, but have target-specific formats. def SDT_SPCallSeqStart : SDCallSeqStart<[ SDTCisVT<0, i64>, SDTCisVT<1, i64> ]>; def SDT_SPCallSeqEnd : SDCallSeqEnd<[ SDTCisVT<0, i64>, SDTCisVT<1, i64> ]>; def callseq_start : SDNode<"ISD::CALLSEQ_START", SDT_SPCallSeqStart, [SDNPHasChain, SDNPOutGlue]>; def callseq_end : SDNode<"ISD::CALLSEQ_END", SDT_SPCallSeqEnd, [SDNPHasChain, SDNPOptInGlue, SDNPOutGlue]>; // def SDT_SPCall : SDTypeProfile<0, -1, [SDTCisVT<0, i64>]>; def retflag : SDNode<"VEISD::RET_FLAG", SDTNone, [SDNPHasChain, SDNPOptInGlue, SDNPVariadic]>; //===----------------------------------------------------------------------===// // VE Flag Conditions //===----------------------------------------------------------------------===// // Note that these values must be kept in sync with the CCOp::CondCode enum // values. class CC_VAL : PatLeaf<(i32 N)>; def CC_IG : CC_VAL< 0>; // Greater def CC_IL : CC_VAL< 1>; // Less def CC_INE : CC_VAL< 2>; // Not Equal def CC_IEQ : CC_VAL< 3>; // Equal def CC_IGE : CC_VAL< 4>; // Greater or Equal def CC_ILE : CC_VAL< 5>; // Less or Equal def CC_AF : CC_VAL< 6>; // Always false def CC_G : CC_VAL< 7>; // Greater def CC_L : CC_VAL< 8>; // Less def CC_NE : CC_VAL< 9>; // Not Equal def CC_EQ : CC_VAL<10>; // Equal def CC_GE : CC_VAL<11>; // Greater or Equal def CC_LE : CC_VAL<12>; // Less or Equal def CC_NUM : CC_VAL<13>; // Number def CC_NAN : CC_VAL<14>; // NaN def CC_GNAN : CC_VAL<15>; // Greater or NaN def CC_LNAN : CC_VAL<16>; // Less or NaN def CC_NENAN : CC_VAL<17>; // Not Equal or NaN def CC_EQNAN : CC_VAL<18>; // Equal or NaN def CC_GENAN : CC_VAL<19>; // Greater or Equal or NaN def CC_LENAN : CC_VAL<20>; // Less or Equal or NaN def CC_AT : CC_VAL<21>; // Always true //===----------------------------------------------------------------------===// // VE Multiclasses for common instruction formats //===----------------------------------------------------------------------===// multiclass RMmopc, RegisterClass RC, ValueType Ty, Operand immOp, Operand immOp2> { def rri : RM< opc, (outs RC:$sx), (ins RC:$sy, RC:$sz, immOp2:$imm32), !strconcat(opcStr, " $sx, ${imm32}($sy, ${sz})")> { let cy = 1; let cz = 1; let hasSideEffects = 0; } def zzi : RM< opc, (outs RC:$sx), (ins immOp2:$imm32), !strconcat(opcStr, " $sx, $imm32")> { let cy = 0; let sy = 0; let cz = 0; let sz = 0; let hasSideEffects = 0; } } // Multiclass for RR type instructions multiclass RRmrropc, RegisterClass RCo, ValueType Tyo, RegisterClass RCi, ValueType Tyi> { def rr : RR { let cy = 1; let cz = 1; let hasSideEffects = 0; } } multiclass RRmriopc, RegisterClass RCo, ValueType Tyo, RegisterClass RCi, ValueType Tyi, Operand immOp> { // VE calculates (OpNode $sy, $sz), but llvm requires to have immediate // in RHS, so we use following definition. def ri : RR { let cy = 0; let cz = 1; let hasSideEffects = 0; } } multiclass RRmizopc, RegisterClass RCo, ValueType Tyo, RegisterClass RCi, ValueType Tyi, Operand immOp> { def zi : RR { let cy = 0; let cz = 0; let sz = 0; let hasSideEffects = 0; } } multiclass RRNDmrmopc, RegisterClass RCo, ValueType Tyo, RegisterClass RCi, ValueType Tyi, Operand immOp2> { def rm0 : RR { let cy = 1; let cz = 0; let sz{6} = 1; // (guess) tblgen conservatively assumes hasSideEffects when // it fails to infer from a pattern. let hasSideEffects = 0; } } // Used by add, mul, div, and similar commutative instructions // The order of operands are "$sx, $sy, $sz" multiclass RRmopc, RegisterClass RC, ValueType Ty, Operand immOp, Operand immOp2> : RRmrr, RRmri, RRmiz, RRNDmrm; // Branch multiclass let isBranch = 1, isTerminator = 1, hasDelaySlot = 1 in multiclass BCRm opc, RegisterClass RC, ValueType Ty, Operand immOp, Operand immOp2> { def rr : CF< opc, (outs), (ins CCOp:$cf, RC:$sy, RC:$sz, brtarget32:$imm32), !strconcat(opcStr, " $sy, $sz, $imm32")> { let cy = 1; let cz = 1; let hasSideEffects = 0; } } //===----------------------------------------------------------------------===// // Instructions //===----------------------------------------------------------------------===// // LEA and LEASL instruction (load 32 bit imm to low or high part) let cx = 0 in defm LEA : RMm<"lea", 0x06, I64, i64, simm7Op64, simm32Op64>; let cx = 1 in defm LEASL : RMm<"lea.sl", 0x06, I64, i64, simm7Op64, simm32Op64>; // 5.3.2.2. Fixed-Point Arithmetic Operation Instructions // ADX instruction let cx = 0 in defm ADX : RRm<"adds.l", 0x59, I64, i64, simm7Op64, uimm6Op64>; // 5.3.2.3. Logical Arithmetic Operation Instructions let cx = 0 in { defm AND : RRm<"and", 0x44, I64, i64, simm7Op64, uimm6Op64>; defm OR : RRm<"or", 0x45, I64, i64, simm7Op64, uimm6Op64>; } // Load and Store instructions // As 1st step, only uses sz and imm32 to represent $addr let mayLoad = 1, hasSideEffects = 0 in { let cy = 0, sy = 0, cz = 1 in { let cx = 0 in def LDSri : RM< 0x01, (outs I64:$sx), (ins MEMri:$addr), "ld $sx, $addr">; } } let mayStore = 1, hasSideEffects = 0 in { let cx = 0, cy = 0, sy = 0, cz = 1 in { def STSri : RM< 0x11, (outs), (ins MEMri:$addr, I64:$sx), "st $sx, $addr">; } } // Return instruction is also a special case of jump. let cx = 0, cx2 = 0, bpf = 0 /* NONE */, cf = 15 /* AT */, cy = 0, sy = 0, cz = 1, sz = 0x10 /* SX10 */, imm32 = 0, Uses = [SX10], isReturn = 1, isTerminator = 1, hasDelaySlot = 1, isBarrier = 1, isCodeGenOnly = 1, hasSideEffects = 0 in def RET : CF< 0x19, (outs), (ins), "b.l (,%lr)", [(retflag)]>; // Branch instruction let cx = 0, cx2 = 0, bpf = 0 /* NONE */ in defm BCRL : BCRm<"br${cf}.l", "br.l", 0x18, I64, i64, simm7Op64, uimm6Op64>; let cx = 0, cy = 0, cz = 1, hasSideEffects = 0 in { let sy = 3 in def SHMri : RM< 0x31, (outs), (ins MEMASri:$addr, I64:$sx), "shm.l $sx, $addr">; } let cx = 0, sx = 0, cy = 0, sy = 0, cz = 0, sz = 0, hasSideEffects = 0 in def MONC : RR< 0x3F, (outs), (ins), "monc">; //===----------------------------------------------------------------------===// // Pseudo Instructions //===----------------------------------------------------------------------===// let Defs = [SX11], Uses = [SX11], hasSideEffects = 0 in { def ADJCALLSTACKDOWN : Pseudo<(outs), (ins i64imm:$amt, i64imm:$amt2), "# ADJCALLSTACKDOWN $amt, $amt2", [(callseq_start timm:$amt, timm:$amt2)]>; def ADJCALLSTACKUP : Pseudo<(outs), (ins i64imm:$amt1, i64imm:$amt2), "# ADJCALLSTACKUP $amt1", [(callseq_end timm:$amt1, timm:$amt2)]>; } let Defs = [SX8], Uses = [SX8, SX11], hasSideEffects = 0 in def EXTEND_STACK : Pseudo<(outs), (ins), "# EXTEND STACK", []>; let hasSideEffects = 0 in def EXTEND_STACK_GUARD : Pseudo<(outs), (ins), "# EXTEND STACK GUARD", []>;