Chromium Code Reviews| 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 VM_CONSTANTS_ARM_H_ | 5 #ifndef VM_CONSTANTS_ARM_H_ |
| 6 #define VM_CONSTANTS_ARM_H_ | 6 #define VM_CONSTANTS_ARM_H_ |
| 7 | 7 |
| 8 namespace dart { | 8 namespace dart { |
| 9 | 9 |
| 10 // We support both VFPv3-D16 and VFPv3-D32 profiles, but currently only one at | 10 // We support both VFPv3-D16 and VFPv3-D32 profiles, but currently only one at |
| (...skipping 120 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 131 const int kNumberOfFpuRegisters = kNumberOfDRegisters; | 131 const int kNumberOfFpuRegisters = kNumberOfDRegisters; |
| 132 | 132 |
| 133 | 133 |
| 134 // Register aliases. | 134 // Register aliases. |
| 135 const Register TMP = kNoRegister; // No scratch register used by assembler. | 135 const Register TMP = kNoRegister; // No scratch register used by assembler. |
| 136 const Register CTX = R9; // Caches current context in generated code. | 136 const Register CTX = R9; // Caches current context in generated code. |
| 137 const Register SPREG = SP; | 137 const Register SPREG = SP; |
| 138 const Register FPREG = FP; | 138 const Register FPREG = FP; |
| 139 | 139 |
| 140 | 140 |
| 141 // Exception object is passed in this register to the catch handlers when an | |
| 142 // exception is thrown. | |
| 143 const Register kExceptionObjectReg = R0; | |
|
Ivan Posva
2013/01/24 18:25:57
Are you sure this is the right register? Or do you
regis
2013/01/24 21:47:48
The exception register is EAX/RAX on ia32/x64, so
| |
| 144 | |
| 145 | |
| 141 // Values for the condition field as defined in section A3.2. | 146 // Values for the condition field as defined in section A3.2. |
| 142 enum Condition { | 147 enum Condition { |
| 143 kNoCondition = -1, | 148 kNoCondition = -1, |
| 144 EQ = 0, // equal | 149 EQ = 0, // equal |
| 145 NE = 1, // not equal | 150 NE = 1, // not equal |
| 146 CS = 2, // carry set/unsigned higher or same | 151 CS = 2, // carry set/unsigned higher or same |
| 147 CC = 3, // carry clear/unsigned lower | 152 CC = 3, // carry clear/unsigned lower |
| 148 MI = 4, // minus/negative | 153 MI = 4, // minus/negative |
| 149 PL = 5, // plus/positive or zero | 154 PL = 5, // plus/positive or zero |
| 150 VS = 6, // overflow | 155 VS = 6, // overflow |
| 151 VC = 7, // no overflow | 156 VC = 7, // no overflow |
| 152 HI = 8, // unsigned higher | 157 HI = 8, // unsigned higher |
| 153 LS = 9, // unsigned lower or same | 158 LS = 9, // unsigned lower or same |
| 154 GE = 10, // signed greater than or equal | 159 GE = 10, // signed greater than or equal |
| 155 LT = 11, // signed less than | 160 LT = 11, // signed less than |
| 156 GT = 12, // signed greater than | 161 GT = 12, // signed greater than |
| 157 LE = 13, // signed less than or equal | 162 LE = 13, // signed less than or equal |
| 158 AL = 14, // always (unconditional) | 163 AL = 14, // always (unconditional) |
| 159 kSpecialCondition = 15, // special condition (refer to section A3.2.1) | 164 kSpecialCondition = 15, // special condition (refer to section A3.2.1) |
| 160 kMaxCondition = 16, | 165 kMaxCondition = 16, |
| 161 }; | 166 }; |
| 162 | 167 |
| 168 | |
| 169 // Opcodes for Data-processing instructions (instructions with a type 0 and 1) | |
| 170 // as defined in section A3.4 | |
| 171 enum Opcode { | |
| 172 kNoOperand = -1, | |
| 173 AND = 0, // Logical AND | |
| 174 EOR = 1, // Logical Exclusive OR | |
| 175 SUB = 2, // Subtract | |
| 176 RSB = 3, // Reverse Subtract | |
| 177 ADD = 4, // Add | |
| 178 ADC = 5, // Add with Carry | |
| 179 SBC = 6, // Subtract with Carry | |
| 180 RSC = 7, // Reverse Subtract with Carry | |
| 181 TST = 8, // Test | |
| 182 TEQ = 9, // Test Equivalence | |
| 183 CMP = 10, // Compare | |
| 184 CMN = 11, // Compare Negated | |
| 185 ORR = 12, // Logical (inclusive) OR | |
| 186 MOV = 13, // Move | |
| 187 BIC = 14, // Bit Clear | |
| 188 MVN = 15, // Move Not | |
| 189 kMaxOperand = 16 | |
| 190 }; | |
| 191 | |
| 192 | |
| 193 // Shifter types for Data-processing operands as defined in section A5.1.2. | |
| 194 enum Shift { | |
| 195 kNoShift = -1, | |
| 196 LSL = 0, // Logical shift left | |
| 197 LSR = 1, // Logical shift right | |
| 198 ASR = 2, // Arithmetic shift right | |
| 199 ROR = 3, // Rotate right | |
| 200 kMaxShift = 4 | |
| 201 }; | |
| 202 | |
| 203 | |
| 204 // Special Supervisor Call 24-bit codes used in the presence of the ARM | |
| 205 // simulator for redirection, breakpoints, stop messages, and spill markers. | |
| 206 // See /usr/include/asm/unistd.h | |
| 207 const uint32_t kRedirectionSvcCode = 0x90001f; // unused syscall, was sys_stty | |
| 208 const uint32_t kBreakpointSvcCode = 0x900020; // unused syscall, was sys_gtty | |
| 209 const uint32_t kStopMessageSvcCode = 0x9f0001; // __ARM_NR_breakpoint | |
| 210 const uint32_t kSpillMarkerSvcBase = 0x9f0100; // unused ARM private syscall | |
| 211 const uint32_t kWordSpillMarkerSvcCode = kSpillMarkerSvcBase + 1; | |
| 212 const uint32_t kDWordSpillMarkerSvcCode = kSpillMarkerSvcBase + 2; | |
| 213 | |
| 214 | |
| 215 // Constants used for the decoding or encoding of the individual fields of | |
| 216 // instructions. Based on the "Figure 3-1 ARM instruction set summary". | |
| 217 enum InstructionFields { | |
| 218 kConditionShift = 28, | |
| 219 kConditionBits = 4, | |
| 220 kTypeShift = 25, | |
| 221 kTypeBits = 3, | |
| 222 kLinkShift = 24, | |
| 223 kLinkBits = 1, | |
| 224 kUShift = 23, | |
| 225 kUBits = 1, | |
| 226 kOpcodeShift = 21, | |
| 227 kOpcodeBits = 4, | |
| 228 kSShift = 20, | |
| 229 kSBits = 1, | |
| 230 kRnShift = 16, | |
| 231 kRnBits = 4, | |
| 232 kRdShift = 12, | |
| 233 kRdBits = 4, | |
| 234 kRsShift = 8, | |
| 235 kRsBits = 4, | |
| 236 kRmShift = 0, | |
| 237 kRmBits = 4, | |
| 238 | |
| 239 // Immediate instruction fields encoding. | |
| 240 kRotateShift = 8, | |
| 241 kRotateBits = 4, | |
| 242 kImmed8Shift = 0, | |
| 243 kImmed8Bits = 8, | |
| 244 | |
| 245 // Shift instruction register fields encodings. | |
| 246 kShiftImmShift = 7, | |
| 247 kShiftRegisterShift = 8, | |
| 248 kShiftImmBits = 5, | |
| 249 kShiftShift = 5, | |
| 250 kShiftBits = 2, | |
| 251 | |
| 252 // Load/store instruction offset field encoding. | |
| 253 kOffset12Shift = 0, | |
| 254 kOffset12Bits = 12, | |
| 255 kOffset12Mask = 0x00000fff, | |
| 256 | |
| 257 // Mul instruction register fields encodings. | |
| 258 kMulRdShift = 16, | |
| 259 kMulRdBits = 4, | |
| 260 kMulRnShift = 12, | |
| 261 kMulRnBits = 4, | |
| 262 | |
| 263 kBranchOffsetMask = 0x00ffffff | |
| 264 }; | |
| 265 | |
| 266 | |
| 267 // The class Instr enables access to individual fields defined in the ARM | |
| 268 // architecture instruction set encoding as described in figure A3-1. | |
| 269 // | |
| 270 // Example: Test whether the instruction at ptr sets the condition code bits. | |
| 271 // | |
| 272 // bool InstructionSetsConditionCodes(byte* ptr) { | |
| 273 // Instr* instr = Instr::At(ptr); | |
| 274 // int type = instr->TypeField(); | |
| 275 // return ((type == 0) || (type == 1)) && instr->HasS(); | |
| 276 // } | |
| 277 // | |
| 278 class Instr { | |
| 279 public: | |
| 280 enum { | |
| 281 kInstrSize = 4, | |
| 282 kInstrSizeLog2 = 2, | |
| 283 kPCReadOffset = 8 | |
| 284 }; | |
| 285 | |
| 286 static const int kBreakPointInstructionSize = kInstrSize; | |
| 287 bool IsBreakPoint() { | |
| 288 return IsBkpt(); | |
| 289 } | |
| 290 | |
| 291 // Get the raw instruction bits. | |
| 292 inline int32_t InstructionBits() const { | |
| 293 return *reinterpret_cast<const int32_t*>(this); | |
| 294 } | |
| 295 | |
| 296 // Set the raw instruction bits to value. | |
| 297 inline void SetInstructionBits(int32_t value) { | |
| 298 *reinterpret_cast<int32_t*>(this) = value; | |
| 299 } | |
| 300 | |
| 301 // Read one particular bit out of the instruction bits. | |
| 302 inline int Bit(int nr) const { | |
| 303 return (InstructionBits() >> nr) & 1; | |
| 304 } | |
| 305 | |
| 306 // Read a bit field out of the instruction bits. | |
| 307 inline int Bits(int shift, int count) const { | |
| 308 return (InstructionBits() >> shift) & ((1 << count) - 1); | |
| 309 } | |
| 310 | |
| 311 | |
| 312 // Accessors for the different named fields used in the ARM encoding. | |
| 313 // The naming of these accessor corresponds to figure A3-1. | |
| 314 // Generally applicable fields | |
| 315 inline Condition ConditionField() const { | |
| 316 return static_cast<Condition>(Bits(kConditionShift, kConditionBits)); | |
| 317 } | |
| 318 inline int TypeField() const { return Bits(kTypeShift, kTypeBits); } | |
| 319 | |
| 320 inline Register RnField() const { return static_cast<Register>( | |
| 321 Bits(kRnShift, kRnBits)); } | |
| 322 inline Register RdField() const { return static_cast<Register>( | |
| 323 Bits(kRdShift, kRdBits)); } | |
| 324 | |
| 325 // Fields used in Data processing instructions | |
| 326 inline Opcode OpcodeField() const { | |
| 327 return static_cast<Opcode>(Bits(kOpcodeShift, kOpcodeBits)); | |
| 328 } | |
| 329 inline int SField() const { return Bits(kSShift, kSBits); } | |
| 330 // with register | |
| 331 inline Register RmField() const { | |
| 332 return static_cast<Register>(Bits(kRmShift, kRmBits)); | |
| 333 } | |
| 334 inline Shift ShiftField() const { return static_cast<Shift>( | |
| 335 Bits(kShiftShift, kShiftBits)); } | |
| 336 inline int RegShiftField() const { return Bit(4); } | |
| 337 inline Register RsField() const { | |
| 338 return static_cast<Register>(Bits(kRsShift, kRsBits)); | |
| 339 } | |
| 340 inline int ShiftAmountField() const { return Bits(kShiftImmShift, | |
| 341 kShiftImmBits); } | |
| 342 // with immediate | |
| 343 inline int RotateField() const { return Bits(kRotateShift, kRotateBits); } | |
| 344 inline int Immed8Field() const { return Bits(kImmed8Shift, kImmed8Bits); } | |
| 345 | |
| 346 // Fields used in Load/Store instructions | |
| 347 inline int PUField() const { return Bits(23, 2); } | |
| 348 inline int BField() const { return Bit(22); } | |
| 349 inline int WField() const { return Bit(21); } | |
| 350 inline int LField() const { return Bit(20); } | |
| 351 // with register uses same fields as Data processing instructions above | |
| 352 // with immediate | |
| 353 inline int Offset12Field() const { return Bits(kOffset12Shift, | |
| 354 kOffset12Bits); } | |
| 355 // multiple | |
| 356 inline int RlistField() const { return Bits(0, 16); } | |
| 357 // extra loads and stores | |
| 358 inline int SignField() const { return Bit(6); } | |
| 359 inline int HField() const { return Bit(5); } | |
| 360 inline int ImmedHField() const { return Bits(8, 4); } | |
| 361 inline int ImmedLField() const { return Bits(0, 4); } | |
| 362 | |
| 363 // Fields used in Branch instructions | |
| 364 inline int LinkField() const { return Bits(kLinkShift, kLinkBits); } | |
| 365 inline int SImmed24Field() const { return ((InstructionBits() << 8) >> 8); } | |
| 366 | |
| 367 // Fields used in Supervisor Call instructions | |
| 368 inline uint32_t SvcField() const { return Bits(0, 24); } | |
| 369 | |
| 370 // Field used in Breakpoint instruction | |
| 371 inline uint16_t BkptField() const { | |
| 372 return ((Bits(8, 12) << 4) | Bits(0, 4)); | |
| 373 } | |
| 374 | |
| 375 // Field used in 16-bit immediate move instructions | |
| 376 inline uint16_t MovwField() const { | |
| 377 return ((Bits(16, 4) << 12) | Bits(0, 12)); | |
| 378 } | |
| 379 | |
| 380 // Field used in VFP float immediate move instruction | |
| 381 inline float ImmFloatField() const { | |
| 382 uint32_t imm32 = (Bit(19) << 31) | (((1 << 5) - Bit(18)) << 25) | | |
| 383 (Bits(16, 2) << 23) | (Bits(0, 4) << 19); | |
| 384 return bit_cast<float, uint32_t>(imm32); | |
| 385 } | |
| 386 | |
| 387 // Field used in VFP double immediate move instruction | |
| 388 inline double ImmDoubleField() const { | |
| 389 uint64_t imm64 = (Bit(19)*(1LL << 63)) | (((1LL << 8) - Bit(18)) << 54) | | |
| 390 (Bits(16, 2)*(1LL << 52)) | (Bits(0, 4)*(1LL << 48)); | |
| 391 return bit_cast<double, uint64_t>(imm64); | |
| 392 } | |
| 393 | |
| 394 // Test for data processing instructions of type 0 or 1. | |
| 395 // See "ARM Architecture Reference Manual ARMv7-A and ARMv7-R edition", | |
| 396 // section A5.1 "ARM instruction set encoding". | |
| 397 inline bool IsDataProcessing() const { | |
| 398 ASSERT(ConditionField() != kSpecialCondition); | |
| 399 ASSERT(Bits(26, 2) == 0); // Type 0 or 1. | |
| 400 return ((Bits(20, 5) & 0x19) != 0x10) && | |
| 401 ((Bit(25) == 1) || // Data processing immediate. | |
| 402 (Bit(4) == 0) || // Data processing register. | |
| 403 (Bit(7) == 0)); // Data processing register-shifted register. | |
| 404 } | |
| 405 | |
| 406 // Tests for special encodings of type 0 instructions (extra loads and stores, | |
| 407 // as well as multiplications, synchronization primitives, and miscellaneous). | |
| 408 // Can only be called for a type 0 or 1 instruction. | |
| 409 inline bool IsMiscellaneous() const { | |
| 410 ASSERT(Bits(26, 2) == 0); // Type 0 or 1. | |
| 411 return ((Bit(25) == 0) && ((Bits(20, 5) & 0x19) == 0x10) && (Bit(7) == 0)); | |
| 412 } | |
| 413 inline bool IsMultiplyOrSyncPrimitive() const { | |
| 414 ASSERT(Bits(26, 2) == 0); // Type 0 or 1. | |
| 415 return ((Bit(25) == 0) && (Bits(4, 4) == 9)); | |
| 416 } | |
| 417 | |
| 418 // Test for Supervisor Call instruction. | |
| 419 inline bool IsSvc() const { | |
| 420 return ((InstructionBits() & 0xff000000) == 0xef000000); | |
| 421 } | |
| 422 | |
| 423 // Test for Breakpoint instruction. | |
| 424 inline bool IsBkpt() const { | |
| 425 return ((InstructionBits() & 0xfff000f0) == 0xe1200070); | |
| 426 } | |
| 427 | |
| 428 // VFP register fields. | |
| 429 inline SRegister SnField() const { | |
| 430 return static_cast<SRegister>((Bits(kRnShift, kRnBits) << 1) + Bit(7)); | |
| 431 } | |
| 432 inline SRegister SdField() const { | |
| 433 return static_cast<SRegister>((Bits(kRdShift, kRdBits) << 1) + Bit(22)); | |
| 434 } | |
| 435 inline SRegister SmField() const { | |
| 436 return static_cast<SRegister>((Bits(kRmShift, kRmBits) << 1) + Bit(5)); | |
| 437 } | |
| 438 inline DRegister DnField() const { | |
| 439 return static_cast<DRegister>(Bits(kRnShift, kRnBits) + (Bit(7) << 4)); | |
| 440 } | |
| 441 inline DRegister DdField() const { | |
| 442 return static_cast<DRegister>(Bits(kRdShift, kRdBits) + (Bit(22) << 4)); | |
| 443 } | |
| 444 inline DRegister DmField() const { | |
| 445 return static_cast<DRegister>(Bits(kRmShift, kRmBits) + (Bit(5) << 4)); | |
| 446 } | |
| 447 | |
| 448 // Test for VFP data processing or single transfer instructions of type 7. | |
| 449 inline bool IsVFPDataProcessingOrSingleTransfer() const { | |
| 450 ASSERT(ConditionField() != kSpecialCondition); | |
| 451 ASSERT(TypeField() == 7); | |
| 452 return ((Bit(24) == 0) && (Bits(9, 3) == 5)); | |
| 453 // Bit(4) == 0: Data Processing | |
| 454 // Bit(4) == 1: 8, 16, or 32-bit Transfer between ARM Core and VFP | |
| 455 } | |
| 456 | |
| 457 // Test for VFP 64-bit transfer instructions of type 6. | |
| 458 inline bool IsVFPDoubleTransfer() const { | |
| 459 ASSERT(ConditionField() != kSpecialCondition); | |
| 460 ASSERT(TypeField() == 6); | |
| 461 return ((Bits(21, 4) == 2) && (Bits(9, 3) == 5) && | |
| 462 ((Bits(4, 4) & 0xd) == 1)); | |
| 463 } | |
| 464 | |
| 465 // Test for VFP load and store instructions of type 6. | |
| 466 inline bool IsVFPLoadStore() const { | |
| 467 ASSERT(ConditionField() != kSpecialCondition); | |
| 468 ASSERT(TypeField() == 6); | |
| 469 return ((Bits(20, 5) & 0x12) == 0x10) && (Bits(9, 3) == 5); | |
| 470 } | |
| 471 | |
| 472 // Special accessors that test for existence of a value. | |
| 473 inline bool HasS() const { return SField() == 1; } | |
| 474 inline bool HasB() const { return BField() == 1; } | |
| 475 inline bool HasW() const { return WField() == 1; } | |
| 476 inline bool HasL() const { return LField() == 1; } | |
| 477 inline bool HasSign() const { return SignField() == 1; } | |
| 478 inline bool HasH() const { return HField() == 1; } | |
| 479 inline bool HasLink() const { return LinkField() == 1; } | |
| 480 | |
| 481 // Instructions are read out of a code stream. The only way to get a | |
| 482 // reference to an instruction is to convert a pointer. There is no way | |
| 483 // to allocate or create instances of class Instr. | |
| 484 // Use the At(pc) function to create references to Instr. | |
| 485 static Instr* At(uword pc) { return reinterpret_cast<Instr*>(pc); } | |
| 486 Instr* Next() { return this + kInstrSize; } | |
| 487 | |
| 488 private: | |
| 489 DISALLOW_ALLOCATION(); | |
| 490 DISALLOW_IMPLICIT_CONSTRUCTORS(Instr); | |
| 491 }; | |
| 492 | |
| 163 } // namespace dart | 493 } // namespace dart |
| 164 | 494 |
| 165 #endif // VM_CONSTANTS_ARM_H_ | 495 #endif // VM_CONSTANTS_ARM_H_ |
| OLD | NEW |