constants-mips.h 55.5 KB
Newer Older
1
// Copyright 2012 the V8 project authors. All rights reserved.
2 3
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
4 5 6

#ifndef  V8_MIPS_CONSTANTS_H_
#define  V8_MIPS_CONSTANTS_H_
7
#include "src/globals.h"
8
// UNIMPLEMENTED_ macro for MIPS.
9
#ifdef DEBUG
10 11 12
#define UNIMPLEMENTED_MIPS()                                                  \
  v8::internal::PrintF("%s, \tline %d: \tfunction %s not implemented. \n",    \
                       __FILE__, __LINE__, __func__)
13 14 15 16
#else
#define UNIMPLEMENTED_MIPS()
#endif

17 18
#define UNSUPPORTED_MIPS() v8::internal::PrintF("Unsupported instruction.\n")

19
enum ArchVariants {
20 21 22
  kMips32r1 = v8::internal::MIPSr1,
  kMips32r2 = v8::internal::MIPSr2,
  kMips32r6 = v8::internal::MIPSr6,
23 24
  kLoongson
};
25

26
#ifdef _MIPS_ARCH_MIPS32R2
27
  static const ArchVariants kArchVariant = kMips32r2;
28 29
#elif _MIPS_ARCH_MIPS32R6
  static const ArchVariants kArchVariant = kMips32r6;
30 31 32 33
#elif _MIPS_ARCH_LOONGSON
// The loongson flag refers to the LOONGSON architectures based on MIPS-III,
// which predates (and is a subset of) the mips32r2 and r1 architectures.
  static const ArchVariants kArchVariant = kLoongson;
34 35 36 37 38
#elif _MIPS_ARCH_MIPS32RX
// This flags referred to compatibility mode that creates universal code that
// can run on any MIPS32 architecture revision. The dynamically generated code
// by v8 is specialized for the MIPS host detected in runtime probing.
  static const ArchVariants kArchVariant = kMips32r1;
39
#else
40
  static const ArchVariants kArchVariant = kMips32r1;
41 42
#endif

43 44 45 46 47 48 49 50 51 52 53 54
enum Endianness {
  kLittle,
  kBig
};

#if defined(V8_TARGET_LITTLE_ENDIAN)
  static const Endianness kArchEndian = kLittle;
#elif defined(V8_TARGET_BIG_ENDIAN)
  static const Endianness kArchEndian = kBig;
#else
#error Unknown endianness
#endif
55

56 57 58 59 60 61 62 63 64 65 66
enum FpuMode {
  kFP32,
  kFP64,
  kFPXX
};

#if defined(FPU_MODE_FP32)
  static const FpuMode kFpuMode = kFP32;
#elif defined(FPU_MODE_FP64)
  static const FpuMode kFpuMode = kFP64;
#elif defined(FPU_MODE_FPXX)
67 68
#if defined(_MIPS_ARCH_MIPS32R2) || defined(_MIPS_ARCH_MIPS32R6)
static const FpuMode kFpuMode = kFPXX;
69
#else
70 71 72 73
#error "FPXX is supported only on Mips32R2 and Mips32R6"
#endif
#else
static const FpuMode kFpuMode = kFP32;
74 75
#endif

76 77 78
#if(defined(__mips_hard_float) && __mips_hard_float != 0)
// Use floating-point coprocessor instructions. This flag is raised when
// -mhard-float is passed to the compiler.
79
const bool IsMipsSoftFloatABI = false;
80
#elif(defined(__mips_soft_float) && __mips_soft_float != 0)
81 82 83
// This flag is raised when -msoft-float is passed to the compiler.
// Although FPU is a base requirement for v8, soft-float ABI is used
// on soft-float systems with FPU kernel emulation.
84
const bool IsMipsSoftFloatABI = true;
85
#else
86
const bool IsMipsSoftFloatABI = true;
87 88
#endif

89 90 91 92 93 94 95 96 97
#if defined(V8_TARGET_LITTLE_ENDIAN)
const uint32_t kHoleNanUpper32Offset = 4;
const uint32_t kHoleNanLower32Offset = 0;
#elif defined(V8_TARGET_BIG_ENDIAN)
const uint32_t kHoleNanUpper32Offset = 0;
const uint32_t kHoleNanLower32Offset = 4;
#else
#error Unknown endianness
#endif
98

99 100 101
#define IsFp64Mode() (kFpuMode == kFP64)
#define IsFp32Mode() (kFpuMode == kFP32)
#define IsFpxxMode() (kFpuMode == kFPXX)
102 103 104 105 106 107

#ifndef _MIPS_ARCH_MIPS32RX
#define IsMipsArchVariant(check) \
  (kArchVariant == check)
#else
#define IsMipsArchVariant(check) \
108
  (CpuFeatures::IsSupported(static_cast<CpuFeature>(check)))
109 110
#endif

111 112 113 114 115 116 117 118 119 120 121 122 123
#if defined(V8_TARGET_LITTLE_ENDIAN)
const uint32_t kMipsLwrOffset = 0;
const uint32_t kMipsLwlOffset = 3;
const uint32_t kMipsSwrOffset = 0;
const uint32_t kMipsSwlOffset = 3;
#elif defined(V8_TARGET_BIG_ENDIAN)
const uint32_t kMipsLwrOffset = 3;
const uint32_t kMipsLwlOffset = 0;
const uint32_t kMipsSwrOffset = 3;
const uint32_t kMipsSwlOffset = 0;
#else
#error Unknown endianness
#endif
124

125
#ifndef __STDC_FORMAT_MACROS
126
#define __STDC_FORMAT_MACROS
127
#endif
128 129
#include <inttypes.h>

130 131 132 133 134 135 136
// Defines constants and accessor classes to assemble, disassemble and
// simulate MIPS32 instructions.
//
// See: MIPS32 Architecture For Programmers
//      Volume II: The MIPS32 Instruction Set
// Try www.cs.cornell.edu/courses/cs3410/2008fa/MIPS_Vol2.pdf.

137 138
namespace v8 {
namespace internal {
139 140

// -----------------------------------------------------------------------------
141
// Registers and FPURegisters.
142 143

// Number of general purpose registers.
144 145
const int kNumRegisters = 32;
const int kInvalidRegister = -1;
146 147

// Number of registers with HI, LO, and pc.
148
const int kNumSimuRegisters = 35;
149 150

// In the simulator, the PC register is simulated as the 34th register.
151
const int kPCRegister = 34;
152 153

// Number coprocessor registers.
154 155
const int kNumFPURegisters = 32;
const int kInvalidFPURegister = -1;
156

157 158 159 160 161 162 163
// Number of MSA registers
const int kNumMSARegisters = 32;
const int kInvalidMSARegister = -1;

const int kInvalidMSAControlRegister = -1;
const int kMSAIRRegister = 0;
const int kMSACSRRegister = 1;
164 165 166 167 168
const int kMSARegSize = 128;
const int kMSALanesByte = kMSARegSize / 8;
const int kMSALanesHalf = kMSARegSize / 16;
const int kMSALanesWord = kMSARegSize / 32;
const int kMSALanesDword = kMSARegSize / 64;
169

170
// FPU (coprocessor 1) control registers. Currently only FCSR is implemented.
171 172
const int kFCSRRegister = 31;
const int kInvalidFPUControlRegister = -1;
173
const uint32_t kFPUInvalidResult = static_cast<uint32_t>(1 << 31) - 1;
174
const int32_t kFPUInvalidResultNegative = static_cast<int32_t>(1 << 31);
175 176
const uint64_t kFPU64InvalidResult =
    static_cast<uint64_t>(static_cast<uint64_t>(1) << 63) - 1;
177 178
const int64_t kFPU64InvalidResultNegative =
    static_cast<int64_t>(static_cast<uint64_t>(1) << 63);
179 180

// FCSR constants.
181 182 183 184 185
const uint32_t kFCSRInexactFlagBit = 2;
const uint32_t kFCSRUnderflowFlagBit = 3;
const uint32_t kFCSROverflowFlagBit = 4;
const uint32_t kFCSRDivideByZeroFlagBit = 5;
const uint32_t kFCSRInvalidOpFlagBit = 6;
186
const uint32_t kFCSRNaN2008FlagBit = 18;
187 188 189 190 191 192

const uint32_t kFCSRInexactFlagMask = 1 << kFCSRInexactFlagBit;
const uint32_t kFCSRUnderflowFlagMask = 1 << kFCSRUnderflowFlagBit;
const uint32_t kFCSROverflowFlagMask = 1 << kFCSROverflowFlagBit;
const uint32_t kFCSRDivideByZeroFlagMask = 1 << kFCSRDivideByZeroFlagBit;
const uint32_t kFCSRInvalidOpFlagMask = 1 << kFCSRInvalidOpFlagBit;
193
const uint32_t kFCSRNaN2008FlagMask = 1 << kFCSRNaN2008FlagBit;
194 195

const uint32_t kFCSRFlagMask =
196 197 198 199 200 201
    kFCSRInexactFlagMask |
    kFCSRUnderflowFlagMask |
    kFCSROverflowFlagMask |
    kFCSRDivideByZeroFlagMask |
    kFCSRInvalidOpFlagMask;

202
const uint32_t kFCSRExceptionFlagMask = kFCSRFlagMask ^ kFCSRInexactFlagMask;
203

plind44@gmail.com's avatar
plind44@gmail.com committed
204 205 206 207 208 209 210 211 212 213
// 'pref' instruction hints
const int32_t kPrefHintLoad = 0;
const int32_t kPrefHintStore = 1;
const int32_t kPrefHintLoadStreamed = 4;
const int32_t kPrefHintStoreStreamed = 5;
const int32_t kPrefHintLoadRetained = 6;
const int32_t kPrefHintStoreRetained = 7;
const int32_t kPrefHintWritebackInvalidate = 25;
const int32_t kPrefHintPrepareForStore = 30;

214 215 216 217 218 219 220 221 222 223 224
// Helper functions for converting between register numbers and names.
class Registers {
 public:
  // Return the name of the register.
  static const char* Name(int reg);

  // Lookup the register number for the name provided.
  static int Number(const char* name);

  struct RegisterAlias {
    int reg;
225
    const char* name;
226 227 228 229 230 231 232 233 234 235 236
  };

  static const int32_t kMaxValue = 0x7fffffff;
  static const int32_t kMinValue = 0x80000000;

