1//===-- VE.h - Top-level interface for VE representation --------*- C++ -*-===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8//
9// This file contains the entry points for global functions defined in the LLVM
10// VE back-end.
11//
12//===----------------------------------------------------------------------===//
13
14#ifndef LLVM_LIB_TARGET_VE_VE_H
15#define LLVM_LIB_TARGET_VE_VE_H
16
17#include "MCTargetDesc/VEMCTargetDesc.h"
18#include "llvm/ADT/StringSwitch.h"
19#include "llvm/Support/ErrorHandling.h"
20#include "llvm/Target/TargetMachine.h"
21
22namespace llvm {
23class FunctionPass;
24class VETargetMachine;
25class formatted_raw_ostream;
26class AsmPrinter;
27class MCInst;
28class MachineInstr;
29
30FunctionPass *createVEISelDag(VETargetMachine &TM);
31FunctionPass *createVEPromoteToI1Pass();
32FunctionPass *createLVLGenPass();
33
34void LowerVEMachineInstrToMCInst(const MachineInstr *MI, MCInst &OutMI,
35                                 AsmPrinter &AP);
36} // namespace llvm
37
38namespace llvm {
39// Enums corresponding to VE condition codes, both icc's and fcc's.  These
40// values must be kept in sync with the ones in the .td file.
41namespace VECC {
42enum CondCode {
43  // Integer comparison
44  CC_IG = 0,  // Greater
45  CC_IL = 1,  // Less
46  CC_INE = 2, // Not Equal
47  CC_IEQ = 3, // Equal
48  CC_IGE = 4, // Greater or Equal
49  CC_ILE = 5, // Less or Equal
50
51  // Floating point comparison
52  CC_AF = 0 + 6,     // Never
53  CC_G = 1 + 6,      // Greater
54  CC_L = 2 + 6,      // Less
55  CC_NE = 3 + 6,     // Not Equal
56  CC_EQ = 4 + 6,     // Equal
57  CC_GE = 5 + 6,     // Greater or Equal
58  CC_LE = 6 + 6,     // Less or Equal
59  CC_NUM = 7 + 6,    // Number
60  CC_NAN = 8 + 6,    // NaN
61  CC_GNAN = 9 + 6,   // Greater or NaN
62  CC_LNAN = 10 + 6,  // Less or NaN
63  CC_NENAN = 11 + 6, // Not Equal or NaN
64  CC_EQNAN = 12 + 6, // Equal or NaN
65  CC_GENAN = 13 + 6, // Greater or Equal or NaN
66  CC_LENAN = 14 + 6, // Less or Equal or NaN
67  CC_AT = 15 + 6,    // Always
68  UNKNOWN
69};
70}
71// Enums corresponding to VE Rounding Mode.  These values must be kept in
72// sync with the ones in the .td file.
73namespace VERD {
74enum RoundingMode {
75  RD_NONE = 0, // According to PSW
76  RD_RZ = 8,   // Round toward Zero
77  RD_RP = 9,   // Round toward Plus infinity
78  RD_RM = 10,  // Round toward Minus infinity
79  RD_RN = 11,  // Round to Nearest (ties to Even)
80  RD_RA = 12,  // Round to Nearest (ties to Away)
81  UNKNOWN
82};
83}
84
85inline static const char *VECondCodeToString(VECC::CondCode CC) {
86  switch (CC) {
87  case VECC::CC_IG:    return "gt";
88  case VECC::CC_IL:    return "lt";
89  case VECC::CC_INE:   return "ne";
90  case VECC::CC_IEQ:   return "eq";
91  case VECC::CC_IGE:   return "ge";
92  case VECC::CC_ILE:   return "le";
93  case VECC::CC_AF:    return "af";
94  case VECC::CC_G:     return "gt";
95  case VECC::CC_L:     return "lt";
96  case VECC::CC_NE:    return "ne";
97  case VECC::CC_EQ:    return "eq";
98  case VECC::CC_GE:    return "ge";
99  case VECC::CC_LE:    return "le";
100  case VECC::CC_NUM:   return "num";
101  case VECC::CC_NAN:   return "nan";
102  case VECC::CC_GNAN:  return "gtnan";
103  case VECC::CC_LNAN:  return "ltnan";
104  case VECC::CC_NENAN: return "nenan";
105  case VECC::CC_EQNAN: return "eqnan";
106  case VECC::CC_GENAN: return "genan";
107  case VECC::CC_LENAN: return "lenan";
108  case VECC::CC_AT:    return "at";
109  default:
110    llvm_unreachable("Invalid cond code");
111  }
112}
113
114inline static VECC::CondCode stringToVEICondCode(StringRef S) {
115  return StringSwitch<VECC::CondCode>(S)
116      .Case("gt", VECC::CC_IG)
117      .Case("lt", VECC::CC_IL)
118      .Case("ne", VECC::CC_INE)
119      .Case("eq", VECC::CC_IEQ)
120      .Case("ge", VECC::CC_IGE)
121      .Case("le", VECC::CC_ILE)
122      .Case("af", VECC::CC_AF)
123      .Case("at", VECC::CC_AT)
124      .Case("", VECC::CC_AT)
125      .Default(VECC::UNKNOWN);
126}
127
128inline static VECC::CondCode stringToVEFCondCode(StringRef S) {
129  return StringSwitch<VECC::CondCode>(S)
130      .Case("gt", VECC::CC_G)
131      .Case("lt", VECC::CC_L)
132      .Case("ne", VECC::CC_NE)
133      .Case("eq", VECC::CC_EQ)
134      .Case("ge", VECC::CC_GE)
135      .Case("le", VECC::CC_LE)
136      .Case("num", VECC::CC_NUM)
137      .Case("nan", VECC::CC_NAN)
138      .Case("gtnan", VECC::CC_GNAN)
139      .Case("ltnan", VECC::CC_LNAN)
140      .Case("nenan", VECC::CC_NENAN)
141      .Case("eqnan", VECC::CC_EQNAN)
142      .Case("genan", VECC::CC_GENAN)
143      .Case("lenan", VECC::CC_LENAN)
144      .Case("af", VECC::CC_AF)
145      .Case("at", VECC::CC_AT)
146      .Case("", VECC::CC_AT)
147      .Default(VECC::UNKNOWN);
148}
149
150inline static unsigned VECondCodeToVal(VECC::CondCode CC) {
151  switch (CC) {
152  case VECC::CC_IG:
153    return 1;
154  case VECC::CC_IL:
155    return 2;
156  case VECC::CC_INE:
157    return 3;
158  case VECC::CC_IEQ:
159    return 4;
160  case VECC::CC_IGE:
161    return 5;
162  case VECC::CC_ILE:
163    return 6;
164  case VECC::CC_AF:
165    return 0;
166  case VECC::CC_G:
167    return 1;
168  case VECC::CC_L:
169    return 2;
170  case VECC::CC_NE:
171    return 3;
172  case VECC::CC_EQ:
173    return 4;
174  case VECC::CC_GE:
175    return 5;
176  case VECC::CC_LE:
177    return 6;
178  case VECC::CC_NUM:
179    return 7;
180  case VECC::CC_NAN:
181    return 8;
182  case VECC::CC_GNAN:
183    return 9;
184  case VECC::CC_LNAN:
185    return 10;
186  case VECC::CC_NENAN:
187    return 11;
188  case VECC::CC_EQNAN:
189    return 12;
190  case VECC::CC_GENAN:
191    return 13;
192  case VECC::CC_LENAN:
193    return 14;
194  case VECC::CC_AT:
195    return 15;
196  default:
197    llvm_unreachable("Invalid cond code");
198  }
199}
200
201inline static VECC::CondCode VEValToCondCode(unsigned Val, bool IsInteger) {
202  if (IsInteger) {
203    switch (Val) {
204    case 0:
205      return VECC::CC_AF;
206    case 1:
207      return VECC::CC_IG;
208    case 2:
209      return VECC::CC_IL;
210    case 3:
211      return VECC::CC_INE;
212    case 4:
213      return VECC::CC_IEQ;
214    case 5:
215      return VECC::CC_IGE;
216    case 6:
217      return VECC::CC_ILE;
218    case 15:
219      return VECC::CC_AT;
220    }
221  } else {
222    switch (Val) {
223    case 0:
224      return VECC::CC_AF;
225    case 1:
226      return VECC::CC_G;
227    case 2:
228      return VECC::CC_L;
229    case 3:
230      return VECC::CC_NE;
231    case 4:
232      return VECC::CC_EQ;
233    case 5:
234      return VECC::CC_GE;
235    case 6:
236      return VECC::CC_LE;
237    case 7:
238      return VECC::CC_NUM;
239    case 8:
240      return VECC::CC_NAN;
241    case 9:
242      return VECC::CC_GNAN;
243    case 10:
244      return VECC::CC_LNAN;
245    case 11:
246      return VECC::CC_NENAN;
247    case 12:
248      return VECC::CC_EQNAN;
249    case 13:
250      return VECC::CC_GENAN;
251    case 14:
252      return VECC::CC_LENAN;
253    case 15:
254      return VECC::CC_AT;
255    }
256  }
257  llvm_unreachable("Invalid cond code");
258}
259
260inline static const char *VERDToString(VERD::RoundingMode R) {
261  switch (R) {
262  case VERD::RD_NONE:
263    return "";
264  case VERD::RD_RZ:
265    return ".rz";
266  case VERD::RD_RP:
267    return ".rp";
268  case VERD::RD_RM:
269    return ".rm";
270  case VERD::RD_RN:
271    return ".rn";
272  case VERD::RD_RA:
273    return ".ra";
274  default:
275    llvm_unreachable("Invalid branch predicate");
276  }
277}
278
279inline static VERD::RoundingMode stringToVERD(StringRef S) {
280  return StringSwitch<VERD::RoundingMode>(S)
281      .Case("", VERD::RD_NONE)
282      .Case(".rz", VERD::RD_RZ)
283      .Case(".rp", VERD::RD_RP)
284      .Case(".rm", VERD::RD_RM)
285      .Case(".rn", VERD::RD_RN)
286      .Case(".ra", VERD::RD_RA)
287      .Default(VERD::UNKNOWN);
288}
289
290inline static unsigned VERDToVal(VERD::RoundingMode R) {
291  switch (R) {
292  case VERD::RD_NONE:
293  case VERD::RD_RZ:
294  case VERD::RD_RP:
295  case VERD::RD_RM:
296  case VERD::RD_RN:
297  case VERD::RD_RA:
298    return static_cast<unsigned>(R);
299  default:
300    break;
301  }
302  llvm_unreachable("Invalid branch predicates");
303}
304
305inline static VERD::RoundingMode VEValToRD(unsigned Val) {
306  switch (Val) {
307  case static_cast<unsigned>(VERD::RD_NONE):
308    return VERD::RD_NONE;
309  case static_cast<unsigned>(VERD::RD_RZ):
310    return VERD::RD_RZ;
311  case static_cast<unsigned>(VERD::RD_RP):
312    return VERD::RD_RP;
313  case static_cast<unsigned>(VERD::RD_RM):
314    return VERD::RD_RM;
315  case static_cast<unsigned>(VERD::RD_RN):
316    return VERD::RD_RN;
317  case static_cast<unsigned>(VERD::RD_RA):
318    return VERD::RD_RA;
319  default:
320    break;
321  }
322  llvm_unreachable("Invalid branch predicates");
323}
324
325// MImm - Special immediate value of sequential bit stream of 0 or 1.
326//   See VEInstrInfo.td for details.
327inline static bool isMImmVal(uint64_t Val) {
328  if (Val == 0) {
329    // (0)1 is 0
330    return true;
331  }
332  if (isMask_64(Val)) {
333    // (m)0 patterns
334    return true;
335  }
336  // (m)1 patterns
337  return (Val & (UINT64_C(1) << 63)) && isShiftedMask_64(Val);
338}
339
340inline static bool isMImm32Val(uint32_t Val) {
341  if (Val == 0) {
342    // (0)1 is 0
343    return true;
344  }
345  if (isMask_32(Val)) {
346    // (m)0 patterns
347    return true;
348  }
349  // (m)1 patterns
350  return (Val & (UINT32_C(1) << 31)) && isShiftedMask_32(Val);
351}
352
353/// val2MImm - Convert an integer immediate value to target MImm immediate.
354inline static uint64_t val2MImm(uint64_t Val) {
355  if (Val == 0)
356    return 0; // (0)1
357  if (Val & (UINT64_C(1) << 63))
358    return countLeadingOnes(Val);       // (m)1
359  return countLeadingZeros(Val) | 0x40; // (m)0
360}
361
362/// mimm2Val - Convert a target MImm immediate to an integer immediate value.
363inline static uint64_t mimm2Val(uint64_t Val) {
364  if (Val == 0)
365    return 0; // (0)1
366  if ((Val & 0x40) == 0)
367    return (uint64_t)((INT64_C(1) << 63) >> (Val & 0x3f)); // (m)1
368  return ((uint64_t)INT64_C(-1) >> (Val & 0x3f));          // (m)0
369}
370
371inline unsigned M0(unsigned Val) { return Val + 64; }
372inline unsigned M1(unsigned Val) { return Val; }
373
374} // namespace llvm
375#endif
376