blob: 6bf2570ebd6d8d7b283fb1a8e06b65f640d6ec78 [file] [log] [blame]
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001// Copyright 2011 the V8 project authors. All rights reserved.
Andrei Popescu31002712010-02-23 13:46:05 +00002// 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.
Ben Murdoch3fb3ca82011-12-02 17:19:32 +000096static 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;
Steve Block44f0eee2011-05-26 01:26:41 +0100117
Andrei Popescu31002712010-02-23 13:46:05 +0000118// 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:
Andrei Popescu31002712010-02-23 13:46:05 +0000136 static const char* names_[kNumSimuRegisters];
137 static const RegisterAlias aliases_[];
138};
139
140// Helper functions for converting between register numbers and names.
Steve Block44f0eee2011-05-26 01:26:41 +0100141class FPURegisters {
Andrei Popescu31002712010-02-23 13:46:05 +0000142 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:
Steve Block44f0eee2011-05-26 01:26:41 +0100155 static const char* names_[kNumFPURegisters];
Andrei Popescu31002712010-02-23 13:46:05 +0000156 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
Andrei Popescu31002712010-02-23 13:46:05 +0000166// 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
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000173// 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
Andrei Popescu31002712010-02-23 13:46:05 +0000185// ----- 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;
Steve Block44f0eee2011-05-26 01:26:41 +0100198static const int kLuiShift = 16;
Andrei Popescu31002712010-02-23 13:46:05 +0000199
200static const int kImm16Shift = 0;
201static const int kImm16Bits = 16;
202static const int kImm26Shift = 0;
203static const int kImm26Bits = 26;
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000204static const int kImm28Shift = 0;
205static const int kImm28Bits = 28;
Andrei Popescu31002712010-02-23 13:46:05 +0000206
207static const int kFsShift = 11;
208static const int kFsBits = 5;
209static const int kFtShift = 16;
210static const int kFtBits = 5;
Steve Block44f0eee2011-05-26 01:26:41 +0100211static const int kFdShift = 6;
212static const int kFdBits = 5;
213static const int kFCccShift = 8;
214static const int kFCccBits = 3;
215static const int kFBccShift = 18;
216static const int kFBccBits = 3;
217static const int kFBtrueShift = 16;
218static const int kFBtrueBits = 1;
Andrei Popescu31002712010-02-23 13:46:05 +0000219
Ben Murdoch257744e2011-11-30 15:57:28 +0000220// ----- Miscellaneous useful masks.
Andrei Popescu31002712010-02-23 13:46:05 +0000221// Instruction bit masks.
222static const int kOpcodeMask = ((1 << kOpcodeBits) - 1) << kOpcodeShift;
223static const int kImm16Mask = ((1 << kImm16Bits) - 1) << kImm16Shift;
224static const int kImm26Mask = ((1 << kImm26Bits) - 1) << kImm26Shift;
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000225static const int kImm28Mask = ((1 << kImm28Bits) - 1) << kImm28Shift;
Andrei Popescu31002712010-02-23 13:46:05 +0000226static const int kRsFieldMask = ((1 << kRsBits) - 1) << kRsShift;
227static const int kRtFieldMask = ((1 << kRtBits) - 1) << kRtShift;
228static const int kRdFieldMask = ((1 << kRdBits) - 1) << kRdShift;
229static const int kSaFieldMask = ((1 << kSaBits) - 1) << kSaShift;
230static const int kFunctionFieldMask =
231 ((1 << kFunctionBits) - 1) << kFunctionShift;
232// Misc masks.
Steve Block44f0eee2011-05-26 01:26:41 +0100233static const int kHiMask = 0xffff << 16;
234static const int kLoMask = 0xffff;
235static const int kSignMask = 0x80000000;
Andrei Popescu31002712010-02-23 13:46:05 +0000236
237
238// ----- MIPS Opcodes and Function Fields.
239// We use this presentation to stay close to the table representation in
240// MIPS32 Architecture For Programmers, Volume II: The MIPS32 Instruction Set.
241enum Opcode {
242 SPECIAL = 0 << kOpcodeShift,
243 REGIMM = 1 << kOpcodeShift,
244
245 J = ((0 << 3) + 2) << kOpcodeShift,
246 JAL = ((0 << 3) + 3) << kOpcodeShift,
247 BEQ = ((0 << 3) + 4) << kOpcodeShift,
248 BNE = ((0 << 3) + 5) << kOpcodeShift,
249 BLEZ = ((0 << 3) + 6) << kOpcodeShift,
250 BGTZ = ((0 << 3) + 7) << kOpcodeShift,
251
252 ADDI = ((1 << 3) + 0) << kOpcodeShift,
253 ADDIU = ((1 << 3) + 1) << kOpcodeShift,
254 SLTI = ((1 << 3) + 2) << kOpcodeShift,
255 SLTIU = ((1 << 3) + 3) << kOpcodeShift,
256 ANDI = ((1 << 3) + 4) << kOpcodeShift,
257 ORI = ((1 << 3) + 5) << kOpcodeShift,
258 XORI = ((1 << 3) + 6) << kOpcodeShift,
259 LUI = ((1 << 3) + 7) << kOpcodeShift,
260
Ben Murdoch257744e2011-11-30 15:57:28 +0000261 COP1 = ((2 << 3) + 1) << kOpcodeShift, // Coprocessor 1 class.
Andrei Popescu31002712010-02-23 13:46:05 +0000262 BEQL = ((2 << 3) + 4) << kOpcodeShift,
263 BNEL = ((2 << 3) + 5) << kOpcodeShift,
264 BLEZL = ((2 << 3) + 6) << kOpcodeShift,
265 BGTZL = ((2 << 3) + 7) << kOpcodeShift,
266
267 SPECIAL2 = ((3 << 3) + 4) << kOpcodeShift,
Steve Block44f0eee2011-05-26 01:26:41 +0100268 SPECIAL3 = ((3 << 3) + 7) << kOpcodeShift,
Andrei Popescu31002712010-02-23 13:46:05 +0000269
270 LB = ((4 << 3) + 0) << kOpcodeShift,
Steve Block44f0eee2011-05-26 01:26:41 +0100271 LH = ((4 << 3) + 1) << kOpcodeShift,
272 LWL = ((4 << 3) + 2) << kOpcodeShift,
Andrei Popescu31002712010-02-23 13:46:05 +0000273 LW = ((4 << 3) + 3) << kOpcodeShift,
274 LBU = ((4 << 3) + 4) << kOpcodeShift,
Steve Block44f0eee2011-05-26 01:26:41 +0100275 LHU = ((4 << 3) + 5) << kOpcodeShift,
276 LWR = ((4 << 3) + 6) << kOpcodeShift,
Andrei Popescu31002712010-02-23 13:46:05 +0000277 SB = ((5 << 3) + 0) << kOpcodeShift,
Steve Block44f0eee2011-05-26 01:26:41 +0100278 SH = ((5 << 3) + 1) << kOpcodeShift,
279 SWL = ((5 << 3) + 2) << kOpcodeShift,
Andrei Popescu31002712010-02-23 13:46:05 +0000280 SW = ((5 << 3) + 3) << kOpcodeShift,
Steve Block44f0eee2011-05-26 01:26:41 +0100281 SWR = ((5 << 3) + 6) << kOpcodeShift,
Andrei Popescu31002712010-02-23 13:46:05 +0000282
283 LWC1 = ((6 << 3) + 1) << kOpcodeShift,
284 LDC1 = ((6 << 3) + 5) << kOpcodeShift,
285
286 SWC1 = ((7 << 3) + 1) << kOpcodeShift,
287 SDC1 = ((7 << 3) + 5) << kOpcodeShift
288};
289
290enum SecondaryField {
291 // SPECIAL Encoding of Function Field.
292 SLL = ((0 << 3) + 0),
293 SRL = ((0 << 3) + 2),
294 SRA = ((0 << 3) + 3),
295 SLLV = ((0 << 3) + 4),
296 SRLV = ((0 << 3) + 6),
297 SRAV = ((0 << 3) + 7),
Steve Block44f0eee2011-05-26 01:26:41 +0100298 MOVCI = ((0 << 3) + 1),
Andrei Popescu31002712010-02-23 13:46:05 +0000299
300 JR = ((1 << 3) + 0),
301 JALR = ((1 << 3) + 1),
Steve Block44f0eee2011-05-26 01:26:41 +0100302 MOVZ = ((1 << 3) + 2),
303 MOVN = ((1 << 3) + 3),
Andrei Popescu31002712010-02-23 13:46:05 +0000304 BREAK = ((1 << 3) + 5),
305
306 MFHI = ((2 << 3) + 0),
307 MFLO = ((2 << 3) + 2),
308
309 MULT = ((3 << 3) + 0),
310 MULTU = ((3 << 3) + 1),
311 DIV = ((3 << 3) + 2),
312 DIVU = ((3 << 3) + 3),
313
314 ADD = ((4 << 3) + 0),
315 ADDU = ((4 << 3) + 1),
316 SUB = ((4 << 3) + 2),
317 SUBU = ((4 << 3) + 3),
318 AND = ((4 << 3) + 4),
319 OR = ((4 << 3) + 5),
320 XOR = ((4 << 3) + 6),
321 NOR = ((4 << 3) + 7),
322
323 SLT = ((5 << 3) + 2),
324 SLTU = ((5 << 3) + 3),
325
326 TGE = ((6 << 3) + 0),
327 TGEU = ((6 << 3) + 1),
328 TLT = ((6 << 3) + 2),
329 TLTU = ((6 << 3) + 3),
330 TEQ = ((6 << 3) + 4),
331 TNE = ((6 << 3) + 6),
332
333 // SPECIAL2 Encoding of Function Field.
334 MUL = ((0 << 3) + 2),
Steve Block44f0eee2011-05-26 01:26:41 +0100335 CLZ = ((4 << 3) + 0),
336 CLO = ((4 << 3) + 1),
337
338 // SPECIAL3 Encoding of Function Field.
339 EXT = ((0 << 3) + 0),
340 INS = ((0 << 3) + 4),
Andrei Popescu31002712010-02-23 13:46:05 +0000341
342 // REGIMM encoding of rt Field.
343 BLTZ = ((0 << 3) + 0) << 16,
344 BGEZ = ((0 << 3) + 1) << 16,
345 BLTZAL = ((2 << 3) + 0) << 16,
346 BGEZAL = ((2 << 3) + 1) << 16,
347
348 // COP1 Encoding of rs Field.
349 MFC1 = ((0 << 3) + 0) << 21,
Steve Block44f0eee2011-05-26 01:26:41 +0100350 CFC1 = ((0 << 3) + 2) << 21,
Andrei Popescu31002712010-02-23 13:46:05 +0000351 MFHC1 = ((0 << 3) + 3) << 21,
352 MTC1 = ((0 << 3) + 4) << 21,
Steve Block44f0eee2011-05-26 01:26:41 +0100353 CTC1 = ((0 << 3) + 6) << 21,
Andrei Popescu31002712010-02-23 13:46:05 +0000354 MTHC1 = ((0 << 3) + 7) << 21,
355 BC1 = ((1 << 3) + 0) << 21,
356 S = ((2 << 3) + 0) << 21,
357 D = ((2 << 3) + 1) << 21,
358 W = ((2 << 3) + 4) << 21,
359 L = ((2 << 3) + 5) << 21,
360 PS = ((2 << 3) + 6) << 21,
361 // COP1 Encoding of Function Field When rs=S.
Steve Block44f0eee2011-05-26 01:26:41 +0100362 ROUND_L_S = ((1 << 3) + 0),
363 TRUNC_L_S = ((1 << 3) + 1),
364 CEIL_L_S = ((1 << 3) + 2),
365 FLOOR_L_S = ((1 << 3) + 3),
366 ROUND_W_S = ((1 << 3) + 4),
367 TRUNC_W_S = ((1 << 3) + 5),
368 CEIL_W_S = ((1 << 3) + 6),
369 FLOOR_W_S = ((1 << 3) + 7),
Andrei Popescu31002712010-02-23 13:46:05 +0000370 CVT_D_S = ((4 << 3) + 1),
371 CVT_W_S = ((4 << 3) + 4),
372 CVT_L_S = ((4 << 3) + 5),
373 CVT_PS_S = ((4 << 3) + 6),
374 // COP1 Encoding of Function Field When rs=D.
Steve Block44f0eee2011-05-26 01:26:41 +0100375 ADD_D = ((0 << 3) + 0),
376 SUB_D = ((0 << 3) + 1),
377 MUL_D = ((0 << 3) + 2),
378 DIV_D = ((0 << 3) + 3),
379 SQRT_D = ((0 << 3) + 4),
380 ABS_D = ((0 << 3) + 5),
381 MOV_D = ((0 << 3) + 6),
382 NEG_D = ((0 << 3) + 7),
383 ROUND_L_D = ((1 << 3) + 0),
384 TRUNC_L_D = ((1 << 3) + 1),
385 CEIL_L_D = ((1 << 3) + 2),
386 FLOOR_L_D = ((1 << 3) + 3),
387 ROUND_W_D = ((1 << 3) + 4),
388 TRUNC_W_D = ((1 << 3) + 5),
389 CEIL_W_D = ((1 << 3) + 6),
390 FLOOR_W_D = ((1 << 3) + 7),
Andrei Popescu31002712010-02-23 13:46:05 +0000391 CVT_S_D = ((4 << 3) + 0),
392 CVT_W_D = ((4 << 3) + 4),
393 CVT_L_D = ((4 << 3) + 5),
Steve Block44f0eee2011-05-26 01:26:41 +0100394 C_F_D = ((6 << 3) + 0),
395 C_UN_D = ((6 << 3) + 1),
396 C_EQ_D = ((6 << 3) + 2),
397 C_UEQ_D = ((6 << 3) + 3),
398 C_OLT_D = ((6 << 3) + 4),
399 C_ULT_D = ((6 << 3) + 5),
400 C_OLE_D = ((6 << 3) + 6),
401 C_ULE_D = ((6 << 3) + 7),
Andrei Popescu31002712010-02-23 13:46:05 +0000402 // COP1 Encoding of Function Field When rs=W or L.
403 CVT_S_W = ((4 << 3) + 0),
404 CVT_D_W = ((4 << 3) + 1),
405 CVT_S_L = ((4 << 3) + 0),
406 CVT_D_L = ((4 << 3) + 1),
407 // COP1 Encoding of Function Field When rs=PS.
408
409 NULLSF = 0
410};
411
412
413// ----- Emulated conditions.
414// On MIPS we use this enum to abstract from conditionnal branch instructions.
415// the 'U' prefix is used to specify unsigned comparisons.
416enum Condition {
417 // Any value < 0 is considered no_condition.
Steve Block44f0eee2011-05-26 01:26:41 +0100418 kNoCondition = -1,
Andrei Popescu31002712010-02-23 13:46:05 +0000419
420 overflow = 0,
421 no_overflow = 1,
422 Uless = 2,
423 Ugreater_equal= 3,
424 equal = 4,
425 not_equal = 5,
426 Uless_equal = 6,
427 Ugreater = 7,
428 negative = 8,
429 positive = 9,
430 parity_even = 10,
431 parity_odd = 11,
432 less = 12,
433 greater_equal = 13,
434 less_equal = 14,
435 greater = 15,
436
437 cc_always = 16,
438
Ben Murdoch257744e2011-11-30 15:57:28 +0000439 // Aliases.
Andrei Popescu31002712010-02-23 13:46:05 +0000440 carry = Uless,
441 not_carry = Ugreater_equal,
442 zero = equal,
443 eq = equal,
444 not_zero = not_equal,
445 ne = not_equal,
Steve Block44f0eee2011-05-26 01:26:41 +0100446 nz = not_equal,
Andrei Popescu31002712010-02-23 13:46:05 +0000447 sign = negative,
448 not_sign = positive,
Steve Block44f0eee2011-05-26 01:26:41 +0100449 mi = negative,
450 pl = positive,
451 hi = Ugreater,
452 ls = Uless_equal,
453 ge = greater_equal,
454 lt = less,
455 gt = greater,
456 le = less_equal,
457 hs = Ugreater_equal,
458 lo = Uless,
459 al = cc_always,
Andrei Popescu31002712010-02-23 13:46:05 +0000460
Steve Block44f0eee2011-05-26 01:26:41 +0100461 cc_default = kNoCondition
Andrei Popescu31002712010-02-23 13:46:05 +0000462};
463
Steve Block44f0eee2011-05-26 01:26:41 +0100464
465// Returns the equivalent of !cc.
466// Negation of the default kNoCondition (-1) results in a non-default
467// no_condition value (-2). As long as tests for no_condition check
468// for condition < 0, this will work as expected.
469inline Condition NegateCondition(Condition cc) {
470 ASSERT(cc != cc_always);
471 return static_cast<Condition>(cc ^ 1);
472}
473
474
475inline Condition ReverseCondition(Condition cc) {
476 switch (cc) {
477 case Uless:
478 return Ugreater;
479 case Ugreater:
480 return Uless;
481 case Ugreater_equal:
482 return Uless_equal;
483 case Uless_equal:
484 return Ugreater_equal;
485 case less:
486 return greater;
487 case greater:
488 return less;
489 case greater_equal:
490 return less_equal;
491 case less_equal:
492 return greater_equal;
493 default:
494 return cc;
495 };
496}
497
498
Andrei Popescu31002712010-02-23 13:46:05 +0000499// ----- Coprocessor conditions.
500enum FPUCondition {
Ben Murdoch257744e2011-11-30 15:57:28 +0000501 F, // False.
502 UN, // Unordered.
503 EQ, // Equal.
504 UEQ, // Unordered or Equal.
505 OLT, // Ordered or Less Than.
506 ULT, // Unordered or Less Than.
507 OLE, // Ordered or Less Than or Equal.
508 ULE // Unordered or Less Than or Equal.
Andrei Popescu31002712010-02-23 13:46:05 +0000509};
510
511
Steve Block44f0eee2011-05-26 01:26:41 +0100512// -----------------------------------------------------------------------------
513// Hints.
514
515// Branch hints are not used on the MIPS. They are defined so that they can
516// appear in shared function signatures, but will be ignored in MIPS
517// implementations.
518enum Hint {
519 no_hint = 0
520};
521
522
523inline Hint NegateHint(Hint hint) {
524 return no_hint;
525}
526
527
528// -----------------------------------------------------------------------------
529// Specific instructions, constants, and masks.
530// These constants are declared in assembler-mips.cc, as they use named
531// registers and other constants.
532
533// addiu(sp, sp, 4) aka Pop() operation or part of Pop(r)
534// operations as post-increment of sp.
535extern const Instr kPopInstruction;
536// addiu(sp, sp, -4) part of Push(r) operation as pre-decrement of sp.
537extern const Instr kPushInstruction;
538// sw(r, MemOperand(sp, 0))
539extern const Instr kPushRegPattern;
Ben Murdoch257744e2011-11-30 15:57:28 +0000540// lw(r, MemOperand(sp, 0))
Steve Block44f0eee2011-05-26 01:26:41 +0100541extern const Instr kPopRegPattern;
542extern const Instr kLwRegFpOffsetPattern;
543extern const Instr kSwRegFpOffsetPattern;
544extern const Instr kLwRegFpNegOffsetPattern;
545extern const Instr kSwRegFpNegOffsetPattern;
546// A mask for the Rt register for push, pop, lw, sw instructions.
547extern const Instr kRtMask;
548extern const Instr kLwSwInstrTypeMask;
549extern const Instr kLwSwInstrArgumentMask;
550extern const Instr kLwSwOffsetMask;
551
Andrei Popescu31002712010-02-23 13:46:05 +0000552// Break 0xfffff, reserved for redirected real time call.
553const Instr rtCallRedirInstr = SPECIAL | BREAK | call_rt_redirected << 6;
554// A nop instruction. (Encoding of sll 0 0 0).
555const Instr nopInstr = 0;
556
557class Instruction {
558 public:
559 enum {
Steve Block44f0eee2011-05-26 01:26:41 +0100560 kInstrSize = 4,
561 kInstrSizeLog2 = 2,
Andrei Popescu31002712010-02-23 13:46:05 +0000562 // On MIPS PC cannot actually be directly accessed. We behave as if PC was
Steve Block44f0eee2011-05-26 01:26:41 +0100563 // always the value of the current instruction being executed.
Andrei Popescu31002712010-02-23 13:46:05 +0000564 kPCReadOffset = 0
565 };
566
567 // Get the raw instruction bits.
568 inline Instr InstructionBits() const {
569 return *reinterpret_cast<const Instr*>(this);
570 }
571
572 // Set the raw instruction bits to value.
573 inline void SetInstructionBits(Instr value) {
574 *reinterpret_cast<Instr*>(this) = value;
575 }
576
577 // Read one particular bit out of the instruction bits.
578 inline int Bit(int nr) const {
579 return (InstructionBits() >> nr) & 1;
580 }
581
582 // Read a bit field out of the instruction bits.
583 inline int Bits(int hi, int lo) const {
584 return (InstructionBits() >> lo) & ((2 << (hi - lo)) - 1);
585 }
586
587 // Instruction type.
588 enum Type {
589 kRegisterType,
590 kImmediateType,
591 kJumpType,
592 kUnsupported = -1
593 };
594
595 // Get the encoding type of the instruction.
596 Type InstructionType() const;
597
598
599 // Accessors for the different named fields used in the MIPS encoding.
Steve Block44f0eee2011-05-26 01:26:41 +0100600 inline Opcode OpcodeValue() const {
Andrei Popescu31002712010-02-23 13:46:05 +0000601 return static_cast<Opcode>(
602 Bits(kOpcodeShift + kOpcodeBits - 1, kOpcodeShift));
603 }
604
Steve Block44f0eee2011-05-26 01:26:41 +0100605 inline int RsValue() const {
Andrei Popescu31002712010-02-23 13:46:05 +0000606 ASSERT(InstructionType() == kRegisterType ||
607 InstructionType() == kImmediateType);
608 return Bits(kRsShift + kRsBits - 1, kRsShift);
609 }
610
Steve Block44f0eee2011-05-26 01:26:41 +0100611 inline int RtValue() const {
Andrei Popescu31002712010-02-23 13:46:05 +0000612 ASSERT(InstructionType() == kRegisterType ||
613 InstructionType() == kImmediateType);
614 return Bits(kRtShift + kRtBits - 1, kRtShift);
615 }
616
Steve Block44f0eee2011-05-26 01:26:41 +0100617 inline int RdValue() const {
Andrei Popescu31002712010-02-23 13:46:05 +0000618 ASSERT(InstructionType() == kRegisterType);
619 return Bits(kRdShift + kRdBits - 1, kRdShift);
620 }
621
Steve Block44f0eee2011-05-26 01:26:41 +0100622 inline int SaValue() const {
Andrei Popescu31002712010-02-23 13:46:05 +0000623 ASSERT(InstructionType() == kRegisterType);
624 return Bits(kSaShift + kSaBits - 1, kSaShift);
625 }
626
Steve Block44f0eee2011-05-26 01:26:41 +0100627 inline int FunctionValue() const {
Andrei Popescu31002712010-02-23 13:46:05 +0000628 ASSERT(InstructionType() == kRegisterType ||
629 InstructionType() == kImmediateType);
630 return Bits(kFunctionShift + kFunctionBits - 1, kFunctionShift);
631 }
632
Steve Block44f0eee2011-05-26 01:26:41 +0100633 inline int FdValue() const {
634 return Bits(kFdShift + kFdBits - 1, kFdShift);
Andrei Popescu31002712010-02-23 13:46:05 +0000635 }
636
Steve Block44f0eee2011-05-26 01:26:41 +0100637 inline int FsValue() const {
638 return Bits(kFsShift + kFsBits - 1, kFsShift);
639 }
640
641 inline int FtValue() const {
642 return Bits(kFtShift + kFtBits - 1, kFtShift);
643 }
644
645 // Float Compare condition code instruction bits.
646 inline int FCccValue() const {
647 return Bits(kFCccShift + kFCccBits - 1, kFCccShift);
648 }
649
650 // Float Branch condition code instruction bits.
651 inline int FBccValue() const {
652 return Bits(kFBccShift + kFBccBits - 1, kFBccShift);
653 }
654
655 // Float Branch true/false instruction bit.
656 inline int FBtrueValue() const {
657 return Bits(kFBtrueShift + kFBtrueBits - 1, kFBtrueShift);
Andrei Popescu31002712010-02-23 13:46:05 +0000658 }
659
660 // Return the fields at their original place in the instruction encoding.
661 inline Opcode OpcodeFieldRaw() const {
662 return static_cast<Opcode>(InstructionBits() & kOpcodeMask);
663 }
664
665 inline int RsFieldRaw() const {
666 ASSERT(InstructionType() == kRegisterType ||
667 InstructionType() == kImmediateType);
668 return InstructionBits() & kRsFieldMask;
669 }
670
Steve Block44f0eee2011-05-26 01:26:41 +0100671 // Same as above function, but safe to call within InstructionType().
672 inline int RsFieldRawNoAssert() const {
673 return InstructionBits() & kRsFieldMask;
674 }
675
Andrei Popescu31002712010-02-23 13:46:05 +0000676 inline int RtFieldRaw() const {
677 ASSERT(InstructionType() == kRegisterType ||
678 InstructionType() == kImmediateType);
679 return InstructionBits() & kRtFieldMask;
680 }
681
682 inline int RdFieldRaw() const {
683 ASSERT(InstructionType() == kRegisterType);
684 return InstructionBits() & kRdFieldMask;
685 }
686
687 inline int SaFieldRaw() const {
688 ASSERT(InstructionType() == kRegisterType);
689 return InstructionBits() & kSaFieldMask;
690 }
691
692 inline int FunctionFieldRaw() const {
693 return InstructionBits() & kFunctionFieldMask;
694 }
695
696 // Get the secondary field according to the opcode.
Steve Block44f0eee2011-05-26 01:26:41 +0100697 inline int SecondaryValue() const {
Andrei Popescu31002712010-02-23 13:46:05 +0000698 Opcode op = OpcodeFieldRaw();
699 switch (op) {
700 case SPECIAL:
701 case SPECIAL2:
Steve Block44f0eee2011-05-26 01:26:41 +0100702 return FunctionValue();
Andrei Popescu31002712010-02-23 13:46:05 +0000703 case COP1:
Steve Block44f0eee2011-05-26 01:26:41 +0100704 return RsValue();
Andrei Popescu31002712010-02-23 13:46:05 +0000705 case REGIMM:
Steve Block44f0eee2011-05-26 01:26:41 +0100706 return RtValue();
Andrei Popescu31002712010-02-23 13:46:05 +0000707 default:
708 return NULLSF;
709 }
710 }
711
Steve Block44f0eee2011-05-26 01:26:41 +0100712 inline int32_t Imm16Value() const {
Andrei Popescu31002712010-02-23 13:46:05 +0000713 ASSERT(InstructionType() == kImmediateType);
714 return Bits(kImm16Shift + kImm16Bits - 1, kImm16Shift);
715 }
716
Steve Block44f0eee2011-05-26 01:26:41 +0100717 inline int32_t Imm26Value() const {
Andrei Popescu31002712010-02-23 13:46:05 +0000718 ASSERT(InstructionType() == kJumpType);
719 return Bits(kImm16Shift + kImm26Bits - 1, kImm26Shift);
720 }
721
722 // Say if the instruction should not be used in a branch delay slot.
Steve Block44f0eee2011-05-26 01:26:41 +0100723 bool IsForbiddenInBranchDelay() const;
Andrei Popescu31002712010-02-23 13:46:05 +0000724 // Say if the instruction 'links'. eg: jal, bal.
Steve Block44f0eee2011-05-26 01:26:41 +0100725 bool IsLinkingInstruction() const;
Andrei Popescu31002712010-02-23 13:46:05 +0000726 // Say if the instruction is a break or a trap.
Steve Block44f0eee2011-05-26 01:26:41 +0100727 bool IsTrap() const;
Andrei Popescu31002712010-02-23 13:46:05 +0000728
729 // Instructions are read of out a code stream. The only way to get a
730 // reference to an instruction is to convert a pointer. There is no way
731 // to allocate or create instances of class Instruction.
732 // Use the At(pc) function to create references to Instruction.
Ben Murdoch257744e2011-11-30 15:57:28 +0000733 static Instruction* At(byte* pc) {
Andrei Popescu31002712010-02-23 13:46:05 +0000734 return reinterpret_cast<Instruction*>(pc);
735 }
736
737 private:
738 // We need to prevent the creation of instances of class Instruction.
739 DISALLOW_IMPLICIT_CONSTRUCTORS(Instruction);
740};
741
742
743// -----------------------------------------------------------------------------
744// MIPS assembly various constants.
745
Steve Block44f0eee2011-05-26 01:26:41 +0100746
747static const int kArgsSlotsSize = 4 * Instruction::kInstrSize;
Andrei Popescu31002712010-02-23 13:46:05 +0000748static const int kArgsSlotsNum = 4;
Steve Block44f0eee2011-05-26 01:26:41 +0100749// C/C++ argument slots size.
750static const int kCArgsSlotsSize = 4 * Instruction::kInstrSize;
751// JS argument slots size.
752static const int kJSArgsSlotsSize = 0 * Instruction::kInstrSize;
753// Assembly builtins argument slots size.
754static const int kBArgsSlotsSize = 0 * Instruction::kInstrSize;
Andrei Popescu31002712010-02-23 13:46:05 +0000755
Steve Block44f0eee2011-05-26 01:26:41 +0100756static const int kBranchReturnOffset = 2 * Instruction::kInstrSize;
Andrei Popescu31002712010-02-23 13:46:05 +0000757
Steve Block44f0eee2011-05-26 01:26:41 +0100758static const int kDoubleAlignmentBits = 3;
759static const int kDoubleAlignment = (1 << kDoubleAlignmentBits);
760static const int kDoubleAlignmentMask = kDoubleAlignment - 1;
Andrei Popescu31002712010-02-23 13:46:05 +0000761
762
Steve Block44f0eee2011-05-26 01:26:41 +0100763} } // namespace v8::internal
Andrei Popescu31002712010-02-23 13:46:05 +0000764
765#endif // #ifndef V8_MIPS_CONSTANTS_H_