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

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

Issue 148293020: Merge experimental/a64 to bleeding_edge. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Remove ARM from OWNERS Created 6 years, 10 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 #undef DEFINE_FLOAT
71 #undef DEFINE_DOUBLE
72
73
74 enum LSDataSize {
75 LSByte = 0,
76 LSHalfword = 1,
77 LSWord = 2,
78 LSDoubleWord = 3
79 };
80
81 LSDataSize CalcLSPairDataSize(LoadStorePairOp op);
82
83 enum ImmBranchType {
84 UnknownBranchType = 0,
85 CondBranchType = 1,
86 UncondBranchType = 2,
87 CompareBranchType = 3,
88 TestBranchType = 4
89 };
90
91 enum AddrMode {
92 Offset,
93 PreIndex,
94 PostIndex
95 };
96
97 enum FPRounding {
98 // The first four values are encodable directly by FPCR<RMode>.
99 FPTieEven = 0x0,
100 FPPositiveInfinity = 0x1,
101 FPNegativeInfinity = 0x2,
102 FPZero = 0x3,
103
104 // The final rounding mode is only available when explicitly specified by the
105 // instruction (such as with fcvta). It cannot be set in FPCR.
106 FPTieAway
107 };
108
109 enum Reg31Mode {
110 Reg31IsStackPointer,
111 Reg31IsZeroRegister
112 };
113
114 // Instructions. ---------------------------------------------------------------
115
116 class Instruction {
117 public:
118 Instr InstructionBits() const {
119 Instr bits;
120 memcpy(&bits, this, sizeof(bits));
121 return bits;
122 }
123
124 void SetInstructionBits(Instr new_instr) {
125 memcpy(this, &new_instr, sizeof(new_instr));
126 }
127
128 int Bit(int pos) const {
129 return (InstructionBits() >> pos) & 1;
130 }
131
132 uint32_t Bits(int msb, int lsb) const {
133 return unsigned_bitextract_32(msb, lsb, InstructionBits());
134 }
135
136 int32_t SignedBits(int msb, int lsb) const {
137 int32_t bits = *(reinterpret_cast<const int32_t*>(this));
138 return signed_bitextract_32(msb, lsb, bits);
139 }
140
141 Instr Mask(uint32_t mask) const {
142 return InstructionBits() & mask;
143 }
144
145 Instruction* following(int count = 1) {
146 return this + count * kInstructionSize;
147 }
148
149 Instruction* preceding(int count = 1) {
150 return this - count * kInstructionSize;
151 }
152
153 #define DEFINE_GETTER(Name, HighBit, LowBit, Func) \
154 int64_t Name() const { return Func(HighBit, LowBit); }
155 INSTRUCTION_FIELDS_LIST(DEFINE_GETTER)
156 #undef DEFINE_GETTER
157
158 // ImmPCRel is a compound field (not present in INSTRUCTION_FIELDS_LIST),
159 // formed from ImmPCRelLo and ImmPCRelHi.
160 int ImmPCRel() const {
161 int const offset = ((ImmPCRelHi() << ImmPCRelLo_width) | ImmPCRelLo());
162 int const width = ImmPCRelLo_width + ImmPCRelHi_width;
163 return signed_bitextract_32(width-1, 0, offset);
164 }
165
166 uint64_t ImmLogical();
167 float ImmFP32();
168 double ImmFP64();
169
170 LSDataSize SizeLSPair() const {
171 return CalcLSPairDataSize(
172 static_cast<LoadStorePairOp>(Mask(LoadStorePairMask)));
173 }
174
175 // Helpers.
176 bool IsCondBranchImm() const {
177 return Mask(ConditionalBranchFMask) == ConditionalBranchFixed;
178 }
179
180 bool IsUncondBranchImm() const {
181 return Mask(UnconditionalBranchFMask) == UnconditionalBranchFixed;
182 }
183
184 bool IsCompareBranch() const {
185 return Mask(CompareBranchFMask) == CompareBranchFixed;
186 }
187
188 bool IsTestBranch() const {
189 return Mask(TestBranchFMask) == TestBranchFixed;
190 }
191
192 bool IsLdrLiteral() const {
193 return Mask(LoadLiteralFMask) == LoadLiteralFixed;
194 }
195
196 bool IsLdrLiteralX() const {
197 return Mask(LoadLiteralMask) == LDR_x_lit;
198 }
199
200 bool IsPCRelAddressing() const {
201 return Mask(PCRelAddressingFMask) == PCRelAddressingFixed;
202 }
203
204 bool IsLogicalImmediate() const {
205 return Mask(LogicalImmediateFMask) == LogicalImmediateFixed;
206 }
207
208 bool IsAddSubImmediate() const {
209 return Mask(AddSubImmediateFMask) == AddSubImmediateFixed;
210 }
211
212 bool IsAddSubExtended() const {
213 return Mask(AddSubExtendedFMask) == AddSubExtendedFixed;
214 }
215
216 // Match any loads or stores, including pairs.
217 bool IsLoadOrStore() const {
218 return Mask(LoadStoreAnyFMask) == LoadStoreAnyFixed;
219 }
220
221 // Match any loads, including pairs.
222 bool IsLoad() const;
223 // Match any stores, including pairs.
224 bool IsStore() const;
225
226 // Indicate whether Rd can be the stack pointer or the zero register. This
227 // does not check that the instruction actually has an Rd field.
228 Reg31Mode RdMode() const {
229 // The following instructions use csp or wsp as Rd:
230 // Add/sub (immediate) when not setting the flags.
231 // Add/sub (extended) when not setting the flags.
232 // Logical (immediate) when not setting the flags.
233 // Otherwise, r31 is the zero register.
234 if (IsAddSubImmediate() || IsAddSubExtended()) {
235 if (Mask(AddSubSetFlagsBit)) {
236 return Reg31IsZeroRegister;
237 } else {
238 return Reg31IsStackPointer;
239 }
240 }
241 if (IsLogicalImmediate()) {
242 // Of the logical (immediate) instructions, only ANDS (and its aliases)
243 // can set the flags. The others can all write into csp.
244 // Note that some logical operations are not available to
245 // immediate-operand instructions, so we have to combine two masks here.
246 if (Mask(LogicalImmediateMask & LogicalOpMask) == ANDS) {
247 return Reg31IsZeroRegister;
248 } else {
249 return Reg31IsStackPointer;
250 }
251 }
252 return Reg31IsZeroRegister;
253 }
254
255 // Indicate whether Rn can be the stack pointer or the zero register. This
256 // does not check that the instruction actually has an Rn field.
257 Reg31Mode RnMode() const {
258 // The following instructions use csp or wsp as Rn:
259 // All loads and stores.
260 // Add/sub (immediate).
261 // Add/sub (extended).
262 // Otherwise, r31 is the zero register.
263 if (IsLoadOrStore() || IsAddSubImmediate() || IsAddSubExtended()) {
264 return Reg31IsStackPointer;
265 }
266 return Reg31IsZeroRegister;
267 }
268
269 ImmBranchType BranchType() const {
270 if (IsCondBranchImm()) {
271 return CondBranchType;
272 } else if (IsUncondBranchImm()) {
273 return UncondBranchType;
274 } else if (IsCompareBranch()) {
275 return CompareBranchType;
276 } else if (IsTestBranch()) {
277 return TestBranchType;
278 } else {
279 return UnknownBranchType;
280 }
281 }
282
283 int ImmBranch() const {
284 switch (BranchType()) {
285 case CondBranchType: return ImmCondBranch();
286 case UncondBranchType: return ImmUncondBranch();
287 case CompareBranchType: return ImmCmpBranch();
288 case TestBranchType: return ImmTestBranch();
289 default: UNREACHABLE();
290 }
291 return 0;
292 }
293
294 bool IsBranchAndLinkToRegister() const {
295 return Mask(UnconditionalBranchToRegisterMask) == BLR;
296 }
297
298 bool IsMovz() const {
299 return (Mask(MoveWideImmediateMask) == MOVZ_x) ||
300 (Mask(MoveWideImmediateMask) == MOVZ_w);
301 }
302
303 bool IsMovk() const {
304 return (Mask(MoveWideImmediateMask) == MOVK_x) ||
305 (Mask(MoveWideImmediateMask) == MOVK_w);
306 }
307
308 bool IsMovn() const {
309 return (Mask(MoveWideImmediateMask) == MOVN_x) ||
310 (Mask(MoveWideImmediateMask) == MOVN_w);
311 }
312
313 bool IsNop(int n) {
314 // A marking nop is an instruction
315 // mov r<n>, r<n>
316 // which is encoded as
317 // orr r<n>, xzr, r<n>
318 return (Mask(LogicalShiftedMask) == ORR_x) &&
319 (Rd() == Rm()) &&
320 (Rd() == n);
321 }
322
323 // Find the PC offset encoded in this instruction. 'this' may be a branch or
324 // a PC-relative addressing instruction.
325 // The offset returned is unscaled.
326 ptrdiff_t ImmPCOffset();
327
328 // Find the target of this instruction. 'this' may be a branch or a
329 // PC-relative addressing instruction.
330 Instruction* ImmPCOffsetTarget();
331
332 // Patch a PC-relative offset to refer to 'target'. 'this' may be a branch or
333 // a PC-relative addressing instruction.
334 void SetImmPCOffsetTarget(Instruction* target);
335 // Patch a literal load instruction to load from 'source'.
336 void SetImmLLiteral(Instruction* source);
337
338 uint8_t* LiteralAddress() {
339 int offset = ImmLLiteral() << kLiteralEntrySizeLog2;
340 return reinterpret_cast<uint8_t*>(this) + offset;
341 }
342
343 uint32_t Literal32() {
344 uint32_t literal;
345 memcpy(&literal, LiteralAddress(), sizeof(literal));
346
347 return literal;
348 }
349
350 uint64_t Literal64() {
351 uint64_t literal;
352 memcpy(&literal, LiteralAddress(), sizeof(literal));
353
354 return literal;
355 }
356
357 float LiteralFP32() {
358 return rawbits_to_float(Literal32());
359 }
360
361 double LiteralFP64() {
362 return rawbits_to_double(Literal64());
363 }
364
365 Instruction* NextInstruction() {
366 return this + kInstructionSize;
367 }
368
369 Instruction* InstructionAtOffset(int64_t offset) {
370 ASSERT(IsAligned(reinterpret_cast<uintptr_t>(this) + offset,
371 kInstructionSize));
372 return this + offset;
373 }
374
375 template<typename T> static Instruction* Cast(T src) {
376 return reinterpret_cast<Instruction*>(src);
377 }
378
379
380 void SetPCRelImmTarget(Instruction* target);
381 void SetBranchImmTarget(Instruction* target);
382 };
383
384
385 // Where Instruction looks at instructions generated by the Assembler,
386 // InstructionSequence looks at instructions sequences generated by the
387 // MacroAssembler.
388 class InstructionSequence : public Instruction {
389 public:
390 static InstructionSequence* At(Address address) {
391 return reinterpret_cast<InstructionSequence*>(address);
392 }
393
394 // Sequences generated by MacroAssembler::InlineData().
395 bool IsInlineData() const;
396 uint64_t InlineData() const;
397 };
398
399
400 // Simulator/Debugger debug instructions ---------------------------------------
401 // Each debug marker is represented by a HLT instruction. The immediate comment
402 // field in the instruction is used to identify the type of debug marker. Each
403 // marker encodes arguments in a different way, as described below.
404
405 // Indicate to the Debugger that the instruction is a redirected call.
406 const Instr kImmExceptionIsRedirectedCall = 0xca11;
407
408 // Represent unreachable code. This is used as a guard in parts of the code that
409 // should not be reachable, such as in data encoded inline in the instructions.
410 const Instr kImmExceptionIsUnreachable = 0xdebf;
411
412 // A pseudo 'printf' instruction. The arguments will be passed to the platform
413 // printf method.
414 const Instr kImmExceptionIsPrintf = 0xdeb1;
415 // Parameters are stored in A64 registers as if the printf pseudo-instruction
416 // was a call to the real printf method:
417 //
418 // x0: The format string, then either of:
419 // x1-x7: Optional arguments.
420 // d0-d7: Optional arguments.
421 //
422 // Floating-point and integer arguments are passed in separate sets of
423 // registers in AAPCS64 (even for varargs functions), so it is not possible to
424 // determine the type of location of each arguments without some information
425 // about the values that were passed in. This information could be retrieved
426 // from the printf format string, but the format string is not trivial to
427 // parse so we encode the relevant information with the HLT instruction.
428 // - Type
429 // Either kRegister or kFPRegister, but stored as a uint32_t because there's
430 // no way to guarantee the size of the CPURegister::RegisterType enum.
431 const unsigned kPrintfTypeOffset = 1 * kInstructionSize;
432 const unsigned kPrintfLength = 2 * kInstructionSize;
433
434 // A pseudo 'debug' instruction.
435 const Instr kImmExceptionIsDebug = 0xdeb0;
436 // Parameters are inlined in the code after a debug pseudo-instruction:
437 // - Debug code.
438 // - Debug parameters.
439 // - Debug message string. This is a NULL-terminated ASCII string, padded to
440 // kInstructionSize so that subsequent instructions are correctly aligned.
441 // - A kImmExceptionIsUnreachable marker, to catch accidental execution of the
442 // string data.
443 const unsigned kDebugCodeOffset = 1 * kInstructionSize;
444 const unsigned kDebugParamsOffset = 2 * kInstructionSize;
445 const unsigned kDebugMessageOffset = 3 * kInstructionSize;
446
447 // Debug parameters.
448 // Used without a TRACE_ option, the Debugger will print the arguments only
449 // once. Otherwise TRACE_ENABLE and TRACE_DISABLE will enable or disable tracing
450 // before every instruction for the specified LOG_ parameters.
451 //
452 // TRACE_OVERRIDE enables the specified LOG_ parameters, and disabled any
453 // others that were not specified.
454 //
455 // For example:
456 //
457 // __ debug("print registers and fp registers", 0, LOG_REGS | LOG_FP_REGS);
458 // will print the registers and fp registers only once.
459 //
460 // __ debug("trace disasm", 1, TRACE_ENABLE | LOG_DISASM);
461 // starts disassembling the code.
462 //
463 // __ debug("trace rets", 2, TRACE_ENABLE | LOG_REGS);
464 // adds the general purpose registers to the trace.
465 //
466 // __ debug("stop regs", 3, TRACE_DISABLE | LOG_REGS);
467 // stops tracing the registers.
468 const unsigned kDebuggerTracingDirectivesMask = 3 << 6;
469 enum DebugParameters {
470 NO_PARAM = 0,
471 BREAK = 1 << 0,
472 LOG_DISASM = 1 << 1, // Use only with TRACE. Disassemble the code.
473 LOG_REGS = 1 << 2, // Log general purpose registers.
474 LOG_FP_REGS = 1 << 3, // Log floating-point registers.
475 LOG_SYS_REGS = 1 << 4, // Log the status flags.
476 LOG_WRITE = 1 << 5, // Log any memory write.
477
478 LOG_STATE = LOG_REGS | LOG_FP_REGS | LOG_SYS_REGS,
479 LOG_ALL = LOG_DISASM | LOG_STATE | LOG_WRITE,
480
481 // Trace control.
482 TRACE_ENABLE = 1 << 6,
483 TRACE_DISABLE = 2 << 6,
484 TRACE_OVERRIDE = 3 << 6
485 };
486
487
488 } } // namespace v8::internal
489
490
491 #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