constants-mips.h 39.8 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 126 127

#define __STDC_FORMAT_MACROS
#include <inttypes.h>

128 129 130 131 132 133 134
// 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.

135 136
namespace v8 {
namespace internal {
137 138

// -----------------------------------------------------------------------------
139
// Registers and FPURegisters.
140 141

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

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

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

// Number coprocessor registers.
152 153
const int kNumFPURegisters = 32;
const int kInvalidFPURegister = -1;
154

155
// FPU (coprocessor 1) control registers. Currently only FCSR is implemented.
156 157
const int kFCSRRegister = 31;
const int kInvalidFPUControlRegister = -1;
158
const uint32_t kFPUInvalidResult = static_cast<uint32_t>(1 << 31) - 1;
159
const int32_t kFPUInvalidResultNegative = static_cast<int32_t>(1 << 31);
160 161
const uint64_t kFPU64InvalidResult =
    static_cast<uint64_t>(static_cast<uint64_t>(1) << 63) - 1;
162 163
const int64_t kFPU64InvalidResultNegative =
    static_cast<int64_t>(static_cast<uint64_t>(1) << 63);
164 165

// FCSR constants.
166 167 168 169 170
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;
171
const uint32_t kFCSRNaN2008FlagBit = 18;
172 173 174 175 176 177

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;
178
const uint32_t kFCSRNaN2008FlagMask = 1 << kFCSRNaN2008FlagBit;
179 180

const uint32_t kFCSRFlagMask =
181 182 183 184 185 186
    kFCSRInexactFlagMask |
    kFCSRUnderflowFlagMask |
    kFCSROverflowFlagMask |
    kFCSRDivideByZeroFlagMask |
    kFCSRInvalidOpFlagMask;

187
const uint32_t kFCSRExceptionFlagMask = kFCSRFlagMask ^ kFCSRInexactFlagMask;
188

plind44@gmail.com's avatar
plind44@gmail.com committed
189 190 191 192 193 194 195 196 197 198
// '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;

199 200 201 202 203 204 205 206 207 208 209
// 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;
210
    const char* name;
211 212 213 214 215 216 217 218 219 220 221
  };

  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.
222
class FPURegisters {
223 224 225 226 227 228 229 230 231
 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;
232
    const char* name;
233 234 235
  };

 private:
236
  static const char* names_[kNumFPURegisters];
237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253
  static const RegisterAlias aliases_[];
};


// -----------------------------------------------------------------------------
// 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
};

254 255 256 257 258 259 260
// 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.
261 262
const uint32_t kMaxWatchpointCode = 31;
const uint32_t kMaxStopCode = 127;
263 264 265
STATIC_ASSERT(kMaxWatchpointCode < kMaxStopCode);


266
// ----- Fields offset and length.
267 268 269 270 271 272 273 274 275 276
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;
277
const int kLsaSaBits = 2;
278 279 280
const int kFunctionShift = 0;
const int kFunctionBits  = 6;
const int kLuiShift      = 16;
281 282
const int kBp2Shift = 6;
const int kBp2Bits = 2;
283 284 285

const int kImm16Shift = 0;
const int kImm16Bits  = 16;
286 287 288 289
const int kImm18Shift = 0;
const int kImm18Bits = 18;
const int kImm19Shift = 0;
const int kImm19Bits = 19;
290 291
const int kImm21Shift = 0;
const int kImm21Bits  = 21;
292 293 294 295
const int kImm26Shift = 0;
const int kImm26Bits  = 26;
const int kImm28Shift = 0;
const int kImm28Bits  = 28;
296 297
const int kImm32Shift = 0;
const int kImm32Bits  = 32;
298

299 300
// In branches and jumps immediate fields point to words, not bytes,
// and are therefore shifted by 2.
301 302
const int kImmFieldShift = 2;

303 304
const int kFrBits        = 5;
const int kFrShift       = 21;
305 306 307 308 309 310 311 312 313 314 315 316
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;
317

318
// ----- Miscellaneous useful masks.
319
// Instruction bit masks.
320 321
const int kOpcodeMask = ((1 << kOpcodeBits) - 1) << kOpcodeShift;
const int kImm16Mask = ((1 << kImm16Bits) - 1) << kImm16Shift;
322 323 324
const int kImm18Mask = ((1 << kImm18Bits) - 1) << kImm18Shift;
const int kImm19Mask = ((1 << kImm19Bits) - 1) << kImm19Shift;
const int kImm21Mask = ((1 << kImm21Bits) - 1) << kImm21Shift;
325 326 327 328 329 330 331
const int kImm26Mask = ((1 << kImm26Bits) - 1) << kImm26Shift;
const int kImm28Mask = ((1 << kImm28Bits) - 1) << kImm28Shift;
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;
332
// Misc masks.
333 334 335 336
const int kHiMask = 0xffff << 16;
const int kLoMask = 0xffff;
const int kSignMask = 0x80000000;
const int kJumpAddrMask = (1 << (kImm26Bits + kImmFieldShift)) - 1;
337 338 339 340

