1 // Copyright 2010 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 #include "checks.h" 32 33 // UNIMPLEMENTED_ macro for MIPS. 34 #define UNIMPLEMENTED_MIPS() \ 35 v8::internal::PrintF("%s, \tline %d: \tfunction %s not implemented. \n", \ 36 __FILE__, __LINE__, __func__) 37 #define UNSUPPORTED_MIPS() v8::internal::PrintF("Unsupported instruction.\n") 38 39 40 // Defines constants and accessor classes to assemble, disassemble and 41 // simulate MIPS32 instructions. 42 // 43 // See: MIPS32 Architecture For Programmers 44 // Volume II: The MIPS32 Instruction Set 45 // Try www.cs.cornell.edu/courses/cs3410/2008fa/MIPS_Vol2.pdf. 46 47 namespace assembler { 48 namespace mips { 49 50 // ----------------------------------------------------------------------------- 51 // Registers and FPURegister. 52 53 // Number of general purpose registers. 54 static const int kNumRegisters = 32; 55 static const int kInvalidRegister = -1; 56 57 // Number of registers with HI, LO, and pc. 58 static const int kNumSimuRegisters = 35; 59 60 // In the simulator, the PC register is simulated as the 34th register. 61 static const int kPCRegister = 34; 62 63 // Number coprocessor registers. 64 static const int kNumFPURegister = 32; 65 static const int kInvalidFPURegister = -1; 66 67 // Helper functions for converting between register numbers and names. 68 class Registers { 69 public: 70 // Return the name of the register. 71 static const char* Name(int reg); 72 73 // Lookup the register number for the name provided. 74 static int Number(const char* name); 75 76 struct RegisterAlias { 77 int reg; 78 const char *name; 79 }; 80 81 static const int32_t kMaxValue = 0x7fffffff; 82 static const int32_t kMinValue = 0x80000000; 83 84 private: 85 86 static const char* names_[kNumSimuRegisters]; 87 static const RegisterAlias aliases_[]; 88 }; 89 90 // Helper functions for converting between register numbers and names. 91 class FPURegister { 92 public: 93 // Return the name of the register. 94 static const char* Name(int reg); 95 96 // Lookup the register number for the name provided. 97 static int Number(const char* name); 98 99 struct RegisterAlias { 100 int creg; 101 const char *name; 102 }; 103 104 private: 105 106 static const char* names_[kNumFPURegister]; 107 static const RegisterAlias aliases_[]; 108 }; 109 110 111 // ----------------------------------------------------------------------------- 112 // Instructions encoding constants. 113 114 // On MIPS all instructions are 32 bits. 115 typedef int32_t Instr; 116 117 typedef unsigned char byte_; 118 119 // Special Software Interrupt codes when used in the presence of the MIPS 120 // simulator. 121 enum SoftwareInterruptCodes { 122 // Transition to C code. 123 call_rt_redirected = 0xfffff 124 }; 125 126 // ----- Fields offset and length. 127 static const int kOpcodeShift = 26; 128 static const int kOpcodeBits = 6; 129 static const int kRsShift = 21; 130 static const int kRsBits = 5; 131 static const int kRtShift = 16; 132 static const int kRtBits = 5; 133 static const int kRdShift = 11; 134 static const int kRdBits = 5; 135 static const int kSaShift = 6; 136 static const int kSaBits = 5; 137 static const int kFunctionShift = 0; 138 static const int kFunctionBits = 6; 139 140 static const int kImm16Shift = 0; 141 static const int kImm16Bits = 16; 142 static const int kImm26Shift = 0; 143 static const int kImm26Bits = 26; 144 145 static const int kFsShift = 11; 146 static const int kFsBits = 5; 147 static const int kFtShift = 16; 148 static const int kFtBits = 5; 149 150 // ----- Miscellianous useful masks. 151 // Instruction bit masks. 152 static const int kOpcodeMask = ((1 << kOpcodeBits) - 1) << kOpcodeShift; 153 static const int kImm16Mask = ((1 << kImm16Bits) - 1) << kImm16Shift; 154 static const int kImm26Mask = ((1 << kImm26Bits) - 1) << kImm26Shift; 155 static const int kRsFieldMask = ((1 << kRsBits) - 1) << kRsShift; 156 static const int kRtFieldMask = ((1 << kRtBits) - 1) << kRtShift; 157 static const int kRdFieldMask = ((1 << kRdBits) - 1) << kRdShift; 158 static const int kSaFieldMask = ((1 << kSaBits) - 1) << kSaShift; 159 static const int kFunctionFieldMask = 160 ((1 << kFunctionBits) - 1) << kFunctionShift; 161 // Misc masks. 162 static const int HIMask = 0xffff << 16; 163 static const int LOMask = 0xffff; 164 static const int signMask = 0x80000000; 165 166 167 // ----- MIPS Opcodes and Function Fields. 168 // We use this presentation to stay close to the table representation in 169 // MIPS32 Architecture For Programmers, Volume II: The MIPS32 Instruction Set. 170 enum Opcode { 171 SPECIAL = 0 << kOpcodeShift, 172 REGIMM = 1 << kOpcodeShift, 173 174 J = ((0 << 3) + 2) << kOpcodeShift, 175 JAL = ((0 << 3) + 3) << kOpcodeShift, 176 BEQ = ((0 << 3) + 4) << kOpcodeShift, 177 BNE = ((0 << 3) + 5) << kOpcodeShift, 178 BLEZ = ((0 << 3) + 6) << kOpcodeShift, 179 BGTZ = ((0 << 3) + 7) << kOpcodeShift, 180 181 ADDI = ((1 << 3) + 0) << kOpcodeShift, 182 ADDIU = ((1 << 3) + 1) << kOpcodeShift, 183 SLTI = ((1 << 3) + 2) << kOpcodeShift, 184 SLTIU = ((1 << 3) + 3) << kOpcodeShift, 185 ANDI = ((1 << 3) + 4) << kOpcodeShift, 186 ORI = ((1 << 3) + 5) << kOpcodeShift, 187 XORI = ((1 << 3) + 6) << kOpcodeShift, 188 LUI = ((1 << 3) + 7) << kOpcodeShift, 189 190 COP1 = ((2 << 3) + 1) << kOpcodeShift, // Coprocessor 1 class 191 BEQL = ((2 << 3) + 4) << kOpcodeShift, 192 BNEL = ((2 << 3) + 5) << kOpcodeShift, 193 BLEZL = ((2 << 3) + 6) << kOpcodeShift, 194 BGTZL = ((2 << 3) + 7) << kOpcodeShift, 195 196 SPECIAL2 = ((3 << 3) + 4) << kOpcodeShift, 197 198 LB = ((4 << 3) + 0) << kOpcodeShift, 199 LW = ((4 << 3) + 3) << kOpcodeShift, 200 LBU = ((4 << 3) + 4) << kOpcodeShift, 201 SB = ((5 << 3) + 0) << kOpcodeShift, 202 SW = ((5 << 3) + 3) << kOpcodeShift, 203 204 LWC1 = ((6 << 3) + 1) << kOpcodeShift, 205 LDC1 = ((6 << 3) + 5) << kOpcodeShift, 206 207 SWC1 = ((7 << 3) + 1) << kOpcodeShift, 208 SDC1 = ((7 << 3) + 5) << kOpcodeShift 209 }; 210 211 enum SecondaryField { 212 // SPECIAL Encoding of Function Field. 213 SLL = ((0 << 3) + 0), 214 SRL = ((0 << 3) + 2), 215 SRA = ((0 << 3) + 3), 216 SLLV = ((0 << 3) + 4), 217 SRLV = ((0 << 3) + 6), 218 SRAV = ((0 << 3) + 7), 219 220 JR = ((1 << 3) + 0), 221 JALR = ((1 << 3) + 1), 222 BREAK = ((1 << 3) + 5), 223 224 MFHI = ((2 << 3) + 0), 225 MFLO = ((2 << 3) + 2), 226 227 MULT = ((3 << 3) + 0), 228 MULTU = ((3 << 3) + 1), 229 DIV = ((3 << 3) + 2), 230 DIVU = ((3 << 3) + 3), 231 232 ADD = ((4 << 3) + 0), 233 ADDU = ((4 << 3) + 1), 234 SUB = ((4 << 3) + 2), 235 SUBU = ((4 << 3) + 3), 236 AND = ((4 << 3) + 4), 237 OR = ((4 << 3) + 5), 238 XOR = ((4 << 3) + 6), 239 NOR = ((4 << 3) + 7), 240 241 SLT = ((5 << 3) + 2), 242 SLTU = ((5 << 3) + 3), 243 244 TGE = ((6 << 3) + 0), 245 TGEU = ((6 << 3) + 1), 246 TLT = ((6 << 3) + 2), 247 TLTU = ((6 << 3) + 3), 248 TEQ = ((6 << 3) + 4), 249 TNE = ((6 << 3) + 6), 250 251 // SPECIAL2 Encoding of Function Field. 252 MUL = ((0 << 3) + 2), 253 254 // REGIMM encoding of rt Field. 255 BLTZ = ((0 << 3) + 0) << 16, 256 BGEZ = ((0 << 3) + 1) << 16, 257 BLTZAL = ((2 << 3) + 0) << 16, 258 BGEZAL = ((2 << 3) + 1) << 16, 259 260 // COP1 Encoding of rs Field. 261 MFC1 = ((0 << 3) + 0) << 21, 262 MFHC1 = ((0 << 3) + 3) << 21, 263 MTC1 = ((0 << 3) + 4) << 21, 264 MTHC1 = ((0 << 3) + 7) << 21, 265 BC1 = ((1 << 3) + 0) << 21, 266 S = ((2 << 3) + 0) << 21, 267 D = ((2 << 3) + 1) << 21, 268 W = ((2 << 3) + 4) << 21, 269 L = ((2 << 3) + 5) << 21, 270 PS = ((2 << 3) + 6) << 21, 271 // COP1 Encoding of Function Field When rs=S. 272 CVT_D_S = ((4 << 3) + 1), 273 CVT_W_S = ((4 << 3) + 4), 274 CVT_L_S = ((4 << 3) + 5), 275 CVT_PS_S = ((4 << 3) + 6), 276 // COP1 Encoding of Function Field When rs=D. 277 CVT_S_D = ((4 << 3) + 0), 278 CVT_W_D = ((4 << 3) + 4), 279 CVT_L_D = ((4 << 3) + 5), 280 // COP1 Encoding of Function Field When rs=W or L. 281 CVT_S_W = ((4 << 3) + 0), 282 CVT_D_W = ((4 << 3) + 1), 283 CVT_S_L = ((4 << 3) + 0), 284 CVT_D_L = ((4 << 3) + 1), 285 // COP1 Encoding of Function Field When rs=PS. 286 287 NULLSF = 0 288 }; 289 290 291 // ----- Emulated conditions. 292 // On MIPS we use this enum to abstract from conditionnal branch instructions. 293 // the 'U' prefix is used to specify unsigned comparisons. 294 enum Condition { 295 // Any value < 0 is considered no_condition. 296 no_condition = -1, 297 298 overflow = 0, 299 no_overflow = 1, 300 Uless = 2, 301 Ugreater_equal= 3, 302 equal = 4, 303 not_equal = 5, 304 Uless_equal = 6, 305 Ugreater = 7, 306 negative = 8, 307 positive = 9, 308 parity_even = 10, 309 parity_odd = 11, 310 less = 12, 311 greater_equal = 13, 312 less_equal = 14, 313 greater = 15, 314 315 cc_always = 16, 316 317 // aliases 318 carry = Uless, 319 not_carry = Ugreater_equal, 320 zero = equal, 321 eq = equal, 322 not_zero = not_equal, 323 ne = not_equal, 324 sign = negative, 325 not_sign = positive, 326 327 cc_default = no_condition 328 }; 329 330 // ----- Coprocessor conditions. 331 enum FPUCondition { 332 F, // False 333 UN, // Unordered 334 EQ, // Equal 335 UEQ, // Unordered or Equal 336 OLT, // Ordered or Less Than 337 ULT, // Unordered or Less Than 338 OLE, // Ordered or Less Than or Equal 339 ULE // Unordered or Less Than or Equal 340 }; 341 342 343 // Break 0xfffff, reserved for redirected real time call. 344 const Instr rtCallRedirInstr = SPECIAL | BREAK | call_rt_redirected << 6; 345 // A nop instruction. (Encoding of sll 0 0 0). 346 const Instr nopInstr = 0; 347 348 class Instruction { 349 public: 350 enum { 351 kInstructionSize = 4, 352 kInstructionSizeLog2 = 2, 353 // On MIPS PC cannot actually be directly accessed. We behave as if PC was 354 // always the value of the current instruction being exectued. 355 kPCReadOffset = 0 356 }; 357 358 // Get the raw instruction bits. InstructionBits()359 inline Instr InstructionBits() const { 360 return *reinterpret_cast<const Instr*>(this); 361 } 362 363 // Set the raw instruction bits to value. SetInstructionBits(Instr value)364 inline void SetInstructionBits(Instr value) { 365 *reinterpret_cast<Instr*>(this) = value; 366 } 367 368 // Read one particular bit out of the instruction bits. Bit(int nr)369 inline int Bit(int nr) const { 370 return (InstructionBits() >> nr) & 1; 371 } 372 373 // Read a bit field out of the instruction bits. Bits(int hi,int lo)374 inline int Bits(int hi, int lo) const { 375 return (InstructionBits() >> lo) & ((2 << (hi - lo)) - 1); 376 } 377 378 // Instruction type. 379 enum Type { 380 kRegisterType, 381 kImmediateType, 382 kJumpType, 383 kUnsupported = -1 384 }; 385 386 // Get the encoding type of the instruction. 387 Type InstructionType() const; 388 389 390 // Accessors for the different named fields used in the MIPS encoding. OpcodeField()391 inline Opcode OpcodeField() const { 392 return static_cast<Opcode>( 393 Bits(kOpcodeShift + kOpcodeBits - 1, kOpcodeShift)); 394 } 395 RsField()396 inline int RsField() const { 397 ASSERT(InstructionType() == kRegisterType || 398 InstructionType() == kImmediateType); 399 return Bits(kRsShift + kRsBits - 1, kRsShift); 400 } 401 RtField()402 inline int RtField() const { 403 ASSERT(InstructionType() == kRegisterType || 404 InstructionType() == kImmediateType); 405 return Bits(kRtShift + kRtBits - 1, kRtShift); 406 } 407 RdField()408 inline int RdField() const { 409 ASSERT(InstructionType() == kRegisterType); 410 return Bits(kRdShift + kRdBits - 1, kRdShift); 411 } 412 SaField()413 inline int SaField() const { 414 ASSERT(InstructionType() == kRegisterType); 415 return Bits(kSaShift + kSaBits - 1, kSaShift); 416 } 417 FunctionField()418 inline int FunctionField() const { 419 ASSERT(InstructionType() == kRegisterType || 420 InstructionType() == kImmediateType); 421 return Bits(kFunctionShift + kFunctionBits - 1, kFunctionShift); 422 } 423 FsField()424 inline int FsField() const { 425 return Bits(kFsShift + kRsBits - 1, kFsShift); 426 } 427 FtField()428 inline int FtField() const { 429 return Bits(kFtShift + kRsBits - 1, kFtShift); 430 } 431 432 // Return the fields at their original place in the instruction encoding. OpcodeFieldRaw()433 inline Opcode OpcodeFieldRaw() const { 434 return static_cast<Opcode>(InstructionBits() & kOpcodeMask); 435 } 436 RsFieldRaw()437 inline int RsFieldRaw() const { 438 ASSERT(InstructionType() == kRegisterType || 439 InstructionType() == kImmediateType); 440 return InstructionBits() & kRsFieldMask; 441 } 442 RtFieldRaw()443 inline int RtFieldRaw() const { 444 ASSERT(InstructionType() == kRegisterType || 445 InstructionType() == kImmediateType); 446 return InstructionBits() & kRtFieldMask; 447 } 448 RdFieldRaw()449 inline int RdFieldRaw() const { 450 ASSERT(InstructionType() == kRegisterType); 451 return InstructionBits() & kRdFieldMask; 452 } 453 SaFieldRaw()454 inline int SaFieldRaw() const { 455 ASSERT(InstructionType() == kRegisterType); 456 return InstructionBits() & kSaFieldMask; 457 } 458 FunctionFieldRaw()459 inline int FunctionFieldRaw() const { 460 return InstructionBits() & kFunctionFieldMask; 461 } 462 463 // Get the secondary field according to the opcode. SecondaryField()464 inline int SecondaryField() const { 465 Opcode op = OpcodeFieldRaw(); 466 switch (op) { 467 case SPECIAL: 468 case SPECIAL2: 469 return FunctionField(); 470 case COP1: 471 return RsField(); 472 case REGIMM: 473 return RtField(); 474 default: 475 return NULLSF; 476 } 477 } 478 Imm16Field()479 inline int32_t Imm16Field() const { 480 ASSERT(InstructionType() == kImmediateType); 481 return Bits(kImm16Shift + kImm16Bits - 1, kImm16Shift); 482 } 483 Imm26Field()484 inline int32_t Imm26Field() const { 485 ASSERT(InstructionType() == kJumpType); 486 return Bits(kImm16Shift + kImm26Bits - 1, kImm26Shift); 487 } 488 489 // Say if the instruction should not be used in a branch delay slot. 490 bool IsForbiddenInBranchDelay(); 491 // Say if the instruction 'links'. eg: jal, bal. 492 bool IsLinkingInstruction(); 493 // Say if the instruction is a break or a trap. 494 bool IsTrap(); 495 496 // Instructions are read of out a code stream. The only way to get a 497 // reference to an instruction is to convert a pointer. There is no way 498 // to allocate or create instances of class Instruction. 499 // Use the At(pc) function to create references to Instruction. At(byte_ * pc)500 static Instruction* At(byte_* pc) { 501 return reinterpret_cast<Instruction*>(pc); 502 } 503 504 private: 505 // We need to prevent the creation of instances of class Instruction. 506 DISALLOW_IMPLICIT_CONSTRUCTORS(Instruction); 507 }; 508 509 510 // ----------------------------------------------------------------------------- 511 // MIPS assembly various constants. 512 513 static const int kArgsSlotsSize = 4 * Instruction::kInstructionSize; 514 static const int kArgsSlotsNum = 4; 515 516 static const int kBranchReturnOffset = 2 * Instruction::kInstructionSize; 517 518 static const int kDoubleAlignment = 2 * 8; 519 static const int kDoubleAlignmentMask = kDoubleAlignmentMask - 1; 520 521 522 } } // namespace assembler::mips 523 524 #endif // #ifndef V8_MIPS_CONSTANTS_H_ 525 526