summaryrefslogtreecommitdiff
path: root/lib/Target/CellSPU/SPUInstrFormats.td
blob: bdbe2552dcdd154b38853a08b98812a3d41ff904 (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
//==== SPUInstrFormats.td - Cell SPU Instruction Formats ---*- tablegen -*-===//
// 
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
// 
//===----------------------------------------------------------------------===//

//===----------------------------------------------------------------------===//
//
// Cell SPU instruction formats. Note that these are notationally similar to
// PowerPC, like "A-Form". But the sizes of operands and fields differ.

// This was kiped from the PPC instruction formats (seemed like a good idea...)

class SPUInstr<dag OOL, dag IOL, string asmstr, InstrItinClass itin>
        : Instruction {
  field bits<32> Inst;

  let Namespace = "SPU";
  let OutOperandList = OOL;
  let InOperandList = IOL;
  let AsmString = asmstr;
  let Itinerary = itin;
}

// RR Format
class RRForm<bits<11> opcode, dag OOL, dag IOL, string asmstr, 
              InstrItinClass itin, list<dag> pattern>
         : SPUInstr<OOL, IOL, asmstr, itin> {
  bits<7> RA;
  bits<7> RB;
  bits<7> RT;

  let Pattern = pattern;

  let Inst{0-10} = opcode;
  let Inst{11-17} = RB;
  let Inst{18-24} = RA;
  let Inst{25-31} = RT;
}

let RB = 0 in {
  // RR Format, where RB is zeroed (dont care):
  class RRForm_1<bits<11> opcode, dag OOL, dag IOL, string asmstr, 
                 InstrItinClass itin, list<dag> pattern>
           : RRForm<opcode, OOL, IOL, asmstr, itin, pattern>
  { }

  let RA = 0 in {
    // RR Format, where RA and RB are zeroed (dont care):
    // Used for reads from status control registers (see FPSCRRr32)
    class RRForm_2<bits<11> opcode, dag OOL, dag IOL, string asmstr,
                   InstrItinClass itin, list<dag> pattern>
             : RRForm<opcode, OOL, IOL, asmstr, itin, pattern>
    { }
  }
}

let RT = 0 in {
  // RR Format, where RT is zeroed (don't care), or as the instruction handbook
  // says, "RT is a false target." Used in "Halt if" instructions
  class RRForm_3<bits<11> opcode, dag OOL, dag IOL, string asmstr,
                 InstrItinClass itin, list<dag> pattern>
      : RRForm<opcode, OOL, IOL, asmstr, itin, pattern>
  { }
}

// RRR Format
class RRRForm<bits<4> opcode, dag OOL, dag IOL, string asmstr,
              InstrItinClass itin, list<dag> pattern>
        : SPUInstr<OOL, IOL, asmstr, itin>
{
  bits<7> RA;
  bits<7> RB;
  bits<7> RC;
  bits<7> RT;

  let Pattern = pattern;

  let Inst{0-3} = opcode;
  let Inst{4-10} = RT;
  let Inst{11-17} = RB;
  let Inst{18-24} = RA;
  let Inst{25-31} = RC;
}

// RI7 Format
class RI7Form<bits<11> opcode, dag OOL, dag IOL, string asmstr,
              InstrItinClass itin, list<dag> pattern>
        : SPUInstr<OOL, IOL, asmstr, itin>
{
  bits<7> i7;
  bits<7> RA;
  bits<7> RT;

  let Pattern = pattern;

  let Inst{0-10} = opcode;
  let Inst{11-17} = i7;
  let Inst{18-24} = RA;
  let Inst{25-31} = RT;
}

// CVTIntFp Format
class CVTIntFPForm<bits<10> opcode, dag OOL, dag IOL, string asmstr,
                   InstrItinClass itin, list<dag> pattern>
        : SPUInstr<OOL, IOL, asmstr, itin>
{
  bits<7> RA;
  bits<7> RT;

  let Pattern = pattern;

  let Inst{0-9} = opcode;
  let Inst{10-17} = 0;
  let Inst{18-24} = RA;
  let Inst{25-31} = RT;
}

let RA = 0 in {
  class BICondForm<bits<11> opcode, dag OOL, dag IOL, string asmstr, list<dag> pattern>
           : RRForm<opcode, OOL, IOL, asmstr, BranchResolv, pattern>
  { }

  let RT = 0 in {
    // Branch instruction format (without D/E flag settings)
    class BRForm<bits<11> opcode, dag OOL, dag IOL, string asmstr,
               InstrItinClass itin, list<dag> pattern>
          : RRForm<opcode, OOL, IOL, asmstr, itin, pattern>
    { }

    class BIForm<bits<11> opcode, string asmstr, list<dag> pattern>
             : RRForm<opcode, (outs), (ins R32C:$func), asmstr, BranchResolv,
                      pattern>
    { }

    let RB = 0 in {
      // Return instruction (bi, branch indirect), RA is zero (LR):
      class RETForm<string asmstr, list<dag> pattern>
             : BRForm<0b00010101100, (outs), (ins), asmstr, BranchResolv,
                      pattern>
      { }
    }
  }
}

// Branch indirect external data forms:
class BISLEDForm<bits<2> DE_flag, string asmstr, list<dag> pattern>
         : SPUInstr<(outs), (ins indcalltarget:$func), asmstr, BranchResolv>
{
  bits<7> Rcalldest;

  let Pattern = pattern;

  let Inst{0-10} = 0b11010101100;
  let Inst{11} = 0;
  let Inst{12-13} = DE_flag;
  let Inst{14-17} = 0b0000;
  let Inst{18-24} = Rcalldest;
  let Inst{25-31} = 0b0000000;
}

// RI10 Format
class RI10Form<bits<8> opcode, dag OOL, dag IOL, string asmstr,
              InstrItinClass itin, list<dag> pattern>
        : SPUInstr<OOL, IOL, asmstr, itin>
{
  bits<10> i10;
  bits<7> RA;
  bits<7> RT;

  let Pattern = pattern;

  let Inst{0-7} = opcode;
  let Inst{8-17} = i10;
  let Inst{18-24} = RA;
  let Inst{25-31} = RT;
}

// RI10 Format, where the constant is zero (or effectively ignored by the
// SPU)
let i10 = 0 in {
  class RI10Form_1<bits<8> opcode, dag OOL, dag IOL, string asmstr,
                   InstrItinClass itin, list<dag> pattern>
          : RI10Form<opcode, OOL, IOL, asmstr, itin, pattern>
  { }
}

// RI10 Format, where RT is ignored.
// This format is used primarily by the Halt If ... Immediate set of
// instructions
let RT = 0 in {
  class RI10Form_2<bits<8> opcode, dag OOL, dag IOL, string asmstr,
                   InstrItinClass itin, list<dag> pattern>
        : RI10Form<opcode, OOL, IOL, asmstr, itin, pattern>
  { }
}

// RI16 Format
class RI16Form<bits<9> opcode, dag OOL, dag IOL, string asmstr,
              InstrItinClass itin, list<dag> pattern>
        : SPUInstr<OOL, IOL, asmstr, itin>
{
  bits<16> i16;
  bits<7> RT;

  let Pattern = pattern;

  let Inst{0-8} = opcode;
  let Inst{9-24} = i16;
  let Inst{25-31} = RT;
}

// Specialized version of the RI16 Format for unconditional branch relative and
// branch absolute, branch and set link. Note that for branch and set link, the
// link register doesn't have to be $lr, but this is actually hard coded into
// the instruction pattern.

let RT = 0 in {
  class UncondBranch<bits<9> opcode, dag OOL, dag IOL, string asmstr,
                     list<dag> pattern>
    : RI16Form<opcode, OOL, IOL, asmstr, BranchResolv, pattern>
  { }

  class BranchSetLink<bits<9> opcode, dag OOL, dag IOL, string asmstr,
                      list<dag> pattern>
        : RI16Form<opcode, OOL, IOL, asmstr, BranchResolv, pattern>
  { }
}

//===----------------------------------------------------------------------===//
// Specialized versions of RI16:
//===----------------------------------------------------------------------===//

// RI18 Format
class RI18Form<bits<7> opcode, dag OOL, dag IOL, string asmstr,
              InstrItinClass itin, list<dag> pattern>
        : SPUInstr<OOL, IOL, asmstr, itin>
{
  bits<18> i18;
  bits<7> RT;

  let Pattern = pattern;

  let Inst{0-6} = opcode;
  let Inst{7-24} = i18;
  let Inst{25-31} = RT;
}

//===----------------------------------------------------------------------===//
// Instruction formats for intrinsics:
//===----------------------------------------------------------------------===//

// RI10 Format for v8i16 intrinsics
class RI10_Int_v8i16<bits<8> opcode, string opc, InstrItinClass itin,
                     Intrinsic IntID> :
  RI10Form<opcode, (outs VECREG:$rT), (ins s10imm:$val, VECREG:$rA),
           !strconcat(opc, " $rT, $rA, $val"), itin,
           [(set (v8i16 VECREG:$rT), (IntID (v8i16 VECREG:$rA),
                                            i16ImmSExt10:$val))] >;

class RI10_Int_v4i32<bits<8> opcode, string opc, InstrItinClass itin,
                     Intrinsic IntID> :
  RI10Form<opcode, (outs VECREG:$rT), (ins s10imm:$val, VECREG:$rA),
           !strconcat(opc, " $rT, $rA, $val"), itin,
           [(set (v4i32 VECREG:$rT), (IntID (v4i32 VECREG:$rA),
                                            i32ImmSExt10:$val))] >;

// RR Format for v8i16 intrinsics
class RR_Int_v8i16<bits<11> opcode, string opc, InstrItinClass itin,
                   Intrinsic IntID> :
  RRForm<opcode, (outs VECREG:$rT), (ins VECREG:$rA, VECREG:$rB),
         !strconcat(opc, " $rT, $rA, $rB"), itin,
         [(set (v8i16 VECREG:$rT), (IntID (v8i16 VECREG:$rA),
                                          (v8i16 VECREG:$rB)))] >;

// RR Format for v4i32 intrinsics
class RR_Int_v4i32<bits<11> opcode, string opc, InstrItinClass itin,
                   Intrinsic IntID> :
  RRForm<opcode, (outs VECREG:$rT), (ins VECREG:$rA, VECREG:$rB),
         !strconcat(opc, " $rT, $rA, $rB"), itin,
         [(set (v4i32 VECREG:$rT), (IntID (v4i32 VECREG:$rA),
                                          (v4i32 VECREG:$rB)))] >;

//===----------------------------------------------------------------------===//
// Pseudo instructions, like call frames:
//===----------------------------------------------------------------------===//

class Pseudo<dag OOL, dag IOL, string asmstr, list<dag> pattern>
    : SPUInstr<OOL, IOL, asmstr, NoItinerary> {
  let OutOperandList = OOL;
  let InOperandList = IOL;
  let AsmString   = asmstr;
  let Pattern = pattern;
  let Inst{31-0} = 0;
}

//===----------------------------------------------------------------------===//
// Branch hint formats
//===----------------------------------------------------------------------===//
// For hbrr and hbra
class HBI16Form<bits<7> opcode, dag IOL, string asmstr>
        : Instruction {
  field bits<32> Inst;
  bits<16>i16;
  bits<9>RO;

  let Namespace = "SPU";
  let InOperandList = IOL;
  let OutOperandList = (outs); //no output
  let AsmString = asmstr;
  let Itinerary = BranchHints;

  let Inst{0-6} = opcode;
  let Inst{7-8} = RO{8-7};
  let Inst{9-24} = i16;
  let Inst{25-31} = RO{6-0};
}