1// Copyright 2012 the V8 project authors. All rights reserved. 2// Redistribution and use in source and binary forms, with or without 3// modification, are permitted provided that the following conditions are 4// met: 5// 6// * Redistributions of source code must retain the above copyright 7// notice, this list of conditions and the following disclaimer. 8// * Redistributions in binary form must reproduce the above 9// copyright notice, this list of conditions and the following 10// disclaimer in the documentation and/or other materials provided 11// with the distribution. 12// * Neither the name of Google Inc. nor the names of its 13// contributors may be used to endorse or promote products derived 14// from this software without specific prior written permission. 15// 16// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 17// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 18// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 19// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 20// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 21// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 22// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 26// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 28#ifndef V8_MIPS_CONSTANTS_H_ 29#define V8_MIPS_CONSTANTS_H_ 30 31// UNIMPLEMENTED_ macro for MIPS. 32#ifdef DEBUG 33#define UNIMPLEMENTED_MIPS() \ 34 v8::internal::PrintF("%s, \tline %d: \tfunction %s not implemented. \n", \ 35 __FILE__, __LINE__, __func__) 36#else 37#define UNIMPLEMENTED_MIPS() 38#endif 39 40#define UNSUPPORTED_MIPS() v8::internal::PrintF("Unsupported instruction.\n") 41 42enum ArchVariants { 43 kMips32r2, 44 kMips32r1, 45 kLoongson 46}; 47 48#ifdef _MIPS_ARCH_MIPS32R2 49 static const ArchVariants kArchVariant = kMips32r2; 50#elif _MIPS_ARCH_LOONGSON 51// The loongson flag refers to the LOONGSON architectures based on MIPS-III, 52// which predates (and is a subset of) the mips32r2 and r1 architectures. 53 static const ArchVariants kArchVariant = kLoongson; 54#else 55 static const ArchVariants kArchVariant = kMips32r1; 56#endif 57 58 59#if(defined(__mips_hard_float) && __mips_hard_float != 0) 60// Use floating-point coprocessor instructions. This flag is raised when 61// -mhard-float is passed to the compiler. 62const bool IsMipsSoftFloatABI = false; 63#elif(defined(__mips_soft_float) && __mips_soft_float != 0) 64// Not using floating-point coprocessor instructions. This flag is raised when 65// -msoft-float is passed to the compiler. 66const bool IsMipsSoftFloatABI = true; 67#else 68const bool IsMipsSoftFloatABI = true; 69#endif 70 71 72// Defines constants and accessor classes to assemble, disassemble and 73// simulate MIPS32 instructions. 74// 75// See: MIPS32 Architecture For Programmers 76// Volume II: The MIPS32 Instruction Set 77// Try www.cs.cornell.edu/courses/cs3410/2008fa/MIPS_Vol2.pdf. 78 79namespace v8 { 80namespace internal { 81 82// ----------------------------------------------------------------------------- 83// Registers and FPURegisters. 84 85// Number of general purpose registers. 86const int kNumRegisters = 32; 87const int kInvalidRegister = -1; 88 89// Number of registers with HI, LO, and pc. 90const int kNumSimuRegisters = 35; 91 92// In the simulator, the PC register is simulated as the 34th register. 93const int kPCRegister = 34; 94 95// Number coprocessor registers. 96const int kNumFPURegisters = 32; 97const int kInvalidFPURegister = -1; 98 99// FPU (coprocessor 1) control registers. Currently only FCSR is implemented. 100const int kFCSRRegister = 31; 101const int kInvalidFPUControlRegister = -1; 102const uint32_t kFPUInvalidResult = (uint32_t) (1 << 31) - 1; 103 104// FCSR constants. 105const uint32_t kFCSRInexactFlagBit = 2; 106const uint32_t kFCSRUnderflowFlagBit = 3; 107const uint32_t kFCSROverflowFlagBit = 4; 108const uint32_t kFCSRDivideByZeroFlagBit = 5; 109const uint32_t kFCSRInvalidOpFlagBit = 6; 110 111const uint32_t kFCSRInexactFlagMask = 1 << kFCSRInexactFlagBit; 112const uint32_t kFCSRUnderflowFlagMask = 1 << kFCSRUnderflowFlagBit; 113const uint32_t kFCSROverflowFlagMask = 1 << kFCSROverflowFlagBit; 114const uint32_t kFCSRDivideByZeroFlagMask = 1 << kFCSRDivideByZeroFlagBit; 115const uint32_t kFCSRInvalidOpFlagMask = 1 << kFCSRInvalidOpFlagBit; 116 117const uint32_t kFCSRFlagMask = 118 kFCSRInexactFlagMask | 119 kFCSRUnderflowFlagMask | 120 kFCSROverflowFlagMask | 121 kFCSRDivideByZeroFlagMask | 122 kFCSRInvalidOpFlagMask; 123 124const uint32_t kFCSRExceptionFlagMask = kFCSRFlagMask ^ kFCSRInexactFlagMask; 125 126// Helper functions for converting between register numbers and names. 127class Registers { 128 public: 129 // Return the name of the register. 130 static const char* Name(int reg); 131 132 // Lookup the register number for the name provided. 133 static int Number(const char* name); 134 135 struct RegisterAlias { 136 int reg; 137 const char* name; 138 }; 139 140 static const int32_t kMaxValue = 0x7fffffff; 141 static const int32_t kMinValue = 0x80000000; 142 143 private: 144 static const char* names_[kNumSimuRegisters]; 145 static const RegisterAlias aliases_[]; 146}; 147 148// Helper functions for converting between register numbers and names. 149class FPURegisters { 150 public: 151 // Return the name of the register. 152 static const char* Name(int reg); 153 154 // Lookup the register number for the name provided. 155 static int Number(const char* name); 156 157 struct RegisterAlias { 158 int creg; 159 const char* name; 160 }; 161 162 private: 163 static const char* names_[kNumFPURegisters]; 164 static const RegisterAlias aliases_[]; 165}; 166 167 168// ----------------------------------------------------------------------------- 169// Instructions encoding constants. 170 171// On MIPS all instructions are 32 bits. 172typedef int32_t Instr; 173 174// Special Software Interrupt codes when used in the presence of the MIPS 175// simulator. 176enum SoftwareInterruptCodes { 177 // Transition to C code. 178 call_rt_redirected = 0xfffff 179}; 180 181// On MIPS Simulator breakpoints can have different codes: 182// - Breaks between 0 and kMaxWatchpointCode are treated as simple watchpoints, 183// the simulator will run through them and print the registers. 184// - Breaks between kMaxWatchpointCode and kMaxStopCode are treated as stop() 185// instructions (see Assembler::stop()). 186// - Breaks larger than kMaxStopCode are simple breaks, dropping you into the 187// debugger. 188const uint32_t kMaxWatchpointCode = 31; 189const uint32_t kMaxStopCode = 127; 190STATIC_ASSERT(kMaxWatchpointCode < kMaxStopCode); 191 192 193// ----- Fields offset and length. 194const int kOpcodeShift = 26; 195const int kOpcodeBits = 6; 196const int kRsShift = 21; 197const int kRsBits = 5; 198const int kRtShift = 16; 199const int kRtBits = 5; 200const int kRdShift = 11; 201const int kRdBits = 5; 202const int kSaShift = 6; 203const int kSaBits = 5; 204const int kFunctionShift = 0; 205const int kFunctionBits = 6; 206const int kLuiShift = 16; 207 208const int kImm16Shift = 0; 209const int kImm16Bits = 16; 210const int kImm26Shift = 0; 211const int kImm26Bits = 26; 212const int kImm28Shift = 0; 213const int kImm28Bits = 28; 214 215// In branches and jumps immediate fields point to words, not bytes, 216// and are therefore shifted by 2. 217const int kImmFieldShift = 2; 218 219const int kFsShift = 11; 220const int kFsBits = 5; 221const int kFtShift = 16; 222const int kFtBits = 5; 223const int kFdShift = 6; 224const int kFdBits = 5; 225const int kFCccShift = 8; 226const int kFCccBits = 3; 227const int kFBccShift = 18; 228const int kFBccBits = 3; 229const int kFBtrueShift = 16; 230const int kFBtrueBits = 1; 231 232// ----- Miscellaneous useful masks. 233// Instruction bit masks. 234const int kOpcodeMask = ((1 << kOpcodeBits) - 1) << kOpcodeShift; 235const int kImm16Mask = ((1 << kImm16Bits) - 1) << kImm16Shift; 236const int kImm26Mask = ((1 << kImm26Bits) - 1) << kImm26Shift; 237const int kImm28Mask = ((1 << kImm28Bits) - 1) << kImm28Shift; 238const int kRsFieldMask = ((1 << kRsBits) - 1) << kRsShift; 239const int kRtFieldMask = ((1 << kRtBits) - 1) << kRtShift; 240const int kRdFieldMask = ((1 << kRdBits) - 1) << kRdShift; 241const int kSaFieldMask = ((1 << kSaBits) - 1) << kSaShift; 242const int kFunctionFieldMask = ((1 << kFunctionBits) - 1) << kFunctionShift; 243// Misc masks. 244const int kHiMask = 0xffff << 16; 245const int kLoMask = 0xffff; 246const int kSignMask = 0x80000000; 247const int kJumpAddrMask = (1 << (kImm26Bits + kImmFieldShift)) - 1; 248 249// ----- MIPS Opcodes and Function Fields. 250// We use this presentation to stay close to the table representation in 251// MIPS32 Architecture For Programmers, Volume II: The MIPS32 Instruction Set. 252enum Opcode { 253 SPECIAL = 0 << kOpcodeShift, 254 REGIMM = 1 << kOpcodeShift, 255 256 J = ((0 << 3) + 2) << kOpcodeShift, 257 JAL = ((0 << 3) + 3) << kOpcodeShift, 258 BEQ = ((0 << 3) + 4) << kOpcodeShift, 259 BNE = ((0 << 3) + 5) << kOpcodeShift, 260 BLEZ = ((0 << 3) + 6) << kOpcodeShift, 261 BGTZ = ((0 << 3) + 7) << kOpcodeShift, 262 263 ADDI = ((1 << 3) + 0) << kOpcodeShift, 264 ADDIU = ((1 << 3) + 1) << kOpcodeShift, 265 SLTI = ((1 << 3) + 2) << kOpcodeShift, 266 SLTIU = ((1 << 3) + 3) << kOpcodeShift, 267 ANDI = ((1 << 3) + 4) << kOpcodeShift, 268 ORI = ((1 << 3) + 5) << kOpcodeShift, 269 XORI = ((1 << 3) + 6) << kOpcodeShift, 270 LUI = ((1 << 3) + 7) << kOpcodeShift, 271 272 COP1 = ((2 << 3) + 1) << kOpcodeShift, // Coprocessor 1 class. 273 BEQL = ((2 << 3) + 4) << kOpcodeShift, 274 BNEL = ((2 << 3) + 5) << kOpcodeShift, 275 BLEZL = ((2 << 3) + 6) << kOpcodeShift, 276 BGTZL = ((2 << 3) + 7) << kOpcodeShift, 277 278 SPECIAL2 = ((3 << 3) + 4) << kOpcodeShift, 279 SPECIAL3 = ((3 << 3) + 7) << kOpcodeShift, 280 281 LB = ((4 << 3) + 0) << kOpcodeShift, 282 LH = ((4 << 3) + 1) << kOpcodeShift, 283 LWL = ((4 << 3) + 2) << kOpcodeShift, 284 LW = ((4 << 3) + 3) << kOpcodeShift, 285 LBU = ((4 << 3) + 4) << kOpcodeShift, 286 LHU = ((4 << 3) + 5) << kOpcodeShift, 287 LWR = ((4 << 3) + 6) << kOpcodeShift, 288 SB = ((5 << 3) + 0) << kOpcodeShift, 289 SH = ((5 << 3) + 1) << kOpcodeShift, 290 SWL = ((5 << 3) + 2) << kOpcodeShift, 291 SW = ((5 << 3) + 3) << kOpcodeShift, 292 SWR = ((5 << 3) + 6) << kOpcodeShift, 293 294 LWC1 = ((6 << 3) + 1) << kOpcodeShift, 295 LDC1 = ((6 << 3) + 5) << kOpcodeShift, 296 297 SWC1 = ((7 << 3) + 1) << kOpcodeShift, 298 SDC1 = ((7 << 3) + 5) << kOpcodeShift 299}; 300 301enum SecondaryField { 302 // SPECIAL Encoding of Function Field. 303 SLL = ((0 << 3) + 0), 304 MOVCI = ((0 << 3) + 1), 305 SRL = ((0 << 3) + 2), 306 SRA = ((0 << 3) + 3), 307 SLLV = ((0 << 3) + 4), 308 SRLV = ((0 << 3) + 6), 309 SRAV = ((0 << 3) + 7), 310 311 JR = ((1 << 3) + 0), 312 JALR = ((1 << 3) + 1), 313 MOVZ = ((1 << 3) + 2), 314 MOVN = ((1 << 3) + 3), 315 BREAK = ((1 << 3) + 5), 316 317 MFHI = ((2 << 3) + 0), 318 MFLO = ((2 << 3) + 2), 319 320 MULT = ((3 << 3) + 0), 321 MULTU = ((3 << 3) + 1), 322 DIV = ((3 << 3) + 2), 323 DIVU = ((3 << 3) + 3), 324 325 ADD = ((4 << 3) + 0), 326 ADDU = ((4 << 3) + 1), 327 SUB = ((4 << 3) + 2), 328 SUBU = ((4 << 3) + 3), 329 AND = ((4 << 3) + 4), 330 OR = ((4 << 3) + 5), 331 XOR = ((4 << 3) + 6), 332 NOR = ((4 << 3) + 7), 333 334 SLT = ((5 << 3) + 2), 335 SLTU = ((5 << 3) + 3), 336 337 TGE = ((6 << 3) + 0), 338 TGEU = ((6 << 3) + 1), 339 TLT = ((6 << 3) + 2), 340 TLTU = ((6 << 3) + 3), 341 TEQ = ((6 << 3) + 4), 342 TNE = ((6 << 3) + 6), 343 344 // SPECIAL2 Encoding of Function Field. 345 MUL = ((0 << 3) + 2), 346 CLZ = ((4 << 3) + 0), 347 CLO = ((4 << 3) + 1), 348 349 // SPECIAL3 Encoding of Function Field. 350 EXT = ((0 << 3) + 0), 351 INS = ((0 << 3) + 4), 352 353 // REGIMM encoding of rt Field. 354 BLTZ = ((0 << 3) + 0) << 16, 355 BGEZ = ((0 << 3) + 1) << 16, 356 BLTZAL = ((2 << 3) + 0) << 16, 357 BGEZAL = ((2 << 3) + 1) << 16, 358 359 // COP1 Encoding of rs Field. 360 MFC1 = ((0 << 3) + 0) << 21, 361 CFC1 = ((0 << 3) + 2) << 21, 362 MFHC1 = ((0 << 3) + 3) << 21, 363 MTC1 = ((0 << 3) + 4) << 21, 364 CTC1 = ((0 << 3) + 6) << 21, 365 MTHC1 = ((0 << 3) + 7) << 21, 366 BC1 = ((1 << 3) + 0) << 21, 367 S = ((2 << 3) + 0) << 21, 368 D = ((2 << 3) + 1) << 21, 369 W = ((2 << 3) + 4) << 21, 370 L = ((2 << 3) + 5) << 21, 371 PS = ((2 << 3) + 6) << 21, 372 // COP1 Encoding of Function Field When rs=S. 373 ROUND_L_S = ((1 << 3) + 0), 374 TRUNC_L_S = ((1 << 3) + 1), 375 CEIL_L_S = ((1 << 3) + 2), 376 FLOOR_L_S = ((1 << 3) + 3), 377 ROUND_W_S = ((1 << 3) + 4), 378 TRUNC_W_S = ((1 << 3) + 5), 379 CEIL_W_S = ((1 << 3) + 6), 380 FLOOR_W_S = ((1 << 3) + 7), 381 CVT_D_S = ((4 << 3) + 1), 382 CVT_W_S = ((4 << 3) + 4), 383 CVT_L_S = ((4 << 3) + 5), 384 CVT_PS_S = ((4 << 3) + 6), 385 // COP1 Encoding of Function Field When rs=D. 386 ADD_D = ((0 << 3) + 0), 387 SUB_D = ((0 << 3) + 1), 388 MUL_D = ((0 << 3) + 2), 389 DIV_D = ((0 << 3) + 3), 390 SQRT_D = ((0 << 3) + 4), 391 ABS_D = ((0 << 3) + 5), 392 MOV_D = ((0 << 3) + 6), 393 NEG_D = ((0 << 3) + 7), 394 ROUND_L_D = ((1 << 3) + 0), 395 TRUNC_L_D = ((1 << 3) + 1), 396 CEIL_L_D = ((1 << 3) + 2), 397 FLOOR_L_D = ((1 << 3) + 3), 398 ROUND_W_D = ((1 << 3) + 4), 399 TRUNC_W_D = ((1 << 3) + 5), 400 CEIL_W_D = ((1 << 3) + 6), 401 FLOOR_W_D = ((1 << 3) + 7), 402 CVT_S_D = ((4 << 3) + 0), 403 CVT_W_D = ((4 << 3) + 4), 404 CVT_L_D = ((4 << 3) + 5), 405 C_F_D = ((6 << 3) + 0), 406 C_UN_D = ((6 << 3) + 1), 407 C_EQ_D = ((6 << 3) + 2), 408 C_UEQ_D = ((6 << 3) + 3), 409 C_OLT_D = ((6 << 3) + 4), 410 C_ULT_D = ((6 << 3) + 5), 411 C_OLE_D = ((6 << 3) + 6), 412 C_ULE_D = ((6 << 3) + 7), 413 // COP1 Encoding of Function Field When rs=W or L. 414 CVT_S_W = ((4 << 3) + 0), 415 CVT_D_W = ((4 << 3) + 1), 416 CVT_S_L = ((4 << 3) + 0), 417 CVT_D_L = ((4 << 3) + 1), 418 // COP1 Encoding of Function Field When rs=PS. 419 420 NULLSF = 0 421}; 422 423 424// ----- Emulated conditions. 425// On MIPS we use this enum to abstract from conditionnal branch instructions. 426// the 'U' prefix is used to specify unsigned comparisons. 427enum Condition { 428 // Any value < 0 is considered no_condition. 429 kNoCondition = -1, 430 431 overflow = 0, 432 no_overflow = 1, 433 Uless = 2, 434 Ugreater_equal= 3, 435 equal = 4, 436 not_equal = 5, 437 Uless_equal = 6, 438 Ugreater = 7, 439 negative = 8, 440 positive = 9, 441 parity_even = 10, 442 parity_odd = 11, 443 less = 12, 444 greater_equal = 13, 445 less_equal = 14, 446 greater = 15, 447 448 cc_always = 16, 449 450 // Aliases. 451 carry = Uless, 452 not_carry = Ugreater_equal, 453 zero = equal, 454 eq = equal, 455 not_zero = not_equal, 456 ne = not_equal, 457 nz = not_equal, 458 sign = negative, 459 not_sign = positive, 460 mi = negative, 461 pl = positive, 462 hi = Ugreater, 463 ls = Uless_equal, 464 ge = greater_equal, 465 lt = less, 466 gt = greater, 467 le = less_equal, 468 hs = Ugreater_equal, 469 lo = Uless, 470 al = cc_always, 471 472 cc_default = kNoCondition 473}; 474 475 476// Returns the equivalent of !cc. 477// Negation of the default kNoCondition (-1) results in a non-default 478// no_condition value (-2). As long as tests for no_condition check 479// for condition < 0, this will work as expected. 480inline Condition NegateCondition(Condition cc) { 481 ASSERT(cc != cc_always); 482 return static_cast<Condition>(cc ^ 1); 483} 484 485 486inline Condition ReverseCondition(Condition cc) { 487 switch (cc) { 488 case Uless: 489 return Ugreater; 490 case Ugreater: 491 return Uless; 492 case Ugreater_equal: 493 return Uless_equal; 494 case Uless_equal: 495 return Ugreater_equal; 496 case less: 497 return greater; 498 case greater: 499 return less; 500 case greater_equal: 501 return less_equal; 502 case less_equal: 503 return greater_equal; 504 default: 505 return cc; 506 }; 507} 508 509 510// ----- Coprocessor conditions. 511enum FPUCondition { 512 kNoFPUCondition = -1, 513 514 F = 0, // False. 515 UN = 1, // Unordered. 516 EQ = 2, // Equal. 517 UEQ = 3, // Unordered or Equal. 518 OLT = 4, // Ordered or Less Than. 519 ULT = 5, // Unordered or Less Than. 520 OLE = 6, // Ordered or Less Than or Equal. 521 ULE = 7 // Unordered or Less Than or Equal. 522}; 523 524 525// FPU rounding modes. 526enum FPURoundingMode { 527 RN = 0 << 0, // Round to Nearest. 528 RZ = 1 << 0, // Round towards zero. 529 RP = 2 << 0, // Round towards Plus Infinity. 530 RM = 3 << 0, // Round towards Minus Infinity. 531 532 // Aliases. 533 kRoundToNearest = RN, 534 kRoundToZero = RZ, 535 kRoundToPlusInf = RP, 536 kRoundToMinusInf = RM 537}; 538 539const uint32_t kFPURoundingModeMask = 3 << 0; 540 541enum CheckForInexactConversion { 542 kCheckForInexactConversion, 543 kDontCheckForInexactConversion 544}; 545 546 547// ----------------------------------------------------------------------------- 548// Hints. 549 550// Branch hints are not used on the MIPS. They are defined so that they can 551// appear in shared function signatures, but will be ignored in MIPS 552// implementations. 553enum Hint { 554 no_hint = 0 555}; 556 557 558inline Hint NegateHint(Hint hint) { 559 return no_hint; 560} 561 562 563// ----------------------------------------------------------------------------- 564// Specific instructions, constants, and masks. 565// These constants are declared in assembler-mips.cc, as they use named 566// registers and other constants. 567 568// addiu(sp, sp, 4) aka Pop() operation or part of Pop(r) 569// operations as post-increment of sp. 570extern const Instr kPopInstruction; 571// addiu(sp, sp, -4) part of Push(r) operation as pre-decrement of sp. 572extern const Instr kPushInstruction; 573// sw(r, MemOperand(sp, 0)) 574extern const Instr kPushRegPattern; 575// lw(r, MemOperand(sp, 0)) 576extern const Instr kPopRegPattern; 577extern const Instr kLwRegFpOffsetPattern; 578extern const Instr kSwRegFpOffsetPattern; 579extern const Instr kLwRegFpNegOffsetPattern; 580extern const Instr kSwRegFpNegOffsetPattern; 581// A mask for the Rt register for push, pop, lw, sw instructions. 582extern const Instr kRtMask; 583extern const Instr kLwSwInstrTypeMask; 584extern const Instr kLwSwInstrArgumentMask; 585extern const Instr kLwSwOffsetMask; 586 587// Break 0xfffff, reserved for redirected real time call. 588const Instr rtCallRedirInstr = SPECIAL | BREAK | call_rt_redirected << 6; 589// A nop instruction. (Encoding of sll 0 0 0). 590const Instr nopInstr = 0; 591 592class Instruction { 593 public: 594 enum { 595 kInstrSize = 4, 596 kInstrSizeLog2 = 2, 597 // On MIPS PC cannot actually be directly accessed. We behave as if PC was 598 // always the value of the current instruction being executed. 599 kPCReadOffset = 0 600 }; 601 602 // Get the raw instruction bits. 603 inline Instr InstructionBits() const { 604 return *reinterpret_cast<const Instr*>(this); 605 } 606 607 // Set the raw instruction bits to value. 608 inline void SetInstructionBits(Instr value) { 609 *reinterpret_cast<Instr*>(this) = value; 610 } 611 612 // Read one particular bit out of the instruction bits. 613 inline int Bit(int nr) const { 614 return (InstructionBits() >> nr) & 1; 615 } 616 617 // Read a bit field out of the instruction bits. 618 inline int Bits(int hi, int lo) const { 619 return (InstructionBits() >> lo) & ((2 << (hi - lo)) - 1); 620 } 621 622 // Instruction type. 623 enum Type { 624 kRegisterType, 625 kImmediateType, 626 kJumpType, 627 kUnsupported = -1 628 }; 629 630 // Get the encoding type of the instruction. 631 Type InstructionType() const; 632 633 634 // Accessors for the different named fields used in the MIPS encoding. 635 inline Opcode OpcodeValue() const { 636 return static_cast<Opcode>( 637 Bits(kOpcodeShift + kOpcodeBits - 1, kOpcodeShift)); 638 } 639 640 inline int RsValue() const { 641 ASSERT(InstructionType() == kRegisterType || 642 InstructionType() == kImmediateType); 643 return Bits(kRsShift + kRsBits - 1, kRsShift); 644 } 645 646 inline int RtValue() const { 647 ASSERT(InstructionType() == kRegisterType || 648 InstructionType() == kImmediateType); 649 return Bits(kRtShift + kRtBits - 1, kRtShift); 650 } 651 652 inline int RdValue() const { 653 ASSERT(InstructionType() == kRegisterType); 654 return Bits(kRdShift + kRdBits - 1, kRdShift); 655 } 656 657 inline int SaValue() const { 658 ASSERT(InstructionType() == kRegisterType); 659 return Bits(kSaShift + kSaBits - 1, kSaShift); 660 } 661 662 inline int FunctionValue() const { 663 ASSERT(InstructionType() == kRegisterType || 664 InstructionType() == kImmediateType); 665 return Bits(kFunctionShift + kFunctionBits - 1, kFunctionShift); 666 } 667 668 inline int FdValue() const { 669 return Bits(kFdShift + kFdBits - 1, kFdShift); 670 } 671 672 inline int FsValue() const { 673 return Bits(kFsShift + kFsBits - 1, kFsShift); 674 } 675 676 inline int FtValue() const { 677 return Bits(kFtShift + kFtBits - 1, kFtShift); 678 } 679 680 // Float Compare condition code instruction bits. 681 inline int FCccValue() const { 682 return Bits(kFCccShift + kFCccBits - 1, kFCccShift); 683 } 684 685 // Float Branch condition code instruction bits. 686 inline int FBccValue() const { 687 return Bits(kFBccShift + kFBccBits - 1, kFBccShift); 688 } 689 690 // Float Branch true/false instruction bit. 691 inline int FBtrueValue() const { 692 return Bits(kFBtrueShift + kFBtrueBits - 1, kFBtrueShift); 693 } 694 695 // Return the fields at their original place in the instruction encoding. 696 inline Opcode OpcodeFieldRaw() const { 697 return static_cast<Opcode>(InstructionBits() & kOpcodeMask); 698 } 699 700 inline int RsFieldRaw() const { 701 ASSERT(InstructionType() == kRegisterType || 702 InstructionType() == kImmediateType); 703 return InstructionBits() & kRsFieldMask; 704 } 705 706 // Same as above function, but safe to call within InstructionType(). 707 inline int RsFieldRawNoAssert() const { 708 return InstructionBits() & kRsFieldMask; 709 } 710 711 inline int RtFieldRaw() const { 712 ASSERT(InstructionType() == kRegisterType || 713 InstructionType() == kImmediateType); 714 return InstructionBits() & kRtFieldMask; 715 } 716 717 inline int RdFieldRaw() const { 718 ASSERT(InstructionType() == kRegisterType); 719 return InstructionBits() & kRdFieldMask; 720 } 721 722 inline int SaFieldRaw() const { 723 ASSERT(InstructionType() == kRegisterType); 724 return InstructionBits() & kSaFieldMask; 725 } 726 727 inline int FunctionFieldRaw() const { 728 return InstructionBits() & kFunctionFieldMask; 729 } 730 731 // Get the secondary field according to the opcode. 732 inline int SecondaryValue() const { 733 Opcode op = OpcodeFieldRaw(); 734 switch (op) { 735 case SPECIAL: 736 case SPECIAL2: 737 return FunctionValue(); 738 case COP1: 739 return RsValue(); 740 case REGIMM: 741 return RtValue(); 742 default: 743 return NULLSF; 744 } 745 } 746 747 inline int32_t Imm16Value() const { 748 ASSERT(InstructionType() == kImmediateType); 749 return Bits(kImm16Shift + kImm16Bits - 1, kImm16Shift); 750 } 751 752 inline int32_t Imm26Value() const { 753 ASSERT(InstructionType() == kJumpType); 754 return Bits(kImm26Shift + kImm26Bits - 1, kImm26Shift); 755 } 756 757 // Say if the instruction should not be used in a branch delay slot. 758 bool IsForbiddenInBranchDelay() const; 759 // Say if the instruction 'links'. e.g. jal, bal. 760 bool IsLinkingInstruction() const; 761 // Say if the instruction is a break or a trap. 762 bool IsTrap() const; 763 764 // Instructions are read of out a code stream. The only way to get a 765 // reference to an instruction is to convert a pointer. There is no way 766 // to allocate or create instances of class Instruction. 767 // Use the At(pc) function to create references to Instruction. 768 static Instruction* At(byte* pc) { 769 return reinterpret_cast<Instruction*>(pc); 770 } 771 772 private: 773 // We need to prevent the creation of instances of class Instruction. 774 DISALLOW_IMPLICIT_CONSTRUCTORS(Instruction); 775}; 776 777 778// ----------------------------------------------------------------------------- 779// MIPS assembly various constants. 780 781// C/C++ argument slots size. 782const int kCArgSlotCount = 4; 783const int kCArgsSlotsSize = kCArgSlotCount * Instruction::kInstrSize; 784// JS argument slots size. 785const int kJSArgsSlotsSize = 0 * Instruction::kInstrSize; 786// Assembly builtins argument slots size. 787const int kBArgsSlotsSize = 0 * Instruction::kInstrSize; 788 789const int kBranchReturnOffset = 2 * Instruction::kInstrSize; 790 791const int kDoubleAlignmentBits = 3; 792const int kDoubleAlignment = (1 << kDoubleAlignmentBits); 793const int kDoubleAlignmentMask = kDoubleAlignment - 1; 794 795 796} } // namespace v8::internal 797 798#endif // #ifndef V8_MIPS_CONSTANTS_H_ 799