blob: fd04722792f8a2f789ac48cb7abc3c1a8652e405 [file] [log] [blame]
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001// Copyright 2012 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
Ben Murdoch3ef787d2012-04-12 10:51:47 +010042enum ArchVariants {
43 kMips32r2,
44 kMips32r1,
45 kLoongson
46};
Andrei Popescu31002712010-02-23 13:46:05 +000047
Steve Block44f0eee2011-05-26 01:26:41 +010048#ifdef _MIPS_ARCH_MIPS32R2
Ben Murdoch3ef787d2012-04-12 10:51:47 +010049 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;
Steve Block44f0eee2011-05-26 01:26:41 +010054#else
Ben Murdoch3ef787d2012-04-12 10:51:47 +010055 static const ArchVariants kArchVariant = kMips32r1;
Steve Block44f0eee2011-05-26 01:26:41 +010056#endif
57
58
Ben Murdoch257744e2011-11-30 15:57:28 +000059#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.
Ben Murdoch3ef787d2012-04-12 10:51:47 +010062const bool IsMipsSoftFloatABI = false;
Ben Murdoch257744e2011-11-30 15:57:28 +000063#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.
Ben Murdoch3ef787d2012-04-12 10:51:47 +010066const bool IsMipsSoftFloatABI = true;
Ben Murdoch257744e2011-11-30 15:57:28 +000067#else
Ben Murdoch3ef787d2012-04-12 10:51:47 +010068const bool IsMipsSoftFloatABI = true;
Ben Murdoch257744e2011-11-30 15:57:28 +000069#endif
70
71
Andrei Popescu31002712010-02-23 13:46:05 +000072// 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
Steve Block44f0eee2011-05-26 01:26:41 +010079namespace v8 {
80namespace internal {
Andrei Popescu31002712010-02-23 13:46:05 +000081
82// -----------------------------------------------------------------------------
Ben Murdoch257744e2011-11-30 15:57:28 +000083// Registers and FPURegisters.
Andrei Popescu31002712010-02-23 13:46:05 +000084
85// Number of general purpose registers.
Ben Murdoch3ef787d2012-04-12 10:51:47 +010086const int kNumRegisters = 32;
87const int kInvalidRegister = -1;
Andrei Popescu31002712010-02-23 13:46:05 +000088
89// Number of registers with HI, LO, and pc.
Ben Murdoch3ef787d2012-04-12 10:51:47 +010090const int kNumSimuRegisters = 35;
Andrei Popescu31002712010-02-23 13:46:05 +000091
92// In the simulator, the PC register is simulated as the 34th register.
Ben Murdoch3ef787d2012-04-12 10:51:47 +010093const int kPCRegister = 34;
Andrei Popescu31002712010-02-23 13:46:05 +000094
95// Number coprocessor registers.
Ben Murdoch3ef787d2012-04-12 10:51:47 +010096const int kNumFPURegisters = 32;
97const int kInvalidFPURegister = -1;
Andrei Popescu31002712010-02-23 13:46:05 +000098
Steve Block44f0eee2011-05-26 01:26:41 +010099// FPU (coprocessor 1) control registers. Currently only FCSR is implemented.
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100100const int kFCSRRegister = 31;
101const int kInvalidFPUControlRegister = -1;
102const uint32_t kFPUInvalidResult = (uint32_t) (1 << 31) - 1;
Steve Block44f0eee2011-05-26 01:26:41 +0100103
104// FCSR constants.
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100105const uint32_t kFCSRInexactFlagBit = 2;
106const uint32_t kFCSRUnderflowFlagBit = 3;
107const uint32_t kFCSROverflowFlagBit = 4;
108const uint32_t kFCSRDivideByZeroFlagBit = 5;
109const uint32_t kFCSRInvalidOpFlagBit = 6;
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000110
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100111const 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;
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000116
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100117const uint32_t kFCSRFlagMask =
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000118 kFCSRInexactFlagMask |
119 kFCSRUnderflowFlagMask |
120 kFCSROverflowFlagMask |
121 kFCSRDivideByZeroFlagMask |
122 kFCSRInvalidOpFlagMask;
123
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100124const uint32_t kFCSRExceptionFlagMask = kFCSRFlagMask ^ kFCSRInexactFlagMask;
Steve Block44f0eee2011-05-26 01:26:41 +0100125
Andrei Popescu31002712010-02-23 13:46:05 +0000126// 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;
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100137 const char* name;
Andrei Popescu31002712010-02-23 13:46:05 +0000138 };
139
140 static const int32_t kMaxValue = 0x7fffffff;
141 static const int32_t kMinValue = 0x80000000;
142
143 private:
Andrei Popescu31002712010-02-23 13:46:05 +0000144 static const char* names_[kNumSimuRegisters];
145 static const RegisterAlias aliases_[];
146};
147
148// Helper functions for converting between register numbers and names.
Steve Block44f0eee2011-05-26 01:26:41 +0100149class FPURegisters {
Andrei Popescu31002712010-02-23 13:46:05 +0000150 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;
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100159 const char* name;
Andrei Popescu31002712010-02-23 13:46:05 +0000160 };
161
162 private:
Steve Block44f0eee2011-05-26 01:26:41 +0100163 static const char* names_[kNumFPURegisters];
Andrei Popescu31002712010-02-23 13:46:05 +0000164 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
Andrei Popescu31002712010-02-23 13:46:05 +0000174// 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
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000181// 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.
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100188const uint32_t kMaxWatchpointCode = 31;
189const uint32_t kMaxStopCode = 127;
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000190STATIC_ASSERT(kMaxWatchpointCode < kMaxStopCode);
191
192
Andrei Popescu31002712010-02-23 13:46:05 +0000193// ----- Fields offset and length.
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100194const 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;
Andrei Popescu31002712010-02-23 13:46:05 +0000207
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100208const int kImm16Shift = 0;
209const int kImm16Bits = 16;
210const int kImm26Shift = 0;
211const int kImm26Bits = 26;
212const int kImm28Shift = 0;
213const int kImm28Bits = 28;
Andrei Popescu31002712010-02-23 13:46:05 +0000214
Ben Murdoch589d6972011-11-30 16:04:58 +0000215// In branches and jumps immediate fields point to words, not bytes,
216// and are therefore shifted by 2.
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100217const int kImmFieldShift = 2;
Ben Murdoch589d6972011-11-30 16:04:58 +0000218
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100219const 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;
Andrei Popescu31002712010-02-23 13:46:05 +0000231
Ben Murdoch257744e2011-11-30 15:57:28 +0000232// ----- Miscellaneous useful masks.
Andrei Popescu31002712010-02-23 13:46:05 +0000233// Instruction bit masks.
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100234const 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;
Andrei Popescu31002712010-02-23 13:46:05 +0000243// Misc masks.
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100244const int kHiMask = 0xffff << 16;
245const int kLoMask = 0xffff;
246const int kSignMask = 0x80000000;
247const int kJumpAddrMask = (1 << (kImm26Bits + kImmFieldShift)) - 1;
Andrei Popescu31002712010-02-23 13:46:05 +0000248
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
Ben Murdoch257744e2011-11-30 15:57:28 +0000272 COP1 = ((2 << 3) + 1) << kOpcodeShift, // Coprocessor 1 class.
Andrei Popescu31002712010-02-23 13:46:05 +0000273 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,
Steve Block44f0eee2011-05-26 01:26:41 +0100279 SPECIAL3 = ((3 << 3) + 7) << kOpcodeShift,
Andrei Popescu31002712010-02-23 13:46:05 +0000280
281 LB = ((4 << 3) + 0) << kOpcodeShift,
Steve Block44f0eee2011-05-26 01:26:41 +0100282 LH = ((4 << 3) + 1) << kOpcodeShift,
283 LWL = ((4 << 3) + 2) << kOpcodeShift,
Andrei Popescu31002712010-02-23 13:46:05 +0000284 LW = ((4 << 3) + 3) << kOpcodeShift,
285 LBU = ((4 << 3) + 4) << kOpcodeShift,
Steve Block44f0eee2011-05-26 01:26:41 +0100286 LHU = ((4 << 3) + 5) << kOpcodeShift,
287 LWR = ((4 << 3) + 6) << kOpcodeShift,
Andrei Popescu31002712010-02-23 13:46:05 +0000288 SB = ((5 << 3) + 0) << kOpcodeShift,
Steve Block44f0eee2011-05-26 01:26:41 +0100289 SH = ((5 << 3) + 1) << kOpcodeShift,
290 SWL = ((5 << 3) + 2) << kOpcodeShift,
Andrei Popescu31002712010-02-23 13:46:05 +0000291 SW = ((5 << 3) + 3) << kOpcodeShift,
Steve Block44f0eee2011-05-26 01:26:41 +0100292 SWR = ((5 << 3) + 6) << kOpcodeShift,
Andrei Popescu31002712010-02-23 13:46:05 +0000293
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),
Ben Murdoch589d6972011-11-30 16:04:58 +0000304 MOVCI = ((0 << 3) + 1),
Andrei Popescu31002712010-02-23 13:46:05 +0000305 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),
Steve Block44f0eee2011-05-26 01:26:41 +0100313 MOVZ = ((1 << 3) + 2),
314 MOVN = ((1 << 3) + 3),
Andrei Popescu31002712010-02-23 13:46:05 +0000315 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),
Steve Block44f0eee2011-05-26 01:26:41 +0100346 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),
Andrei Popescu31002712010-02-23 13:46:05 +0000352
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,
Steve Block44f0eee2011-05-26 01:26:41 +0100361 CFC1 = ((0 << 3) + 2) << 21,
Andrei Popescu31002712010-02-23 13:46:05 +0000362 MFHC1 = ((0 << 3) + 3) << 21,
363 MTC1 = ((0 << 3) + 4) << 21,
Steve Block44f0eee2011-05-26 01:26:41 +0100364 CTC1 = ((0 << 3) + 6) << 21,
Andrei Popescu31002712010-02-23 13:46:05 +0000365 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.
Steve Block44f0eee2011-05-26 01:26:41 +0100373 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),
Andrei Popescu31002712010-02-23 13:46:05 +0000381 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.
Steve Block44f0eee2011-05-26 01:26:41 +0100386 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),
Andrei Popescu31002712010-02-23 13:46:05 +0000402 CVT_S_D = ((4 << 3) + 0),
403 CVT_W_D = ((4 << 3) + 4),
404 CVT_L_D = ((4 << 3) + 5),
Steve Block44f0eee2011-05-26 01:26:41 +0100405 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),
Andrei Popescu31002712010-02-23 13:46:05 +0000413 // 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.
Steve Block44f0eee2011-05-26 01:26:41 +0100429 kNoCondition = -1,
Andrei Popescu31002712010-02-23 13:46:05 +0000430
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
Ben Murdoch257744e2011-11-30 15:57:28 +0000450 // Aliases.
Andrei Popescu31002712010-02-23 13:46:05 +0000451 carry = Uless,
452 not_carry = Ugreater_equal,
453 zero = equal,
454 eq = equal,
455 not_zero = not_equal,
456 ne = not_equal,
Steve Block44f0eee2011-05-26 01:26:41 +0100457 nz = not_equal,
Andrei Popescu31002712010-02-23 13:46:05 +0000458 sign = negative,
459 not_sign = positive,
Steve Block44f0eee2011-05-26 01:26:41 +0100460 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,
Andrei Popescu31002712010-02-23 13:46:05 +0000471
Steve Block44f0eee2011-05-26 01:26:41 +0100472 cc_default = kNoCondition
Andrei Popescu31002712010-02-23 13:46:05 +0000473};
474
Steve Block44f0eee2011-05-26 01:26:41 +0100475
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
Andrei Popescu31002712010-02-23 13:46:05 +0000510// ----- Coprocessor conditions.
511enum FPUCondition {
Ben Murdoch589d6972011-11-30 16:04:58 +0000512 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
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100539const uint32_t kFPURoundingModeMask = 3 << 0;
Ben Murdoch589d6972011-11-30 16:04:58 +0000540
541enum CheckForInexactConversion {
542 kCheckForInexactConversion,
543 kDontCheckForInexactConversion
Andrei Popescu31002712010-02-23 13:46:05 +0000544};
545
546
Steve Block44f0eee2011-05-26 01:26:41 +0100547// -----------------------------------------------------------------------------
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;
Ben Murdoch257744e2011-11-30 15:57:28 +0000575// lw(r, MemOperand(sp, 0))
Steve Block44f0eee2011-05-26 01:26:41 +0100576extern 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
Andrei Popescu31002712010-02-23 13:46:05 +0000587// 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 {
Steve Block44f0eee2011-05-26 01:26:41 +0100595 kInstrSize = 4,
596 kInstrSizeLog2 = 2,
Andrei Popescu31002712010-02-23 13:46:05 +0000597 // On MIPS PC cannot actually be directly accessed. We behave as if PC was
Steve Block44f0eee2011-05-26 01:26:41 +0100598 // always the value of the current instruction being executed.
Andrei Popescu31002712010-02-23 13:46:05 +0000599 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.
Steve Block44f0eee2011-05-26 01:26:41 +0100635 inline Opcode OpcodeValue() const {
Andrei Popescu31002712010-02-23 13:46:05 +0000636 return static_cast<Opcode>(
637 Bits(kOpcodeShift + kOpcodeBits - 1, kOpcodeShift));
638 }
639
Steve Block44f0eee2011-05-26 01:26:41 +0100640 inline int RsValue() const {
Andrei Popescu31002712010-02-23 13:46:05 +0000641 ASSERT(InstructionType() == kRegisterType ||
642 InstructionType() == kImmediateType);
643 return Bits(kRsShift + kRsBits - 1, kRsShift);
644 }
645
Steve Block44f0eee2011-05-26 01:26:41 +0100646 inline int RtValue() const {
Andrei Popescu31002712010-02-23 13:46:05 +0000647 ASSERT(InstructionType() == kRegisterType ||
648 InstructionType() == kImmediateType);
649 return Bits(kRtShift + kRtBits - 1, kRtShift);
650 }
651
Steve Block44f0eee2011-05-26 01:26:41 +0100652 inline int RdValue() const {
Andrei Popescu31002712010-02-23 13:46:05 +0000653 ASSERT(InstructionType() == kRegisterType);
654 return Bits(kRdShift + kRdBits - 1, kRdShift);
655 }
656
Steve Block44f0eee2011-05-26 01:26:41 +0100657 inline int SaValue() const {
Andrei Popescu31002712010-02-23 13:46:05 +0000658 ASSERT(InstructionType() == kRegisterType);
659 return Bits(kSaShift + kSaBits - 1, kSaShift);
660 }
661
Steve Block44f0eee2011-05-26 01:26:41 +0100662 inline int FunctionValue() const {
Andrei Popescu31002712010-02-23 13:46:05 +0000663 ASSERT(InstructionType() == kRegisterType ||
664 InstructionType() == kImmediateType);
665 return Bits(kFunctionShift + kFunctionBits - 1, kFunctionShift);
666 }
667
Steve Block44f0eee2011-05-26 01:26:41 +0100668 inline int FdValue() const {
669 return Bits(kFdShift + kFdBits - 1, kFdShift);
Andrei Popescu31002712010-02-23 13:46:05 +0000670 }
671
Steve Block44f0eee2011-05-26 01:26:41 +0100672 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);
Andrei Popescu31002712010-02-23 13:46:05 +0000693 }
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
Steve Block44f0eee2011-05-26 01:26:41 +0100706 // Same as above function, but safe to call within InstructionType().
707 inline int RsFieldRawNoAssert() const {
708 return InstructionBits() & kRsFieldMask;
709 }
710
Andrei Popescu31002712010-02-23 13:46:05 +0000711 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.
Steve Block44f0eee2011-05-26 01:26:41 +0100732 inline int SecondaryValue() const {
Andrei Popescu31002712010-02-23 13:46:05 +0000733 Opcode op = OpcodeFieldRaw();
734 switch (op) {
735 case SPECIAL:
736 case SPECIAL2:
Steve Block44f0eee2011-05-26 01:26:41 +0100737 return FunctionValue();
Andrei Popescu31002712010-02-23 13:46:05 +0000738 case COP1:
Steve Block44f0eee2011-05-26 01:26:41 +0100739 return RsValue();
Andrei Popescu31002712010-02-23 13:46:05 +0000740 case REGIMM:
Steve Block44f0eee2011-05-26 01:26:41 +0100741 return RtValue();
Andrei Popescu31002712010-02-23 13:46:05 +0000742 default:
743 return NULLSF;
744 }
745 }
746
Steve Block44f0eee2011-05-26 01:26:41 +0100747 inline int32_t Imm16Value() const {
Andrei Popescu31002712010-02-23 13:46:05 +0000748 ASSERT(InstructionType() == kImmediateType);
749 return Bits(kImm16Shift + kImm16Bits - 1, kImm16Shift);
750 }
751
Steve Block44f0eee2011-05-26 01:26:41 +0100752 inline int32_t Imm26Value() const {
Andrei Popescu31002712010-02-23 13:46:05 +0000753 ASSERT(InstructionType() == kJumpType);
Ben Murdoch589d6972011-11-30 16:04:58 +0000754 return Bits(kImm26Shift + kImm26Bits - 1, kImm26Shift);
Andrei Popescu31002712010-02-23 13:46:05 +0000755 }
756
757 // Say if the instruction should not be used in a branch delay slot.
Steve Block44f0eee2011-05-26 01:26:41 +0100758 bool IsForbiddenInBranchDelay() const;
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100759 // Say if the instruction 'links'. e.g. jal, bal.
Steve Block44f0eee2011-05-26 01:26:41 +0100760 bool IsLinkingInstruction() const;
Andrei Popescu31002712010-02-23 13:46:05 +0000761 // Say if the instruction is a break or a trap.
Steve Block44f0eee2011-05-26 01:26:41 +0100762 bool IsTrap() const;
Andrei Popescu31002712010-02-23 13:46:05 +0000763
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.
Ben Murdoch257744e2011-11-30 15:57:28 +0000768 static Instruction* At(byte* pc) {
Andrei Popescu31002712010-02-23 13:46:05 +0000769 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
Steve Block44f0eee2011-05-26 01:26:41 +0100781// C/C++ argument slots size.
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100782const int kCArgSlotCount = 4;
783const int kCArgsSlotsSize = kCArgSlotCount * Instruction::kInstrSize;
Steve Block44f0eee2011-05-26 01:26:41 +0100784// JS argument slots size.
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100785const int kJSArgsSlotsSize = 0 * Instruction::kInstrSize;
Steve Block44f0eee2011-05-26 01:26:41 +0100786// Assembly builtins argument slots size.
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100787const int kBArgsSlotsSize = 0 * Instruction::kInstrSize;
Andrei Popescu31002712010-02-23 13:46:05 +0000788
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100789const int kBranchReturnOffset = 2 * Instruction::kInstrSize;
Andrei Popescu31002712010-02-23 13:46:05 +0000790
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100791const int kDoubleAlignmentBits = 3;
792const int kDoubleAlignment = (1 << kDoubleAlignmentBits);
793const int kDoubleAlignmentMask = kDoubleAlignment - 1;
Andrei Popescu31002712010-02-23 13:46:05 +0000794
795
Steve Block44f0eee2011-05-26 01:26:41 +0100796} } // namespace v8::internal
Andrei Popescu31002712010-02-23 13:46:05 +0000797
798#endif // #ifndef V8_MIPS_CONSTANTS_H_