 private:
  static const char* names_[kNumSimuRegisters];
  static const RegisterAlias aliases_[];
};

// Helper functions for converting between register numbers and names.
237
class FPURegisters {
238 239 240 241 242 243 244 245 246
 public:
  // Return the name of the register.
  static const char* Name(int reg);

  // Lookup the register number for the name provided.
  static int Number(const char* name);

  struct RegisterAlias {
    int creg;
247
    const char* name;
248 249 250
  };

 private:
251
  static const char* names_[kNumFPURegisters];
252 253 254
  static const RegisterAlias aliases_[];
};

255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272
// Helper functions for converting between register numbers and names.
class MSARegisters {
 public:
  // Return the name of the register.
  static const char* Name(int reg);

  // Lookup the register number for the name provided.
  static int Number(const char* name);

  struct RegisterAlias {
    int creg;
    const char* name;
  };

 private:
  static const char* names_[kNumMSARegisters];
  static const RegisterAlias aliases_[];
};
273 274 275 276 277 278 279 280 281 282 283 284 285 286

// -----------------------------------------------------------------------------
// Instructions encoding constants.

// On MIPS all instructions are 32 bits.
typedef int32_t Instr;

// Special Software Interrupt codes when used in the presence of the MIPS
// simulator.
enum SoftwareInterruptCodes {
  // Transition to C code.
  call_rt_redirected = 0xfffff
};

287 288 289 290 291 292 293
// On MIPS Simulator breakpoints can have different codes:
// - Breaks between 0 and kMaxWatchpointCode are treated as simple watchpoints,
//   the simulator will run through them and print the registers.
// - Breaks between kMaxWatchpointCode and kMaxStopCode are treated as stop()
//   instructions (see Assembler::stop()).
// - Breaks larger than kMaxStopCode are simple breaks, dropping you into the
//   debugger.
294 295
const uint32_t kMaxWatchpointCode = 31;
const uint32_t kMaxStopCode = 127;
296 297 298
STATIC_ASSERT(kMaxWatchpointCode < kMaxStopCode);


299
// ----- Fields offset and length.
300 301 302 303 304 305 306 307 308 309
const int kOpcodeShift   = 26;
const int kOpcodeBits    = 6;
const int kRsShift       = 21;
const int kRsBits        = 5;
const int kRtShift       = 16;
const int kRtBits        = 5;
const int kRdShift       = 11;
const int kRdBits        = 5;
const int kSaShift       = 6;
const int kSaBits        = 5;
310
const int kLsaSaBits = 2;
311 312 313
const int kFunctionShift = 0;
const int kFunctionBits  = 6;
const int kLuiShift      = 16;
314 315
const int kBp2Shift = 6;
const int kBp2Bits = 2;
316 317 318 319
const int kBaseShift = 21;
const int kBaseBits = 5;
const int kBit6Shift = 6;
const int kBit6Bits = 1;
320

321 322
const int kImm9Shift = 7;
const int kImm9Bits = 9;
323 324
const int kImm16Shift = 0;
const int kImm16Bits  = 16;
325 326 327 328
const int kImm18Shift = 0;
const int kImm18Bits = 18;
const int kImm19Shift = 0;
const int kImm19Bits = 19;
329 330
const int kImm21Shift = 0;
const int kImm21Bits  = 21;
331 332 333 334
const int kImm26Shift = 0;
const int kImm26Bits  = 26;
const int kImm28Shift = 0;
const int kImm28Bits  = 28;
335 336
const int kImm32Shift = 0;
const int kImm32Bits  = 32;
337 338 339 340 341 342 343 344
const int kMsaImm8Shift = 16;
const int kMsaImm8Bits = 8;
const int kMsaImm5Shift = 16;
const int kMsaImm5Bits = 5;
const int kMsaImm10Shift = 11;
const int kMsaImm10Bits = 10;
const int kMsaImmMI10Shift = 16;
const int kMsaImmMI10Bits = 10;
345

346 347
// In branches and jumps immediate fields point to words, not bytes,
// and are therefore shifted by 2.
348 349
const int kImmFieldShift = 2;

350 351
const int kFrBits        = 5;
const int kFrShift       = 21;
352 353 354 355 356 357 358 359 360 361 362 363
const int kFsShift       = 11;
const int kFsBits        = 5;
const int kFtShift       = 16;
const int kFtBits        = 5;
const int kFdShift       = 6;
const int kFdBits        = 5;
const int kFCccShift     = 8;
const int kFCccBits      = 3;
const int kFBccShift     = 18;
const int kFBccBits      = 3;
const int kFBtrueShift   = 16;
const int kFBtrueBits    = 1;
364 365 366 367 368 369
const int kWtBits = 5;
const int kWtShift = 16;
const int kWsBits = 5;
const int kWsShift = 11;
const int kWdBits = 5;
const int kWdShift = 6;
370

371
// ----- Miscellaneous useful masks.
372
// Instruction bit masks.
373
const int kOpcodeMask = ((1 << kOpcodeBits) - 1) << kOpcodeShift;
374
const int kImm9Mask = ((1 << kImm9Bits) - 1) << kImm9Shift;
375
const int kImm16Mask = ((1 << kImm16Bits) - 1) << kImm16Shift;
376 377 378
const int kImm18Mask = ((1 << kImm18Bits) - 1) << kImm18Shift;
const int kImm19Mask = ((1 << kImm19Bits) - 1) << kImm19Shift;
const int kImm21Mask = ((1 << kImm21Bits) - 1) << kImm21Shift;
379 380
const int kImm26Mask = ((1 << kImm26Bits) - 1) << kImm26Shift;
const int kImm28Mask = ((1 << kImm28Bits) - 1) << kImm28Shift;
381 382 383 384
const int kImm5Mask = ((1 << 5) - 1);
const int kImm8Mask = ((1 << 8) - 1);
const int kImm10Mask = ((1 << 10) - 1);
const int kMsaI5I10Mask = ((7U << 23) | ((1 << 6) - 1));
385 386 387 388 389
const int kMsaI8Mask = ((3U << 24) | ((1 << 6) - 1));
const int kMsaI5Mask = ((7U << 23) | ((1 << 6) - 1));
const int kMsaMI10Mask = (15U << 2);
const int kMsaBITMask = ((7U << 23) | ((1 << 6) - 1));
const int kMsaELMMask = (15U << 22);
390
const int kMsaLongerELMMask = kMsaELMMask | (63U << 16);
391 392 393 394 395
const int kMsa3RMask = ((7U << 23) | ((1 << 6) - 1));
const int kMsa3RFMask = ((15U << 22) | ((1 << 6) - 1));
const int kMsaVECMask = (23U << 21);
const int kMsa2RMask = (7U << 18);
const int kMsa2RFMask = (15U << 17);
396 397 398 399 400
const int kRsFieldMask = ((1 << kRsBits) - 1) << kRsShift;
const int kRtFieldMask = ((1 << kRtBits) - 1) << kRtShift;
const int kRdFieldMask = ((1 << kRdBits) - 1) << kRdShift;
const int kSaFieldMask = ((1 << kSaBits) - 1) << kSaShift;
const int kFunctionFieldMask = ((1 << kFunctionBits) - 1) << kFunctionShift;
401
// Misc masks.
402 403 404 405
const int kHiMask = 0xffff << 16;
const int kLoMask = 0xffff;
const int kSignMask = 0x80000000;
const int kJumpAddrMask = (1 << (kImm26Bits + kImmFieldShift)) - 1;
406 407 408 409

// ----- MIPS Opcodes and Function Fields.
// We use this presentation to stay close to the table representation in
// MIPS32 Architecture For Programmers, Volume II: The MIPS32 Instruction Set.
410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438
enum Opcode : uint32_t {
  SPECIAL = 0U << kOpcodeShift,
  REGIMM = 1U << kOpcodeShift,

  J = ((0U << 3) + 2) << kOpcodeShift,
  JAL = ((0U << 3) + 3) << kOpcodeShift,
  BEQ = ((0U << 3) + 4) << kOpcodeShift,
  BNE = ((0U << 3) + 5) << kOpcodeShift,
  BLEZ = ((0U << 3) + 6) << kOpcodeShift,
  BGTZ = ((0U << 3) + 7) << kOpcodeShift,

  ADDI = ((1U << 3) + 0) << kOpcodeShift,
  ADDIU = ((1U << 3) + 1) << kOpcodeShift,
  SLTI = ((1U << 3) + 2) << kOpcodeShift,
  SLTIU = ((1U << 3) + 3) << kOpcodeShift,
  ANDI = ((1U << 3) + 4) << kOpcodeShift,
  ORI = ((1U << 3) + 5) << kOpcodeShift,
  XORI = ((1U << 3) + 6) << kOpcodeShift,
  LUI = ((1U << 3) + 7) << kOpcodeShift,  // LUI/AUI family.

  BEQC = ((2U << 3) + 0) << kOpcodeShift,
  COP1 = ((2U << 3) + 1) << kOpcodeShift,  // Coprocessor 1 class.
  BEQL = ((2U << 3) + 4) << kOpcodeShift,
  BNEL = ((2U << 3) + 5) << kOpcodeShift,
  BLEZL = ((2U << 3) + 6) << kOpcodeShift,
  BGTZL = ((2U << 3) + 7) << kOpcodeShift,

  DADDI = ((3U << 3) + 0) << kOpcodeShift,  // This is also BNEC.
  SPECIAL2 = ((3U << 3) + 4) << kOpcodeShift,
439
  MSA = ((3U << 3) + 6) << kOpcodeShift,
440 441 442 443 444 445 446 447 448 449 450 451 452 453 454
  SPECIAL3 = ((3U << 3) + 7) << kOpcodeShift,

  LB = ((4U << 3) + 0) << kOpcodeShift,
  LH = ((4U << 3) + 1) << kOpcodeShift,
  LWL = ((4U << 3) + 2) << kOpcodeShift,
  LW = ((4U << 3) + 3) << kOpcodeShift,
  LBU = ((4U << 3) + 4) << kOpcodeShift,
  LHU = ((4U << 3) + 5) << kOpcodeShift,
  LWR = ((4U << 3) + 6) << kOpcodeShift,
  SB = ((5U << 3) + 0) << kOpcodeShift,
  SH = ((5U << 3) + 1) << kOpcodeShift,
  SWL = ((5U << 3) + 2) << kOpcodeShift,
  SW = ((5U << 3) + 3) << kOpcodeShift,
  SWR = ((5U << 3) + 6) << kOpcodeShift,

455
  LL = ((6U << 3) + 0) << kOpcodeShift,
456 457 458 459 460 461 462
  LWC1 = ((6U << 3) + 1) << kOpcodeShift,
  BC = ((6U << 3) + 2) << kOpcodeShift,
  LDC1 = ((6U << 3) + 5) << kOpcodeShift,
  POP66 = ((6U << 3) + 6) << kOpcodeShift,  // beqzc, jic

