OLD | NEW |
1 // Copyright 2013 the V8 project authors. All rights reserved. | 1 // Copyright 2013 the V8 project authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #ifndef V8_ARM64_INSTRUCTIONS_ARM64_H_ | 5 #ifndef V8_ARM64_INSTRUCTIONS_ARM64_H_ |
6 #define V8_ARM64_INSTRUCTIONS_ARM64_H_ | 6 #define V8_ARM64_INSTRUCTIONS_ARM64_H_ |
7 | 7 |
8 #include "src/arm64/constants-arm64.h" | 8 #include "src/arm64/constants-arm64.h" |
9 #include "src/arm64/utils-arm64.h" | 9 #include "src/arm64/utils-arm64.h" |
10 #include "src/globals.h" | 10 #include "src/globals.h" |
11 #include "src/utils.h" | 11 #include "src/utils.h" |
12 | 12 |
13 namespace v8 { | 13 namespace v8 { |
14 namespace internal { | 14 namespace internal { |
15 | 15 |
16 | 16 |
17 // ISA constants. -------------------------------------------------------------- | 17 // ISA constants. -------------------------------------------------------------- |
18 | 18 |
19 typedef uint32_t Instr; | 19 typedef uint32_t Instr; |
20 | 20 |
21 // The following macros initialize a float/double variable with a bit pattern | 21 // The following macros initialize a float/double variable with a bit pattern |
22 // without using static initializers: If ARM64_DEFINE_FP_STATICS is defined, the | 22 // without using static initializers: If ARM64_DEFINE_FP_STATICS is defined, the |
23 // symbol is defined as uint32_t/uint64_t initialized with the desired bit | 23 // symbol is defined as uint32_t/uint64_t initialized with the desired bit |
24 // pattern. Otherwise, the same symbol is declared as an external float/double. | 24 // pattern. Otherwise, the same symbol is declared as an external float/double. |
25 #if defined(ARM64_DEFINE_FP_STATICS) | 25 #if defined(ARM64_DEFINE_FP_STATICS) |
| 26 #define DEFINE_FLOAT16(name, value) extern const uint16_t name = value |
26 #define DEFINE_FLOAT(name, value) extern const uint32_t name = value | 27 #define DEFINE_FLOAT(name, value) extern const uint32_t name = value |
27 #define DEFINE_DOUBLE(name, value) extern const uint64_t name = value | 28 #define DEFINE_DOUBLE(name, value) extern const uint64_t name = value |
28 #else | 29 #else |
| 30 #define DEFINE_FLOAT16(name, value) extern const float16 name |
29 #define DEFINE_FLOAT(name, value) extern const float name | 31 #define DEFINE_FLOAT(name, value) extern const float name |
30 #define DEFINE_DOUBLE(name, value) extern const double name | 32 #define DEFINE_DOUBLE(name, value) extern const double name |
31 #endif // defined(ARM64_DEFINE_FP_STATICS) | 33 #endif // defined(ARM64_DEFINE_FP_STATICS) |
32 | 34 |
| 35 DEFINE_FLOAT16(kFP16PositiveInfinity, 0x7c00); |
| 36 DEFINE_FLOAT16(kFP16NegativeInfinity, 0xfc00); |
33 DEFINE_FLOAT(kFP32PositiveInfinity, 0x7f800000); | 37 DEFINE_FLOAT(kFP32PositiveInfinity, 0x7f800000); |
34 DEFINE_FLOAT(kFP32NegativeInfinity, 0xff800000); | 38 DEFINE_FLOAT(kFP32NegativeInfinity, 0xff800000); |
35 DEFINE_DOUBLE(kFP64PositiveInfinity, 0x7ff0000000000000UL); | 39 DEFINE_DOUBLE(kFP64PositiveInfinity, 0x7ff0000000000000UL); |
36 DEFINE_DOUBLE(kFP64NegativeInfinity, 0xfff0000000000000UL); | 40 DEFINE_DOUBLE(kFP64NegativeInfinity, 0xfff0000000000000UL); |
37 | 41 |
38 // This value is a signalling NaN as both a double and as a float (taking the | 42 // This value is a signalling NaN as both a double and as a float (taking the |
39 // least-significant word). | 43 // least-significant word). |
40 DEFINE_DOUBLE(kFP64SignallingNaN, 0x7ff000007f800001); | 44 DEFINE_DOUBLE(kFP64SignallingNaN, 0x7ff000007f800001); |
41 DEFINE_FLOAT(kFP32SignallingNaN, 0x7f800001); | 45 DEFINE_FLOAT(kFP32SignallingNaN, 0x7f800001); |
42 | 46 |
43 // A similar value, but as a quiet NaN. | 47 // A similar value, but as a quiet NaN. |
44 DEFINE_DOUBLE(kFP64QuietNaN, 0x7ff800007fc00001); | 48 DEFINE_DOUBLE(kFP64QuietNaN, 0x7ff800007fc00001); |
45 DEFINE_FLOAT(kFP32QuietNaN, 0x7fc00001); | 49 DEFINE_FLOAT(kFP32QuietNaN, 0x7fc00001); |
46 | 50 |
47 // The default NaN values (for FPCR.DN=1). | 51 // The default NaN values (for FPCR.DN=1). |
48 DEFINE_DOUBLE(kFP64DefaultNaN, 0x7ff8000000000000UL); | 52 DEFINE_DOUBLE(kFP64DefaultNaN, 0x7ff8000000000000UL); |
49 DEFINE_FLOAT(kFP32DefaultNaN, 0x7fc00000); | 53 DEFINE_FLOAT(kFP32DefaultNaN, 0x7fc00000); |
| 54 DEFINE_FLOAT16(kFP16DefaultNaN, 0x7e00); |
50 | 55 |
| 56 #undef DEFINE_FLOAT16 |
51 #undef DEFINE_FLOAT | 57 #undef DEFINE_FLOAT |
52 #undef DEFINE_DOUBLE | 58 #undef DEFINE_DOUBLE |
53 | 59 |
54 | 60 unsigned CalcLSDataSize(LoadStoreOp op); |
55 enum LSDataSize { | 61 unsigned CalcLSPairDataSize(LoadStorePairOp op); |
56 LSByte = 0, | |
57 LSHalfword = 1, | |
58 LSWord = 2, | |
59 LSDoubleWord = 3 | |
60 }; | |
61 | |
62 LSDataSize CalcLSPairDataSize(LoadStorePairOp op); | |
63 | 62 |
64 enum ImmBranchType { | 63 enum ImmBranchType { |
65 UnknownBranchType = 0, | 64 UnknownBranchType = 0, |
66 CondBranchType = 1, | 65 CondBranchType = 1, |
67 UncondBranchType = 2, | 66 UncondBranchType = 2, |
68 CompareBranchType = 3, | 67 CompareBranchType = 3, |
69 TestBranchType = 4 | 68 TestBranchType = 4 |
70 }; | 69 }; |
71 | 70 |
72 enum AddrMode { | 71 enum AddrMode { |
73 Offset, | 72 Offset, |
74 PreIndex, | 73 PreIndex, |
75 PostIndex | 74 PostIndex |
76 }; | 75 }; |
77 | 76 |
78 enum FPRounding { | 77 enum FPRounding { |
79 // The first four values are encodable directly by FPCR<RMode>. | 78 // The first four values are encodable directly by FPCR<RMode>. |
80 FPTieEven = 0x0, | 79 FPTieEven = 0x0, |
81 FPPositiveInfinity = 0x1, | 80 FPPositiveInfinity = 0x1, |
82 FPNegativeInfinity = 0x2, | 81 FPNegativeInfinity = 0x2, |
83 FPZero = 0x3, | 82 FPZero = 0x3, |
84 | 83 |
85 // The final rounding mode is only available when explicitly specified by the | 84 // The final rounding modes are only available when explicitly specified by |
86 // instruction (such as with fcvta). It cannot be set in FPCR. | 85 // the instruction (such as with fcvta). They cannot be set in FPCR. |
87 FPTieAway | 86 FPTieAway, |
| 87 FPRoundOdd |
88 }; | 88 }; |
89 | 89 |
90 enum Reg31Mode { | 90 enum Reg31Mode { |
91 Reg31IsStackPointer, | 91 Reg31IsStackPointer, |
92 Reg31IsZeroRegister | 92 Reg31IsZeroRegister |
93 }; | 93 }; |
94 | 94 |
95 // Instructions. --------------------------------------------------------------- | 95 // Instructions. --------------------------------------------------------------- |
96 | 96 |
97 class Instruction { | 97 class Instruction { |
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
145 // ImmPCRel is a compound field (not present in INSTRUCTION_FIELDS_LIST), | 145 // ImmPCRel is a compound field (not present in INSTRUCTION_FIELDS_LIST), |
146 // formed from ImmPCRelLo and ImmPCRelHi. | 146 // formed from ImmPCRelLo and ImmPCRelHi. |
147 int ImmPCRel() const { | 147 int ImmPCRel() const { |
148 DCHECK(IsPCRelAddressing()); | 148 DCHECK(IsPCRelAddressing()); |
149 int offset = ((ImmPCRelHi() << ImmPCRelLo_width) | ImmPCRelLo()); | 149 int offset = ((ImmPCRelHi() << ImmPCRelLo_width) | ImmPCRelLo()); |
150 int width = ImmPCRelLo_width + ImmPCRelHi_width; | 150 int width = ImmPCRelLo_width + ImmPCRelHi_width; |
151 return signed_bitextract_32(width - 1, 0, offset); | 151 return signed_bitextract_32(width - 1, 0, offset); |
152 } | 152 } |
153 | 153 |
154 uint64_t ImmLogical(); | 154 uint64_t ImmLogical(); |
| 155 unsigned ImmNEONabcdefgh() const; |
155 float ImmFP32(); | 156 float ImmFP32(); |
156 double ImmFP64(); | 157 double ImmFP64(); |
| 158 float ImmNEONFP32() const; |
| 159 double ImmNEONFP64() const; |
157 | 160 |
158 LSDataSize SizeLSPair() const { | 161 unsigned SizeLS() const { |
| 162 return CalcLSDataSize(static_cast<LoadStoreOp>(Mask(LoadStoreMask))); |
| 163 } |
| 164 |
| 165 unsigned SizeLSPair() const { |
159 return CalcLSPairDataSize( | 166 return CalcLSPairDataSize( |
160 static_cast<LoadStorePairOp>(Mask(LoadStorePairMask))); | 167 static_cast<LoadStorePairOp>(Mask(LoadStorePairMask))); |
161 } | 168 } |
162 | 169 |
| 170 int NEONLSIndex(int access_size_shift) const { |
| 171 int q = NEONQ(); |
| 172 int s = NEONS(); |
| 173 int size = NEONLSSize(); |
| 174 int index = (q << 3) | (s << 2) | size; |
| 175 return index >> access_size_shift; |
| 176 } |
| 177 |
163 // Helpers. | 178 // Helpers. |
164 bool IsCondBranchImm() const { | 179 bool IsCondBranchImm() const { |
165 return Mask(ConditionalBranchFMask) == ConditionalBranchFixed; | 180 return Mask(ConditionalBranchFMask) == ConditionalBranchFixed; |
166 } | 181 } |
167 | 182 |
168 bool IsUncondBranchImm() const { | 183 bool IsUncondBranchImm() const { |
169 return Mask(UnconditionalBranchFMask) == UnconditionalBranchFixed; | 184 return Mask(UnconditionalBranchFMask) == UnconditionalBranchFixed; |
170 } | 185 } |
171 | 186 |
172 bool IsCompareBranch() const { | 187 bool IsCompareBranch() const { |
173 return Mask(CompareBranchFMask) == CompareBranchFixed; | 188 return Mask(CompareBranchFMask) == CompareBranchFixed; |
174 } | 189 } |
175 | 190 |
176 bool IsTestBranch() const { | 191 bool IsTestBranch() const { |
177 return Mask(TestBranchFMask) == TestBranchFixed; | 192 return Mask(TestBranchFMask) == TestBranchFixed; |
178 } | 193 } |
179 | 194 |
180 bool IsImmBranch() const { | 195 bool IsImmBranch() const { |
181 return BranchType() != UnknownBranchType; | 196 return BranchType() != UnknownBranchType; |
182 } | 197 } |
183 | 198 |
| 199 static float Imm8ToFP32(uint32_t imm8) { |
| 200 // Imm8: abcdefgh (8 bits) |
| 201 // Single: aBbb.bbbc.defg.h000.0000.0000.0000.0000 (32 bits) |
| 202 // where B is b ^ 1 |
| 203 uint32_t bits = imm8; |
| 204 uint32_t bit7 = (bits >> 7) & 0x1; |
| 205 uint32_t bit6 = (bits >> 6) & 0x1; |
| 206 uint32_t bit5_to_0 = bits & 0x3f; |
| 207 uint32_t result = (bit7 << 31) | ((32 - bit6) << 25) | (bit5_to_0 << 19); |
| 208 |
| 209 return bit_cast<float>(result); |
| 210 } |
| 211 |
| 212 static double Imm8ToFP64(uint32_t imm8) { |
| 213 // Imm8: abcdefgh (8 bits) |
| 214 // Double: aBbb.bbbb.bbcd.efgh.0000.0000.0000.0000 |
| 215 // 0000.0000.0000.0000.0000.0000.0000.0000 (64 bits) |
| 216 // where B is b ^ 1 |
| 217 uint32_t bits = imm8; |
| 218 uint64_t bit7 = (bits >> 7) & 0x1; |
| 219 uint64_t bit6 = (bits >> 6) & 0x1; |
| 220 uint64_t bit5_to_0 = bits & 0x3f; |
| 221 uint64_t result = (bit7 << 63) | ((256 - bit6) << 54) | (bit5_to_0 << 48); |
| 222 |
| 223 return bit_cast<double>(result); |
| 224 } |
| 225 |
184 bool IsLdrLiteral() const { | 226 bool IsLdrLiteral() const { |
185 return Mask(LoadLiteralFMask) == LoadLiteralFixed; | 227 return Mask(LoadLiteralFMask) == LoadLiteralFixed; |
186 } | 228 } |
187 | 229 |
188 bool IsLdrLiteralX() const { | 230 bool IsLdrLiteralX() const { |
189 return Mask(LoadLiteralMask) == LDR_x_lit; | 231 return Mask(LoadLiteralMask) == LDR_x_lit; |
190 } | 232 } |
191 | 233 |
192 bool IsPCRelAddressing() const { | 234 bool IsPCRelAddressing() const { |
193 return Mask(PCRelAddressingFMask) == PCRelAddressingFixed; | 235 return Mask(PCRelAddressingFMask) == PCRelAddressingFixed; |
(...skipping 214 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
408 return reinterpret_cast<Address>(target) - reinterpret_cast<Address>(this); | 450 return reinterpret_cast<Address>(target) - reinterpret_cast<Address>(this); |
409 } | 451 } |
410 | 452 |
411 | 453 |
412 static const int ImmPCRelRangeBitwidth = 21; | 454 static const int ImmPCRelRangeBitwidth = 21; |
413 static bool IsValidPCRelOffset(ptrdiff_t offset) { return is_int21(offset); } | 455 static bool IsValidPCRelOffset(ptrdiff_t offset) { return is_int21(offset); } |
414 void SetPCRelImmTarget(Isolate* isolate, Instruction* target); | 456 void SetPCRelImmTarget(Isolate* isolate, Instruction* target); |
415 void SetBranchImmTarget(Instruction* target); | 457 void SetBranchImmTarget(Instruction* target); |
416 }; | 458 }; |
417 | 459 |
| 460 // Functions for handling NEON vector format information. |
| 461 enum VectorFormat { |
| 462 kFormatUndefined = 0xffffffff, |
| 463 kFormat8B = NEON_8B, |
| 464 kFormat16B = NEON_16B, |
| 465 kFormat4H = NEON_4H, |
| 466 kFormat8H = NEON_8H, |
| 467 kFormat2S = NEON_2S, |
| 468 kFormat4S = NEON_4S, |
| 469 kFormat1D = NEON_1D, |
| 470 kFormat2D = NEON_2D, |
| 471 |
| 472 // Scalar formats. We add the scalar bit to distinguish between scalar and |
| 473 // vector enumerations; the bit is always set in the encoding of scalar ops |
| 474 // and always clear for vector ops. Although kFormatD and kFormat1D appear |
| 475 // to be the same, their meaning is subtly different. The first is a scalar |
| 476 // operation, the second a vector operation that only affects one lane. |
| 477 kFormatB = NEON_B | NEONScalar, |
| 478 kFormatH = NEON_H | NEONScalar, |
| 479 kFormatS = NEON_S | NEONScalar, |
| 480 kFormatD = NEON_D | NEONScalar |
| 481 }; |
| 482 |
| 483 VectorFormat VectorFormatHalfWidth(VectorFormat vform); |
| 484 VectorFormat VectorFormatDoubleWidth(VectorFormat vform); |
| 485 VectorFormat VectorFormatDoubleLanes(VectorFormat vform); |
| 486 VectorFormat VectorFormatHalfLanes(VectorFormat vform); |
| 487 VectorFormat ScalarFormatFromLaneSize(int lanesize); |
| 488 VectorFormat VectorFormatHalfWidthDoubleLanes(VectorFormat vform); |
| 489 VectorFormat VectorFormatFillQ(VectorFormat vform); |
| 490 VectorFormat ScalarFormatFromFormat(VectorFormat vform); |
| 491 unsigned RegisterSizeInBitsFromFormat(VectorFormat vform); |
| 492 unsigned RegisterSizeInBytesFromFormat(VectorFormat vform); |
| 493 int LaneSizeInBytesFromFormat(VectorFormat vform); |
| 494 unsigned LaneSizeInBitsFromFormat(VectorFormat vform); |
| 495 int LaneSizeInBytesLog2FromFormat(VectorFormat vform); |
| 496 int LaneCountFromFormat(VectorFormat vform); |
| 497 int MaxLaneCountFromFormat(VectorFormat vform); |
| 498 bool IsVectorFormat(VectorFormat vform); |
| 499 int64_t MaxIntFromFormat(VectorFormat vform); |
| 500 int64_t MinIntFromFormat(VectorFormat vform); |
| 501 uint64_t MaxUintFromFormat(VectorFormat vform); |
418 | 502 |
419 // Where Instruction looks at instructions generated by the Assembler, | 503 // Where Instruction looks at instructions generated by the Assembler, |
420 // InstructionSequence looks at instructions sequences generated by the | 504 // InstructionSequence looks at instructions sequences generated by the |
421 // MacroAssembler. | 505 // MacroAssembler. |
422 class InstructionSequence : public Instruction { | 506 class InstructionSequence : public Instruction { |
423 public: | 507 public: |
424 static InstructionSequence* At(Address address) { | 508 static InstructionSequence* At(Address address) { |
425 return reinterpret_cast<InstructionSequence*>(address); | 509 return reinterpret_cast<InstructionSequence*>(address); |
426 } | 510 } |
427 | 511 |
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
495 // Debug parameters. | 579 // Debug parameters. |
496 // Used without a TRACE_ option, the Debugger will print the arguments only | 580 // Used without a TRACE_ option, the Debugger will print the arguments only |
497 // once. Otherwise TRACE_ENABLE and TRACE_DISABLE will enable or disable tracing | 581 // once. Otherwise TRACE_ENABLE and TRACE_DISABLE will enable or disable tracing |
498 // before every instruction for the specified LOG_ parameters. | 582 // before every instruction for the specified LOG_ parameters. |
499 // | 583 // |
500 // TRACE_OVERRIDE enables the specified LOG_ parameters, and disabled any | 584 // TRACE_OVERRIDE enables the specified LOG_ parameters, and disabled any |
501 // others that were not specified. | 585 // others that were not specified. |
502 // | 586 // |
503 // For example: | 587 // For example: |
504 // | 588 // |
505 // __ debug("print registers and fp registers", 0, LOG_REGS | LOG_FP_REGS); | 589 // __ debug("print registers and fp registers", 0, LOG_REGS | LOG_VREGS); |
506 // will print the registers and fp registers only once. | 590 // will print the registers and fp registers only once. |
507 // | 591 // |
508 // __ debug("trace disasm", 1, TRACE_ENABLE | LOG_DISASM); | 592 // __ debug("trace disasm", 1, TRACE_ENABLE | LOG_DISASM); |
509 // starts disassembling the code. | 593 // starts disassembling the code. |
510 // | 594 // |
511 // __ debug("trace rets", 2, TRACE_ENABLE | LOG_REGS); | 595 // __ debug("trace rets", 2, TRACE_ENABLE | LOG_REGS); |
512 // adds the general purpose registers to the trace. | 596 // adds the general purpose registers to the trace. |
513 // | 597 // |
514 // __ debug("stop regs", 3, TRACE_DISABLE | LOG_REGS); | 598 // __ debug("stop regs", 3, TRACE_DISABLE | LOG_REGS); |
515 // stops tracing the registers. | 599 // stops tracing the registers. |
516 const unsigned kDebuggerTracingDirectivesMask = 3 << 6; | 600 const unsigned kDebuggerTracingDirectivesMask = 3 << 6; |
517 enum DebugParameters { | 601 enum DebugParameters { |
518 NO_PARAM = 0, | 602 NO_PARAM = 0, |
519 BREAK = 1 << 0, | 603 BREAK = 1 << 0, |
520 LOG_DISASM = 1 << 1, // Use only with TRACE. Disassemble the code. | 604 LOG_DISASM = 1 << 1, // Use only with TRACE. Disassemble the code. |
521 LOG_REGS = 1 << 2, // Log general purpose registers. | 605 LOG_REGS = 1 << 2, // Log general purpose registers. |
522 LOG_FP_REGS = 1 << 3, // Log floating-point registers. | 606 LOG_VREGS = 1 << 3, // Log NEON and floating-point registers. |
523 LOG_SYS_REGS = 1 << 4, // Log the status flags. | 607 LOG_SYS_REGS = 1 << 4, // Log the status flags. |
524 LOG_WRITE = 1 << 5, // Log any memory write. | 608 LOG_WRITE = 1 << 5, // Log any memory write. |
525 | 609 |
526 LOG_STATE = LOG_REGS | LOG_FP_REGS | LOG_SYS_REGS, | 610 LOG_NONE = 0, |
527 LOG_ALL = LOG_DISASM | LOG_STATE | LOG_WRITE, | 611 LOG_STATE = LOG_REGS | LOG_VREGS | LOG_SYS_REGS, |
| 612 LOG_ALL = LOG_DISASM | LOG_STATE | LOG_WRITE, |
528 | 613 |
529 // Trace control. | 614 // Trace control. |
530 TRACE_ENABLE = 1 << 6, | 615 TRACE_ENABLE = 1 << 6, |
531 TRACE_DISABLE = 2 << 6, | 616 TRACE_DISABLE = 2 << 6, |
532 TRACE_OVERRIDE = 3 << 6 | 617 TRACE_OVERRIDE = 3 << 6 |
533 }; | 618 }; |
534 | 619 |
535 | 620 enum NEONFormat { |
| 621 NF_UNDEF = 0, |
| 622 NF_8B = 1, |
| 623 NF_16B = 2, |
| 624 NF_4H = 3, |
| 625 NF_8H = 4, |
| 626 NF_2S = 5, |
| 627 NF_4S = 6, |
| 628 NF_1D = 7, |
| 629 NF_2D = 8, |
| 630 NF_B = 9, |
| 631 NF_H = 10, |
| 632 NF_S = 11, |
| 633 NF_D = 12 |
| 634 }; |
| 635 |
| 636 static const unsigned kNEONFormatMaxBits = 6; |
| 637 |
| 638 struct NEONFormatMap { |
| 639 // The bit positions in the instruction to consider. |
| 640 uint8_t bits[kNEONFormatMaxBits]; |
| 641 |
| 642 // Mapping from concatenated bits to format. |
| 643 NEONFormat map[1 << kNEONFormatMaxBits]; |
| 644 }; |
| 645 |
| 646 class NEONFormatDecoder { |
| 647 public: |
| 648 enum SubstitutionMode { kPlaceholder, kFormat }; |
| 649 |
| 650 // Construct a format decoder with increasingly specific format maps for each |
| 651 // substitution. If no format map is specified, the default is the integer |
| 652 // format map. |
| 653 explicit NEONFormatDecoder(const Instruction* instr); |
| 654 NEONFormatDecoder(const Instruction* instr, const NEONFormatMap* format); |
| 655 NEONFormatDecoder(const Instruction* instr, const NEONFormatMap* format0, |
| 656 const NEONFormatMap* format1); |
| 657 NEONFormatDecoder(const Instruction* instr, const NEONFormatMap* format0, |
| 658 const NEONFormatMap* format1, const NEONFormatMap* format2); |
| 659 |
| 660 // Set the format mapping for all or individual substitutions. |
| 661 void SetFormatMaps(const NEONFormatMap* format0, |
| 662 const NEONFormatMap* format1 = NULL, |
| 663 const NEONFormatMap* format2 = NULL); |
| 664 void SetFormatMap(unsigned index, const NEONFormatMap* format); |
| 665 |
| 666 // Substitute %s in the input string with the placeholder string for each |
| 667 // register, ie. "'B", "'H", etc. |
| 668 const char* SubstitutePlaceholders(const char* string); |
| 669 |
| 670 // Substitute %s in the input string with a new string based on the |
| 671 // substitution mode. |
| 672 const char* Substitute(const char* string, SubstitutionMode mode0 = kFormat, |
| 673 SubstitutionMode mode1 = kFormat, |
| 674 SubstitutionMode mode2 = kFormat); |
| 675 |
| 676 // Append a "2" to a mnemonic string based of the state of the Q bit. |
| 677 const char* Mnemonic(const char* mnemonic); |
| 678 |
| 679 VectorFormat GetVectorFormat(int format_index = 0); |
| 680 VectorFormat GetVectorFormat(const NEONFormatMap* format_map); |
| 681 |
| 682 // Built in mappings for common cases. |
| 683 |
| 684 // The integer format map uses three bits (Q, size<1:0>) to encode the |
| 685 // "standard" set of NEON integer vector formats. |
| 686 static const NEONFormatMap* IntegerFormatMap() { |
| 687 static const NEONFormatMap map = { |
| 688 {23, 22, 30}, |
| 689 {NF_8B, NF_16B, NF_4H, NF_8H, NF_2S, NF_4S, NF_UNDEF, NF_2D}}; |
| 690 return ↦ |
| 691 } |
| 692 |
| 693 // The long integer format map uses two bits (size<1:0>) to encode the |
| 694 // long set of NEON integer vector formats. These are used in narrow, wide |
| 695 // and long operations. |
| 696 static const NEONFormatMap* LongIntegerFormatMap() { |
| 697 static const NEONFormatMap map = {{23, 22}, {NF_8H, NF_4S, NF_2D}}; |
| 698 return ↦ |
| 699 } |
| 700 |
| 701 // The FP format map uses two bits (Q, size<0>) to encode the NEON FP vector |
| 702 // formats: NF_2S, NF_4S, NF_2D. |
| 703 static const NEONFormatMap* FPFormatMap() { |
| 704 // The FP format map assumes two bits (Q, size<0>) are used to encode the |
| 705 // NEON FP vector formats: NF_2S, NF_4S, NF_2D. |
| 706 static const NEONFormatMap map = {{22, 30}, |
| 707 {NF_2S, NF_4S, NF_UNDEF, NF_2D}}; |
| 708 return ↦ |
| 709 } |
| 710 |
| 711 // The load/store format map uses three bits (Q, 11, 10) to encode the |
| 712 // set of NEON vector formats. |
| 713 static const NEONFormatMap* LoadStoreFormatMap() { |
| 714 static const NEONFormatMap map = { |
| 715 {11, 10, 30}, |
| 716 {NF_8B, NF_16B, NF_4H, NF_8H, NF_2S, NF_4S, NF_1D, NF_2D}}; |
| 717 return ↦ |
| 718 } |
| 719 |
| 720 // The logical format map uses one bit (Q) to encode the NEON vector format: |
| 721 // NF_8B, NF_16B. |
| 722 static const NEONFormatMap* LogicalFormatMap() { |
| 723 static const NEONFormatMap map = {{30}, {NF_8B, NF_16B}}; |
| 724 return ↦ |
| 725 } |
| 726 |
| 727 // The triangular format map uses between two and five bits to encode the NEON |
| 728 // vector format: |
| 729 // xxx10->8B, xxx11->16B, xx100->4H, xx101->8H |
| 730 // x1000->2S, x1001->4S, 10001->2D, all others undefined. |
| 731 static const NEONFormatMap* TriangularFormatMap() { |
| 732 static const NEONFormatMap map = { |
| 733 {19, 18, 17, 16, 30}, |
| 734 {NF_UNDEF, NF_UNDEF, NF_8B, NF_16B, NF_4H, NF_8H, NF_8B, NF_16B, |
| 735 NF_2S, NF_4S, NF_8B, NF_16B, NF_4H, NF_8H, NF_8B, NF_16B, |
| 736 NF_UNDEF, NF_2D, NF_8B, NF_16B, NF_4H, NF_8H, NF_8B, NF_16B, |
| 737 NF_2S, NF_4S, NF_8B, NF_16B, NF_4H, NF_8H, NF_8B, NF_16B}}; |
| 738 return ↦ |
| 739 } |
| 740 |
| 741 // The scalar format map uses two bits (size<1:0>) to encode the NEON scalar |
| 742 // formats: NF_B, NF_H, NF_S, NF_D. |
| 743 static const NEONFormatMap* ScalarFormatMap() { |
| 744 static const NEONFormatMap map = {{23, 22}, {NF_B, NF_H, NF_S, NF_D}}; |
| 745 return ↦ |
| 746 } |
| 747 |
| 748 // The long scalar format map uses two bits (size<1:0>) to encode the longer |
| 749 // NEON scalar formats: NF_H, NF_S, NF_D. |
| 750 static const NEONFormatMap* LongScalarFormatMap() { |
| 751 static const NEONFormatMap map = {{23, 22}, {NF_H, NF_S, NF_D}}; |
| 752 return ↦ |
| 753 } |
| 754 |
| 755 // The FP scalar format map assumes one bit (size<0>) is used to encode the |
| 756 // NEON FP scalar formats: NF_S, NF_D. |
| 757 static const NEONFormatMap* FPScalarFormatMap() { |
| 758 static const NEONFormatMap map = {{22}, {NF_S, NF_D}}; |
| 759 return ↦ |
| 760 } |
| 761 |
| 762 // The triangular scalar format map uses between one and four bits to encode |
| 763 // the NEON FP scalar formats: |
| 764 // xxx1->B, xx10->H, x100->S, 1000->D, all others undefined. |
| 765 static const NEONFormatMap* TriangularScalarFormatMap() { |
| 766 static const NEONFormatMap map = { |
| 767 {19, 18, 17, 16}, |
| 768 {NF_UNDEF, NF_B, NF_H, NF_B, NF_S, NF_B, NF_H, NF_B, NF_D, NF_B, NF_H, |
| 769 NF_B, NF_S, NF_B, NF_H, NF_B}}; |
| 770 return ↦ |
| 771 } |
| 772 |
| 773 private: |
| 774 // Get a pointer to a string that represents the format or placeholder for |
| 775 // the specified substitution index, based on the format map and instruction. |
| 776 const char* GetSubstitute(int index, SubstitutionMode mode); |
| 777 |
| 778 // Get the NEONFormat enumerated value for bits obtained from the |
| 779 // instruction based on the specified format mapping. |
| 780 NEONFormat GetNEONFormat(const NEONFormatMap* format_map); |
| 781 |
| 782 // Convert a NEONFormat into a string. |
| 783 static const char* NEONFormatAsString(NEONFormat format); |
| 784 |
| 785 // Convert a NEONFormat into a register placeholder string. |
| 786 static const char* NEONFormatAsPlaceholder(NEONFormat format); |
| 787 |
| 788 // Select bits from instrbits_ defined by the bits array, concatenate them, |
| 789 // and return the value. |
| 790 uint8_t PickBits(const uint8_t bits[]); |
| 791 |
| 792 Instr instrbits_; |
| 793 const NEONFormatMap* formats_[3]; |
| 794 char form_buffer_[64]; |
| 795 char mne_buffer_[16]; |
| 796 }; |
536 } // namespace internal | 797 } // namespace internal |
537 } // namespace v8 | 798 } // namespace v8 |
538 | 799 |
539 | 800 |
540 #endif // V8_ARM64_INSTRUCTIONS_ARM64_H_ | 801 #endif // V8_ARM64_INSTRUCTIONS_ARM64_H_ |
OLD | NEW |