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 const int kMaxLanesPerVector = 16; | |
bbudge
2017/01/31 01:41:31
It seems kind of random to have this here. Could t
martyn.capewell
2017/02/03 11:01:31
Done.
| |
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); | |
418 | 504 |
419 // Where Instruction looks at instructions generated by the Assembler, | 505 // Where Instruction looks at instructions generated by the Assembler, |
420 // InstructionSequence looks at instructions sequences generated by the | 506 // InstructionSequence looks at instructions sequences generated by the |
421 // MacroAssembler. | 507 // MacroAssembler. |
422 class InstructionSequence : public Instruction { | 508 class InstructionSequence : public Instruction { |
423 public: | 509 public: |
424 static InstructionSequence* At(Address address) { | 510 static InstructionSequence* At(Address address) { |
425 return reinterpret_cast<InstructionSequence*>(address); | 511 return reinterpret_cast<InstructionSequence*>(address); |
426 } | 512 } |
427 | 513 |
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
495 // Debug parameters. | 581 // Debug parameters. |
496 // 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 |
497 // 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 |
498 // before every instruction for the specified LOG_ parameters. | 584 // before every instruction for the specified LOG_ parameters. |
499 // | 585 // |
500 // TRACE_OVERRIDE enables the specified LOG_ parameters, and disabled any | 586 // TRACE_OVERRIDE enables the specified LOG_ parameters, and disabled any |
501 // others that were not specified. | 587 // others that were not specified. |
502 // | 588 // |
503 // For example: | 589 // For example: |
504 // | 590 // |
505 // __ debug("print registers and fp registers", 0, LOG_REGS | LOG_FP_REGS); | 591 // __ debug("print registers and fp registers", 0, LOG_REGS | LOG_VREGS); |
506 // will print the registers and fp registers only once. | 592 // will print the registers and fp registers only once. |
507 // | 593 // |
508 // __ debug("trace disasm", 1, TRACE_ENABLE | LOG_DISASM); | 594 // __ debug("trace disasm", 1, TRACE_ENABLE | LOG_DISASM); |
509 // starts disassembling the code. | 595 // starts disassembling the code. |
510 // | 596 // |
511 // __ debug("trace rets", 2, TRACE_ENABLE | LOG_REGS); | 597 // __ debug("trace rets", 2, TRACE_ENABLE | LOG_REGS); |
512 // adds the general purpose registers to the trace. | 598 // adds the general purpose registers to the trace. |
513 // | 599 // |
514 // __ debug("stop regs", 3, TRACE_DISABLE | LOG_REGS); | 600 // __ debug("stop regs", 3, TRACE_DISABLE | LOG_REGS); |
515 // stops tracing the registers. | 601 // stops tracing the registers. |
516 const unsigned kDebuggerTracingDirectivesMask = 3 << 6; | 602 const unsigned kDebuggerTracingDirectivesMask = 3 << 6; |
517 enum DebugParameters { | 603 enum DebugParameters { |
518 NO_PARAM = 0, | 604 NO_PARAM = 0, |
519 BREAK = 1 << 0, | 605 BREAK = 1 << 0, |
520 LOG_DISASM = 1 << 1, // Use only with TRACE. Disassemble the code. | 606 LOG_DISASM = 1 << 1, // Use only with TRACE. Disassemble the code. |
521 LOG_REGS = 1 << 2, // Log general purpose registers. | 607 LOG_REGS = 1 << 2, // Log general purpose registers. |
522 LOG_FP_REGS = 1 << 3, // Log floating-point registers. | 608 LOG_VREGS = 1 << 3, // Log NEON and floating-point registers. |
523 LOG_SYS_REGS = 1 << 4, // Log the status flags. | 609 LOG_SYS_REGS = 1 << 4, // Log the status flags. |
524 LOG_WRITE = 1 << 5, // Log any memory write. | 610 LOG_WRITE = 1 << 5, // Log any memory write. |
525 | 611 |
526 LOG_STATE = LOG_REGS | LOG_FP_REGS | LOG_SYS_REGS, | 612 LOG_NONE = 0, |
527 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, | |
528 | 615 |
529 // Trace control. | 616 // Trace control. |
530 TRACE_ENABLE = 1 << 6, | 617 TRACE_ENABLE = 1 << 6, |
531 TRACE_DISABLE = 2 << 6, | 618 TRACE_DISABLE = 2 << 6, |
532 TRACE_OVERRIDE = 3 << 6 | 619 TRACE_OVERRIDE = 3 << 6 |
533 }; | 620 }; |
534 | 621 |
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 { | |
bbudge
2017/01/31 01:41:31
Is there a reason so much of this class is defined
martyn.capewell
2017/02/03 11:01:31
I've moved all but the default format maps out of
| |
649 public: | |
650 enum SubstitutionMode { kPlaceholder, kFormat }; | |
651 | |
652 // Construct a format decoder with increasingly specific format maps for each | |
653 // subsitution. If no format map is specified, the default is the integer | |
654 // format map. | |
655 explicit NEONFormatDecoder(const Instruction* instr) { | |
656 instrbits_ = instr->InstructionBits(); | |
657 SetFormatMaps(IntegerFormatMap()); | |
658 } | |
659 NEONFormatDecoder(const Instruction* instr, const NEONFormatMap* format) { | |
660 instrbits_ = instr->InstructionBits(); | |
661 SetFormatMaps(format); | |
662 } | |
663 NEONFormatDecoder(const Instruction* instr, const NEONFormatMap* format0, | |
664 const NEONFormatMap* format1) { | |
665 instrbits_ = instr->InstructionBits(); | |
666 SetFormatMaps(format0, format1); | |
667 } | |
668 NEONFormatDecoder(const Instruction* instr, const NEONFormatMap* format0, | |
669 const NEONFormatMap* format1, | |
670 const NEONFormatMap* format2) { | |
671 instrbits_ = instr->InstructionBits(); | |
672 SetFormatMaps(format0, format1, format2); | |
673 } | |
674 | |
675 // Set the format mapping for all or individual substitutions. | |
676 void SetFormatMaps(const NEONFormatMap* format0, | |
677 const NEONFormatMap* format1 = NULL, | |
678 const NEONFormatMap* format2 = NULL) { | |
679 DCHECK_NOT_NULL(format0); | |
680 formats_[0] = format0; | |
681 formats_[1] = (format1 == NULL) ? formats_[0] : format1; | |
682 formats_[2] = (format2 == NULL) ? formats_[1] : format2; | |
683 } | |
684 void SetFormatMap(unsigned index, const NEONFormatMap* format) { | |
685 DCHECK_LT(index, arraysize(formats_)); | |
686 DCHECK_NOT_NULL(format); | |
687 formats_[index] = format; | |
688 } | |
689 | |
690 // Substitute %s in the input string with the placeholder string for each | |
691 // register, ie. "'B", "'H", etc. | |
692 const char* SubstitutePlaceholders(const char* string) { | |
693 return Substitute(string, kPlaceholder, kPlaceholder, kPlaceholder); | |
694 } | |
695 | |
696 // Substitute %s in the input string with a new string based on the | |
697 // substitution mode. | |
698 const char* Substitute(const char* string, SubstitutionMode mode0 = kFormat, | |
699 SubstitutionMode mode1 = kFormat, | |
700 SubstitutionMode mode2 = kFormat) { | |
701 snprintf(form_buffer_, sizeof(form_buffer_), string, | |
702 GetSubstitute(0, mode0), GetSubstitute(1, mode1), | |
703 GetSubstitute(2, mode2)); | |
704 return form_buffer_; | |
705 } | |
706 | |
707 // Append a "2" to a mnemonic string based of the state of the Q bit. | |
708 const char* Mnemonic(const char* mnemonic) { | |
709 if ((instrbits_ & NEON_Q) != 0) { | |
710 snprintf(mne_buffer_, sizeof(mne_buffer_), "%s2", mnemonic); | |
711 return mne_buffer_; | |
712 } | |
713 return mnemonic; | |
714 } | |
715 | |
716 VectorFormat GetVectorFormat(int format_index = 0) { | |
717 return GetVectorFormat(formats_[format_index]); | |
718 } | |
719 | |
720 VectorFormat GetVectorFormat(const NEONFormatMap* format_map) { | |
721 static const VectorFormat vform[] = { | |
722 kFormatUndefined, kFormat8B, kFormat16B, kFormat4H, kFormat8H, | |
723 kFormat2S, kFormat4S, kFormat1D, kFormat2D, kFormatB, | |
724 kFormatH, kFormatS, kFormatD}; | |
725 DCHECK_LT(GetNEONFormat(format_map), arraysize(vform)); | |
726 return vform[GetNEONFormat(format_map)]; | |
727 } | |
728 | |
729 // Built in mappings for common cases. | |
730 | |
731 // The integer format map uses three bits (Q, size<1:0>) to encode the | |
732 // "standard" set of NEON integer vector formats. | |
733 static const NEONFormatMap* IntegerFormatMap() { | |
734 static const NEONFormatMap map = { | |
735 {23, 22, 30}, | |
736 {NF_8B, NF_16B, NF_4H, NF_8H, NF_2S, NF_4S, NF_UNDEF, NF_2D}}; | |
737 return ↦ | |
738 } | |
739 | |
740 // The long integer format map uses two bits (size<1:0>) to encode the | |
741 // long set of NEON integer vector formats. These are used in narrow, wide | |
742 // and long operations. | |
743 static const NEONFormatMap* LongIntegerFormatMap() { | |
744 static const NEONFormatMap map = {{23, 22}, {NF_8H, NF_4S, NF_2D}}; | |
745 return ↦ | |
746 } | |
747 | |
748 // The FP format map uses two bits (Q, size<0>) to encode the NEON FP vector | |
749 // formats: NF_2S, NF_4S, NF_2D. | |
750 static const NEONFormatMap* FPFormatMap() { | |
751 // The FP format map assumes two bits (Q, size<0>) are used to encode the | |
752 // NEON FP vector formats: NF_2S, NF_4S, NF_2D. | |
753 static const NEONFormatMap map = {{22, 30}, | |
754 {NF_2S, NF_4S, NF_UNDEF, NF_2D}}; | |
755 return ↦ | |
756 } | |
757 | |
758 // The load/store format map uses three bits (Q, 11, 10) to encode the | |
759 // set of NEON vector formats. | |
760 static const NEONFormatMap* LoadStoreFormatMap() { | |
761 static const NEONFormatMap map = { | |
762 {11, 10, 30}, | |
763 {NF_8B, NF_16B, NF_4H, NF_8H, NF_2S, NF_4S, NF_1D, NF_2D}}; | |
764 return ↦ | |
765 } | |
766 | |
767 // The logical format map uses one bit (Q) to encode the NEON vector format: | |
768 // NF_8B, NF_16B. | |
769 static const NEONFormatMap* LogicalFormatMap() { | |
770 static const NEONFormatMap map = {{30}, {NF_8B, NF_16B}}; | |
771 return ↦ | |
772 } | |
773 | |
774 // The triangular format map uses between two and five bits to encode the NEON | |
775 // vector format: | |
776 // xxx10->8B, xxx11->16B, xx100->4H, xx101->8H | |
777 // x1000->2S, x1001->4S, 10001->2D, all others undefined. | |
778 static const NEONFormatMap* TriangularFormatMap() { | |
779 static const NEONFormatMap map = { | |
780 {19, 18, 17, 16, 30}, | |
781 {NF_UNDEF, NF_UNDEF, NF_8B, NF_16B, NF_4H, NF_8H, NF_8B, NF_16B, | |
782 NF_2S, NF_4S, NF_8B, NF_16B, NF_4H, NF_8H, NF_8B, NF_16B, | |
783 NF_UNDEF, NF_2D, NF_8B, NF_16B, NF_4H, NF_8H, NF_8B, NF_16B, | |
784 NF_2S, NF_4S, NF_8B, NF_16B, NF_4H, NF_8H, NF_8B, NF_16B}}; | |
785 return ↦ | |
786 } | |
787 | |
788 // The scalar format map uses two bits (size<1:0>) to encode the NEON scalar | |
789 // formats: NF_B, NF_H, NF_S, NF_D. | |
790 static const NEONFormatMap* ScalarFormatMap() { | |
791 static const NEONFormatMap map = {{23, 22}, {NF_B, NF_H, NF_S, NF_D}}; | |
792 return ↦ | |
793 } | |
794 | |
795 // The long scalar format map uses two bits (size<1:0>) to encode the longer | |
796 // NEON scalar formats: NF_H, NF_S, NF_D. | |
797 static const NEONFormatMap* LongScalarFormatMap() { | |
798 static const NEONFormatMap map = {{23, 22}, {NF_H, NF_S, NF_D}}; | |
799 return ↦ | |
800 } | |
801 | |
802 // The FP scalar format map assumes one bit (size<0>) is used to encode the | |
803 // NEON FP scalar formats: NF_S, NF_D. | |
804 static const NEONFormatMap* FPScalarFormatMap() { | |
805 static const NEONFormatMap map = {{22}, {NF_S, NF_D}}; | |
806 return ↦ | |
807 } | |
808 | |
809 // The triangular scalar format map uses between one and four bits to encode | |
810 // the NEON FP scalar formats: | |
811 // xxx1->B, xx10->H, x100->S, 1000->D, all others undefined. | |
812 static const NEONFormatMap* TriangularScalarFormatMap() { | |
813 static const NEONFormatMap map = { | |
814 {19, 18, 17, 16}, | |
815 {NF_UNDEF, NF_B, NF_H, NF_B, NF_S, NF_B, NF_H, NF_B, NF_D, NF_B, NF_H, | |
816 NF_B, NF_S, NF_B, NF_H, NF_B}}; | |
817 return ↦ | |
818 } | |
819 | |
820 private: | |
821 // Get a pointer to a string that represents the format or placeholder for | |
822 // the specified substitution index, based on the format map and instruction. | |
823 const char* GetSubstitute(int index, SubstitutionMode mode) { | |
824 if (mode == kFormat) { | |
825 return NEONFormatAsString(GetNEONFormat(formats_[index])); | |
826 } | |
827 DCHECK_EQ(mode, kPlaceholder); | |
828 return NEONFormatAsPlaceholder(GetNEONFormat(formats_[index])); | |
829 } | |
830 | |
831 // Get the NEONFormat enumerated value for bits obtained from the | |
832 // instruction based on the specified format mapping. | |
833 NEONFormat GetNEONFormat(const NEONFormatMap* format_map) { | |
834 return format_map->map[PickBits(format_map->bits)]; | |
835 } | |
836 | |
837 // Convert a NEONFormat into a string. | |
838 static const char* NEONFormatAsString(NEONFormat format) { | |
839 static const char* formats[] = {"undefined", "8b", "16b", "4h", "8h", | |
840 "2s", "4s", "1d", "2d", "b", | |
841 "h", "s", "d"}; | |
842 DCHECK_LT(format, arraysize(formats)); | |
843 return formats[format]; | |
844 } | |
845 | |
846 // Convert a NEONFormat into a register placeholder string. | |
847 static const char* NEONFormatAsPlaceholder(NEONFormat format) { | |
848 DCHECK((format == NF_B) || (format == NF_H) || (format == NF_S) || | |
849 (format == NF_D) || (format == NF_UNDEF)); | |
850 static const char* formats[] = { | |
851 "undefined", "undefined", "undefined", "undefined", "undefined", | |
852 "undefined", "undefined", "undefined", "undefined", "'B", | |
853 "'H", "'S", "'D"}; | |
854 return formats[format]; | |
855 } | |
856 | |
857 // Select bits from instrbits_ defined by the bits array, concatenate them, | |
858 // and return the value. | |
859 uint8_t PickBits(const uint8_t bits[]) { | |
860 uint8_t result = 0; | |
861 for (unsigned b = 0; b < kNEONFormatMaxBits; b++) { | |
862 if (bits[b] == 0) break; | |
863 result <<= 1; | |
864 result |= ((instrbits_ & (1 << bits[b])) == 0) ? 0 : 1; | |
865 } | |
866 return result; | |
867 } | |
868 | |
869 Instr instrbits_; | |
870 const NEONFormatMap* formats_[3]; | |
871 char form_buffer_[64]; | |
872 char mne_buffer_[16]; | |
873 }; | |
535 | 874 |
536 } // namespace internal | 875 } // namespace internal |
537 } // namespace v8 | 876 } // namespace v8 |
538 | 877 |
539 | 878 |
540 #endif // V8_ARM64_INSTRUCTIONS_ARM64_H_ | 879 #endif // V8_ARM64_INSTRUCTIONS_ARM64_H_ |
OLD | NEW |