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

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

Issue 2622643005: ARM64: Add NEON support (Closed)
Patch Set: Fix Math.abs properly 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
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 216 matching lines...) Expand 10 before | Expand all | Expand 10 after
410 } 452 }
411 453
412 454
413 static const int ImmPCRelRangeBitwidth = 21; 455 static const int ImmPCRelRangeBitwidth = 21;
414 static bool IsValidPCRelOffset(ptrdiff_t offset) { return is_int21(offset); } 456 static bool IsValidPCRelOffset(ptrdiff_t offset) { return is_int21(offset); }
415 void SetPCRelImmTarget(AssemblerBase::IsolateData isolate_data, 457 void SetPCRelImmTarget(AssemblerBase::IsolateData isolate_data,
416 Instruction* target); 458 Instruction* target);
417 void SetBranchImmTarget(Instruction* target); 459 void SetBranchImmTarget(Instruction* target);
418 }; 460 };
419 461
462 // Functions for handling NEON vector format information.
463 enum VectorFormat {
464 kFormatUndefined = 0xffffffff,
465 kFormat8B = NEON_8B,
466 kFormat16B = NEON_16B,
467 kFormat4H = NEON_4H,
468 kFormat8H = NEON_8H,
469 kFormat2S = NEON_2S,
470 kFormat4S = NEON_4S,
471 kFormat1D = NEON_1D,
472 kFormat2D = NEON_2D,
473
474 // Scalar formats. We add the scalar bit to distinguish between scalar and
475 // vector enumerations; the bit is always set in the encoding of scalar ops
476 // and always clear for vector ops. Although kFormatD and kFormat1D appear
477 // to be the same, their meaning is subtly different. The first is a scalar
478 // operation, the second a vector operation that only affects one lane.
479 kFormatB = NEON_B | NEONScalar,
480 kFormatH = NEON_H | NEONScalar,
481 kFormatS = NEON_S | NEONScalar,
482 kFormatD = NEON_D | NEONScalar
483 };
484
485 VectorFormat VectorFormatHalfWidth(VectorFormat vform);
486 VectorFormat VectorFormatDoubleWidth(VectorFormat vform);
487 VectorFormat VectorFormatDoubleLanes(VectorFormat vform);
488 VectorFormat VectorFormatHalfLanes(VectorFormat vform);
489 VectorFormat ScalarFormatFromLaneSize(int lanesize);
490 VectorFormat VectorFormatHalfWidthDoubleLanes(VectorFormat vform);
491 VectorFormat VectorFormatFillQ(VectorFormat vform);
492 VectorFormat ScalarFormatFromFormat(VectorFormat vform);
493 unsigned RegisterSizeInBitsFromFormat(VectorFormat vform);
494 unsigned RegisterSizeInBytesFromFormat(VectorFormat vform);
495 int LaneSizeInBytesFromFormat(VectorFormat vform);
496 unsigned LaneSizeInBitsFromFormat(VectorFormat vform);
497 int LaneSizeInBytesLog2FromFormat(VectorFormat vform);
498 int LaneCountFromFormat(VectorFormat vform);
499 int MaxLaneCountFromFormat(VectorFormat vform);
500 bool IsVectorFormat(VectorFormat vform);
501 int64_t MaxIntFromFormat(VectorFormat vform);
502 int64_t MinIntFromFormat(VectorFormat vform);
503 uint64_t MaxUintFromFormat(VectorFormat vform);
420 504
421 // Where Instruction looks at instructions generated by the Assembler, 505 // Where Instruction looks at instructions generated by the Assembler,
422 // InstructionSequence looks at instructions sequences generated by the 506 // InstructionSequence looks at instructions sequences generated by the
423 // MacroAssembler. 507 // MacroAssembler.
424 class InstructionSequence : public Instruction { 508 class InstructionSequence : public Instruction {
425 public: 509 public:
426 static InstructionSequence* At(Address address) { 510 static InstructionSequence* At(Address address) {
427 return reinterpret_cast<InstructionSequence*>(address); 511 return reinterpret_cast<InstructionSequence*>(address);
428 } 512 }
429 513
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after
497 // Debug parameters. 581 // Debug parameters.
498 // Used without a TRACE_ option, the Debugger will print the arguments only 582 // Used without a TRACE_ option, the Debugger will print the arguments only
499 // once. Otherwise TRACE_ENABLE and TRACE_DISABLE will enable or disable tracing 583 // once. Otherwise TRACE_ENABLE and TRACE_DISABLE will enable or disable tracing
500 // before every instruction for the specified LOG_ parameters. 584 // before every instruction for the specified LOG_ parameters.
501 // 585 //
502 // TRACE_OVERRIDE enables the specified LOG_ parameters, and disabled any 586 // TRACE_OVERRIDE enables the specified LOG_ parameters, and disabled any
503 // others that were not specified. 587 // others that were not specified.
504 // 588 //
505 // For example: 589 // For example:
506 // 590 //
507 // __ debug("print registers and fp registers", 0, LOG_REGS | LOG_FP_REGS); 591 // __ debug("print registers and fp registers", 0, LOG_REGS | LOG_VREGS);
508 // will print the registers and fp registers only once. 592 // will print the registers and fp registers only once.
509 // 593 //
510 // __ debug("trace disasm", 1, TRACE_ENABLE | LOG_DISASM); 594 // __ debug("trace disasm", 1, TRACE_ENABLE | LOG_DISASM);
511 // starts disassembling the code. 595 // starts disassembling the code.
512 // 596 //
513 // __ debug("trace rets", 2, TRACE_ENABLE | LOG_REGS); 597 // __ debug("trace rets", 2, TRACE_ENABLE | LOG_REGS);
514 // adds the general purpose registers to the trace. 598 // adds the general purpose registers to the trace.
515 // 599 //
516 // __ debug("stop regs", 3, TRACE_DISABLE | LOG_REGS); 600 // __ debug("stop regs", 3, TRACE_DISABLE | LOG_REGS);
517 // stops tracing the registers. 601 // stops tracing the registers.
518 const unsigned kDebuggerTracingDirectivesMask = 3 << 6; 602 const unsigned kDebuggerTracingDirectivesMask = 3 << 6;
519 enum DebugParameters { 603 enum DebugParameters {
520 NO_PARAM = 0, 604 NO_PARAM = 0,
521 BREAK = 1 << 0, 605 BREAK = 1 << 0,
522 LOG_DISASM = 1 << 1, // Use only with TRACE. Disassemble the code. 606 LOG_DISASM = 1 << 1, // Use only with TRACE. Disassemble the code.
523 LOG_REGS = 1 << 2, // Log general purpose registers. 607 LOG_REGS = 1 << 2, // Log general purpose registers.
524 LOG_FP_REGS = 1 << 3, // Log floating-point registers. 608 LOG_VREGS = 1 << 3, // Log NEON and floating-point registers.
525 LOG_SYS_REGS = 1 << 4, // Log the status flags. 609 LOG_SYS_REGS = 1 << 4, // Log the status flags.
526 LOG_WRITE = 1 << 5, // Log any memory write. 610 LOG_WRITE = 1 << 5, // Log any memory write.
527 611
528 LOG_STATE = LOG_REGS | LOG_FP_REGS | LOG_SYS_REGS, 612 LOG_NONE = 0,
529 LOG_ALL = LOG_DISASM | LOG_STATE | LOG_WRITE, 613 LOG_STATE = LOG_REGS | LOG_VREGS | LOG_SYS_REGS,
614 LOG_ALL = LOG_DISASM | LOG_STATE | LOG_WRITE,
530 615
531 // Trace control. 616 // Trace control.
532 TRACE_ENABLE = 1 << 6, 617 TRACE_ENABLE = 1 << 6,
533 TRACE_DISABLE = 2 << 6, 618 TRACE_DISABLE = 2 << 6,
534 TRACE_OVERRIDE = 3 << 6 619 TRACE_OVERRIDE = 3 << 6
535 }; 620 };
536 621
537 622 enum NEONFormat {
623 NF_UNDEF = 0,
624 NF_8B = 1,
625 NF_16B = 2,
626 NF_4H = 3,
627 NF_8H = 4,
628 NF_2S = 5,
629 NF_4S = 6,
630 NF_1D = 7,
631 NF_2D = 8,
632 NF_B = 9,
633 NF_H = 10,
634 NF_S = 11,
635 NF_D = 12
636 };
637
638 static const unsigned kNEONFormatMaxBits = 6;
639
640 struct NEONFormatMap {
641 // The bit positions in the instruction to consider.
642 uint8_t bits[kNEONFormatMaxBits];
643
644 // Mapping from concatenated bits to format.
645 NEONFormat map[1 << kNEONFormatMaxBits];
646 };
647
648 class NEONFormatDecoder {
649 public:
650 enum SubstitutionMode { kPlaceholder, kFormat };
651
652 // Construct a format decoder with increasingly specific format maps for each
653 // substitution. If no format map is specified, the default is the integer
654 // format map.
655 explicit NEONFormatDecoder(const Instruction* instr);
656 NEONFormatDecoder(const Instruction* instr, const NEONFormatMap* format);
657 NEONFormatDecoder(const Instruction* instr, const NEONFormatMap* format0,
658 const NEONFormatMap* format1);
659 NEONFormatDecoder(const Instruction* instr, const NEONFormatMap* format0,
660 const NEONFormatMap* format1, const NEONFormatMap* format2);
661
662 // Set the format mapping for all or individual substitutions.
663 void SetFormatMaps(const NEONFormatMap* format0,
664 const NEONFormatMap* format1 = NULL,
665 const NEONFormatMap* format2 = NULL);
666 void SetFormatMap(unsigned index, const NEONFormatMap* format);
667
668 // Substitute %s in the input string with the placeholder string for each
669 // register, ie. "'B", "'H", etc.
670 const char* SubstitutePlaceholders(const char* string);
671
672 // Substitute %s in the input string with a new string based on the
673 // substitution mode.
674 const char* Substitute(const char* string, SubstitutionMode mode0 = kFormat,
675 SubstitutionMode mode1 = kFormat,
676 SubstitutionMode mode2 = kFormat);
677
678 // Append a "2" to a mnemonic string based of the state of the Q bit.
679 const char* Mnemonic(const char* mnemonic);
680
681 VectorFormat GetVectorFormat(int format_index = 0);
682 VectorFormat GetVectorFormat(const NEONFormatMap* format_map);
683
684 // Built in mappings for common cases.
685
686 // The integer format map uses three bits (Q, size<1:0>) to encode the
687 // "standard" set of NEON integer vector formats.
688 static const NEONFormatMap* IntegerFormatMap() {
689 static const NEONFormatMap map = {
690 {23, 22, 30},
691 {NF_8B, NF_16B, NF_4H, NF_8H, NF_2S, NF_4S, NF_UNDEF, NF_2D}};
692 return &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 };
538 } // namespace internal 799 } // namespace internal
539 } // namespace v8 800 } // namespace v8
540 801
541 802
542 #endif // V8_ARM64_INSTRUCTIONS_ARM64_H_ 803 #endif // V8_ARM64_INSTRUCTIONS_ARM64_H_
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