| 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 |