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
42enum 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.
62const 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.
66const bool IsMipsSoftFloatABI = true;
67#else
68const 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
79namespace v8 {
80namespace internal {
81
82// -----------------------------------------------------------------------------
83// Registers and FPURegisters.
84
85// Number of general purpose registers.
86const int kNumRegisters = 32;
87const int kInvalidRegister = -1;
88
89// Number of registers with HI, LO, and pc.
90const int kNumSimuRegisters = 35;
91
92// In the simulator, the PC register is simulated as the 34th register.
93const int kPCRegister = 34;
94
95// Number coprocessor registers.
96const int kNumFPURegisters = 32;
97const int kInvalidFPURegister = -1;
98
99// FPU (coprocessor 1) control registers. Currently only FCSR is implemented.
100const int kFCSRRegister = 31;
101const int kInvalidFPUControlRegister = -1;
102const uint32_t kFPUInvalidResult = (uint32_t) (1 << 31) - 1;
103
104// FCSR constants.
105const uint32_t kFCSRInexactFlagBit = 2;
106const uint32_t kFCSRUnderflowFlagBit = 3;
107const uint32_t kFCSROverflowFlagBit = 4;
108const uint32_t kFCSRDivideByZeroFlagBit = 5;
109const uint32_t kFCSRInvalidOpFlagBit = 6;
110
111const uint32_t kFCSRInexactFlagMask = 1 << kFCSRInexactFlagBit;
112const uint32_t kFCSRUnderflowFlagMask = 1 << kFCSRUnderflowFlagBit;
113const uint32_t kFCSROverflowFlagMask = 1 << kFCSROverflowFlagBit;
114const uint32_t kFCSRDivideByZeroFlagMask = 1 << kFCSRDivideByZeroFlagBit;
115const uint32_t kFCSRInvalidOpFlagMask = 1 << kFCSRInvalidOpFlagBit;
116
117const uint32_t kFCSRFlagMask =
118    kFCSRInexactFlagMask |
119    kFCSRUnderflowFlagMask |
120    kFCSROverflowFlagMask |
121    kFCSRDivideByZeroFlagMask |
122    kFCSRInvalidOpFlagMask;
123
124const uint32_t kFCSRExceptionFlagMask = kFCSRFlagMask ^ kFCSRInexactFlagMask;
125
126// Helper functions for converting between register numbers and names.
127class 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.
149class 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.
172typedef int32_t Instr;
173
174// Special Software Interrupt codes when used in the presence of the MIPS
175// simulator.
176enum 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.
188const uint32_t kMaxWatchpointCode = 31;
189const uint32_t kMaxStopCode = 127;
190STATIC_ASSERT(kMaxWatchpointCode < kMaxStopCode);
191
192
193// ----- Fields offset and length.
194const int kOpcodeShift   = 26;
195const int kOpcodeBits    = 6;
196const int kRsShift       = 21;
197const int kRsBits        = 5;
198const int kRtShift       = 16;
199const int kRtBits        = 5;
200const int kRdShift       = 11;
201const int kRdBits        = 5;
202const int kSaShift       = 6;
203const int kSaBits        = 5;
204const int kFunctionShift = 0;
205const int kFunctionBits  = 6;
206const int kLuiShift      = 16;
207
208const int kImm16Shift = 0;
209const int kImm16Bits  = 16;
210const int kImm26Shift = 0;
211const int kImm26Bits  = 26;
212const int kImm28Shift = 0;
213const int kImm28Bits  = 28;
214
215// In branches and jumps immediate fields point to words, not bytes,
216// and are therefore shifted by 2.
217const int kImmFieldShift = 2;
218
219const int kFsShift       = 11;
220const int kFsBits        = 5;
221const int kFtShift       = 16;
222const int kFtBits        = 5;
223const int kFdShift       = 6;
224const int kFdBits        = 5;
225const int kFCccShift     = 8;
226const int kFCccBits      = 3;
227const int kFBccShift     = 18;
228const int kFBccBits      = 3;
229const int kFBtrueShift   = 16;
230const int kFBtrueBits    = 1;
231
232// ----- Miscellaneous useful masks.
233// Instruction bit masks.
234const int  kOpcodeMask   = ((1 << kOpcodeBits) - 1) << kOpcodeShift;
235const int  kImm16Mask    = ((1 << kImm16Bits) - 1) << kImm16Shift;
236const int  kImm26Mask    = ((1 << kImm26Bits) - 1) << kImm26Shift;
237const int  kImm28Mask    = ((1 << kImm28Bits) - 1) << kImm28Shift;
238const int  kRsFieldMask  = ((1 << kRsBits) - 1) << kRsShift;
239const int  kRtFieldMask  = ((1 << kRtBits) - 1) << kRtShift;
240const int  kRdFieldMask  = ((1 << kRdBits) - 1) << kRdShift;
241const int  kSaFieldMask  = ((1 << kSaBits) - 1) << kSaShift;
242const int  kFunctionFieldMask = ((1 << kFunctionBits) - 1) << kFunctionShift;
243// Misc masks.
244const int  kHiMask       =   0xffff << 16;
245const int  kLoMask       =   0xffff;
246const int  kSignMask     =   0x80000000;
247const 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.
252enum 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
301enum 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.
427enum 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.
480inline Condition NegateCondition(Condition cc) {
481  ASSERT(cc != cc_always);
482  return static_cast<Condition>(cc ^ 1);
483}
484
485
486inline 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.
511enum 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.
526enum 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
539const uint32_t kFPURoundingModeMask = 3 << 0;
540
541enum 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.
553enum Hint {
554  no_hint = 0
555};
556
557
558inline 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.
570extern const Instr kPopInstruction;
571// addiu(sp, sp, -4) part of Push(r) operation as pre-decrement of sp.
572extern const Instr kPushInstruction;
573// sw(r, MemOperand(sp, 0))
574extern const Instr kPushRegPattern;
575// lw(r, MemOperand(sp, 0))
576extern const Instr kPopRegPattern;
577extern const Instr kLwRegFpOffsetPattern;
578extern const Instr kSwRegFpOffsetPattern;
579extern const Instr kLwRegFpNegOffsetPattern;
580extern const Instr kSwRegFpNegOffsetPattern;
581// A mask for the Rt register for push, pop, lw, sw instructions.
582extern const Instr kRtMask;
583extern const Instr kLwSwInstrTypeMask;
584extern const Instr kLwSwInstrArgumentMask;
585extern const Instr kLwSwOffsetMask;
586
587// Break 0xfffff, reserved for redirected real time call.
588const Instr rtCallRedirInstr = SPECIAL | BREAK | call_rt_redirected << 6;
589// A nop instruction. (Encoding of sll 0 0 0).
590const Instr nopInstr = 0;
591
592class 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.
603  inline Instr InstructionBits() const {
604    return *reinterpret_cast<const Instr*>(this);
605  }
606
607  // Set the raw instruction bits to 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.
613  inline int Bit(int nr) const {
614    return (InstructionBits() >> nr) & 1;
615  }
616
617  // Read a bit field out of the instruction bits.
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.
635  inline Opcode OpcodeValue() const {
636    return static_cast<Opcode>(
637        Bits(kOpcodeShift + kOpcodeBits - 1, kOpcodeShift));
638  }
639
640  inline int RsValue() const {
641    ASSERT(InstructionType() == kRegisterType ||
642           InstructionType() == kImmediateType);
643    return Bits(kRsShift + kRsBits - 1, kRsShift);
644  }
645
646  inline int RtValue() const {
647    ASSERT(InstructionType() == kRegisterType ||
648           InstructionType() == kImmediateType);
649    return Bits(kRtShift + kRtBits - 1, kRtShift);
650  }
651
652  inline int RdValue() const {
653    ASSERT(InstructionType() == kRegisterType);
654    return Bits(kRdShift + kRdBits - 1, kRdShift);
655  }
656
657  inline int SaValue() const {
658    ASSERT(InstructionType() == kRegisterType);
659    return Bits(kSaShift + kSaBits - 1, kSaShift);
660  }
661
662  inline int FunctionValue() const {
663    ASSERT(InstructionType() == kRegisterType ||
664           InstructionType() == kImmediateType);
665    return Bits(kFunctionShift + kFunctionBits - 1, kFunctionShift);
666  }
667
668  inline int FdValue() const {
669    return Bits(kFdShift + kFdBits - 1, kFdShift);
670  }
671
672  inline int FsValue() const {
673    return Bits(kFsShift + kFsBits - 1, kFsShift);
674  }
675
676  inline int FtValue() const {
677    return Bits(kFtShift + kFtBits - 1, kFtShift);
678  }
679
680  // Float Compare condition code instruction bits.
681  inline int FCccValue() const {
682    return Bits(kFCccShift + kFCccBits - 1, kFCccShift);
683  }
684
685  // Float Branch condition code instruction bits.
686  inline int FBccValue() const {
687    return Bits(kFBccShift + kFBccBits - 1, kFBccShift);
688  }
689
690  // Float Branch true/false instruction bit.
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.
696  inline Opcode OpcodeFieldRaw() const {
697    return static_cast<Opcode>(InstructionBits() & kOpcodeMask);
698  }
699
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().
707  inline int RsFieldRawNoAssert() const {
708    return InstructionBits() & kRsFieldMask;
709  }
710
711  inline int RtFieldRaw() const {
712    ASSERT(InstructionType() == kRegisterType ||
713           InstructionType() == kImmediateType);
714    return InstructionBits() & kRtFieldMask;
715  }
716
717  inline int RdFieldRaw() const {
718    ASSERT(InstructionType() == kRegisterType);
719    return InstructionBits() & kRdFieldMask;
720  }
721
722  inline int SaFieldRaw() const {
723    ASSERT(InstructionType() == kRegisterType);
724    return InstructionBits() & kSaFieldMask;
725  }
726
727  inline int FunctionFieldRaw() const {
728    return InstructionBits() & kFunctionFieldMask;
729  }
730
731  // Get the secondary field according to the opcode.
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
747  inline int32_t Imm16Value() const {
748    ASSERT(InstructionType() == kImmediateType);
749    return Bits(kImm16Shift + kImm16Bits - 1, kImm16Shift);
750  }
751
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.
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.
782const int kCArgSlotCount = 4;
783const int kCArgsSlotsSize = kCArgSlotCount * Instruction::kInstrSize;
784// JS argument slots size.
785const int kJSArgsSlotsSize = 0 * Instruction::kInstrSize;
786// Assembly builtins argument slots size.
787const int kBArgsSlotsSize = 0 * Instruction::kInstrSize;
788
789const int kBranchReturnOffset = 2 * Instruction::kInstrSize;
790
791const int kDoubleAlignmentBits = 3;
792const int kDoubleAlignment = (1 << kDoubleAlignmentBits);
793const int kDoubleAlignmentMask = kDoubleAlignment - 1;
794
795
796} }   // namespace v8::internal
797
798#endif    // #ifndef V8_MIPS_CONSTANTS_H_
799