// ----- 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.
341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405
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,
  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,

  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,

  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
406
  POP30 = DADDI,  // bnezalc, bnvc, bnec
407 408
};

409
enum SecondaryField : uint32_t {
410
  // SPECIAL Encoding of Function Field.
411 412 413 414 415
  SLL = ((0U << 3) + 0),
  MOVCI = ((0U << 3) + 1),
  SRL = ((0U << 3) + 2),
  SRA = ((0U << 3) + 3),
  SLLV = ((0U << 3) + 4),
416
  LSA = ((0U << 3) + 5),
417 418 419 420 421 422 423 424
  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),
425
  SYNC = ((1U << 3) + 7),
426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456

  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),
457 458

  // Multiply integers in r6.
459 460 461
  MUL_MUH = ((3U << 3) + 0),    // MUL, MUH.
  MUL_MUH_U = ((3U << 3) + 1),  // MUL_U, MUH_U.
  RINT = ((3U << 3) + 2),
462

463 464 465 466
  MUL_OP = ((0U << 3) + 2),
  MUH_OP = ((0U << 3) + 3),
  DIV_OP = ((0U << 3) + 2),
  MOD_OP = ((0U << 3) + 3),
467

468 469
  DIV_MOD = ((3U << 3) + 2),
  DIV_MOD_U = ((3U << 3) + 3),
470 471

  // SPECIAL2 Encoding of Function Field.
472 473 474
  MUL = ((0U << 3) + 2),
  CLZ = ((4U << 3) + 0),
  CLO = ((4U << 3) + 1),
475 476

  // SPECIAL3 Encoding of Function Field.
477 478 479
  EXT = ((0U << 3) + 0),
  INS = ((0U << 3) + 4),
  BSHFL = ((4U << 3) + 0),
480 481

  // SPECIAL3 Encoding of sa Field.
482 483 484 485 486
  BITSWAP = ((0U << 3) + 0),
  ALIGN = ((0U << 3) + 2),
  WSBH = ((0U << 3) + 2),
  SEB = ((2U << 3) + 0),
  SEH = ((3U << 3) + 0),
487 488

  // REGIMM  encoding of rt Field.
489 490 491 492 493
  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,
494 495

  // COP1 Encoding of rs Field.
496 497 498 499 500 501 502 503 504 505 506 507
  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,
508
  // COP1 Encoding of Function Field When rs=S.
509

510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527
  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),
528 529
  MADDF_S = ((3U << 3) + 0),
  MSUBF_S = ((3U << 3) + 1),
530 531 532 533 534
  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),
535

536
  // COP1 Encoding of Function Field When rs=D.
537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554
  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),
555 556
  MADDF_D = ((3U << 3) + 0),
  MSUBF_D = ((3U << 3) + 1),
557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572
  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),
573

574
  // COP1 Encoding of Function Field When rs=W or L.
575 576 577 578 579 580
  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,
581
  // COP1 CMP positive predicates Bit 5..4 = 00.
582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597
  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),
598
  // COP1 CMP negative predicates Bit 5..4 = 01.
599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621
  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.
622
  // COP1 Encoding of Function Field When rs=PS.
623

624
  // COP1X Encoding of Function Field.
625
  MADD_S = ((4U << 3) + 0),
626
  MADD_D = ((4U << 3) + 1),
627 628
  MSUB_S = ((5U << 3) + 0),
  MSUB_D = ((5U << 3) + 1),
629

630
  // PCREL Encoding of rt Field.
631 632 633 634
  ADDIUPC = ((0U << 2) + 0),
  LWPC = ((0U << 2) + 1),
  AUIPC = ((3U << 3) + 6),
  ALUIPC = ((3U << 3) + 7),
635 636

  // POP66 Encoding of rs Field.
637
  JIC = ((0U << 5) + 0),
638 639

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

642
  NULLSF = 0U
643 644 645
};

