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 | |
27 #define DEFINE_FLOAT(name, value) extern const uint32_t name = value | 26 #define DEFINE_FLOAT(name, value) extern const uint32_t name = value |
28 #define DEFINE_DOUBLE(name, value) extern const uint64_t name = value | 27 #define DEFINE_DOUBLE(name, value) extern const uint64_t name = value |
29 #else | 28 #else |
30 #define DEFINE_FLOAT16(name, value) extern const float16 name | |
31 #define DEFINE_FLOAT(name, value) extern const float name | 29 #define DEFINE_FLOAT(name, value) extern const float name |
32 #define DEFINE_DOUBLE(name, value) extern const double name | 30 #define DEFINE_DOUBLE(name, value) extern const double name |
33 #endif // defined(ARM64_DEFINE_FP_STATICS) | 31 #endif // defined(ARM64_DEFINE_FP_STATICS) |
34 | 32 |
35 DEFINE_FLOAT16(kFP16PositiveInfinity, 0x7c00); | |
36 DEFINE_FLOAT16(kFP16NegativeInfinity, 0xfc00); | |
37 DEFINE_FLOAT(kFP32PositiveInfinity, 0x7f800000); | 33 DEFINE_FLOAT(kFP32PositiveInfinity, 0x7f800000); |
38 DEFINE_FLOAT(kFP32NegativeInfinity, 0xff800000); | 34 DEFINE_FLOAT(kFP32NegativeInfinity, 0xff800000); |
39 DEFINE_DOUBLE(kFP64PositiveInfinity, 0x7ff0000000000000UL); | 35 DEFINE_DOUBLE(kFP64PositiveInfinity, 0x7ff0000000000000UL); |
40 DEFINE_DOUBLE(kFP64NegativeInfinity, 0xfff0000000000000UL); | 36 DEFINE_DOUBLE(kFP64NegativeInfinity, 0xfff0000000000000UL); |
41 | 37 |
42 // This value is a signalling NaN as both a double and as a float (taking the | 38 // This value is a signalling NaN as both a double and as a float (taking the |
43 // least-significant word). | 39 // least-significant word). |
44 DEFINE_DOUBLE(kFP64SignallingNaN, 0x7ff000007f800001); | 40 DEFINE_DOUBLE(kFP64SignallingNaN, 0x7ff000007f800001); |
45 DEFINE_FLOAT(kFP32SignallingNaN, 0x7f800001); | 41 DEFINE_FLOAT(kFP32SignallingNaN, 0x7f800001); |
46 | 42 |
47 // A similar value, but as a quiet NaN. | 43 // A similar value, but as a quiet NaN. |
48 DEFINE_DOUBLE(kFP64QuietNaN, 0x7ff800007fc00001); | 44 DEFINE_DOUBLE(kFP64QuietNaN, 0x7ff800007fc00001); |
49 DEFINE_FLOAT(kFP32QuietNaN, 0x7fc00001); | 45 DEFINE_FLOAT(kFP32QuietNaN, 0x7fc00001); |
50 | 46 |
51 // The default NaN values (for FPCR.DN=1). | 47 // The default NaN values (for FPCR.DN=1). |
52 DEFINE_DOUBLE(kFP64DefaultNaN, 0x7ff8000000000000UL); | 48 DEFINE_DOUBLE(kFP64DefaultNaN, 0x7ff8000000000000UL); |
53 DEFINE_FLOAT(kFP32DefaultNaN, 0x7fc00000); | 49 DEFINE_FLOAT(kFP32DefaultNaN, 0x7fc00000); |
54 DEFINE_FLOAT16(kFP16DefaultNaN, 0x7e00); | |
55 | 50 |
56 #undef DEFINE_FLOAT16 | |
57 #undef DEFINE_FLOAT | 51 #undef DEFINE_FLOAT |
58 #undef DEFINE_DOUBLE | 52 #undef DEFINE_DOUBLE |
59 | 53 |
60 unsigned CalcLSDataSize(LoadStoreOp op); | 54 |
61 unsigned CalcLSPairDataSize(LoadStorePairOp op); | 55 enum LSDataSize { |
| 56 LSByte = 0, |
| 57 LSHalfword = 1, |
| 58 LSWord = 2, |
| 59 LSDoubleWord = 3 |
| 60 }; |
| 61 |
| 62 LSDataSize CalcLSPairDataSize(LoadStorePairOp op); |
62 | 63 |
63 enum ImmBranchType { | 64 enum ImmBranchType { |
64 UnknownBranchType = 0, | 65 UnknownBranchType = 0, |
65 CondBranchType = 1, | 66 CondBranchType = 1, |
66 UncondBranchType = 2, | 67 UncondBranchType = 2, |
67 CompareBranchType = 3, | 68 CompareBranchType = 3, |
68 TestBranchType = 4 | 69 TestBranchType = 4 |
69 }; | 70 }; |
70 | 71 |
71 enum AddrMode { | 72 enum AddrMode { |
72 Offset, | 73 Offset, |
73 PreIndex, | 74 PreIndex, |
74 PostIndex | 75 PostIndex |
75 }; | 76 }; |
76 | 77 |
77 enum FPRounding { | 78 enum FPRounding { |
78 // The first four values are encodable directly by FPCR<RMode>. | 79 // The first four values are encodable directly by FPCR<RMode>. |
79 FPTieEven = 0x0, | 80 FPTieEven = 0x0, |
80 FPPositiveInfinity = 0x1, | 81 FPPositiveInfinity = 0x1, |
81 FPNegativeInfinity = 0x2, | 82 FPNegativeInfinity = 0x2, |
82 FPZero = 0x3, | 83 FPZero = 0x3, |
83 | 84 |
84 // The final rounding modes are only available when explicitly specified by | 85 // The final rounding mode is only available when explicitly specified by the |
85 // the instruction (such as with fcvta). They cannot be set in FPCR. | 86 // instruction (such as with fcvta). It cannot be set in FPCR. |
86 FPTieAway, | 87 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; | |
156 float ImmFP32(); | 155 float ImmFP32(); |
157 double ImmFP64(); | 156 double ImmFP64(); |
158 float ImmNEONFP32() const; | |
159 double ImmNEONFP64() const; | |
160 | 157 |
161 unsigned SizeLS() const { | 158 LSDataSize SizeLSPair() const { |
162 return CalcLSDataSize(static_cast<LoadStoreOp>(Mask(LoadStoreMask))); | |
163 } | |
164 | |
165 unsigned SizeLSPair() const { | |
166 return CalcLSPairDataSize( | 159 return CalcLSPairDataSize( |
167 static_cast<LoadStorePairOp>(Mask(LoadStorePairMask))); | 160 static_cast<LoadStorePairOp>(Mask(LoadStorePairMask))); |
168 } | 161 } |
169 | 162 |
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 | |
178 // Helpers. | 163 // Helpers. |
179 bool IsCondBranchImm() const { | 164 bool IsCondBranchImm() const { |
180 return Mask(ConditionalBranchFMask) == ConditionalBranchFixed; | 165 return Mask(ConditionalBranchFMask) == ConditionalBranchFixed; |
181 } | 166 } |
182 | 167 |
183 bool IsUncondBranchImm() const { | 168 bool IsUncondBranchImm() const { |
184 return Mask(UnconditionalBranchFMask) == UnconditionalBranchFixed; | 169 return Mask(UnconditionalBranchFMask) == UnconditionalBranchFixed; |
185 } | 170 } |
186 | 171 |
187 bool IsCompareBranch() const { | 172 bool IsCompareBranch() const { |
188 return Mask(CompareBranchFMask) == CompareBranchFixed; | 173 return Mask(CompareBranchFMask) == CompareBranchFixed; |
189 } | 174 } |
190 | 175 |
191 bool IsTestBranch() const { | 176 bool IsTestBranch() const { |
192 return Mask(TestBranchFMask) == TestBranchFixed; | 177 return Mask(TestBranchFMask) == TestBranchFixed; |
193 } | 178 } |
194 | 179 |
195 bool IsImmBranch() const { | 180 bool IsImmBranch() const { |
196 return BranchType() != UnknownBranchType; | 181 return BranchType() != UnknownBranchType; |
197 } | 182 } |
198 | 183 |
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 | |
226 bool IsLdrLiteral() const { | 184 bool IsLdrLiteral() const { |
227 return Mask(LoadLiteralFMask) == LoadLiteralFixed; | 185 return Mask(LoadLiteralFMask) == LoadLiteralFixed; |
228 } | 186 } |
229 | 187 |
230 bool IsLdrLiteralX() const { | 188 bool IsLdrLiteralX() const { |
231 return Mask(LoadLiteralMask) == LDR_x_lit; | 189 return Mask(LoadLiteralMask) == LDR_x_lit; |
232 } | 190 } |
233 | 191 |
234 bool IsPCRelAddressing() const { | 192 bool IsPCRelAddressing() const { |
235 return Mask(PCRelAddressingFMask) == PCRelAddressingFixed; | 193 return Mask(PCRelAddressingFMask) == PCRelAddressingFixed; |
(...skipping 216 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
452 } | 410 } |
453 | 411 |
454 | 412 |
455 static const int ImmPCRelRangeBitwidth = 21; | 413 static const int ImmPCRelRangeBitwidth = 21; |
456 static bool IsValidPCRelOffset(ptrdiff_t offset) { return is_int21(offset); } | 414 static bool IsValidPCRelOffset(ptrdiff_t offset) { return is_int21(offset); } |
457 void SetPCRelImmTarget(AssemblerBase::IsolateData isolate_data, | 415 void SetPCRelImmTarget(AssemblerBase::IsolateData isolate_data, |
458 Instruction* target); | 416 Instruction* target); |
459 void SetBranchImmTarget(Instruction* target); | 417 void SetBranchImmTarget(Instruction* target); |
460 }; | 418 }; |
461 | 419 |
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); | |
504 | 420 |
505 // Where Instruction looks at instructions generated by the Assembler, | 421 // Where Instruction looks at instructions generated by the Assembler, |
506 // InstructionSequence looks at instructions sequences generated by the | 422 // InstructionSequence looks at instructions sequences generated by the |
507 // MacroAssembler. | 423 // MacroAssembler. |
508 class InstructionSequence : public Instruction { | 424 class InstructionSequence : public Instruction { |
509 public: | 425 public: |
510 static InstructionSequence* At(Address address) { | 426 static InstructionSequence* At(Address address) { |
511 return reinterpret_cast<InstructionSequence*>(address); | 427 return reinterpret_cast<InstructionSequence*>(address); |
512 } | 428 } |
513 | 429 |
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
581 // Debug parameters. | 497 // Debug parameters. |
582 // Used without a TRACE_ option, the Debugger will print the arguments only | 498 // Used without a TRACE_ option, the Debugger will print the arguments only |
583 // once. Otherwise TRACE_ENABLE and TRACE_DISABLE will enable or disable tracing | 499 // once. Otherwise TRACE_ENABLE and TRACE_DISABLE will enable or disable tracing |
584 // before every instruction for the specified LOG_ parameters. | 500 // before every instruction for the specified LOG_ parameters. |
585 // | 501 // |
586 // TRACE_OVERRIDE enables the specified LOG_ parameters, and disabled any | 502 // TRACE_OVERRIDE enables the specified LOG_ parameters, and disabled any |
587 // others that were not specified. | 503 // others that were not specified. |
588 // | 504 // |
589 // For example: | 505 // For example: |
590 // | 506 // |
591 // __ debug("print registers and fp registers", 0, LOG_REGS | LOG_VREGS); | 507 // __ debug("print registers and fp registers", 0, LOG_REGS | LOG_FP_REGS); |
592 // will print the registers and fp registers only once. | 508 // will print the registers and fp registers only once. |
593 // | 509 // |
594 // __ debug("trace disasm", 1, TRACE_ENABLE | LOG_DISASM); | 510 // __ debug("trace disasm", 1, TRACE_ENABLE | LOG_DISASM); |
595 // starts disassembling the code. | 511 // starts disassembling the code. |
596 // | 512 // |
597 // __ debug("trace rets", 2, TRACE_ENABLE | LOG_REGS); | 513 // __ debug("trace rets", 2, TRACE_ENABLE | LOG_REGS); |
598 // adds the general purpose registers to the trace. | 514 // adds the general purpose registers to the trace. |
599 // | 515 // |
600 // __ debug("stop regs", 3, TRACE_DISABLE | LOG_REGS); | 516 // __ debug("stop regs", 3, TRACE_DISABLE | LOG_REGS); |
601 // stops tracing the registers. | 517 // stops tracing the registers. |
602 const unsigned kDebuggerTracingDirectivesMask = 3 << 6; | 518 const unsigned kDebuggerTracingDirectivesMask = 3 << 6; |
603 enum DebugParameters { | 519 enum DebugParameters { |
604 NO_PARAM = 0, | 520 NO_PARAM = 0, |
605 BREAK = 1 << 0, | 521 BREAK = 1 << 0, |
606 LOG_DISASM = 1 << 1, // Use only with TRACE. Disassemble the code. | 522 LOG_DISASM = 1 << 1, // Use only with TRACE. Disassemble the code. |
607 LOG_REGS = 1 << 2, // Log general purpose registers. | 523 LOG_REGS = 1 << 2, // Log general purpose registers. |
608 LOG_VREGS = 1 << 3, // Log NEON and floating-point registers. | 524 LOG_FP_REGS = 1 << 3, // Log floating-point registers. |
609 LOG_SYS_REGS = 1 << 4, // Log the status flags. | 525 LOG_SYS_REGS = 1 << 4, // Log the status flags. |
610 LOG_WRITE = 1 << 5, // Log any memory write. | 526 LOG_WRITE = 1 << 5, // Log any memory write. |
611 | 527 |
612 LOG_NONE = 0, | 528 LOG_STATE = LOG_REGS | LOG_FP_REGS | LOG_SYS_REGS, |
613 LOG_STATE = LOG_REGS | LOG_VREGS | LOG_SYS_REGS, | 529 LOG_ALL = LOG_DISASM | LOG_STATE | LOG_WRITE, |
614 LOG_ALL = LOG_DISASM | LOG_STATE | LOG_WRITE, | |
615 | 530 |
616 // Trace control. | 531 // Trace control. |
617 TRACE_ENABLE = 1 << 6, | 532 TRACE_ENABLE = 1 << 6, |
618 TRACE_DISABLE = 2 << 6, | 533 TRACE_DISABLE = 2 << 6, |
619 TRACE_OVERRIDE = 3 << 6 | 534 TRACE_OVERRIDE = 3 << 6 |
620 }; | 535 }; |
621 | 536 |
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 | 537 |
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 }; | |
799 } // namespace internal | 538 } // namespace internal |
800 } // namespace v8 | 539 } // namespace v8 |
801 | 540 |
802 | 541 |
803 #endif // V8_ARM64_INSTRUCTIONS_ARM64_H_ | 542 #endif // V8_ARM64_INSTRUCTIONS_ARM64_H_ |
OLD | NEW |