  PREF = ((6U << 3) + 3) << kOpcodeShift,

463
  SC = ((7U << 3) + 0) << kOpcodeShift,
464 465 466 467 468 469 470 471 472 473 474 475 476 477
  SWC1 = ((7U << 3) + 1) << kOpcodeShift,
  BALC = ((7U << 3) + 2) << kOpcodeShift,
  PCREL = ((7U << 3) + 3) << kOpcodeShift,
  SDC1 = ((7U << 3) + 5) << kOpcodeShift,
  POP76 = ((7U << 3) + 6) << kOpcodeShift,  // bnezc, jialc

  COP1X = ((1U << 4) + 3) << kOpcodeShift,

  // New r6 instruction.
  POP06 = BLEZ,   // bgeuc/bleuc, blezalc, bgezalc
  POP07 = BGTZ,   // bltuc/bgtuc, bgtzalc, bltzalc
  POP10 = ADDI,   // beqzalc, bovc, beqc
  POP26 = BLEZL,  // bgezc, blezc, bgec/blec
  POP27 = BGTZL,  // bgtzc, bltzc, bltc/bgtc
478
  POP30 = DADDI,  // bnezalc, bnvc, bnec
479 480
};

481
enum SecondaryField : uint32_t {
482
  // SPECIAL Encoding of Function Field.
483 484 485 486 487
  SLL = ((0U << 3) + 0),
  MOVCI = ((0U << 3) + 1),
  SRL = ((0U << 3) + 2),
  SRA = ((0U << 3) + 3),
  SLLV = ((0U << 3) + 4),
488
  LSA = ((0U << 3) + 5),
489 490 491 492 493 494 495 496
  SRLV = ((0U << 3) + 6),
  SRAV = ((0U << 3) + 7),

  JR = ((1U << 3) + 0),
  JALR = ((1U << 3) + 1),
  MOVZ = ((1U << 3) + 2),
  MOVN = ((1U << 3) + 3),
  BREAK = ((1U << 3) + 5),
497
  SYNC = ((1U << 3) + 7),
498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528

  MFHI = ((2U << 3) + 0),
  CLZ_R6 = ((2U << 3) + 0),
  CLO_R6 = ((2U << 3) + 1),
  MFLO = ((2U << 3) + 2),

  MULT = ((3U << 3) + 0),
  MULTU = ((3U << 3) + 1),
  DIV = ((3U << 3) + 2),
  DIVU = ((3U << 3) + 3),

  ADD = ((4U << 3) + 0),
  ADDU = ((4U << 3) + 1),
  SUB = ((4U << 3) + 2),
  SUBU = ((4U << 3) + 3),
  AND = ((4U << 3) + 4),
  OR = ((4U << 3) + 5),
  XOR = ((4U << 3) + 6),
  NOR = ((4U << 3) + 7),

  SLT = ((5U << 3) + 2),
  SLTU = ((5U << 3) + 3),

  TGE = ((6U << 3) + 0),
  TGEU = ((6U << 3) + 1),
  TLT = ((6U << 3) + 2),
  TLTU = ((6U << 3) + 3),
  TEQ = ((6U << 3) + 4),
  SELEQZ_S = ((6U << 3) + 5),
  TNE = ((6U << 3) + 6),
  SELNEZ_S = ((6U << 3) + 7),
529 530

  // Multiply integers in r6.
531 532 533
  MUL_MUH = ((3U << 3) + 0),    // MUL, MUH.
  MUL_MUH_U = ((3U << 3) + 1),  // MUL_U, MUH_U.
  RINT = ((3U << 3) + 2),
534

535 536 537 538
  MUL_OP = ((0U << 3) + 2),
  MUH_OP = ((0U << 3) + 3),
  DIV_OP = ((0U << 3) + 2),
  MOD_OP = ((0U << 3) + 3),
539

540 541
  DIV_MOD = ((3U << 3) + 2),
  DIV_MOD_U = ((3U << 3) + 3),
542 543

  // SPECIAL2 Encoding of Function Field.
544 545 546
  MUL = ((0U << 3) + 2),
  CLZ = ((4U << 3) + 0),
  CLO = ((4U << 3) + 1),
547 548

  // SPECIAL3 Encoding of Function Field.
549 550 551
  EXT = ((0U << 3) + 0),
  INS = ((0U << 3) + 4),
  BSHFL = ((4U << 3) + 0),
552 553
  SC_R6 = ((4U << 3) + 6),
  LL_R6 = ((6U << 3) + 6),
554 555

  // SPECIAL3 Encoding of sa Field.
556 557 558 559 560
  BITSWAP = ((0U << 3) + 0),
  ALIGN = ((0U << 3) + 2),
  WSBH = ((0U << 3) + 2),
  SEB = ((2U << 3) + 0),
  SEH = ((3U << 3) + 0),
561 562

  // REGIMM  encoding of rt Field.
563 564 565 566 567
  BLTZ = ((0U << 3) + 0) << 16,
  BGEZ = ((0U << 3) + 1) << 16,
  BLTZAL = ((2U << 3) + 0) << 16,
  BGEZAL = ((2U << 3) + 1) << 16,
  BGEZALL = ((2U << 3) + 3) << 16,
568 569

  // COP1 Encoding of rs Field.
570 571 572 573 574 575 576 577 578 579 580 581
  MFC1 = ((0U << 3) + 0) << 21,
  CFC1 = ((0U << 3) + 2) << 21,
  MFHC1 = ((0U << 3) + 3) << 21,
  MTC1 = ((0U << 3) + 4) << 21,
  CTC1 = ((0U << 3) + 6) << 21,
  MTHC1 = ((0U << 3) + 7) << 21,
  BC1 = ((1U << 3) + 0) << 21,
  S = ((2U << 3) + 0) << 21,
  D = ((2U << 3) + 1) << 21,
  W = ((2U << 3) + 4) << 21,
  L = ((2U << 3) + 5) << 21,
  PS = ((2U << 3) + 6) << 21,
582
  // COP1 Encoding of Function Field When rs=S.
583

584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601
  ADD_S = ((0U << 3) + 0),
  SUB_S = ((0U << 3) + 1),
  MUL_S = ((0U << 3) + 2),
  DIV_S = ((0U << 3) + 3),
  ABS_S = ((0U << 3) + 5),
  SQRT_S = ((0U << 3) + 4),
  MOV_S = ((0U << 3) + 6),
  NEG_S = ((0U << 3) + 7),
  ROUND_L_S = ((1U << 3) + 0),
  TRUNC_L_S = ((1U << 3) + 1),
  CEIL_L_S = ((1U << 3) + 2),
  FLOOR_L_S = ((1U << 3) + 3),
  ROUND_W_S = ((1U << 3) + 4),
  TRUNC_W_S = ((1U << 3) + 5),
  CEIL_W_S = ((1U << 3) + 6),
  FLOOR_W_S = ((1U << 3) + 7),
  RECIP_S = ((2U << 3) + 5),
  RSQRT_S = ((2U << 3) + 6),
602 603
  MADDF_S = ((3U << 3) + 0),
  MSUBF_S = ((3U << 3) + 1),
604 605 606 607 608
  CLASS_S = ((3U << 3) + 3),
  CVT_D_S = ((4U << 3) + 1),
  CVT_W_S = ((4U << 3) + 4),
  CVT_L_S = ((4U << 3) + 5),
  CVT_PS_S = ((4U << 3) + 6),
609

610
  // COP1 Encoding of Function Field When rs=D.
611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628
  ADD_D = ((0U << 3) + 0),
  SUB_D = ((0U << 3) + 1),
  MUL_D = ((0U << 3) + 2),
  DIV_D = ((0U << 3) + 3),
  SQRT_D = ((0U << 3) + 4),
  ABS_D = ((0U << 3) + 5),
  MOV_D = ((0U << 3) + 6),
  NEG_D = ((0U << 3) + 7),
  ROUND_L_D = ((1U << 3) + 0),
  TRUNC_L_D = ((1U << 3) + 1),
  CEIL_L_D = ((1U << 3) + 2),
  FLOOR_L_D = ((1U << 3) + 3),
  ROUND_W_D = ((1U << 3) + 4),
  TRUNC_W_D = ((1U << 3) + 5),
  CEIL_W_D = ((1U << 3) + 6),
  FLOOR_W_D = ((1U << 3) + 7),
  RECIP_D = ((2U << 3) + 5),
  RSQRT_D = ((2U << 3) + 6),
629 630
  MADDF_D = ((3U << 3) + 0),
  MSUBF_D = ((3U << 3) + 1),
631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646
  CLASS_D = ((3U << 3) + 3),
  MIN = ((3U << 3) + 4),
  MINA = ((3U << 3) + 5),
  MAX = ((3U << 3) + 6),
  MAXA = ((3U << 3) + 7),
  CVT_S_D = ((4U << 3) + 0),
  CVT_W_D = ((4U << 3) + 4),
  CVT_L_D = ((4U << 3) + 5),
  C_F_D = ((6U << 3) + 0),
  C_UN_D = ((6U << 3) + 1),
  C_EQ_D = ((6U << 3) + 2),
  C_UEQ_D = ((6U << 3) + 3),
  C_OLT_D = ((6U << 3) + 4),
  C_ULT_D = ((6U << 3) + 5),
  C_OLE_D = ((6U << 3) + 6),
  C_ULE_D = ((6U << 3) + 7),
647

648
  // COP1 Encoding of Function Field When rs=W or L.
649 650 651 652 653 654
  CVT_S_W = ((4U << 3) + 0),
  CVT_D_W = ((4U << 3) + 1),
  CVT_S_L = ((4U << 3) + 0),
  CVT_D_L = ((4U << 3) + 1),
  BC1EQZ = ((2U << 2) + 1) << 21,
  BC1NEZ = ((3U << 2) + 1) << 21,
655
  // COP1 CMP positive predicates Bit 5..4 = 00.
656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671
  CMP_AF = ((0U << 3) + 0),
  CMP_UN = ((0U << 3) + 1),
  CMP_EQ = ((0U << 3) + 2),
  CMP_UEQ = ((0U << 3) + 3),
  CMP_LT = ((0U << 3) + 4),
  CMP_ULT = ((0U << 3) + 5),
  CMP_LE = ((0U << 3) + 6),
  CMP_ULE = ((0U << 3) + 7),
  CMP_SAF = ((1U << 3) + 0),
  CMP_SUN = ((1U << 3) + 1),
  CMP_SEQ = ((1U << 3) + 2),
  CMP_SUEQ = ((1U << 3) + 3),
  CMP_SSLT = ((1U << 3) + 4),
  CMP_SSULT = ((1U << 3) + 5),
  CMP_SLE = ((1U << 3) + 6),
  CMP_SULE = ((1U << 3) + 7),
672
  // COP1 CMP negative predicates Bit 5..4 = 01.
673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695
  CMP_AT = ((2U << 3) + 0),  // Reserved, not implemented.
  CMP_OR = ((2U << 3) + 1),
  CMP_UNE = ((2U << 3) + 2),
  CMP_NE = ((2U << 3) + 3),
  CMP_UGE = ((2U << 3) + 4),  // Reserved, not implemented.
  CMP_OGE = ((2U << 3) + 5),  // Reserved, not implemented.
  CMP_UGT = ((2U << 3) + 6),  // Reserved, not implemented.
  CMP_OGT = ((2U << 3) + 7),  // Reserved, not implemented.
  CMP_SAT = ((3U << 3) + 0),  // Reserved, not implemented.
  CMP_SOR = ((3U << 3) + 1),
  CMP_SUNE = ((3U << 3) + 2),
  CMP_SNE = ((3U << 3) + 3),
  CMP_SUGE = ((3U << 3) + 4),  // Reserved, not implemented.
  CMP_SOGE = ((3U << 3) + 5),  // Reserved, not implemented.
  CMP_SUGT = ((3U << 3) + 6),  // Reserved, not implemented.
  CMP_SOGT = ((3U << 3) + 7),  // Reserved, not implemented.

