blob: 25673301331a312c03a9d7de9134efc23e40b944 [file] [log] [blame]
Andrei Popescu31002712010-02-23 13:46:05 +00001// Copyright 2010 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
Andrei Popescu31002712010-02-23 13:46:05 +000031// UNIMPLEMENTED_ macro for MIPS.
Steve Block44f0eee2011-05-26 01:26:41 +010032#ifdef DEBUG
Andrei Popescu31002712010-02-23 13:46:05 +000033#define UNIMPLEMENTED_MIPS() \
34 v8::internal::PrintF("%s, \tline %d: \tfunction %s not implemented. \n", \
35 __FILE__, __LINE__, __func__)
Steve Block44f0eee2011-05-26 01:26:41 +010036#else
37#define UNIMPLEMENTED_MIPS()
38#endif
39
Andrei Popescu31002712010-02-23 13:46:05 +000040#define UNSUPPORTED_MIPS() v8::internal::PrintF("Unsupported instruction.\n")
41
42
Steve Block44f0eee2011-05-26 01:26:41 +010043#ifdef _MIPS_ARCH_MIPS32R2
44 #define mips32r2 1
45#else
46 #define mips32r2 0
47#endif
48
49
Ben Murdoch257744e2011-11-30 15:57:28 +000050#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
Andrei Popescu31002712010-02-23 13:46:05 +000063// 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
Steve Block44f0eee2011-05-26 01:26:41 +010070namespace v8 {
71namespace internal {
Andrei Popescu31002712010-02-23 13:46:05 +000072
73// -----------------------------------------------------------------------------
Ben Murdoch257744e2011-11-30 15:57:28 +000074// Registers and FPURegisters.
Andrei Popescu31002712010-02-23 13:46:05 +000075
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.
Steve Block44f0eee2011-05-26 01:26:41 +010087static const int kNumFPURegisters = 32;
Andrei Popescu31002712010-02-23 13:46:05 +000088static const int kInvalidFPURegister = -1;
89
Steve Block44f0eee2011-05-26 01:26:41 +010090// 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 kFCSRFlagMask = (1 << 6) - 1;
97static const uint32_t kFCSRFlagShift = 2;
Ben Murdoch257744e2011-11-30 15:57:28 +000098static const uint32_t kFCSRInexactFlagBit = 1 << 0;
99static const uint32_t kFCSRUnderflowFlagBit = 1 << 1;
100static const uint32_t kFCSROverflowFlagBit = 1 << 2;
101static const uint32_t kFCSRDivideByZeroFlagBit = 1 << 3;
102static const uint32_t kFCSRInvalidOpFlagBit = 1 << 4;
Steve Block44f0eee2011-05-26 01:26:41 +0100103
Andrei Popescu31002712010-02-23 13:46:05 +0000104// Helper functions for converting between register numbers and names.
105class Registers {
106 public:
107 // Return the name of the register.
108 static const char* Name(int reg);
109
110 // Lookup the register number for the name provided.
111 static int Number(const char* name);
112
113 struct RegisterAlias {
114 int reg;
115 const char *name;
116 };
117
118 static const int32_t kMaxValue = 0x7fffffff;
119 static const int32_t kMinValue = 0x80000000;
120
121 private:
122
123 static const char* names_[kNumSimuRegisters];
124 static const RegisterAlias aliases_[];
125};
126
127// Helper functions for converting between register numbers and names.
Steve Block44f0eee2011-05-26 01:26:41 +0100128class FPURegisters {
Andrei Popescu31002712010-02-23 13:46:05 +0000129 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 creg;
138 const char *name;
139 };
140
141 private:
142
Steve Block44f0eee2011-05-26 01:26:41 +0100143 static const char* names_[kNumFPURegisters];
Andrei Popescu31002712010-02-23 13:46:05 +0000144 static const RegisterAlias aliases_[];
145};
146
147
148// -----------------------------------------------------------------------------
149// Instructions encoding constants.
150
151// On MIPS all instructions are 32 bits.
152typedef int32_t Instr;
153
Andrei Popescu31002712010-02-23 13:46:05 +0000154// Special Software Interrupt codes when used in the presence of the MIPS
155// simulator.
156enum SoftwareInterruptCodes {
157 // Transition to C code.
158 call_rt_redirected = 0xfffff
159};
160
161// ----- Fields offset and length.
162static const int kOpcodeShift = 26;
163static const int kOpcodeBits = 6;
164static const int kRsShift = 21;
165static const int kRsBits = 5;
166static const int kRtShift = 16;
167static const int kRtBits = 5;
168static const int kRdShift = 11;
169static const int kRdBits = 5;
170static const int kSaShift = 6;
171static const int kSaBits = 5;
172static const int kFunctionShift = 0;
173static const int kFunctionBits = 6;
Steve Block44f0eee2011-05-26 01:26:41 +0100174static const int kLuiShift = 16;
Andrei Popescu31002712010-02-23 13:46:05 +0000175
176static const int kImm16Shift = 0;
177static const int kImm16Bits = 16;
178static const int kImm26Shift = 0;
179static const int kImm26Bits = 26;
180
181static const int kFsShift = 11;
182static const int kFsBits = 5;
183static const int kFtShift = 16;
184static const int kFtBits = 5;
Steve Block44f0eee2011-05-26 01:26:41 +0100185static const int kFdShift = 6;
186static const int kFdBits = 5;
187static const int kFCccShift = 8;
188static const int kFCccBits = 3;
189static const int kFBccShift = 18;
190static const int kFBccBits = 3;
191static const int kFBtrueShift = 16;
192static const int kFBtrueBits = 1;
Andrei Popescu31002712010-02-23 13:46:05 +0000193
Ben Murdoch257744e2011-11-30 15:57:28 +0000194// ----- Miscellaneous useful masks.
Andrei Popescu31002712010-02-23 13:46:05 +0000195// Instruction bit masks.
196static const int kOpcodeMask = ((1 << kOpcodeBits) - 1) << kOpcodeShift;
197static const int kImm16Mask = ((1 << kImm16Bits) - 1) << kImm16Shift;
198static const int kImm26Mask = ((1 << kImm26Bits) - 1) << kImm26Shift;
199static const int kRsFieldMask = ((1 << kRsBits) - 1) << kRsShift;
200static const int kRtFieldMask = ((1 << kRtBits) - 1) << kRtShift;
201static const int kRdFieldMask = ((1 << kRdBits) - 1) << kRdShift;
202static const int kSaFieldMask = ((1 << kSaBits) - 1) << kSaShift;
203static const int kFunctionFieldMask =
204 ((1 << kFunctionBits) - 1) << kFunctionShift;
205// Misc masks.
Steve Block44f0eee2011-05-26 01:26:41 +0100206static const int kHiMask = 0xffff << 16;
207static const int kLoMask = 0xffff;
208static const int kSignMask = 0x80000000;
Andrei Popescu31002712010-02-23 13:46:05 +0000209
210
211// ----- MIPS Opcodes and Function Fields.
212// We use this presentation to stay close to the table representation in
213// MIPS32 Architecture For Programmers, Volume II: The MIPS32 Instruction Set.
214enum Opcode {
215 SPECIAL = 0 << kOpcodeShift,
216 REGIMM = 1 << kOpcodeShift,
217
218 J = ((0 << 3) + 2) << kOpcodeShift,
219 JAL = ((0 << 3) + 3) << kOpcodeShift,
220 BEQ = ((0 << 3) + 4) << kOpcodeShift,
221 BNE = ((0 << 3) + 5) << kOpcodeShift,
222 BLEZ = ((0 << 3) + 6) << kOpcodeShift,
223 BGTZ = ((0 << 3) + 7) << kOpcodeShift,
224
225 ADDI = ((1 << 3) + 0) << kOpcodeShift,
226 ADDIU = ((1 << 3) + 1) << kOpcodeShift,
227 SLTI = ((1 << 3) + 2) << kOpcodeShift,
228 SLTIU = ((1 << 3) + 3) << kOpcodeShift,
229 ANDI = ((1 << 3) + 4) << kOpcodeShift,
230 ORI = ((1 << 3) + 5) << kOpcodeShift,
231 XORI = ((1 << 3) + 6) << kOpcodeShift,
232 LUI = ((1 << 3) + 7) << kOpcodeShift,
233
Ben Murdoch257744e2011-11-30 15:57:28 +0000234 COP1 = ((2 << 3) + 1) << kOpcodeShift, // Coprocessor 1 class.
Andrei Popescu31002712010-02-23 13:46:05 +0000235 BEQL = ((2 << 3) + 4) << kOpcodeShift,
236 BNEL = ((2 << 3) + 5) << kOpcodeShift,
237 BLEZL = ((2 << 3) + 6) << kOpcodeShift,
238 BGTZL = ((2 << 3) + 7) << kOpcodeShift,
239
240 SPECIAL2 = ((3 << 3) + 4) << kOpcodeShift,
Steve Block44f0eee2011-05-26 01:26:41 +0100241 SPECIAL3 = ((3 << 3) + 7) << kOpcodeShift,
Andrei Popescu31002712010-02-23 13:46:05 +0000242
243 LB = ((4 << 3) + 0) << kOpcodeShift,
Steve Block44f0eee2011-05-26 01:26:41 +0100244 LH = ((4 << 3) + 1) << kOpcodeShift,
245 LWL = ((4 << 3) + 2) << kOpcodeShift,
Andrei Popescu31002712010-02-23 13:46:05 +0000246 LW = ((4 << 3) + 3) << kOpcodeShift,
247 LBU = ((4 << 3) + 4) << kOpcodeShift,
Steve Block44f0eee2011-05-26 01:26:41 +0100248 LHU = ((4 << 3) + 5) << kOpcodeShift,
249 LWR = ((4 << 3) + 6) << kOpcodeShift,
Andrei Popescu31002712010-02-23 13:46:05 +0000250 SB = ((5 << 3) + 0) << kOpcodeShift,
Steve Block44f0eee2011-05-26 01:26:41 +0100251 SH = ((5 << 3) + 1) << kOpcodeShift,
252 SWL = ((5 << 3) + 2) << kOpcodeShift,
Andrei Popescu31002712010-02-23 13:46:05 +0000253 SW = ((5 << 3) + 3) << kOpcodeShift,
Steve Block44f0eee2011-05-26 01:26:41 +0100254 SWR = ((5 << 3) + 6) << kOpcodeShift,
Andrei Popescu31002712010-02-23 13:46:05 +0000255
256 LWC1 = ((6 << 3) + 1) << kOpcodeShift,
257 LDC1 = ((6 << 3) + 5) << kOpcodeShift,
258
259 SWC1 = ((7 << 3) + 1) << kOpcodeShift,
260 SDC1 = ((7 << 3) + 5) << kOpcodeShift
261};
262
263enum SecondaryField {
264 // SPECIAL Encoding of Function Field.
265 SLL = ((0 << 3) + 0),
266 SRL = ((0 << 3) + 2),
267 SRA = ((0 << 3) + 3),
268 SLLV = ((0 << 3) + 4),
269 SRLV = ((0 << 3) + 6),
270 SRAV = ((0 << 3) + 7),
Steve Block44f0eee2011-05-26 01:26:41 +0100271 MOVCI = ((0 << 3) + 1),
Andrei Popescu31002712010-02-23 13:46:05 +0000272
273 JR = ((1 << 3) + 0),
274 JALR = ((1 << 3) + 1),
Steve Block44f0eee2011-05-26 01:26:41 +0100275 MOVZ = ((1 << 3) + 2),
276 MOVN = ((1 << 3) + 3),
Andrei Popescu31002712010-02-23 13:46:05 +0000277 BREAK = ((1 << 3) + 5),
278
279 MFHI = ((2 << 3) + 0),
280 MFLO = ((2 << 3) + 2),
281
282 MULT = ((3 << 3) + 0),
283 MULTU = ((3 << 3) + 1),
284 DIV = ((3 << 3) + 2),
285 DIVU = ((3 << 3) + 3),
286
287 ADD = ((4 << 3) + 0),
288 ADDU = ((4 << 3) + 1),
289 SUB = ((4 << 3) + 2),
290 SUBU = ((4 << 3) + 3),
291 AND = ((4 << 3) + 4),
292 OR = ((4 << 3) + 5),
293 XOR = ((4 << 3) + 6),
294 NOR = ((4 << 3) + 7),
295
296 SLT = ((5 << 3) + 2),
297 SLTU = ((5 << 3) + 3),
298
299 TGE = ((6 << 3) + 0),
300 TGEU = ((6 << 3) + 1),
301 TLT = ((6 << 3) + 2),
302 TLTU = ((6 << 3) + 3),
303 TEQ = ((6 << 3) + 4),
304 TNE = ((6 << 3) + 6),
305
306 // SPECIAL2 Encoding of Function Field.
307 MUL = ((0 << 3) + 2),
Steve Block44f0eee2011-05-26 01:26:41 +0100308 CLZ = ((4 << 3) + 0),
309 CLO = ((4 << 3) + 1),
310
311 // SPECIAL3 Encoding of Function Field.
312 EXT = ((0 << 3) + 0),
313 INS = ((0 << 3) + 4),
Andrei Popescu31002712010-02-23 13:46:05 +0000314
315 // REGIMM encoding of rt Field.
316 BLTZ = ((0 << 3) + 0) << 16,
317 BGEZ = ((0 << 3) + 1) << 16,
318 BLTZAL = ((2 << 3) + 0) << 16,
319 BGEZAL = ((2 << 3) + 1) << 16,
320
321 // COP1 Encoding of rs Field.
322 MFC1 = ((0 << 3) + 0) << 21,
Steve Block44f0eee2011-05-26 01:26:41 +0100323 CFC1 = ((0 << 3) + 2) << 21,
Andrei Popescu31002712010-02-23 13:46:05 +0000324 MFHC1 = ((0 << 3) + 3) << 21,
325 MTC1 = ((0 << 3) + 4) << 21,
Steve Block44f0eee2011-05-26 01:26:41 +0100326 CTC1 = ((0 << 3) + 6) << 21,
Andrei Popescu31002712010-02-23 13:46:05 +0000327 MTHC1 = ((0 << 3) + 7) << 21,
328 BC1 = ((1 << 3) + 0) << 21,
329 S = ((2 << 3) + 0) << 21,
330 D = ((2 << 3) + 1) << 21,
331 W = ((2 << 3) + 4) << 21,
332 L = ((2 << 3) + 5) << 21,
333 PS = ((2 << 3) + 6) << 21,
334 // COP1 Encoding of Function Field When rs=S.
Steve Block44f0eee2011-05-26 01:26:41 +0100335 ROUND_L_S = ((1 << 3) + 0),
336 TRUNC_L_S = ((1 << 3) + 1),
337 CEIL_L_S = ((1 << 3) + 2),
338 FLOOR_L_S = ((1 << 3) + 3),
339 ROUND_W_S = ((1 << 3) + 4),
340 TRUNC_W_S = ((1 << 3) + 5),
341 CEIL_W_S = ((1 << 3) + 6),
342 FLOOR_W_S = ((1 << 3) + 7),
Andrei Popescu31002712010-02-23 13:46:05 +0000343 CVT_D_S = ((4 << 3) + 1),
344 CVT_W_S = ((4 << 3) + 4),
345 CVT_L_S = ((4 << 3) + 5),
346 CVT_PS_S = ((4 << 3) + 6),
347 // COP1 Encoding of Function Field When rs=D.
Steve Block44f0eee2011-05-26 01:26:41 +0100348 ADD_D = ((0 << 3) + 0),
349 SUB_D = ((0 << 3) + 1),
350 MUL_D = ((0 << 3) + 2),
351 DIV_D = ((0 << 3) + 3),
352 SQRT_D = ((0 << 3) + 4),
353 ABS_D = ((0 << 3) + 5),
354 MOV_D = ((0 << 3) + 6),
355 NEG_D = ((0 << 3) + 7),
356 ROUND_L_D = ((1 << 3) + 0),
357 TRUNC_L_D = ((1 << 3) + 1),
358 CEIL_L_D = ((1 << 3) + 2),
359 FLOOR_L_D = ((1 << 3) + 3),
360 ROUND_W_D = ((1 << 3) + 4),
361 TRUNC_W_D = ((1 << 3) + 5),
362 CEIL_W_D = ((1 << 3) + 6),
363 FLOOR_W_D = ((1 << 3) + 7),
Andrei Popescu31002712010-02-23 13:46:05 +0000364 CVT_S_D = ((4 << 3) + 0),
365 CVT_W_D = ((4 << 3) + 4),
366 CVT_L_D = ((4 << 3) + 5),
Steve Block44f0eee2011-05-26 01:26:41 +0100367 C_F_D = ((6 << 3) + 0),
368 C_UN_D = ((6 << 3) + 1),
369 C_EQ_D = ((6 << 3) + 2),
370 C_UEQ_D = ((6 << 3) + 3),
371 C_OLT_D = ((6 << 3) + 4),
372 C_ULT_D = ((6 << 3) + 5),
373 C_OLE_D = ((6 << 3) + 6),
374 C_ULE_D = ((6 << 3) + 7),
Andrei Popescu31002712010-02-23 13:46:05 +0000375 // COP1 Encoding of Function Field When rs=W or L.
376 CVT_S_W = ((4 << 3) + 0),
377 CVT_D_W = ((4 << 3) + 1),
378 CVT_S_L = ((4 << 3) + 0),
379 CVT_D_L = ((4 << 3) + 1),
380 // COP1 Encoding of Function Field When rs=PS.
381
382 NULLSF = 0
383};
384
385
386// ----- Emulated conditions.
387// On MIPS we use this enum to abstract from conditionnal branch instructions.
388// the 'U' prefix is used to specify unsigned comparisons.
389enum Condition {
390 // Any value < 0 is considered no_condition.
Steve Block44f0eee2011-05-26 01:26:41 +0100391 kNoCondition = -1,
Andrei Popescu31002712010-02-23 13:46:05 +0000392
393 overflow = 0,
394 no_overflow = 1,
395 Uless = 2,
396 Ugreater_equal= 3,
397 equal = 4,
398 not_equal = 5,
399 Uless_equal = 6,
400 Ugreater = 7,
401 negative = 8,
402 positive = 9,
403 parity_even = 10,
404 parity_odd = 11,
405 less = 12,
406 greater_equal = 13,
407 less_equal = 14,
408 greater = 15,
409
410 cc_always = 16,
411
Ben Murdoch257744e2011-11-30 15:57:28 +0000412 // Aliases.
Andrei Popescu31002712010-02-23 13:46:05 +0000413 carry = Uless,
414 not_carry = Ugreater_equal,
415 zero = equal,
416 eq = equal,
417 not_zero = not_equal,
418 ne = not_equal,
Steve Block44f0eee2011-05-26 01:26:41 +0100419 nz = not_equal,
Andrei Popescu31002712010-02-23 13:46:05 +0000420 sign = negative,
421 not_sign = positive,
Steve Block44f0eee2011-05-26 01:26:41 +0100422 mi = negative,
423 pl = positive,
424 hi = Ugreater,
425 ls = Uless_equal,
426 ge = greater_equal,
427 lt = less,
428 gt = greater,
429 le = less_equal,
430 hs = Ugreater_equal,
431 lo = Uless,
432 al = cc_always,
Andrei Popescu31002712010-02-23 13:46:05 +0000433
Steve Block44f0eee2011-05-26 01:26:41 +0100434 cc_default = kNoCondition
Andrei Popescu31002712010-02-23 13:46:05 +0000435};
436
Steve Block44f0eee2011-05-26 01:26:41 +0100437
438// Returns the equivalent of !cc.
439// Negation of the default kNoCondition (-1) results in a non-default
440// no_condition value (-2). As long as tests for no_condition check
441// for condition < 0, this will work as expected.
442inline Condition NegateCondition(Condition cc) {
443 ASSERT(cc != cc_always);
444 return static_cast<Condition>(cc ^ 1);
445}
446
447
448inline Condition ReverseCondition(Condition cc) {
449 switch (cc) {
450 case Uless:
451 return Ugreater;
452 case Ugreater:
453 return Uless;
454 case Ugreater_equal:
455 return Uless_equal;
456 case Uless_equal:
457 return Ugreater_equal;
458 case less:
459 return greater;
460 case greater:
461 return less;
462 case greater_equal:
463 return less_equal;
464 case less_equal:
465 return greater_equal;
466 default:
467 return cc;
468 };
469}
470
471
Andrei Popescu31002712010-02-23 13:46:05 +0000472// ----- Coprocessor conditions.
473enum FPUCondition {
Ben Murdoch257744e2011-11-30 15:57:28 +0000474 F, // False.
475 UN, // Unordered.
476 EQ, // Equal.
477 UEQ, // Unordered or Equal.
478 OLT, // Ordered or Less Than.
479 ULT, // Unordered or Less Than.
480 OLE, // Ordered or Less Than or Equal.
481 ULE // Unordered or Less Than or Equal.
Andrei Popescu31002712010-02-23 13:46:05 +0000482};
483
484
Steve Block44f0eee2011-05-26 01:26:41 +0100485// -----------------------------------------------------------------------------
486// Hints.
487
488// Branch hints are not used on the MIPS. They are defined so that they can
489// appear in shared function signatures, but will be ignored in MIPS
490// implementations.
491enum Hint {
492 no_hint = 0
493};
494
495
496inline Hint NegateHint(Hint hint) {
497 return no_hint;
498}
499
500
501// -----------------------------------------------------------------------------
502// Specific instructions, constants, and masks.
503// These constants are declared in assembler-mips.cc, as they use named
504// registers and other constants.
505
506// addiu(sp, sp, 4) aka Pop() operation or part of Pop(r)
507// operations as post-increment of sp.
508extern const Instr kPopInstruction;
509// addiu(sp, sp, -4) part of Push(r) operation as pre-decrement of sp.
510extern const Instr kPushInstruction;
511// sw(r, MemOperand(sp, 0))
512extern const Instr kPushRegPattern;
Ben Murdoch257744e2011-11-30 15:57:28 +0000513// lw(r, MemOperand(sp, 0))
Steve Block44f0eee2011-05-26 01:26:41 +0100514extern const Instr kPopRegPattern;
515extern const Instr kLwRegFpOffsetPattern;
516extern const Instr kSwRegFpOffsetPattern;
517extern const Instr kLwRegFpNegOffsetPattern;
518extern const Instr kSwRegFpNegOffsetPattern;
519// A mask for the Rt register for push, pop, lw, sw instructions.
520extern const Instr kRtMask;
521extern const Instr kLwSwInstrTypeMask;
522extern const Instr kLwSwInstrArgumentMask;
523extern const Instr kLwSwOffsetMask;
524
Andrei Popescu31002712010-02-23 13:46:05 +0000525// Break 0xfffff, reserved for redirected real time call.
526const Instr rtCallRedirInstr = SPECIAL | BREAK | call_rt_redirected << 6;
527// A nop instruction. (Encoding of sll 0 0 0).
528const Instr nopInstr = 0;
529
530class Instruction {
531 public:
532 enum {
Steve Block44f0eee2011-05-26 01:26:41 +0100533 kInstrSize = 4,
534 kInstrSizeLog2 = 2,
Andrei Popescu31002712010-02-23 13:46:05 +0000535 // On MIPS PC cannot actually be directly accessed. We behave as if PC was
Steve Block44f0eee2011-05-26 01:26:41 +0100536 // always the value of the current instruction being executed.
Andrei Popescu31002712010-02-23 13:46:05 +0000537 kPCReadOffset = 0
538 };
539
540 // Get the raw instruction bits.
541 inline Instr InstructionBits() const {
542 return *reinterpret_cast<const Instr*>(this);
543 }
544
545 // Set the raw instruction bits to value.
546 inline void SetInstructionBits(Instr value) {
547 *reinterpret_cast<Instr*>(this) = value;
548 }
549
550 // Read one particular bit out of the instruction bits.
551 inline int Bit(int nr) const {
552 return (InstructionBits() >> nr) & 1;
553 }
554
555 // Read a bit field out of the instruction bits.
556 inline int Bits(int hi, int lo) const {
557 return (InstructionBits() >> lo) & ((2 << (hi - lo)) - 1);
558 }
559
560 // Instruction type.
561 enum Type {
562 kRegisterType,
563 kImmediateType,
564 kJumpType,
565 kUnsupported = -1
566 };
567
568 // Get the encoding type of the instruction.
569 Type InstructionType() const;
570
571
572 // Accessors for the different named fields used in the MIPS encoding.
Steve Block44f0eee2011-05-26 01:26:41 +0100573 inline Opcode OpcodeValue() const {
Andrei Popescu31002712010-02-23 13:46:05 +0000574 return static_cast<Opcode>(
575 Bits(kOpcodeShift + kOpcodeBits - 1, kOpcodeShift));
576 }
577
Steve Block44f0eee2011-05-26 01:26:41 +0100578 inline int RsValue() const {
Andrei Popescu31002712010-02-23 13:46:05 +0000579 ASSERT(InstructionType() == kRegisterType ||
580 InstructionType() == kImmediateType);
581 return Bits(kRsShift + kRsBits - 1, kRsShift);
582 }
583
Steve Block44f0eee2011-05-26 01:26:41 +0100584 inline int RtValue() const {
Andrei Popescu31002712010-02-23 13:46:05 +0000585 ASSERT(InstructionType() == kRegisterType ||
586 InstructionType() == kImmediateType);
587 return Bits(kRtShift + kRtBits - 1, kRtShift);
588 }
589
Steve Block44f0eee2011-05-26 01:26:41 +0100590 inline int RdValue() const {
Andrei Popescu31002712010-02-23 13:46:05 +0000591 ASSERT(InstructionType() == kRegisterType);
592 return Bits(kRdShift + kRdBits - 1, kRdShift);
593 }
594
Steve Block44f0eee2011-05-26 01:26:41 +0100595 inline int SaValue() const {
Andrei Popescu31002712010-02-23 13:46:05 +0000596 ASSERT(InstructionType() == kRegisterType);
597 return Bits(kSaShift + kSaBits - 1, kSaShift);
598 }
599
Steve Block44f0eee2011-05-26 01:26:41 +0100600 inline int FunctionValue() const {
Andrei Popescu31002712010-02-23 13:46:05 +0000601 ASSERT(InstructionType() == kRegisterType ||
602 InstructionType() == kImmediateType);
603 return Bits(kFunctionShift + kFunctionBits - 1, kFunctionShift);
604 }
605
Steve Block44f0eee2011-05-26 01:26:41 +0100606 inline int FdValue() const {
607 return Bits(kFdShift + kFdBits - 1, kFdShift);
Andrei Popescu31002712010-02-23 13:46:05 +0000608 }
609
Steve Block44f0eee2011-05-26 01:26:41 +0100610 inline int FsValue() const {
611 return Bits(kFsShift + kFsBits - 1, kFsShift);
612 }
613
614 inline int FtValue() const {
615 return Bits(kFtShift + kFtBits - 1, kFtShift);
616 }
617
618 // Float Compare condition code instruction bits.
619 inline int FCccValue() const {
620 return Bits(kFCccShift + kFCccBits - 1, kFCccShift);
621 }
622
623 // Float Branch condition code instruction bits.
624 inline int FBccValue() const {
625 return Bits(kFBccShift + kFBccBits - 1, kFBccShift);
626 }
627
628 // Float Branch true/false instruction bit.
629 inline int FBtrueValue() const {
630 return Bits(kFBtrueShift + kFBtrueBits - 1, kFBtrueShift);
Andrei Popescu31002712010-02-23 13:46:05 +0000631 }
632
633 // Return the fields at their original place in the instruction encoding.
634 inline Opcode OpcodeFieldRaw() const {
635 return static_cast<Opcode>(InstructionBits() & kOpcodeMask);
636 }
637
638 inline int RsFieldRaw() const {
639 ASSERT(InstructionType() == kRegisterType ||
640 InstructionType() == kImmediateType);
641 return InstructionBits() & kRsFieldMask;
642 }
643
Steve Block44f0eee2011-05-26 01:26:41 +0100644 // Same as above function, but safe to call within InstructionType().
645 inline int RsFieldRawNoAssert() const {
646 return InstructionBits() & kRsFieldMask;
647 }
648
Andrei Popescu31002712010-02-23 13:46:05 +0000649 inline int RtFieldRaw() const {
650 ASSERT(InstructionType() == kRegisterType ||
651 InstructionType() == kImmediateType);
652 return InstructionBits() & kRtFieldMask;
653 }
654
655 inline int RdFieldRaw() const {
656 ASSERT(InstructionType() == kRegisterType);
657 return InstructionBits() & kRdFieldMask;
658 }
659
660 inline int SaFieldRaw() const {
661 ASSERT(InstructionType() == kRegisterType);
662 return InstructionBits() & kSaFieldMask;
663 }
664
665 inline int FunctionFieldRaw() const {
666 return InstructionBits() & kFunctionFieldMask;
667 }
668
669 // Get the secondary field according to the opcode.
Steve Block44f0eee2011-05-26 01:26:41 +0100670 inline int SecondaryValue() const {
Andrei Popescu31002712010-02-23 13:46:05 +0000671 Opcode op = OpcodeFieldRaw();
672 switch (op) {
673 case SPECIAL:
674 case SPECIAL2:
Steve Block44f0eee2011-05-26 01:26:41 +0100675 return FunctionValue();
Andrei Popescu31002712010-02-23 13:46:05 +0000676 case COP1:
Steve Block44f0eee2011-05-26 01:26:41 +0100677 return RsValue();
Andrei Popescu31002712010-02-23 13:46:05 +0000678 case REGIMM:
Steve Block44f0eee2011-05-26 01:26:41 +0100679 return RtValue();
Andrei Popescu31002712010-02-23 13:46:05 +0000680 default:
681 return NULLSF;
682 }
683 }
684
Steve Block44f0eee2011-05-26 01:26:41 +0100685 inline int32_t Imm16Value() const {
Andrei Popescu31002712010-02-23 13:46:05 +0000686 ASSERT(InstructionType() == kImmediateType);
687 return Bits(kImm16Shift + kImm16Bits - 1, kImm16Shift);
688 }
689
Steve Block44f0eee2011-05-26 01:26:41 +0100690 inline int32_t Imm26Value() const {
Andrei Popescu31002712010-02-23 13:46:05 +0000691 ASSERT(InstructionType() == kJumpType);
692 return Bits(kImm16Shift + kImm26Bits - 1, kImm26Shift);
693 }
694
695 // Say if the instruction should not be used in a branch delay slot.
Steve Block44f0eee2011-05-26 01:26:41 +0100696 bool IsForbiddenInBranchDelay() const;
Andrei Popescu31002712010-02-23 13:46:05 +0000697 // Say if the instruction 'links'. eg: jal, bal.
Steve Block44f0eee2011-05-26 01:26:41 +0100698 bool IsLinkingInstruction() const;
Andrei Popescu31002712010-02-23 13:46:05 +0000699 // Say if the instruction is a break or a trap.
Steve Block44f0eee2011-05-26 01:26:41 +0100700 bool IsTrap() const;
Andrei Popescu31002712010-02-23 13:46:05 +0000701
702 // Instructions are read of out a code stream. The only way to get a
703 // reference to an instruction is to convert a pointer. There is no way
704 // to allocate or create instances of class Instruction.
705 // Use the At(pc) function to create references to Instruction.
Ben Murdoch257744e2011-11-30 15:57:28 +0000706 static Instruction* At(byte* pc) {
Andrei Popescu31002712010-02-23 13:46:05 +0000707 return reinterpret_cast<Instruction*>(pc);
708 }
709
710 private:
711 // We need to prevent the creation of instances of class Instruction.
712 DISALLOW_IMPLICIT_CONSTRUCTORS(Instruction);
713};
714
715
716// -----------------------------------------------------------------------------
717// MIPS assembly various constants.
718
Steve Block44f0eee2011-05-26 01:26:41 +0100719
720static const int kArgsSlotsSize = 4 * Instruction::kInstrSize;
Andrei Popescu31002712010-02-23 13:46:05 +0000721static const int kArgsSlotsNum = 4;
Steve Block44f0eee2011-05-26 01:26:41 +0100722// C/C++ argument slots size.
723static const int kCArgsSlotsSize = 4 * Instruction::kInstrSize;
724// JS argument slots size.
725static const int kJSArgsSlotsSize = 0 * Instruction::kInstrSize;
726// Assembly builtins argument slots size.
727static const int kBArgsSlotsSize = 0 * Instruction::kInstrSize;
Andrei Popescu31002712010-02-23 13:46:05 +0000728
Steve Block44f0eee2011-05-26 01:26:41 +0100729static const int kBranchReturnOffset = 2 * Instruction::kInstrSize;
Andrei Popescu31002712010-02-23 13:46:05 +0000730
Steve Block44f0eee2011-05-26 01:26:41 +0100731static const int kDoubleAlignmentBits = 3;
732static const int kDoubleAlignment = (1 << kDoubleAlignmentBits);
733static const int kDoubleAlignmentMask = kDoubleAlignment - 1;
Andrei Popescu31002712010-02-23 13:46:05 +0000734
735
Steve Block44f0eee2011-05-26 01:26:41 +0100736} } // namespace v8::internal
Andrei Popescu31002712010-02-23 13:46:05 +0000737
738#endif // #ifndef V8_MIPS_CONSTANTS_H_
739