Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(679)

Side by Side Diff: src/arm64/instructions-arm64.h

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

Powered by Google App Engine
This is Rietveld 408576698