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