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

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

Issue 2819093002: Revert "Reland "ARM64: Add NEON support"" (Closed)
Patch Set: Created 3 years, 8 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
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
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
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
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 &map;
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 &map;
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 &map;
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 &map;
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 &map;
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 &map;
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 &map;
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 &map;
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 &map;
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 &map;
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_
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