1 //===- SPUOperands.td - Cell SPU Instruction Operands ------*- tablegen -*-===//
3 // The LLVM Compiler Infrastructure
5 // This file was developed by The Aerospace Corporation.
7 //===----------------------------------------------------------------------===//
8 // Cell SPU Instruction Operands:
9 //===----------------------------------------------------------------------===//
11 def LO16 : SDNodeXForm<imm, [{
12 unsigned val = N->getValue();
13 // Transformation function: get the low 16 bits.
14 return getI32Imm(val & 0xffff);
17 def LO16_vec : SDNodeXForm<scalar_to_vector, [{
18 SDOperand OpVal(0, 0);
20 // Transformation function: get the low 16 bit immediate from a build_vector
22 assert(N->getOpcode() == ISD::BUILD_VECTOR
23 && "LO16_vec got something other than a BUILD_VECTOR");
25 // Get first constant operand...
26 for (unsigned i = 0, e = N->getNumOperands(); OpVal.Val == 0 && i != e; ++i) {
27 if (N->getOperand(i).getOpcode() == ISD::UNDEF) continue;
29 OpVal = N->getOperand(i);
32 assert(OpVal.Val != 0 && "LO16_vec did not locate a <defined> node");
33 ConstantSDNode *CN = dyn_cast<ConstantSDNode>(OpVal);
34 return getI32Imm((unsigned)CN->getValue() & 0xffff);
37 // Transform an immediate, returning the high 16 bits shifted down:
38 def HI16 : SDNodeXForm<imm, [{
39 return getI32Imm((unsigned)N->getValue() >> 16);
42 // Transformation function: shift the high 16 bit immediate from a build_vector
43 // node into the low 16 bits, and return a 16-bit constant.
44 def HI16_vec : SDNodeXForm<scalar_to_vector, [{
45 SDOperand OpVal(0, 0);
47 assert(N->getOpcode() == ISD::BUILD_VECTOR
48 && "HI16_vec got something other than a BUILD_VECTOR");
50 // Get first constant operand...
51 for (unsigned i = 0, e = N->getNumOperands(); OpVal.Val == 0 && i != e; ++i) {
52 if (N->getOperand(i).getOpcode() == ISD::UNDEF) continue;
54 OpVal = N->getOperand(i);
57 assert(OpVal.Val != 0 && "HI16_vec did not locate a <defined> node");
58 ConstantSDNode *CN = dyn_cast<ConstantSDNode>(OpVal);
59 return getI32Imm((unsigned)CN->getValue() >> 16);
62 // simm7 predicate - True if the immediate fits in an 7-bit signed
64 def simm7: PatLeaf<(imm), [{
65 int sextVal = ((((int) N->getValue()) << 25) >> 25);
66 return (sextVal >= -64 && sextVal <= 63);
69 // uimm7 predicate - True if the immediate fits in an 7-bit unsigned
71 def uimm7: PatLeaf<(imm), [{
72 return (N->getValue() <= 0x7f);
75 // immSExt8 predicate - True if the immediate fits in an 8-bit sign extended
77 def immSExt8 : PatLeaf<(imm), [{
78 int Value = (int) N->getValue();
79 int Value8 = (Value << 24) >> 24;
80 return (Value < 0xff && (Value8 >= -128 && Value8 < 127));
83 // immU8: immediate, unsigned 8-bit quantity
84 def immU8 : PatLeaf<(imm), [{
85 return (N->getValue() <= 0xff);
88 // i64ImmSExt10 predicate - True if the i64 immediate fits in a 10-bit sign
89 // extended field. Used by RI10Form instructions like 'ldq'.
90 def i64ImmSExt10 : PatLeaf<(imm), [{
91 return isI64IntS10Immediate(N);
94 // i32ImmSExt10 predicate - True if the i32 immediate fits in a 10-bit sign
95 // extended field. Used by RI10Form instructions like 'ldq'.
96 def i32ImmSExt10 : PatLeaf<(imm), [{
97 return isI32IntS10Immediate(N);
100 // i16ImmSExt10 predicate - True if the i32 immediate fits in a 10-bit sign
101 // extended field. Used by RI10Form instructions like 'ldq'.
102 def i16ImmSExt10 : PatLeaf<(imm), [{
103 return isI16IntS10Immediate(N);
106 def immSExt16 : PatLeaf<(imm), [{
107 // immSExt16 predicate - True if the immediate fits in a 16-bit sign extended
110 return isIntS16Immediate(N, Ignored);
113 def immZExt16 : PatLeaf<(imm), [{
114 // immZExt16 predicate - True if the immediate fits in a 16-bit zero extended
116 return (uint64_t)N->getValue() == (unsigned short)N->getValue();
119 def immU16 : PatLeaf<(imm), [{
120 // immU16 predicate- True if the immediate fits into a 16-bit unsigned field.
121 return (uint64_t)N->getValue() == (N->getValue() & 0xffff);
124 def imm18 : PatLeaf<(imm), [{
125 // imm18 predicate: True if the immediate fits into an 18-bit unsigned field.
126 int Value = (int) N->getValue();
127 return ((Value & ((1 << 19) - 1)) == Value);
130 def hi16 : PatLeaf<(imm), [{
131 // hi16 predicate - returns true if the immediate has all zeros in the
132 // low order bits and is a 32-bit constant:
133 if (N->getValueType(0) == MVT::i32) {
134 uint32_t val = N->getValue();
135 return ((val & 0xffff0000) == val);
141 //===----------------------------------------------------------------------===//
142 // Floating point operands:
143 //===----------------------------------------------------------------------===//
145 // Transform a float, returning the high 16 bits shifted down, as if
146 // the float was really an unsigned integer:
147 def HI16_f32 : SDNodeXForm<fpimm, [{
148 const APFloat &apf = N->getValueAPF();
149 float fval = apf.convertToFloat();
150 unsigned val = *((unsigned *) &fval);
151 return getI32Imm(val >> 16);
154 // Transformation function on floats: get the low 16 bits as if the float was
155 // an unsigned integer.
156 def LO16_f32 : SDNodeXForm<fpimm, [{
157 const APFloat &apf = N->getValueAPF();
158 float fval = apf.convertToFloat();
159 unsigned val = *((unsigned *) &fval);
160 return getI32Imm(val & 0xffff);
163 def FPimm_sext16 : SDNodeXForm<fpimm, [{
164 const APFloat &apf = N->getValueAPF();
165 float fval = apf.convertToFloat();
166 unsigned val = *((unsigned *) &fval);
167 return getI32Imm((int) ((val << 16) >> 16));
170 def FPimm_u18 : SDNodeXForm<fpimm, [{
171 const APFloat &apf = N->getValueAPF();
172 float fval = apf.convertToFloat();
173 unsigned val = *((unsigned *) &fval);
174 return getI32Imm(val & ((1 << 19) - 1));
177 def fpimmSExt16 : PatLeaf<(fpimm), [{
179 return isFPS16Immediate(N, Ignored);
182 // Does the SFP constant only have upp 16 bits set?
183 def hi16_f32 : PatLeaf<(fpimm), [{
184 if (N->getValueType(0) == MVT::f32) {
185 const APFloat &apf = N->getValueAPF();
186 float fval = apf.convertToFloat();
187 uint32_t val = *((unsigned *) &fval);
188 return ((val & 0xffff0000) == val);
194 // Does the SFP constant fit into 18 bits?
195 def fpimm18 : PatLeaf<(fpimm), [{
196 if (N->getValueType(0) == MVT::f32) {
197 const APFloat &apf = N->getValueAPF();
198 float fval = apf.convertToFloat();
199 uint32_t Value = *((uint32_t *) &fval);
200 return ((Value & ((1 << 19) - 1)) == Value);
206 //===----------------------------------------------------------------------===//
208 //===----------------------------------------------------------------------===//
210 //===----------------------------------------------------------------------===//
211 // build_vector operands:
212 //===----------------------------------------------------------------------===//
214 // v16i8SExt8Imm_xform function: convert build_vector to 8-bit sign extended
215 // immediate constant load for v16i8 vectors. N.B.: The incoming constant has
216 // to be a 16-bit quantity with the upper and lower bytes equal (e.g., 0x2a2a).
217 def v16i8SExt8Imm_xform: SDNodeXForm<build_vector, [{
218 return SPU::get_vec_i8imm(N, *CurDAG, MVT::i8);
221 // v16i8SExt8Imm: Predicate test for 8-bit sign extended immediate constant
222 // load, works in conjunction with its transform function. N.B.: This relies the
223 // incoming constant being a 16-bit quantity, where the upper and lower bytes
224 // are EXACTLY the same (e.g., 0x2a2a)
225 def v16i8SExt8Imm: PatLeaf<(build_vector), [{
226 return SPU::get_vec_i8imm(N, *CurDAG, MVT::i8).Val != 0;
227 }], v16i8SExt8Imm_xform>;
229 // v16i8U8Imm_xform function: convert build_vector to unsigned 8-bit
230 // immediate constant load for v16i8 vectors. N.B.: The incoming constant has
231 // to be a 16-bit quantity with the upper and lower bytes equal (e.g., 0x2a2a).
232 def v16i8U8Imm_xform: SDNodeXForm<build_vector, [{
233 return SPU::get_vec_i8imm(N, *CurDAG, MVT::i8);
236 // v16i8U8Imm: Predicate test for unsigned 8-bit immediate constant
237 // load, works in conjunction with its transform function. N.B.: This relies the
238 // incoming constant being a 16-bit quantity, where the upper and lower bytes
239 // are EXACTLY the same (e.g., 0x2a2a)
240 def v16i8U8Imm: PatLeaf<(build_vector), [{
241 return SPU::get_vec_i8imm(N, *CurDAG, MVT::i8).Val != 0;
242 }], v16i8U8Imm_xform>;
244 // v8i16SExt8Imm_xform function: convert build_vector to 8-bit sign extended
245 // immediate constant load for v8i16 vectors.
246 def v8i16SExt8Imm_xform: SDNodeXForm<build_vector, [{
247 return SPU::get_vec_i8imm(N, *CurDAG, MVT::i16);
250 // v8i16SExt8Imm: Predicate test for 8-bit sign extended immediate constant
251 // load, works in conjunction with its transform function.
252 def v8i16SExt8Imm: PatLeaf<(build_vector), [{
253 return SPU::get_vec_i8imm(N, *CurDAG, MVT::i16).Val != 0;
254 }], v8i16SExt8Imm_xform>;
256 // v8i16SExt10Imm_xform function: convert build_vector to 16-bit sign extended
257 // immediate constant load for v8i16 vectors.
258 def v8i16SExt10Imm_xform: SDNodeXForm<build_vector, [{
259 return SPU::get_vec_i10imm(N, *CurDAG, MVT::i16);
262 // v8i16SExt10Imm: Predicate test for 16-bit sign extended immediate constant
263 // load, works in conjunction with its transform function.
264 def v8i16SExt10Imm: PatLeaf<(build_vector), [{
265 return SPU::get_vec_i10imm(N, *CurDAG, MVT::i16).Val != 0;
266 }], v8i16SExt10Imm_xform>;
268 // v8i16SExt16Imm_xform function: convert build_vector to 16-bit sign extended
269 // immediate constant load for v8i16 vectors.
270 def v8i16SExt16Imm_xform: SDNodeXForm<build_vector, [{
271 return SPU::get_vec_i16imm(N, *CurDAG, MVT::i16);
274 // v8i16SExt16Imm: Predicate test for 16-bit sign extended immediate constant
275 // load, works in conjunction with its transform function.
276 def v8i16SExt16Imm: PatLeaf<(build_vector), [{
277 return SPU::get_vec_i16imm(N, *CurDAG, MVT::i16).Val != 0;
278 }], v8i16SExt16Imm_xform>;
280 // v4i32SExt10Imm_xform function: convert build_vector to 10-bit sign extended
281 // immediate constant load for v4i32 vectors.
282 def v4i32SExt10Imm_xform: SDNodeXForm<build_vector, [{
283 return SPU::get_vec_i10imm(N, *CurDAG, MVT::i32);
286 // v4i32SExt10Imm: Predicate test for 10-bit sign extended immediate constant
287 // load, works in conjunction with its transform function.
288 def v4i32SExt10Imm: PatLeaf<(build_vector), [{
289 return SPU::get_vec_i10imm(N, *CurDAG, MVT::i32).Val != 0;
290 }], v4i32SExt10Imm_xform>;
292 // v4i32SExt16Imm_xform function: convert build_vector to 16-bit sign extended
293 // immediate constant load for v4i32 vectors.
294 def v4i32SExt16Imm_xform: SDNodeXForm<build_vector, [{
295 return SPU::get_vec_i16imm(N, *CurDAG, MVT::i32);
298 // v4i32SExt16Imm: Predicate test for 16-bit sign extended immediate constant
299 // load, works in conjunction with its transform function.
300 def v4i32SExt16Imm: PatLeaf<(build_vector), [{
301 return SPU::get_vec_i16imm(N, *CurDAG, MVT::i32).Val != 0;
302 }], v4i32SExt16Imm_xform>;
304 // v4i32Uns18Imm_xform function: convert build_vector to 18-bit unsigned
305 // immediate constant load for v4i32 vectors.
306 def v4i32Uns18Imm_xform: SDNodeXForm<build_vector, [{
307 return SPU::get_vec_u18imm(N, *CurDAG, MVT::i32);
310 // v4i32Uns18Imm: Predicate test for 18-bit unsigned immediate constant load,
311 // works in conjunction with its transform function.
312 def v4i32Uns18Imm: PatLeaf<(build_vector), [{
313 return SPU::get_vec_u18imm(N, *CurDAG, MVT::i32).Val != 0;
314 }], v4i32Uns18Imm_xform>;
316 // ILHUvec_get_imm xform function: convert build_vector to ILHUvec imm constant
318 def ILHUvec_get_imm: SDNodeXForm<build_vector, [{
319 return SPU::get_ILHUvec_imm(N, *CurDAG, MVT::i32);
322 /// immILHUvec: Predicate test for a ILHU constant vector.
323 def immILHUvec: PatLeaf<(build_vector), [{
324 return SPU::get_ILHUvec_imm(N, *CurDAG, MVT::i32).Val != 0;
325 }], ILHUvec_get_imm>;
327 // Catch-all for any other i32 vector constants
328 def v4i32_get_imm: SDNodeXForm<build_vector, [{
329 return SPU::get_v4i32_imm(N, *CurDAG);
332 def v4i32Imm: PatLeaf<(build_vector), [{
333 return SPU::get_v4i32_imm(N, *CurDAG).Val != 0;
336 // v2i64SExt10Imm_xform function: convert build_vector to 10-bit sign extended
337 // immediate constant load for v2i64 vectors.
338 def v2i64SExt10Imm_xform: SDNodeXForm<build_vector, [{
339 return SPU::get_vec_i10imm(N, *CurDAG, MVT::i64);
342 // v2i64SExt10Imm: Predicate test for 10-bit sign extended immediate constant
343 // load, works in conjunction with its transform function.
344 def v2i64SExt10Imm: PatLeaf<(build_vector), [{
345 return SPU::get_vec_i10imm(N, *CurDAG, MVT::i64).Val != 0;
346 }], v2i64SExt10Imm_xform>;
348 // v2i64SExt16Imm_xform function: convert build_vector to 16-bit sign extended
349 // immediate constant load for v2i64 vectors.
350 def v2i64SExt16Imm_xform: SDNodeXForm<build_vector, [{
351 return SPU::get_vec_i16imm(N, *CurDAG, MVT::i64);
354 // v2i64SExt16Imm: Predicate test for 16-bit sign extended immediate constant
355 // load, works in conjunction with its transform function.
356 def v2i64SExt16Imm: PatLeaf<(build_vector), [{
357 return SPU::get_vec_i16imm(N, *CurDAG, MVT::i64).Val != 0;
358 }], v2i64SExt16Imm_xform>;
360 // v2i64Uns18Imm_xform function: convert build_vector to 18-bit unsigned
361 // immediate constant load for v2i64 vectors.
362 def v2i64Uns18Imm_xform: SDNodeXForm<build_vector, [{
363 return SPU::get_vec_u18imm(N, *CurDAG, MVT::i64);
366 // v2i64Uns18Imm: Predicate test for 18-bit unsigned immediate constant load,
367 // works in conjunction with its transform function.
368 def v2i64Uns18Imm: PatLeaf<(build_vector), [{
369 return SPU::get_vec_u18imm(N, *CurDAG, MVT::i64).Val != 0;
370 }], v2i64Uns18Imm_xform>;
372 /// immILHUvec: Predicate test for a ILHU constant vector.
373 def immILHUvec_i64: PatLeaf<(build_vector), [{
374 return SPU::get_ILHUvec_imm(N, *CurDAG, MVT::i64).Val != 0;
375 }], ILHUvec_get_imm>;
377 // Catch-all for any other i32 vector constants
378 def v2i64_get_imm: SDNodeXForm<build_vector, [{
379 return SPU::get_v2i64_imm(N, *CurDAG);
382 def v2i64Imm: PatLeaf<(build_vector), [{
383 return SPU::get_v2i64_imm(N, *CurDAG).Val != 0;
386 //===----------------------------------------------------------------------===//
387 // Operand Definitions.
389 def s7imm: Operand<i16> {
390 let PrintMethod = "printS7ImmOperand";
393 def u7imm: Operand<i16> {
394 let PrintMethod = "printU7ImmOperand";
397 def u7imm_i32: Operand<i32> {
398 let PrintMethod = "printU7ImmOperand";
401 // Halfword, signed 10-bit constant
402 def s10imm : Operand<i16> {
403 let PrintMethod = "printS10ImmOperand";
406 def s10imm_i32: Operand<i32> {
407 let PrintMethod = "printS10ImmOperand";
410 def s10imm_i64: Operand<i64> {
411 let PrintMethod = "printS10ImmOperand";
414 // Unsigned 10-bit integers:
415 def u10imm: Operand<i16> {
416 let PrintMethod = "printU10ImmOperand";
419 def u10imm_i32: Operand<i32> {
420 let PrintMethod = "printU10ImmOperand";
423 def s16imm : Operand<i16> {
424 let PrintMethod = "printS16ImmOperand";
427 def s16imm_i32: Operand<i32> {
428 let PrintMethod = "printS16ImmOperand";
431 def s16imm_i64: Operand<i64> {
432 let PrintMethod = "printS16ImmOperand";
435 def s16imm_f32: Operand<f32> {
436 let PrintMethod = "printS16ImmOperand";
439 def s16imm_f64: Operand<f64> {
440 let PrintMethod = "printS16ImmOperand";
443 def u16imm : Operand<i32> {
444 let PrintMethod = "printU16ImmOperand";
447 def f16imm : Operand<f32> {
448 let PrintMethod = "printU16ImmOperand";
451 def s18imm : Operand<i32> {
452 let PrintMethod = "printS18ImmOperand";
455 def u18imm : Operand<i32> {
456 let PrintMethod = "printU18ImmOperand";
459 def u18imm_i64 : Operand<i64> {
460 let PrintMethod = "printU18ImmOperand";
463 def f18imm : Operand<f32> {
464 let PrintMethod = "printU18ImmOperand";
467 def f18imm_f64 : Operand<f64> {
468 let PrintMethod = "printU18ImmOperand";
471 // Negated 7-bit halfword rotate immediate operands
472 def rothNeg7imm : Operand<i32> {
473 let PrintMethod = "printROTHNeg7Imm";
476 def rothNeg7imm_i16 : Operand<i16> {
477 let PrintMethod = "printROTHNeg7Imm";
480 // Negated 7-bit word rotate immediate operands
481 def rotNeg7imm : Operand<i32> {
482 let PrintMethod = "printROTNeg7Imm";
485 def rotNeg7imm_i16 : Operand<i16> {
486 let PrintMethod = "printROTNeg7Imm";
489 // Floating point immediate operands
490 def f32imm : Operand<f32>;
492 def target : Operand<OtherVT> {
493 let PrintMethod = "printBranchOperand";
496 // Absolute address call target
497 def calltarget : Operand<iPTR> {
498 let PrintMethod = "printCallOperand";
499 let MIOperandInfo = (ops u18imm:$calldest);
502 // Relative call target
503 def relcalltarget : Operand<iPTR> {
504 let PrintMethod = "printPCRelativeOperand";
505 let MIOperandInfo = (ops s16imm:$calldest);
509 def brtarget : Operand<OtherVT> {
510 let PrintMethod = "printPCRelativeOperand";
513 // Indirect call target
514 def indcalltarget : Operand<iPTR> {
515 let PrintMethod = "printCallOperand";
516 let MIOperandInfo = (ops ptr_rc:$calldest);
519 def symbolHi: Operand<i32> {
520 let PrintMethod = "printSymbolHi";
523 def symbolLo: Operand<i32> {
524 let PrintMethod = "printSymbolLo";
527 def symbolLSA: Operand<i32> {
528 let PrintMethod = "printSymbolLSA";
531 // memory s7imm(reg) operaand
532 def memri7 : Operand<iPTR> {
533 let PrintMethod = "printMemRegImmS7";
534 let MIOperandInfo = (ops s7imm:$imm, ptr_rc:$reg);
537 // memory s10imm(reg) operand
538 def memri10 : Operand<iPTR> {
539 let PrintMethod = "printMemRegImmS10";
540 let MIOperandInfo = (ops s10imm:$imm, ptr_rc:$reg);
543 // 256K local store address
544 // N.B.: The tblgen code generator expects to have two operands, an offset
545 // and a pointer. Of these, only the immediate is actually used.
546 def addr256k : Operand<iPTR> {
547 let PrintMethod = "printAddr256K";
548 let MIOperandInfo = (ops s16imm:$imm, ptr_rc:$reg);
551 // memory s18imm(reg) operand
552 def memri18 : Operand<iPTR> {
553 let PrintMethod = "printMemRegImmS18";
554 let MIOperandInfo = (ops s18imm:$imm, ptr_rc:$reg);
557 // memory register + register operand
558 def memrr : Operand<iPTR> {
559 let PrintMethod = "printMemRegReg";
560 let MIOperandInfo = (ops ptr_rc:$reg_a, ptr_rc:$reg_b);
563 // Define SPU-specific addressing modes: These come in three basic
566 // D-form : [r+I10] (10-bit signed offset + reg)
567 // X-form : [r+r] (reg+reg)
568 // A-form : abs (256K LSA offset)
569 // D-form(2): [r+I7] (7-bit signed offset + reg)
571 def dform_addr : ComplexPattern<iPTR, 2, "SelectDFormAddr", [], []>;
572 def xform_addr : ComplexPattern<iPTR, 2, "SelectXFormAddr", [], []>;
573 def aform_addr : ComplexPattern<iPTR, 2, "SelectAFormAddr", [], []>;
574 def dform2_addr : ComplexPattern<iPTR, 2, "SelectDForm2Addr", [], []>;