OLD | NEW |
(Empty) | |
| 1 // Copyright (c) 2014, 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 VM_CONSTANTS_ARM64_H_ |
| 6 #define VM_CONSTANTS_ARM64_H_ |
| 7 |
| 8 #include "platform/assert.h" |
| 9 |
| 10 namespace dart { |
| 11 |
| 12 enum Register { |
| 13 kFirstFreeCpuRegister = 0, |
| 14 R0 = 0, |
| 15 R1 = 1, |
| 16 R2 = 2, |
| 17 R3 = 3, |
| 18 R4 = 4, |
| 19 R5 = 5, |
| 20 R6 = 6, |
| 21 R7 = 7, |
| 22 R8 = 8, |
| 23 R9 = 9, |
| 24 R10 = 10, |
| 25 R11 = 11, |
| 26 R12 = 12, |
| 27 R13 = 13, |
| 28 R14 = 14, |
| 29 R15 = 15, |
| 30 R16 = 16, |
| 31 R17 = 17, |
| 32 R18 = 18, |
| 33 R19 = 19, |
| 34 R20 = 20, |
| 35 R21 = 21, |
| 36 R22 = 22, |
| 37 R23 = 23, |
| 38 R24 = 24, |
| 39 kLastFreeCpuRegister = 24, |
| 40 R25 = 25, // IP0 |
| 41 R26 = 26, // IP1 |
| 42 R27 = 27, // PP |
| 43 R28 = 28, // CTX |
| 44 R29 = 29, // FP |
| 45 R30 = 30, // LR |
| 46 R31 = 31, // ZR, SP |
| 47 kNumberOfCpuRegisters = 32, |
| 48 kNoRegister = -1, |
| 49 |
| 50 // Aliases. |
| 51 IP0 = R25, |
| 52 IP1 = R26, |
| 53 FP = R29, |
| 54 LR = R30, |
| 55 ZR = R31, |
| 56 SP = R31, |
| 57 }; |
| 58 |
| 59 enum VRegister { |
| 60 V0 = 0, |
| 61 V1 = 1, |
| 62 V2 = 2, |
| 63 V3 = 3, |
| 64 V4 = 4, |
| 65 V5 = 5, |
| 66 V6 = 6, |
| 67 V7 = 7, |
| 68 V8 = 8, |
| 69 V9 = 9, |
| 70 V10 = 10, |
| 71 V11 = 11, |
| 72 V12 = 12, |
| 73 V13 = 13, |
| 74 V14 = 14, |
| 75 V15 = 15, |
| 76 V16 = 16, |
| 77 V17 = 17, |
| 78 V18 = 18, |
| 79 V19 = 19, |
| 80 V20 = 20, |
| 81 V21 = 21, |
| 82 V22 = 22, |
| 83 V23 = 24, |
| 84 V24 = 24, |
| 85 V25 = 25, |
| 86 V26 = 26, |
| 87 V27 = 27, |
| 88 V28 = 28, |
| 89 V29 = 29, |
| 90 V30 = 30, |
| 91 V31 = 31, |
| 92 kNumberOfVRegisters = 32, |
| 93 kNoVRegister = -1, |
| 94 }; |
| 95 |
| 96 // Register alias for floating point scratch register. |
| 97 const VRegister VTMP0 = V30; |
| 98 const VRegister VTMP1 = V31; |
| 99 |
| 100 // Architecture independent aliases. |
| 101 typedef VRegister FpuRegister; |
| 102 const FpuRegister FpuTMP = VTMP0; |
| 103 const int kNumberOfFpuRegisters = kNumberOfVRegisters; |
| 104 const FpuRegister kNoFpuRegister = kNoVRegister; |
| 105 |
| 106 // Register aliases. |
| 107 const Register TMP = R25; // Used as scratch register by assembler. |
| 108 const Register TMP0 = R25; |
| 109 const Register TMP1 = R26; |
| 110 const Register CTX = R27; // Caches current context in generated code. |
| 111 const Register PP = R26; // Caches object pool pointer in generated code. |
| 112 const Register SPREG = R31; // Stack pointer register. |
| 113 const Register FPREG = FP; // Frame pointer register. |
| 114 const Register ICREG = R5; // IC data register. |
| 115 |
| 116 // Exception object is passed in this register to the catch handlers when an |
| 117 // exception is thrown. |
| 118 const Register kExceptionObjectReg = R0; |
| 119 |
| 120 // Stack trace object is passed in this register to the catch handlers when |
| 121 // an exception is thrown. |
| 122 const Register kStackTraceObjectReg = R1; |
| 123 |
| 124 // Masks, sizes, etc. |
| 125 const int kXRegSizeInBits = 64; |
| 126 const int kWRegSizeInBits = 32; |
| 127 const int64_t kXRegMask = 0xffffffffffffffffL; |
| 128 const int64_t kWRegMask = 0x00000000ffffffffL; |
| 129 |
| 130 // List of registers used in load/store multiple. |
| 131 typedef uint32_t RegList; |
| 132 const RegList kAllCpuRegistersList = 0xFFFF; |
| 133 |
| 134 |
| 135 // C++ ABI call registers. |
| 136 const RegList kAbiArgumentCpuRegs = |
| 137 (1 << R0) | (1 << R1) | (1 << R2) | (1 << R3) | |
| 138 (1 << R4) | (1 << R5) | (1 << R6) | (1 << R7); |
| 139 const RegList kAbiPreservedCpuRegs = |
| 140 (1 << R19) | (1 << R20) | (1 << R21) | (1 << R22) | |
| 141 (1 << R23) | (1 << R24) | (1 << R25) | (1 << R26) | |
| 142 (1 << R27) | (1 << R28) | (1 << R29); |
| 143 const int kAbiPreservedCpuRegCount = 11; |
| 144 const VRegister kAbiFirstPreservedFpuReg = V8; |
| 145 const VRegister kAbiLastPreservedFpuReg = V15; |
| 146 const int kAbiPreservedFpuRegCount = 8; |
| 147 |
| 148 // CPU registers available to Dart allocator. |
| 149 const RegList kDartAvailableCpuRegs = |
| 150 (1 << R0) | (1 << R1) | (1 << R2) | (1 << R3) | |
| 151 (1 << R4) | (1 << R5) | (1 << R6) | (1 << R7) | |
| 152 (1 << R8) | (1 << R9) | (1 << R10) | (1 << R11) | |
| 153 (1 << R12) | (1 << R13) | (1 << R14) | (1 << R15) | |
| 154 (1 << R16) | (1 << R17) | (1 << R18) | (1 << R19) | |
| 155 (1 << R20) | (1 << R21) | (1 << R22) | (1 << R23) | |
| 156 (1 << R24); |
| 157 |
| 158 // Registers available to Dart that are not preserved by runtime calls. |
| 159 const RegList kDartVolatileCpuRegs = |
| 160 kDartAvailableCpuRegs & ~kAbiPreservedCpuRegs; |
| 161 const int kDartVolatileCpuRegCount = 19; |
| 162 const VRegister kDartFirstVolatileFpuReg = V0; |
| 163 const VRegister kDartLastVolatileFpuReg = V7; |
| 164 const int kDartVolatileFpuRegCount = 8; |
| 165 |
| 166 // Values for the condition field as defined in section A3.2. |
| 167 enum Condition { |
| 168 kNoCondition = -1, |
| 169 EQ = 0, // equal |
| 170 NE = 1, // not equal |
| 171 CS = 2, // carry set/unsigned higher or same |
| 172 CC = 3, // carry clear/unsigned lower |
| 173 MI = 4, // minus/negative |
| 174 PL = 5, // plus/positive or zero |
| 175 VS = 6, // overflow |
| 176 VC = 7, // no overflow |
| 177 HI = 8, // unsigned higher |
| 178 LS = 9, // unsigned lower or same |
| 179 GE = 10, // signed greater than or equal |
| 180 LT = 11, // signed less than |
| 181 GT = 12, // signed greater than |
| 182 LE = 13, // signed less than or equal |
| 183 AL = 14, // always (unconditional) |
| 184 NV = 15, // special condition (refer to section C1.2.3) |
| 185 kMaxCondition = 16, |
| 186 }; |
| 187 |
| 188 enum Bits { |
| 189 B0 = (1 << 0), B1 = (1 << 1), B2 = (1 << 2), B3 = (1 << 3), |
| 190 B4 = (1 << 4), B5 = (1 << 5), B6 = (1 << 6), B7 = (1 << 7), |
| 191 B8 = (1 << 8), B9 = (1 << 9), B10 = (1 << 10), B11 = (1 << 11), |
| 192 B12 = (1 << 12), B13 = (1 << 13), B14 = (1 << 14), B15 = (1 << 15), |
| 193 B16 = (1 << 16), B17 = (1 << 17), B18 = (1 << 18), B19 = (1 << 19), |
| 194 B20 = (1 << 20), B21 = (1 << 21), B22 = (1 << 22), B23 = (1 << 23), |
| 195 B24 = (1 << 24), B25 = (1 << 25), B26 = (1 << 26), B27 = (1 << 27), |
| 196 B28 = (1 << 28), B29 = (1 << 29), B30 = (1 << 30), B31 = (1 << 31), |
| 197 }; |
| 198 |
| 199 enum OperandSize { |
| 200 kByte, |
| 201 kUnsignedByte, |
| 202 kHalfword, |
| 203 kUnsignedHalfword, |
| 204 kWord, |
| 205 kUnsignedWord, |
| 206 kDoubleWord, |
| 207 kSWord, |
| 208 kDWord, |
| 209 }; |
| 210 |
| 211 // Opcodes from C3 |
| 212 // C3.1. |
| 213 enum MainOp { |
| 214 DPImmediateMask = 0x1c000000, |
| 215 DPImmediateFixed = B28, |
| 216 |
| 217 CompareBranchMask = 0x1c000000, |
| 218 CompareBranchFixed = B28 | B26, |
| 219 |
| 220 LoadStoreMask = B27 | B25, |
| 221 LoadStoreFixed = B27, |
| 222 |
| 223 DPRegisterMask = 0x0e000000, |
| 224 DPRegisterFixed = B27 | B25, |
| 225 |
| 226 DPSimd1Mask = 0x1e000000, |
| 227 DPSimd1Fixed = B27 | B26 | B25, |
| 228 |
| 229 DPSimd2Mask = 0x1e000000, |
| 230 DPSimd2Fixed = B28 | DPSimd1Fixed, |
| 231 }; |
| 232 |
| 233 // C3.2.3 |
| 234 enum ExceptionGenOp { |
| 235 ExceptionGenMask = 0xff000000, |
| 236 ExceptionGenFixed = CompareBranchFixed | B31 | B30, |
| 237 SVC = ExceptionGenFixed | B0, |
| 238 BRK = ExceptionGenFixed | B21, |
| 239 HLT = ExceptionGenFixed | B22, |
| 240 }; |
| 241 |
| 242 // C3.2.4 |
| 243 enum SystemOp { |
| 244 SystemMask = 0xffc00000, |
| 245 SystemFixed = CompareBranchFixed | B31 | B30 | B24, |
| 246 HINT = SystemFixed | B17 | B16 | B13 | B4 | B3 | B2 | B1 | B0, |
| 247 }; |
| 248 |
| 249 // C3.2.7 |
| 250 enum UnconditionalBranchRegOp { |
| 251 UnconditionalBranchRegMask = 0xfe000000, |
| 252 UnconditionalBranchRegFixed = CompareBranchFixed | B31 | B30 | B25, |
| 253 BR = UnconditionalBranchRegFixed | B20 | B19 | B18 | B17 | B16, |
| 254 BLR = BR | B21, |
| 255 RET = BR | B22, |
| 256 }; |
| 257 |
| 258 // C3.4.1 |
| 259 enum AddSubImmOp { |
| 260 AddSubImmMask = 0x1f000000, |
| 261 AddSubImmFixed = DPImmediateFixed | B24, |
| 262 ADDI = AddSubImmFixed, |
| 263 SUBI = AddSubImmFixed | B30, |
| 264 }; |
| 265 |
| 266 // C3.4.5 |
| 267 enum MoveWideOp { |
| 268 MoveWideMask = 0x1f800000, |
| 269 MoveWideFixed = DPImmediateFixed | B25 | B23, |
| 270 MOVN = MoveWideFixed, |
| 271 MOVZ = MoveWideFixed | B30, |
| 272 MOVK = MoveWideFixed | B30 | B29, |
| 273 }; |
| 274 |
| 275 |
| 276 // C3.5.1 |
| 277 enum AddSubShiftExtOp { |
| 278 AddSubShiftExtMask = 0x1f200000, |
| 279 AddSubShiftExtFixed = DPRegisterFixed | B24, |
| 280 ADD = AddSubShiftExtFixed, |
| 281 SUB = AddSubShiftExtFixed | B30, |
| 282 }; |
| 283 |
| 284 #define APPLY_OP_LIST(_V) \ |
| 285 _V(DPImmediate) \ |
| 286 _V(CompareBranch) \ |
| 287 _V(LoadStore) \ |
| 288 _V(DPRegister) \ |
| 289 _V(DPSimd1) \ |
| 290 _V(DPSimd2) \ |
| 291 _V(ExceptionGen) \ |
| 292 _V(System) \ |
| 293 _V(UnconditionalBranchReg) \ |
| 294 _V(AddSubImm) \ |
| 295 _V(MoveWide) \ |
| 296 _V(AddSubShiftExt) \ |
| 297 |
| 298 |
| 299 enum Shift { |
| 300 kNoShift = -1, |
| 301 LSL = 0, // Logical shift left |
| 302 LSR = 1, // Logical shift right |
| 303 ASR = 2, // Arithmetic shift right |
| 304 ROR = 3, // Rotate right |
| 305 kMaxShift = 4, |
| 306 }; |
| 307 |
| 308 enum Extend { |
| 309 kNoExtend = -1, |
| 310 UXTB = 0, |
| 311 UXTH = 1, |
| 312 UXTW = 2, |
| 313 UXTX = 3, |
| 314 SXTB = 4, |
| 315 SXTH = 5, |
| 316 SXTW = 6, |
| 317 SXTX = 7, |
| 318 kMaxExtend = 8, |
| 319 }; |
| 320 |
| 321 enum R31Type { |
| 322 R31IsSP, |
| 323 R31IsZR, |
| 324 R31IsUndef, |
| 325 }; |
| 326 |
| 327 // Constants used for the decoding or encoding of the individual fields of |
| 328 // instructions. Based on the "Figure 3-1 ARM instruction set summary". |
| 329 enum InstructionFields { |
| 330 // S-bit (modify condition register) |
| 331 kSShift = 29, |
| 332 kSBits = 1, |
| 333 |
| 334 // sf field. |
| 335 kSFShift = 31, |
| 336 kSFBits = 1, |
| 337 |
| 338 // Registers. |
| 339 kRdShift = 0, |
| 340 kRdBits = 5, |
| 341 kRnShift = 5, |
| 342 kRnBits = 5, |
| 343 kRaShift = 10, |
| 344 kRaBits = 5, |
| 345 kRmShift = 16, |
| 346 kRmBits = 5, |
| 347 |
| 348 // Immediates. |
| 349 kImm3Shift = 10, |
| 350 kImm3Bits = 3, |
| 351 kImm6Shift = 10, |
| 352 kImm6Bits = 6, |
| 353 kImm12Shift = 10, |
| 354 kImm12Bits = 12, |
| 355 kImm12ShiftShift = 22, |
| 356 kImm12ShiftBits = 2, |
| 357 kImm16Shift = 5, |
| 358 kImm16Bits = 16, |
| 359 |
| 360 // Shift and Extend. |
| 361 kShiftExtendShift = 21, |
| 362 kShiftExtendBits = 1, |
| 363 kShiftTypeShift = 22, |
| 364 kShiftTypeBits = 2, |
| 365 kExtendTypeShift = 13, |
| 366 kExtendTypeBits = 3, |
| 367 |
| 368 // Hint Fields. |
| 369 kHintCRmShift = 8, |
| 370 kHintCRmBits = 4, |
| 371 kHintOp2Shift = 5, |
| 372 kHintOp2Bits = 3, |
| 373 }; |
| 374 |
| 375 |
| 376 const uint32_t kImmExceptionIsRedirectedCall = 0xca11; |
| 377 const uint32_t kImmExceptionIsUnreachable = 0xdebf; |
| 378 const uint32_t kImmExceptionIsPrintf = 0xdeb1; |
| 379 const uint32_t kImmExceptionIsDebug = 0xdeb0; |
| 380 |
| 381 // The class Instr enables access to individual fields defined in the ARM |
| 382 // architecture instruction set encoding as described in figure A3-1. |
| 383 // |
| 384 // Example: Test whether the instruction at ptr sets the condition code bits. |
| 385 // |
| 386 // bool InstructionSetsConditionCodes(byte* ptr) { |
| 387 // Instr* instr = Instr::At(ptr); |
| 388 // int type = instr->TypeField(); |
| 389 // return ((type == 0) || (type == 1)) && instr->HasS(); |
| 390 // } |
| 391 // |
| 392 class Instr { |
| 393 public: |
| 394 enum { |
| 395 kInstrSize = 4, |
| 396 kInstrSizeLog2 = 2, |
| 397 kPCReadOffset = 8 |
| 398 }; |
| 399 |
| 400 static const int32_t kNopInstruction = HINT; // hint #0 === nop. |
| 401 static const int32_t kBreakPointInstruction = // hlt #kImmExceptionIsDebug. |
| 402 HLT | (kImmExceptionIsDebug << kImm16Shift); |
| 403 static const int kBreakPointInstructionSize = kInstrSize; |
| 404 |
| 405 // Get the raw instruction bits. |
| 406 inline int32_t InstructionBits() const { |
| 407 return *reinterpret_cast<const int32_t*>(this); |
| 408 } |
| 409 |
| 410 // Set the raw instruction bits to value. |
| 411 inline void SetInstructionBits(int32_t value) { |
| 412 *reinterpret_cast<int32_t*>(this) = value; |
| 413 } |
| 414 |
| 415 // Read one particular bit out of the instruction bits. |
| 416 inline int Bit(int nr) const { |
| 417 return (InstructionBits() >> nr) & 1; |
| 418 } |
| 419 |
| 420 // Read a bit field out of the instruction bits. |
| 421 inline int Bits(int shift, int count) const { |
| 422 return (InstructionBits() >> shift) & ((1 << count) - 1); |
| 423 } |
| 424 |
| 425 |
| 426 inline int SField() const { return Bit(kSShift); } |
| 427 inline int SFField() const { return Bit(kSFShift); } |
| 428 inline Register RdField() const { return static_cast<Register>( |
| 429 Bits(kRdShift, kRdBits)); } |
| 430 inline Register RnField() const { return static_cast<Register>( |
| 431 Bits(kRnShift, kRnBits)); } |
| 432 inline Register RaField() const { return static_cast<Register>( |
| 433 Bits(kRaShift, kRaBits)); } |
| 434 inline Register RmField() const { return static_cast<Register>( |
| 435 Bits(kRmShift, kRmBits)); } |
| 436 |
| 437 // Immediates |
| 438 inline int Imm3Field() const { return Bits(kImm3Shift, kImm3Bits); } |
| 439 inline int Imm6Field() const { return Bits(kImm6Shift, kImm6Bits); } |
| 440 inline int Imm12Field() const { return Bits(kImm12Shift, kImm12Bits); } |
| 441 inline int Imm16Field() const { return Bits(kImm16Shift, kImm16Bits); } |
| 442 |
| 443 inline int Imm12ShiftField() const { |
| 444 return Bits(kImm12ShiftShift, kImm12ShiftBits); } |
| 445 |
| 446 // Shift and Extend. |
| 447 inline bool IsShift() const { return (Bit(kShiftExtendShift) == 0); } |
| 448 inline bool IsExtend() const { return (Bit(kShiftExtendShift) == 1); } |
| 449 inline Shift ShiftTypeField() const { |
| 450 return static_cast<Shift>(Bits(kShiftTypeShift, kShiftTypeBits)); } |
| 451 inline Extend ExtendTypeField() const { |
| 452 return static_cast<Extend>(Bits(kExtendTypeShift, kExtendTypeBits)); } |
| 453 inline int ShiftAmountField() const { return Imm6Field(); } |
| 454 inline int ExtShiftAmountField() const { return Imm3Field(); } |
| 455 |
| 456 // Instruction identification. |
| 457 #define IS_OP(op) \ |
| 458 inline bool Is##op##Op() const { \ |
| 459 return ((InstructionBits() & op##Mask) == (op##Fixed & op##Mask)); } |
| 460 APPLY_OP_LIST(IS_OP) |
| 461 #undef IS_OP |
| 462 |
| 463 inline bool HasS() const { return (SField() == 1); } |
| 464 |
| 465 // Indicate whether Rd can be the SP or ZR. This does not check that the |
| 466 // instruction actually has an Rd field. |
| 467 R31Type RdMode() const { |
| 468 // The following instructions use SP as Rd: |
| 469 // Add/sub (immediate) when not setting the flags. |
| 470 // Add/sub (extended) when not setting the flags. |
| 471 // Logical (immediate) when not setting the flags. |
| 472 // Otherwise, R31 is the ZR. |
| 473 if (IsAddSubImmOp() || (IsAddSubShiftExtOp() && IsExtend())) { |
| 474 if (HasS()) { |
| 475 return R31IsZR; |
| 476 } else { |
| 477 return R31IsSP; |
| 478 } |
| 479 } |
| 480 // TODO(zra): Handle for logical immediate operations. |
| 481 return R31IsZR; |
| 482 } |
| 483 |
| 484 // Indicate whether Rn can be SP or ZR. This does not check that the |
| 485 // instruction actually has an Rn field. |
| 486 R31Type RnMode() const { |
| 487 // The following instructions use SP as Rn: |
| 488 // All loads and stores. |
| 489 // Add/sub (immediate). |
| 490 // Add/sub (extended). |
| 491 // Otherwise, r31 is ZR. |
| 492 if (IsLoadStoreOp() || |
| 493 IsAddSubImmOp() || |
| 494 (IsAddSubShiftExtOp() && IsExtend())) { |
| 495 return R31IsSP; |
| 496 } |
| 497 return R31IsZR; |
| 498 } |
| 499 |
| 500 // Instructions are read out of a code stream. The only way to get a |
| 501 // reference to an instruction is to convert a pointer. There is no way |
| 502 // to allocate or create instances of class Instr. |
| 503 // Use the At(pc) function to create references to Instr. |
| 504 static Instr* At(uword pc) { return reinterpret_cast<Instr*>(pc); } |
| 505 |
| 506 private: |
| 507 DISALLOW_ALLOCATION(); |
| 508 DISALLOW_IMPLICIT_CONSTRUCTORS(Instr); |
| 509 }; |
| 510 |
| 511 } // namespace dart |
| 512 |
| 513 #endif // VM_CONSTANTS_ARM64_H_ |
OLD | NEW |