// ----- Emulated conditions.
646
// On MIPS we use this enum to abstract from conditional branch instructions.
647
// The 'U' prefix is used to specify unsigned comparisons.
648
// Opposite conditions must be paired as odd/even numbers
649
// because 'NegateCondition' function flips LSB to negate condition.
650 651
enum Condition {
  // Any value < 0 is considered no_condition.
Benedikt Meurer's avatar
Benedikt Meurer committed
652 653 654 655 656
  kNoCondition = -1,
  overflow = 0,
  no_overflow = 1,
  Uless = 2,
  Ugreater_equal = 3,
657 658 659 660
  Uless_equal = 4,
  Ugreater = 5,
  equal = 6,
  not_equal = 7,  // Unordered or Not Equal.
Benedikt Meurer's avatar
Benedikt Meurer committed
661 662 663 664 665
  negative = 8,
  positive = 9,
  parity_even = 10,
  parity_odd = 11,
  less = 12,
666
  greater_equal = 13,
Benedikt Meurer's avatar
Benedikt Meurer committed
667 668 669
  less_equal = 14,
  greater = 15,
  ueq = 16,  // Unordered or Equal.
670
  ogl = 17,  // Ordered and Not Equal.
Benedikt Meurer's avatar
Benedikt Meurer committed
671
  cc_always = 18,
672

673
  // Aliases.
Benedikt Meurer's avatar
Benedikt Meurer committed
674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693
  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,
694 695 696 697
  ult = Uless,
  uge = Ugreater_equal,
  ule = Uless_equal,
  ugt = Ugreater,
Benedikt Meurer's avatar
Benedikt Meurer committed
698
  cc_default = kNoCondition
699 700
};

701 702 703 704 705 706

// 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) {
707
  DCHECK(cc != cc_always);
708 709 710 711
  return static_cast<Condition>(cc ^ 1);
}


712 713 714 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
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;
  }
}


745
// Commute a condition such that {a cond b == b cond' a}.
746
inline Condition CommuteCondition(Condition cc) {
747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765
  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;
766
  }
767 768 769
}


770 771
// ----- Coprocessor conditions.
enum FPUCondition {
772 773
  kNoFPUCondition = -1,

774 775 776 777 778 779 780 781 782 783 784 785 786 787 788
  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.
789 790 791 792 793 794 795 796 797 798 799 800 801 802
};


// 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,
803 804 805 806 807 808
  kRoundToMinusInf = RM,

  mode_round = RN,
  mode_ceil = RP,
  mode_floor = RM,
  mode_trunc = RZ
809 810
};

811
const uint32_t kFPURoundingModeMask = 3 << 0;
812 813 814 815

enum CheckForInexactConversion {
  kCheckForInexactConversion,
  kDontCheckForInexactConversion
816 817
};

818
enum class MaxMinKind : int { kMin = 0, kMax = 1 };
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
// -----------------------------------------------------------------------------
// 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;
848
// lw(r, MemOperand(sp, 0))
849 850 851 852 853 854 855 856 857 858 859
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;

860 861 862 863 864
// 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;

865 866 867 868
static constexpr uint64_t OpcodeToBitNumber(Opcode opcode) {
  return 1ULL << (static_cast<uint32_t>(opcode) >> kOpcodeShift);
}

869
class InstructionBase {
870 871
 public:
  enum {
872 873
    kInstrSize = 4,
    kInstrSizeLog2 = 2,
874
    // On MIPS PC cannot actually be directly accessed. We behave as if PC was
875
    // always the value of the current instruction being executed.
876 877 878
    kPCReadOffset = 0
  };

879 880 881
  // Instruction type.
  enum Type { kRegisterType, kImmediateType, kJumpType, kUnsupported = -1 };

882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898
  // 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 {
899
    return (InstructionBits() >> lo) & ((2U << (hi - lo)) - 1);
900
  }
901 902


903
  static constexpr uint64_t kOpcodeImmediateTypeMask =
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
      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) |
930 931 932 933 934 935 936 937 938 939 940 941 942 943
      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) |
944
      FunctionFieldToBitNumber(SELNEZ_S) | FunctionFieldToBitNumber(SYNC);
945 946

  // Accessors for the different named fields used in the MIPS encoding.
947
  inline Opcode OpcodeValue() const {
948 949 950 951
    return static_cast<Opcode>(
        Bits(kOpcodeShift + kOpcodeBits - 1, kOpcodeShift));
  }

952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968
  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.
969
  inline Type InstructionType() const;
970 971 972 973 974 975 976 977

 protected:
  InstructionBase() {}
};

