1 // Copyright 2021 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #ifndef V8_CODEGEN_LOONG64_CONSTANTS_LOONG64_H_
6 #define V8_CODEGEN_LOONG64_CONSTANTS_LOONG64_H_
7
8 #include "src/base/logging.h"
9 #include "src/base/macros.h"
10 #include "src/common/globals.h"
11
12 // Get the standard printf format macros for C99 stdint types.
13 #ifndef __STDC_FORMAT_MACROS
14 #define __STDC_FORMAT_MACROS
15 #endif
16 #include <inttypes.h>
17
18 // Defines constants and accessor classes to assemble, disassemble and
19 // simulate LOONG64 instructions.
20
21 namespace v8 {
22 namespace internal {
23
24 constexpr size_t kMaxPCRelativeCodeRangeInMB = 128;
25
26 // -----------------------------------------------------------------------------
27 // Registers and FPURegisters.
28
29 // Number of general purpose registers.
30 const int kNumRegisters = 32;
31 const int kInvalidRegister = -1;
32
33 // Number of registers with pc.
34 const int kNumSimuRegisters = 33;
35
36 // In the simulator, the PC register is simulated as the 33th register.
37 const int kPCRegister = 32;
38
39 // Number of floating point registers.
40 const int kNumFPURegisters = 32;
41 const int kInvalidFPURegister = -1;
42
43 // FPU control registers.
44 const int kFCSRRegister = 0;
45 const int kInvalidFPUControlRegister = -1;
46 const uint32_t kFPUInvalidResult = static_cast<uint32_t>(1u << 31) - 1;
47 const int32_t kFPUInvalidResultNegative = static_cast<int32_t>(1u << 31);
48 const uint64_t kFPU64InvalidResult =
49 static_cast<uint64_t>(static_cast<uint64_t>(1) << 63) - 1;
50 const int64_t kFPU64InvalidResultNegative =
51 static_cast<int64_t>(static_cast<uint64_t>(1) << 63);
52
53 // FCSR constants.
54 const uint32_t kFCSRInexactCauseBit = 24;
55 const uint32_t kFCSRUnderflowCauseBit = 25;
56 const uint32_t kFCSROverflowCauseBit = 26;
57 const uint32_t kFCSRDivideByZeroCauseBit = 27;
58 const uint32_t kFCSRInvalidOpCauseBit = 28;
59
60 const uint32_t kFCSRInexactCauseMask = 1 << kFCSRInexactCauseBit;
61 const uint32_t kFCSRUnderflowCauseMask = 1 << kFCSRUnderflowCauseBit;
62 const uint32_t kFCSROverflowCauseMask = 1 << kFCSROverflowCauseBit;
63 const uint32_t kFCSRDivideByZeroCauseMask = 1 << kFCSRDivideByZeroCauseBit;
64 const uint32_t kFCSRInvalidOpCauseMask = 1 << kFCSRInvalidOpCauseBit;
65
66 const uint32_t kFCSRCauseMask =
67 kFCSRInexactCauseMask | kFCSRUnderflowCauseMask | kFCSROverflowCauseMask |
68 kFCSRDivideByZeroCauseMask | kFCSRInvalidOpCauseMask;
69
70 const uint32_t kFCSRExceptionCauseMask = kFCSRCauseMask ^ kFCSRInexactCauseMask;
71
72 // Actual value of root register is offset from the root array's start
73 // to take advantage of negative displacement values.
74 // TODO(sigurds): Choose best value.
75 constexpr int kRootRegisterBias = 256;
76
77 // Helper functions for converting between register numbers and names.
78 class Registers {
79 public:
80 // Return the name of the register.
81 static const char* Name(int reg);
82
83 // Lookup the register number for the name provided.
84 static int Number(const char* name);
85
86 struct RegisterAlias {
87 int reg;
88 const char* name;
89 };
90
91 static const int64_t kMaxValue = 0x7fffffffffffffffl;
92 static const int64_t kMinValue = 0x8000000000000000l;
93
94 private:
95 static const char* names_[kNumSimuRegisters];
96 static const RegisterAlias aliases_[];
97 };
98
99 // Helper functions for converting between register numbers and names.
100 class FPURegisters {
101 public:
102 // Return the name of the register.
103 static const char* Name(int reg);
104
105 // Lookup the register number for the name provided.
106 static int Number(const char* name);
107
108 struct RegisterAlias {
109 int creg;
110 const char* name;
111 };
112
113 private:
114 static const char* names_[kNumFPURegisters];
115 static const RegisterAlias aliases_[];
116 };
117
118 // -----------------------------------------------------------------------------
119 // Instructions encoding constants.
120
121 // On LoongArch all instructions are 32 bits.
122 using Instr = int32_t;
123
124 // Special Software Interrupt codes when used in the presence of the LOONG64
125 // simulator.
126 enum SoftwareInterruptCodes {
127 // Transition to C code.
128 call_rt_redirected = 0x7fff
129 };
130
131 // On LOONG64 Simulator breakpoints can have different codes:
132 // - Breaks between 0 and kMaxWatchpointCode are treated as simple watchpoints,
133 // the simulator will run through them and print the registers.
134 // - Breaks between kMaxWatchpointCode and kMaxStopCode are treated as stop()
135 // instructions (see Assembler::stop()).
136 // - Breaks larger than kMaxStopCode are simple breaks, dropping you into the
137 // debugger.
138 const uint32_t kMaxWatchpointCode = 31;
139 const uint32_t kMaxStopCode = 127;
140 STATIC_ASSERT(kMaxWatchpointCode < kMaxStopCode);
141
142 // ----- Fields offset and length.
143 const int kRjShift = 5;
144 const int kRjBits = 5;
145 const int kRkShift = 10;
146 const int kRkBits = 5;
147 const int kRdShift = 0;
148 const int kRdBits = 5;
149 const int kSaShift = 15;
150 const int kSa2Bits = 2;
151 const int kSa3Bits = 3;
152 const int kCdShift = 0;
153 const int kCdBits = 3;
154 const int kCjShift = 5;
155 const int kCjBits = 3;
156 const int kCodeShift = 0;
157 const int kCodeBits = 15;
158 const int kCondShift = 15;
159 const int kCondBits = 5;
160 const int kUi5Shift = 10;
161 const int kUi5Bits = 5;
162 const int kUi6Shift = 10;
163 const int kUi6Bits = 6;
164 const int kUi12Shift = 10;
165 const int kUi12Bits = 12;
166 const int kSi12Shift = 10;
167 const int kSi12Bits = 12;
168 const int kSi14Shift = 10;
169 const int kSi14Bits = 14;
170 const int kSi16Shift = 10;
171 const int kSi16Bits = 16;
172 const int kSi20Shift = 5;
173 const int kSi20Bits = 20;
174 const int kMsbwShift = 16;
175 const int kMsbwBits = 5;
176 const int kLsbwShift = 10;
177 const int kLsbwBits = 5;
178 const int kMsbdShift = 16;
179 const int kMsbdBits = 6;
180 const int kLsbdShift = 10;
181 const int kLsbdBits = 6;
182 const int kFdShift = 0;
183 const int kFdBits = 5;
184 const int kFjShift = 5;
185 const int kFjBits = 5;
186 const int kFkShift = 10;
187 const int kFkBits = 5;
188 const int kFaShift = 15;
189 const int kFaBits = 5;
190 const int kCaShift = 15;
191 const int kCaBits = 3;
192 const int kHint15Shift = 0;
193 const int kHint15Bits = 15;
194 const int kHint5Shift = 0;
195 const int kHint5Bits = 5;
196 const int kOffsLowShift = 10;
197 const int kOffsLowBits = 16;
198 const int kOffs26HighShift = 0;
199 const int kOffs26HighBits = 10;
200 const int kOffs21HighShift = 0;
201 const int kOffs21HighBits = 5;
202 const int kImm12Shift = 0;
203 const int kImm12Bits = 12;
204 const int kImm16Shift = 0;
205 const int kImm16Bits = 16;
206 const int kImm26Shift = 0;
207 const int kImm26Bits = 26;
208 const int kImm28Shift = 0;
209 const int kImm28Bits = 28;
210 const int kImm32Shift = 0;
211 const int kImm32Bits = 32;
212
213 // ----- Miscellaneous useful masks.
214 // Instruction bit masks.
215 const int kRjFieldMask = ((1 << kRjBits) - 1) << kRjShift;
216 const int kRkFieldMask = ((1 << kRkBits) - 1) << kRkShift;
217 const int kRdFieldMask = ((1 << kRdBits) - 1) << kRdShift;
218 const int kSa2FieldMask = ((1 << kSa2Bits) - 1) << kSaShift;
219 const int kSa3FieldMask = ((1 << kSa3Bits) - 1) << kSaShift;
220 // Misc masks.
221 const int kHiMaskOf32 = 0xffff << 16; // Only to be used with 32-bit values
222 const int kLoMaskOf32 = 0xffff;
223 const int kSignMaskOf32 = 0x80000000; // Only to be used with 32-bit values
224 const int64_t kTop16MaskOf64 = (int64_t)0xffff << 48;
225 const int64_t kHigher16MaskOf64 = (int64_t)0xffff << 32;
226 const int64_t kUpper16MaskOf64 = (int64_t)0xffff << 16;
227
228 const int kImm12Mask = ((1 << kImm12Bits) - 1) << kImm12Shift;
229 const int kImm16Mask = ((1 << kImm16Bits) - 1) << kImm16Shift;
230 const int kImm26Mask = ((1 << kImm26Bits) - 1) << kImm26Shift;
231 const int kImm28Mask = ((1 << kImm28Bits) - 1) << kImm28Shift;
232
233 // ----- LOONG64 Opcodes and Function Fields.
234 enum Opcode : uint32_t {
235 BEQZ = 0x10U << 26,
236 BNEZ = 0x11U << 26,
237 BCZ = 0x12U << 26, // BCEQZ & BCNEZ
238 JIRL = 0x13U << 26,
239 B = 0x14U << 26,
240 BL = 0x15U << 26,
241 BEQ = 0x16U << 26,
242 BNE = 0x17U << 26,
243 BLT = 0x18U << 26,
244 BGE = 0x19U << 26,
245 BLTU = 0x1aU << 26,
246 BGEU = 0x1bU << 26,
247
248 ADDU16I_D = 0x4U << 26,
249
250 LU12I_W = 0xaU << 25,
251 LU32I_D = 0xbU << 25,
252 PCADDI = 0xcU << 25,
253 PCALAU12I = 0xdU << 25,
254 PCADDU12I = 0xeU << 25,
255 PCADDU18I = 0xfU << 25,
256
257 LL_W = 0x20U << 24,
258 SC_W = 0x21U << 24,
259 LL_D = 0x22U << 24,
260 SC_D = 0x23U << 24,
261 LDPTR_W = 0x24U << 24,
262 STPTR_W = 0x25U << 24,
263 LDPTR_D = 0x26U << 24,
264 STPTR_D = 0x27U << 24,
265
266 BSTR_W = 0x1U << 22, // BSTRINS_W & BSTRPICK_W
267 BSTRINS_W = BSTR_W,
268 BSTRPICK_W = BSTR_W,
269 BSTRINS_D = 0x2U << 22,
270 BSTRPICK_D = 0x3U << 22,
271
272 SLTI = 0x8U << 22,
273 SLTUI = 0x9U << 22,
274 ADDI_W = 0xaU << 22,
275 ADDI_D = 0xbU << 22,
276 LU52I_D = 0xcU << 22,
277 ANDI = 0xdU << 22,
278 ORI = 0xeU << 22,
279 XORI = 0xfU << 22,
280
281 LD_B = 0xa0U << 22,
282 LD_H = 0xa1U << 22,
283 LD_W = 0xa2U << 22,
284 LD_D = 0xa3U << 22,
285 ST_B = 0xa4U << 22,
286 ST_H = 0xa5U << 22,
287 ST_W = 0xa6U << 22,
288 ST_D = 0xa7U << 22,
289 LD_BU = 0xa8U << 22,
290 LD_HU = 0xa9U << 22,
291 LD_WU = 0xaaU << 22,
292 FLD_S = 0xacU << 22,
293 FST_S = 0xadU << 22,
294 FLD_D = 0xaeU << 22,
295 FST_D = 0xafU << 22,
296
297 FMADD_S = 0x81U << 20,
298 FMADD_D = 0x82U << 20,
299 FMSUB_S = 0x85U << 20,
300 FMSUB_D = 0x86U << 20,
301 FNMADD_S = 0x89U << 20,
302 FNMADD_D = 0x8aU << 20,
303 FNMSUB_S = 0x8dU << 20,
304 FNMSUB_D = 0x8eU << 20,
305 FCMP_COND_S = 0xc1U << 20,
306 FCMP_COND_D = 0xc2U << 20,
307
308 BYTEPICK_D = 0x3U << 18,
309 BYTEPICK_W = 0x2U << 18,
310
311 FSEL = 0x340U << 18,
312
313 ALSL = 0x1U << 18,
314 ALSL_W = ALSL,
315 ALSL_WU = ALSL,
316
317 ALSL_D = 0xbU << 18,
318
319 SLLI_W = 0x40U << 16,
320 SRLI_W = 0x44U << 16,
321 SRAI_W = 0x48U << 16,
322 ROTRI_W = 0x4cU << 16,
323
324 SLLI_D = 0x41U << 16,
325 SRLI_D = 0x45U << 16,
326 SRAI_D = 0x49U << 16,
327 ROTRI_D = 0x4dU << 16,
328
329 SLLI = 0x10U << 18,
330 SRLI = 0x11U << 18,
331 SRAI = 0x12U << 18,
332 ROTRI = 0x13U << 18,
333
334 ADD_W = 0x20U << 15,
335 ADD_D = 0x21U << 15,
336 SUB_W = 0x22U << 15,
337 SUB_D = 0x23U << 15,
338 SLT = 0x24U << 15,
339 SLTU = 0x25U << 15,
340 MASKEQZ = 0x26U << 15,
341 MASKNEZ = 0x27U << 15,
342 NOR = 0x28U << 15,
343 AND = 0x29U << 15,
344 OR = 0x2aU << 15,
345 XOR = 0x2bU << 15,
346 ORN = 0x2cU << 15,
347 ANDN = 0x2dU << 15,
348 SLL_W = 0x2eU << 15,
349 SRL_W = 0x2fU << 15,
350 SRA_W = 0x30U << 15,
351 SLL_D = 0x31U << 15,
352 SRL_D = 0x32U << 15,
353 SRA_D = 0x33U << 15,
354 ROTR_W = 0x36U << 15,
355 ROTR_D = 0x37U << 15,
356 MUL_W = 0x38U << 15,
357 MULH_W = 0x39U << 15,
358 MULH_WU = 0x3aU << 15,
359 MUL_D = 0x3bU << 15,
360 MULH_D = 0x3cU << 15,
361 MULH_DU = 0x3dU << 15,
362 MULW_D_W = 0x3eU << 15,
363 MULW_D_WU = 0x3fU << 15,
364
365 DIV_W = 0x40U << 15,
366 MOD_W = 0x41U << 15,
367 DIV_WU = 0x42U << 15,
368 MOD_WU = 0x43U << 15,
369 DIV_D = 0x44U << 15,
370 MOD_D = 0x45U << 15,
371 DIV_DU = 0x46U << 15,
372 MOD_DU = 0x47U << 15,
373
374 BREAK = 0x54U << 15,
375
376 FADD_S = 0x201U << 15,
377 FADD_D = 0x202U << 15,
378 FSUB_S = 0x205U << 15,
379 FSUB_D = 0x206U << 15,
380 FMUL_S = 0x209U << 15,
381 FMUL_D = 0x20aU << 15,
382 FDIV_S = 0x20dU << 15,
383 FDIV_D = 0x20eU << 15,
384 FMAX_S = 0x211U << 15,
385 FMAX_D = 0x212U << 15,
386 FMIN_S = 0x215U << 15,
387 FMIN_D = 0x216U << 15,
388 FMAXA_S = 0x219U << 15,
389 FMAXA_D = 0x21aU << 15,
390 FMINA_S = 0x21dU << 15,
391 FMINA_D = 0x21eU << 15,
392 FSCALEB_S = 0x221U << 15,
393 FSCALEB_D = 0x222U << 15,
394 FCOPYSIGN_S = 0x225U << 15,
395 FCOPYSIGN_D = 0x226U << 15,
396
397 LDX_B = 0x7000U << 15,
398 LDX_H = 0x7008U << 15,
399 LDX_W = 0x7010U << 15,
400 LDX_D = 0x7018U << 15,
401 STX_B = 0x7020U << 15,
402 STX_H = 0x7028U << 15,
403 STX_W = 0x7030U << 15,
404 STX_D = 0x7038U << 15,
405 LDX_BU = 0x7040U << 15,
406 LDX_HU = 0x7048U << 15,
407 LDX_WU = 0x7050U << 15,
408 FLDX_S = 0x7060U << 15,
409 FLDX_D = 0x7068U << 15,
410 FSTX_S = 0x7070U << 15,
411 FSTX_D = 0x7078U << 15,
412
413 AMSWAP_W = 0x70c0U << 15,
414 AMSWAP_D = 0x70c1U << 15,
415 AMADD_W = 0x70c2U << 15,
416 AMADD_D = 0x70c3U << 15,
417 AMAND_W = 0x70c4U << 15,
418 AMAND_D = 0x70c5U << 15,
419 AMOR_W = 0x70c6U << 15,
420 AMOR_D = 0x70c7U << 15,
421 AMXOR_W = 0x70c8U << 15,
422 AMXOR_D = 0x70c9U << 15,
423 AMMAX_W = 0x70caU << 15,
424 AMMAX_D = 0x70cbU << 15,
425 AMMIN_W = 0x70ccU << 15,
426 AMMIN_D = 0x70cdU << 15,
427 AMMAX_WU = 0x70ceU << 15,
428 AMMAX_DU = 0x70cfU << 15,
429 AMMIN_WU = 0x70d0U << 15,
430 AMMIN_DU = 0x70d1U << 15,
431 AMSWAP_DB_W = 0x70d2U << 15,
432 AMSWAP_DB_D = 0x70d3U << 15,
433 AMADD_DB_W = 0x70d4U << 15,
434 AMADD_DB_D = 0x70d5U << 15,
435 AMAND_DB_W = 0x70d6U << 15,
436 AMAND_DB_D = 0x70d7U << 15,
437 AMOR_DB_W = 0x70d8U << 15,
438 AMOR_DB_D = 0x70d9U << 15,
439 AMXOR_DB_W = 0x70daU << 15,
440 AMXOR_DB_D = 0x70dbU << 15,
441 AMMAX_DB_W = 0x70dcU << 15,
442 AMMAX_DB_D = 0x70ddU << 15,
443 AMMIN_DB_W = 0x70deU << 15,
444 AMMIN_DB_D = 0x70dfU << 15,
445 AMMAX_DB_WU = 0x70e0U << 15,
446 AMMAX_DB_DU = 0x70e1U << 15,
447 AMMIN_DB_WU = 0x70e2U << 15,
448 AMMIN_DB_DU = 0x70e3U << 15,
449
450 DBAR = 0x70e4U << 15,
451 IBAR = 0x70e5U << 15,
452
453 CLO_W = 0X4U << 10,
454 CLZ_W = 0X5U << 10,
455 CTO_W = 0X6U << 10,
456 CTZ_W = 0X7U << 10,
457 CLO_D = 0X8U << 10,
458 CLZ_D = 0X9U << 10,
459 CTO_D = 0XaU << 10,
460 CTZ_D = 0XbU << 10,
461 REVB_2H = 0XcU << 10,
462 REVB_4H = 0XdU << 10,
463 REVB_2W = 0XeU << 10,
464 REVB_D = 0XfU << 10,
465 REVH_2W = 0X10U << 10,
466 REVH_D = 0X11U << 10,
467 BITREV_4B = 0X12U << 10,
468 BITREV_8B = 0X13U << 10,
469 BITREV_W = 0X14U << 10,
470 BITREV_D = 0X15U << 10,
471 EXT_W_H = 0X16U << 10,
472 EXT_W_B = 0X17U << 10,
473
474 FABS_S = 0X4501U << 10,
475 FABS_D = 0X4502U << 10,
476 FNEG_S = 0X4505U << 10,
477 FNEG_D = 0X4506U << 10,
478 FLOGB_S = 0X4509U << 10,
479 FLOGB_D = 0X450aU << 10,
480 FCLASS_S = 0X450dU << 10,
481 FCLASS_D = 0X450eU << 10,
482 FSQRT_S = 0X4511U << 10,
483 FSQRT_D = 0X4512U << 10,
484 FRECIP_S = 0X4515U << 10,
485 FRECIP_D = 0X4516U << 10,
486 FRSQRT_S = 0X4519U << 10,
487 FRSQRT_D = 0X451aU << 10,
488 FMOV_S = 0X4525U << 10,
489 FMOV_D = 0X4526U << 10,
490 MOVGR2FR_W = 0X4529U << 10,
491 MOVGR2FR_D = 0X452aU << 10,
492 MOVGR2FRH_W = 0X452bU << 10,
493 MOVFR2GR_S = 0X452dU << 10,
494 MOVFR2GR_D = 0X452eU << 10,
495 MOVFRH2GR_S = 0X452fU << 10,
496 MOVGR2FCSR = 0X4530U << 10,
497 MOVFCSR2GR = 0X4532U << 10,
498 MOVFR2CF = 0X4534U << 10,
499 MOVGR2CF = 0X4536U << 10,
500
501 FCVT_S_D = 0x4646U << 10,
502 FCVT_D_S = 0x4649U << 10,
503 FTINTRM_W_S = 0x4681U << 10,
504 FTINTRM_W_D = 0x4682U << 10,
505 FTINTRM_L_S = 0x4689U << 10,
506 FTINTRM_L_D = 0x468aU << 10,
507 FTINTRP_W_S = 0x4691U << 10,
508 FTINTRP_W_D = 0x4692U << 10,
509 FTINTRP_L_S = 0x4699U << 10,
510 FTINTRP_L_D = 0x469aU << 10,
511 FTINTRZ_W_S = 0x46a1U << 10,
512 FTINTRZ_W_D = 0x46a2U << 10,
513 FTINTRZ_L_S = 0x46a9U << 10,
514 FTINTRZ_L_D = 0x46aaU << 10,
515 FTINTRNE_W_S = 0x46b1U << 10,
516 FTINTRNE_W_D = 0x46b2U << 10,
517 FTINTRNE_L_S = 0x46b9U << 10,
518 FTINTRNE_L_D = 0x46baU << 10,
519 FTINT_W_S = 0x46c1U << 10,
520 FTINT_W_D = 0x46c2U << 10,
521 FTINT_L_S = 0x46c9U << 10,
522 FTINT_L_D = 0x46caU << 10,
523 FFINT_S_W = 0x4744U << 10,
524 FFINT_S_L = 0x4746U << 10,
525 FFINT_D_W = 0x4748U << 10,
526 FFINT_D_L = 0x474aU << 10,
527 FRINT_S = 0x4791U << 10,
528 FRINT_D = 0x4792U << 10,
529
530 MOVCF2FR = 0x4535U << 10,
531 MOVCF2GR = 0x4537U << 10
532 };
533
534 // ----- Emulated conditions.
535 // On LOONG64 we use this enum to abstract from conditional branch instructions.
536 // The 'U' prefix is used to specify unsigned comparisons.
537 enum Condition {
538 // Any value < 0 is considered no_condition.
539 kNoCondition = -1,
540 overflow = 0,
541 no_overflow = 1,
542 Uless = 2,
543 Ugreater_equal = 3,
544 Uless_equal = 4,
545 Ugreater = 5,
546 equal = 6,
547 not_equal = 7, // Unordered or Not Equal.
548 negative = 8,
549 positive = 9,
550 parity_even = 10,
551 parity_odd = 11,
552 less = 12,
553 greater_equal = 13,
554 less_equal = 14,
555 greater = 15,
556 ueq = 16, // Unordered or Equal.
557 ogl = 17, // Ordered and Not Equal.
558 cc_always = 18,
559
560 // Aliases.
561 carry = Uless,
562 not_carry = Ugreater_equal,
563 zero = equal,
564 eq = equal,
565 not_zero = not_equal,
566 ne = not_equal,
567 nz = not_equal,
568 sign = negative,
569 not_sign = positive,
570 mi = negative,
571 pl = positive,
572 hi = Ugreater,
573 ls = Uless_equal,
574 ge = greater_equal,
575 lt = less,
576 gt = greater,
577 le = less_equal,
578 hs = Ugreater_equal,
579 lo = Uless,
580 al = cc_always,
581 ult = Uless,
582 uge = Ugreater_equal,
583 ule = Uless_equal,
584 ugt = Ugreater,
585 cc_default = kNoCondition
586 };
587
588 // Returns the equivalent of !cc.
589 // Negation of the default kNoCondition (-1) results in a non-default
590 // no_condition value (-2). As long as tests for no_condition check
591 // for condition < 0, this will work as expected.
NegateCondition(Condition cc)592 inline Condition NegateCondition(Condition cc) {
593 DCHECK(cc != cc_always);
594 return static_cast<Condition>(cc ^ 1);
595 }
596
NegateFpuCondition(Condition cc)597 inline Condition NegateFpuCondition(Condition cc) {
598 DCHECK(cc != cc_always);
599 switch (cc) {
600 case ult:
601 return ge;
602 case ugt:
603 return le;
604 case uge:
605 return lt;
606 case ule:
607 return gt;
608 case lt:
609 return uge;
610 case gt:
611 return ule;
612 case ge:
613 return ult;
614 case le:
615 return ugt;
616 case eq:
617 return ne;
618 case ne:
619 return eq;
620 case ueq:
621 return ogl;
622 case ogl:
623 return ueq;
624 default:
625 return cc;
626 }
627 }
628
629 // ----- Coprocessor conditions.
630 enum FPUCondition {
631 kNoFPUCondition = -1,
632
633 CAF = 0x00, // False.
634 SAF = 0x01, // False.
635 CLT = 0x02, // Less Than quiet
636 // SLT = 0x03, // Less Than signaling
637 CEQ = 0x04,
638 SEQ = 0x05,
639 CLE = 0x06,
640 SLE = 0x07,
641 CUN = 0x08,
642 SUN = 0x09,
643 CULT = 0x0a,
644 SULT = 0x0b,
645 CUEQ = 0x0c,
646 SUEQ = 0x0d,
647 CULE = 0x0e,
648 SULE = 0x0f,
649 CNE = 0x10,
650 SNE = 0x11,
651 COR = 0x14,
652 SOR = 0x15,
653 CUNE = 0x18,
654 SUNE = 0x19,
655 };
656
657 const uint32_t kFPURoundingModeShift = 8;
658 const uint32_t kFPURoundingModeMask = 0b11 << kFPURoundingModeShift;
659
660 // FPU rounding modes.
661 enum FPURoundingMode {
662 RN = 0b00 << kFPURoundingModeShift, // Round to Nearest.
663 RZ = 0b01 << kFPURoundingModeShift, // Round towards zero.
664 RP = 0b10 << kFPURoundingModeShift, // Round towards Plus Infinity.
665 RM = 0b11 << kFPURoundingModeShift, // Round towards Minus Infinity.
666
667 // Aliases.
668 kRoundToNearest = RN,
669 kRoundToZero = RZ,
670 kRoundToPlusInf = RP,
671 kRoundToMinusInf = RM,
672
673 mode_round = RN,
674 mode_ceil = RP,
675 mode_floor = RM,
676 mode_trunc = RZ
677 };
678
679 enum CheckForInexactConversion {
680 kCheckForInexactConversion,
681 kDontCheckForInexactConversion
682 };
683
684 enum class MaxMinKind : int { kMin = 0, kMax = 1 };
685
686 // -----------------------------------------------------------------------------
687 // Hints.
688
689 // Branch hints are not used on the LOONG64. They are defined so that they can
690 // appear in shared function signatures, but will be ignored in LOONG64
691 // implementations.
692 enum Hint { no_hint = 0 };
693
NegateHint(Hint hint)694 inline Hint NegateHint(Hint hint) { return no_hint; }
695
696 // -----------------------------------------------------------------------------
697 // Specific instructions, constants, and masks.
698 // These constants are declared in assembler-loong64.cc, as they use named
699 // registers and other constants.
700
701 // Break 0xfffff, reserved for redirected real time call.
702 const Instr rtCallRedirInstr = BREAK | call_rt_redirected;
703 // A nop instruction. (Encoding of addi_w 0 0 0).
704 const Instr nopInstr = ADDI_W;
705
706 constexpr uint8_t kInstrSize = 4;
707 constexpr uint8_t kInstrSizeLog2 = 2;
708
709 class InstructionBase {
710 public:
711 enum Type {
712 kOp6Type,
713 kOp7Type,
714 kOp8Type,
715 kOp10Type,
716 kOp12Type,
717 kOp14Type,
718 kOp17Type,
719 kOp22Type,
720 kUnsupported = -1
721 };
722
723 // Get the raw instruction bits.
InstructionBits()724 inline Instr InstructionBits() const {
725 return *reinterpret_cast<const Instr*>(this);
726 }
727
728 // Set the raw instruction bits to value.
SetInstructionBits(Instr value)729 inline void SetInstructionBits(Instr value) {
730 *reinterpret_cast<Instr*>(this) = value;
731 }
732
733 // Read one particular bit out of the instruction bits.
Bit(int nr)734 inline int Bit(int nr) const { return (InstructionBits() >> nr) & 1; }
735
736 // Read a bit field out of the instruction bits.
Bits(int hi,int lo)737 inline int Bits(int hi, int lo) const {
738 return (InstructionBits() >> lo) & ((2U << (hi - lo)) - 1);
739 }
740
741 // Safe to call within InstructionType().
RjFieldRawNoAssert()742 inline int RjFieldRawNoAssert() const {
743 return InstructionBits() & kRjFieldMask;
744 }
745
746 // Get the encoding type of the instruction.
747 inline Type InstructionType() const;
748
749 protected:
InstructionBase()750 InstructionBase() {}
751 };
752
753 template <class T>
754 class InstructionGetters : public T {
755 public:
RjValue()756 inline int RjValue() const {
757 return this->Bits(kRjShift + kRjBits - 1, kRjShift);
758 }
759
RkValue()760 inline int RkValue() const {
761 return this->Bits(kRkShift + kRkBits - 1, kRkShift);
762 }
763
RdValue()764 inline int RdValue() const {
765 return this->Bits(kRdShift + kRdBits - 1, kRdShift);
766 }
767
Sa2Value()768 inline int Sa2Value() const {
769 return this->Bits(kSaShift + kSa2Bits - 1, kSaShift);
770 }
771
Sa3Value()772 inline int Sa3Value() const {
773 return this->Bits(kSaShift + kSa3Bits - 1, kSaShift);
774 }
775
Ui5Value()776 inline int Ui5Value() const {
777 return this->Bits(kUi5Shift + kUi5Bits - 1, kUi5Shift);
778 }
779
Ui6Value()780 inline int Ui6Value() const {
781 return this->Bits(kUi6Shift + kUi6Bits - 1, kUi6Shift);
782 }
783
Ui12Value()784 inline int Ui12Value() const {
785 return this->Bits(kUi12Shift + kUi12Bits - 1, kUi12Shift);
786 }
787
LsbwValue()788 inline int LsbwValue() const {
789 return this->Bits(kLsbwShift + kLsbwBits - 1, kLsbwShift);
790 }
791
MsbwValue()792 inline int MsbwValue() const {
793 return this->Bits(kMsbwShift + kMsbwBits - 1, kMsbwShift);
794 }
795
LsbdValue()796 inline int LsbdValue() const {
797 return this->Bits(kLsbdShift + kLsbdBits - 1, kLsbdShift);
798 }
799
MsbdValue()800 inline int MsbdValue() const {
801 return this->Bits(kMsbdShift + kMsbdBits - 1, kMsbdShift);
802 }
803
CondValue()804 inline int CondValue() const {
805 return this->Bits(kCondShift + kCondBits - 1, kCondShift);
806 }
807
Si12Value()808 inline int Si12Value() const {
809 return this->Bits(kSi12Shift + kSi12Bits - 1, kSi12Shift);
810 }
811
Si14Value()812 inline int Si14Value() const {
813 return this->Bits(kSi14Shift + kSi14Bits - 1, kSi14Shift);
814 }
815
Si16Value()816 inline int Si16Value() const {
817 return this->Bits(kSi16Shift + kSi16Bits - 1, kSi16Shift);
818 }
819
Si20Value()820 inline int Si20Value() const {
821 return this->Bits(kSi20Shift + kSi20Bits - 1, kSi20Shift);
822 }
823
FdValue()824 inline int FdValue() const {
825 return this->Bits(kFdShift + kFdBits - 1, kFdShift);
826 }
827
FaValue()828 inline int FaValue() const {
829 return this->Bits(kFaShift + kFaBits - 1, kFaShift);
830 }
831
FjValue()832 inline int FjValue() const {
833 return this->Bits(kFjShift + kFjBits - 1, kFjShift);
834 }
835
FkValue()836 inline int FkValue() const {
837 return this->Bits(kFkShift + kFkBits - 1, kFkShift);
838 }
839
CjValue()840 inline int CjValue() const {
841 return this->Bits(kCjShift + kCjBits - 1, kCjShift);
842 }
843
CdValue()844 inline int CdValue() const {
845 return this->Bits(kCdShift + kCdBits - 1, kCdShift);
846 }
847
CaValue()848 inline int CaValue() const {
849 return this->Bits(kCaShift + kCaBits - 1, kCaShift);
850 }
851
CodeValue()852 inline int CodeValue() const {
853 return this->Bits(kCodeShift + kCodeBits - 1, kCodeShift);
854 }
855
Hint5Value()856 inline int Hint5Value() const {
857 return this->Bits(kHint5Shift + kHint5Bits - 1, kHint5Shift);
858 }
859
Hint15Value()860 inline int Hint15Value() const {
861 return this->Bits(kHint15Shift + kHint15Bits - 1, kHint15Shift);
862 }
863
Offs16Value()864 inline int Offs16Value() const {
865 return this->Bits(kOffsLowShift + kOffsLowBits - 1, kOffsLowShift);
866 }
867
Offs21Value()868 inline int Offs21Value() const {
869 int low = this->Bits(kOffsLowShift + kOffsLowBits - 1, kOffsLowShift);
870 int high =
871 this->Bits(kOffs21HighShift + kOffs21HighBits - 1, kOffs21HighShift);
872 return ((high << kOffsLowBits) + low);
873 }
874
Offs26Value()875 inline int Offs26Value() const {
876 int low = this->Bits(kOffsLowShift + kOffsLowBits - 1, kOffsLowShift);
877 int high =
878 this->Bits(kOffs26HighShift + kOffs26HighBits - 1, kOffs26HighShift);
879 return ((high << kOffsLowBits) + low);
880 }
881
RjFieldRaw()882 inline int RjFieldRaw() const {
883 return this->InstructionBits() & kRjFieldMask;
884 }
885
RkFieldRaw()886 inline int RkFieldRaw() const {
887 return this->InstructionBits() & kRkFieldMask;
888 }
889
RdFieldRaw()890 inline int RdFieldRaw() const {
891 return this->InstructionBits() & kRdFieldMask;
892 }
893
ImmValue(int bits)894 inline int32_t ImmValue(int bits) const { return this->Bits(bits - 1, 0); }
895
896 /*TODO*/
Imm12Value()897 inline int32_t Imm12Value() const { abort(); }
898
Imm14Value()899 inline int32_t Imm14Value() const { abort(); }
900
Imm16Value()901 inline int32_t Imm16Value() const { abort(); }
902
903 // Say if the instruction is a break.
904 bool IsTrap() const;
905 };
906
907 class Instruction : public InstructionGetters<InstructionBase> {
908 public:
909 // Instructions are read of out a code stream. The only way to get a
910 // reference to an instruction is to convert a pointer. There is no way
911 // to allocate or create instances of class Instruction.
912 // Use the At(pc) function to create references to Instruction.
At(byte * pc)913 static Instruction* At(byte* pc) {
914 return reinterpret_cast<Instruction*>(pc);
915 }
916
917 private:
918 // We need to prevent the creation of instances of class Instruction.
919 DISALLOW_IMPLICIT_CONSTRUCTORS(Instruction);
920 };
921
922 // -----------------------------------------------------------------------------
923 // LOONG64 assembly various constants.
924
925 const int kInvalidStackOffset = -1;
926
927 static const int kNegOffset = 0x00008000;
928
InstructionType()929 InstructionBase::Type InstructionBase::InstructionType() const {
930 InstructionBase::Type kType = kUnsupported;
931
932 // Check for kOp6Type
933 switch (Bits(31, 26) << 26) {
934 case ADDU16I_D:
935 case BEQZ:
936 case BNEZ:
937 case BCZ:
938 case JIRL:
939 case B:
940 case BL:
941 case BEQ:
942 case BNE:
943 case BLT:
944 case BGE:
945 case BLTU:
946 case BGEU:
947 kType = kOp6Type;
948 break;
949 default:
950 kType = kUnsupported;
951 }
952
953 if (kType == kUnsupported) {
954 // Check for kOp7Type
955 switch (Bits(31, 25) << 25) {
956 case LU12I_W:
957 case LU32I_D:
958 case PCADDI:
959 case PCALAU12I:
960 case PCADDU12I:
961 case PCADDU18I:
962 kType = kOp7Type;
963 break;
964 default:
965 kType = kUnsupported;
966 }
967 }
968
969 if (kType == kUnsupported) {
970 // Check for kOp8Type
971 switch (Bits(31, 24) << 24) {
972 case LDPTR_W:
973 case STPTR_W:
974 case LDPTR_D:
975 case STPTR_D:
976 case LL_W:
977 case SC_W:
978 case LL_D:
979 case SC_D:
980 kType = kOp8Type;
981 break;
982 default:
983 kType = kUnsupported;
984 }
985 }
986
987 if (kType == kUnsupported) {
988 // Check for kOp10Type
989 switch (Bits(31, 22) << 22) {
990 case BSTR_W: {
991 // If Bit(21) = 0, then the Opcode is not BSTR_W.
992 if (Bit(21) == 0)
993 kType = kUnsupported;
994 else
995 kType = kOp10Type;
996 break;
997 }
998 case BSTRINS_D:
999 case BSTRPICK_D:
1000 case SLTI:
1001 case SLTUI:
1002 case ADDI_W:
1003 case ADDI_D:
1004 case LU52I_D:
1005 case ANDI:
1006 case ORI:
1007 case XORI:
1008 case LD_B:
1009 case LD_H:
1010 case LD_W:
1011 case LD_D:
1012 case ST_B:
1013 case ST_H:
1014 case ST_W:
1015 case ST_D:
1016 case LD_BU:
1017 case LD_HU:
1018 case LD_WU:
1019 case FLD_S:
1020 case FST_S:
1021 case FLD_D:
1022 case FST_D:
1023 kType = kOp10Type;
1024 break;
1025 default:
1026 kType = kUnsupported;
1027 }
1028 }
1029
1030 if (kType == kUnsupported) {
1031 // Check for kOp12Type
1032 switch (Bits(31, 20) << 20) {
1033 case FMADD_S:
1034 case FMADD_D:
1035 case FMSUB_S:
1036 case FMSUB_D:
1037 case FNMADD_S:
1038 case FNMADD_D:
1039 case FNMSUB_S:
1040 case FNMSUB_D:
1041 case FCMP_COND_S:
1042 case FCMP_COND_D:
1043 case FSEL:
1044 kType = kOp12Type;
1045 break;
1046 default:
1047 kType = kUnsupported;
1048 }
1049 }
1050
1051 if (kType == kUnsupported) {
1052 // Check for kOp14Type
1053 switch (Bits(31, 18) << 18) {
1054 case ALSL:
1055 case BYTEPICK_W:
1056 case BYTEPICK_D:
1057 case ALSL_D:
1058 case SLLI:
1059 case SRLI:
1060 case SRAI:
1061 case ROTRI:
1062 kType = kOp14Type;
1063 break;
1064 default:
1065 kType = kUnsupported;
1066 }
1067 }
1068
1069 if (kType == kUnsupported) {
1070 // Check for kOp17Type
1071 switch (Bits(31, 15) << 15) {
1072 case ADD_W:
1073 case ADD_D:
1074 case SUB_W:
1075 case SUB_D:
1076 case SLT:
1077 case SLTU:
1078 case MASKEQZ:
1079 case MASKNEZ:
1080 case NOR:
1081 case AND:
1082 case OR:
1083 case XOR:
1084 case ORN:
1085 case ANDN:
1086 case SLL_W:
1087 case SRL_W:
1088 case SRA_W:
1089 case SLL_D:
1090 case SRL_D:
1091 case SRA_D:
1092 case ROTR_D:
1093 case ROTR_W:
1094 case MUL_W:
1095 case MULH_W:
1096 case MULH_WU:
1097 case MUL_D:
1098 case MULH_D:
1099 case MULH_DU:
1100 case MULW_D_W:
1101 case MULW_D_WU:
1102 case DIV_W:
1103 case MOD_W:
1104 case DIV_WU:
1105 case MOD_WU:
1106 case DIV_D:
1107 case MOD_D:
1108 case DIV_DU:
1109 case MOD_DU:
1110 case BREAK:
1111 case FADD_S:
1112 case FADD_D:
1113 case FSUB_S:
1114 case FSUB_D:
1115 case FMUL_S:
1116 case FMUL_D:
1117 case FDIV_S:
1118 case FDIV_D:
1119 case FMAX_S:
1120 case FMAX_D:
1121 case FMIN_S:
1122 case FMIN_D:
1123 case FMAXA_S:
1124 case FMAXA_D:
1125 case FMINA_S:
1126 case FMINA_D:
1127 case LDX_B:
1128 case LDX_H:
1129 case LDX_W:
1130 case LDX_D:
1131 case STX_B:
1132 case STX_H:
1133 case STX_W:
1134 case STX_D:
1135 case LDX_BU:
1136 case LDX_HU:
1137 case LDX_WU:
1138 case FLDX_S:
1139 case FLDX_D:
1140 case FSTX_S:
1141 case FSTX_D:
1142 case AMSWAP_W:
1143 case AMSWAP_D:
1144 case AMADD_W:
1145 case AMADD_D:
1146 case AMAND_W:
1147 case AMAND_D:
1148 case AMOR_W:
1149 case AMOR_D:
1150 case AMXOR_W:
1151 case AMXOR_D:
1152 case AMMAX_W:
1153 case AMMAX_D:
1154 case AMMIN_W:
1155 case AMMIN_D:
1156 case AMMAX_WU:
1157 case AMMAX_DU:
1158 case AMMIN_WU:
1159 case AMMIN_DU:
1160 case AMSWAP_DB_W:
1161 case AMSWAP_DB_D:
1162 case AMADD_DB_W:
1163 case AMADD_DB_D:
1164 case AMAND_DB_W:
1165 case AMAND_DB_D:
1166 case AMOR_DB_W:
1167 case AMOR_DB_D:
1168 case AMXOR_DB_W:
1169 case AMXOR_DB_D:
1170 case AMMAX_DB_W:
1171 case AMMAX_DB_D:
1172 case AMMIN_DB_W:
1173 case AMMIN_DB_D:
1174 case AMMAX_DB_WU:
1175 case AMMAX_DB_DU:
1176 case AMMIN_DB_WU:
1177 case AMMIN_DB_DU:
1178 case DBAR:
1179 case IBAR:
1180 case FSCALEB_S:
1181 case FSCALEB_D:
1182 case FCOPYSIGN_S:
1183 case FCOPYSIGN_D:
1184 kType = kOp17Type;
1185 break;
1186 default:
1187 kType = kUnsupported;
1188 }
1189 }
1190
1191 if (kType == kUnsupported) {
1192 // Check for kOp22Type
1193 switch (Bits(31, 10) << 10) {
1194 case CLZ_W:
1195 case CTZ_W:
1196 case CLZ_D:
1197 case CTZ_D:
1198 case REVB_2H:
1199 case REVB_4H:
1200 case REVB_2W:
1201 case REVB_D:
1202 case REVH_2W:
1203 case REVH_D:
1204 case BITREV_4B:
1205 case BITREV_8B:
1206 case BITREV_W:
1207 case BITREV_D:
1208 case EXT_W_B:
1209 case EXT_W_H:
1210 case FABS_S:
1211 case FABS_D:
1212 case FNEG_S:
1213 case FNEG_D:
1214 case FSQRT_S:
1215 case FSQRT_D:
1216 case FMOV_S:
1217 case FMOV_D:
1218 case MOVGR2FR_W:
1219 case MOVGR2FR_D:
1220 case MOVGR2FRH_W:
1221 case MOVFR2GR_S:
1222 case MOVFR2GR_D:
1223 case MOVFRH2GR_S:
1224 case MOVGR2FCSR:
1225 case MOVFCSR2GR:
1226 case FCVT_S_D:
1227 case FCVT_D_S:
1228 case FTINTRM_W_S:
1229 case FTINTRM_W_D:
1230 case FTINTRM_L_S:
1231 case FTINTRM_L_D:
1232 case FTINTRP_W_S:
1233 case FTINTRP_W_D:
1234 case FTINTRP_L_S:
1235 case FTINTRP_L_D:
1236 case FTINTRZ_W_S:
1237 case FTINTRZ_W_D:
1238 case FTINTRZ_L_S:
1239 case FTINTRZ_L_D:
1240 case FTINTRNE_W_S:
1241 case FTINTRNE_W_D:
1242 case FTINTRNE_L_S:
1243 case FTINTRNE_L_D:
1244 case FTINT_W_S:
1245 case FTINT_W_D:
1246 case FTINT_L_S:
1247 case FTINT_L_D:
1248 case FFINT_S_W:
1249 case FFINT_S_L:
1250 case FFINT_D_W:
1251 case FFINT_D_L:
1252 case FRINT_S:
1253 case FRINT_D:
1254 case MOVFR2CF:
1255 case MOVCF2FR:
1256 case MOVGR2CF:
1257 case MOVCF2GR:
1258 case FRECIP_S:
1259 case FRECIP_D:
1260 case FRSQRT_S:
1261 case FRSQRT_D:
1262 case FCLASS_S:
1263 case FCLASS_D:
1264 case FLOGB_S:
1265 case FLOGB_D:
1266 case CLO_W:
1267 case CTO_W:
1268 case CLO_D:
1269 case CTO_D:
1270 kType = kOp22Type;
1271 break;
1272 default:
1273 kType = kUnsupported;
1274 }
1275 }
1276
1277 return kType;
1278 }
1279
1280 // -----------------------------------------------------------------------------
1281 // Instructions.
1282
1283 template <class P>
IsTrap()1284 bool InstructionGetters<P>::IsTrap() const {
1285 return true;
1286 }
1287
1288 } // namespace internal
1289 } // namespace v8
1290
1291 #endif // V8_CODEGEN_LOONG64_CONSTANTS_LOONG64_H_
1292