llvm-project/llvm/lib/Target/VE/VEInstrInfo.td

344 lines
12 KiB
TableGen

//===-- 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 uimm32 : PatLeaf<(imm), [{ return isUInt<32>(N->getZExtValue()); }]>;
def uimm6 : PatLeaf<(imm), [{ return isUInt<6>(N->getZExtValue()); }]>;
def lomsbzero : PatLeaf<(imm), [{ return (N->getZExtValue() & 0x80000000)
== 0; }]>;
def lozero : PatLeaf<(imm), [{ return (N->getZExtValue() & 0xffffffff)
== 0; }]>;
def LO32 : SDNodeXForm<imm, [{
return CurDAG->getTargetConstant(Lo_32(N->getZExtValue()),
SDLoc(N), MVT::i64);
}]>;
def HI32 : SDNodeXForm<imm, [{
// Transformation function: shift the immediate value down into the low bits.
return CurDAG->getTargetConstant(Hi_32(N->getZExtValue()),
SDLoc(N), MVT::i32);
}]>;
// ASX format of memory address
def MEMri : Operand<iPTR> {
let PrintMethod = "printMemASXOperand";
let MIOperandInfo = (ops ptr_rc, i64imm);
}
// AS format of memory address
def MEMASri : Operand<iPTR> {
let PrintMethod = "printMemASOperand";
let MIOperandInfo = (ops ptr_rc, i64imm);
}
// Branch targets have OtherVT type.
def brtarget32 : Operand<OtherVT> {
let EncoderMethod = "getBranchTarget32OpValue";
}
def simm7Op64 : Operand<i64> {
let DecoderMethod = "DecodeSIMM7";
}
def simm32Op64 : Operand<i64> {
let DecoderMethod = "DecodeSIMM32";
}
def uimm6Op64 : Operand<i64> {
let DecoderMethod = "DecodeUIMM6";
}
// Operand for printing out a condition code.
let PrintMethod = "printCCOperand" in
def CCOp : Operand<i32>;
// 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<int N> : 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 RMm<string opcStr, bits<8>opc,
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 rzi : RM<
opc, (outs RC:$sx), (ins RC:$sz, immOp2:$imm32),
!strconcat(opcStr, " $sx, ${imm32}(${sz})")> {
let cy = 0;
let sy = 0;
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 RRmrr<string opcStr, bits<8>opc,
RegisterClass RCo, ValueType Tyo,
RegisterClass RCi, ValueType Tyi> {
def rr : RR<opc, (outs RCo:$sx), (ins RCi:$sy, RCi:$sz),
!strconcat(opcStr, " $sx, $sy, $sz")>
{ let cy = 1; let cz = 1; let hasSideEffects = 0; }
}
multiclass RRmri<string opcStr, bits<8>opc,
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<opc, (outs RCo:$sx), (ins RCi:$sz, immOp:$sy),
!strconcat(opcStr, " $sx, $sy, $sz")>
{ let cy = 0; let cz = 1; let hasSideEffects = 0; }
}
multiclass RRmiz<string opcStr, bits<8>opc,
RegisterClass RCo, ValueType Tyo,
RegisterClass RCi, ValueType Tyi, Operand immOp> {
def zi : RR<opc, (outs RCo:$sx), (ins immOp:$sy),
!strconcat(opcStr, " $sx, $sy")>
{ let cy = 0; let cz = 0; let sz = 0; let hasSideEffects = 0; }
}
multiclass RRNDmrm<string opcStr, bits<8>opc,
RegisterClass RCo, ValueType Tyo,
RegisterClass RCi, ValueType Tyi, Operand immOp2> {
def rm0 : RR<opc, (outs RCo:$sx), (ins RCi:$sy, immOp2:$sz),
!strconcat(opcStr, " $sx, $sy, (${sz})0")> {
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;
}
}
multiclass RRNDmim<string opcStr, bits<8>opc,
RegisterClass RCo, ValueType Tyo,
RegisterClass RCi, ValueType Tyi,
Operand immOp, Operand immOp2> {
def im1 : RR<opc, (outs RCo:$sx), (ins immOp:$sy, immOp2:$sz),
!strconcat(opcStr, " $sx, $sy, (${sz})1")> {
let cy = 0;
let cz = 0;
let hasSideEffects = 0;
}
}
// Used by add, mul, div, and similar commutative instructions
// The order of operands are "$sx, $sy, $sz"
multiclass RRm<string opcStr, bits<8>opc,
RegisterClass RC, ValueType Ty, Operand immOp, Operand immOp2> :
RRmrr<opcStr, opc, RC, Ty, RC, Ty>,
RRmri<opcStr, opc, RC, Ty, RC, Ty, immOp>,
RRmiz<opcStr, opc, RC, Ty, RC, Ty, immOp>,
RRNDmrm<opcStr, opc, RC, Ty, RC, Ty, immOp2>,
RRNDmim<opcStr, opc, RC, Ty, RC, Ty, immOp, immOp2>;
// Branch multiclass
let isBranch = 1, isTerminator = 1, hasDelaySlot = 1 in
multiclass BCRm<string opcStr, string opcStrAt, bits<8> 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">;
//===----------------------------------------------------------------------===//
// Pattern Matchings
//===----------------------------------------------------------------------===//
// Small immediates.
def : Pat<(i64 simm7:$val), (ORim1 imm:$val, 0)>;
// Medium immediates.
def : Pat<(i64 simm32:$val), (LEAzzi imm:$val)>;
def : Pat<(i64 uimm32:$val), (ANDrm0 (LEAzzi imm:$val), 32)>;
// Arbitrary immediates.
def : Pat<(i64 lozero:$val),
(LEASLzzi (HI32 imm:$val))>;
def : Pat<(i64 lomsbzero:$val),
(LEASLrzi (LEAzzi (LO32 imm:$val)), (HI32 imm:$val))>;
def : Pat<(i64 imm:$val),
(LEASLrzi (ANDrm0 (LEAzzi (LO32 imm:$val)), 32),
(HI32 imm:$val))>;
//===----------------------------------------------------------------------===//
// 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",
[]>;