template <class T>
class InstructionGetters : public T {
 public:
978
  inline int RsValue() const {
979 980 981
    DCHECK(this->InstructionType() == InstructionBase::kRegisterType ||
           this->InstructionType() == InstructionBase::kImmediateType);
    return InstructionBase::Bits(kRsShift + kRsBits - 1, kRsShift);
982 983
  }

984
  inline int RtValue() const {
985 986 987
    DCHECK(this->InstructionType() == InstructionBase::kRegisterType ||
           this->InstructionType() == InstructionBase::kImmediateType);
    return this->Bits(kRtShift + kRtBits - 1, kRtShift);
988 989
  }

990
  inline int RdValue() const {
991 992
    DCHECK(this->InstructionType() == InstructionBase::kRegisterType);
    return this->Bits(kRdShift + kRdBits - 1, kRdShift);
993 994
  }

995
  inline int SaValue() const {
996 997
    DCHECK(this->InstructionType() == InstructionBase::kRegisterType);
    return this->Bits(kSaShift + kSaBits - 1, kSaShift);
998 999
  }

1000
  inline int LsaSaValue() const {
1001 1002
    DCHECK(this->InstructionType() == InstructionBase::kRegisterType);
    return this->Bits(kSaShift + kLsaSaBits - 1, kSaShift);
1003 1004
  }

1005
  inline int FunctionValue() const {
1006 1007 1008
    DCHECK(this->InstructionType() == InstructionBase::kRegisterType ||
           this->InstructionType() == InstructionBase::kImmediateType);
    return this->Bits(kFunctionShift + kFunctionBits - 1, kFunctionShift);
1009 1010
  }

1011
  inline int FdValue() const {
1012
    return this->Bits(kFdShift + kFdBits - 1, kFdShift);
1013 1014 1015
  }

  inline int FsValue() const {
1016
    return this->Bits(kFsShift + kFsBits - 1, kFsShift);
1017 1018 1019
  }

  inline int FtValue() const {
1020
    return this->Bits(kFtShift + kFtBits - 1, kFtShift);
1021 1022
  }

1023
  inline int FrValue() const {
1024
    return this->Bits(kFrShift + kFrBits - 1, kFrShift);
1025 1026
  }

1027
  inline int Bp2Value() const {
1028 1029
    DCHECK(this->InstructionType() == InstructionBase::kRegisterType);
    return this->Bits(kBp2Shift + kBp2Bits - 1, kBp2Shift);
1030 1031
  }

1032 1033
  // Float Compare condition code instruction bits.
  inline int FCccValue() const {
1034
    return this->Bits(kFCccShift + kFCccBits - 1, kFCccShift);
1035 1036 1037 1038
  }

  // Float Branch condition code instruction bits.
  inline int FBccValue() const {
1039
    return this->Bits(kFBccShift + kFBccBits - 1, kFBccShift);
1040 1041 1042 1043
  }

  // Float Branch true/false instruction bit.
  inline int FBtrueValue() const {
1044
    return this->Bits(kFBtrueShift + kFBtrueBits - 1, kFBtrueShift);
1045 1046 1047 1048
  }

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

  inline int RsFieldRaw() const {
1053 1054 1055
    DCHECK(this->InstructionType() == InstructionBase::kRegisterType ||
           this->InstructionType() == InstructionBase::kImmediateType);
    return this->InstructionBits() & kRsFieldMask;
1056 1057
  }

1058
  inline int RtFieldRaw() const {
1059 1060 1061
    DCHECK(this->InstructionType() == InstructionBase::kRegisterType ||
           this->InstructionType() == InstructionBase::kImmediateType);
    return this->InstructionBits() & kRtFieldMask;
1062 1063 1064
  }

  inline int RdFieldRaw() const {
1065 1066
    DCHECK(this->InstructionType() == InstructionBase::kRegisterType);
    return this->InstructionBits() & kRdFieldMask;
1067 1068 1069
  }

  inline int SaFieldRaw() const {
1070
    return this->InstructionBits() & kSaFieldMask;
1071 1072 1073
  }

  inline int FunctionFieldRaw() const {
1074
    return this->InstructionBits() & kFunctionFieldMask;
1075 1076 1077
  }

  // Get the secondary field according to the opcode.
1078
  inline int SecondaryValue() const {
1079
    Opcode op = this->OpcodeFieldRaw();
1080 1081 1082
    switch (op) {
      case SPECIAL:
      case SPECIAL2:
1083
        return FunctionValue();
1084
      case COP1:
1085
        return RsValue();
1086
      case REGIMM:
1087
        return RtValue();
1088 1089 1090 1091 1092
      default:
        return NULLSF;
    }
  }

1093
  inline int32_t ImmValue(int bits) const {
1094 1095
    DCHECK(this->InstructionType() == InstructionBase::kImmediateType);
    return this->Bits(bits - 1, 0);
1096 1097
  }

1098
  inline int32_t Imm16Value() const {
1099 1100
    DCHECK(this->InstructionType() == InstructionBase::kImmediateType);
    return this->Bits(kImm16Shift + kImm16Bits - 1, kImm16Shift);
1101 1102
  }

1103
  inline int32_t Imm18Value() const {
1104 1105
    DCHECK(this->InstructionType() == InstructionBase::kImmediateType);
    return this->Bits(kImm18Shift + kImm18Bits - 1, kImm18Shift);
1106 1107 1108
  }

