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