1 // Copyright 2015, ARM Limited
2 // All rights reserved.
3 //
4 // Redistribution and use in source and binary forms, with or without
5 // modification, are permitted provided that the following conditions are met:
6 //
7 // * Redistributions of source code must retain the above copyright notice,
8 // this list of conditions and the following disclaimer.
9 // * Redistributions in binary form must reproduce the above copyright notice,
10 // this list of conditions and the following disclaimer in the documentation
11 // and/or other materials provided with the distribution.
12 // * Neither the name of ARM Limited nor the names of its contributors may be
13 // used to endorse or promote products derived from this software without
14 // specific prior written permission.
15 //
16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS CONTRIBUTORS "AS IS" AND
17 // ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 // WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
20 // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21 // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
22 // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
23 // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
24 // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
25 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26
27 #ifndef VIXL_A64_SIMULATOR_A64_H_
28 #define VIXL_A64_SIMULATOR_A64_H_
29
30 #include "js-config.h"
31
32 #ifdef JS_SIMULATOR_ARM64
33
34 #include "mozilla/Vector.h"
35
36 #include "jsalloc.h"
37
38 #include "jit/arm64/vixl/Assembler-vixl.h"
39 #include "jit/arm64/vixl/Disasm-vixl.h"
40 #include "jit/arm64/vixl/Globals-vixl.h"
41 #include "jit/arm64/vixl/Instructions-vixl.h"
42 #include "jit/arm64/vixl/Instrument-vixl.h"
43 #include "jit/arm64/vixl/Utils-vixl.h"
44
45 #include "jit/IonTypes.h"
46 #include "vm/PosixNSPR.h"
47
48 #define JS_CHECK_SIMULATOR_RECURSION_WITH_EXTRA(cx, extra, onerror) \
49 JS_BEGIN_MACRO \
50 if (cx->mainThread().simulator()->overRecursedWithExtra(extra)) { \
51 js::ReportOverRecursed(cx); \
52 onerror; \
53 } \
54 JS_END_MACRO
55
56 namespace vixl {
57
58 // Debug instructions.
59 //
60 // VIXL's macro-assembler and simulator support a few pseudo instructions to
61 // make debugging easier. These pseudo instructions do not exist on real
62 // hardware.
63 //
64 // TODO: Provide controls to prevent the macro assembler from emitting
65 // pseudo-instructions. This is important for ahead-of-time compilers, where the
66 // macro assembler is built with USE_SIMULATOR but the code will eventually be
67 // run on real hardware.
68 //
69 // TODO: Also consider allowing these pseudo-instructions to be disabled in the
70 // simulator, so that users can check that the input is a valid native code.
71 // (This isn't possible in all cases. Printf won't work, for example.)
72 //
73 // Each debug pseudo instruction is represented by a HLT instruction. The HLT
74 // immediate field is used to identify the type of debug pseudo instruction.
75
76 enum DebugHltOpcodes {
77 kUnreachableOpcode = 0xdeb0,
78 kPrintfOpcode,
79 kTraceOpcode,
80 kLogOpcode,
81 // Aliases.
82 kDebugHltFirstOpcode = kUnreachableOpcode,
83 kDebugHltLastOpcode = kLogOpcode
84 };
85
86 // Each pseudo instruction uses a custom encoding for additional arguments, as
87 // described below.
88
89 // Unreachable - kUnreachableOpcode
90 //
91 // Instruction which should never be executed. This is used as a guard in parts
92 // of the code that should not be reachable, such as in data encoded inline in
93 // the instructions.
94
95 // Printf - kPrintfOpcode
96 // - arg_count: The number of arguments.
97 // - arg_pattern: A set of PrintfArgPattern values, packed into two-bit fields.
98 //
99 // Simulate a call to printf.
100 //
101 // Floating-point and integer arguments are passed in separate sets of registers
102 // in AAPCS64 (even for varargs functions), so it is not possible to determine
103 // the type of each argument without some information about the values that were
104 // passed in. This information could be retrieved from the printf format string,
105 // but the format string is not trivial to parse so we encode the relevant
106 // information with the HLT instruction.
107 //
108 // Also, the following registers are populated (as if for a native A64 call):
109 // x0: The format string
110 // x1-x7: Optional arguments, if type == CPURegister::kRegister
111 // d0-d7: Optional arguments, if type == CPURegister::kFPRegister
112 const unsigned kPrintfArgCountOffset = 1 * kInstructionSize;
113 const unsigned kPrintfArgPatternListOffset = 2 * kInstructionSize;
114 const unsigned kPrintfLength = 3 * kInstructionSize;
115
116 const unsigned kPrintfMaxArgCount = 4;
117
118 // The argument pattern is a set of two-bit-fields, each with one of the
119 // following values:
120 enum PrintfArgPattern {
121 kPrintfArgW = 1,
122 kPrintfArgX = 2,
123 // There is no kPrintfArgS because floats are always converted to doubles in C
124 // varargs calls.
125 kPrintfArgD = 3
126 };
127 static const unsigned kPrintfArgPatternBits = 2;
128
129 // Trace - kTraceOpcode
130 // - parameter: TraceParameter stored as a uint32_t
131 // - command: TraceCommand stored as a uint32_t
132 //
133 // Allow for trace management in the generated code. This enables or disables
134 // automatic tracing of the specified information for every simulated
135 // instruction.
136 const unsigned kTraceParamsOffset = 1 * kInstructionSize;
137 const unsigned kTraceCommandOffset = 2 * kInstructionSize;
138 const unsigned kTraceLength = 3 * kInstructionSize;
139
140 // Trace parameters.
141 enum TraceParameters {
142 LOG_DISASM = 1 << 0, // Log disassembly.
143 LOG_REGS = 1 << 1, // Log general purpose registers.
144 LOG_VREGS = 1 << 2, // Log NEON and floating-point registers.
145 LOG_SYSREGS = 1 << 3, // Log the flags and system registers.
146 LOG_WRITE = 1 << 4, // Log writes to memory.
147
148 LOG_NONE = 0,
149 LOG_STATE = LOG_REGS | LOG_VREGS | LOG_SYSREGS,
150 LOG_ALL = LOG_DISASM | LOG_STATE | LOG_WRITE
151 };
152
153 // Trace commands.
154 enum TraceCommand {
155 TRACE_ENABLE = 1,
156 TRACE_DISABLE = 2
157 };
158
159 // Log - kLogOpcode
160 // - parameter: TraceParameter stored as a uint32_t
161 //
162 // Print the specified information once. This mechanism is separate from Trace.
163 // In particular, _all_ of the specified registers are printed, rather than just
164 // the registers that the instruction writes.
165 //
166 // Any combination of the TraceParameters values can be used, except that
167 // LOG_DISASM is not supported for Log.
168 const unsigned kLogParamsOffset = 1 * kInstructionSize;
169 const unsigned kLogLength = 2 * kInstructionSize;
170
171
172 // Assemble the specified IEEE-754 components into the target type and apply
173 // appropriate rounding.
174 // sign: 0 = positive, 1 = negative
175 // exponent: Unbiased IEEE-754 exponent.
176 // mantissa: The mantissa of the input. The top bit (which is not encoded for
177 // normal IEEE-754 values) must not be omitted. This bit has the
178 // value 'pow(2, exponent)'.
179 //
180 // The input value is assumed to be a normalized value. That is, the input may
181 // not be infinity or NaN. If the source value is subnormal, it must be
182 // normalized before calling this function such that the highest set bit in the
183 // mantissa has the value 'pow(2, exponent)'.
184 //
185 // Callers should use FPRoundToFloat or FPRoundToDouble directly, rather than
186 // calling a templated FPRound.
187 template <class T, int ebits, int mbits>
FPRound(int64_t sign,int64_t exponent,uint64_t mantissa,FPRounding round_mode)188 T FPRound(int64_t sign, int64_t exponent, uint64_t mantissa,
189 FPRounding round_mode) {
190 VIXL_ASSERT((sign == 0) || (sign == 1));
191
192 // Only FPTieEven and FPRoundOdd rounding modes are implemented.
193 VIXL_ASSERT((round_mode == FPTieEven) || (round_mode == FPRoundOdd));
194
195 // Rounding can promote subnormals to normals, and normals to infinities. For
196 // example, a double with exponent 127 (FLT_MAX_EXP) would appear to be
197 // encodable as a float, but rounding based on the low-order mantissa bits
198 // could make it overflow. With ties-to-even rounding, this value would become
199 // an infinity.
200
201 // ---- Rounding Method ----
202 //
203 // The exponent is irrelevant in the rounding operation, so we treat the
204 // lowest-order bit that will fit into the result ('onebit') as having
205 // the value '1'. Similarly, the highest-order bit that won't fit into
206 // the result ('halfbit') has the value '0.5'. The 'point' sits between
207 // 'onebit' and 'halfbit':
208 //
209 // These bits fit into the result.
210 // |---------------------|
211 // mantissa = 0bxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
212 // ||
213 // / |
214 // / halfbit
215 // onebit
216 //
217 // For subnormal outputs, the range of representable bits is smaller and
218 // the position of onebit and halfbit depends on the exponent of the
219 // input, but the method is otherwise similar.
220 //
221 // onebit(frac)
222 // |
223 // | halfbit(frac) halfbit(adjusted)
224 // | / /
225 // | | |
226 // 0b00.0 (exact) -> 0b00.0 (exact) -> 0b00
227 // 0b00.0... -> 0b00.0... -> 0b00
228 // 0b00.1 (exact) -> 0b00.0111..111 -> 0b00
229 // 0b00.1... -> 0b00.1... -> 0b01
230 // 0b01.0 (exact) -> 0b01.0 (exact) -> 0b01
231 // 0b01.0... -> 0b01.0... -> 0b01
232 // 0b01.1 (exact) -> 0b01.1 (exact) -> 0b10
233 // 0b01.1... -> 0b01.1... -> 0b10
234 // 0b10.0 (exact) -> 0b10.0 (exact) -> 0b10
235 // 0b10.0... -> 0b10.0... -> 0b10
236 // 0b10.1 (exact) -> 0b10.0111..111 -> 0b10
237 // 0b10.1... -> 0b10.1... -> 0b11
238 // 0b11.0 (exact) -> 0b11.0 (exact) -> 0b11
239 // ... / | / |
240 // / | / |
241 // / |
242 // adjusted = frac - (halfbit(mantissa) & ~onebit(frac)); / |
243 //
244 // mantissa = (mantissa >> shift) + halfbit(adjusted);
245
246 static const int mantissa_offset = 0;
247 static const int exponent_offset = mantissa_offset + mbits;
248 static const int sign_offset = exponent_offset + ebits;
249 VIXL_ASSERT(sign_offset == (sizeof(T) * 8 - 1));
250
251 // Bail out early for zero inputs.
252 if (mantissa == 0) {
253 return static_cast<T>(sign << sign_offset);
254 }
255
256 // If all bits in the exponent are set, the value is infinite or NaN.
257 // This is true for all binary IEEE-754 formats.
258 static const int infinite_exponent = (1 << ebits) - 1;
259 static const int max_normal_exponent = infinite_exponent - 1;
260
261 // Apply the exponent bias to encode it for the result. Doing this early makes
262 // it easy to detect values that will be infinite or subnormal.
263 exponent += max_normal_exponent >> 1;
264
265 if (exponent > max_normal_exponent) {
266 // Overflow: the input is too large for the result type to represent.
267 if (round_mode == FPTieEven) {
268 // FPTieEven rounding mode handles overflows using infinities.
269 exponent = infinite_exponent;
270 mantissa = 0;
271 } else {
272 VIXL_ASSERT(round_mode == FPRoundOdd);
273 // FPRoundOdd rounding mode handles overflows using the largest magnitude
274 // normal number.
275 exponent = max_normal_exponent;
276 mantissa = (UINT64_C(1) << exponent_offset) - 1;
277 }
278 return static_cast<T>((sign << sign_offset) |
279 (exponent << exponent_offset) |
280 (mantissa << mantissa_offset));
281 }
282
283 // Calculate the shift required to move the top mantissa bit to the proper
284 // place in the destination type.
285 const int highest_significant_bit = 63 - CountLeadingZeros(mantissa);
286 int shift = highest_significant_bit - mbits;
287
288 if (exponent <= 0) {
289 // The output will be subnormal (before rounding).
290 // For subnormal outputs, the shift must be adjusted by the exponent. The +1
291 // is necessary because the exponent of a subnormal value (encoded as 0) is
292 // the same as the exponent of the smallest normal value (encoded as 1).
293 shift += -exponent + 1;
294
295 // Handle inputs that would produce a zero output.
296 //
297 // Shifts higher than highest_significant_bit+1 will always produce a zero
298 // result. A shift of exactly highest_significant_bit+1 might produce a
299 // non-zero result after rounding.
300 if (shift > (highest_significant_bit + 1)) {
301 if (round_mode == FPTieEven) {
302 // The result will always be +/-0.0.
303 return static_cast<T>(sign << sign_offset);
304 } else {
305 VIXL_ASSERT(round_mode == FPRoundOdd);
306 VIXL_ASSERT(mantissa != 0);
307 // For FPRoundOdd, if the mantissa is too small to represent and
308 // non-zero return the next "odd" value.
309 return static_cast<T>((sign << sign_offset) | 1);
310 }
311 }
312
313 // Properly encode the exponent for a subnormal output.
314 exponent = 0;
315 } else {
316 // Clear the topmost mantissa bit, since this is not encoded in IEEE-754
317 // normal values.
318 mantissa &= ~(UINT64_C(1) << highest_significant_bit);
319 }
320
321 if (shift > 0) {
322 if (round_mode == FPTieEven) {
323 // We have to shift the mantissa to the right. Some precision is lost, so
324 // we need to apply rounding.
325 uint64_t onebit_mantissa = (mantissa >> (shift)) & 1;
326 uint64_t halfbit_mantissa = (mantissa >> (shift-1)) & 1;
327 uint64_t adjustment = (halfbit_mantissa & ~onebit_mantissa);
328 uint64_t adjusted = mantissa - adjustment;
329 T halfbit_adjusted = (adjusted >> (shift-1)) & 1;
330
331 T result = static_cast<T>((sign << sign_offset) |
332 (exponent << exponent_offset) |
333 ((mantissa >> shift) << mantissa_offset));
334
335 // A very large mantissa can overflow during rounding. If this happens,
336 // the exponent should be incremented and the mantissa set to 1.0
337 // (encoded as 0). Applying halfbit_adjusted after assembling the float
338 // has the nice side-effect that this case is handled for free.
339 //
340 // This also handles cases where a very large finite value overflows to
341 // infinity, or where a very large subnormal value overflows to become
342 // normal.
343 return result + halfbit_adjusted;
344 } else {
345 VIXL_ASSERT(round_mode == FPRoundOdd);
346 // If any bits at position halfbit or below are set, onebit (ie. the
347 // bottom bit of the resulting mantissa) must be set.
348 uint64_t fractional_bits = mantissa & ((UINT64_C(1) << shift) - 1);
349 if (fractional_bits != 0) {
350 mantissa |= UINT64_C(1) << shift;
351 }
352
353 return static_cast<T>((sign << sign_offset) |
354 (exponent << exponent_offset) |
355 ((mantissa >> shift) << mantissa_offset));
356 }
357 } else {
358 // We have to shift the mantissa to the left (or not at all). The input
359 // mantissa is exactly representable in the output mantissa, so apply no
360 // rounding correction.
361 return static_cast<T>((sign << sign_offset) |
362 (exponent << exponent_offset) |
363 ((mantissa << -shift) << mantissa_offset));
364 }
365 }
366
367
368 // Representation of memory, with typed getters and setters for access.
369 class Memory {
370 public:
371 template <typename T>
AddressUntag(T address)372 static T AddressUntag(T address) {
373 // Cast the address using a C-style cast. A reinterpret_cast would be
374 // appropriate, but it can't cast one integral type to another.
375 uint64_t bits = (uint64_t)address;
376 return (T)(bits & ~kAddressTagMask);
377 }
378
379 template <typename T, typename A>
Read(A address)380 static T Read(A address) {
381 T value;
382 address = AddressUntag(address);
383 VIXL_ASSERT((sizeof(value) == 1) || (sizeof(value) == 2) ||
384 (sizeof(value) == 4) || (sizeof(value) == 8) ||
385 (sizeof(value) == 16));
386 memcpy(&value, reinterpret_cast<const char *>(address), sizeof(value));
387 return value;
388 }
389
390 template <typename T, typename A>
Write(A address,T value)391 static void Write(A address, T value) {
392 address = AddressUntag(address);
393 VIXL_ASSERT((sizeof(value) == 1) || (sizeof(value) == 2) ||
394 (sizeof(value) == 4) || (sizeof(value) == 8) ||
395 (sizeof(value) == 16));
396 memcpy(reinterpret_cast<char *>(address), &value, sizeof(value));
397 }
398 };
399
400 // Represent a register (r0-r31, v0-v31).
401 template<int kSizeInBytes>
402 class SimRegisterBase {
403 public:
SimRegisterBase()404 SimRegisterBase() : written_since_last_log_(false) {}
405
406 // Write the specified value. The value is zero-extended if necessary.
407 template<typename T>
Set(T new_value)408 void Set(T new_value) {
409 VIXL_STATIC_ASSERT(sizeof(new_value) <= kSizeInBytes);
410 if (sizeof(new_value) < kSizeInBytes) {
411 // All AArch64 registers are zero-extending.
412 memset(value_ + sizeof(new_value), 0, kSizeInBytes - sizeof(new_value));
413 }
414 memcpy(value_, &new_value, sizeof(new_value));
415 NotifyRegisterWrite();
416 }
417
418 // Insert a typed value into a register, leaving the rest of the register
419 // unchanged. The lane parameter indicates where in the register the value
420 // should be inserted, in the range [ 0, sizeof(value_) / sizeof(T) ), where
421 // 0 represents the least significant bits.
422 template<typename T>
Insert(int lane,T new_value)423 void Insert(int lane, T new_value) {
424 VIXL_ASSERT(lane >= 0);
425 VIXL_ASSERT((sizeof(new_value) +
426 (lane * sizeof(new_value))) <= kSizeInBytes);
427 memcpy(&value_[lane * sizeof(new_value)], &new_value, sizeof(new_value));
428 NotifyRegisterWrite();
429 }
430
431 // Read the value as the specified type. The value is truncated if necessary.
432 template<typename T>
433 T Get(int lane = 0) const {
434 T result;
435 VIXL_ASSERT(lane >= 0);
436 VIXL_ASSERT((sizeof(result) + (lane * sizeof(result))) <= kSizeInBytes);
437 memcpy(&result, &value_[lane * sizeof(result)], sizeof(result));
438 return result;
439 }
440
441 // TODO: Make this return a map of updated bytes, so that we can highlight
442 // updated lanes for load-and-insert. (That never happens for scalar code, but
443 // NEON has some instructions that can update individual lanes.)
WrittenSinceLastLog()444 bool WrittenSinceLastLog() const {
445 return written_since_last_log_;
446 }
447
NotifyRegisterLogged()448 void NotifyRegisterLogged() {
449 written_since_last_log_ = false;
450 }
451
452 protected:
453 uint8_t value_[kSizeInBytes];
454
455 // Helpers to aid with register tracing.
456 bool written_since_last_log_;
457
NotifyRegisterWrite()458 void NotifyRegisterWrite() {
459 written_since_last_log_ = true;
460 }
461 };
462 typedef SimRegisterBase<kXRegSizeInBytes> SimRegister; // r0-r31
463 typedef SimRegisterBase<kQRegSizeInBytes> SimVRegister; // v0-v31
464
465 // Representation of a vector register, with typed getters and setters for lanes
466 // and additional information to represent lane state.
467 class LogicVRegister {
468 public:
LogicVRegister(SimVRegister & other)469 inline LogicVRegister(SimVRegister& other) // NOLINT
470 : register_(other) {
471 for (unsigned i = 0; i < sizeof(saturated_) / sizeof(saturated_[0]); i++) {
472 saturated_[i] = kNotSaturated;
473 }
474 for (unsigned i = 0; i < sizeof(round_) / sizeof(round_[0]); i++) {
475 round_[i] = 0;
476 }
477 }
478
Int(VectorFormat vform,int index)479 int64_t Int(VectorFormat vform, int index) const {
480 int64_t element;
481 switch (LaneSizeInBitsFromFormat(vform)) {
482 case 8: element = register_.Get<int8_t>(index); break;
483 case 16: element = register_.Get<int16_t>(index); break;
484 case 32: element = register_.Get<int32_t>(index); break;
485 case 64: element = register_.Get<int64_t>(index); break;
486 default: VIXL_UNREACHABLE(); return 0;
487 }
488 return element;
489 }
490
Uint(VectorFormat vform,int index)491 uint64_t Uint(VectorFormat vform, int index) const {
492 uint64_t element;
493 switch (LaneSizeInBitsFromFormat(vform)) {
494 case 8: element = register_.Get<uint8_t>(index); break;
495 case 16: element = register_.Get<uint16_t>(index); break;
496 case 32: element = register_.Get<uint32_t>(index); break;
497 case 64: element = register_.Get<uint64_t>(index); break;
498 default: VIXL_UNREACHABLE(); return 0;
499 }
500 return element;
501 }
502
IntLeftJustified(VectorFormat vform,int index)503 int64_t IntLeftJustified(VectorFormat vform, int index) const {
504 return Int(vform, index) << (64 - LaneSizeInBitsFromFormat(vform));
505 }
506
UintLeftJustified(VectorFormat vform,int index)507 uint64_t UintLeftJustified(VectorFormat vform, int index) const {
508 return Uint(vform, index) << (64 - LaneSizeInBitsFromFormat(vform));
509 }
510
SetInt(VectorFormat vform,int index,int64_t value)511 void SetInt(VectorFormat vform, int index, int64_t value) const {
512 switch (LaneSizeInBitsFromFormat(vform)) {
513 case 8: register_.Insert(index, static_cast<int8_t>(value)); break;
514 case 16: register_.Insert(index, static_cast<int16_t>(value)); break;
515 case 32: register_.Insert(index, static_cast<int32_t>(value)); break;
516 case 64: register_.Insert(index, static_cast<int64_t>(value)); break;
517 default: VIXL_UNREACHABLE(); return;
518 }
519 }
520
SetUint(VectorFormat vform,int index,uint64_t value)521 void SetUint(VectorFormat vform, int index, uint64_t value) const {
522 switch (LaneSizeInBitsFromFormat(vform)) {
523 case 8: register_.Insert(index, static_cast<uint8_t>(value)); break;
524 case 16: register_.Insert(index, static_cast<uint16_t>(value)); break;
525 case 32: register_.Insert(index, static_cast<uint32_t>(value)); break;
526 case 64: register_.Insert(index, static_cast<uint64_t>(value)); break;
527 default: VIXL_UNREACHABLE(); return;
528 }
529 }
530
ReadUintFromMem(VectorFormat vform,int index,uint64_t addr)531 void ReadUintFromMem(VectorFormat vform, int index, uint64_t addr) const {
532 switch (LaneSizeInBitsFromFormat(vform)) {
533 case 8: register_.Insert(index, Memory::Read<uint8_t>(addr)); break;
534 case 16: register_.Insert(index, Memory::Read<uint16_t>(addr)); break;
535 case 32: register_.Insert(index, Memory::Read<uint32_t>(addr)); break;
536 case 64: register_.Insert(index, Memory::Read<uint64_t>(addr)); break;
537 default: VIXL_UNREACHABLE(); return;
538 }
539 }
540
WriteUintToMem(VectorFormat vform,int index,uint64_t addr)541 void WriteUintToMem(VectorFormat vform, int index, uint64_t addr) const {
542 uint64_t value = Uint(vform, index);
543 switch (LaneSizeInBitsFromFormat(vform)) {
544 case 8: Memory::Write(addr, static_cast<uint8_t>(value)); break;
545 case 16: Memory::Write(addr, static_cast<uint16_t>(value)); break;
546 case 32: Memory::Write(addr, static_cast<uint32_t>(value)); break;
547 case 64: Memory::Write(addr, value); break;
548 }
549 }
550
551 template <typename T>
Float(int index)552 T Float(int index) const {
553 return register_.Get<T>(index);
554 }
555
556 template <typename T>
SetFloat(int index,T value)557 void SetFloat(int index, T value) const {
558 register_.Insert(index, value);
559 }
560
561 // When setting a result in a register of size less than Q, the top bits of
562 // the Q register must be cleared.
ClearForWrite(VectorFormat vform)563 void ClearForWrite(VectorFormat vform) const {
564 unsigned size = RegisterSizeInBytesFromFormat(vform);
565 for (unsigned i = size; i < kQRegSizeInBytes; i++) {
566 SetUint(kFormat16B, i, 0);
567 }
568 }
569
570 // Saturation state for each lane of a vector.
571 enum Saturation {
572 kNotSaturated = 0,
573 kSignedSatPositive = 1 << 0,
574 kSignedSatNegative = 1 << 1,
575 kSignedSatMask = kSignedSatPositive | kSignedSatNegative,
576 kSignedSatUndefined = kSignedSatMask,
577 kUnsignedSatPositive = 1 << 2,
578 kUnsignedSatNegative = 1 << 3,
579 kUnsignedSatMask = kUnsignedSatPositive | kUnsignedSatNegative,
580 kUnsignedSatUndefined = kUnsignedSatMask
581 };
582
583 // Getters for saturation state.
GetSignedSaturation(int index)584 Saturation GetSignedSaturation(int index) {
585 return static_cast<Saturation>(saturated_[index] & kSignedSatMask);
586 }
587
GetUnsignedSaturation(int index)588 Saturation GetUnsignedSaturation(int index) {
589 return static_cast<Saturation>(saturated_[index] & kUnsignedSatMask);
590 }
591
592 // Setters for saturation state.
ClearSat(int index)593 void ClearSat(int index) {
594 saturated_[index] = kNotSaturated;
595 }
596
SetSignedSat(int index,bool positive)597 void SetSignedSat(int index, bool positive) {
598 SetSatFlag(index, positive ? kSignedSatPositive : kSignedSatNegative);
599 }
600
SetUnsignedSat(int index,bool positive)601 void SetUnsignedSat(int index, bool positive) {
602 SetSatFlag(index, positive ? kUnsignedSatPositive : kUnsignedSatNegative);
603 }
604
SetSatFlag(int index,Saturation sat)605 void SetSatFlag(int index, Saturation sat) {
606 saturated_[index] = static_cast<Saturation>(saturated_[index] | sat);
607 VIXL_ASSERT((sat & kUnsignedSatMask) != kUnsignedSatUndefined);
608 VIXL_ASSERT((sat & kSignedSatMask) != kSignedSatUndefined);
609 }
610
611 // Saturate lanes of a vector based on saturation state.
SignedSaturate(VectorFormat vform)612 LogicVRegister& SignedSaturate(VectorFormat vform) {
613 for (int i = 0; i < LaneCountFromFormat(vform); i++) {
614 Saturation sat = GetSignedSaturation(i);
615 if (sat == kSignedSatPositive) {
616 SetInt(vform, i, MaxIntFromFormat(vform));
617 } else if (sat == kSignedSatNegative) {
618 SetInt(vform, i, MinIntFromFormat(vform));
619 }
620 }
621 return *this;
622 }
623
UnsignedSaturate(VectorFormat vform)624 LogicVRegister& UnsignedSaturate(VectorFormat vform) {
625 for (int i = 0; i < LaneCountFromFormat(vform); i++) {
626 Saturation sat = GetUnsignedSaturation(i);
627 if (sat == kUnsignedSatPositive) {
628 SetUint(vform, i, MaxUintFromFormat(vform));
629 } else if (sat == kUnsignedSatNegative) {
630 SetUint(vform, i, 0);
631 }
632 }
633 return *this;
634 }
635
636 // Getter for rounding state.
GetRounding(int index)637 bool GetRounding(int index) {
638 return round_[index];
639 }
640
641 // Setter for rounding state.
SetRounding(int index,bool round)642 void SetRounding(int index, bool round) {
643 round_[index] = round;
644 }
645
646 // Round lanes of a vector based on rounding state.
Round(VectorFormat vform)647 LogicVRegister& Round(VectorFormat vform) {
648 for (int i = 0; i < LaneCountFromFormat(vform); i++) {
649 SetInt(vform, i, Int(vform, i) + (GetRounding(i) ? 1 : 0));
650 }
651 return *this;
652 }
653
654 // Unsigned halve lanes of a vector, and use the saturation state to set the
655 // top bit.
Uhalve(VectorFormat vform)656 LogicVRegister& Uhalve(VectorFormat vform) {
657 for (int i = 0; i < LaneCountFromFormat(vform); i++) {
658 uint64_t val = Uint(vform, i);
659 SetRounding(i, (val & 1) == 1);
660 val >>= 1;
661 if (GetUnsignedSaturation(i) != kNotSaturated) {
662 // If the operation causes unsigned saturation, the bit shifted into the
663 // most significant bit must be set.
664 val |= (MaxUintFromFormat(vform) >> 1) + 1;
665 }
666 SetInt(vform, i, val);
667 }
668 return *this;
669 }
670
671 // Signed halve lanes of a vector, and use the carry state to set the top bit.
Halve(VectorFormat vform)672 LogicVRegister& Halve(VectorFormat vform) {
673 for (int i = 0; i < LaneCountFromFormat(vform); i++) {
674 int64_t val = Int(vform, i);
675 SetRounding(i, (val & 1) == 1);
676 val >>= 1;
677 if (GetSignedSaturation(i) != kNotSaturated) {
678 // If the operation causes signed saturation, the sign bit must be
679 // inverted.
680 val ^= (MaxUintFromFormat(vform) >> 1) + 1;
681 }
682 SetInt(vform, i, val);
683 }
684 return *this;
685 }
686
687 private:
688 SimVRegister& register_;
689
690 // Allocate one saturation state entry per lane; largest register is type Q,
691 // and lanes can be a minimum of one byte wide.
692 Saturation saturated_[kQRegSizeInBytes];
693
694 // Allocate one rounding state entry per lane.
695 bool round_[kQRegSizeInBytes];
696 };
697
698 // The proper way to initialize a simulated system register (such as NZCV) is as
699 // follows:
700 // SimSystemRegister nzcv = SimSystemRegister::DefaultValueFor(NZCV);
701 class SimSystemRegister {
702 public:
703 // The default constructor represents a register which has no writable bits.
704 // It is not possible to set its value to anything other than 0.
SimSystemRegister()705 SimSystemRegister() : value_(0), write_ignore_mask_(0xffffffff) { }
706
RawValue()707 uint32_t RawValue() const {
708 return value_;
709 }
710
SetRawValue(uint32_t new_value)711 void SetRawValue(uint32_t new_value) {
712 value_ = (value_ & write_ignore_mask_) | (new_value & ~write_ignore_mask_);
713 }
714
Bits(int msb,int lsb)715 uint32_t Bits(int msb, int lsb) const {
716 return unsigned_bitextract_32(msb, lsb, value_);
717 }
718
SignedBits(int msb,int lsb)719 int32_t SignedBits(int msb, int lsb) const {
720 return signed_bitextract_32(msb, lsb, value_);
721 }
722
723 void SetBits(int msb, int lsb, uint32_t bits);
724
725 // Default system register values.
726 static SimSystemRegister DefaultValueFor(SystemRegister id);
727
728 #define DEFINE_GETTER(Name, HighBit, LowBit, Func) \
729 uint32_t Name() const { return Func(HighBit, LowBit); } \
730 void Set##Name(uint32_t bits) { SetBits(HighBit, LowBit, bits); }
731 #define DEFINE_WRITE_IGNORE_MASK(Name, Mask) \
732 static const uint32_t Name##WriteIgnoreMask = ~static_cast<uint32_t>(Mask);
733
SYSTEM_REGISTER_FIELDS_LIST(DEFINE_GETTER,DEFINE_WRITE_IGNORE_MASK)734 SYSTEM_REGISTER_FIELDS_LIST(DEFINE_GETTER, DEFINE_WRITE_IGNORE_MASK)
735
736 #undef DEFINE_ZERO_BITS
737 #undef DEFINE_GETTER
738
739 protected:
740 // Most system registers only implement a few of the bits in the word. Other
741 // bits are "read-as-zero, write-ignored". The write_ignore_mask argument
742 // describes the bits which are not modifiable.
743 SimSystemRegister(uint32_t value, uint32_t write_ignore_mask)
744 : value_(value), write_ignore_mask_(write_ignore_mask) { }
745
746 uint32_t value_;
747 uint32_t write_ignore_mask_;
748 };
749
750
751 class SimExclusiveLocalMonitor {
752 public:
SimExclusiveLocalMonitor()753 SimExclusiveLocalMonitor() : kSkipClearProbability(8), seed_(0x87654321) {
754 Clear();
755 }
756
757 // Clear the exclusive monitor (like clrex).
Clear()758 void Clear() {
759 address_ = 0;
760 size_ = 0;
761 }
762
763 // Clear the exclusive monitor most of the time.
MaybeClear()764 void MaybeClear() {
765 if ((seed_ % kSkipClearProbability) != 0) {
766 Clear();
767 }
768
769 // Advance seed_ using a simple linear congruential generator.
770 seed_ = (seed_ * 48271) % 2147483647;
771 }
772
773 // Mark the address range for exclusive access (like load-exclusive).
MarkExclusive(uint64_t address,size_t size)774 void MarkExclusive(uint64_t address, size_t size) {
775 address_ = address;
776 size_ = size;
777 }
778
779 // Return true if the address range is marked (like store-exclusive).
780 // This helper doesn't implicitly clear the monitor.
IsExclusive(uint64_t address,size_t size)781 bool IsExclusive(uint64_t address, size_t size) {
782 VIXL_ASSERT(size > 0);
783 // Be pedantic: Require both the address and the size to match.
784 return (size == size_) && (address == address_);
785 }
786
787 private:
788 uint64_t address_;
789 size_t size_;
790
791 const int kSkipClearProbability;
792 uint32_t seed_;
793 };
794
795
796 // We can't accurate simulate the global monitor since it depends on external
797 // influences. Instead, this implementation occasionally causes accesses to
798 // fail, according to kPassProbability.
799 class SimExclusiveGlobalMonitor {
800 public:
SimExclusiveGlobalMonitor()801 SimExclusiveGlobalMonitor() : kPassProbability(8), seed_(0x87654321) {}
802
IsExclusive(uint64_t address,size_t size)803 bool IsExclusive(uint64_t address, size_t size) {
804 USE(address, size);
805
806 bool pass = (seed_ % kPassProbability) != 0;
807 // Advance seed_ using a simple linear congruential generator.
808 seed_ = (seed_ * 48271) % 2147483647;
809 return pass;
810 }
811
812 private:
813 const int kPassProbability;
814 uint32_t seed_;
815 };
816
817 class Redirection;
818
819 class Simulator : public DecoderVisitor {
820 friend class AutoLockSimulatorCache;
821
822 public:
823 explicit Simulator(Decoder* decoder, FILE* stream = stdout);
824 ~Simulator();
825
826 // Moz changes.
827 void init(Decoder* decoder, FILE* stream);
828 static Simulator* Current();
829 static Simulator* Create();
830 static void Destroy(Simulator* sim);
831 uintptr_t stackLimit() const;
832 uintptr_t* addressOfStackLimit();
833 bool overRecursed(uintptr_t newsp = 0) const;
834 bool overRecursedWithExtra(uint32_t extra) const;
835 int64_t call(uint8_t* entry, int argument_count, ...);
836 void setRedirection(Redirection* redirection);
837 Redirection* redirection() const;
838 static void* RedirectNativeFunction(void* nativeFunction, js::jit::ABIFunctionType type);
839 void setGPR32Result(int32_t result);
840 void setGPR64Result(int64_t result);
841 void setFP32Result(float result);
842 void setFP64Result(double result);
843 void VisitCallRedirection(const Instruction* instr);
StackLimit()844 static inline uintptr_t StackLimit() {
845 return Simulator::Current()->stackLimit();
846 }
847
848 void ResetState();
849
850 // Run the simulator.
851 virtual void Run();
852 void RunFrom(const Instruction* first);
853
854 // Simulation helpers.
pc()855 const Instruction* pc() const { return pc_; }
get_pc()856 const Instruction* get_pc() const { return pc_; }
857
858 template <typename T>
get_pc_as()859 T get_pc_as() const { return reinterpret_cast<T>(const_cast<Instruction*>(pc())); }
860
set_pc(const Instruction * new_pc)861 void set_pc(const Instruction* new_pc) {
862 pc_ = Memory::AddressUntag(new_pc);
863 pc_modified_ = true;
864 }
865
866 void set_resume_pc(void* new_resume_pc);
867
increment_pc()868 void increment_pc() {
869 if (!pc_modified_) {
870 pc_ = pc_->NextInstruction();
871 }
872
873 pc_modified_ = false;
874 }
875
876 void ExecuteInstruction();
877
878 // Declare all Visitor functions.
879 #define DECLARE(A) virtual void Visit##A(const Instruction* instr);
VISITOR_LIST(DECLARE)880 VISITOR_LIST(DECLARE)
881 #undef DECLARE
882
883 // Integer register accessors.
884
885 // Basic accessor: Read the register as the specified type.
886 template<typename T>
887 T reg(unsigned code, Reg31Mode r31mode = Reg31IsZeroRegister) const {
888 VIXL_ASSERT(code < kNumberOfRegisters);
889 if ((code == 31) && (r31mode == Reg31IsZeroRegister)) {
890 T result;
891 memset(&result, 0, sizeof(result));
892 return result;
893 }
894 return registers_[code].Get<T>();
895 }
896
897 // Common specialized accessors for the reg() template.
898 int32_t wreg(unsigned code,
899 Reg31Mode r31mode = Reg31IsZeroRegister) const {
900 return reg<int32_t>(code, r31mode);
901 }
902
903 int64_t xreg(unsigned code,
904 Reg31Mode r31mode = Reg31IsZeroRegister) const {
905 return reg<int64_t>(code, r31mode);
906 }
907
908 // As above, with parameterized size and return type. The value is
909 // either zero-extended or truncated to fit, as required.
910 template<typename T>
911 T reg(unsigned size, unsigned code,
912 Reg31Mode r31mode = Reg31IsZeroRegister) const {
913 uint64_t raw;
914 switch (size) {
915 case kWRegSize: raw = reg<uint32_t>(code, r31mode); break;
916 case kXRegSize: raw = reg<uint64_t>(code, r31mode); break;
917 default:
918 VIXL_UNREACHABLE();
919 return 0;
920 }
921
922 T result;
923 VIXL_STATIC_ASSERT(sizeof(result) <= sizeof(raw));
924 // Copy the result and truncate to fit. This assumes a little-endian host.
925 memcpy(&result, &raw, sizeof(result));
926 return result;
927 }
928
929 // Use int64_t by default if T is not specified.
930 int64_t reg(unsigned size, unsigned code,
931 Reg31Mode r31mode = Reg31IsZeroRegister) const {
932 return reg<int64_t>(size, code, r31mode);
933 }
934
935 enum RegLogMode {
936 LogRegWrites,
937 NoRegLog
938 };
939
940 // Write 'value' into an integer register. The value is zero-extended. This
941 // behaviour matches AArch64 register writes.
942 template<typename T>
943 void set_reg(unsigned code, T value,
944 RegLogMode log_mode = LogRegWrites,
945 Reg31Mode r31mode = Reg31IsZeroRegister) {
946 VIXL_STATIC_ASSERT((sizeof(T) == kWRegSizeInBytes) ||
947 (sizeof(T) == kXRegSizeInBytes));
948 VIXL_ASSERT(code < kNumberOfRegisters);
949
950 if ((code == 31) && (r31mode == Reg31IsZeroRegister)) {
951 return;
952 }
953
954 registers_[code].Set(value);
955
956 if (log_mode == LogRegWrites) LogRegister(code, r31mode);
957 }
958
959 // Common specialized accessors for the set_reg() template.
960 void set_wreg(unsigned code, int32_t value,
961 RegLogMode log_mode = LogRegWrites,
962 Reg31Mode r31mode = Reg31IsZeroRegister) {
963 set_reg(code, value, log_mode, r31mode);
964 }
965
966 void set_xreg(unsigned code, int64_t value,
967 RegLogMode log_mode = LogRegWrites,
968 Reg31Mode r31mode = Reg31IsZeroRegister) {
969 set_reg(code, value, log_mode, r31mode);
970 }
971
972 // As above, with parameterized size and type. The value is either
973 // zero-extended or truncated to fit, as required.
974 template<typename T>
975 void set_reg(unsigned size, unsigned code, T value,
976 RegLogMode log_mode = LogRegWrites,
977 Reg31Mode r31mode = Reg31IsZeroRegister) {
978 // Zero-extend the input.
979 uint64_t raw = 0;
980 VIXL_STATIC_ASSERT(sizeof(value) <= sizeof(raw));
981 memcpy(&raw, &value, sizeof(value));
982
983 // Write (and possibly truncate) the value.
984 switch (size) {
985 case kWRegSize:
986 set_reg(code, static_cast<uint32_t>(raw), log_mode, r31mode);
987 break;
988 case kXRegSize:
989 set_reg(code, raw, log_mode, r31mode);
990 break;
991 default:
992 VIXL_UNREACHABLE();
993 return;
994 }
995 }
996
997 // Common specialized accessors for the set_reg() template.
998
999 // Commonly-used special cases.
1000 template<typename T>
set_lr(T value)1001 void set_lr(T value) {
1002 set_reg(kLinkRegCode, value);
1003 }
1004
1005 template<typename T>
set_sp(T value)1006 void set_sp(T value) {
1007 set_reg(31, value, LogRegWrites, Reg31IsStackPointer);
1008 }
1009
1010 // Vector register accessors.
1011 // These are equivalent to the integer register accessors, but for vector
1012 // registers.
1013
1014 // A structure for representing a 128-bit Q register.
1015 struct qreg_t { uint8_t val[kQRegSizeInBytes]; };
1016
1017 // Basic accessor: read the register as the specified type.
1018 template<typename T>
vreg(unsigned code)1019 T vreg(unsigned code) const {
1020 VIXL_STATIC_ASSERT((sizeof(T) == kBRegSizeInBytes) ||
1021 (sizeof(T) == kHRegSizeInBytes) ||
1022 (sizeof(T) == kSRegSizeInBytes) ||
1023 (sizeof(T) == kDRegSizeInBytes) ||
1024 (sizeof(T) == kQRegSizeInBytes));
1025 VIXL_ASSERT(code < kNumberOfVRegisters);
1026
1027 return vregisters_[code].Get<T>();
1028 }
1029
1030 // Common specialized accessors for the vreg() template.
breg(unsigned code)1031 int8_t breg(unsigned code) const {
1032 return vreg<int8_t>(code);
1033 }
1034
hreg(unsigned code)1035 int16_t hreg(unsigned code) const {
1036 return vreg<int16_t>(code);
1037 }
1038
sreg(unsigned code)1039 float sreg(unsigned code) const {
1040 return vreg<float>(code);
1041 }
1042
sreg_bits(unsigned code)1043 uint32_t sreg_bits(unsigned code) const {
1044 return vreg<uint32_t>(code);
1045 }
1046
dreg(unsigned code)1047 double dreg(unsigned code) const {
1048 return vreg<double>(code);
1049 }
1050
dreg_bits(unsigned code)1051 uint64_t dreg_bits(unsigned code) const {
1052 return vreg<uint64_t>(code);
1053 }
1054
qreg(unsigned code)1055 qreg_t qreg(unsigned code) const {
1056 return vreg<qreg_t>(code);
1057 }
1058
1059 // As above, with parameterized size and return type. The value is
1060 // either zero-extended or truncated to fit, as required.
1061 template<typename T>
vreg(unsigned size,unsigned code)1062 T vreg(unsigned size, unsigned code) const {
1063 uint64_t raw = 0;
1064 T result;
1065
1066 switch (size) {
1067 case kSRegSize: raw = vreg<uint32_t>(code); break;
1068 case kDRegSize: raw = vreg<uint64_t>(code); break;
1069 default:
1070 VIXL_UNREACHABLE();
1071 break;
1072 }
1073
1074 VIXL_STATIC_ASSERT(sizeof(result) <= sizeof(raw));
1075 // Copy the result and truncate to fit. This assumes a little-endian host.
1076 memcpy(&result, &raw, sizeof(result));
1077 return result;
1078 }
1079
vreg(unsigned code)1080 inline SimVRegister& vreg(unsigned code) {
1081 return vregisters_[code];
1082 }
1083
1084 // Basic accessor: Write the specified value.
1085 template<typename T>
1086 void set_vreg(unsigned code, T value,
1087 RegLogMode log_mode = LogRegWrites) {
1088 VIXL_STATIC_ASSERT((sizeof(value) == kBRegSizeInBytes) ||
1089 (sizeof(value) == kHRegSizeInBytes) ||
1090 (sizeof(value) == kSRegSizeInBytes) ||
1091 (sizeof(value) == kDRegSizeInBytes) ||
1092 (sizeof(value) == kQRegSizeInBytes));
1093 VIXL_ASSERT(code < kNumberOfVRegisters);
1094 vregisters_[code].Set(value);
1095
1096 if (log_mode == LogRegWrites) {
1097 LogVRegister(code, GetPrintRegisterFormat(value));
1098 }
1099 }
1100
1101 // Common specialized accessors for the set_vreg() template.
1102 void set_breg(unsigned code, int8_t value,
1103 RegLogMode log_mode = LogRegWrites) {
1104 set_vreg(code, value, log_mode);
1105 }
1106
1107 void set_hreg(unsigned code, int16_t value,
1108 RegLogMode log_mode = LogRegWrites) {
1109 set_vreg(code, value, log_mode);
1110 }
1111
1112 void set_sreg(unsigned code, float value,
1113 RegLogMode log_mode = LogRegWrites) {
1114 set_vreg(code, value, log_mode);
1115 }
1116
1117 void set_sreg_bits(unsigned code, uint32_t value,
1118 RegLogMode log_mode = LogRegWrites) {
1119 set_vreg(code, value, log_mode);
1120 }
1121
1122 void set_dreg(unsigned code, double value,
1123 RegLogMode log_mode = LogRegWrites) {
1124 set_vreg(code, value, log_mode);
1125 }
1126
1127 void set_dreg_bits(unsigned code, uint64_t value,
1128 RegLogMode log_mode = LogRegWrites) {
1129 set_vreg(code, value, log_mode);
1130 }
1131
1132 void set_qreg(unsigned code, qreg_t value,
1133 RegLogMode log_mode = LogRegWrites) {
1134 set_vreg(code, value, log_mode);
1135 }
1136
N()1137 bool N() const { return nzcv_.N() != 0; }
Z()1138 bool Z() const { return nzcv_.Z() != 0; }
C()1139 bool C() const { return nzcv_.C() != 0; }
V()1140 bool V() const { return nzcv_.V() != 0; }
nzcv()1141 SimSystemRegister& nzcv() { return nzcv_; }
1142
1143 // TODO: Find a way to make the fpcr_ members return the proper types, so
1144 // these accessors are not necessary.
RMode()1145 FPRounding RMode() { return static_cast<FPRounding>(fpcr_.RMode()); }
DN()1146 bool DN() { return fpcr_.DN() != 0; }
fpcr()1147 SimSystemRegister& fpcr() { return fpcr_; }
1148
1149 // Specify relevant register formats for Print(V)Register and related helpers.
1150 enum PrintRegisterFormat {
1151 // The lane size.
1152 kPrintRegLaneSizeB = 0 << 0,
1153 kPrintRegLaneSizeH = 1 << 0,
1154 kPrintRegLaneSizeS = 2 << 0,
1155 kPrintRegLaneSizeW = kPrintRegLaneSizeS,
1156 kPrintRegLaneSizeD = 3 << 0,
1157 kPrintRegLaneSizeX = kPrintRegLaneSizeD,
1158 kPrintRegLaneSizeQ = 4 << 0,
1159
1160 kPrintRegLaneSizeOffset = 0,
1161 kPrintRegLaneSizeMask = 7 << 0,
1162
1163 // The lane count.
1164 kPrintRegAsScalar = 0,
1165 kPrintRegAsDVector = 1 << 3,
1166 kPrintRegAsQVector = 2 << 3,
1167
1168 kPrintRegAsVectorMask = 3 << 3,
1169
1170 // Indicate floating-point format lanes. (This flag is only supported for S-
1171 // and D-sized lanes.)
1172 kPrintRegAsFP = 1 << 5,
1173
1174 // Supported combinations.
1175
1176 kPrintXReg = kPrintRegLaneSizeX | kPrintRegAsScalar,
1177 kPrintWReg = kPrintRegLaneSizeW | kPrintRegAsScalar,
1178 kPrintSReg = kPrintRegLaneSizeS | kPrintRegAsScalar | kPrintRegAsFP,
1179 kPrintDReg = kPrintRegLaneSizeD | kPrintRegAsScalar | kPrintRegAsFP,
1180
1181 kPrintReg1B = kPrintRegLaneSizeB | kPrintRegAsScalar,
1182 kPrintReg8B = kPrintRegLaneSizeB | kPrintRegAsDVector,
1183 kPrintReg16B = kPrintRegLaneSizeB | kPrintRegAsQVector,
1184 kPrintReg1H = kPrintRegLaneSizeH | kPrintRegAsScalar,
1185 kPrintReg4H = kPrintRegLaneSizeH | kPrintRegAsDVector,
1186 kPrintReg8H = kPrintRegLaneSizeH | kPrintRegAsQVector,
1187 kPrintReg1S = kPrintRegLaneSizeS | kPrintRegAsScalar,
1188 kPrintReg2S = kPrintRegLaneSizeS | kPrintRegAsDVector,
1189 kPrintReg4S = kPrintRegLaneSizeS | kPrintRegAsQVector,
1190 kPrintReg1SFP = kPrintRegLaneSizeS | kPrintRegAsScalar | kPrintRegAsFP,
1191 kPrintReg2SFP = kPrintRegLaneSizeS | kPrintRegAsDVector | kPrintRegAsFP,
1192 kPrintReg4SFP = kPrintRegLaneSizeS | kPrintRegAsQVector | kPrintRegAsFP,
1193 kPrintReg1D = kPrintRegLaneSizeD | kPrintRegAsScalar,
1194 kPrintReg2D = kPrintRegLaneSizeD | kPrintRegAsQVector,
1195 kPrintReg1DFP = kPrintRegLaneSizeD | kPrintRegAsScalar | kPrintRegAsFP,
1196 kPrintReg2DFP = kPrintRegLaneSizeD | kPrintRegAsQVector | kPrintRegAsFP,
1197 kPrintReg1Q = kPrintRegLaneSizeQ | kPrintRegAsScalar
1198 };
1199
GetPrintRegLaneSizeInBytesLog2(PrintRegisterFormat format)1200 unsigned GetPrintRegLaneSizeInBytesLog2(PrintRegisterFormat format) {
1201 return (format & kPrintRegLaneSizeMask) >> kPrintRegLaneSizeOffset;
1202 }
1203
GetPrintRegLaneSizeInBytes(PrintRegisterFormat format)1204 unsigned GetPrintRegLaneSizeInBytes(PrintRegisterFormat format) {
1205 return 1 << GetPrintRegLaneSizeInBytesLog2(format);
1206 }
1207
GetPrintRegSizeInBytesLog2(PrintRegisterFormat format)1208 unsigned GetPrintRegSizeInBytesLog2(PrintRegisterFormat format) {
1209 if (format & kPrintRegAsDVector) return kDRegSizeInBytesLog2;
1210 if (format & kPrintRegAsQVector) return kQRegSizeInBytesLog2;
1211
1212 // Scalar types.
1213 return GetPrintRegLaneSizeInBytesLog2(format);
1214 }
1215
GetPrintRegSizeInBytes(PrintRegisterFormat format)1216 unsigned GetPrintRegSizeInBytes(PrintRegisterFormat format) {
1217 return 1 << GetPrintRegSizeInBytesLog2(format);
1218 }
1219
GetPrintRegLaneCount(PrintRegisterFormat format)1220 unsigned GetPrintRegLaneCount(PrintRegisterFormat format) {
1221 unsigned reg_size_log2 = GetPrintRegSizeInBytesLog2(format);
1222 unsigned lane_size_log2 = GetPrintRegLaneSizeInBytesLog2(format);
1223 VIXL_ASSERT(reg_size_log2 >= lane_size_log2);
1224 return 1 << (reg_size_log2 - lane_size_log2);
1225 }
1226
1227 PrintRegisterFormat GetPrintRegisterFormatForSize(unsigned reg_size,
1228 unsigned lane_size);
1229
GetPrintRegisterFormatForSize(unsigned size)1230 PrintRegisterFormat GetPrintRegisterFormatForSize(unsigned size) {
1231 return GetPrintRegisterFormatForSize(size, size);
1232 }
1233
GetPrintRegisterFormatForSizeFP(unsigned size)1234 PrintRegisterFormat GetPrintRegisterFormatForSizeFP(unsigned size) {
1235 switch (size) {
1236 default: VIXL_UNREACHABLE(); return kPrintDReg;
1237 case kDRegSizeInBytes: return kPrintDReg;
1238 case kSRegSizeInBytes: return kPrintSReg;
1239 }
1240 }
1241
GetPrintRegisterFormatTryFP(PrintRegisterFormat format)1242 PrintRegisterFormat GetPrintRegisterFormatTryFP(PrintRegisterFormat format) {
1243 if ((GetPrintRegLaneSizeInBytes(format) == kSRegSizeInBytes) ||
1244 (GetPrintRegLaneSizeInBytes(format) == kDRegSizeInBytes)) {
1245 return static_cast<PrintRegisterFormat>(format | kPrintRegAsFP);
1246 }
1247 return format;
1248 }
1249
1250 template<typename T>
GetPrintRegisterFormat(T value)1251 PrintRegisterFormat GetPrintRegisterFormat(T value) {
1252 return GetPrintRegisterFormatForSize(sizeof(value));
1253 }
1254
GetPrintRegisterFormat(double value)1255 PrintRegisterFormat GetPrintRegisterFormat(double value) {
1256 VIXL_STATIC_ASSERT(sizeof(value) == kDRegSizeInBytes);
1257 return GetPrintRegisterFormatForSizeFP(sizeof(value));
1258 }
1259
GetPrintRegisterFormat(float value)1260 PrintRegisterFormat GetPrintRegisterFormat(float value) {
1261 VIXL_STATIC_ASSERT(sizeof(value) == kSRegSizeInBytes);
1262 return GetPrintRegisterFormatForSizeFP(sizeof(value));
1263 }
1264
1265 PrintRegisterFormat GetPrintRegisterFormat(VectorFormat vform);
1266
1267 // Print all registers of the specified types.
1268 void PrintRegisters();
1269 void PrintVRegisters();
1270 void PrintSystemRegisters();
1271
1272 // As above, but only print the registers that have been updated.
1273 void PrintWrittenRegisters();
1274 void PrintWrittenVRegisters();
1275
1276 // As above, but respect LOG_REG and LOG_VREG.
LogWrittenRegisters()1277 void LogWrittenRegisters() {
1278 if (trace_parameters() & LOG_REGS) PrintWrittenRegisters();
1279 }
LogWrittenVRegisters()1280 void LogWrittenVRegisters() {
1281 if (trace_parameters() & LOG_VREGS) PrintWrittenVRegisters();
1282 }
LogAllWrittenRegisters()1283 void LogAllWrittenRegisters() {
1284 LogWrittenRegisters();
1285 LogWrittenVRegisters();
1286 }
1287
1288 // Print individual register values (after update).
1289 void PrintRegister(unsigned code, Reg31Mode r31mode = Reg31IsStackPointer);
1290 void PrintVRegister(unsigned code, PrintRegisterFormat format);
1291 void PrintSystemRegister(SystemRegister id);
1292
1293 // Like Print* (above), but respect trace_parameters().
1294 void LogRegister(unsigned code, Reg31Mode r31mode = Reg31IsStackPointer) {
1295 if (trace_parameters() & LOG_REGS) PrintRegister(code, r31mode);
1296 }
LogVRegister(unsigned code,PrintRegisterFormat format)1297 void LogVRegister(unsigned code, PrintRegisterFormat format) {
1298 if (trace_parameters() & LOG_VREGS) PrintVRegister(code, format);
1299 }
LogSystemRegister(SystemRegister id)1300 void LogSystemRegister(SystemRegister id) {
1301 if (trace_parameters() & LOG_SYSREGS) PrintSystemRegister(id);
1302 }
1303
1304 // Print memory accesses.
1305 void PrintRead(uintptr_t address, unsigned reg_code,
1306 PrintRegisterFormat format);
1307 void PrintWrite(uintptr_t address, unsigned reg_code,
1308 PrintRegisterFormat format);
1309 void PrintVRead(uintptr_t address, unsigned reg_code,
1310 PrintRegisterFormat format, unsigned lane);
1311 void PrintVWrite(uintptr_t address, unsigned reg_code,
1312 PrintRegisterFormat format, unsigned lane);
1313
1314 // Like Print* (above), but respect trace_parameters().
LogRead(uintptr_t address,unsigned reg_code,PrintRegisterFormat format)1315 void LogRead(uintptr_t address, unsigned reg_code,
1316 PrintRegisterFormat format) {
1317 if (trace_parameters() & LOG_REGS) PrintRead(address, reg_code, format);
1318 }
LogWrite(uintptr_t address,unsigned reg_code,PrintRegisterFormat format)1319 void LogWrite(uintptr_t address, unsigned reg_code,
1320 PrintRegisterFormat format) {
1321 if (trace_parameters() & LOG_WRITE) PrintWrite(address, reg_code, format);
1322 }
1323 void LogVRead(uintptr_t address, unsigned reg_code,
1324 PrintRegisterFormat format, unsigned lane = 0) {
1325 if (trace_parameters() & LOG_VREGS) {
1326 PrintVRead(address, reg_code, format, lane);
1327 }
1328 }
1329 void LogVWrite(uintptr_t address, unsigned reg_code,
1330 PrintRegisterFormat format, unsigned lane = 0) {
1331 if (trace_parameters() & LOG_WRITE) {
1332 PrintVWrite(address, reg_code, format, lane);
1333 }
1334 }
1335
1336 // Helper functions for register tracing.
1337 void PrintRegisterRawHelper(unsigned code, Reg31Mode r31mode,
1338 int size_in_bytes = kXRegSizeInBytes);
1339 void PrintVRegisterRawHelper(unsigned code, int bytes = kQRegSizeInBytes,
1340 int lsb = 0);
1341 void PrintVRegisterFPHelper(unsigned code, unsigned lane_size_in_bytes,
1342 int lane_count = 1, int rightmost_lane = 0);
1343
1344 void DoUnreachable(const Instruction* instr);
1345 void DoTrace(const Instruction* instr);
1346 void DoLog(const Instruction* instr);
1347
1348 static const char* WRegNameForCode(unsigned code,
1349 Reg31Mode mode = Reg31IsZeroRegister);
1350 static const char* XRegNameForCode(unsigned code,
1351 Reg31Mode mode = Reg31IsZeroRegister);
1352 static const char* SRegNameForCode(unsigned code);
1353 static const char* DRegNameForCode(unsigned code);
1354 static const char* VRegNameForCode(unsigned code);
1355
coloured_trace()1356 bool coloured_trace() const { return coloured_trace_; }
1357 void set_coloured_trace(bool value);
1358
trace_parameters()1359 int trace_parameters() const { return trace_parameters_; }
1360 void set_trace_parameters(int parameters);
1361
1362 void set_instruction_stats(bool value);
1363
1364 // Clear the simulated local monitor to force the next store-exclusive
1365 // instruction to fail.
ClearLocalMonitor()1366 void ClearLocalMonitor() {
1367 local_monitor_.Clear();
1368 }
1369
SilenceExclusiveAccessWarning()1370 void SilenceExclusiveAccessWarning() {
1371 print_exclusive_access_warning_ = false;
1372 }
1373
1374 protected:
1375 const char* clr_normal;
1376 const char* clr_flag_name;
1377 const char* clr_flag_value;
1378 const char* clr_reg_name;
1379 const char* clr_reg_value;
1380 const char* clr_vreg_name;
1381 const char* clr_vreg_value;
1382 const char* clr_memory_address;
1383 const char* clr_warning;
1384 const char* clr_warning_message;
1385 const char* clr_printf;
1386
1387 // Simulation helpers ------------------------------------
ConditionPassed(Condition cond)1388 bool ConditionPassed(Condition cond) {
1389 switch (cond) {
1390 case eq:
1391 return Z();
1392 case ne:
1393 return !Z();
1394 case hs:
1395 return C();
1396 case lo:
1397 return !C();
1398 case mi:
1399 return N();
1400 case pl:
1401 return !N();
1402 case vs:
1403 return V();
1404 case vc:
1405 return !V();
1406 case hi:
1407 return C() && !Z();
1408 case ls:
1409 return !(C() && !Z());
1410 case ge:
1411 return N() == V();
1412 case lt:
1413 return N() != V();
1414 case gt:
1415 return !Z() && (N() == V());
1416 case le:
1417 return !(!Z() && (N() == V()));
1418 case nv:
1419 VIXL_FALLTHROUGH();
1420 case al:
1421 return true;
1422 default:
1423 VIXL_UNREACHABLE();
1424 return false;
1425 }
1426 }
1427
ConditionPassed(Instr cond)1428 bool ConditionPassed(Instr cond) {
1429 return ConditionPassed(static_cast<Condition>(cond));
1430 }
1431
ConditionFailed(Condition cond)1432 bool ConditionFailed(Condition cond) {
1433 return !ConditionPassed(cond);
1434 }
1435
1436 void AddSubHelper(const Instruction* instr, int64_t op2);
1437 int64_t AddWithCarry(unsigned reg_size,
1438 bool set_flags,
1439 int64_t src1,
1440 int64_t src2,
1441 int64_t carry_in = 0);
1442 void LogicalHelper(const Instruction* instr, int64_t op2);
1443 void ConditionalCompareHelper(const Instruction* instr, int64_t op2);
1444 void LoadStoreHelper(const Instruction* instr,
1445 int64_t offset,
1446 AddrMode addrmode);
1447 void LoadStorePairHelper(const Instruction* instr, AddrMode addrmode);
1448 uintptr_t AddressModeHelper(unsigned addr_reg,
1449 int64_t offset,
1450 AddrMode addrmode);
1451 void NEONLoadStoreMultiStructHelper(const Instruction* instr,
1452 AddrMode addr_mode);
1453 void NEONLoadStoreSingleStructHelper(const Instruction* instr,
1454 AddrMode addr_mode);
1455
AddressUntag(uint64_t address)1456 uint64_t AddressUntag(uint64_t address) {
1457 return address & ~kAddressTagMask;
1458 }
1459
1460 template <typename T>
AddressUntag(T * address)1461 T* AddressUntag(T* address) {
1462 uintptr_t address_raw = reinterpret_cast<uintptr_t>(address);
1463 return reinterpret_cast<T*>(AddressUntag(address_raw));
1464 }
1465
1466 int64_t ShiftOperand(unsigned reg_size,
1467 int64_t value,
1468 Shift shift_type,
1469 unsigned amount);
1470 int64_t Rotate(unsigned reg_width,
1471 int64_t value,
1472 Shift shift_type,
1473 unsigned amount);
1474 int64_t ExtendValue(unsigned reg_width,
1475 int64_t value,
1476 Extend extend_type,
1477 unsigned left_shift = 0);
1478 uint16_t PolynomialMult(uint8_t op1, uint8_t op2);
1479
1480 void ld1(VectorFormat vform,
1481 LogicVRegister dst,
1482 uint64_t addr);
1483 void ld1(VectorFormat vform,
1484 LogicVRegister dst,
1485 int index,
1486 uint64_t addr);
1487 void ld1r(VectorFormat vform,
1488 LogicVRegister dst,
1489 uint64_t addr);
1490 void ld2(VectorFormat vform,
1491 LogicVRegister dst1,
1492 LogicVRegister dst2,
1493 uint64_t addr);
1494 void ld2(VectorFormat vform,
1495 LogicVRegister dst1,
1496 LogicVRegister dst2,
1497 int index,
1498 uint64_t addr);
1499 void ld2r(VectorFormat vform,
1500 LogicVRegister dst1,
1501 LogicVRegister dst2,
1502 uint64_t addr);
1503 void ld3(VectorFormat vform,
1504 LogicVRegister dst1,
1505 LogicVRegister dst2,
1506 LogicVRegister dst3,
1507 uint64_t addr);
1508 void ld3(VectorFormat vform,
1509 LogicVRegister dst1,
1510 LogicVRegister dst2,
1511 LogicVRegister dst3,
1512 int index,
1513 uint64_t addr);
1514 void ld3r(VectorFormat vform,
1515 LogicVRegister dst1,
1516 LogicVRegister dst2,
1517 LogicVRegister dst3,
1518 uint64_t addr);
1519 void ld4(VectorFormat vform,
1520 LogicVRegister dst1,
1521 LogicVRegister dst2,
1522 LogicVRegister dst3,
1523 LogicVRegister dst4,
1524 uint64_t addr);
1525 void ld4(VectorFormat vform,
1526 LogicVRegister dst1,
1527 LogicVRegister dst2,
1528 LogicVRegister dst3,
1529 LogicVRegister dst4,
1530 int index,
1531 uint64_t addr);
1532 void ld4r(VectorFormat vform,
1533 LogicVRegister dst1,
1534 LogicVRegister dst2,
1535 LogicVRegister dst3,
1536 LogicVRegister dst4,
1537 uint64_t addr);
1538 void st1(VectorFormat vform,
1539 LogicVRegister src,
1540 uint64_t addr);
1541 void st1(VectorFormat vform,
1542 LogicVRegister src,
1543 int index,
1544 uint64_t addr);
1545 void st2(VectorFormat vform,
1546 LogicVRegister src,
1547 LogicVRegister src2,
1548 uint64_t addr);
1549 void st2(VectorFormat vform,
1550 LogicVRegister src,
1551 LogicVRegister src2,
1552 int index,
1553 uint64_t addr);
1554 void st3(VectorFormat vform,
1555 LogicVRegister src,
1556 LogicVRegister src2,
1557 LogicVRegister src3,
1558 uint64_t addr);
1559 void st3(VectorFormat vform,
1560 LogicVRegister src,
1561 LogicVRegister src2,
1562 LogicVRegister src3,
1563 int index,
1564 uint64_t addr);
1565 void st4(VectorFormat vform,
1566 LogicVRegister src,
1567 LogicVRegister src2,
1568 LogicVRegister src3,
1569 LogicVRegister src4,
1570 uint64_t addr);
1571 void st4(VectorFormat vform,
1572 LogicVRegister src,
1573 LogicVRegister src2,
1574 LogicVRegister src3,
1575 LogicVRegister src4,
1576 int index,
1577 uint64_t addr);
1578 LogicVRegister cmp(VectorFormat vform,
1579 LogicVRegister dst,
1580 const LogicVRegister& src1,
1581 const LogicVRegister& src2,
1582 Condition cond);
1583 LogicVRegister cmp(VectorFormat vform,
1584 LogicVRegister dst,
1585 const LogicVRegister& src1,
1586 int imm,
1587 Condition cond);
1588 LogicVRegister cmptst(VectorFormat vform,
1589 LogicVRegister dst,
1590 const LogicVRegister& src1,
1591 const LogicVRegister& src2);
1592 LogicVRegister add(VectorFormat vform,
1593 LogicVRegister dst,
1594 const LogicVRegister& src1,
1595 const LogicVRegister& src2);
1596 LogicVRegister addp(VectorFormat vform,
1597 LogicVRegister dst,
1598 const LogicVRegister& src1,
1599 const LogicVRegister& src2);
1600 LogicVRegister mla(VectorFormat vform,
1601 LogicVRegister dst,
1602 const LogicVRegister& src1,
1603 const LogicVRegister& src2);
1604 LogicVRegister mls(VectorFormat vform,
1605 LogicVRegister dst,
1606 const LogicVRegister& src1,
1607 const LogicVRegister& src2);
1608 LogicVRegister mul(VectorFormat vform,
1609 LogicVRegister dst,
1610 const LogicVRegister& src1,
1611 const LogicVRegister& src2);
1612 LogicVRegister mul(VectorFormat vform,
1613 LogicVRegister dst,
1614 const LogicVRegister& src1,
1615 const LogicVRegister& src2,
1616 int index);
1617 LogicVRegister mla(VectorFormat vform,
1618 LogicVRegister dst,
1619 const LogicVRegister& src1,
1620 const LogicVRegister& src2,
1621 int index);
1622 LogicVRegister mls(VectorFormat vform,
1623 LogicVRegister dst,
1624 const LogicVRegister& src1,
1625 const LogicVRegister& src2,
1626 int index);
1627 LogicVRegister pmul(VectorFormat vform,
1628 LogicVRegister dst,
1629 const LogicVRegister& src1,
1630 const LogicVRegister& src2);
1631
1632 typedef LogicVRegister (Simulator::*ByElementOp)(VectorFormat vform,
1633 LogicVRegister dst,
1634 const LogicVRegister& src1,
1635 const LogicVRegister& src2,
1636 int index);
1637 LogicVRegister fmul(VectorFormat vform,
1638 LogicVRegister dst,
1639 const LogicVRegister& src1,
1640 const LogicVRegister& src2,
1641 int index);
1642 LogicVRegister fmla(VectorFormat vform,
1643 LogicVRegister dst,
1644 const LogicVRegister& src1,
1645 const LogicVRegister& src2,
1646 int index);
1647 LogicVRegister fmls(VectorFormat vform,
1648 LogicVRegister dst,
1649 const LogicVRegister& src1,
1650 const LogicVRegister& src2,
1651 int index);
1652 LogicVRegister fmulx(VectorFormat vform,
1653 LogicVRegister dst,
1654 const LogicVRegister& src1,
1655 const LogicVRegister& src2,
1656 int index);
1657 LogicVRegister smull(VectorFormat vform,
1658 LogicVRegister dst,
1659 const LogicVRegister& src1,
1660 const LogicVRegister& src2,
1661 int index);
1662 LogicVRegister smull2(VectorFormat vform,
1663 LogicVRegister dst,
1664 const LogicVRegister& src1,
1665 const LogicVRegister& src2,
1666 int index);
1667 LogicVRegister umull(VectorFormat vform,
1668 LogicVRegister dst,
1669 const LogicVRegister& src1,
1670 const LogicVRegister& src2,
1671 int index);
1672 LogicVRegister umull2(VectorFormat vform,
1673 LogicVRegister dst,
1674 const LogicVRegister& src1,
1675 const LogicVRegister& src2,
1676 int index);
1677 LogicVRegister smlal(VectorFormat vform,
1678 LogicVRegister dst,
1679 const LogicVRegister& src1,
1680 const LogicVRegister& src2,
1681 int index);
1682 LogicVRegister smlal2(VectorFormat vform,
1683 LogicVRegister dst,
1684 const LogicVRegister& src1,
1685 const LogicVRegister& src2,
1686 int index);
1687 LogicVRegister umlal(VectorFormat vform,
1688 LogicVRegister dst,
1689 const LogicVRegister& src1,
1690 const LogicVRegister& src2,
1691 int index);
1692 LogicVRegister umlal2(VectorFormat vform,
1693 LogicVRegister dst,
1694 const LogicVRegister& src1,
1695 const LogicVRegister& src2,
1696 int index);
1697 LogicVRegister smlsl(VectorFormat vform,
1698 LogicVRegister dst,
1699 const LogicVRegister& src1,
1700 const LogicVRegister& src2,
1701 int index);
1702 LogicVRegister smlsl2(VectorFormat vform,
1703 LogicVRegister dst,
1704 const LogicVRegister& src1,
1705 const LogicVRegister& src2,
1706 int index);
1707 LogicVRegister umlsl(VectorFormat vform,
1708 LogicVRegister dst,
1709 const LogicVRegister& src1,
1710 const LogicVRegister& src2,
1711 int index);
1712 LogicVRegister umlsl2(VectorFormat vform,
1713 LogicVRegister dst,
1714 const LogicVRegister& src1,
1715 const LogicVRegister& src2,
1716 int index);
1717 LogicVRegister sqdmull(VectorFormat vform,
1718 LogicVRegister dst,
1719 const LogicVRegister& src1,
1720 const LogicVRegister& src2,
1721 int index);
1722 LogicVRegister sqdmull2(VectorFormat vform,
1723 LogicVRegister dst,
1724 const LogicVRegister& src1,
1725 const LogicVRegister& src2,
1726 int index);
1727 LogicVRegister sqdmlal(VectorFormat vform,
1728 LogicVRegister dst,
1729 const LogicVRegister& src1,
1730 const LogicVRegister& src2,
1731 int index);
1732 LogicVRegister sqdmlal2(VectorFormat vform,
1733 LogicVRegister dst,
1734 const LogicVRegister& src1,
1735 const LogicVRegister& src2,
1736 int index);
1737 LogicVRegister sqdmlsl(VectorFormat vform,
1738 LogicVRegister dst,
1739 const LogicVRegister& src1,
1740 const LogicVRegister& src2,
1741 int index);
1742 LogicVRegister sqdmlsl2(VectorFormat vform,
1743 LogicVRegister dst,
1744 const LogicVRegister& src1,
1745 const LogicVRegister& src2,
1746 int index);
1747 LogicVRegister sqdmulh(VectorFormat vform,
1748 LogicVRegister dst,
1749 const LogicVRegister& src1,
1750 const LogicVRegister& src2,
1751 int index);
1752 LogicVRegister sqrdmulh(VectorFormat vform,
1753 LogicVRegister dst,
1754 const LogicVRegister& src1,
1755 const LogicVRegister& src2,
1756 int index);
1757 LogicVRegister sub(VectorFormat vform,
1758 LogicVRegister dst,
1759 const LogicVRegister& src1,
1760 const LogicVRegister& src2);
1761 LogicVRegister and_(VectorFormat vform,
1762 LogicVRegister dst,
1763 const LogicVRegister& src1,
1764 const LogicVRegister& src2);
1765 LogicVRegister orr(VectorFormat vform,
1766 LogicVRegister dst,
1767 const LogicVRegister& src1,
1768 const LogicVRegister& src2);
1769 LogicVRegister orn(VectorFormat vform,
1770 LogicVRegister dst,
1771 const LogicVRegister& src1,
1772 const LogicVRegister& src2);
1773 LogicVRegister eor(VectorFormat vform,
1774 LogicVRegister dst,
1775 const LogicVRegister& src1,
1776 const LogicVRegister& src2);
1777 LogicVRegister bic(VectorFormat vform,
1778 LogicVRegister dst,
1779 const LogicVRegister& src1,
1780 const LogicVRegister& src2);
1781 LogicVRegister bic(VectorFormat vform,
1782 LogicVRegister dst,
1783 const LogicVRegister& src,
1784 uint64_t imm);
1785 LogicVRegister bif(VectorFormat vform,
1786 LogicVRegister dst,
1787 const LogicVRegister& src1,
1788 const LogicVRegister& src2);
1789 LogicVRegister bit(VectorFormat vform,
1790 LogicVRegister dst,
1791 const LogicVRegister& src1,
1792 const LogicVRegister& src2);
1793 LogicVRegister bsl(VectorFormat vform,
1794 LogicVRegister dst,
1795 const LogicVRegister& src1,
1796 const LogicVRegister& src2);
1797 LogicVRegister cls(VectorFormat vform,
1798 LogicVRegister dst,
1799 const LogicVRegister& src);
1800 LogicVRegister clz(VectorFormat vform,
1801 LogicVRegister dst,
1802 const LogicVRegister& src);
1803 LogicVRegister cnt(VectorFormat vform,
1804 LogicVRegister dst,
1805 const LogicVRegister& src);
1806 LogicVRegister not_(VectorFormat vform,
1807 LogicVRegister dst,
1808 const LogicVRegister& src);
1809 LogicVRegister rbit(VectorFormat vform,
1810 LogicVRegister dst,
1811 const LogicVRegister& src);
1812 LogicVRegister rev(VectorFormat vform,
1813 LogicVRegister dst,
1814 const LogicVRegister& src,
1815 int revSize);
1816 LogicVRegister rev16(VectorFormat vform,
1817 LogicVRegister dst,
1818 const LogicVRegister& src);
1819 LogicVRegister rev32(VectorFormat vform,
1820 LogicVRegister dst,
1821 const LogicVRegister& src);
1822 LogicVRegister rev64(VectorFormat vform,
1823 LogicVRegister dst,
1824 const LogicVRegister& src);
1825 LogicVRegister addlp(VectorFormat vform,
1826 LogicVRegister dst,
1827 const LogicVRegister& src,
1828 bool is_signed,
1829 bool do_accumulate);
1830 LogicVRegister saddlp(VectorFormat vform,
1831 LogicVRegister dst,
1832 const LogicVRegister& src);
1833 LogicVRegister uaddlp(VectorFormat vform,
1834 LogicVRegister dst,
1835 const LogicVRegister& src);
1836 LogicVRegister sadalp(VectorFormat vform,
1837 LogicVRegister dst,
1838 const LogicVRegister& src);
1839 LogicVRegister uadalp(VectorFormat vform,
1840 LogicVRegister dst,
1841 const LogicVRegister& src);
1842 LogicVRegister ext(VectorFormat vform,
1843 LogicVRegister dst,
1844 const LogicVRegister& src1,
1845 const LogicVRegister& src2,
1846 int index);
1847 LogicVRegister ins_element(VectorFormat vform,
1848 LogicVRegister dst,
1849 int dst_index,
1850 const LogicVRegister& src,
1851 int src_index);
1852 LogicVRegister ins_immediate(VectorFormat vform,
1853 LogicVRegister dst,
1854 int dst_index,
1855 uint64_t imm);
1856 LogicVRegister dup_element(VectorFormat vform,
1857 LogicVRegister dst,
1858 const LogicVRegister& src,
1859 int src_index);
1860 LogicVRegister dup_immediate(VectorFormat vform,
1861 LogicVRegister dst,
1862 uint64_t imm);
1863 LogicVRegister movi(VectorFormat vform,
1864 LogicVRegister dst,
1865 uint64_t imm);
1866 LogicVRegister mvni(VectorFormat vform,
1867 LogicVRegister dst,
1868 uint64_t imm);
1869 LogicVRegister orr(VectorFormat vform,
1870 LogicVRegister dst,
1871 const LogicVRegister& src,
1872 uint64_t imm);
1873 LogicVRegister sshl(VectorFormat vform,
1874 LogicVRegister dst,
1875 const LogicVRegister& src1,
1876 const LogicVRegister& src2);
1877 LogicVRegister ushl(VectorFormat vform,
1878 LogicVRegister dst,
1879 const LogicVRegister& src1,
1880 const LogicVRegister& src2);
1881 LogicVRegister sminmax(VectorFormat vform,
1882 LogicVRegister dst,
1883 const LogicVRegister& src1,
1884 const LogicVRegister& src2,
1885 bool max);
1886 LogicVRegister smax(VectorFormat vform,
1887 LogicVRegister dst,
1888 const LogicVRegister& src1,
1889 const LogicVRegister& src2);
1890 LogicVRegister smin(VectorFormat vform,
1891 LogicVRegister dst,
1892 const LogicVRegister& src1,
1893 const LogicVRegister& src2);
1894 LogicVRegister sminmaxp(VectorFormat vform,
1895 LogicVRegister dst,
1896 int dst_index,
1897 const LogicVRegister& src,
1898 bool max);
1899 LogicVRegister smaxp(VectorFormat vform,
1900 LogicVRegister dst,
1901 const LogicVRegister& src1,
1902 const LogicVRegister& src2);
1903 LogicVRegister sminp(VectorFormat vform,
1904 LogicVRegister dst,
1905 const LogicVRegister& src1,
1906 const LogicVRegister& src2);
1907 LogicVRegister addp(VectorFormat vform,
1908 LogicVRegister dst,
1909 const LogicVRegister& src);
1910 LogicVRegister addv(VectorFormat vform,
1911 LogicVRegister dst,
1912 const LogicVRegister& src);
1913 LogicVRegister uaddlv(VectorFormat vform,
1914 LogicVRegister dst,
1915 const LogicVRegister& src);
1916 LogicVRegister saddlv(VectorFormat vform,
1917 LogicVRegister dst,
1918 const LogicVRegister& src);
1919 LogicVRegister sminmaxv(VectorFormat vform,
1920 LogicVRegister dst,
1921 const LogicVRegister& src,
1922 bool max);
1923 LogicVRegister smaxv(VectorFormat vform,
1924 LogicVRegister dst,
1925 const LogicVRegister& src);
1926 LogicVRegister sminv(VectorFormat vform,
1927 LogicVRegister dst,
1928 const LogicVRegister& src);
1929 LogicVRegister uxtl(VectorFormat vform,
1930 LogicVRegister dst,
1931 const LogicVRegister& src);
1932 LogicVRegister uxtl2(VectorFormat vform,
1933 LogicVRegister dst,
1934 const LogicVRegister& src);
1935 LogicVRegister sxtl(VectorFormat vform,
1936 LogicVRegister dst,
1937 const LogicVRegister& src);
1938 LogicVRegister sxtl2(VectorFormat vform,
1939 LogicVRegister dst,
1940 const LogicVRegister& src);
1941 LogicVRegister tbl(VectorFormat vform,
1942 LogicVRegister dst,
1943 const LogicVRegister& tab,
1944 const LogicVRegister& ind);
1945 LogicVRegister tbl(VectorFormat vform,
1946 LogicVRegister dst,
1947 const LogicVRegister& tab,
1948 const LogicVRegister& tab2,
1949 const LogicVRegister& ind);
1950 LogicVRegister tbl(VectorFormat vform,
1951 LogicVRegister dst,
1952 const LogicVRegister& tab,
1953 const LogicVRegister& tab2,
1954 const LogicVRegister& tab3,
1955 const LogicVRegister& ind);
1956 LogicVRegister tbl(VectorFormat vform,
1957 LogicVRegister dst,
1958 const LogicVRegister& tab,
1959 const LogicVRegister& tab2,
1960 const LogicVRegister& tab3,
1961 const LogicVRegister& tab4,
1962 const LogicVRegister& ind);
1963 LogicVRegister tbx(VectorFormat vform,
1964 LogicVRegister dst,
1965 const LogicVRegister& tab,
1966 const LogicVRegister& ind);
1967 LogicVRegister tbx(VectorFormat vform,
1968 LogicVRegister dst,
1969 const LogicVRegister& tab,
1970 const LogicVRegister& tab2,
1971 const LogicVRegister& ind);
1972 LogicVRegister tbx(VectorFormat vform,
1973 LogicVRegister dst,
1974 const LogicVRegister& tab,
1975 const LogicVRegister& tab2,
1976 const LogicVRegister& tab3,
1977 const LogicVRegister& ind);
1978 LogicVRegister tbx(VectorFormat vform,
1979 LogicVRegister dst,
1980 const LogicVRegister& tab,
1981 const LogicVRegister& tab2,
1982 const LogicVRegister& tab3,
1983 const LogicVRegister& tab4,
1984 const LogicVRegister& ind);
1985 LogicVRegister uaddl(VectorFormat vform,
1986 LogicVRegister dst,
1987 const LogicVRegister& src1,
1988 const LogicVRegister& src2);
1989 LogicVRegister uaddl2(VectorFormat vform,
1990 LogicVRegister dst,
1991 const LogicVRegister& src1,
1992 const LogicVRegister& src2);
1993 LogicVRegister uaddw(VectorFormat vform,
1994 LogicVRegister dst,
1995 const LogicVRegister& src1,
1996 const LogicVRegister& src2);
1997 LogicVRegister uaddw2(VectorFormat vform,
1998 LogicVRegister dst,
1999 const LogicVRegister& src1,
2000 const LogicVRegister& src2);
2001 LogicVRegister saddl(VectorFormat vform,
2002 LogicVRegister dst,
2003 const LogicVRegister& src1,
2004 const LogicVRegister& src2);
2005 LogicVRegister saddl2(VectorFormat vform,
2006 LogicVRegister dst,
2007 const LogicVRegister& src1,
2008 const LogicVRegister& src2);
2009 LogicVRegister saddw(VectorFormat vform,
2010 LogicVRegister dst,
2011 const LogicVRegister& src1,
2012 const LogicVRegister& src2);
2013 LogicVRegister saddw2(VectorFormat vform,
2014 LogicVRegister dst,
2015 const LogicVRegister& src1,
2016 const LogicVRegister& src2);
2017 LogicVRegister usubl(VectorFormat vform,
2018 LogicVRegister dst,
2019 const LogicVRegister& src1,
2020 const LogicVRegister& src2);
2021 LogicVRegister usubl2(VectorFormat vform,
2022 LogicVRegister dst,
2023 const LogicVRegister& src1,
2024 const LogicVRegister& src2);
2025 LogicVRegister usubw(VectorFormat vform,
2026 LogicVRegister dst,
2027 const LogicVRegister& src1,
2028 const LogicVRegister& src2);
2029 LogicVRegister usubw2(VectorFormat vform,
2030 LogicVRegister dst,
2031 const LogicVRegister& src1,
2032 const LogicVRegister& src2);
2033 LogicVRegister ssubl(VectorFormat vform,
2034 LogicVRegister dst,
2035 const LogicVRegister& src1,
2036 const LogicVRegister& src2);
2037 LogicVRegister ssubl2(VectorFormat vform,
2038 LogicVRegister dst,
2039 const LogicVRegister& src1,
2040 const LogicVRegister& src2);
2041 LogicVRegister ssubw(VectorFormat vform,
2042 LogicVRegister dst,
2043 const LogicVRegister& src1,
2044 const LogicVRegister& src2);
2045 LogicVRegister ssubw2(VectorFormat vform,
2046 LogicVRegister dst,
2047 const LogicVRegister& src1,
2048 const LogicVRegister& src2);
2049 LogicVRegister uminmax(VectorFormat vform,
2050 LogicVRegister dst,
2051 const LogicVRegister& src1,
2052 const LogicVRegister& src2,
2053 bool max);
2054 LogicVRegister umax(VectorFormat vform,
2055 LogicVRegister dst,
2056 const LogicVRegister& src1,
2057 const LogicVRegister& src2);
2058 LogicVRegister umin(VectorFormat vform,
2059 LogicVRegister dst,
2060 const LogicVRegister& src1,
2061 const LogicVRegister& src2);
2062 LogicVRegister uminmaxp(VectorFormat vform,
2063 LogicVRegister dst,
2064 int dst_index,
2065 const LogicVRegister& src,
2066 bool max);
2067 LogicVRegister umaxp(VectorFormat vform,
2068 LogicVRegister dst,
2069 const LogicVRegister& src1,
2070 const LogicVRegister& src2);
2071 LogicVRegister uminp(VectorFormat vform,
2072 LogicVRegister dst,
2073 const LogicVRegister& src1,
2074 const LogicVRegister& src2);
2075 LogicVRegister uminmaxv(VectorFormat vform,
2076 LogicVRegister dst,
2077 const LogicVRegister& src,
2078 bool max);
2079 LogicVRegister umaxv(VectorFormat vform,
2080 LogicVRegister dst,
2081 const LogicVRegister& src);
2082 LogicVRegister uminv(VectorFormat vform,
2083 LogicVRegister dst,
2084 const LogicVRegister& src);
2085 LogicVRegister trn1(VectorFormat vform,
2086 LogicVRegister dst,
2087 const LogicVRegister& src1,
2088 const LogicVRegister& src2);
2089 LogicVRegister trn2(VectorFormat vform,
2090 LogicVRegister dst,
2091 const LogicVRegister& src1,
2092 const LogicVRegister& src2);
2093 LogicVRegister zip1(VectorFormat vform,
2094 LogicVRegister dst,
2095 const LogicVRegister& src1,
2096 const LogicVRegister& src2);
2097 LogicVRegister zip2(VectorFormat vform,
2098 LogicVRegister dst,
2099 const LogicVRegister& src1,
2100 const LogicVRegister& src2);
2101 LogicVRegister uzp1(VectorFormat vform,
2102 LogicVRegister dst,
2103 const LogicVRegister& src1,
2104 const LogicVRegister& src2);
2105 LogicVRegister uzp2(VectorFormat vform,
2106 LogicVRegister dst,
2107 const LogicVRegister& src1,
2108 const LogicVRegister& src2);
2109 LogicVRegister shl(VectorFormat vform,
2110 LogicVRegister dst,
2111 const LogicVRegister& src,
2112 int shift);
2113 LogicVRegister scvtf(VectorFormat vform,
2114 LogicVRegister dst,
2115 const LogicVRegister& src,
2116 int fbits,
2117 FPRounding rounding_mode);
2118 LogicVRegister ucvtf(VectorFormat vform,
2119 LogicVRegister dst,
2120 const LogicVRegister& src,
2121 int fbits,
2122 FPRounding rounding_mode);
2123 LogicVRegister sshll(VectorFormat vform,
2124 LogicVRegister dst,
2125 const LogicVRegister& src,
2126 int shift);
2127 LogicVRegister sshll2(VectorFormat vform,
2128 LogicVRegister dst,
2129 const LogicVRegister& src,
2130 int shift);
2131 LogicVRegister shll(VectorFormat vform,
2132 LogicVRegister dst,
2133 const LogicVRegister& src);
2134 LogicVRegister shll2(VectorFormat vform,
2135 LogicVRegister dst,
2136 const LogicVRegister& src);
2137 LogicVRegister ushll(VectorFormat vform,
2138 LogicVRegister dst,
2139 const LogicVRegister& src,
2140 int shift);
2141 LogicVRegister ushll2(VectorFormat vform,
2142 LogicVRegister dst,
2143 const LogicVRegister& src,
2144 int shift);
2145 LogicVRegister sli(VectorFormat vform,
2146 LogicVRegister dst,
2147 const LogicVRegister& src,
2148 int shift);
2149 LogicVRegister sri(VectorFormat vform,
2150 LogicVRegister dst,
2151 const LogicVRegister& src,
2152 int shift);
2153 LogicVRegister sshr(VectorFormat vform,
2154 LogicVRegister dst,
2155 const LogicVRegister& src,
2156 int shift);
2157 LogicVRegister ushr(VectorFormat vform,
2158 LogicVRegister dst,
2159 const LogicVRegister& src,
2160 int shift);
2161 LogicVRegister ssra(VectorFormat vform,
2162 LogicVRegister dst,
2163 const LogicVRegister& src,
2164 int shift);
2165 LogicVRegister usra(VectorFormat vform,
2166 LogicVRegister dst,
2167 const LogicVRegister& src,
2168 int shift);
2169 LogicVRegister srsra(VectorFormat vform,
2170 LogicVRegister dst,
2171 const LogicVRegister& src,
2172 int shift);
2173 LogicVRegister ursra(VectorFormat vform,
2174 LogicVRegister dst,
2175 const LogicVRegister& src,
2176 int shift);
2177 LogicVRegister suqadd(VectorFormat vform,
2178 LogicVRegister dst,
2179 const LogicVRegister& src);
2180 LogicVRegister usqadd(VectorFormat vform,
2181 LogicVRegister dst,
2182 const LogicVRegister& src);
2183 LogicVRegister sqshl(VectorFormat vform,
2184 LogicVRegister dst,
2185 const LogicVRegister& src,
2186 int shift);
2187 LogicVRegister uqshl(VectorFormat vform,
2188 LogicVRegister dst,
2189 const LogicVRegister& src,
2190 int shift);
2191 LogicVRegister sqshlu(VectorFormat vform,
2192 LogicVRegister dst,
2193 const LogicVRegister& src,
2194 int shift);
2195 LogicVRegister abs(VectorFormat vform,
2196 LogicVRegister dst,
2197 const LogicVRegister& src);
2198 LogicVRegister neg(VectorFormat vform,
2199 LogicVRegister dst,
2200 const LogicVRegister& src);
2201 LogicVRegister extractnarrow(VectorFormat vform,
2202 LogicVRegister dst,
2203 bool dstIsSigned,
2204 const LogicVRegister& src,
2205 bool srcIsSigned);
2206 LogicVRegister xtn(VectorFormat vform,
2207 LogicVRegister dst,
2208 const LogicVRegister& src);
2209 LogicVRegister sqxtn(VectorFormat vform,
2210 LogicVRegister dst,
2211 const LogicVRegister& src);
2212 LogicVRegister uqxtn(VectorFormat vform,
2213 LogicVRegister dst,
2214 const LogicVRegister& src);
2215 LogicVRegister sqxtun(VectorFormat vform,
2216 LogicVRegister dst,
2217 const LogicVRegister& src);
2218 LogicVRegister absdiff(VectorFormat vform,
2219 LogicVRegister dst,
2220 const LogicVRegister& src1,
2221 const LogicVRegister& src2,
2222 bool issigned);
2223 LogicVRegister saba(VectorFormat vform,
2224 LogicVRegister dst,
2225 const LogicVRegister& src1,
2226 const LogicVRegister& src2);
2227 LogicVRegister uaba(VectorFormat vform,
2228 LogicVRegister dst,
2229 const LogicVRegister& src1,
2230 const LogicVRegister& src2);
2231 LogicVRegister shrn(VectorFormat vform,
2232 LogicVRegister dst,
2233 const LogicVRegister& src,
2234 int shift);
2235 LogicVRegister shrn2(VectorFormat vform,
2236 LogicVRegister dst,
2237 const LogicVRegister& src,
2238 int shift);
2239 LogicVRegister rshrn(VectorFormat vform,
2240 LogicVRegister dst,
2241 const LogicVRegister& src,
2242 int shift);
2243 LogicVRegister rshrn2(VectorFormat vform,
2244 LogicVRegister dst,
2245 const LogicVRegister& src,
2246 int shift);
2247 LogicVRegister uqshrn(VectorFormat vform,
2248 LogicVRegister dst,
2249 const LogicVRegister& src,
2250 int shift);
2251 LogicVRegister uqshrn2(VectorFormat vform,
2252 LogicVRegister dst,
2253 const LogicVRegister& src,
2254 int shift);
2255 LogicVRegister uqrshrn(VectorFormat vform,
2256 LogicVRegister dst,
2257 const LogicVRegister& src,
2258 int shift);
2259 LogicVRegister uqrshrn2(VectorFormat vform,
2260 LogicVRegister dst,
2261 const LogicVRegister& src,
2262 int shift);
2263 LogicVRegister sqshrn(VectorFormat vform,
2264 LogicVRegister dst,
2265 const LogicVRegister& src,
2266 int shift);
2267 LogicVRegister sqshrn2(VectorFormat vform,
2268 LogicVRegister dst,
2269 const LogicVRegister& src,
2270 int shift);
2271 LogicVRegister sqrshrn(VectorFormat vform,
2272 LogicVRegister dst,
2273 const LogicVRegister& src,
2274 int shift);
2275 LogicVRegister sqrshrn2(VectorFormat vform,
2276 LogicVRegister dst,
2277 const LogicVRegister& src,
2278 int shift);
2279 LogicVRegister sqshrun(VectorFormat vform,
2280 LogicVRegister dst,
2281 const LogicVRegister& src,
2282 int shift);
2283 LogicVRegister sqshrun2(VectorFormat vform,
2284 LogicVRegister dst,
2285 const LogicVRegister& src,
2286 int shift);
2287 LogicVRegister sqrshrun(VectorFormat vform,
2288 LogicVRegister dst,
2289 const LogicVRegister& src,
2290 int shift);
2291 LogicVRegister sqrshrun2(VectorFormat vform,
2292 LogicVRegister dst,
2293 const LogicVRegister& src,
2294 int shift);
2295 LogicVRegister sqrdmulh(VectorFormat vform,
2296 LogicVRegister dst,
2297 const LogicVRegister& src1,
2298 const LogicVRegister& src2,
2299 bool round = true);
2300 LogicVRegister sqdmulh(VectorFormat vform,
2301 LogicVRegister dst,
2302 const LogicVRegister& src1,
2303 const LogicVRegister& src2);
2304 #define NEON_3VREG_LOGIC_LIST(V) \
2305 V(addhn) \
2306 V(addhn2) \
2307 V(raddhn) \
2308 V(raddhn2) \
2309 V(subhn) \
2310 V(subhn2) \
2311 V(rsubhn) \
2312 V(rsubhn2) \
2313 V(pmull) \
2314 V(pmull2) \
2315 V(sabal) \
2316 V(sabal2) \
2317 V(uabal) \
2318 V(uabal2) \
2319 V(sabdl) \
2320 V(sabdl2) \
2321 V(uabdl) \
2322 V(uabdl2) \
2323 V(smull) \
2324 V(smull2) \
2325 V(umull) \
2326 V(umull2) \
2327 V(smlal) \
2328 V(smlal2) \
2329 V(umlal) \
2330 V(umlal2) \
2331 V(smlsl) \
2332 V(smlsl2) \
2333 V(umlsl) \
2334 V(umlsl2) \
2335 V(sqdmlal) \
2336 V(sqdmlal2) \
2337 V(sqdmlsl) \
2338 V(sqdmlsl2) \
2339 V(sqdmull) \
2340 V(sqdmull2)
2341
2342 #define DEFINE_LOGIC_FUNC(FXN) \
2343 LogicVRegister FXN(VectorFormat vform, \
2344 LogicVRegister dst, \
2345 const LogicVRegister& src1, \
2346 const LogicVRegister& src2);
2347 NEON_3VREG_LOGIC_LIST(DEFINE_LOGIC_FUNC)
2348 #undef DEFINE_LOGIC_FUNC
2349
2350 #define NEON_FP3SAME_LIST(V) \
2351 V(fadd, FPAdd, false) \
2352 V(fsub, FPSub, true) \
2353 V(fmul, FPMul, true) \
2354 V(fmulx, FPMulx, true) \
2355 V(fdiv, FPDiv, true) \
2356 V(fmax, FPMax, false) \
2357 V(fmin, FPMin, false) \
2358 V(fmaxnm, FPMaxNM, false) \
2359 V(fminnm, FPMinNM, false)
2360
2361 #define DECLARE_NEON_FP_VECTOR_OP(FN, OP, PROCNAN) \
2362 template <typename T> \
2363 LogicVRegister FN(VectorFormat vform, \
2364 LogicVRegister dst, \
2365 const LogicVRegister& src1, \
2366 const LogicVRegister& src2); \
2367 LogicVRegister FN(VectorFormat vform, \
2368 LogicVRegister dst, \
2369 const LogicVRegister& src1, \
2370 const LogicVRegister& src2);
2371 NEON_FP3SAME_LIST(DECLARE_NEON_FP_VECTOR_OP)
2372 #undef DECLARE_NEON_FP_VECTOR_OP
2373
2374 #define NEON_FPPAIRWISE_LIST(V) \
2375 V(faddp, fadd, FPAdd) \
2376 V(fmaxp, fmax, FPMax) \
2377 V(fmaxnmp, fmaxnm, FPMaxNM) \
2378 V(fminp, fmin, FPMin) \
2379 V(fminnmp, fminnm, FPMinNM)
2380
2381 #define DECLARE_NEON_FP_PAIR_OP(FNP, FN, OP) \
2382 LogicVRegister FNP(VectorFormat vform, \
2383 LogicVRegister dst, \
2384 const LogicVRegister& src1, \
2385 const LogicVRegister& src2); \
2386 LogicVRegister FNP(VectorFormat vform, \
2387 LogicVRegister dst, \
2388 const LogicVRegister& src);
2389 NEON_FPPAIRWISE_LIST(DECLARE_NEON_FP_PAIR_OP)
2390 #undef DECLARE_NEON_FP_PAIR_OP
2391
2392 template <typename T>
2393 LogicVRegister frecps(VectorFormat vform,
2394 LogicVRegister dst,
2395 const LogicVRegister& src1,
2396 const LogicVRegister& src2);
2397 LogicVRegister frecps(VectorFormat vform,
2398 LogicVRegister dst,
2399 const LogicVRegister& src1,
2400 const LogicVRegister& src2);
2401 template <typename T>
2402 LogicVRegister frsqrts(VectorFormat vform,
2403 LogicVRegister dst,
2404 const LogicVRegister& src1,
2405 const LogicVRegister& src2);
2406 LogicVRegister frsqrts(VectorFormat vform,
2407 LogicVRegister dst,
2408 const LogicVRegister& src1,
2409 const LogicVRegister& src2);
2410 template <typename T>
2411 LogicVRegister fmla(VectorFormat vform,
2412 LogicVRegister dst,
2413 const LogicVRegister& src1,
2414 const LogicVRegister& src2);
2415 LogicVRegister fmla(VectorFormat vform,
2416 LogicVRegister dst,
2417 const LogicVRegister& src1,
2418 const LogicVRegister& src2);
2419 template <typename T>
2420 LogicVRegister fmls(VectorFormat vform,
2421 LogicVRegister dst,
2422 const LogicVRegister& src1,
2423 const LogicVRegister& src2);
2424 LogicVRegister fmls(VectorFormat vform,
2425 LogicVRegister dst,
2426 const LogicVRegister& src1,
2427 const LogicVRegister& src2);
2428 LogicVRegister fnmul(VectorFormat vform,
2429 LogicVRegister dst,
2430 const LogicVRegister& src1,
2431 const LogicVRegister& src2);
2432
2433 template <typename T>
2434 LogicVRegister fcmp(VectorFormat vform,
2435 LogicVRegister dst,
2436 const LogicVRegister& src1,
2437 const LogicVRegister& src2,
2438 Condition cond);
2439 LogicVRegister fcmp(VectorFormat vform,
2440 LogicVRegister dst,
2441 const LogicVRegister& src1,
2442 const LogicVRegister& src2,
2443 Condition cond);
2444 LogicVRegister fabscmp(VectorFormat vform,
2445 LogicVRegister dst,
2446 const LogicVRegister& src1,
2447 const LogicVRegister& src2,
2448 Condition cond);
2449 LogicVRegister fcmp_zero(VectorFormat vform,
2450 LogicVRegister dst,
2451 const LogicVRegister& src,
2452 Condition cond);
2453
2454 template <typename T>
2455 LogicVRegister fneg(VectorFormat vform,
2456 LogicVRegister dst,
2457 const LogicVRegister& src);
2458 LogicVRegister fneg(VectorFormat vform,
2459 LogicVRegister dst,
2460 const LogicVRegister& src);
2461 template <typename T>
2462 LogicVRegister frecpx(VectorFormat vform,
2463 LogicVRegister dst,
2464 const LogicVRegister& src);
2465 LogicVRegister frecpx(VectorFormat vform,
2466 LogicVRegister dst,
2467 const LogicVRegister& src);
2468 template <typename T>
2469 LogicVRegister fabs_(VectorFormat vform,
2470 LogicVRegister dst,
2471 const LogicVRegister& src);
2472 LogicVRegister fabs_(VectorFormat vform,
2473 LogicVRegister dst,
2474 const LogicVRegister& src);
2475 LogicVRegister fabd(VectorFormat vform,
2476 LogicVRegister dst,
2477 const LogicVRegister& src1,
2478 const LogicVRegister& src2);
2479 LogicVRegister frint(VectorFormat vform,
2480 LogicVRegister dst,
2481 const LogicVRegister& src,
2482 FPRounding rounding_mode,
2483 bool inexact_exception = false);
2484 LogicVRegister fcvts(VectorFormat vform,
2485 LogicVRegister dst,
2486 const LogicVRegister& src,
2487 FPRounding rounding_mode,
2488 int fbits = 0);
2489 LogicVRegister fcvtu(VectorFormat vform,
2490 LogicVRegister dst,
2491 const LogicVRegister& src,
2492 FPRounding rounding_mode,
2493 int fbits = 0);
2494 LogicVRegister fcvtl(VectorFormat vform,
2495 LogicVRegister dst,
2496 const LogicVRegister& src);
2497 LogicVRegister fcvtl2(VectorFormat vform,
2498 LogicVRegister dst,
2499 const LogicVRegister& src);
2500 LogicVRegister fcvtn(VectorFormat vform,
2501 LogicVRegister dst,
2502 const LogicVRegister& src);
2503 LogicVRegister fcvtn2(VectorFormat vform,
2504 LogicVRegister dst,
2505 const LogicVRegister& src);
2506 LogicVRegister fcvtxn(VectorFormat vform,
2507 LogicVRegister dst,
2508 const LogicVRegister& src);
2509 LogicVRegister fcvtxn2(VectorFormat vform,
2510 LogicVRegister dst,
2511 const LogicVRegister& src);
2512 LogicVRegister fsqrt(VectorFormat vform,
2513 LogicVRegister dst,
2514 const LogicVRegister& src);
2515 LogicVRegister frsqrte(VectorFormat vform,
2516 LogicVRegister dst,
2517 const LogicVRegister& src);
2518 LogicVRegister frecpe(VectorFormat vform,
2519 LogicVRegister dst,
2520 const LogicVRegister& src,
2521 FPRounding rounding);
2522 LogicVRegister ursqrte(VectorFormat vform,
2523 LogicVRegister dst,
2524 const LogicVRegister& src);
2525 LogicVRegister urecpe(VectorFormat vform,
2526 LogicVRegister dst,
2527 const LogicVRegister& src);
2528
2529 typedef float (Simulator::*FPMinMaxOp)(float a, float b);
2530
2531 LogicVRegister fminmaxv(VectorFormat vform,
2532 LogicVRegister dst,
2533 const LogicVRegister& src,
2534 FPMinMaxOp Op);
2535
2536 LogicVRegister fminv(VectorFormat vform,
2537 LogicVRegister dst,
2538 const LogicVRegister& src);
2539 LogicVRegister fmaxv(VectorFormat vform,
2540 LogicVRegister dst,
2541 const LogicVRegister& src);
2542 LogicVRegister fminnmv(VectorFormat vform,
2543 LogicVRegister dst,
2544 const LogicVRegister& src);
2545 LogicVRegister fmaxnmv(VectorFormat vform,
2546 LogicVRegister dst,
2547 const LogicVRegister& src);
2548
2549 static const uint32_t CRC32_POLY = 0x04C11DB7;
2550 static const uint32_t CRC32C_POLY = 0x1EDC6F41;
2551 uint32_t Poly32Mod2(unsigned n, uint64_t data, uint32_t poly);
2552 template <typename T>
2553 uint32_t Crc32Checksum(uint32_t acc, T val, uint32_t poly);
2554 uint32_t Crc32Checksum(uint32_t acc, uint64_t val, uint32_t poly);
2555
2556 void SysOp_W(int op, int64_t val);
2557
2558 template <typename T>
2559 T FPRecipSqrtEstimate(T op);
2560 template <typename T>
2561 T FPRecipEstimate(T op, FPRounding rounding);
2562 template <typename T, typename R>
2563 R FPToFixed(T op, int fbits, bool is_signed, FPRounding rounding);
2564
2565 void FPCompare(double val0, double val1, FPTrapFlags trap);
2566 double FPRoundInt(double value, FPRounding round_mode);
2567 double FPToDouble(float value);
2568 float FPToFloat(double value, FPRounding round_mode);
2569 float FPToFloat(float16 value);
2570 float16 FPToFloat16(float value, FPRounding round_mode);
2571 float16 FPToFloat16(double value, FPRounding round_mode);
2572 double recip_sqrt_estimate(double a);
2573 double recip_estimate(double a);
2574 double FPRecipSqrtEstimate(double a);
2575 double FPRecipEstimate(double a);
2576 double FixedToDouble(int64_t src, int fbits, FPRounding round_mode);
2577 double UFixedToDouble(uint64_t src, int fbits, FPRounding round_mode);
2578 float FixedToFloat(int64_t src, int fbits, FPRounding round_mode);
2579 float UFixedToFloat(uint64_t src, int fbits, FPRounding round_mode);
2580 int32_t FPToInt32(double value, FPRounding rmode);
2581 int64_t FPToInt64(double value, FPRounding rmode);
2582 uint32_t FPToUInt32(double value, FPRounding rmode);
2583 uint64_t FPToUInt64(double value, FPRounding rmode);
2584
2585 template <typename T>
2586 T FPAdd(T op1, T op2);
2587
2588 template <typename T>
2589 T FPDiv(T op1, T op2);
2590
2591 template <typename T>
2592 T FPMax(T a, T b);
2593
2594 template <typename T>
2595 T FPMaxNM(T a, T b);
2596
2597 template <typename T>
2598 T FPMin(T a, T b);
2599
2600 template <typename T>
2601 T FPMinNM(T a, T b);
2602
2603 template <typename T>
2604 T FPMul(T op1, T op2);
2605
2606 template <typename T>
2607 T FPMulx(T op1, T op2);
2608
2609 template <typename T>
2610 T FPMulAdd(T a, T op1, T op2);
2611
2612 template <typename T>
2613 T FPSqrt(T op);
2614
2615 template <typename T>
2616 T FPSub(T op1, T op2);
2617
2618 template <typename T>
2619 T FPRecipStepFused(T op1, T op2);
2620
2621 template <typename T>
2622 T FPRSqrtStepFused(T op1, T op2);
2623
2624 // This doesn't do anything at the moment. We'll need it if we want support
2625 // for cumulative exception bits or floating-point exceptions.
FPProcessException()2626 void FPProcessException() { }
2627
2628 bool FPProcessNaNs(const Instruction* instr);
2629
2630 // Pseudo Printf instruction
2631 void DoPrintf(const Instruction* instr);
2632
2633 // Processor state ---------------------------------------
2634
2635 // Simulated monitors for exclusive access instructions.
2636 SimExclusiveLocalMonitor local_monitor_;
2637 SimExclusiveGlobalMonitor global_monitor_;
2638
2639 // Output stream.
2640 FILE* stream_;
2641 PrintDisassembler* print_disasm_;
2642
2643 // Instruction statistics instrumentation.
2644 Instrument* instrumentation_;
2645
2646 // General purpose registers. Register 31 is the stack pointer.
2647 SimRegister registers_[kNumberOfRegisters];
2648
2649 // Vector registers
2650 SimVRegister vregisters_[kNumberOfVRegisters];
2651
2652 // Program Status Register.
2653 // bits[31, 27]: Condition flags N, Z, C, and V.
2654 // (Negative, Zero, Carry, Overflow)
2655 SimSystemRegister nzcv_;
2656
2657 // Floating-Point Control Register
2658 SimSystemRegister fpcr_;
2659
2660 // Only a subset of FPCR features are supported by the simulator. This helper
2661 // checks that the FPCR settings are supported.
2662 //
2663 // This is checked when floating-point instructions are executed, not when
2664 // FPCR is set. This allows generated code to modify FPCR for external
2665 // functions, or to save and restore it when entering and leaving generated
2666 // code.
AssertSupportedFPCR()2667 void AssertSupportedFPCR() {
2668 VIXL_ASSERT(fpcr().FZ() == 0); // No flush-to-zero support.
2669 VIXL_ASSERT(fpcr().RMode() == FPTieEven); // Ties-to-even rounding only.
2670
2671 // The simulator does not support half-precision operations so fpcr().AHP()
2672 // is irrelevant, and is not checked here.
2673 }
2674
CalcNFlag(uint64_t result,unsigned reg_size)2675 static int CalcNFlag(uint64_t result, unsigned reg_size) {
2676 return (result >> (reg_size - 1)) & 1;
2677 }
2678
CalcZFlag(uint64_t result)2679 static int CalcZFlag(uint64_t result) {
2680 return result == 0;
2681 }
2682
2683 static const uint32_t kConditionFlagsMask = 0xf0000000;
2684
2685 // Stack
2686 byte* stack_;
2687 static const int stack_protection_size_ = 128 * KBytes;
2688 static const int stack_size_ = (2 * MBytes) + (2 * stack_protection_size_);
2689 byte* stack_limit_;
2690
2691 Decoder* decoder_;
2692 // Indicates if the pc has been modified by the instruction and should not be
2693 // automatically incremented.
2694 bool pc_modified_;
2695 const Instruction* pc_;
2696 const Instruction* resume_pc_;
2697
2698 static const char* xreg_names[];
2699 static const char* wreg_names[];
2700 static const char* sreg_names[];
2701 static const char* dreg_names[];
2702 static const char* vreg_names[];
2703
2704 static const Instruction* kEndOfSimAddress;
2705
2706 private:
2707 template <typename T>
2708 static T FPDefaultNaN();
2709
2710 // Standard NaN processing.
2711 template <typename T>
FPProcessNaN(T op)2712 T FPProcessNaN(T op) {
2713 VIXL_ASSERT(std::isnan(op));
2714 if (IsSignallingNaN(op)) {
2715 FPProcessException();
2716 }
2717 return DN() ? FPDefaultNaN<T>() : ToQuietNaN(op);
2718 }
2719
2720 template <typename T>
FPProcessNaNs(T op1,T op2)2721 T FPProcessNaNs(T op1, T op2) {
2722 if (IsSignallingNaN(op1)) {
2723 return FPProcessNaN(op1);
2724 } else if (IsSignallingNaN(op2)) {
2725 return FPProcessNaN(op2);
2726 } else if (std::isnan(op1)) {
2727 VIXL_ASSERT(IsQuietNaN(op1));
2728 return FPProcessNaN(op1);
2729 } else if (std::isnan(op2)) {
2730 VIXL_ASSERT(IsQuietNaN(op2));
2731 return FPProcessNaN(op2);
2732 } else {
2733 return 0.0;
2734 }
2735 }
2736
2737 template <typename T>
FPProcessNaNs3(T op1,T op2,T op3)2738 T FPProcessNaNs3(T op1, T op2, T op3) {
2739 if (IsSignallingNaN(op1)) {
2740 return FPProcessNaN(op1);
2741 } else if (IsSignallingNaN(op2)) {
2742 return FPProcessNaN(op2);
2743 } else if (IsSignallingNaN(op3)) {
2744 return FPProcessNaN(op3);
2745 } else if (std::isnan(op1)) {
2746 VIXL_ASSERT(IsQuietNaN(op1));
2747 return FPProcessNaN(op1);
2748 } else if (std::isnan(op2)) {
2749 VIXL_ASSERT(IsQuietNaN(op2));
2750 return FPProcessNaN(op2);
2751 } else if (std::isnan(op3)) {
2752 VIXL_ASSERT(IsQuietNaN(op3));
2753 return FPProcessNaN(op3);
2754 } else {
2755 return 0.0;
2756 }
2757 }
2758
2759 bool coloured_trace_;
2760
2761 // A set of TraceParameters flags.
2762 int trace_parameters_;
2763
2764 // Indicates whether the instruction instrumentation is active.
2765 bool instruction_stats_;
2766
2767 // Indicates whether the exclusive-access warning has been printed.
2768 bool print_exclusive_access_warning_;
2769 void PrintExclusiveAccessWarning();
2770
2771 // Indicates that the simulator ran out of memory at some point.
2772 // Data structures may not be fully allocated.
2773 bool oom_;
2774
2775 public:
2776 // True if the simulator ran out of memory during or after construction.
oom()2777 bool oom() const { return oom_; }
2778
2779 protected:
2780 // Moz: Synchronizes access between main thread and compilation threads.
2781 PRLock* lock_;
2782 #ifdef DEBUG
2783 PRThread* lockOwner_;
2784 #endif
2785 Redirection* redirection_;
2786 mozilla::Vector<int64_t, 0, js::SystemAllocPolicy> spStack_;
2787 };
2788 } // namespace vixl
2789
2790 #endif // JS_SIMULATOR_ARM64
2791 #endif // VIXL_A64_SIMULATOR_A64_H_
2792