  inline int32_t Imm19Value() const {
1109 1110
    DCHECK(this->InstructionType() == InstructionBase::kImmediateType);
    return this->Bits(kImm19Shift + kImm19Bits - 1, kImm19Shift);
1111 1112
  }

1113
  inline int32_t Imm21Value() const {
1114 1115
    DCHECK(this->InstructionType() == InstructionBase::kImmediateType);
    return this->Bits(kImm21Shift + kImm21Bits - 1, kImm21Shift);
1116 1117
  }

1118
  inline int32_t Imm26Value() const {
1119 1120 1121
    DCHECK((this->InstructionType() == InstructionBase::kJumpType) ||
           (this->InstructionType() == InstructionBase::kImmediateType));
    return this->Bits(kImm26Shift + kImm26Bits - 1, kImm26Shift);
1122 1123
  }

1124 1125 1126 1127 1128
  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 {
1129
    return IsForbiddenAfterBranchInstr(this->InstructionBits());
1130 1131 1132 1133 1134 1135
  }

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

1136
  // Say if the instruction 'links'. e.g. jal, bal.
1137
  bool IsLinkingInstruction() const;
1138
  // Say if the instruction is a break or a trap.
1139
  bool IsTrap() const;
1140
};
1141

1142 1143
class Instruction : public InstructionGetters<InstructionBase> {
 public:
1144 1145 1146 1147
  // 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.
1148
  static Instruction* At(byte* pc) {
1149 1150 1151 1152
    return reinterpret_cast<Instruction*>(pc);
  }

 private:
1153
  // We need to prevent the creation of instances of class Instruction.
1154 1155 1156 1157 1158 1159 1160
  DISALLOW_IMPLICIT_CONSTRUCTORS(Instruction);
};


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

1161
// C/C++ argument slots size.
1162 1163
const int kCArgSlotCount = 4;
const int kCArgsSlotsSize = kCArgSlotCount * Instruction::kInstrSize;
1164
const int kInvalidStackOffset = -1;
1165
// JS argument slots size.
1166
const int kJSArgsSlotsSize = 0 * Instruction::kInstrSize;
1167
// Assembly builtins argument slots size.
1168
const int kBArgsSlotsSize = 0 * Instruction::kInstrSize;
1169

1170
const int kBranchReturnOffset = 2 * Instruction::kInstrSize;
1171

1172
InstructionBase::Type InstructionBase::InstructionType() const {
1173 1174
  switch (OpcodeFieldRaw()) {
    case SPECIAL:
1175 1176
      if (FunctionFieldToBitNumber(FunctionFieldRaw()) &
          kFunctionFieldRegisterTypeMask) {
1177 1178
        return kRegisterType;
      }
1179
      return kUnsupported;
1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200
    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:
1201
              return kRegisterType;
1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239
          }
          sa >>= kBp2Bits;
          switch (sa) {
            case ALIGN:
              return kRegisterType;
            default:
              return kUnsupported;
          }
        }
        default:
          return kUnsupported;
      }
      break;
    case COP1:  // Coprocessor instructions.
      switch (RsFieldRawNoAssert()) {
        case BC1:  // Branch on coprocessor condition.
        case BC1EQZ:
        case BC1NEZ:
          return kImmediateType;
        default:
          return kRegisterType;
      }
      break;
    case COP1X:
      return kRegisterType;

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

    default:
        return kImmediateType;
  }
}

#undef OpcodeToBitNumber
#undef FunctionFieldToBitNumber
1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 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 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327 1328 1329 1330 1331 1332 1333 1334 1335 1336 1337 1338 1339 1340 1341 1342 1343 1344 1345 1346 1347 1348 1349 1350 1351

// -----------------------------------------------------------------------------
// 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:
          return true;
          break;
        default:
          return false;
      }
      break;
    default:
      return false;
  }
}
1352 1353
}  // namespace internal
}  // namespace v8
1354 1355

#endif    // #ifndef V8_MIPS_CONSTANTS_H_