| OLD | NEW |
| (Empty) |
| 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | |
| 2 // for details. All rights reserved. Use of this source code is governed by a | |
| 3 // BSD-style license that can be found in the LICENSE file. | |
| 4 | |
| 5 #ifndef RUNTIME_VM_CONSTANTS_MIPS_H_ | |
| 6 #define RUNTIME_VM_CONSTANTS_MIPS_H_ | |
| 7 | |
| 8 #include "platform/assert.h" | |
| 9 | |
| 10 namespace dart { | |
| 11 | |
| 12 enum Register { | |
| 13 R0 = 0, | |
| 14 R1 = 1, // AT aka TMP | |
| 15 R2 = 2, | |
| 16 R3 = 3, | |
| 17 R4 = 4, | |
| 18 R5 = 5, | |
| 19 R6 = 6, | |
| 20 R7 = 7, | |
| 21 R8 = 8, | |
| 22 R9 = 9, | |
| 23 R10 = 10, | |
| 24 R11 = 11, | |
| 25 R12 = 12, | |
| 26 R13 = 13, | |
| 27 R14 = 14, | |
| 28 R15 = 15, | |
| 29 R16 = 16, | |
| 30 R17 = 17, | |
| 31 R18 = 18, | |
| 32 R19 = 19, // THR | |
| 33 R20 = 20, | |
| 34 R21 = 21, | |
| 35 R22 = 22, // CTX | |
| 36 R23 = 23, // PP | |
| 37 R24 = 24, | |
| 38 R25 = 25, | |
| 39 R26 = 26, | |
| 40 R27 = 27, | |
| 41 R28 = 28, | |
| 42 R29 = 29, // SP | |
| 43 R30 = 30, // FP | |
| 44 R31 = 31, // RA | |
| 45 kNumberOfCpuRegisters = 32, | |
| 46 IMM = 32, // Positive value is easier to encode than kNoRegister in bitfield. | |
| 47 kNoRegister = -1, // Signals an illegal register. | |
| 48 | |
| 49 | |
| 50 // Register aliases. | |
| 51 ZR = R0, | |
| 52 AT = R1, | |
| 53 | |
| 54 V0 = R2, | |
| 55 V1 = R3, | |
| 56 | |
| 57 A0 = R4, | |
| 58 A1 = R5, | |
| 59 A2 = R6, | |
| 60 A3 = R7, | |
| 61 | |
| 62 T0 = R8, | |
| 63 T1 = R9, | |
| 64 T2 = R10, | |
| 65 T3 = R11, | |
| 66 T4 = R12, | |
| 67 T5 = R13, | |
| 68 T6 = R14, | |
| 69 T7 = R15, | |
| 70 | |
| 71 S0 = R16, | |
| 72 S1 = R17, | |
| 73 S2 = R18, | |
| 74 S3 = R19, | |
| 75 S4 = R20, | |
| 76 S5 = R21, | |
| 77 S6 = R22, | |
| 78 S7 = R23, | |
| 79 | |
| 80 T8 = R24, | |
| 81 T9 = R25, | |
| 82 | |
| 83 K0 = R26, | |
| 84 K1 = R27, | |
| 85 | |
| 86 GP = R28, | |
| 87 SP = R29, | |
| 88 FP = R30, | |
| 89 RA = R31, | |
| 90 }; | |
| 91 | |
| 92 | |
| 93 // Values for floating point registers. | |
| 94 // Double-precision values use register pairs. | |
| 95 enum FRegister { | |
| 96 F0 = 0, | |
| 97 F1 = 1, | |
| 98 F2 = 2, | |
| 99 F3 = 3, | |
| 100 F4 = 4, | |
| 101 F5 = 5, | |
| 102 F6 = 6, | |
| 103 F7 = 7, | |
| 104 F8 = 8, | |
| 105 F9 = 9, | |
| 106 F10 = 10, | |
| 107 F11 = 11, | |
| 108 F12 = 12, | |
| 109 F13 = 13, | |
| 110 F14 = 14, | |
| 111 F15 = 15, | |
| 112 F16 = 16, | |
| 113 F17 = 17, | |
| 114 F18 = 18, | |
| 115 F19 = 19, | |
| 116 F20 = 20, | |
| 117 F21 = 21, | |
| 118 F22 = 22, | |
| 119 F23 = 23, | |
| 120 F24 = 24, | |
| 121 F25 = 25, | |
| 122 F26 = 26, | |
| 123 F27 = 27, | |
| 124 F28 = 28, | |
| 125 F29 = 29, | |
| 126 F30 = 30, | |
| 127 F31 = 31, | |
| 128 kNumberOfFRegisters = 32, | |
| 129 kNoFRegister = -1, | |
| 130 }; | |
| 131 | |
| 132 // The double precision floating point registers are concatenated pairs of the | |
| 133 // single precision registers, e.g. D0 is F1:F0, D1 is F3:F2, etc.. We only | |
| 134 // tell the architecture generic code about the double precision registers, then | |
| 135 // convert to the single precision registers when needed in the mips-specific | |
| 136 // code. | |
| 137 enum DRegister { | |
| 138 D0 = 0, // Function return value 1. | |
| 139 D1 = 1, // Function return value 2. | |
| 140 D2 = 2, // Not preserved. | |
| 141 D3 = 3, // Not preserved. | |
| 142 D4 = 4, // Not preserved. | |
| 143 D5 = 5, // Not preserved. | |
| 144 D6 = 6, // Argument 1. | |
| 145 D7 = 7, // Argument 2. | |
| 146 D8 = 8, // Not preserved. | |
| 147 D9 = 9, // Not preserved. | |
| 148 D10 = 10, // Preserved. | |
| 149 D11 = 11, // Preserved. | |
| 150 D12 = 12, // Preserved. | |
| 151 D13 = 13, // Preserved. | |
| 152 D14 = 14, // Preserved. | |
| 153 D15 = 15, // Preserved. | |
| 154 kNumberOfDRegisters = 16, | |
| 155 kNoDRegister = -1, | |
| 156 }; | |
| 157 | |
| 158 static inline FRegister EvenFRegisterOf(DRegister d) { | |
| 159 return static_cast<FRegister>(d * 2); | |
| 160 } | |
| 161 | |
| 162 static inline FRegister OddFRegisterOf(DRegister d) { | |
| 163 return static_cast<FRegister>((d * 2) + 1); | |
| 164 } | |
| 165 | |
| 166 const DRegister DTMP = D9; | |
| 167 const FRegister STMP1 = F18; | |
| 168 const FRegister STMP2 = F19; | |
| 169 | |
| 170 // Architecture independent aliases. | |
| 171 typedef DRegister FpuRegister; | |
| 172 const FpuRegister FpuTMP = DTMP; | |
| 173 const int kNumberOfFpuRegisters = kNumberOfDRegisters; | |
| 174 const FpuRegister kNoFpuRegister = kNoDRegister; | |
| 175 | |
| 176 | |
| 177 // Register aliases. | |
| 178 const Register TMP = AT; // Used as scratch register by assembler. | |
| 179 const Register TMP2 = kNoRegister; // No second assembler scratch register. | |
| 180 const Register CTX = S6; // Location of current context at method entry. | |
| 181 const Register CODE_REG = S6; | |
| 182 const Register PP = S7; // Caches object pool pointer in generated code. | |
| 183 const Register SPREG = SP; // Stack pointer register. | |
| 184 const Register FPREG = FP; // Frame pointer register. | |
| 185 const Register LRREG = RA; // Link register. | |
| 186 const Register ICREG = S5; // IC data register. | |
| 187 const Register ARGS_DESC_REG = S4; | |
| 188 const Register THR = S3; // Caches current thread in generated code. | |
| 189 const Register CALLEE_SAVED_TEMP = S5; | |
| 190 | |
| 191 // The code that generates a comparison can be far away from the code that | |
| 192 // generates the branch that uses the result of that comparison. In this case, | |
| 193 // CMPRES1 and CMPRES2 are used for the results of the comparison. We need two | |
| 194 // since TMP is clobbered by a far branch. | |
| 195 const Register CMPRES1 = T8; | |
| 196 const Register CMPRES2 = T9; | |
| 197 | |
| 198 // Exception object is passed in this register to the catch handlers when an | |
| 199 // exception is thrown. | |
| 200 const Register kExceptionObjectReg = V0; | |
| 201 | |
| 202 // Stack trace object is passed in this register to the catch handlers when | |
| 203 // an exception is thrown. | |
| 204 const Register kStackTraceObjectReg = V1; | |
| 205 | |
| 206 | |
| 207 typedef uint32_t RegList; | |
| 208 const RegList kAllCpuRegistersList = 0xFFFFFFFF; | |
| 209 | |
| 210 const RegList kAbiArgumentCpuRegs = | |
| 211 (1 << A0) | (1 << A1) | (1 << A2) | (1 << A3); | |
| 212 const RegList kAbiPreservedCpuRegs = (1 << S0) | (1 << S1) | (1 << S2) | | |
| 213 (1 << S3) | (1 << S4) | (1 << S5) | | |
| 214 (1 << S6) | (1 << S7); | |
| 215 const int kAbiPreservedCpuRegCount = 8; | |
| 216 | |
| 217 // FPU registers 20 - 31 are preserved across calls. | |
| 218 const FRegister kAbiFirstPreservedFpuReg = F20; | |
| 219 const FRegister kAbiLastPreservedFpuReg = | |
| 220 static_cast<FRegister>(kNumberOfFRegisters - 1); | |
| 221 const int kAbiPreservedFpuRegCount = 12; | |
| 222 | |
| 223 const RegList kReservedCpuRegisters = | |
| 224 (1 << SPREG) | (1 << FPREG) | (1 << TMP) | (1 << PP) | (1 << THR) | | |
| 225 (1 << CTX) | (1 << ZR) | (1 << CMPRES1) | (1 << CMPRES2) | (1 << K0) | | |
| 226 (1 << K1) | (1 << GP) | (1 << RA); | |
| 227 // CPU registers available to Dart allocator. | |
| 228 const RegList kDartAvailableCpuRegs = | |
| 229 kAllCpuRegistersList & ~kReservedCpuRegisters; | |
| 230 // Registers available to Dart that are not preserved by runtime calls. | |
| 231 const RegList kDartVolatileCpuRegs = | |
| 232 kDartAvailableCpuRegs & ~kAbiPreservedCpuRegs; | |
| 233 const int kDartVolatileCpuRegCount = 14; | |
| 234 const Register kDartFirstVolatileCpuReg = R2; | |
| 235 const Register kDartLastVolatileCpuReg = R15; | |
| 236 | |
| 237 // FPU registers 0 - 19 are not preserved across calls. | |
| 238 const FRegister kDartFirstVolatileFpuReg = F0; | |
| 239 const FRegister kDartLastVolatileFpuReg = F19; | |
| 240 const int kDartVolatileFpuRegCount = 20; | |
| 241 | |
| 242 | |
| 243 // There is no status register on MIPS. Instead of representing a condition | |
| 244 // code, type Condition (see assembler_mips.h) represents a pair of operands and | |
| 245 // a relation operator between them. | |
| 246 enum RelationOperator { | |
| 247 AL, // always | |
| 248 NV, // never | |
| 249 EQ, // equal | |
| 250 NE, // not equal | |
| 251 GT, // greater than | |
| 252 GE, // greater equal | |
| 253 LT, // less than | |
| 254 LE, // less equal | |
| 255 UGT, // unsigned greater than | |
| 256 UGE, // unsigned greater equal | |
| 257 ULT, // unsigned less than | |
| 258 ULE, // unsigned less equal | |
| 259 INVALID_RELATION | |
| 260 }; | |
| 261 | |
| 262 | |
| 263 // Constants used for the decoding or encoding of the individual fields of | |
| 264 // instructions. Based on the "Table 4.25 CPU Instruction Format Fields". | |
| 265 enum InstructionFields { | |
| 266 kOpcodeShift = 26, | |
| 267 kOpcodeBits = 6, | |
| 268 kRsShift = 21, | |
| 269 kRsBits = 5, | |
| 270 kFmtShift = 21, | |
| 271 kFmtBits = 5, | |
| 272 kRtShift = 16, | |
| 273 kRtBits = 5, | |
| 274 kFtShift = 16, | |
| 275 kFtBits = 5, | |
| 276 kRdShift = 11, | |
| 277 kRdBits = 5, | |
| 278 kFsShift = 11, | |
| 279 kFsBits = 5, | |
| 280 kSaShift = 6, | |
| 281 kSaBits = 5, | |
| 282 kFdShift = 6, | |
| 283 kFdBits = 5, | |
| 284 kFunctionShift = 0, | |
| 285 kFunctionBits = 6, | |
| 286 kCop1FnShift = 0, | |
| 287 kCop1FnBits = 6, | |
| 288 kCop1SubShift = 21, | |
| 289 kCop1SubBits = 5, | |
| 290 kImmShift = 0, | |
| 291 kImmBits = 16, | |
| 292 kInstrShift = 0, | |
| 293 kInstrBits = 26, | |
| 294 kBreakCodeShift = 6, | |
| 295 kBreakCodeBits = 20, | |
| 296 kFpuCCShift = 8, | |
| 297 kFpuCCBits = 3, | |
| 298 | |
| 299 kBranchOffsetMask = 0x0000ffff, | |
| 300 }; | |
| 301 | |
| 302 | |
| 303 enum Opcode { | |
| 304 SPECIAL = 0, | |
| 305 REGIMM = 1, | |
| 306 J = 2, | |
| 307 JAL = 3, | |
| 308 BEQ = 4, | |
| 309 BNE = 5, | |
| 310 BLEZ = 6, | |
| 311 BGTZ = 7, | |
| 312 ADDI = 8, | |
| 313 ADDIU = 9, | |
| 314 SLTI = 10, | |
| 315 SLTIU = 11, | |
| 316 ANDI = 12, | |
| 317 ORI = 13, | |
| 318 XORI = 14, | |
| 319 LUI = 15, | |
| 320 CPO0 = 16, | |
| 321 COP1 = 17, | |
| 322 COP2 = 18, | |
| 323 COP1X = 19, | |
| 324 BEQL = 20, | |
| 325 BNEL = 21, | |
| 326 BLEZL = 22, | |
| 327 BGTZL = 23, | |
| 328 SPECIAL2 = 28, | |
| 329 JALX = 29, | |
| 330 SPECIAL3 = 31, | |
| 331 LB = 32, | |
| 332 LH = 33, | |
| 333 LWL = 34, | |
| 334 LW = 35, | |
| 335 LBU = 36, | |
| 336 LHU = 37, | |
| 337 LWR = 38, | |
| 338 SB = 40, | |
| 339 SH = 41, | |
| 340 SWL = 42, | |
| 341 SW = 43, | |
| 342 SWR = 46, | |
| 343 CACHE = 47, | |
| 344 LL = 48, | |
| 345 LWC1 = 49, | |
| 346 LWC2 = 50, | |
| 347 PREF = 51, | |
| 348 LDC1 = 53, | |
| 349 LDC2 = 54, | |
| 350 SC = 56, | |
| 351 SWC1 = 57, | |
| 352 SWC2 = 58, | |
| 353 SDC1 = 61, | |
| 354 SDC2 = 62, | |
| 355 }; | |
| 356 | |
| 357 | |
| 358 enum SpecialFunction { | |
| 359 // SPECIAL opcodes. | |
| 360 SLL = 0, | |
| 361 MOVCI = 1, | |
| 362 SRL = 2, | |
| 363 SRA = 3, | |
| 364 SLLV = 4, | |
| 365 SRLV = 6, | |
| 366 SRAV = 7, | |
| 367 JR = 8, | |
| 368 JALR = 9, | |
| 369 MOVZ = 10, | |
| 370 MOVN = 11, | |
| 371 SYSCALL = 12, | |
| 372 BREAK = 13, | |
| 373 SYNC = 15, | |
| 374 MFHI = 16, | |
| 375 MTHI = 17, | |
| 376 MFLO = 18, | |
| 377 MTLO = 19, | |
| 378 MULT = 24, | |
| 379 MULTU = 25, | |
| 380 DIV = 26, | |
| 381 DIVU = 27, | |
| 382 ADD = 32, | |
| 383 ADDU = 33, | |
| 384 SUB = 34, | |
| 385 SUBU = 35, | |
| 386 AND = 36, | |
| 387 OR = 37, | |
| 388 XOR = 38, | |
| 389 NOR = 39, | |
| 390 SLT = 42, | |
| 391 SLTU = 43, | |
| 392 TGE = 48, | |
| 393 TGEU = 49, | |
| 394 TLT = 50, | |
| 395 TLTU = 51, | |
| 396 TEQ = 52, | |
| 397 TNE = 54, | |
| 398 | |
| 399 // SPECIAL2 opcodes. | |
| 400 MADD = 0, | |
| 401 MADDU = 1, | |
| 402 CLZ = 32, | |
| 403 CLO = 33, | |
| 404 }; | |
| 405 | |
| 406 | |
| 407 enum RtRegImm { | |
| 408 BLTZ = 0, | |
| 409 BGEZ = 1, | |
| 410 BLTZL = 2, | |
| 411 BGEZL = 3, | |
| 412 TGEI = 8, | |
| 413 TGEIU = 9, | |
| 414 TLTI = 10, | |
| 415 TLTIU = 11, | |
| 416 TEQI = 12, | |
| 417 TNEI = 14, | |
| 418 BLTZAL = 16, | |
| 419 BGEZAL = 17, | |
| 420 BLTZALL = 18, | |
| 421 BGEZALL = 19, | |
| 422 SYNCI = 31, | |
| 423 }; | |
| 424 | |
| 425 | |
| 426 enum Cop1Function { | |
| 427 COP1_ADD = 0x00, | |
| 428 COP1_SUB = 0x01, | |
| 429 COP1_MUL = 0x02, | |
| 430 COP1_DIV = 0x03, | |
| 431 COP1_SQRT = 0x04, | |
| 432 COP1_MOV = 0x06, | |
| 433 COP1_NEG = 0x07, | |
| 434 COP1_TRUNC_W = 0x0d, | |
| 435 COP1_CVT_S = 0x20, | |
| 436 COP1_CVT_D = 0x21, | |
| 437 COP1_C_F = 0x30, | |
| 438 COP1_C_UN = 0x31, | |
| 439 COP1_C_EQ = 0x32, | |
| 440 COP1_C_UEQ = 0x33, | |
| 441 COP1_C_OLT = 0x34, | |
| 442 COP1_C_ULT = 0x35, | |
| 443 COP1_C_OLE = 0x36, | |
| 444 COP1_C_ULE = 0x37, | |
| 445 }; | |
| 446 | |
| 447 | |
| 448 enum Cop1Sub { | |
| 449 COP1_MF = 0, | |
| 450 COP1_MT = 4, | |
| 451 COP1_BC = 8, | |
| 452 }; | |
| 453 | |
| 454 | |
| 455 enum Format { | |
| 456 FMT_S = 16, | |
| 457 FMT_D = 17, | |
| 458 FMT_W = 20, | |
| 459 FMT_L = 21, | |
| 460 FMT_PS = 22, | |
| 461 }; | |
| 462 | |
| 463 | |
| 464 class Instr { | |
| 465 public: | |
| 466 enum { | |
| 467 kInstrSize = 4, | |
| 468 }; | |
| 469 | |
| 470 static const int32_t kNopInstruction = 0; | |
| 471 | |
| 472 // Reserved break instruction codes. | |
| 473 static const int32_t kBreakPointCode = 0xdeb0; // For breakpoint. | |
| 474 static const int32_t kStopMessageCode = 0xdeb1; // For Stop(message). | |
| 475 static const int32_t kSimulatorBreakCode = 0xdeb2; // For breakpoint in sim. | |
| 476 static const int32_t kSimulatorRedirectCode = 0xca11; // For redirection. | |
| 477 | |
| 478 static const int32_t kBreakPointZeroInstruction = | |
| 479 (SPECIAL << kOpcodeShift) | (BREAK << kFunctionShift); | |
| 480 | |
| 481 // Breakpoint instruction filling assembler code buffers in debug mode. | |
| 482 static const int32_t kBreakPointInstruction = | |
| 483 kBreakPointZeroInstruction | (kBreakPointCode << kBreakCodeShift); | |
| 484 | |
| 485 // Breakpoint instruction used by the simulator. | |
| 486 // Should be distinct from kBreakPointInstruction and from a typical user | |
| 487 // breakpoint inserted in generated code for debugging, e.g. break_(0). | |
| 488 static const int32_t kSimulatorBreakpointInstruction = | |
| 489 kBreakPointZeroInstruction | (kSimulatorBreakCode << kBreakCodeShift); | |
| 490 | |
| 491 // Runtime call redirection instruction used by the simulator. | |
| 492 static const int32_t kSimulatorRedirectInstruction = | |
| 493 kBreakPointZeroInstruction | (kSimulatorRedirectCode << kBreakCodeShift); | |
| 494 | |
| 495 // Get the raw instruction bits. | |
| 496 inline int32_t InstructionBits() const { | |
| 497 return *reinterpret_cast<const int32_t*>(this); | |
| 498 } | |
| 499 | |
| 500 // Set the raw instruction bits to value. | |
| 501 inline void SetInstructionBits(int32_t value) { | |
| 502 *reinterpret_cast<int32_t*>(this) = value; | |
| 503 } | |
| 504 | |
| 505 inline void SetImmInstrBits(Opcode op, | |
| 506 Register rs, | |
| 507 Register rt, | |
| 508 uint16_t imm) { | |
| 509 SetInstructionBits(op << kOpcodeShift | rs << kRsShift | rt << kRtShift | | |
| 510 imm << kImmShift); | |
| 511 } | |
| 512 | |
| 513 inline void SetSpecialInstrBits(SpecialFunction f, | |
| 514 Register rs, | |
| 515 Register rt, | |
| 516 Register rd) { | |
| 517 SetInstructionBits(SPECIAL << kOpcodeShift | f << kFunctionShift | | |
| 518 rs << kRsShift | rt << kRtShift | rd << kRdShift); | |
| 519 } | |
| 520 | |
| 521 // Read one particular bit out of the instruction bits. | |
| 522 inline int32_t Bit(int nr) const { return (InstructionBits() >> nr) & 1; } | |
| 523 | |
| 524 // Read a bit field out of the instruction bits. | |
| 525 inline int32_t Bits(int shift, int count) const { | |
| 526 return (InstructionBits() >> shift) & ((1 << count) - 1); | |
| 527 } | |
| 528 | |
| 529 // Accessors to the different named fields used in the MIPS encoding. | |
| 530 inline Opcode OpcodeField() const { | |
| 531 return static_cast<Opcode>(Bits(kOpcodeShift, kOpcodeBits)); | |
| 532 } | |
| 533 | |
| 534 inline void SetOpcodeField(Opcode b) { | |
| 535 int32_t instr = InstructionBits(); | |
| 536 int32_t mask = ((1 << kOpcodeBits) - 1) << kOpcodeShift; | |
| 537 SetInstructionBits((b << kOpcodeShift) | (instr & ~mask)); | |
| 538 } | |
| 539 | |
| 540 inline Register RsField() const { | |
| 541 return static_cast<Register>(Bits(kRsShift, kRsBits)); | |
| 542 } | |
| 543 | |
| 544 inline Register RtField() const { | |
| 545 return static_cast<Register>(Bits(kRtShift, kRtBits)); | |
| 546 } | |
| 547 | |
| 548 inline Register RdField() const { | |
| 549 return static_cast<Register>(Bits(kRdShift, kRdBits)); | |
| 550 } | |
| 551 | |
| 552 inline FRegister FsField() const { | |
| 553 return static_cast<FRegister>(Bits(kFsShift, kFsBits)); | |
| 554 } | |
| 555 | |
| 556 inline FRegister FtField() const { | |
| 557 return static_cast<FRegister>(Bits(kFtShift, kFtBits)); | |
| 558 } | |
| 559 | |
| 560 inline FRegister FdField() const { | |
| 561 return static_cast<FRegister>(Bits(kFdShift, kFdBits)); | |
| 562 } | |
| 563 | |
| 564 inline int SaField() const { return Bits(kSaShift, kSaBits); } | |
| 565 | |
| 566 inline int32_t UImmField() const { return Bits(kImmShift, kImmBits); } | |
| 567 | |
| 568 inline int32_t SImmField() const { | |
| 569 // Sign-extend the imm field. | |
| 570 return (Bits(kImmShift, kImmBits) << (32 - kImmBits)) >> (32 - kImmBits); | |
| 571 } | |
| 572 | |
| 573 inline int32_t BreakCodeField() const { | |
| 574 return Bits(kBreakCodeShift, kBreakCodeBits); | |
| 575 } | |
| 576 | |
| 577 inline SpecialFunction FunctionField() const { | |
| 578 return static_cast<SpecialFunction>(Bits(kFunctionShift, kFunctionBits)); | |
| 579 } | |
| 580 | |
| 581 inline RtRegImm RegImmFnField() const { | |
| 582 return static_cast<RtRegImm>(Bits(kRtShift, kRtBits)); | |
| 583 } | |
| 584 | |
| 585 inline void SetRegImmFnField(RtRegImm b) { | |
| 586 int32_t instr = InstructionBits(); | |
| 587 int32_t mask = ((1 << kRtBits) - 1) << kRtShift; | |
| 588 SetInstructionBits((b << kRtShift) | (instr & ~mask)); | |
| 589 } | |
| 590 | |
| 591 inline bool IsBreakPoint() { | |
| 592 return (OpcodeField() == SPECIAL) && (FunctionField() == BREAK); | |
| 593 } | |
| 594 | |
| 595 inline Cop1Function Cop1FunctionField() const { | |
| 596 return static_cast<Cop1Function>(Bits(kCop1FnShift, kCop1FnBits)); | |
| 597 } | |
| 598 | |
| 599 inline Cop1Sub Cop1SubField() const { | |
| 600 return static_cast<Cop1Sub>(Bits(kCop1SubShift, kCop1SubBits)); | |
| 601 } | |
| 602 | |
| 603 inline bool HasFormat() const { | |
| 604 return (OpcodeField() == COP1) && (Bit(25) == 1); | |
| 605 } | |
| 606 | |
| 607 inline Format FormatField() const { | |
| 608 return static_cast<Format>(Bits(kFmtShift, kFmtBits)); | |
| 609 } | |
| 610 | |
| 611 inline int32_t FpuCCField() const { return Bits(kFpuCCShift, kFpuCCBits); } | |
| 612 | |
| 613 // Instructions are read out of a code stream. The only way to get a | |
| 614 // reference to an instruction is to convert a pc. There is no way | |
| 615 // to allocate or create instances of class Instr. | |
| 616 // Use the At(pc) function to create references to Instr. | |
| 617 static Instr* At(uword pc) { return reinterpret_cast<Instr*>(pc); } | |
| 618 | |
| 619 #if defined(DEBUG) | |
| 620 inline void AssertIsImmInstr(Opcode op, | |
| 621 Register rs, | |
| 622 Register rt, | |
| 623 int32_t imm) { | |
| 624 ASSERT((OpcodeField() == op) && (RsField() == rs) && (RtField() == rt) && | |
| 625 (SImmField() == imm)); | |
| 626 } | |
| 627 | |
| 628 inline void AssertIsSpecialInstr(SpecialFunction f, | |
| 629 Register rs, | |
| 630 Register rt, | |
| 631 Register rd) { | |
| 632 ASSERT((OpcodeField() == SPECIAL) && (FunctionField() == f) && | |
| 633 (RsField() == rs) && (RtField() == rt) && (RdField() == rd)); | |
| 634 } | |
| 635 #endif // defined(DEBUG) | |
| 636 | |
| 637 private: | |
| 638 DISALLOW_ALLOCATION(); | |
| 639 DISALLOW_IMPLICIT_CONSTRUCTORS(Instr); | |
| 640 }; | |
| 641 | |
| 642 } // namespace dart | |
| 643 | |
| 644 #endif // RUNTIME_VM_CONSTANTS_MIPS_H_ | |
| OLD | NEW |