OLD | NEW |
| (Empty) |
1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | |
2 // for details. All rights reserved. Use of this source code is governed by a | |
3 // BSD-style license that can be found in the LICENSE file. | |
4 | |
5 #ifndef RUNTIME_VM_CONSTANTS_MIPS_H_ | |
6 #define RUNTIME_VM_CONSTANTS_MIPS_H_ | |
7 | |
8 #include "platform/assert.h" | |
9 | |
10 namespace dart { | |
11 | |
12 enum Register { | |
13 R0 = 0, | |
14 R1 = 1, // AT aka TMP | |
15 R2 = 2, | |
16 R3 = 3, | |
17 R4 = 4, | |
18 R5 = 5, | |
19 R6 = 6, | |
20 R7 = 7, | |
21 R8 = 8, | |
22 R9 = 9, | |
23 R10 = 10, | |
24 R11 = 11, | |
25 R12 = 12, | |
26 R13 = 13, | |
27 R14 = 14, | |
28 R15 = 15, | |
29 R16 = 16, | |
30 R17 = 17, | |
31 R18 = 18, | |
32 R19 = 19, // THR | |
33 R20 = 20, | |
34 R21 = 21, | |
35 R22 = 22, // CTX | |
36 R23 = 23, // PP | |
37 R24 = 24, | |
38 R25 = 25, | |
39 R26 = 26, | |
40 R27 = 27, | |
41 R28 = 28, | |
42 R29 = 29, // SP | |
43 R30 = 30, // FP | |
44 R31 = 31, // RA | |
45 kNumberOfCpuRegisters = 32, | |
46 IMM = 32, // Positive value is easier to encode than kNoRegister in bitfield. | |
47 kNoRegister = -1, // Signals an illegal register. | |
48 | |
49 | |
50 // Register aliases. | |
51 ZR = R0, | |
52 AT = R1, | |
53 | |
54 V0 = R2, | |
55 V1 = R3, | |
56 | |
57 A0 = R4, | |
58 A1 = R5, | |
59 A2 = R6, | |
60 A3 = R7, | |
61 | |
62 T0 = R8, | |
63 T1 = R9, | |
64 T2 = R10, | |
65 T3 = R11, | |
66 T4 = R12, | |
67 T5 = R13, | |
68 T6 = R14, | |
69 T7 = R15, | |
70 | |
71 S0 = R16, | |
72 S1 = R17, | |
73 S2 = R18, | |
74 S3 = R19, | |
75 S4 = R20, | |
76 S5 = R21, | |
77 S6 = R22, | |
78 S7 = R23, | |
79 | |
80 T8 = R24, | |
81 T9 = R25, | |
82 | |
83 K0 = R26, | |
84 K1 = R27, | |
85 | |
86 GP = R28, | |
87 SP = R29, | |
88 FP = R30, | |
89 RA = R31, | |
90 }; | |
91 | |
92 | |
93 // Values for floating point registers. | |
94 // Double-precision values use register pairs. | |
95 enum FRegister { | |
96 F0 = 0, | |
97 F1 = 1, | |
98 F2 = 2, | |
99 F3 = 3, | |
100 F4 = 4, | |
101 F5 = 5, | |
102 F6 = 6, | |
103 F7 = 7, | |
104 F8 = 8, | |
105 F9 = 9, | |
106 F10 = 10, | |
107 F11 = 11, | |
108 F12 = 12, | |
109 F13 = 13, | |
110 F14 = 14, | |
111 F15 = 15, | |
112 F16 = 16, | |
113 F17 = 17, | |
114 F18 = 18, | |
115 F19 = 19, | |
116 F20 = 20, | |
117 F21 = 21, | |
118 F22 = 22, | |
119 F23 = 23, | |
120 F24 = 24, | |
121 F25 = 25, | |
122 F26 = 26, | |
123 F27 = 27, | |
124 F28 = 28, | |
125 F29 = 29, | |
126 F30 = 30, | |
127 F31 = 31, | |
128 kNumberOfFRegisters = 32, | |
129 kNoFRegister = -1, | |
130 }; | |
131 | |
132 // The double precision floating point registers are concatenated pairs of the | |
133 // single precision registers, e.g. D0 is F1:F0, D1 is F3:F2, etc.. We only | |
134 // tell the architecture generic code about the double precision registers, then | |
135 // convert to the single precision registers when needed in the mips-specific | |
136 // code. | |
137 enum DRegister { | |
138 D0 = 0, // Function return value 1. | |
139 D1 = 1, // Function return value 2. | |
140 D2 = 2, // Not preserved. | |
141 D3 = 3, // Not preserved. | |
142 D4 = 4, // Not preserved. | |
143 D5 = 5, // Not preserved. | |
144 D6 = 6, // Argument 1. | |
145 D7 = 7, // Argument 2. | |
146 D8 = 8, // Not preserved. | |
147 D9 = 9, // Not preserved. | |
148 D10 = 10, // Preserved. | |
149 D11 = 11, // Preserved. | |
150 D12 = 12, // Preserved. | |
151 D13 = 13, // Preserved. | |
152 D14 = 14, // Preserved. | |
153 D15 = 15, // Preserved. | |
154 kNumberOfDRegisters = 16, | |
155 kNoDRegister = -1, | |
156 }; | |
157 | |
158 static inline FRegister EvenFRegisterOf(DRegister d) { | |
159 return static_cast<FRegister>(d * 2); | |
160 } | |
161 | |
162 static inline FRegister OddFRegisterOf(DRegister d) { | |
163 return static_cast<FRegister>((d * 2) + 1); | |
164 } | |
165 | |
166 const DRegister DTMP = D9; | |
167 const FRegister STMP1 = F18; | |
168 const FRegister STMP2 = F19; | |
169 | |
170 // Architecture independent aliases. | |
171 typedef DRegister FpuRegister; | |
172 const FpuRegister FpuTMP = DTMP; | |
173 const int kNumberOfFpuRegisters = kNumberOfDRegisters; | |
174 const FpuRegister kNoFpuRegister = kNoDRegister; | |
175 | |
176 | |
177 // Register aliases. | |
178 const Register TMP = AT; // Used as scratch register by assembler. | |
179 const Register TMP2 = kNoRegister; // No second assembler scratch register. | |
180 const Register CTX = S6; // Location of current context at method entry. | |
181 const Register CODE_REG = S6; | |
182 const Register PP = S7; // Caches object pool pointer in generated code. | |
183 const Register SPREG = SP; // Stack pointer register. | |
184 const Register FPREG = FP; // Frame pointer register. | |
185 const Register LRREG = RA; // Link register. | |
186 const Register ICREG = S5; // IC data register. | |
187 const Register ARGS_DESC_REG = S4; | |
188 const Register THR = S3; // Caches current thread in generated code. | |
189 const Register CALLEE_SAVED_TEMP = S5; | |
190 | |
191 // The code that generates a comparison can be far away from the code that | |
192 // generates the branch that uses the result of that comparison. In this case, | |
193 // CMPRES1 and CMPRES2 are used for the results of the comparison. We need two | |
194 // since TMP is clobbered by a far branch. | |
195 const Register CMPRES1 = T8; | |
196 const Register CMPRES2 = T9; | |
197 | |
198 // Exception object is passed in this register to the catch handlers when an | |
199 // exception is thrown. | |
200 const Register kExceptionObjectReg = V0; | |
201 | |
202 // Stack trace object is passed in this register to the catch handlers when | |
203 // an exception is thrown. | |
204 const Register kStackTraceObjectReg = V1; | |
205 | |
206 | |
207 typedef uint32_t RegList; | |
208 const RegList kAllCpuRegistersList = 0xFFFFFFFF; | |
209 | |
210 const RegList kAbiArgumentCpuRegs = | |
211 (1 << A0) | (1 << A1) | (1 << A2) | (1 << A3); | |
212 const RegList kAbiPreservedCpuRegs = (1 << S0) | (1 << S1) | (1 << S2) | | |
213 (1 << S3) | (1 << S4) | (1 << S5) | | |
214 (1 << S6) | (1 << S7); | |
215 const int kAbiPreservedCpuRegCount = 8; | |
216 | |
217 // FPU registers 20 - 31 are preserved across calls. | |
218 const FRegister kAbiFirstPreservedFpuReg = F20; | |
219 const FRegister kAbiLastPreservedFpuReg = | |
220 static_cast<FRegister>(kNumberOfFRegisters - 1); | |
221 const int kAbiPreservedFpuRegCount = 12; | |
222 | |
223 const RegList kReservedCpuRegisters = | |
224 (1 << SPREG) | (1 << FPREG) | (1 << TMP) | (1 << PP) | (1 << THR) | | |
225 (1 << CTX) | (1 << ZR) | (1 << CMPRES1) | (1 << CMPRES2) | (1 << K0) | | |
226 (1 << K1) | (1 << GP) | (1 << RA); | |
227 // CPU registers available to Dart allocator. | |
228 const RegList kDartAvailableCpuRegs = | |
229 kAllCpuRegistersList & ~kReservedCpuRegisters; | |
230 // Registers available to Dart that are not preserved by runtime calls. | |
231 const RegList kDartVolatileCpuRegs = | |
232 kDartAvailableCpuRegs & ~kAbiPreservedCpuRegs; | |
233 const int kDartVolatileCpuRegCount = 14; | |
234 const Register kDartFirstVolatileCpuReg = R2; | |
235 const Register kDartLastVolatileCpuReg = R15; | |
236 | |
237 // FPU registers 0 - 19 are not preserved across calls. | |
238 const FRegister kDartFirstVolatileFpuReg = F0; | |
239 const FRegister kDartLastVolatileFpuReg = F19; | |
240 const int kDartVolatileFpuRegCount = 20; | |
241 | |
242 | |
243 // There is no status register on MIPS. Instead of representing a condition | |
244 // code, type Condition (see assembler_mips.h) represents a pair of operands and | |
245 // a relation operator between them. | |
246 enum RelationOperator { | |
247 AL, // always | |
248 NV, // never | |
249 EQ, // equal | |
250 NE, // not equal | |
251 GT, // greater than | |
252 GE, // greater equal | |
253 LT, // less than | |
254 LE, // less equal | |
255 UGT, // unsigned greater than | |
256 UGE, // unsigned greater equal | |
257 ULT, // unsigned less than | |
258 ULE, // unsigned less equal | |
259 }; | |
260 | |
261 | |
262 // Constants used for the decoding or encoding of the individual fields of | |
263 // instructions. Based on the "Table 4.25 CPU Instruction Format Fields". | |
264 enum InstructionFields { | |
265 kOpcodeShift = 26, | |
266 kOpcodeBits = 6, | |
267 kRsShift = 21, | |
268 kRsBits = 5, | |
269 kFmtShift = 21, | |
270 kFmtBits = 5, | |
271 kRtShift = 16, | |
272 kRtBits = 5, | |
273 kFtShift = 16, | |
274 kFtBits = 5, | |
275 kRdShift = 11, | |
276 kRdBits = 5, | |
277 kFsShift = 11, | |
278 kFsBits = 5, | |
279 kSaShift = 6, | |
280 kSaBits = 5, | |
281 kFdShift = 6, | |
282 kFdBits = 5, | |
283 kFunctionShift = 0, | |
284 kFunctionBits = 6, | |
285 kCop1FnShift = 0, | |
286 kCop1FnBits = 6, | |
287 kCop1SubShift = 21, | |
288 kCop1SubBits = 5, | |
289 kImmShift = 0, | |
290 kImmBits = 16, | |
291 kInstrShift = 0, | |
292 kInstrBits = 26, | |
293 kBreakCodeShift = 6, | |
294 kBreakCodeBits = 20, | |
295 kFpuCCShift = 8, | |
296 kFpuCCBits = 3, | |
297 | |
298 kBranchOffsetMask = 0x0000ffff, | |
299 }; | |
300 | |
301 | |
302 enum Opcode { | |
303 SPECIAL = 0, | |
304 REGIMM = 1, | |
305 J = 2, | |
306 JAL = 3, | |
307 BEQ = 4, | |
308 BNE = 5, | |
309 BLEZ = 6, | |
310 BGTZ = 7, | |
311 ADDI = 8, | |
312 ADDIU = 9, | |
313 SLTI = 10, | |
314 SLTIU = 11, | |
315 ANDI = 12, | |
316 ORI = 13, | |
317 XORI = 14, | |
318 LUI = 15, | |
319 CPO0 = 16, | |
320 COP1 = 17, | |
321 COP2 = 18, | |
322 COP1X = 19, | |
323 BEQL = 20, | |
324 BNEL = 21, | |
325 BLEZL = 22, | |
326 BGTZL = 23, | |
327 SPECIAL2 = 28, | |
328 JALX = 29, | |
329 SPECIAL3 = 31, | |
330 LB = 32, | |
331 LH = 33, | |
332 LWL = 34, | |
333 LW = 35, | |
334 LBU = 36, | |
335 LHU = 37, | |
336 LWR = 38, | |
337 SB = 40, | |
338 SH = 41, | |
339 SWL = 42, | |
340 SW = 43, | |
341 SWR = 46, | |
342 CACHE = 47, | |
343 LL = 48, | |
344 LWC1 = 49, | |
345 LWC2 = 50, | |
346 PREF = 51, | |
347 LDC1 = 53, | |
348 LDC2 = 54, | |
349 SC = 56, | |
350 SWC1 = 57, | |
351 SWC2 = 58, | |
352 SDC1 = 61, | |
353 SDC2 = 62, | |
354 }; | |
355 | |
356 | |
357 enum SpecialFunction { | |
358 // SPECIAL opcodes. | |
359 SLL = 0, | |
360 MOVCI = 1, | |
361 SRL = 2, | |
362 SRA = 3, | |
363 SLLV = 4, | |
364 SRLV = 6, | |
365 SRAV = 7, | |
366 JR = 8, | |
367 JALR = 9, | |
368 MOVZ = 10, | |
369 MOVN = 11, | |
370 SYSCALL = 12, | |
371 BREAK = 13, | |
372 SYNC = 15, | |
373 MFHI = 16, | |
374 MTHI = 17, | |
375 MFLO = 18, | |
376 MTLO = 19, | |
377 MULT = 24, | |
378 MULTU = 25, | |
379 DIV = 26, | |
380 DIVU = 27, | |
381 ADD = 32, | |
382 ADDU = 33, | |
383 SUB = 34, | |
384 SUBU = 35, | |
385 AND = 36, | |
386 OR = 37, | |
387 XOR = 38, | |
388 NOR = 39, | |
389 SLT = 42, | |
390 SLTU = 43, | |
391 TGE = 48, | |
392 TGEU = 49, | |
393 TLT = 50, | |
394 TLTU = 51, | |
395 TEQ = 52, | |
396 TNE = 54, | |
397 | |
398 // SPECIAL2 opcodes. | |
399 MADD = 0, | |
400 MADDU = 1, | |
401 CLZ = 32, | |
402 CLO = 33, | |
403 }; | |
404 | |
405 | |
406 enum RtRegImm { | |
407 BLTZ = 0, | |
408 BGEZ = 1, | |
409 BLTZL = 2, | |
410 BGEZL = 3, | |
411 TGEI = 8, | |
412 TGEIU = 9, | |
413 TLTI = 10, | |
414 TLTIU = 11, | |
415 TEQI = 12, | |
416 TNEI = 14, | |
417 BLTZAL = 16, | |
418 BGEZAL = 17, | |
419 BLTZALL = 18, | |
420 BGEZALL = 19, | |
421 SYNCI = 31, | |
422 }; | |
423 | |
424 | |
425 enum Cop1Function { | |
426 COP1_ADD = 0x00, | |
427 COP1_SUB = 0x01, | |
428 COP1_MUL = 0x02, | |
429 COP1_DIV = 0x03, | |
430 COP1_SQRT = 0x04, | |
431 COP1_MOV = 0x06, | |
432 COP1_NEG = 0x07, | |
433 COP1_TRUNC_W = 0x0d, | |
434 COP1_CVT_S = 0x20, | |
435 COP1_CVT_D = 0x21, | |
436 COP1_C_F = 0x30, | |
437 COP1_C_UN = 0x31, | |
438 COP1_C_EQ = 0x32, | |
439 COP1_C_UEQ = 0x33, | |
440 COP1_C_OLT = 0x34, | |
441 COP1_C_ULT = 0x35, | |
442 COP1_C_OLE = 0x36, | |
443 COP1_C_ULE = 0x37, | |
444 }; | |
445 | |
446 | |
447 enum Cop1Sub { | |
448 COP1_MF = 0, | |
449 COP1_MT = 4, | |
450 COP1_BC = 8, | |
451 }; | |
452 | |
453 | |
454 enum Format { | |
455 FMT_S = 16, | |
456 FMT_D = 17, | |
457 FMT_W = 20, | |
458 FMT_L = 21, | |
459 FMT_PS = 22, | |
460 }; | |
461 | |
462 | |
463 class Instr { | |
464 public: | |
465 enum { | |
466 kInstrSize = 4, | |
467 }; | |
468 | |
469 static const int32_t kNopInstruction = 0; | |
470 | |
471 // Reserved break instruction codes. | |
472 static const int32_t kBreakPointCode = 0xdeb0; // For breakpoint. | |
473 static const int32_t kStopMessageCode = 0xdeb1; // For Stop(message). | |
474 static const int32_t kSimulatorBreakCode = 0xdeb2; // For breakpoint in sim. | |
475 static const int32_t kSimulatorRedirectCode = 0xca11; // For redirection. | |
476 | |
477 static const int32_t kBreakPointZeroInstruction = | |
478 (SPECIAL << kOpcodeShift) | (BREAK << kFunctionShift); | |
479 | |
480 // Breakpoint instruction filling assembler code buffers in debug mode. | |
481 static const int32_t kBreakPointInstruction = | |
482 kBreakPointZeroInstruction | (kBreakPointCode << kBreakCodeShift); | |
483 | |
484 // Breakpoint instruction used by the simulator. | |
485 // Should be distinct from kBreakPointInstruction and from a typical user | |
486 // breakpoint inserted in generated code for debugging, e.g. break_(0). | |
487 static const int32_t kSimulatorBreakpointInstruction = | |
488 kBreakPointZeroInstruction | (kSimulatorBreakCode << kBreakCodeShift); | |
489 | |
490 // Runtime call redirection instruction used by the simulator. | |
491 static const int32_t kSimulatorRedirectInstruction = | |
492 kBreakPointZeroInstruction | (kSimulatorRedirectCode << kBreakCodeShift); | |
493 | |
494 // Get the raw instruction bits. | |
495 inline int32_t InstructionBits() const { | |
496 return *reinterpret_cast<const int32_t*>(this); | |
497 } | |
498 | |
499 // Set the raw instruction bits to value. | |
500 inline void SetInstructionBits(int32_t value) { | |
501 *reinterpret_cast<int32_t*>(this) = value; | |
502 } | |
503 | |
504 inline void SetImmInstrBits(Opcode op, | |
505 Register rs, | |
506 Register rt, | |
507 uint16_t imm) { | |
508 SetInstructionBits(op << kOpcodeShift | rs << kRsShift | rt << kRtShift | | |
509 imm << kImmShift); | |
510 } | |
511 | |
512 inline void SetSpecialInstrBits(SpecialFunction f, | |
513 Register rs, | |
514 Register rt, | |
515 Register rd) { | |
516 SetInstructionBits(SPECIAL << kOpcodeShift | f << kFunctionShift | | |
517 rs << kRsShift | rt << kRtShift | rd << kRdShift); | |
518 } | |
519 | |
520 // Read one particular bit out of the instruction bits. | |
521 inline int32_t Bit(int nr) const { return (InstructionBits() >> nr) & 1; } | |
522 | |
523 // Read a bit field out of the instruction bits. | |
524 inline int32_t Bits(int shift, int count) const { | |
525 return (InstructionBits() >> shift) & ((1 << count) - 1); | |
526 } | |
527 | |
528 // Accessors to the different named fields used in the MIPS encoding. | |
529 inline Opcode OpcodeField() const { | |
530 return static_cast<Opcode>(Bits(kOpcodeShift, kOpcodeBits)); | |
531 } | |
532 | |
533 inline void SetOpcodeField(Opcode b) { | |
534 int32_t instr = InstructionBits(); | |
535 int32_t mask = ((1 << kOpcodeBits) - 1) << kOpcodeShift; | |
536 SetInstructionBits((b << kOpcodeShift) | (instr & ~mask)); | |
537 } | |
538 | |
539 inline Register RsField() const { | |
540 return static_cast<Register>(Bits(kRsShift, kRsBits)); | |
541 } | |
542 | |
543 inline Register RtField() const { | |
544 return static_cast<Register>(Bits(kRtShift, kRtBits)); | |
545 } | |
546 | |
547 inline Register RdField() const { | |
548 return static_cast<Register>(Bits(kRdShift, kRdBits)); | |
549 } | |
550 | |
551 inline FRegister FsField() const { | |
552 return static_cast<FRegister>(Bits(kFsShift, kFsBits)); | |
553 } | |
554 | |
555 inline FRegister FtField() const { | |
556 return static_cast<FRegister>(Bits(kFtShift, kFtBits)); | |
557 } | |
558 | |
559 inline FRegister FdField() const { | |
560 return static_cast<FRegister>(Bits(kFdShift, kFdBits)); | |
561 } | |
562 | |
563 inline int SaField() const { return Bits(kSaShift, kSaBits); } | |
564 | |
565 inline int32_t UImmField() const { return Bits(kImmShift, kImmBits); } | |
566 | |
567 inline int32_t SImmField() const { | |
568 // Sign-extend the imm field. | |
569 return (Bits(kImmShift, kImmBits) << (32 - kImmBits)) >> (32 - kImmBits); | |
570 } | |
571 | |
572 inline int32_t BreakCodeField() const { | |
573 return Bits(kBreakCodeShift, kBreakCodeBits); | |
574 } | |
575 | |
576 inline SpecialFunction FunctionField() const { | |
577 return static_cast<SpecialFunction>(Bits(kFunctionShift, kFunctionBits)); | |
578 } | |
579 | |
580 inline RtRegImm RegImmFnField() const { | |
581 return static_cast<RtRegImm>(Bits(kRtShift, kRtBits)); | |
582 } | |
583 | |
584 inline void SetRegImmFnField(RtRegImm b) { | |
585 int32_t instr = InstructionBits(); | |
586 int32_t mask = ((1 << kRtBits) - 1) << kRtShift; | |
587 SetInstructionBits((b << kRtShift) | (instr & ~mask)); | |
588 } | |
589 | |
590 inline bool IsBreakPoint() { | |
591 return (OpcodeField() == SPECIAL) && (FunctionField() == BREAK); | |
592 } | |
593 | |
594 inline Cop1Function Cop1FunctionField() const { | |
595 return static_cast<Cop1Function>(Bits(kCop1FnShift, kCop1FnBits)); | |
596 } | |
597 | |
598 inline Cop1Sub Cop1SubField() const { | |
599 return static_cast<Cop1Sub>(Bits(kCop1SubShift, kCop1SubBits)); | |
600 } | |
601 | |
602 inline bool HasFormat() const { | |
603 return (OpcodeField() == COP1) && (Bit(25) == 1); | |
604 } | |
605 | |
606 inline Format FormatField() const { | |
607 return static_cast<Format>(Bits(kFmtShift, kFmtBits)); | |
608 } | |
609 | |
610 inline int32_t FpuCCField() const { return Bits(kFpuCCShift, kFpuCCBits); } | |
611 | |
612 // Instructions are read out of a code stream. The only way to get a | |
613 // reference to an instruction is to convert a pc. There is no way | |
614 // to allocate or create instances of class Instr. | |
615 // Use the At(pc) function to create references to Instr. | |
616 static Instr* At(uword pc) { return reinterpret_cast<Instr*>(pc); } | |
617 | |
618 #if defined(DEBUG) | |
619 inline void AssertIsImmInstr(Opcode op, | |
620 Register rs, | |
621 Register rt, | |
622 int32_t imm) { | |
623 ASSERT((OpcodeField() == op) && (RsField() == rs) && (RtField() == rt) && | |
624 (SImmField() == imm)); | |
625 } | |
626 | |
627 inline void AssertIsSpecialInstr(SpecialFunction f, | |
628 Register rs, | |
629 Register rt, | |
630 Register rd) { | |
631 ASSERT((OpcodeField() == SPECIAL) && (FunctionField() == f) && | |
632 (RsField() == rs) && (RtField() == rt) && (RdField() == rd)); | |
633 } | |
634 #endif // defined(DEBUG) | |
635 | |
636 private: | |
637 DISALLOW_ALLOCATION(); | |
638 DISALLOW_IMPLICIT_CONSTRUCTORS(Instr); | |
639 }; | |
640 | |
641 } // namespace dart | |
642 | |
643 #endif // RUNTIME_VM_CONSTANTS_MIPS_H_ | |
OLD | NEW |