• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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