  SEL = ((2U << 3) + 0),
  MOVZ_C = ((2U << 3) + 2),
  MOVN_C = ((2U << 3) + 3),
  SELEQZ_C = ((2U << 3) + 4),  // COP1 on FPR registers.
  MOVF = ((2U << 3) + 1),      // Function field for MOVT.fmt and MOVF.fmt
  SELNEZ_C = ((2U << 3) + 7),  // COP1 on FPR registers.
696
                               // COP1 Encoding of Function Field When rs=PS.
697

698
  // COP1X Encoding of Function Field.
699
  MADD_S = ((4U << 3) + 0),
700
  MADD_D = ((4U << 3) + 1),
701 702
  MSUB_S = ((5U << 3) + 0),
  MSUB_D = ((5U << 3) + 1),
703

704
  // PCREL Encoding of rt Field.
705 706 707 708
  ADDIUPC = ((0U << 2) + 0),
  LWPC = ((0U << 2) + 1),
  AUIPC = ((3U << 3) + 6),
  ALUIPC = ((3U << 3) + 7),
709 710

  // POP66 Encoding of rs Field.
711
  JIC = ((0U << 5) + 0),
712 713

  // POP76 Encoding of rs Field.
714
  JIALC = ((0U << 5) + 0),
715

716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958
  // COP1 Encoding of rs Field for MSA Branch Instructions
  BZ_V = (((1U << 3) + 3) << kRsShift),
  BNZ_V = (((1U << 3) + 7) << kRsShift),
  BZ_B = (((3U << 3) + 0) << kRsShift),
  BZ_H = (((3U << 3) + 1) << kRsShift),
  BZ_W = (((3U << 3) + 2) << kRsShift),
  BZ_D = (((3U << 3) + 3) << kRsShift),
  BNZ_B = (((3U << 3) + 4) << kRsShift),
  BNZ_H = (((3U << 3) + 5) << kRsShift),
  BNZ_W = (((3U << 3) + 6) << kRsShift),
  BNZ_D = (((3U << 3) + 7) << kRsShift),

  // MSA: Operation Field for MI10 Instruction Formats
  MSA_LD = (8U << 2),
  MSA_ST = (9U << 2),
  LD_B = ((8U << 2) + 0),
  LD_H = ((8U << 2) + 1),
  LD_W = ((8U << 2) + 2),
  LD_D = ((8U << 2) + 3),
  ST_B = ((9U << 2) + 0),
  ST_H = ((9U << 2) + 1),
  ST_W = ((9U << 2) + 2),
  ST_D = ((9U << 2) + 3),

  // MSA: Operation Field for I5 Instruction Format
  ADDVI = ((0U << 23) + 6),
  SUBVI = ((1U << 23) + 6),
  MAXI_S = ((2U << 23) + 6),
  MAXI_U = ((3U << 23) + 6),
  MINI_S = ((4U << 23) + 6),
  MINI_U = ((5U << 23) + 6),
  CEQI = ((0U << 23) + 7),
  CLTI_S = ((2U << 23) + 7),
  CLTI_U = ((3U << 23) + 7),
  CLEI_S = ((4U << 23) + 7),
  CLEI_U = ((5U << 23) + 7),
  LDI = ((6U << 23) + 7),  // I10 instruction format
  I5_DF_b = (0U << 21),
  I5_DF_h = (1U << 21),
  I5_DF_w = (2U << 21),
  I5_DF_d = (3U << 21),

  // MSA: Operation Field for I8 Instruction Format
  ANDI_B = ((0U << 24) + 0),
  ORI_B = ((1U << 24) + 0),
  NORI_B = ((2U << 24) + 0),
  XORI_B = ((3U << 24) + 0),
  BMNZI_B = ((0U << 24) + 1),
  BMZI_B = ((1U << 24) + 1),
  BSELI_B = ((2U << 24) + 1),
  SHF_B = ((0U << 24) + 2),
  SHF_H = ((1U << 24) + 2),
  SHF_W = ((2U << 24) + 2),

  MSA_VEC_2R_2RF_MINOR = ((3U << 3) + 6),

  // MSA: Operation Field for VEC Instruction Formats
  AND_V = (((0U << 2) + 0) << 21),
  OR_V = (((0U << 2) + 1) << 21),
  NOR_V = (((0U << 2) + 2) << 21),
  XOR_V = (((0U << 2) + 3) << 21),
  BMNZ_V = (((1U << 2) + 0) << 21),
  BMZ_V = (((1U << 2) + 1) << 21),
  BSEL_V = (((1U << 2) + 2) << 21),

  // MSA: Operation Field for 2R Instruction Formats
  MSA_2R_FORMAT = (((6U << 2) + 0) << 21),
  FILL = (0U << 18),
  PCNT = (1U << 18),
  NLOC = (2U << 18),
  NLZC = (3U << 18),
  MSA_2R_DF_b = (0U << 16),
  MSA_2R_DF_h = (1U << 16),
  MSA_2R_DF_w = (2U << 16),
  MSA_2R_DF_d = (3U << 16),

  // MSA: Operation Field for 2RF Instruction Formats
  MSA_2RF_FORMAT = (((6U << 2) + 1) << 21),
  FCLASS = (0U << 17),
  FTRUNC_S = (1U << 17),
  FTRUNC_U = (2U << 17),
  FSQRT = (3U << 17),
  FRSQRT = (4U << 17),
  FRCP = (5U << 17),
  FRINT = (6U << 17),
  FLOG2 = (7U << 17),
  FEXUPL = (8U << 17),
  FEXUPR = (9U << 17),
  FFQL = (10U << 17),
  FFQR = (11U << 17),
  FTINT_S = (12U << 17),
  FTINT_U = (13U << 17),
  FFINT_S = (14U << 17),
  FFINT_U = (15U << 17),
  MSA_2RF_DF_w = (0U << 16),
  MSA_2RF_DF_d = (1U << 16),

  // MSA: Operation Field for 3R Instruction Format
  SLL_MSA = ((0U << 23) + 13),
  SRA_MSA = ((1U << 23) + 13),
  SRL_MSA = ((2U << 23) + 13),
  BCLR = ((3U << 23) + 13),
  BSET = ((4U << 23) + 13),
  BNEG = ((5U << 23) + 13),
  BINSL = ((6U << 23) + 13),
  BINSR = ((7U << 23) + 13),
  ADDV = ((0U << 23) + 14),
  SUBV = ((1U << 23) + 14),
  MAX_S = ((2U << 23) + 14),
  MAX_U = ((3U << 23) + 14),
  MIN_S = ((4U << 23) + 14),
  MIN_U = ((5U << 23) + 14),
  MAX_A = ((6U << 23) + 14),
  MIN_A = ((7U << 23) + 14),
  CEQ = ((0U << 23) + 15),
  CLT_S = ((2U << 23) + 15),
  CLT_U = ((3U << 23) + 15),
  CLE_S = ((4U << 23) + 15),
  CLE_U = ((5U << 23) + 15),
  ADD_A = ((0U << 23) + 16),
  ADDS_A = ((1U << 23) + 16),
  ADDS_S = ((2U << 23) + 16),
  ADDS_U = ((3U << 23) + 16),
  AVE_S = ((4U << 23) + 16),
  AVE_U = ((5U << 23) + 16),
  AVER_S = ((6U << 23) + 16),
  AVER_U = ((7U << 23) + 16),
  SUBS_S = ((0U << 23) + 17),
  SUBS_U = ((1U << 23) + 17),
  SUBSUS_U = ((2U << 23) + 17),
  SUBSUU_S = ((3U << 23) + 17),
  ASUB_S = ((4U << 23) + 17),
  ASUB_U = ((5U << 23) + 17),
  MULV = ((0U << 23) + 18),
  MADDV = ((1U << 23) + 18),
  MSUBV = ((2U << 23) + 18),
  DIV_S_MSA = ((4U << 23) + 18),
  DIV_U = ((5U << 23) + 18),
  MOD_S = ((6U << 23) + 18),
  MOD_U = ((7U << 23) + 18),
  DOTP_S = ((0U << 23) + 19),
  DOTP_U = ((1U << 23) + 19),
  DPADD_S = ((2U << 23) + 19),
  DPADD_U = ((3U << 23) + 19),
  DPSUB_S = ((4U << 23) + 19),
  DPSUB_U = ((5U << 23) + 19),
  SLD = ((0U << 23) + 20),
  SPLAT = ((1U << 23) + 20),
  PCKEV = ((2U << 23) + 20),
  PCKOD = ((3U << 23) + 20),
  ILVL = ((4U << 23) + 20),
  ILVR = ((5U << 23) + 20),
  ILVEV = ((6U << 23) + 20),
  ILVOD = ((7U << 23) + 20),
  VSHF = ((0U << 23) + 21),
  SRAR = ((1U << 23) + 21),
  SRLR = ((2U << 23) + 21),
  HADD_S = ((4U << 23) + 21),
  HADD_U = ((5U << 23) + 21),
  HSUB_S = ((6U << 23) + 21),
  HSUB_U = ((7U << 23) + 21),
  MSA_3R_DF_b = (0U << 21),
  MSA_3R_DF_h = (1U << 21),
  MSA_3R_DF_w = (2U << 21),
  MSA_3R_DF_d = (3U << 21),

