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 42 enum 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. 62 const 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. 66 const bool IsMipsSoftFloatABI = true; 67 #else 68 const 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 79 namespace v8 { 80 namespace internal { 81 82 // ----------------------------------------------------------------------------- 83 // Registers and FPURegisters. 84 85 // Number of general purpose registers. 86 const int kNumRegisters = 32; 87 const int kInvalidRegister = -1; 88 89 // Number of registers with HI, LO, and pc. 90 const int kNumSimuRegisters = 35; 91 92 // In the simulator, the PC register is simulated as the 34th register. 93 const int kPCRegister = 34; 94 95 // Number coprocessor registers. 96 const int kNumFPURegisters = 32; 97 const int kInvalidFPURegister = -1; 98 99 // FPU (coprocessor 1) control registers. Currently only FCSR is implemented. 100 const int kFCSRRegister = 31; 101 const int kInvalidFPUControlRegister = -1; 102 const uint32_t kFPUInvalidResult = (uint32_t) (1 << 31) - 1; 103 104 // FCSR constants. 105 const uint32_t kFCSRInexactFlagBit = 2; 106 const uint32_t kFCSRUnderflowFlagBit = 3; 107 const uint32_t kFCSROverflowFlagBit = 4; 108 const uint32_t kFCSRDivideByZeroFlagBit = 5; 109 const uint32_t kFCSRInvalidOpFlagBit = 6; 110 111 const uint32_t kFCSRInexactFlagMask = 1 << kFCSRInexactFlagBit; 112 const uint32_t kFCSRUnderflowFlagMask = 1 << kFCSRUnderflowFlagBit; 113 const uint32_t kFCSROverflowFlagMask = 1 << kFCSROverflowFlagBit; 114 const uint32_t kFCSRDivideByZeroFlagMask = 1 << kFCSRDivideByZeroFlagBit; 115 const uint32_t kFCSRInvalidOpFlagMask = 1 << kFCSRInvalidOpFlagBit; 116 117 const uint32_t kFCSRFlagMask = 118 kFCSRInexactFlagMask | 119 kFCSRUnderflowFlagMask | 120 kFCSROverflowFlagMask | 121 kFCSRDivideByZeroFlagMask | 122 kFCSRInvalidOpFlagMask; 123 124 const uint32_t kFCSRExceptionFlagMask = kFCSRFlagMask ^ kFCSRInexactFlagMask; 125 126 // Helper functions for converting between register numbers and names. 127 class 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. 149 class 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. 172 typedef int32_t Instr; 173 174 // Special Software Interrupt codes when used in the presence of the MIPS 175 // simulator. 176 enum 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. 188 const uint32_t kMaxWatchpointCode = 31; 189 const uint32_t kMaxStopCode = 127; 190 STATIC_ASSERT(kMaxWatchpointCode < kMaxStopCode); 191 192 193 // ----- Fields offset and length. 194 const int kOpcodeShift = 26; 195 const int kOpcodeBits = 6; 196 const int kRsShift = 21; 197 const int kRsBits = 5; 198 const int kRtShift = 16; 199 const int kRtBits = 5; 200 const int kRdShift = 11; 201 const int kRdBits = 5; 202 const int kSaShift = 6; 203 const int kSaBits = 5; 204 const int kFunctionShift = 0; 205 const int kFunctionBits = 6; 206 const int kLuiShift = 16; 207 208 const int kImm16Shift = 0; 209 const int kImm16Bits = 16; 210 const int kImm26Shift = 0; 211 const int kImm26Bits = 26; 212 const int kImm28Shift = 0; 213 const int kImm28Bits = 28; 214 215 // In branches and jumps immediate fields point to words, not bytes, 216 // and are therefore shifted by 2. 217 const int kImmFieldShift = 2; 218 219 const int kFsShift = 11; 220 const int kFsBits = 5; 221 const int kFtShift = 16; 222 const int kFtBits = 5; 223 const int kFdShift = 6; 224 const int kFdBits = 5; 225 const int kFCccShift = 8; 226 const int kFCccBits = 3; 227 const int kFBccShift = 18; 228 const int kFBccBits = 3; 229 const int kFBtrueShift = 16; 230 const int kFBtrueBits = 1; 231 232 // ----- Miscellaneous useful masks. 233 // Instruction bit masks. 234 const int kOpcodeMask = ((1 << kOpcodeBits) - 1) << kOpcodeShift; 235 const int kImm16Mask = ((1 << kImm16Bits) - 1) << kImm16Shift; 236 const int kImm26Mask = ((1 << kImm26Bits) - 1) << kImm26Shift; 237 const int kImm28Mask = ((1 << kImm28Bits) - 1) << kImm28Shift; 238 const int kRsFieldMask = ((1 << kRsBits) - 1) << kRsShift; 239 const int kRtFieldMask = ((1 << kRtBits) - 1) << kRtShift; 240 const int kRdFieldMask = ((1 << kRdBits) - 1) << kRdShift; 241 const int kSaFieldMask = ((1 << kSaBits) - 1) << kSaShift; 242 const int kFunctionFieldMask = ((1 << kFunctionBits) - 1) << kFunctionShift; 243 // Misc masks. 244 const int kHiMask = 0xffff << 16; 245 const int kLoMask = 0xffff; 246 const int kSignMask = 0x80000000; 247 const 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. 252 enum 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 301 enum 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. 427 enum 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. 480 inline Condition NegateCondition(Condition cc) { 481 ASSERT(cc != cc_always); 482 return static_cast<Condition>(cc ^ 1); 483 } 484 485 486 inline 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. 511 enum 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. 526 enum 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 539 const uint32_t kFPURoundingModeMask = 3 << 0; 540 541 enum 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. 553 enum Hint { 554 no_hint = 0 555 }; 556 557 558 inline 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. 570 extern const Instr kPopInstruction; 571 // addiu(sp, sp, -4) part of Push(r) operation as pre-decrement of sp. 572 extern const Instr kPushInstruction; 573 // sw(r, MemOperand(sp, 0)) 574 extern const Instr kPushRegPattern; 575 // lw(r, MemOperand(sp, 0)) 576 extern const Instr kPopRegPattern; 577 extern const Instr kLwRegFpOffsetPattern; 578 extern const Instr kSwRegFpOffsetPattern; 579 extern const Instr kLwRegFpNegOffsetPattern; 580 extern const Instr kSwRegFpNegOffsetPattern; 581 // A mask for the Rt register for push, pop, lw, sw instructions. 582 extern const Instr kRtMask; 583 extern const Instr kLwSwInstrTypeMask; 584 extern const Instr kLwSwInstrArgumentMask; 585 extern const Instr kLwSwOffsetMask; 586 587 // Break 0xfffff, reserved for redirected real time call. 588 const Instr rtCallRedirInstr = SPECIAL | BREAK | call_rt_redirected << 6; 589 // A nop instruction. (Encoding of sll 0 0 0). 590 const Instr nopInstr = 0; 591 592 class 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. 782 const int kCArgSlotCount = 4; 783 const int kCArgsSlotsSize = kCArgSlotCount * Instruction::kInstrSize; 784 // JS argument slots size. 785 const int kJSArgsSlotsSize = 0 * Instruction::kInstrSize; 786 // Assembly builtins argument slots size. 787 const int kBArgsSlotsSize = 0 * Instruction::kInstrSize; 788 789 const int kBranchReturnOffset = 2 * Instruction::kInstrSize; 790 791 const int kDoubleAlignmentBits = 3; 792 const int kDoubleAlignment = (1 << kDoubleAlignmentBits); 793 const int kDoubleAlignmentMask = kDoubleAlignment - 1; 794 795 796 } } // namespace v8::internal 797 798 #endif // #ifndef V8_MIPS_CONSTANTS_H_ 799