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