1 /* simulator.c -- Interface for the AArch64 simulator.
3 Copyright (C) 2015 Free Software Foundation, Inc.
5 Contributed by Red Hat.
7 This file is part of GDB.
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 3 of the License, or
12 (at your option) any later version.
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with this program. If not, see <http://www.gnu.org/licenses/>. */
26 #include <sys/types.h>
34 #include "simulator.h"
41 bfd_boolean disas = FALSE;
43 #define TST(_flag) (aarch64_test_CPSR_bit (cpu, _flag))
44 #define IS_SET(_X) ( TST (( _X )))
45 #define IS_CLEAR(_X) (!TST (( _X )))
47 #define HALT_UNALLOC \
50 if (TRACE_INSN_P (cpu)) \
52 aarch64_print_insn (CPU_STATE (cpu), aarch64_get_PC (cpu)); \
54 "Unallocated instruction detected at sim line %d,"\
55 " exe addr %" PRIx64, \
56 __LINE__, aarch64_get_PC (cpu)); \
58 sim_engine_halt (CPU_STATE (cpu), cpu, NULL, aarch64_get_PC (cpu),\
59 sim_stopped, SIM_SIGILL); \
66 if (TRACE_INSN_P (cpu)) \
68 aarch64_print_insn (CPU_STATE (cpu), aarch64_get_PC (cpu)); \
70 "Unimplemented instruction detected at sim line %d,"\
71 " exe addr %" PRIx64, \
72 __LINE__, aarch64_get_PC (cpu)); \
74 sim_engine_halt (CPU_STATE (cpu), cpu, NULL, aarch64_get_PC (cpu),\
75 sim_stopped, SIM_SIGABRT); \
79 #define NYI_assert(HI, LO, EXPECTED) \
82 if (uimm (aarch64_get_instr (cpu), (HI), (LO)) != (EXPECTED)) \
87 #define HALT_UNREACHABLE \
90 TRACE_EVENTS (cpu, "ISE: unreachable code point"); \
91 sim_engine_abort (NULL, cpu, aarch64_get_PC (cpu), "Internal Error"); \
95 /* Helper functions used by expandLogicalImmediate. */
97 /* for i = 1, ... N result<i-1> = 1 other bits are zero */
98 static inline uint64_t
101 return (N == 64 ? (uint64_t)-1UL : ((1UL << N) - 1));
104 /* result<0> to val<N> */
105 static inline uint64_t
106 pickbit (uint64_t val, int N)
108 return pickbits64 (val, N, N);
112 expand_logical_immediate (uint32_t S, uint32_t R, uint32_t N)
118 /* The immediate value is S+1 bits to 1, left rotated by SIMDsize - R
119 (in other words, right rotated by R), then replicated. */
123 mask = 0xffffffffffffffffull;
129 case 0x00 ... 0x1f: /* 0xxxxx */ simd_size = 32; break;
130 case 0x20 ... 0x2f: /* 10xxxx */ simd_size = 16; S &= 0xf; break;
131 case 0x30 ... 0x37: /* 110xxx */ simd_size = 8; S &= 0x7; break;
132 case 0x38 ... 0x3b: /* 1110xx */ simd_size = 4; S &= 0x3; break;
133 case 0x3c ... 0x3d: /* 11110x */ simd_size = 2; S &= 0x1; break;
136 mask = (1ull << simd_size) - 1;
137 /* Top bits are IGNORED. */
141 /* NOTE: if S = simd_size - 1 we get 0xf..f which is rejected. */
142 if (S == simd_size - 1)
145 /* S+1 consecutive bits to 1. */
146 /* NOTE: S can't be 63 due to detection above. */
147 imm = (1ull << (S + 1)) - 1;
149 /* Rotate to the left by simd_size - R. */
151 imm = ((imm << (simd_size - R)) & mask) | (imm >> R);
153 /* Replicate the value according to SIMD size. */
156 case 2: imm = (imm << 2) | imm;
157 case 4: imm = (imm << 4) | imm;
158 case 8: imm = (imm << 8) | imm;
159 case 16: imm = (imm << 16) | imm;
160 case 32: imm = (imm << 32) | imm;
168 /* Instr[22,10] encodes N immr and imms. we want a lookup table
169 for each possible combination i.e. 13 bits worth of int entries. */
170 #define LI_TABLE_SIZE (1 << 13)
171 static uint64_t LITable[LI_TABLE_SIZE];
174 aarch64_init_LIT_table (void)
178 for (index = 0; index < LI_TABLE_SIZE; index++)
180 uint32_t N = uimm (index, 12, 12);
181 uint32_t immr = uimm (index, 11, 6);
182 uint32_t imms = uimm (index, 5, 0);
184 LITable [index] = expand_logical_immediate (imms, immr, N);
189 dexNotify (sim_cpu *cpu)
191 /* instr[14,0] == type : 0 ==> method entry, 1 ==> method reentry
192 2 ==> exit Java, 3 ==> start next bytecode. */
193 uint32_t type = uimm (aarch64_get_instr (cpu), 14, 0);
195 TRACE_EVENTS (cpu, "Notify Insn encountered, type = 0x%x", type);
200 /* aarch64_notifyMethodEntry (aarch64_get_reg_u64 (cpu, R23, 0),
201 aarch64_get_reg_u64 (cpu, R22, 0)); */
204 /* aarch64_notifyMethodReentry (aarch64_get_reg_u64 (cpu, R23, 0),
205 aarch64_get_reg_u64 (cpu, R22, 0)); */
208 /* aarch64_notifyMethodExit (); */
211 /* aarch64_notifyBCStart (aarch64_get_reg_u64 (cpu, R23, 0),
212 aarch64_get_reg_u64 (cpu, R22, 0)); */
217 /* secondary decode within top level groups */
220 dexPseudo (sim_cpu *cpu)
222 /* assert instr[28,27] = 00
224 We provide 2 pseudo instructions:
226 HALT stops execution of the simulator causing an immediate
227 return to the x86 code which entered it.
229 CALLOUT initiates recursive entry into x86 code. A register
230 argument holds the address of the x86 routine. Immediate
231 values in the instruction identify the number of general
232 purpose and floating point register arguments to be passed
233 and the type of any value to be returned. */
235 uint32_t PSEUDO_HALT = 0xE0000000U;
236 uint32_t PSEUDO_CALLOUT = 0x00018000U;
237 uint32_t PSEUDO_CALLOUTR = 0x00018001U;
238 uint32_t PSEUDO_NOTIFY = 0x00014000U;
241 if (aarch64_get_instr (cpu) == PSEUDO_HALT)
243 TRACE_EVENTS (cpu, " Pseudo Halt Instruction");
244 sim_engine_halt (CPU_STATE (cpu), cpu, NULL, aarch64_get_PC (cpu),
245 sim_stopped, SIM_SIGTRAP);
248 dispatch = uimm (aarch64_get_instr (cpu), 31, 15);
250 /* We do not handle callouts at the moment. */
251 if (dispatch == PSEUDO_CALLOUT || dispatch == PSEUDO_CALLOUTR)
253 TRACE_EVENTS (cpu, " Callout");
254 sim_engine_halt (CPU_STATE (cpu), cpu, NULL, aarch64_get_PC (cpu),
255 sim_stopped, SIM_SIGABRT);
258 else if (dispatch == PSEUDO_NOTIFY)
265 /* Load-store single register (unscaled offset)
266 These instructions employ a base register plus an unscaled signed
269 N.B. the base register (source) can be Xn or SP. all other
270 registers may not be SP. */
272 /* 32 bit load 32 bit unscaled signed 9 bit. */
274 ldur32 (sim_cpu *cpu, int32_t offset)
276 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
277 unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
279 aarch64_set_reg_u64 (cpu, rt, NO_SP, aarch64_get_mem_u32
280 (cpu, aarch64_get_reg_u64 (cpu, rn, SP_OK)
284 /* 64 bit load 64 bit unscaled signed 9 bit. */
286 ldur64 (sim_cpu *cpu, int32_t offset)
288 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
289 unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
291 aarch64_set_reg_u64 (cpu, rt, NO_SP, aarch64_get_mem_u64
292 (cpu, aarch64_get_reg_u64 (cpu, rn, SP_OK)
296 /* 32 bit load zero-extended byte unscaled signed 9 bit. */
298 ldurb32 (sim_cpu *cpu, int32_t offset)
300 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
301 unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
303 aarch64_set_reg_u64 (cpu, rt, NO_SP, aarch64_get_mem_u8
304 (cpu, aarch64_get_reg_u64 (cpu, rn, SP_OK)
308 /* 32 bit load sign-extended byte unscaled signed 9 bit. */
310 ldursb32 (sim_cpu *cpu, int32_t offset)
312 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
313 unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
315 aarch64_set_reg_u64 (cpu, rt, NO_SP, (uint32_t) aarch64_get_mem_s8
316 (cpu, aarch64_get_reg_u64 (cpu, rn, SP_OK)
320 /* 64 bit load sign-extended byte unscaled signed 9 bit. */
322 ldursb64 (sim_cpu *cpu, int32_t offset)
324 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
325 unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
327 aarch64_set_reg_s64 (cpu, rt, NO_SP, aarch64_get_mem_s8
328 (cpu, aarch64_get_reg_u64 (cpu, rn, SP_OK)
332 /* 32 bit load zero-extended short unscaled signed 9 bit */
334 ldurh32 (sim_cpu *cpu, int32_t offset)
336 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
337 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
339 aarch64_set_reg_u64 (cpu, rd, NO_SP, aarch64_get_mem_u16
340 (cpu, aarch64_get_reg_u64 (cpu, rn, SP_OK)
344 /* 32 bit load sign-extended short unscaled signed 9 bit */
346 ldursh32 (sim_cpu *cpu, int32_t offset)
348 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
349 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
351 aarch64_set_reg_u64 (cpu, rd, NO_SP, (uint32_t) aarch64_get_mem_s16
352 (cpu, aarch64_get_reg_u64 (cpu, rn, SP_OK)
356 /* 64 bit load sign-extended short unscaled signed 9 bit */
358 ldursh64 (sim_cpu *cpu, int32_t offset)
360 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
361 unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
363 aarch64_set_reg_s64 (cpu, rt, NO_SP, aarch64_get_mem_s16
364 (cpu, aarch64_get_reg_u64 (cpu, rn, SP_OK)
368 /* 64 bit load sign-extended word unscaled signed 9 bit */
370 ldursw (sim_cpu *cpu, int32_t offset)
372 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
373 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
375 aarch64_set_reg_u64 (cpu, rd, NO_SP, (uint32_t) aarch64_get_mem_s32
376 (cpu, aarch64_get_reg_u64 (cpu, rn, SP_OK)
380 /* N.B. with stores the value in source is written to the address
381 identified by source2 modified by offset. */
383 /* 32 bit store 32 bit unscaled signed 9 bit. */
385 stur32 (sim_cpu *cpu, int32_t offset)
387 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
388 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
390 aarch64_set_mem_u32 (cpu,
391 aarch64_get_reg_u64 (cpu, rn, SP_OK) + offset,
392 aarch64_get_reg_u32 (cpu, rd, NO_SP));
395 /* 64 bit store 64 bit unscaled signed 9 bit */
397 stur64 (sim_cpu *cpu, int32_t offset)
399 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
400 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
402 aarch64_set_mem_u64 (cpu,
403 aarch64_get_reg_u64 (cpu, rn, SP_OK) + offset,
404 aarch64_get_reg_u64 (cpu, rd, NO_SP));
407 /* 32 bit store byte unscaled signed 9 bit */
409 sturb (sim_cpu *cpu, int32_t offset)
411 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
412 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
414 aarch64_set_mem_u8 (cpu,
415 aarch64_get_reg_u64 (cpu, rn, SP_OK) + offset,
416 aarch64_get_reg_u8 (cpu, rd, NO_SP));
419 /* 32 bit store short unscaled signed 9 bit */
421 sturh (sim_cpu *cpu, int32_t offset)
423 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
424 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
426 aarch64_set_mem_u16 (cpu,
427 aarch64_get_reg_u64 (cpu, rn, SP_OK) + offset,
428 aarch64_get_reg_u16 (cpu, rd, NO_SP));
431 /* Load single register pc-relative label
432 Offset is a signed 19 bit immediate count in words
435 /* 32 bit pc-relative load */
437 ldr32_pcrel (sim_cpu *cpu, int32_t offset)
439 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
441 aarch64_set_reg_u64 (cpu, rd, NO_SP,
443 (cpu, aarch64_get_PC (cpu) + offset * 4));
446 /* 64 bit pc-relative load */
448 ldr_pcrel (sim_cpu *cpu, int32_t offset)
450 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
452 aarch64_set_reg_u64 (cpu, rd, NO_SP,
454 (cpu, aarch64_get_PC (cpu) + offset * 4));
457 /* sign extended 32 bit pc-relative load */
459 ldrsw_pcrel (sim_cpu *cpu, int32_t offset)
461 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
463 aarch64_set_reg_u64 (cpu, rd, NO_SP,
465 (cpu, aarch64_get_PC (cpu) + offset * 4));
468 /* float pc-relative load */
470 fldrs_pcrel (sim_cpu *cpu, int32_t offset)
472 unsigned int rd = uimm (aarch64_get_instr (cpu), 4, 0);
474 aarch64_set_FP_float (cpu, rd,
475 aarch64_get_mem_float
476 (cpu, aarch64_get_PC (cpu) + offset * 4));
479 /* double pc-relative load */
481 fldrd_pcrel (sim_cpu *cpu, int32_t offset)
483 unsigned int st = uimm (aarch64_get_instr (cpu), 4, 0);
485 aarch64_set_FP_double (cpu, st,
486 aarch64_get_mem_double
487 (cpu, aarch64_get_PC (cpu) + offset * 4));
490 /* long double pc-relative load. */
492 fldrq_pcrel (sim_cpu *cpu, int32_t offset)
494 unsigned int st = uimm (aarch64_get_instr (cpu), 4, 0);
495 uint64_t addr = aarch64_get_PC (cpu) + offset * 4;
498 aarch64_get_mem_long_double (cpu, addr, & a);
499 aarch64_set_FP_long_double (cpu, st, a);
502 /* This can be used to scale an offset by applying
503 the requisite shift. the second argument is either
506 #define SCALE(_offset, _elementSize) \
507 ((_offset) << ScaleShift ## _elementSize)
509 /* This can be used to optionally scale a register derived offset
510 by applying the requisite shift as indicated by the Scaling
511 argument. the second argument is either Byte, Short, Word
512 or Long. The third argument is either Scaled or Unscaled.
513 N.B. when _Scaling is Scaled the shift gets ANDed with
514 all 1s while when it is Unscaled it gets ANDed with 0. */
516 #define OPT_SCALE(_offset, _elementType, _Scaling) \
517 ((_offset) << (_Scaling ? ScaleShift ## _elementType : 0))
519 /* This can be used to zero or sign extend a 32 bit register derived
520 value to a 64 bit value. the first argument must be the value as
521 a uint32_t and the second must be either UXTW or SXTW. The result
522 is returned as an int64_t. */
524 static inline int64_t
525 extend (uint32_t value, Extension extension)
533 /* A branchless variant of this ought to be possible. */
534 if (extension == UXTW || extension == NoExtension)
541 /* Scalar Floating Point
543 FP load/store single register (4 addressing modes)
545 N.B. the base register (source) can be the stack pointer.
546 The secondary source register (source2) can only be an Xn register. */
548 /* Load 32 bit unscaled signed 9 bit with pre- or post-writeback. */
550 fldrs_wb (sim_cpu *cpu, int32_t offset, WriteBack wb)
552 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
553 unsigned st = uimm (aarch64_get_instr (cpu), 4, 0);
554 uint64_t address = aarch64_get_reg_u64 (cpu, rn, SP_OK);
559 aarch64_set_FP_float (cpu, st, aarch64_get_mem_float (cpu, address));
563 if (wb != NoWriteBack)
564 aarch64_set_reg_u64 (cpu, rn, SP_OK, address);
567 /* Load 32 bit scaled unsigned 12 bit. */
569 fldrs_abs (sim_cpu *cpu, uint32_t offset)
571 unsigned st = uimm (aarch64_get_instr (cpu), 4, 0);
572 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
574 aarch64_set_FP_float (cpu, st,
575 aarch64_get_mem_float
576 (cpu, aarch64_get_reg_u64 (cpu, rn, SP_OK)
577 + SCALE (offset, 32)));
580 /* Load 32 bit scaled or unscaled zero- or sign-extended
581 32-bit register offset. */
583 fldrs_scale_ext (sim_cpu *cpu, Scaling scaling, Extension extension)
585 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
586 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
587 unsigned st = uimm (aarch64_get_instr (cpu), 4, 0);
588 uint64_t address = aarch64_get_reg_u64 (cpu, rn, SP_OK);
589 int64_t extended = extend (aarch64_get_reg_u32 (cpu, rm, NO_SP), extension);
590 uint64_t displacement = OPT_SCALE (extended, 32, scaling);
592 aarch64_set_FP_float (cpu, st,
593 aarch64_get_mem_float
594 (cpu, address + displacement));
597 /* Load 64 bit unscaled signed 9 bit with pre- or post-writeback. */
599 fldrd_wb (sim_cpu *cpu, int32_t offset, WriteBack wb)
601 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
602 unsigned st = uimm (aarch64_get_instr (cpu), 4, 0);
603 uint64_t address = aarch64_get_reg_u64 (cpu, rn, SP_OK);
608 aarch64_set_FP_double (cpu, st, aarch64_get_mem_double (cpu, address));
613 if (wb != NoWriteBack)
614 aarch64_set_reg_u64 (cpu, rn, SP_OK, address);
617 /* Load 64 bit scaled unsigned 12 bit. */
619 fldrd_abs (sim_cpu *cpu, uint32_t offset)
621 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
622 unsigned st = uimm (aarch64_get_instr (cpu), 4, 0);
623 uint64_t address = aarch64_get_reg_u64 (cpu, rn, SP_OK) + SCALE (offset, 64);
625 aarch64_set_FP_double (cpu, st, aarch64_get_mem_double (cpu, address));
628 /* Load 64 bit scaled or unscaled zero- or sign-extended 32-bit register offset. */
630 fldrd_scale_ext (sim_cpu *cpu, Scaling scaling, Extension extension)
632 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
633 int64_t extended = extend (aarch64_get_reg_u32 (cpu, rm, NO_SP), extension);
634 uint64_t displacement = OPT_SCALE (extended, 64, scaling);
636 fldrd_wb (cpu, displacement, NoWriteBack);
639 /* Load 128 bit unscaled signed 9 bit with pre- or post-writeback. */
641 fldrq_wb (sim_cpu *cpu, int32_t offset, WriteBack wb)
644 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
645 unsigned st = uimm (aarch64_get_instr (cpu), 4, 0);
646 uint64_t address = aarch64_get_reg_u64 (cpu, rn, SP_OK);
651 aarch64_get_mem_long_double (cpu, address, & a);
652 aarch64_set_FP_long_double (cpu, st, a);
657 if (wb != NoWriteBack)
658 aarch64_set_reg_u64 (cpu, rn, SP_OK, address);
661 /* Load 128 bit scaled unsigned 12 bit. */
663 fldrq_abs (sim_cpu *cpu, uint32_t offset)
666 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
667 unsigned st = uimm (aarch64_get_instr (cpu), 4, 0);
668 uint64_t address = aarch64_get_reg_u64 (cpu, rn, SP_OK) + SCALE (offset, 128);
670 aarch64_get_mem_long_double (cpu, address, & a);
671 aarch64_set_FP_long_double (cpu, st, a);
674 /* Load 128 bit scaled or unscaled zero- or sign-extended 32-bit register offset */
676 fldrq_scale_ext (sim_cpu *cpu, Scaling scaling, Extension extension)
678 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
679 int64_t extended = extend (aarch64_get_reg_u32 (cpu, rm, NO_SP), extension);
680 uint64_t displacement = OPT_SCALE (extended, 128, scaling);
682 fldrq_wb (cpu, displacement, NoWriteBack);
687 load-store single register
688 There are four addressing modes available here which all employ a
689 64 bit source (base) register.
691 N.B. the base register (source) can be the stack pointer.
692 The secondary source register (source2)can only be an Xn register.
694 Scaled, 12-bit, unsigned immediate offset, without pre- and
696 Unscaled, 9-bit, signed immediate offset with pre- or post-index
698 scaled or unscaled 64-bit register offset.
699 scaled or unscaled 32-bit extended register offset.
701 All offsets are assumed to be raw from the decode i.e. the
702 simulator is expected to adjust scaled offsets based on the
703 accessed data size with register or extended register offset
704 versions the same applies except that in the latter case the
705 operation may also require a sign extend.
707 A separate method is provided for each possible addressing mode. */
709 /* 32 bit load 32 bit scaled unsigned 12 bit */
711 ldr32_abs (sim_cpu *cpu, uint32_t offset)
713 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
714 unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
716 /* The target register may not be SP but the source may be. */
717 aarch64_set_reg_u64 (cpu, rt, NO_SP, aarch64_get_mem_u32
718 (cpu, aarch64_get_reg_u64 (cpu, rn, SP_OK)
719 + SCALE (offset, 32)));
722 /* 32 bit load 32 bit unscaled signed 9 bit with pre- or post-writeback. */
724 ldr32_wb (sim_cpu *cpu, int32_t offset, WriteBack wb)
726 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
727 unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
730 if (rn == rt && wb != NoWriteBack)
733 address = aarch64_get_reg_u64 (cpu, rn, SP_OK);
738 aarch64_set_reg_u64 (cpu, rt, NO_SP, aarch64_get_mem_u32 (cpu, address));
743 if (wb != NoWriteBack)
744 aarch64_set_reg_u64 (cpu, rn, SP_OK, address);
747 /* 32 bit load 32 bit scaled or unscaled
748 zero- or sign-extended 32-bit register offset */
750 ldr32_scale_ext (sim_cpu *cpu, Scaling scaling, Extension extension)
752 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
753 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
754 unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
755 /* rn may reference SP, rm and rt must reference ZR */
757 uint64_t address = aarch64_get_reg_u64 (cpu, rn, SP_OK);
758 int64_t extended = extend (aarch64_get_reg_u32 (cpu, rm, NO_SP), extension);
759 uint64_t displacement = OPT_SCALE (extended, 32, scaling);
761 aarch64_set_reg_u64 (cpu, rt, NO_SP,
762 aarch64_get_mem_u32 (cpu, address + displacement));
765 /* 64 bit load 64 bit scaled unsigned 12 bit */
767 ldr_abs (sim_cpu *cpu, uint32_t offset)
769 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
770 unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
772 /* The target register may not be SP but the source may be. */
773 aarch64_set_reg_u64 (cpu, rt, NO_SP, aarch64_get_mem_u64
774 (cpu, aarch64_get_reg_u64 (cpu, rn, SP_OK)
775 + SCALE (offset, 64)));
778 /* 64 bit load 64 bit unscaled signed 9 bit with pre- or post-writeback. */
780 ldr_wb (sim_cpu *cpu, int32_t offset, WriteBack wb)
782 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
783 unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
786 if (rn == rt && wb != NoWriteBack)
789 address = aarch64_get_reg_u64 (cpu, rn, SP_OK);
794 aarch64_set_reg_u64 (cpu, rt, NO_SP, aarch64_get_mem_u64 (cpu, address));
799 if (wb != NoWriteBack)
800 aarch64_set_reg_u64 (cpu, rn, SP_OK, address);
803 /* 64 bit load 64 bit scaled or unscaled zero-
804 or sign-extended 32-bit register offset. */
806 ldr_scale_ext (sim_cpu *cpu, Scaling scaling, Extension extension)
808 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
809 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
810 unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
811 /* rn may reference SP, rm and rt must reference ZR */
813 uint64_t address = aarch64_get_reg_u64 (cpu, rn, SP_OK);
814 int64_t extended = extend (aarch64_get_reg_u32 (cpu, rm, NO_SP), extension);
815 uint64_t displacement = OPT_SCALE (extended, 64, scaling);
817 aarch64_set_reg_u64 (cpu, rt, NO_SP,
818 aarch64_get_mem_u64 (cpu, address + displacement));
821 /* 32 bit load zero-extended byte scaled unsigned 12 bit. */
823 ldrb32_abs (sim_cpu *cpu, uint32_t offset)
825 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
826 unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
828 /* The target register may not be SP but the source may be
829 there is no scaling required for a byte load. */
830 aarch64_set_reg_u64 (cpu, rt, NO_SP,
832 (cpu, aarch64_get_reg_u64 (cpu, rn, SP_OK) + offset));
835 /* 32 bit load zero-extended byte unscaled signed 9 bit with pre- or post-writeback. */
837 ldrb32_wb (sim_cpu *cpu, int32_t offset, WriteBack wb)
839 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
840 unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
843 if (rn == rt && wb != NoWriteBack)
846 address = aarch64_get_reg_u64 (cpu, rn, SP_OK);
851 aarch64_set_reg_u64 (cpu, rt, NO_SP, aarch64_get_mem_u8 (cpu, address));
856 if (wb != NoWriteBack)
857 aarch64_set_reg_u64 (cpu, rn, SP_OK, address);
860 /* 32 bit load zero-extended byte scaled or unscaled zero-
861 or sign-extended 32-bit register offset. */
863 ldrb32_scale_ext (sim_cpu *cpu, Scaling scaling, Extension extension)
865 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
866 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
867 unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
868 /* rn may reference SP, rm and rt must reference ZR */
870 uint64_t address = aarch64_get_reg_u64 (cpu, rn, SP_OK);
871 int64_t displacement = extend (aarch64_get_reg_u32 (cpu, rm, NO_SP),
874 /* There is no scaling required for a byte load. */
875 aarch64_set_reg_u64 (cpu, rt, NO_SP,
876 aarch64_get_mem_u8 (cpu, address + displacement));
879 /* 64 bit load sign-extended byte unscaled signed 9 bit
880 with pre- or post-writeback. */
882 ldrsb_wb (sim_cpu *cpu, int32_t offset, WriteBack wb)
884 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
885 unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
888 if (rn == rt && wb != NoWriteBack)
891 address = aarch64_get_reg_u64 (cpu, rn, SP_OK);
896 aarch64_set_reg_u64 (cpu, rt, NO_SP, aarch64_get_mem_s8 (cpu, address));
901 if (wb != NoWriteBack)
902 aarch64_set_reg_u64 (cpu, rn, SP_OK, address);
905 /* 64 bit load sign-extended byte scaled unsigned 12 bit. */
907 ldrsb_abs (sim_cpu *cpu, uint32_t offset)
909 ldrsb_wb (cpu, offset, NoWriteBack);
912 /* 64 bit load sign-extended byte scaled or unscaled zero-
913 or sign-extended 32-bit register offset. */
915 ldrsb_scale_ext (sim_cpu *cpu, Scaling scaling, Extension extension)
917 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
918 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
919 unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
920 /* rn may reference SP, rm and rt must reference ZR */
922 uint64_t address = aarch64_get_reg_u64 (cpu, rn, SP_OK);
923 int64_t displacement = extend (aarch64_get_reg_u32 (cpu, rm, NO_SP),
925 /* There is no scaling required for a byte load. */
926 aarch64_set_reg_u64 (cpu, rt, NO_SP,
927 aarch64_get_mem_s8 (cpu, address + displacement));
930 /* 32 bit load zero-extended short scaled unsigned 12 bit. */
932 ldrh32_abs (sim_cpu *cpu, uint32_t offset)
934 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
935 unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
937 /* The target register may not be SP but the source may be. */
938 aarch64_set_reg_u64 (cpu, rt, NO_SP, aarch64_get_mem_u16
939 (cpu, aarch64_get_reg_u64 (cpu, rn, SP_OK)
940 + SCALE (offset, 16)));
943 /* 32 bit load zero-extended short unscaled signed 9 bit
944 with pre- or post-writeback. */
946 ldrh32_wb (sim_cpu *cpu, int32_t offset, WriteBack wb)
948 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
949 unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
952 if (rn == rt && wb != NoWriteBack)
955 address = aarch64_get_reg_u64 (cpu, rn, SP_OK);
960 aarch64_set_reg_u64 (cpu, rt, NO_SP, aarch64_get_mem_u16 (cpu, address));
965 if (wb != NoWriteBack)
966 aarch64_set_reg_u64 (cpu, rn, SP_OK, address);
969 /* 32 bit load zero-extended short scaled or unscaled zero-
970 or sign-extended 32-bit register offset. */
972 ldrh32_scale_ext (sim_cpu *cpu, Scaling scaling, Extension extension)
974 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
975 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
976 unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
977 /* rn may reference SP, rm and rt must reference ZR */
979 uint64_t address = aarch64_get_reg_u64 (cpu, rn, SP_OK);
980 int64_t extended = extend (aarch64_get_reg_u32 (cpu, rm, NO_SP), extension);
981 uint64_t displacement = OPT_SCALE (extended, 16, scaling);
983 aarch64_set_reg_u64 (cpu, rt, NO_SP,
984 aarch64_get_mem_u16 (cpu, address + displacement));
987 /* 32 bit load sign-extended short scaled unsigned 12 bit. */
989 ldrsh32_abs (sim_cpu *cpu, uint32_t offset)
991 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
992 unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
994 /* The target register may not be SP but the source may be. */
995 aarch64_set_reg_u64 (cpu, rt, NO_SP, (uint32_t) aarch64_get_mem_s16
997 aarch64_get_reg_u64 (cpu, rn, SP_OK)
998 + SCALE (offset, 16)));
1001 /* 32 bit load sign-extended short unscaled signed 9 bit
1002 with pre- or post-writeback. */
1004 ldrsh32_wb (sim_cpu *cpu, int32_t offset, WriteBack wb)
1006 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
1007 unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
1010 if (rn == rt && wb != NoWriteBack)
1013 address = aarch64_get_reg_u64 (cpu, rn, SP_OK);
1018 aarch64_set_reg_u64 (cpu, rt, NO_SP,
1019 (uint32_t) aarch64_get_mem_s16 (cpu, address));
1024 if (wb != NoWriteBack)
1025 aarch64_set_reg_u64 (cpu, rn, SP_OK, address);
1028 /* 32 bit load sign-extended short scaled or unscaled zero-
1029 or sign-extended 32-bit register offset. */
1031 ldrsh32_scale_ext (sim_cpu *cpu, Scaling scaling, Extension extension)
1033 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
1034 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
1035 unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
1036 /* rn may reference SP, rm and rt must reference ZR */
1038 uint64_t address = aarch64_get_reg_u64 (cpu, rn, SP_OK);
1039 int64_t extended = extend (aarch64_get_reg_u32 (cpu, rm, NO_SP), extension);
1040 uint64_t displacement = OPT_SCALE (extended, 16, scaling);
1042 aarch64_set_reg_u64 (cpu, rt, NO_SP,
1043 (uint32_t) aarch64_get_mem_s16
1044 (cpu, address + displacement));
1047 /* 64 bit load sign-extended short scaled unsigned 12 bit. */
1049 ldrsh_abs (sim_cpu *cpu, uint32_t offset)
1051 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
1052 unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
1054 /* The target register may not be SP but the source may be. */
1055 aarch64_set_reg_u64 (cpu, rt, NO_SP, aarch64_get_mem_s16
1056 (cpu, aarch64_get_reg_u64 (cpu, rn, SP_OK)
1057 + SCALE (offset, 16)));
1060 /* 64 bit load sign-extended short unscaled signed 9 bit
1061 with pre- or post-writeback. */
1063 ldrsh64_wb (sim_cpu *cpu, int32_t offset, WriteBack wb)
1065 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
1066 unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
1069 if (rn == rt && wb != NoWriteBack)
1072 address = aarch64_get_reg_u64 (cpu, rn, SP_OK);
1077 aarch64_set_reg_u64 (cpu, rt, NO_SP, aarch64_get_mem_s16 (cpu, address));
1082 if (wb != NoWriteBack)
1083 aarch64_set_reg_u64 (cpu, rn, SP_OK, address);
1086 /* 64 bit load sign-extended short scaled or unscaled zero-
1087 or sign-extended 32-bit register offset. */
1089 ldrsh_scale_ext (sim_cpu *cpu, Scaling scaling, Extension extension)
1091 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
1092 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
1093 unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
1094 /* rn may reference SP, rm and rt must reference ZR */
1096 uint64_t address = aarch64_get_reg_u64 (cpu, rn, SP_OK);
1097 int64_t extended = extend (aarch64_get_reg_u32 (cpu, rm, NO_SP), extension);
1098 uint64_t displacement = OPT_SCALE (extended, 16, scaling);
1100 aarch64_set_reg_u64 (cpu, rt, NO_SP,
1101 aarch64_get_mem_s16 (cpu, address + displacement));
1104 /* 64 bit load sign-extended 32 bit scaled unsigned 12 bit. */
1106 ldrsw_abs (sim_cpu *cpu, uint32_t offset)
1108 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
1109 unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
1111 /* The target register may not be SP but the source may be. */
1112 return aarch64_set_reg_s64 (cpu, rt, NO_SP, aarch64_get_mem_s32
1113 (cpu, aarch64_get_reg_u64 (cpu, rn, SP_OK)
1114 + SCALE (offset, 32)));
1117 /* 64 bit load sign-extended 32 bit unscaled signed 9 bit
1118 with pre- or post-writeback. */
1120 ldrsw_wb (sim_cpu *cpu, int32_t offset, WriteBack wb)
1122 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
1123 unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
1126 if (rn == rt && wb != NoWriteBack)
1129 address = aarch64_get_reg_u64 (cpu, rn, SP_OK);
1134 aarch64_set_reg_s64 (cpu, rt, NO_SP, aarch64_get_mem_s32 (cpu, address));
1139 if (wb != NoWriteBack)
1140 aarch64_set_reg_u64 (cpu, rn, SP_OK, address);
1143 /* 64 bit load sign-extended 32 bit scaled or unscaled zero-
1144 or sign-extended 32-bit register offset. */
1146 ldrsw_scale_ext (sim_cpu *cpu, Scaling scaling, Extension extension)
1148 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
1149 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
1150 unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
1151 /* rn may reference SP, rm and rt must reference ZR */
1153 uint64_t address = aarch64_get_reg_u64 (cpu, rn, SP_OK);
1154 int64_t extended = extend (aarch64_get_reg_u32 (cpu, rm, NO_SP), extension);
1155 uint64_t displacement = OPT_SCALE (extended, 32, scaling);
1157 aarch64_set_reg_s64 (cpu, rt, NO_SP,
1158 aarch64_get_mem_s32 (cpu, address + displacement));
1161 /* N.B. with stores the value in source is written to the
1162 address identified by source2 modified by source3/offset. */
1164 /* 32 bit store scaled unsigned 12 bit. */
1166 str32_abs (sim_cpu *cpu, uint32_t offset)
1168 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
1169 unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
1171 /* The target register may not be SP but the source may be. */
1172 aarch64_set_mem_u32 (cpu, (aarch64_get_reg_u64 (cpu, rn, SP_OK)
1173 + SCALE (offset, 32)),
1174 aarch64_get_reg_u32 (cpu, rt, NO_SP));
1177 /* 32 bit store unscaled signed 9 bit with pre- or post-writeback. */
1179 str32_wb (sim_cpu *cpu, int32_t offset, WriteBack wb)
1181 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
1182 unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
1185 if (rn == rt && wb != NoWriteBack)
1188 address = aarch64_get_reg_u64 (cpu, rn, SP_OK);
1192 aarch64_set_mem_u32 (cpu, address, aarch64_get_reg_u32 (cpu, rt, NO_SP));
1197 if (wb != NoWriteBack)
1198 aarch64_set_reg_u64 (cpu, rn, SP_OK, address);
1201 /* 32 bit store scaled or unscaled zero- or
1202 sign-extended 32-bit register offset. */
1204 str32_scale_ext (sim_cpu *cpu, Scaling scaling, Extension extension)
1206 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
1207 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
1208 unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
1210 uint64_t address = aarch64_get_reg_u64 (cpu, rn, SP_OK);
1211 int64_t extended = extend (aarch64_get_reg_u32 (cpu, rm, NO_SP), extension);
1212 uint64_t displacement = OPT_SCALE (extended, 32, scaling);
1214 aarch64_set_mem_u32 (cpu, address + displacement,
1215 aarch64_get_reg_u64 (cpu, rt, NO_SP));
1218 /* 64 bit store scaled unsigned 12 bit. */
1220 str_abs (sim_cpu *cpu, uint32_t offset)
1222 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
1223 unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
1225 aarch64_set_mem_u64 (cpu,
1226 aarch64_get_reg_u64 (cpu, rn, SP_OK)
1227 + SCALE (offset, 64),
1228 aarch64_get_reg_u64 (cpu, rt, NO_SP));
1231 /* 64 bit store unscaled signed 9 bit with pre- or post-writeback. */
1233 str_wb (sim_cpu *cpu, int32_t offset, WriteBack wb)
1235 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
1236 unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
1239 if (rn == rt && wb != NoWriteBack)
1242 address = aarch64_get_reg_u64 (cpu, rn, SP_OK);
1247 aarch64_set_mem_u64 (cpu, address, aarch64_get_reg_u64 (cpu, rt, NO_SP));
1252 if (wb != NoWriteBack)
1253 aarch64_set_reg_u64 (cpu, rn, SP_OK, address);
1256 /* 64 bit store scaled or unscaled zero-
1257 or sign-extended 32-bit register offset. */
1259 str_scale_ext (sim_cpu *cpu, Scaling scaling, Extension extension)
1261 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
1262 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
1263 unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
1264 /* rn may reference SP, rm and rt must reference ZR */
1266 uint64_t address = aarch64_get_reg_u64 (cpu, rn, SP_OK);
1267 int64_t extended = extend (aarch64_get_reg_u32 (cpu, rm, NO_SP),
1269 uint64_t displacement = OPT_SCALE (extended, 64, scaling);
1271 aarch64_set_mem_u64 (cpu, address + displacement,
1272 aarch64_get_reg_u64 (cpu, rt, NO_SP));
1275 /* 32 bit store byte scaled unsigned 12 bit. */
1277 strb_abs (sim_cpu *cpu, uint32_t offset)
1279 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
1280 unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
1282 /* The target register may not be SP but the source may be.
1283 There is no scaling required for a byte load. */
1284 aarch64_set_mem_u8 (cpu,
1285 aarch64_get_reg_u64 (cpu, rn, SP_OK) + offset,
1286 aarch64_get_reg_u8 (cpu, rt, NO_SP));
1289 /* 32 bit store byte unscaled signed 9 bit with pre- or post-writeback. */
1291 strb_wb (sim_cpu *cpu, int32_t offset, WriteBack wb)
1293 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
1294 unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
1297 if (rn == rt && wb != NoWriteBack)
1300 address = aarch64_get_reg_u64 (cpu, rn, SP_OK);
1305 aarch64_set_mem_u8 (cpu, address, aarch64_get_reg_u8 (cpu, rt, NO_SP));
1310 if (wb != NoWriteBack)
1311 aarch64_set_reg_u64 (cpu, rn, SP_OK, address);
1314 /* 32 bit store byte scaled or unscaled zero-
1315 or sign-extended 32-bit register offset. */
1317 strb_scale_ext (sim_cpu *cpu, Scaling scaling, Extension extension)
1319 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
1320 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
1321 unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
1322 /* rn may reference SP, rm and rt must reference ZR */
1324 uint64_t address = aarch64_get_reg_u64 (cpu, rn, SP_OK);
1325 int64_t displacement = extend (aarch64_get_reg_u32 (cpu, rm, NO_SP),
1328 /* There is no scaling required for a byte load. */
1329 aarch64_set_mem_u8 (cpu, address + displacement,
1330 aarch64_get_reg_u8 (cpu, rt, NO_SP));
1333 /* 32 bit store short scaled unsigned 12 bit. */
1335 strh_abs (sim_cpu *cpu, uint32_t offset)
1337 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
1338 unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
1340 /* The target register may not be SP but the source may be. */
1341 aarch64_set_mem_u16 (cpu, aarch64_get_reg_u64 (cpu, rn, SP_OK)
1342 + SCALE (offset, 16),
1343 aarch64_get_reg_u16 (cpu, rt, NO_SP));
1346 /* 32 bit store short unscaled signed 9 bit with pre- or post-writeback. */
1348 strh_wb (sim_cpu *cpu, int32_t offset, WriteBack wb)
1350 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
1351 unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
1354 if (rn == rt && wb != NoWriteBack)
1357 address = aarch64_get_reg_u64 (cpu, rn, SP_OK);
1362 aarch64_set_mem_u16 (cpu, address, aarch64_get_reg_u16 (cpu, rt, NO_SP));
1367 if (wb != NoWriteBack)
1368 aarch64_set_reg_u64 (cpu, rn, SP_OK, address);
1371 /* 32 bit store short scaled or unscaled zero-
1372 or sign-extended 32-bit register offset. */
1374 strh_scale_ext (sim_cpu *cpu, Scaling scaling, Extension extension)
1376 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
1377 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
1378 unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
1379 /* rn may reference SP, rm and rt must reference ZR */
1381 uint64_t address = aarch64_get_reg_u64 (cpu, rn, SP_OK);
1382 int64_t extended = extend (aarch64_get_reg_u32 (cpu, rm, NO_SP), extension);
1383 uint64_t displacement = OPT_SCALE (extended, 16, scaling);
1385 aarch64_set_mem_u16 (cpu, address + displacement,
1386 aarch64_get_reg_u16 (cpu, rt, NO_SP));
1389 /* Prefetch unsigned 12 bit. */
1391 prfm_abs (sim_cpu *cpu, uint32_t offset)
1393 /* instr[4,0] = prfop : 00000 ==> PLDL1KEEP, 00001 ==> PLDL1STRM,
1394 00010 ==> PLDL2KEEP, 00001 ==> PLDL2STRM,
1395 00100 ==> PLDL3KEEP, 00101 ==> PLDL3STRM,
1396 10000 ==> PSTL1KEEP, 10001 ==> PSTL1STRM,
1397 10010 ==> PSTL2KEEP, 10001 ==> PSTL2STRM,
1398 10100 ==> PSTL3KEEP, 10101 ==> PSTL3STRM,
1400 PrfOp prfop = prfop (aarch64_get_instr (cpu), 4, 0);
1401 uint64_t address = aarch64_get_reg_u64 (cpu, rn, SP_OK)
1402 + SCALE (offset, 64). */
1404 /* TODO : implement prefetch of address. */
1407 /* Prefetch scaled or unscaled zero- or sign-extended 32-bit register offset. */
1409 prfm_scale_ext (sim_cpu *cpu, Scaling scaling, Extension extension)
1411 /* instr[4,0] = prfop : 00000 ==> PLDL1KEEP, 00001 ==> PLDL1STRM,
1412 00010 ==> PLDL2KEEP, 00001 ==> PLDL2STRM,
1413 00100 ==> PLDL3KEEP, 00101 ==> PLDL3STRM,
1414 10000 ==> PSTL1KEEP, 10001 ==> PSTL1STRM,
1415 10010 ==> PSTL2KEEP, 10001 ==> PSTL2STRM,
1416 10100 ==> PSTL3KEEP, 10101 ==> PSTL3STRM,
1418 rn may reference SP, rm may only reference ZR
1419 PrfOp prfop = prfop (aarch64_get_instr (cpu), 4, 0);
1420 uint64_t base = aarch64_get_reg_u64 (cpu, rn, SP_OK);
1421 int64_t extended = extend (aarch64_get_reg_u32 (cpu, rm, NO_SP),
1423 uint64_t displacement = OPT_SCALE (extended, 64, scaling);
1424 uint64_t address = base + displacement. */
1426 /* TODO : implement prefetch of address */
1429 /* 64 bit pc-relative prefetch. */
1431 prfm_pcrel (sim_cpu *cpu, int32_t offset)
1433 /* instr[4,0] = prfop : 00000 ==> PLDL1KEEP, 00001 ==> PLDL1STRM,
1434 00010 ==> PLDL2KEEP, 00001 ==> PLDL2STRM,
1435 00100 ==> PLDL3KEEP, 00101 ==> PLDL3STRM,
1436 10000 ==> PSTL1KEEP, 10001 ==> PSTL1STRM,
1437 10010 ==> PSTL2KEEP, 10001 ==> PSTL2STRM,
1438 10100 ==> PSTL3KEEP, 10101 ==> PSTL3STRM,
1440 PrfOp prfop = prfop (aarch64_get_instr (cpu), 4, 0);
1441 uint64_t address = aarch64_get_PC (cpu) + offset. */
1443 /* TODO : implement this */
1446 /* Load-store exclusive. */
1451 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
1452 unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
1453 uint64_t address = aarch64_get_reg_u64 (cpu, rn, SP_OK);
1454 int size = uimm (aarch64_get_instr (cpu), 31, 30);
1455 /* int ordered = uimm (aarch64_get_instr (cpu), 15, 15); */
1456 /* int exclusive = ! uimm (aarch64_get_instr (cpu), 23, 23); */
1461 aarch64_set_reg_u64 (cpu, rt, NO_SP, aarch64_get_mem_u8 (cpu, address));
1464 aarch64_set_reg_u64 (cpu, rt, NO_SP, aarch64_get_mem_u16 (cpu, address));
1467 aarch64_set_reg_u64 (cpu, rt, NO_SP, aarch64_get_mem_u32 (cpu, address));
1470 aarch64_set_reg_u64 (cpu, rt, NO_SP, aarch64_get_mem_u64 (cpu, address));
1480 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
1481 unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
1482 unsigned rs = uimm (aarch64_get_instr (cpu), 20, 16);
1483 uint64_t address = aarch64_get_reg_u64 (cpu, rn, SP_OK);
1484 int size = uimm (aarch64_get_instr (cpu), 31, 30);
1485 uint64_t data = aarch64_get_reg_u64 (cpu, rt, NO_SP);
1489 case 0: aarch64_set_mem_u8 (cpu, address, data); break;
1490 case 1: aarch64_set_mem_u16 (cpu, address, data); break;
1491 case 2: aarch64_set_mem_u32 (cpu, address, data); break;
1492 case 3: aarch64_set_mem_u64 (cpu, address, data); break;
1493 default: HALT_UNALLOC;
1496 aarch64_set_reg_u64 (cpu, rs, NO_SP, 0); /* Always exclusive... */
1500 dexLoadLiteral (sim_cpu *cpu)
1502 /* instr[29,27] == 011
1504 instr[31,30:26] = opc: 000 ==> LDRW, 001 ==> FLDRS
1505 010 ==> LDRX, 011 ==> FLDRD
1506 100 ==> LDRSW, 101 ==> FLDRQ
1507 110 ==> PRFM, 111 ==> UNALLOC
1508 instr[26] ==> V : 0 ==> GReg, 1 ==> FReg
1509 instr[23, 5] == simm19 */
1511 /* unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0); */
1512 uint32_t dispatch = ( (uimm (aarch64_get_instr (cpu), 31, 30) << 1)
1513 | uimm (aarch64_get_instr (cpu), 26, 26));
1514 int32_t imm = simm32 (aarch64_get_instr (cpu), 23, 5);
1518 case 0: ldr32_pcrel (cpu, imm); break;
1519 case 1: fldrs_pcrel (cpu, imm); break;
1520 case 2: ldr_pcrel (cpu, imm); break;
1521 case 3: fldrd_pcrel (cpu, imm); break;
1522 case 4: ldrsw_pcrel (cpu, imm); break;
1523 case 5: fldrq_pcrel (cpu, imm); break;
1524 case 6: prfm_pcrel (cpu, imm); break;
1531 /* Immediate arithmetic
1532 The aimm argument is a 12 bit unsigned value or a 12 bit unsigned
1533 value left shifted by 12 bits (done at decode).
1535 N.B. the register args (dest, source) can normally be Xn or SP.
1536 the exception occurs for flag setting instructions which may
1537 only use Xn for the output (dest). */
1539 /* 32 bit add immediate. */
1541 add32 (sim_cpu *cpu, uint32_t aimm)
1543 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
1544 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
1546 aarch64_set_reg_u64 (cpu, rd, SP_OK,
1547 aarch64_get_reg_u32 (cpu, rn, SP_OK) + aimm);
1550 /* 64 bit add immediate. */
1552 add64 (sim_cpu *cpu, uint32_t aimm)
1554 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
1555 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
1557 aarch64_set_reg_u64 (cpu, rd, SP_OK,
1558 aarch64_get_reg_u64 (cpu, rn, SP_OK) + aimm);
1562 set_flags_for_add32 (sim_cpu *cpu, int32_t value1, int32_t value2)
1564 int32_t result = value1 + value2;
1565 int64_t sresult = (int64_t) value1 + (int64_t) value2;
1566 uint64_t uresult = (uint64_t)(uint32_t) value1
1567 + (uint64_t)(uint32_t) value2;
1573 if (result & (1 << 31))
1576 if (uresult != result)
1579 if (sresult != result)
1582 aarch64_set_CPSR (cpu, flags);
1586 set_flags_for_add64 (sim_cpu *cpu, uint64_t value1, uint64_t value2)
1588 int64_t sval1 = value1;
1589 int64_t sval2 = value2;
1590 uint64_t result = value1 + value2;
1591 int64_t sresult = sval1 + sval2;
1597 if (result & (1ULL << 63))
1604 /* Negative plus a negative. Overflow happens if
1605 the result is greater than either of the operands. */
1606 if (sresult > sval1 || sresult > sval2)
1609 /* else Negative plus a positive. Overflow cannot happen. */
1611 else /* value1 is +ve. */
1615 /* Overflow can only occur if we computed "0 - MININT". */
1616 if (sval1 == 0 && sval2 == (1LL << 63))
1621 /* Postive plus positive - overflow has happened if the
1622 result is smaller than either of the operands. */
1623 if (result < value1 || result < value2)
1628 aarch64_set_CPSR (cpu, flags);
1631 #define NEG(a) (((a) & signbit) == signbit)
1632 #define POS(a) (((a) & signbit) == 0)
1635 set_flags_for_sub32 (sim_cpu *cpu, uint32_t value1, uint32_t value2)
1637 uint32_t result = value1 - value2;
1639 uint32_t signbit = 1ULL << 31;
1647 if ( (NEG (value1) && POS (value2))
1648 || (NEG (value1) && POS (result))
1649 || (POS (value2) && POS (result)))
1652 if ( (NEG (value1) && POS (value2) && POS (result))
1653 || (POS (value1) && NEG (value2) && NEG (result)))
1656 aarch64_set_CPSR (cpu, flags);
1660 set_flags_for_sub64 (sim_cpu *cpu, uint64_t value1, uint64_t value2)
1662 uint64_t result = value1 - value2;
1664 uint64_t signbit = 1ULL << 63;
1672 if ( (NEG (value1) && POS (value2))
1673 || (NEG (value1) && POS (result))
1674 || (POS (value2) && POS (result)))
1677 if ( (NEG (value1) && POS (value2) && POS (result))
1678 || (POS (value1) && NEG (value2) && NEG (result)))
1681 aarch64_set_CPSR (cpu, flags);
1685 set_flags_for_binop32 (sim_cpu *cpu, uint32_t result)
1694 if (result & (1 << 31))
1699 aarch64_set_CPSR (cpu, flags);
1703 set_flags_for_binop64 (sim_cpu *cpu, uint64_t result)
1712 if (result & (1ULL << 63))
1717 aarch64_set_CPSR (cpu, flags);
1720 /* 32 bit add immediate set flags. */
1722 adds32 (sim_cpu *cpu, uint32_t aimm)
1724 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
1725 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
1726 /* TODO : do we need to worry about signs here? */
1727 int32_t value1 = aarch64_get_reg_s32 (cpu, rn, SP_OK);
1729 aarch64_set_reg_u64 (cpu, rd, NO_SP, value1 + aimm);
1730 set_flags_for_add32 (cpu, value1, aimm);
1733 /* 64 bit add immediate set flags. */
1735 adds64 (sim_cpu *cpu, uint32_t aimm)
1737 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
1738 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
1739 uint64_t value1 = aarch64_get_reg_u64 (cpu, rn, SP_OK);
1740 uint64_t value2 = aimm;
1742 aarch64_set_reg_u64 (cpu, rd, NO_SP, value1 + value2);
1743 set_flags_for_add64 (cpu, value1, value2);
1746 /* 32 bit sub immediate. */
1748 sub32 (sim_cpu *cpu, uint32_t aimm)
1750 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
1751 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
1753 aarch64_set_reg_u64 (cpu, rd, SP_OK,
1754 aarch64_get_reg_u32 (cpu, rn, SP_OK) - aimm);
1757 /* 64 bit sub immediate. */
1759 sub64 (sim_cpu *cpu, uint32_t aimm)
1761 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
1762 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
1764 aarch64_set_reg_u64 (cpu, rd, SP_OK,
1765 aarch64_get_reg_u64 (cpu, rn, SP_OK) - aimm);
1768 /* 32 bit sub immediate set flags. */
1770 subs32 (sim_cpu *cpu, uint32_t aimm)
1772 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
1773 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
1774 uint32_t value1 = aarch64_get_reg_u64 (cpu, rn, SP_OK);
1775 uint32_t value2 = aimm;
1777 aarch64_set_reg_u64 (cpu, rd, NO_SP, value1 - value2);
1778 set_flags_for_sub32 (cpu, value1, value2);
1781 /* 64 bit sub immediate set flags. */
1783 subs64 (sim_cpu *cpu, uint32_t aimm)
1785 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
1786 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
1787 uint64_t value1 = aarch64_get_reg_u64 (cpu, rn, SP_OK);
1788 uint32_t value2 = aimm;
1790 aarch64_set_reg_u64 (cpu, rd, NO_SP, value1 - value2);
1791 set_flags_for_sub64 (cpu, value1, value2);
1794 /* Data Processing Register. */
1796 /* First two helpers to perform the shift operations. */
1798 static inline uint32_t
1799 shifted32 (uint32_t value, Shift shift, uint32_t count)
1805 return (value << count);
1807 return (value >> count);
1810 int32_t svalue = value;
1811 return (svalue >> count);
1815 uint32_t top = value >> count;
1816 uint32_t bottom = value << (32 - count);
1817 return (bottom | top);
1822 static inline uint64_t
1823 shifted64 (uint64_t value, Shift shift, uint32_t count)
1829 return (value << count);
1831 return (value >> count);
1834 int64_t svalue = value;
1835 return (svalue >> count);
1839 uint64_t top = value >> count;
1840 uint64_t bottom = value << (64 - count);
1841 return (bottom | top);
1846 /* Arithmetic shifted register.
1847 These allow an optional LSL, ASR or LSR to the second source
1848 register with a count up to the register bit count.
1850 N.B register args may not be SP. */
1852 /* 32 bit ADD shifted register. */
1854 add32_shift (sim_cpu *cpu, Shift shift, uint32_t count)
1856 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
1857 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
1858 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
1860 aarch64_set_reg_u64 (cpu, rd, NO_SP,
1861 aarch64_get_reg_u32 (cpu, rn, NO_SP)
1862 + shifted32 (aarch64_get_reg_u32 (cpu, rm, NO_SP),
1866 /* 64 bit ADD shifted register. */
1868 add64_shift (sim_cpu *cpu, Shift shift, uint32_t count)
1870 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
1871 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
1872 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
1874 aarch64_set_reg_u64 (cpu, rd, NO_SP,
1875 aarch64_get_reg_u64 (cpu, rn, NO_SP)
1876 + shifted64 (aarch64_get_reg_u64 (cpu, rm, NO_SP),
1880 /* 32 bit ADD shifted register setting flags. */
1882 adds32_shift (sim_cpu *cpu, Shift shift, uint32_t count)
1884 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
1885 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
1886 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
1888 uint32_t value1 = aarch64_get_reg_u32 (cpu, rn, NO_SP);
1889 uint32_t value2 = shifted32 (aarch64_get_reg_u32 (cpu, rm, NO_SP),
1892 aarch64_set_reg_u64 (cpu, rd, NO_SP, value1 + value2);
1893 set_flags_for_add32 (cpu, value1, value2);
1896 /* 64 bit ADD shifted register setting flags. */
1898 adds64_shift (sim_cpu *cpu, Shift shift, uint32_t count)
1900 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
1901 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
1902 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
1904 uint64_t value1 = aarch64_get_reg_u64 (cpu, rn, NO_SP);
1905 uint64_t value2 = shifted64 (aarch64_get_reg_u64 (cpu, rm, NO_SP),
1908 aarch64_set_reg_u64 (cpu, rd, NO_SP, value1 + value2);
1909 set_flags_for_add64 (cpu, value1, value2);
1912 /* 32 bit SUB shifted register. */
1914 sub32_shift (sim_cpu *cpu, Shift shift, uint32_t count)
1916 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
1917 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
1918 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
1920 aarch64_set_reg_u64 (cpu, rd, NO_SP,
1921 aarch64_get_reg_u32 (cpu, rn, NO_SP)
1922 - shifted32 (aarch64_get_reg_u32 (cpu, rm, NO_SP),
1926 /* 64 bit SUB shifted register. */
1928 sub64_shift (sim_cpu *cpu, Shift shift, uint32_t count)
1930 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
1931 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
1932 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
1934 aarch64_set_reg_u64 (cpu, rd, NO_SP,
1935 aarch64_get_reg_u64 (cpu, rn, NO_SP)
1936 - shifted64 (aarch64_get_reg_u64 (cpu, rm, NO_SP),
1940 /* 32 bit SUB shifted register setting flags. */
1942 subs32_shift (sim_cpu *cpu, Shift shift, uint32_t count)
1944 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
1945 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
1946 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
1948 uint32_t value1 = aarch64_get_reg_u32 (cpu, rn, NO_SP);
1949 uint32_t value2 = shifted32 (aarch64_get_reg_u32 (cpu, rm, NO_SP),
1952 aarch64_set_reg_u64 (cpu, rd, NO_SP, value1 - value2);
1953 set_flags_for_sub32 (cpu, value1, value2);
1956 /* 64 bit SUB shifted register setting flags. */
1958 subs64_shift (sim_cpu *cpu, Shift shift, uint32_t count)
1960 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
1961 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
1962 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
1964 uint64_t value1 = aarch64_get_reg_u64 (cpu, rn, NO_SP);
1965 uint64_t value2 = shifted64 (aarch64_get_reg_u64 (cpu, rm, NO_SP),
1968 aarch64_set_reg_u64 (cpu, rd, NO_SP, value1 - value2);
1969 set_flags_for_sub64 (cpu, value1, value2);
1972 /* First a couple more helpers to fetch the
1973 relevant source register element either
1974 sign or zero extended as required by the
1978 extreg32 (sim_cpu *cpu, unsigned int lo, Extension extension)
1982 case UXTB: return aarch64_get_reg_u8 (cpu, lo, NO_SP);
1983 case UXTH: return aarch64_get_reg_u16 (cpu, lo, NO_SP);
1984 case UXTW: /* Fall through. */
1985 case UXTX: return aarch64_get_reg_u32 (cpu, lo, NO_SP);
1986 case SXTB: return aarch64_get_reg_s8 (cpu, lo, NO_SP);
1987 case SXTH: return aarch64_get_reg_s16 (cpu, lo, NO_SP);
1988 case SXTW: /* Fall through. */
1989 case SXTX: /* Fall through. */
1990 default: return aarch64_get_reg_s32 (cpu, lo, NO_SP);
1995 extreg64 (sim_cpu *cpu, unsigned int lo, Extension extension)
1999 case UXTB: return aarch64_get_reg_u8 (cpu, lo, NO_SP);
2000 case UXTH: return aarch64_get_reg_u16 (cpu, lo, NO_SP);
2001 case UXTW: return aarch64_get_reg_u32 (cpu, lo, NO_SP);
2002 case UXTX: return aarch64_get_reg_u64 (cpu, lo, NO_SP);
2003 case SXTB: return aarch64_get_reg_s8 (cpu, lo, NO_SP);
2004 case SXTH: return aarch64_get_reg_s16 (cpu, lo, NO_SP);
2005 case SXTW: return aarch64_get_reg_s32 (cpu, lo, NO_SP);
2007 default: return aarch64_get_reg_s64 (cpu, lo, NO_SP);
2011 /* Arithmetic extending register
2012 These allow an optional sign extension of some portion of the
2013 second source register followed by an optional left shift of
2014 between 1 and 4 bits (i.e. a shift of 0-4 bits???)
2016 N.B output (dest) and first input arg (source) may normally be Xn
2017 or SP. However, for flag setting operations dest can only be
2018 Xn. Second input registers are always Xn. */
2020 /* 32 bit ADD extending register. */
2022 add32_ext (sim_cpu *cpu, Extension extension, uint32_t shift)
2024 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
2025 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
2026 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
2028 aarch64_set_reg_u64 (cpu, rd, SP_OK,
2029 aarch64_get_reg_u32 (cpu, rn, SP_OK)
2030 + (extreg32 (cpu, rm, extension) << shift));
2033 /* 64 bit ADD extending register.
2034 N.B. This subsumes the case with 64 bit source2 and UXTX #n or LSL #0. */
2036 add64_ext (sim_cpu *cpu, Extension extension, uint32_t shift)
2038 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
2039 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
2040 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
2042 aarch64_set_reg_u64 (cpu, rd, SP_OK,
2043 aarch64_get_reg_u64 (cpu, rn, SP_OK)
2044 + (extreg64 (cpu, rm, extension) << shift));
2047 /* 32 bit ADD extending register setting flags. */
2049 adds32_ext (sim_cpu *cpu, Extension extension, uint32_t shift)
2051 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
2052 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
2053 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
2055 uint32_t value1 = aarch64_get_reg_u32 (cpu, rn, SP_OK);
2056 uint32_t value2 = extreg32 (cpu, rm, extension) << shift;
2058 aarch64_set_reg_u64 (cpu, rd, NO_SP, value1 + value2);
2059 set_flags_for_add32 (cpu, value1, value2);
2062 /* 64 bit ADD extending register setting flags */
2063 /* N.B. this subsumes the case with 64 bit source2 and UXTX #n or LSL #0 */
2065 adds64_ext (sim_cpu *cpu, Extension extension, uint32_t shift)
2067 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
2068 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
2069 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
2071 uint64_t value1 = aarch64_get_reg_u64 (cpu, rn, SP_OK);
2072 uint64_t value2 = extreg64 (cpu, rm, extension) << shift;
2074 aarch64_set_reg_u64 (cpu, rd, NO_SP, value1 + value2);
2075 set_flags_for_add64 (cpu, value1, value2);
2078 /* 32 bit SUB extending register. */
2080 sub32_ext (sim_cpu *cpu, Extension extension, uint32_t shift)
2082 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
2083 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
2084 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
2086 aarch64_set_reg_u64 (cpu, rd, SP_OK,
2087 aarch64_get_reg_u32 (cpu, rn, SP_OK)
2088 - (extreg32 (cpu, rm, extension) << shift));
2091 /* 64 bit SUB extending register. */
2092 /* N.B. this subsumes the case with 64 bit source2 and UXTX #n or LSL #0. */
2094 sub64_ext (sim_cpu *cpu, Extension extension, uint32_t shift)
2096 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
2097 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
2098 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
2100 aarch64_set_reg_u64 (cpu, rd, SP_OK,
2101 aarch64_get_reg_u64 (cpu, rn, SP_OK)
2102 - (extreg64 (cpu, rm, extension) << shift));
2105 /* 32 bit SUB extending register setting flags. */
2107 subs32_ext (sim_cpu *cpu, Extension extension, uint32_t shift)
2109 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
2110 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
2111 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
2113 uint32_t value1 = aarch64_get_reg_u32 (cpu, rn, SP_OK);
2114 uint32_t value2 = extreg32 (cpu, rm, extension) << shift;
2116 aarch64_set_reg_u64 (cpu, rd, NO_SP, value1 - value2);
2117 set_flags_for_sub32 (cpu, value1, value2);
2120 /* 64 bit SUB extending register setting flags */
2121 /* N.B. this subsumes the case with 64 bit source2 and UXTX #n or LSL #0 */
2123 subs64_ext (sim_cpu *cpu, Extension extension, uint32_t shift)
2125 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
2126 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
2127 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
2129 uint64_t value1 = aarch64_get_reg_u64 (cpu, rn, SP_OK);
2130 uint64_t value2 = extreg64 (cpu, rm, extension) << shift;
2132 aarch64_set_reg_u64 (cpu, rd, NO_SP, value1 - value2);
2133 set_flags_for_sub64 (cpu, value1, value2);
2137 dexAddSubtractImmediate (sim_cpu *cpu)
2139 /* instr[31] = size : 0 ==> 32 bit, 1 ==> 64 bit
2140 instr[30] = op : 0 ==> ADD, 1 ==> SUB
2141 instr[29] = set : 0 ==> no flags, 1 ==> set flags
2142 instr[28,24] = 10001
2143 instr[23,22] = shift : 00 == LSL#0, 01 = LSL#12 1x = UNALLOC
2144 instr[21,10] = uimm12
2148 /* N.B. the shift is applied at decode before calling the add/sub routine. */
2149 uint32_t shift = uimm (aarch64_get_instr (cpu), 23, 22);
2150 uint32_t imm = uimm (aarch64_get_instr (cpu), 21, 10);
2151 uint32_t dispatch = uimm (aarch64_get_instr (cpu), 31, 29);
2153 NYI_assert (28, 24, 0x11);
2163 case 0: add32 (cpu, imm); break;
2164 case 1: adds32 (cpu, imm); break;
2165 case 2: sub32 (cpu, imm); break;
2166 case 3: subs32 (cpu, imm); break;
2167 case 4: add64 (cpu, imm); break;
2168 case 5: adds64 (cpu, imm); break;
2169 case 6: sub64 (cpu, imm); break;
2170 case 7: subs64 (cpu, imm); break;
2177 dexAddSubtractShiftedRegister (sim_cpu *cpu)
2179 /* instr[31] = size : 0 ==> 32 bit, 1 ==> 64 bit
2180 instr[30,29] = op : 00 ==> ADD, 01 ==> ADDS, 10 ==> SUB, 11 ==> SUBS
2181 instr[28,24] = 01011
2182 instr[23,22] = shift : 0 ==> LSL, 1 ==> LSR, 2 ==> ASR, 3 ==> UNALLOC
2185 instr[15,10] = count : must be 0xxxxx for 32 bit
2189 uint32_t size = uimm (aarch64_get_instr (cpu), 31, 31);
2190 /* 32 bit operations must have count[5] = 0
2191 or else we have an UNALLOC. */
2192 uint32_t count = uimm (aarch64_get_instr (cpu), 15, 10);
2193 /* Shift encoded as ROR is unallocated. */
2194 Shift shiftType = shift (aarch64_get_instr (cpu), 22);
2195 /* Dispatch on size:op i.e aarch64_get_instr (cpu)[31,29]. */
2196 uint32_t dispatch = uimm (aarch64_get_instr (cpu), 31, 29);
2198 NYI_assert (28, 24, 0x0B);
2199 NYI_assert (21, 21, 0);
2201 if (shiftType == ROR)
2204 if (!size && uimm (count, 5, 5))
2209 case 0: add32_shift (cpu, shiftType, count); break;
2210 case 1: adds32_shift (cpu, shiftType, count); break;
2211 case 2: sub32_shift (cpu, shiftType, count); break;
2212 case 3: subs32_shift (cpu, shiftType, count); break;
2213 case 4: add64_shift (cpu, shiftType, count); break;
2214 case 5: adds64_shift (cpu, shiftType, count); break;
2215 case 6: sub64_shift (cpu, shiftType, count); break;
2216 case 7: subs64_shift (cpu, shiftType, count); break;
2223 dexAddSubtractExtendedRegister (sim_cpu *cpu)
2225 /* instr[31] = size : 0 ==> 32 bit, 1 ==> 64 bit
2226 instr[30] = op : 0 ==> ADD, 1 ==> SUB
2227 instr[29] = set? : 0 ==> no flags, 1 ==> set flags
2228 instr[28,24] = 01011
2229 instr[23,22] = opt : 0 ==> ok, 1,2,3 ==> UNALLOC
2232 instr[15,13] = option : 000 ==> UXTB, 001 ==> UXTH,
2233 000 ==> LSL|UXTW, 001 ==> UXTZ,
2234 000 ==> SXTB, 001 ==> SXTH,
2235 000 ==> SXTW, 001 ==> SXTX,
2236 instr[12,10] = shift : 0,1,2,3,4 ==> ok, 5,6,7 ==> UNALLOC
2240 Extension extensionType = extension (aarch64_get_instr (cpu), 13);
2241 uint32_t shift = uimm (aarch64_get_instr (cpu), 12, 10);
2242 /* dispatch on size:op:set? i.e aarch64_get_instr (cpu)[31,29] */
2243 uint32_t dispatch = uimm (aarch64_get_instr (cpu), 31, 29);
2245 NYI_assert (28, 24, 0x0B);
2246 NYI_assert (21, 21, 1);
2248 /* Shift may not exceed 4. */
2254 case 0: add32_ext (cpu, extensionType, shift); break;
2255 case 1: adds32_ext (cpu, extensionType, shift); break;
2256 case 2: sub32_ext (cpu, extensionType, shift); break;
2257 case 3: subs32_ext (cpu, extensionType, shift); break;
2258 case 4: add64_ext (cpu, extensionType, shift); break;
2259 case 5: adds64_ext (cpu, extensionType, shift); break;
2260 case 6: sub64_ext (cpu, extensionType, shift); break;
2261 case 7: subs64_ext (cpu, extensionType, shift); break;
2262 default: HALT_UNALLOC;
2266 /* Conditional data processing
2267 Condition register is implicit 3rd source. */
2269 /* 32 bit add with carry. */
2270 /* N.B register args may not be SP. */
2273 adc32 (sim_cpu *cpu)
2275 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
2276 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
2277 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
2279 aarch64_set_reg_u64 (cpu, rd, NO_SP,
2280 aarch64_get_reg_u32 (cpu, rn, NO_SP)
2281 + aarch64_get_reg_u32 (cpu, rm, NO_SP)
2285 /* 64 bit add with carry */
2287 adc64 (sim_cpu *cpu)
2289 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
2290 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
2291 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
2293 aarch64_set_reg_u64 (cpu, rd, NO_SP,
2294 aarch64_get_reg_u64 (cpu, rn, NO_SP)
2295 + aarch64_get_reg_u64 (cpu, rm, NO_SP)
2299 /* 32 bit add with carry setting flags. */
2301 adcs32 (sim_cpu *cpu)
2303 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
2304 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
2305 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
2307 uint32_t value1 = aarch64_get_reg_u32 (cpu, rn, NO_SP);
2308 uint32_t value2 = aarch64_get_reg_u32 (cpu, rm, NO_SP);
2309 uint32_t carry = IS_SET (C);
2311 aarch64_set_reg_u64 (cpu, rd, NO_SP, value1 + value2 + carry);
2312 set_flags_for_add32 (cpu, value1, value2 + carry);
2315 /* 64 bit add with carry setting flags. */
2317 adcs64 (sim_cpu *cpu)
2319 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
2320 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
2321 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
2323 uint64_t value1 = aarch64_get_reg_u64 (cpu, rn, NO_SP);
2324 uint64_t value2 = aarch64_get_reg_u64 (cpu, rm, NO_SP);
2325 uint64_t carry = IS_SET (C);
2327 aarch64_set_reg_u64 (cpu, rd, NO_SP, value1 + value2 + carry);
2328 set_flags_for_add64 (cpu, value1, value2 + carry);
2331 /* 32 bit sub with carry. */
2333 sbc32 (sim_cpu *cpu)
2335 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
2336 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
2337 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
2339 aarch64_set_reg_u64 (cpu, rd, NO_SP,
2340 aarch64_get_reg_u32 (cpu, rn, NO_SP)
2341 - aarch64_get_reg_u32 (cpu, rm, NO_SP)
2345 /* 64 bit sub with carry */
2347 sbc64 (sim_cpu *cpu)
2349 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
2350 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
2351 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
2353 aarch64_set_reg_u64 (cpu, rd, NO_SP,
2354 aarch64_get_reg_u64 (cpu, rn, NO_SP)
2355 - aarch64_get_reg_u64 (cpu, rm, NO_SP)
2359 /* 32 bit sub with carry setting flags */
2361 sbcs32 (sim_cpu *cpu)
2363 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
2364 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
2365 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
2367 uint32_t value1 = aarch64_get_reg_u32 (cpu, rn, NO_SP);
2368 uint32_t value2 = aarch64_get_reg_u32 (cpu, rm, NO_SP);
2369 uint32_t carry = IS_SET (C);
2370 uint32_t result = value1 - value2 + 1 - carry;
2372 aarch64_set_reg_u64 (cpu, rd, NO_SP, result);
2373 set_flags_for_sub32 (cpu, value1, value2 + 1 - carry);
2376 /* 64 bit sub with carry setting flags */
2378 sbcs64 (sim_cpu *cpu)
2380 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
2381 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
2382 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
2384 uint64_t value1 = aarch64_get_reg_u64 (cpu, rn, NO_SP);
2385 uint64_t value2 = aarch64_get_reg_u64 (cpu, rm, NO_SP);
2386 uint64_t carry = IS_SET (C);
2387 uint64_t result = value1 - value2 + 1 - carry;
2389 aarch64_set_reg_u64 (cpu, rd, NO_SP, result);
2390 set_flags_for_sub64 (cpu, value1, value2 + 1 - carry);
2394 dexAddSubtractWithCarry (sim_cpu *cpu)
2396 /* instr[31] = size : 0 ==> 32 bit, 1 ==> 64 bit
2397 instr[30] = op : 0 ==> ADC, 1 ==> SBC
2398 instr[29] = set? : 0 ==> no flags, 1 ==> set flags
2399 instr[28,21] = 1 1010 000
2401 instr[15,10] = op2 : 00000 ==> ok, ow ==> UNALLOC
2405 uint32_t op2 = uimm (aarch64_get_instr (cpu), 15, 10);
2406 /* Dispatch on size:op:set? i.e aarch64_get_instr (cpu)[31,29] */
2407 uint32_t dispatch = uimm (aarch64_get_instr (cpu), 31, 29);
2409 NYI_assert (28, 21, 0xD0);
2416 case 0: adc32 (cpu); break;
2417 case 1: adcs32 (cpu); break;
2418 case 2: sbc32 (cpu); break;
2419 case 3: sbcs32 (cpu); break;
2420 case 4: adc64 (cpu); break;
2421 case 5: adcs64 (cpu); break;
2422 case 6: sbc64 (cpu); break;
2423 case 7: sbcs64 (cpu); break;
2424 default: HALT_UNALLOC;
2429 testConditionCode (sim_cpu *cpu, CondCode cc)
2431 /* This should be reduceable to branchless logic
2432 by some careful testing of bits in CC followed
2433 by the requisite masking and combining of bits
2434 from the flag register.
2436 For now we do it with a switch. */
2441 case EQ: res = IS_SET (Z); break;
2442 case NE: res = IS_CLEAR (Z); break;
2443 case CS: res = IS_SET (C); break;
2444 case CC: res = IS_CLEAR (C); break;
2445 case MI: res = IS_SET (N); break;
2446 case PL: res = IS_CLEAR (N); break;
2447 case VS: res = IS_SET (V); break;
2448 case VC: res = IS_CLEAR (V); break;
2449 case HI: res = IS_SET (C) && IS_CLEAR (Z); break;
2450 case LS: res = IS_CLEAR (C) || IS_SET (Z); break;
2451 case GE: res = IS_SET (N) == IS_SET (V); break;
2452 case LT: res = IS_SET (N) != IS_SET (V); break;
2453 case GT: res = IS_CLEAR (Z) && (IS_SET (N) == IS_SET (V)); break;
2454 case LE: res = IS_SET (Z) || (IS_SET (N) != IS_SET (V)); break;
2465 CondCompare (sim_cpu *cpu) /* aka: ccmp and ccmn */
2467 /* instr[31] = size : 0 ==> 32 bit, 1 ==> 64 bit
2468 instr[30] = compare with positive (0) or negative value (1)
2469 instr[29,21] = 1 1101 0010
2470 instr[20,16] = Rm or const
2472 instr[11] = compare reg (0) or const (1)
2476 instr[3,0] = value for CPSR bits if the comparison does not take place. */
2481 NYI_assert (29, 21, 0x1d2);
2482 NYI_assert (10, 10, 0);
2483 NYI_assert (4, 4, 0);
2485 if (! testConditionCode (cpu, uimm (aarch64_get_instr (cpu), 15, 12)))
2487 aarch64_set_CPSR (cpu, uimm (aarch64_get_instr (cpu), 3, 0));
2491 negate = uimm (aarch64_get_instr (cpu), 30, 30) ? -1 : 1;
2492 rm = uimm (aarch64_get_instr (cpu), 20, 16);
2493 rn = uimm (aarch64_get_instr (cpu), 9, 5);
2495 if (uimm (aarch64_get_instr (cpu), 31, 31))
2497 if (uimm (aarch64_get_instr (cpu), 11, 11))
2498 set_flags_for_sub64 (cpu, aarch64_get_reg_u64 (cpu, rn, SP_OK),
2499 negate * (uint64_t) rm);
2501 set_flags_for_sub64 (cpu, aarch64_get_reg_u64 (cpu, rn, SP_OK),
2502 negate * aarch64_get_reg_u64 (cpu, rm, SP_OK));
2506 if (uimm (aarch64_get_instr (cpu), 11, 11))
2507 set_flags_for_sub32 (cpu, aarch64_get_reg_u32 (cpu, rn, SP_OK),
2510 set_flags_for_sub32 (cpu, aarch64_get_reg_u32 (cpu, rn, SP_OK),
2511 negate * aarch64_get_reg_u32 (cpu, rm, SP_OK));
2516 do_vec_MOV_whole_vector (sim_cpu *cpu)
2518 /* MOV Vd.T, Vs.T (alias for ORR Vd.T, Vn.T, Vm.T where Vn == Vm)
2521 instr[30] = half(0)/full(1)
2522 instr[29,21] = 001110101
2524 instr[15,10] = 000111
2528 unsigned vs = uimm (aarch64_get_instr (cpu), 9, 5);
2529 unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
2531 NYI_assert (29, 21, 0x075);
2532 NYI_assert (15, 10, 0x07);
2534 if (uimm (aarch64_get_instr (cpu), 20, 16) != vs)
2537 if (uimm (aarch64_get_instr (cpu), 30, 30))
2538 aarch64_set_vec_u64 (cpu, vd, 1, aarch64_get_vec_u64 (cpu, vs, 1));
2540 aarch64_set_vec_u64 (cpu, vd, 0, aarch64_get_vec_u64 (cpu, vs, 0));
2544 do_vec_MOV_into_scalar (sim_cpu *cpu)
2547 instr[30] = word(0)/long(1)
2548 instr[29,21] = 00 1110 000
2549 instr[20,18] = element size and index
2550 instr[17,10] = 00 0011 11
2551 instr[9,5] = V source
2552 instr[4,0] = R dest */
2554 unsigned vs = uimm (aarch64_get_instr (cpu), 9, 5);
2555 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
2557 NYI_assert (29, 21, 0x070);
2558 NYI_assert (17, 10, 0x0F);
2560 switch (uimm (aarch64_get_instr (cpu), 20, 18))
2563 aarch64_set_reg_u64 (cpu, rd, NO_SP, aarch64_get_vec_u64 (cpu, vs, 0));
2567 aarch64_set_reg_u64 (cpu, rd, NO_SP, aarch64_get_vec_u64 (cpu, vs, 1));
2574 aarch64_set_reg_u64 (cpu, rd, NO_SP, aarch64_get_vec_u32
2575 (cpu, vs, uimm (aarch64_get_instr (cpu), 20, 19)));
2584 do_vec_INS (sim_cpu *cpu)
2586 /* instr[31,21] = 01001110000
2587 instr[20,16] = element size and index
2588 instr[15,10] = 000111
2589 instr[9,5] = W source
2590 instr[4,0] = V dest */
2593 unsigned rs = uimm (aarch64_get_instr (cpu), 9, 5);
2594 unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
2596 NYI_assert (31, 21, 0x270);
2597 NYI_assert (15, 10, 0x07);
2599 if (uimm (aarch64_get_instr (cpu), 16, 16))
2601 index = uimm (aarch64_get_instr (cpu), 20, 17);
2602 aarch64_set_vec_u8 (cpu, vd, index,
2603 aarch64_get_reg_u8 (cpu, rs, NO_SP));
2605 else if (uimm (aarch64_get_instr (cpu), 17, 17))
2607 index = uimm (aarch64_get_instr (cpu), 20, 18);
2608 aarch64_set_vec_u16 (cpu, vd, index,
2609 aarch64_get_reg_u16 (cpu, rs, NO_SP));
2611 else if (uimm (aarch64_get_instr (cpu), 18, 18))
2613 index = uimm (aarch64_get_instr (cpu), 20, 19);
2614 aarch64_set_vec_u32 (cpu, vd, index,
2615 aarch64_get_reg_u32 (cpu, rs, NO_SP));
2617 else if (uimm (aarch64_get_instr (cpu), 19, 19))
2619 index = uimm (aarch64_get_instr (cpu), 20, 20);
2620 aarch64_set_vec_u64 (cpu, vd, index,
2621 aarch64_get_reg_u64 (cpu, rs, NO_SP));
2628 do_vec_DUP_vector_into_vector (sim_cpu *cpu)
2631 instr[30] = half(0)/full(1)
2632 instr[29,21] = 00 1110 000
2633 instr[20,16] = element size and index
2634 instr[15,10] = 0000 01
2635 instr[9,5] = V source
2636 instr[4,0] = V dest. */
2638 unsigned full = uimm (aarch64_get_instr (cpu), 30, 30);
2639 unsigned vs = uimm (aarch64_get_instr (cpu), 9, 5);
2640 unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
2643 NYI_assert (29, 21, 0x070);
2644 NYI_assert (15, 10, 0x01);
2646 if (uimm (aarch64_get_instr (cpu), 16, 16))
2648 index = uimm (aarch64_get_instr (cpu), 20, 17);
2650 for (i = 0; i < (full ? 16 : 8); i++)
2651 aarch64_set_vec_u8 (cpu, vd, i, aarch64_get_vec_u8 (cpu, vs, index));
2653 else if (uimm (aarch64_get_instr (cpu), 17, 17))
2655 index = uimm (aarch64_get_instr (cpu), 20, 18);
2657 for (i = 0; i < (full ? 8 : 4); i++)
2658 aarch64_set_vec_u16 (cpu, vd, i, aarch64_get_vec_u16 (cpu, vs, index));
2660 else if (uimm (aarch64_get_instr (cpu), 18, 18))
2662 index = uimm (aarch64_get_instr (cpu), 20, 19);
2664 for (i = 0; i < (full ? 4 : 2); i++)
2665 aarch64_set_vec_u32 (cpu, vd, i, aarch64_get_vec_u32 (cpu, vs, index));
2669 if (uimm (aarch64_get_instr (cpu), 19, 19) == 0)
2675 index = uimm (aarch64_get_instr (cpu), 20, 20);
2677 for (i = 0; i < 2; i++)
2678 aarch64_set_vec_u64 (cpu, vd, i, aarch64_get_vec_u64 (cpu, vs, index));
2683 do_vec_TBL (sim_cpu *cpu)
2686 instr[30] = half(0)/full(1)
2687 instr[29,21] = 00 1110 000
2690 instr[14,13] = vec length
2692 instr[9,5] = V start
2693 instr[4,0] = V dest */
2695 int full = uimm (aarch64_get_instr (cpu), 30, 30);
2696 int len = uimm (aarch64_get_instr (cpu), 14, 13) + 1;
2697 unsigned vm = uimm (aarch64_get_instr (cpu), 20, 16);
2698 unsigned vn = uimm (aarch64_get_instr (cpu), 9, 5);
2699 unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
2702 NYI_assert (29, 21, 0x070);
2703 NYI_assert (12, 10, 0);
2705 for (i = 0; i < (full ? 16 : 8); i++)
2707 unsigned int selector = aarch64_get_vec_u8 (cpu, vm, i);
2711 val = aarch64_get_vec_u8 (cpu, vn, selector);
2712 else if (selector < 32)
2713 val = len < 2 ? 0 : aarch64_get_vec_u8 (cpu, vn + 1, selector - 16);
2714 else if (selector < 48)
2715 val = len < 3 ? 0 : aarch64_get_vec_u8 (cpu, vn + 2, selector - 32);
2716 else if (selector < 64)
2717 val = len < 4 ? 0 : aarch64_get_vec_u8 (cpu, vn + 3, selector - 48);
2721 aarch64_set_vec_u8 (cpu, vd, i, val);
2726 do_vec_TRN (sim_cpu *cpu)
2729 instr[30] = half(0)/full(1)
2730 instr[29,24] = 00 1110
2735 instr[14] = TRN1 (0) / TRN2 (1)
2737 instr[9,5] = V source
2738 instr[4,0] = V dest. */
2740 int full = uimm (aarch64_get_instr (cpu), 30, 30);
2741 int second = uimm (aarch64_get_instr (cpu), 14, 14);
2742 unsigned vm = uimm (aarch64_get_instr (cpu), 20, 16);
2743 unsigned vn = uimm (aarch64_get_instr (cpu), 9, 5);
2744 unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
2747 NYI_assert (29, 24, 0x0E);
2748 NYI_assert (13, 10, 0xA);
2750 switch (uimm (aarch64_get_instr (cpu), 23, 22))
2753 for (i = 0; i < (full ? 8 : 4); i++)
2757 aarch64_get_vec_u8 (cpu, second ? vm : vn, i * 2));
2759 (cpu, vd, 1 * 2 + 1,
2760 aarch64_get_vec_u8 (cpu, second ? vn : vm, i * 2 + 1));
2765 for (i = 0; i < (full ? 4 : 2); i++)
2769 aarch64_get_vec_u16 (cpu, second ? vm : vn, i * 2));
2771 (cpu, vd, 1 * 2 + 1,
2772 aarch64_get_vec_u16 (cpu, second ? vn : vm, i * 2 + 1));
2778 (cpu, vd, 0, aarch64_get_vec_u32 (cpu, second ? vm : vn, 0));
2780 (cpu, vd, 1, aarch64_get_vec_u32 (cpu, second ? vn : vm, 1));
2782 (cpu, vd, 2, aarch64_get_vec_u32 (cpu, second ? vm : vn, 2));
2784 (cpu, vd, 3, aarch64_get_vec_u32 (cpu, second ? vn : vm, 3));
2791 aarch64_set_vec_u64 (cpu, vd, 0,
2792 aarch64_get_vec_u64 (cpu, second ? vm : vn, 0));
2793 aarch64_set_vec_u64 (cpu, vd, 1,
2794 aarch64_get_vec_u64 (cpu, second ? vn : vm, 1));
2803 do_vec_DUP_scalar_into_vector (sim_cpu *cpu)
2806 instr[30] = 0=> zero top 64-bits, 1=> duplicate into top 64-bits
2807 [must be 1 for 64-bit xfer]
2808 instr[29,20] = 00 1110 0000
2809 instr[19,16] = element size: 0001=> 8-bits, 0010=> 16-bits,
2810 0100=> 32-bits. 1000=>64-bits
2811 instr[15,10] = 0000 11
2812 instr[9,5] = W source
2813 instr[4,0] = V dest. */
2816 unsigned Vd = uimm (aarch64_get_instr (cpu), 4, 0);
2817 unsigned Rs = uimm (aarch64_get_instr (cpu), 9, 5);
2818 int both = uimm (aarch64_get_instr (cpu), 30, 30);
2820 NYI_assert (29, 20, 0x0E0);
2821 NYI_assert (15, 10, 0x03);
2823 switch (uimm (aarch64_get_instr (cpu), 19, 16))
2826 for (i = 0; i < (both ? 16 : 8); i++)
2827 aarch64_set_vec_u8 (cpu, Vd, i, aarch64_get_reg_u8 (cpu, Rs, NO_SP));
2831 for (i = 0; i < (both ? 8 : 4); i++)
2832 aarch64_set_vec_u16 (cpu, Vd, i, aarch64_get_reg_u16 (cpu, Rs, NO_SP));
2836 for (i = 0; i < (both ? 4 : 2); i++)
2837 aarch64_set_vec_u32 (cpu, Vd, i, aarch64_get_reg_u32 (cpu, Rs, NO_SP));
2843 aarch64_set_vec_u64 (cpu, Vd, 0, aarch64_get_reg_u64 (cpu, Rs, NO_SP));
2844 aarch64_set_vec_u64 (cpu, Vd, 1, aarch64_get_reg_u64 (cpu, Rs, NO_SP));
2853 do_vec_UZP (sim_cpu *cpu)
2856 instr[30] = half(0)/full(1)
2857 instr[29,24] = 00 1110
2858 instr[23,22] = size: byte(00), half(01), word (10), long (11)
2862 instr[14] = lower (0) / upper (1)
2867 int full = uimm (aarch64_get_instr (cpu), 30, 30);
2868 int upper = uimm (aarch64_get_instr (cpu), 14, 14);
2870 unsigned vm = uimm (aarch64_get_instr (cpu), 20, 16);
2871 unsigned vn = uimm (aarch64_get_instr (cpu), 9, 5);
2872 unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
2874 uint64_t val_m1 = aarch64_get_vec_u64 (cpu, vm, 0);
2875 uint64_t val_m2 = aarch64_get_vec_u64 (cpu, vm, 1);
2876 uint64_t val_n1 = aarch64_get_vec_u64 (cpu, vn, 0);
2877 uint64_t val_n2 = aarch64_get_vec_u64 (cpu, vn, 1);
2882 uint64_t input1 = upper ? val_n1 : val_m1;
2883 uint64_t input2 = upper ? val_n2 : val_m2;
2886 NYI_assert (29, 24, 0x0E);
2887 NYI_assert (21, 21, 0);
2888 NYI_assert (15, 15, 0);
2889 NYI_assert (13, 10, 6);
2891 switch (uimm (aarch64_get_instr (cpu), 23, 23))
2894 for (i = 0; i < 8; i++)
2896 val1 |= (input1 >> (i * 8)) & (0xFFULL << (i * 8));
2897 val2 |= (input2 >> (i * 8)) & (0xFFULL << (i * 8));
2902 for (i = 0; i < 4; i++)
2904 val1 |= (input1 >> (i * 16)) & (0xFFFFULL << (i * 16));
2905 val2 |= (input2 >> (i * 16)) & (0xFFFFULL << (i * 16));
2910 val1 = ((input1 & 0xFFFFFFFF) | ((input1 >> 32) & 0xFFFFFFFF00000000ULL));
2911 val2 = ((input2 & 0xFFFFFFFF) | ((input2 >> 32) & 0xFFFFFFFF00000000ULL));
2919 aarch64_set_vec_u64 (cpu, vd, 0, val1);
2921 aarch64_set_vec_u64 (cpu, vd, 1, val2);
2925 do_vec_ZIP (sim_cpu *cpu)
2928 instr[30] = half(0)/full(1)
2929 instr[29,24] = 00 1110
2930 instr[23,22] = size: byte(00), hald(01), word (10), long (11)
2934 instr[14] = lower (0) / upper (1)
2939 int full = uimm (aarch64_get_instr (cpu), 30, 30);
2940 int upper = uimm (aarch64_get_instr (cpu), 14, 14);
2942 unsigned vm = uimm (aarch64_get_instr (cpu), 20, 16);
2943 unsigned vn = uimm (aarch64_get_instr (cpu), 9, 5);
2944 unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
2946 uint64_t val_m1 = aarch64_get_vec_u64 (cpu, vm, 0);
2947 uint64_t val_m2 = aarch64_get_vec_u64 (cpu, vm, 1);
2948 uint64_t val_n1 = aarch64_get_vec_u64 (cpu, vn, 0);
2949 uint64_t val_n2 = aarch64_get_vec_u64 (cpu, vn, 1);
2954 uint64_t input1 = upper ? val_n1 : val_m1;
2955 uint64_t input2 = upper ? val_n2 : val_m2;
2957 NYI_assert (29, 24, 0x0E);
2958 NYI_assert (21, 21, 0);
2959 NYI_assert (15, 15, 0);
2960 NYI_assert (13, 10, 0xE);
2962 switch (uimm (aarch64_get_instr (cpu), 23, 23))
2966 ((input1 << 0) & (0xFF << 0))
2967 | ((input2 << 8) & (0xFF << 8))
2968 | ((input1 << 8) & (0xFF << 16))
2969 | ((input2 << 16) & (0xFF << 24))
2970 | ((input1 << 16) & (0xFFULL << 32))
2971 | ((input2 << 24) & (0xFFULL << 40))
2972 | ((input1 << 24) & (0xFFULL << 48))
2973 | ((input2 << 32) & (0xFFULL << 56));
2976 ((input1 >> 32) & (0xFF << 0))
2977 | ((input2 >> 24) & (0xFF << 8))
2978 | ((input1 >> 24) & (0xFF << 16))
2979 | ((input2 >> 16) & (0xFF << 24))
2980 | ((input1 >> 16) & (0xFFULL << 32))
2981 | ((input2 >> 8) & (0xFFULL << 40))
2982 | ((input1 >> 8) & (0xFFULL << 48))
2983 | ((input2 >> 0) & (0xFFULL << 56));
2988 ((input1 << 0) & (0xFFFF << 0))
2989 | ((input2 << 16) & (0xFFFF << 16))
2990 | ((input1 << 16) & (0xFFFFULL << 32))
2991 | ((input2 << 32) & (0xFFFFULL << 48));
2994 ((input1 >> 32) & (0xFFFF << 0))
2995 | ((input2 >> 16) & (0xFFFF << 16))
2996 | ((input1 >> 16) & (0xFFFFULL << 32))
2997 | ((input2 >> 0) & (0xFFFFULL << 48));
3001 val1 = (input1 & 0xFFFFFFFFULL) | (input2 << 32);
3002 val2 = (input2 & 0xFFFFFFFFULL) | (input1 << 32);
3011 aarch64_set_vec_u64 (cpu, vd, 0, val1);
3013 aarch64_set_vec_u64 (cpu, vd, 1, val2);
3016 /* Floating point immediates are encoded in 8 bits.
3017 fpimm[7] = sign bit.
3018 fpimm[6:4] = signed exponent.
3019 fpimm[3:0] = fraction (assuming leading 1).
3020 i.e. F = s * 1.f * 2^(e - b). */
3023 fp_immediate_for_encoding_32 (uint32_t imm8)
3026 uint32_t s, e, f, i;
3028 s = (imm8 >> 7) & 0x1;
3029 e = (imm8 >> 4) & 0x7;
3032 /* The fp value is s * n/16 * 2r where n is 16+e. */
3033 u = (16.0 + f) / 16.0;
3035 /* N.B. exponent is signed. */
3040 for (i = 0; i <= epos; i++)
3047 for (i = 0; i < eneg; i++)
3058 fp_immediate_for_encoding_64 (uint32_t imm8)
3061 uint32_t s, e, f, i;
3063 s = (imm8 >> 7) & 0x1;
3064 e = (imm8 >> 4) & 0x7;
3067 /* The fp value is s * n/16 * 2r where n is 16+e. */
3068 u = (16.0 + f) / 16.0;
3070 /* N.B. exponent is signed. */
3075 for (i = 0; i <= epos; i++)
3082 for (i = 0; i < eneg; i++)
3093 do_vec_MOV_immediate (sim_cpu *cpu)
3096 instr[30] = full/half selector
3097 instr[29,19] = 00111100000
3098 instr[18,16] = high 3 bits of uimm8
3099 instr[15,12] = size & shift:
3101 0010 => 32-bit + LSL#8
3102 0100 => 32-bit + LSL#16
3103 0110 => 32-bit + LSL#24
3104 1010 => 16-bit + LSL#8
3106 1101 => 32-bit + MSL#16
3107 1100 => 32-bit + MSL#8
3111 instr[9,5] = low 5-bits of uimm8
3114 int full = uimm (aarch64_get_instr (cpu), 30, 30);
3115 unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
3116 unsigned val = uimm (aarch64_get_instr (cpu), 18, 16) << 5
3117 | uimm (aarch64_get_instr (cpu), 9, 5);
3120 NYI_assert (29, 19, 0x1E0);
3121 NYI_assert (11, 10, 1);
3123 switch (uimm (aarch64_get_instr (cpu), 15, 12))
3125 case 0x0: /* 32-bit, no shift. */
3126 case 0x2: /* 32-bit, shift by 8. */
3127 case 0x4: /* 32-bit, shift by 16. */
3128 case 0x6: /* 32-bit, shift by 24. */
3129 val <<= (8 * uimm (aarch64_get_instr (cpu), 14, 13));
3130 for (i = 0; i < (full ? 4 : 2); i++)
3131 aarch64_set_vec_u32 (cpu, vd, i, val);
3134 case 0xa: /* 16-bit, shift by 8. */
3137 case 0x8: /* 16-bit, no shift. */
3138 for (i = 0; i < (full ? 8 : 4); i++)
3139 aarch64_set_vec_u16 (cpu, vd, i, val);
3141 case 0xd: /* 32-bit, mask shift by 16. */
3145 case 0xc: /* 32-bit, mask shift by 8. */
3148 for (i = 0; i < (full ? 4 : 2); i++)
3149 aarch64_set_vec_u32 (cpu, vd, i, val);
3152 case 0xe: /* 8-bit, no shift. */
3153 for (i = 0; i < (full ? 16 : 8); i++)
3154 aarch64_set_vec_u8 (cpu, vd, i, val);
3157 case 0xf: /* FMOV Vs.{2|4}S, #fpimm. */
3159 float u = fp_immediate_for_encoding_32 (val);
3160 for (i = 0; i < (full ? 4 : 2); i++)
3161 aarch64_set_vec_float (cpu, vd, i, u);
3171 do_vec_MVNI (sim_cpu *cpu)
3174 instr[30] = full/half selector
3175 instr[29,19] = 10111100000
3176 instr[18,16] = high 3 bits of uimm8
3177 instr[15,12] = selector
3179 instr[9,5] = low 5-bits of uimm8
3182 int full = uimm (aarch64_get_instr (cpu), 30, 30);
3183 unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
3184 unsigned val = uimm (aarch64_get_instr (cpu), 18, 16) << 5
3185 | uimm (aarch64_get_instr (cpu), 9, 5);
3188 NYI_assert (29, 19, 0x5E0);
3189 NYI_assert (11, 10, 1);
3191 switch (uimm (aarch64_get_instr (cpu), 15, 12))
3193 case 0x0: /* 32-bit, no shift. */
3194 case 0x2: /* 32-bit, shift by 8. */
3195 case 0x4: /* 32-bit, shift by 16. */
3196 case 0x6: /* 32-bit, shift by 24. */
3197 val <<= (8 * uimm (aarch64_get_instr (cpu), 14, 13));
3199 for (i = 0; i < (full ? 4 : 2); i++)
3200 aarch64_set_vec_u32 (cpu, vd, i, val);
3203 case 0xa: /* 16-bit, 8 bit shift. */
3205 case 0x8: /* 16-bit, no shift. */
3207 for (i = 0; i < (full ? 8 : 4); i++)
3208 aarch64_set_vec_u16 (cpu, vd, i, val);
3211 case 0xd: /* 32-bit, mask shift by 16. */
3214 case 0xc: /* 32-bit, mask shift by 8. */
3218 for (i = 0; i < (full ? 4 : 2); i++)
3219 aarch64_set_vec_u32 (cpu, vd, i, val);
3222 case 0xE: /* MOVI Dn, #mask64 */
3226 for (i = 0; i < 8; i++)
3228 mask |= (0xF << (i * 4));
3229 aarch64_set_vec_u64 (cpu, vd, 0, mask);
3230 aarch64_set_vec_u64 (cpu, vd, 1, 0);
3234 case 0xf: /* FMOV Vd.2D, #fpimm. */
3236 double u = fp_immediate_for_encoding_64 (val);
3241 aarch64_set_vec_double (cpu, vd, 0, u);
3242 aarch64_set_vec_double (cpu, vd, 1, u);
3251 #define ABS(A) ((A) < 0 ? - (A) : (A))
3254 do_vec_ABS (sim_cpu *cpu)
3257 instr[30] = half(0)/full(1)
3258 instr[29,24] = 00 1110
3259 instr[23,22] = size: 00=> 8-bit, 01=> 16-bit, 10=> 32-bit, 11=> 64-bit
3260 instr[21,10] = 10 0000 1011 10
3264 unsigned vn = uimm (aarch64_get_instr (cpu), 9, 5);
3265 unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
3266 unsigned full = uimm (aarch64_get_instr (cpu), 30, 30);
3269 NYI_assert (29, 24, 0x0E);
3270 NYI_assert (21, 10, 0x82E);
3272 switch (uimm (aarch64_get_instr (cpu), 23, 22))
3275 for (i = 0; i < (full ? 16 : 8); i++)
3276 aarch64_set_vec_s8 (cpu, vd, i,
3277 ABS (aarch64_get_vec_s8 (cpu, vn, i)));
3281 for (i = 0; i < (full ? 8 : 4); i++)
3282 aarch64_set_vec_s16 (cpu, vd, i,
3283 ABS (aarch64_get_vec_s16 (cpu, vn, i)));
3287 for (i = 0; i < (full ? 4 : 2); i++)
3288 aarch64_set_vec_s32 (cpu, vd, i,
3289 ABS (aarch64_get_vec_s32 (cpu, vn, i)));
3295 for (i = 0; i < 2; i++)
3296 aarch64_set_vec_s64 (cpu, vd, i,
3297 ABS (aarch64_get_vec_s64 (cpu, vn, i)));
3303 do_vec_ADDV (sim_cpu *cpu)
3306 instr[30] = full/half selector
3307 instr[29,24] = 00 1110
3308 instr[23,22] = size: 00=> 8-bit, 01=> 16-bit, 10=> 32-bit, 11=> 64-bit
3309 instr[21,10] = 11 0001 1011 10
3313 unsigned vm = uimm (aarch64_get_instr (cpu), 9, 5);
3314 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
3317 int full = uimm (aarch64_get_instr (cpu), 30, 30);
3319 NYI_assert (29, 24, 0x0E);
3320 NYI_assert (21, 10, 0xC6E);
3322 switch (uimm (aarch64_get_instr (cpu), 23, 22))
3325 for (i = 0; i < (full ? 16 : 8); i++)
3326 val += aarch64_get_vec_u8 (cpu, vm, i);
3327 aarch64_set_reg_u64 (cpu, rd, NO_SP, val);
3331 for (i = 0; i < (full ? 8 : 4); i++)
3332 val += aarch64_get_vec_u16 (cpu, vm, i);
3333 aarch64_set_reg_u64 (cpu, rd, NO_SP, val);
3337 for (i = 0; i < (full ? 4 : 2); i++)
3338 val += aarch64_get_vec_u32 (cpu, vm, i);
3339 aarch64_set_reg_u64 (cpu, rd, NO_SP, val);
3345 val = aarch64_get_vec_u64 (cpu, vm, 0);
3346 val += aarch64_get_vec_u64 (cpu, vm, 1);
3347 aarch64_set_reg_u64 (cpu, rd, NO_SP, val);
3356 do_vec_ins_2 (sim_cpu *cpu)
3358 /* instr[31,21] = 01001110000
3359 instr[20,18] = size & element selector
3361 instr[13] = direction: to vec(0), from vec (1)
3367 unsigned vm = uimm (aarch64_get_instr (cpu), 9, 5);
3368 unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
3370 NYI_assert (31, 21, 0x270);
3371 NYI_assert (17, 14, 0);
3372 NYI_assert (12, 10, 7);
3374 if (uimm (aarch64_get_instr (cpu), 13, 13) == 1)
3376 if (uimm (aarch64_get_instr (cpu), 18, 18) == 1)
3379 elem = uimm (aarch64_get_instr (cpu), 20, 19);
3380 aarch64_set_reg_u64 (cpu, vd, NO_SP,
3381 aarch64_get_vec_u32 (cpu, vm, elem));
3386 if (uimm (aarch64_get_instr (cpu), 19, 19) != 1)
3389 elem = uimm (aarch64_get_instr (cpu), 20, 20);
3390 aarch64_set_reg_u64 (cpu, vd, NO_SP,
3391 aarch64_get_vec_u64 (cpu, vm, elem));
3396 if (uimm (aarch64_get_instr (cpu), 18, 18) == 1)
3399 elem = uimm (aarch64_get_instr (cpu), 20, 19);
3400 aarch64_set_vec_u32 (cpu, vd, elem,
3401 aarch64_get_reg_u32 (cpu, vm, NO_SP));
3406 if (uimm (aarch64_get_instr (cpu), 19, 19) != 1)
3409 elem = uimm (aarch64_get_instr (cpu), 20, 20);
3410 aarch64_set_vec_u64 (cpu, vd, elem,
3411 aarch64_get_reg_u64 (cpu, vm, NO_SP));
3417 do_vec_mull (sim_cpu *cpu)
3420 instr[30] = lower(0)/upper(1) selector
3421 instr[29] = signed(0)/unsigned(1)
3422 instr[28,24] = 0 1110
3423 instr[23,22] = size: 8-bit (00), 16-bit (01), 32-bit (10)
3426 instr[15,10] = 11 0000
3430 int unsign = uimm (aarch64_get_instr (cpu), 29, 29);
3431 int bias = uimm (aarch64_get_instr (cpu), 30, 30);
3432 unsigned vm = uimm (aarch64_get_instr (cpu), 20, 16);
3433 unsigned vn = uimm (aarch64_get_instr (cpu), 9, 5);
3434 unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
3437 NYI_assert (28, 24, 0x0E);
3438 NYI_assert (15, 10, 0x30);
3440 switch (uimm (aarch64_get_instr (cpu), 23, 22))
3446 for (i = 0; i < 8; i++)
3447 aarch64_set_vec_u16 (cpu, vd, i,
3448 aarch64_get_vec_u8 (cpu, vn, i + bias)
3449 * aarch64_get_vec_u8 (cpu, vm, i + bias));
3451 for (i = 0; i < 8; i++)
3452 aarch64_set_vec_s16 (cpu, vd, i,
3453 aarch64_get_vec_s8 (cpu, vn, i + bias)
3454 * aarch64_get_vec_s8 (cpu, vm, i + bias));
3461 for (i = 0; i < 4; i++)
3462 aarch64_set_vec_u32 (cpu, vd, i,
3463 aarch64_get_vec_u16 (cpu, vn, i + bias)
3464 * aarch64_get_vec_u16 (cpu, vm, i + bias));
3466 for (i = 0; i < 4; i++)
3467 aarch64_set_vec_s32 (cpu, vd, i,
3468 aarch64_get_vec_s16 (cpu, vn, i + bias)
3469 * aarch64_get_vec_s16 (cpu, vm, i + bias));
3476 for (i = 0; i < 2; i++)
3477 aarch64_set_vec_u64 (cpu, vd, i,
3478 (uint64_t) aarch64_get_vec_u32 (cpu, vn,
3480 * (uint64_t) aarch64_get_vec_u32 (cpu, vm,
3483 for (i = 0; i < 2; i++)
3484 aarch64_set_vec_s64 (cpu, vd, i,
3485 aarch64_get_vec_s32 (cpu, vn, i + bias)
3486 * aarch64_get_vec_s32 (cpu, vm, i + bias));
3496 do_vec_fadd (sim_cpu *cpu)
3499 instr[30] = half(0)/full(1)
3500 instr[29,24] = 001110
3501 instr[23] = FADD(0)/FSUB(1)
3502 instr[22] = float (0)/double(1)
3505 instr[15,10] = 110101
3509 unsigned vm = uimm (aarch64_get_instr (cpu), 20, 16);
3510 unsigned vn = uimm (aarch64_get_instr (cpu), 9, 5);
3511 unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
3513 int full = uimm (aarch64_get_instr (cpu), 30, 30);
3515 NYI_assert (29, 24, 0x0E);
3516 NYI_assert (21, 21, 1);
3517 NYI_assert (15, 10, 0x35);
3519 if (uimm (aarch64_get_instr (cpu), 23, 23))
3521 if (uimm (aarch64_get_instr (cpu), 22, 22))
3526 for (i = 0; i < 2; i++)
3527 aarch64_set_vec_double (cpu, vd, i,
3528 aarch64_get_vec_double (cpu, vn, i)
3529 - aarch64_get_vec_double (cpu, vm, i));
3533 for (i = 0; i < (full ? 4 : 2); i++)
3534 aarch64_set_vec_float (cpu, vd, i,
3535 aarch64_get_vec_float (cpu, vn, i)
3536 - aarch64_get_vec_float (cpu, vm, i));
3541 if (uimm (aarch64_get_instr (cpu), 22, 22))
3546 for (i = 0; i < 2; i++)
3547 aarch64_set_vec_double (cpu, vd, i,
3548 aarch64_get_vec_double (cpu, vm, i)
3549 + aarch64_get_vec_double (cpu, vn, i));
3553 for (i = 0; i < (full ? 4 : 2); i++)
3554 aarch64_set_vec_float (cpu, vd, i,
3555 aarch64_get_vec_float (cpu, vm, i)
3556 + aarch64_get_vec_float (cpu, vn, i));
3562 do_vec_add (sim_cpu *cpu)
3565 instr[30] = full/half selector
3566 instr[29,24] = 001110
3567 instr[23,22] = size: 00=> 8-bit, 01=> 16-bit, 10=> 32-bit, 11=> 64-bit
3570 instr[15,10] = 100001
3574 unsigned vm = uimm (aarch64_get_instr (cpu), 20, 16);
3575 unsigned vn = uimm (aarch64_get_instr (cpu), 9, 5);
3576 unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
3578 int full = uimm (aarch64_get_instr (cpu), 30, 30);
3580 NYI_assert (29, 24, 0x0E);
3581 NYI_assert (21, 21, 1);
3582 NYI_assert (15, 10, 0x21);
3584 switch (uimm (aarch64_get_instr (cpu), 23, 22))
3587 for (i = 0; i < (full ? 16 : 8); i++)
3588 aarch64_set_vec_u8 (cpu, vd, i, aarch64_get_vec_u8 (cpu, vn, i)
3589 + aarch64_get_vec_u8 (cpu, vm, i));
3593 for (i = 0; i < (full ? 8 : 4); i++)
3594 aarch64_set_vec_u16 (cpu, vd, i, aarch64_get_vec_u16 (cpu, vn, i)
3595 + aarch64_get_vec_u16 (cpu, vm, i));
3599 for (i = 0; i < (full ? 4 : 2); i++)
3600 aarch64_set_vec_u32 (cpu, vd, i, aarch64_get_vec_u32 (cpu, vn, i)
3601 + aarch64_get_vec_u32 (cpu, vm, i));
3607 aarch64_set_vec_u64 (cpu, vd, 0, aarch64_get_vec_u64 (cpu, vn, 0)
3608 + aarch64_get_vec_u64 (cpu, vm, 0));
3609 aarch64_set_vec_u64 (cpu, vd, 1,
3610 aarch64_get_vec_u64 (cpu, vn, 1)
3611 + aarch64_get_vec_u64 (cpu, vm, 1));
3620 do_vec_mul (sim_cpu *cpu)
3623 instr[30] = full/half selector
3624 instr[29,24] = 00 1110
3625 instr[23,22] = size: 00=> 8-bit, 01=> 16-bit, 10=> 32-bit
3628 instr[15,10] = 10 0111
3632 unsigned vm = uimm (aarch64_get_instr (cpu), 20, 16);
3633 unsigned vn = uimm (aarch64_get_instr (cpu), 9, 5);
3634 unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
3636 int full = uimm (aarch64_get_instr (cpu), 30, 30);
3638 NYI_assert (29, 24, 0x0E);
3639 NYI_assert (21, 21, 1);
3640 NYI_assert (15, 10, 0x27);
3642 switch (uimm (aarch64_get_instr (cpu), 23, 22))
3645 for (i = 0; i < (full ? 16 : 8); i++)
3647 uint16_t val = aarch64_get_vec_u8 (cpu, vn, i);
3648 val *= aarch64_get_vec_u8 (cpu, vm, i);
3650 aarch64_set_vec_u16 (cpu, vd, i, val);
3655 for (i = 0; i < (full ? 8 : 4); i++)
3657 uint32_t val = aarch64_get_vec_u16 (cpu, vn, i);
3658 val *= aarch64_get_vec_u16 (cpu, vm, i);
3660 aarch64_set_vec_u32 (cpu, vd, i, val);
3665 for (i = 0; i < (full ? 4 : 2); i++)
3667 uint64_t val = aarch64_get_vec_u32 (cpu, vn, i);
3668 val *= aarch64_get_vec_u32 (cpu, vm, i);
3670 aarch64_set_vec_u64 (cpu, vd, i, val);
3681 do_vec_MLA (sim_cpu *cpu)
3684 instr[30] = full/half selector
3685 instr[29,24] = 00 1110
3686 instr[23,22] = size: 00=> 8-bit, 01=> 16-bit, 10=> 32-bit
3689 instr[15,10] = 1001 01
3693 unsigned vm = uimm (aarch64_get_instr (cpu), 20, 16);
3694 unsigned vn = uimm (aarch64_get_instr (cpu), 9, 5);
3695 unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
3697 int full = uimm (aarch64_get_instr (cpu), 30, 30);
3699 NYI_assert (29, 24, 0x0E);
3700 NYI_assert (21, 21, 1);
3701 NYI_assert (15, 10, 0x25);
3703 switch (uimm (aarch64_get_instr (cpu), 23, 22))
3706 for (i = 0; i < (full ? 16 : 8); i++)
3708 uint16_t val = aarch64_get_vec_u8 (cpu, vn, i);
3709 val *= aarch64_get_vec_u8 (cpu, vm, i);
3710 val += aarch64_get_vec_u8 (cpu, vd, i);
3712 aarch64_set_vec_u16 (cpu, vd, i, val);
3717 for (i = 0; i < (full ? 8 : 4); i++)
3719 uint32_t val = aarch64_get_vec_u16 (cpu, vn, i);
3720 val *= aarch64_get_vec_u16 (cpu, vm, i);
3721 val += aarch64_get_vec_u16 (cpu, vd, i);
3723 aarch64_set_vec_u32 (cpu, vd, i, val);
3728 for (i = 0; i < (full ? 4 : 2); i++)
3730 uint64_t val = aarch64_get_vec_u32 (cpu, vn, i);
3731 val *= aarch64_get_vec_u32 (cpu, vm, i);
3732 val += aarch64_get_vec_u32 (cpu, vd, i);
3734 aarch64_set_vec_u64 (cpu, vd, i, val);
3745 fmaxnm (float a, float b)
3747 if (fpclassify (a) == FP_NORMAL)
3749 if (fpclassify (b) == FP_NORMAL)
3750 return a > b ? a : b;
3753 else if (fpclassify (b) == FP_NORMAL)
3759 fminnm (float a, float b)
3761 if (fpclassify (a) == FP_NORMAL)
3763 if (fpclassify (b) == FP_NORMAL)
3764 return a < b ? a : b;
3767 else if (fpclassify (b) == FP_NORMAL)
3773 dmaxnm (double a, double b)
3775 if (fpclassify (a) == FP_NORMAL)
3777 if (fpclassify (b) == FP_NORMAL)
3778 return a > b ? a : b;
3781 else if (fpclassify (b) == FP_NORMAL)
3787 dminnm (double a, double b)
3789 if (fpclassify (a) == FP_NORMAL)
3791 if (fpclassify (b) == FP_NORMAL)
3792 return a < b ? a : b;
3795 else if (fpclassify (b) == FP_NORMAL)
3801 do_vec_FminmaxNMP (sim_cpu *cpu)
3803 /* aarch64_get_instr (cpu)[31] = 0
3804 aarch64_get_instr (cpu)[30] = half (0)/full (1)
3805 aarch64_get_instr (cpu)[29,24] = 10 1110
3806 aarch64_get_instr (cpu)[23] = max(0)/min(1)
3807 aarch64_get_instr (cpu)[22] = float (0)/double (1)
3808 aarch64_get_instr (cpu)[21] = 1
3809 aarch64_get_instr (cpu)[20,16] = Vn
3810 aarch64_get_instr (cpu)[15,10] = 1100 01
3811 aarch64_get_instr (cpu)[9,5] = Vm
3812 aarch64_get_instr (cpu)[4.0] = Vd. */
3814 unsigned vm = uimm (aarch64_get_instr (cpu), 20, 16);
3815 unsigned vn = uimm (aarch64_get_instr (cpu), 9, 5);
3816 unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
3817 int full = uimm (aarch64_get_instr (cpu), 30, 30);
3819 NYI_assert (29, 24, 0x2E);
3820 NYI_assert (21, 21, 1);
3821 NYI_assert (15, 10, 0x31);
3823 if (uimm (aarch64_get_instr (cpu), 22, 22))
3825 double (* fn)(double, double) = uimm (aarch64_get_instr (cpu), 23, 23)
3830 aarch64_set_vec_double (cpu, vd, 0,
3831 fn (aarch64_get_vec_double (cpu, vn, 0),
3832 aarch64_get_vec_double (cpu, vn, 1)));
3833 aarch64_set_vec_double (cpu, vd, 0,
3834 fn (aarch64_get_vec_double (cpu, vm, 0),
3835 aarch64_get_vec_double (cpu, vm, 1)));
3839 float (* fn)(float, float) = uimm (aarch64_get_instr (cpu), 23, 23)
3842 aarch64_set_vec_float (cpu, vd, 0,
3843 fn (aarch64_get_vec_float (cpu, vn, 0),
3844 aarch64_get_vec_float (cpu, vn, 1)));
3846 aarch64_set_vec_float (cpu, vd, 1,
3847 fn (aarch64_get_vec_float (cpu, vn, 2),
3848 aarch64_get_vec_float (cpu, vn, 3)));
3850 aarch64_set_vec_float (cpu, vd, (full ? 2 : 1),
3851 fn (aarch64_get_vec_float (cpu, vm, 0),
3852 aarch64_get_vec_float (cpu, vm, 1)));
3854 aarch64_set_vec_float (cpu, vd, 3,
3855 fn (aarch64_get_vec_float (cpu, vm, 2),
3856 aarch64_get_vec_float (cpu, vm, 3)));
3861 do_vec_AND (sim_cpu *cpu)
3864 instr[30] = half (0)/full (1)
3865 instr[29,21] = 001110001
3867 instr[15,10] = 000111
3871 unsigned vm = uimm (aarch64_get_instr (cpu), 20, 16);
3872 unsigned vn = uimm (aarch64_get_instr (cpu), 9, 5);
3873 unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
3875 int full = uimm (aarch64_get_instr (cpu), 30, 30);
3877 NYI_assert (29, 21, 0x071);
3878 NYI_assert (15, 10, 0x07);
3880 for (i = 0; i < (full ? 4 : 2); i++)
3881 aarch64_set_vec_u32 (cpu, vd, i,
3882 aarch64_get_vec_u32 (cpu, vn, i)
3883 & aarch64_get_vec_u32 (cpu, vm, i));
3887 do_vec_BSL (sim_cpu *cpu)
3890 instr[30] = half (0)/full (1)
3891 instr[29,21] = 101110011
3893 instr[15,10] = 000111
3897 unsigned vm = uimm (aarch64_get_instr (cpu), 20, 16);
3898 unsigned vn = uimm (aarch64_get_instr (cpu), 9, 5);
3899 unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
3901 int full = uimm (aarch64_get_instr (cpu), 30, 30);
3903 NYI_assert (29, 21, 0x173);
3904 NYI_assert (15, 10, 0x07);
3906 for (i = 0; i < (full ? 16 : 8); i++)
3907 aarch64_set_vec_u8 (cpu, vd, i,
3908 ( aarch64_get_vec_u8 (cpu, vd, i)
3909 & aarch64_get_vec_u8 (cpu, vn, i))
3910 | ((~ aarch64_get_vec_u8 (cpu, vd, i))
3911 & aarch64_get_vec_u8 (cpu, vm, i)));
3915 do_vec_EOR (sim_cpu *cpu)
3918 instr[30] = half (0)/full (1)
3919 instr[29,21] = 10 1110 001
3921 instr[15,10] = 000111
3925 unsigned vm = uimm (aarch64_get_instr (cpu), 20, 16);
3926 unsigned vn = uimm (aarch64_get_instr (cpu), 9, 5);
3927 unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
3929 int full = uimm (aarch64_get_instr (cpu), 30, 30);
3931 NYI_assert (29, 21, 0x171);
3932 NYI_assert (15, 10, 0x07);
3934 for (i = 0; i < (full ? 4 : 2); i++)
3935 aarch64_set_vec_u32 (cpu, vd, i,
3936 aarch64_get_vec_u32 (cpu, vn, i)
3937 ^ aarch64_get_vec_u32 (cpu, vm, i));
3941 do_vec_bit (sim_cpu *cpu)
3944 instr[30] = half (0)/full (1)
3945 instr[29,23] = 10 1110 1
3946 instr[22] = BIT (0) / BIF (1)
3949 instr[15,10] = 0001 11
3953 unsigned vm = uimm (aarch64_get_instr (cpu), 20, 16);
3954 unsigned vn = uimm (aarch64_get_instr (cpu), 9, 5);
3955 unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
3956 unsigned full = uimm (aarch64_get_instr (cpu), 30, 30);
3957 unsigned test_false = uimm (aarch64_get_instr (cpu), 22, 22);
3960 NYI_assert (29, 23, 0x5D);
3961 NYI_assert (21, 21, 1);
3962 NYI_assert (15, 10, 0x07);
3966 for (i = 0; i < (full ? 16 : 8); i++)
3967 if (aarch64_get_vec_u32 (cpu, vn, i) == 0)
3968 aarch64_set_vec_u32 (cpu, vd, i, aarch64_get_vec_u32 (cpu, vm, i));
3972 for (i = 0; i < (full ? 16 : 8); i++)
3973 if (aarch64_get_vec_u32 (cpu, vn, i) != 0)
3974 aarch64_set_vec_u32 (cpu, vd, i, aarch64_get_vec_u32 (cpu, vm, i));
3979 do_vec_ORN (sim_cpu *cpu)
3982 instr[30] = half (0)/full (1)
3983 instr[29,21] = 00 1110 111
3985 instr[15,10] = 00 0111
3989 unsigned vm = uimm (aarch64_get_instr (cpu), 20, 16);
3990 unsigned vn = uimm (aarch64_get_instr (cpu), 9, 5);
3991 unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
3993 int full = uimm (aarch64_get_instr (cpu), 30, 30);
3995 NYI_assert (29, 21, 0x077);
3996 NYI_assert (15, 10, 0x07);
3998 for (i = 0; i < (full ? 16 : 8); i++)
3999 aarch64_set_vec_u8 (cpu, vd, i,
4000 aarch64_get_vec_u8 (cpu, vn, i)
4001 | ~ aarch64_get_vec_u8 (cpu, vm, i));
4005 do_vec_ORR (sim_cpu *cpu)
4008 instr[30] = half (0)/full (1)
4009 instr[29,21] = 00 1110 101
4011 instr[15,10] = 0001 11
4015 unsigned vm = uimm (aarch64_get_instr (cpu), 20, 16);
4016 unsigned vn = uimm (aarch64_get_instr (cpu), 9, 5);
4017 unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
4019 int full = uimm (aarch64_get_instr (cpu), 30, 30);
4021 NYI_assert (29, 21, 0x075);
4022 NYI_assert (15, 10, 0x07);
4024 for (i = 0; i < (full ? 16 : 8); i++)
4025 aarch64_set_vec_u8 (cpu, vd, i,
4026 aarch64_get_vec_u8 (cpu, vn, i)
4027 | aarch64_get_vec_u8 (cpu, vm, i));
4031 do_vec_BIC (sim_cpu *cpu)
4034 instr[30] = half (0)/full (1)
4035 instr[29,21] = 00 1110 011
4037 instr[15,10] = 00 0111
4041 unsigned vm = uimm (aarch64_get_instr (cpu), 20, 16);
4042 unsigned vn = uimm (aarch64_get_instr (cpu), 9, 5);
4043 unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
4045 int full = uimm (aarch64_get_instr (cpu), 30, 30);
4047 NYI_assert (29, 21, 0x073);
4048 NYI_assert (15, 10, 0x07);
4050 for (i = 0; i < (full ? 16 : 8); i++)
4051 aarch64_set_vec_u8 (cpu, vd, i,
4052 aarch64_get_vec_u8 (cpu, vn, i)
4053 & ~ aarch64_get_vec_u8 (cpu, vm, i));
4057 do_vec_XTN (sim_cpu *cpu)
4060 instr[30] = first part (0)/ second part (1)
4061 instr[29,24] = 00 1110
4062 instr[23,22] = size: byte(00), half(01), word (10)
4063 instr[21,10] = 1000 0100 1010
4067 unsigned vs = uimm (aarch64_get_instr (cpu), 9, 5);
4068 unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
4069 unsigned bias = uimm (aarch64_get_instr (cpu), 30, 30);
4072 NYI_assert (29, 24, 0x0E);
4073 NYI_assert (21, 10, 0x84A);
4075 switch (uimm (aarch64_get_instr (cpu), 23, 22))
4079 for (i = 0; i < 8; i++)
4080 aarch64_set_vec_u8 (cpu, vd, i + 8,
4081 aarch64_get_vec_u16 (cpu, vs, i) >> 8);
4083 for (i = 0; i < 8; i++)
4084 aarch64_set_vec_u8 (cpu, vd, i, aarch64_get_vec_u16 (cpu, vs, i));
4089 for (i = 0; i < 4; i++)
4090 aarch64_set_vec_u16 (cpu, vd, i + 4,
4091 aarch64_get_vec_u32 (cpu, vs, i) >> 16);
4093 for (i = 0; i < 4; i++)
4094 aarch64_set_vec_u16 (cpu, vd, i, aarch64_get_vec_u32 (cpu, vs, i));
4099 for (i = 0; i < 2; i++)
4100 aarch64_set_vec_u32 (cpu, vd, i + 4,
4101 aarch64_get_vec_u64 (cpu, vs, i) >> 32);
4103 for (i = 0; i < 2; i++)
4104 aarch64_set_vec_u32 (cpu, vd, i, aarch64_get_vec_u64 (cpu, vs, i));
4112 #define MAX(A,B) ((A) > (B) ? (A) : (B))
4113 #define MIN(A,B) ((A) < (B) ? (A) : (B))
4116 do_vec_maxv (sim_cpu *cpu)
4119 instr[30] = half(0)/full(1)
4120 instr[29] = signed (0)/unsigned(1)
4121 instr[28,24] = 0 1110
4122 instr[23,22] = size: byte(00), half(01), word (10)
4124 instr[20,17] = 1 000
4125 instr[16] = max(0)/min(1)
4126 instr[15,10] = 1010 10
4127 instr[9,5] = V source
4128 instr[4.0] = R dest. */
4130 unsigned vs = uimm (aarch64_get_instr (cpu), 9, 5);
4131 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
4132 unsigned full = uimm (aarch64_get_instr (cpu), 30, 30);
4135 NYI_assert (28, 24, 0x0E);
4136 NYI_assert (21, 21, 1);
4137 NYI_assert (20, 17, 8);
4138 NYI_assert (15, 10, 0x2A);
4140 switch ((uimm (aarch64_get_instr (cpu), 29, 29) << 1)
4141 | uimm (aarch64_get_instr (cpu), 16, 16))
4143 case 0: /* SMAXV. */
4146 switch (uimm (aarch64_get_instr (cpu), 23, 22))
4149 smax = aarch64_get_vec_s8 (cpu, vs, 0);
4150 for (i = 1; i < (full ? 16 : 8); i++)
4151 smax = MAX (smax, aarch64_get_vec_s8 (cpu, vs, i));
4154 smax = aarch64_get_vec_s16 (cpu, vs, 0);
4155 for (i = 1; i < (full ? 8 : 4); i++)
4156 smax = MAX (smax, aarch64_get_vec_s16 (cpu, vs, i));
4159 smax = aarch64_get_vec_s32 (cpu, vs, 0);
4160 for (i = 1; i < (full ? 4 : 2); i++)
4161 smax = MAX (smax, aarch64_get_vec_s32 (cpu, vs, i));
4167 aarch64_set_reg_s64 (cpu, rd, NO_SP, smax);
4171 case 1: /* SMINV. */
4174 switch (uimm (aarch64_get_instr (cpu), 23, 22))
4177 smin = aarch64_get_vec_s8 (cpu, vs, 0);
4178 for (i = 1; i < (full ? 16 : 8); i++)
4179 smin = MIN (smin, aarch64_get_vec_s8 (cpu, vs, i));
4182 smin = aarch64_get_vec_s16 (cpu, vs, 0);
4183 for (i = 1; i < (full ? 8 : 4); i++)
4184 smin = MIN (smin, aarch64_get_vec_s16 (cpu, vs, i));
4187 smin = aarch64_get_vec_s32 (cpu, vs, 0);
4188 for (i = 1; i < (full ? 4 : 2); i++)
4189 smin = MIN (smin, aarch64_get_vec_s32 (cpu, vs, i));
4195 aarch64_set_reg_s64 (cpu, rd, NO_SP, smin);
4199 case 2: /* UMAXV. */
4202 switch (uimm (aarch64_get_instr (cpu), 23, 22))
4205 umax = aarch64_get_vec_u8 (cpu, vs, 0);
4206 for (i = 1; i < (full ? 16 : 8); i++)
4207 umax = MAX (umax, aarch64_get_vec_u8 (cpu, vs, i));
4210 umax = aarch64_get_vec_u16 (cpu, vs, 0);
4211 for (i = 1; i < (full ? 8 : 4); i++)
4212 umax = MAX (umax, aarch64_get_vec_u16 (cpu, vs, i));
4215 umax = aarch64_get_vec_u32 (cpu, vs, 0);
4216 for (i = 1; i < (full ? 4 : 2); i++)
4217 umax = MAX (umax, aarch64_get_vec_u32 (cpu, vs, i));
4223 aarch64_set_reg_u64 (cpu, rd, NO_SP, umax);
4227 case 3: /* UMINV. */
4230 switch (uimm (aarch64_get_instr (cpu), 23, 22))
4233 umin = aarch64_get_vec_u8 (cpu, vs, 0);
4234 for (i = 1; i < (full ? 16 : 8); i++)
4235 umin = MIN (umin, aarch64_get_vec_u8 (cpu, vs, i));
4238 umin = aarch64_get_vec_u16 (cpu, vs, 0);
4239 for (i = 1; i < (full ? 8 : 4); i++)
4240 umin = MIN (umin, aarch64_get_vec_u16 (cpu, vs, i));
4243 umin = aarch64_get_vec_u32 (cpu, vs, 0);
4244 for (i = 1; i < (full ? 4 : 2); i++)
4245 umin = MIN (umin, aarch64_get_vec_u32 (cpu, vs, i));
4251 aarch64_set_reg_u64 (cpu, rd, NO_SP, umin);
4261 do_vec_fminmaxV (sim_cpu *cpu)
4263 /* instr[31,24] = 0110 1110
4264 instr[23] = max(0)/min(1)
4265 instr[22,14] = 011 0000 11
4266 instr[13,12] = nm(00)/normal(11)
4268 instr[9,5] = V source
4269 instr[4.0] = R dest. */
4271 unsigned vs = uimm (aarch64_get_instr (cpu), 9, 5);
4272 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
4274 float res = aarch64_get_vec_float (cpu, vs, 0);
4276 NYI_assert (31, 24, 0x6E);
4277 NYI_assert (22, 14, 0x0C3);
4278 NYI_assert (11, 10, 2);
4280 if (uimm (aarch64_get_instr (cpu), 23, 23))
4282 switch (uimm (aarch64_get_instr (cpu), 13, 12))
4284 case 0: /* FMNINNMV. */
4285 for (i = 1; i < 4; i++)
4286 res = fminnm (res, aarch64_get_vec_float (cpu, vs, i));
4289 case 3: /* FMINV. */
4290 for (i = 1; i < 4; i++)
4291 res = MIN (res, aarch64_get_vec_float (cpu, vs, i));
4300 switch (uimm (aarch64_get_instr (cpu), 13, 12))
4302 case 0: /* FMNAXNMV. */
4303 for (i = 1; i < 4; i++)
4304 res = fmaxnm (res, aarch64_get_vec_float (cpu, vs, i));
4307 case 3: /* FMAXV. */
4308 for (i = 1; i < 4; i++)
4309 res = MAX (res, aarch64_get_vec_float (cpu, vs, i));
4317 aarch64_set_FP_float (cpu, rd, res);
4321 do_vec_Fminmax (sim_cpu *cpu)
4324 instr[30] = half(0)/full(1)
4325 instr[29,24] = 00 1110
4326 instr[23] = max(0)/min(1)
4327 instr[22] = float(0)/double(1)
4331 instr[13,12] = nm(00)/normal(11)
4336 unsigned vm = uimm (aarch64_get_instr (cpu), 20, 16);
4337 unsigned vn = uimm (aarch64_get_instr (cpu), 9, 5);
4338 unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
4339 unsigned full = uimm (aarch64_get_instr (cpu), 30, 30);
4340 unsigned min = uimm (aarch64_get_instr (cpu), 23, 23);
4343 NYI_assert (29, 24, 0x0E);
4344 NYI_assert (21, 21, 1);
4345 NYI_assert (15, 14, 3);
4346 NYI_assert (11, 10, 1);
4348 if (uimm (aarch64_get_instr (cpu), 22, 22))
4350 double (* func)(double, double);
4355 if (uimm (aarch64_get_instr (cpu), 13, 12) == 0)
4356 func = min ? dminnm : dmaxnm;
4357 else if (uimm (aarch64_get_instr (cpu), 13, 12) == 3)
4358 func = min ? fmin : fmax;
4362 for (i = 0; i < 2; i++)
4363 aarch64_set_vec_double (cpu, vd, i,
4364 func (aarch64_get_vec_double (cpu, vn, i),
4365 aarch64_get_vec_double (cpu, vm, i)));
4369 float (* func)(float, float);
4371 if (uimm (aarch64_get_instr (cpu), 13, 12) == 0)
4372 func = min ? fminnm : fmaxnm;
4373 else if (uimm (aarch64_get_instr (cpu), 13, 12) == 3)
4374 func = min ? fminf : fmaxf;
4378 for (i = 0; i < (full ? 4 : 2); i++)
4379 aarch64_set_vec_float (cpu, vd, i,
4380 func (aarch64_get_vec_float (cpu, vn, i),
4381 aarch64_get_vec_float (cpu, vm, i)));
4386 do_vec_SCVTF (sim_cpu *cpu)
4390 instr[29,23] = 00 1110 0
4391 instr[22] = float(0)/double(1)
4392 instr[21,10] = 10 0001 1101 10
4396 unsigned vn = uimm (aarch64_get_instr (cpu), 9, 5);
4397 unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
4398 unsigned full = uimm (aarch64_get_instr (cpu), 30, 30);
4399 unsigned size = uimm (aarch64_get_instr (cpu), 22, 22);
4402 NYI_assert (29, 23, 0x1C);
4403 NYI_assert (21, 10, 0x876);
4410 for (i = 0; i < 2; i++)
4412 double val = (double) aarch64_get_vec_u64 (cpu, vn, i);
4413 aarch64_set_vec_double (cpu, vd, i, val);
4418 for (i = 0; i < (full ? 4 : 2); i++)
4420 float val = (float) aarch64_get_vec_u32 (cpu, vn, i);
4421 aarch64_set_vec_float (cpu, vd, i, val);
4426 #define VEC_CMP(SOURCE, CMP) \
4432 for (i = 0; i < (full ? 16 : 8); i++) \
4433 aarch64_set_vec_u8 (cpu, vd, i, \
4434 aarch64_get_vec_##SOURCE##8 (cpu, vn, i) \
4436 aarch64_get_vec_##SOURCE##8 (cpu, vm, i) \
4440 for (i = 0; i < (full ? 8 : 4); i++) \
4441 aarch64_set_vec_u16 (cpu, vd, i, \
4442 aarch64_get_vec_##SOURCE##16 (cpu, vn, i) \
4444 aarch64_get_vec_##SOURCE##16 (cpu, vm, i) \
4448 for (i = 0; i < (full ? 4 : 2); i++) \
4449 aarch64_set_vec_u32 (cpu, vd, i, \
4450 aarch64_get_vec_##SOURCE##32 (cpu, vn, i) \
4452 aarch64_get_vec_##SOURCE##32 (cpu, vm, i) \
4458 for (i = 0; i < 2; i++) \
4459 aarch64_set_vec_u64 (cpu, vd, i, \
4460 aarch64_get_vec_##SOURCE##64 (cpu, vn, i) \
4462 aarch64_get_vec_##SOURCE##64 (cpu, vm, i) \
4471 #define VEC_CMP0(SOURCE, CMP) \
4477 for (i = 0; i < (full ? 16 : 8); i++) \
4478 aarch64_set_vec_u8 (cpu, vd, i, \
4479 aarch64_get_vec_##SOURCE##8 (cpu, vn, i) \
4483 for (i = 0; i < (full ? 8 : 4); i++) \
4484 aarch64_set_vec_u16 (cpu, vd, i, \
4485 aarch64_get_vec_##SOURCE##16 (cpu, vn, i) \
4489 for (i = 0; i < (full ? 4 : 2); i++) \
4490 aarch64_set_vec_u32 (cpu, vd, i, \
4491 aarch64_get_vec_##SOURCE##32 (cpu, vn, i) \
4497 for (i = 0; i < 2; i++) \
4498 aarch64_set_vec_u64 (cpu, vd, i, \
4499 aarch64_get_vec_##SOURCE##64 (cpu, vn, i) \
4500 CMP 0 ? -1ULL : 0); \
4508 #define VEC_FCMP0(CMP) \
4513 if (uimm (aarch64_get_instr (cpu), 22, 22)) \
4517 for (i = 0; i < 2; i++) \
4518 aarch64_set_vec_u64 (cpu, vd, i, \
4519 aarch64_get_vec_double (cpu, vn, i) \
4520 CMP 0.0 ? -1 : 0); \
4524 for (i = 0; i < (full ? 4 : 2); i++) \
4525 aarch64_set_vec_u32 (cpu, vd, i, \
4526 aarch64_get_vec_float (cpu, vn, i) \
4527 CMP 0.0 ? -1 : 0); \
4533 #define VEC_FCMP(CMP) \
4536 if (uimm (aarch64_get_instr (cpu), 22, 22)) \
4540 for (i = 0; i < 2; i++) \
4541 aarch64_set_vec_u64 (cpu, vd, i, \
4542 aarch64_get_vec_double (cpu, vn, i) \
4544 aarch64_get_vec_double (cpu, vm, i) \
4549 for (i = 0; i < (full ? 4 : 2); i++) \
4550 aarch64_set_vec_u32 (cpu, vd, i, \
4551 aarch64_get_vec_float (cpu, vn, i) \
4553 aarch64_get_vec_float (cpu, vm, i) \
4561 do_vec_compare (sim_cpu *cpu)
4564 instr[30] = half(0)/full(1)
4565 instr[29] = part-of-comparison-type
4566 instr[28,24] = 0 1110
4567 instr[23,22] = size of integer compares: byte(00), half(01), word (10), long (11)
4568 type of float compares: single (-0) / double (-1)
4570 instr[20,16] = Vm or 00000 (compare vs 0)
4571 instr[15,10] = part-of-comparison-type
4575 int full = uimm (aarch64_get_instr (cpu), 30, 30);
4576 int size = uimm (aarch64_get_instr (cpu), 23, 22);
4577 unsigned vm = uimm (aarch64_get_instr (cpu), 20, 16);
4578 unsigned vn = uimm (aarch64_get_instr (cpu), 9, 5);
4579 unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
4582 NYI_assert (28, 24, 0x0E);
4583 NYI_assert (21, 21, 1);
4585 if ((uimm (aarch64_get_instr (cpu), 11, 11)
4586 && uimm (aarch64_get_instr (cpu), 14, 14))
4587 || ((uimm (aarch64_get_instr (cpu), 11, 11) == 0
4588 && uimm (aarch64_get_instr (cpu), 10, 10) == 0)))
4590 /* A compare vs 0. */
4593 if (uimm (aarch64_get_instr (cpu), 15, 10) == 0x2A)
4595 else if (uimm (aarch64_get_instr (cpu), 15, 10) == 0x32
4596 || uimm (aarch64_get_instr (cpu), 15, 10) == 0x3E)
4597 do_vec_fminmaxV (cpu);
4598 else if (uimm (aarch64_get_instr (cpu), 29, 23) == 0x1C
4599 && uimm (aarch64_get_instr (cpu), 21, 10) == 0x876)
4607 if (uimm (aarch64_get_instr (cpu), 14, 14))
4609 /* A floating point compare. */
4610 unsigned decode = (uimm (aarch64_get_instr (cpu), 29, 29) << 5)
4611 | (uimm (aarch64_get_instr (cpu), 23, 23) << 4)
4612 | uimm (aarch64_get_instr (cpu), 13, 10);
4614 NYI_assert (15, 15, 1);
4618 case /* 0b010010: GT#0 */ 0x12: VEC_FCMP0 (>);
4619 case /* 0b110010: GE#0 */ 0x32: VEC_FCMP0 (>=);
4620 case /* 0b010110: EQ#0 */ 0x16: VEC_FCMP0 (==);
4621 case /* 0b110110: LE#0 */ 0x36: VEC_FCMP0 (<=);
4622 case /* 0b011010: LT#0 */ 0x1A: VEC_FCMP0 (<);
4623 case /* 0b111001: GT */ 0x39: VEC_FCMP (>);
4624 case /* 0b101001: GE */ 0x29: VEC_FCMP (>=);
4625 case /* 0b001001: EQ */ 0x09: VEC_FCMP (==);
4633 unsigned decode = (uimm (aarch64_get_instr (cpu), 29, 29) << 6)
4634 | uimm (aarch64_get_instr (cpu), 15, 10);
4638 case 0x0D: /* 0001101 GT */ VEC_CMP (s, > );
4639 case 0x0F: /* 0001111 GE */ VEC_CMP (s, >= );
4640 case 0x22: /* 0100010 GT #0 */ VEC_CMP0 (s, > );
4641 case 0x26: /* 0100110 EQ #0 */ VEC_CMP0 (s, == );
4642 case 0x2A: /* 0101010 LT #0 */ VEC_CMP0 (s, < );
4643 case 0x4D: /* 1001101 HI */ VEC_CMP (u, > );
4644 case 0x4F: /* 1001111 HS */ VEC_CMP (u, >= );
4645 case 0x62: /* 1100010 GE #0 */ VEC_CMP0 (s, >= );
4646 case 0x63: /* 1100011 EQ */ VEC_CMP (u, == );
4647 case 0x66: /* 1100110 LE #0 */ VEC_CMP0 (s, <= );
4657 do_vec_SSHL (sim_cpu *cpu)
4660 instr[30] = first part (0)/ second part (1)
4661 instr[29,24] = 00 1110
4662 instr[23,22] = size: byte(00), half(01), word (10), long (11)
4665 instr[15,10] = 0100 01
4669 unsigned full = uimm (aarch64_get_instr (cpu), 30, 30);
4670 unsigned vm = uimm (aarch64_get_instr (cpu), 20, 16);
4671 unsigned vn = uimm (aarch64_get_instr (cpu), 9, 5);
4672 unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
4675 NYI_assert (29, 24, 0x0E);
4676 NYI_assert (21, 21, 1);
4677 NYI_assert (15, 10, 0x11);
4679 /* FIXME: What is a signed shift left in this context ?. */
4681 switch (uimm (aarch64_get_instr (cpu), 23, 22))
4684 for (i = 0; i < (full ? 16 : 8); i++)
4685 aarch64_set_vec_s8 (cpu, vd, i, aarch64_get_vec_s8 (cpu, vn, i)
4686 << aarch64_get_vec_s8 (cpu, vm, i));
4690 for (i = 0; i < (full ? 8 : 4); i++)
4691 aarch64_set_vec_s16 (cpu, vd, i, aarch64_get_vec_s16 (cpu, vn, i)
4692 << aarch64_get_vec_s16 (cpu, vm, i));
4696 for (i = 0; i < (full ? 4 : 2); i++)
4697 aarch64_set_vec_s32 (cpu, vd, i, aarch64_get_vec_s32 (cpu, vn, i)
4698 << aarch64_get_vec_s32 (cpu, vm, i));
4704 for (i = 0; i < 2; i++)
4705 aarch64_set_vec_s64 (cpu, vd, i, aarch64_get_vec_s64 (cpu, vn, i)
4706 << aarch64_get_vec_s64 (cpu, vm, i));
4715 do_vec_USHL (sim_cpu *cpu)
4718 instr[30] = first part (0)/ second part (1)
4719 instr[29,24] = 10 1110
4720 instr[23,22] = size: byte(00), half(01), word (10), long (11)
4723 instr[15,10] = 0100 01
4727 unsigned full = uimm (aarch64_get_instr (cpu), 30, 30);
4728 unsigned vm = uimm (aarch64_get_instr (cpu), 20, 16);
4729 unsigned vn = uimm (aarch64_get_instr (cpu), 9, 5);
4730 unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
4733 NYI_assert (29, 24, 0x2E);
4734 NYI_assert (15, 10, 0x11);
4736 switch (uimm (aarch64_get_instr (cpu), 23, 22))
4739 for (i = 0; i < (full ? 16 : 8); i++)
4740 aarch64_set_vec_u8 (cpu, vd, i, aarch64_get_vec_u8 (cpu, vn, i)
4741 << aarch64_get_vec_u8 (cpu, vm, i));
4745 for (i = 0; i < (full ? 8 : 4); i++)
4746 aarch64_set_vec_u16 (cpu, vd, i, aarch64_get_vec_u16 (cpu, vn, i)
4747 << aarch64_get_vec_u16 (cpu, vm, i));
4751 for (i = 0; i < (full ? 4 : 2); i++)
4752 aarch64_set_vec_u32 (cpu, vd, i, aarch64_get_vec_u32 (cpu, vn, i)
4753 << aarch64_get_vec_u32 (cpu, vm, i));
4759 for (i = 0; i < 2; i++)
4760 aarch64_set_vec_u64 (cpu, vd, i, aarch64_get_vec_u64 (cpu, vn, i)
4761 << aarch64_get_vec_u64 (cpu, vm, i));
4770 do_vec_FMLA (sim_cpu *cpu)
4773 instr[30] = full/half selector
4774 instr[29,23] = 0011100
4775 instr[22] = size: 0=>float, 1=>double
4778 instr[15,10] = 1100 11
4782 unsigned vm = uimm (aarch64_get_instr (cpu), 20, 16);
4783 unsigned vn = uimm (aarch64_get_instr (cpu), 9, 5);
4784 unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
4786 int full = uimm (aarch64_get_instr (cpu), 30, 30);
4788 NYI_assert (29, 23, 0x1C);
4789 NYI_assert (21, 21, 1);
4790 NYI_assert (15, 10, 0x33);
4792 if (uimm (aarch64_get_instr (cpu), 22, 22))
4796 for (i = 0; i < 2; i++)
4797 aarch64_set_vec_double (cpu, vd, i,
4798 aarch64_get_vec_double (cpu, vn, i) *
4799 aarch64_get_vec_double (cpu, vm, i) +
4800 aarch64_get_vec_double (cpu, vd, i));
4804 for (i = 0; i < (full ? 4 : 2); i++)
4805 aarch64_set_vec_float (cpu, vd, i,
4806 aarch64_get_vec_float (cpu, vn, i) *
4807 aarch64_get_vec_float (cpu, vm, i) +
4808 aarch64_get_vec_float (cpu, vd, i));
4813 do_vec_max (sim_cpu *cpu)
4816 instr[30] = full/half selector
4817 instr[29] = SMAX (0) / UMAX (1)
4818 instr[28,24] = 0 1110
4819 instr[23,22] = size: 00=> 8-bit, 01=> 16-bit, 10=> 32-bit
4822 instr[15,10] = 0110 01
4826 unsigned vm = uimm (aarch64_get_instr (cpu), 20, 16);
4827 unsigned vn = uimm (aarch64_get_instr (cpu), 9, 5);
4828 unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
4830 int full = uimm (aarch64_get_instr (cpu), 30, 30);
4832 NYI_assert (28, 24, 0x0E);
4833 NYI_assert (21, 21, 1);
4834 NYI_assert (15, 10, 0x19);
4836 if (uimm (aarch64_get_instr (cpu), 29, 29))
4838 switch (uimm (aarch64_get_instr (cpu), 23, 22))
4841 for (i = 0; i < (full ? 16 : 8); i++)
4842 aarch64_set_vec_u8 (cpu, vd, i,
4843 aarch64_get_vec_u8 (cpu, vn, i)
4844 > aarch64_get_vec_u8 (cpu, vm, i)
4845 ? aarch64_get_vec_u8 (cpu, vn, i)
4846 : aarch64_get_vec_u8 (cpu, vm, i));
4850 for (i = 0; i < (full ? 8 : 4); i++)
4851 aarch64_set_vec_u16 (cpu, vd, i,
4852 aarch64_get_vec_u16 (cpu, vn, i)
4853 > aarch64_get_vec_u16 (cpu, vm, i)
4854 ? aarch64_get_vec_u16 (cpu, vn, i)
4855 : aarch64_get_vec_u16 (cpu, vm, i));
4859 for (i = 0; i < (full ? 4 : 2); i++)
4860 aarch64_set_vec_u32 (cpu, vd, i,
4861 aarch64_get_vec_u32 (cpu, vn, i)
4862 > aarch64_get_vec_u32 (cpu, vm, i)
4863 ? aarch64_get_vec_u32 (cpu, vn, i)
4864 : aarch64_get_vec_u32 (cpu, vm, i));
4874 switch (uimm (aarch64_get_instr (cpu), 23, 22))
4877 for (i = 0; i < (full ? 16 : 8); i++)
4878 aarch64_set_vec_s8 (cpu, vd, i,
4879 aarch64_get_vec_s8 (cpu, vn, i)
4880 > aarch64_get_vec_s8 (cpu, vm, i)
4881 ? aarch64_get_vec_s8 (cpu, vn, i)
4882 : aarch64_get_vec_s8 (cpu, vm, i));
4886 for (i = 0; i < (full ? 8 : 4); i++)
4887 aarch64_set_vec_s16 (cpu, vd, i,
4888 aarch64_get_vec_s16 (cpu, vn, i)
4889 > aarch64_get_vec_s16 (cpu, vm, i)
4890 ? aarch64_get_vec_s16 (cpu, vn, i)
4891 : aarch64_get_vec_s16 (cpu, vm, i));
4895 for (i = 0; i < (full ? 4 : 2); i++)
4896 aarch64_set_vec_s32 (cpu, vd, i,
4897 aarch64_get_vec_s32 (cpu, vn, i)
4898 > aarch64_get_vec_s32 (cpu, vm, i)
4899 ? aarch64_get_vec_s32 (cpu, vn, i)
4900 : aarch64_get_vec_s32 (cpu, vm, i));
4911 do_vec_min (sim_cpu *cpu)
4914 instr[30] = full/half selector
4915 instr[29] = SMIN (0) / UMIN (1)
4916 instr[28,24] = 0 1110
4917 instr[23,22] = size: 00=> 8-bit, 01=> 16-bit, 10=> 32-bit
4920 instr[15,10] = 0110 11
4924 unsigned vm = uimm (aarch64_get_instr (cpu), 20, 16);
4925 unsigned vn = uimm (aarch64_get_instr (cpu), 9, 5);
4926 unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
4928 int full = uimm (aarch64_get_instr (cpu), 30, 30);
4930 NYI_assert (28, 24, 0x0E);
4931 NYI_assert (21, 21, 1);
4932 NYI_assert (15, 10, 0x1B);
4934 if (uimm (aarch64_get_instr (cpu), 29, 29))
4936 switch (uimm (aarch64_get_instr (cpu), 23, 22))
4939 for (i = 0; i < (full ? 16 : 8); i++)
4940 aarch64_set_vec_u8 (cpu, vd, i,
4941 aarch64_get_vec_u8 (cpu, vn, i)
4942 < aarch64_get_vec_u8 (cpu, vm, i)
4943 ? aarch64_get_vec_u8 (cpu, vn, i)
4944 : aarch64_get_vec_u8 (cpu, vm, i));
4948 for (i = 0; i < (full ? 8 : 4); i++)
4949 aarch64_set_vec_u16 (cpu, vd, i,
4950 aarch64_get_vec_u16 (cpu, vn, i)
4951 < aarch64_get_vec_u16 (cpu, vm, i)
4952 ? aarch64_get_vec_u16 (cpu, vn, i)
4953 : aarch64_get_vec_u16 (cpu, vm, i));
4957 for (i = 0; i < (full ? 4 : 2); i++)
4958 aarch64_set_vec_u32 (cpu, vd, i,
4959 aarch64_get_vec_u32 (cpu, vn, i)
4960 < aarch64_get_vec_u32 (cpu, vm, i)
4961 ? aarch64_get_vec_u32 (cpu, vn, i)
4962 : aarch64_get_vec_u32 (cpu, vm, i));
4972 switch (uimm (aarch64_get_instr (cpu), 23, 22))
4975 for (i = 0; i < (full ? 16 : 8); i++)
4976 aarch64_set_vec_s8 (cpu, vd, i,
4977 aarch64_get_vec_s8 (cpu, vn, i)
4978 < aarch64_get_vec_s8 (cpu, vm, i)
4979 ? aarch64_get_vec_s8 (cpu, vn, i)
4980 : aarch64_get_vec_s8 (cpu, vm, i));
4984 for (i = 0; i < (full ? 8 : 4); i++)
4985 aarch64_set_vec_s16 (cpu, vd, i,
4986 aarch64_get_vec_s16 (cpu, vn, i)
4987 < aarch64_get_vec_s16 (cpu, vm, i)
4988 ? aarch64_get_vec_s16 (cpu, vn, i)
4989 : aarch64_get_vec_s16 (cpu, vm, i));
4993 for (i = 0; i < (full ? 4 : 2); i++)
4994 aarch64_set_vec_s32 (cpu, vd, i,
4995 aarch64_get_vec_s32 (cpu, vn, i)
4996 < aarch64_get_vec_s32 (cpu, vm, i)
4997 ? aarch64_get_vec_s32 (cpu, vn, i)
4998 : aarch64_get_vec_s32 (cpu, vm, i));
5009 do_vec_sub_long (sim_cpu *cpu)
5012 instr[30] = lower (0) / upper (1)
5013 instr[29] = signed (0) / unsigned (1)
5014 instr[28,24] = 0 1110
5015 instr[23,22] = size: bytes (00), half (01), word (10)
5018 instr[15,10] = 0010 00
5020 instr[4,0] = V dest. */
5022 unsigned size = uimm (aarch64_get_instr (cpu), 23, 22);
5023 unsigned vm = uimm (aarch64_get_instr (cpu), 20, 16);
5024 unsigned vn = uimm (aarch64_get_instr (cpu), 9, 5);
5025 unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
5029 NYI_assert (28, 24, 0x0E);
5030 NYI_assert (21, 21, 1);
5031 NYI_assert (15, 10, 0x08);
5036 switch (uimm (aarch64_get_instr (cpu), 30, 29))
5038 case 2: /* SSUBL2. */
5040 case 0: /* SSUBL. */
5045 for (i = 0; i < 8; i++)
5046 aarch64_set_vec_s16 (cpu, vd, i,
5047 aarch64_get_vec_s8 (cpu, vn, i + bias)
5048 - aarch64_get_vec_s8 (cpu, vm, i + bias));
5053 for (i = 0; i < 4; i++)
5054 aarch64_set_vec_s32 (cpu, vd, i,
5055 aarch64_get_vec_s16 (cpu, vn, i + bias)
5056 - aarch64_get_vec_s16 (cpu, vm, i + bias));
5060 for (i = 0; i < 2; i++)
5061 aarch64_set_vec_s64 (cpu, vd, i,
5062 aarch64_get_vec_s32 (cpu, vn, i + bias)
5063 - aarch64_get_vec_s32 (cpu, vm, i + bias));
5071 case 3: /* USUBL2. */
5073 case 1: /* USUBL. */
5078 for (i = 0; i < 8; i++)
5079 aarch64_set_vec_u16 (cpu, vd, i,
5080 aarch64_get_vec_u8 (cpu, vn, i + bias)
5081 - aarch64_get_vec_u8 (cpu, vm, i + bias));
5086 for (i = 0; i < 4; i++)
5087 aarch64_set_vec_u32 (cpu, vd, i,
5088 aarch64_get_vec_u16 (cpu, vn, i + bias)
5089 - aarch64_get_vec_u16 (cpu, vm, i + bias));
5093 for (i = 0; i < 2; i++)
5094 aarch64_set_vec_u64 (cpu, vd, i,
5095 aarch64_get_vec_u32 (cpu, vn, i + bias)
5096 - aarch64_get_vec_u32 (cpu, vm, i + bias));
5106 #define DO_ADDP(FN) \
5109 for (i = 0; i < range; i++) \
5111 aarch64_set_vec_##FN (cpu, vd, i, \
5112 aarch64_get_vec_##FN (cpu, vn, i * 2) \
5113 + aarch64_get_vec_##FN (cpu, vn, i * 2 + 1)); \
5114 aarch64_set_vec_##FN (cpu, vd, i + range, \
5115 aarch64_get_vec_##FN (cpu, vm, i * 2) \
5116 + aarch64_get_vec_##FN (cpu, vm, i * 2 + 1)); \
5122 do_vec_ADDP (sim_cpu *cpu)
5125 instr[30] = half(0)/full(1)
5126 instr[29,24] = 00 1110
5127 instr[23,22] = size: bytes (00), half (01), word (10), long (11)
5130 instr[15,10] = 1011 11
5132 instr[4,0] = V dest. */
5134 unsigned full = uimm (aarch64_get_instr (cpu), 30, 30);
5135 unsigned size = uimm (aarch64_get_instr (cpu), 23, 22);
5136 unsigned vm = uimm (aarch64_get_instr (cpu), 20, 16);
5137 unsigned vn = uimm (aarch64_get_instr (cpu), 9, 5);
5138 unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
5141 NYI_assert (29, 24, 0x0E);
5142 NYI_assert (21, 21, 1);
5143 NYI_assert (15, 10, 0x2F);
5148 range = full ? 8 : 4;
5153 range = full ? 4 : 2;
5158 range = full ? 2 : 1;
5175 do_vec_UMOV (sim_cpu *cpu)
5178 instr[30] = 32-bit(0)/64-bit(1)
5179 instr[29,21] = 00 1110 000
5180 insrt[20,16] = size & index
5181 instr[15,10] = 0011 11
5182 instr[9,5] = V source
5183 instr[4,0] = R dest. */
5185 unsigned vs = uimm (aarch64_get_instr (cpu), 9, 5);
5186 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
5189 NYI_assert (29, 21, 0x070);
5190 NYI_assert (15, 10, 0x0F);
5192 if (uimm (aarch64_get_instr (cpu), 16, 16))
5194 /* Byte transfer. */
5195 index = uimm (aarch64_get_instr (cpu), 20, 17);
5196 aarch64_set_reg_u64 (cpu, rd, NO_SP,
5197 aarch64_get_vec_u8 (cpu, vs, index));
5199 else if (uimm (aarch64_get_instr (cpu), 17, 17))
5201 index = uimm (aarch64_get_instr (cpu), 20, 18);
5202 aarch64_set_reg_u64 (cpu, rd, NO_SP,
5203 aarch64_get_vec_u16 (cpu, vs, index));
5205 else if (uimm (aarch64_get_instr (cpu), 18, 18))
5207 index = uimm (aarch64_get_instr (cpu), 20, 19);
5208 aarch64_set_reg_u64 (cpu, rd, NO_SP,
5209 aarch64_get_vec_u32 (cpu, vs, index));
5213 if (uimm (aarch64_get_instr (cpu), 30, 30) != 1)
5216 index = uimm (aarch64_get_instr (cpu), 20, 20);
5217 aarch64_set_reg_u64 (cpu, rd, NO_SP,
5218 aarch64_get_vec_u64 (cpu, vs, index));
5223 do_vec_FABS (sim_cpu *cpu)
5226 instr[30] = half(0)/full(1)
5227 instr[29,23] = 00 1110 1
5228 instr[22] = float(0)/double(1)
5229 instr[21,16] = 10 0000
5230 instr[15,10] = 1111 10
5234 unsigned vn = uimm (aarch64_get_instr (cpu), 9, 5);
5235 unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
5236 unsigned full = uimm (aarch64_get_instr (cpu), 30, 30);
5239 NYI_assert (29, 23, 0x1D);
5240 NYI_assert (21, 10, 0x83E);
5242 if (uimm (aarch64_get_instr (cpu), 22, 22))
5247 for (i = 0; i < 2; i++)
5248 aarch64_set_vec_double (cpu, vd, i,
5249 fabs (aarch64_get_vec_double (cpu, vn, i)));
5253 for (i = 0; i < (full ? 4 : 2); i++)
5254 aarch64_set_vec_float (cpu, vd, i,
5255 fabsf (aarch64_get_vec_float (cpu, vn, i)));
5260 do_vec_FCVTZS (sim_cpu *cpu)
5263 instr[30] = half (0) / all (1)
5264 instr[29,23] = 00 1110 1
5265 instr[22] = single (0) / double (1)
5266 instr[21,10] = 10 0001 1011 10
5270 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
5271 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
5272 unsigned full = uimm (aarch64_get_instr (cpu), 30, 30);
5275 NYI_assert (31, 31, 0);
5276 NYI_assert (29, 23, 0x1D);
5277 NYI_assert (21, 10, 0x86E);
5279 if (uimm (aarch64_get_instr (cpu), 22, 22))
5284 for (i = 0; i < 2; i++)
5285 aarch64_set_vec_s64 (cpu, rd, i,
5286 (int64_t) aarch64_get_vec_double (cpu, rn, i));
5289 for (i = 0; i < (full ? 4 : 2); i++)
5290 aarch64_set_vec_s32 (cpu, rd, i,
5291 (int32_t) aarch64_get_vec_float (cpu, rn, i));
5295 do_vec_op1 (sim_cpu *cpu)
5298 instr[30] = half/full
5299 instr[29,24] = 00 1110
5302 instr[15,10] = sub-opcode
5305 NYI_assert (29, 24, 0x0E);
5307 if (uimm (aarch64_get_instr (cpu), 21, 21) == 0)
5309 if (uimm (aarch64_get_instr (cpu), 23, 22) == 0)
5311 if (uimm (aarch64_get_instr (cpu), 30, 30) == 1
5312 && uimm (aarch64_get_instr (cpu), 17, 14) == 0
5313 && uimm (aarch64_get_instr (cpu), 12, 10) == 7)
5314 return do_vec_ins_2 (cpu);
5316 switch (uimm (aarch64_get_instr (cpu), 15, 10))
5318 case 0x01: do_vec_DUP_vector_into_vector (cpu); return;
5319 case 0x03: do_vec_DUP_scalar_into_vector (cpu); return;
5320 case 0x07: do_vec_INS (cpu); return;
5321 case 0x0A: do_vec_TRN (cpu); return;
5324 if (uimm (aarch64_get_instr (cpu), 17, 16) == 0)
5326 do_vec_MOV_into_scalar (cpu);
5335 do_vec_TBL (cpu); return;
5339 do_vec_UZP (cpu); return;
5343 do_vec_ZIP (cpu); return;
5350 switch (uimm (aarch64_get_instr (cpu), 13, 10))
5352 case 0x6: do_vec_UZP (cpu); return;
5353 case 0xE: do_vec_ZIP (cpu); return;
5354 case 0xA: do_vec_TRN (cpu); return;
5355 case 0xF: do_vec_UMOV (cpu); return;
5360 switch (uimm (aarch64_get_instr (cpu), 15, 10))
5363 switch (uimm (aarch64_get_instr (cpu), 23, 21))
5365 case 1: do_vec_AND (cpu); return;
5366 case 3: do_vec_BIC (cpu); return;
5367 case 5: do_vec_ORR (cpu); return;
5368 case 7: do_vec_ORN (cpu); return;
5372 case 0x08: do_vec_sub_long (cpu); return;
5373 case 0x0a: do_vec_XTN (cpu); return;
5374 case 0x11: do_vec_SSHL (cpu); return;
5375 case 0x19: do_vec_max (cpu); return;
5376 case 0x1B: do_vec_min (cpu); return;
5377 case 0x21: do_vec_add (cpu); return;
5378 case 0x25: do_vec_MLA (cpu); return;
5379 case 0x27: do_vec_mul (cpu); return;
5380 case 0x2F: do_vec_ADDP (cpu); return;
5381 case 0x30: do_vec_mull (cpu); return;
5382 case 0x33: do_vec_FMLA (cpu); return;
5383 case 0x35: do_vec_fadd (cpu); return;
5386 switch (uimm (aarch64_get_instr (cpu), 20, 16))
5388 case 0x00: do_vec_ABS (cpu); return;
5389 case 0x01: do_vec_FCVTZS (cpu); return;
5390 case 0x11: do_vec_ADDV (cpu); return;
5396 do_vec_Fminmax (cpu); return;
5408 do_vec_compare (cpu); return;
5411 do_vec_FABS (cpu); return;
5419 do_vec_xtl (sim_cpu *cpu)
5422 instr[30,29] = SXTL (00), UXTL (01), SXTL2 (10), UXTL2 (11)
5423 instr[28,22] = 0 1111 00
5424 instr[21,16] = size & shift (USHLL, SSHLL, USHLL2, SSHLL2)
5425 instr[15,10] = 1010 01
5426 instr[9,5] = V source
5427 instr[4,0] = V dest. */
5429 unsigned vs = uimm (aarch64_get_instr (cpu), 9, 5);
5430 unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
5431 unsigned i, shift, bias = 0;
5433 NYI_assert (28, 22, 0x3C);
5434 NYI_assert (15, 10, 0x29);
5436 switch (uimm (aarch64_get_instr (cpu), 30, 29))
5438 case 2: /* SXTL2, SSHLL2. */
5440 case 0: /* SXTL, SSHLL. */
5441 if (uimm (aarch64_get_instr (cpu), 21, 21))
5443 shift = uimm (aarch64_get_instr (cpu), 20, 16);
5445 (cpu, vd, 0, aarch64_get_vec_s32 (cpu, vs, bias) << shift);
5447 (cpu, vd, 1, aarch64_get_vec_s32 (cpu, vs, bias + 1) << shift);
5449 else if (uimm (aarch64_get_instr (cpu), 20, 20))
5451 shift = uimm (aarch64_get_instr (cpu), 19, 16);
5453 for (i = 0; i < 4; i++)
5455 (cpu, vd, i, aarch64_get_vec_s16 (cpu, vs, i + bias) << shift);
5459 NYI_assert (19, 19, 1);
5461 shift = uimm (aarch64_get_instr (cpu), 18, 16);
5463 for (i = 0; i < 8; i++)
5465 (cpu, vd, i, aarch64_get_vec_s8 (cpu, vs, i + bias) << shift);
5469 case 3: /* UXTL2, USHLL2. */
5471 case 1: /* UXTL, USHLL. */
5472 if (uimm (aarch64_get_instr (cpu), 21, 21))
5474 shift = uimm (aarch64_get_instr (cpu), 20, 16);
5476 (cpu, vd, 0, aarch64_get_vec_u32 (cpu, vs, bias) << shift);
5478 (cpu, vd, 1, aarch64_get_vec_u32 (cpu, vs, bias + 1) << shift);
5480 else if (uimm (aarch64_get_instr (cpu), 20, 20))
5482 shift = uimm (aarch64_get_instr (cpu), 19, 16);
5484 for (i = 0; i < 4; i++)
5486 (cpu, vd, i, aarch64_get_vec_u16 (cpu, vs, i + bias) << shift);
5490 NYI_assert (19, 19, 1);
5492 shift = uimm (aarch64_get_instr (cpu), 18, 16);
5494 for (i = 0; i < 8; i++)
5496 (cpu, vd, i, aarch64_get_vec_u8 (cpu, vs, i + bias) << shift);
5506 do_vec_SHL (sim_cpu *cpu)
5509 instr [30] = half(0)/full(1)
5510 instr [29,23] = 001 1110
5511 instr [22,16] = size and shift amount
5512 instr [15,10] = 01 0101
5514 instr [4, 0] = Vd. */
5517 int full = uimm (aarch64_get_instr (cpu), 30, 30);
5518 unsigned vs = uimm (aarch64_get_instr (cpu), 9, 5);
5519 unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
5522 NYI_assert (29, 23, 0x1E);
5523 NYI_assert (15, 10, 0x15);
5525 if (uimm (aarch64_get_instr (cpu), 22, 22))
5527 shift = uimm (aarch64_get_instr (cpu), 21, 16) - 1;
5532 for (i = 0; i < 2; i++)
5534 uint64_t val = aarch64_get_vec_u64 (cpu, vs, i);
5535 aarch64_set_vec_u64 (cpu, vd, i, val << shift);
5541 if (uimm (aarch64_get_instr (cpu), 21, 21))
5543 shift = uimm (aarch64_get_instr (cpu), 20, 16) - 1;
5545 for (i = 0; i < (full ? 4 : 2); i++)
5547 uint32_t val = aarch64_get_vec_u32 (cpu, vs, i);
5548 aarch64_set_vec_u32 (cpu, vd, i, val << shift);
5554 if (uimm (aarch64_get_instr (cpu), 20, 20))
5556 shift = uimm (aarch64_get_instr (cpu), 19, 16) - 1;
5558 for (i = 0; i < (full ? 8 : 4); i++)
5560 uint16_t val = aarch64_get_vec_u16 (cpu, vs, i);
5561 aarch64_set_vec_u16 (cpu, vd, i, val << shift);
5567 if (uimm (aarch64_get_instr (cpu), 19, 19) == 0)
5570 shift = uimm (aarch64_get_instr (cpu), 18, 16) - 1;
5572 for (i = 0; i < (full ? 16 : 8); i++)
5574 uint8_t val = aarch64_get_vec_u8 (cpu, vs, i);
5575 aarch64_set_vec_u8 (cpu, vd, i, val << shift);
5580 do_vec_SSHR_USHR (sim_cpu *cpu)
5583 instr [30] = half(0)/full(1)
5584 instr [29] = signed(0)/unsigned(1)
5585 instr [28,23] = 01 1110
5586 instr [22,16] = size and shift amount
5587 instr [15,10] = 0000 01
5589 instr [4, 0] = Vd. */
5592 int full = uimm (aarch64_get_instr (cpu), 30, 30);
5593 int sign = uimm (aarch64_get_instr (cpu), 29, 29);
5594 unsigned vs = uimm (aarch64_get_instr (cpu), 9, 5);
5595 unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
5598 NYI_assert (28, 23, 0x1E);
5599 NYI_assert (15, 10, 0x01);
5601 if (uimm (aarch64_get_instr (cpu), 22, 22))
5603 shift = uimm (aarch64_get_instr (cpu), 21, 16);
5609 for (i = 0; i < 2; i++)
5611 int64_t val = aarch64_get_vec_s64 (cpu, vs, i);
5612 aarch64_set_vec_s64 (cpu, vd, i, val >> shift);
5615 for (i = 0; i < 2; i++)
5617 uint64_t val = aarch64_get_vec_u64 (cpu, vs, i);
5618 aarch64_set_vec_u64 (cpu, vd, i, val >> shift);
5624 if (uimm (aarch64_get_instr (cpu), 21, 21))
5626 shift = uimm (aarch64_get_instr (cpu), 20, 16);
5629 for (i = 0; i < (full ? 4 : 2); i++)
5631 int32_t val = aarch64_get_vec_s32 (cpu, vs, i);
5632 aarch64_set_vec_s32 (cpu, vd, i, val >> shift);
5635 for (i = 0; i < (full ? 4 : 2); i++)
5637 uint32_t val = aarch64_get_vec_u32 (cpu, vs, i);
5638 aarch64_set_vec_u32 (cpu, vd, i, val >> shift);
5644 if (uimm (aarch64_get_instr (cpu), 20, 20))
5646 shift = uimm (aarch64_get_instr (cpu), 19, 16);
5649 for (i = 0; i < (full ? 8 : 4); i++)
5651 int16_t val = aarch64_get_vec_s16 (cpu, vs, i);
5652 aarch64_set_vec_s16 (cpu, vd, i, val >> shift);
5655 for (i = 0; i < (full ? 8 : 4); i++)
5657 uint16_t val = aarch64_get_vec_u16 (cpu, vs, i);
5658 aarch64_set_vec_u16 (cpu, vd, i, val >> shift);
5664 if (uimm (aarch64_get_instr (cpu), 19, 19) == 0)
5667 shift = uimm (aarch64_get_instr (cpu), 18, 16);
5670 for (i = 0; i < (full ? 16 : 8); i++)
5672 int8_t val = aarch64_get_vec_s8 (cpu, vs, i);
5673 aarch64_set_vec_s8 (cpu, vd, i, val >> shift);
5676 for (i = 0; i < (full ? 16 : 8); i++)
5678 uint8_t val = aarch64_get_vec_u8 (cpu, vs, i);
5679 aarch64_set_vec_u8 (cpu, vd, i, val >> shift);
5684 do_vec_op2 (sim_cpu *cpu)
5687 instr[30] = half/full
5688 instr[29,24] = 00 1111
5690 instr[22,16] = element size & index
5691 instr[15,10] = sub-opcode
5695 NYI_assert (29, 24, 0x0F);
5697 if (uimm (aarch64_get_instr (cpu), 23, 23) != 0)
5700 switch (uimm (aarch64_get_instr (cpu), 15, 10))
5702 case 0x01: do_vec_SSHR_USHR (cpu); return;
5703 case 0x15: do_vec_SHL (cpu); return;
5704 case 0x29: do_vec_xtl (cpu); return;
5710 do_vec_neg (sim_cpu *cpu)
5713 instr[30] = full(1)/half(0)
5714 instr[29,24] = 10 1110
5715 instr[23,22] = size: byte(00), half (01), word (10), long (11)
5716 instr[21,10] = 1000 0010 1110
5720 int full = uimm (aarch64_get_instr (cpu), 30, 30);
5721 unsigned vs = uimm (aarch64_get_instr (cpu), 9, 5);
5722 unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
5725 NYI_assert (29, 24, 0x2E);
5726 NYI_assert (21, 10, 0x82E);
5728 switch (uimm (aarch64_get_instr (cpu), 23, 22))
5731 for (i = 0; i < (full ? 16 : 8); i++)
5732 aarch64_set_vec_s8 (cpu, vd, i, - aarch64_get_vec_s8 (cpu, vs, i));
5736 for (i = 0; i < (full ? 8 : 4); i++)
5737 aarch64_set_vec_s16 (cpu, vd, i, - aarch64_get_vec_s16 (cpu, vs, i));
5741 for (i = 0; i < (full ? 4 : 2); i++)
5742 aarch64_set_vec_s32 (cpu, vd, i, - aarch64_get_vec_s32 (cpu, vs, i));
5748 for (i = 0; i < 2; i++)
5749 aarch64_set_vec_s64 (cpu, vd, i, - aarch64_get_vec_s64 (cpu, vs, i));
5758 do_vec_sqrt (sim_cpu *cpu)
5761 instr[30] = full(1)/half(0)
5762 instr[29,23] = 101 1101
5763 instr[22] = single(0)/double(1)
5764 instr[21,10] = 1000 0111 1110
5768 int full = uimm (aarch64_get_instr (cpu), 30, 30);
5769 unsigned vs = uimm (aarch64_get_instr (cpu), 9, 5);
5770 unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
5773 NYI_assert (29, 23, 0x5B);
5774 NYI_assert (21, 10, 0x87E);
5776 if (uimm (aarch64_get_instr (cpu), 22, 22) == 0)
5777 for (i = 0; i < (full ? 4 : 2); i++)
5778 aarch64_set_vec_float (cpu, vd, i,
5779 sqrtf (aarch64_get_vec_float (cpu, vs, i)));
5781 for (i = 0; i < 2; i++)
5782 aarch64_set_vec_double (cpu, vd, i,
5783 sqrt (aarch64_get_vec_double (cpu, vs, i)));
5787 do_vec_mls_indexed (sim_cpu *cpu)
5790 instr[30] = half(0)/full(1)
5791 instr[29,24] = 10 1111
5792 instr[23,22] = 16-bit(01)/32-bit(10)
5793 instr[21,20+11] = index (if 16-bit)
5794 instr[21+11] = index (if 32-bit)
5797 instr[11] = part of index
5802 int full = uimm (aarch64_get_instr (cpu), 30, 30);
5803 unsigned vs = uimm (aarch64_get_instr (cpu), 9, 5);
5804 unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
5805 unsigned vm = uimm (aarch64_get_instr (cpu), 20, 16);
5808 NYI_assert (15, 12, 4);
5809 NYI_assert (10, 10, 0);
5811 switch (uimm (aarch64_get_instr (cpu), 23, 22))
5821 elem = (uimm (aarch64_get_instr (cpu), 21, 20) << 1)
5822 | uimm (aarch64_get_instr (cpu), 11, 11);
5823 val = aarch64_get_vec_u16 (cpu, vm, elem);
5825 for (i = 0; i < (full ? 8 : 4); i++)
5826 aarch64_set_vec_u32 (cpu, vd, i,
5827 aarch64_get_vec_u32 (cpu, vd, i) -
5828 (aarch64_get_vec_u32 (cpu, vs, i) * val));
5834 unsigned elem = (uimm (aarch64_get_instr (cpu), 21, 21) << 1)
5835 | uimm (aarch64_get_instr (cpu), 11, 11);
5836 uint64_t val = aarch64_get_vec_u32 (cpu, vm, elem);
5838 for (i = 0; i < (full ? 4 : 2); i++)
5839 aarch64_set_vec_u64 (cpu, vd, i,
5840 aarch64_get_vec_u64 (cpu, vd, i) -
5841 (aarch64_get_vec_u64 (cpu, vs, i) * val));
5853 do_vec_SUB (sim_cpu *cpu)
5856 instr [30] = half(0)/full(1)
5857 instr [29,24] = 10 1110
5858 instr [23,22] = size: byte(00, half(01), word (10), long (11)
5861 instr [15,10] = 10 0001
5863 instr [4, 0] = Vd. */
5865 unsigned full = uimm (aarch64_get_instr (cpu), 30, 30);
5866 unsigned vm = uimm (aarch64_get_instr (cpu), 20, 16);
5867 unsigned vn = uimm (aarch64_get_instr (cpu), 9, 5);
5868 unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
5871 NYI_assert (29, 24, 0x2E);
5872 NYI_assert (21, 21, 1);
5873 NYI_assert (15, 10, 0x21);
5875 switch (uimm (aarch64_get_instr (cpu), 23, 22))
5878 for (i = 0; i < (full ? 16 : 8); i++)
5879 aarch64_set_vec_s8 (cpu, vd, i,
5880 aarch64_get_vec_s8 (cpu, vn, i)
5881 - aarch64_get_vec_s8 (cpu, vm, i));
5885 for (i = 0; i < (full ? 8 : 4); i++)
5886 aarch64_set_vec_s16 (cpu, vd, i,
5887 aarch64_get_vec_s16 (cpu, vn, i)
5888 - aarch64_get_vec_s16 (cpu, vm, i));
5892 for (i = 0; i < (full ? 4 : 2); i++)
5893 aarch64_set_vec_s32 (cpu, vd, i,
5894 aarch64_get_vec_s32 (cpu, vn, i)
5895 - aarch64_get_vec_s32 (cpu, vm, i));
5902 for (i = 0; i < 2; i++)
5903 aarch64_set_vec_s64 (cpu, vd, i,
5904 aarch64_get_vec_s64 (cpu, vn, i)
5905 - aarch64_get_vec_s64 (cpu, vm, i));
5914 do_vec_MLS (sim_cpu *cpu)
5917 instr [30] = half(0)/full(1)
5918 instr [29,24] = 10 1110
5919 instr [23,22] = size: byte(00, half(01), word (10)
5922 instr [15,10] = 10 0101
5924 instr [4, 0] = Vd. */
5926 unsigned full = uimm (aarch64_get_instr (cpu), 30, 30);
5927 unsigned vm = uimm (aarch64_get_instr (cpu), 20, 16);
5928 unsigned vn = uimm (aarch64_get_instr (cpu), 9, 5);
5929 unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
5932 NYI_assert (29, 24, 0x2E);
5933 NYI_assert (21, 21, 1);
5934 NYI_assert (15, 10, 0x25);
5936 switch (uimm (aarch64_get_instr (cpu), 23, 22))
5939 for (i = 0; i < (full ? 16 : 8); i++)
5940 aarch64_set_vec_u8 (cpu, vd, i,
5941 (aarch64_get_vec_u8 (cpu, vn, i)
5942 * aarch64_get_vec_u8 (cpu, vm, i))
5943 - aarch64_get_vec_u8 (cpu, vd, i));
5947 for (i = 0; i < (full ? 8 : 4); i++)
5948 aarch64_set_vec_u16 (cpu, vd, i,
5949 (aarch64_get_vec_u16 (cpu, vn, i)
5950 * aarch64_get_vec_u16 (cpu, vm, i))
5951 - aarch64_get_vec_u16 (cpu, vd, i));
5955 for (i = 0; i < (full ? 4 : 2); i++)
5956 aarch64_set_vec_u32 (cpu, vd, i,
5957 (aarch64_get_vec_u32 (cpu, vn, i)
5958 * aarch64_get_vec_u32 (cpu, vm, i))
5959 - aarch64_get_vec_u32 (cpu, vd, i));
5968 do_vec_FDIV (sim_cpu *cpu)
5971 instr [30] = half(0)/full(1)
5972 instr [29,23] = 10 1110 0
5973 instr [22] = float()/double(1)
5976 instr [15,10] = 1111 11
5978 instr [4, 0] = Vd. */
5980 unsigned full = uimm (aarch64_get_instr (cpu), 30, 30);
5981 unsigned vm = uimm (aarch64_get_instr (cpu), 20, 16);
5982 unsigned vn = uimm (aarch64_get_instr (cpu), 9, 5);
5983 unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
5986 NYI_assert (29, 23, 0x5C);
5987 NYI_assert (21, 21, 1);
5988 NYI_assert (15, 10, 0x3F);
5990 if (uimm (aarch64_get_instr (cpu), 22, 22))
5995 for (i = 0; i < 2; i++)
5996 aarch64_set_vec_double (cpu, vd, i,
5997 aarch64_get_vec_double (cpu, vn, i)
5998 / aarch64_get_vec_double (cpu, vm, i));
6001 for (i = 0; i < (full ? 4 : 2); i++)
6002 aarch64_set_vec_float (cpu, vd, i,
6003 aarch64_get_vec_float (cpu, vn, i)
6004 / aarch64_get_vec_float (cpu, vm, i));
6008 do_vec_FMUL (sim_cpu *cpu)
6011 instr [30] = half(0)/full(1)
6012 instr [29,23] = 10 1110 0
6013 instr [22] = float(0)/double(1)
6016 instr [15,10] = 1101 11
6018 instr [4, 0] = Vd. */
6020 unsigned full = uimm (aarch64_get_instr (cpu), 30, 30);
6021 unsigned vm = uimm (aarch64_get_instr (cpu), 20, 16);
6022 unsigned vn = uimm (aarch64_get_instr (cpu), 9, 5);
6023 unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
6026 NYI_assert (29, 23, 0x5C);
6027 NYI_assert (21, 21, 1);
6028 NYI_assert (15, 10, 0x37);
6030 if (uimm (aarch64_get_instr (cpu), 22, 22))
6035 for (i = 0; i < 2; i++)
6036 aarch64_set_vec_double (cpu, vd, i,
6037 aarch64_get_vec_double (cpu, vn, i)
6038 * aarch64_get_vec_double (cpu, vm, i));
6041 for (i = 0; i < (full ? 4 : 2); i++)
6042 aarch64_set_vec_float (cpu, vd, i,
6043 aarch64_get_vec_float (cpu, vn, i)
6044 * aarch64_get_vec_float (cpu, vm, i));
6048 do_vec_FADDP (sim_cpu *cpu)
6051 instr [30] = half(0)/full(1)
6052 instr [29,23] = 10 1110 0
6053 instr [22] = float(0)/double(1)
6056 instr [15,10] = 1101 01
6058 instr [4, 0] = Vd. */
6060 unsigned full = uimm (aarch64_get_instr (cpu), 30, 30);
6061 unsigned vm = uimm (aarch64_get_instr (cpu), 20, 16);
6062 unsigned vn = uimm (aarch64_get_instr (cpu), 9, 5);
6063 unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
6065 NYI_assert (29, 23, 0x5C);
6066 NYI_assert (21, 21, 1);
6067 NYI_assert (15, 10, 0x35);
6069 if (uimm (aarch64_get_instr (cpu), 22, 22))
6074 aarch64_set_vec_double (cpu, vd, 0, aarch64_get_vec_double (cpu, vn, 0)
6075 + aarch64_get_vec_double (cpu, vn, 1));
6076 aarch64_set_vec_double (cpu, vd, 1, aarch64_get_vec_double (cpu, vm, 0)
6077 + aarch64_get_vec_double (cpu, vm, 1));
6081 aarch64_set_vec_float (cpu, vd, 0, aarch64_get_vec_float (cpu, vn, 0)
6082 + aarch64_get_vec_float (cpu, vn, 1));
6084 aarch64_set_vec_float (cpu, vd, 1, aarch64_get_vec_float (cpu, vn, 2)
6085 + aarch64_get_vec_float (cpu, vn, 3));
6086 aarch64_set_vec_float (cpu, vd, full ? 2 : 1,
6087 aarch64_get_vec_float (cpu, vm, 0)
6088 + aarch64_get_vec_float (cpu, vm, 1));
6090 aarch64_set_vec_float (cpu, vd, 3,
6091 aarch64_get_vec_float (cpu, vm, 2)
6092 + aarch64_get_vec_float (cpu, vm, 3));
6097 do_vec_FSQRT (sim_cpu *cpu)
6100 instr[30] = half(0)/full(1)
6101 instr[29,23] = 10 1110 1
6102 instr[22] = single(0)/double(1)
6103 instr[21,10] = 10 0001 1111 10
6105 instr[4,0] = Vdest. */
6107 unsigned vn = uimm (aarch64_get_instr (cpu), 9, 5);
6108 unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
6109 unsigned full = uimm (aarch64_get_instr (cpu), 30, 30);
6112 NYI_assert (29, 23, 0x5D);
6113 NYI_assert (21, 10, 0x87E);
6115 if (uimm (aarch64_get_instr (cpu), 22, 22))
6120 for (i = 0; i < 2; i++)
6121 aarch64_set_vec_double (cpu, vd, i,
6122 sqrt (aarch64_get_vec_double (cpu, vn, i)));
6126 for (i = 0; i < (full ? 4 : 2); i++)
6127 aarch64_set_vec_float (cpu, vd, i,
6128 sqrtf (aarch64_get_vec_float (cpu, vn, i)));
6133 do_vec_FNEG (sim_cpu *cpu)
6136 instr[30] = half (0)/full (1)
6137 instr[29,23] = 10 1110 1
6138 instr[22] = single (0)/double (1)
6139 instr[21,10] = 10 0000 1111 10
6141 instr[4,0] = Vdest. */
6143 unsigned vn = uimm (aarch64_get_instr (cpu), 9, 5);
6144 unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
6145 unsigned full = uimm (aarch64_get_instr (cpu), 30, 30);
6148 NYI_assert (29, 23, 0x5D);
6149 NYI_assert (21, 10, 0x83E);
6151 if (uimm (aarch64_get_instr (cpu), 22, 22))
6156 for (i = 0; i < 2; i++)
6157 aarch64_set_vec_double (cpu, vd, i,
6158 - aarch64_get_vec_double (cpu, vn, i));
6162 for (i = 0; i < (full ? 4 : 2); i++)
6163 aarch64_set_vec_float (cpu, vd, i,
6164 - aarch64_get_vec_float (cpu, vn, i));
6169 do_vec_NOT (sim_cpu *cpu)
6172 instr[30] = half (0)/full (1)
6173 instr[29,21] = 10 1110 001
6174 instr[20,16] = 0 0000
6175 instr[15,10] = 0101 10
6179 unsigned vn = uimm (aarch64_get_instr (cpu), 9, 5);
6180 unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
6182 int full = uimm (aarch64_get_instr (cpu), 30, 30);
6184 NYI_assert (29, 10, 0xB8816);
6186 for (i = 0; i < (full ? 16 : 8); i++)
6187 aarch64_set_vec_u8 (cpu, vd, i, ~ aarch64_get_vec_u8 (cpu, vn, i));
6191 do_vec_MOV_element (sim_cpu *cpu)
6193 /* instr[31,21] = 0110 1110 000
6194 instr[20,16] = size & dest index
6196 instr[14,11] = source index
6201 unsigned vs = uimm (aarch64_get_instr (cpu), 9, 5);
6202 unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
6206 NYI_assert (31, 21, 0x370);
6207 NYI_assert (15, 15, 0);
6208 NYI_assert (10, 10, 1);
6210 if (uimm (aarch64_get_instr (cpu), 16, 16))
6213 src_index = uimm (aarch64_get_instr (cpu), 14, 11);
6214 dst_index = uimm (aarch64_get_instr (cpu), 20, 17);
6215 aarch64_set_vec_u8 (cpu, vd, dst_index,
6216 aarch64_get_vec_u8 (cpu, vs, src_index));
6218 else if (uimm (aarch64_get_instr (cpu), 17, 17))
6221 NYI_assert (11, 11, 0);
6222 src_index = uimm (aarch64_get_instr (cpu), 14, 12);
6223 dst_index = uimm (aarch64_get_instr (cpu), 20, 18);
6224 aarch64_set_vec_u16 (cpu, vd, dst_index,
6225 aarch64_get_vec_u16 (cpu, vs, src_index));
6227 else if (uimm (aarch64_get_instr (cpu), 18, 18))
6230 NYI_assert (12, 11, 0);
6231 src_index = uimm (aarch64_get_instr (cpu), 14, 13);
6232 dst_index = uimm (aarch64_get_instr (cpu), 20, 19);
6233 aarch64_set_vec_u32 (cpu, vd, dst_index,
6234 aarch64_get_vec_u32 (cpu, vs, src_index));
6238 NYI_assert (19, 19, 1);
6239 NYI_assert (13, 11, 0);
6240 src_index = uimm (aarch64_get_instr (cpu), 14, 14);
6241 dst_index = uimm (aarch64_get_instr (cpu), 20, 20);
6242 aarch64_set_vec_u64 (cpu, vd, dst_index,
6243 aarch64_get_vec_u64 (cpu, vs, src_index));
6248 dexAdvSIMD0 (sim_cpu *cpu)
6250 /* instr [28,25] = 0 111. */
6251 if ( uimm (aarch64_get_instr (cpu), 15, 10) == 0x07
6252 && (uimm (aarch64_get_instr (cpu), 9, 5) ==
6253 uimm (aarch64_get_instr (cpu), 20, 16)))
6255 if (uimm (aarch64_get_instr (cpu), 31, 21) == 0x075
6256 || uimm (aarch64_get_instr (cpu), 31, 21) == 0x275)
6258 do_vec_MOV_whole_vector (cpu);
6263 if (uimm (aarch64_get_instr (cpu), 29, 19) == 0x1E0)
6265 do_vec_MOV_immediate (cpu);
6269 if (uimm (aarch64_get_instr (cpu), 29, 19) == 0x5E0)
6275 if (uimm (aarch64_get_instr (cpu), 29, 19) == 0x1C0
6276 || uimm (aarch64_get_instr (cpu), 29, 19) == 0x1C1)
6278 if (uimm (aarch64_get_instr (cpu), 15, 10) == 0x03)
6280 do_vec_DUP_scalar_into_vector (cpu);
6285 switch (uimm (aarch64_get_instr (cpu), 29, 24))
6287 case 0x0E: do_vec_op1 (cpu); return;
6288 case 0x0F: do_vec_op2 (cpu); return;
6291 switch (uimm (aarch64_get_instr (cpu), 15, 10))
6293 case 0x01: do_vec_SSHR_USHR (cpu); return;
6295 case 0x12: do_vec_mls_indexed (cpu); return;
6296 case 0x29: do_vec_xtl (cpu); return;
6302 if (uimm (aarch64_get_instr (cpu), 21, 21) == 1)
6304 switch (uimm (aarch64_get_instr (cpu), 15, 10))
6307 switch (uimm (aarch64_get_instr (cpu), 23, 22))
6309 case 0: do_vec_EOR (cpu); return;
6310 case 1: do_vec_BSL (cpu); return;
6312 case 3: do_vec_bit (cpu); return;
6316 case 0x08: do_vec_sub_long (cpu); return;
6317 case 0x11: do_vec_USHL (cpu); return;
6318 case 0x16: do_vec_NOT (cpu); return;
6319 case 0x19: do_vec_max (cpu); return;
6320 case 0x1B: do_vec_min (cpu); return;
6321 case 0x21: do_vec_SUB (cpu); return;
6322 case 0x25: do_vec_MLS (cpu); return;
6323 case 0x31: do_vec_FminmaxNMP (cpu); return;
6324 case 0x35: do_vec_FADDP (cpu); return;
6325 case 0x37: do_vec_FMUL (cpu); return;
6326 case 0x3F: do_vec_FDIV (cpu); return;
6329 switch (uimm (aarch64_get_instr (cpu), 20, 16))
6331 case 0x00: do_vec_FNEG (cpu); return;
6332 case 0x01: do_vec_FSQRT (cpu); return;
6346 do_vec_compare (cpu); return;
6352 if (uimm (aarch64_get_instr (cpu), 31, 21) == 0x370)
6354 do_vec_MOV_element (cpu);
6358 switch (uimm (aarch64_get_instr (cpu), 21, 10))
6360 case 0x82E: do_vec_neg (cpu); return;
6361 case 0x87E: do_vec_sqrt (cpu); return;
6363 if (uimm (aarch64_get_instr (cpu), 15, 10) == 0x30)
6381 /* Float multiply add. */
6383 fmadds (sim_cpu *cpu)
6385 unsigned sa = uimm (aarch64_get_instr (cpu), 14, 10);
6386 unsigned sm = uimm (aarch64_get_instr (cpu), 20, 16);
6387 unsigned sn = uimm (aarch64_get_instr (cpu), 9, 5);
6388 unsigned sd = uimm (aarch64_get_instr (cpu), 4, 0);
6390 aarch64_set_FP_float (cpu, sd, aarch64_get_FP_float (cpu, sa)
6391 + aarch64_get_FP_float (cpu, sn)
6392 * aarch64_get_FP_float (cpu, sm));
6395 /* Double multiply add. */
6397 fmaddd (sim_cpu *cpu)
6399 unsigned sa = uimm (aarch64_get_instr (cpu), 14, 10);
6400 unsigned sm = uimm (aarch64_get_instr (cpu), 20, 16);
6401 unsigned sn = uimm (aarch64_get_instr (cpu), 9, 5);
6402 unsigned sd = uimm (aarch64_get_instr (cpu), 4, 0);
6404 aarch64_set_FP_double (cpu, sd, aarch64_get_FP_double (cpu, sa)
6405 + aarch64_get_FP_double (cpu, sn)
6406 * aarch64_get_FP_double (cpu, sm));
6409 /* Float multiply subtract. */
6411 fmsubs (sim_cpu *cpu)
6413 unsigned sa = uimm (aarch64_get_instr (cpu), 14, 10);
6414 unsigned sm = uimm (aarch64_get_instr (cpu), 20, 16);
6415 unsigned sn = uimm (aarch64_get_instr (cpu), 9, 5);
6416 unsigned sd = uimm (aarch64_get_instr (cpu), 4, 0);
6418 aarch64_set_FP_float (cpu, sd, aarch64_get_FP_float (cpu, sa)
6419 - aarch64_get_FP_float (cpu, sn)
6420 * aarch64_get_FP_float (cpu, sm));
6423 /* Double multiply subtract. */
6425 fmsubd (sim_cpu *cpu)
6427 unsigned sa = uimm (aarch64_get_instr (cpu), 14, 10);
6428 unsigned sm = uimm (aarch64_get_instr (cpu), 20, 16);
6429 unsigned sn = uimm (aarch64_get_instr (cpu), 9, 5);
6430 unsigned sd = uimm (aarch64_get_instr (cpu), 4, 0);
6432 aarch64_set_FP_double (cpu, sd, aarch64_get_FP_double (cpu, sa)
6433 - aarch64_get_FP_double (cpu, sn)
6434 * aarch64_get_FP_double (cpu, sm));
6437 /* Float negative multiply add. */
6439 fnmadds (sim_cpu *cpu)
6441 unsigned sa = uimm (aarch64_get_instr (cpu), 14, 10);
6442 unsigned sm = uimm (aarch64_get_instr (cpu), 20, 16);
6443 unsigned sn = uimm (aarch64_get_instr (cpu), 9, 5);
6444 unsigned sd = uimm (aarch64_get_instr (cpu), 4, 0);
6446 aarch64_set_FP_float (cpu, sd, - aarch64_get_FP_float (cpu, sa)
6447 + (- aarch64_get_FP_float (cpu, sn))
6448 * aarch64_get_FP_float (cpu, sm));
6451 /* Double negative multiply add. */
6453 fnmaddd (sim_cpu *cpu)
6455 unsigned sa = uimm (aarch64_get_instr (cpu), 14, 10);
6456 unsigned sm = uimm (aarch64_get_instr (cpu), 20, 16);
6457 unsigned sn = uimm (aarch64_get_instr (cpu), 9, 5);
6458 unsigned sd = uimm (aarch64_get_instr (cpu), 4, 0);
6460 aarch64_set_FP_double (cpu, sd, - aarch64_get_FP_double (cpu, sa)
6461 + (- aarch64_get_FP_double (cpu, sn))
6462 * aarch64_get_FP_double (cpu, sm));
6465 /* Float negative multiply subtract. */
6467 fnmsubs (sim_cpu *cpu)
6469 unsigned sa = uimm (aarch64_get_instr (cpu), 14, 10);
6470 unsigned sm = uimm (aarch64_get_instr (cpu), 20, 16);
6471 unsigned sn = uimm (aarch64_get_instr (cpu), 9, 5);
6472 unsigned sd = uimm (aarch64_get_instr (cpu), 4, 0);
6474 aarch64_set_FP_float (cpu, sd, - aarch64_get_FP_float (cpu, sa)
6475 + aarch64_get_FP_float (cpu, sn)
6476 * aarch64_get_FP_float (cpu, sm));
6479 /* Double negative multiply subtract. */
6481 fnmsubd (sim_cpu *cpu)
6483 unsigned sa = uimm (aarch64_get_instr (cpu), 14, 10);
6484 unsigned sm = uimm (aarch64_get_instr (cpu), 20, 16);
6485 unsigned sn = uimm (aarch64_get_instr (cpu), 9, 5);
6486 unsigned sd = uimm (aarch64_get_instr (cpu), 4, 0);
6488 aarch64_set_FP_double (cpu, sd, - aarch64_get_FP_double (cpu, sa)
6489 + aarch64_get_FP_double (cpu, sn)
6490 * aarch64_get_FP_double (cpu, sm));
6494 dexSimpleFPDataProc3Source (sim_cpu *cpu)
6496 /* instr[31] ==> M : 0 ==> OK, 1 ==> UNALLOC
6498 instr[29] ==> S : 0 ==> OK, 1 ==> UNALLOC
6501 instr[23,22] ==> type : 0 ==> single, 01 ==> double, 1x ==> UNALLOC
6502 instr[21] ==> o1 : 0 ==> unnegated, 1 ==> negated
6503 instr[15] ==> o2 : 0 ==> ADD, 1 ==> SUB */
6505 uint32_t M_S = (uimm (aarch64_get_instr (cpu), 31, 31) << 1)
6506 | uimm (aarch64_get_instr (cpu), 29, 29);
6507 /* dispatch on combined type:o1:o2. */
6508 uint32_t dispatch = (uimm (aarch64_get_instr (cpu), 23, 21) << 1)
6509 | uimm (aarch64_get_instr (cpu), 15, 15);
6516 case 0: fmadds (cpu); return;
6517 case 1: fmsubs (cpu); return;
6518 case 2: fnmadds (cpu); return;
6519 case 3: fnmsubs (cpu); return;
6520 case 4: fmaddd (cpu); return;
6521 case 5: fmsubd (cpu); return;
6522 case 6: fnmaddd (cpu); return;
6523 case 7: fnmsubd (cpu); return;
6525 /* type > 1 is currently unallocated. */
6531 dexSimpleFPFixedConvert (sim_cpu *cpu)
6537 dexSimpleFPCondCompare (sim_cpu *cpu)
6546 fadds (sim_cpu *cpu)
6548 unsigned sm = uimm (aarch64_get_instr (cpu), 20, 16);
6549 unsigned sn = uimm (aarch64_get_instr (cpu), 9, 5);
6550 unsigned sd = uimm (aarch64_get_instr (cpu), 4, 0);
6552 aarch64_set_FP_float (cpu, sd, aarch64_get_FP_float (cpu, sn)
6553 + aarch64_get_FP_float (cpu, sm));
6558 faddd (sim_cpu *cpu)
6560 unsigned sm = uimm (aarch64_get_instr (cpu), 20, 16);
6561 unsigned sn = uimm (aarch64_get_instr (cpu), 9, 5);
6562 unsigned sd = uimm (aarch64_get_instr (cpu), 4, 0);
6564 aarch64_set_FP_double (cpu, sd, aarch64_get_FP_double (cpu, sn)
6565 + aarch64_get_FP_double (cpu, sm));
6570 fdivs (sim_cpu *cpu)
6572 unsigned sm = uimm (aarch64_get_instr (cpu), 20, 16);
6573 unsigned sn = uimm (aarch64_get_instr (cpu), 9, 5);
6574 unsigned sd = uimm (aarch64_get_instr (cpu), 4, 0);
6576 aarch64_set_FP_float (cpu, sd, aarch64_get_FP_float (cpu, sn)
6577 / aarch64_get_FP_float (cpu, sm));
6580 /* Double divide. */
6582 fdivd (sim_cpu *cpu)
6584 unsigned sm = uimm (aarch64_get_instr (cpu), 20, 16);
6585 unsigned sn = uimm (aarch64_get_instr (cpu), 9, 5);
6586 unsigned sd = uimm (aarch64_get_instr (cpu), 4, 0);
6588 aarch64_set_FP_double (cpu, sd, aarch64_get_FP_double (cpu, sn)
6589 / aarch64_get_FP_double (cpu, sm));
6592 /* Float multiply. */
6594 fmuls (sim_cpu *cpu)
6596 unsigned sm = uimm (aarch64_get_instr (cpu), 20, 16);
6597 unsigned sn = uimm (aarch64_get_instr (cpu), 9, 5);
6598 unsigned sd = uimm (aarch64_get_instr (cpu), 4, 0);
6600 aarch64_set_FP_float (cpu, sd, aarch64_get_FP_float (cpu, sn)
6601 * aarch64_get_FP_float (cpu, sm));
6604 /* Double multiply. */
6606 fmuld (sim_cpu *cpu)
6608 unsigned sm = uimm (aarch64_get_instr (cpu), 20, 16);
6609 unsigned sn = uimm (aarch64_get_instr (cpu), 9, 5);
6610 unsigned sd = uimm (aarch64_get_instr (cpu), 4, 0);
6612 aarch64_set_FP_double (cpu, sd, aarch64_get_FP_double (cpu, sn)
6613 * aarch64_get_FP_double (cpu, sm));
6616 /* Float negate and multiply. */
6618 fnmuls (sim_cpu *cpu)
6620 unsigned sm = uimm (aarch64_get_instr (cpu), 20, 16);
6621 unsigned sn = uimm (aarch64_get_instr (cpu), 9, 5);
6622 unsigned sd = uimm (aarch64_get_instr (cpu), 4, 0);
6624 aarch64_set_FP_float (cpu, sd, - (aarch64_get_FP_float (cpu, sn)
6625 * aarch64_get_FP_float (cpu, sm)));
6628 /* Double negate and multiply. */
6630 fnmuld (sim_cpu *cpu)
6632 unsigned sm = uimm (aarch64_get_instr (cpu), 20, 16);
6633 unsigned sn = uimm (aarch64_get_instr (cpu), 9, 5);
6634 unsigned sd = uimm (aarch64_get_instr (cpu), 4, 0);
6636 aarch64_set_FP_double (cpu, sd, - (aarch64_get_FP_double (cpu, sn)
6637 * aarch64_get_FP_double (cpu, sm)));
6640 /* Float subtract. */
6642 fsubs (sim_cpu *cpu)
6644 unsigned sm = uimm (aarch64_get_instr (cpu), 20, 16);
6645 unsigned sn = uimm (aarch64_get_instr (cpu), 9, 5);
6646 unsigned sd = uimm (aarch64_get_instr (cpu), 4, 0);
6648 aarch64_set_FP_float (cpu, sd, aarch64_get_FP_float (cpu, sn)
6649 - aarch64_get_FP_float (cpu, sm));
6652 /* Double subtract. */
6654 fsubd (sim_cpu *cpu)
6656 unsigned sm = uimm (aarch64_get_instr (cpu), 20, 16);
6657 unsigned sn = uimm (aarch64_get_instr (cpu), 9, 5);
6658 unsigned sd = uimm (aarch64_get_instr (cpu), 4, 0);
6660 aarch64_set_FP_double (cpu, sd, aarch64_get_FP_double (cpu, sn)
6661 - aarch64_get_FP_double (cpu, sm));
6665 do_FMINNM (sim_cpu *cpu)
6667 /* instr[31,23] = 0 0011 1100
6668 instr[22] = float(0)/double(1)
6671 instr[15,10] = 01 1110
6675 unsigned sm = uimm (aarch64_get_instr (cpu), 20, 16);
6676 unsigned sn = uimm (aarch64_get_instr (cpu), 9, 5);
6677 unsigned sd = uimm (aarch64_get_instr (cpu), 4, 0);
6679 NYI_assert (31, 23, 0x03C);
6680 NYI_assert (15, 10, 0x1E);
6682 if (uimm (aarch64_get_instr (cpu), 22, 22))
6683 aarch64_set_FP_double (cpu, sd,
6684 dminnm (aarch64_get_FP_double (cpu, sn),
6685 aarch64_get_FP_double (cpu, sm)));
6687 aarch64_set_FP_float (cpu, sd,
6688 fminnm (aarch64_get_FP_float (cpu, sn),
6689 aarch64_get_FP_float (cpu, sm)));
6693 do_FMAXNM (sim_cpu *cpu)
6695 /* instr[31,23] = 0 0011 1100
6696 instr[22] = float(0)/double(1)
6699 instr[15,10] = 01 1010
6703 unsigned sm = uimm (aarch64_get_instr (cpu), 20, 16);
6704 unsigned sn = uimm (aarch64_get_instr (cpu), 9, 5);
6705 unsigned sd = uimm (aarch64_get_instr (cpu), 4, 0);
6707 NYI_assert (31, 23, 0x03C);
6708 NYI_assert (15, 10, 0x1A);
6710 if (uimm (aarch64_get_instr (cpu), 22, 22))
6711 aarch64_set_FP_double (cpu, sd,
6712 dmaxnm (aarch64_get_FP_double (cpu, sn),
6713 aarch64_get_FP_double (cpu, sm)));
6715 aarch64_set_FP_float (cpu, sd,
6716 fmaxnm (aarch64_get_FP_float (cpu, sn),
6717 aarch64_get_FP_float (cpu, sm)));
6721 dexSimpleFPDataProc2Source (sim_cpu *cpu)
6723 /* instr[31] ==> M : 0 ==> OK, 1 ==> UNALLOC
6725 instr[29] ==> S : 0 ==> OK, 1 ==> UNALLOC
6728 instr[23,22] ==> type : 0 ==> single, 01 ==> double, 1x ==> UNALLOC
6731 instr[15,12] ==> opcode : 0000 ==> FMUL, 0001 ==> FDIV
6732 0010 ==> FADD, 0011 ==> FSUB,
6733 0100 ==> FMAX, 0101 ==> FMIN
6734 0110 ==> FMAXNM, 0111 ==> FMINNM
6735 1000 ==> FNMUL, ow ==> UNALLOC
6740 uint32_t M_S = (uimm (aarch64_get_instr (cpu), 31, 31) << 1)
6741 | uimm (aarch64_get_instr (cpu), 29, 29);
6742 uint32_t type = uimm (aarch64_get_instr (cpu), 23, 22);
6743 /* Dispatch on opcode. */
6744 uint32_t dispatch = uimm (aarch64_get_instr (cpu), 15, 12);
6755 case 0: fmuld (cpu); return;
6756 case 1: fdivd (cpu); return;
6757 case 2: faddd (cpu); return;
6758 case 3: fsubd (cpu); return;
6759 case 6: do_FMAXNM (cpu); return;
6760 case 7: do_FMINNM (cpu); return;
6761 case 8: fnmuld (cpu); return;
6763 /* Have not yet implemented fmax and fmin. */
6771 else /* type == 0 => floats. */
6774 case 0: fmuls (cpu); return;
6775 case 1: fdivs (cpu); return;
6776 case 2: fadds (cpu); return;
6777 case 3: fsubs (cpu); return;
6778 case 6: do_FMAXNM (cpu); return;
6779 case 7: do_FMINNM (cpu); return;
6780 case 8: fnmuls (cpu); return;
6792 dexSimpleFPCondSelect (sim_cpu *cpu)
6795 instr[31,23] = 0 0011 1100
6796 instr[22] = 0=>single 1=>double
6803 unsigned sm = uimm (aarch64_get_instr (cpu), 20, 16);
6804 unsigned sn = uimm (aarch64_get_instr (cpu), 9, 5);
6805 unsigned sd = uimm (aarch64_get_instr (cpu), 4, 0);
6806 uint32_t set = testConditionCode (cpu, uimm (aarch64_get_instr (cpu), 15, 12));
6808 NYI_assert (31, 23, 0x03C);
6809 NYI_assert (11, 10, 0x3);
6811 if (uimm (aarch64_get_instr (cpu), 22, 22))
6812 aarch64_set_FP_double (cpu, sd, set ? sn : sm);
6814 aarch64_set_FP_float (cpu, sd, set ? sn : sm);
6817 /* Store 32 bit unscaled signed 9 bit. */
6819 fsturs (sim_cpu *cpu, int32_t offset)
6821 unsigned int rn = uimm (aarch64_get_instr (cpu), 9, 5);
6822 unsigned int st = uimm (aarch64_get_instr (cpu), 4, 0);
6824 aarch64_set_mem_float (cpu, aarch64_get_reg_u64 (cpu, st, 1) + offset,
6825 aarch64_get_FP_float (cpu, rn));
6828 /* Store 64 bit unscaled signed 9 bit. */
6830 fsturd (sim_cpu *cpu, int32_t offset)
6832 unsigned int rn = uimm (aarch64_get_instr (cpu), 9, 5);
6833 unsigned int st = uimm (aarch64_get_instr (cpu), 4, 0);
6835 aarch64_set_mem_double (cpu, aarch64_get_reg_u64 (cpu, st, 1) + offset,
6836 aarch64_get_FP_double (cpu, rn));
6839 /* Store 128 bit unscaled signed 9 bit. */
6841 fsturq (sim_cpu *cpu, int32_t offset)
6843 unsigned int rn = uimm (aarch64_get_instr (cpu), 9, 5);
6844 unsigned int st = uimm (aarch64_get_instr (cpu), 4, 0);
6847 aarch64_get_FP_long_double (cpu, rn, & a);
6848 aarch64_set_mem_long_double (cpu,
6849 aarch64_get_reg_u64 (cpu, st, 1)
6853 /* TODO FP move register. */
6855 /* 32 bit fp to fp move register. */
6857 ffmovs (sim_cpu *cpu)
6859 unsigned int rn = uimm (aarch64_get_instr (cpu), 9, 5);
6860 unsigned int st = uimm (aarch64_get_instr (cpu), 4, 0);
6862 aarch64_set_FP_float (cpu, st, aarch64_get_FP_float (cpu, rn));
6865 /* 64 bit fp to fp move register. */
6867 ffmovd (sim_cpu *cpu)
6869 unsigned int rn = uimm (aarch64_get_instr (cpu), 9, 5);
6870 unsigned int st = uimm (aarch64_get_instr (cpu), 4, 0);
6872 aarch64_set_FP_double (cpu, st, aarch64_get_FP_double (cpu, rn));
6875 /* 32 bit GReg to Vec move register. */
6877 fgmovs (sim_cpu *cpu)
6879 unsigned int rn = uimm (aarch64_get_instr (cpu), 9, 5);
6880 unsigned int st = uimm (aarch64_get_instr (cpu), 4, 0);
6882 aarch64_set_vec_u32 (cpu, st, 0, aarch64_get_reg_u32 (cpu, rn, NO_SP));
6885 /* 64 bit g to fp move register. */
6887 fgmovd (sim_cpu *cpu)
6889 unsigned int rn = uimm (aarch64_get_instr (cpu), 9, 5);
6890 unsigned int st = uimm (aarch64_get_instr (cpu), 4, 0);
6892 aarch64_set_vec_u64 (cpu, st, 0, aarch64_get_reg_u64 (cpu, rn, NO_SP));
6895 /* 32 bit fp to g move register. */
6897 gfmovs (sim_cpu *cpu)
6899 unsigned int rn = uimm (aarch64_get_instr (cpu), 9, 5);
6900 unsigned int st = uimm (aarch64_get_instr (cpu), 4, 0);
6902 aarch64_set_reg_u64 (cpu, st, NO_SP, aarch64_get_vec_u32 (cpu, rn, 0));
6905 /* 64 bit fp to g move register. */
6907 gfmovd (sim_cpu *cpu)
6909 unsigned int rn = uimm (aarch64_get_instr (cpu), 9, 5);
6910 unsigned int st = uimm (aarch64_get_instr (cpu), 4, 0);
6912 aarch64_set_reg_u64 (cpu, st, NO_SP, aarch64_get_vec_u64 (cpu, rn, 0));
6915 /* FP move immediate
6917 These install an immediate 8 bit value in the target register
6918 where the 8 bits comprise 1 sign bit, 4 bits of fraction and a 3
6922 fmovs (sim_cpu *cpu)
6924 unsigned int sd = uimm (aarch64_get_instr (cpu), 4, 0);
6925 uint32_t imm = uimm (aarch64_get_instr (cpu), 20, 13);
6926 float f = fp_immediate_for_encoding_32 (imm);
6928 aarch64_set_FP_float (cpu, sd, f);
6932 fmovd (sim_cpu *cpu)
6934 unsigned int sd = uimm (aarch64_get_instr (cpu), 4, 0);
6935 uint32_t imm = uimm (aarch64_get_instr (cpu), 20, 13);
6936 double d = fp_immediate_for_encoding_64 (imm);
6938 aarch64_set_FP_double (cpu, sd, d);
6942 dexSimpleFPImmediate (sim_cpu *cpu)
6944 /* instr[31,23] == 00111100
6945 instr[22] == type : single(0)/double(1)
6947 instr[20,13] == imm8
6949 instr[9,5] == imm5 : 00000 ==> PK, ow ==> UNALLOC
6951 uint32_t imm5 = uimm (aarch64_get_instr (cpu), 9, 5);
6953 NYI_assert (31, 23, 0x3C);
6958 if (uimm (aarch64_get_instr (cpu), 22, 22))
6964 /* TODO specific decode and execute for group Load Store. */
6966 /* TODO FP load/store single register (unscaled offset). */
6968 /* TODO load 8 bit unscaled signed 9 bit. */
6969 /* TODO load 16 bit unscaled signed 9 bit. */
6971 /* Load 32 bit unscaled signed 9 bit. */
6973 fldurs (sim_cpu *cpu, int32_t offset)
6975 unsigned int rn = uimm (aarch64_get_instr (cpu), 9, 5);
6976 unsigned int st = uimm (aarch64_get_instr (cpu), 4, 0);
6978 aarch64_set_FP_float (cpu, st, aarch64_get_mem_float
6979 (cpu, aarch64_get_reg_u64 (cpu, rn, SP_OK) + offset));
6982 /* Load 64 bit unscaled signed 9 bit. */
6984 fldurd (sim_cpu *cpu, int32_t offset)
6986 unsigned int rn = uimm (aarch64_get_instr (cpu), 9, 5);
6987 unsigned int st = uimm (aarch64_get_instr (cpu), 4, 0);
6989 aarch64_set_FP_double (cpu, st, aarch64_get_mem_double
6990 (cpu, aarch64_get_reg_u64 (cpu, rn, SP_OK) + offset));
6993 /* Load 128 bit unscaled signed 9 bit. */
6995 fldurq (sim_cpu *cpu, int32_t offset)
6997 unsigned int rn = uimm (aarch64_get_instr (cpu), 9, 5);
6998 unsigned int st = uimm (aarch64_get_instr (cpu), 4, 0);
7000 uint64_t addr = aarch64_get_reg_u64 (cpu, rn, SP_OK) + offset;
7002 aarch64_get_mem_long_double (cpu, addr, & a);
7003 aarch64_set_FP_long_double (cpu, st, a);
7006 /* TODO store 8 bit unscaled signed 9 bit. */
7007 /* TODO store 16 bit unscaled signed 9 bit. */
7012 /* Float absolute value. */
7014 fabss (sim_cpu *cpu)
7016 unsigned sn = uimm (aarch64_get_instr (cpu), 9, 5);
7017 unsigned sd = uimm (aarch64_get_instr (cpu), 4, 0);
7018 float value = aarch64_get_FP_float (cpu, sn);
7020 aarch64_set_FP_float (cpu, sd, fabsf (value));
7023 /* Double absolute value. */
7025 fabcpu (sim_cpu *cpu)
7027 unsigned sn = uimm (aarch64_get_instr (cpu), 9, 5);
7028 unsigned sd = uimm (aarch64_get_instr (cpu), 4, 0);
7029 double value = aarch64_get_FP_double (cpu, sn);
7031 aarch64_set_FP_double (cpu, sd, fabs (value));
7034 /* Float negative value. */
7036 fnegs (sim_cpu *cpu)
7038 unsigned sn = uimm (aarch64_get_instr (cpu), 9, 5);
7039 unsigned sd = uimm (aarch64_get_instr (cpu), 4, 0);
7041 aarch64_set_FP_float (cpu, sd, - aarch64_get_FP_float (cpu, sn));
7044 /* Double negative value. */
7046 fnegd (sim_cpu *cpu)
7048 unsigned sn = uimm (aarch64_get_instr (cpu), 9, 5);
7049 unsigned sd = uimm (aarch64_get_instr (cpu), 4, 0);
7051 aarch64_set_FP_double (cpu, sd, - aarch64_get_FP_double (cpu, sn));
7054 /* Float square root. */
7056 fsqrts (sim_cpu *cpu)
7058 unsigned sn = uimm (aarch64_get_instr (cpu), 9, 5);
7059 unsigned sd = uimm (aarch64_get_instr (cpu), 4, 0);
7061 aarch64_set_FP_float (cpu, sd, sqrt (aarch64_get_FP_float (cpu, sn)));
7064 /* Double square root. */
7066 fsqrtd (sim_cpu *cpu)
7068 unsigned sn = uimm (aarch64_get_instr (cpu), 9, 5);
7069 unsigned sd = uimm (aarch64_get_instr (cpu), 4, 0);
7071 aarch64_set_FP_double (cpu, sd,
7072 sqrt (aarch64_get_FP_double (cpu, sn)));
7075 /* Convert double to float. */
7077 fcvtds (sim_cpu *cpu)
7079 unsigned sn = uimm (aarch64_get_instr (cpu), 9, 5);
7080 unsigned sd = uimm (aarch64_get_instr (cpu), 4, 0);
7082 aarch64_set_FP_float (cpu, sd, (float) aarch64_get_FP_double (cpu, sn));
7085 /* Convert float to double. */
7087 fcvtcpu (sim_cpu *cpu)
7089 unsigned sn = uimm (aarch64_get_instr (cpu), 9, 5);
7090 unsigned sd = uimm (aarch64_get_instr (cpu), 4, 0);
7092 aarch64_set_FP_double (cpu, sd, (double) aarch64_get_FP_float (cpu, sn));
7096 do_FRINT (sim_cpu *cpu)
7098 /* instr[31,23] = 0001 1110 0
7099 instr[22] = single(0)/double(1)
7101 instr[17,15] = rounding mode
7102 instr[14,10] = 10000
7104 instr[4,0] = dest */
7107 unsigned rs = uimm (aarch64_get_instr (cpu), 9, 5);
7108 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
7109 unsigned int rmode = uimm (aarch64_get_instr (cpu), 17, 15);
7111 NYI_assert (31, 23, 0x03C);
7112 NYI_assert (21, 18, 0x9);
7113 NYI_assert (14, 10, 0x10);
7115 if (rmode == 6 || rmode == 7)
7116 /* FIXME: Add support for rmode == 6 exactness check. */
7117 rmode = uimm (aarch64_get_FPSR (cpu), 23, 22);
7119 if (uimm (aarch64_get_instr (cpu), 22, 22))
7121 double val = aarch64_get_FP_double (cpu, rs);
7125 case 0: /* mode N: nearest or even. */
7127 double rval = round (val);
7129 if (val - rval == 0.5)
7131 if (((rval / 2.0) * 2.0) != rval)
7135 aarch64_set_FP_double (cpu, rd, round (val));
7139 case 1: /* mode P: towards +inf. */
7141 aarch64_set_FP_double (cpu, rd, trunc (val));
7143 aarch64_set_FP_double (cpu, rd, round (val));
7146 case 2: /* mode M: towards -inf. */
7148 aarch64_set_FP_double (cpu, rd, round (val));
7150 aarch64_set_FP_double (cpu, rd, trunc (val));
7153 case 3: /* mode Z: towards 0. */
7154 aarch64_set_FP_double (cpu, rd, trunc (val));
7157 case 4: /* mode A: away from 0. */
7158 aarch64_set_FP_double (cpu, rd, round (val));
7161 case 6: /* mode X: use FPCR with exactness check. */
7162 case 7: /* mode I: use FPCR mode. */
7170 val = aarch64_get_FP_float (cpu, rs);
7174 case 0: /* mode N: nearest or even. */
7176 float rval = roundf (val);
7178 if (val - rval == 0.5)
7180 if (((rval / 2.0) * 2.0) != rval)
7184 aarch64_set_FP_float (cpu, rd, rval);
7188 case 1: /* mode P: towards +inf. */
7190 aarch64_set_FP_float (cpu, rd, truncf (val));
7192 aarch64_set_FP_float (cpu, rd, roundf (val));
7195 case 2: /* mode M: towards -inf. */
7197 aarch64_set_FP_float (cpu, rd, truncf (val));
7199 aarch64_set_FP_float (cpu, rd, roundf (val));
7202 case 3: /* mode Z: towards 0. */
7203 aarch64_set_FP_float (cpu, rd, truncf (val));
7206 case 4: /* mode A: away from 0. */
7207 aarch64_set_FP_float (cpu, rd, roundf (val));
7210 case 6: /* mode X: use FPCR with exactness check. */
7211 case 7: /* mode I: use FPCR mode. */
7220 dexSimpleFPDataProc1Source (sim_cpu *cpu)
7222 /* instr[31] ==> M : 0 ==> OK, 1 ==> UNALLOC
7224 instr[29] ==> S : 0 ==> OK, 1 ==> UNALLOC
7227 instr[23,22] ==> type : 00 ==> source is single,
7228 01 ==> source is double
7230 11 ==> UNALLOC or source is half
7232 instr[20,15] ==> opcode : with type 00 or 01
7233 000000 ==> FMOV, 000001 ==> FABS,
7234 000010 ==> FNEG, 000011 ==> FSQRT,
7235 000100 ==> UNALLOC, 000101 ==> FCVT,(to single/double)
7236 000110 ==> UNALLOC, 000111 ==> FCVT (to half)
7237 001000 ==> FRINTN, 001001 ==> FRINTP,
7238 001010 ==> FRINTM, 001011 ==> FRINTZ,
7239 001100 ==> FRINTA, 001101 ==> UNALLOC
7240 001110 ==> FRINTX, 001111 ==> FRINTI
7242 000100 ==> FCVT (half-to-single)
7243 000101 ==> FCVT (half-to-double)
7244 instr[14,10] = 10000. */
7246 uint32_t M_S = (uimm (aarch64_get_instr (cpu), 31, 31) << 1)
7247 | uimm (aarch64_get_instr (cpu), 29, 29);
7248 uint32_t type = uimm (aarch64_get_instr (cpu), 23, 22);
7249 uint32_t opcode = uimm (aarch64_get_instr (cpu), 20, 15);
7256 if (opcode == 4 || opcode == 5)
7308 case 8: /* FRINTN etc. */
7318 case 7: /* FCVT double/single to half precision. */
7327 /* 32 bit signed int to float. */
7329 scvtf32 (sim_cpu *cpu)
7331 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
7332 unsigned sd = uimm (aarch64_get_instr (cpu), 4, 0);
7334 aarch64_set_FP_float
7335 (cpu, sd, (float) aarch64_get_reg_s32 (cpu, rn, NO_SP));
7338 /* signed int to float. */
7340 scvtf (sim_cpu *cpu)
7342 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
7343 unsigned sd = uimm (aarch64_get_instr (cpu), 4, 0);
7345 aarch64_set_FP_float
7346 (cpu, sd, (float) aarch64_get_reg_s64 (cpu, rn, NO_SP));
7349 /* 32 bit signed int to double. */
7351 scvtd32 (sim_cpu *cpu)
7353 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
7354 unsigned sd = uimm (aarch64_get_instr (cpu), 4, 0);
7356 aarch64_set_FP_double
7357 (cpu, sd, (double) aarch64_get_reg_s32 (cpu, rn, NO_SP));
7360 /* signed int to double. */
7362 scvtd (sim_cpu *cpu)
7364 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
7365 unsigned sd = uimm (aarch64_get_instr (cpu), 4, 0);
7367 aarch64_set_FP_double
7368 (cpu, sd, (double) aarch64_get_reg_s64 (cpu, rn, NO_SP));
7371 static const float FLOAT_INT_MAX = (float) INT_MAX;
7372 static const float FLOAT_INT_MIN = (float) INT_MIN;
7373 static const double DOUBLE_INT_MAX = (double) INT_MAX;
7374 static const double DOUBLE_INT_MIN = (double) INT_MIN;
7375 static const float FLOAT_LONG_MAX = (float) LONG_MAX;
7376 static const float FLOAT_LONG_MIN = (float) LONG_MIN;
7377 static const double DOUBLE_LONG_MAX = (double) LONG_MAX;
7378 static const double DOUBLE_LONG_MIN = (double) LONG_MIN;
7380 /* Check for FP exception conditions:
7383 Out of Range raises IO and IX and saturates value
7384 Denormal raises ID and IX and sets to zero. */
7385 #define RAISE_EXCEPTIONS(F, VALUE, FTYPE, ITYPE) \
7388 switch (fpclassify (F)) \
7392 aarch64_set_FPSR (cpu, IO); \
7394 VALUE = ITYPE##_MAX; \
7396 VALUE = ITYPE##_MIN; \
7400 if (F >= FTYPE##_##ITYPE##_MAX) \
7402 aarch64_set_FPSR_bits (cpu, IO | IX, IO | IX); \
7403 VALUE = ITYPE##_MAX; \
7405 else if (F <= FTYPE##_##ITYPE##_MIN) \
7407 aarch64_set_FPSR_bits (cpu, IO | IX, IO | IX); \
7408 VALUE = ITYPE##_MIN; \
7412 case FP_SUBNORMAL: \
7413 aarch64_set_FPSR_bits (cpu, IO | IX | ID, IX | ID); \
7425 /* 32 bit convert float to signed int truncate towards zero. */
7427 fcvtszs32 (sim_cpu *cpu)
7429 unsigned sn = uimm (aarch64_get_instr (cpu), 9, 5);
7430 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
7431 /* TODO : check that this rounds toward zero. */
7432 float f = aarch64_get_FP_float (cpu, sn);
7433 int32_t value = (int32_t) f;
7435 RAISE_EXCEPTIONS (f, value, FLOAT, INT);
7437 /* Avoid sign extension to 64 bit. */
7438 aarch64_set_reg_u64 (cpu, rd, NO_SP, (uint32_t) value);
7441 /* 64 bit convert float to signed int truncate towards zero. */
7443 fcvtszs (sim_cpu *cpu)
7445 unsigned sn = uimm (aarch64_get_instr (cpu), 9, 5);
7446 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
7447 float f = aarch64_get_FP_float (cpu, sn);
7448 int64_t value = (int64_t) f;
7450 RAISE_EXCEPTIONS (f, value, FLOAT, LONG);
7452 aarch64_set_reg_s64 (cpu, rd, NO_SP, value);
7455 /* 32 bit convert double to signed int truncate towards zero. */
7457 fcvtszd32 (sim_cpu *cpu)
7459 unsigned sn = uimm (aarch64_get_instr (cpu), 9, 5);
7460 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
7461 /* TODO : check that this rounds toward zero. */
7462 double d = aarch64_get_FP_double (cpu, sn);
7463 int32_t value = (int32_t) d;
7465 RAISE_EXCEPTIONS (d, value, DOUBLE, INT);
7467 /* Avoid sign extension to 64 bit. */
7468 aarch64_set_reg_u64 (cpu, rd, NO_SP, (uint32_t) value);
7471 /* 64 bit convert double to signed int truncate towards zero. */
7473 fcvtszd (sim_cpu *cpu)
7475 unsigned sn = uimm (aarch64_get_instr (cpu), 9, 5);
7476 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
7477 /* TODO : check that this rounds toward zero. */
7478 double d = aarch64_get_FP_double (cpu, sn);
7481 value = (int64_t) d;
7483 RAISE_EXCEPTIONS (d, value, DOUBLE, LONG);
7485 aarch64_set_reg_s64 (cpu, rd, NO_SP, value);
7489 do_fcvtzu (sim_cpu *cpu)
7491 /* instr[31] = size: 32-bit (0), 64-bit (1)
7492 instr[30,23] = 00111100
7493 instr[22] = type: single (0)/ double (1)
7494 instr[21] = enable (0)/disable(1) precision
7495 instr[20,16] = 11001
7496 instr[15,10] = precision
7500 unsigned rs = uimm (aarch64_get_instr (cpu), 9, 5);
7501 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
7503 NYI_assert (30, 23, 0x3C);
7504 NYI_assert (20, 16, 0x19);
7506 if (uimm (aarch64_get_instr (cpu), 21, 21) != 1)
7507 /* Convert to fixed point. */
7510 if (uimm (aarch64_get_instr (cpu), 31, 31))
7512 /* Convert to unsigned 64-bit integer. */
7513 if (uimm (aarch64_get_instr (cpu), 22, 22))
7515 double d = aarch64_get_FP_double (cpu, rs);
7516 uint64_t value = (uint64_t) d;
7518 /* Do not raise an exception if we have reached ULONG_MAX. */
7519 if (value != (1UL << 63))
7520 RAISE_EXCEPTIONS (d, value, DOUBLE, LONG);
7522 aarch64_set_reg_u64 (cpu, rd, NO_SP, value);
7526 float f = aarch64_get_FP_float (cpu, rs);
7527 uint64_t value = (uint64_t) f;
7529 /* Do not raise an exception if we have reached ULONG_MAX. */
7530 if (value != (1UL << 63))
7531 RAISE_EXCEPTIONS (f, value, FLOAT, LONG);
7533 aarch64_set_reg_u64 (cpu, rd, NO_SP, value);
7540 /* Convert to unsigned 32-bit integer. */
7541 if (uimm (aarch64_get_instr (cpu), 22, 22))
7543 double d = aarch64_get_FP_double (cpu, rs);
7545 value = (uint32_t) d;
7546 /* Do not raise an exception if we have reached UINT_MAX. */
7547 if (value != (1UL << 31))
7548 RAISE_EXCEPTIONS (d, value, DOUBLE, INT);
7552 float f = aarch64_get_FP_float (cpu, rs);
7554 value = (uint32_t) f;
7555 /* Do not raise an exception if we have reached UINT_MAX. */
7556 if (value != (1UL << 31))
7557 RAISE_EXCEPTIONS (f, value, FLOAT, INT);
7560 aarch64_set_reg_u64 (cpu, rd, NO_SP, value);
7565 do_UCVTF (sim_cpu *cpu)
7567 /* instr[31] = size: 32-bit (0), 64-bit (1)
7568 instr[30,23] = 001 1110 0
7569 instr[22] = type: single (0)/ double (1)
7570 instr[21] = enable (0)/disable(1) precision
7571 instr[20,16] = 0 0011
7572 instr[15,10] = precision
7576 unsigned rs = uimm (aarch64_get_instr (cpu), 9, 5);
7577 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
7579 NYI_assert (30, 23, 0x3C);
7580 NYI_assert (20, 16, 0x03);
7582 if (uimm (aarch64_get_instr (cpu), 21, 21) != 1)
7585 /* FIXME: Add exception raising. */
7586 if (uimm (aarch64_get_instr (cpu), 31, 31))
7588 uint64_t value = aarch64_get_reg_u64 (cpu, rs, NO_SP);
7590 if (uimm (aarch64_get_instr (cpu), 22, 22))
7591 aarch64_set_FP_double (cpu, rd, (double) value);
7593 aarch64_set_FP_float (cpu, rd, (float) value);
7597 uint32_t value = aarch64_get_reg_u32 (cpu, rs, NO_SP);
7599 if (uimm (aarch64_get_instr (cpu), 22, 22))
7600 aarch64_set_FP_double (cpu, rd, (double) value);
7602 aarch64_set_FP_float (cpu, rd, (float) value);
7607 float_vector_move (sim_cpu *cpu)
7609 /* instr[31,17] == 100 1111 0101 0111
7610 instr[16] ==> direction 0=> to GR, 1=> from GR
7612 instr[9,5] ==> source
7613 instr[4,0] ==> dest. */
7615 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
7616 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
7618 NYI_assert (31, 17, 0x4F57);
7620 if (uimm (aarch64_get_instr (cpu), 15, 10) != 0)
7623 if (uimm (aarch64_get_instr (cpu), 16, 16))
7624 aarch64_set_vec_u64 (cpu, rd, 1, aarch64_get_reg_u64 (cpu, rn, NO_SP));
7626 aarch64_set_reg_u64 (cpu, rd, NO_SP, aarch64_get_vec_u64 (cpu, rn, 1));
7630 dexSimpleFPIntegerConvert (sim_cpu *cpu)
7632 /* instr[31] = size : 0 ==> 32 bit, 1 ==> 64 bit
7634 instr[29] = S : 0 ==> OK, 1 ==> UNALLOC
7637 instr[23,22] = type : 00 ==> single, 01 ==> double, 1x ==> UNALLOC
7639 instr[20,19] = rmode
7640 instr[18,16] = opcode
7641 instr[15,10] = 10 0000 */
7643 uint32_t rmode_opcode;
7649 if (uimm (aarch64_get_instr (cpu), 31, 17) == 0x4F57)
7651 float_vector_move (cpu);
7655 size = uimm (aarch64_get_instr (cpu), 31, 31);
7656 S = uimm (aarch64_get_instr (cpu), 29, 29);
7660 type = uimm (aarch64_get_instr (cpu), 23, 22);
7664 rmode_opcode = uimm (aarch64_get_instr (cpu), 20, 16);
7665 size_type = (size << 1) | type; /* 0==32f, 1==32d, 2==64f, 3==64d. */
7667 switch (rmode_opcode)
7669 case 2: /* SCVTF. */
7672 case 0: scvtf32 (cpu); return;
7673 case 1: scvtd32 (cpu); return;
7674 case 2: scvtf (cpu); return;
7675 case 3: scvtd (cpu); return;
7680 case 6: /* FMOV GR, Vec. */
7683 case 0: gfmovs (cpu); return;
7684 case 3: gfmovd (cpu); return;
7685 default: HALT_UNALLOC;
7688 case 7: /* FMOV vec, GR. */
7691 case 0: fgmovs (cpu); return;
7692 case 3: fgmovd (cpu); return;
7693 default: HALT_UNALLOC;
7696 case 24: /* FCVTZS. */
7699 case 0: fcvtszs32 (cpu); return;
7700 case 1: fcvtszd32 (cpu); return;
7701 case 2: fcvtszs (cpu); return;
7702 case 3: fcvtszd (cpu); return;
7703 default: HALT_UNREACHABLE;
7706 case 25: do_fcvtzu (cpu); return;
7707 case 3: do_UCVTF (cpu); return;
7709 case 0: /* FCVTNS. */
7710 case 1: /* FCVTNU. */
7711 case 4: /* FCVTAS. */
7712 case 5: /* FCVTAU. */
7713 case 8: /* FCVPTS. */
7714 case 9: /* FCVTPU. */
7715 case 16: /* FCVTMS. */
7716 case 17: /* FCVTMU. */
7723 set_flags_for_float_compare (sim_cpu *cpu, float fvalue1, float fvalue2)
7727 if (isnan (fvalue1) || isnan (fvalue2))
7731 float result = fvalue1 - fvalue2;
7735 else if (result < 0)
7737 else /* (result > 0). */
7741 aarch64_set_CPSR (cpu, flags);
7745 fcmps (sim_cpu *cpu)
7747 unsigned sm = uimm (aarch64_get_instr (cpu), 20, 16);
7748 unsigned sn = uimm (aarch64_get_instr (cpu), 9, 5);
7750 float fvalue1 = aarch64_get_FP_float (cpu, sn);
7751 float fvalue2 = aarch64_get_FP_float (cpu, sm);
7753 set_flags_for_float_compare (cpu, fvalue1, fvalue2);
7756 /* Float compare to zero -- Invalid Operation exception
7757 only on signaling NaNs. */
7759 fcmpzs (sim_cpu *cpu)
7761 unsigned sn = uimm (aarch64_get_instr (cpu), 9, 5);
7762 float fvalue1 = aarch64_get_FP_float (cpu, sn);
7764 set_flags_for_float_compare (cpu, fvalue1, 0.0f);
7767 /* Float compare -- Invalid Operation exception on all NaNs. */
7769 fcmpes (sim_cpu *cpu)
7771 unsigned sm = uimm (aarch64_get_instr (cpu), 20, 16);
7772 unsigned sn = uimm (aarch64_get_instr (cpu), 9, 5);
7774 float fvalue1 = aarch64_get_FP_float (cpu, sn);
7775 float fvalue2 = aarch64_get_FP_float (cpu, sm);
7777 set_flags_for_float_compare (cpu, fvalue1, fvalue2);
7780 /* Float compare to zero -- Invalid Operation exception on all NaNs. */
7782 fcmpzes (sim_cpu *cpu)
7784 unsigned sn = uimm (aarch64_get_instr (cpu), 9, 5);
7785 float fvalue1 = aarch64_get_FP_float (cpu, sn);
7787 set_flags_for_float_compare (cpu, fvalue1, 0.0f);
7791 set_flags_for_double_compare (sim_cpu *cpu, double dval1, double dval2)
7795 if (isnan (dval1) || isnan (dval2))
7799 double result = dval1 - dval2;
7803 else if (result < 0)
7805 else /* (result > 0). */
7809 aarch64_set_CPSR (cpu, flags);
7812 /* Double compare -- Invalid Operation exception only on signaling NaNs. */
7814 fcmpd (sim_cpu *cpu)
7816 unsigned sm = uimm (aarch64_get_instr (cpu), 20, 16);
7817 unsigned sn = uimm (aarch64_get_instr (cpu), 9, 5);
7819 double dvalue1 = aarch64_get_FP_double (cpu, sn);
7820 double dvalue2 = aarch64_get_FP_double (cpu, sm);
7822 set_flags_for_double_compare (cpu, dvalue1, dvalue2);
7825 /* Double compare to zero -- Invalid Operation exception
7826 only on signaling NaNs. */
7828 fcmpzd (sim_cpu *cpu)
7830 unsigned sn = uimm (aarch64_get_instr (cpu), 9, 5);
7831 double dvalue1 = aarch64_get_FP_double (cpu, sn);
7833 set_flags_for_double_compare (cpu, dvalue1, 0.0);
7836 /* Double compare -- Invalid Operation exception on all NaNs. */
7838 fcmped (sim_cpu *cpu)
7840 unsigned sm = uimm (aarch64_get_instr (cpu), 20, 16);
7841 unsigned sn = uimm (aarch64_get_instr (cpu), 9, 5);
7843 double dvalue1 = aarch64_get_FP_double (cpu, sn);
7844 double dvalue2 = aarch64_get_FP_double (cpu, sm);
7846 set_flags_for_double_compare (cpu, dvalue1, dvalue2);
7849 /* Double compare to zero -- Invalid Operation exception on all NaNs. */
7851 fcmpzed (sim_cpu *cpu)
7853 unsigned sn = uimm (aarch64_get_instr (cpu), 9, 5);
7854 double dvalue1 = aarch64_get_FP_double (cpu, sn);
7856 set_flags_for_double_compare (cpu, dvalue1, 0.0);
7860 dexSimpleFPCompare (sim_cpu *cpu)
7862 /* assert instr[28,25] == 1111
7863 instr[30:24:21:13,10] = 0011000
7864 instr[31] = M : 0 ==> OK, 1 ==> UNALLOC
7865 instr[29] ==> S : 0 ==> OK, 1 ==> UNALLOC
7866 instr[23,22] ==> type : 0 ==> single, 01 ==> double, 1x ==> UNALLOC
7867 instr[15,14] ==> op : 00 ==> OK, ow ==> UNALLOC
7868 instr[4,0] ==> opcode2 : 00000 ==> FCMP, 10000 ==> FCMPE,
7869 01000 ==> FCMPZ, 11000 ==> FCMPEZ,
7872 uint32_t M_S = (uimm (aarch64_get_instr (cpu), 31, 31) << 1)
7873 | uimm (aarch64_get_instr (cpu), 29, 29);
7874 uint32_t type = uimm (aarch64_get_instr (cpu), 23, 22);
7875 uint32_t op = uimm (aarch64_get_instr (cpu), 15, 14);
7876 uint32_t op2_2_0 = uimm (aarch64_get_instr (cpu), 2, 0);
7890 /* dispatch on type and top 2 bits of opcode. */
7891 dispatch = (type << 2) | uimm (aarch64_get_instr (cpu), 4, 3);
7895 case 0: fcmps (cpu); return;
7896 case 1: fcmpzs (cpu); return;
7897 case 2: fcmpes (cpu); return;
7898 case 3: fcmpzes (cpu); return;
7899 case 4: fcmpd (cpu); return;
7900 case 5: fcmpzd (cpu); return;
7901 case 6: fcmped (cpu); return;
7902 case 7: fcmpzed (cpu); return;
7903 default: HALT_UNREACHABLE;
7908 do_scalar_FADDP (sim_cpu *cpu)
7910 /* instr [31,23] = 011111100
7911 instr [22] = single(0)/double(1)
7912 instr [21,10] = 1100 0011 0110
7914 instr [4,0] = Fd. */
7916 unsigned Fn = uimm (aarch64_get_instr (cpu), 9, 5);
7917 unsigned Fd = uimm (aarch64_get_instr (cpu), 4, 0);
7919 NYI_assert (31, 23, 0x0FC);
7920 NYI_assert (21, 10, 0xC36);
7922 if (uimm (aarch64_get_instr (cpu), 22, 22))
7924 double val1 = aarch64_get_vec_double (cpu, Fn, 0);
7925 double val2 = aarch64_get_vec_double (cpu, Fn, 1);
7927 aarch64_set_FP_double (cpu, Fd, val1 + val2);
7931 float val1 = aarch64_get_vec_float (cpu, Fn, 0);
7932 float val2 = aarch64_get_vec_float (cpu, Fn, 1);
7934 aarch64_set_FP_float (cpu, Fd, val1 + val2);
7938 /* Floating point absolute difference. */
7941 do_scalar_FABD (sim_cpu *cpu)
7943 /* instr [31,23] = 0111 1110 1
7944 instr [22] = float(0)/double(1)
7947 instr [15,10] = 1101 01
7949 instr [4, 0] = Rd. */
7951 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
7952 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
7953 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
7955 NYI_assert (31, 23, 0x0FD);
7956 NYI_assert (21, 21, 1);
7957 NYI_assert (15, 10, 0x35);
7959 if (uimm (aarch64_get_instr (cpu), 22, 22))
7960 aarch64_set_FP_double (cpu, rd,
7961 fabs (aarch64_get_FP_double (cpu, rn)
7962 - aarch64_get_FP_double (cpu, rm)));
7964 aarch64_set_FP_float (cpu, rd,
7965 fabsf (aarch64_get_FP_float (cpu, rn)
7966 - aarch64_get_FP_float (cpu, rm)));
7970 do_scalar_CMGT (sim_cpu *cpu)
7972 /* instr [31,21] = 0101 1110 111
7974 instr [15,10] = 00 1101
7976 instr [4, 0] = Rd. */
7978 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
7979 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
7980 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
7982 NYI_assert (31, 21, 0x2F7);
7983 NYI_assert (15, 10, 0x0D);
7985 aarch64_set_vec_u64 (cpu, rd, 0,
7986 aarch64_get_vec_u64 (cpu, rn, 0) >
7987 aarch64_get_vec_u64 (cpu, rm, 0) ? -1L : 0L);
7991 do_scalar_USHR (sim_cpu *cpu)
7993 /* instr [31,23] = 0111 1111 0
7994 instr [22,16] = shift amount
7995 instr [15,10] = 0000 01
7997 instr [4, 0] = Rd. */
7999 unsigned amount = 128 - uimm (aarch64_get_instr (cpu), 22, 16);
8000 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
8001 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
8003 NYI_assert (31, 23, 0x0FE);
8004 NYI_assert (15, 10, 0x01);
8006 aarch64_set_vec_u64 (cpu, rd, 0,
8007 aarch64_get_vec_u64 (cpu, rn, 0) >> amount);
8011 do_scalar_SHL (sim_cpu *cpu)
8013 /* instr [31,23] = 0111 1101 0
8014 instr [22,16] = shift amount
8015 instr [15,10] = 0101 01
8017 instr [4, 0] = Rd. */
8019 unsigned amount = uimm (aarch64_get_instr (cpu), 22, 16) - 64;
8020 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
8021 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
8023 NYI_assert (31, 23, 0x0BE);
8024 NYI_assert (15, 10, 0x15);
8026 if (uimm (aarch64_get_instr (cpu), 22, 22) == 0)
8029 aarch64_set_vec_u64 (cpu, rd, 0,
8030 aarch64_get_vec_u64 (cpu, rn, 0) << amount);
8033 /* FCMEQ FCMGT FCMGE. */
8035 do_scalar_FCM (sim_cpu *cpu)
8037 /* instr [31,30] = 01
8039 instr [28,24] = 1 1110
8044 instr [15,12] = 1110
8048 instr [4, 0] = Rd. */
8050 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
8051 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
8052 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
8053 unsigned EUac = (uimm (aarch64_get_instr (cpu), 23, 23) << 2)
8054 | (uimm (aarch64_get_instr (cpu), 29, 29) << 1)
8055 | uimm (aarch64_get_instr (cpu), 11, 11);
8060 NYI_assert (31, 30, 1);
8061 NYI_assert (28, 24, 0x1E);
8062 NYI_assert (21, 21, 1);
8063 NYI_assert (15, 12, 0xE);
8064 NYI_assert (10, 10, 1);
8066 if (uimm (aarch64_get_instr (cpu), 22, 22))
8068 double val1 = aarch64_get_FP_double (cpu, rn);
8069 double val2 = aarch64_get_FP_double (cpu, rm);
8074 result = val1 == val2;
8082 result = val1 >= val2;
8090 result = val1 > val2;
8097 aarch64_set_vec_u32 (cpu, rd, 0, result ? -1 : 0);
8101 val1 = aarch64_get_FP_float (cpu, rn);
8102 val2 = aarch64_get_FP_float (cpu, rm);
8107 result = val1 == val2;
8111 val1 = fabsf (val1);
8112 val2 = fabsf (val2);
8115 result = val1 >= val2;
8119 val1 = fabsf (val1);
8120 val2 = fabsf (val2);
8123 result = val1 > val2;
8130 aarch64_set_vec_u32 (cpu, rd, 0, result ? -1 : 0);
8133 /* An alias of DUP. */
8135 do_scalar_MOV (sim_cpu *cpu)
8137 /* instr [31,21] = 0101 1110 000
8138 instr [20,16] = imm5
8139 instr [15,10] = 0000 01
8141 instr [4, 0] = Rd. */
8143 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
8144 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
8147 NYI_assert (31, 21, 0x2F0);
8148 NYI_assert (15, 10, 0x01);
8150 if (uimm (aarch64_get_instr (cpu), 16, 16))
8153 index = uimm (aarch64_get_instr (cpu), 20, 17);
8155 (cpu, rd, 0, aarch64_get_vec_u8 (cpu, rn, index));
8157 else if (uimm (aarch64_get_instr (cpu), 17, 17))
8160 index = uimm (aarch64_get_instr (cpu), 20, 18);
8162 (cpu, rd, 0, aarch64_get_vec_u16 (cpu, rn, index));
8164 else if (uimm (aarch64_get_instr (cpu), 18, 18))
8167 index = uimm (aarch64_get_instr (cpu), 20, 19);
8169 (cpu, rd, 0, aarch64_get_vec_u32 (cpu, rn, index));
8171 else if (uimm (aarch64_get_instr (cpu), 19, 19))
8174 index = uimm (aarch64_get_instr (cpu), 20, 20);
8176 (cpu, rd, 0, aarch64_get_vec_u64 (cpu, rn, index));
8183 do_double_add (sim_cpu *cpu)
8185 /* instr [28,25] = 1111. */
8192 switch (uimm (aarch64_get_instr (cpu), 31, 23))
8195 switch (uimm (aarch64_get_instr (cpu), 15, 10))
8197 case 0x01: do_scalar_MOV (cpu); return;
8198 case 0x39: do_scalar_FCM (cpu); return;
8199 case 0x3B: do_scalar_FCM (cpu); return;
8203 case 0xBE: do_scalar_SHL (cpu); return;
8206 switch (uimm (aarch64_get_instr (cpu), 15, 10))
8208 case 0x36: do_scalar_FADDP (cpu); return;
8209 case 0x39: do_scalar_FCM (cpu); return;
8210 case 0x3B: do_scalar_FCM (cpu); return;
8215 switch (uimm (aarch64_get_instr (cpu), 15, 10))
8217 case 0x0D: do_scalar_CMGT (cpu); return;
8218 case 0x35: do_scalar_FABD (cpu); return;
8219 case 0x39: do_scalar_FCM (cpu); return;
8220 case 0x3B: do_scalar_FCM (cpu); return;
8225 case 0xFE: do_scalar_USHR (cpu); return;
8230 /* instr [31,21] = 0101 1110 111
8232 instr [15,10] = 1000 01
8234 instr [4,0] = Fd. */
8235 if (uimm (aarch64_get_instr (cpu), 31, 21) != 0x2F7
8236 || uimm (aarch64_get_instr (cpu), 15, 10) != 0x21)
8239 Fd = uimm (aarch64_get_instr (cpu), 4, 0);
8240 Fm = uimm (aarch64_get_instr (cpu), 9, 5);
8241 Fn = uimm (aarch64_get_instr (cpu), 20, 16);
8243 val1 = aarch64_get_FP_double (cpu, Fm);
8244 val2 = aarch64_get_FP_double (cpu, Fn);
8246 aarch64_set_FP_double (cpu, Fd, val1 + val2);
8250 dexAdvSIMD1 (sim_cpu *cpu)
8252 /* instr [28,25] = 1 111. */
8254 /* we are currently only interested in the basic
8255 scalar fp routines which all have bit 30 = 0. */
8256 if (uimm (aarch64_get_instr (cpu), 30, 30))
8257 do_double_add (cpu);
8259 /* instr[24] is set for FP data processing 3-source and clear for
8260 all other basic scalar fp instruction groups. */
8261 else if (uimm (aarch64_get_instr (cpu), 24, 24))
8262 dexSimpleFPDataProc3Source (cpu);
8264 /* instr[21] is clear for floating <-> fixed conversions and set for
8265 all other basic scalar fp instruction groups. */
8266 else if (!uimm (aarch64_get_instr (cpu), 21, 21))
8267 dexSimpleFPFixedConvert (cpu);
8269 /* instr[11,10] : 01 ==> cond compare, 10 ==> Data Proc 2 Source
8270 11 ==> cond select, 00 ==> other. */
8272 switch (uimm (aarch64_get_instr (cpu), 11, 10))
8274 case 1: dexSimpleFPCondCompare (cpu); return;
8275 case 2: dexSimpleFPDataProc2Source (cpu); return;
8276 case 3: dexSimpleFPCondSelect (cpu); return;
8279 /* Now an ordered cascade of tests.
8280 FP immediate has aarch64_get_instr (cpu)[12] == 1.
8281 FP compare has aarch64_get_instr (cpu)[13] == 1.
8282 FP Data Proc 1 Source has aarch64_get_instr (cpu)[14] == 1.
8283 FP floating <--> integer conversions has aarch64_get_instr (cpu)[15] == 0. */
8284 if (uimm (aarch64_get_instr (cpu), 12, 12))
8285 dexSimpleFPImmediate (cpu);
8287 else if (uimm (aarch64_get_instr (cpu), 13, 13))
8288 dexSimpleFPCompare (cpu);
8290 else if (uimm (aarch64_get_instr (cpu), 14, 14))
8291 dexSimpleFPDataProc1Source (cpu);
8293 else if (!uimm (aarch64_get_instr (cpu), 15, 15))
8294 dexSimpleFPIntegerConvert (cpu);
8297 /* If we get here then instr[15] == 1 which means UNALLOC. */
8302 /* PC relative addressing. */
8305 pcadr (sim_cpu *cpu)
8307 /* instr[31] = op : 0 ==> ADR, 1 ==> ADRP
8308 instr[30,29] = immlo
8309 instr[23,5] = immhi. */
8311 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
8312 uint32_t isPage = uimm (aarch64_get_instr (cpu), 31, 31);
8313 union { int64_t u64; uint64_t s64; } imm;
8316 imm.s64 = simm64 (aarch64_get_instr (cpu), 23, 5);
8318 offset = (offset << 2) | uimm (aarch64_get_instr (cpu), 30, 29);
8320 address = aarch64_get_PC (cpu);
8328 aarch64_set_reg_u64 (cpu, rd, NO_SP, address + offset);
8331 /* Specific decode and execute for group Data Processing Immediate. */
8334 dexPCRelAddressing (sim_cpu *cpu)
8336 /* assert instr[28,24] = 10000. */
8340 /* Immediate logical.
8341 The bimm32/64 argument is constructed by replicating a 2, 4, 8,
8342 16, 32 or 64 bit sequence pulled out at decode and possibly
8345 N.B. the output register (dest) can normally be Xn or SP
8346 the exception occurs for flag setting instructions which may
8347 only use Xn for the output (dest). The input register can
8350 /* 32 bit and immediate. */
8352 and32 (sim_cpu *cpu, uint32_t bimm)
8354 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
8355 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
8357 aarch64_set_reg_u64 (cpu, rd, SP_OK,
8358 aarch64_get_reg_u32 (cpu, rn, NO_SP) & bimm);
8361 /* 64 bit and immediate. */
8363 and64 (sim_cpu *cpu, uint64_t bimm)
8365 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
8366 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
8368 aarch64_set_reg_u64 (cpu, rd, SP_OK,
8369 aarch64_get_reg_u64 (cpu, rn, NO_SP) & bimm);
8372 /* 32 bit and immediate set flags. */
8374 ands32 (sim_cpu *cpu, uint32_t bimm)
8376 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
8377 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
8379 uint32_t value1 = aarch64_get_reg_u32 (cpu, rn, NO_SP);
8380 uint32_t value2 = bimm;
8382 aarch64_set_reg_u64 (cpu, rd, NO_SP, value1 & value2);
8383 set_flags_for_binop32 (cpu, value1 & value2);
8386 /* 64 bit and immediate set flags. */
8388 ands64 (sim_cpu *cpu, uint64_t bimm)
8390 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
8391 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
8393 uint64_t value1 = aarch64_get_reg_u64 (cpu, rn, NO_SP);
8394 uint64_t value2 = bimm;
8396 aarch64_set_reg_u64 (cpu, rd, NO_SP, value1 & value2);
8397 set_flags_for_binop64 (cpu, value1 & value2);
8400 /* 32 bit exclusive or immediate. */
8402 eor32 (sim_cpu *cpu, uint32_t bimm)
8404 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
8405 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
8407 aarch64_set_reg_u64 (cpu, rd, SP_OK,
8408 aarch64_get_reg_u32 (cpu, rn, NO_SP) ^ bimm);
8411 /* 64 bit exclusive or immediate. */
8413 eor64 (sim_cpu *cpu, uint64_t bimm)
8415 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
8416 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
8418 aarch64_set_reg_u64 (cpu, rd, SP_OK,
8419 aarch64_get_reg_u64 (cpu, rn, NO_SP) ^ bimm);
8422 /* 32 bit or immediate. */
8424 orr32 (sim_cpu *cpu, uint32_t bimm)
8426 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
8427 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
8429 aarch64_set_reg_u64 (cpu, rd, SP_OK,
8430 aarch64_get_reg_u32 (cpu, rn, NO_SP) | bimm);
8433 /* 64 bit or immediate. */
8435 orr64 (sim_cpu *cpu, uint64_t bimm)
8437 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
8438 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
8440 aarch64_set_reg_u64 (cpu, rd, SP_OK,
8441 aarch64_get_reg_u64 (cpu, rn, NO_SP) | bimm);
8444 /* Logical shifted register.
8445 These allow an optional LSL, ASR, LSR or ROR to the second source
8446 register with a count up to the register bit count.
8447 N.B register args may not be SP. */
8449 /* 32 bit AND shifted register. */
8451 and32_shift (sim_cpu *cpu, Shift shift, uint32_t count)
8453 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
8454 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
8455 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
8458 (cpu, rd, NO_SP, aarch64_get_reg_u32 (cpu, rn, NO_SP)
8459 & shifted32 (aarch64_get_reg_u32 (cpu, rm, NO_SP), shift, count));
8462 /* 64 bit AND shifted register. */
8464 and64_shift (sim_cpu *cpu, Shift shift, uint32_t count)
8466 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
8467 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
8468 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
8471 (cpu, rd, NO_SP, aarch64_get_reg_u64 (cpu, rn, NO_SP)
8472 & shifted64 (aarch64_get_reg_u64 (cpu, rm, NO_SP), shift, count));
8475 /* 32 bit AND shifted register setting flags. */
8477 ands32_shift (sim_cpu *cpu, Shift shift, uint32_t count)
8479 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
8480 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
8481 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
8483 uint32_t value1 = aarch64_get_reg_u32 (cpu, rn, NO_SP);
8484 uint32_t value2 = shifted32 (aarch64_get_reg_u32 (cpu, rm, NO_SP),
8487 aarch64_set_reg_u64 (cpu, rd, NO_SP, value1 & value2);
8488 set_flags_for_binop32 (cpu, value1 & value2);
8491 /* 64 bit AND shifted register setting flags. */
8493 ands64_shift (sim_cpu *cpu, Shift shift, uint32_t count)
8495 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
8496 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
8497 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
8499 uint64_t value1 = aarch64_get_reg_u64 (cpu, rn, NO_SP);
8500 uint64_t value2 = shifted64 (aarch64_get_reg_u64 (cpu, rm, NO_SP),
8503 aarch64_set_reg_u64 (cpu, rd, NO_SP, value1 & value2);
8504 set_flags_for_binop64 (cpu, value1 & value2);
8507 /* 32 bit BIC shifted register. */
8509 bic32_shift (sim_cpu *cpu, Shift shift, uint32_t count)
8511 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
8512 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
8513 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
8516 (cpu, rd, NO_SP, aarch64_get_reg_u32 (cpu, rn, NO_SP)
8517 & ~ shifted32 (aarch64_get_reg_u32 (cpu, rm, NO_SP), shift, count));
8520 /* 64 bit BIC shifted register. */
8522 bic64_shift (sim_cpu *cpu, Shift shift, uint32_t count)
8524 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
8525 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
8526 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
8529 (cpu, rd, NO_SP, aarch64_get_reg_u64 (cpu, rn, NO_SP)
8530 & ~ shifted64 (aarch64_get_reg_u64 (cpu, rm, NO_SP), shift, count));
8533 /* 32 bit BIC shifted register setting flags. */
8535 bics32_shift (sim_cpu *cpu, Shift shift, uint32_t count)
8537 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
8538 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
8539 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
8541 uint32_t value1 = aarch64_get_reg_u32 (cpu, rn, NO_SP);
8542 uint32_t value2 = ~ shifted32 (aarch64_get_reg_u32 (cpu, rm, NO_SP),
8545 aarch64_set_reg_u64 (cpu, rd, NO_SP, value1 & value2);
8546 set_flags_for_binop32 (cpu, value1 & value2);
8549 /* 64 bit BIC shifted register setting flags. */
8551 bics64_shift (sim_cpu *cpu, Shift shift, uint32_t count)
8553 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
8554 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
8555 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
8557 uint64_t value1 = aarch64_get_reg_u64 (cpu, rn, NO_SP);
8558 uint64_t value2 = ~ shifted64 (aarch64_get_reg_u64 (cpu, rm, NO_SP),
8561 aarch64_set_reg_u64 (cpu, rd, NO_SP, value1 & value2);
8562 set_flags_for_binop64 (cpu, value1 & value2);
8565 /* 32 bit EON shifted register. */
8567 eon32_shift (sim_cpu *cpu, Shift shift, uint32_t count)
8569 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
8570 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
8571 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
8574 (cpu, rd, NO_SP, aarch64_get_reg_u32 (cpu, rn, NO_SP)
8575 ^ ~ shifted32 (aarch64_get_reg_u32 (cpu, rm, NO_SP), shift, count));
8578 /* 64 bit EON shifted register. */
8580 eon64_shift (sim_cpu *cpu, Shift shift, uint32_t count)
8582 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
8583 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
8584 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
8587 (cpu, rd, NO_SP, aarch64_get_reg_u64 (cpu, rn, NO_SP)
8588 ^ ~ shifted64 (aarch64_get_reg_u64 (cpu, rm, NO_SP), shift, count));
8591 /* 32 bit EOR shifted register. */
8593 eor32_shift (sim_cpu *cpu, Shift shift, uint32_t count)
8595 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
8596 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
8597 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
8600 (cpu, rd, NO_SP, aarch64_get_reg_u32 (cpu, rn, NO_SP)
8601 ^ shifted32 (aarch64_get_reg_u32 (cpu, rm, NO_SP), shift, count));
8604 /* 64 bit EOR shifted register. */
8606 eor64_shift (sim_cpu *cpu, Shift shift, uint32_t count)
8608 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
8609 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
8610 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
8613 (cpu, rd, NO_SP, aarch64_get_reg_u64 (cpu, rn, NO_SP)
8614 ^ shifted64 (aarch64_get_reg_u64 (cpu, rm, NO_SP), shift, count));
8617 /* 32 bit ORR shifted register. */
8619 orr32_shift (sim_cpu *cpu, Shift shift, uint32_t count)
8621 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
8622 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
8623 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
8626 (cpu, rd, NO_SP, aarch64_get_reg_u32 (cpu, rn, NO_SP)
8627 | shifted32 (aarch64_get_reg_u32 (cpu, rm, NO_SP), shift, count));
8630 /* 64 bit ORR shifted register. */
8632 orr64_shift (sim_cpu *cpu, Shift shift, uint32_t count)
8634 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
8635 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
8636 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
8639 (cpu, rd, NO_SP, aarch64_get_reg_u64 (cpu, rn, NO_SP)
8640 | shifted64 (aarch64_get_reg_u64 (cpu, rm, NO_SP), shift, count));
8643 /* 32 bit ORN shifted register. */
8645 orn32_shift (sim_cpu *cpu, Shift shift, uint32_t count)
8647 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
8648 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
8649 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
8652 (cpu, rd, NO_SP, aarch64_get_reg_u32 (cpu, rn, NO_SP)
8653 | ~ shifted32 (aarch64_get_reg_u32 (cpu, rm, NO_SP), shift, count));
8656 /* 64 bit ORN shifted register. */
8658 orn64_shift (sim_cpu *cpu, Shift shift, uint32_t count)
8660 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
8661 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
8662 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
8665 (cpu, rd, NO_SP, aarch64_get_reg_u64 (cpu, rn, NO_SP)
8666 | ~ shifted64 (aarch64_get_reg_u64 (cpu, rm, NO_SP), shift, count));
8670 dexLogicalImmediate (sim_cpu *cpu)
8672 /* assert instr[28,23] = 1001000
8673 instr[31] = size : 0 ==> 32 bit, 1 ==> 64 bit
8674 instr[30,29] = op : 0 ==> AND, 1 ==> ORR, 2 ==> EOR, 3 ==> ANDS
8675 instr[22] = N : used to construct immediate mask
8681 /* 32 bit operations must have N = 0 or else we have an UNALLOC. */
8682 uint32_t size = uimm (aarch64_get_instr (cpu), 31, 31);
8683 uint32_t N = uimm (aarch64_get_instr (cpu), 22, 22);
8684 /* uint32_t immr = uimm (aarch64_get_instr (cpu), 21, 16);. */
8685 /* uint32_t imms = uimm (aarch64_get_instr (cpu), 15, 10);. */
8686 uint32_t index = uimm (aarch64_get_instr (cpu), 22, 10);
8687 uint64_t bimm64 = LITable [index];
8688 uint32_t dispatch = uimm (aarch64_get_instr (cpu), 30, 29);
8698 uint32_t bimm = (uint32_t) bimm64;
8702 case 0: and32 (cpu, bimm); return;
8703 case 1: orr32 (cpu, bimm); return;
8704 case 2: eor32 (cpu, bimm); return;
8705 case 3: ands32 (cpu, bimm); return;
8712 case 0: and64 (cpu, bimm64); return;
8713 case 1: orr64 (cpu, bimm64); return;
8714 case 2: eor64 (cpu, bimm64); return;
8715 case 3: ands64 (cpu, bimm64); return;
8722 The uimm argument is a 16 bit value to be inserted into the
8723 target register the pos argument locates the 16 bit word in the
8724 dest register i.e. it is in {0, 1} for 32 bit and {0, 1, 2,
8726 N.B register arg may not be SP so it should be.
8727 accessed using the setGZRegisterXXX accessors. */
8729 /* 32 bit move 16 bit immediate zero remaining shorts. */
8731 movz32 (sim_cpu *cpu, uint32_t val, uint32_t pos)
8733 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
8735 aarch64_set_reg_u64 (cpu, rd, NO_SP, val << (pos * 16));
8738 /* 64 bit move 16 bit immediate zero remaining shorts. */
8740 movz64 (sim_cpu *cpu, uint32_t val, uint32_t pos)
8742 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
8744 aarch64_set_reg_u64 (cpu, rd, NO_SP, ((uint64_t) val) << (pos * 16));
8747 /* 32 bit move 16 bit immediate negated. */
8749 movn32 (sim_cpu *cpu, uint32_t val, uint32_t pos)
8751 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
8753 aarch64_set_reg_u64 (cpu, rd, NO_SP, ((val << (pos * 16)) ^ 0xffffffffU));
8756 /* 64 bit move 16 bit immediate negated. */
8758 movn64 (sim_cpu *cpu, uint32_t val, uint32_t pos)
8760 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
8763 (cpu, rd, NO_SP, ((((uint64_t) val) << (pos * 16))
8764 ^ 0xffffffffffffffffULL));
8767 /* 32 bit move 16 bit immediate keep remaining shorts. */
8769 movk32 (sim_cpu *cpu, uint32_t val, uint32_t pos)
8771 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
8772 uint32_t current = aarch64_get_reg_u32 (cpu, rd, NO_SP);
8773 uint32_t value = val << (pos * 16);
8774 uint32_t mask = ~(0xffffU << (pos * 16));
8776 aarch64_set_reg_u64 (cpu, rd, NO_SP, (value | (current & mask)));
8779 /* 64 bit move 16 it immediate keep remaining shorts. */
8781 movk64 (sim_cpu *cpu, uint32_t val, uint32_t pos)
8783 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
8784 uint64_t current = aarch64_get_reg_u64 (cpu, rd, NO_SP);
8785 uint64_t value = (uint64_t) val << (pos * 16);
8786 uint64_t mask = ~(0xffffULL << (pos * 16));
8788 aarch64_set_reg_u64 (cpu, rd, NO_SP, (value | (current & mask)));
8792 dexMoveWideImmediate (sim_cpu *cpu)
8794 /* assert instr[28:23] = 100101
8795 instr[31] = size : 0 ==> 32 bit, 1 ==> 64 bit
8796 instr[30,29] = op : 0 ==> MOVN, 1 ==> UNALLOC, 2 ==> MOVZ, 3 ==> MOVK
8797 instr[22,21] = shift : 00 == LSL#0, 01 = LSL#16, 10 = LSL#32, 11 = LSL#48
8798 instr[20,5] = uimm16
8801 /* N.B. the (multiple of 16) shift is applied by the called routine,
8802 we just pass the multiplier. */
8805 uint32_t size = uimm (aarch64_get_instr (cpu), 31, 31);
8806 uint32_t op = uimm (aarch64_get_instr (cpu), 30, 29);
8807 uint32_t shift = uimm (aarch64_get_instr (cpu), 22, 21);
8809 /* 32 bit can only shift 0 or 1 lot of 16.
8810 anything else is an unallocated instruction. */
8811 if (size == 0 && (shift > 1))
8817 imm = uimm (aarch64_get_instr (cpu), 20, 5);
8822 movn32 (cpu, imm, shift);
8824 movz32 (cpu, imm, shift);
8826 movk32 (cpu, imm, shift);
8831 movn64 (cpu, imm, shift);
8833 movz64 (cpu, imm, shift);
8835 movk64 (cpu, imm, shift);
8839 /* Bitfield operations.
8840 These take a pair of bit positions r and s which are in {0..31}
8841 or {0..63} depending on the instruction word size.
8842 N.B register args may not be SP. */
8844 /* OK, we start with ubfm which just needs to pick
8845 some bits out of source zero the rest and write
8846 the result to dest. Just need two logical shifts. */
8848 /* 32 bit bitfield move, left and right of affected zeroed
8849 if r <= s Wd<s-r:0> = Wn<s:r> else Wd<32+s-r,32-r> = Wn<s:0>. */
8851 ubfm32 (sim_cpu *cpu, uint32_t r, uint32_t s)
8854 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
8855 uint32_t value = aarch64_get_reg_u32 (cpu, rn, NO_SP);
8857 /* Pick either s+1-r or s+1 consecutive bits out of the original word. */
8860 /* 31:...:s:xxx:r:...:0 ==> 31:...:s-r:xxx:0.
8861 We want only bits s:xxx:r at the bottom of the word
8862 so we LSL bit s up to bit 31 i.e. by 31 - s
8863 and then we LSR to bring bit 31 down to bit s - r
8864 i.e. by 31 + r - s. */
8866 value >>= 31 + r - s;
8870 /* 31:...:s:xxx:0 ==> 31:...:31-(r-1)+s:xxx:31-(r-1):...:0
8871 We want only bits s:xxx:0 starting at it 31-(r-1)
8872 so we LSL bit s up to bit 31 i.e. by 31 - s
8873 and then we LSL to bring bit 31 down to 31-(r-1)+s
8874 i.e. by r - (s + 1). */
8876 value >>= r - (s + 1);
8879 rd = uimm (aarch64_get_instr (cpu), 4, 0);
8880 aarch64_set_reg_u64 (cpu, rd, NO_SP, value);
8883 /* 64 bit bitfield move, left and right of affected zeroed
8884 if r <= s Wd<s-r:0> = Wn<s:r> else Wd<64+s-r,64-r> = Wn<s:0>. */
8886 ubfm (sim_cpu *cpu, uint32_t r, uint32_t s)
8889 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
8890 uint64_t value = aarch64_get_reg_u64 (cpu, rn, NO_SP);
8894 /* 63:...:s:xxx:r:...:0 ==> 63:...:s-r:xxx:0.
8895 We want only bits s:xxx:r at the bottom of the word.
8896 So we LSL bit s up to bit 63 i.e. by 63 - s
8897 and then we LSR to bring bit 63 down to bit s - r
8898 i.e. by 63 + r - s. */
8900 value >>= 63 + r - s;
8904 /* 63:...:s:xxx:0 ==> 63:...:63-(r-1)+s:xxx:63-(r-1):...:0.
8905 We want only bits s:xxx:0 starting at it 63-(r-1).
8906 So we LSL bit s up to bit 63 i.e. by 63 - s
8907 and then we LSL to bring bit 63 down to 63-(r-1)+s
8908 i.e. by r - (s + 1). */
8910 value >>= r - (s + 1);
8913 rd = uimm (aarch64_get_instr (cpu), 4, 0);
8914 aarch64_set_reg_u64 (cpu, rd, NO_SP, value);
8917 /* The signed versions need to insert sign bits
8918 on the left of the inserted bit field. so we do
8919 much the same as the unsigned version except we
8920 use an arithmetic shift right -- this just means
8921 we need to operate on signed values. */
8923 /* 32 bit bitfield move, left of affected sign-extended, right zeroed. */
8924 /* If r <= s Wd<s-r:0> = Wn<s:r> else Wd<32+s-r,32-r> = Wn<s:0>. */
8926 sbfm32 (sim_cpu *cpu, uint32_t r, uint32_t s)
8929 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
8930 /* as per ubfm32 but use an ASR instead of an LSR. */
8931 int32_t value = aarch64_get_reg_s32 (cpu, rn, NO_SP);
8936 value >>= 31 + r - s;
8941 value >>= r - (s + 1);
8944 rd = uimm (aarch64_get_instr (cpu), 4, 0);
8945 aarch64_set_reg_u64 (cpu, rd, NO_SP, (uint32_t) value);
8948 /* 64 bit bitfield move, left of affected sign-extended, right zeroed. */
8949 /* If r <= s Wd<s-r:0> = Wn<s:r> else Wd<64+s-r,64-r> = Wn<s:0>. */
8951 sbfm (sim_cpu *cpu, uint32_t r, uint32_t s)
8954 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
8955 /* acpu per ubfm but use an ASR instead of an LSR. */
8956 int64_t value = aarch64_get_reg_s64 (cpu, rn, NO_SP);
8961 value >>= 63 + r - s;
8966 value >>= r - (s + 1);
8969 rd = uimm (aarch64_get_instr (cpu), 4, 0);
8970 aarch64_set_reg_s64 (cpu, rd, NO_SP, value);
8973 /* Finally, these versions leave non-affected bits
8974 as is. so we need to generate the bits as per
8975 ubfm and also generate a mask to pick the
8976 bits from the original and computed values. */
8978 /* 32 bit bitfield move, non-affected bits left as is.
8979 If r <= s Wd<s-r:0> = Wn<s:r> else Wd<32+s-r,32-r> = Wn<s:0>. */
8981 bfm32 (sim_cpu *cpu, uint32_t r, uint32_t s)
8983 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
8984 uint32_t value = aarch64_get_reg_u32 (cpu, rn, NO_SP);
8989 /* Pick either s+1-r or s+1 consecutive bits out of the original word. */
8992 /* 31:...:s:xxx:r:...:0 ==> 31:...:s-r:xxx:0.
8993 We want only bits s:xxx:r at the bottom of the word
8994 so we LSL bit s up to bit 31 i.e. by 31 - s
8995 and then we LSR to bring bit 31 down to bit s - r
8996 i.e. by 31 + r - s. */
8998 value >>= 31 + r - s;
8999 /* the mask must include the same bits. */
9001 mask >>= 31 + r - s;
9005 /* 31:...:s:xxx:0 ==> 31:...:31-(r-1)+s:xxx:31-(r-1):...:0.
9006 We want only bits s:xxx:0 starting at it 31-(r-1)
9007 so we LSL bit s up to bit 31 i.e. by 31 - s
9008 and then we LSL to bring bit 31 down to 31-(r-1)+s
9009 i.e. by r - (s + 1). */
9011 value >>= r - (s + 1);
9012 /* The mask must include the same bits. */
9014 mask >>= r - (s + 1);
9017 rd = uimm (aarch64_get_instr (cpu), 4, 0);
9018 value2 = aarch64_get_reg_u32 (cpu, rd, NO_SP);
9024 (cpu, rd, NO_SP, (aarch64_get_reg_u32 (cpu, rd, NO_SP) & ~mask) | value);
9027 /* 64 bit bitfield move, non-affected bits left as is.
9028 If r <= s Wd<s-r:0> = Wn<s:r> else Wd<64+s-r,64-r> = Wn<s:0>. */
9030 bfm (sim_cpu *cpu, uint32_t r, uint32_t s)
9033 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
9034 uint64_t value = aarch64_get_reg_u64 (cpu, rn, NO_SP);
9035 uint64_t mask = 0xffffffffffffffffULL;
9039 /* 63:...:s:xxx:r:...:0 ==> 63:...:s-r:xxx:0.
9040 We want only bits s:xxx:r at the bottom of the word
9041 so we LSL bit s up to bit 63 i.e. by 63 - s
9042 and then we LSR to bring bit 63 down to bit s - r
9043 i.e. by 63 + r - s. */
9045 value >>= 63 + r - s;
9046 /* The mask must include the same bits. */
9048 mask >>= 63 + r - s;
9052 /* 63:...:s:xxx:0 ==> 63:...:63-(r-1)+s:xxx:63-(r-1):...:0
9053 We want only bits s:xxx:0 starting at it 63-(r-1)
9054 so we LSL bit s up to bit 63 i.e. by 63 - s
9055 and then we LSL to bring bit 63 down to 63-(r-1)+s
9056 i.e. by r - (s + 1). */
9058 value >>= r - (s + 1);
9059 /* The mask must include the same bits. */
9061 mask >>= r - (s + 1);
9064 rd = uimm (aarch64_get_instr (cpu), 4, 0);
9066 (cpu, rd, NO_SP, (aarch64_get_reg_u64 (cpu, rd, NO_SP) & ~mask) | value);
9070 dexBitfieldImmediate (sim_cpu *cpu)
9072 /* assert instr[28:23] = 100110
9073 instr[31] = size : 0 ==> 32 bit, 1 ==> 64 bit
9074 instr[30,29] = op : 0 ==> SBFM, 1 ==> BFM, 2 ==> UBFM, 3 ==> UNALLOC
9075 instr[22] = N : must be 0 for 32 bit, 1 for 64 bit ow UNALLOC
9076 instr[21,16] = immr : 0xxxxx for 32 bit, xxxxxx for 64 bit
9077 instr[15,10] = imms : 0xxxxx for 32 bit, xxxxxx for 64 bit
9081 /* 32 bit operations must have N = 0 or else we have an UNALLOC. */
9084 uint32_t size = uimm (aarch64_get_instr (cpu), 31, 31);
9085 uint32_t N = uimm (aarch64_get_instr (cpu), 22, 22);
9086 /* 32 bit operations must have immr[5] = 0 and imms[5] = 0. */
9087 /* or else we have an UNALLOC. */
9088 uint32_t immr = uimm (aarch64_get_instr (cpu), 21, 16);
9093 if (!size && uimm (immr, 5, 5))
9096 imms = uimm (aarch64_get_instr (cpu), 15, 10);
9097 if (!size && uimm (imms, 5, 5))
9100 /* Switch on combined size and op. */
9101 dispatch = uimm (aarch64_get_instr (cpu), 31, 29);
9104 case 0: sbfm32 (cpu, immr, imms); return;
9105 case 1: bfm32 (cpu, immr, imms); return;
9106 case 2: ubfm32 (cpu, immr, imms); return;
9107 case 4: sbfm (cpu, immr, imms); return;
9108 case 5: bfm (cpu, immr, imms); return;
9109 case 6: ubfm (cpu, immr, imms); return;
9110 default: HALT_UNALLOC;
9115 do_EXTR_32 (sim_cpu *cpu)
9117 /* instr[31:21] = 00010011100
9119 instr[15,10] = imms : 0xxxxx for 32 bit
9122 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
9123 unsigned imms = uimm (aarch64_get_instr (cpu), 15, 10) & 31;
9124 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
9125 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
9129 val1 = aarch64_get_reg_u32 (cpu, rm, NO_SP);
9131 val2 = aarch64_get_reg_u32 (cpu, rn, NO_SP);
9132 val2 <<= (32 - imms);
9134 aarch64_set_reg_u64 (cpu, rd, NO_SP, val1 | val2);
9138 do_EXTR_64 (sim_cpu *cpu)
9140 /* instr[31:21] = 10010011100
9145 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
9146 unsigned imms = uimm (aarch64_get_instr (cpu), 15, 10) & 63;
9147 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
9148 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
9151 val = aarch64_get_reg_u64 (cpu, rm, NO_SP);
9153 val |= (aarch64_get_reg_u64 (cpu, rn, NO_SP) << (64 - imms));
9155 aarch64_set_reg_u64 (cpu, rd, NO_SP, val);
9159 dexExtractImmediate (sim_cpu *cpu)
9161 /* assert instr[28:23] = 100111
9162 instr[31] = size : 0 ==> 32 bit, 1 ==> 64 bit
9163 instr[30,29] = op21 : 0 ==> EXTR, 1,2,3 ==> UNALLOC
9164 instr[22] = N : must be 0 for 32 bit, 1 for 64 bit or UNALLOC
9165 instr[21] = op0 : must be 0 or UNALLOC
9167 instr[15,10] = imms : 0xxxxx for 32 bit, xxxxxx for 64 bit
9171 /* 32 bit operations must have N = 0 or else we have an UNALLOC. */
9172 /* 64 bit operations must have N = 1 or else we have an UNALLOC. */
9174 uint32_t size = uimm (aarch64_get_instr (cpu), 31, 31);
9175 uint32_t N = uimm (aarch64_get_instr (cpu), 22, 22);
9176 /* 32 bit operations must have imms[5] = 0
9177 or else we have an UNALLOC. */
9178 uint32_t imms = uimm (aarch64_get_instr (cpu), 15, 10);
9183 if (!size && uimm (imms, 5, 5))
9186 /* Switch on combined size and op. */
9187 dispatch = uimm (aarch64_get_instr (cpu), 31, 29);
9192 else if (dispatch == 4)
9195 else if (dispatch == 1)
9202 dexDPImm (sim_cpu *cpu)
9204 /* uint32_t group = dispatchGroup (aarch64_get_instr (cpu));
9205 assert group == GROUP_DPIMM_1000 || grpoup == GROUP_DPIMM_1001
9206 bits [25,23] of a DPImm are the secondary dispatch vector. */
9207 uint32_t group2 = dispatchDPImm (aarch64_get_instr (cpu));
9211 case DPIMM_PCADR_000:
9212 case DPIMM_PCADR_001:
9213 dexPCRelAddressing (cpu);
9216 case DPIMM_ADDSUB_010:
9217 case DPIMM_ADDSUB_011:
9218 dexAddSubtractImmediate (cpu);
9222 dexLogicalImmediate (cpu);
9226 dexMoveWideImmediate (cpu);
9229 case DPIMM_BITF_110:
9230 dexBitfieldImmediate (cpu);
9233 case DPIMM_EXTR_111:
9234 dexExtractImmediate (cpu);
9238 /* Should never reach here. */
9244 dexLoadUnscaledImmediate (sim_cpu *cpu)
9246 /* instr[29,24] == 111_00
9252 instr[20,12] = simm9
9253 instr[9,5] = rn may be SP. */
9254 /* unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0); */
9255 uint32_t V = uimm (aarch64_get_instr (cpu), 26, 26);
9256 uint32_t dispatch = ( (uimm (aarch64_get_instr (cpu), 31, 30) << 2)
9257 | uimm (aarch64_get_instr (cpu), 23, 22));
9258 int32_t imm = simm32 (aarch64_get_instr (cpu), 20, 12);
9262 /* GReg operations. */
9265 case 0: sturb (cpu, imm); return;
9266 case 1: ldurb32 (cpu, imm); return;
9267 case 2: ldursb64 (cpu, imm); return;
9268 case 3: ldursb32 (cpu, imm); return;
9269 case 4: sturh (cpu, imm); return;
9270 case 5: ldurh32 (cpu, imm); return;
9271 case 6: ldursh64 (cpu, imm); return;
9272 case 7: ldursh32 (cpu, imm); return;
9273 case 8: stur32 (cpu, imm); return;
9274 case 9: ldur32 (cpu, imm); return;
9275 case 10: ldursw (cpu, imm); return;
9276 case 12: stur64 (cpu, imm); return;
9277 case 13: ldur64 (cpu, imm); return;
9290 /* FReg operations. */
9293 case 2: fsturq (cpu, imm); return;
9294 case 3: fldurq (cpu, imm); return;
9295 case 8: fsturs (cpu, imm); return;
9296 case 9: fldurs (cpu, imm); return;
9297 case 12: fsturd (cpu, imm); return;
9298 case 13: fldurd (cpu, imm); return;
9300 case 0: /* STUR 8 bit FP. */
9301 case 1: /* LDUR 8 bit FP. */
9302 case 4: /* STUR 16 bit FP. */
9303 case 5: /* LDUR 8 bit FP. */
9317 /* N.B. A preliminary note regarding all the ldrs<x>32
9320 The signed value loaded by these instructions is cast to unsigned
9321 before being assigned to aarch64_get_reg_u64 (cpu, N) i.e. to the
9322 64 bit element of the GReg union. this performs a 32 bit sign extension
9323 (as required) but avoids 64 bit sign extension, thus ensuring that the
9324 top half of the register word is zero. this is what the spec demands
9325 when a 32 bit load occurs. */
9327 /* 32 bit load sign-extended byte scaled unsigned 12 bit. */
9329 ldrsb32_abs (sim_cpu *cpu, uint32_t offset)
9331 unsigned int rn = uimm (aarch64_get_instr (cpu), 9, 5);
9332 unsigned int rt = uimm (aarch64_get_instr (cpu), 4, 0);
9334 /* The target register may not be SP but the source may be
9335 there is no scaling required for a byte load. */
9336 uint64_t address = aarch64_get_reg_u64 (cpu, rn, SP_OK) + offset;
9337 aarch64_set_reg_u64 (cpu, rt, NO_SP,
9338 (int64_t) aarch64_get_mem_s8 (cpu, address));
9341 /* 32 bit load sign-extended byte scaled or unscaled zero-
9342 or sign-extended 32-bit register offset. */
9344 ldrsb32_scale_ext (sim_cpu *cpu, Scaling scaling, Extension extension)
9346 unsigned int rm = uimm (aarch64_get_instr (cpu), 20, 16);
9347 unsigned int rn = uimm (aarch64_get_instr (cpu), 9, 5);
9348 unsigned int rt = uimm (aarch64_get_instr (cpu), 4, 0);
9350 /* rn may reference SP, rm and rt must reference ZR. */
9352 uint64_t address = aarch64_get_reg_u64 (cpu, rn, SP_OK);
9353 int64_t displacement = extend (aarch64_get_reg_u32 (cpu, rm, NO_SP),
9356 /* There is no scaling required for a byte load. */
9358 (cpu, rt, NO_SP, (int64_t) aarch64_get_mem_s8 (cpu, address
9362 /* 32 bit load sign-extended byte unscaled signed 9 bit with
9363 pre- or post-writeback. */
9365 ldrsb32_wb (sim_cpu *cpu, int32_t offset, WriteBack wb)
9368 unsigned int rn = uimm (aarch64_get_instr (cpu), 9, 5);
9369 unsigned int rt = uimm (aarch64_get_instr (cpu), 4, 0);
9371 if (rn == rt && wb != NoWriteBack)
9374 address = aarch64_get_reg_u64 (cpu, rn, SP_OK);
9379 aarch64_set_reg_u64 (cpu, rt, NO_SP,
9380 (int64_t) aarch64_get_mem_s8 (cpu, address));
9385 if (wb != NoWriteBack)
9386 aarch64_set_reg_u64 (cpu, rn, NO_SP, address);
9389 /* 8 bit store scaled. */
9391 fstrb_abs (sim_cpu *cpu, uint32_t offset)
9393 unsigned st = uimm (aarch64_get_instr (cpu), 4, 0);
9394 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
9396 aarch64_set_mem_u8 (cpu,
9397 aarch64_get_reg_u64 (cpu, rn, SP_OK) + offset,
9398 aarch64_get_vec_u8 (cpu, st, 0));
9401 /* 8 bit store scaled or unscaled zero- or
9402 sign-extended 8-bit register offset. */
9404 fstrb_scale_ext (sim_cpu *cpu, Scaling scaling, Extension extension)
9406 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
9407 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
9408 unsigned st = uimm (aarch64_get_instr (cpu), 4, 0);
9410 uint64_t address = aarch64_get_reg_u64 (cpu, rn, SP_OK);
9411 int64_t extended = extend (aarch64_get_reg_u32 (cpu, rm, NO_SP),
9413 uint64_t displacement = OPT_SCALE (extended, 32, scaling);
9416 (cpu, address + displacement, aarch64_get_vec_u8 (cpu, st, 0));
9419 /* 16 bit store scaled. */
9421 fstrh_abs (sim_cpu *cpu, uint32_t offset)
9423 unsigned st = uimm (aarch64_get_instr (cpu), 4, 0);
9424 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
9428 aarch64_get_reg_u64 (cpu, rn, SP_OK) + SCALE (offset, 16),
9429 aarch64_get_vec_u16 (cpu, st, 0));
9432 /* 16 bit store scaled or unscaled zero-
9433 or sign-extended 16-bit register offset. */
9435 fstrh_scale_ext (sim_cpu *cpu, Scaling scaling, Extension extension)
9437 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
9438 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
9439 unsigned st = uimm (aarch64_get_instr (cpu), 4, 0);
9441 uint64_t address = aarch64_get_reg_u64 (cpu, rn, SP_OK);
9442 int64_t extended = extend (aarch64_get_reg_u32 (cpu, rm, NO_SP),
9444 uint64_t displacement = OPT_SCALE (extended, 32, scaling);
9447 (cpu, address + displacement, aarch64_get_vec_u16 (cpu, st, 0));
9450 /* 32 bit store scaled unsigned 12 bit. */
9452 fstrs_abs (sim_cpu *cpu, uint32_t offset)
9454 unsigned st = uimm (aarch64_get_instr (cpu), 4, 0);
9455 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
9457 aarch64_set_mem_float
9459 aarch64_get_reg_u64 (cpu, rn, SP_OK) + SCALE (offset, 32),
9460 aarch64_get_FP_float (cpu, st));
9463 /* 32 bit store unscaled signed 9 bit with pre- or post-writeback. */
9465 fstrs_wb (sim_cpu *cpu, int32_t offset, WriteBack wb)
9467 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
9468 unsigned st = uimm (aarch64_get_instr (cpu), 4, 0);
9470 uint64_t address = aarch64_get_reg_u64 (cpu, rn, SP_OK);
9475 aarch64_set_mem_float (cpu, address, aarch64_get_FP_float (cpu, st));
9480 if (wb != NoWriteBack)
9481 aarch64_set_reg_u64 (cpu, rn, SP_OK, address);
9484 /* 32 bit store scaled or unscaled zero-
9485 or sign-extended 32-bit register offset. */
9487 fstrs_scale_ext (sim_cpu *cpu, Scaling scaling, Extension extension)
9489 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
9490 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
9491 unsigned st = uimm (aarch64_get_instr (cpu), 4, 0);
9493 uint64_t address = aarch64_get_reg_u64 (cpu, rn, SP_OK);
9494 int64_t extended = extend (aarch64_get_reg_u32 (cpu, rm, NO_SP),
9496 uint64_t displacement = OPT_SCALE (extended, 32, scaling);
9498 aarch64_set_mem_float
9499 (cpu, address + displacement, aarch64_get_FP_float (cpu, st));
9502 /* 64 bit store scaled unsigned 12 bit. */
9504 fstrd_abs (sim_cpu *cpu, uint32_t offset)
9506 unsigned st = uimm (aarch64_get_instr (cpu), 4, 0);
9507 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
9509 aarch64_set_mem_double
9511 aarch64_get_reg_u64 (cpu, rn, SP_OK) + SCALE (offset, 64),
9512 aarch64_get_FP_double (cpu, st));
9515 /* 64 bit store unscaled signed 9 bit with pre- or post-writeback. */
9517 fstrd_wb (sim_cpu *cpu, int32_t offset, WriteBack wb)
9519 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
9520 unsigned st = uimm (aarch64_get_instr (cpu), 4, 0);
9522 uint64_t address = aarch64_get_reg_u64 (cpu, rn, SP_OK);
9527 aarch64_set_mem_double (cpu, address, aarch64_get_FP_double (cpu, st));
9532 if (wb != NoWriteBack)
9533 aarch64_set_reg_u64 (cpu, rn, SP_OK, address);
9536 /* 64 bit store scaled or unscaled zero-
9537 or sign-extended 32-bit register offset. */
9539 fstrd_scale_ext (sim_cpu *cpu, Scaling scaling, Extension extension)
9541 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
9542 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
9543 unsigned st = uimm (aarch64_get_instr (cpu), 4, 0);
9545 uint64_t address = aarch64_get_reg_u64 (cpu, rn, SP_OK);
9546 int64_t extended = extend (aarch64_get_reg_u32 (cpu, rm, NO_SP),
9548 uint64_t displacement = OPT_SCALE (extended, 64, scaling);
9550 aarch64_set_mem_double
9551 (cpu, address + displacement, aarch64_get_FP_double (cpu, st));
9554 /* 128 bit store scaled unsigned 12 bit. */
9556 fstrq_abs (sim_cpu *cpu, uint32_t offset)
9559 unsigned st = uimm (aarch64_get_instr (cpu), 4, 0);
9560 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
9563 aarch64_get_FP_long_double (cpu, st, & a);
9565 addr = aarch64_get_reg_u64 (cpu, rn, SP_OK) + SCALE (offset, 128);
9566 aarch64_set_mem_long_double (cpu, addr, a);
9569 /* 128 bit store unscaled signed 9 bit with pre- or post-writeback. */
9571 fstrq_wb (sim_cpu *cpu, int32_t offset, WriteBack wb)
9574 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
9575 unsigned st = uimm (aarch64_get_instr (cpu), 4, 0);
9576 uint64_t address = aarch64_get_reg_u64 (cpu, rn, SP_OK);
9581 aarch64_get_FP_long_double (cpu, st, & a);
9582 aarch64_set_mem_long_double (cpu, address, a);
9587 if (wb != NoWriteBack)
9588 aarch64_set_reg_u64 (cpu, rn, SP_OK, address);
9591 /* 128 bit store scaled or unscaled zero-
9592 or sign-extended 32-bit register offset. */
9594 fstrq_scale_ext (sim_cpu *cpu, Scaling scaling, Extension extension)
9596 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
9597 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
9598 unsigned st = uimm (aarch64_get_instr (cpu), 4, 0);
9600 uint64_t address = aarch64_get_reg_u64 (cpu, rn, SP_OK);
9601 int64_t extended = extend (aarch64_get_reg_u32 (cpu, rm, NO_SP),
9603 uint64_t displacement = OPT_SCALE (extended, 128, scaling);
9607 aarch64_get_FP_long_double (cpu, st, & a);
9608 aarch64_set_mem_long_double (cpu, address + displacement, a);
9612 dexLoadImmediatePrePost (sim_cpu *cpu)
9614 /* instr[29,24] == 111_00
9620 instr[20,12] = simm9
9621 instr[11] = wb : 0 ==> Post, 1 ==> Pre
9622 instr[9,5] = rn may be SP. */
9623 /* unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0); */
9624 uint32_t V = uimm (aarch64_get_instr (cpu), 26, 26);
9625 uint32_t dispatch = ( (uimm (aarch64_get_instr (cpu), 31, 30) << 2)
9626 | uimm (aarch64_get_instr (cpu), 23, 22));
9627 int32_t imm = simm32 (aarch64_get_instr (cpu), 20, 12);
9628 WriteBack wb = writeback (aarch64_get_instr (cpu), 11);
9632 /* GReg operations. */
9635 case 0: strb_wb (cpu, imm, wb); return;
9636 case 1: ldrb32_wb (cpu, imm, wb); return;
9637 case 2: ldrsb_wb (cpu, imm, wb); return;
9638 case 3: ldrsb32_wb (cpu, imm, wb); return;
9639 case 4: strh_wb (cpu, imm, wb); return;
9640 case 5: ldrh32_wb (cpu, imm, wb); return;
9641 case 6: ldrsh64_wb (cpu, imm, wb); return;
9642 case 7: ldrsh32_wb (cpu, imm, wb); return;
9643 case 8: str32_wb (cpu, imm, wb); return;
9644 case 9: ldr32_wb (cpu, imm, wb); return;
9645 case 10: ldrsw_wb (cpu, imm, wb); return;
9646 case 12: str_wb (cpu, imm, wb); return;
9647 case 13: ldr_wb (cpu, imm, wb); return;
9657 /* FReg operations. */
9660 case 2: fstrq_wb (cpu, imm, wb); return;
9661 case 3: fldrq_wb (cpu, imm, wb); return;
9662 case 8: fstrs_wb (cpu, imm, wb); return;
9663 case 9: fldrs_wb (cpu, imm, wb); return;
9664 case 12: fstrd_wb (cpu, imm, wb); return;
9665 case 13: fldrd_wb (cpu, imm, wb); return;
9667 case 0: /* STUR 8 bit FP. */
9668 case 1: /* LDUR 8 bit FP. */
9669 case 4: /* STUR 16 bit FP. */
9670 case 5: /* LDUR 8 bit FP. */
9685 dexLoadRegisterOffset (sim_cpu *cpu)
9687 /* instr[31,30] = size
9694 instr[15,13] = option : 010 ==> UXTW, 011 ==> UXTX/LSL,
9695 110 ==> SXTW, 111 ==> SXTX,
9702 uint32_t V = uimm (aarch64_get_instr (cpu), 26,26);
9703 uint32_t dispatch = ( (uimm (aarch64_get_instr (cpu), 31, 30) << 2)
9704 | uimm (aarch64_get_instr (cpu), 23, 22));
9705 Scaling scale = scaling (aarch64_get_instr (cpu), 12);
9706 Extension extensionType = extension (aarch64_get_instr (cpu), 13);
9708 /* Check for illegal extension types. */
9709 if (uimm (extensionType, 1, 1) == 0)
9712 if (extensionType == UXTX || extensionType == SXTX)
9713 extensionType = NoExtension;
9717 /* GReg operations. */
9720 case 0: strb_scale_ext (cpu, scale, extensionType); return;
9721 case 1: ldrb32_scale_ext (cpu, scale, extensionType); return;
9722 case 2: ldrsb_scale_ext (cpu, scale, extensionType); return;
9723 case 3: ldrsb32_scale_ext (cpu, scale, extensionType); return;
9724 case 4: strh_scale_ext (cpu, scale, extensionType); return;
9725 case 5: ldrh32_scale_ext (cpu, scale, extensionType); return;
9726 case 6: ldrsh_scale_ext (cpu, scale, extensionType); return;
9727 case 7: ldrsh32_scale_ext (cpu, scale, extensionType); return;
9728 case 8: str32_scale_ext (cpu, scale, extensionType); return;
9729 case 9: ldr32_scale_ext (cpu, scale, extensionType); return;
9730 case 10: ldrsw_scale_ext (cpu, scale, extensionType); return;
9731 case 12: str_scale_ext (cpu, scale, extensionType); return;
9732 case 13: ldr_scale_ext (cpu, scale, extensionType); return;
9733 case 14: prfm_scale_ext (cpu, scale, extensionType); return;
9742 /* FReg operations. */
9745 case 1: /* LDUR 8 bit FP. */
9747 case 3: fldrq_scale_ext (cpu, scale, extensionType); return;
9748 case 5: /* LDUR 8 bit FP. */
9750 case 9: fldrs_scale_ext (cpu, scale, extensionType); return;
9751 case 13: fldrd_scale_ext (cpu, scale, extensionType); return;
9753 case 0: fstrb_scale_ext (cpu, scale, extensionType); return;
9754 case 2: fstrq_scale_ext (cpu, scale, extensionType); return;
9755 case 4: fstrh_scale_ext (cpu, scale, extensionType); return;
9756 case 8: fstrs_scale_ext (cpu, scale, extensionType); return;
9757 case 12: fstrd_scale_ext (cpu, scale, extensionType); return;
9771 dexLoadUnsignedImmediate (sim_cpu *cpu)
9773 /* assert instr[29,24] == 111_01
9777 instr[21,10] = uimm12 : unsigned immediate offset
9778 instr[9,5] = rn may be SP. */
9779 /* unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0); */
9780 uint32_t V = uimm (aarch64_get_instr (cpu), 26,26);
9781 uint32_t dispatch = ( (uimm (aarch64_get_instr (cpu), 31, 30) << 2)
9782 | uimm (aarch64_get_instr (cpu), 23, 22));
9783 uint32_t imm = uimm (aarch64_get_instr (cpu), 21, 10);
9787 /* GReg operations. */
9790 case 0: strb_abs (cpu, imm); return;
9791 case 1: ldrb32_abs (cpu, imm); return;
9792 case 2: ldrsb_abs (cpu, imm); return;
9793 case 3: ldrsb32_abs (cpu, imm); return;
9794 case 4: strh_abs (cpu, imm); return;
9795 case 5: ldrh32_abs (cpu, imm); return;
9796 case 6: ldrsh_abs (cpu, imm); return;
9797 case 7: ldrsh32_abs (cpu, imm); return;
9798 case 8: str32_abs (cpu, imm); return;
9799 case 9: ldr32_abs (cpu, imm); return;
9800 case 10: ldrsw_abs (cpu, imm); return;
9801 case 12: str_abs (cpu, imm); return;
9802 case 13: ldr_abs (cpu, imm); return;
9803 case 14: prfm_abs (cpu, imm); return;
9812 /* FReg operations. */
9815 case 3: fldrq_abs (cpu, imm); return;
9816 case 9: fldrs_abs (cpu, imm); return;
9817 case 13: fldrd_abs (cpu, imm); return;
9819 case 0: fstrb_abs (cpu, imm); return;
9820 case 2: fstrq_abs (cpu, imm); return;
9821 case 4: fstrh_abs (cpu, imm); return;
9822 case 8: fstrs_abs (cpu, imm); return;
9823 case 12: fstrd_abs (cpu, imm); return;
9825 case 1: /* LDR 8 bit FP. */
9826 case 5: /* LDR 8 bit FP. */
9841 dexLoadExclusive (sim_cpu *cpu)
9843 /* assert instr[29:24] = 001000;
9845 instr[23] = 0 if exclusive
9846 instr[22] = L : 1 if load, 0 if store
9847 instr[21] = 1 if pair
9849 instr[15] = o0 : 1 if ordered
9854 switch (uimm (aarch64_get_instr (cpu), 22, 21))
9856 case 2: ldxr (cpu); return;
9857 case 0: stxr (cpu); return;
9863 dexLoadOther (sim_cpu *cpu)
9867 /* instr[29,25] = 111_0
9868 instr[24] == 0 ==> dispatch, 1 ==> ldst reg unsigned immediate
9869 instr[21:11,10] is the secondary dispatch. */
9870 if (uimm (aarch64_get_instr (cpu), 24, 24))
9872 dexLoadUnsignedImmediate (cpu);
9876 dispatch = ( (uimm (aarch64_get_instr (cpu), 21, 21) << 2)
9877 | uimm (aarch64_get_instr (cpu), 11, 10));
9880 case 0: dexLoadUnscaledImmediate (cpu); return;
9881 case 1: dexLoadImmediatePrePost (cpu); return;
9882 case 3: dexLoadImmediatePrePost (cpu); return;
9883 case 6: dexLoadRegisterOffset (cpu); return;
9895 store_pair_u32 (sim_cpu *cpu, int32_t offset, WriteBack wb)
9897 unsigned rn = uimm (aarch64_get_instr (cpu), 14, 10);
9898 unsigned rd = uimm (aarch64_get_instr (cpu), 9, 5);
9899 unsigned rm = uimm (aarch64_get_instr (cpu), 4, 0);
9900 uint64_t address = aarch64_get_reg_u64 (cpu, rd, SP_OK);
9902 if ((rn == rd || rm == rd) && wb != NoWriteBack)
9903 HALT_UNALLOC; /* ??? */
9910 aarch64_set_mem_u32 (cpu, address,
9911 aarch64_get_reg_u32 (cpu, rm, NO_SP));
9912 aarch64_set_mem_u32 (cpu, address + 4,
9913 aarch64_get_reg_u32 (cpu, rn, NO_SP));
9918 if (wb != NoWriteBack)
9919 aarch64_set_reg_u64 (cpu, rd, SP_OK, address);
9923 store_pair_u64 (sim_cpu *cpu, int32_t offset, WriteBack wb)
9925 unsigned rn = uimm (aarch64_get_instr (cpu), 14, 10);
9926 unsigned rd = uimm (aarch64_get_instr (cpu), 9, 5);
9927 unsigned rm = uimm (aarch64_get_instr (cpu), 4, 0);
9928 uint64_t address = aarch64_get_reg_u64 (cpu, rd, SP_OK);
9930 if ((rn == rd || rm == rd) && wb != NoWriteBack)
9931 HALT_UNALLOC; /* ??? */
9938 aarch64_set_mem_u64 (cpu, address,
9939 aarch64_get_reg_u64 (cpu, rm, SP_OK));
9940 aarch64_set_mem_u64 (cpu, address + 8,
9941 aarch64_get_reg_u64 (cpu, rn, SP_OK));
9946 if (wb != NoWriteBack)
9947 aarch64_set_reg_u64 (cpu, rd, SP_OK, address);
9951 load_pair_u32 (sim_cpu *cpu, int32_t offset, WriteBack wb)
9953 unsigned rn = uimm (aarch64_get_instr (cpu), 14, 10);
9954 unsigned rd = uimm (aarch64_get_instr (cpu), 9, 5);
9955 unsigned rm = uimm (aarch64_get_instr (cpu), 4, 0);
9956 uint64_t address = aarch64_get_reg_u64 (cpu, rd, SP_OK);
9958 /* treat this as unalloc to make sure we don't do it. */
9967 aarch64_set_reg_u64 (cpu, rm, SP_OK, aarch64_get_mem_u32 (cpu, address));
9968 aarch64_set_reg_u64 (cpu, rn, SP_OK, aarch64_get_mem_u32 (cpu, address + 4));
9973 if (wb != NoWriteBack)
9974 aarch64_set_reg_u64 (cpu, rd, SP_OK, address);
9978 load_pair_s32 (sim_cpu *cpu, int32_t offset, WriteBack wb)
9980 unsigned rn = uimm (aarch64_get_instr (cpu), 14, 10);
9981 unsigned rd = uimm (aarch64_get_instr (cpu), 9, 5);
9982 unsigned rm = uimm (aarch64_get_instr (cpu), 4, 0);
9983 uint64_t address = aarch64_get_reg_u64 (cpu, rd, SP_OK);
9985 /* Treat this as unalloc to make sure we don't do it. */
9994 aarch64_set_reg_s64 (cpu, rm, SP_OK, aarch64_get_mem_s32 (cpu, address));
9995 aarch64_set_reg_s64 (cpu, rn, SP_OK, aarch64_get_mem_s32 (cpu, address + 4));
10000 if (wb != NoWriteBack)
10001 aarch64_set_reg_u64 (cpu, rd, SP_OK, address);
10005 load_pair_u64 (sim_cpu *cpu, int32_t offset, WriteBack wb)
10007 unsigned rn = uimm (aarch64_get_instr (cpu), 14, 10);
10008 unsigned rd = uimm (aarch64_get_instr (cpu), 9, 5);
10009 unsigned rm = uimm (aarch64_get_instr (cpu), 4, 0);
10010 uint64_t address = aarch64_get_reg_u64 (cpu, rd, SP_OK);
10012 /* Treat this as unalloc to make sure we don't do it. */
10021 aarch64_set_reg_u64 (cpu, rm, SP_OK, aarch64_get_mem_u64 (cpu, address));
10022 aarch64_set_reg_u64 (cpu, rn, SP_OK, aarch64_get_mem_u64 (cpu, address + 8));
10027 if (wb != NoWriteBack)
10028 aarch64_set_reg_u64 (cpu, rd, SP_OK, address);
10032 dex_load_store_pair_gr (sim_cpu *cpu)
10034 /* instr[31,30] = size (10=> 64-bit, 01=> signed 32-bit, 00=> 32-bit)
10035 instr[29,25] = instruction encoding: 101_0
10036 instr[26] = V : 1 if fp 0 if gp
10037 instr[24,23] = addressing mode (10=> offset, 01=> post, 11=> pre)
10038 instr[22] = load/store (1=> load)
10039 instr[21,15] = signed, scaled, offset
10042 instr[ 4, 0] = Rm. */
10044 uint32_t dispatch = ((uimm (aarch64_get_instr (cpu), 31, 30) << 3)
10045 | uimm (aarch64_get_instr (cpu), 24, 22));
10046 int32_t offset = simm32 (aarch64_get_instr (cpu), 21, 15);
10050 case 2: store_pair_u32 (cpu, offset, Post); return;
10051 case 3: load_pair_u32 (cpu, offset, Post); return;
10052 case 4: store_pair_u32 (cpu, offset, NoWriteBack); return;
10053 case 5: load_pair_u32 (cpu, offset, NoWriteBack); return;
10054 case 6: store_pair_u32 (cpu, offset, Pre); return;
10055 case 7: load_pair_u32 (cpu, offset, Pre); return;
10057 case 11: load_pair_s32 (cpu, offset, Post); return;
10058 case 13: load_pair_s32 (cpu, offset, NoWriteBack); return;
10059 case 15: load_pair_s32 (cpu, offset, Pre); return;
10061 case 18: store_pair_u64 (cpu, offset, Post); return;
10062 case 19: load_pair_u64 (cpu, offset, Post); return;
10063 case 20: store_pair_u64 (cpu, offset, NoWriteBack); return;
10064 case 21: load_pair_u64 (cpu, offset, NoWriteBack); return;
10065 case 22: store_pair_u64 (cpu, offset, Pre); return;
10066 case 23: load_pair_u64 (cpu, offset, Pre); return;
10074 store_pair_float (sim_cpu *cpu, int32_t offset, WriteBack wb)
10076 unsigned rn = uimm (aarch64_get_instr (cpu), 14, 10);
10077 unsigned rd = uimm (aarch64_get_instr (cpu), 9, 5);
10078 unsigned rm = uimm (aarch64_get_instr (cpu), 4, 0);
10079 uint64_t address = aarch64_get_reg_u64 (cpu, rd, SP_OK);
10086 aarch64_set_mem_float (cpu, address, aarch64_get_FP_float (cpu, rm));
10087 aarch64_set_mem_float (cpu, address + 4, aarch64_get_FP_float (cpu, rn));
10092 if (wb != NoWriteBack)
10093 aarch64_set_reg_u64 (cpu, rd, SP_OK, address);
10097 store_pair_double (sim_cpu *cpu, int32_t offset, WriteBack wb)
10099 unsigned rn = uimm (aarch64_get_instr (cpu), 14, 10);
10100 unsigned rd = uimm (aarch64_get_instr (cpu), 9, 5);
10101 unsigned rm = uimm (aarch64_get_instr (cpu), 4, 0);
10102 uint64_t address = aarch64_get_reg_u64 (cpu, rd, SP_OK);
10109 aarch64_set_mem_double (cpu, address, aarch64_get_FP_double (cpu, rm));
10110 aarch64_set_mem_double (cpu, address + 8, aarch64_get_FP_double (cpu, rn));
10115 if (wb != NoWriteBack)
10116 aarch64_set_reg_u64 (cpu, rd, SP_OK, address);
10120 store_pair_long_double (sim_cpu *cpu, int32_t offset, WriteBack wb)
10123 unsigned rn = uimm (aarch64_get_instr (cpu), 14, 10);
10124 unsigned rd = uimm (aarch64_get_instr (cpu), 9, 5);
10125 unsigned rm = uimm (aarch64_get_instr (cpu), 4, 0);
10126 uint64_t address = aarch64_get_reg_u64 (cpu, rd, SP_OK);
10133 aarch64_get_FP_long_double (cpu, rm, & a);
10134 aarch64_set_mem_long_double (cpu, address, a);
10135 aarch64_get_FP_long_double (cpu, rn, & a);
10136 aarch64_set_mem_long_double (cpu, address + 16, a);
10141 if (wb != NoWriteBack)
10142 aarch64_set_reg_u64 (cpu, rd, SP_OK, address);
10146 load_pair_float (sim_cpu *cpu, int32_t offset, WriteBack wb)
10148 unsigned rn = uimm (aarch64_get_instr (cpu), 14, 10);
10149 unsigned rd = uimm (aarch64_get_instr (cpu), 9, 5);
10150 unsigned rm = uimm (aarch64_get_instr (cpu), 4, 0);
10151 uint64_t address = aarch64_get_reg_u64 (cpu, rd, SP_OK);
10161 aarch64_set_FP_float (cpu, rm, aarch64_get_mem_float (cpu, address));
10162 aarch64_set_FP_float (cpu, rn, aarch64_get_mem_float (cpu, address + 4));
10167 if (wb != NoWriteBack)
10168 aarch64_set_reg_u64 (cpu, rd, SP_OK, address);
10172 load_pair_double (sim_cpu *cpu, int32_t offset, WriteBack wb)
10174 unsigned rn = uimm (aarch64_get_instr (cpu), 14, 10);
10175 unsigned rd = uimm (aarch64_get_instr (cpu), 9, 5);
10176 unsigned rm = uimm (aarch64_get_instr (cpu), 4, 0);
10177 uint64_t address = aarch64_get_reg_u64 (cpu, rd, SP_OK);
10187 aarch64_set_FP_double (cpu, rm, aarch64_get_mem_double (cpu, address));
10188 aarch64_set_FP_double (cpu, rn, aarch64_get_mem_double (cpu, address + 8));
10193 if (wb != NoWriteBack)
10194 aarch64_set_reg_u64 (cpu, rd, SP_OK, address);
10198 load_pair_long_double (sim_cpu *cpu, int32_t offset, WriteBack wb)
10201 unsigned rn = uimm (aarch64_get_instr (cpu), 14, 10);
10202 unsigned rd = uimm (aarch64_get_instr (cpu), 9, 5);
10203 unsigned rm = uimm (aarch64_get_instr (cpu), 4, 0);
10204 uint64_t address = aarch64_get_reg_u64 (cpu, rd, SP_OK);
10214 aarch64_get_mem_long_double (cpu, address, & a);
10215 aarch64_set_FP_long_double (cpu, rm, a);
10216 aarch64_get_mem_long_double (cpu, address + 16, & a);
10217 aarch64_set_FP_long_double (cpu, rn, a);
10222 if (wb != NoWriteBack)
10223 aarch64_set_reg_u64 (cpu, rd, SP_OK, address);
10227 dex_load_store_pair_fp (sim_cpu *cpu)
10229 /* instr[31,30] = size (10=> 128-bit, 01=> 64-bit, 00=> 32-bit)
10230 instr[29,25] = instruction encoding
10231 instr[24,23] = addressing mode (10=> offset, 01=> post, 11=> pre)
10232 instr[22] = load/store (1=> load)
10233 instr[21,15] = signed, scaled, offset
10236 instr[ 4, 0] = Rm */
10238 uint32_t dispatch = ((uimm (aarch64_get_instr (cpu), 31, 30) << 3)
10239 | uimm (aarch64_get_instr (cpu), 24, 22));
10240 int32_t offset = simm32 (aarch64_get_instr (cpu), 21, 15);
10244 case 2: store_pair_float (cpu, offset, Post); return;
10245 case 3: load_pair_float (cpu, offset, Post); return;
10246 case 4: store_pair_float (cpu, offset, NoWriteBack); return;
10247 case 5: load_pair_float (cpu, offset, NoWriteBack); return;
10248 case 6: store_pair_float (cpu, offset, Pre); return;
10249 case 7: load_pair_float (cpu, offset, Pre); return;
10251 case 10: store_pair_double (cpu, offset, Post); return;
10252 case 11: load_pair_double (cpu, offset, Post); return;
10253 case 12: store_pair_double (cpu, offset, NoWriteBack); return;
10254 case 13: load_pair_double (cpu, offset, NoWriteBack); return;
10255 case 14: store_pair_double (cpu, offset, Pre); return;
10256 case 15: load_pair_double (cpu, offset, Pre); return;
10258 case 18: store_pair_long_double (cpu, offset, Post); return;
10259 case 19: load_pair_long_double (cpu, offset, Post); return;
10260 case 20: store_pair_long_double (cpu, offset, NoWriteBack); return;
10261 case 21: load_pair_long_double (cpu, offset, NoWriteBack); return;
10262 case 22: store_pair_long_double (cpu, offset, Pre); return;
10263 case 23: load_pair_long_double (cpu, offset, Pre); return;
10270 static inline unsigned
10271 vec_reg (unsigned v, unsigned o)
10273 return (v + o) & 0x3F;
10276 /* Load multiple N-element structures to N consecutive registers. */
10278 vec_load (sim_cpu *cpu, uint64_t address, unsigned N)
10280 int all = uimm (aarch64_get_instr (cpu), 30, 30);
10281 unsigned size = uimm (aarch64_get_instr (cpu), 11, 10);
10282 unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
10287 case 0: /* 8-bit operations. */
10289 for (i = 0; i < (16 * N); i++)
10290 aarch64_set_vec_u8 (cpu, vec_reg (vd, i >> 4), i & 15,
10291 aarch64_get_mem_u8 (cpu, address + i));
10293 for (i = 0; i < (8 * N); i++)
10294 aarch64_set_vec_u8 (cpu, vec_reg (vd, i >> 3), i & 7,
10295 aarch64_get_mem_u8 (cpu, address + i));
10298 case 1: /* 16-bit operations. */
10300 for (i = 0; i < (8 * N); i++)
10301 aarch64_set_vec_u16 (cpu, vec_reg (vd, i >> 3), i & 7,
10302 aarch64_get_mem_u16 (cpu, address + i * 2));
10304 for (i = 0; i < (4 * N); i++)
10305 aarch64_set_vec_u16 (cpu, vec_reg (vd, i >> 2), i & 3,
10306 aarch64_get_mem_u16 (cpu, address + i * 2));
10309 case 2: /* 32-bit operations. */
10311 for (i = 0; i < (4 * N); i++)
10312 aarch64_set_vec_u32 (cpu, vec_reg (vd, i >> 2), i & 3,
10313 aarch64_get_mem_u32 (cpu, address + i * 4));
10315 for (i = 0; i < (2 * N); i++)
10316 aarch64_set_vec_u32 (cpu, vec_reg (vd, i >> 1), i & 1,
10317 aarch64_get_mem_u32 (cpu, address + i * 4));
10320 case 3: /* 64-bit operations. */
10322 for (i = 0; i < (2 * N); i++)
10323 aarch64_set_vec_u64 (cpu, vec_reg (vd, i >> 1), i & 1,
10324 aarch64_get_mem_u64 (cpu, address + i * 8));
10326 for (i = 0; i < N; i++)
10327 aarch64_set_vec_u64 (cpu, vec_reg (vd, i), 0,
10328 aarch64_get_mem_u64 (cpu, address + i * 8));
10336 /* LD4: load multiple 4-element to four consecutive registers. */
10338 LD4 (sim_cpu *cpu, uint64_t address)
10340 vec_load (cpu, address, 4);
10343 /* LD3: load multiple 3-element structures to three consecutive registers. */
10345 LD3 (sim_cpu *cpu, uint64_t address)
10347 vec_load (cpu, address, 3);
10350 /* LD2: load multiple 2-element structures to two consecutive registers. */
10352 LD2 (sim_cpu *cpu, uint64_t address)
10354 vec_load (cpu, address, 2);
10357 /* Load multiple 1-element structures into one register. */
10359 LD1_1 (sim_cpu *cpu, uint64_t address)
10361 int all = uimm (aarch64_get_instr (cpu), 30, 30);
10362 unsigned size = uimm (aarch64_get_instr (cpu), 11, 10);
10363 unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
10369 /* LD1 {Vd.16b}, addr, #16 */
10370 /* LD1 {Vd.8b}, addr, #8 */
10371 for (i = 0; i < (all ? 16 : 8); i++)
10372 aarch64_set_vec_u8 (cpu, vd, i,
10373 aarch64_get_mem_u8 (cpu, address + i));
10377 /* LD1 {Vd.8h}, addr, #16 */
10378 /* LD1 {Vd.4h}, addr, #8 */
10379 for (i = 0; i < (all ? 8 : 4); i++)
10380 aarch64_set_vec_u16 (cpu, vd, i,
10381 aarch64_get_mem_u16 (cpu, address + i * 2));
10385 /* LD1 {Vd.4s}, addr, #16 */
10386 /* LD1 {Vd.2s}, addr, #8 */
10387 for (i = 0; i < (all ? 4 : 2); i++)
10388 aarch64_set_vec_u32 (cpu, vd, i,
10389 aarch64_get_mem_u32 (cpu, address + i * 4));
10393 /* LD1 {Vd.2d}, addr, #16 */
10394 /* LD1 {Vd.1d}, addr, #8 */
10395 for (i = 0; i < (all ? 2 : 1); i++)
10396 aarch64_set_vec_u64 (cpu, vd, i,
10397 aarch64_get_mem_u64 (cpu, address + i * 8));
10405 /* Load multiple 1-element structures into two registers. */
10407 LD1_2 (sim_cpu *cpu, uint64_t address)
10409 /* FIXME: This algorithm is *exactly* the same as the LD2 version.
10410 So why have two different instructions ? There must be something
10411 wrong somewhere. */
10412 vec_load (cpu, address, 2);
10415 /* Load multiple 1-element structures into three registers. */
10417 LD1_3 (sim_cpu *cpu, uint64_t address)
10419 /* FIXME: This algorithm is *exactly* the same as the LD3 version.
10420 So why have two different instructions ? There must be something
10421 wrong somewhere. */
10422 vec_load (cpu, address, 3);
10425 /* Load multiple 1-element structures into four registers. */
10427 LD1_4 (sim_cpu *cpu, uint64_t address)
10429 /* FIXME: This algorithm is *exactly* the same as the LD4 version.
10430 So why have two different instructions ? There must be something
10431 wrong somewhere. */
10432 vec_load (cpu, address, 4);
10435 /* Store multiple N-element structures to N consecutive registers. */
10437 vec_store (sim_cpu *cpu, uint64_t address, unsigned N)
10439 int all = uimm (aarch64_get_instr (cpu), 30, 30);
10440 unsigned size = uimm (aarch64_get_instr (cpu), 11, 10);
10441 unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
10446 case 0: /* 8-bit operations. */
10448 for (i = 0; i < (16 * N); i++)
10451 aarch64_get_vec_u8 (cpu, vec_reg (vd, i >> 4), i & 15));
10453 for (i = 0; i < (8 * N); i++)
10456 aarch64_get_vec_u8 (cpu, vec_reg (vd, i >> 3), i & 7));
10459 case 1: /* 16-bit operations. */
10461 for (i = 0; i < (8 * N); i++)
10462 aarch64_set_mem_u16
10463 (cpu, address + i * 2,
10464 aarch64_get_vec_u16 (cpu, vec_reg (vd, i >> 3), i & 7));
10466 for (i = 0; i < (4 * N); i++)
10467 aarch64_set_mem_u16
10468 (cpu, address + i * 2,
10469 aarch64_get_vec_u16 (cpu, vec_reg (vd, i >> 2), i & 3));
10472 case 2: /* 32-bit operations. */
10474 for (i = 0; i < (4 * N); i++)
10475 aarch64_set_mem_u32
10476 (cpu, address + i * 4,
10477 aarch64_get_vec_u32 (cpu, vec_reg (vd, i >> 2), i & 3));
10479 for (i = 0; i < (2 * N); i++)
10480 aarch64_set_mem_u32
10481 (cpu, address + i * 4,
10482 aarch64_get_vec_u32 (cpu, vec_reg (vd, i >> 1), i & 1));
10485 case 3: /* 64-bit operations. */
10487 for (i = 0; i < (2 * N); i++)
10488 aarch64_set_mem_u64
10489 (cpu, address + i * 8,
10490 aarch64_get_vec_u64 (cpu, vec_reg (vd, i >> 1), i & 1));
10492 for (i = 0; i < N; i++)
10493 aarch64_set_mem_u64
10494 (cpu, address + i * 8,
10495 aarch64_get_vec_u64 (cpu, vec_reg (vd, i), 0));
10503 /* Store multiple 4-element structure to four consecutive registers. */
10505 ST4 (sim_cpu *cpu, uint64_t address)
10507 vec_store (cpu, address, 4);
10510 /* Store multiple 3-element structures to three consecutive registers. */
10512 ST3 (sim_cpu *cpu, uint64_t address)
10514 vec_store (cpu, address, 3);
10517 /* Store multiple 2-element structures to two consecutive registers. */
10519 ST2 (sim_cpu *cpu, uint64_t address)
10521 vec_store (cpu, address, 2);
10524 /* Store multiple 1-element structures into one register. */
10526 ST1_1 (sim_cpu *cpu, uint64_t address)
10528 int all = uimm (aarch64_get_instr (cpu), 30, 30);
10529 unsigned size = uimm (aarch64_get_instr (cpu), 11, 10);
10530 unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
10536 for (i = 0; i < (all ? 16 : 8); i++)
10537 aarch64_set_mem_u8 (cpu, address + i,
10538 aarch64_get_vec_u8 (cpu, vd, i));
10542 for (i = 0; i < (all ? 8 : 4); i++)
10543 aarch64_set_mem_u16 (cpu, address + i * 2,
10544 aarch64_get_vec_u16 (cpu, vd, i));
10548 for (i = 0; i < (all ? 4 : 2); i++)
10549 aarch64_set_mem_u32 (cpu, address + i * 4,
10550 aarch64_get_vec_u32 (cpu, vd, i));
10554 for (i = 0; i < (all ? 2 : 1); i++)
10555 aarch64_set_mem_u64 (cpu, address + i * 8,
10556 aarch64_get_vec_u64 (cpu, vd, i));
10564 /* Store multiple 1-element structures into two registers. */
10566 ST1_2 (sim_cpu *cpu, uint64_t address)
10568 /* FIXME: This algorithm is *exactly* the same as the ST2 version.
10569 So why have two different instructions ? There must be
10570 something wrong somewhere. */
10571 vec_store (cpu, address, 2);
10574 /* Store multiple 1-element structures into three registers. */
10576 ST1_3 (sim_cpu *cpu, uint64_t address)
10578 /* FIXME: This algorithm is *exactly* the same as the ST3 version.
10579 So why have two different instructions ? There must be
10580 something wrong somewhere. */
10581 vec_store (cpu, address, 3);
10584 /* Store multiple 1-element structures into four registers. */
10586 ST1_4 (sim_cpu *cpu, uint64_t address)
10588 /* FIXME: This algorithm is *exactly* the same as the ST4 version.
10589 So why have two different instructions ? There must be
10590 something wrong somewhere. */
10591 vec_store (cpu, address, 4);
10595 do_vec_LDnR (sim_cpu *cpu, uint64_t address)
10598 instr[30] = element selector 0=>half, 1=>all elements
10599 instr[29,24] = 00 1101
10600 instr[23] = 0=>simple, 1=>post
10602 instr[21] = width: LD1R-or-LD3R (0) / LD2R-or-LD4R (1)
10603 instr[20,16] = 0 0000 (simple), Vinc (reg-post-inc, no SP),
10604 11111 (immediate post inc)
10606 instr[13] = width: LD1R-or-LD2R (0) / LD3R-or-LD4R (1)
10608 instr[11,10] = element size 00=> byte(b), 01=> half(h),
10609 10=> word(s), 11=> double(d)
10610 instr[9,5] = address
10613 unsigned full = uimm (aarch64_get_instr (cpu), 30, 30);
10614 unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
10615 unsigned size = uimm (aarch64_get_instr (cpu), 11, 10);
10618 NYI_assert (29, 24, 0x0D);
10619 NYI_assert (22, 22, 1);
10620 NYI_assert (15, 14, 3);
10621 NYI_assert (12, 12, 0);
10623 switch ((uimm (aarch64_get_instr (cpu), 13, 13) << 1)
10624 | uimm (aarch64_get_instr (cpu), 21, 21))
10626 case 0: /* LD1R. */
10631 uint8_t val = aarch64_get_mem_u8 (cpu, address);
10632 for (i = 0; i < (full ? 16 : 8); i++)
10633 aarch64_set_vec_u8 (cpu, vd, i, val);
10639 uint16_t val = aarch64_get_mem_u16 (cpu, address);
10640 for (i = 0; i < (full ? 8 : 4); i++)
10641 aarch64_set_vec_u16 (cpu, vd, i, val);
10647 uint32_t val = aarch64_get_mem_u32 (cpu, address);
10648 for (i = 0; i < (full ? 4 : 2); i++)
10649 aarch64_set_vec_u32 (cpu, vd, i, val);
10655 uint64_t val = aarch64_get_mem_u64 (cpu, address);
10656 for (i = 0; i < (full ? 2 : 1); i++)
10657 aarch64_set_vec_u64 (cpu, vd, i, val);
10666 case 1: /* LD2R. */
10671 uint8_t val1 = aarch64_get_mem_u8 (cpu, address);
10672 uint8_t val2 = aarch64_get_mem_u8 (cpu, address + 1);
10674 for (i = 0; i < (full ? 16 : 8); i++)
10676 aarch64_set_vec_u8 (cpu, vd, 0, val1);
10677 aarch64_set_vec_u8 (cpu, vd + 1, 0, val2);
10684 uint16_t val1 = aarch64_get_mem_u16 (cpu, address);
10685 uint16_t val2 = aarch64_get_mem_u16 (cpu, address + 2);
10687 for (i = 0; i < (full ? 8 : 4); i++)
10689 aarch64_set_vec_u16 (cpu, vd, 0, val1);
10690 aarch64_set_vec_u16 (cpu, vd + 1, 0, val2);
10697 uint32_t val1 = aarch64_get_mem_u32 (cpu, address);
10698 uint32_t val2 = aarch64_get_mem_u32 (cpu, address + 4);
10700 for (i = 0; i < (full ? 4 : 2); i++)
10702 aarch64_set_vec_u32 (cpu, vd, 0, val1);
10703 aarch64_set_vec_u32 (cpu, vd + 1, 0, val2);
10710 uint64_t val1 = aarch64_get_mem_u64 (cpu, address);
10711 uint64_t val2 = aarch64_get_mem_u64 (cpu, address + 8);
10713 for (i = 0; i < (full ? 2 : 1); i++)
10715 aarch64_set_vec_u64 (cpu, vd, 0, val1);
10716 aarch64_set_vec_u64 (cpu, vd + 1, 0, val2);
10726 case 2: /* LD3R. */
10731 uint8_t val1 = aarch64_get_mem_u8 (cpu, address);
10732 uint8_t val2 = aarch64_get_mem_u8 (cpu, address + 1);
10733 uint8_t val3 = aarch64_get_mem_u8 (cpu, address + 2);
10735 for (i = 0; i < (full ? 16 : 8); i++)
10737 aarch64_set_vec_u8 (cpu, vd, 0, val1);
10738 aarch64_set_vec_u8 (cpu, vd + 1, 0, val2);
10739 aarch64_set_vec_u8 (cpu, vd + 2, 0, val3);
10746 uint32_t val1 = aarch64_get_mem_u16 (cpu, address);
10747 uint32_t val2 = aarch64_get_mem_u16 (cpu, address + 2);
10748 uint32_t val3 = aarch64_get_mem_u16 (cpu, address + 4);
10750 for (i = 0; i < (full ? 8 : 4); i++)
10752 aarch64_set_vec_u16 (cpu, vd, 0, val1);
10753 aarch64_set_vec_u16 (cpu, vd + 1, 0, val2);
10754 aarch64_set_vec_u16 (cpu, vd + 2, 0, val3);
10761 uint32_t val1 = aarch64_get_mem_u32 (cpu, address);
10762 uint32_t val2 = aarch64_get_mem_u32 (cpu, address + 4);
10763 uint32_t val3 = aarch64_get_mem_u32 (cpu, address + 8);
10765 for (i = 0; i < (full ? 4 : 2); i++)
10767 aarch64_set_vec_u32 (cpu, vd, 0, val1);
10768 aarch64_set_vec_u32 (cpu, vd + 1, 0, val2);
10769 aarch64_set_vec_u32 (cpu, vd + 2, 0, val3);
10776 uint64_t val1 = aarch64_get_mem_u64 (cpu, address);
10777 uint64_t val2 = aarch64_get_mem_u64 (cpu, address + 8);
10778 uint64_t val3 = aarch64_get_mem_u64 (cpu, address + 16);
10780 for (i = 0; i < (full ? 2 : 1); i++)
10782 aarch64_set_vec_u64 (cpu, vd, 0, val1);
10783 aarch64_set_vec_u64 (cpu, vd + 1, 0, val2);
10784 aarch64_set_vec_u64 (cpu, vd + 2, 0, val3);
10794 case 3: /* LD4R. */
10799 uint8_t val1 = aarch64_get_mem_u8 (cpu, address);
10800 uint8_t val2 = aarch64_get_mem_u8 (cpu, address + 1);
10801 uint8_t val3 = aarch64_get_mem_u8 (cpu, address + 2);
10802 uint8_t val4 = aarch64_get_mem_u8 (cpu, address + 3);
10804 for (i = 0; i < (full ? 16 : 8); i++)
10806 aarch64_set_vec_u8 (cpu, vd, 0, val1);
10807 aarch64_set_vec_u8 (cpu, vd + 1, 0, val2);
10808 aarch64_set_vec_u8 (cpu, vd + 2, 0, val3);
10809 aarch64_set_vec_u8 (cpu, vd + 3, 0, val4);
10816 uint32_t val1 = aarch64_get_mem_u16 (cpu, address);
10817 uint32_t val2 = aarch64_get_mem_u16 (cpu, address + 2);
10818 uint32_t val3 = aarch64_get_mem_u16 (cpu, address + 4);
10819 uint32_t val4 = aarch64_get_mem_u16 (cpu, address + 6);
10821 for (i = 0; i < (full ? 8 : 4); i++)
10823 aarch64_set_vec_u16 (cpu, vd, 0, val1);
10824 aarch64_set_vec_u16 (cpu, vd + 1, 0, val2);
10825 aarch64_set_vec_u16 (cpu, vd + 2, 0, val3);
10826 aarch64_set_vec_u16 (cpu, vd + 3, 0, val4);
10833 uint32_t val1 = aarch64_get_mem_u32 (cpu, address);
10834 uint32_t val2 = aarch64_get_mem_u32 (cpu, address + 4);
10835 uint32_t val3 = aarch64_get_mem_u32 (cpu, address + 8);
10836 uint32_t val4 = aarch64_get_mem_u32 (cpu, address + 12);
10838 for (i = 0; i < (full ? 4 : 2); i++)
10840 aarch64_set_vec_u32 (cpu, vd, 0, val1);
10841 aarch64_set_vec_u32 (cpu, vd + 1, 0, val2);
10842 aarch64_set_vec_u32 (cpu, vd + 2, 0, val3);
10843 aarch64_set_vec_u32 (cpu, vd + 3, 0, val4);
10850 uint64_t val1 = aarch64_get_mem_u64 (cpu, address);
10851 uint64_t val2 = aarch64_get_mem_u64 (cpu, address + 8);
10852 uint64_t val3 = aarch64_get_mem_u64 (cpu, address + 16);
10853 uint64_t val4 = aarch64_get_mem_u64 (cpu, address + 24);
10855 for (i = 0; i < (full ? 2 : 1); i++)
10857 aarch64_set_vec_u64 (cpu, vd, 0, val1);
10858 aarch64_set_vec_u64 (cpu, vd + 1, 0, val2);
10859 aarch64_set_vec_u64 (cpu, vd + 2, 0, val3);
10860 aarch64_set_vec_u64 (cpu, vd + 3, 0, val4);
10876 do_vec_load_store (sim_cpu *cpu)
10878 /* {LD|ST}<N> {Vd..Vd+N}, vaddr
10881 instr[30] = element selector 0=>half, 1=>all elements
10882 instr[29,25] = 00110
10884 instr[23] = 0=>simple, 1=>post
10885 instr[22] = 0=>store, 1=>load
10886 instr[21] = 0 (LDn) / small(0)-large(1) selector (LDnR)
10887 instr[20,16] = 00000 (simple), Vinc (reg-post-inc, no SP),
10888 11111 (immediate post inc)
10889 instr[15,12] = elements and destinations. eg for load:
10890 0000=>LD4 => load multiple 4-element to
10891 four consecutive registers
10892 0100=>LD3 => load multiple 3-element to
10893 three consecutive registers
10894 1000=>LD2 => load multiple 2-element to
10895 two consecutive registers
10896 0010=>LD1 => load multiple 1-element to
10897 four consecutive registers
10898 0110=>LD1 => load multiple 1-element to
10899 three consecutive registers
10900 1010=>LD1 => load multiple 1-element to
10901 two consecutive registers
10902 0111=>LD1 => load multiple 1-element to
10906 instr[11,10] = element size 00=> byte(b), 01=> half(h),
10907 10=> word(s), 11=> double(d)
10908 instr[9,5] = Vn, can be SP
10917 if (uimm (aarch64_get_instr (cpu), 31, 31) != 0
10918 || uimm (aarch64_get_instr (cpu), 29, 25) != 0x06)
10921 type = uimm (aarch64_get_instr (cpu), 15, 12);
10922 if (type != 0xE && type != 0xE && uimm (aarch64_get_instr (cpu), 21, 21) != 0)
10925 post = uimm (aarch64_get_instr (cpu), 23, 23);
10926 load = uimm (aarch64_get_instr (cpu), 22, 22);
10927 vn = uimm (aarch64_get_instr (cpu), 9, 5);
10928 address = aarch64_get_reg_u64 (cpu, vn, SP_OK);
10932 unsigned vm = uimm (aarch64_get_instr (cpu), 20, 16);
10936 unsigned sizeof_operation;
10940 case 0: sizeof_operation = 32; break;
10941 case 4: sizeof_operation = 24; break;
10942 case 8: sizeof_operation = 16; break;
10945 sizeof_operation = uimm (aarch64_get_instr (cpu), 21, 21) ? 2 : 1;
10946 sizeof_operation <<= uimm (aarch64_get_instr (cpu), 11, 10);
10950 sizeof_operation = uimm (aarch64_get_instr (cpu), 21, 21) ? 8 : 4;
10951 sizeof_operation <<= uimm (aarch64_get_instr (cpu), 11, 10);
10958 sizeof_operation = 2 << uimm (aarch64_get_instr (cpu), 11, 10);
10965 if (uimm (aarch64_get_instr (cpu), 30, 30))
10966 sizeof_operation *= 2;
10968 aarch64_set_reg_u64 (cpu, vn, SP_OK, address + sizeof_operation);
10971 aarch64_set_reg_u64 (cpu, vn, SP_OK,
10972 address + aarch64_get_reg_u64 (cpu, vm, NO_SP));
10976 NYI_assert (20, 16, 0);
10983 case 0: LD4 (cpu, address); return;
10984 case 4: LD3 (cpu, address); return;
10985 case 8: LD2 (cpu, address); return;
10986 case 2: LD1_4 (cpu, address); return;
10987 case 6: LD1_3 (cpu, address); return;
10988 case 10: LD1_2 (cpu, address); return;
10989 case 7: LD1_1 (cpu, address); return;
10992 case 0xC: do_vec_LDnR (cpu, address); return;
11002 case 0: ST4 (cpu, address); return;
11003 case 4: ST3 (cpu, address); return;
11004 case 8: ST2 (cpu, address); return;
11005 case 2: ST1_4 (cpu, address); return;
11006 case 6: ST1_3 (cpu, address); return;
11007 case 10: ST1_2 (cpu, address); return;
11008 case 7: ST1_1 (cpu, address); return;
11015 dexLdSt (sim_cpu *cpu)
11017 /* uint32_t group = dispatchGroup (aarch64_get_instr (cpu));
11018 assert group == GROUP_LDST_0100 || group == GROUP_LDST_0110 ||
11019 group == GROUP_LDST_1100 || group == GROUP_LDST_1110
11020 bits [29,28:26] of a LS are the secondary dispatch vector. */
11021 uint32_t group2 = dispatchLS (aarch64_get_instr (cpu));
11026 dexLoadExclusive (cpu); return;
11030 dexLoadLiteral (cpu); return;
11034 dexLoadOther (cpu); return;
11036 case LS_ADVSIMD_001:
11037 do_vec_load_store (cpu); return;
11040 dex_load_store_pair_gr (cpu); return;
11043 dex_load_store_pair_fp (cpu); return;
11046 /* Should never reach here. */
11051 /* Specific decode and execute for group Data Processing Register. */
11054 dexLogicalShiftedRegister (sim_cpu *cpu)
11056 /* assert instr[28:24] = 01010
11057 instr[31] = size : 0 ==> 32 bit, 1 ==> 64 bit
11058 instr[30,29:21] = op,N : 000 ==> AND, 001 ==> BIC,
11059 010 ==> ORR, 011 ==> ORN
11060 100 ==> EOR, 101 ==> EON,
11061 110 ==> ANDS, 111 ==> BICS
11062 instr[23,22] = shift : 0 ==> LSL, 1 ==> LSR, 2 ==> ASR, 3 ==> ROR
11063 instr[15,10] = count : must be 0xxxxx for 32 bit
11067 /* unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16); */
11070 uint32_t size = uimm (aarch64_get_instr (cpu), 31, 31);
11072 /* 32 bit operations must have count[5] = 0. */
11073 /* or else we have an UNALLOC. */
11074 uint32_t count = uimm (aarch64_get_instr (cpu), 15, 10);
11076 if (!size && uimm (count, 5, 5))
11079 shiftType = shift (aarch64_get_instr (cpu), 22);
11081 /* dispatch on size:op:N i.e aarch64_get_instr (cpu)[31,29:21]. */
11082 dispatch = ( (uimm (aarch64_get_instr (cpu), 31, 29) << 1)
11083 | uimm (aarch64_get_instr (cpu), 21, 21));
11087 case 0: and32_shift (cpu, shiftType, count); return;
11088 case 1: bic32_shift (cpu, shiftType, count); return;
11089 case 2: orr32_shift (cpu, shiftType, count); return;
11090 case 3: orn32_shift (cpu, shiftType, count); return;
11091 case 4: eor32_shift (cpu, shiftType, count); return;
11092 case 5: eon32_shift (cpu, shiftType, count); return;
11093 case 6: ands32_shift (cpu, shiftType, count); return;
11094 case 7: bics32_shift (cpu, shiftType, count); return;
11095 case 8: and64_shift (cpu, shiftType, count); return;
11096 case 9: bic64_shift (cpu, shiftType, count); return;
11097 case 10:orr64_shift (cpu, shiftType, count); return;
11098 case 11:orn64_shift (cpu, shiftType, count); return;
11099 case 12:eor64_shift (cpu, shiftType, count); return;
11100 case 13:eon64_shift (cpu, shiftType, count); return;
11101 case 14:ands64_shift (cpu, shiftType, count); return;
11102 case 15:bics64_shift (cpu, shiftType, count); return;
11103 default: HALT_UNALLOC;
11107 /* 32 bit conditional select. */
11109 csel32 (sim_cpu *cpu, CondCode cc)
11111 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
11112 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
11113 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
11115 aarch64_set_reg_u64 (cpu, rd, NO_SP,
11116 testConditionCode (cpu, cc)
11117 ? aarch64_get_reg_u32 (cpu, rn, NO_SP)
11118 : aarch64_get_reg_u32 (cpu, rm, NO_SP));
11121 /* 64 bit conditional select. */
11123 csel64 (sim_cpu *cpu, CondCode cc)
11125 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
11126 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
11127 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
11129 aarch64_set_reg_u64 (cpu, rd, NO_SP,
11130 testConditionCode (cpu, cc)
11131 ? aarch64_get_reg_u64 (cpu, rn, NO_SP)
11132 : aarch64_get_reg_u64 (cpu, rm, NO_SP));
11135 /* 32 bit conditional increment. */
11137 csinc32 (sim_cpu *cpu, CondCode cc)
11139 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
11140 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
11141 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
11143 aarch64_set_reg_u64 (cpu, rd, NO_SP,
11144 testConditionCode (cpu, cc)
11145 ? aarch64_get_reg_u32 (cpu, rn, NO_SP)
11146 : aarch64_get_reg_u32 (cpu, rm, NO_SP) + 1);
11149 /* 64 bit conditional increment. */
11151 csinc64 (sim_cpu *cpu, CondCode cc)
11153 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
11154 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
11155 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
11157 aarch64_set_reg_u64 (cpu, rd, NO_SP,
11158 testConditionCode (cpu, cc)
11159 ? aarch64_get_reg_u64 (cpu, rn, NO_SP)
11160 : aarch64_get_reg_u64 (cpu, rm, NO_SP) + 1);
11163 /* 32 bit conditional invert. */
11165 csinv32 (sim_cpu *cpu, CondCode cc)
11167 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
11168 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
11169 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
11171 aarch64_set_reg_u64 (cpu, rd, NO_SP,
11172 testConditionCode (cpu, cc)
11173 ? aarch64_get_reg_u32 (cpu, rn, NO_SP)
11174 : ~ aarch64_get_reg_u32 (cpu, rm, NO_SP));
11177 /* 64 bit conditional invert. */
11179 csinv64 (sim_cpu *cpu, CondCode cc)
11181 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
11182 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
11183 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
11185 aarch64_set_reg_u64 (cpu, rd, NO_SP,
11186 testConditionCode (cpu, cc)
11187 ? aarch64_get_reg_u64 (cpu, rn, NO_SP)
11188 : ~ aarch64_get_reg_u64 (cpu, rm, NO_SP));
11191 /* 32 bit conditional negate. */
11193 csneg32 (sim_cpu *cpu, CondCode cc)
11195 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
11196 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
11197 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
11199 aarch64_set_reg_u64 (cpu, rd, NO_SP,
11200 testConditionCode (cpu, cc)
11201 ? aarch64_get_reg_u32 (cpu, rn, NO_SP)
11202 : - aarch64_get_reg_u32 (cpu, rm, NO_SP));
11205 /* 64 bit conditional negate. */
11207 csneg64 (sim_cpu *cpu, CondCode cc)
11209 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
11210 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
11211 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
11213 aarch64_set_reg_u64 (cpu, rd, NO_SP,
11214 testConditionCode (cpu, cc)
11215 ? aarch64_get_reg_u64 (cpu, rn, NO_SP)
11216 : - aarch64_get_reg_u64 (cpu, rm, NO_SP));
11220 dexCondSelect (sim_cpu *cpu)
11222 /* assert instr[28,21] = 11011011
11223 instr[31] = size : 0 ==> 32 bit, 1 ==> 64 bit
11224 instr[30:11,10] = op : 000 ==> CSEL, 001 ==> CSINC,
11225 100 ==> CSINV, 101 ==> CSNEG,
11227 instr[29] = S : 0 ==> ok, 1 ==> UNALLOC
11228 instr[15,12] = cond
11229 instr[29] = S : 0 ==> ok, 1 ==> UNALLOC */
11233 uint32_t S = uimm (aarch64_get_instr (cpu), 29, 29);
11234 uint32_t op2 = uimm (aarch64_get_instr (cpu), 11, 10);
11242 cc = condcode (aarch64_get_instr (cpu), 12);
11243 dispatch = ((uimm (aarch64_get_instr (cpu), 31, 30) << 1) | op2);
11247 case 0: csel32 (cpu, cc); return;
11248 case 1: csinc32 (cpu, cc); return;
11249 case 2: csinv32 (cpu, cc); return;
11250 case 3: csneg32 (cpu, cc); return;
11251 case 4: csel64 (cpu, cc); return;
11252 case 5: csinc64 (cpu, cc); return;
11253 case 6: csinv64 (cpu, cc); return;
11254 case 7: csneg64 (cpu, cc); return;
11255 default: HALT_UNALLOC;
11259 /* Some helpers for counting leading 1 or 0 bits. */
11261 /* Counts the number of leading bits which are the same
11262 in a 32 bit value in the range 1 to 32. */
11264 leading32 (uint32_t value)
11266 int32_t mask= 0xffff0000;
11267 uint32_t count= 16; /* Counts number of bits set in mask. */
11268 uint32_t lo = 1; /* Lower bound for number of sign bits. */
11269 uint32_t hi = 32; /* Upper bound for number of sign bits. */
11271 while (lo + 1 < hi)
11273 int32_t test = (value & mask);
11275 if (test == 0 || test == mask)
11278 count = (lo + hi) / 2;
11279 mask >>= (count - lo);
11284 count = (lo + hi) / 2;
11285 mask <<= hi - count;
11294 test = (value & mask);
11296 if (test == 0 || test == mask)
11305 /* Counts the number of leading bits which are the same
11306 in a 64 bit value in the range 1 to 64. */
11308 leading64 (uint64_t value)
11310 int64_t mask= 0xffffffff00000000LL;
11311 uint64_t count = 32; /* Counts number of bits set in mask. */
11312 uint64_t lo = 1; /* Lower bound for number of sign bits. */
11313 uint64_t hi = 64; /* Upper bound for number of sign bits. */
11315 while (lo + 1 < hi)
11317 int64_t test = (value & mask);
11319 if (test == 0 || test == mask)
11322 count = (lo + hi) / 2;
11323 mask >>= (count - lo);
11328 count = (lo + hi) / 2;
11329 mask <<= hi - count;
11338 test = (value & mask);
11340 if (test == 0 || test == mask)
11349 /* Bit operations. */
11350 /* N.B register args may not be SP. */
11352 /* 32 bit count leading sign bits. */
11354 cls32 (sim_cpu *cpu)
11356 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
11357 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
11359 /* N.B. the result needs to exclude the leading bit. */
11360 aarch64_set_reg_u64
11361 (cpu, rd, NO_SP, leading32 (aarch64_get_reg_u32 (cpu, rn, NO_SP)) - 1);
11364 /* 64 bit count leading sign bits. */
11366 cls64 (sim_cpu *cpu)
11368 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
11369 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
11371 /* N.B. the result needs to exclude the leading bit. */
11372 aarch64_set_reg_u64
11373 (cpu, rd, NO_SP, leading64 (aarch64_get_reg_u64 (cpu, rn, NO_SP)) - 1);
11376 /* 32 bit count leading zero bits. */
11378 clz32 (sim_cpu *cpu)
11380 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
11381 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
11382 uint32_t value = aarch64_get_reg_u32 (cpu, rn, NO_SP);
11384 /* if the sign (top) bit is set then the count is 0. */
11385 if (pick32 (value, 31, 31))
11386 aarch64_set_reg_u64 (cpu, rd, NO_SP, 0L);
11388 aarch64_set_reg_u64 (cpu, rd, NO_SP, leading32 (value));
11391 /* 64 bit count leading zero bits. */
11393 clz64 (sim_cpu *cpu)
11395 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
11396 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
11397 uint64_t value = aarch64_get_reg_u64 (cpu, rn, NO_SP);
11399 /* if the sign (top) bit is set then the count is 0. */
11400 if (pick64 (value, 63, 63))
11401 aarch64_set_reg_u64 (cpu, rd, NO_SP, 0L);
11403 aarch64_set_reg_u64 (cpu, rd, NO_SP, leading64 (value));
11406 /* 32 bit reverse bits. */
11408 rbit32 (sim_cpu *cpu)
11410 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
11411 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
11412 uint32_t value = aarch64_get_reg_u32 (cpu, rn, NO_SP);
11413 uint32_t result = 0;
11416 for (i = 0; i < 32; i++)
11419 result |= (value & 1);
11422 aarch64_set_reg_u64 (cpu, rd, NO_SP, result);
11425 /* 64 bit reverse bits. */
11427 rbit64 (sim_cpu *cpu)
11429 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
11430 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
11431 uint64_t value = aarch64_get_reg_u64 (cpu, rn, NO_SP);
11432 uint64_t result = 0;
11435 for (i = 0; i < 64; i++)
11438 result |= (value & 1L);
11441 aarch64_set_reg_u64 (cpu, rd, NO_SP, result);
11444 /* 32 bit reverse bytes. */
11446 rev32 (sim_cpu *cpu)
11448 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
11449 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
11450 uint32_t value = aarch64_get_reg_u32 (cpu, rn, NO_SP);
11451 uint32_t result = 0;
11454 for (i = 0; i < 4; i++)
11457 result |= (value & 0xff);
11460 aarch64_set_reg_u64 (cpu, rd, NO_SP, result);
11463 /* 64 bit reverse bytes. */
11465 rev64 (sim_cpu *cpu)
11467 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
11468 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
11469 uint64_t value = aarch64_get_reg_u64 (cpu, rn, NO_SP);
11470 uint64_t result = 0;
11473 for (i = 0; i < 8; i++)
11476 result |= (value & 0xffULL);
11479 aarch64_set_reg_u64 (cpu, rd, NO_SP, result);
11482 /* 32 bit reverse shorts. */
11483 /* N.B.this reverses the order of the bytes in each half word. */
11485 revh32 (sim_cpu *cpu)
11487 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
11488 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
11489 uint32_t value = aarch64_get_reg_u32 (cpu, rn, NO_SP);
11490 uint32_t result = 0;
11493 for (i = 0; i < 2; i++)
11496 result |= (value & 0x00ff00ff);
11499 aarch64_set_reg_u64 (cpu, rd, NO_SP, result);
11502 /* 64 bit reverse shorts. */
11503 /* N.B.this reverses the order of the bytes in each half word. */
11505 revh64 (sim_cpu *cpu)
11507 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
11508 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
11509 uint64_t value = aarch64_get_reg_u64 (cpu, rn, NO_SP);
11510 uint64_t result = 0;
11513 for (i = 0; i < 2; i++)
11516 result |= (value & 0x00ff00ff00ff00ffULL);
11519 aarch64_set_reg_u64 (cpu, rd, NO_SP, result);
11523 dexDataProc1Source (sim_cpu *cpu)
11525 /* assert instr[30] == 1
11526 aarch64_get_instr (cpu)[28,21] == 111010110
11527 instr[31] = size : 0 ==> 32 bit, 1 ==> 64 bit
11528 instr[29] = S : 0 ==> ok, 1 ==> UNALLOC
11529 instr[20,16] = opcode2 : 00000 ==> ok, ow ==> UNALLOC
11530 instr[15,10] = opcode : 000000 ==> RBIT, 000001 ==> REV16,
11531 000010 ==> REV, 000011 ==> UNALLOC
11532 000100 ==> CLZ, 000101 ==> CLS
11534 instr[9,5] = rn : may not be SP
11535 instr[4,0] = rd : may not be SP. */
11537 uint32_t S = uimm (aarch64_get_instr (cpu), 29, 29);
11538 uint32_t opcode2 = uimm (aarch64_get_instr (cpu), 20, 16);
11539 uint32_t opcode = uimm (aarch64_get_instr (cpu), 15, 10);
11540 uint32_t dispatch = ((uimm (aarch64_get_instr (cpu), 31, 31) << 3) | opcode);
11553 case 0: rbit32 (cpu); return;
11554 case 1: revh32 (cpu); return;
11555 case 2: rev32 (cpu); return;
11556 case 4: clz32 (cpu); return;
11557 case 5: cls32 (cpu); return;
11558 case 8: rbit64 (cpu); return;
11559 case 9: revh64 (cpu); return;
11560 case 10:rev32 (cpu); return;
11561 case 11:rev64 (cpu); return;
11562 case 12:clz64 (cpu); return;
11563 case 13:cls64 (cpu); return;
11564 default: HALT_UNALLOC;
11569 Shifts by count supplied in register.
11570 N.B register args may not be SP.
11571 These all use the shifted auxiliary function for
11572 simplicity and clarity. Writing the actual shift
11573 inline would avoid a branch and so be faster but
11574 would also necessitate getting signs right. */
11576 /* 32 bit arithmetic shift right. */
11578 asrv32 (sim_cpu *cpu)
11580 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
11581 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
11582 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
11584 aarch64_set_reg_u64
11586 shifted32 (aarch64_get_reg_u32 (cpu, rn, NO_SP), ASR,
11587 (aarch64_get_reg_u32 (cpu, rm, NO_SP) & 0x1f)));
11590 /* 64 bit arithmetic shift right. */
11592 asrv64 (sim_cpu *cpu)
11594 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
11595 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
11596 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
11598 aarch64_set_reg_u64
11600 shifted64 (aarch64_get_reg_u64 (cpu, rn, NO_SP), ASR,
11601 (aarch64_get_reg_u64 (cpu, rm, NO_SP) & 0x3f)));
11604 /* 32 bit logical shift left. */
11606 lslv32 (sim_cpu *cpu)
11608 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
11609 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
11610 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
11612 aarch64_set_reg_u64
11614 shifted32 (aarch64_get_reg_u32 (cpu, rn, NO_SP), LSL,
11615 (aarch64_get_reg_u32 (cpu, rm, NO_SP) & 0x1f)));
11618 /* 64 bit arithmetic shift left. */
11620 lslv64 (sim_cpu *cpu)
11622 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
11623 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
11624 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
11626 aarch64_set_reg_u64
11628 shifted64 (aarch64_get_reg_u64 (cpu, rn, NO_SP), LSL,
11629 (aarch64_get_reg_u64 (cpu, rm, NO_SP) & 0x3f)));
11632 /* 32 bit logical shift right. */
11634 lsrv32 (sim_cpu *cpu)
11636 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
11637 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
11638 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
11640 aarch64_set_reg_u64
11642 shifted32 (aarch64_get_reg_u32 (cpu, rn, NO_SP), LSR,
11643 (aarch64_get_reg_u32 (cpu, rm, NO_SP) & 0x1f)));
11646 /* 64 bit logical shift right. */
11648 lsrv64 (sim_cpu *cpu)
11650 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
11651 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
11652 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
11654 aarch64_set_reg_u64
11656 shifted64 (aarch64_get_reg_u64 (cpu, rn, NO_SP), LSR,
11657 (aarch64_get_reg_u64 (cpu, rm, NO_SP) & 0x3f)));
11660 /* 32 bit rotate right. */
11662 rorv32 (sim_cpu *cpu)
11664 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
11665 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
11666 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
11668 aarch64_set_reg_u64
11670 shifted32 (aarch64_get_reg_u32 (cpu, rn, NO_SP), ROR,
11671 (aarch64_get_reg_u32 (cpu, rm, NO_SP) & 0x1f)));
11674 /* 64 bit rotate right. */
11676 rorv64 (sim_cpu *cpu)
11678 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
11679 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
11680 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
11682 aarch64_set_reg_u64
11684 shifted64 (aarch64_get_reg_u64 (cpu, rn, NO_SP), ROR,
11685 (aarch64_get_reg_u64 (cpu, rm, NO_SP) & 0x3f)));
11691 /* 32 bit signed divide. */
11693 cpuiv32 (sim_cpu *cpu)
11695 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
11696 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
11697 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
11698 /* N.B. the pseudo-code does the divide using 64 bit data. */
11699 /* TODO : check that this rounds towards zero as required. */
11700 int64_t dividend = aarch64_get_reg_s32 (cpu, rn, NO_SP);
11701 int64_t divisor = aarch64_get_reg_s32 (cpu, rm, NO_SP);
11703 aarch64_set_reg_s64 (cpu, rd, NO_SP,
11704 divisor ? ((int32_t) (dividend / divisor)) : 0);
11707 /* 64 bit signed divide. */
11709 cpuiv64 (sim_cpu *cpu)
11711 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
11712 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
11713 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
11715 /* TODO : check that this rounds towards zero as required. */
11716 int64_t divisor = aarch64_get_reg_s64 (cpu, rm, NO_SP);
11718 aarch64_set_reg_s64
11720 divisor ? (aarch64_get_reg_s64 (cpu, rn, NO_SP) / divisor) : 0);
11723 /* 32 bit unsigned divide. */
11725 udiv32 (sim_cpu *cpu)
11727 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
11728 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
11729 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
11731 /* N.B. the pseudo-code does the divide using 64 bit data. */
11732 uint64_t dividend = aarch64_get_reg_u32 (cpu, rn, NO_SP);
11733 uint64_t divisor = aarch64_get_reg_u32 (cpu, rm, NO_SP);
11735 aarch64_set_reg_u64 (cpu, rd, NO_SP,
11736 divisor ? (uint32_t) (dividend / divisor) : 0);
11739 /* 64 bit unsigned divide. */
11741 udiv64 (sim_cpu *cpu)
11743 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
11744 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
11745 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
11747 /* TODO : check that this rounds towards zero as required. */
11748 uint64_t divisor = aarch64_get_reg_u64 (cpu, rm, NO_SP);
11750 aarch64_set_reg_u64
11752 divisor ? (aarch64_get_reg_u64 (cpu, rn, NO_SP) / divisor) : 0);
11756 dexDataProc2Source (sim_cpu *cpu)
11758 /* assert instr[30] == 0
11759 instr[28,21] == 11010110
11760 instr[31] = size : 0 ==> 32 bit, 1 ==> 64 bit
11761 instr[29] = S : 0 ==> ok, 1 ==> UNALLOC
11762 instr[15,10] = opcode : 000010 ==> UDIV, 000011 ==> CPUIV,
11763 001000 ==> LSLV, 001001 ==> LSRV
11764 001010 ==> ASRV, 001011 ==> RORV
11768 uint32_t S = uimm (aarch64_get_instr (cpu), 29, 29);
11769 uint32_t opcode = uimm (aarch64_get_instr (cpu), 15, 10);
11777 dispatch = ( (uimm (aarch64_get_instr (cpu), 31, 31) << 3)
11778 | (uimm (opcode, 3, 3) << 2)
11779 | uimm (opcode, 1, 0));
11782 case 2: udiv32 (cpu); return;
11783 case 3: cpuiv32 (cpu); return;
11784 case 4: lslv32 (cpu); return;
11785 case 5: lsrv32 (cpu); return;
11786 case 6: asrv32 (cpu); return;
11787 case 7: rorv32 (cpu); return;
11788 case 10: udiv64 (cpu); return;
11789 case 11: cpuiv64 (cpu); return;
11790 case 12: lslv64 (cpu); return;
11791 case 13: lsrv64 (cpu); return;
11792 case 14: asrv64 (cpu); return;
11793 case 15: rorv64 (cpu); return;
11794 default: HALT_UNALLOC;
11801 /* 32 bit multiply and add. */
11803 madd32 (sim_cpu *cpu)
11805 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
11806 unsigned ra = uimm (aarch64_get_instr (cpu), 14, 10);
11807 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
11808 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
11810 aarch64_set_reg_u64 (cpu, rd, NO_SP,
11811 aarch64_get_reg_u32 (cpu, ra, NO_SP)
11812 + aarch64_get_reg_u32 (cpu, rn, NO_SP)
11813 * aarch64_get_reg_u32 (cpu, rm, NO_SP));
11816 /* 64 bit multiply and add. */
11818 madd64 (sim_cpu *cpu)
11820 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
11821 unsigned ra = uimm (aarch64_get_instr (cpu), 14, 10);
11822 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
11823 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
11825 aarch64_set_reg_u64 (cpu, rd, NO_SP,
11826 aarch64_get_reg_u64 (cpu, ra, NO_SP)
11827 + aarch64_get_reg_u64 (cpu, rn, NO_SP)
11828 * aarch64_get_reg_u64 (cpu, rm, NO_SP));
11831 /* 32 bit multiply and sub. */
11833 msub32 (sim_cpu *cpu)
11835 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
11836 unsigned ra = uimm (aarch64_get_instr (cpu), 14, 10);
11837 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
11838 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
11840 aarch64_set_reg_u64 (cpu, rd, NO_SP,
11841 aarch64_get_reg_u32 (cpu, ra, NO_SP)
11842 - aarch64_get_reg_u32 (cpu, rn, NO_SP)
11843 * aarch64_get_reg_u32 (cpu, rm, NO_SP));
11846 /* 64 bit multiply and sub. */
11848 msub64 (sim_cpu *cpu)
11850 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
11851 unsigned ra = uimm (aarch64_get_instr (cpu), 14, 10);
11852 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
11853 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
11855 aarch64_set_reg_u64 (cpu, rd, NO_SP,
11856 aarch64_get_reg_u64 (cpu, ra, NO_SP)
11857 - aarch64_get_reg_u64 (cpu, rn, NO_SP)
11858 * aarch64_get_reg_u64 (cpu, rm, NO_SP));
11861 /* Signed multiply add long -- source, source2 : 32 bit, source3 : 64 bit. */
11863 smaddl (sim_cpu *cpu)
11865 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
11866 unsigned ra = uimm (aarch64_get_instr (cpu), 14, 10);
11867 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
11868 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
11870 /* N.B. we need to multiply the signed 32 bit values in rn, rm to
11871 obtain a 64 bit product. */
11872 aarch64_set_reg_s64
11874 aarch64_get_reg_s64 (cpu, ra, NO_SP)
11875 + ((int64_t) aarch64_get_reg_s32 (cpu, rn, NO_SP))
11876 * ((int64_t) aarch64_get_reg_s32 (cpu, rm, NO_SP)));
11879 /* Signed multiply sub long -- source, source2 : 32 bit, source3 : 64 bit. */
11881 smsubl (sim_cpu *cpu)
11883 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
11884 unsigned ra = uimm (aarch64_get_instr (cpu), 14, 10);
11885 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
11886 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
11888 /* N.B. we need to multiply the signed 32 bit values in rn, rm to
11889 obtain a 64 bit product. */
11890 aarch64_set_reg_s64
11892 aarch64_get_reg_s64 (cpu, ra, NO_SP)
11893 - ((int64_t) aarch64_get_reg_s32 (cpu, rn, NO_SP))
11894 * ((int64_t) aarch64_get_reg_s32 (cpu, rm, NO_SP)));
11897 /* Integer Multiply/Divide. */
11899 /* First some macros and a helper function. */
11900 /* Macros to test or access elements of 64 bit words. */
11902 /* Mask used to access lo 32 bits of 64 bit unsigned int. */
11903 #define LOW_WORD_MASK ((1ULL << 32) - 1)
11904 /* Return the lo 32 bit word of a 64 bit unsigned int as a 64 bit unsigned int. */
11905 #define lowWordToU64(_value_u64) ((_value_u64) & LOW_WORD_MASK)
11906 /* Return the hi 32 bit word of a 64 bit unsigned int as a 64 bit unsigned int. */
11907 #define highWordToU64(_value_u64) ((_value_u64) >> 32)
11909 /* Offset of sign bit in 64 bit signed integger. */
11910 #define SIGN_SHIFT_U64 63
11911 /* The sign bit itself -- also identifies the minimum negative int value. */
11912 #define SIGN_BIT_U64 (1UL << SIGN_SHIFT_U64)
11913 /* Return true if a 64 bit signed int presented as an unsigned int is the
11914 most negative value. */
11915 #define isMinimumU64(_value_u64) ((_value_u64) == SIGN_BIT_U64)
11916 /* Return true (non-zero) if a 64 bit signed int presented as an unsigned
11917 int has its sign bit set to false. */
11918 #define isSignSetU64(_value_u64) ((_value_u64) & SIGN_BIT_U64)
11919 /* Return 1L or -1L according to whether a 64 bit signed int presented as
11920 an unsigned int has its sign bit set or not. */
11921 #define signOfU64(_value_u64) (1L + (((value_u64) >> SIGN_SHIFT_U64) * -2L)
11922 /* Clear the sign bit of a 64 bit signed int presented as an unsigned int. */
11923 #define clearSignU64(_value_u64) ((_value_u64) &= ~SIGN_BIT_U64)
11925 /* Multiply two 64 bit ints and return.
11926 the hi 64 bits of the 128 bit product. */
11929 mul64hi (uint64_t value1, uint64_t value2)
11931 uint64_t resultmid1;
11933 uint64_t value1_lo = lowWordToU64 (value1);
11934 uint64_t value1_hi = highWordToU64 (value1) ;
11935 uint64_t value2_lo = lowWordToU64 (value2);
11936 uint64_t value2_hi = highWordToU64 (value2);
11938 /* Cross-multiply and collect results. */
11940 uint64_t xproductlo = value1_lo * value2_lo;
11941 uint64_t xproductmid1 = value1_lo * value2_hi;
11942 uint64_t xproductmid2 = value1_hi * value2_lo;
11943 uint64_t xproducthi = value1_hi * value2_hi;
11944 uint64_t carry = 0;
11945 /* Start accumulating 64 bit results. */
11946 /* Drop bottom half of lowest cross-product. */
11947 uint64_t resultmid = xproductlo >> 32;
11948 /* Add in middle products. */
11949 resultmid = resultmid + xproductmid1;
11951 /* Check for overflow. */
11952 if (resultmid < xproductmid1)
11953 /* Carry over 1 into top cross-product. */
11956 resultmid1 = resultmid + xproductmid2;
11958 /* Check for overflow. */
11959 if (resultmid1 < xproductmid2)
11960 /* Carry over 1 into top cross-product. */
11963 /* Drop lowest 32 bits of middle cross-product. */
11964 result = resultmid1 >> 32;
11966 /* Add top cross-product plus and any carry. */
11967 result += xproducthi + carry;
11972 /* Signed multiply high, source, source2 :
11973 64 bit, dest <-- high 64-bit of result. */
11975 smulh (sim_cpu *cpu)
11979 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
11980 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
11981 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
11982 GReg ra = greg (aarch64_get_instr (cpu), 10);
11983 int64_t value1 = aarch64_get_reg_u64 (cpu, rn, NO_SP);
11984 int64_t value2 = aarch64_get_reg_u64 (cpu, rm, NO_SP);
11987 int64_t signum = 1;
11992 /* Convert to unsigned and use the unsigned mul64hi routine
11993 the fix the sign up afterwards. */
12014 uresult = mul64hi (uvalue1, uvalue2);
12018 aarch64_set_reg_s64 (cpu, rd, NO_SP, result);
12021 /* Unsigned multiply add long -- source, source2 :
12022 32 bit, source3 : 64 bit. */
12024 umaddl (sim_cpu *cpu)
12026 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
12027 unsigned ra = uimm (aarch64_get_instr (cpu), 14, 10);
12028 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
12029 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
12031 /* N.B. we need to multiply the signed 32 bit values in rn, rm to
12032 obtain a 64 bit product. */
12033 aarch64_set_reg_u64
12035 aarch64_get_reg_u64 (cpu, ra, NO_SP)
12036 + ((uint64_t) aarch64_get_reg_u32 (cpu, rn, NO_SP))
12037 * ((uint64_t) aarch64_get_reg_u32 (cpu, rm, NO_SP)));
12040 /* Unsigned multiply sub long -- source, source2 : 32 bit, source3 : 64 bit. */
12042 umsubl (sim_cpu *cpu)
12044 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
12045 unsigned ra = uimm (aarch64_get_instr (cpu), 14, 10);
12046 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
12047 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
12049 /* N.B. we need to multiply the signed 32 bit values in rn, rm to
12050 obtain a 64 bit product. */
12051 aarch64_set_reg_u64
12053 aarch64_get_reg_u64 (cpu, ra, NO_SP)
12054 - ((uint64_t) aarch64_get_reg_u32 (cpu, rn, NO_SP))
12055 * ((uint64_t) aarch64_get_reg_u32 (cpu, rm, NO_SP)));
12058 /* Unsigned multiply high, source, source2 :
12059 64 bit, dest <-- high 64-bit of result. */
12061 umulh (sim_cpu *cpu)
12063 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
12064 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
12065 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
12066 GReg ra = greg (aarch64_get_instr (cpu), 10);
12071 aarch64_set_reg_u64 (cpu, rd, NO_SP,
12072 mul64hi (aarch64_get_reg_u64 (cpu, rn, NO_SP),
12073 aarch64_get_reg_u64 (cpu, rm, NO_SP)));
12077 dexDataProc3Source (sim_cpu *cpu)
12079 /* assert instr[28,24] == 11011. */
12080 /* instr[31] = size : 0 ==> 32 bit, 1 ==> 64 bit (for rd at least)
12081 instr[30,29] = op54 : 00 ==> ok, ow ==> UNALLOC
12082 instr[23,21] = op31 : 111 ==> UNALLOC, o2 ==> ok
12083 instr[15] = o0 : 0/1 ==> ok
12084 instr[23,21:15] ==> op : 0000 ==> MADD, 0001 ==> MSUB, (32/64 bit)
12085 0010 ==> SMADDL, 0011 ==> SMSUBL, (64 bit only)
12086 0100 ==> SMULH, (64 bit only)
12087 1010 ==> UMADDL, 1011 ==> UNSUBL, (64 bit only)
12088 1100 ==> UMULH (64 bit only)
12092 uint32_t size = uimm (aarch64_get_instr (cpu), 31, 31);
12093 uint32_t op54 = uimm (aarch64_get_instr (cpu), 30, 29);
12094 uint32_t op31 = uimm (aarch64_get_instr (cpu), 23, 21);
12095 uint32_t o0 = uimm (aarch64_get_instr (cpu), 15, 15);
12112 dispatch = (op31 << 1) | o0;
12116 case 0: madd64 (cpu); return;
12117 case 1: msub64 (cpu); return;
12118 case 2: smaddl (cpu); return;
12119 case 3: smsubl (cpu); return;
12120 case 4: smulh (cpu); return;
12121 case 10: umaddl (cpu); return;
12122 case 11: umsubl (cpu); return;
12123 case 12: umulh (cpu); return;
12124 default: HALT_UNALLOC;
12129 dexDPReg (sim_cpu *cpu)
12131 /* uint32_t group = dispatchGroup (aarch64_get_instr (cpu));
12132 assert group == GROUP_DPREG_0101 || group == GROUP_DPREG_1101
12133 bits [28:24:21] of a DPReg are the secondary dispatch vector. */
12134 uint32_t group2 = dispatchDPReg (aarch64_get_instr (cpu));
12138 case DPREG_LOG_000:
12139 case DPREG_LOG_001:
12140 dexLogicalShiftedRegister (cpu); return;
12142 case DPREG_ADDSHF_010:
12143 dexAddSubtractShiftedRegister (cpu); return;
12145 case DPREG_ADDEXT_011:
12146 dexAddSubtractExtendedRegister (cpu); return;
12148 case DPREG_ADDCOND_100:
12150 /* This set bundles a variety of different operations. */
12152 /* 1) add/sub w carry. */
12153 uint32_t mask1 = 0x1FE00000U;
12154 uint32_t val1 = 0x1A000000U;
12155 /* 2) cond compare register/immediate. */
12156 uint32_t mask2 = 0x1FE00000U;
12157 uint32_t val2 = 0x1A400000U;
12158 /* 3) cond select. */
12159 uint32_t mask3 = 0x1FE00000U;
12160 uint32_t val3 = 0x1A800000U;
12161 /* 4) data proc 1/2 source. */
12162 uint32_t mask4 = 0x1FE00000U;
12163 uint32_t val4 = 0x1AC00000U;
12165 if ((aarch64_get_instr (cpu) & mask1) == val1)
12166 dexAddSubtractWithCarry (cpu);
12168 else if ((aarch64_get_instr (cpu) & mask2) == val2)
12171 else if ((aarch64_get_instr (cpu) & mask3) == val3)
12172 dexCondSelect (cpu);
12174 else if ((aarch64_get_instr (cpu) & mask4) == val4)
12176 /* Bit 30 is clear for data proc 2 source
12177 and set for data proc 1 source. */
12178 if (aarch64_get_instr (cpu) & (1U << 30))
12179 dexDataProc1Source (cpu);
12181 dexDataProc2Source (cpu);
12185 /* Should not reach here. */
12191 case DPREG_3SRC_110:
12192 dexDataProc3Source (cpu); return;
12194 case DPREG_UNALLOC_101:
12197 case DPREG_3SRC_111:
12198 dexDataProc3Source (cpu); return;
12201 /* Should never reach here. */
12206 /* Unconditional Branch immediate.
12207 Offset is a PC-relative byte offset in the range +/- 128MiB.
12208 The offset is assumed to be raw from the decode i.e. the
12209 simulator is expected to scale them from word offsets to byte. */
12211 /* Unconditional branch. */
12213 buc (sim_cpu *cpu, int32_t offset)
12215 aarch64_set_next_PC_by_offset (cpu, offset);
12218 static unsigned stack_depth = 0;
12220 /* Unconditional branch and link -- writes return PC to LR. */
12222 bl (sim_cpu *cpu, int32_t offset)
12224 aarch64_save_LR (cpu);
12225 aarch64_set_next_PC_by_offset (cpu, offset);
12227 if (TRACE_BRANCH_P (cpu))
12231 " %*scall %" PRIx64 " [%s]"
12232 " [args: %" PRIx64 " %" PRIx64 " %" PRIx64 "]",
12233 stack_depth, " ", aarch64_get_next_PC (cpu),
12234 aarch64_get_func (aarch64_get_next_PC (cpu)),
12235 aarch64_get_reg_u64 (cpu, 0, NO_SP),
12236 aarch64_get_reg_u64 (cpu, 1, NO_SP),
12237 aarch64_get_reg_u64 (cpu, 2, NO_SP)
12242 /* Unconditional Branch register.
12243 Branch/return address is in source register. */
12245 /* Unconditional branch. */
12249 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
12250 aarch64_set_next_PC (cpu, aarch64_get_reg_u64 (cpu, rn, NO_SP));
12253 /* Unconditional branch and link -- writes return PC to LR. */
12257 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
12259 /* The pseudo code in the spec says we update LR before fetching.
12260 the value from the rn. */
12261 aarch64_save_LR (cpu);
12262 aarch64_set_next_PC (cpu, aarch64_get_reg_u64 (cpu, rn, NO_SP));
12264 if (TRACE_BRANCH_P (cpu))
12268 " %*scall %" PRIx64 " [%s]"
12269 " [args: %" PRIx64 " %" PRIx64 " %" PRIx64 "]",
12270 stack_depth, " ", aarch64_get_next_PC (cpu),
12271 aarch64_get_func (aarch64_get_next_PC (cpu)),
12272 aarch64_get_reg_u64 (cpu, 0, NO_SP),
12273 aarch64_get_reg_u64 (cpu, 1, NO_SP),
12274 aarch64_get_reg_u64 (cpu, 2, NO_SP)
12279 /* Return -- assembler will default source to LR this is functionally
12280 equivalent to br but, presumably, unlike br it side effects the
12281 branch predictor. */
12285 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
12286 aarch64_set_next_PC (cpu, aarch64_get_reg_u64 (cpu, rn, NO_SP));
12288 if (TRACE_BRANCH_P (cpu))
12291 " %*sreturn [result: %" PRIx64 "]",
12292 stack_depth, " ", aarch64_get_reg_u64 (cpu, 0, NO_SP));
12297 /* NOP -- we implement this and call it from the decode in case we
12298 want to intercept it later. */
12305 /* Data synchronization barrier. */
12312 /* Data memory barrier. */
12319 /* Instruction synchronization barrier. */
12327 dexBranchImmediate (sim_cpu *cpu)
12329 /* assert instr[30,26] == 00101
12330 instr[31] ==> 0 == B, 1 == BL
12331 instr[25,0] == imm26 branch offset counted in words. */
12333 uint32_t top = uimm (aarch64_get_instr (cpu), 31, 31);
12334 /* We have a 26 byte signed word offset which we need to pass to the
12335 execute routine as a signed byte offset. */
12336 int32_t offset = simm32 (aarch64_get_instr (cpu), 25, 0) << 2;
12344 /* Control Flow. */
12346 /* Conditional branch
12348 Offset is a PC-relative byte offset in the range +/- 1MiB pos is
12349 a bit position in the range 0 .. 63
12351 cc is a CondCode enum value as pulled out of the decode
12353 N.B. any offset register (source) can only be Xn or Wn. */
12356 bcc (sim_cpu *cpu, int32_t offset, CondCode cc)
12358 /* the test returns TRUE if CC is met. */
12359 if (testConditionCode (cpu, cc))
12360 aarch64_set_next_PC_by_offset (cpu, offset);
12363 /* 32 bit branch on register non-zero. */
12365 cbnz32 (sim_cpu *cpu, int32_t offset)
12367 unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
12369 if (aarch64_get_reg_u32 (cpu, rt, NO_SP) != 0)
12370 aarch64_set_next_PC_by_offset (cpu, offset);
12373 /* 64 bit branch on register zero. */
12375 cbnz (sim_cpu *cpu, int32_t offset)
12377 unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
12379 if (aarch64_get_reg_u64 (cpu, rt, NO_SP) != 0)
12380 aarch64_set_next_PC_by_offset (cpu, offset);
12383 /* 32 bit branch on register non-zero. */
12385 cbz32 (sim_cpu *cpu, int32_t offset)
12387 unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
12389 if (aarch64_get_reg_u32 (cpu, rt, NO_SP) == 0)
12390 aarch64_set_next_PC_by_offset (cpu, offset);
12393 /* 64 bit branch on register zero. */
12395 cbz (sim_cpu *cpu, int32_t offset)
12397 unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
12399 if (aarch64_get_reg_u64 (cpu, rt, NO_SP) == 0)
12400 aarch64_set_next_PC_by_offset (cpu, offset);
12403 /* Branch on register bit test non-zero -- one size fits all. */
12405 tbnz (sim_cpu *cpu, uint32_t pos, int32_t offset)
12407 unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
12409 if (aarch64_get_reg_u64 (cpu, rt, NO_SP) & (1 << pos))
12410 aarch64_set_next_PC_by_offset (cpu, offset);
12413 /* branch on register bit test zero -- one size fits all. */
12415 tbz (sim_cpu *cpu, uint32_t pos, int32_t offset)
12417 unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
12419 if (!(aarch64_get_reg_u64 (cpu, rt, NO_SP) & (1 << pos)))
12420 aarch64_set_next_PC_by_offset (cpu, offset);
12424 dexCompareBranchImmediate (sim_cpu *cpu)
12426 /* instr[30,25] = 01 1010
12427 instr[31] = size : 0 ==> 32, 1 ==> 64
12428 instr[24] = op : 0 ==> CBZ, 1 ==> CBNZ
12429 instr[23,5] = simm19 branch offset counted in words
12432 uint32_t size = uimm (aarch64_get_instr (cpu), 31, 31);
12433 uint32_t op = uimm (aarch64_get_instr (cpu), 24, 24);
12434 int32_t offset = simm32 (aarch64_get_instr (cpu), 23, 5) << 2;
12439 cbz32 (cpu, offset);
12441 cbnz32 (cpu, offset);
12448 cbnz (cpu, offset);
12453 dexTestBranchImmediate (sim_cpu *cpu)
12455 /* instr[31] = b5 : bit 5 of test bit idx
12456 instr[30,25] = 01 1011
12457 instr[24] = op : 0 ==> TBZ, 1 == TBNZ
12458 instr[23,19] = b40 : bits 4 to 0 of test bit idx
12459 instr[18,5] = simm14 : signed offset counted in words
12460 instr[4,0] = uimm5 */
12462 uint32_t pos = ((uimm (aarch64_get_instr (cpu), 31, 31) << 4)
12463 | uimm (aarch64_get_instr (cpu), 23,19));
12464 int32_t offset = simm32 (aarch64_get_instr (cpu), 18, 5) << 2;
12466 NYI_assert (30, 25, 0x1b);
12468 if (uimm (aarch64_get_instr (cpu), 24, 24) == 0)
12469 tbz (cpu, pos, offset);
12471 tbnz (cpu, pos, offset);
12475 dexCondBranchImmediate (sim_cpu *cpu)
12477 /* instr[31,25] = 010 1010
12478 instr[24] = op1; op => 00 ==> B.cond
12479 instr[23,5] = simm19 : signed offset counted in words
12481 instr[3,0] = cond */
12485 uint32_t op = ((uimm (aarch64_get_instr (cpu), 24, 24) << 1)
12486 | uimm (aarch64_get_instr (cpu), 4, 4));
12488 NYI_assert (31, 25, 0x2a);
12493 offset = simm32 (aarch64_get_instr (cpu), 23, 5) << 2;
12494 cc = condcode (aarch64_get_instr (cpu), 0);
12496 bcc (cpu, offset, cc);
12500 dexBranchRegister (sim_cpu *cpu)
12502 /* instr[31,25] = 110 1011
12503 instr[24,21] = op : 0 ==> BR, 1 => BLR, 2 => RET, 3 => ERET, 4 => DRPS
12504 instr[20,16] = op2 : must be 11111
12505 instr[15,10] = op3 : must be 000000
12506 instr[4,0] = op2 : must be 11111. */
12508 uint32_t op = uimm (aarch64_get_instr (cpu), 24, 21);
12509 uint32_t op2 = uimm (aarch64_get_instr (cpu), 20, 16);
12510 uint32_t op3 = uimm (aarch64_get_instr (cpu), 15, 10);
12511 uint32_t op4 = uimm (aarch64_get_instr (cpu), 4, 0);
12513 NYI_assert (31, 25, 0x6b);
12515 if (op2 != 0x1F || op3 != 0 || op4 != 0)
12529 /* ERET and DRPS accept 0b11111 for rn = aarch64_get_instr (cpu)[4,0]. */
12530 /* anything else is unallocated. */
12531 uint32_t rn = greg (aarch64_get_instr (cpu), 0);
12536 if (op == 4 || op == 5)
12543 /* FIXME: We should get the Angel SWI values from ../../libgloss/aarch64/svc.h
12544 but this may not be available. So instead we define the values we need
12546 #define AngelSVC_Reason_Open 0x01
12547 #define AngelSVC_Reason_Close 0x02
12548 #define AngelSVC_Reason_Write 0x05
12549 #define AngelSVC_Reason_Read 0x06
12550 #define AngelSVC_Reason_IsTTY 0x09
12551 #define AngelSVC_Reason_Seek 0x0A
12552 #define AngelSVC_Reason_FLen 0x0C
12553 #define AngelSVC_Reason_Remove 0x0E
12554 #define AngelSVC_Reason_Rename 0x0F
12555 #define AngelSVC_Reason_Clock 0x10
12556 #define AngelSVC_Reason_Time 0x11
12557 #define AngelSVC_Reason_System 0x12
12558 #define AngelSVC_Reason_Errno 0x13
12559 #define AngelSVC_Reason_GetCmdLine 0x15
12560 #define AngelSVC_Reason_HeapInfo 0x16
12561 #define AngelSVC_Reason_ReportException 0x18
12562 #define AngelSVC_Reason_Elapsed 0x30
12566 handle_halt (sim_cpu *cpu, uint32_t val)
12568 uint64_t result = 0;
12572 TRACE_SYSCALL (cpu, " HLT [0x%x]", val);
12573 sim_engine_halt (CPU_STATE (cpu), cpu, NULL, aarch64_get_PC (cpu),
12574 sim_stopped, SIM_SIGTRAP);
12577 /* We have encountered an Angel SVC call. See if we can process it. */
12578 switch (aarch64_get_reg_u32 (cpu, 0, NO_SP))
12580 case AngelSVC_Reason_HeapInfo:
12582 /* Get the values. */
12583 uint64_t stack_top = aarch64_get_stack_start (cpu);
12584 uint64_t heap_base = aarch64_get_heap_start (cpu);
12586 /* Get the pointer */
12587 uint64_t ptr = aarch64_get_reg_u64 (cpu, 1, SP_OK);
12588 ptr = aarch64_get_mem_u64 (cpu, ptr);
12590 /* Fill in the memory block. */
12591 /* Start addr of heap. */
12592 aarch64_set_mem_u64 (cpu, ptr + 0, heap_base);
12593 /* End addr of heap. */
12594 aarch64_set_mem_u64 (cpu, ptr + 8, stack_top);
12595 /* Lowest stack addr. */
12596 aarch64_set_mem_u64 (cpu, ptr + 16, heap_base);
12597 /* Initial stack addr. */
12598 aarch64_set_mem_u64 (cpu, ptr + 24, stack_top);
12600 TRACE_SYSCALL (cpu, " AngelSVC: Get Heap Info");
12604 case AngelSVC_Reason_Open:
12606 /* Get the pointer */
12607 /* uint64_t ptr = aarch64_get_reg_u64 (cpu, 1, SP_OK);. */
12608 /* FIXME: For now we just assume that we will only be asked
12609 to open the standard file descriptors. */
12613 TRACE_SYSCALL (cpu, " AngelSVC: Open file %d", fd - 1);
12617 case AngelSVC_Reason_Close:
12619 uint64_t fh = aarch64_get_reg_u64 (cpu, 1, SP_OK);
12620 TRACE_SYSCALL (cpu, " AngelSVC: Close file %d", (int) fh);
12625 case AngelSVC_Reason_Errno:
12627 TRACE_SYSCALL (cpu, " AngelSVC: Get Errno");
12630 case AngelSVC_Reason_Clock:
12632 #ifdef CLOCKS_PER_SEC
12633 (CLOCKS_PER_SEC >= 100)
12634 ? (clock () / (CLOCKS_PER_SEC / 100))
12635 : ((clock () * 100) / CLOCKS_PER_SEC)
12637 /* Presume unix... clock() returns microseconds. */
12641 TRACE_SYSCALL (cpu, " AngelSVC: Get Clock");
12644 case AngelSVC_Reason_GetCmdLine:
12646 /* Get the pointer */
12647 uint64_t ptr = aarch64_get_reg_u64 (cpu, 1, SP_OK);
12648 ptr = aarch64_get_mem_u64 (cpu, ptr);
12650 /* FIXME: No command line for now. */
12651 aarch64_set_mem_u64 (cpu, ptr, 0);
12652 TRACE_SYSCALL (cpu, " AngelSVC: Get Command Line");
12656 case AngelSVC_Reason_IsTTY:
12658 TRACE_SYSCALL (cpu, " AngelSVC: IsTTY ?");
12661 case AngelSVC_Reason_Write:
12663 /* Get the pointer */
12664 uint64_t ptr = aarch64_get_reg_u64 (cpu, 1, SP_OK);
12665 /* Get the write control block. */
12666 uint64_t fd = aarch64_get_mem_u64 (cpu, ptr);
12667 uint64_t buf = aarch64_get_mem_u64 (cpu, ptr + 8);
12668 uint64_t len = aarch64_get_mem_u64 (cpu, ptr + 16);
12670 TRACE_SYSCALL (cpu, "write of %" PRIx64 " bytes from %"
12671 PRIx64 " on descriptor %" PRIx64,
12676 TRACE_SYSCALL (cpu,
12677 " AngelSVC: Write: Suspiciously long write: %ld",
12679 sim_engine_halt (CPU_STATE (cpu), cpu, NULL, aarch64_get_PC (cpu),
12680 sim_stopped, SIM_SIGBUS);
12684 printf ("%.*s", (int) len, aarch64_get_mem_ptr (cpu, buf));
12686 /* So that the output stays in sync with trace output. */
12691 TRACE (cpu, 0, "\n");
12692 sim_io_eprintf (CPU_STATE (cpu), "%.*s",
12693 (int) len, aarch64_get_mem_ptr (cpu, buf));
12694 TRACE (cpu, 0, "\n");
12698 TRACE_SYSCALL (cpu,
12699 " AngelSVC: Write: Unexpected file handle: %d",
12701 sim_engine_halt (CPU_STATE (cpu), cpu, NULL, aarch64_get_PC (cpu),
12702 sim_stopped, SIM_SIGABRT);
12707 case AngelSVC_Reason_ReportException:
12709 /* Get the pointer */
12710 uint64_t ptr = aarch64_get_reg_u64 (cpu, 1, SP_OK);
12711 /*ptr = aarch64_get_mem_u64 (cpu, ptr);. */
12712 uint64_t type = aarch64_get_mem_u64 (cpu, ptr);
12713 uint64_t state = aarch64_get_mem_u64 (cpu, ptr + 8);
12715 TRACE_SYSCALL (cpu,
12716 "Angel Exception: type 0x%" PRIx64 " state %" PRIx64,
12719 if (type == 0x20026)
12720 sim_engine_halt (CPU_STATE (cpu), cpu, NULL, aarch64_get_PC (cpu),
12721 sim_exited, state);
12723 sim_engine_halt (CPU_STATE (cpu), cpu, NULL, aarch64_get_PC (cpu),
12724 sim_stopped, SIM_SIGINT);
12728 case AngelSVC_Reason_Read:
12729 case AngelSVC_Reason_FLen:
12730 case AngelSVC_Reason_Seek:
12731 case AngelSVC_Reason_Remove:
12732 case AngelSVC_Reason_Time:
12733 case AngelSVC_Reason_System:
12734 case AngelSVC_Reason_Rename:
12735 case AngelSVC_Reason_Elapsed:
12737 TRACE_SYSCALL (cpu, " HLT [Unknown angel %x]",
12738 aarch64_get_reg_u32 (cpu, 0, NO_SP));
12739 sim_engine_halt (CPU_STATE (cpu), cpu, NULL, aarch64_get_PC (cpu),
12740 sim_stopped, SIM_SIGTRAP);
12743 aarch64_set_reg_u64 (cpu, 0, NO_SP, result);
12747 dexExcpnGen (sim_cpu *cpu)
12749 /* instr[31:24] = 11010100
12750 instr[23,21] = opc : 000 ==> GEN EXCPN, 001 ==> BRK
12751 010 ==> HLT, 101 ==> DBG GEN EXCPN
12752 instr[20,5] = imm16
12753 instr[4,2] = opc2 000 ==> OK, ow ==> UNALLOC
12754 instr[1,0] = LL : discriminates opc */
12756 uint32_t opc = uimm (aarch64_get_instr (cpu), 23, 21);
12757 uint32_t imm16 = uimm (aarch64_get_instr (cpu), 20, 5);
12758 uint32_t opc2 = uimm (aarch64_get_instr (cpu), 4, 2);
12761 NYI_assert (31, 24, 0xd4);
12766 LL = uimm (aarch64_get_instr (cpu), 1, 0);
12768 /* We only implement HLT and BRK for now. */
12769 if (opc == 1 && LL == 0)
12771 TRACE_EVENTS (cpu, " BRK [0x%x]", imm16);
12772 sim_engine_halt (CPU_STATE (cpu), cpu, NULL, aarch64_get_PC (cpu),
12773 sim_exited, aarch64_get_reg_s32 (cpu, R0, SP_OK));
12776 if (opc == 2 && LL == 0)
12777 handle_halt (cpu, imm16);
12779 else if (opc == 0 || opc == 5)
12787 dexSystem (sim_cpu *cpu)
12789 /* instr[31:22] = 1101 01010 0
12796 instr[4,0] = uimm5 */
12798 /* We are interested in HINT, DSB, DMB and ISB
12800 Hint #0 encodes NOOP (this is the only hint we care about)
12801 L == 0, op0 == 0, op1 = 011, CRn = 0010, Rt = 11111,
12802 CRm op2 != 0000 000 OR CRm op2 == 0000 000 || CRm op > 0000 101
12804 DSB, DMB, ISB are data store barrier, data memory barrier and
12805 instruction store barrier, respectively, where
12807 L == 0, op0 == 0, op1 = 011, CRn = 0011, Rt = 11111,
12808 op2 : DSB ==> 100, DMB ==> 101, ISB ==> 110
12809 CRm<3:2> ==> domain, CRm<1:0> ==> types,
12810 domain : 00 ==> OuterShareable, 01 ==> Nonshareable,
12811 10 ==> InerShareable, 11 ==> FullSystem
12812 types : 01 ==> Reads, 10 ==> Writes,
12813 11 ==> All, 00 ==> All (domain == FullSystem). */
12815 unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
12816 uint32_t l_op0_op1_crn = uimm (aarch64_get_instr (cpu), 21, 12);
12818 NYI_assert (31, 22, 0x354);
12820 switch (l_op0_op1_crn)
12825 /* NOP has CRm != 0000 OR. */
12826 /* (CRm == 0000 AND (op2 == 000 OR op2 > 101)). */
12827 uint32_t crm = uimm (aarch64_get_instr (cpu), 11, 8);
12828 uint32_t op2 = uimm (aarch64_get_instr (cpu), 7, 5);
12830 if (crm != 0 || (op2 == 0 || op2 > 5))
12832 /* Actually call nop method so we can reimplement it later. */
12841 uint32_t op2 = uimm (aarch64_get_instr (cpu), 7, 5);
12848 case 4: dsb (cpu); return;
12849 case 5: dmb (cpu); return;
12850 case 6: isb (cpu); return;
12852 default: HALT_UNALLOC;
12857 /* MRS Wt, sys-reg. */
12858 /* FIXME: Ignore for now. */
12863 /* MRS Xt, sys-reg. */
12864 /* FIXME: Ignore for now. */
12868 /* DC <type>, x<n>. */
12869 /* FIXME: Ignore for now. */
12873 if (uimm (aarch64_get_instr (cpu), 21, 20) == 0x1)
12874 /* MSR <sys-reg>, <Xreg>. */
12881 dexBr (sim_cpu *cpu)
12883 /* uint32_t group = dispatchGroup (aarch64_get_instr (cpu));
12884 assert group == GROUP_BREXSYS_1010 || group == GROUP_BREXSYS_1011
12885 bits [31,29] of a BrExSys are the secondary dispatch vector. */
12886 uint32_t group2 = dispatchBrExSys (aarch64_get_instr (cpu));
12891 return dexBranchImmediate (cpu);
12893 case BR_IMMCMP_001:
12894 /* Compare has bit 25 clear while test has it set. */
12895 if (!uimm (aarch64_get_instr (cpu), 25, 25))
12896 dexCompareBranchImmediate (cpu);
12898 dexTestBranchImmediate (cpu);
12901 case BR_IMMCOND_010:
12902 /* This is a conditional branch if bit 25 is clear otherwise
12904 if (!uimm (aarch64_get_instr (cpu), 25, 25))
12905 dexCondBranchImmediate (cpu);
12910 case BR_UNALLOC_011:
12914 dexBranchImmediate (cpu);
12917 case BR_IMMCMP_101:
12918 /* Compare has bit 25 clear while test has it set. */
12919 if (!uimm (aarch64_get_instr (cpu), 25, 25))
12920 dexCompareBranchImmediate (cpu);
12922 dexTestBranchImmediate (cpu);
12926 /* Unconditional branch reg has bit 25 set. */
12927 if (uimm (aarch64_get_instr (cpu), 25, 25))
12928 dexBranchRegister (cpu);
12930 /* This includes both Excpn Gen, System and unalloc operations.
12931 We need to decode the Excpn Gen operation BRK so we can plant
12932 debugger entry points.
12933 Excpn Gen operations have aarch64_get_instr (cpu)[24] = 0.
12934 we need to decode at least one of the System operations NOP
12935 which is an alias for HINT #0.
12936 System operations have aarch64_get_instr (cpu)[24,22] = 100. */
12937 else if (uimm (aarch64_get_instr (cpu), 24, 24) == 0)
12940 else if (uimm (aarch64_get_instr (cpu), 24, 22) == 4)
12948 case BR_UNALLOC_111:
12952 /* Should never reach here. */
12958 aarch64_decode_and_execute (sim_cpu *cpu, uint64_t pc)
12960 /* We need to check if gdb wants an in here. */
12961 /* checkBreak (cpu);. */
12963 uint64_t group = dispatchGroup (aarch64_get_instr (cpu));
12967 case GROUP_PSEUDO_0000: dexPseudo (cpu); break;
12968 case GROUP_LDST_0100: dexLdSt (cpu); break;
12969 case GROUP_DPREG_0101: dexDPReg (cpu); break;
12970 case GROUP_LDST_0110: dexLdSt (cpu); break;
12971 case GROUP_ADVSIMD_0111: dexAdvSIMD0 (cpu); break;
12972 case GROUP_DPIMM_1000: dexDPImm (cpu); break;
12973 case GROUP_DPIMM_1001: dexDPImm (cpu); break;
12974 case GROUP_BREXSYS_1010: dexBr (cpu); break;
12975 case GROUP_BREXSYS_1011: dexBr (cpu); break;
12976 case GROUP_LDST_1100: dexLdSt (cpu); break;
12977 case GROUP_DPREG_1101: dexDPReg (cpu); break;
12978 case GROUP_LDST_1110: dexLdSt (cpu); break;
12979 case GROUP_ADVSIMD_1111: dexAdvSIMD1 (cpu); break;
12981 case GROUP_UNALLOC_0001:
12982 case GROUP_UNALLOC_0010:
12983 case GROUP_UNALLOC_0011:
12987 /* Should never reach here. */
12993 aarch64_step (sim_cpu *cpu)
12995 uint64_t pc = aarch64_get_PC (cpu);
12997 if (pc == TOP_LEVEL_RETURN_PC)
13000 aarch64_set_next_PC (cpu, pc + 4);
13001 aarch64_get_instr (cpu) = aarch64_get_mem_u32 (cpu, pc);
13003 if (TRACE_INSN_P (cpu))
13006 TRACE_INSN (cpu, " pc = %" PRIx64 " ", pc);
13008 TRACE_INSN (cpu, " pc = %" PRIx64 " instr = %x", pc,
13009 aarch64_get_instr (cpu));
13012 sim_io_eprintf (CPU_STATE (cpu), " %" PRIx64 " ", pc);
13015 aarch64_print_insn (CPU_STATE (cpu), pc);
13017 aarch64_decode_and_execute (cpu, pc);
13023 aarch64_run (SIM_DESC sd)
13025 sim_cpu *cpu = STATE_CPU (sd, 0);
13027 while (aarch64_step (cpu))
13028 aarch64_update_PC (cpu);
13030 sim_engine_halt (sd, NULL, NULL, aarch64_get_PC (cpu),
13031 sim_exited, aarch64_get_reg_s32 (cpu, R0, SP_OK));
13035 aarch64_init (sim_cpu *cpu, uint64_t pc)
13037 uint64_t sp = aarch64_get_stack_start (cpu);
13039 /* Install SP, FP and PC and set LR to -20
13040 so we can detect a top-level return. */
13041 aarch64_set_reg_u64 (cpu, SP, SP_OK, sp);
13042 aarch64_set_reg_u64 (cpu, FP, SP_OK, sp);
13043 aarch64_set_reg_u64 (cpu, LR, SP_OK, TOP_LEVEL_RETURN_PC);
13044 aarch64_set_next_PC (cpu, pc);
13045 aarch64_update_PC (cpu);
13046 aarch64_init_LIT_table ();