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

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

Issue 2622643005: ARM64: Add NEON support (Closed)
Patch Set: Created 3 years, 11 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
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/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
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
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
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 &map;
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 &map;
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 &map;
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 &map;
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 &map;
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 &map;
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 &map;
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 &map;
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 &map;
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 &map;
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_
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698