OLD | NEW |
1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | 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 | 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. | 3 // BSD-style license that can be found in the LICENSE file. |
4 | 4 |
5 #ifndef RUNTIME_VM_CONSTANTS_ARM_H_ | 5 #ifndef RUNTIME_VM_CONSTANTS_ARM_H_ |
6 #define RUNTIME_VM_CONSTANTS_ARM_H_ | 6 #define RUNTIME_VM_CONSTANTS_ARM_H_ |
7 | 7 |
8 #include "platform/globals.h" | 8 #include "platform/globals.h" |
9 #include "platform/assert.h" | 9 #include "platform/assert.h" |
10 | 10 |
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
54 // R12: Volatile | 54 // R12: Volatile |
55 // R13: Stack pointer | 55 // R13: Stack pointer |
56 // R14: Link register | 56 // R14: Link register |
57 // R15: Program counter | 57 // R15: Program counter |
58 // Stack alignment: 4 bytes always, 4 bytes at public interfaces | 58 // Stack alignment: 4 bytes always, 4 bytes at public interfaces |
59 | 59 |
60 // iOS passes floating point arguments in registers (hardfp) | 60 // iOS passes floating point arguments in registers (hardfp) |
61 | 61 |
62 | 62 |
63 enum Register { | 63 enum Register { |
64 R0 = 0, | 64 R0 = 0, |
65 R1 = 1, | 65 R1 = 1, |
66 R2 = 2, | 66 R2 = 2, |
67 R3 = 3, | 67 R3 = 3, |
68 R4 = 4, | 68 R4 = 4, |
69 R5 = 5, // PP | 69 R5 = 5, // PP |
70 R6 = 6, // CTX | 70 R6 = 6, // CTX |
71 R7 = 7, // iOS FP | 71 R7 = 7, // iOS FP |
72 R8 = 8, | 72 R8 = 8, |
73 R9 = 9, | 73 R9 = 9, |
74 R10 = 10, // THR | 74 R10 = 10, // THR |
75 R11 = 11, // Linux FP | 75 R11 = 11, // Linux FP |
76 R12 = 12, // IP aka TMP | 76 R12 = 12, // IP aka TMP |
77 R13 = 13, // SP | 77 R13 = 13, // SP |
78 R14 = 14, // LR | 78 R14 = 14, // LR |
79 R15 = 15, // PC | 79 R15 = 15, // PC |
80 kNumberOfCpuRegisters = 16, | 80 kNumberOfCpuRegisters = 16, |
81 kNoRegister = -1, // Signals an illegal register. | 81 kNoRegister = -1, // Signals an illegal register. |
82 | 82 |
83 // Aliases. | 83 // Aliases. |
84 #if defined(TARGET_ABI_IOS) | 84 #if defined(TARGET_ABI_IOS) |
85 FP = R7, | 85 FP = R7, |
86 NOTFP = R11, | 86 NOTFP = R11, |
87 #elif defined(TARGET_ABI_EABI) | 87 #elif defined(TARGET_ABI_EABI) |
88 FP = R11, | 88 FP = R11, |
89 NOTFP = R7, | 89 NOTFP = R7, |
90 #else | 90 #else |
91 #error Unknown ABI | 91 #error Unknown ABI |
92 #endif | 92 #endif |
93 IP = R12, | 93 IP = R12, |
94 SP = R13, | 94 SP = R13, |
95 LR = R14, | 95 LR = R14, |
96 PC = R15, | 96 PC = R15, |
97 }; | 97 }; |
98 | 98 |
99 | 99 |
100 // Values for single-precision floating point registers. | 100 // Values for single-precision floating point registers. |
101 enum SRegister { | 101 enum SRegister { |
102 kNoSRegister = -1, | 102 kNoSRegister = -1, |
103 S0 = 0, | 103 S0 = 0, |
104 S1 = 1, | 104 S1 = 1, |
105 S2 = 2, | 105 S2 = 2, |
106 S3 = 3, | 106 S3 = 3, |
107 S4 = 4, | 107 S4 = 4, |
108 S5 = 5, | 108 S5 = 5, |
109 S6 = 6, | 109 S6 = 6, |
110 S7 = 7, | 110 S7 = 7, |
111 S8 = 8, | 111 S8 = 8, |
112 S9 = 9, | 112 S9 = 9, |
113 S10 = 10, | 113 S10 = 10, |
114 S11 = 11, | 114 S11 = 11, |
115 S12 = 12, | 115 S12 = 12, |
116 S13 = 13, | 116 S13 = 13, |
117 S14 = 14, | 117 S14 = 14, |
118 S15 = 15, | 118 S15 = 15, |
119 S16 = 16, | 119 S16 = 16, |
120 S17 = 17, | 120 S17 = 17, |
121 S18 = 18, | 121 S18 = 18, |
122 S19 = 19, | 122 S19 = 19, |
123 S20 = 20, | 123 S20 = 20, |
124 S21 = 21, | 124 S21 = 21, |
125 S22 = 22, | 125 S22 = 22, |
126 S23 = 23, | 126 S23 = 23, |
127 S24 = 24, | 127 S24 = 24, |
128 S25 = 25, | 128 S25 = 25, |
129 S26 = 26, | 129 S26 = 26, |
130 S27 = 27, | 130 S27 = 27, |
131 S28 = 28, | 131 S28 = 28, |
132 S29 = 29, | 132 S29 = 29, |
133 S30 = 30, | 133 S30 = 30, |
134 S31 = 31, | 134 S31 = 31, |
135 kNumberOfSRegisters = 32, | 135 kNumberOfSRegisters = 32, |
136 }; | 136 }; |
137 | 137 |
138 | 138 |
139 // Values for double-precision floating point registers. | 139 // Values for double-precision floating point registers. |
140 enum DRegister { | 140 enum DRegister { |
141 kNoDRegister = -1, | 141 kNoDRegister = -1, |
142 D0 = 0, | 142 D0 = 0, |
143 D1 = 1, | 143 D1 = 1, |
144 D2 = 2, | 144 D2 = 2, |
145 D3 = 3, | 145 D3 = 3, |
146 D4 = 4, | 146 D4 = 4, |
147 D5 = 5, | 147 D5 = 5, |
148 D6 = 6, | 148 D6 = 6, |
149 D7 = 7, | 149 D7 = 7, |
150 D8 = 8, | 150 D8 = 8, |
151 D9 = 9, | 151 D9 = 9, |
152 D10 = 10, | 152 D10 = 10, |
153 D11 = 11, | 153 D11 = 11, |
154 D12 = 12, | 154 D12 = 12, |
155 D13 = 13, | 155 D13 = 13, |
156 D14 = 14, | 156 D14 = 14, |
157 D15 = 15, | 157 D15 = 15, |
158 #if defined(VFPv3_D16) | 158 #if defined(VFPv3_D16) |
159 kNumberOfDRegisters = 16, | 159 kNumberOfDRegisters = 16, |
160 // Leaving these defined, but marking them as kNoDRegister to avoid polluting | 160 // Leaving these defined, but marking them as kNoDRegister to avoid polluting |
161 // other parts of the code with #ifdef's. Instead, query kNumberOfDRegisters | 161 // other parts of the code with #ifdef's. Instead, query kNumberOfDRegisters |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
194 D30 = 30, | 194 D30 = 30, |
195 D31 = 31, | 195 D31 = 31, |
196 kNumberOfDRegisters = 32, | 196 kNumberOfDRegisters = 32, |
197 #endif | 197 #endif |
198 kNumberOfOverlappingDRegisters = 16, | 198 kNumberOfOverlappingDRegisters = 16, |
199 }; | 199 }; |
200 | 200 |
201 | 201 |
202 enum QRegister { | 202 enum QRegister { |
203 kNoQRegister = -1, | 203 kNoQRegister = -1, |
204 Q0 = 0, | 204 Q0 = 0, |
205 Q1 = 1, | 205 Q1 = 1, |
206 Q2 = 2, | 206 Q2 = 2, |
207 Q3 = 3, | 207 Q3 = 3, |
208 Q4 = 4, | 208 Q4 = 4, |
209 Q5 = 5, | 209 Q5 = 5, |
210 Q6 = 6, | 210 Q6 = 6, |
211 Q7 = 7, | 211 Q7 = 7, |
212 #if defined(VFPv3_D16) | 212 #if defined(VFPv3_D16) |
213 kNumberOfQRegisters = 8, | 213 kNumberOfQRegisters = 8, |
214 Q8 = kNoQRegister, | 214 Q8 = kNoQRegister, |
215 Q9 = kNoQRegister, | 215 Q9 = kNoQRegister, |
216 Q10 = kNoQRegister, | 216 Q10 = kNoQRegister, |
217 Q11 = kNoQRegister, | 217 Q11 = kNoQRegister, |
218 Q12 = kNoQRegister, | 218 Q12 = kNoQRegister, |
219 Q13 = kNoQRegister, | 219 Q13 = kNoQRegister, |
220 Q14 = kNoQRegister, | 220 Q14 = kNoQRegister, |
221 Q15 = kNoQRegister, | 221 Q15 = kNoQRegister, |
222 #else | 222 #else |
223 Q8 = 8, | 223 Q8 = 8, |
224 Q9 = 9, | 224 Q9 = 9, |
225 Q10 = 10, | 225 Q10 = 10, |
226 Q11 = 11, | 226 Q11 = 11, |
227 Q12 = 12, | 227 Q12 = 12, |
228 Q13 = 13, | 228 Q13 = 13, |
229 Q14 = 14, | 229 Q14 = 14, |
230 Q15 = 15, | 230 Q15 = 15, |
231 kNumberOfQRegisters = 16, | 231 kNumberOfQRegisters = 16, |
232 #endif | 232 #endif |
233 }; | 233 }; |
234 | 234 |
(...skipping 18 matching lines...) Expand all Loading... |
253 | 253 |
254 static inline SRegister OddSRegisterOf(DRegister d) { | 254 static inline SRegister OddSRegisterOf(DRegister d) { |
255 #if defined(VFPv3_D32) | 255 #if defined(VFPv3_D32) |
256 ASSERT(d < D16); | 256 ASSERT(d < D16); |
257 #endif | 257 #endif |
258 return static_cast<SRegister>((d * 2) + 1); | 258 return static_cast<SRegister>((d * 2) + 1); |
259 } | 259 } |
260 | 260 |
261 | 261 |
262 // Register aliases for floating point scratch registers. | 262 // Register aliases for floating point scratch registers. |
263 const QRegister QTMP = Q7; // Overlaps with DTMP, STMP. | 263 const QRegister QTMP = Q7; // Overlaps with DTMP, STMP. |
264 const DRegister DTMP = EvenDRegisterOf(QTMP); // Overlaps with STMP. | 264 const DRegister DTMP = EvenDRegisterOf(QTMP); // Overlaps with STMP. |
265 const SRegister STMP = EvenSRegisterOf(DTMP); | 265 const SRegister STMP = EvenSRegisterOf(DTMP); |
266 | 266 |
267 // Architecture independent aliases. | 267 // Architecture independent aliases. |
268 typedef QRegister FpuRegister; | 268 typedef QRegister FpuRegister; |
269 | 269 |
270 const FpuRegister FpuTMP = QTMP; | 270 const FpuRegister FpuTMP = QTMP; |
271 const int kNumberOfFpuRegisters = kNumberOfQRegisters; | 271 const int kNumberOfFpuRegisters = kNumberOfQRegisters; |
272 const FpuRegister kNoFpuRegister = kNoQRegister; | 272 const FpuRegister kNoFpuRegister = kNoQRegister; |
273 | 273 |
274 // Register aliases. | 274 // Register aliases. |
275 const Register TMP = IP; // Used as scratch register by assembler. | 275 const Register TMP = IP; // Used as scratch register by assembler. |
276 const Register TMP2 = kNoRegister; // There is no second assembler temporary. | 276 const Register TMP2 = kNoRegister; // There is no second assembler temporary. |
277 const Register CTX = R6; // Location of current context at method entry. | 277 const Register CTX = R6; // Location of current context at method entry. |
278 const Register PP = R5; // Caches object pool pointer in generated code. | 278 const Register PP = R5; // Caches object pool pointer in generated code. |
279 const Register SPREG = SP; // Stack pointer register. | 279 const Register SPREG = SP; // Stack pointer register. |
280 const Register FPREG = FP; // Frame pointer register. | 280 const Register FPREG = FP; // Frame pointer register. |
281 const Register LRREG = LR; // Link register. | 281 const Register LRREG = LR; // Link register. |
282 const Register ICREG = R9; // IC data register. | 282 const Register ICREG = R9; // IC data register. |
283 const Register ARGS_DESC_REG = R4; | 283 const Register ARGS_DESC_REG = R4; |
284 const Register CODE_REG = R6; | 284 const Register CODE_REG = R6; |
285 const Register THR = R10; // Caches current thread in generated code. | 285 const Register THR = R10; // Caches current thread in generated code. |
286 const Register CALLEE_SAVED_TEMP = R8; | 286 const Register CALLEE_SAVED_TEMP = R8; |
287 | 287 |
288 // R15 encodes APSR in the vmrs instruction. | 288 // R15 encodes APSR in the vmrs instruction. |
(...skipping 11 matching lines...) Expand all Loading... |
300 // List of registers used in load/store multiple. | 300 // List of registers used in load/store multiple. |
301 typedef uint16_t RegList; | 301 typedef uint16_t RegList; |
302 const RegList kAllCpuRegistersList = 0xFFFF; | 302 const RegList kAllCpuRegistersList = 0xFFFF; |
303 | 303 |
304 | 304 |
305 // C++ ABI call registers. | 305 // C++ ABI call registers. |
306 const RegList kAbiArgumentCpuRegs = | 306 const RegList kAbiArgumentCpuRegs = |
307 (1 << R0) | (1 << R1) | (1 << R2) | (1 << R3); | 307 (1 << R0) | (1 << R1) | (1 << R2) | (1 << R3); |
308 #if defined(TARGET_ABI_IOS) | 308 #if defined(TARGET_ABI_IOS) |
309 const RegList kAbiPreservedCpuRegs = | 309 const RegList kAbiPreservedCpuRegs = |
310 (1 << R4) | (1 << R5) | (1 << R6) | (1 << R8) | | 310 (1 << R4) | (1 << R5) | (1 << R6) | (1 << R8) | (1 << R10) | (1 << R11); |
311 (1 << R10) | (1 << R11); | |
312 const int kAbiPreservedCpuRegCount = 6; | 311 const int kAbiPreservedCpuRegCount = 6; |
313 #elif defined(TARGET_ABI_EABI) | 312 #elif defined(TARGET_ABI_EABI) |
314 const RegList kAbiPreservedCpuRegs = | 313 const RegList kAbiPreservedCpuRegs = (1 << R4) | (1 << R5) | (1 << R6) | |
315 (1 << R4) | (1 << R5) | (1 << R6) | (1 << R7) | | 314 (1 << R7) | (1 << R8) | (1 << R9) | |
316 (1 << R8) | (1 << R9) | (1 << R10); | 315 (1 << R10); |
317 const int kAbiPreservedCpuRegCount = 7; | 316 const int kAbiPreservedCpuRegCount = 7; |
318 #else | 317 #else |
319 #error Unknown ABI | 318 #error Unknown ABI |
320 #endif | 319 #endif |
321 const QRegister kAbiFirstPreservedFpuReg = Q4; | 320 const QRegister kAbiFirstPreservedFpuReg = Q4; |
322 const QRegister kAbiLastPreservedFpuReg = Q7; | 321 const QRegister kAbiLastPreservedFpuReg = Q7; |
323 const int kAbiPreservedFpuRegCount = 4; | 322 const int kAbiPreservedFpuRegCount = 4; |
324 | 323 |
325 const RegList kReservedCpuRegisters = | 324 const RegList kReservedCpuRegisters = (1 << SPREG) | (1 << FPREG) | (1 << TMP) | |
326 (1 << SPREG) | | 325 (1 << PP) | (1 << THR) | (1 << PC); |
327 (1 << FPREG) | | |
328 (1 << TMP) | | |
329 (1 << PP) | | |
330 (1 << THR) | | |
331 (1 << PC); | |
332 // CPU registers available to Dart allocator. | 326 // CPU registers available to Dart allocator. |
333 const RegList kDartAvailableCpuRegs = | 327 const RegList kDartAvailableCpuRegs = |
334 kAllCpuRegistersList & ~kReservedCpuRegisters; | 328 kAllCpuRegistersList & ~kReservedCpuRegisters; |
335 // Registers available to Dart that are not preserved by runtime calls. | 329 // Registers available to Dart that are not preserved by runtime calls. |
336 const RegList kDartVolatileCpuRegs = | 330 const RegList kDartVolatileCpuRegs = |
337 kDartAvailableCpuRegs & ~kAbiPreservedCpuRegs; | 331 kDartAvailableCpuRegs & ~kAbiPreservedCpuRegs; |
338 #if defined(TARGET_ABI_IOS) | 332 #if defined(TARGET_ABI_IOS) |
339 const int kDartVolatileCpuRegCount = 6; | 333 const int kDartVolatileCpuRegCount = 6; |
340 #elif defined(TARGET_ABI_EABI) | 334 #elif defined(TARGET_ABI_EABI) |
341 const int kDartVolatileCpuRegCount = 5; | 335 const int kDartVolatileCpuRegCount = 5; |
342 #endif | 336 #endif |
343 const QRegister kDartFirstVolatileFpuReg = Q0; | 337 const QRegister kDartFirstVolatileFpuReg = Q0; |
344 const QRegister kDartLastVolatileFpuReg = Q3; | 338 const QRegister kDartLastVolatileFpuReg = Q3; |
345 const int kDartVolatileFpuRegCount = 4; | 339 const int kDartVolatileFpuRegCount = 4; |
346 | 340 |
347 | 341 |
348 // Values for the condition field as defined in section A3.2. | 342 // Values for the condition field as defined in section A3.2. |
349 enum Condition { | 343 enum Condition { |
350 kNoCondition = -1, | 344 kNoCondition = -1, |
351 EQ = 0, // equal | 345 EQ = 0, // equal |
352 NE = 1, // not equal | 346 NE = 1, // not equal |
353 CS = 2, // carry set/unsigned higher or same | 347 CS = 2, // carry set/unsigned higher or same |
354 CC = 3, // carry clear/unsigned lower | 348 CC = 3, // carry clear/unsigned lower |
355 MI = 4, // minus/negative | 349 MI = 4, // minus/negative |
356 PL = 5, // plus/positive or zero | 350 PL = 5, // plus/positive or zero |
357 VS = 6, // overflow | 351 VS = 6, // overflow |
358 VC = 7, // no overflow | 352 VC = 7, // no overflow |
359 HI = 8, // unsigned higher | 353 HI = 8, // unsigned higher |
360 LS = 9, // unsigned lower or same | 354 LS = 9, // unsigned lower or same |
361 GE = 10, // signed greater than or equal | 355 GE = 10, // signed greater than or equal |
362 LT = 11, // signed less than | 356 LT = 11, // signed less than |
363 GT = 12, // signed greater than | 357 GT = 12, // signed greater than |
364 LE = 13, // signed less than or equal | 358 LE = 13, // signed less than or equal |
365 AL = 14, // always (unconditional) | 359 AL = 14, // always (unconditional) |
366 kSpecialCondition = 15, // special condition (refer to section A3.2.1) | 360 kSpecialCondition = 15, // special condition (refer to section A3.2.1) |
367 kMaxCondition = 16, | 361 kMaxCondition = 16, |
368 }; | 362 }; |
369 | 363 |
370 | 364 |
371 // Opcodes for Data-processing instructions (instructions with a type 0 and 1) | 365 // Opcodes for Data-processing instructions (instructions with a type 0 and 1) |
372 // as defined in section A3.4 | 366 // as defined in section A3.4 |
373 enum Opcode { | 367 enum Opcode { |
374 kNoOperand = -1, | 368 kNoOperand = -1, |
375 AND = 0, // Logical AND | 369 AND = 0, // Logical AND |
376 EOR = 1, // Logical Exclusive OR | 370 EOR = 1, // Logical Exclusive OR |
377 SUB = 2, // Subtract | 371 SUB = 2, // Subtract |
378 RSB = 3, // Reverse Subtract | 372 RSB = 3, // Reverse Subtract |
379 ADD = 4, // Add | 373 ADD = 4, // Add |
380 ADC = 5, // Add with Carry | 374 ADC = 5, // Add with Carry |
381 SBC = 6, // Subtract with Carry | 375 SBC = 6, // Subtract with Carry |
382 RSC = 7, // Reverse Subtract with Carry | 376 RSC = 7, // Reverse Subtract with Carry |
383 TST = 8, // Test | 377 TST = 8, // Test |
384 TEQ = 9, // Test Equivalence | 378 TEQ = 9, // Test Equivalence |
385 CMP = 10, // Compare | 379 CMP = 10, // Compare |
386 CMN = 11, // Compare Negated | 380 CMN = 11, // Compare Negated |
387 ORR = 12, // Logical (inclusive) OR | 381 ORR = 12, // Logical (inclusive) OR |
388 MOV = 13, // Move | 382 MOV = 13, // Move |
389 BIC = 14, // Bit Clear | 383 BIC = 14, // Bit Clear |
390 MVN = 15, // Move Not | 384 MVN = 15, // Move Not |
391 kMaxOperand = 16 | 385 kMaxOperand = 16 |
392 }; | 386 }; |
393 | 387 |
394 | 388 |
(...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
488 // Example: Test whether the instruction at ptr sets the condition code bits. | 482 // Example: Test whether the instruction at ptr sets the condition code bits. |
489 // | 483 // |
490 // bool InstructionSetsConditionCodes(byte* ptr) { | 484 // bool InstructionSetsConditionCodes(byte* ptr) { |
491 // Instr* instr = Instr::At(ptr); | 485 // Instr* instr = Instr::At(ptr); |
492 // int type = instr->TypeField(); | 486 // int type = instr->TypeField(); |
493 // return ((type == 0) || (type == 1)) && instr->HasS(); | 487 // return ((type == 0) || (type == 1)) && instr->HasS(); |
494 // } | 488 // } |
495 // | 489 // |
496 class Instr { | 490 class Instr { |
497 public: | 491 public: |
498 enum { | 492 enum { kInstrSize = 4, kInstrSizeLog2 = 2, kPCReadOffset = 8 }; |
499 kInstrSize = 4, | |
500 kInstrSizeLog2 = 2, | |
501 kPCReadOffset = 8 | |
502 }; | |
503 | 493 |
504 static const int32_t kNopInstruction = // nop | 494 static const int32_t kNopInstruction = // nop |
505 ((AL << kConditionShift) | (0x32 << 20) | (0xf << 12)); | 495 ((AL << kConditionShift) | (0x32 << 20) | (0xf << 12)); |
506 | 496 |
507 static const int32_t kBreakPointCode = 0xdeb0; // For breakpoint. | 497 static const int32_t kBreakPointCode = 0xdeb0; // For breakpoint. |
508 static const int32_t kStopMessageCode = 0xdeb1; // For Stop(message). | 498 static const int32_t kStopMessageCode = 0xdeb1; // For Stop(message). |
509 static const int32_t kSimulatorBreakCode = 0xdeb2; // For breakpoint in sim. | 499 static const int32_t kSimulatorBreakCode = 0xdeb2; // For breakpoint in sim. |
510 static const int32_t kSimulatorRedirectCode = 0xca11; // For redirection. | 500 static const int32_t kSimulatorRedirectCode = 0xca11; // For redirection. |
511 | 501 |
512 // Breakpoint instruction filling assembler code buffers in debug mode. | 502 // Breakpoint instruction filling assembler code buffers in debug mode. |
513 static const int32_t kBreakPointInstruction = // bkpt(0xdeb0) | 503 static const int32_t kBreakPointInstruction = // bkpt(0xdeb0) |
514 ((AL << kConditionShift) | (0x12 << 20) | (0xdeb << 8) | (0x7 << 4)); | 504 ((AL << kConditionShift) | (0x12 << 20) | (0xdeb << 8) | (0x7 << 4)); |
515 | 505 |
516 // Breakpoint instruction used by the simulator. | 506 // Breakpoint instruction used by the simulator. |
517 // Should be distinct from kBreakPointInstruction and from a typical user | 507 // Should be distinct from kBreakPointInstruction and from a typical user |
518 // breakpoint inserted in generated code for debugging, e.g. bkpt(0). | 508 // breakpoint inserted in generated code for debugging, e.g. bkpt(0). |
519 static const int32_t kSimulatorBreakpointInstruction = | 509 static const int32_t kSimulatorBreakpointInstruction = |
520 // svc #kBreakpointSvcCode | 510 // svc #kBreakpointSvcCode |
521 ((AL << kConditionShift) | (0xf << 24) | kSimulatorBreakCode); | 511 ((AL << kConditionShift) | (0xf << 24) | kSimulatorBreakCode); |
522 | 512 |
523 // Runtime call redirection instruction used by the simulator. | 513 // Runtime call redirection instruction used by the simulator. |
524 static const int32_t kSimulatorRedirectInstruction = | 514 static const int32_t kSimulatorRedirectInstruction = |
525 ((AL << kConditionShift) | (0xf << 24) | kSimulatorRedirectCode); | 515 ((AL << kConditionShift) | (0xf << 24) | kSimulatorRedirectCode); |
526 | 516 |
527 // Get the raw instruction bits. | 517 // Get the raw instruction bits. |
528 inline int32_t InstructionBits() const { | 518 inline int32_t InstructionBits() const { |
529 return *reinterpret_cast<const int32_t*>(this); | 519 return *reinterpret_cast<const int32_t*>(this); |
530 } | 520 } |
531 | 521 |
532 // Set the raw instruction bits to value. | 522 // Set the raw instruction bits to value. |
533 inline void SetInstructionBits(int32_t value) { | 523 inline void SetInstructionBits(int32_t value) { |
534 *reinterpret_cast<int32_t*>(this) = value; | 524 *reinterpret_cast<int32_t*>(this) = value; |
535 } | 525 } |
536 | 526 |
537 // Read one particular bit out of the instruction bits. | 527 // Read one particular bit out of the instruction bits. |
538 inline int Bit(int nr) const { | 528 inline int Bit(int nr) const { return (InstructionBits() >> nr) & 1; } |
539 return (InstructionBits() >> nr) & 1; | |
540 } | |
541 | 529 |
542 // Read a bit field out of the instruction bits. | 530 // Read a bit field out of the instruction bits. |
543 inline int Bits(int shift, int count) const { | 531 inline int Bits(int shift, int count) const { |
544 return (InstructionBits() >> shift) & ((1 << count) - 1); | 532 return (InstructionBits() >> shift) & ((1 << count) - 1); |
545 } | 533 } |
546 | 534 |
547 | 535 |
548 // Accessors for the different named fields used in the ARM encoding. | 536 // Accessors for the different named fields used in the ARM encoding. |
549 // The naming of these accessor corresponds to figure A3-1. | 537 // The naming of these accessor corresponds to figure A3-1. |
550 // Generally applicable fields | 538 // Generally applicable fields |
551 inline Condition ConditionField() const { | 539 inline Condition ConditionField() const { |
552 return static_cast<Condition>(Bits(kConditionShift, kConditionBits)); | 540 return static_cast<Condition>(Bits(kConditionShift, kConditionBits)); |
553 } | 541 } |
554 inline int TypeField() const { return Bits(kTypeShift, kTypeBits); } | 542 inline int TypeField() const { return Bits(kTypeShift, kTypeBits); } |
555 | 543 |
556 inline Register RnField() const { return static_cast<Register>( | 544 inline Register RnField() const { |
557 Bits(kRnShift, kRnBits)); } | 545 return static_cast<Register>(Bits(kRnShift, kRnBits)); |
558 inline Register RdField() const { return static_cast<Register>( | 546 } |
559 Bits(kRdShift, kRdBits)); } | 547 inline Register RdField() const { |
| 548 return static_cast<Register>(Bits(kRdShift, kRdBits)); |
| 549 } |
560 | 550 |
561 // Fields used in Data processing instructions | 551 // Fields used in Data processing instructions |
562 inline Opcode OpcodeField() const { | 552 inline Opcode OpcodeField() const { |
563 return static_cast<Opcode>(Bits(kOpcodeShift, kOpcodeBits)); | 553 return static_cast<Opcode>(Bits(kOpcodeShift, kOpcodeBits)); |
564 } | 554 } |
565 inline int SField() const { return Bits(kSShift, kSBits); } | 555 inline int SField() const { return Bits(kSShift, kSBits); } |
566 // with register | 556 // with register |
567 inline Register RmField() const { | 557 inline Register RmField() const { |
568 return static_cast<Register>(Bits(kRmShift, kRmBits)); | 558 return static_cast<Register>(Bits(kRmShift, kRmBits)); |
569 } | 559 } |
570 inline Shift ShiftField() const { return static_cast<Shift>( | 560 inline Shift ShiftField() const { |
571 Bits(kShiftShift, kShiftBits)); } | 561 return static_cast<Shift>(Bits(kShiftShift, kShiftBits)); |
| 562 } |
572 inline int RegShiftField() const { return Bit(4); } | 563 inline int RegShiftField() const { return Bit(4); } |
573 inline Register RsField() const { | 564 inline Register RsField() const { |
574 return static_cast<Register>(Bits(kRsShift, kRsBits)); | 565 return static_cast<Register>(Bits(kRsShift, kRsBits)); |
575 } | 566 } |
576 inline int ShiftAmountField() const { return Bits(kShiftImmShift, | 567 inline int ShiftAmountField() const { |
577 kShiftImmBits); } | 568 return Bits(kShiftImmShift, kShiftImmBits); |
| 569 } |
578 // with immediate | 570 // with immediate |
579 inline int RotateField() const { return Bits(kRotateShift, kRotateBits); } | 571 inline int RotateField() const { return Bits(kRotateShift, kRotateBits); } |
580 inline int Immed8Field() const { return Bits(kImmed8Shift, kImmed8Bits); } | 572 inline int Immed8Field() const { return Bits(kImmed8Shift, kImmed8Bits); } |
581 | 573 |
582 // Fields used in Load/Store instructions | 574 // Fields used in Load/Store instructions |
583 inline int PUField() const { return Bits(23, 2); } | 575 inline int PUField() const { return Bits(23, 2); } |
584 inline int BField() const { return Bit(22); } | 576 inline int BField() const { return Bit(22); } |
585 inline int WField() const { return Bit(21); } | 577 inline int WField() const { return Bit(21); } |
586 inline int LField() const { return Bit(20); } | 578 inline int LField() const { return Bit(20); } |
587 // with register uses same fields as Data processing instructions above | 579 // with register uses same fields as Data processing instructions above |
588 // with immediate | 580 // with immediate |
589 inline int Offset12Field() const { return Bits(kOffset12Shift, | 581 inline int Offset12Field() const { |
590 kOffset12Bits); } | 582 return Bits(kOffset12Shift, kOffset12Bits); |
| 583 } |
591 // multiple | 584 // multiple |
592 inline int RlistField() const { return Bits(0, 16); } | 585 inline int RlistField() const { return Bits(0, 16); } |
593 // extra loads and stores | 586 // extra loads and stores |
594 inline int SignField() const { return Bit(6); } | 587 inline int SignField() const { return Bit(6); } |
595 inline int HField() const { return Bit(5); } | 588 inline int HField() const { return Bit(5); } |
596 inline int ImmedHField() const { return Bits(8, 4); } | 589 inline int ImmedHField() const { return Bits(8, 4); } |
597 inline int ImmedLField() const { return Bits(0, 4); } | 590 inline int ImmedLField() const { return Bits(0, 4); } |
598 | 591 |
599 // Fields used in Branch instructions | 592 // Fields used in Branch instructions |
600 inline int LinkField() const { return Bits(kLinkShift, kLinkBits); } | 593 inline int LinkField() const { return Bits(kLinkShift, kLinkBits); } |
(...skipping 14 matching lines...) Expand all Loading... |
615 | 608 |
616 // Field used in VFP float immediate move instruction | 609 // Field used in VFP float immediate move instruction |
617 inline float ImmFloatField() const { | 610 inline float ImmFloatField() const { |
618 uint32_t imm32 = (Bit(19) << 31) | (((1 << 5) - Bit(18)) << 25) | | 611 uint32_t imm32 = (Bit(19) << 31) | (((1 << 5) - Bit(18)) << 25) | |
619 (Bits(16, 2) << 23) | (Bits(0, 4) << 19); | 612 (Bits(16, 2) << 23) | (Bits(0, 4) << 19); |
620 return bit_cast<float, uint32_t>(imm32); | 613 return bit_cast<float, uint32_t>(imm32); |
621 } | 614 } |
622 | 615 |
623 // Field used in VFP double immediate move instruction | 616 // Field used in VFP double immediate move instruction |
624 inline double ImmDoubleField() const { | 617 inline double ImmDoubleField() const { |
625 uint64_t imm64 = (Bit(19)*(1LL << 63)) | (((1LL << 8) - Bit(18)) << 54) | | 618 uint64_t imm64 = (Bit(19) * (1LL << 63)) | (((1LL << 8) - Bit(18)) << 54) | |
626 (Bits(16, 2)*(1LL << 52)) | (Bits(0, 4)*(1LL << 48)); | 619 (Bits(16, 2) * (1LL << 52)) | (Bits(0, 4) * (1LL << 48)); |
627 return bit_cast<double, uint64_t>(imm64); | 620 return bit_cast<double, uint64_t>(imm64); |
628 } | 621 } |
629 | 622 |
630 inline Register DivRdField() const { | 623 inline Register DivRdField() const { |
631 return static_cast<Register>(Bits(kDivRdShift, kDivRdBits)); | 624 return static_cast<Register>(Bits(kDivRdShift, kDivRdBits)); |
632 } | 625 } |
633 inline Register DivRmField() const { | 626 inline Register DivRmField() const { |
634 return static_cast<Register>(Bits(kDivRmShift, kDivRmBits)); | 627 return static_cast<Register>(Bits(kDivRmShift, kDivRmBits)); |
635 } | 628 } |
636 inline Register DivRnField() const { | 629 inline Register DivRnField() const { |
637 return static_cast<Register>(Bits(kDivRnShift, kDivRnBits)); | 630 return static_cast<Register>(Bits(kDivRnShift, kDivRnBits)); |
638 } | 631 } |
639 | 632 |
640 // Test for data processing instructions of type 0 or 1. | 633 // Test for data processing instructions of type 0 or 1. |
641 // See "ARM Architecture Reference Manual ARMv7-A and ARMv7-R edition", | 634 // See "ARM Architecture Reference Manual ARMv7-A and ARMv7-R edition", |
642 // section A5.1 "ARM instruction set encoding". | 635 // section A5.1 "ARM instruction set encoding". |
643 inline bool IsDataProcessing() const { | 636 inline bool IsDataProcessing() const { |
644 ASSERT(ConditionField() != kSpecialCondition); | 637 ASSERT(ConditionField() != kSpecialCondition); |
645 ASSERT(Bits(26, 2) == 0); // Type 0 or 1. | 638 ASSERT(Bits(26, 2) == 0); // Type 0 or 1. |
646 return ((Bits(20, 5) & 0x19) != 0x10) && | 639 return ((Bits(20, 5) & 0x19) != 0x10) && |
647 ((Bit(25) == 1) || // Data processing immediate. | 640 ((Bit(25) == 1) || // Data processing immediate. |
648 (Bit(4) == 0) || // Data processing register. | 641 (Bit(4) == 0) || // Data processing register. |
649 (Bit(7) == 0)); // Data processing register-shifted register. | 642 (Bit(7) == 0)); // Data processing register-shifted register. |
650 } | 643 } |
651 | 644 |
652 // Tests for special encodings of type 0 instructions (extra loads and stores, | 645 // Tests for special encodings of type 0 instructions (extra loads and stores, |
653 // as well as multiplications, synchronization primitives, and miscellaneous). | 646 // as well as multiplications, synchronization primitives, and miscellaneous). |
654 // Can only be called for a type 0 or 1 instruction. | 647 // Can only be called for a type 0 or 1 instruction. |
655 inline bool IsMiscellaneous() const { | 648 inline bool IsMiscellaneous() const { |
656 ASSERT(Bits(26, 2) == 0); // Type 0 or 1. | 649 ASSERT(Bits(26, 2) == 0); // Type 0 or 1. |
657 return ((Bit(25) == 0) && ((Bits(20, 5) & 0x19) == 0x10) && (Bit(7) == 0)); | 650 return ((Bit(25) == 0) && ((Bits(20, 5) & 0x19) == 0x10) && (Bit(7) == 0)); |
658 } | 651 } |
659 inline bool IsMultiplyOrSyncPrimitive() const { | 652 inline bool IsMultiplyOrSyncPrimitive() const { |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
699 return static_cast<QRegister>(bits >> 1); | 692 return static_cast<QRegister>(bits >> 1); |
700 } | 693 } |
701 inline QRegister QmField() const { | 694 inline QRegister QmField() const { |
702 const intptr_t bits = Bits(kRmShift, kRmBits) + (Bit(5) << 4); | 695 const intptr_t bits = Bits(kRmShift, kRmBits) + (Bit(5) << 4); |
703 return static_cast<QRegister>(bits >> 1); | 696 return static_cast<QRegister>(bits >> 1); |
704 } | 697 } |
705 | 698 |
706 inline bool IsDivision() const { | 699 inline bool IsDivision() const { |
707 ASSERT(ConditionField() != kSpecialCondition); | 700 ASSERT(ConditionField() != kSpecialCondition); |
708 ASSERT(TypeField() == 3); | 701 ASSERT(TypeField() == 3); |
709 return ((Bit(4) == 1) && (Bits(5, 3) == 0) && | 702 return ((Bit(4) == 1) && (Bits(5, 3) == 0) && (Bit(20) == 1) && |
710 (Bit(20) == 1) && (Bits(22, 3) == 4)); | 703 (Bits(22, 3) == 4)); |
711 } | 704 } |
712 | 705 |
713 // Test for VFP data processing or single transfer instructions of type 7. | 706 // Test for VFP data processing or single transfer instructions of type 7. |
714 inline bool IsVFPDataProcessingOrSingleTransfer() const { | 707 inline bool IsVFPDataProcessingOrSingleTransfer() const { |
715 ASSERT(ConditionField() != kSpecialCondition); | 708 ASSERT(ConditionField() != kSpecialCondition); |
716 ASSERT(TypeField() == 7); | 709 ASSERT(TypeField() == 7); |
717 return ((Bit(24) == 0) && (Bits(9, 3) == 5)); | 710 return ((Bit(24) == 0) && (Bits(9, 3) == 5)); |
718 // Bit(4) == 0: Data Processing | 711 // Bit(4) == 0: Data Processing |
719 // Bit(4) == 1: 8, 16, or 32-bit Transfer between ARM Core and VFP | 712 // Bit(4) == 1: 8, 16, or 32-bit Transfer between ARM Core and VFP |
720 } | 713 } |
(...skipping 25 matching lines...) Expand all Loading... |
746 ASSERT(ConditionField() == kSpecialCondition); | 739 ASSERT(ConditionField() == kSpecialCondition); |
747 return (Bits(25, 3) == 1); | 740 return (Bits(25, 3) == 1); |
748 } | 741 } |
749 | 742 |
750 inline bool IsSIMDLoadStore() const { | 743 inline bool IsSIMDLoadStore() const { |
751 ASSERT(ConditionField() == kSpecialCondition); | 744 ASSERT(ConditionField() == kSpecialCondition); |
752 return (Bits(24, 4) == 4) && (Bit(20) == 0); | 745 return (Bits(24, 4) == 4) && (Bit(20) == 0); |
753 } | 746 } |
754 | 747 |
755 // Special accessors that test for existence of a value. | 748 // Special accessors that test for existence of a value. |
756 inline bool HasS() const { return SField() == 1; } | 749 inline bool HasS() const { return SField() == 1; } |
757 inline bool HasB() const { return BField() == 1; } | 750 inline bool HasB() const { return BField() == 1; } |
758 inline bool HasW() const { return WField() == 1; } | 751 inline bool HasW() const { return WField() == 1; } |
759 inline bool HasL() const { return LField() == 1; } | 752 inline bool HasL() const { return LField() == 1; } |
760 inline bool HasSign() const { return SignField() == 1; } | 753 inline bool HasSign() const { return SignField() == 1; } |
761 inline bool HasH() const { return HField() == 1; } | 754 inline bool HasH() const { return HField() == 1; } |
762 inline bool HasLink() const { return LinkField() == 1; } | 755 inline bool HasLink() const { return LinkField() == 1; } |
763 | 756 |
764 // Instructions are read out of a code stream. The only way to get a | 757 // Instructions are read out of a code stream. The only way to get a |
765 // reference to an instruction is to convert a pointer. There is no way | 758 // reference to an instruction is to convert a pointer. There is no way |
766 // to allocate or create instances of class Instr. | 759 // to allocate or create instances of class Instr. |
767 // Use the At(pc) function to create references to Instr. | 760 // Use the At(pc) function to create references to Instr. |
768 static Instr* At(uword pc) { return reinterpret_cast<Instr*>(pc); } | 761 static Instr* At(uword pc) { return reinterpret_cast<Instr*>(pc); } |
769 | 762 |
770 private: | 763 private: |
771 DISALLOW_ALLOCATION(); | 764 DISALLOW_ALLOCATION(); |
772 DISALLOW_IMPLICIT_CONSTRUCTORS(Instr); | 765 DISALLOW_IMPLICIT_CONSTRUCTORS(Instr); |
773 }; | 766 }; |
774 | 767 |
775 } // namespace dart | 768 } // namespace dart |
776 | 769 |
777 #endif // RUNTIME_VM_CONSTANTS_ARM_H_ | 770 #endif // RUNTIME_VM_CONSTANTS_ARM_H_ |
OLD | NEW |