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.
NegateCondition(Condition cc)480 inline Condition NegateCondition(Condition cc) {
481 ASSERT(cc != cc_always);
482 return static_cast<Condition>(cc ^ 1);
483 }
484
485
ReverseCondition(Condition cc)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
NegateHint(Hint hint)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.
InstructionBits()603 inline Instr InstructionBits() const {
604 return *reinterpret_cast<const Instr*>(this);
605 }
606
607 // Set the raw instruction bits to value.
SetInstructionBits(Instr 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.
Bit(int nr)613 inline int Bit(int nr) const {
614 return (InstructionBits() >> nr) & 1;
615 }
616
617 // Read a bit field out of the instruction bits.
Bits(int hi,int lo)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.
OpcodeValue()635 inline Opcode OpcodeValue() const {
636 return static_cast<Opcode>(
637 Bits(kOpcodeShift + kOpcodeBits - 1, kOpcodeShift));
638 }
639
RsValue()640 inline int RsValue() const {
641 ASSERT(InstructionType() == kRegisterType ||
642 InstructionType() == kImmediateType);
643 return Bits(kRsShift + kRsBits - 1, kRsShift);
644 }
645
RtValue()646 inline int RtValue() const {
647 ASSERT(InstructionType() == kRegisterType ||
648 InstructionType() == kImmediateType);
649 return Bits(kRtShift + kRtBits - 1, kRtShift);
650 }
651
RdValue()652 inline int RdValue() const {
653 ASSERT(InstructionType() == kRegisterType);
654 return Bits(kRdShift + kRdBits - 1, kRdShift);
655 }
656
SaValue()657 inline int SaValue() const {
658 ASSERT(InstructionType() == kRegisterType);
659 return Bits(kSaShift + kSaBits - 1, kSaShift);
660 }
661
FunctionValue()662 inline int FunctionValue() const {
663 ASSERT(InstructionType() == kRegisterType ||
664 InstructionType() == kImmediateType);
665 return Bits(kFunctionShift + kFunctionBits - 1, kFunctionShift);
666 }
667
FdValue()668 inline int FdValue() const {
669 return Bits(kFdShift + kFdBits - 1, kFdShift);
670 }
671
FsValue()672 inline int FsValue() const {
673 return Bits(kFsShift + kFsBits - 1, kFsShift);
674 }
675
FtValue()676 inline int FtValue() const {
677 return Bits(kFtShift + kFtBits - 1, kFtShift);
678 }
679
680 // Float Compare condition code instruction bits.
FCccValue()681 inline int FCccValue() const {
682 return Bits(kFCccShift + kFCccBits - 1, kFCccShift);
683 }
684
685 // Float Branch condition code instruction bits.
FBccValue()686 inline int FBccValue() const {
687 return Bits(kFBccShift + kFBccBits - 1, kFBccShift);
688 }
689
690 // Float Branch true/false instruction bit.
FBtrueValue()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.
OpcodeFieldRaw()696 inline Opcode OpcodeFieldRaw() const {
697 return static_cast<Opcode>(InstructionBits() & kOpcodeMask);
698 }
699
RsFieldRaw()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().
RsFieldRawNoAssert()707 inline int RsFieldRawNoAssert() const {
708 return InstructionBits() & kRsFieldMask;
709 }
710
RtFieldRaw()711 inline int RtFieldRaw() const {
712 ASSERT(InstructionType() == kRegisterType ||
713 InstructionType() == kImmediateType);
714 return InstructionBits() & kRtFieldMask;
715 }
716
RdFieldRaw()717 inline int RdFieldRaw() const {
718 ASSERT(InstructionType() == kRegisterType);
719 return InstructionBits() & kRdFieldMask;
720 }
721
SaFieldRaw()722 inline int SaFieldRaw() const {
723 ASSERT(InstructionType() == kRegisterType);
724 return InstructionBits() & kSaFieldMask;
725 }
726
FunctionFieldRaw()727 inline int FunctionFieldRaw() const {
728 return InstructionBits() & kFunctionFieldMask;
729 }
730
731 // Get the secondary field according to the opcode.
SecondaryValue()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
Imm16Value()747 inline int32_t Imm16Value() const {
748 ASSERT(InstructionType() == kImmediateType);
749 return Bits(kImm16Shift + kImm16Bits - 1, kImm16Shift);
750 }
751
Imm26Value()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.
At(byte * pc)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