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

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

Issue 207823003: Rename A64 port to ARM64 port (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: retry Created 6 years, 9 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 | Annotate | Revision Log
« no previous file with comments | « src/a64/ic-a64.cc ('k') | src/a64/instructions-a64.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 // Copyright 2013 the V8 project authors. All rights reserved.
2 // Redistribution and use in source and binary forms, with or without
3 // modification, are permitted provided that the following conditions are
4 // met:
5 //
6 // * Redistributions of source code must retain the above copyright
7 // notice, this list of conditions and the following disclaimer.
8 // * Redistributions in binary form must reproduce the above
9 // copyright notice, this list of conditions and the following
10 // disclaimer in the documentation and/or other materials provided
11 // with the distribution.
12 // * Neither the name of Google Inc. nor the names of its
13 // contributors may be used to endorse or promote products derived
14 // from this software without specific prior written permission.
15 //
16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
28 #ifndef V8_A64_INSTRUCTIONS_A64_H_
29 #define V8_A64_INSTRUCTIONS_A64_H_
30
31 #include "globals.h"
32 #include "utils.h"
33 #include "a64/constants-a64.h"
34 #include "a64/utils-a64.h"
35
36 namespace v8 {
37 namespace internal {
38
39
40 // ISA constants. --------------------------------------------------------------
41
42 typedef uint32_t Instr;
43
44 // The following macros initialize a float/double variable with a bit pattern
45 // without using static initializers: If A64_DEFINE_FP_STATICS is defined, the
46 // symbol is defined as uint32_t/uint64_t initialized with the desired bit
47 // pattern. Otherwise, the same symbol is declared as an external float/double.
48 #if defined(A64_DEFINE_FP_STATICS)
49 #define DEFINE_FLOAT(name, value) extern const uint32_t name = value
50 #define DEFINE_DOUBLE(name, value) extern const uint64_t name = value
51 #else
52 #define DEFINE_FLOAT(name, value) extern const float name
53 #define DEFINE_DOUBLE(name, value) extern const double name
54 #endif // defined(A64_DEFINE_FP_STATICS)
55
56 DEFINE_FLOAT(kFP32PositiveInfinity, 0x7f800000);
57 DEFINE_FLOAT(kFP32NegativeInfinity, 0xff800000);
58 DEFINE_DOUBLE(kFP64PositiveInfinity, 0x7ff0000000000000UL);
59 DEFINE_DOUBLE(kFP64NegativeInfinity, 0xfff0000000000000UL);
60
61 // This value is a signalling NaN as both a double and as a float (taking the
62 // least-significant word).
63 DEFINE_DOUBLE(kFP64SignallingNaN, 0x7ff000007f800001);
64 DEFINE_FLOAT(kFP32SignallingNaN, 0x7f800001);
65
66 // A similar value, but as a quiet NaN.
67 DEFINE_DOUBLE(kFP64QuietNaN, 0x7ff800007fc00001);
68 DEFINE_FLOAT(kFP32QuietNaN, 0x7fc00001);
69
70 // The default NaN values (for FPCR.DN=1).
71 DEFINE_DOUBLE(kFP64DefaultNaN, 0x7ff8000000000000UL);
72 DEFINE_FLOAT(kFP32DefaultNaN, 0x7fc00000);
73
74 #undef DEFINE_FLOAT
75 #undef DEFINE_DOUBLE
76
77
78 enum LSDataSize {
79 LSByte = 0,
80 LSHalfword = 1,
81 LSWord = 2,
82 LSDoubleWord = 3
83 };
84
85 LSDataSize CalcLSPairDataSize(LoadStorePairOp op);
86
87 enum ImmBranchType {
88 UnknownBranchType = 0,
89 CondBranchType = 1,
90 UncondBranchType = 2,
91 CompareBranchType = 3,
92 TestBranchType = 4
93 };
94
95 enum AddrMode {
96 Offset,
97 PreIndex,
98 PostIndex
99 };
100
101 enum FPRounding {
102 // The first four values are encodable directly by FPCR<RMode>.
103 FPTieEven = 0x0,
104 FPPositiveInfinity = 0x1,
105 FPNegativeInfinity = 0x2,
106 FPZero = 0x3,
107
108 // The final rounding mode is only available when explicitly specified by the
109 // instruction (such as with fcvta). It cannot be set in FPCR.
110 FPTieAway
111 };
112
113 enum Reg31Mode {
114 Reg31IsStackPointer,
115 Reg31IsZeroRegister
116 };
117
118 // Instructions. ---------------------------------------------------------------
119
120 class Instruction {
121 public:
122 V8_INLINE Instr InstructionBits() const {
123 return *reinterpret_cast<const Instr*>(this);
124 }
125
126 V8_INLINE void SetInstructionBits(Instr new_instr) {
127 *reinterpret_cast<Instr*>(this) = new_instr;
128 }
129
130 int Bit(int pos) const {
131 return (InstructionBits() >> pos) & 1;
132 }
133
134 uint32_t Bits(int msb, int lsb) const {
135 return unsigned_bitextract_32(msb, lsb, InstructionBits());
136 }
137
138 int32_t SignedBits(int msb, int lsb) const {
139 int32_t bits = *(reinterpret_cast<const int32_t*>(this));
140 return signed_bitextract_32(msb, lsb, bits);
141 }
142
143 Instr Mask(uint32_t mask) const {
144 return InstructionBits() & mask;
145 }
146
147 V8_INLINE Instruction* following(int count = 1) {
148 return InstructionAtOffset(count * static_cast<int>(kInstructionSize));
149 }
150
151 V8_INLINE Instruction* preceding(int count = 1) {
152 return following(-count);
153 }
154
155 #define DEFINE_GETTER(Name, HighBit, LowBit, Func) \
156 int64_t Name() const { return Func(HighBit, LowBit); }
157 INSTRUCTION_FIELDS_LIST(DEFINE_GETTER)
158 #undef DEFINE_GETTER
159
160 // ImmPCRel is a compound field (not present in INSTRUCTION_FIELDS_LIST),
161 // formed from ImmPCRelLo and ImmPCRelHi.
162 int ImmPCRel() const {
163 int const offset = ((ImmPCRelHi() << ImmPCRelLo_width) | ImmPCRelLo());
164 int const width = ImmPCRelLo_width + ImmPCRelHi_width;
165 return signed_bitextract_32(width-1, 0, offset);
166 }
167
168 uint64_t ImmLogical();
169 float ImmFP32();
170 double ImmFP64();
171
172 LSDataSize SizeLSPair() const {
173 return CalcLSPairDataSize(
174 static_cast<LoadStorePairOp>(Mask(LoadStorePairMask)));
175 }
176
177 // Helpers.
178 bool IsCondBranchImm() const {
179 return Mask(ConditionalBranchFMask) == ConditionalBranchFixed;
180 }
181
182 bool IsUncondBranchImm() const {
183 return Mask(UnconditionalBranchFMask) == UnconditionalBranchFixed;
184 }
185
186 bool IsCompareBranch() const {
187 return Mask(CompareBranchFMask) == CompareBranchFixed;
188 }
189
190 bool IsTestBranch() const {
191 return Mask(TestBranchFMask) == TestBranchFixed;
192 }
193
194 bool IsLdrLiteral() const {
195 return Mask(LoadLiteralFMask) == LoadLiteralFixed;
196 }
197
198 bool IsLdrLiteralX() const {
199 return Mask(LoadLiteralMask) == LDR_x_lit;
200 }
201
202 bool IsPCRelAddressing() const {
203 return Mask(PCRelAddressingFMask) == PCRelAddressingFixed;
204 }
205
206 bool IsLogicalImmediate() const {
207 return Mask(LogicalImmediateFMask) == LogicalImmediateFixed;
208 }
209
210 bool IsAddSubImmediate() const {
211 return Mask(AddSubImmediateFMask) == AddSubImmediateFixed;
212 }
213
214 bool IsAddSubExtended() const {
215 return Mask(AddSubExtendedFMask) == AddSubExtendedFixed;
216 }
217
218 // Match any loads or stores, including pairs.
219 bool IsLoadOrStore() const {
220 return Mask(LoadStoreAnyFMask) == LoadStoreAnyFixed;
221 }
222
223 // Match any loads, including pairs.
224 bool IsLoad() const;
225 // Match any stores, including pairs.
226 bool IsStore() const;
227
228 // Indicate whether Rd can be the stack pointer or the zero register. This
229 // does not check that the instruction actually has an Rd field.
230 Reg31Mode RdMode() const {
231 // The following instructions use csp or wsp as Rd:
232 // Add/sub (immediate) when not setting the flags.
233 // Add/sub (extended) when not setting the flags.
234 // Logical (immediate) when not setting the flags.
235 // Otherwise, r31 is the zero register.
236 if (IsAddSubImmediate() || IsAddSubExtended()) {
237 if (Mask(AddSubSetFlagsBit)) {
238 return Reg31IsZeroRegister;
239 } else {
240 return Reg31IsStackPointer;
241 }
242 }
243 if (IsLogicalImmediate()) {
244 // Of the logical (immediate) instructions, only ANDS (and its aliases)
245 // can set the flags. The others can all write into csp.
246 // Note that some logical operations are not available to
247 // immediate-operand instructions, so we have to combine two masks here.
248 if (Mask(LogicalImmediateMask & LogicalOpMask) == ANDS) {
249 return Reg31IsZeroRegister;
250 } else {
251 return Reg31IsStackPointer;
252 }
253 }
254 return Reg31IsZeroRegister;
255 }
256
257 // Indicate whether Rn can be the stack pointer or the zero register. This
258 // does not check that the instruction actually has an Rn field.
259 Reg31Mode RnMode() const {
260 // The following instructions use csp or wsp as Rn:
261 // All loads and stores.
262 // Add/sub (immediate).
263 // Add/sub (extended).
264 // Otherwise, r31 is the zero register.
265 if (IsLoadOrStore() || IsAddSubImmediate() || IsAddSubExtended()) {
266 return Reg31IsStackPointer;
267 }
268 return Reg31IsZeroRegister;
269 }
270
271 ImmBranchType BranchType() const {
272 if (IsCondBranchImm()) {
273 return CondBranchType;
274 } else if (IsUncondBranchImm()) {
275 return UncondBranchType;
276 } else if (IsCompareBranch()) {
277 return CompareBranchType;
278 } else if (IsTestBranch()) {
279 return TestBranchType;
280 } else {
281 return UnknownBranchType;
282 }
283 }
284
285 static int ImmBranchRangeBitwidth(ImmBranchType branch_type) {
286 switch (branch_type) {
287 case UncondBranchType:
288 return ImmUncondBranch_width;
289 case CondBranchType:
290 return ImmCondBranch_width;
291 case CompareBranchType:
292 return ImmCmpBranch_width;
293 case TestBranchType:
294 return ImmTestBranch_width;
295 default:
296 UNREACHABLE();
297 return 0;
298 }
299 }
300
301 // The range of the branch instruction, expressed as 'instr +- range'.
302 static int32_t ImmBranchRange(ImmBranchType branch_type) {
303 return
304 (1 << (ImmBranchRangeBitwidth(branch_type) + kInstructionSizeLog2)) / 2 -
305 kInstructionSize;
306 }
307
308 int ImmBranch() const {
309 switch (BranchType()) {
310 case CondBranchType: return ImmCondBranch();
311 case UncondBranchType: return ImmUncondBranch();
312 case CompareBranchType: return ImmCmpBranch();
313 case TestBranchType: return ImmTestBranch();
314 default: UNREACHABLE();
315 }
316 return 0;
317 }
318
319 bool IsBranchAndLinkToRegister() const {
320 return Mask(UnconditionalBranchToRegisterMask) == BLR;
321 }
322
323 bool IsMovz() const {
324 return (Mask(MoveWideImmediateMask) == MOVZ_x) ||
325 (Mask(MoveWideImmediateMask) == MOVZ_w);
326 }
327
328 bool IsMovk() const {
329 return (Mask(MoveWideImmediateMask) == MOVK_x) ||
330 (Mask(MoveWideImmediateMask) == MOVK_w);
331 }
332
333 bool IsMovn() const {
334 return (Mask(MoveWideImmediateMask) == MOVN_x) ||
335 (Mask(MoveWideImmediateMask) == MOVN_w);
336 }
337
338 bool IsNop(int n) {
339 // A marking nop is an instruction
340 // mov r<n>, r<n>
341 // which is encoded as
342 // orr r<n>, xzr, r<n>
343 return (Mask(LogicalShiftedMask) == ORR_x) &&
344 (Rd() == Rm()) &&
345 (Rd() == n);
346 }
347
348 // Find the PC offset encoded in this instruction. 'this' may be a branch or
349 // a PC-relative addressing instruction.
350 // The offset returned is unscaled.
351 ptrdiff_t ImmPCOffset();
352
353 // Find the target of this instruction. 'this' may be a branch or a
354 // PC-relative addressing instruction.
355 Instruction* ImmPCOffsetTarget();
356
357 static bool IsValidImmPCOffset(ImmBranchType branch_type, int32_t offset);
358 bool IsTargetInImmPCOffsetRange(Instruction* target);
359 // Patch a PC-relative offset to refer to 'target'. 'this' may be a branch or
360 // a PC-relative addressing instruction.
361 void SetImmPCOffsetTarget(Instruction* target);
362 // Patch a literal load instruction to load from 'source'.
363 void SetImmLLiteral(Instruction* source);
364
365 uint8_t* LiteralAddress() {
366 int offset = ImmLLiteral() << kLiteralEntrySizeLog2;
367 return reinterpret_cast<uint8_t*>(this) + offset;
368 }
369
370 enum CheckAlignment { NO_CHECK, CHECK_ALIGNMENT };
371
372 V8_INLINE Instruction* InstructionAtOffset(
373 int64_t offset,
374 CheckAlignment check = CHECK_ALIGNMENT) {
375 Address addr = reinterpret_cast<Address>(this) + offset;
376 // The FUZZ_disasm test relies on no check being done.
377 ASSERT(check == NO_CHECK || IsAddressAligned(addr, kInstructionSize));
378 return Cast(addr);
379 }
380
381 template<typename T> V8_INLINE static Instruction* Cast(T src) {
382 return reinterpret_cast<Instruction*>(src);
383 }
384
385 V8_INLINE ptrdiff_t DistanceTo(Instruction* target) {
386 return reinterpret_cast<Address>(target) - reinterpret_cast<Address>(this);
387 }
388
389
390 void SetPCRelImmTarget(Instruction* target);
391 void SetBranchImmTarget(Instruction* target);
392 };
393
394
395 // Where Instruction looks at instructions generated by the Assembler,
396 // InstructionSequence looks at instructions sequences generated by the
397 // MacroAssembler.
398 class InstructionSequence : public Instruction {
399 public:
400 static InstructionSequence* At(Address address) {
401 return reinterpret_cast<InstructionSequence*>(address);
402 }
403
404 // Sequences generated by MacroAssembler::InlineData().
405 bool IsInlineData() const;
406 uint64_t InlineData() const;
407 };
408
409
410 // Simulator/Debugger debug instructions ---------------------------------------
411 // Each debug marker is represented by a HLT instruction. The immediate comment
412 // field in the instruction is used to identify the type of debug marker. Each
413 // marker encodes arguments in a different way, as described below.
414
415 // Indicate to the Debugger that the instruction is a redirected call.
416 const Instr kImmExceptionIsRedirectedCall = 0xca11;
417
418 // Represent unreachable code. This is used as a guard in parts of the code that
419 // should not be reachable, such as in data encoded inline in the instructions.
420 const Instr kImmExceptionIsUnreachable = 0xdebf;
421
422 // A pseudo 'printf' instruction. The arguments will be passed to the platform
423 // printf method.
424 const Instr kImmExceptionIsPrintf = 0xdeb1;
425 // Parameters are stored in A64 registers as if the printf pseudo-instruction
426 // was a call to the real printf method:
427 //
428 // x0: The format string, then either of:
429 // x1-x7: Optional arguments.
430 // d0-d7: Optional arguments.
431 //
432 // Floating-point and integer arguments are passed in separate sets of
433 // registers in AAPCS64 (even for varargs functions), so it is not possible to
434 // determine the type of location of each arguments without some information
435 // about the values that were passed in. This information could be retrieved
436 // from the printf format string, but the format string is not trivial to
437 // parse so we encode the relevant information with the HLT instruction.
438 // - Type
439 // Either kRegister or kFPRegister, but stored as a uint32_t because there's
440 // no way to guarantee the size of the CPURegister::RegisterType enum.
441 const unsigned kPrintfTypeOffset = 1 * kInstructionSize;
442 const unsigned kPrintfLength = 2 * kInstructionSize;
443
444 // A pseudo 'debug' instruction.
445 const Instr kImmExceptionIsDebug = 0xdeb0;
446 // Parameters are inlined in the code after a debug pseudo-instruction:
447 // - Debug code.
448 // - Debug parameters.
449 // - Debug message string. This is a NULL-terminated ASCII string, padded to
450 // kInstructionSize so that subsequent instructions are correctly aligned.
451 // - A kImmExceptionIsUnreachable marker, to catch accidental execution of the
452 // string data.
453 const unsigned kDebugCodeOffset = 1 * kInstructionSize;
454 const unsigned kDebugParamsOffset = 2 * kInstructionSize;
455 const unsigned kDebugMessageOffset = 3 * kInstructionSize;
456
457 // Debug parameters.
458 // Used without a TRACE_ option, the Debugger will print the arguments only
459 // once. Otherwise TRACE_ENABLE and TRACE_DISABLE will enable or disable tracing
460 // before every instruction for the specified LOG_ parameters.
461 //
462 // TRACE_OVERRIDE enables the specified LOG_ parameters, and disabled any
463 // others that were not specified.
464 //
465 // For example:
466 //
467 // __ debug("print registers and fp registers", 0, LOG_REGS | LOG_FP_REGS);
468 // will print the registers and fp registers only once.
469 //
470 // __ debug("trace disasm", 1, TRACE_ENABLE | LOG_DISASM);
471 // starts disassembling the code.
472 //
473 // __ debug("trace rets", 2, TRACE_ENABLE | LOG_REGS);
474 // adds the general purpose registers to the trace.
475 //
476 // __ debug("stop regs", 3, TRACE_DISABLE | LOG_REGS);
477 // stops tracing the registers.
478 const unsigned kDebuggerTracingDirectivesMask = 3 << 6;
479 enum DebugParameters {
480 NO_PARAM = 0,
481 BREAK = 1 << 0,
482 LOG_DISASM = 1 << 1, // Use only with TRACE. Disassemble the code.
483 LOG_REGS = 1 << 2, // Log general purpose registers.
484 LOG_FP_REGS = 1 << 3, // Log floating-point registers.
485 LOG_SYS_REGS = 1 << 4, // Log the status flags.
486 LOG_WRITE = 1 << 5, // Log any memory write.
487
488 LOG_STATE = LOG_REGS | LOG_FP_REGS | LOG_SYS_REGS,
489 LOG_ALL = LOG_DISASM | LOG_STATE | LOG_WRITE,
490
491 // Trace control.
492 TRACE_ENABLE = 1 << 6,
493 TRACE_DISABLE = 2 << 6,
494 TRACE_OVERRIDE = 3 << 6
495 };
496
497
498 } } // namespace v8::internal
499
500
501 #endif // V8_A64_INSTRUCTIONS_A64_H_
OLDNEW
« no previous file with comments | « src/a64/ic-a64.cc ('k') | src/a64/instructions-a64.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698