  // MSA: Operation Field for 3RF Instruction Format
  FCAF = ((0U << 22) + 26),
  FCUN = ((1U << 22) + 26),
  FCEQ = ((2U << 22) + 26),
  FCUEQ = ((3U << 22) + 26),
  FCLT = ((4U << 22) + 26),
  FCULT = ((5U << 22) + 26),
  FCLE = ((6U << 22) + 26),
  FCULE = ((7U << 22) + 26),
  FSAF = ((8U << 22) + 26),
  FSUN = ((9U << 22) + 26),
  FSEQ = ((10U << 22) + 26),
  FSUEQ = ((11U << 22) + 26),
  FSLT = ((12U << 22) + 26),
  FSULT = ((13U << 22) + 26),
  FSLE = ((14U << 22) + 26),
  FSULE = ((15U << 22) + 26),
  FADD = ((0U << 22) + 27),
  FSUB = ((1U << 22) + 27),
  FMUL = ((2U << 22) + 27),
  FDIV = ((3U << 22) + 27),
  FMADD = ((4U << 22) + 27),
  FMSUB = ((5U << 22) + 27),
  FEXP2 = ((7U << 22) + 27),
  FEXDO = ((8U << 22) + 27),
  FTQ = ((10U << 22) + 27),
  FMIN = ((12U << 22) + 27),
  FMIN_A = ((13U << 22) + 27),
  FMAX = ((14U << 22) + 27),
  FMAX_A = ((15U << 22) + 27),
  FCOR = ((1U << 22) + 28),
  FCUNE = ((2U << 22) + 28),
  FCNE = ((3U << 22) + 28),
  MUL_Q = ((4U << 22) + 28),
  MADD_Q = ((5U << 22) + 28),
  MSUB_Q = ((6U << 22) + 28),
  FSOR = ((9U << 22) + 28),
  FSUNE = ((10U << 22) + 28),
  FSNE = ((11U << 22) + 28),
  MULR_Q = ((12U << 22) + 28),
  MADDR_Q = ((13U << 22) + 28),
  MSUBR_Q = ((14U << 22) + 28),

  // MSA: Operation Field for ELM Instruction Format
  MSA_ELM_MINOR = ((3U << 3) + 1),
  SLDI = (0U << 22),
  CTCMSA = ((0U << 22) | (62U << 16)),
  SPLATI = (1U << 22),
  CFCMSA = ((1U << 22) | (62U << 16)),
  COPY_S = (2U << 22),
  MOVE_V = ((2U << 22) | (62U << 16)),
  COPY_U = (3U << 22),
  INSERT = (4U << 22),
  INSVE = (5U << 22),
  ELM_DF_B = ((0U << 4) << 16),
  ELM_DF_H = ((4U << 3) << 16),
  ELM_DF_W = ((12U << 2) << 16),
  ELM_DF_D = ((28U << 1) << 16),

  // MSA: Operation Field for BIT Instruction Format
  SLLI = ((0U << 23) + 9),
  SRAI = ((1U << 23) + 9),
  SRLI = ((2U << 23) + 9),
  BCLRI = ((3U << 23) + 9),
  BSETI = ((4U << 23) + 9),
  BNEGI = ((5U << 23) + 9),
  BINSLI = ((6U << 23) + 9),
  BINSRI = ((7U << 23) + 9),
  SAT_S = ((0U << 23) + 10),
  SAT_U = ((1U << 23) + 10),
  SRARI = ((2U << 23) + 10),
  SRLRI = ((3U << 23) + 10),
  BIT_DF_b = ((14U << 3) << 16),
  BIT_DF_h = ((6U << 4) << 16),
  BIT_DF_w = ((2U << 5) << 16),
  BIT_DF_d = ((0U << 6) << 16),

959
  nullptrSF = 0U
960 961
};

962 963 964 965 966 967 968 969 970 971 972 973 974 975 976
enum MSAMinorOpcode : uint32_t {
  kMsaMinorUndefined = 0,
  kMsaMinorI8,
  kMsaMinorI5,
  kMsaMinorI10,
  kMsaMinorBIT,
  kMsaMinor3R,
  kMsaMinor3RF,
  kMsaMinorELM,
  kMsaMinorVEC,
  kMsaMinor2R,
  kMsaMinor2RF,
  kMsaMinorMI10
};

977
// ----- Emulated conditions.
978
// On MIPS we use this enum to abstract from conditional branch instructions.
979
// The 'U' prefix is used to specify unsigned comparisons.
980
// Opposite conditions must be paired as odd/even numbers
981
// because 'NegateCondition' function flips LSB to negate condition.
982 983
enum Condition {
  // Any value < 0 is considered no_condition.
Benedikt Meurer's avatar
Benedikt Meurer committed
984 985 986 987 988
  kNoCondition = -1,
  overflow = 0,
  no_overflow = 1,
  Uless = 2,
  Ugreater_equal = 3,
989 990 991 992
  Uless_equal = 4,
  Ugreater = 5,
  equal = 6,
  not_equal = 7,  // Unordered or Not Equal.
Benedikt Meurer's avatar
Benedikt Meurer committed
993 994 995 996 997
  negative = 8,
  positive = 9,
  parity_even = 10,
  parity_odd = 11,
  less = 12,
998
  greater_equal = 13,
Benedikt Meurer's avatar
Benedikt Meurer committed
999 1000 1001
  less_equal = 14,
  greater = 15,
  ueq = 16,  // Unordered or Equal.
1002
  ogl = 17,  // Ordered and Not Equal.
Benedikt Meurer's avatar
Benedikt Meurer committed
1003
  cc_always = 18,
1004

1005
  // Aliases.
Benedikt Meurer's avatar
Benedikt Meurer committed
1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025
  carry = Uless,
  not_carry = Ugreater_equal,
  zero = equal,
  eq = equal,
  not_zero = not_equal,
  ne = not_equal,
  nz = not_equal,
  sign = negative,
  not_sign = positive,
  mi = negative,
  pl = positive,
  hi = Ugreater,
  ls = Uless_equal,
  ge = greater_equal,
  lt = less,
  gt = greater,
  le = less_equal,
  hs = Ugreater_equal,
  lo = Uless,
  al = cc_always,
1026 1027 1028 1029
  ult = Uless,
  uge = Ugreater_equal,
  ule = Uless_equal,
  ugt = Ugreater,
Benedikt Meurer's avatar
Benedikt Meurer committed
1030
  cc_default = kNoCondition
1031 1032
};

1033 1034 1035 1036 1037 1038

// Returns the equivalent of !cc.
// Negation of the default kNoCondition (-1) results in a non-default
// no_condition value (-2). As long as tests for no_condition check
// for condition < 0, this will work as expected.
inline Condition NegateCondition(Condition cc) {
1039
  DCHECK(cc != cc_always);
1040 1041 1042 1043
  return static_cast<Condition>(cc ^ 1);
}


1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075
inline Condition NegateFpuCondition(Condition cc) {
  DCHECK(cc != cc_always);
  switch (cc) {
    case ult:
      return ge;
    case ugt:
      return le;
    case uge:
      return lt;
    case ule:
      return gt;
    case lt:
      return uge;
    case gt:
      return ule;
    case ge:
      return ult;
    case le:
      return ugt;
    case eq:
      return ne;
    case ne:
      return eq;
    case ueq:
      return ogl;
    case ogl:
      return ueq;
    default:
      return cc;
  }
}

1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105
enum MSABranchCondition {
  all_not_zero = 0,   // Branch If All Elements Are Not Zero
  one_elem_not_zero,  // Branch If At Least One Element of Any Format Is Not
                      // Zero
  one_elem_zero,      // Branch If At Least One Element Is Zero
  all_zero            // Branch If All Elements of Any Format Are Zero
};

inline MSABranchCondition NegateMSABranchCondition(MSABranchCondition cond) {
  switch (cond) {
    case all_not_zero:
      return one_elem_zero;
    case one_elem_not_zero:
      return all_zero;
    case one_elem_zero:
      return all_not_zero;
    case all_zero:
      return one_elem_not_zero;
    default:
      return cond;
  }
}

enum MSABranchDF {
  MSA_BRANCH_B = 0,
  MSA_BRANCH_H,
  MSA_BRANCH_W,
  MSA_BRANCH_D,
  MSA_BRANCH_V
};
1106

1107
// Commute a condition such that {a cond b == b cond' a}.
1108
inline Condition CommuteCondition(Condition cc) {
1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127
  switch (cc) {
    case Uless:
      return Ugreater;
    case Ugreater:
      return Uless;
    case Ugreater_equal:
      return Uless_equal;
    case Uless_equal:
      return Ugreater_equal;
    case less:
      return greater;
    case greater:
      return less;
    case greater_equal:
      return less_equal;
    case less_equal:
      return greater_equal;
    default:
      return cc;
1128
  }
1129 1130 1131
}


1132 1133
// ----- Coprocessor conditions.
enum FPUCondition {
1134 1135
  kNoFPUCondition = -1,

1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150
  F = 0x00,    // False.
  UN = 0x01,   // Unordered.
  EQ = 0x02,   // Equal.
  UEQ = 0x03,  // Unordered or Equal.
  OLT = 0x04,  // Ordered or Less Than, on Mips release < 6.
  LT = 0x04,   // Ordered or Less Than, on Mips release >= 6.
  ULT = 0x05,  // Unordered or Less Than.
  OLE = 0x06,  // Ordered or Less Than or Equal, on Mips release < 6.
  LE = 0x06,   // Ordered or Less Than or Equal, on Mips release >= 6.
  ULE = 0x07,  // Unordered or Less Than or Equal.

