• 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 // 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