llvm-6502/lib/Target/IA64/IA64InstrInfo.td
Duraid Madina 25d0a88eb8 add some FP stuff, some mix.* stuff, and constant pool support to the
DAG instruction selector, which should be destroyed one day (in the pattern
isel also) since ia64 can pack any constant in the instruction stream


git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@24094 91177308-0d34-0410-b5e6-96231b3b80d8
2005-10-29 16:08:30 +00:00

599 lines
24 KiB
C++

//===- IA64InstrInfo.td - Describe the IA64 Instruction Set -----*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file was developed by Duraid Madina and is distributed under the
// University of Illinois Open Source License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file describes the IA64 instruction set, defining the instructions, and
// properties of the instructions which are needed for code generation, machine
// code emission, and analysis.
//
//===----------------------------------------------------------------------===//
include "IA64InstrFormats.td"
def u2imm : Operand<i8>;
def u6imm : Operand<i8>;
def s8imm : Operand<i8> {
let PrintMethod = "printS8ImmOperand";
}
def s14imm : Operand<i64> {
let PrintMethod = "printS14ImmOperand";
}
def s22imm : Operand<i32> {
let PrintMethod = "printS22ImmOperand";
}
def u64imm : Operand<i64> {
let PrintMethod = "printU64ImmOperand";
}
def s64imm : Operand<i64> {
let PrintMethod = "printS64ImmOperand";
}
let PrintMethod = "printGlobalOperand" in
def globaladdress : Operand<i64>;
// the asmprinter needs to know about calls
let PrintMethod = "printCallOperand" in
def calltarget : Operand<i64>;
/* new daggy action!!! */
def is32ones : PatLeaf<(i64 imm), [{
// is32ones predicate - True if the immediate is 0x00000000FFFFFFFF
// Used to create ZXT4s appropriately
uint64_t v = (uint64_t)N->getValue();
return (v == 0x00000000FFFFFFFFLL);
}]>;
// isMIXable predicates - True if the immediate is
// 0xFF00FF00FF00FF00, 0x00FF00FF00FF00FF
// etc, through 0x00000000FFFFFFFF
// Used to test for the suitability of mix*
def isMIX1Lable: PatLeaf<(i64 imm), [{
return((uint64_t)N->getValue()==0xFF00FF00FF00FF00LL);
}]>;
def isMIX1Rable: PatLeaf<(i64 imm), [{
return((uint64_t)N->getValue()==0x00FF00FF00FF00FFLL);
}]>;
def isMIX2Lable: PatLeaf<(i64 imm), [{
return((uint64_t)N->getValue()==0xFFFF0000FFFF0000LL);
}]>;
def isMIX2Rable: PatLeaf<(i64 imm), [{
return((uint64_t)N->getValue()==0x0000FFFF0000FFFFLL);
}]>;
def isMIX4Lable: PatLeaf<(i64 imm), [{
return((uint64_t)N->getValue()==0xFFFFFFFF00000000LL);
}]>;
def isMIX4Rable: PatLeaf<(i64 imm), [{
return((uint64_t)N->getValue()==0x00000000FFFFFFFFLL);
}]>;
def isSHLADDimm: PatLeaf<(i64 imm), [{
// isSHLADDimm predicate - True if the immediate is exactly 1, 2, 3 or 4
// - 0 is *not* okay.
// Used to create shladd instructions appropriately
int64_t v = (int64_t)N->getValue();
return (v >= 1 && v <= 4);
}]>;
def immSExt14 : PatLeaf<(i64 imm), [{
// immSExt14 predicate - True if the immediate fits in a 14-bit sign extended
// field. Used by instructions like 'adds'.
int64_t v = (int64_t)N->getValue();
return (v <= 8191 && v >= -8192);
}]>;
def imm64 : PatLeaf<(i64 imm), [{
// imm64 predicate - True if the immediate fits in a 64-bit
// field - i.e., true. used to keep movl happy
return true;
}]>;
def SXT1 : AForm_DAG<0x03, 0x0b, (ops GR:$dst, GR:$src), "sxt1 $dst = $src;;",
[(set GR:$dst, (sext_inreg GR:$src, i8))]>;
def ZXT1 : AForm_DAG<0x03, 0x0b, (ops GR:$dst, GR:$src), "zxt1 $dst = $src;;",
[(set GR:$dst, (and GR:$src, 255))]>;
def SXT2 : AForm_DAG<0x03, 0x0b, (ops GR:$dst, GR:$src), "sxt2 $dst = $src;;",
[(set GR:$dst, (sext_inreg GR:$src, i16))]>;
def ZXT2 : AForm_DAG<0x03, 0x0b, (ops GR:$dst, GR:$src), "zxt2 $dst = $src;;",
[(set GR:$dst, (and GR:$src, 65535))]>;
def SXT4 : AForm_DAG<0x03, 0x0b, (ops GR:$dst, GR:$src), "sxt4 $dst = $src;;",
[(set GR:$dst, (sext_inreg GR:$src, i32))]>;
def ZXT4 : AForm_DAG<0x03, 0x0b, (ops GR:$dst, GR:$src), "zxt4 $dst = $src;;",
[(set GR:$dst, (and GR:$src, is32ones))]>;
// fixme: shrs vs shru?
def MIX1L : AForm_DAG<0x03, 0x0b, (ops GR:$dst, GR:$src1, GR:$src2),
"mix1.l $dst = $src1, $src2;;",
[(set GR:$dst, (or (and GR:$src1, isMIX1Lable),
(and (srl GR:$src2, 8), isMIX1Lable)))]>;
def MIX2L : AForm_DAG<0x03, 0x0b, (ops GR:$dst, GR:$src1, GR:$src2),
"mix2.l $dst = $src1, $src2;;",
[(set GR:$dst, (or (and GR:$src1, isMIX2Lable),
(and (srl GR:$src2, 16), isMIX2Lable)))]>;
def MIX4L : AForm_DAG<0x03, 0x0b, (ops GR:$dst, GR:$src1, GR:$src2),
"mix4.l $dst = $src1, $src2;;",
[(set GR:$dst, (or (and GR:$src1, isMIX4Lable),
(and (srl GR:$src2, 32), isMIX4Lable)))]>;
def MIX1R : AForm_DAG<0x03, 0x0b, (ops GR:$dst, GR:$src1, GR:$src2),
"mix1.r $dst = $src1, $src2;;",
[(set GR:$dst, (or (and (shl GR:$src1, 8), isMIX1Rable),
(and GR:$src2, isMIX1Rable)))]>;
def MIX2R : AForm_DAG<0x03, 0x0b, (ops GR:$dst, GR:$src1, GR:$src2),
"mix2.r $dst = $src1, $src2;;",
[(set GR:$dst, (or (and (shl GR:$src1, 16), isMIX2Rable),
(and GR:$src2, isMIX2Rable)))]>;
def MIX4R : AForm_DAG<0x03, 0x0b, (ops GR:$dst, GR:$src1, GR:$src2),
"mix4.r $dst = $src1, $src2;;",
[(set GR:$dst, (or (and (shl GR:$src1, 32), isMIX4Rable),
(and GR:$src2, isMIX4Rable)))]>;
def ADD : AForm_DAG<0x03, 0x0b, (ops GR:$dst, GR:$src1, GR:$src2),
"add $dst = $src1, $src2;;",
[(set GR:$dst, (add GR:$src1, GR:$src2))]>;
def ADD1 : AForm_DAG<0x03, 0x0b, (ops GR:$dst, GR:$src1, GR:$src2),
"add $dst = $src1, $src2, 1;;",
[(set GR:$dst, (add (add GR:$src1, GR:$src2), 1))]>;
def ADDS : AForm_DAG<0x03, 0x0b, (ops GR:$dst, GR:$src1, s14imm:$imm),
"adds $dst = $imm, $src1;;",
[(set GR:$dst, (add GR:$src1, immSExt14:$imm))]>;
def MOVL : AForm_DAG<0x03, 0x0b, (ops GR:$dst, s64imm:$imm),
"movl $dst = $imm;;",
[(set GR:$dst, imm64:$imm)]>;
def ADDL_GA : AForm_DAG<0x03, 0x0b, (ops GR:$dst, GR:$src1, globaladdress:$imm),
"addl $dst = $imm, $src1;;",
[]>;
def SUB : AForm_DAG<0x03, 0x0b, (ops GR:$dst, GR:$src1, GR:$src2),
"sub $dst = $src1, $src2;;",
[(set GR:$dst, (sub GR:$src1, GR:$src2))]>;
def SUB1 : AForm_DAG<0x03, 0x0b, (ops GR:$dst, GR:$src1, GR:$src2),
"sub $dst = $src1, $src2, 1;;",
[(set GR:$dst, (add (sub GR: $src1, GR:$src2), -1))]>;
def GETFSIGD : AForm_DAG<0x03, 0x0b, (ops GR:$dst, FP:$src),
"getf.sig $dst = $src;;",
[]>;
def SETFSIGD : AForm_DAG<0x03, 0x0b, (ops FP:$dst, GR:$src),
"setf.sig $dst = $src;;",
[]>;
def XMALD : AForm_DAG<0x03, 0x0b, (ops FP:$dst, FP:$src1, FP:$src2, FP:$src3),
"xma.l $dst = $src1, $src2, $src3;;",
[]>;
def XMAHD : AForm_DAG<0x03, 0x0b, (ops FP:$dst, FP:$src1, FP:$src2, FP:$src3),
"xma.h $dst = $src1, $src2, $src3;;",
[]>;
def XMAHUD : AForm_DAG<0x03, 0x0b, (ops FP:$dst, FP:$src1, FP:$src2, FP:$src3),
"xma.hu $dst = $src1, $src2, $src3;;",
[]>;
// pseudocode for integer multiplication
def : Pat<(mul GR:$src1, GR:$src2),
(GETFSIGD (XMALD (SETFSIGD GR:$src1), (SETFSIGD GR:$src2), F0))>;
def : Pat<(mulhs GR:$src1, GR:$src2),
(GETFSIGD (XMAHD (SETFSIGD GR:$src1), (SETFSIGD GR:$src2), F0))>;
def : Pat<(mulhu GR:$src1, GR:$src2),
(GETFSIGD (XMAHUD (SETFSIGD GR:$src1), (SETFSIGD GR:$src2), F0))>;
// TODO: addp4 (addp4 dst = src, r0 is a 32-bit add)
// has imm form, too
// def ADDS : AForm<0x03, 0x0b, (ops GR:$dst, GR:$src1, s14imm:$imm),
// "adds $dst = $imm, $src1;;">;
// load constants of various sizes // FIXME: prettyprint -ve constants
def : Pat<(i64 immSExt14:$imm), (ADDS r0, immSExt14:$imm)>;
def : Pat<(i64 imm64:$imm), (MOVL imm64:$imm)>;
// TODO: def : Pat<(i1 1), (MOV p0)>;
def AND : AForm_DAG<0x03, 0x0b, (ops GR:$dst, GR:$src1, GR:$src2),
"and $dst = $src1, $src2;;",
[(set GR:$dst, (and GR:$src1, GR:$src2))]>;
def ANDCM : AForm_DAG<0x03, 0x0b, (ops GR:$dst, GR:$src1, GR:$src2),
"andcm $dst = $src1, $src2;;",
[(set GR:$dst, (and GR:$src1, (not GR:$src2)))]>;
// TODO: and/andcm/or/xor/add/sub/shift immediate forms
def OR : AForm_DAG<0x03, 0x0b, (ops GR:$dst, GR:$src1, GR:$src2),
"or $dst = $src1, $src2;;",
[(set GR:$dst, (or GR:$src1, GR:$src2))]>;
def pOR : AForm<0x03, 0x0b, (ops GR:$dst, GR:$src1, GR:$src2, PR:$qp),
"($qp) or $dst = $src1, $src2;;">;
def PCMPEQUNCR0R0 : AForm<0x03, 0x0b, (ops PR:$dst, PR:$qp),
"($qp) cmp.eq.unc $dst, p0 = r0, r0;;">;
let isTwoAddress=1 in
def TPCMPEQR0R0 : AForm<0x03, 0x0b, (ops PR:$dst, PR:$bogus, PR:$qp),
"($qp) cmp.eq $dst, p0 = r0, r0;;">;
/* our pseudocode for OR on predicates is:
pC = pA OR pB
-------------
(pA) cmp.eq.unc pC,p0 = r0,r0 // pC = pA
;;
(pB) cmp.eq pC,p0 = r0,r0 // if (pB) pC = 1 */
def bOR : Pat<(or PR:$src1, PR:$src2),
(TPCMPEQR0R0 (PCMPEQUNCR0R0 PR:$src1), PR:$src2)>;
// FIXME: these are bogus
def bXOR : Pat<(xor PR:$src1, PR:$src2),
(PCMPEQUNCR0R0 PR:$src1)>;
def XOR : AForm_DAG<0x03, 0x0b, (ops GR:$dst, GR:$src1, GR:$src2),
"xor $dst = $src1, $src2;;",
[(set GR:$dst, (xor GR:$src1, GR:$src2))]>;
def SHLADD: AForm_DAG<0x03, 0x0b, (ops GR:$dst,GR:$src1,s64imm:$imm,GR:$src2),
"shladd $dst = $src1, $imm, $src2;;",
[(set GR:$dst, (add GR:$src2, (shl GR:$src1, isSHLADDimm:$imm)))]>;
def SHL : AForm_DAG<0x03, 0x0b, (ops GR:$dst, GR:$src1, GR:$src2),
"shl $dst = $src1, $src2;;",
[(set GR:$dst, (shl GR:$src1, GR:$src2))]>;
def SHRU : AForm_DAG<0x03, 0x0b, (ops GR:$dst, GR:$src1, GR:$src2),
"shr.u $dst = $src1, $src2;;",
[(set GR:$dst, (srl GR:$src1, GR:$src2))]>;
def SHRS : AForm_DAG<0x03, 0x0b, (ops GR:$dst, GR:$src1, GR:$src2),
"shr $dst = $src1, $src2;;",
[(set GR:$dst, (sra GR:$src1, GR:$src2))]>;
/*
def CMPEQ : AForm<0x03, 0x0b, (ops PR:$dst, GR:$src1, GR:$src2),
"cmp.eq $dst, p0 = $src1, $src2;;">;
def CMPGT : AForm<0x03, 0x0b, (ops PR:$dst, GR:$src1, GR:$src2),
"cmp.gt $dst, p0 = $src1, $src2;;">;
def CMPGE : AForm<0x03, 0x0b, (ops PR:$dst, GR:$src1, GR:$src2),
"cmp.ge $dst, p0 = $src1, $src2;;">;
def CMPLT : AForm<0x03, 0x0b, (ops PR:$dst, GR:$src1, GR:$src2),
"cmp.lt $dst, p0 = $src1, $src2;;">;
def CMPLE : AForm<0x03, 0x0b, (ops PR:$dst, GR:$src1, GR:$src2),
"cmp.le $dst, p0 = $src1, $src2;;">;
def CMPNE : AForm<0x03, 0x0b, (ops PR:$dst, GR:$src1, GR:$src2),
"cmp.ne $dst, p0 = $src1, $src2;;">;
def CMPLTU : AForm<0x03, 0x0b, (ops PR:$dst, GR:$src1, GR:$src2),
"cmp.ltu $dst, p0 = $src1, $src2;;">;
def CMPGTU : AForm<0x03, 0x0b, (ops PR:$dst, GR:$src1, GR:$src2),
"cmp.gtu $dst, p0 = $src1, $src2;;">;
def CMPLEU : AForm<0x03, 0x0b, (ops PR:$dst, GR:$src1, GR:$src2),
"cmp.leu $dst, p0 = $src1, $src2;;">;
def CMPGEU : AForm<0x03, 0x0b, (ops PR:$dst, GR:$src1, GR:$src2),
"cmp.geu $dst, p0 = $src1, $src2;;">;
*/
// the following are all a bit unfortunate: we throw away the complement
// of the compare!
def CMPEQ : AForm_DAG<0x03, 0x0b, (ops PR:$dst, GR:$src1, GR:$src2),
"cmp.eq $dst, p0 = $src1, $src2;;",
[(set PR:$dst, (seteq GR:$src1, GR:$src2))]>;
def CMPGT : AForm_DAG<0x03, 0x0b, (ops PR:$dst, GR:$src1, GR:$src2),
"cmp.gt $dst, p0 = $src1, $src2;;",
[(set PR:$dst, (setgt GR:$src1, GR:$src2))]>;
def CMPGE : AForm_DAG<0x03, 0x0b, (ops PR:$dst, GR:$src1, GR:$src2),
"cmp.ge $dst, p0 = $src1, $src2;;",
[(set PR:$dst, (setge GR:$src1, GR:$src2))]>;
def CMPLT : AForm_DAG<0x03, 0x0b, (ops PR:$dst, GR:$src1, GR:$src2),
"cmp.lt $dst, p0 = $src1, $src2;;",
[(set PR:$dst, (setlt GR:$src1, GR:$src2))]>;
def CMPLE : AForm_DAG<0x03, 0x0b, (ops PR:$dst, GR:$src1, GR:$src2),
"cmp.le $dst, p0 = $src1, $src2;;",
[(set PR:$dst, (setle GR:$src1, GR:$src2))]>;
def CMPNE : AForm_DAG<0x03, 0x0b, (ops PR:$dst, GR:$src1, GR:$src2),
"cmp.ne $dst, p0 = $src1, $src2;;",
[(set PR:$dst, (setne GR:$src1, GR:$src2))]>;
def CMPLTU: AForm_DAG<0x03, 0x0b, (ops PR:$dst, GR:$src1, GR:$src2),
"cmp.eq $dst, p0 = $src1, $src2;;",
[(set PR:$dst, (setult GR:$src1, GR:$src2))]>;
def CMPGTU: AForm_DAG<0x03, 0x0b, (ops PR:$dst, GR:$src1, GR:$src2),
"cmp.eq $dst, p0 = $src1, $src2;;",
[(set PR:$dst, (setugt GR:$src1, GR:$src2))]>;
def CMPLEU: AForm_DAG<0x03, 0x0b, (ops PR:$dst, GR:$src1, GR:$src2),
"cmp.eq $dst, p0 = $src1, $src2;;",
[(set PR:$dst, (setule GR:$src1, GR:$src2))]>;
def CMPGEU: AForm_DAG<0x03, 0x0b, (ops PR:$dst, GR:$src1, GR:$src2),
"cmp.eq $dst, p0 = $src1, $src2;;",
[(set PR:$dst, (setuge GR:$src1, GR:$src2))]>;
// TODO: support postincrement (reg, imm9) loads+stores - this needs more
// tablegen support
def PHI : PseudoInstIA64<(ops variable_ops), "PHI">;
def IDEF : PseudoInstIA64<(ops variable_ops), "// IDEF">;
def IUSE : PseudoInstIA64<(ops variable_ops), "// IUSE">;
def ADJUSTCALLSTACKUP : PseudoInstIA64<(ops variable_ops),
"// ADJUSTCALLSTACKUP">;
def ADJUSTCALLSTACKDOWN : PseudoInstIA64<(ops variable_ops),
"// ADJUSTCALLSTACKDOWN">;
def PSEUDO_ALLOC : PseudoInstIA64<(ops GR:$foo), "// PSEUDO_ALLOC">;
def ALLOC : AForm<0x03, 0x0b,
(ops GR:$dst, i8imm:$inputs, i8imm:$locals, i8imm:$outputs, i8imm:$rotating),
"alloc $dst = ar.pfs,$inputs,$locals,$outputs,$rotating;;">;
def MOV : AForm<0x03, 0x0b, (ops GR:$dst, GR:$src), "mov $dst = $src;;">;
def PMOV : AForm<0x03, 0x0b, (ops GR:$dst, GR:$src, PR:$qp),
"($qp) mov $dst = $src;;">;
def SPILL_ALL_PREDICATES_TO_GR : AForm<0x03, 0x0b, (ops GR:$dst),
"mov $dst = pr;;">;
def FILL_ALL_PREDICATES_FROM_GR : AForm<0x03, 0x0b, (ops GR:$src),
"mov pr = $src;;">;
let isTwoAddress = 1 in {
def CMOV : AForm<0x03, 0x0b, (ops GR:$dst, GR:$src2, GR:$src, PR:$qp),
"($qp) mov $dst = $src;;">;
}
def PFMOV : AForm<0x03, 0x0b, (ops FP:$dst, FP:$src, PR:$qp),
"($qp) mov $dst = $src;;">;
let isTwoAddress = 1 in {
def CFMOV : AForm<0x03, 0x0b, (ops FP:$dst, FP:$src2, FP:$src, PR:$qp),
"($qp) mov $dst = $src;;">;
}
let isTwoAddress = 1 in {
def TCMPNE : AForm<0x03, 0x0b,
(ops PR:$dst, PR:$src2, GR:$src3, GR:$src4),
"cmp.ne $dst, p0 = $src3, $src4;;">;
def TPCMPEQOR : AForm<0x03, 0x0b,
(ops PR:$dst, PR:$src2, GR:$src3, GR:$src4, PR:$qp),
"($qp) cmp.eq.or $dst, p0 = $src3, $src4;;">;
def TPCMPNE : AForm<0x03, 0x0b,
(ops PR:$dst, PR:$src2, GR:$src3, GR:$src4, PR:$qp),
"($qp) cmp.ne $dst, p0 = $src3, $src4;;">;
def TPCMPEQ : AForm<0x03, 0x0b,
(ops PR:$dst, PR:$src2, GR:$src3, GR:$src4, PR:$qp),
"($qp) cmp.eq $dst, p0 = $src3, $src4;;">;
}
def MOVSIMM14 : AForm<0x03, 0x0b, (ops GR:$dst, s14imm:$imm),
"mov $dst = $imm;;">;
def MOVSIMM22 : AForm<0x03, 0x0b, (ops GR:$dst, s22imm:$imm),
"mov $dst = $imm;;">;
def MOVLIMM64 : AForm<0x03, 0x0b, (ops GR:$dst, s64imm:$imm),
"movl $dst = $imm;;">;
def SHLI : AForm<0x03, 0x0b, (ops GR:$dst, GR:$src1, u6imm:$imm),
"shl $dst = $src1, $imm;;">;
def SHRUI : AForm<0x03, 0x0b, (ops GR:$dst, GR:$src1, u6imm:$imm),
"shr.u $dst = $src1, $imm;;">;
def SHRSI : AForm<0x03, 0x0b, (ops GR:$dst, GR:$src1, u6imm:$imm),
"shr $dst = $src1, $imm;;">;
def EXTRU : AForm<0x03, 0x0b, (ops GR:$dst, GR:$src1, u6imm:$imm1, u6imm:$imm2),
"extr.u $dst = $src1, $imm1, $imm2;;">;
def DEPZ : AForm<0x03, 0x0b, (ops GR:$dst, GR:$src1, u6imm:$imm1, u6imm:$imm2), "dep.z $dst = $src1, $imm1, $imm2;;">;
// and we do the whole thing again for FP compares!
def FCMPEQ : AForm<0x03, 0x0b, (ops PR:$dst, FP:$src1, FP:$src2),
"fcmp.eq $dst, p0 = $src1, $src2;;">;
def FCMPGT : AForm<0x03, 0x0b, (ops PR:$dst, FP:$src1, FP:$src2),
"fcmp.gt $dst, p0 = $src1, $src2;;">;
def FCMPGE : AForm<0x03, 0x0b, (ops PR:$dst, FP:$src1, FP:$src2),
"fcmp.ge $dst, p0 = $src1, $src2;;">;
def FCMPLT : AForm<0x03, 0x0b, (ops PR:$dst, FP:$src1, FP:$src2),
"fcmp.lt $dst, p0 = $src1, $src2;;">;
def FCMPLE : AForm<0x03, 0x0b, (ops PR:$dst, FP:$src1, FP:$src2),
"fcmp.le $dst, p0 = $src1, $src2;;">;
def FCMPNE : AForm<0x03, 0x0b, (ops PR:$dst, FP:$src1, FP:$src2),
"fcmp.neq $dst, p0 = $src1, $src2;;">;
def FCMPLTU : AForm<0x03, 0x0b, (ops PR:$dst, FP:$src1, FP:$src2),
"fcmp.ltu $dst, p0 = $src1, $src2;;">;
def FCMPGTU : AForm<0x03, 0x0b, (ops PR:$dst, FP:$src1, FP:$src2),
"fcmp.gtu $dst, p0 = $src1, $src2;;">;
def FCMPLEU : AForm<0x03, 0x0b, (ops PR:$dst, FP:$src1, FP:$src2),
"fcmp.leu $dst, p0 = $src1, $src2;;">;
def FCMPGEU : AForm<0x03, 0x0b, (ops PR:$dst, FP:$src1, FP:$src2),
"fcmp.geu $dst, p0 = $src1, $src2;;">;
def PCMPEQOR : AForm<0x03, 0x0b, (ops PR:$dst, GR:$src1, GR:$src2, PR:$qp),
"($qp) cmp.eq.or $dst, p0 = $src1, $src2;;">;
def PCMPEQUNC : AForm<0x03, 0x0b, (ops PR:$dst, GR:$src1, GR:$src2, PR:$qp),
"($qp) cmp.eq.unc $dst, p0 = $src1, $src2;;">;
def PCMPNE : AForm<0x03, 0x0b, (ops PR:$dst, GR:$src1, GR:$src2, PR:$qp),
"($qp) cmp.ne $dst, p0 = $src1, $src2;;">;
// two destinations!
def BCMPEQ : AForm<0x03, 0x0b, (ops PR:$dst1, PR:$dst2, GR:$src1, GR:$src2),
"cmp.eq $dst1, dst2 = $src1, $src2;;">;
def ADDIMM14 : AForm<0x03, 0x0b, (ops GR:$dst, GR:$src1, s14imm:$imm),
"adds $dst = $imm, $src1;;">;
def ADDIMM22 : AForm<0x03, 0x0b, (ops GR:$dst, GR:$src1, s22imm:$imm),
"add $dst = $imm, $src1;;">;
def CADDIMM22 : AForm<0x03, 0x0b, (ops GR:$dst, GR:$src1, s22imm:$imm, PR:$qp),
"($qp) add $dst = $imm, $src1;;">;
let isTwoAddress = 1 in {
def TPCADDIMM22 : AForm<0x03, 0x0b,
(ops GR:$dst, GR:$src1, s22imm:$imm, PR:$qp),
"($qp) add $dst = $imm, $dst;;">;
def TPCMPIMM8NE : AForm<0x03, 0x0b,
(ops PR:$dst, PR:$src1, s22imm:$imm, GR:$src2, PR:$qp),
"($qp) cmp.ne $dst , p0 = $imm, $src2;;">;
}
def SUBIMM8 : AForm<0x03, 0x0b, (ops GR:$dst, s8imm:$imm, GR:$src2),
"sub $dst = $imm, $src2;;">;
let isStore = 1 in {
def ST1 : AForm<0x03, 0x0b, (ops GR:$dstPtr, GR:$value),
"st1 [$dstPtr] = $value;;">;
def ST2 : AForm<0x03, 0x0b, (ops GR:$dstPtr, GR:$value),
"st2 [$dstPtr] = $value;;">;
def ST4 : AForm<0x03, 0x0b, (ops GR:$dstPtr, GR:$value),
"st4 [$dstPtr] = $value;;">;
def ST8 : AForm<0x03, 0x0b, (ops GR:$dstPtr, GR:$value),
"st8 [$dstPtr] = $value;;">;
def STF4 : AForm<0x03, 0x0b, (ops GR:$dstPtr, FP:$value),
"stfs [$dstPtr] = $value;;">;
def STF8 : AForm<0x03, 0x0b, (ops GR:$dstPtr, FP:$value),
"stfd [$dstPtr] = $value;;">;
}
let isLoad = 1 in {
def LD1 : AForm<0x03, 0x0b, (ops GR:$dst, GR:$srcPtr),
"ld1 $dst = [$srcPtr];;">;
def LD2 : AForm<0x03, 0x0b, (ops GR:$dst, GR:$srcPtr),
"ld2 $dst = [$srcPtr];;">;
def LD4 : AForm<0x03, 0x0b, (ops GR:$dst, GR:$srcPtr),
"ld4 $dst = [$srcPtr];;">;
def LD8 : AForm<0x03, 0x0b, (ops GR:$dst, GR:$srcPtr),
"ld8 $dst = [$srcPtr];;">;
def LDF4 : AForm<0x03, 0x0b, (ops FP:$dst, GR:$srcPtr),
"ldfs $dst = [$srcPtr];;">;
def LDF8 : AForm<0x03, 0x0b, (ops FP:$dst, GR:$srcPtr),
"ldfd $dst = [$srcPtr];;">;
}
def POPCNT : AForm_DAG<0x03, 0x0b, (ops GR:$dst, GR:$src),
"popcnt $dst = $src;;",
[(set GR:$dst, (ctpop GR:$src))]>;
// some FP stuff: // TODO: single-precision stuff?
def FADD : AForm_DAG<0x03, 0x0b, (ops FP:$dst, FP:$src1, FP:$src2),
"fadd $dst = $src1, $src2;;",
[(set FP:$dst, (fadd FP:$src1, FP:$src2))]>;
def FADDS: AForm<0x03, 0x0b, (ops FP:$dst, FP:$src1, FP:$src2),
"fadd.s $dst = $src1, $src2;;">;
def FSUB : AForm_DAG<0x03, 0x0b, (ops FP:$dst, FP:$src1, FP:$src2),
"fsub $dst = $src1, $src2;;",
[(set FP:$dst, (fsub FP:$src1, FP:$src2))]>;
def FMPY : AForm_DAG<0x03, 0x0b, (ops FP:$dst, FP:$src1, FP:$src2),
"fmpy $dst = $src1, $src2;;",
[(set FP:$dst, (fmul FP:$src1, FP:$src2))]>;
def FMOV : AForm<0x03, 0x0b, (ops FP:$dst, FP:$src),
"mov $dst = $src;;">; // XXX: there _is_ no fmov
def FMA : AForm_DAG<0x03, 0x0b, (ops FP:$dst, FP:$src1, FP:$src2, FP:$src3),
"fma $dst = $src1, $src2, $src3;;",
[(set FP:$dst, (fadd (fmul FP:$src1, FP:$src2), FP:$src3))]>;
def FMS : AForm_DAG<0x03, 0x0b, (ops FP:$dst, FP:$src1, FP:$src2, FP:$src3),
"fms $dst = $src1, $src2, $src3;;",
[(set FP:$dst, (fsub (fmul FP:$src1, FP:$src2), FP:$src3))]>;
def FNMA : AForm_DAG<0x03, 0x0b, (ops FP:$dst, FP:$src1, FP:$src2, FP:$src3),
"fnma $dst = $src1, $src2, $src3;;",
[(set FP:$dst, (fneg (fadd (fmul FP:$src1, FP:$src2), FP:$src3)))]>;
def FABS : AForm<0x03, 0x0b, (ops FP:$dst, FP:$src),
"fabs $dst = $src;;">;
def FNEG : AForm_DAG<0x03, 0x0b, (ops FP:$dst, FP:$src),
"fneg $dst = $src;;",
[(set FP:$dst, (fneg FP:$src))]>;
def FNEGABS : AForm<0x03, 0x0b, (ops FP:$dst, FP:$src),
"fnegabs $dst = $src;;">;
def CFMAS1 : AForm<0x03, 0x0b,
(ops FP:$dst, FP:$src1, FP:$src2, FP:$src3, PR:$qp),
"($qp) fma.s1 $dst = $src1, $src2, $src3;;">;
def CFNMAS1 : AForm<0x03, 0x0b,
(ops FP:$dst, FP:$src1, FP:$src2, FP:$src3, PR:$qp),
"($qp) fnma.s1 $dst = $src1, $src2, $src3;;">;
def FRCPAS1 : AForm<0x03, 0x0b, (ops FP:$dstFR, PR:$dstPR, FP:$src1, FP:$src2),
"frcpa.s1 $dstFR, $dstPR = $src1, $src2;;">;
def XMAL : AForm<0x03, 0x0b, (ops FP:$dst, FP:$src1, FP:$src2, FP:$src3),
"xma.l $dst = $src1, $src2, $src3;;">;
def FCVTXF : AForm<0x03, 0x0b, (ops FP:$dst, FP:$src),
"fcvt.xf $dst = $src;;">;
def FCVTXUF : AForm<0x03, 0x0b, (ops FP:$dst, FP:$src),
"fcvt.xuf $dst = $src;;">;
def FCVTXUFS1 : AForm<0x03, 0x0b, (ops FP:$dst, FP:$src),
"fcvt.xuf.s1 $dst = $src;;">;
def FCVTFX : AForm<0x03, 0x0b, (ops FP:$dst, FP:$src),
"fcvt.fx $dst = $src;;">;
def FCVTFXU : AForm<0x03, 0x0b, (ops FP:$dst, FP:$src),
"fcvt.fxu $dst = $src;;">;
def FCVTFXTRUNC : AForm<0x03, 0x0b, (ops FP:$dst, FP:$src),
"fcvt.fx.trunc $dst = $src;;">;
def FCVTFXUTRUNC : AForm<0x03, 0x0b, (ops FP:$dst, FP:$src),
"fcvt.fxu.trunc $dst = $src;;">;
def FCVTFXTRUNCS1 : AForm<0x03, 0x0b, (ops FP:$dst, FP:$src),
"fcvt.fx.trunc.s1 $dst = $src;;">;
def FCVTFXUTRUNCS1 : AForm<0x03, 0x0b, (ops FP:$dst, FP:$src),
"fcvt.fxu.trunc.s1 $dst = $src;;">;
def FNORMD : AForm<0x03, 0x0b, (ops FP:$dst, FP:$src),
"fnorm.d $dst = $src;;">;
def GETFD : AForm<0x03, 0x0b, (ops GR:$dst, FP:$src),
"getf.d $dst = $src;;">;
def SETFD : AForm<0x03, 0x0b, (ops FP:$dst, GR:$src),
"setf.d $dst = $src;;">;
def GETFSIG : AForm<0x03, 0x0b, (ops GR:$dst, FP:$src),
"getf.sig $dst = $src;;">;
def SETFSIG : AForm<0x03, 0x0b, (ops FP:$dst, GR:$src),
"setf.sig $dst = $src;;">;
let isTerminator = 1, isBranch = 1 in {
def BRL_NOTCALL : RawForm<0x03, 0xb0, (ops i64imm:$dst),
"(p0) brl.cond.sptk $dst;;">;
def BRLCOND_NOTCALL : RawForm<0x03, 0xb0, (ops PR:$qp, i64imm:$dst),
"($qp) brl.cond.sptk $dst;;">;
def BRCOND_NOTCALL : RawForm<0x03, 0xb0, (ops PR:$qp, GR:$dst),
"($qp) br.cond.sptk $dst;;">;
}
let isCall = 1, isTerminator = 1, isBranch = 1,
Uses = [out0,out1,out2,out3,out4,out5,out6,out7],
// all calls clobber non-callee-saved registers, and for now, they are these:
Defs = [r2,r3,r8,r9,r10,r11,r14,r15,r16,r17,r18,r19,r20,r21,r22,r23,r24,
r25,r26,r27,r28,r29,r30,r31,
p6,p7,p8,p9,p10,p11,p12,p13,p14,p15,
F6,F7,F8,F9,F10,F11,F12,F13,F14,F15,
F32,F33,F34,F35,F36,F37,F38,F39,F40,F41,F42,F43,F44,F45,F46,F47,F48,F49,
F50,F51,F52,F53,F54,F55,F56,
F57,F58,F59,F60,F61,F62,F63,F64,F65,F66,F67,F68,F69,F70,F71,F72,F73,F74,
F75,F76,F77,F78,F79,F80,F81,
F82,F83,F84,F85,F86,F87,F88,F89,F90,F91,F92,F93,F94,F95,F96,F97,F98,F99,
F100,F101,F102,F103,F104,F105,
F106,F107,F108,F109,F110,F111,F112,F113,F114,F115,F116,F117,F118,F119,
F120,F121,F122,F123,F124,F125,F126,F127,
out0,out1,out2,out3,out4,out5,out6,out7] in {
// old pattern call
def BRCALL: RawForm<0x03, 0xb0, (ops calltarget:$dst),
"br.call.sptk rp = $dst;;">; // FIXME: teach llvm about branch regs?
// new daggy stuff!
def BRCALL_IPREL : RawForm<0x03, 0xb0, (ops calltarget:$dst, variable_ops),
"br.call.sptk rp = $dst;;">; // FIXME: teach llvm about branch regs?
def BRCALL_INDIRECT : RawForm<0x03, 0xb0, (ops GR:$branchreg, variable_ops),
"br.call.sptk rp = $branchreg;;">; // FIXME: teach llvm about branch regs?
def BRLCOND_CALL : RawForm<0x03, 0xb0, (ops PR:$qp, i64imm:$dst),
"($qp) brl.cond.call.sptk $dst;;">;
def BRCOND_CALL : RawForm<0x03, 0xb0, (ops PR:$qp, GR:$dst),
"($qp) br.cond.call.sptk $dst;;">;
}
let isTerminator = 1, isReturn = 1 in
def RET : RawForm<0x03, 0xb0, (ops), "br.ret.sptk.many rp;;">; // return