  // Following constants are available on Mips release >= 6 only.
  ORD = 0x11,  // Ordered, on Mips release >= 6.
  UNE = 0x12,  // Not equal, on Mips release >= 6.
  NE = 0x13,   // Ordered Greater Than or Less Than. on Mips >= 6 only.
1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164
};


// FPU rounding modes.
enum FPURoundingMode {
  RN = 0 << 0,  // Round to Nearest.
  RZ = 1 << 0,  // Round towards zero.
  RP = 2 << 0,  // Round towards Plus Infinity.
  RM = 3 << 0,  // Round towards Minus Infinity.

  // Aliases.
  kRoundToNearest = RN,
  kRoundToZero = RZ,
  kRoundToPlusInf = RP,
1165 1166 1167 1168 1169 1170
  kRoundToMinusInf = RM,

  mode_round = RN,
  mode_ceil = RP,
  mode_floor = RM,
  mode_trunc = RZ
1171 1172
};

1173
const uint32_t kFPURoundingModeMask = 3 << 0;
1174 1175 1176 1177

enum CheckForInexactConversion {
  kCheckForInexactConversion,
  kDontCheckForInexactConversion
1178 1179
};

1180
enum class MaxMinKind : int { kMin = 0, kMax = 1 };
1181

1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209
// -----------------------------------------------------------------------------
// Hints.

// Branch hints are not used on the MIPS.  They are defined so that they can
// appear in shared function signatures, but will be ignored in MIPS
// implementations.
enum Hint {
  no_hint = 0
};


inline Hint NegateHint(Hint hint) {
  return no_hint;
}


// -----------------------------------------------------------------------------
// Specific instructions, constants, and masks.
// These constants are declared in assembler-mips.cc, as they use named
// registers and other constants.

// addiu(sp, sp, 4) aka Pop() operation or part of Pop(r)
// operations as post-increment of sp.
extern const Instr kPopInstruction;
// addiu(sp, sp, -4) part of Push(r) operation as pre-decrement of sp.
extern const Instr kPushInstruction;
// sw(r, MemOperand(sp, 0))
extern const Instr kPushRegPattern;
1210
// lw(r, MemOperand(sp, 0))
1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221
extern const Instr kPopRegPattern;
extern const Instr kLwRegFpOffsetPattern;
extern const Instr kSwRegFpOffsetPattern;
extern const Instr kLwRegFpNegOffsetPattern;
extern const Instr kSwRegFpNegOffsetPattern;
// A mask for the Rt register for push, pop, lw, sw instructions.
extern const Instr kRtMask;
extern const Instr kLwSwInstrTypeMask;
extern const Instr kLwSwInstrArgumentMask;
extern const Instr kLwSwOffsetMask;

1222 1223 1224 1225 1226
// Break 0xfffff, reserved for redirected real time call.
const Instr rtCallRedirInstr = SPECIAL | BREAK | call_rt_redirected << 6;
// A nop instruction. (Encoding of sll 0 0 0).
const Instr nopInstr = 0;

1227 1228 1229 1230
static constexpr uint64_t OpcodeToBitNumber(Opcode opcode) {
  return 1ULL << (static_cast<uint32_t>(opcode) >> kOpcodeShift);
}

1231
class InstructionBase {
1232 1233
 public:
  enum {
1234 1235
    kInstrSize = 4,
    kInstrSizeLog2 = 2,
1236
    // On MIPS PC cannot actually be directly accessed. We behave as if PC was
1237
    // always the value of the current instruction being executed.
1238 1239 1240
    kPCReadOffset = 0
  };

1241 1242 1243
  // Instruction type.
  enum Type { kRegisterType, kImmediateType, kJumpType, kUnsupported = -1 };

1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260
  // Get the raw instruction bits.
  inline Instr InstructionBits() const {
    return *reinterpret_cast<const Instr*>(this);
  }

  // Set the raw instruction bits to value.
  inline void SetInstructionBits(Instr value) {
    *reinterpret_cast<Instr*>(this) = value;
  }

  // Read one particular bit out of the instruction bits.
  inline int Bit(int nr) const {
    return (InstructionBits() >> nr) & 1;
  }

  // Read a bit field out of the instruction bits.
  inline int Bits(int hi, int lo) const {
1261
    return (InstructionBits() >> lo) & ((2U << (hi - lo)) - 1);
1262
  }
1263 1264


1265
  static constexpr uint64_t kOpcodeImmediateTypeMask =
1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291
      OpcodeToBitNumber(REGIMM) | OpcodeToBitNumber(BEQ) |
      OpcodeToBitNumber(BNE) | OpcodeToBitNumber(BLEZ) |
      OpcodeToBitNumber(BGTZ) | OpcodeToBitNumber(ADDI) |
      OpcodeToBitNumber(DADDI) | OpcodeToBitNumber(ADDIU) |
      OpcodeToBitNumber(SLTI) | OpcodeToBitNumber(SLTIU) |
      OpcodeToBitNumber(ANDI) | OpcodeToBitNumber(ORI) |
      OpcodeToBitNumber(XORI) | OpcodeToBitNumber(LUI) |
      OpcodeToBitNumber(BEQL) | OpcodeToBitNumber(BNEL) |
      OpcodeToBitNumber(BLEZL) | OpcodeToBitNumber(BGTZL) |
      OpcodeToBitNumber(POP66) | OpcodeToBitNumber(POP76) |
      OpcodeToBitNumber(LB) | OpcodeToBitNumber(LH) | OpcodeToBitNumber(LWL) |
      OpcodeToBitNumber(LW) | OpcodeToBitNumber(LBU) | OpcodeToBitNumber(LHU) |
      OpcodeToBitNumber(LWR) | OpcodeToBitNumber(SB) | OpcodeToBitNumber(SH) |
      OpcodeToBitNumber(SWL) | OpcodeToBitNumber(SW) | OpcodeToBitNumber(SWR) |
      OpcodeToBitNumber(LWC1) | OpcodeToBitNumber(LDC1) |
      OpcodeToBitNumber(SWC1) | OpcodeToBitNumber(SDC1) |
      OpcodeToBitNumber(PCREL) | OpcodeToBitNumber(BC) |
      OpcodeToBitNumber(BALC);

#define FunctionFieldToBitNumber(function) (1ULL << function)

  static const uint64_t kFunctionFieldRegisterTypeMask =
      FunctionFieldToBitNumber(JR) | FunctionFieldToBitNumber(JALR) |
      FunctionFieldToBitNumber(BREAK) | FunctionFieldToBitNumber(SLL) |
      FunctionFieldToBitNumber(SRL) | FunctionFieldToBitNumber(SRA) |
      FunctionFieldToBitNumber(SLLV) | FunctionFieldToBitNumber(SRLV) |
1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305
      FunctionFieldToBitNumber(SRAV) | FunctionFieldToBitNumber(LSA) |
      FunctionFieldToBitNumber(MFHI) | FunctionFieldToBitNumber(MFLO) |
      FunctionFieldToBitNumber(MULT) | FunctionFieldToBitNumber(MULTU) |
      FunctionFieldToBitNumber(DIV) | FunctionFieldToBitNumber(DIVU) |
      FunctionFieldToBitNumber(ADD) | FunctionFieldToBitNumber(ADDU) |
      FunctionFieldToBitNumber(SUB) | FunctionFieldToBitNumber(SUBU) |
      FunctionFieldToBitNumber(AND) | FunctionFieldToBitNumber(OR) |
      FunctionFieldToBitNumber(XOR) | FunctionFieldToBitNumber(NOR) |
      FunctionFieldToBitNumber(SLT) | FunctionFieldToBitNumber(SLTU) |
      FunctionFieldToBitNumber(TGE) | FunctionFieldToBitNumber(TGEU) |
      FunctionFieldToBitNumber(TLT) | FunctionFieldToBitNumber(TLTU) |
      FunctionFieldToBitNumber(TEQ) | FunctionFieldToBitNumber(TNE) |
      FunctionFieldToBitNumber(MOVZ) | FunctionFieldToBitNumber(MOVN) |
      FunctionFieldToBitNumber(MOVCI) | FunctionFieldToBitNumber(SELEQZ_S) |
1306
      FunctionFieldToBitNumber(SELNEZ_S) | FunctionFieldToBitNumber(SYNC);
1307 1308

  // Accessors for the different named fields used in the MIPS encoding.
1309
  inline Opcode OpcodeValue() const {
1310 1311 1312 1313
    return static_cast<Opcode>(
        Bits(kOpcodeShift + kOpcodeBits - 1, kOpcodeShift));
  }

1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327 1328 1329 1330
  inline int FunctionFieldRaw() const {
    return InstructionBits() & kFunctionFieldMask;
  }

  // Return the fields at their original place in the instruction encoding.
  inline Opcode OpcodeFieldRaw() const {
    return static_cast<Opcode>(InstructionBits() & kOpcodeMask);
  }

  // Safe to call within InstructionType().
  inline int RsFieldRawNoAssert() const {
    return InstructionBits() & kRsFieldMask;
  }

  inline int SaFieldRaw() const { return InstructionBits() & kSaFieldMask; }

