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/assembler.h" | 10 #include "src/assembler.h" |
11 #include "src/globals.h" | 11 #include "src/globals.h" |
12 #include "src/utils.h" | 12 #include "src/utils.h" |
13 | 13 |
14 namespace v8 { | 14 namespace v8 { |
15 namespace internal { | 15 namespace internal { |
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 216 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
410 } | 452 } |
411 | 453 |
412 | 454 |
413 static const int ImmPCRelRangeBitwidth = 21; | 455 static const int ImmPCRelRangeBitwidth = 21; |
414 static bool IsValidPCRelOffset(ptrdiff_t offset) { return is_int21(offset); } | 456 static bool IsValidPCRelOffset(ptrdiff_t offset) { return is_int21(offset); } |
415 void SetPCRelImmTarget(AssemblerBase::IsolateData isolate_data, | 457 void SetPCRelImmTarget(AssemblerBase::IsolateData isolate_data, |
416 Instruction* target); | 458 Instruction* target); |
417 void SetBranchImmTarget(Instruction* target); | 459 void SetBranchImmTarget(Instruction* target); |
418 }; | 460 }; |
419 | 461 |
| 462 // Functions for handling NEON vector format information. |
| 463 enum VectorFormat { |
| 464 kFormatUndefined = 0xffffffff, |
| 465 kFormat8B = NEON_8B, |
| 466 kFormat16B = NEON_16B, |
| 467 kFormat4H = NEON_4H, |
| 468 kFormat8H = NEON_8H, |
| 469 kFormat2S = NEON_2S, |
| 470 kFormat4S = NEON_4S, |
| 471 kFormat1D = NEON_1D, |
| 472 kFormat2D = NEON_2D, |
| 473 |
| 474 // Scalar formats. We add the scalar bit to distinguish between scalar and |
| 475 // vector enumerations; the bit is always set in the encoding of scalar ops |
| 476 // and always clear for vector ops. Although kFormatD and kFormat1D appear |
| 477 // to be the same, their meaning is subtly different. The first is a scalar |
| 478 // operation, the second a vector operation that only affects one lane. |
| 479 kFormatB = NEON_B | NEONScalar, |
| 480 kFormatH = NEON_H | NEONScalar, |
| 481 kFormatS = NEON_S | NEONScalar, |
| 482 kFormatD = NEON_D | NEONScalar |
| 483 }; |
| 484 |
| 485 VectorFormat VectorFormatHalfWidth(VectorFormat vform); |
| 486 VectorFormat VectorFormatDoubleWidth(VectorFormat vform); |
| 487 VectorFormat VectorFormatDoubleLanes(VectorFormat vform); |
| 488 VectorFormat VectorFormatHalfLanes(VectorFormat vform); |
| 489 VectorFormat ScalarFormatFromLaneSize(int lanesize); |
| 490 VectorFormat VectorFormatHalfWidthDoubleLanes(VectorFormat vform); |
| 491 VectorFormat VectorFormatFillQ(VectorFormat vform); |
| 492 VectorFormat ScalarFormatFromFormat(VectorFormat vform); |
| 493 unsigned RegisterSizeInBitsFromFormat(VectorFormat vform); |
| 494 unsigned RegisterSizeInBytesFromFormat(VectorFormat vform); |
| 495 int LaneSizeInBytesFromFormat(VectorFormat vform); |
| 496 unsigned LaneSizeInBitsFromFormat(VectorFormat vform); |
| 497 int LaneSizeInBytesLog2FromFormat(VectorFormat vform); |
| 498 int LaneCountFromFormat(VectorFormat vform); |
| 499 int MaxLaneCountFromFormat(VectorFormat vform); |
| 500 bool IsVectorFormat(VectorFormat vform); |
| 501 int64_t MaxIntFromFormat(VectorFormat vform); |
| 502 int64_t MinIntFromFormat(VectorFormat vform); |
| 503 uint64_t MaxUintFromFormat(VectorFormat vform); |
420 | 504 |
421 // Where Instruction looks at instructions generated by the Assembler, | 505 // Where Instruction looks at instructions generated by the Assembler, |
422 // InstructionSequence looks at instructions sequences generated by the | 506 // InstructionSequence looks at instructions sequences generated by the |
423 // MacroAssembler. | 507 // MacroAssembler. |
424 class InstructionSequence : public Instruction { | 508 class InstructionSequence : public Instruction { |
425 public: | 509 public: |
426 static InstructionSequence* At(Address address) { | 510 static InstructionSequence* At(Address address) { |
427 return reinterpret_cast<InstructionSequence*>(address); | 511 return reinterpret_cast<InstructionSequence*>(address); |
428 } | 512 } |
429 | 513 |
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
497 // Debug parameters. | 581 // Debug parameters. |
498 // Used without a TRACE_ option, the Debugger will print the arguments only | 582 // Used without a TRACE_ option, the Debugger will print the arguments only |
499 // once. Otherwise TRACE_ENABLE and TRACE_DISABLE will enable or disable tracing | 583 // once. Otherwise TRACE_ENABLE and TRACE_DISABLE will enable or disable tracing |
500 // before every instruction for the specified LOG_ parameters. | 584 // before every instruction for the specified LOG_ parameters. |
501 // | 585 // |
502 // TRACE_OVERRIDE enables the specified LOG_ parameters, and disabled any | 586 // TRACE_OVERRIDE enables the specified LOG_ parameters, and disabled any |
503 // others that were not specified. | 587 // others that were not specified. |
504 // | 588 // |
505 // For example: | 589 // For example: |
506 // | 590 // |
507 // __ debug("print registers and fp registers", 0, LOG_REGS | LOG_FP_REGS); | 591 // __ debug("print registers and fp registers", 0, LOG_REGS | LOG_VREGS); |
508 // will print the registers and fp registers only once. | 592 // will print the registers and fp registers only once. |
509 // | 593 // |
510 // __ debug("trace disasm", 1, TRACE_ENABLE | LOG_DISASM); | 594 // __ debug("trace disasm", 1, TRACE_ENABLE | LOG_DISASM); |
511 // starts disassembling the code. | 595 // starts disassembling the code. |
512 // | 596 // |
513 // __ debug("trace rets", 2, TRACE_ENABLE | LOG_REGS); | 597 // __ debug("trace rets", 2, TRACE_ENABLE | LOG_REGS); |
514 // adds the general purpose registers to the trace. | 598 // adds the general purpose registers to the trace. |
515 // | 599 // |
516 // __ debug("stop regs", 3, TRACE_DISABLE | LOG_REGS); | 600 // __ debug("stop regs", 3, TRACE_DISABLE | LOG_REGS); |
517 // stops tracing the registers. | 601 // stops tracing the registers. |
518 const unsigned kDebuggerTracingDirectivesMask = 3 << 6; | 602 const unsigned kDebuggerTracingDirectivesMask = 3 << 6; |
519 enum DebugParameters { | 603 enum DebugParameters { |
520 NO_PARAM = 0, | 604 NO_PARAM = 0, |
521 BREAK = 1 << 0, | 605 BREAK = 1 << 0, |
522 LOG_DISASM = 1 << 1, // Use only with TRACE. Disassemble the code. | 606 LOG_DISASM = 1 << 1, // Use only with TRACE. Disassemble the code. |
523 LOG_REGS = 1 << 2, // Log general purpose registers. | 607 LOG_REGS = 1 << 2, // Log general purpose registers. |
524 LOG_FP_REGS = 1 << 3, // Log floating-point registers. | 608 LOG_VREGS = 1 << 3, // Log NEON and floating-point registers. |
525 LOG_SYS_REGS = 1 << 4, // Log the status flags. | 609 LOG_SYS_REGS = 1 << 4, // Log the status flags. |
526 LOG_WRITE = 1 << 5, // Log any memory write. | 610 LOG_WRITE = 1 << 5, // Log any memory write. |
527 | 611 |
528 LOG_STATE = LOG_REGS | LOG_FP_REGS | LOG_SYS_REGS, | 612 LOG_NONE = 0, |
529 LOG_ALL = LOG_DISASM | LOG_STATE | LOG_WRITE, | 613 LOG_STATE = LOG_REGS | LOG_VREGS | LOG_SYS_REGS, |
| 614 LOG_ALL = LOG_DISASM | LOG_STATE | LOG_WRITE, |
530 | 615 |
531 // Trace control. | 616 // Trace control. |
532 TRACE_ENABLE = 1 << 6, | 617 TRACE_ENABLE = 1 << 6, |
533 TRACE_DISABLE = 2 << 6, | 618 TRACE_DISABLE = 2 << 6, |
534 TRACE_OVERRIDE = 3 << 6 | 619 TRACE_OVERRIDE = 3 << 6 |
535 }; | 620 }; |
536 | 621 |
537 | 622 enum NEONFormat { |
| 623 NF_UNDEF = 0, |
| 624 NF_8B = 1, |
| 625 NF_16B = 2, |
| 626 NF_4H = 3, |
| 627 NF_8H = 4, |
| 628 NF_2S = 5, |
| 629 NF_4S = 6, |
| 630 NF_1D = 7, |
| 631 NF_2D = 8, |
| 632 NF_B = 9, |
| 633 NF_H = 10, |
| 634 NF_S = 11, |
| 635 NF_D = 12 |
| 636 }; |
| 637 |
| 638 static const unsigned kNEONFormatMaxBits = 6; |
| 639 |
| 640 struct NEONFormatMap { |
| 641 // The bit positions in the instruction to consider. |
| 642 uint8_t bits[kNEONFormatMaxBits]; |
| 643 |
| 644 // Mapping from concatenated bits to format. |
| 645 NEONFormat map[1 << kNEONFormatMaxBits]; |
| 646 }; |
| 647 |
| 648 class NEONFormatDecoder { |
| 649 public: |
| 650 enum SubstitutionMode { kPlaceholder, kFormat }; |
| 651 |
| 652 // Construct a format decoder with increasingly specific format maps for each |
| 653 // substitution. If no format map is specified, the default is the integer |
| 654 // format map. |
| 655 explicit NEONFormatDecoder(const Instruction* instr); |
| 656 NEONFormatDecoder(const Instruction* instr, const NEONFormatMap* format); |
| 657 NEONFormatDecoder(const Instruction* instr, const NEONFormatMap* format0, |
| 658 const NEONFormatMap* format1); |
| 659 NEONFormatDecoder(const Instruction* instr, const NEONFormatMap* format0, |
| 660 const NEONFormatMap* format1, const NEONFormatMap* format2); |
| 661 |
| 662 // Set the format mapping for all or individual substitutions. |
| 663 void SetFormatMaps(const NEONFormatMap* format0, |
| 664 const NEONFormatMap* format1 = NULL, |
| 665 const NEONFormatMap* format2 = NULL); |
| 666 void SetFormatMap(unsigned index, const NEONFormatMap* format); |
| 667 |
| 668 // Substitute %s in the input string with the placeholder string for each |
| 669 // register, ie. "'B", "'H", etc. |
| 670 const char* SubstitutePlaceholders(const char* string); |
| 671 |
| 672 // Substitute %s in the input string with a new string based on the |
| 673 // substitution mode. |
| 674 const char* Substitute(const char* string, SubstitutionMode mode0 = kFormat, |
| 675 SubstitutionMode mode1 = kFormat, |
| 676 SubstitutionMode mode2 = kFormat); |
| 677 |
| 678 // Append a "2" to a mnemonic string based of the state of the Q bit. |
| 679 const char* Mnemonic(const char* mnemonic); |
| 680 |
| 681 VectorFormat GetVectorFormat(int format_index = 0); |
| 682 VectorFormat GetVectorFormat(const NEONFormatMap* format_map); |
| 683 |
| 684 // Built in mappings for common cases. |
| 685 |
| 686 // The integer format map uses three bits (Q, size<1:0>) to encode the |
| 687 // "standard" set of NEON integer vector formats. |
| 688 static const NEONFormatMap* IntegerFormatMap() { |
| 689 static const NEONFormatMap map = { |
| 690 {23, 22, 30}, |
| 691 {NF_8B, NF_16B, NF_4H, NF_8H, NF_2S, NF_4S, NF_UNDEF, NF_2D}}; |
| 692 return ↦ |
| 693 } |
| 694 |
| 695 // The long integer format map uses two bits (size<1:0>) to encode the |
| 696 // long set of NEON integer vector formats. These are used in narrow, wide |
| 697 // and long operations. |
| 698 static const NEONFormatMap* LongIntegerFormatMap() { |
| 699 static const NEONFormatMap map = {{23, 22}, {NF_8H, NF_4S, NF_2D}}; |
| 700 return ↦ |
| 701 } |
| 702 |
| 703 // The FP format map uses two bits (Q, size<0>) to encode the NEON FP vector |
| 704 // formats: NF_2S, NF_4S, NF_2D. |
| 705 static const NEONFormatMap* FPFormatMap() { |
| 706 // The FP format map assumes two bits (Q, size<0>) are used to encode the |
| 707 // NEON FP vector formats: NF_2S, NF_4S, NF_2D. |
| 708 static const NEONFormatMap map = {{22, 30}, |
| 709 {NF_2S, NF_4S, NF_UNDEF, NF_2D}}; |
| 710 return ↦ |
| 711 } |
| 712 |
| 713 // The load/store format map uses three bits (Q, 11, 10) to encode the |
| 714 // set of NEON vector formats. |
| 715 static const NEONFormatMap* LoadStoreFormatMap() { |
| 716 static const NEONFormatMap map = { |
| 717 {11, 10, 30}, |
| 718 {NF_8B, NF_16B, NF_4H, NF_8H, NF_2S, NF_4S, NF_1D, NF_2D}}; |
| 719 return ↦ |
| 720 } |
| 721 |
| 722 // The logical format map uses one bit (Q) to encode the NEON vector format: |
| 723 // NF_8B, NF_16B. |
| 724 static const NEONFormatMap* LogicalFormatMap() { |
| 725 static const NEONFormatMap map = {{30}, {NF_8B, NF_16B}}; |
| 726 return ↦ |
| 727 } |
| 728 |
| 729 // The triangular format map uses between two and five bits to encode the NEON |
| 730 // vector format: |
| 731 // xxx10->8B, xxx11->16B, xx100->4H, xx101->8H |
| 732 // x1000->2S, x1001->4S, 10001->2D, all others undefined. |
| 733 static const NEONFormatMap* TriangularFormatMap() { |
| 734 static const NEONFormatMap map = { |
| 735 {19, 18, 17, 16, 30}, |
| 736 {NF_UNDEF, NF_UNDEF, 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 NF_UNDEF, NF_2D, NF_8B, NF_16B, NF_4H, NF_8H, NF_8B, NF_16B, |
| 739 NF_2S, NF_4S, NF_8B, NF_16B, NF_4H, NF_8H, NF_8B, NF_16B}}; |
| 740 return ↦ |
| 741 } |
| 742 |
| 743 // The scalar format map uses two bits (size<1:0>) to encode the NEON scalar |
| 744 // formats: NF_B, NF_H, NF_S, NF_D. |
| 745 static const NEONFormatMap* ScalarFormatMap() { |
| 746 static const NEONFormatMap map = {{23, 22}, {NF_B, NF_H, NF_S, NF_D}}; |
| 747 return ↦ |
| 748 } |
| 749 |
| 750 // The long scalar format map uses two bits (size<1:0>) to encode the longer |
| 751 // NEON scalar formats: NF_H, NF_S, NF_D. |
| 752 static const NEONFormatMap* LongScalarFormatMap() { |
| 753 static const NEONFormatMap map = {{23, 22}, {NF_H, NF_S, NF_D}}; |
| 754 return ↦ |
| 755 } |
| 756 |
| 757 // The FP scalar format map assumes one bit (size<0>) is used to encode the |
| 758 // NEON FP scalar formats: NF_S, NF_D. |
| 759 static const NEONFormatMap* FPScalarFormatMap() { |
| 760 static const NEONFormatMap map = {{22}, {NF_S, NF_D}}; |
| 761 return ↦ |
| 762 } |
| 763 |
| 764 // The triangular scalar format map uses between one and four bits to encode |
| 765 // the NEON FP scalar formats: |
| 766 // xxx1->B, xx10->H, x100->S, 1000->D, all others undefined. |
| 767 static const NEONFormatMap* TriangularScalarFormatMap() { |
| 768 static const NEONFormatMap map = { |
| 769 {19, 18, 17, 16}, |
| 770 {NF_UNDEF, NF_B, NF_H, NF_B, NF_S, NF_B, NF_H, NF_B, NF_D, NF_B, NF_H, |
| 771 NF_B, NF_S, NF_B, NF_H, NF_B}}; |
| 772 return ↦ |
| 773 } |
| 774 |
| 775 private: |
| 776 // Get a pointer to a string that represents the format or placeholder for |
| 777 // the specified substitution index, based on the format map and instruction. |
| 778 const char* GetSubstitute(int index, SubstitutionMode mode); |
| 779 |
| 780 // Get the NEONFormat enumerated value for bits obtained from the |
| 781 // instruction based on the specified format mapping. |
| 782 NEONFormat GetNEONFormat(const NEONFormatMap* format_map); |
| 783 |
| 784 // Convert a NEONFormat into a string. |
| 785 static const char* NEONFormatAsString(NEONFormat format); |
| 786 |
| 787 // Convert a NEONFormat into a register placeholder string. |
| 788 static const char* NEONFormatAsPlaceholder(NEONFormat format); |
| 789 |
| 790 // Select bits from instrbits_ defined by the bits array, concatenate them, |
| 791 // and return the value. |
| 792 uint8_t PickBits(const uint8_t bits[]); |
| 793 |
| 794 Instr instrbits_; |
| 795 const NEONFormatMap* formats_[3]; |
| 796 char form_buffer_[64]; |
| 797 char mne_buffer_[16]; |
| 798 }; |
538 } // namespace internal | 799 } // namespace internal |
539 } // namespace v8 | 800 } // namespace v8 |
540 | 801 |
541 | 802 |
542 #endif // V8_ARM64_INSTRUCTIONS_ARM64_H_ | 803 #endif // V8_ARM64_INSTRUCTIONS_ARM64_H_ |
OLD | NEW |