aboutsummaryrefslogtreecommitdiffstats
path: root/lib/Target/IA64/IA64InstrInfo.td
blob: 1da7ee77b4f317147b189b7b88e30301e6388f3b (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
//===- 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 u6imm : Operand<i8>;
def s8imm : Operand<i8> {
  let PrintMethod = "printS8ImmOperand";
}
def s14imm  : Operand<i16> {
  let PrintMethod = "printS14ImmOperand";
}
def s22imm  : Operand<i32> {
  let PrintMethod = "printS22ImmOperand";
}
def u64imm  : Operand<i64> {
  let PrintMethod = "printU64ImmOperand";
}
def s64imm  : Operand<i64> {
  let PrintMethod = "printS64ImmOperand";
}

// the asmprinter needs to know about calls
let PrintMethod = "printCallOperand" in
  def calltarget : Operand<i64>;
  
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), "// 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 AND : AForm<0x03, 0x0b, (ops GR:$dst, GR:$src1, GR:$src2),
  "and $dst = $src1, $src2;;">;
def OR : AForm<0x03, 0x0b, (ops GR:$dst, GR:$src1, GR:$src2),
  "or $dst = $src1, $src2;;">;
def XOR : AForm<0x03, 0x0b, (ops GR:$dst, GR:$src1, GR:$src2),
  "xor $dst = $src1, $src2;;">;
def SHL : AForm<0x03, 0x0b, (ops GR:$dst, GR:$src1, GR:$src2),
  "shl $dst = $src1, $src2;;">;
def SHLI : AForm<0x03, 0x0b, (ops GR:$dst, GR:$src1, u6imm:$imm), 
  "shl $dst = $src1, $imm;;">;
def SHRU : AForm<0x03, 0x0b, (ops GR:$dst, GR:$src1, GR:$src2),
  "shr.u $dst = $src1, $src2;;">;
def SHRUI : AForm<0x03, 0x0b, (ops GR:$dst, GR:$src1, u6imm:$imm),
  "shr.u $dst = $src1, $imm;;">;
def SHRS : AForm<0x03, 0x0b, (ops GR:$dst, GR:$src1, GR:$src2),
  "shr $dst = $src1, $src2;;">;
def SHRSI : AForm<0x03, 0x0b, (ops GR:$dst, GR:$src1, u6imm:$imm),
  "shr $dst = $src1, $imm;;">;

def SHLADD : AForm<0x03, 0x0b, (ops GR:$dst, GR:$src1, u6imm:$imm, GR:$src2), 
  "shladd $dst = $src1, $imm, $src2;;">;

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;;">;

def SXT1 : AForm<0x03, 0x0b, (ops GR:$dst, GR:$src), "sxt1 $dst = $src;;">;
def ZXT1 : AForm<0x03, 0x0b, (ops GR:$dst, GR:$src), "zxt1 $dst = $src;;">;
def SXT2 : AForm<0x03, 0x0b, (ops GR:$dst, GR:$src), "sxt2 $dst = $src;;">;
def ZXT2 : AForm<0x03, 0x0b, (ops GR:$dst, GR:$src), "zxt2 $dst = $src;;">;
def SXT4 : AForm<0x03, 0x0b, (ops GR:$dst, GR:$src), "sxt4 $dst = $src;;">;
def ZXT4 : AForm<0x03, 0x0b, (ops GR:$dst, GR:$src), "zxt4 $dst = $src;;">;

// the following are all a bit unfortunate: we throw away the complement
// of the compare!
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;;">;

// 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 ADD : AForm<0x03, 0x0b, (ops GR:$dst, GR:$src1, GR:$src2),
  "add $dst = $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 SUB : AForm<0x03, 0x0b, (ops GR:$dst, GR:$src1, GR:$src2),
  "sub $dst = $src1, $src2;;">;
def SUBIMM8 : AForm<0x03, 0x0b, (ops GR:$dst, s8imm:$imm, GR:$src2),
  "sub $dst = $imm, $src2;;">;

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 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 POPCNT : AForm<0x03, 0x0b, (ops GR:$dst, GR:$src), "popcnt $dst = $src;;">;

// some FP stuff:
def FADD : AForm<0x03, 0x0b, (ops FP:$dst, FP:$src1, FP:$src2),
  "fadd $dst = $src1, $src2;;">;
def FADDS: AForm<0x03, 0x0b, (ops FP:$dst, FP:$src1, FP:$src2),
  "fadd.s $dst = $src1, $src2;;">;
def FSUB : AForm<0x03, 0x0b, (ops FP:$dst, FP:$src1, FP:$src2),
  "fsub $dst = $src1, $src2;;">;
def FMPY : AForm<0x03, 0x0b, (ops FP:$dst, FP:$src1, FP:$src2),
  "fmpy $dst = $src1, $src2;;">;
def FMOV : AForm<0x03, 0x0b, (ops FP:$dst, FP:$src),
  "mov $dst = $src;;">; // XXX: there _is_ no fmov
def FMA : AForm<0x03, 0x0b, (ops FP:$dst, FP:$src1, FP:$src2, FP:$src3),
  "fma $dst = $src1, $src2, $src3;;">;
def FMS : AForm<0x03, 0x0b, (ops FP:$dst, FP:$src1, FP:$src2, FP:$src3),
  "fms $dst = $src1, $src2, $src3;;">;
def FNMA : AForm<0x03, 0x0b, (ops FP:$dst, FP:$src1, FP:$src2, FP:$src3),
  "fnma $dst = $src1, $src2, $src3;;">;
def FABS : AForm<0x03, 0x0b, (ops FP:$dst, FP:$src),
  "fabs $dst = $src;;">;
def FNEG : AForm<0x03, 0x0b, (ops FP:$dst, FP:$src),
  "fneg $dst = $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;;">;

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 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 isTerminator = 1, isBranch = 1 in {
  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 {
  def BRCALL : RawForm<0x03, 0xb0, (ops calltarget:$dst),
  "br.call.sptk rp = $dst;;">;       // 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