  // Get the encoding type of the instruction.
1331
  inline Type InstructionType() const;
1332

1333 1334 1335 1336 1337 1338 1339 1340 1341 1342 1343 1344 1345 1346 1347 1348 1349 1350 1351 1352 1353 1354 1355 1356 1357 1358 1359 1360 1361 1362 1363 1364 1365 1366 1367 1368 1369 1370 1371 1372 1373 1374 1375 1376 1377 1378 1379 1380 1381 1382 1383 1384 1385 1386 1387 1388
  inline MSAMinorOpcode MSAMinorOpcodeField() const {
    int op = this->FunctionFieldRaw();
    switch (op) {
      case 0:
      case 1:
      case 2:
        return kMsaMinorI8;
      case 6:
        return kMsaMinorI5;
      case 7:
        return (((this->InstructionBits() & kMsaI5I10Mask) == LDI)
                    ? kMsaMinorI10
                    : kMsaMinorI5);
      case 9:
      case 10:
        return kMsaMinorBIT;
      case 13:
      case 14:
      case 15:
      case 16:
      case 17:
      case 18:
      case 19:
      case 20:
      case 21:
        return kMsaMinor3R;
      case 25:
        return kMsaMinorELM;
      case 26:
      case 27:
      case 28:
        return kMsaMinor3RF;
      case 30:
        switch (this->RsFieldRawNoAssert()) {
          case MSA_2R_FORMAT:
            return kMsaMinor2R;
          case MSA_2RF_FORMAT:
            return kMsaMinor2RF;
          default:
            return kMsaMinorVEC;
        }
        break;
      case 32:
      case 33:
      case 34:
      case 35:
      case 36:
      case 37:
      case 38:
      case 39:
        return kMsaMinorMI10;
      default:
        return kMsaMinorUndefined;
    }
  }

1389 1390 1391 1392 1393 1394 1395
 protected:
  InstructionBase() {}
};

template <class T>
class InstructionGetters : public T {
 public:
1396
  inline int RsValue() const {
1397 1398 1399
    DCHECK(this->InstructionType() == InstructionBase::kRegisterType ||
           this->InstructionType() == InstructionBase::kImmediateType);
    return InstructionBase::Bits(kRsShift + kRsBits - 1, kRsShift);
1400 1401
  }

1402
  inline int RtValue() const {
1403 1404 1405
    DCHECK(this->InstructionType() == InstructionBase::kRegisterType ||
           this->InstructionType() == InstructionBase::kImmediateType);
    return this->Bits(kRtShift + kRtBits - 1, kRtShift);
1406 1407
  }

1408
  inline int RdValue() const {
1409
    DCHECK_EQ(this->InstructionType(), InstructionBase::kRegisterType);
1410
    return this->Bits(kRdShift + kRdBits - 1, kRdShift);
1411 1412
  }

1413
  inline int BaseValue() const {
1414
    DCHECK_EQ(this->InstructionType(), InstructionBase::kImmediateType);
1415 1416 1417
    return this->Bits(kBaseShift + kBaseBits - 1, kBaseShift);
  }

1418
  inline int SaValue() const {
1419
    DCHECK_EQ(this->InstructionType(), InstructionBase::kRegisterType);
1420
    return this->Bits(kSaShift + kSaBits - 1, kSaShift);
1421 1422
  }

1423
  inline int LsaSaValue() const {
1424
    DCHECK_EQ(this->InstructionType(), InstructionBase::kRegisterType);
1425
    return this->Bits(kSaShift + kLsaSaBits - 1, kSaShift);
1426 1427
  }

1428
  inline int FunctionValue() const {
1429 1430 1431
    DCHECK(this->InstructionType() == InstructionBase::kRegisterType ||
           this->InstructionType() == InstructionBase::kImmediateType);
    return this->Bits(kFunctionShift + kFunctionBits - 1, kFunctionShift);
1432 1433
  }

1434
  inline int FdValue() const {
1435
    return this->Bits(kFdShift + kFdBits - 1, kFdShift);
1436 1437 1438
  }

  inline int FsValue() const {
1439
    return this->Bits(kFsShift + kFsBits - 1, kFsShift);
1440 1441 1442
  }

  inline int FtValue() const {
1443
    return this->Bits(kFtShift + kFtBits - 1, kFtShift);
1444 1445
  }

1446
  inline int FrValue() const {
1447
    return this->Bits(kFrShift + kFrBits - 1, kFrShift);
1448 1449
  }

1450 1451 1452 1453 1454 1455 1456 1457 1458 1459 1460 1461
  inline int WdValue() const {
    return this->Bits(kWdShift + kWdBits - 1, kWdShift);
  }

  inline int WsValue() const {
    return this->Bits(kWsShift + kWsBits - 1, kWsShift);
  }

  inline int WtValue() const {
    return this->Bits(kWtShift + kWtBits - 1, kWtShift);
  }

1462
  inline int Bp2Value() const {
1463
    DCHECK_EQ(this->InstructionType(), InstructionBase::kRegisterType);
1464
    return this->Bits(kBp2Shift + kBp2Bits - 1, kBp2Shift);
1465 1466
  }

1467 1468
  // Float Compare condition code instruction bits.
  inline int FCccValue() const {
1469
    return this->Bits(kFCccShift + kFCccBits - 1, kFCccShift);
1470 1471 1472 1473
  }

  // Float Branch condition code instruction bits.
  inline int FBccValue() const {
1474
    return this->Bits(kFBccShift + kFBccBits - 1, kFBccShift);
1475 1476 1477 1478
  }

  // Float Branch true/false instruction bit.
  inline int FBtrueValue() const {
1479
    return this->Bits(kFBtrueShift + kFBtrueBits - 1, kFBtrueShift);
1480 1481 1482 1483
  }

  // Return the fields at their original place in the instruction encoding.
  inline Opcode OpcodeFieldRaw() const {
1484
    return static_cast<Opcode>(this->InstructionBits() & kOpcodeMask);
1485 1486 1487
  }

  inline int RsFieldRaw() const {
1488 1489 1490
    DCHECK(this->InstructionType() == InstructionBase::kRegisterType ||
           this->InstructionType() == InstructionBase::kImmediateType);
    return this->InstructionBits() & kRsFieldMask;
1491 1492
  }

1493
  inline int RtFieldRaw() const {
1494 1495 1496
    DCHECK(this->InstructionType() == InstructionBase::kRegisterType ||
           this->InstructionType() == InstructionBase::kImmediateType);
    return this->InstructionBits() & kRtFieldMask;
1497 1498 1499
  }

  inline int RdFieldRaw() const {
1500
    DCHECK_EQ(this->InstructionType(), InstructionBase::kRegisterType);
1501
    return this->InstructionBits() & kRdFieldMask;
1502 1503 1504
  }

  inline int SaFieldRaw() const {
1505
    return this->InstructionBits() & kSaFieldMask;
1506 1507 1508
  }

  inline int FunctionFieldRaw() const {
1509
    return this->InstructionBits() & kFunctionFieldMask;
1510 1511 1512
  }

  // Get the secondary field according to the opcode.
1513
  inline int SecondaryValue() const {
1514
    Opcode op = this->OpcodeFieldRaw();
1515 1516 1517
    switch (op) {
      case SPECIAL:
      case SPECIAL2:
1518
        return FunctionValue();
1519
      case COP1:
1520
        return RsValue();
1521
      case REGIMM:
1522
        return RtValue();
1523
      default:
1524
        return nullptrSF;
1525 1526 1527
    }
  }

1528
  inline int32_t ImmValue(int bits) const {
1529
    DCHECK_EQ(this->InstructionType(), InstructionBase::kImmediateType);
1530
    return this->Bits(bits - 1, 0);
1531 1532
  }

1533
  inline int32_t Imm9Value() const {
1534
    DCHECK_EQ(this->InstructionType(), InstructionBase::kImmediateType);
1535 1536 1537
    return this->Bits(kImm9Shift + kImm9Bits - 1, kImm9Shift);
  }

1538
  inline int32_t Imm16Value() const {
1539
    DCHECK_EQ(this->InstructionType(), InstructionBase::kImmediateType);
1540
    return this->Bits(kImm16Shift + kImm16Bits - 1, kImm16Shift);
1541 1542
  }

1543
  inline int32_t Imm18Value() const {
1544
    DCHECK_EQ(this->InstructionType(), InstructionBase::kImmediateType);
1545
    return this->Bits(kImm18Shift + kImm18Bits - 1, kImm18Shift);
1546 1547 1548
  }

  inline int32_t Imm19Value() const {
1549
    DCHECK_EQ(this->InstructionType(), InstructionBase::kImmediateType);
1550
    return this->Bits(kImm19Shift + kImm19Bits - 1, kImm19Shift);
1551 1552
  }

1553
  inline int32_t Imm21Value() const {
1554
    DCHECK_EQ(this->InstructionType(), InstructionBase::kImmediateType);
1555
    return this->Bits(kImm21Shift + kImm21Bits - 1, kImm21Shift);
1556 1557
  }

1558
  inline int32_t Imm26Value() const {
1559 1560 1561
    DCHECK((this->InstructionType() == InstructionBase::kJumpType) ||
           (this->InstructionType() == InstructionBase::kImmediateType));
    return this->Bits(kImm26Shift + kImm26Bits - 1, kImm26Shift);
1562 1563
  }

1564
  inline int32_t MsaImm8Value() const {
1565
    DCHECK_EQ(this->InstructionType(), InstructionBase::kImmediateType);
1566 1567 1568 1569
    return this->Bits(kMsaImm8Shift + kMsaImm8Bits - 1, kMsaImm8Shift);
  }

  inline int32_t MsaImm5Value() const {
1570
    DCHECK_EQ(this->InstructionType(), InstructionBase::kImmediateType);
1571 1572 1573 1574
    return this->Bits(kMsaImm5Shift + kMsaImm5Bits - 1, kMsaImm5Shift);
  }

  inline int32_t MsaImm10Value() const {
1575
    DCHECK_EQ(this->InstructionType(), InstructionBase::kImmediateType);
1576 1577 1578 1579
    return this->Bits(kMsaImm10Shift + kMsaImm10Bits - 1, kMsaImm10Shift);
  }

  inline int32_t MsaImmMI10Value() const {
1580
    DCHECK_EQ(this->InstructionType(), InstructionBase::kImmediateType);
1581 1582 1583 1584
    return this->Bits(kMsaImmMI10Shift + kMsaImmMI10Bits - 1, kMsaImmMI10Shift);
  }

  inline int32_t MsaBitDf() const {
1585
    DCHECK_EQ(this->InstructionType(), InstructionBase::kImmediateType);
1586 1587 1588 1589 1590 1591 1592 1593 1594 1595 1596 1597 1598 1599 1600
    int32_t df_m = this->Bits(22, 16);
    if (((df_m >> 6) & 1U) == 0) {
      return 3;
    } else if (((df_m >> 5) & 3U) == 2) {
      return 2;
    } else if (((df_m >> 4) & 7U) == 6) {
      return 1;
    } else if (((df_m >> 3) & 15U) == 14) {
      return 0;
    } else {
      return -1;
    }
  }

  inline int32_t MsaBitMValue() const {
1601
    DCHECK_EQ(this->InstructionType(), InstructionBase::kImmediateType);
1602 1603 1604 1605
    return this->Bits(16 + this->MsaBitDf() + 3, 16);
  }

  inline int32_t MsaElmDf() const {
1606 1607
    DCHECK(this->InstructionType() == InstructionBase::kRegisterType ||
           this->InstructionType() == InstructionBase::kImmediateType);
1608 1609 1610 1611 1612 1613 1614 1615 1616 1617 1618 1619 1620 1621 1622
    int32_t df_n = this->Bits(21, 16);
    if (((df_n >> 4) & 3U) == 0) {
      return 0;
    } else if (((df_n >> 3) & 7U) == 4) {
      return 1;
    } else if (((df_n >> 2) & 15U) == 12) {
      return 2;
    } else if (((df_n >> 1) & 31U) == 28) {
      return 3;
    } else {
      return -1;
    }
  }

