blob: d76ae59ff690c8a6e3b86905a313f50c0fa05e3e [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
Ben Murdoch589d6972011-11-30 16:04:58 +0000207// In branches and jumps immediate fields point to words, not bytes,
208// and are therefore shifted by 2.
209static const int kImmFieldShift = 2;
210
Andrei Popescu31002712010-02-23 13:46:05 +0000211static const int kFsShift = 11;
212static const int kFsBits = 5;
213static const int kFtShift = 16;
214static const int kFtBits = 5;
Steve Block44f0eee2011-05-26 01:26:41 +0100215static 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;
Andrei Popescu31002712010-02-23 13:46:05 +0000223
Ben Murdoch257744e2011-11-30 15:57:28 +0000224// ----- Miscellaneous useful masks.
Andrei Popescu31002712010-02-23 13:46:05 +0000225// 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;
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000229static const int kImm28Mask = ((1 << kImm28Bits) - 1) << kImm28Shift;
Andrei Popescu31002712010-02-23 13:46:05 +0000230static 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.
Steve Block44f0eee2011-05-26 01:26:41 +0100237static const int kHiMask = 0xffff << 16;
238static const int kLoMask = 0xffff;
239static const int kSignMask = 0x80000000;
Ben Murdoch589d6972011-11-30 16:04:58 +0000240static const int kJumpAddrMask = (1 << (kImm26Bits + kImmFieldShift)) - 1;
Andrei Popescu31002712010-02-23 13:46:05 +0000241
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
Ben Murdoch257744e2011-11-30 15:57:28 +0000265 COP1 = ((2 << 3) + 1) << kOpcodeShift, // Coprocessor 1 class.
Andrei Popescu31002712010-02-23 13:46:05 +0000266 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,
Steve Block44f0eee2011-05-26 01:26:41 +0100272 SPECIAL3 = ((3 << 3) + 7) << kOpcodeShift,
Andrei Popescu31002712010-02-23 13:46:05 +0000273
274 LB = ((4 << 3) + 0) << kOpcodeShift,
Steve Block44f0eee2011-05-26 01:26:41 +0100275 LH = ((4 << 3) + 1) << kOpcodeShift,
276 LWL = ((4 << 3) + 2) << kOpcodeShift,
Andrei Popescu31002712010-02-23 13:46:05 +0000277 LW = ((4 << 3) + 3) << kOpcodeShift,
278 LBU = ((4 << 3) + 4) << kOpcodeShift,
Steve Block44f0eee2011-05-26 01:26:41 +0100279 LHU = ((4 << 3) + 5) << kOpcodeShift,
280 LWR = ((4 << 3) + 6) << kOpcodeShift,
Andrei Popescu31002712010-02-23 13:46:05 +0000281 SB = ((5 << 3) + 0) << kOpcodeShift,
Steve Block44f0eee2011-05-26 01:26:41 +0100282 SH = ((5 << 3) + 1) << kOpcodeShift,
283 SWL = ((5 << 3) + 2) << kOpcodeShift,
Andrei Popescu31002712010-02-23 13:46:05 +0000284 SW = ((5 << 3) + 3) << kOpcodeShift,
Steve Block44f0eee2011-05-26 01:26:41 +0100285 SWR = ((5 << 3) + 6) << kOpcodeShift,
Andrei Popescu31002712010-02-23 13:46:05 +0000286
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),
Ben Murdoch589d6972011-11-30 16:04:58 +0000297 MOVCI = ((0 << 3) + 1),
Andrei Popescu31002712010-02-23 13:46:05 +0000298 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),
Steve Block44f0eee2011-05-26 01:26:41 +0100306 MOVZ = ((1 << 3) + 2),
307 MOVN = ((1 << 3) + 3),
Andrei Popescu31002712010-02-23 13:46:05 +0000308 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),
Steve Block44f0eee2011-05-26 01:26:41 +0100339 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),
Andrei Popescu31002712010-02-23 13:46:05 +0000345
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,
Steve Block44f0eee2011-05-26 01:26:41 +0100354 CFC1 = ((0 << 3) + 2) << 21,
Andrei Popescu31002712010-02-23 13:46:05 +0000355 MFHC1 = ((0 << 3) + 3) << 21,
356 MTC1 = ((0 << 3) + 4) << 21,
Steve Block44f0eee2011-05-26 01:26:41 +0100357 CTC1 = ((0 << 3) + 6) << 21,
Andrei Popescu31002712010-02-23 13:46:05 +0000358 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.
Steve Block44f0eee2011-05-26 01:26:41 +0100366 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),
Andrei Popescu31002712010-02-23 13:46:05 +0000374 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.
Steve Block44f0eee2011-05-26 01:26:41 +0100379 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),
Andrei Popescu31002712010-02-23 13:46:05 +0000395 CVT_S_D = ((4 << 3) + 0),
396 CVT_W_D = ((4 << 3) + 4),
397 CVT_L_D = ((4 << 3) + 5),
Steve Block44f0eee2011-05-26 01:26:41 +0100398 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),
Andrei Popescu31002712010-02-23 13:46:05 +0000406 // 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.
Steve Block44f0eee2011-05-26 01:26:41 +0100422 kNoCondition = -1,
Andrei Popescu31002712010-02-23 13:46:05 +0000423
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
Ben Murdoch257744e2011-11-30 15:57:28 +0000443 // Aliases.
Andrei Popescu31002712010-02-23 13:46:05 +0000444 carry = Uless,
445 not_carry = Ugreater_equal,
446 zero = equal,
447 eq = equal,
448 not_zero = not_equal,
449 ne = not_equal,
Steve Block44f0eee2011-05-26 01:26:41 +0100450 nz = not_equal,
Andrei Popescu31002712010-02-23 13:46:05 +0000451 sign = negative,
452 not_sign = positive,
Steve Block44f0eee2011-05-26 01:26:41 +0100453 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,
Andrei Popescu31002712010-02-23 13:46:05 +0000464
Steve Block44f0eee2011-05-26 01:26:41 +0100465 cc_default = kNoCondition
Andrei Popescu31002712010-02-23 13:46:05 +0000466};
467
Steve Block44f0eee2011-05-26 01:26:41 +0100468
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
Andrei Popescu31002712010-02-23 13:46:05 +0000503// ----- Coprocessor conditions.
504enum FPUCondition {
Ben Murdoch589d6972011-11-30 16:04:58 +0000505 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
Andrei Popescu31002712010-02-23 13:46:05 +0000537};
538
539
Steve Block44f0eee2011-05-26 01:26:41 +0100540// -----------------------------------------------------------------------------
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;
Ben Murdoch257744e2011-11-30 15:57:28 +0000568// lw(r, MemOperand(sp, 0))
Steve Block44f0eee2011-05-26 01:26:41 +0100569extern 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
Andrei Popescu31002712010-02-23 13:46:05 +0000580// 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 {
Steve Block44f0eee2011-05-26 01:26:41 +0100588 kInstrSize = 4,
589 kInstrSizeLog2 = 2,
Andrei Popescu31002712010-02-23 13:46:05 +0000590 // On MIPS PC cannot actually be directly accessed. We behave as if PC was
Steve Block44f0eee2011-05-26 01:26:41 +0100591 // always the value of the current instruction being executed.
Andrei Popescu31002712010-02-23 13:46:05 +0000592 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.
Steve Block44f0eee2011-05-26 01:26:41 +0100628 inline Opcode OpcodeValue() const {
Andrei Popescu31002712010-02-23 13:46:05 +0000629 return static_cast<Opcode>(
630 Bits(kOpcodeShift + kOpcodeBits - 1, kOpcodeShift));
631 }
632
Steve Block44f0eee2011-05-26 01:26:41 +0100633 inline int RsValue() const {
Andrei Popescu31002712010-02-23 13:46:05 +0000634 ASSERT(InstructionType() == kRegisterType ||
635 InstructionType() == kImmediateType);
636 return Bits(kRsShift + kRsBits - 1, kRsShift);
637 }
638
Steve Block44f0eee2011-05-26 01:26:41 +0100639 inline int RtValue() const {
Andrei Popescu31002712010-02-23 13:46:05 +0000640 ASSERT(InstructionType() == kRegisterType ||
641 InstructionType() == kImmediateType);
642 return Bits(kRtShift + kRtBits - 1, kRtShift);
643 }
644
Steve Block44f0eee2011-05-26 01:26:41 +0100645 inline int RdValue() const {
Andrei Popescu31002712010-02-23 13:46:05 +0000646 ASSERT(InstructionType() == kRegisterType);
647 return Bits(kRdShift + kRdBits - 1, kRdShift);
648 }
649
Steve Block44f0eee2011-05-26 01:26:41 +0100650 inline int SaValue() const {
Andrei Popescu31002712010-02-23 13:46:05 +0000651 ASSERT(InstructionType() == kRegisterType);
652 return Bits(kSaShift + kSaBits - 1, kSaShift);
653 }
654
Steve Block44f0eee2011-05-26 01:26:41 +0100655 inline int FunctionValue() const {
Andrei Popescu31002712010-02-23 13:46:05 +0000656 ASSERT(InstructionType() == kRegisterType ||
657 InstructionType() == kImmediateType);
658 return Bits(kFunctionShift + kFunctionBits - 1, kFunctionShift);
659 }
660
Steve Block44f0eee2011-05-26 01:26:41 +0100661 inline int FdValue() const {
662 return Bits(kFdShift + kFdBits - 1, kFdShift);
Andrei Popescu31002712010-02-23 13:46:05 +0000663 }
664
Steve Block44f0eee2011-05-26 01:26:41 +0100665 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);
Andrei Popescu31002712010-02-23 13:46:05 +0000686 }
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
Steve Block44f0eee2011-05-26 01:26:41 +0100699 // Same as above function, but safe to call within InstructionType().
700 inline int RsFieldRawNoAssert() const {
701 return InstructionBits() & kRsFieldMask;
702 }
703
Andrei Popescu31002712010-02-23 13:46:05 +0000704 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.
Steve Block44f0eee2011-05-26 01:26:41 +0100725 inline int SecondaryValue() const {
Andrei Popescu31002712010-02-23 13:46:05 +0000726 Opcode op = OpcodeFieldRaw();
727 switch (op) {
728 case SPECIAL:
729 case SPECIAL2:
Steve Block44f0eee2011-05-26 01:26:41 +0100730 return FunctionValue();
Andrei Popescu31002712010-02-23 13:46:05 +0000731 case COP1:
Steve Block44f0eee2011-05-26 01:26:41 +0100732 return RsValue();
Andrei Popescu31002712010-02-23 13:46:05 +0000733 case REGIMM:
Steve Block44f0eee2011-05-26 01:26:41 +0100734 return RtValue();
Andrei Popescu31002712010-02-23 13:46:05 +0000735 default:
736 return NULLSF;
737 }
738 }
739
Steve Block44f0eee2011-05-26 01:26:41 +0100740 inline int32_t Imm16Value() const {
Andrei Popescu31002712010-02-23 13:46:05 +0000741 ASSERT(InstructionType() == kImmediateType);
742 return Bits(kImm16Shift + kImm16Bits - 1, kImm16Shift);
743 }
744
Steve Block44f0eee2011-05-26 01:26:41 +0100745 inline int32_t Imm26Value() const {
Andrei Popescu31002712010-02-23 13:46:05 +0000746 ASSERT(InstructionType() == kJumpType);
Ben Murdoch589d6972011-11-30 16:04:58 +0000747 return Bits(kImm26Shift + kImm26Bits - 1, kImm26Shift);
Andrei Popescu31002712010-02-23 13:46:05 +0000748 }
749
750 // Say if the instruction should not be used in a branch delay slot.
Steve Block44f0eee2011-05-26 01:26:41 +0100751 bool IsForbiddenInBranchDelay() const;
Andrei Popescu31002712010-02-23 13:46:05 +0000752 // Say if the instruction 'links'. eg: jal, bal.
Steve Block44f0eee2011-05-26 01:26:41 +0100753 bool IsLinkingInstruction() const;
Andrei Popescu31002712010-02-23 13:46:05 +0000754 // Say if the instruction is a break or a trap.
Steve Block44f0eee2011-05-26 01:26:41 +0100755 bool IsTrap() const;
Andrei Popescu31002712010-02-23 13:46:05 +0000756
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.
Ben Murdoch257744e2011-11-30 15:57:28 +0000761 static Instruction* At(byte* pc) {
Andrei Popescu31002712010-02-23 13:46:05 +0000762 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
Steve Block44f0eee2011-05-26 01:26:41 +0100774// C/C++ argument slots size.
Ben Murdoch589d6972011-11-30 16:04:58 +0000775static const int kCArgSlotCount = 4;
776static const int kCArgsSlotsSize = kCArgSlotCount * Instruction::kInstrSize;
Steve Block44f0eee2011-05-26 01:26:41 +0100777// JS argument slots size.
778static const int kJSArgsSlotsSize = 0 * Instruction::kInstrSize;
779// Assembly builtins argument slots size.
780static const int kBArgsSlotsSize = 0 * Instruction::kInstrSize;
Andrei Popescu31002712010-02-23 13:46:05 +0000781
Steve Block44f0eee2011-05-26 01:26:41 +0100782static const int kBranchReturnOffset = 2 * Instruction::kInstrSize;
Andrei Popescu31002712010-02-23 13:46:05 +0000783
Steve Block44f0eee2011-05-26 01:26:41 +0100784static const int kDoubleAlignmentBits = 3;
785static const int kDoubleAlignment = (1 << kDoubleAlignmentBits);
786static const int kDoubleAlignmentMask = kDoubleAlignment - 1;
Andrei Popescu31002712010-02-23 13:46:05 +0000787
788
Steve Block44f0eee2011-05-26 01:26:41 +0100789} } // namespace v8::internal
Andrei Popescu31002712010-02-23 13:46:05 +0000790
791#endif // #ifndef V8_MIPS_CONSTANTS_H_