  inline int32_t MsaElmNValue() const {
1623 1624
    DCHECK(this->InstructionType() == InstructionBase::kRegisterType ||
           this->InstructionType() == InstructionBase::kImmediateType);
1625 1626 1627
    return this->Bits(16 + 4 - this->MsaElmDf(), 16);
  }

1628 1629 1630 1631 1632
  static bool IsForbiddenAfterBranchInstr(Instr instr);

  // Say if the instruction should not be used in a branch delay slot or
  // immediately after a compact branch.
  inline bool IsForbiddenAfterBranch() const {
1633
    return IsForbiddenAfterBranchInstr(this->InstructionBits());
1634 1635 1636 1637 1638 1639
  }

  inline bool IsForbiddenInBranchDelay() const {
    return IsForbiddenAfterBranch();
  }

1640
  // Say if the instruction 'links'. e.g. jal, bal.
1641
  bool IsLinkingInstruction() const;
1642
  // Say if the instruction is a break or a trap.
1643
  bool IsTrap() const;
1644 1645 1646 1647 1648 1649 1650 1651 1652 1653 1654 1655 1656 1657 1658 1659 1660 1661 1662 1663 1664 1665 1666 1667 1668 1669 1670

  inline bool IsMSABranchInstr() const {
    if (this->OpcodeFieldRaw() == COP1) {
      switch (this->RsFieldRaw()) {
        case BZ_V:
        case BZ_B:
        case BZ_H:
        case BZ_W:
        case BZ_D:
        case BNZ_V:
        case BNZ_B:
        case BNZ_H:
        case BNZ_W:
        case BNZ_D:
          return true;
        default:
          return false;
      }
    }
    return false;
  }

  inline bool IsMSAInstr() const {
    if (this->IsMSABranchInstr() || (this->OpcodeFieldRaw() == MSA))
      return true;
    return false;
  }
1671
};
1672

1673 1674
class Instruction : public InstructionGetters<InstructionBase> {
 public:
1675 1676 1677 1678
  // Instructions are read of out a code stream. The only way to get a
  // reference to an instruction is to convert a pointer. There is no way
  // to allocate or create instances of class Instruction.
  // Use the At(pc) function to create references to Instruction.
1679
  static Instruction* At(byte* pc) {
1680 1681 1682 1683
    return reinterpret_cast<Instruction*>(pc);
  }

 private:
1684
  // We need to prevent the creation of instances of class Instruction.
1685 1686 1687 1688 1689 1690 1691
  DISALLOW_IMPLICIT_CONSTRUCTORS(Instruction);
};


// -----------------------------------------------------------------------------
// MIPS assembly various constants.

1692
// C/C++ argument slots size.
1693 1694
const int kCArgSlotCount = 4;
const int kCArgsSlotsSize = kCArgSlotCount * Instruction::kInstrSize;
1695
const int kInvalidStackOffset = -1;
1696
// JS argument slots size.
1697
const int kJSArgsSlotsSize = 0 * Instruction::kInstrSize;
1698
// Assembly builtins argument slots size.
1699
const int kBArgsSlotsSize = 0 * Instruction::kInstrSize;
1700

1701
const int kBranchReturnOffset = 2 * Instruction::kInstrSize;
1702

1703
InstructionBase::Type InstructionBase::InstructionType() const {
1704 1705
  switch (OpcodeFieldRaw()) {
    case SPECIAL:
1706 1707
      if (FunctionFieldToBitNumber(FunctionFieldRaw()) &
          kFunctionFieldRegisterTypeMask) {
1708 1709
        return kRegisterType;
      }
1710
      return kUnsupported;
1711 1712 1713 1714 1715 1716 1717 1718 1719 1720 1721 1722 1723 1724 1725 1726 1727 1728 1729 1730 1731
    case SPECIAL2:
      switch (FunctionFieldRaw()) {
        case MUL:
        case CLZ:
          return kRegisterType;
        default:
          return kUnsupported;
      }
      break;
    case SPECIAL3:
      switch (FunctionFieldRaw()) {
        case INS:
        case EXT:
          return kRegisterType;
        case BSHFL: {
          int sa = SaFieldRaw() >> kSaShift;
          switch (sa) {
            case BITSWAP:
            case WSBH:
            case SEB:
            case SEH:
1732
              return kRegisterType;
1733 1734 1735 1736 1737 1738 1739 1740 1741
          }
          sa >>= kBp2Bits;
          switch (sa) {
            case ALIGN:
              return kRegisterType;
            default:
              return kUnsupported;
          }
        }
1742 1743 1744 1745 1746
        case LL_R6:
        case SC_R6: {
          DCHECK(IsMipsArchVariant(kMips32r6));
          return kImmediateType;
        }
1747 1748 1749 1750 1751 1752 1753 1754 1755 1756
        default:
          return kUnsupported;
      }
      break;
    case COP1:  // Coprocessor instructions.
      switch (RsFieldRawNoAssert()) {
        case BC1:  // Branch on coprocessor condition.
        case BC1EQZ:
        case BC1NEZ:
          return kImmediateType;
1757 1758 1759 1760 1761 1762 1763 1764 1765 1766 1767 1768
        // MSA Branch instructions
        case BZ_V:
        case BNZ_V:
        case BZ_B:
        case BZ_H:
        case BZ_W:
        case BZ_D:
        case BNZ_B:
        case BNZ_H:
        case BNZ_W:
        case BNZ_D:
          return kImmediateType;
1769 1770 1771 1772 1773 1774 1775 1776 1777 1778 1779 1780
        default:
          return kRegisterType;
      }
      break;
    case COP1X:
      return kRegisterType;

    // 26 bits immediate type instructions. e.g.: j imm26.
    case J:
    case JAL:
      return kJumpType;

1781 1782 1783 1784 1785 1786 1787 1788
    case MSA:
      switch (MSAMinorOpcodeField()) {
        case kMsaMinor3R:
        case kMsaMinor3RF:
        case kMsaMinorVEC:
        case kMsaMinor2R:
        case kMsaMinor2RF:
          return kRegisterType;
1789 1790 1791 1792 1793 1794 1795 1796 1797
        case kMsaMinorELM:
          switch (InstructionBits() & kMsaLongerELMMask) {
            case CFCMSA:
            case CTCMSA:
            case MOVE_V:
              return kRegisterType;
            default:
              return kImmediateType;
          }
1798 1799 1800 1801
        default:
          return kImmediateType;
      }

1802 1803 1804 1805 1806 1807 1808
    default:
        return kImmediateType;
  }
}

#undef OpcodeToBitNumber
#undef FunctionFieldToBitNumber
1809 1810 1811 1812 1813 1814 1815 1816 1817 1818 1819 1820 1821 1822 1823 1824 1825 1826 1827 1828 1829 1830 1831 1832 1833 1834 1835 1836 1837 1838 1839 1840 1841 1842 1843 1844 1845 1846 1847 1848 1849 1850 1851 1852 1853 1854 1855 1856 1857 1858 1859 1860 1861 1862 1863 1864 1865 1866 1867 1868 1869 1870 1871 1872 1873 1874 1875 1876 1877 1878 1879 1880 1881 1882 1883 1884 1885 1886 1887 1888 1889 1890 1891 1892 1893 1894 1895 1896 1897 1898 1899 1900 1901 1902 1903 1904 1905 1906 1907 1908 1909 1910

// -----------------------------------------------------------------------------
// Instructions.

template <class P>
bool InstructionGetters<P>::IsLinkingInstruction() const {
  uint32_t op = this->OpcodeFieldRaw();
  switch (op) {
    case JAL:
      return true;
    case POP76:
      if (this->RsFieldRawNoAssert() == JIALC)
        return true;  // JIALC
      else
        return false;  // BNEZC
    case REGIMM:
      switch (this->RtFieldRaw()) {
        case BGEZAL:
        case BLTZAL:
          return true;
        default:
          return false;
      }
    case SPECIAL:
      switch (this->FunctionFieldRaw()) {
        case JALR:
          return true;
        default:
          return false;
      }
    default:
      return false;
  }
}

template <class P>
bool InstructionGetters<P>::IsTrap() const {
  if (this->OpcodeFieldRaw() != SPECIAL) {
    return false;
  } else {
    switch (this->FunctionFieldRaw()) {
      case BREAK:
      case TGE:
      case TGEU:
      case TLT:
      case TLTU:
      case TEQ:
      case TNE:
        return true;
      default:
        return false;
    }
  }
}

// static
template <class T>
bool InstructionGetters<T>::IsForbiddenAfterBranchInstr(Instr instr) {
  Opcode opcode = static_cast<Opcode>(instr & kOpcodeMask);
  switch (opcode) {
    case J:
    case JAL:
    case BEQ:
    case BNE:
    case BLEZ:  // POP06 bgeuc/bleuc, blezalc, bgezalc
    case BGTZ:  // POP07 bltuc/bgtuc, bgtzalc, bltzalc
    case BEQL:
    case BNEL:
    case BLEZL:  // POP26 bgezc, blezc, bgec/blec
    case BGTZL:  // POP27 bgtzc, bltzc, bltc/bgtc
    case BC:
    case BALC:
    case POP10:  // beqzalc, bovc, beqc
    case POP30:  // bnezalc, bnvc, bnec
    case POP66:  // beqzc, jic
    case POP76:  // bnezc, jialc
      return true;
    case REGIMM:
      switch (instr & kRtFieldMask) {
        case BLTZ:
        case BGEZ:
        case BLTZAL:
        case BGEZAL:
          return true;
        default:
          return false;
      }
      break;
    case SPECIAL:
      switch (instr & kFunctionFieldMask) {
        case JR:
        case JALR:
          return true;
        default:
          return false;
      }
      break;
    case COP1:
      switch (instr & kRsFieldMask) {
        case BC1:
        case BC1EQZ:
        case BC1NEZ:
1911 1912 1913 1914 1915 1916 1917 1918 1919 1920
        case BZ_V:
        case BZ_B:
        case BZ_H:
        case BZ_W:
        case BZ_D:
        case BNZ_V:
        case BNZ_B:
        case BNZ_H:
        case BNZ_W:
        case BNZ_D:
1921 1922 1923 1924 1925 1926 1927 1928 1929 1930
          return true;
          break;
        default:
          return false;
      }
      break;
    default:
      return false;
  }
}
1931 1932
}  // namespace internal
}  // namespace v8
1933 1934

#endif    // #ifndef V8_MIPS_CONSTANTS_H_