1 /* simulator.c -- Interface for the AArch64 simulator.
3 Copyright (C) 2015-2016 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>
31 #include "simulator.h"
38 #define TST(_flag) (aarch64_test_CPSR_bit (cpu, _flag))
39 #define IS_SET(_X) ( TST (( _X )))
40 #define IS_CLEAR(_X) (!TST (( _X )))
42 #define HALT_UNALLOC \
45 TRACE_DISASM (cpu, aarch64_get_PC (cpu)); \
47 "Unallocated instruction detected at sim line %d," \
48 " exe addr %" PRIx64, \
49 __LINE__, aarch64_get_PC (cpu)); \
50 sim_engine_halt (CPU_STATE (cpu), cpu, NULL, aarch64_get_PC (cpu),\
51 sim_stopped, SIM_SIGILL); \
58 TRACE_DISASM (cpu, aarch64_get_PC (cpu)); \
60 "Unimplemented instruction detected at sim line %d," \
61 " exe addr %" PRIx64, \
62 __LINE__, aarch64_get_PC (cpu)); \
63 sim_engine_halt (CPU_STATE (cpu), cpu, NULL, aarch64_get_PC (cpu),\
64 sim_stopped, SIM_SIGABRT); \
68 #define NYI_assert(HI, LO, EXPECTED) \
71 if (uimm (aarch64_get_instr (cpu), (HI), (LO)) != (EXPECTED)) \
76 #define HALT_UNREACHABLE \
79 TRACE_EVENTS (cpu, "ISE: unreachable code point"); \
80 sim_engine_abort (NULL, cpu, aarch64_get_PC (cpu), "Internal Error"); \
84 /* Helper functions used by expandLogicalImmediate. */
86 /* for i = 1, ... N result<i-1> = 1 other bits are zero */
87 static inline uint64_t
90 return (N == 64 ? (uint64_t)-1UL : ((1UL << N) - 1));
93 /* result<0> to val<N> */
94 static inline uint64_t
95 pickbit (uint64_t val, int N)
97 return pickbits64 (val, N, N);
101 expand_logical_immediate (uint32_t S, uint32_t R, uint32_t N)
107 /* The immediate value is S+1 bits to 1, left rotated by SIMDsize - R
108 (in other words, right rotated by R), then replicated. */
112 mask = 0xffffffffffffffffull;
118 case 0x00 ... 0x1f: /* 0xxxxx */ simd_size = 32; break;
119 case 0x20 ... 0x2f: /* 10xxxx */ simd_size = 16; S &= 0xf; break;
120 case 0x30 ... 0x37: /* 110xxx */ simd_size = 8; S &= 0x7; break;
121 case 0x38 ... 0x3b: /* 1110xx */ simd_size = 4; S &= 0x3; break;
122 case 0x3c ... 0x3d: /* 11110x */ simd_size = 2; S &= 0x1; break;
125 mask = (1ull << simd_size) - 1;
126 /* Top bits are IGNORED. */
130 /* NOTE: if S = simd_size - 1 we get 0xf..f which is rejected. */
131 if (S == simd_size - 1)
134 /* S+1 consecutive bits to 1. */
135 /* NOTE: S can't be 63 due to detection above. */
136 imm = (1ull << (S + 1)) - 1;
138 /* Rotate to the left by simd_size - R. */
140 imm = ((imm << (simd_size - R)) & mask) | (imm >> R);
142 /* Replicate the value according to SIMD size. */
145 case 2: imm = (imm << 2) | imm;
146 case 4: imm = (imm << 4) | imm;
147 case 8: imm = (imm << 8) | imm;
148 case 16: imm = (imm << 16) | imm;
149 case 32: imm = (imm << 32) | imm;
157 /* Instr[22,10] encodes N immr and imms. we want a lookup table
158 for each possible combination i.e. 13 bits worth of int entries. */
159 #define LI_TABLE_SIZE (1 << 13)
160 static uint64_t LITable[LI_TABLE_SIZE];
163 aarch64_init_LIT_table (void)
167 for (index = 0; index < LI_TABLE_SIZE; index++)
169 uint32_t N = uimm (index, 12, 12);
170 uint32_t immr = uimm (index, 11, 6);
171 uint32_t imms = uimm (index, 5, 0);
173 LITable [index] = expand_logical_immediate (imms, immr, N);
178 dexNotify (sim_cpu *cpu)
180 /* instr[14,0] == type : 0 ==> method entry, 1 ==> method reentry
181 2 ==> exit Java, 3 ==> start next bytecode. */
182 uint32_t type = uimm (aarch64_get_instr (cpu), 14, 0);
184 TRACE_EVENTS (cpu, "Notify Insn encountered, type = 0x%x", type);
189 /* aarch64_notifyMethodEntry (aarch64_get_reg_u64 (cpu, R23, 0),
190 aarch64_get_reg_u64 (cpu, R22, 0)); */
193 /* aarch64_notifyMethodReentry (aarch64_get_reg_u64 (cpu, R23, 0),
194 aarch64_get_reg_u64 (cpu, R22, 0)); */
197 /* aarch64_notifyMethodExit (); */
200 /* aarch64_notifyBCStart (aarch64_get_reg_u64 (cpu, R23, 0),
201 aarch64_get_reg_u64 (cpu, R22, 0)); */
206 /* secondary decode within top level groups */
209 dexPseudo (sim_cpu *cpu)
211 /* assert instr[28,27] = 00
213 We provide 2 pseudo instructions:
215 HALT stops execution of the simulator causing an immediate
216 return to the x86 code which entered it.
218 CALLOUT initiates recursive entry into x86 code. A register
219 argument holds the address of the x86 routine. Immediate
220 values in the instruction identify the number of general
221 purpose and floating point register arguments to be passed
222 and the type of any value to be returned. */
224 uint32_t PSEUDO_HALT = 0xE0000000U;
225 uint32_t PSEUDO_CALLOUT = 0x00018000U;
226 uint32_t PSEUDO_CALLOUTR = 0x00018001U;
227 uint32_t PSEUDO_NOTIFY = 0x00014000U;
230 if (aarch64_get_instr (cpu) == PSEUDO_HALT)
232 TRACE_EVENTS (cpu, " Pseudo Halt Instruction");
233 sim_engine_halt (CPU_STATE (cpu), cpu, NULL, aarch64_get_PC (cpu),
234 sim_stopped, SIM_SIGTRAP);
237 dispatch = uimm (aarch64_get_instr (cpu), 31, 15);
239 /* We do not handle callouts at the moment. */
240 if (dispatch == PSEUDO_CALLOUT || dispatch == PSEUDO_CALLOUTR)
242 TRACE_EVENTS (cpu, " Callout");
243 sim_engine_halt (CPU_STATE (cpu), cpu, NULL, aarch64_get_PC (cpu),
244 sim_stopped, SIM_SIGABRT);
247 else if (dispatch == PSEUDO_NOTIFY)
254 /* Load-store single register (unscaled offset)
255 These instructions employ a base register plus an unscaled signed
258 N.B. the base register (source) can be Xn or SP. all other
259 registers may not be SP. */
261 /* 32 bit load 32 bit unscaled signed 9 bit. */
263 ldur32 (sim_cpu *cpu, int32_t offset)
265 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
266 unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
268 aarch64_set_reg_u64 (cpu, rt, NO_SP, aarch64_get_mem_u32
269 (cpu, aarch64_get_reg_u64 (cpu, rn, SP_OK)
273 /* 64 bit load 64 bit unscaled signed 9 bit. */
275 ldur64 (sim_cpu *cpu, int32_t offset)
277 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
278 unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
280 aarch64_set_reg_u64 (cpu, rt, NO_SP, aarch64_get_mem_u64
281 (cpu, aarch64_get_reg_u64 (cpu, rn, SP_OK)
285 /* 32 bit load zero-extended byte unscaled signed 9 bit. */
287 ldurb32 (sim_cpu *cpu, int32_t offset)
289 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
290 unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
292 aarch64_set_reg_u64 (cpu, rt, NO_SP, aarch64_get_mem_u8
293 (cpu, aarch64_get_reg_u64 (cpu, rn, SP_OK)
297 /* 32 bit load sign-extended byte unscaled signed 9 bit. */
299 ldursb32 (sim_cpu *cpu, int32_t offset)
301 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
302 unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
304 aarch64_set_reg_u64 (cpu, rt, NO_SP, (uint32_t) aarch64_get_mem_s8
305 (cpu, aarch64_get_reg_u64 (cpu, rn, SP_OK)
309 /* 64 bit load sign-extended byte unscaled signed 9 bit. */
311 ldursb64 (sim_cpu *cpu, int32_t offset)
313 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
314 unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
316 aarch64_set_reg_s64 (cpu, rt, NO_SP, aarch64_get_mem_s8
317 (cpu, aarch64_get_reg_u64 (cpu, rn, SP_OK)
321 /* 32 bit load zero-extended short unscaled signed 9 bit */
323 ldurh32 (sim_cpu *cpu, int32_t offset)
325 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
326 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
328 aarch64_set_reg_u64 (cpu, rd, NO_SP, aarch64_get_mem_u16
329 (cpu, aarch64_get_reg_u64 (cpu, rn, SP_OK)
333 /* 32 bit load sign-extended short unscaled signed 9 bit */
335 ldursh32 (sim_cpu *cpu, int32_t offset)
337 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
338 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
340 aarch64_set_reg_u64 (cpu, rd, NO_SP, (uint32_t) aarch64_get_mem_s16
341 (cpu, aarch64_get_reg_u64 (cpu, rn, SP_OK)
345 /* 64 bit load sign-extended short unscaled signed 9 bit */
347 ldursh64 (sim_cpu *cpu, int32_t offset)
349 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
350 unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
352 aarch64_set_reg_s64 (cpu, rt, NO_SP, aarch64_get_mem_s16
353 (cpu, aarch64_get_reg_u64 (cpu, rn, SP_OK)
357 /* 64 bit load sign-extended word unscaled signed 9 bit */
359 ldursw (sim_cpu *cpu, int32_t offset)
361 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
362 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
364 aarch64_set_reg_u64 (cpu, rd, NO_SP, (uint32_t) aarch64_get_mem_s32
365 (cpu, aarch64_get_reg_u64 (cpu, rn, SP_OK)
369 /* N.B. with stores the value in source is written to the address
370 identified by source2 modified by offset. */
372 /* 32 bit store 32 bit unscaled signed 9 bit. */
374 stur32 (sim_cpu *cpu, int32_t offset)
376 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
377 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
379 aarch64_set_mem_u32 (cpu,
380 aarch64_get_reg_u64 (cpu, rn, SP_OK) + offset,
381 aarch64_get_reg_u32 (cpu, rd, NO_SP));
384 /* 64 bit store 64 bit unscaled signed 9 bit */
386 stur64 (sim_cpu *cpu, int32_t offset)
388 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
389 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
391 aarch64_set_mem_u64 (cpu,
392 aarch64_get_reg_u64 (cpu, rn, SP_OK) + offset,
393 aarch64_get_reg_u64 (cpu, rd, NO_SP));
396 /* 32 bit store byte unscaled signed 9 bit */
398 sturb (sim_cpu *cpu, int32_t offset)
400 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
401 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
403 aarch64_set_mem_u8 (cpu,
404 aarch64_get_reg_u64 (cpu, rn, SP_OK) + offset,
405 aarch64_get_reg_u8 (cpu, rd, NO_SP));
408 /* 32 bit store short unscaled signed 9 bit */
410 sturh (sim_cpu *cpu, int32_t offset)
412 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
413 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
415 aarch64_set_mem_u16 (cpu,
416 aarch64_get_reg_u64 (cpu, rn, SP_OK) + offset,
417 aarch64_get_reg_u16 (cpu, rd, NO_SP));
420 /* Load single register pc-relative label
421 Offset is a signed 19 bit immediate count in words
424 /* 32 bit pc-relative load */
426 ldr32_pcrel (sim_cpu *cpu, int32_t offset)
428 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
430 aarch64_set_reg_u64 (cpu, rd, NO_SP,
432 (cpu, aarch64_get_PC (cpu) + offset * 4));
435 /* 64 bit pc-relative load */
437 ldr_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 /* sign extended 32 bit pc-relative load */
448 ldrsw_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 /* float pc-relative load */
459 fldrs_pcrel (sim_cpu *cpu, int32_t offset)
461 unsigned int rd = uimm (aarch64_get_instr (cpu), 4, 0);
463 aarch64_set_FP_float (cpu, rd,
464 aarch64_get_mem_float
465 (cpu, aarch64_get_PC (cpu) + offset * 4));
468 /* double pc-relative load */
470 fldrd_pcrel (sim_cpu *cpu, int32_t offset)
472 unsigned int st = uimm (aarch64_get_instr (cpu), 4, 0);
474 aarch64_set_FP_double (cpu, st,
475 aarch64_get_mem_double
476 (cpu, aarch64_get_PC (cpu) + offset * 4));
479 /* long double pc-relative load. */
481 fldrq_pcrel (sim_cpu *cpu, int32_t offset)
483 unsigned int st = uimm (aarch64_get_instr (cpu), 4, 0);
484 uint64_t addr = aarch64_get_PC (cpu) + offset * 4;
487 aarch64_get_mem_long_double (cpu, addr, & a);
488 aarch64_set_FP_long_double (cpu, st, a);
491 /* This can be used to scale an offset by applying
492 the requisite shift. the second argument is either
495 #define SCALE(_offset, _elementSize) \
496 ((_offset) << ScaleShift ## _elementSize)
498 /* This can be used to optionally scale a register derived offset
499 by applying the requisite shift as indicated by the Scaling
500 argument. the second argument is either Byte, Short, Word
501 or Long. The third argument is either Scaled or Unscaled.
502 N.B. when _Scaling is Scaled the shift gets ANDed with
503 all 1s while when it is Unscaled it gets ANDed with 0. */
505 #define OPT_SCALE(_offset, _elementType, _Scaling) \
506 ((_offset) << (_Scaling ? ScaleShift ## _elementType : 0))
508 /* This can be used to zero or sign extend a 32 bit register derived
509 value to a 64 bit value. the first argument must be the value as
510 a uint32_t and the second must be either UXTW or SXTW. The result
511 is returned as an int64_t. */
513 static inline int64_t
514 extend (uint32_t value, Extension extension)
522 /* A branchless variant of this ought to be possible. */
523 if (extension == UXTW || extension == NoExtension)
530 /* Scalar Floating Point
532 FP load/store single register (4 addressing modes)
534 N.B. the base register (source) can be the stack pointer.
535 The secondary source register (source2) can only be an Xn register. */
537 /* Load 32 bit unscaled signed 9 bit with pre- or post-writeback. */
539 fldrs_wb (sim_cpu *cpu, int32_t offset, WriteBack wb)
541 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
542 unsigned st = uimm (aarch64_get_instr (cpu), 4, 0);
543 uint64_t address = aarch64_get_reg_u64 (cpu, rn, SP_OK);
548 aarch64_set_FP_float (cpu, st, aarch64_get_mem_float (cpu, address));
552 if (wb != NoWriteBack)
553 aarch64_set_reg_u64 (cpu, rn, SP_OK, address);
556 /* Load 32 bit scaled unsigned 12 bit. */
558 fldrs_abs (sim_cpu *cpu, uint32_t offset)
560 unsigned st = uimm (aarch64_get_instr (cpu), 4, 0);
561 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
563 aarch64_set_FP_float (cpu, st,
564 aarch64_get_mem_float
565 (cpu, aarch64_get_reg_u64 (cpu, rn, SP_OK)
566 + SCALE (offset, 32)));
569 /* Load 32 bit scaled or unscaled zero- or sign-extended
570 32-bit register offset. */
572 fldrs_scale_ext (sim_cpu *cpu, Scaling scaling, Extension extension)
574 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
575 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
576 unsigned st = uimm (aarch64_get_instr (cpu), 4, 0);
577 uint64_t address = aarch64_get_reg_u64 (cpu, rn, SP_OK);
578 int64_t extended = extend (aarch64_get_reg_u32 (cpu, rm, NO_SP), extension);
579 uint64_t displacement = OPT_SCALE (extended, 32, scaling);
581 aarch64_set_FP_float (cpu, st,
582 aarch64_get_mem_float
583 (cpu, address + displacement));
586 /* Load 64 bit unscaled signed 9 bit with pre- or post-writeback. */
588 fldrd_wb (sim_cpu *cpu, int32_t offset, WriteBack wb)
590 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
591 unsigned st = uimm (aarch64_get_instr (cpu), 4, 0);
592 uint64_t address = aarch64_get_reg_u64 (cpu, rn, SP_OK);
597 aarch64_set_FP_double (cpu, st, aarch64_get_mem_double (cpu, address));
602 if (wb != NoWriteBack)
603 aarch64_set_reg_u64 (cpu, rn, SP_OK, address);
606 /* Load 64 bit scaled unsigned 12 bit. */
608 fldrd_abs (sim_cpu *cpu, uint32_t offset)
610 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
611 unsigned st = uimm (aarch64_get_instr (cpu), 4, 0);
612 uint64_t address = aarch64_get_reg_u64 (cpu, rn, SP_OK) + SCALE (offset, 64);
614 aarch64_set_FP_double (cpu, st, aarch64_get_mem_double (cpu, address));
617 /* Load 64 bit scaled or unscaled zero- or sign-extended 32-bit register offset. */
619 fldrd_scale_ext (sim_cpu *cpu, Scaling scaling, Extension extension)
621 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
622 int64_t extended = extend (aarch64_get_reg_u32 (cpu, rm, NO_SP), extension);
623 uint64_t displacement = OPT_SCALE (extended, 64, scaling);
625 fldrd_wb (cpu, displacement, NoWriteBack);
628 /* Load 128 bit unscaled signed 9 bit with pre- or post-writeback. */
630 fldrq_wb (sim_cpu *cpu, int32_t offset, WriteBack wb)
633 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
634 unsigned st = uimm (aarch64_get_instr (cpu), 4, 0);
635 uint64_t address = aarch64_get_reg_u64 (cpu, rn, SP_OK);
640 aarch64_get_mem_long_double (cpu, address, & a);
641 aarch64_set_FP_long_double (cpu, st, a);
646 if (wb != NoWriteBack)
647 aarch64_set_reg_u64 (cpu, rn, SP_OK, address);
650 /* Load 128 bit scaled unsigned 12 bit. */
652 fldrq_abs (sim_cpu *cpu, uint32_t offset)
655 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
656 unsigned st = uimm (aarch64_get_instr (cpu), 4, 0);
657 uint64_t address = aarch64_get_reg_u64 (cpu, rn, SP_OK) + SCALE (offset, 128);
659 aarch64_get_mem_long_double (cpu, address, & a);
660 aarch64_set_FP_long_double (cpu, st, a);
663 /* Load 128 bit scaled or unscaled zero- or sign-extended 32-bit register offset */
665 fldrq_scale_ext (sim_cpu *cpu, Scaling scaling, Extension extension)
667 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
668 int64_t extended = extend (aarch64_get_reg_u32 (cpu, rm, NO_SP), extension);
669 uint64_t displacement = OPT_SCALE (extended, 128, scaling);
671 fldrq_wb (cpu, displacement, NoWriteBack);
676 load-store single register
677 There are four addressing modes available here which all employ a
678 64 bit source (base) register.
680 N.B. the base register (source) can be the stack pointer.
681 The secondary source register (source2)can only be an Xn register.
683 Scaled, 12-bit, unsigned immediate offset, without pre- and
685 Unscaled, 9-bit, signed immediate offset with pre- or post-index
687 scaled or unscaled 64-bit register offset.
688 scaled or unscaled 32-bit extended register offset.
690 All offsets are assumed to be raw from the decode i.e. the
691 simulator is expected to adjust scaled offsets based on the
692 accessed data size with register or extended register offset
693 versions the same applies except that in the latter case the
694 operation may also require a sign extend.
696 A separate method is provided for each possible addressing mode. */
698 /* 32 bit load 32 bit scaled unsigned 12 bit */
700 ldr32_abs (sim_cpu *cpu, uint32_t offset)
702 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
703 unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
705 /* The target register may not be SP but the source may be. */
706 aarch64_set_reg_u64 (cpu, rt, NO_SP, aarch64_get_mem_u32
707 (cpu, aarch64_get_reg_u64 (cpu, rn, SP_OK)
708 + SCALE (offset, 32)));
711 /* 32 bit load 32 bit unscaled signed 9 bit with pre- or post-writeback. */
713 ldr32_wb (sim_cpu *cpu, int32_t offset, WriteBack wb)
715 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
716 unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
719 if (rn == rt && wb != NoWriteBack)
722 address = aarch64_get_reg_u64 (cpu, rn, SP_OK);
727 aarch64_set_reg_u64 (cpu, rt, NO_SP, aarch64_get_mem_u32 (cpu, address));
732 if (wb != NoWriteBack)
733 aarch64_set_reg_u64 (cpu, rn, SP_OK, address);
736 /* 32 bit load 32 bit scaled or unscaled
737 zero- or sign-extended 32-bit register offset */
739 ldr32_scale_ext (sim_cpu *cpu, Scaling scaling, Extension extension)
741 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
742 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
743 unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
744 /* rn may reference SP, rm and rt must reference ZR */
746 uint64_t address = aarch64_get_reg_u64 (cpu, rn, SP_OK);
747 int64_t extended = extend (aarch64_get_reg_u32 (cpu, rm, NO_SP), extension);
748 uint64_t displacement = OPT_SCALE (extended, 32, scaling);
750 aarch64_set_reg_u64 (cpu, rt, NO_SP,
751 aarch64_get_mem_u32 (cpu, address + displacement));
754 /* 64 bit load 64 bit scaled unsigned 12 bit */
756 ldr_abs (sim_cpu *cpu, uint32_t offset)
758 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
759 unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
761 /* The target register may not be SP but the source may be. */
762 aarch64_set_reg_u64 (cpu, rt, NO_SP, aarch64_get_mem_u64
763 (cpu, aarch64_get_reg_u64 (cpu, rn, SP_OK)
764 + SCALE (offset, 64)));
767 /* 64 bit load 64 bit unscaled signed 9 bit with pre- or post-writeback. */
769 ldr_wb (sim_cpu *cpu, int32_t offset, WriteBack wb)
771 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
772 unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
775 if (rn == rt && wb != NoWriteBack)
778 address = aarch64_get_reg_u64 (cpu, rn, SP_OK);
783 aarch64_set_reg_u64 (cpu, rt, NO_SP, aarch64_get_mem_u64 (cpu, address));
788 if (wb != NoWriteBack)
789 aarch64_set_reg_u64 (cpu, rn, SP_OK, address);
792 /* 64 bit load 64 bit scaled or unscaled zero-
793 or sign-extended 32-bit register offset. */
795 ldr_scale_ext (sim_cpu *cpu, Scaling scaling, Extension extension)
797 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
798 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
799 unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
800 /* rn may reference SP, rm and rt must reference ZR */
802 uint64_t address = aarch64_get_reg_u64 (cpu, rn, SP_OK);
803 int64_t extended = extend (aarch64_get_reg_u32 (cpu, rm, NO_SP), extension);
804 uint64_t displacement = OPT_SCALE (extended, 64, scaling);
806 aarch64_set_reg_u64 (cpu, rt, NO_SP,
807 aarch64_get_mem_u64 (cpu, address + displacement));
810 /* 32 bit load zero-extended byte scaled unsigned 12 bit. */
812 ldrb32_abs (sim_cpu *cpu, uint32_t offset)
814 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
815 unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
817 /* The target register may not be SP but the source may be
818 there is no scaling required for a byte load. */
819 aarch64_set_reg_u64 (cpu, rt, NO_SP,
821 (cpu, aarch64_get_reg_u64 (cpu, rn, SP_OK) + offset));
824 /* 32 bit load zero-extended byte unscaled signed 9 bit with pre- or post-writeback. */
826 ldrb32_wb (sim_cpu *cpu, int32_t offset, WriteBack wb)
828 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
829 unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
832 if (rn == rt && wb != NoWriteBack)
835 address = aarch64_get_reg_u64 (cpu, rn, SP_OK);
840 aarch64_set_reg_u64 (cpu, rt, NO_SP, aarch64_get_mem_u8 (cpu, address));
845 if (wb != NoWriteBack)
846 aarch64_set_reg_u64 (cpu, rn, SP_OK, address);
849 /* 32 bit load zero-extended byte scaled or unscaled zero-
850 or sign-extended 32-bit register offset. */
852 ldrb32_scale_ext (sim_cpu *cpu, Scaling scaling, Extension extension)
854 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
855 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
856 unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
857 /* rn may reference SP, rm and rt must reference ZR */
859 uint64_t address = aarch64_get_reg_u64 (cpu, rn, SP_OK);
860 int64_t displacement = extend (aarch64_get_reg_u32 (cpu, rm, NO_SP),
863 /* There is no scaling required for a byte load. */
864 aarch64_set_reg_u64 (cpu, rt, NO_SP,
865 aarch64_get_mem_u8 (cpu, address + displacement));
868 /* 64 bit load sign-extended byte unscaled signed 9 bit
869 with pre- or post-writeback. */
871 ldrsb_wb (sim_cpu *cpu, int32_t offset, WriteBack wb)
873 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
874 unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
877 if (rn == rt && wb != NoWriteBack)
880 address = aarch64_get_reg_u64 (cpu, rn, SP_OK);
885 aarch64_set_reg_u64 (cpu, rt, NO_SP, aarch64_get_mem_s8 (cpu, address));
890 if (wb != NoWriteBack)
891 aarch64_set_reg_u64 (cpu, rn, SP_OK, address);
894 /* 64 bit load sign-extended byte scaled unsigned 12 bit. */
896 ldrsb_abs (sim_cpu *cpu, uint32_t offset)
898 ldrsb_wb (cpu, offset, NoWriteBack);
901 /* 64 bit load sign-extended byte scaled or unscaled zero-
902 or sign-extended 32-bit register offset. */
904 ldrsb_scale_ext (sim_cpu *cpu, Scaling scaling, Extension extension)
906 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
907 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
908 unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
909 /* rn may reference SP, rm and rt must reference ZR */
911 uint64_t address = aarch64_get_reg_u64 (cpu, rn, SP_OK);
912 int64_t displacement = extend (aarch64_get_reg_u32 (cpu, rm, NO_SP),
914 /* There is no scaling required for a byte load. */
915 aarch64_set_reg_u64 (cpu, rt, NO_SP,
916 aarch64_get_mem_s8 (cpu, address + displacement));
919 /* 32 bit load zero-extended short scaled unsigned 12 bit. */
921 ldrh32_abs (sim_cpu *cpu, uint32_t offset)
923 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
924 unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
926 /* The target register may not be SP but the source may be. */
927 aarch64_set_reg_u64 (cpu, rt, NO_SP, aarch64_get_mem_u16
928 (cpu, aarch64_get_reg_u64 (cpu, rn, SP_OK)
929 + SCALE (offset, 16)));
932 /* 32 bit load zero-extended short unscaled signed 9 bit
933 with pre- or post-writeback. */
935 ldrh32_wb (sim_cpu *cpu, int32_t offset, WriteBack wb)
937 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
938 unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
941 if (rn == rt && wb != NoWriteBack)
944 address = aarch64_get_reg_u64 (cpu, rn, SP_OK);
949 aarch64_set_reg_u64 (cpu, rt, NO_SP, aarch64_get_mem_u16 (cpu, address));
954 if (wb != NoWriteBack)
955 aarch64_set_reg_u64 (cpu, rn, SP_OK, address);
958 /* 32 bit load zero-extended short scaled or unscaled zero-
959 or sign-extended 32-bit register offset. */
961 ldrh32_scale_ext (sim_cpu *cpu, Scaling scaling, Extension extension)
963 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
964 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
965 unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
966 /* rn may reference SP, rm and rt must reference ZR */
968 uint64_t address = aarch64_get_reg_u64 (cpu, rn, SP_OK);
969 int64_t extended = extend (aarch64_get_reg_u32 (cpu, rm, NO_SP), extension);
970 uint64_t displacement = OPT_SCALE (extended, 16, scaling);
972 aarch64_set_reg_u64 (cpu, rt, NO_SP,
973 aarch64_get_mem_u16 (cpu, address + displacement));
976 /* 32 bit load sign-extended short scaled unsigned 12 bit. */
978 ldrsh32_abs (sim_cpu *cpu, uint32_t offset)
980 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
981 unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
983 /* The target register may not be SP but the source may be. */
984 aarch64_set_reg_u64 (cpu, rt, NO_SP, (uint32_t) aarch64_get_mem_s16
986 aarch64_get_reg_u64 (cpu, rn, SP_OK)
987 + SCALE (offset, 16)));
990 /* 32 bit load sign-extended short unscaled signed 9 bit
991 with pre- or post-writeback. */
993 ldrsh32_wb (sim_cpu *cpu, int32_t offset, WriteBack wb)
995 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
996 unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
999 if (rn == rt && wb != NoWriteBack)
1002 address = aarch64_get_reg_u64 (cpu, rn, SP_OK);
1007 aarch64_set_reg_u64 (cpu, rt, NO_SP,
1008 (uint32_t) aarch64_get_mem_s16 (cpu, address));
1013 if (wb != NoWriteBack)
1014 aarch64_set_reg_u64 (cpu, rn, SP_OK, address);
1017 /* 32 bit load sign-extended short scaled or unscaled zero-
1018 or sign-extended 32-bit register offset. */
1020 ldrsh32_scale_ext (sim_cpu *cpu, Scaling scaling, Extension extension)
1022 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
1023 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
1024 unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
1025 /* rn may reference SP, rm and rt must reference ZR */
1027 uint64_t address = aarch64_get_reg_u64 (cpu, rn, SP_OK);
1028 int64_t extended = extend (aarch64_get_reg_u32 (cpu, rm, NO_SP), extension);
1029 uint64_t displacement = OPT_SCALE (extended, 16, scaling);
1031 aarch64_set_reg_u64 (cpu, rt, NO_SP,
1032 (uint32_t) aarch64_get_mem_s16
1033 (cpu, address + displacement));
1036 /* 64 bit load sign-extended short scaled unsigned 12 bit. */
1038 ldrsh_abs (sim_cpu *cpu, uint32_t offset)
1040 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
1041 unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
1043 /* The target register may not be SP but the source may be. */
1044 aarch64_set_reg_u64 (cpu, rt, NO_SP, aarch64_get_mem_s16
1045 (cpu, aarch64_get_reg_u64 (cpu, rn, SP_OK)
1046 + SCALE (offset, 16)));
1049 /* 64 bit load sign-extended short unscaled signed 9 bit
1050 with pre- or post-writeback. */
1052 ldrsh64_wb (sim_cpu *cpu, int32_t offset, WriteBack wb)
1054 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
1055 unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
1058 if (rn == rt && wb != NoWriteBack)
1061 address = aarch64_get_reg_u64 (cpu, rn, SP_OK);
1066 aarch64_set_reg_u64 (cpu, rt, NO_SP, aarch64_get_mem_s16 (cpu, address));
1071 if (wb != NoWriteBack)
1072 aarch64_set_reg_u64 (cpu, rn, SP_OK, address);
1075 /* 64 bit load sign-extended short scaled or unscaled zero-
1076 or sign-extended 32-bit register offset. */
1078 ldrsh_scale_ext (sim_cpu *cpu, Scaling scaling, Extension extension)
1080 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
1081 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
1082 unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
1083 /* rn may reference SP, rm and rt must reference ZR */
1085 uint64_t address = aarch64_get_reg_u64 (cpu, rn, SP_OK);
1086 int64_t extended = extend (aarch64_get_reg_u32 (cpu, rm, NO_SP), extension);
1087 uint64_t displacement = OPT_SCALE (extended, 16, scaling);
1089 aarch64_set_reg_u64 (cpu, rt, NO_SP,
1090 aarch64_get_mem_s16 (cpu, address + displacement));
1093 /* 64 bit load sign-extended 32 bit scaled unsigned 12 bit. */
1095 ldrsw_abs (sim_cpu *cpu, uint32_t offset)
1097 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
1098 unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
1100 /* The target register may not be SP but the source may be. */
1101 return aarch64_set_reg_s64 (cpu, rt, NO_SP, aarch64_get_mem_s32
1102 (cpu, aarch64_get_reg_u64 (cpu, rn, SP_OK)
1103 + SCALE (offset, 32)));
1106 /* 64 bit load sign-extended 32 bit unscaled signed 9 bit
1107 with pre- or post-writeback. */
1109 ldrsw_wb (sim_cpu *cpu, int32_t offset, WriteBack wb)
1111 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
1112 unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
1115 if (rn == rt && wb != NoWriteBack)
1118 address = aarch64_get_reg_u64 (cpu, rn, SP_OK);
1123 aarch64_set_reg_s64 (cpu, rt, NO_SP, aarch64_get_mem_s32 (cpu, address));
1128 if (wb != NoWriteBack)
1129 aarch64_set_reg_u64 (cpu, rn, SP_OK, address);
1132 /* 64 bit load sign-extended 32 bit scaled or unscaled zero-
1133 or sign-extended 32-bit register offset. */
1135 ldrsw_scale_ext (sim_cpu *cpu, Scaling scaling, Extension extension)
1137 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
1138 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
1139 unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
1140 /* rn may reference SP, rm and rt must reference ZR */
1142 uint64_t address = aarch64_get_reg_u64 (cpu, rn, SP_OK);
1143 int64_t extended = extend (aarch64_get_reg_u32 (cpu, rm, NO_SP), extension);
1144 uint64_t displacement = OPT_SCALE (extended, 32, scaling);
1146 aarch64_set_reg_s64 (cpu, rt, NO_SP,
1147 aarch64_get_mem_s32 (cpu, address + displacement));
1150 /* N.B. with stores the value in source is written to the
1151 address identified by source2 modified by source3/offset. */
1153 /* 32 bit store scaled unsigned 12 bit. */
1155 str32_abs (sim_cpu *cpu, uint32_t offset)
1157 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
1158 unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
1160 /* The target register may not be SP but the source may be. */
1161 aarch64_set_mem_u32 (cpu, (aarch64_get_reg_u64 (cpu, rn, SP_OK)
1162 + SCALE (offset, 32)),
1163 aarch64_get_reg_u32 (cpu, rt, NO_SP));
1166 /* 32 bit store unscaled signed 9 bit with pre- or post-writeback. */
1168 str32_wb (sim_cpu *cpu, int32_t offset, WriteBack wb)
1170 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
1171 unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
1174 if (rn == rt && wb != NoWriteBack)
1177 address = aarch64_get_reg_u64 (cpu, rn, SP_OK);
1181 aarch64_set_mem_u32 (cpu, address, aarch64_get_reg_u32 (cpu, rt, NO_SP));
1186 if (wb != NoWriteBack)
1187 aarch64_set_reg_u64 (cpu, rn, SP_OK, address);
1190 /* 32 bit store scaled or unscaled zero- or
1191 sign-extended 32-bit register offset. */
1193 str32_scale_ext (sim_cpu *cpu, Scaling scaling, Extension extension)
1195 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
1196 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
1197 unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
1199 uint64_t address = aarch64_get_reg_u64 (cpu, rn, SP_OK);
1200 int64_t extended = extend (aarch64_get_reg_u32 (cpu, rm, NO_SP), extension);
1201 uint64_t displacement = OPT_SCALE (extended, 32, scaling);
1203 aarch64_set_mem_u32 (cpu, address + displacement,
1204 aarch64_get_reg_u64 (cpu, rt, NO_SP));
1207 /* 64 bit store scaled unsigned 12 bit. */
1209 str_abs (sim_cpu *cpu, uint32_t offset)
1211 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
1212 unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
1214 aarch64_set_mem_u64 (cpu,
1215 aarch64_get_reg_u64 (cpu, rn, SP_OK)
1216 + SCALE (offset, 64),
1217 aarch64_get_reg_u64 (cpu, rt, NO_SP));
1220 /* 64 bit store unscaled signed 9 bit with pre- or post-writeback. */
1222 str_wb (sim_cpu *cpu, int32_t offset, WriteBack wb)
1224 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
1225 unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
1228 if (rn == rt && wb != NoWriteBack)
1231 address = aarch64_get_reg_u64 (cpu, rn, SP_OK);
1236 aarch64_set_mem_u64 (cpu, address, aarch64_get_reg_u64 (cpu, rt, NO_SP));
1241 if (wb != NoWriteBack)
1242 aarch64_set_reg_u64 (cpu, rn, SP_OK, address);
1245 /* 64 bit store scaled or unscaled zero-
1246 or sign-extended 32-bit register offset. */
1248 str_scale_ext (sim_cpu *cpu, Scaling scaling, Extension extension)
1250 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
1251 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
1252 unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
1253 /* rn may reference SP, rm and rt must reference ZR */
1255 uint64_t address = aarch64_get_reg_u64 (cpu, rn, SP_OK);
1256 int64_t extended = extend (aarch64_get_reg_u32 (cpu, rm, NO_SP),
1258 uint64_t displacement = OPT_SCALE (extended, 64, scaling);
1260 aarch64_set_mem_u64 (cpu, address + displacement,
1261 aarch64_get_reg_u64 (cpu, rt, NO_SP));
1264 /* 32 bit store byte scaled unsigned 12 bit. */
1266 strb_abs (sim_cpu *cpu, uint32_t offset)
1268 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
1269 unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
1271 /* The target register may not be SP but the source may be.
1272 There is no scaling required for a byte load. */
1273 aarch64_set_mem_u8 (cpu,
1274 aarch64_get_reg_u64 (cpu, rn, SP_OK) + offset,
1275 aarch64_get_reg_u8 (cpu, rt, NO_SP));
1278 /* 32 bit store byte unscaled signed 9 bit with pre- or post-writeback. */
1280 strb_wb (sim_cpu *cpu, int32_t offset, WriteBack wb)
1282 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
1283 unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
1286 if (rn == rt && wb != NoWriteBack)
1289 address = aarch64_get_reg_u64 (cpu, rn, SP_OK);
1294 aarch64_set_mem_u8 (cpu, address, aarch64_get_reg_u8 (cpu, rt, NO_SP));
1299 if (wb != NoWriteBack)
1300 aarch64_set_reg_u64 (cpu, rn, SP_OK, address);
1303 /* 32 bit store byte scaled or unscaled zero-
1304 or sign-extended 32-bit register offset. */
1306 strb_scale_ext (sim_cpu *cpu, Scaling scaling, Extension extension)
1308 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
1309 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
1310 unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
1311 /* rn may reference SP, rm and rt must reference ZR */
1313 uint64_t address = aarch64_get_reg_u64 (cpu, rn, SP_OK);
1314 int64_t displacement = extend (aarch64_get_reg_u32 (cpu, rm, NO_SP),
1317 /* There is no scaling required for a byte load. */
1318 aarch64_set_mem_u8 (cpu, address + displacement,
1319 aarch64_get_reg_u8 (cpu, rt, NO_SP));
1322 /* 32 bit store short scaled unsigned 12 bit. */
1324 strh_abs (sim_cpu *cpu, uint32_t offset)
1326 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
1327 unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
1329 /* The target register may not be SP but the source may be. */
1330 aarch64_set_mem_u16 (cpu, aarch64_get_reg_u64 (cpu, rn, SP_OK)
1331 + SCALE (offset, 16),
1332 aarch64_get_reg_u16 (cpu, rt, NO_SP));
1335 /* 32 bit store short unscaled signed 9 bit with pre- or post-writeback. */
1337 strh_wb (sim_cpu *cpu, int32_t offset, WriteBack wb)
1339 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
1340 unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
1343 if (rn == rt && wb != NoWriteBack)
1346 address = aarch64_get_reg_u64 (cpu, rn, SP_OK);
1351 aarch64_set_mem_u16 (cpu, address, aarch64_get_reg_u16 (cpu, rt, NO_SP));
1356 if (wb != NoWriteBack)
1357 aarch64_set_reg_u64 (cpu, rn, SP_OK, address);
1360 /* 32 bit store short scaled or unscaled zero-
1361 or sign-extended 32-bit register offset. */
1363 strh_scale_ext (sim_cpu *cpu, Scaling scaling, Extension extension)
1365 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
1366 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
1367 unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
1368 /* rn may reference SP, rm and rt must reference ZR */
1370 uint64_t address = aarch64_get_reg_u64 (cpu, rn, SP_OK);
1371 int64_t extended = extend (aarch64_get_reg_u32 (cpu, rm, NO_SP), extension);
1372 uint64_t displacement = OPT_SCALE (extended, 16, scaling);
1374 aarch64_set_mem_u16 (cpu, address + displacement,
1375 aarch64_get_reg_u16 (cpu, rt, NO_SP));
1378 /* Prefetch unsigned 12 bit. */
1380 prfm_abs (sim_cpu *cpu, uint32_t offset)
1382 /* instr[4,0] = prfop : 00000 ==> PLDL1KEEP, 00001 ==> PLDL1STRM,
1383 00010 ==> PLDL2KEEP, 00001 ==> PLDL2STRM,
1384 00100 ==> PLDL3KEEP, 00101 ==> PLDL3STRM,
1385 10000 ==> PSTL1KEEP, 10001 ==> PSTL1STRM,
1386 10010 ==> PSTL2KEEP, 10001 ==> PSTL2STRM,
1387 10100 ==> PSTL3KEEP, 10101 ==> PSTL3STRM,
1389 PrfOp prfop = prfop (aarch64_get_instr (cpu), 4, 0);
1390 uint64_t address = aarch64_get_reg_u64 (cpu, rn, SP_OK)
1391 + SCALE (offset, 64). */
1393 /* TODO : implement prefetch of address. */
1396 /* Prefetch scaled or unscaled zero- or sign-extended 32-bit register offset. */
1398 prfm_scale_ext (sim_cpu *cpu, Scaling scaling, Extension extension)
1400 /* instr[4,0] = prfop : 00000 ==> PLDL1KEEP, 00001 ==> PLDL1STRM,
1401 00010 ==> PLDL2KEEP, 00001 ==> PLDL2STRM,
1402 00100 ==> PLDL3KEEP, 00101 ==> PLDL3STRM,
1403 10000 ==> PSTL1KEEP, 10001 ==> PSTL1STRM,
1404 10010 ==> PSTL2KEEP, 10001 ==> PSTL2STRM,
1405 10100 ==> PSTL3KEEP, 10101 ==> PSTL3STRM,
1407 rn may reference SP, rm may only reference ZR
1408 PrfOp prfop = prfop (aarch64_get_instr (cpu), 4, 0);
1409 uint64_t base = aarch64_get_reg_u64 (cpu, rn, SP_OK);
1410 int64_t extended = extend (aarch64_get_reg_u32 (cpu, rm, NO_SP),
1412 uint64_t displacement = OPT_SCALE (extended, 64, scaling);
1413 uint64_t address = base + displacement. */
1415 /* TODO : implement prefetch of address */
1418 /* 64 bit pc-relative prefetch. */
1420 prfm_pcrel (sim_cpu *cpu, int32_t offset)
1422 /* instr[4,0] = prfop : 00000 ==> PLDL1KEEP, 00001 ==> PLDL1STRM,
1423 00010 ==> PLDL2KEEP, 00001 ==> PLDL2STRM,
1424 00100 ==> PLDL3KEEP, 00101 ==> PLDL3STRM,
1425 10000 ==> PSTL1KEEP, 10001 ==> PSTL1STRM,
1426 10010 ==> PSTL2KEEP, 10001 ==> PSTL2STRM,
1427 10100 ==> PSTL3KEEP, 10101 ==> PSTL3STRM,
1429 PrfOp prfop = prfop (aarch64_get_instr (cpu), 4, 0);
1430 uint64_t address = aarch64_get_PC (cpu) + offset. */
1432 /* TODO : implement this */
1435 /* Load-store exclusive. */
1440 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
1441 unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
1442 uint64_t address = aarch64_get_reg_u64 (cpu, rn, SP_OK);
1443 int size = uimm (aarch64_get_instr (cpu), 31, 30);
1444 /* int ordered = uimm (aarch64_get_instr (cpu), 15, 15); */
1445 /* int exclusive = ! uimm (aarch64_get_instr (cpu), 23, 23); */
1450 aarch64_set_reg_u64 (cpu, rt, NO_SP, aarch64_get_mem_u8 (cpu, address));
1453 aarch64_set_reg_u64 (cpu, rt, NO_SP, aarch64_get_mem_u16 (cpu, address));
1456 aarch64_set_reg_u64 (cpu, rt, NO_SP, aarch64_get_mem_u32 (cpu, address));
1459 aarch64_set_reg_u64 (cpu, rt, NO_SP, aarch64_get_mem_u64 (cpu, address));
1469 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
1470 unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
1471 unsigned rs = uimm (aarch64_get_instr (cpu), 20, 16);
1472 uint64_t address = aarch64_get_reg_u64 (cpu, rn, SP_OK);
1473 int size = uimm (aarch64_get_instr (cpu), 31, 30);
1474 uint64_t data = aarch64_get_reg_u64 (cpu, rt, NO_SP);
1478 case 0: aarch64_set_mem_u8 (cpu, address, data); break;
1479 case 1: aarch64_set_mem_u16 (cpu, address, data); break;
1480 case 2: aarch64_set_mem_u32 (cpu, address, data); break;
1481 case 3: aarch64_set_mem_u64 (cpu, address, data); break;
1482 default: HALT_UNALLOC;
1485 aarch64_set_reg_u64 (cpu, rs, NO_SP, 0); /* Always exclusive... */
1489 dexLoadLiteral (sim_cpu *cpu)
1491 /* instr[29,27] == 011
1493 instr[31,30:26] = opc: 000 ==> LDRW, 001 ==> FLDRS
1494 010 ==> LDRX, 011 ==> FLDRD
1495 100 ==> LDRSW, 101 ==> FLDRQ
1496 110 ==> PRFM, 111 ==> UNALLOC
1497 instr[26] ==> V : 0 ==> GReg, 1 ==> FReg
1498 instr[23, 5] == simm19 */
1500 /* unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0); */
1501 uint32_t dispatch = ( (uimm (aarch64_get_instr (cpu), 31, 30) << 1)
1502 | uimm (aarch64_get_instr (cpu), 26, 26));
1503 int32_t imm = simm32 (aarch64_get_instr (cpu), 23, 5);
1507 case 0: ldr32_pcrel (cpu, imm); break;
1508 case 1: fldrs_pcrel (cpu, imm); break;
1509 case 2: ldr_pcrel (cpu, imm); break;
1510 case 3: fldrd_pcrel (cpu, imm); break;
1511 case 4: ldrsw_pcrel (cpu, imm); break;
1512 case 5: fldrq_pcrel (cpu, imm); break;
1513 case 6: prfm_pcrel (cpu, imm); break;
1520 /* Immediate arithmetic
1521 The aimm argument is a 12 bit unsigned value or a 12 bit unsigned
1522 value left shifted by 12 bits (done at decode).
1524 N.B. the register args (dest, source) can normally be Xn or SP.
1525 the exception occurs for flag setting instructions which may
1526 only use Xn for the output (dest). */
1528 /* 32 bit add immediate. */
1530 add32 (sim_cpu *cpu, uint32_t aimm)
1532 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
1533 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
1535 aarch64_set_reg_u64 (cpu, rd, SP_OK,
1536 aarch64_get_reg_u32 (cpu, rn, SP_OK) + aimm);
1539 /* 64 bit add immediate. */
1541 add64 (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_u64 (cpu, rn, SP_OK) + aimm);
1551 set_flags_for_add32 (sim_cpu *cpu, int32_t value1, int32_t value2)
1553 int32_t result = value1 + value2;
1554 int64_t sresult = (int64_t) value1 + (int64_t) value2;
1555 uint64_t uresult = (uint64_t)(uint32_t) value1
1556 + (uint64_t)(uint32_t) value2;
1562 if (result & (1 << 31))
1565 if (uresult != result)
1568 if (sresult != result)
1571 aarch64_set_CPSR (cpu, flags);
1575 set_flags_for_add64 (sim_cpu *cpu, uint64_t value1, uint64_t value2)
1577 int64_t sval1 = value1;
1578 int64_t sval2 = value2;
1579 uint64_t result = value1 + value2;
1580 int64_t sresult = sval1 + sval2;
1586 if (result & (1ULL << 63))
1593 /* Negative plus a negative. Overflow happens if
1594 the result is greater than either of the operands. */
1595 if (sresult > sval1 || sresult > sval2)
1598 /* else Negative plus a positive. Overflow cannot happen. */
1600 else /* value1 is +ve. */
1604 /* Overflow can only occur if we computed "0 - MININT". */
1605 if (sval1 == 0 && sval2 == (1LL << 63))
1610 /* Postive plus positive - overflow has happened if the
1611 result is smaller than either of the operands. */
1612 if (result < value1 || result < value2)
1617 aarch64_set_CPSR (cpu, flags);
1620 #define NEG(a) (((a) & signbit) == signbit)
1621 #define POS(a) (((a) & signbit) == 0)
1624 set_flags_for_sub32 (sim_cpu *cpu, uint32_t value1, uint32_t value2)
1626 uint32_t result = value1 - value2;
1628 uint32_t signbit = 1U << 31;
1636 if ( (NEG (value1) && POS (value2))
1637 || (NEG (value1) && POS (result))
1638 || (POS (value2) && POS (result)))
1641 if ( (NEG (value1) && POS (value2) && POS (result))
1642 || (POS (value1) && NEG (value2) && NEG (result)))
1645 aarch64_set_CPSR (cpu, flags);
1649 set_flags_for_sub64 (sim_cpu *cpu, uint64_t value1, uint64_t value2)
1651 uint64_t result = value1 - value2;
1653 uint64_t signbit = 1ULL << 63;
1661 if ( (NEG (value1) && POS (value2))
1662 || (NEG (value1) && POS (result))
1663 || (POS (value2) && POS (result)))
1666 if ( (NEG (value1) && POS (value2) && POS (result))
1667 || (POS (value1) && NEG (value2) && NEG (result)))
1670 aarch64_set_CPSR (cpu, flags);
1674 set_flags_for_binop32 (sim_cpu *cpu, uint32_t result)
1683 if (result & (1 << 31))
1688 aarch64_set_CPSR (cpu, flags);
1692 set_flags_for_binop64 (sim_cpu *cpu, uint64_t result)
1701 if (result & (1ULL << 63))
1706 aarch64_set_CPSR (cpu, flags);
1709 /* 32 bit add immediate set flags. */
1711 adds32 (sim_cpu *cpu, uint32_t aimm)
1713 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
1714 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
1715 /* TODO : do we need to worry about signs here? */
1716 int32_t value1 = aarch64_get_reg_s32 (cpu, rn, SP_OK);
1718 aarch64_set_reg_u64 (cpu, rd, NO_SP, value1 + aimm);
1719 set_flags_for_add32 (cpu, value1, aimm);
1722 /* 64 bit add immediate set flags. */
1724 adds64 (sim_cpu *cpu, uint32_t aimm)
1726 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
1727 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
1728 uint64_t value1 = aarch64_get_reg_u64 (cpu, rn, SP_OK);
1729 uint64_t value2 = aimm;
1731 aarch64_set_reg_u64 (cpu, rd, NO_SP, value1 + value2);
1732 set_flags_for_add64 (cpu, value1, value2);
1735 /* 32 bit sub immediate. */
1737 sub32 (sim_cpu *cpu, uint32_t aimm)
1739 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
1740 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
1742 aarch64_set_reg_u64 (cpu, rd, SP_OK,
1743 aarch64_get_reg_u32 (cpu, rn, SP_OK) - aimm);
1746 /* 64 bit sub immediate. */
1748 sub64 (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_u64 (cpu, rn, SP_OK) - aimm);
1757 /* 32 bit sub immediate set flags. */
1759 subs32 (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);
1763 uint32_t value1 = aarch64_get_reg_u64 (cpu, rn, SP_OK);
1764 uint32_t value2 = aimm;
1766 aarch64_set_reg_u64 (cpu, rd, NO_SP, value1 - value2);
1767 set_flags_for_sub32 (cpu, value1, value2);
1770 /* 64 bit sub immediate set flags. */
1772 subs64 (sim_cpu *cpu, uint32_t aimm)
1774 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
1775 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
1776 uint64_t value1 = aarch64_get_reg_u64 (cpu, rn, SP_OK);
1777 uint32_t value2 = aimm;
1779 aarch64_set_reg_u64 (cpu, rd, NO_SP, value1 - value2);
1780 set_flags_for_sub64 (cpu, value1, value2);
1783 /* Data Processing Register. */
1785 /* First two helpers to perform the shift operations. */
1787 static inline uint32_t
1788 shifted32 (uint32_t value, Shift shift, uint32_t count)
1794 return (value << count);
1796 return (value >> count);
1799 int32_t svalue = value;
1800 return (svalue >> count);
1804 uint32_t top = value >> count;
1805 uint32_t bottom = value << (32 - count);
1806 return (bottom | top);
1811 static inline uint64_t
1812 shifted64 (uint64_t value, Shift shift, uint32_t count)
1818 return (value << count);
1820 return (value >> count);
1823 int64_t svalue = value;
1824 return (svalue >> count);
1828 uint64_t top = value >> count;
1829 uint64_t bottom = value << (64 - count);
1830 return (bottom | top);
1835 /* Arithmetic shifted register.
1836 These allow an optional LSL, ASR or LSR to the second source
1837 register with a count up to the register bit count.
1839 N.B register args may not be SP. */
1841 /* 32 bit ADD shifted register. */
1843 add32_shift (sim_cpu *cpu, Shift shift, uint32_t count)
1845 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
1846 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
1847 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
1849 aarch64_set_reg_u64 (cpu, rd, NO_SP,
1850 aarch64_get_reg_u32 (cpu, rn, NO_SP)
1851 + shifted32 (aarch64_get_reg_u32 (cpu, rm, NO_SP),
1855 /* 64 bit ADD shifted register. */
1857 add64_shift (sim_cpu *cpu, Shift shift, uint32_t count)
1859 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
1860 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
1861 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
1863 aarch64_set_reg_u64 (cpu, rd, NO_SP,
1864 aarch64_get_reg_u64 (cpu, rn, NO_SP)
1865 + shifted64 (aarch64_get_reg_u64 (cpu, rm, NO_SP),
1869 /* 32 bit ADD shifted register setting flags. */
1871 adds32_shift (sim_cpu *cpu, Shift shift, uint32_t count)
1873 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
1874 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
1875 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
1877 uint32_t value1 = aarch64_get_reg_u32 (cpu, rn, NO_SP);
1878 uint32_t value2 = shifted32 (aarch64_get_reg_u32 (cpu, rm, NO_SP),
1881 aarch64_set_reg_u64 (cpu, rd, NO_SP, value1 + value2);
1882 set_flags_for_add32 (cpu, value1, value2);
1885 /* 64 bit ADD shifted register setting flags. */
1887 adds64_shift (sim_cpu *cpu, Shift shift, uint32_t count)
1889 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
1890 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
1891 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
1893 uint64_t value1 = aarch64_get_reg_u64 (cpu, rn, NO_SP);
1894 uint64_t value2 = shifted64 (aarch64_get_reg_u64 (cpu, rm, NO_SP),
1897 aarch64_set_reg_u64 (cpu, rd, NO_SP, value1 + value2);
1898 set_flags_for_add64 (cpu, value1, value2);
1901 /* 32 bit SUB shifted register. */
1903 sub32_shift (sim_cpu *cpu, Shift shift, uint32_t count)
1905 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
1906 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
1907 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
1909 aarch64_set_reg_u64 (cpu, rd, NO_SP,
1910 aarch64_get_reg_u32 (cpu, rn, NO_SP)
1911 - shifted32 (aarch64_get_reg_u32 (cpu, rm, NO_SP),
1915 /* 64 bit SUB shifted register. */
1917 sub64_shift (sim_cpu *cpu, Shift shift, uint32_t count)
1919 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
1920 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
1921 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
1923 aarch64_set_reg_u64 (cpu, rd, NO_SP,
1924 aarch64_get_reg_u64 (cpu, rn, NO_SP)
1925 - shifted64 (aarch64_get_reg_u64 (cpu, rm, NO_SP),
1929 /* 32 bit SUB shifted register setting flags. */
1931 subs32_shift (sim_cpu *cpu, Shift shift, uint32_t count)
1933 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
1934 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
1935 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
1937 uint32_t value1 = aarch64_get_reg_u32 (cpu, rn, NO_SP);
1938 uint32_t value2 = shifted32 (aarch64_get_reg_u32 (cpu, rm, NO_SP),
1941 aarch64_set_reg_u64 (cpu, rd, NO_SP, value1 - value2);
1942 set_flags_for_sub32 (cpu, value1, value2);
1945 /* 64 bit SUB shifted register setting flags. */
1947 subs64_shift (sim_cpu *cpu, Shift shift, uint32_t count)
1949 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
1950 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
1951 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
1953 uint64_t value1 = aarch64_get_reg_u64 (cpu, rn, NO_SP);
1954 uint64_t value2 = shifted64 (aarch64_get_reg_u64 (cpu, rm, NO_SP),
1957 aarch64_set_reg_u64 (cpu, rd, NO_SP, value1 - value2);
1958 set_flags_for_sub64 (cpu, value1, value2);
1961 /* First a couple more helpers to fetch the
1962 relevant source register element either
1963 sign or zero extended as required by the
1967 extreg32 (sim_cpu *cpu, unsigned int lo, Extension extension)
1971 case UXTB: return aarch64_get_reg_u8 (cpu, lo, NO_SP);
1972 case UXTH: return aarch64_get_reg_u16 (cpu, lo, NO_SP);
1973 case UXTW: /* Fall through. */
1974 case UXTX: return aarch64_get_reg_u32 (cpu, lo, NO_SP);
1975 case SXTB: return aarch64_get_reg_s8 (cpu, lo, NO_SP);
1976 case SXTH: return aarch64_get_reg_s16 (cpu, lo, NO_SP);
1977 case SXTW: /* Fall through. */
1978 case SXTX: /* Fall through. */
1979 default: return aarch64_get_reg_s32 (cpu, lo, NO_SP);
1984 extreg64 (sim_cpu *cpu, unsigned int lo, Extension extension)
1988 case UXTB: return aarch64_get_reg_u8 (cpu, lo, NO_SP);
1989 case UXTH: return aarch64_get_reg_u16 (cpu, lo, NO_SP);
1990 case UXTW: return aarch64_get_reg_u32 (cpu, lo, NO_SP);
1991 case UXTX: return aarch64_get_reg_u64 (cpu, lo, NO_SP);
1992 case SXTB: return aarch64_get_reg_s8 (cpu, lo, NO_SP);
1993 case SXTH: return aarch64_get_reg_s16 (cpu, lo, NO_SP);
1994 case SXTW: return aarch64_get_reg_s32 (cpu, lo, NO_SP);
1996 default: return aarch64_get_reg_s64 (cpu, lo, NO_SP);
2000 /* Arithmetic extending register
2001 These allow an optional sign extension of some portion of the
2002 second source register followed by an optional left shift of
2003 between 1 and 4 bits (i.e. a shift of 0-4 bits???)
2005 N.B output (dest) and first input arg (source) may normally be Xn
2006 or SP. However, for flag setting operations dest can only be
2007 Xn. Second input registers are always Xn. */
2009 /* 32 bit ADD extending register. */
2011 add32_ext (sim_cpu *cpu, Extension extension, uint32_t shift)
2013 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
2014 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
2015 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
2017 aarch64_set_reg_u64 (cpu, rd, SP_OK,
2018 aarch64_get_reg_u32 (cpu, rn, SP_OK)
2019 + (extreg32 (cpu, rm, extension) << shift));
2022 /* 64 bit ADD extending register.
2023 N.B. This subsumes the case with 64 bit source2 and UXTX #n or LSL #0. */
2025 add64_ext (sim_cpu *cpu, Extension extension, uint32_t shift)
2027 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
2028 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
2029 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
2031 aarch64_set_reg_u64 (cpu, rd, SP_OK,
2032 aarch64_get_reg_u64 (cpu, rn, SP_OK)
2033 + (extreg64 (cpu, rm, extension) << shift));
2036 /* 32 bit ADD extending register setting flags. */
2038 adds32_ext (sim_cpu *cpu, Extension extension, uint32_t shift)
2040 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
2041 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
2042 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
2044 uint32_t value1 = aarch64_get_reg_u32 (cpu, rn, SP_OK);
2045 uint32_t value2 = extreg32 (cpu, rm, extension) << shift;
2047 aarch64_set_reg_u64 (cpu, rd, NO_SP, value1 + value2);
2048 set_flags_for_add32 (cpu, value1, value2);
2051 /* 64 bit ADD extending register setting flags */
2052 /* N.B. this subsumes the case with 64 bit source2 and UXTX #n or LSL #0 */
2054 adds64_ext (sim_cpu *cpu, Extension extension, uint32_t shift)
2056 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
2057 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
2058 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
2060 uint64_t value1 = aarch64_get_reg_u64 (cpu, rn, SP_OK);
2061 uint64_t value2 = extreg64 (cpu, rm, extension) << shift;
2063 aarch64_set_reg_u64 (cpu, rd, NO_SP, value1 + value2);
2064 set_flags_for_add64 (cpu, value1, value2);
2067 /* 32 bit SUB extending register. */
2069 sub32_ext (sim_cpu *cpu, Extension extension, uint32_t shift)
2071 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
2072 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
2073 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
2075 aarch64_set_reg_u64 (cpu, rd, SP_OK,
2076 aarch64_get_reg_u32 (cpu, rn, SP_OK)
2077 - (extreg32 (cpu, rm, extension) << shift));
2080 /* 64 bit SUB extending register. */
2081 /* N.B. this subsumes the case with 64 bit source2 and UXTX #n or LSL #0. */
2083 sub64_ext (sim_cpu *cpu, Extension extension, uint32_t shift)
2085 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
2086 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
2087 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
2089 aarch64_set_reg_u64 (cpu, rd, SP_OK,
2090 aarch64_get_reg_u64 (cpu, rn, SP_OK)
2091 - (extreg64 (cpu, rm, extension) << shift));
2094 /* 32 bit SUB extending register setting flags. */
2096 subs32_ext (sim_cpu *cpu, Extension extension, uint32_t shift)
2098 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
2099 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
2100 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
2102 uint32_t value1 = aarch64_get_reg_u32 (cpu, rn, SP_OK);
2103 uint32_t value2 = extreg32 (cpu, rm, extension) << shift;
2105 aarch64_set_reg_u64 (cpu, rd, NO_SP, value1 - value2);
2106 set_flags_for_sub32 (cpu, value1, value2);
2109 /* 64 bit SUB extending register setting flags */
2110 /* N.B. this subsumes the case with 64 bit source2 and UXTX #n or LSL #0 */
2112 subs64_ext (sim_cpu *cpu, Extension extension, uint32_t shift)
2114 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
2115 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
2116 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
2118 uint64_t value1 = aarch64_get_reg_u64 (cpu, rn, SP_OK);
2119 uint64_t value2 = extreg64 (cpu, rm, extension) << shift;
2121 aarch64_set_reg_u64 (cpu, rd, NO_SP, value1 - value2);
2122 set_flags_for_sub64 (cpu, value1, value2);
2126 dexAddSubtractImmediate (sim_cpu *cpu)
2128 /* instr[31] = size : 0 ==> 32 bit, 1 ==> 64 bit
2129 instr[30] = op : 0 ==> ADD, 1 ==> SUB
2130 instr[29] = set : 0 ==> no flags, 1 ==> set flags
2131 instr[28,24] = 10001
2132 instr[23,22] = shift : 00 == LSL#0, 01 = LSL#12 1x = UNALLOC
2133 instr[21,10] = uimm12
2137 /* N.B. the shift is applied at decode before calling the add/sub routine. */
2138 uint32_t shift = uimm (aarch64_get_instr (cpu), 23, 22);
2139 uint32_t imm = uimm (aarch64_get_instr (cpu), 21, 10);
2140 uint32_t dispatch = uimm (aarch64_get_instr (cpu), 31, 29);
2142 NYI_assert (28, 24, 0x11);
2152 case 0: add32 (cpu, imm); break;
2153 case 1: adds32 (cpu, imm); break;
2154 case 2: sub32 (cpu, imm); break;
2155 case 3: subs32 (cpu, imm); break;
2156 case 4: add64 (cpu, imm); break;
2157 case 5: adds64 (cpu, imm); break;
2158 case 6: sub64 (cpu, imm); break;
2159 case 7: subs64 (cpu, imm); break;
2166 dexAddSubtractShiftedRegister (sim_cpu *cpu)
2168 /* instr[31] = size : 0 ==> 32 bit, 1 ==> 64 bit
2169 instr[30,29] = op : 00 ==> ADD, 01 ==> ADDS, 10 ==> SUB, 11 ==> SUBS
2170 instr[28,24] = 01011
2171 instr[23,22] = shift : 0 ==> LSL, 1 ==> LSR, 2 ==> ASR, 3 ==> UNALLOC
2174 instr[15,10] = count : must be 0xxxxx for 32 bit
2178 uint32_t size = uimm (aarch64_get_instr (cpu), 31, 31);
2179 /* 32 bit operations must have count[5] = 0
2180 or else we have an UNALLOC. */
2181 uint32_t count = uimm (aarch64_get_instr (cpu), 15, 10);
2182 /* Shift encoded as ROR is unallocated. */
2183 Shift shiftType = shift (aarch64_get_instr (cpu), 22);
2184 /* Dispatch on size:op i.e aarch64_get_instr (cpu)[31,29]. */
2185 uint32_t dispatch = uimm (aarch64_get_instr (cpu), 31, 29);
2187 NYI_assert (28, 24, 0x0B);
2188 NYI_assert (21, 21, 0);
2190 if (shiftType == ROR)
2193 if (!size && uimm (count, 5, 5))
2198 case 0: add32_shift (cpu, shiftType, count); break;
2199 case 1: adds32_shift (cpu, shiftType, count); break;
2200 case 2: sub32_shift (cpu, shiftType, count); break;
2201 case 3: subs32_shift (cpu, shiftType, count); break;
2202 case 4: add64_shift (cpu, shiftType, count); break;
2203 case 5: adds64_shift (cpu, shiftType, count); break;
2204 case 6: sub64_shift (cpu, shiftType, count); break;
2205 case 7: subs64_shift (cpu, shiftType, count); break;
2212 dexAddSubtractExtendedRegister (sim_cpu *cpu)
2214 /* instr[31] = size : 0 ==> 32 bit, 1 ==> 64 bit
2215 instr[30] = op : 0 ==> ADD, 1 ==> SUB
2216 instr[29] = set? : 0 ==> no flags, 1 ==> set flags
2217 instr[28,24] = 01011
2218 instr[23,22] = opt : 0 ==> ok, 1,2,3 ==> UNALLOC
2221 instr[15,13] = option : 000 ==> UXTB, 001 ==> UXTH,
2222 000 ==> LSL|UXTW, 001 ==> UXTZ,
2223 000 ==> SXTB, 001 ==> SXTH,
2224 000 ==> SXTW, 001 ==> SXTX,
2225 instr[12,10] = shift : 0,1,2,3,4 ==> ok, 5,6,7 ==> UNALLOC
2229 Extension extensionType = extension (aarch64_get_instr (cpu), 13);
2230 uint32_t shift = uimm (aarch64_get_instr (cpu), 12, 10);
2231 /* dispatch on size:op:set? i.e aarch64_get_instr (cpu)[31,29] */
2232 uint32_t dispatch = uimm (aarch64_get_instr (cpu), 31, 29);
2234 NYI_assert (28, 24, 0x0B);
2235 NYI_assert (21, 21, 1);
2237 /* Shift may not exceed 4. */
2243 case 0: add32_ext (cpu, extensionType, shift); break;
2244 case 1: adds32_ext (cpu, extensionType, shift); break;
2245 case 2: sub32_ext (cpu, extensionType, shift); break;
2246 case 3: subs32_ext (cpu, extensionType, shift); break;
2247 case 4: add64_ext (cpu, extensionType, shift); break;
2248 case 5: adds64_ext (cpu, extensionType, shift); break;
2249 case 6: sub64_ext (cpu, extensionType, shift); break;
2250 case 7: subs64_ext (cpu, extensionType, shift); break;
2251 default: HALT_UNALLOC;
2255 /* Conditional data processing
2256 Condition register is implicit 3rd source. */
2258 /* 32 bit add with carry. */
2259 /* N.B register args may not be SP. */
2262 adc32 (sim_cpu *cpu)
2264 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
2265 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
2266 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
2268 aarch64_set_reg_u64 (cpu, rd, NO_SP,
2269 aarch64_get_reg_u32 (cpu, rn, NO_SP)
2270 + aarch64_get_reg_u32 (cpu, rm, NO_SP)
2274 /* 64 bit add with carry */
2276 adc64 (sim_cpu *cpu)
2278 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
2279 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
2280 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
2282 aarch64_set_reg_u64 (cpu, rd, NO_SP,
2283 aarch64_get_reg_u64 (cpu, rn, NO_SP)
2284 + aarch64_get_reg_u64 (cpu, rm, NO_SP)
2288 /* 32 bit add with carry setting flags. */
2290 adcs32 (sim_cpu *cpu)
2292 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
2293 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
2294 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
2296 uint32_t value1 = aarch64_get_reg_u32 (cpu, rn, NO_SP);
2297 uint32_t value2 = aarch64_get_reg_u32 (cpu, rm, NO_SP);
2298 uint32_t carry = IS_SET (C);
2300 aarch64_set_reg_u64 (cpu, rd, NO_SP, value1 + value2 + carry);
2301 set_flags_for_add32 (cpu, value1, value2 + carry);
2304 /* 64 bit add with carry setting flags. */
2306 adcs64 (sim_cpu *cpu)
2308 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
2309 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
2310 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
2312 uint64_t value1 = aarch64_get_reg_u64 (cpu, rn, NO_SP);
2313 uint64_t value2 = aarch64_get_reg_u64 (cpu, rm, NO_SP);
2314 uint64_t carry = IS_SET (C);
2316 aarch64_set_reg_u64 (cpu, rd, NO_SP, value1 + value2 + carry);
2317 set_flags_for_add64 (cpu, value1, value2 + carry);
2320 /* 32 bit sub with carry. */
2322 sbc32 (sim_cpu *cpu)
2324 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
2325 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
2326 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
2328 aarch64_set_reg_u64 (cpu, rd, NO_SP,
2329 aarch64_get_reg_u32 (cpu, rn, NO_SP)
2330 - aarch64_get_reg_u32 (cpu, rm, NO_SP)
2334 /* 64 bit sub with carry */
2336 sbc64 (sim_cpu *cpu)
2338 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
2339 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
2340 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
2342 aarch64_set_reg_u64 (cpu, rd, NO_SP,
2343 aarch64_get_reg_u64 (cpu, rn, NO_SP)
2344 - aarch64_get_reg_u64 (cpu, rm, NO_SP)
2348 /* 32 bit sub with carry setting flags */
2350 sbcs32 (sim_cpu *cpu)
2352 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
2353 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
2354 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
2356 uint32_t value1 = aarch64_get_reg_u32 (cpu, rn, NO_SP);
2357 uint32_t value2 = aarch64_get_reg_u32 (cpu, rm, NO_SP);
2358 uint32_t carry = IS_SET (C);
2359 uint32_t result = value1 - value2 + 1 - carry;
2361 aarch64_set_reg_u64 (cpu, rd, NO_SP, result);
2362 set_flags_for_sub32 (cpu, value1, value2 + 1 - carry);
2365 /* 64 bit sub with carry setting flags */
2367 sbcs64 (sim_cpu *cpu)
2369 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
2370 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
2371 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
2373 uint64_t value1 = aarch64_get_reg_u64 (cpu, rn, NO_SP);
2374 uint64_t value2 = aarch64_get_reg_u64 (cpu, rm, NO_SP);
2375 uint64_t carry = IS_SET (C);
2376 uint64_t result = value1 - value2 + 1 - carry;
2378 aarch64_set_reg_u64 (cpu, rd, NO_SP, result);
2379 set_flags_for_sub64 (cpu, value1, value2 + 1 - carry);
2383 dexAddSubtractWithCarry (sim_cpu *cpu)
2385 /* instr[31] = size : 0 ==> 32 bit, 1 ==> 64 bit
2386 instr[30] = op : 0 ==> ADC, 1 ==> SBC
2387 instr[29] = set? : 0 ==> no flags, 1 ==> set flags
2388 instr[28,21] = 1 1010 000
2390 instr[15,10] = op2 : 00000 ==> ok, ow ==> UNALLOC
2394 uint32_t op2 = uimm (aarch64_get_instr (cpu), 15, 10);
2395 /* Dispatch on size:op:set? i.e aarch64_get_instr (cpu)[31,29] */
2396 uint32_t dispatch = uimm (aarch64_get_instr (cpu), 31, 29);
2398 NYI_assert (28, 21, 0xD0);
2405 case 0: adc32 (cpu); break;
2406 case 1: adcs32 (cpu); break;
2407 case 2: sbc32 (cpu); break;
2408 case 3: sbcs32 (cpu); break;
2409 case 4: adc64 (cpu); break;
2410 case 5: adcs64 (cpu); break;
2411 case 6: sbc64 (cpu); break;
2412 case 7: sbcs64 (cpu); break;
2413 default: HALT_UNALLOC;
2418 testConditionCode (sim_cpu *cpu, CondCode cc)
2420 /* This should be reduceable to branchless logic
2421 by some careful testing of bits in CC followed
2422 by the requisite masking and combining of bits
2423 from the flag register.
2425 For now we do it with a switch. */
2430 case EQ: res = IS_SET (Z); break;
2431 case NE: res = IS_CLEAR (Z); break;
2432 case CS: res = IS_SET (C); break;
2433 case CC: res = IS_CLEAR (C); break;
2434 case MI: res = IS_SET (N); break;
2435 case PL: res = IS_CLEAR (N); break;
2436 case VS: res = IS_SET (V); break;
2437 case VC: res = IS_CLEAR (V); break;
2438 case HI: res = IS_SET (C) && IS_CLEAR (Z); break;
2439 case LS: res = IS_CLEAR (C) || IS_SET (Z); break;
2440 case GE: res = IS_SET (N) == IS_SET (V); break;
2441 case LT: res = IS_SET (N) != IS_SET (V); break;
2442 case GT: res = IS_CLEAR (Z) && (IS_SET (N) == IS_SET (V)); break;
2443 case LE: res = IS_SET (Z) || (IS_SET (N) != IS_SET (V)); break;
2454 CondCompare (sim_cpu *cpu) /* aka: ccmp and ccmn */
2456 /* instr[31] = size : 0 ==> 32 bit, 1 ==> 64 bit
2457 instr[30] = compare with positive (1) or negative value (0)
2458 instr[29,21] = 1 1101 0010
2459 instr[20,16] = Rm or const
2461 instr[11] = compare reg (0) or const (1)
2465 instr[3,0] = value for CPSR bits if the comparison does not take place. */
2470 NYI_assert (29, 21, 0x1d2);
2471 NYI_assert (10, 10, 0);
2472 NYI_assert (4, 4, 0);
2474 if (! testConditionCode (cpu, uimm (aarch64_get_instr (cpu), 15, 12)))
2476 aarch64_set_CPSR (cpu, uimm (aarch64_get_instr (cpu), 3, 0));
2480 negate = uimm (aarch64_get_instr (cpu), 30, 30) ? 1 : -1;
2481 rm = uimm (aarch64_get_instr (cpu), 20, 16);
2482 rn = uimm (aarch64_get_instr (cpu), 9, 5);
2484 if (uimm (aarch64_get_instr (cpu), 31, 31))
2486 if (uimm (aarch64_get_instr (cpu), 11, 11))
2487 set_flags_for_sub64 (cpu, aarch64_get_reg_u64 (cpu, rn, SP_OK),
2488 negate * (uint64_t) rm);
2490 set_flags_for_sub64 (cpu, aarch64_get_reg_u64 (cpu, rn, SP_OK),
2491 negate * aarch64_get_reg_u64 (cpu, rm, SP_OK));
2495 if (uimm (aarch64_get_instr (cpu), 11, 11))
2496 set_flags_for_sub32 (cpu, aarch64_get_reg_u32 (cpu, rn, SP_OK),
2499 set_flags_for_sub32 (cpu, aarch64_get_reg_u32 (cpu, rn, SP_OK),
2500 negate * aarch64_get_reg_u32 (cpu, rm, SP_OK));
2505 do_vec_MOV_whole_vector (sim_cpu *cpu)
2507 /* MOV Vd.T, Vs.T (alias for ORR Vd.T, Vn.T, Vm.T where Vn == Vm)
2510 instr[30] = half(0)/full(1)
2511 instr[29,21] = 001110101
2513 instr[15,10] = 000111
2517 unsigned vs = uimm (aarch64_get_instr (cpu), 9, 5);
2518 unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
2520 NYI_assert (29, 21, 0x075);
2521 NYI_assert (15, 10, 0x07);
2523 if (uimm (aarch64_get_instr (cpu), 20, 16) != vs)
2526 if (uimm (aarch64_get_instr (cpu), 30, 30))
2527 aarch64_set_vec_u64 (cpu, vd, 1, aarch64_get_vec_u64 (cpu, vs, 1));
2529 aarch64_set_vec_u64 (cpu, vd, 0, aarch64_get_vec_u64 (cpu, vs, 0));
2533 do_vec_MOV_into_scalar (sim_cpu *cpu)
2536 instr[30] = word(0)/long(1)
2537 instr[29,21] = 00 1110 000
2538 instr[20,18] = element size and index
2539 instr[17,10] = 00 0011 11
2540 instr[9,5] = V source
2541 instr[4,0] = R dest */
2543 unsigned vs = uimm (aarch64_get_instr (cpu), 9, 5);
2544 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
2546 NYI_assert (29, 21, 0x070);
2547 NYI_assert (17, 10, 0x0F);
2549 switch (uimm (aarch64_get_instr (cpu), 20, 18))
2552 aarch64_set_reg_u64 (cpu, rd, NO_SP, aarch64_get_vec_u64 (cpu, vs, 0));
2556 aarch64_set_reg_u64 (cpu, rd, NO_SP, aarch64_get_vec_u64 (cpu, vs, 1));
2563 aarch64_set_reg_u64 (cpu, rd, NO_SP, aarch64_get_vec_u32
2564 (cpu, vs, uimm (aarch64_get_instr (cpu), 20, 19)));
2573 do_vec_INS (sim_cpu *cpu)
2575 /* instr[31,21] = 01001110000
2576 instr[20,16] = element size and index
2577 instr[15,10] = 000111
2578 instr[9,5] = W source
2579 instr[4,0] = V dest */
2582 unsigned rs = uimm (aarch64_get_instr (cpu), 9, 5);
2583 unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
2585 NYI_assert (31, 21, 0x270);
2586 NYI_assert (15, 10, 0x07);
2588 if (uimm (aarch64_get_instr (cpu), 16, 16))
2590 index = uimm (aarch64_get_instr (cpu), 20, 17);
2591 aarch64_set_vec_u8 (cpu, vd, index,
2592 aarch64_get_reg_u8 (cpu, rs, NO_SP));
2594 else if (uimm (aarch64_get_instr (cpu), 17, 17))
2596 index = uimm (aarch64_get_instr (cpu), 20, 18);
2597 aarch64_set_vec_u16 (cpu, vd, index,
2598 aarch64_get_reg_u16 (cpu, rs, NO_SP));
2600 else if (uimm (aarch64_get_instr (cpu), 18, 18))
2602 index = uimm (aarch64_get_instr (cpu), 20, 19);
2603 aarch64_set_vec_u32 (cpu, vd, index,
2604 aarch64_get_reg_u32 (cpu, rs, NO_SP));
2606 else if (uimm (aarch64_get_instr (cpu), 19, 19))
2608 index = uimm (aarch64_get_instr (cpu), 20, 20);
2609 aarch64_set_vec_u64 (cpu, vd, index,
2610 aarch64_get_reg_u64 (cpu, rs, NO_SP));
2617 do_vec_DUP_vector_into_vector (sim_cpu *cpu)
2620 instr[30] = half(0)/full(1)
2621 instr[29,21] = 00 1110 000
2622 instr[20,16] = element size and index
2623 instr[15,10] = 0000 01
2624 instr[9,5] = V source
2625 instr[4,0] = V dest. */
2627 unsigned full = uimm (aarch64_get_instr (cpu), 30, 30);
2628 unsigned vs = uimm (aarch64_get_instr (cpu), 9, 5);
2629 unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
2632 NYI_assert (29, 21, 0x070);
2633 NYI_assert (15, 10, 0x01);
2635 if (uimm (aarch64_get_instr (cpu), 16, 16))
2637 index = uimm (aarch64_get_instr (cpu), 20, 17);
2639 for (i = 0; i < (full ? 16 : 8); i++)
2640 aarch64_set_vec_u8 (cpu, vd, i, aarch64_get_vec_u8 (cpu, vs, index));
2642 else if (uimm (aarch64_get_instr (cpu), 17, 17))
2644 index = uimm (aarch64_get_instr (cpu), 20, 18);
2646 for (i = 0; i < (full ? 8 : 4); i++)
2647 aarch64_set_vec_u16 (cpu, vd, i, aarch64_get_vec_u16 (cpu, vs, index));
2649 else if (uimm (aarch64_get_instr (cpu), 18, 18))
2651 index = uimm (aarch64_get_instr (cpu), 20, 19);
2653 for (i = 0; i < (full ? 4 : 2); i++)
2654 aarch64_set_vec_u32 (cpu, vd, i, aarch64_get_vec_u32 (cpu, vs, index));
2658 if (uimm (aarch64_get_instr (cpu), 19, 19) == 0)
2664 index = uimm (aarch64_get_instr (cpu), 20, 20);
2666 for (i = 0; i < 2; i++)
2667 aarch64_set_vec_u64 (cpu, vd, i, aarch64_get_vec_u64 (cpu, vs, index));
2672 do_vec_TBL (sim_cpu *cpu)
2675 instr[30] = half(0)/full(1)
2676 instr[29,21] = 00 1110 000
2679 instr[14,13] = vec length
2681 instr[9,5] = V start
2682 instr[4,0] = V dest */
2684 int full = uimm (aarch64_get_instr (cpu), 30, 30);
2685 int len = uimm (aarch64_get_instr (cpu), 14, 13) + 1;
2686 unsigned vm = uimm (aarch64_get_instr (cpu), 20, 16);
2687 unsigned vn = uimm (aarch64_get_instr (cpu), 9, 5);
2688 unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
2691 NYI_assert (29, 21, 0x070);
2692 NYI_assert (12, 10, 0);
2694 for (i = 0; i < (full ? 16 : 8); i++)
2696 unsigned int selector = aarch64_get_vec_u8 (cpu, vm, i);
2700 val = aarch64_get_vec_u8 (cpu, vn, selector);
2701 else if (selector < 32)
2702 val = len < 2 ? 0 : aarch64_get_vec_u8 (cpu, vn + 1, selector - 16);
2703 else if (selector < 48)
2704 val = len < 3 ? 0 : aarch64_get_vec_u8 (cpu, vn + 2, selector - 32);
2705 else if (selector < 64)
2706 val = len < 4 ? 0 : aarch64_get_vec_u8 (cpu, vn + 3, selector - 48);
2710 aarch64_set_vec_u8 (cpu, vd, i, val);
2715 do_vec_TRN (sim_cpu *cpu)
2718 instr[30] = half(0)/full(1)
2719 instr[29,24] = 00 1110
2724 instr[14] = TRN1 (0) / TRN2 (1)
2726 instr[9,5] = V source
2727 instr[4,0] = V dest. */
2729 int full = uimm (aarch64_get_instr (cpu), 30, 30);
2730 int second = uimm (aarch64_get_instr (cpu), 14, 14);
2731 unsigned vm = uimm (aarch64_get_instr (cpu), 20, 16);
2732 unsigned vn = uimm (aarch64_get_instr (cpu), 9, 5);
2733 unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
2736 NYI_assert (29, 24, 0x0E);
2737 NYI_assert (13, 10, 0xA);
2739 switch (uimm (aarch64_get_instr (cpu), 23, 22))
2742 for (i = 0; i < (full ? 8 : 4); i++)
2746 aarch64_get_vec_u8 (cpu, second ? vm : vn, i * 2));
2748 (cpu, vd, 1 * 2 + 1,
2749 aarch64_get_vec_u8 (cpu, second ? vn : vm, i * 2 + 1));
2754 for (i = 0; i < (full ? 4 : 2); i++)
2758 aarch64_get_vec_u16 (cpu, second ? vm : vn, i * 2));
2760 (cpu, vd, 1 * 2 + 1,
2761 aarch64_get_vec_u16 (cpu, second ? vn : vm, i * 2 + 1));
2767 (cpu, vd, 0, aarch64_get_vec_u32 (cpu, second ? vm : vn, 0));
2769 (cpu, vd, 1, aarch64_get_vec_u32 (cpu, second ? vn : vm, 1));
2771 (cpu, vd, 2, aarch64_get_vec_u32 (cpu, second ? vm : vn, 2));
2773 (cpu, vd, 3, aarch64_get_vec_u32 (cpu, second ? vn : vm, 3));
2780 aarch64_set_vec_u64 (cpu, vd, 0,
2781 aarch64_get_vec_u64 (cpu, second ? vm : vn, 0));
2782 aarch64_set_vec_u64 (cpu, vd, 1,
2783 aarch64_get_vec_u64 (cpu, second ? vn : vm, 1));
2792 do_vec_DUP_scalar_into_vector (sim_cpu *cpu)
2795 instr[30] = 0=> zero top 64-bits, 1=> duplicate into top 64-bits
2796 [must be 1 for 64-bit xfer]
2797 instr[29,20] = 00 1110 0000
2798 instr[19,16] = element size: 0001=> 8-bits, 0010=> 16-bits,
2799 0100=> 32-bits. 1000=>64-bits
2800 instr[15,10] = 0000 11
2801 instr[9,5] = W source
2802 instr[4,0] = V dest. */
2805 unsigned Vd = uimm (aarch64_get_instr (cpu), 4, 0);
2806 unsigned Rs = uimm (aarch64_get_instr (cpu), 9, 5);
2807 int both = uimm (aarch64_get_instr (cpu), 30, 30);
2809 NYI_assert (29, 20, 0x0E0);
2810 NYI_assert (15, 10, 0x03);
2812 switch (uimm (aarch64_get_instr (cpu), 19, 16))
2815 for (i = 0; i < (both ? 16 : 8); i++)
2816 aarch64_set_vec_u8 (cpu, Vd, i, aarch64_get_reg_u8 (cpu, Rs, NO_SP));
2820 for (i = 0; i < (both ? 8 : 4); i++)
2821 aarch64_set_vec_u16 (cpu, Vd, i, aarch64_get_reg_u16 (cpu, Rs, NO_SP));
2825 for (i = 0; i < (both ? 4 : 2); i++)
2826 aarch64_set_vec_u32 (cpu, Vd, i, aarch64_get_reg_u32 (cpu, Rs, NO_SP));
2832 aarch64_set_vec_u64 (cpu, Vd, 0, aarch64_get_reg_u64 (cpu, Rs, NO_SP));
2833 aarch64_set_vec_u64 (cpu, Vd, 1, aarch64_get_reg_u64 (cpu, Rs, NO_SP));
2842 do_vec_UZP (sim_cpu *cpu)
2845 instr[30] = half(0)/full(1)
2846 instr[29,24] = 00 1110
2847 instr[23,22] = size: byte(00), half(01), word (10), long (11)
2851 instr[14] = lower (0) / upper (1)
2856 int full = uimm (aarch64_get_instr (cpu), 30, 30);
2857 int upper = uimm (aarch64_get_instr (cpu), 14, 14);
2859 unsigned vm = uimm (aarch64_get_instr (cpu), 20, 16);
2860 unsigned vn = uimm (aarch64_get_instr (cpu), 9, 5);
2861 unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
2863 uint64_t val_m1 = aarch64_get_vec_u64 (cpu, vm, 0);
2864 uint64_t val_m2 = aarch64_get_vec_u64 (cpu, vm, 1);
2865 uint64_t val_n1 = aarch64_get_vec_u64 (cpu, vn, 0);
2866 uint64_t val_n2 = aarch64_get_vec_u64 (cpu, vn, 1);
2871 uint64_t input1 = upper ? val_n1 : val_m1;
2872 uint64_t input2 = upper ? val_n2 : val_m2;
2875 NYI_assert (29, 24, 0x0E);
2876 NYI_assert (21, 21, 0);
2877 NYI_assert (15, 15, 0);
2878 NYI_assert (13, 10, 6);
2880 switch (uimm (aarch64_get_instr (cpu), 23, 23))
2883 for (i = 0; i < 8; i++)
2885 val1 |= (input1 >> (i * 8)) & (0xFFULL << (i * 8));
2886 val2 |= (input2 >> (i * 8)) & (0xFFULL << (i * 8));
2891 for (i = 0; i < 4; i++)
2893 val1 |= (input1 >> (i * 16)) & (0xFFFFULL << (i * 16));
2894 val2 |= (input2 >> (i * 16)) & (0xFFFFULL << (i * 16));
2899 val1 = ((input1 & 0xFFFFFFFF) | ((input1 >> 32) & 0xFFFFFFFF00000000ULL));
2900 val2 = ((input2 & 0xFFFFFFFF) | ((input2 >> 32) & 0xFFFFFFFF00000000ULL));
2908 aarch64_set_vec_u64 (cpu, vd, 0, val1);
2910 aarch64_set_vec_u64 (cpu, vd, 1, val2);
2914 do_vec_ZIP (sim_cpu *cpu)
2917 instr[30] = half(0)/full(1)
2918 instr[29,24] = 00 1110
2919 instr[23,22] = size: byte(00), hald(01), word (10), long (11)
2923 instr[14] = lower (0) / upper (1)
2928 int full = uimm (aarch64_get_instr (cpu), 30, 30);
2929 int upper = uimm (aarch64_get_instr (cpu), 14, 14);
2931 unsigned vm = uimm (aarch64_get_instr (cpu), 20, 16);
2932 unsigned vn = uimm (aarch64_get_instr (cpu), 9, 5);
2933 unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
2935 uint64_t val_m1 = aarch64_get_vec_u64 (cpu, vm, 0);
2936 uint64_t val_m2 = aarch64_get_vec_u64 (cpu, vm, 1);
2937 uint64_t val_n1 = aarch64_get_vec_u64 (cpu, vn, 0);
2938 uint64_t val_n2 = aarch64_get_vec_u64 (cpu, vn, 1);
2943 uint64_t input1 = upper ? val_n1 : val_m1;
2944 uint64_t input2 = upper ? val_n2 : val_m2;
2946 NYI_assert (29, 24, 0x0E);
2947 NYI_assert (21, 21, 0);
2948 NYI_assert (15, 15, 0);
2949 NYI_assert (13, 10, 0xE);
2951 switch (uimm (aarch64_get_instr (cpu), 23, 23))
2955 ((input1 << 0) & (0xFF << 0))
2956 | ((input2 << 8) & (0xFF << 8))
2957 | ((input1 << 8) & (0xFF << 16))
2958 | ((input2 << 16) & (0xFF << 24))
2959 | ((input1 << 16) & (0xFFULL << 32))
2960 | ((input2 << 24) & (0xFFULL << 40))
2961 | ((input1 << 24) & (0xFFULL << 48))
2962 | ((input2 << 32) & (0xFFULL << 56));
2965 ((input1 >> 32) & (0xFF << 0))
2966 | ((input2 >> 24) & (0xFF << 8))
2967 | ((input1 >> 24) & (0xFF << 16))
2968 | ((input2 >> 16) & (0xFF << 24))
2969 | ((input1 >> 16) & (0xFFULL << 32))
2970 | ((input2 >> 8) & (0xFFULL << 40))
2971 | ((input1 >> 8) & (0xFFULL << 48))
2972 | ((input2 >> 0) & (0xFFULL << 56));
2977 ((input1 << 0) & (0xFFFF << 0))
2978 | ((input2 << 16) & (0xFFFF << 16))
2979 | ((input1 << 16) & (0xFFFFULL << 32))
2980 | ((input2 << 32) & (0xFFFFULL << 48));
2983 ((input1 >> 32) & (0xFFFF << 0))
2984 | ((input2 >> 16) & (0xFFFF << 16))
2985 | ((input1 >> 16) & (0xFFFFULL << 32))
2986 | ((input2 >> 0) & (0xFFFFULL << 48));
2990 val1 = (input1 & 0xFFFFFFFFULL) | (input2 << 32);
2991 val2 = (input2 & 0xFFFFFFFFULL) | (input1 << 32);
3000 aarch64_set_vec_u64 (cpu, vd, 0, val1);
3002 aarch64_set_vec_u64 (cpu, vd, 1, val2);
3005 /* Floating point immediates are encoded in 8 bits.
3006 fpimm[7] = sign bit.
3007 fpimm[6:4] = signed exponent.
3008 fpimm[3:0] = fraction (assuming leading 1).
3009 i.e. F = s * 1.f * 2^(e - b). */
3012 fp_immediate_for_encoding_32 (uint32_t imm8)
3015 uint32_t s, e, f, i;
3017 s = (imm8 >> 7) & 0x1;
3018 e = (imm8 >> 4) & 0x7;
3021 /* The fp value is s * n/16 * 2r where n is 16+e. */
3022 u = (16.0 + f) / 16.0;
3024 /* N.B. exponent is signed. */
3029 for (i = 0; i <= epos; i++)
3036 for (i = 0; i < eneg; i++)
3047 fp_immediate_for_encoding_64 (uint32_t imm8)
3050 uint32_t s, e, f, i;
3052 s = (imm8 >> 7) & 0x1;
3053 e = (imm8 >> 4) & 0x7;
3056 /* The fp value is s * n/16 * 2r where n is 16+e. */
3057 u = (16.0 + f) / 16.0;
3059 /* N.B. exponent is signed. */
3064 for (i = 0; i <= epos; i++)
3071 for (i = 0; i < eneg; i++)
3082 do_vec_MOV_immediate (sim_cpu *cpu)
3085 instr[30] = full/half selector
3086 instr[29,19] = 00111100000
3087 instr[18,16] = high 3 bits of uimm8
3088 instr[15,12] = size & shift:
3090 0010 => 32-bit + LSL#8
3091 0100 => 32-bit + LSL#16
3092 0110 => 32-bit + LSL#24
3093 1010 => 16-bit + LSL#8
3095 1101 => 32-bit + MSL#16
3096 1100 => 32-bit + MSL#8
3100 instr[9,5] = low 5-bits of uimm8
3103 int full = uimm (aarch64_get_instr (cpu), 30, 30);
3104 unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
3105 unsigned val = uimm (aarch64_get_instr (cpu), 18, 16) << 5
3106 | uimm (aarch64_get_instr (cpu), 9, 5);
3109 NYI_assert (29, 19, 0x1E0);
3110 NYI_assert (11, 10, 1);
3112 switch (uimm (aarch64_get_instr (cpu), 15, 12))
3114 case 0x0: /* 32-bit, no shift. */
3115 case 0x2: /* 32-bit, shift by 8. */
3116 case 0x4: /* 32-bit, shift by 16. */
3117 case 0x6: /* 32-bit, shift by 24. */
3118 val <<= (8 * uimm (aarch64_get_instr (cpu), 14, 13));
3119 for (i = 0; i < (full ? 4 : 2); i++)
3120 aarch64_set_vec_u32 (cpu, vd, i, val);
3123 case 0xa: /* 16-bit, shift by 8. */
3126 case 0x8: /* 16-bit, no shift. */
3127 for (i = 0; i < (full ? 8 : 4); i++)
3128 aarch64_set_vec_u16 (cpu, vd, i, val);
3130 case 0xd: /* 32-bit, mask shift by 16. */
3134 case 0xc: /* 32-bit, mask shift by 8. */
3137 for (i = 0; i < (full ? 4 : 2); i++)
3138 aarch64_set_vec_u32 (cpu, vd, i, val);
3141 case 0xe: /* 8-bit, no shift. */
3142 for (i = 0; i < (full ? 16 : 8); i++)
3143 aarch64_set_vec_u8 (cpu, vd, i, val);
3146 case 0xf: /* FMOV Vs.{2|4}S, #fpimm. */
3148 float u = fp_immediate_for_encoding_32 (val);
3149 for (i = 0; i < (full ? 4 : 2); i++)
3150 aarch64_set_vec_float (cpu, vd, i, u);
3160 do_vec_MVNI (sim_cpu *cpu)
3163 instr[30] = full/half selector
3164 instr[29,19] = 10111100000
3165 instr[18,16] = high 3 bits of uimm8
3166 instr[15,12] = selector
3168 instr[9,5] = low 5-bits of uimm8
3171 int full = uimm (aarch64_get_instr (cpu), 30, 30);
3172 unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
3173 unsigned val = uimm (aarch64_get_instr (cpu), 18, 16) << 5
3174 | uimm (aarch64_get_instr (cpu), 9, 5);
3177 NYI_assert (29, 19, 0x5E0);
3178 NYI_assert (11, 10, 1);
3180 switch (uimm (aarch64_get_instr (cpu), 15, 12))
3182 case 0x0: /* 32-bit, no shift. */
3183 case 0x2: /* 32-bit, shift by 8. */
3184 case 0x4: /* 32-bit, shift by 16. */
3185 case 0x6: /* 32-bit, shift by 24. */
3186 val <<= (8 * uimm (aarch64_get_instr (cpu), 14, 13));
3188 for (i = 0; i < (full ? 4 : 2); i++)
3189 aarch64_set_vec_u32 (cpu, vd, i, val);
3192 case 0xa: /* 16-bit, 8 bit shift. */
3194 case 0x8: /* 16-bit, no shift. */
3196 for (i = 0; i < (full ? 8 : 4); i++)
3197 aarch64_set_vec_u16 (cpu, vd, i, val);
3200 case 0xd: /* 32-bit, mask shift by 16. */
3203 case 0xc: /* 32-bit, mask shift by 8. */
3207 for (i = 0; i < (full ? 4 : 2); i++)
3208 aarch64_set_vec_u32 (cpu, vd, i, val);
3211 case 0xE: /* MOVI Dn, #mask64 */
3215 for (i = 0; i < 8; i++)
3217 mask |= (0xF << (i * 4));
3218 aarch64_set_vec_u64 (cpu, vd, 0, mask);
3219 aarch64_set_vec_u64 (cpu, vd, 1, 0);
3223 case 0xf: /* FMOV Vd.2D, #fpimm. */
3225 double u = fp_immediate_for_encoding_64 (val);
3230 aarch64_set_vec_double (cpu, vd, 0, u);
3231 aarch64_set_vec_double (cpu, vd, 1, u);
3240 #define ABS(A) ((A) < 0 ? - (A) : (A))
3243 do_vec_ABS (sim_cpu *cpu)
3246 instr[30] = half(0)/full(1)
3247 instr[29,24] = 00 1110
3248 instr[23,22] = size: 00=> 8-bit, 01=> 16-bit, 10=> 32-bit, 11=> 64-bit
3249 instr[21,10] = 10 0000 1011 10
3253 unsigned vn = uimm (aarch64_get_instr (cpu), 9, 5);
3254 unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
3255 unsigned full = uimm (aarch64_get_instr (cpu), 30, 30);
3258 NYI_assert (29, 24, 0x0E);
3259 NYI_assert (21, 10, 0x82E);
3261 switch (uimm (aarch64_get_instr (cpu), 23, 22))
3264 for (i = 0; i < (full ? 16 : 8); i++)
3265 aarch64_set_vec_s8 (cpu, vd, i,
3266 ABS (aarch64_get_vec_s8 (cpu, vn, i)));
3270 for (i = 0; i < (full ? 8 : 4); i++)
3271 aarch64_set_vec_s16 (cpu, vd, i,
3272 ABS (aarch64_get_vec_s16 (cpu, vn, i)));
3276 for (i = 0; i < (full ? 4 : 2); i++)
3277 aarch64_set_vec_s32 (cpu, vd, i,
3278 ABS (aarch64_get_vec_s32 (cpu, vn, i)));
3284 for (i = 0; i < 2; i++)
3285 aarch64_set_vec_s64 (cpu, vd, i,
3286 ABS (aarch64_get_vec_s64 (cpu, vn, i)));
3292 do_vec_ADDV (sim_cpu *cpu)
3295 instr[30] = full/half selector
3296 instr[29,24] = 00 1110
3297 instr[23,22] = size: 00=> 8-bit, 01=> 16-bit, 10=> 32-bit, 11=> 64-bit
3298 instr[21,10] = 11 0001 1011 10
3302 unsigned vm = uimm (aarch64_get_instr (cpu), 9, 5);
3303 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
3306 int full = uimm (aarch64_get_instr (cpu), 30, 30);
3308 NYI_assert (29, 24, 0x0E);
3309 NYI_assert (21, 10, 0xC6E);
3311 switch (uimm (aarch64_get_instr (cpu), 23, 22))
3314 for (i = 0; i < (full ? 16 : 8); i++)
3315 val += aarch64_get_vec_u8 (cpu, vm, i);
3316 aarch64_set_reg_u64 (cpu, rd, NO_SP, val);
3320 for (i = 0; i < (full ? 8 : 4); i++)
3321 val += aarch64_get_vec_u16 (cpu, vm, i);
3322 aarch64_set_reg_u64 (cpu, rd, NO_SP, val);
3326 for (i = 0; i < (full ? 4 : 2); i++)
3327 val += aarch64_get_vec_u32 (cpu, vm, i);
3328 aarch64_set_reg_u64 (cpu, rd, NO_SP, val);
3334 val = aarch64_get_vec_u64 (cpu, vm, 0);
3335 val += aarch64_get_vec_u64 (cpu, vm, 1);
3336 aarch64_set_reg_u64 (cpu, rd, NO_SP, val);
3345 do_vec_ins_2 (sim_cpu *cpu)
3347 /* instr[31,21] = 01001110000
3348 instr[20,18] = size & element selector
3350 instr[13] = direction: to vec(0), from vec (1)
3356 unsigned vm = uimm (aarch64_get_instr (cpu), 9, 5);
3357 unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
3359 NYI_assert (31, 21, 0x270);
3360 NYI_assert (17, 14, 0);
3361 NYI_assert (12, 10, 7);
3363 if (uimm (aarch64_get_instr (cpu), 13, 13) == 1)
3365 if (uimm (aarch64_get_instr (cpu), 18, 18) == 1)
3368 elem = uimm (aarch64_get_instr (cpu), 20, 19);
3369 aarch64_set_reg_u64 (cpu, vd, NO_SP,
3370 aarch64_get_vec_u32 (cpu, vm, elem));
3375 if (uimm (aarch64_get_instr (cpu), 19, 19) != 1)
3378 elem = uimm (aarch64_get_instr (cpu), 20, 20);
3379 aarch64_set_reg_u64 (cpu, vd, NO_SP,
3380 aarch64_get_vec_u64 (cpu, vm, elem));
3385 if (uimm (aarch64_get_instr (cpu), 18, 18) == 1)
3388 elem = uimm (aarch64_get_instr (cpu), 20, 19);
3389 aarch64_set_vec_u32 (cpu, vd, elem,
3390 aarch64_get_reg_u32 (cpu, vm, NO_SP));
3395 if (uimm (aarch64_get_instr (cpu), 19, 19) != 1)
3398 elem = uimm (aarch64_get_instr (cpu), 20, 20);
3399 aarch64_set_vec_u64 (cpu, vd, elem,
3400 aarch64_get_reg_u64 (cpu, vm, NO_SP));
3406 do_vec_mull (sim_cpu *cpu)
3409 instr[30] = lower(0)/upper(1) selector
3410 instr[29] = signed(0)/unsigned(1)
3411 instr[28,24] = 0 1110
3412 instr[23,22] = size: 8-bit (00), 16-bit (01), 32-bit (10)
3415 instr[15,10] = 11 0000
3419 int unsign = uimm (aarch64_get_instr (cpu), 29, 29);
3420 int bias = uimm (aarch64_get_instr (cpu), 30, 30);
3421 unsigned vm = uimm (aarch64_get_instr (cpu), 20, 16);
3422 unsigned vn = uimm (aarch64_get_instr (cpu), 9, 5);
3423 unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
3426 NYI_assert (28, 24, 0x0E);
3427 NYI_assert (15, 10, 0x30);
3429 switch (uimm (aarch64_get_instr (cpu), 23, 22))
3435 for (i = 0; i < 8; i++)
3436 aarch64_set_vec_u16 (cpu, vd, i,
3437 aarch64_get_vec_u8 (cpu, vn, i + bias)
3438 * aarch64_get_vec_u8 (cpu, vm, i + bias));
3440 for (i = 0; i < 8; i++)
3441 aarch64_set_vec_s16 (cpu, vd, i,
3442 aarch64_get_vec_s8 (cpu, vn, i + bias)
3443 * aarch64_get_vec_s8 (cpu, vm, i + bias));
3450 for (i = 0; i < 4; i++)
3451 aarch64_set_vec_u32 (cpu, vd, i,
3452 aarch64_get_vec_u16 (cpu, vn, i + bias)
3453 * aarch64_get_vec_u16 (cpu, vm, i + bias));
3455 for (i = 0; i < 4; i++)
3456 aarch64_set_vec_s32 (cpu, vd, i,
3457 aarch64_get_vec_s16 (cpu, vn, i + bias)
3458 * aarch64_get_vec_s16 (cpu, vm, i + bias));
3465 for (i = 0; i < 2; i++)
3466 aarch64_set_vec_u64 (cpu, vd, i,
3467 (uint64_t) aarch64_get_vec_u32 (cpu, vn,
3469 * (uint64_t) aarch64_get_vec_u32 (cpu, vm,
3472 for (i = 0; i < 2; i++)
3473 aarch64_set_vec_s64 (cpu, vd, i,
3474 aarch64_get_vec_s32 (cpu, vn, i + bias)
3475 * aarch64_get_vec_s32 (cpu, vm, i + bias));
3485 do_vec_fadd (sim_cpu *cpu)
3488 instr[30] = half(0)/full(1)
3489 instr[29,24] = 001110
3490 instr[23] = FADD(0)/FSUB(1)
3491 instr[22] = float (0)/double(1)
3494 instr[15,10] = 110101
3498 unsigned vm = uimm (aarch64_get_instr (cpu), 20, 16);
3499 unsigned vn = uimm (aarch64_get_instr (cpu), 9, 5);
3500 unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
3502 int full = uimm (aarch64_get_instr (cpu), 30, 30);
3504 NYI_assert (29, 24, 0x0E);
3505 NYI_assert (21, 21, 1);
3506 NYI_assert (15, 10, 0x35);
3508 if (uimm (aarch64_get_instr (cpu), 23, 23))
3510 if (uimm (aarch64_get_instr (cpu), 22, 22))
3515 for (i = 0; i < 2; i++)
3516 aarch64_set_vec_double (cpu, vd, i,
3517 aarch64_get_vec_double (cpu, vn, i)
3518 - aarch64_get_vec_double (cpu, vm, i));
3522 for (i = 0; i < (full ? 4 : 2); i++)
3523 aarch64_set_vec_float (cpu, vd, i,
3524 aarch64_get_vec_float (cpu, vn, i)
3525 - aarch64_get_vec_float (cpu, vm, i));
3530 if (uimm (aarch64_get_instr (cpu), 22, 22))
3535 for (i = 0; i < 2; i++)
3536 aarch64_set_vec_double (cpu, vd, i,
3537 aarch64_get_vec_double (cpu, vm, i)
3538 + aarch64_get_vec_double (cpu, vn, i));
3542 for (i = 0; i < (full ? 4 : 2); i++)
3543 aarch64_set_vec_float (cpu, vd, i,
3544 aarch64_get_vec_float (cpu, vm, i)
3545 + aarch64_get_vec_float (cpu, vn, i));
3551 do_vec_add (sim_cpu *cpu)
3554 instr[30] = full/half selector
3555 instr[29,24] = 001110
3556 instr[23,22] = size: 00=> 8-bit, 01=> 16-bit, 10=> 32-bit, 11=> 64-bit
3559 instr[15,10] = 100001
3563 unsigned vm = uimm (aarch64_get_instr (cpu), 20, 16);
3564 unsigned vn = uimm (aarch64_get_instr (cpu), 9, 5);
3565 unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
3567 int full = uimm (aarch64_get_instr (cpu), 30, 30);
3569 NYI_assert (29, 24, 0x0E);
3570 NYI_assert (21, 21, 1);
3571 NYI_assert (15, 10, 0x21);
3573 switch (uimm (aarch64_get_instr (cpu), 23, 22))
3576 for (i = 0; i < (full ? 16 : 8); i++)
3577 aarch64_set_vec_u8 (cpu, vd, i, aarch64_get_vec_u8 (cpu, vn, i)
3578 + aarch64_get_vec_u8 (cpu, vm, i));
3582 for (i = 0; i < (full ? 8 : 4); i++)
3583 aarch64_set_vec_u16 (cpu, vd, i, aarch64_get_vec_u16 (cpu, vn, i)
3584 + aarch64_get_vec_u16 (cpu, vm, i));
3588 for (i = 0; i < (full ? 4 : 2); i++)
3589 aarch64_set_vec_u32 (cpu, vd, i, aarch64_get_vec_u32 (cpu, vn, i)
3590 + aarch64_get_vec_u32 (cpu, vm, i));
3596 aarch64_set_vec_u64 (cpu, vd, 0, aarch64_get_vec_u64 (cpu, vn, 0)
3597 + aarch64_get_vec_u64 (cpu, vm, 0));
3598 aarch64_set_vec_u64 (cpu, vd, 1,
3599 aarch64_get_vec_u64 (cpu, vn, 1)
3600 + aarch64_get_vec_u64 (cpu, vm, 1));
3609 do_vec_mul (sim_cpu *cpu)
3612 instr[30] = full/half selector
3613 instr[29,24] = 00 1110
3614 instr[23,22] = size: 00=> 8-bit, 01=> 16-bit, 10=> 32-bit
3617 instr[15,10] = 10 0111
3621 unsigned vm = uimm (aarch64_get_instr (cpu), 20, 16);
3622 unsigned vn = uimm (aarch64_get_instr (cpu), 9, 5);
3623 unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
3625 int full = uimm (aarch64_get_instr (cpu), 30, 30);
3627 NYI_assert (29, 24, 0x0E);
3628 NYI_assert (21, 21, 1);
3629 NYI_assert (15, 10, 0x27);
3631 switch (uimm (aarch64_get_instr (cpu), 23, 22))
3634 for (i = 0; i < (full ? 16 : 8); i++)
3636 uint16_t val = aarch64_get_vec_u8 (cpu, vn, i);
3637 val *= aarch64_get_vec_u8 (cpu, vm, i);
3639 aarch64_set_vec_u16 (cpu, vd, i, val);
3644 for (i = 0; i < (full ? 8 : 4); i++)
3646 uint32_t val = aarch64_get_vec_u16 (cpu, vn, i);
3647 val *= aarch64_get_vec_u16 (cpu, vm, i);
3649 aarch64_set_vec_u32 (cpu, vd, i, val);
3654 for (i = 0; i < (full ? 4 : 2); i++)
3656 uint64_t val = aarch64_get_vec_u32 (cpu, vn, i);
3657 val *= aarch64_get_vec_u32 (cpu, vm, i);
3659 aarch64_set_vec_u64 (cpu, vd, i, val);
3670 do_vec_MLA (sim_cpu *cpu)
3673 instr[30] = full/half selector
3674 instr[29,24] = 00 1110
3675 instr[23,22] = size: 00=> 8-bit, 01=> 16-bit, 10=> 32-bit
3678 instr[15,10] = 1001 01
3682 unsigned vm = uimm (aarch64_get_instr (cpu), 20, 16);
3683 unsigned vn = uimm (aarch64_get_instr (cpu), 9, 5);
3684 unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
3686 int full = uimm (aarch64_get_instr (cpu), 30, 30);
3688 NYI_assert (29, 24, 0x0E);
3689 NYI_assert (21, 21, 1);
3690 NYI_assert (15, 10, 0x25);
3692 switch (uimm (aarch64_get_instr (cpu), 23, 22))
3695 for (i = 0; i < (full ? 16 : 8); i++)
3697 uint16_t val = aarch64_get_vec_u8 (cpu, vn, i);
3698 val *= aarch64_get_vec_u8 (cpu, vm, i);
3699 val += aarch64_get_vec_u8 (cpu, vd, i);
3701 aarch64_set_vec_u16 (cpu, vd, i, val);
3706 for (i = 0; i < (full ? 8 : 4); i++)
3708 uint32_t val = aarch64_get_vec_u16 (cpu, vn, i);
3709 val *= aarch64_get_vec_u16 (cpu, vm, i);
3710 val += aarch64_get_vec_u16 (cpu, vd, i);
3712 aarch64_set_vec_u32 (cpu, vd, i, val);
3717 for (i = 0; i < (full ? 4 : 2); i++)
3719 uint64_t val = aarch64_get_vec_u32 (cpu, vn, i);
3720 val *= aarch64_get_vec_u32 (cpu, vm, i);
3721 val += aarch64_get_vec_u32 (cpu, vd, i);
3723 aarch64_set_vec_u64 (cpu, vd, i, val);
3734 fmaxnm (float a, float b)
3736 if (fpclassify (a) == FP_NORMAL)
3738 if (fpclassify (b) == FP_NORMAL)
3739 return a > b ? a : b;
3742 else if (fpclassify (b) == FP_NORMAL)
3748 fminnm (float a, float b)
3750 if (fpclassify (a) == FP_NORMAL)
3752 if (fpclassify (b) == FP_NORMAL)
3753 return a < b ? a : b;
3756 else if (fpclassify (b) == FP_NORMAL)
3762 dmaxnm (double a, double b)
3764 if (fpclassify (a) == FP_NORMAL)
3766 if (fpclassify (b) == FP_NORMAL)
3767 return a > b ? a : b;
3770 else if (fpclassify (b) == FP_NORMAL)
3776 dminnm (double a, double b)
3778 if (fpclassify (a) == FP_NORMAL)
3780 if (fpclassify (b) == FP_NORMAL)
3781 return a < b ? a : b;
3784 else if (fpclassify (b) == FP_NORMAL)
3790 do_vec_FminmaxNMP (sim_cpu *cpu)
3792 /* aarch64_get_instr (cpu)[31] = 0
3793 aarch64_get_instr (cpu)[30] = half (0)/full (1)
3794 aarch64_get_instr (cpu)[29,24] = 10 1110
3795 aarch64_get_instr (cpu)[23] = max(0)/min(1)
3796 aarch64_get_instr (cpu)[22] = float (0)/double (1)
3797 aarch64_get_instr (cpu)[21] = 1
3798 aarch64_get_instr (cpu)[20,16] = Vn
3799 aarch64_get_instr (cpu)[15,10] = 1100 01
3800 aarch64_get_instr (cpu)[9,5] = Vm
3801 aarch64_get_instr (cpu)[4.0] = Vd. */
3803 unsigned vm = uimm (aarch64_get_instr (cpu), 20, 16);
3804 unsigned vn = uimm (aarch64_get_instr (cpu), 9, 5);
3805 unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
3806 int full = uimm (aarch64_get_instr (cpu), 30, 30);
3808 NYI_assert (29, 24, 0x2E);
3809 NYI_assert (21, 21, 1);
3810 NYI_assert (15, 10, 0x31);
3812 if (uimm (aarch64_get_instr (cpu), 22, 22))
3814 double (* fn)(double, double) = uimm (aarch64_get_instr (cpu), 23, 23)
3819 aarch64_set_vec_double (cpu, vd, 0,
3820 fn (aarch64_get_vec_double (cpu, vn, 0),
3821 aarch64_get_vec_double (cpu, vn, 1)));
3822 aarch64_set_vec_double (cpu, vd, 0,
3823 fn (aarch64_get_vec_double (cpu, vm, 0),
3824 aarch64_get_vec_double (cpu, vm, 1)));
3828 float (* fn)(float, float) = uimm (aarch64_get_instr (cpu), 23, 23)
3831 aarch64_set_vec_float (cpu, vd, 0,
3832 fn (aarch64_get_vec_float (cpu, vn, 0),
3833 aarch64_get_vec_float (cpu, vn, 1)));
3835 aarch64_set_vec_float (cpu, vd, 1,
3836 fn (aarch64_get_vec_float (cpu, vn, 2),
3837 aarch64_get_vec_float (cpu, vn, 3)));
3839 aarch64_set_vec_float (cpu, vd, (full ? 2 : 1),
3840 fn (aarch64_get_vec_float (cpu, vm, 0),
3841 aarch64_get_vec_float (cpu, vm, 1)));
3843 aarch64_set_vec_float (cpu, vd, 3,
3844 fn (aarch64_get_vec_float (cpu, vm, 2),
3845 aarch64_get_vec_float (cpu, vm, 3)));
3850 do_vec_AND (sim_cpu *cpu)
3853 instr[30] = half (0)/full (1)
3854 instr[29,21] = 001110001
3856 instr[15,10] = 000111
3860 unsigned vm = uimm (aarch64_get_instr (cpu), 20, 16);
3861 unsigned vn = uimm (aarch64_get_instr (cpu), 9, 5);
3862 unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
3864 int full = uimm (aarch64_get_instr (cpu), 30, 30);
3866 NYI_assert (29, 21, 0x071);
3867 NYI_assert (15, 10, 0x07);
3869 for (i = 0; i < (full ? 4 : 2); i++)
3870 aarch64_set_vec_u32 (cpu, vd, i,
3871 aarch64_get_vec_u32 (cpu, vn, i)
3872 & aarch64_get_vec_u32 (cpu, vm, i));
3876 do_vec_BSL (sim_cpu *cpu)
3879 instr[30] = half (0)/full (1)
3880 instr[29,21] = 101110011
3882 instr[15,10] = 000111
3886 unsigned vm = uimm (aarch64_get_instr (cpu), 20, 16);
3887 unsigned vn = uimm (aarch64_get_instr (cpu), 9, 5);
3888 unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
3890 int full = uimm (aarch64_get_instr (cpu), 30, 30);
3892 NYI_assert (29, 21, 0x173);
3893 NYI_assert (15, 10, 0x07);
3895 for (i = 0; i < (full ? 16 : 8); i++)
3896 aarch64_set_vec_u8 (cpu, vd, i,
3897 ( aarch64_get_vec_u8 (cpu, vd, i)
3898 & aarch64_get_vec_u8 (cpu, vn, i))
3899 | ((~ aarch64_get_vec_u8 (cpu, vd, i))
3900 & aarch64_get_vec_u8 (cpu, vm, i)));
3904 do_vec_EOR (sim_cpu *cpu)
3907 instr[30] = half (0)/full (1)
3908 instr[29,21] = 10 1110 001
3910 instr[15,10] = 000111
3914 unsigned vm = uimm (aarch64_get_instr (cpu), 20, 16);
3915 unsigned vn = uimm (aarch64_get_instr (cpu), 9, 5);
3916 unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
3918 int full = uimm (aarch64_get_instr (cpu), 30, 30);
3920 NYI_assert (29, 21, 0x171);
3921 NYI_assert (15, 10, 0x07);
3923 for (i = 0; i < (full ? 4 : 2); i++)
3924 aarch64_set_vec_u32 (cpu, vd, i,
3925 aarch64_get_vec_u32 (cpu, vn, i)
3926 ^ aarch64_get_vec_u32 (cpu, vm, i));
3930 do_vec_bit (sim_cpu *cpu)
3933 instr[30] = half (0)/full (1)
3934 instr[29,23] = 10 1110 1
3935 instr[22] = BIT (0) / BIF (1)
3938 instr[15,10] = 0001 11
3942 unsigned vm = uimm (aarch64_get_instr (cpu), 20, 16);
3943 unsigned vn = uimm (aarch64_get_instr (cpu), 9, 5);
3944 unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
3945 unsigned full = uimm (aarch64_get_instr (cpu), 30, 30);
3946 unsigned test_false = uimm (aarch64_get_instr (cpu), 22, 22);
3949 NYI_assert (29, 23, 0x5D);
3950 NYI_assert (21, 21, 1);
3951 NYI_assert (15, 10, 0x07);
3955 for (i = 0; i < (full ? 16 : 8); i++)
3956 if (aarch64_get_vec_u32 (cpu, vn, i) == 0)
3957 aarch64_set_vec_u32 (cpu, vd, i, aarch64_get_vec_u32 (cpu, vm, i));
3961 for (i = 0; i < (full ? 16 : 8); i++)
3962 if (aarch64_get_vec_u32 (cpu, vn, i) != 0)
3963 aarch64_set_vec_u32 (cpu, vd, i, aarch64_get_vec_u32 (cpu, vm, i));
3968 do_vec_ORN (sim_cpu *cpu)
3971 instr[30] = half (0)/full (1)
3972 instr[29,21] = 00 1110 111
3974 instr[15,10] = 00 0111
3978 unsigned vm = uimm (aarch64_get_instr (cpu), 20, 16);
3979 unsigned vn = uimm (aarch64_get_instr (cpu), 9, 5);
3980 unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
3982 int full = uimm (aarch64_get_instr (cpu), 30, 30);
3984 NYI_assert (29, 21, 0x077);
3985 NYI_assert (15, 10, 0x07);
3987 for (i = 0; i < (full ? 16 : 8); i++)
3988 aarch64_set_vec_u8 (cpu, vd, i,
3989 aarch64_get_vec_u8 (cpu, vn, i)
3990 | ~ aarch64_get_vec_u8 (cpu, vm, i));
3994 do_vec_ORR (sim_cpu *cpu)
3997 instr[30] = half (0)/full (1)
3998 instr[29,21] = 00 1110 101
4000 instr[15,10] = 0001 11
4004 unsigned vm = uimm (aarch64_get_instr (cpu), 20, 16);
4005 unsigned vn = uimm (aarch64_get_instr (cpu), 9, 5);
4006 unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
4008 int full = uimm (aarch64_get_instr (cpu), 30, 30);
4010 NYI_assert (29, 21, 0x075);
4011 NYI_assert (15, 10, 0x07);
4013 for (i = 0; i < (full ? 16 : 8); i++)
4014 aarch64_set_vec_u8 (cpu, vd, i,
4015 aarch64_get_vec_u8 (cpu, vn, i)
4016 | aarch64_get_vec_u8 (cpu, vm, i));
4020 do_vec_BIC (sim_cpu *cpu)
4023 instr[30] = half (0)/full (1)
4024 instr[29,21] = 00 1110 011
4026 instr[15,10] = 00 0111
4030 unsigned vm = uimm (aarch64_get_instr (cpu), 20, 16);
4031 unsigned vn = uimm (aarch64_get_instr (cpu), 9, 5);
4032 unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
4034 int full = uimm (aarch64_get_instr (cpu), 30, 30);
4036 NYI_assert (29, 21, 0x073);
4037 NYI_assert (15, 10, 0x07);
4039 for (i = 0; i < (full ? 16 : 8); i++)
4040 aarch64_set_vec_u8 (cpu, vd, i,
4041 aarch64_get_vec_u8 (cpu, vn, i)
4042 & ~ aarch64_get_vec_u8 (cpu, vm, i));
4046 do_vec_XTN (sim_cpu *cpu)
4049 instr[30] = first part (0)/ second part (1)
4050 instr[29,24] = 00 1110
4051 instr[23,22] = size: byte(00), half(01), word (10)
4052 instr[21,10] = 1000 0100 1010
4056 unsigned vs = uimm (aarch64_get_instr (cpu), 9, 5);
4057 unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
4058 unsigned bias = uimm (aarch64_get_instr (cpu), 30, 30);
4061 NYI_assert (29, 24, 0x0E);
4062 NYI_assert (21, 10, 0x84A);
4064 switch (uimm (aarch64_get_instr (cpu), 23, 22))
4068 for (i = 0; i < 8; i++)
4069 aarch64_set_vec_u8 (cpu, vd, i + 8,
4070 aarch64_get_vec_u16 (cpu, vs, i) >> 8);
4072 for (i = 0; i < 8; i++)
4073 aarch64_set_vec_u8 (cpu, vd, i, aarch64_get_vec_u16 (cpu, vs, i));
4078 for (i = 0; i < 4; i++)
4079 aarch64_set_vec_u16 (cpu, vd, i + 4,
4080 aarch64_get_vec_u32 (cpu, vs, i) >> 16);
4082 for (i = 0; i < 4; i++)
4083 aarch64_set_vec_u16 (cpu, vd, i, aarch64_get_vec_u32 (cpu, vs, i));
4088 for (i = 0; i < 2; i++)
4089 aarch64_set_vec_u32 (cpu, vd, i + 4,
4090 aarch64_get_vec_u64 (cpu, vs, i) >> 32);
4092 for (i = 0; i < 2; i++)
4093 aarch64_set_vec_u32 (cpu, vd, i, aarch64_get_vec_u64 (cpu, vs, i));
4102 do_vec_maxv (sim_cpu *cpu)
4105 instr[30] = half(0)/full(1)
4106 instr[29] = signed (0)/unsigned(1)
4107 instr[28,24] = 0 1110
4108 instr[23,22] = size: byte(00), half(01), word (10)
4110 instr[20,17] = 1 000
4111 instr[16] = max(0)/min(1)
4112 instr[15,10] = 1010 10
4113 instr[9,5] = V source
4114 instr[4.0] = R dest. */
4116 unsigned vs = uimm (aarch64_get_instr (cpu), 9, 5);
4117 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
4118 unsigned full = uimm (aarch64_get_instr (cpu), 30, 30);
4121 NYI_assert (28, 24, 0x0E);
4122 NYI_assert (21, 21, 1);
4123 NYI_assert (20, 17, 8);
4124 NYI_assert (15, 10, 0x2A);
4126 switch ((uimm (aarch64_get_instr (cpu), 29, 29) << 1)
4127 | uimm (aarch64_get_instr (cpu), 16, 16))
4129 case 0: /* SMAXV. */
4132 switch (uimm (aarch64_get_instr (cpu), 23, 22))
4135 smax = aarch64_get_vec_s8 (cpu, vs, 0);
4136 for (i = 1; i < (full ? 16 : 8); i++)
4137 smax = max (smax, aarch64_get_vec_s8 (cpu, vs, i));
4140 smax = aarch64_get_vec_s16 (cpu, vs, 0);
4141 for (i = 1; i < (full ? 8 : 4); i++)
4142 smax = max (smax, aarch64_get_vec_s16 (cpu, vs, i));
4145 smax = aarch64_get_vec_s32 (cpu, vs, 0);
4146 for (i = 1; i < (full ? 4 : 2); i++)
4147 smax = max (smax, aarch64_get_vec_s32 (cpu, vs, i));
4153 aarch64_set_reg_s64 (cpu, rd, NO_SP, smax);
4157 case 1: /* SMINV. */
4160 switch (uimm (aarch64_get_instr (cpu), 23, 22))
4163 smin = aarch64_get_vec_s8 (cpu, vs, 0);
4164 for (i = 1; i < (full ? 16 : 8); i++)
4165 smin = min (smin, aarch64_get_vec_s8 (cpu, vs, i));
4168 smin = aarch64_get_vec_s16 (cpu, vs, 0);
4169 for (i = 1; i < (full ? 8 : 4); i++)
4170 smin = min (smin, aarch64_get_vec_s16 (cpu, vs, i));
4173 smin = aarch64_get_vec_s32 (cpu, vs, 0);
4174 for (i = 1; i < (full ? 4 : 2); i++)
4175 smin = min (smin, aarch64_get_vec_s32 (cpu, vs, i));
4181 aarch64_set_reg_s64 (cpu, rd, NO_SP, smin);
4185 case 2: /* UMAXV. */
4188 switch (uimm (aarch64_get_instr (cpu), 23, 22))
4191 umax = aarch64_get_vec_u8 (cpu, vs, 0);
4192 for (i = 1; i < (full ? 16 : 8); i++)
4193 umax = max (umax, aarch64_get_vec_u8 (cpu, vs, i));
4196 umax = aarch64_get_vec_u16 (cpu, vs, 0);
4197 for (i = 1; i < (full ? 8 : 4); i++)
4198 umax = max (umax, aarch64_get_vec_u16 (cpu, vs, i));
4201 umax = aarch64_get_vec_u32 (cpu, vs, 0);
4202 for (i = 1; i < (full ? 4 : 2); i++)
4203 umax = max (umax, aarch64_get_vec_u32 (cpu, vs, i));
4209 aarch64_set_reg_u64 (cpu, rd, NO_SP, umax);
4213 case 3: /* UMINV. */
4216 switch (uimm (aarch64_get_instr (cpu), 23, 22))
4219 umin = aarch64_get_vec_u8 (cpu, vs, 0);
4220 for (i = 1; i < (full ? 16 : 8); i++)
4221 umin = min (umin, aarch64_get_vec_u8 (cpu, vs, i));
4224 umin = aarch64_get_vec_u16 (cpu, vs, 0);
4225 for (i = 1; i < (full ? 8 : 4); i++)
4226 umin = min (umin, aarch64_get_vec_u16 (cpu, vs, i));
4229 umin = aarch64_get_vec_u32 (cpu, vs, 0);
4230 for (i = 1; i < (full ? 4 : 2); i++)
4231 umin = min (umin, aarch64_get_vec_u32 (cpu, vs, i));
4237 aarch64_set_reg_u64 (cpu, rd, NO_SP, umin);
4247 do_vec_fminmaxV (sim_cpu *cpu)
4249 /* instr[31,24] = 0110 1110
4250 instr[23] = max(0)/min(1)
4251 instr[22,14] = 011 0000 11
4252 instr[13,12] = nm(00)/normal(11)
4254 instr[9,5] = V source
4255 instr[4.0] = R dest. */
4257 unsigned vs = uimm (aarch64_get_instr (cpu), 9, 5);
4258 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
4260 float res = aarch64_get_vec_float (cpu, vs, 0);
4262 NYI_assert (31, 24, 0x6E);
4263 NYI_assert (22, 14, 0x0C3);
4264 NYI_assert (11, 10, 2);
4266 if (uimm (aarch64_get_instr (cpu), 23, 23))
4268 switch (uimm (aarch64_get_instr (cpu), 13, 12))
4270 case 0: /* FMNINNMV. */
4271 for (i = 1; i < 4; i++)
4272 res = fminnm (res, aarch64_get_vec_float (cpu, vs, i));
4275 case 3: /* FMINV. */
4276 for (i = 1; i < 4; i++)
4277 res = min (res, aarch64_get_vec_float (cpu, vs, i));
4286 switch (uimm (aarch64_get_instr (cpu), 13, 12))
4288 case 0: /* FMNAXNMV. */
4289 for (i = 1; i < 4; i++)
4290 res = fmaxnm (res, aarch64_get_vec_float (cpu, vs, i));
4293 case 3: /* FMAXV. */
4294 for (i = 1; i < 4; i++)
4295 res = max (res, aarch64_get_vec_float (cpu, vs, i));
4303 aarch64_set_FP_float (cpu, rd, res);
4307 do_vec_Fminmax (sim_cpu *cpu)
4310 instr[30] = half(0)/full(1)
4311 instr[29,24] = 00 1110
4312 instr[23] = max(0)/min(1)
4313 instr[22] = float(0)/double(1)
4317 instr[13,12] = nm(00)/normal(11)
4322 unsigned vm = uimm (aarch64_get_instr (cpu), 20, 16);
4323 unsigned vn = uimm (aarch64_get_instr (cpu), 9, 5);
4324 unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
4325 unsigned full = uimm (aarch64_get_instr (cpu), 30, 30);
4326 unsigned min = uimm (aarch64_get_instr (cpu), 23, 23);
4329 NYI_assert (29, 24, 0x0E);
4330 NYI_assert (21, 21, 1);
4331 NYI_assert (15, 14, 3);
4332 NYI_assert (11, 10, 1);
4334 if (uimm (aarch64_get_instr (cpu), 22, 22))
4336 double (* func)(double, double);
4341 if (uimm (aarch64_get_instr (cpu), 13, 12) == 0)
4342 func = min ? dminnm : dmaxnm;
4343 else if (uimm (aarch64_get_instr (cpu), 13, 12) == 3)
4344 func = min ? fmin : fmax;
4348 for (i = 0; i < 2; i++)
4349 aarch64_set_vec_double (cpu, vd, i,
4350 func (aarch64_get_vec_double (cpu, vn, i),
4351 aarch64_get_vec_double (cpu, vm, i)));
4355 float (* func)(float, float);
4357 if (uimm (aarch64_get_instr (cpu), 13, 12) == 0)
4358 func = min ? fminnm : fmaxnm;
4359 else if (uimm (aarch64_get_instr (cpu), 13, 12) == 3)
4360 func = min ? fminf : fmaxf;
4364 for (i = 0; i < (full ? 4 : 2); i++)
4365 aarch64_set_vec_float (cpu, vd, i,
4366 func (aarch64_get_vec_float (cpu, vn, i),
4367 aarch64_get_vec_float (cpu, vm, i)));
4372 do_vec_SCVTF (sim_cpu *cpu)
4376 instr[29,23] = 00 1110 0
4377 instr[22] = float(0)/double(1)
4378 instr[21,10] = 10 0001 1101 10
4382 unsigned vn = uimm (aarch64_get_instr (cpu), 9, 5);
4383 unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
4384 unsigned full = uimm (aarch64_get_instr (cpu), 30, 30);
4385 unsigned size = uimm (aarch64_get_instr (cpu), 22, 22);
4388 NYI_assert (29, 23, 0x1C);
4389 NYI_assert (21, 10, 0x876);
4396 for (i = 0; i < 2; i++)
4398 double val = (double) aarch64_get_vec_u64 (cpu, vn, i);
4399 aarch64_set_vec_double (cpu, vd, i, val);
4404 for (i = 0; i < (full ? 4 : 2); i++)
4406 float val = (float) aarch64_get_vec_u32 (cpu, vn, i);
4407 aarch64_set_vec_float (cpu, vd, i, val);
4412 #define VEC_CMP(SOURCE, CMP) \
4418 for (i = 0; i < (full ? 16 : 8); i++) \
4419 aarch64_set_vec_u8 (cpu, vd, i, \
4420 aarch64_get_vec_##SOURCE##8 (cpu, vn, i) \
4422 aarch64_get_vec_##SOURCE##8 (cpu, vm, i) \
4426 for (i = 0; i < (full ? 8 : 4); i++) \
4427 aarch64_set_vec_u16 (cpu, vd, i, \
4428 aarch64_get_vec_##SOURCE##16 (cpu, vn, i) \
4430 aarch64_get_vec_##SOURCE##16 (cpu, vm, i) \
4434 for (i = 0; i < (full ? 4 : 2); i++) \
4435 aarch64_set_vec_u32 (cpu, vd, i, \
4436 aarch64_get_vec_##SOURCE##32 (cpu, vn, i) \
4438 aarch64_get_vec_##SOURCE##32 (cpu, vm, i) \
4444 for (i = 0; i < 2; i++) \
4445 aarch64_set_vec_u64 (cpu, vd, i, \
4446 aarch64_get_vec_##SOURCE##64 (cpu, vn, i) \
4448 aarch64_get_vec_##SOURCE##64 (cpu, vm, i) \
4457 #define VEC_CMP0(SOURCE, CMP) \
4463 for (i = 0; i < (full ? 16 : 8); i++) \
4464 aarch64_set_vec_u8 (cpu, vd, i, \
4465 aarch64_get_vec_##SOURCE##8 (cpu, vn, i) \
4469 for (i = 0; i < (full ? 8 : 4); i++) \
4470 aarch64_set_vec_u16 (cpu, vd, i, \
4471 aarch64_get_vec_##SOURCE##16 (cpu, vn, i) \
4475 for (i = 0; i < (full ? 4 : 2); i++) \
4476 aarch64_set_vec_u32 (cpu, vd, i, \
4477 aarch64_get_vec_##SOURCE##32 (cpu, vn, i) \
4483 for (i = 0; i < 2; i++) \
4484 aarch64_set_vec_u64 (cpu, vd, i, \
4485 aarch64_get_vec_##SOURCE##64 (cpu, vn, i) \
4486 CMP 0 ? -1ULL : 0); \
4494 #define VEC_FCMP0(CMP) \
4499 if (uimm (aarch64_get_instr (cpu), 22, 22)) \
4503 for (i = 0; i < 2; i++) \
4504 aarch64_set_vec_u64 (cpu, vd, i, \
4505 aarch64_get_vec_double (cpu, vn, i) \
4506 CMP 0.0 ? -1 : 0); \
4510 for (i = 0; i < (full ? 4 : 2); i++) \
4511 aarch64_set_vec_u32 (cpu, vd, i, \
4512 aarch64_get_vec_float (cpu, vn, i) \
4513 CMP 0.0 ? -1 : 0); \
4519 #define VEC_FCMP(CMP) \
4522 if (uimm (aarch64_get_instr (cpu), 22, 22)) \
4526 for (i = 0; i < 2; i++) \
4527 aarch64_set_vec_u64 (cpu, vd, i, \
4528 aarch64_get_vec_double (cpu, vn, i) \
4530 aarch64_get_vec_double (cpu, vm, i) \
4535 for (i = 0; i < (full ? 4 : 2); i++) \
4536 aarch64_set_vec_u32 (cpu, vd, i, \
4537 aarch64_get_vec_float (cpu, vn, i) \
4539 aarch64_get_vec_float (cpu, vm, i) \
4547 do_vec_compare (sim_cpu *cpu)
4550 instr[30] = half(0)/full(1)
4551 instr[29] = part-of-comparison-type
4552 instr[28,24] = 0 1110
4553 instr[23,22] = size of integer compares: byte(00), half(01), word (10), long (11)
4554 type of float compares: single (-0) / double (-1)
4556 instr[20,16] = Vm or 00000 (compare vs 0)
4557 instr[15,10] = part-of-comparison-type
4561 int full = uimm (aarch64_get_instr (cpu), 30, 30);
4562 int size = uimm (aarch64_get_instr (cpu), 23, 22);
4563 unsigned vm = uimm (aarch64_get_instr (cpu), 20, 16);
4564 unsigned vn = uimm (aarch64_get_instr (cpu), 9, 5);
4565 unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
4568 NYI_assert (28, 24, 0x0E);
4569 NYI_assert (21, 21, 1);
4571 if ((uimm (aarch64_get_instr (cpu), 11, 11)
4572 && uimm (aarch64_get_instr (cpu), 14, 14))
4573 || ((uimm (aarch64_get_instr (cpu), 11, 11) == 0
4574 && uimm (aarch64_get_instr (cpu), 10, 10) == 0)))
4576 /* A compare vs 0. */
4579 if (uimm (aarch64_get_instr (cpu), 15, 10) == 0x2A)
4581 else if (uimm (aarch64_get_instr (cpu), 15, 10) == 0x32
4582 || uimm (aarch64_get_instr (cpu), 15, 10) == 0x3E)
4583 do_vec_fminmaxV (cpu);
4584 else if (uimm (aarch64_get_instr (cpu), 29, 23) == 0x1C
4585 && uimm (aarch64_get_instr (cpu), 21, 10) == 0x876)
4593 if (uimm (aarch64_get_instr (cpu), 14, 14))
4595 /* A floating point compare. */
4596 unsigned decode = (uimm (aarch64_get_instr (cpu), 29, 29) << 5)
4597 | (uimm (aarch64_get_instr (cpu), 23, 23) << 4)
4598 | uimm (aarch64_get_instr (cpu), 13, 10);
4600 NYI_assert (15, 15, 1);
4604 case /* 0b010010: GT#0 */ 0x12: VEC_FCMP0 (>);
4605 case /* 0b110010: GE#0 */ 0x32: VEC_FCMP0 (>=);
4606 case /* 0b010110: EQ#0 */ 0x16: VEC_FCMP0 (==);
4607 case /* 0b110110: LE#0 */ 0x36: VEC_FCMP0 (<=);
4608 case /* 0b011010: LT#0 */ 0x1A: VEC_FCMP0 (<);
4609 case /* 0b111001: GT */ 0x39: VEC_FCMP (>);
4610 case /* 0b101001: GE */ 0x29: VEC_FCMP (>=);
4611 case /* 0b001001: EQ */ 0x09: VEC_FCMP (==);
4619 unsigned decode = (uimm (aarch64_get_instr (cpu), 29, 29) << 6)
4620 | uimm (aarch64_get_instr (cpu), 15, 10);
4624 case 0x0D: /* 0001101 GT */ VEC_CMP (s, > );
4625 case 0x0F: /* 0001111 GE */ VEC_CMP (s, >= );
4626 case 0x22: /* 0100010 GT #0 */ VEC_CMP0 (s, > );
4627 case 0x26: /* 0100110 EQ #0 */ VEC_CMP0 (s, == );
4628 case 0x2A: /* 0101010 LT #0 */ VEC_CMP0 (s, < );
4629 case 0x4D: /* 1001101 HI */ VEC_CMP (u, > );
4630 case 0x4F: /* 1001111 HS */ VEC_CMP (u, >= );
4631 case 0x62: /* 1100010 GE #0 */ VEC_CMP0 (s, >= );
4632 case 0x63: /* 1100011 EQ */ VEC_CMP (u, == );
4633 case 0x66: /* 1100110 LE #0 */ VEC_CMP0 (s, <= );
4643 do_vec_SSHL (sim_cpu *cpu)
4646 instr[30] = first part (0)/ second part (1)
4647 instr[29,24] = 00 1110
4648 instr[23,22] = size: byte(00), half(01), word (10), long (11)
4651 instr[15,10] = 0100 01
4655 unsigned full = uimm (aarch64_get_instr (cpu), 30, 30);
4656 unsigned vm = uimm (aarch64_get_instr (cpu), 20, 16);
4657 unsigned vn = uimm (aarch64_get_instr (cpu), 9, 5);
4658 unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
4661 NYI_assert (29, 24, 0x0E);
4662 NYI_assert (21, 21, 1);
4663 NYI_assert (15, 10, 0x11);
4665 /* FIXME: What is a signed shift left in this context ?. */
4667 switch (uimm (aarch64_get_instr (cpu), 23, 22))
4670 for (i = 0; i < (full ? 16 : 8); i++)
4671 aarch64_set_vec_s8 (cpu, vd, i, aarch64_get_vec_s8 (cpu, vn, i)
4672 << aarch64_get_vec_s8 (cpu, vm, i));
4676 for (i = 0; i < (full ? 8 : 4); i++)
4677 aarch64_set_vec_s16 (cpu, vd, i, aarch64_get_vec_s16 (cpu, vn, i)
4678 << aarch64_get_vec_s16 (cpu, vm, i));
4682 for (i = 0; i < (full ? 4 : 2); i++)
4683 aarch64_set_vec_s32 (cpu, vd, i, aarch64_get_vec_s32 (cpu, vn, i)
4684 << aarch64_get_vec_s32 (cpu, vm, i));
4690 for (i = 0; i < 2; i++)
4691 aarch64_set_vec_s64 (cpu, vd, i, aarch64_get_vec_s64 (cpu, vn, i)
4692 << aarch64_get_vec_s64 (cpu, vm, i));
4701 do_vec_USHL (sim_cpu *cpu)
4704 instr[30] = first part (0)/ second part (1)
4705 instr[29,24] = 10 1110
4706 instr[23,22] = size: byte(00), half(01), word (10), long (11)
4709 instr[15,10] = 0100 01
4713 unsigned full = uimm (aarch64_get_instr (cpu), 30, 30);
4714 unsigned vm = uimm (aarch64_get_instr (cpu), 20, 16);
4715 unsigned vn = uimm (aarch64_get_instr (cpu), 9, 5);
4716 unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
4719 NYI_assert (29, 24, 0x2E);
4720 NYI_assert (15, 10, 0x11);
4722 switch (uimm (aarch64_get_instr (cpu), 23, 22))
4725 for (i = 0; i < (full ? 16 : 8); i++)
4726 aarch64_set_vec_u8 (cpu, vd, i, aarch64_get_vec_u8 (cpu, vn, i)
4727 << aarch64_get_vec_u8 (cpu, vm, i));
4731 for (i = 0; i < (full ? 8 : 4); i++)
4732 aarch64_set_vec_u16 (cpu, vd, i, aarch64_get_vec_u16 (cpu, vn, i)
4733 << aarch64_get_vec_u16 (cpu, vm, i));
4737 for (i = 0; i < (full ? 4 : 2); i++)
4738 aarch64_set_vec_u32 (cpu, vd, i, aarch64_get_vec_u32 (cpu, vn, i)
4739 << aarch64_get_vec_u32 (cpu, vm, i));
4745 for (i = 0; i < 2; i++)
4746 aarch64_set_vec_u64 (cpu, vd, i, aarch64_get_vec_u64 (cpu, vn, i)
4747 << aarch64_get_vec_u64 (cpu, vm, i));
4756 do_vec_FMLA (sim_cpu *cpu)
4759 instr[30] = full/half selector
4760 instr[29,23] = 0011100
4761 instr[22] = size: 0=>float, 1=>double
4764 instr[15,10] = 1100 11
4768 unsigned vm = uimm (aarch64_get_instr (cpu), 20, 16);
4769 unsigned vn = uimm (aarch64_get_instr (cpu), 9, 5);
4770 unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
4772 int full = uimm (aarch64_get_instr (cpu), 30, 30);
4774 NYI_assert (29, 23, 0x1C);
4775 NYI_assert (21, 21, 1);
4776 NYI_assert (15, 10, 0x33);
4778 if (uimm (aarch64_get_instr (cpu), 22, 22))
4782 for (i = 0; i < 2; i++)
4783 aarch64_set_vec_double (cpu, vd, i,
4784 aarch64_get_vec_double (cpu, vn, i) *
4785 aarch64_get_vec_double (cpu, vm, i) +
4786 aarch64_get_vec_double (cpu, vd, i));
4790 for (i = 0; i < (full ? 4 : 2); i++)
4791 aarch64_set_vec_float (cpu, vd, i,
4792 aarch64_get_vec_float (cpu, vn, i) *
4793 aarch64_get_vec_float (cpu, vm, i) +
4794 aarch64_get_vec_float (cpu, vd, i));
4799 do_vec_max (sim_cpu *cpu)
4802 instr[30] = full/half selector
4803 instr[29] = SMAX (0) / UMAX (1)
4804 instr[28,24] = 0 1110
4805 instr[23,22] = size: 00=> 8-bit, 01=> 16-bit, 10=> 32-bit
4808 instr[15,10] = 0110 01
4812 unsigned vm = uimm (aarch64_get_instr (cpu), 20, 16);
4813 unsigned vn = uimm (aarch64_get_instr (cpu), 9, 5);
4814 unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
4816 int full = uimm (aarch64_get_instr (cpu), 30, 30);
4818 NYI_assert (28, 24, 0x0E);
4819 NYI_assert (21, 21, 1);
4820 NYI_assert (15, 10, 0x19);
4822 if (uimm (aarch64_get_instr (cpu), 29, 29))
4824 switch (uimm (aarch64_get_instr (cpu), 23, 22))
4827 for (i = 0; i < (full ? 16 : 8); i++)
4828 aarch64_set_vec_u8 (cpu, vd, i,
4829 aarch64_get_vec_u8 (cpu, vn, i)
4830 > aarch64_get_vec_u8 (cpu, vm, i)
4831 ? aarch64_get_vec_u8 (cpu, vn, i)
4832 : aarch64_get_vec_u8 (cpu, vm, i));
4836 for (i = 0; i < (full ? 8 : 4); i++)
4837 aarch64_set_vec_u16 (cpu, vd, i,
4838 aarch64_get_vec_u16 (cpu, vn, i)
4839 > aarch64_get_vec_u16 (cpu, vm, i)
4840 ? aarch64_get_vec_u16 (cpu, vn, i)
4841 : aarch64_get_vec_u16 (cpu, vm, i));
4845 for (i = 0; i < (full ? 4 : 2); i++)
4846 aarch64_set_vec_u32 (cpu, vd, i,
4847 aarch64_get_vec_u32 (cpu, vn, i)
4848 > aarch64_get_vec_u32 (cpu, vm, i)
4849 ? aarch64_get_vec_u32 (cpu, vn, i)
4850 : aarch64_get_vec_u32 (cpu, vm, i));
4860 switch (uimm (aarch64_get_instr (cpu), 23, 22))
4863 for (i = 0; i < (full ? 16 : 8); i++)
4864 aarch64_set_vec_s8 (cpu, vd, i,
4865 aarch64_get_vec_s8 (cpu, vn, i)
4866 > aarch64_get_vec_s8 (cpu, vm, i)
4867 ? aarch64_get_vec_s8 (cpu, vn, i)
4868 : aarch64_get_vec_s8 (cpu, vm, i));
4872 for (i = 0; i < (full ? 8 : 4); i++)
4873 aarch64_set_vec_s16 (cpu, vd, i,
4874 aarch64_get_vec_s16 (cpu, vn, i)
4875 > aarch64_get_vec_s16 (cpu, vm, i)
4876 ? aarch64_get_vec_s16 (cpu, vn, i)
4877 : aarch64_get_vec_s16 (cpu, vm, i));
4881 for (i = 0; i < (full ? 4 : 2); i++)
4882 aarch64_set_vec_s32 (cpu, vd, i,
4883 aarch64_get_vec_s32 (cpu, vn, i)
4884 > aarch64_get_vec_s32 (cpu, vm, i)
4885 ? aarch64_get_vec_s32 (cpu, vn, i)
4886 : aarch64_get_vec_s32 (cpu, vm, i));
4897 do_vec_min (sim_cpu *cpu)
4900 instr[30] = full/half selector
4901 instr[29] = SMIN (0) / UMIN (1)
4902 instr[28,24] = 0 1110
4903 instr[23,22] = size: 00=> 8-bit, 01=> 16-bit, 10=> 32-bit
4906 instr[15,10] = 0110 11
4910 unsigned vm = uimm (aarch64_get_instr (cpu), 20, 16);
4911 unsigned vn = uimm (aarch64_get_instr (cpu), 9, 5);
4912 unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
4914 int full = uimm (aarch64_get_instr (cpu), 30, 30);
4916 NYI_assert (28, 24, 0x0E);
4917 NYI_assert (21, 21, 1);
4918 NYI_assert (15, 10, 0x1B);
4920 if (uimm (aarch64_get_instr (cpu), 29, 29))
4922 switch (uimm (aarch64_get_instr (cpu), 23, 22))
4925 for (i = 0; i < (full ? 16 : 8); i++)
4926 aarch64_set_vec_u8 (cpu, vd, i,
4927 aarch64_get_vec_u8 (cpu, vn, i)
4928 < aarch64_get_vec_u8 (cpu, vm, i)
4929 ? aarch64_get_vec_u8 (cpu, vn, i)
4930 : aarch64_get_vec_u8 (cpu, vm, i));
4934 for (i = 0; i < (full ? 8 : 4); i++)
4935 aarch64_set_vec_u16 (cpu, vd, i,
4936 aarch64_get_vec_u16 (cpu, vn, i)
4937 < aarch64_get_vec_u16 (cpu, vm, i)
4938 ? aarch64_get_vec_u16 (cpu, vn, i)
4939 : aarch64_get_vec_u16 (cpu, vm, i));
4943 for (i = 0; i < (full ? 4 : 2); i++)
4944 aarch64_set_vec_u32 (cpu, vd, i,
4945 aarch64_get_vec_u32 (cpu, vn, i)
4946 < aarch64_get_vec_u32 (cpu, vm, i)
4947 ? aarch64_get_vec_u32 (cpu, vn, i)
4948 : aarch64_get_vec_u32 (cpu, vm, i));
4958 switch (uimm (aarch64_get_instr (cpu), 23, 22))
4961 for (i = 0; i < (full ? 16 : 8); i++)
4962 aarch64_set_vec_s8 (cpu, vd, i,
4963 aarch64_get_vec_s8 (cpu, vn, i)
4964 < aarch64_get_vec_s8 (cpu, vm, i)
4965 ? aarch64_get_vec_s8 (cpu, vn, i)
4966 : aarch64_get_vec_s8 (cpu, vm, i));
4970 for (i = 0; i < (full ? 8 : 4); i++)
4971 aarch64_set_vec_s16 (cpu, vd, i,
4972 aarch64_get_vec_s16 (cpu, vn, i)
4973 < aarch64_get_vec_s16 (cpu, vm, i)
4974 ? aarch64_get_vec_s16 (cpu, vn, i)
4975 : aarch64_get_vec_s16 (cpu, vm, i));
4979 for (i = 0; i < (full ? 4 : 2); i++)
4980 aarch64_set_vec_s32 (cpu, vd, i,
4981 aarch64_get_vec_s32 (cpu, vn, i)
4982 < aarch64_get_vec_s32 (cpu, vm, i)
4983 ? aarch64_get_vec_s32 (cpu, vn, i)
4984 : aarch64_get_vec_s32 (cpu, vm, i));
4995 do_vec_sub_long (sim_cpu *cpu)
4998 instr[30] = lower (0) / upper (1)
4999 instr[29] = signed (0) / unsigned (1)
5000 instr[28,24] = 0 1110
5001 instr[23,22] = size: bytes (00), half (01), word (10)
5004 instr[15,10] = 0010 00
5006 instr[4,0] = V dest. */
5008 unsigned size = uimm (aarch64_get_instr (cpu), 23, 22);
5009 unsigned vm = uimm (aarch64_get_instr (cpu), 20, 16);
5010 unsigned vn = uimm (aarch64_get_instr (cpu), 9, 5);
5011 unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
5015 NYI_assert (28, 24, 0x0E);
5016 NYI_assert (21, 21, 1);
5017 NYI_assert (15, 10, 0x08);
5022 switch (uimm (aarch64_get_instr (cpu), 30, 29))
5024 case 2: /* SSUBL2. */
5026 case 0: /* SSUBL. */
5031 for (i = 0; i < 8; i++)
5032 aarch64_set_vec_s16 (cpu, vd, i,
5033 aarch64_get_vec_s8 (cpu, vn, i + bias)
5034 - aarch64_get_vec_s8 (cpu, vm, i + bias));
5039 for (i = 0; i < 4; i++)
5040 aarch64_set_vec_s32 (cpu, vd, i,
5041 aarch64_get_vec_s16 (cpu, vn, i + bias)
5042 - aarch64_get_vec_s16 (cpu, vm, i + bias));
5046 for (i = 0; i < 2; i++)
5047 aarch64_set_vec_s64 (cpu, vd, i,
5048 aarch64_get_vec_s32 (cpu, vn, i + bias)
5049 - aarch64_get_vec_s32 (cpu, vm, i + bias));
5057 case 3: /* USUBL2. */
5059 case 1: /* USUBL. */
5064 for (i = 0; i < 8; i++)
5065 aarch64_set_vec_u16 (cpu, vd, i,
5066 aarch64_get_vec_u8 (cpu, vn, i + bias)
5067 - aarch64_get_vec_u8 (cpu, vm, i + bias));
5072 for (i = 0; i < 4; i++)
5073 aarch64_set_vec_u32 (cpu, vd, i,
5074 aarch64_get_vec_u16 (cpu, vn, i + bias)
5075 - aarch64_get_vec_u16 (cpu, vm, i + bias));
5079 for (i = 0; i < 2; i++)
5080 aarch64_set_vec_u64 (cpu, vd, i,
5081 aarch64_get_vec_u32 (cpu, vn, i + bias)
5082 - aarch64_get_vec_u32 (cpu, vm, i + bias));
5093 do_vec_ADDP (sim_cpu *cpu)
5096 instr[30] = half(0)/full(1)
5097 instr[29,24] = 00 1110
5098 instr[23,22] = size: bytes (00), half (01), word (10), long (11)
5101 instr[15,10] = 1011 11
5103 instr[4,0] = V dest. */
5107 unsigned full = uimm (aarch64_get_instr (cpu), 30, 30);
5108 unsigned size = uimm (aarch64_get_instr (cpu), 23, 22);
5109 unsigned vm = uimm (aarch64_get_instr (cpu), 20, 16);
5110 unsigned vn = uimm (aarch64_get_instr (cpu), 9, 5);
5111 unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
5114 NYI_assert (29, 24, 0x0E);
5115 NYI_assert (21, 21, 1);
5116 NYI_assert (15, 10, 0x2F);
5118 /* Make copies of the source registers in case vd == vn/vm. */
5119 copy_vn = cpu->fr[vn];
5120 copy_vm = cpu->fr[vm];
5125 range = full ? 8 : 4;
5126 for (i = 0; i < range; i++)
5128 aarch64_set_vec_u8 (cpu, vd, i,
5129 copy_vn.b[i * 2] + copy_vn.b[i * 2 + 1]);
5130 aarch64_set_vec_u8 (cpu, vd, i + range,
5131 copy_vm.b[i * 2] + copy_vm.b[i * 2 + 1]);
5136 range = full ? 4 : 2;
5137 for (i = 0; i < range; i++)
5139 aarch64_set_vec_u16 (cpu, vd, i,
5140 copy_vn.h[i * 2] + copy_vn.h[i * 2 + 1]);
5141 aarch64_set_vec_u16 (cpu, vd, i + range,
5142 copy_vm.h[i * 2] + copy_vm.h[i * 2 + 1]);
5147 range = full ? 2 : 1;
5148 for (i = 0; i < range; i++)
5150 aarch64_set_vec_u32 (cpu, vd, i,
5151 copy_vn.w[i * 2] + copy_vn.w[i * 2 + 1]);
5152 aarch64_set_vec_u32 (cpu, vd, i + range,
5153 copy_vm.w[i * 2] + copy_vm.w[i * 2 + 1]);
5160 aarch64_set_vec_u64 (cpu, vd, 0, copy_vn.v[0] + copy_vn.v[1]);
5161 aarch64_set_vec_u64 (cpu, vd, 1, copy_vm.v[0] + copy_vm.v[1]);
5170 do_vec_UMOV (sim_cpu *cpu)
5173 instr[30] = 32-bit(0)/64-bit(1)
5174 instr[29,21] = 00 1110 000
5175 insrt[20,16] = size & index
5176 instr[15,10] = 0011 11
5177 instr[9,5] = V source
5178 instr[4,0] = R dest. */
5180 unsigned vs = uimm (aarch64_get_instr (cpu), 9, 5);
5181 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
5184 NYI_assert (29, 21, 0x070);
5185 NYI_assert (15, 10, 0x0F);
5187 if (uimm (aarch64_get_instr (cpu), 16, 16))
5189 /* Byte transfer. */
5190 index = uimm (aarch64_get_instr (cpu), 20, 17);
5191 aarch64_set_reg_u64 (cpu, rd, NO_SP,
5192 aarch64_get_vec_u8 (cpu, vs, index));
5194 else if (uimm (aarch64_get_instr (cpu), 17, 17))
5196 index = uimm (aarch64_get_instr (cpu), 20, 18);
5197 aarch64_set_reg_u64 (cpu, rd, NO_SP,
5198 aarch64_get_vec_u16 (cpu, vs, index));
5200 else if (uimm (aarch64_get_instr (cpu), 18, 18))
5202 index = uimm (aarch64_get_instr (cpu), 20, 19);
5203 aarch64_set_reg_u64 (cpu, rd, NO_SP,
5204 aarch64_get_vec_u32 (cpu, vs, index));
5208 if (uimm (aarch64_get_instr (cpu), 30, 30) != 1)
5211 index = uimm (aarch64_get_instr (cpu), 20, 20);
5212 aarch64_set_reg_u64 (cpu, rd, NO_SP,
5213 aarch64_get_vec_u64 (cpu, vs, index));
5218 do_vec_FABS (sim_cpu *cpu)
5221 instr[30] = half(0)/full(1)
5222 instr[29,23] = 00 1110 1
5223 instr[22] = float(0)/double(1)
5224 instr[21,16] = 10 0000
5225 instr[15,10] = 1111 10
5229 unsigned vn = uimm (aarch64_get_instr (cpu), 9, 5);
5230 unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
5231 unsigned full = uimm (aarch64_get_instr (cpu), 30, 30);
5234 NYI_assert (29, 23, 0x1D);
5235 NYI_assert (21, 10, 0x83E);
5237 if (uimm (aarch64_get_instr (cpu), 22, 22))
5242 for (i = 0; i < 2; i++)
5243 aarch64_set_vec_double (cpu, vd, i,
5244 fabs (aarch64_get_vec_double (cpu, vn, i)));
5248 for (i = 0; i < (full ? 4 : 2); i++)
5249 aarch64_set_vec_float (cpu, vd, i,
5250 fabsf (aarch64_get_vec_float (cpu, vn, i)));
5255 do_vec_FCVTZS (sim_cpu *cpu)
5258 instr[30] = half (0) / all (1)
5259 instr[29,23] = 00 1110 1
5260 instr[22] = single (0) / double (1)
5261 instr[21,10] = 10 0001 1011 10
5265 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
5266 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
5267 unsigned full = uimm (aarch64_get_instr (cpu), 30, 30);
5270 NYI_assert (31, 31, 0);
5271 NYI_assert (29, 23, 0x1D);
5272 NYI_assert (21, 10, 0x86E);
5274 if (uimm (aarch64_get_instr (cpu), 22, 22))
5279 for (i = 0; i < 2; i++)
5280 aarch64_set_vec_s64 (cpu, rd, i,
5281 (int64_t) aarch64_get_vec_double (cpu, rn, i));
5284 for (i = 0; i < (full ? 4 : 2); i++)
5285 aarch64_set_vec_s32 (cpu, rd, i,
5286 (int32_t) aarch64_get_vec_float (cpu, rn, i));
5290 do_vec_op1 (sim_cpu *cpu)
5293 instr[30] = half/full
5294 instr[29,24] = 00 1110
5297 instr[15,10] = sub-opcode
5300 NYI_assert (29, 24, 0x0E);
5302 if (uimm (aarch64_get_instr (cpu), 21, 21) == 0)
5304 if (uimm (aarch64_get_instr (cpu), 23, 22) == 0)
5306 if (uimm (aarch64_get_instr (cpu), 30, 30) == 1
5307 && uimm (aarch64_get_instr (cpu), 17, 14) == 0
5308 && uimm (aarch64_get_instr (cpu), 12, 10) == 7)
5309 return do_vec_ins_2 (cpu);
5311 switch (uimm (aarch64_get_instr (cpu), 15, 10))
5313 case 0x01: do_vec_DUP_vector_into_vector (cpu); return;
5314 case 0x03: do_vec_DUP_scalar_into_vector (cpu); return;
5315 case 0x07: do_vec_INS (cpu); return;
5316 case 0x0A: do_vec_TRN (cpu); return;
5319 if (uimm (aarch64_get_instr (cpu), 17, 16) == 0)
5321 do_vec_MOV_into_scalar (cpu);
5330 do_vec_TBL (cpu); return;
5334 do_vec_UZP (cpu); return;
5338 do_vec_ZIP (cpu); return;
5345 switch (uimm (aarch64_get_instr (cpu), 13, 10))
5347 case 0x6: do_vec_UZP (cpu); return;
5348 case 0xE: do_vec_ZIP (cpu); return;
5349 case 0xA: do_vec_TRN (cpu); return;
5350 case 0xF: do_vec_UMOV (cpu); return;
5355 switch (uimm (aarch64_get_instr (cpu), 15, 10))
5358 switch (uimm (aarch64_get_instr (cpu), 23, 21))
5360 case 1: do_vec_AND (cpu); return;
5361 case 3: do_vec_BIC (cpu); return;
5362 case 5: do_vec_ORR (cpu); return;
5363 case 7: do_vec_ORN (cpu); return;
5367 case 0x08: do_vec_sub_long (cpu); return;
5368 case 0x0a: do_vec_XTN (cpu); return;
5369 case 0x11: do_vec_SSHL (cpu); return;
5370 case 0x19: do_vec_max (cpu); return;
5371 case 0x1B: do_vec_min (cpu); return;
5372 case 0x21: do_vec_add (cpu); return;
5373 case 0x25: do_vec_MLA (cpu); return;
5374 case 0x27: do_vec_mul (cpu); return;
5375 case 0x2F: do_vec_ADDP (cpu); return;
5376 case 0x30: do_vec_mull (cpu); return;
5377 case 0x33: do_vec_FMLA (cpu); return;
5378 case 0x35: do_vec_fadd (cpu); return;
5381 switch (uimm (aarch64_get_instr (cpu), 20, 16))
5383 case 0x00: do_vec_ABS (cpu); return;
5384 case 0x01: do_vec_FCVTZS (cpu); return;
5385 case 0x11: do_vec_ADDV (cpu); return;
5391 do_vec_Fminmax (cpu); return;
5403 do_vec_compare (cpu); return;
5406 do_vec_FABS (cpu); return;
5414 do_vec_xtl (sim_cpu *cpu)
5417 instr[30,29] = SXTL (00), UXTL (01), SXTL2 (10), UXTL2 (11)
5418 instr[28,22] = 0 1111 00
5419 instr[21,16] = size & shift (USHLL, SSHLL, USHLL2, SSHLL2)
5420 instr[15,10] = 1010 01
5421 instr[9,5] = V source
5422 instr[4,0] = V dest. */
5424 unsigned vs = uimm (aarch64_get_instr (cpu), 9, 5);
5425 unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
5426 unsigned i, shift, bias = 0;
5428 NYI_assert (28, 22, 0x3C);
5429 NYI_assert (15, 10, 0x29);
5431 switch (uimm (aarch64_get_instr (cpu), 30, 29))
5433 case 2: /* SXTL2, SSHLL2. */
5435 case 0: /* SXTL, SSHLL. */
5436 if (uimm (aarch64_get_instr (cpu), 21, 21))
5438 shift = uimm (aarch64_get_instr (cpu), 20, 16);
5440 (cpu, vd, 0, aarch64_get_vec_s32 (cpu, vs, bias) << shift);
5442 (cpu, vd, 1, aarch64_get_vec_s32 (cpu, vs, bias + 1) << shift);
5444 else if (uimm (aarch64_get_instr (cpu), 20, 20))
5446 shift = uimm (aarch64_get_instr (cpu), 19, 16);
5448 for (i = 0; i < 4; i++)
5450 (cpu, vd, i, aarch64_get_vec_s16 (cpu, vs, i + bias) << shift);
5454 NYI_assert (19, 19, 1);
5456 shift = uimm (aarch64_get_instr (cpu), 18, 16);
5458 for (i = 0; i < 8; i++)
5460 (cpu, vd, i, aarch64_get_vec_s8 (cpu, vs, i + bias) << shift);
5464 case 3: /* UXTL2, USHLL2. */
5466 case 1: /* UXTL, USHLL. */
5467 if (uimm (aarch64_get_instr (cpu), 21, 21))
5469 shift = uimm (aarch64_get_instr (cpu), 20, 16);
5471 (cpu, vd, 0, aarch64_get_vec_u32 (cpu, vs, bias) << shift);
5473 (cpu, vd, 1, aarch64_get_vec_u32 (cpu, vs, bias + 1) << shift);
5475 else if (uimm (aarch64_get_instr (cpu), 20, 20))
5477 shift = uimm (aarch64_get_instr (cpu), 19, 16);
5479 for (i = 0; i < 4; i++)
5481 (cpu, vd, i, aarch64_get_vec_u16 (cpu, vs, i + bias) << shift);
5485 NYI_assert (19, 19, 1);
5487 shift = uimm (aarch64_get_instr (cpu), 18, 16);
5489 for (i = 0; i < 8; i++)
5491 (cpu, vd, i, aarch64_get_vec_u8 (cpu, vs, i + bias) << shift);
5501 do_vec_SHL (sim_cpu *cpu)
5504 instr [30] = half(0)/full(1)
5505 instr [29,23] = 001 1110
5506 instr [22,16] = size and shift amount
5507 instr [15,10] = 01 0101
5509 instr [4, 0] = Vd. */
5512 int full = uimm (aarch64_get_instr (cpu), 30, 30);
5513 unsigned vs = uimm (aarch64_get_instr (cpu), 9, 5);
5514 unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
5517 NYI_assert (29, 23, 0x1E);
5518 NYI_assert (15, 10, 0x15);
5520 if (uimm (aarch64_get_instr (cpu), 22, 22))
5522 shift = uimm (aarch64_get_instr (cpu), 21, 16) - 1;
5527 for (i = 0; i < 2; i++)
5529 uint64_t val = aarch64_get_vec_u64 (cpu, vs, i);
5530 aarch64_set_vec_u64 (cpu, vd, i, val << shift);
5536 if (uimm (aarch64_get_instr (cpu), 21, 21))
5538 shift = uimm (aarch64_get_instr (cpu), 20, 16) - 1;
5540 for (i = 0; i < (full ? 4 : 2); i++)
5542 uint32_t val = aarch64_get_vec_u32 (cpu, vs, i);
5543 aarch64_set_vec_u32 (cpu, vd, i, val << shift);
5549 if (uimm (aarch64_get_instr (cpu), 20, 20))
5551 shift = uimm (aarch64_get_instr (cpu), 19, 16) - 1;
5553 for (i = 0; i < (full ? 8 : 4); i++)
5555 uint16_t val = aarch64_get_vec_u16 (cpu, vs, i);
5556 aarch64_set_vec_u16 (cpu, vd, i, val << shift);
5562 if (uimm (aarch64_get_instr (cpu), 19, 19) == 0)
5565 shift = uimm (aarch64_get_instr (cpu), 18, 16) - 1;
5567 for (i = 0; i < (full ? 16 : 8); i++)
5569 uint8_t val = aarch64_get_vec_u8 (cpu, vs, i);
5570 aarch64_set_vec_u8 (cpu, vd, i, val << shift);
5575 do_vec_SSHR_USHR (sim_cpu *cpu)
5578 instr [30] = half(0)/full(1)
5579 instr [29] = signed(0)/unsigned(1)
5580 instr [28,23] = 01 1110
5581 instr [22,16] = size and shift amount
5582 instr [15,10] = 0000 01
5584 instr [4, 0] = Vd. */
5587 int full = uimm (aarch64_get_instr (cpu), 30, 30);
5588 int sign = uimm (aarch64_get_instr (cpu), 29, 29);
5589 unsigned vs = uimm (aarch64_get_instr (cpu), 9, 5);
5590 unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
5593 NYI_assert (28, 23, 0x1E);
5594 NYI_assert (15, 10, 0x01);
5596 if (uimm (aarch64_get_instr (cpu), 22, 22))
5598 shift = uimm (aarch64_get_instr (cpu), 21, 16);
5604 for (i = 0; i < 2; i++)
5606 int64_t val = aarch64_get_vec_s64 (cpu, vs, i);
5607 aarch64_set_vec_s64 (cpu, vd, i, val >> shift);
5610 for (i = 0; i < 2; i++)
5612 uint64_t val = aarch64_get_vec_u64 (cpu, vs, i);
5613 aarch64_set_vec_u64 (cpu, vd, i, val >> shift);
5619 if (uimm (aarch64_get_instr (cpu), 21, 21))
5621 shift = uimm (aarch64_get_instr (cpu), 20, 16);
5624 for (i = 0; i < (full ? 4 : 2); i++)
5626 int32_t val = aarch64_get_vec_s32 (cpu, vs, i);
5627 aarch64_set_vec_s32 (cpu, vd, i, val >> shift);
5630 for (i = 0; i < (full ? 4 : 2); i++)
5632 uint32_t val = aarch64_get_vec_u32 (cpu, vs, i);
5633 aarch64_set_vec_u32 (cpu, vd, i, val >> shift);
5639 if (uimm (aarch64_get_instr (cpu), 20, 20))
5641 shift = uimm (aarch64_get_instr (cpu), 19, 16);
5644 for (i = 0; i < (full ? 8 : 4); i++)
5646 int16_t val = aarch64_get_vec_s16 (cpu, vs, i);
5647 aarch64_set_vec_s16 (cpu, vd, i, val >> shift);
5650 for (i = 0; i < (full ? 8 : 4); i++)
5652 uint16_t val = aarch64_get_vec_u16 (cpu, vs, i);
5653 aarch64_set_vec_u16 (cpu, vd, i, val >> shift);
5659 if (uimm (aarch64_get_instr (cpu), 19, 19) == 0)
5662 shift = uimm (aarch64_get_instr (cpu), 18, 16);
5665 for (i = 0; i < (full ? 16 : 8); i++)
5667 int8_t val = aarch64_get_vec_s8 (cpu, vs, i);
5668 aarch64_set_vec_s8 (cpu, vd, i, val >> shift);
5671 for (i = 0; i < (full ? 16 : 8); i++)
5673 uint8_t val = aarch64_get_vec_u8 (cpu, vs, i);
5674 aarch64_set_vec_u8 (cpu, vd, i, val >> shift);
5679 do_vec_op2 (sim_cpu *cpu)
5682 instr[30] = half/full
5683 instr[29,24] = 00 1111
5685 instr[22,16] = element size & index
5686 instr[15,10] = sub-opcode
5690 NYI_assert (29, 24, 0x0F);
5692 if (uimm (aarch64_get_instr (cpu), 23, 23) != 0)
5695 switch (uimm (aarch64_get_instr (cpu), 15, 10))
5697 case 0x01: do_vec_SSHR_USHR (cpu); return;
5698 case 0x15: do_vec_SHL (cpu); return;
5699 case 0x29: do_vec_xtl (cpu); return;
5705 do_vec_neg (sim_cpu *cpu)
5708 instr[30] = full(1)/half(0)
5709 instr[29,24] = 10 1110
5710 instr[23,22] = size: byte(00), half (01), word (10), long (11)
5711 instr[21,10] = 1000 0010 1110
5715 int full = uimm (aarch64_get_instr (cpu), 30, 30);
5716 unsigned vs = uimm (aarch64_get_instr (cpu), 9, 5);
5717 unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
5720 NYI_assert (29, 24, 0x2E);
5721 NYI_assert (21, 10, 0x82E);
5723 switch (uimm (aarch64_get_instr (cpu), 23, 22))
5726 for (i = 0; i < (full ? 16 : 8); i++)
5727 aarch64_set_vec_s8 (cpu, vd, i, - aarch64_get_vec_s8 (cpu, vs, i));
5731 for (i = 0; i < (full ? 8 : 4); i++)
5732 aarch64_set_vec_s16 (cpu, vd, i, - aarch64_get_vec_s16 (cpu, vs, i));
5736 for (i = 0; i < (full ? 4 : 2); i++)
5737 aarch64_set_vec_s32 (cpu, vd, i, - aarch64_get_vec_s32 (cpu, vs, i));
5743 for (i = 0; i < 2; i++)
5744 aarch64_set_vec_s64 (cpu, vd, i, - aarch64_get_vec_s64 (cpu, vs, i));
5753 do_vec_sqrt (sim_cpu *cpu)
5756 instr[30] = full(1)/half(0)
5757 instr[29,23] = 101 1101
5758 instr[22] = single(0)/double(1)
5759 instr[21,10] = 1000 0111 1110
5763 int full = uimm (aarch64_get_instr (cpu), 30, 30);
5764 unsigned vs = uimm (aarch64_get_instr (cpu), 9, 5);
5765 unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
5768 NYI_assert (29, 23, 0x5B);
5769 NYI_assert (21, 10, 0x87E);
5771 if (uimm (aarch64_get_instr (cpu), 22, 22) == 0)
5772 for (i = 0; i < (full ? 4 : 2); i++)
5773 aarch64_set_vec_float (cpu, vd, i,
5774 sqrtf (aarch64_get_vec_float (cpu, vs, i)));
5776 for (i = 0; i < 2; i++)
5777 aarch64_set_vec_double (cpu, vd, i,
5778 sqrt (aarch64_get_vec_double (cpu, vs, i)));
5782 do_vec_mls_indexed (sim_cpu *cpu)
5785 instr[30] = half(0)/full(1)
5786 instr[29,24] = 10 1111
5787 instr[23,22] = 16-bit(01)/32-bit(10)
5788 instr[21,20+11] = index (if 16-bit)
5789 instr[21+11] = index (if 32-bit)
5792 instr[11] = part of index
5797 int full = uimm (aarch64_get_instr (cpu), 30, 30);
5798 unsigned vs = uimm (aarch64_get_instr (cpu), 9, 5);
5799 unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
5800 unsigned vm = uimm (aarch64_get_instr (cpu), 20, 16);
5803 NYI_assert (15, 12, 4);
5804 NYI_assert (10, 10, 0);
5806 switch (uimm (aarch64_get_instr (cpu), 23, 22))
5816 elem = (uimm (aarch64_get_instr (cpu), 21, 20) << 1)
5817 | uimm (aarch64_get_instr (cpu), 11, 11);
5818 val = aarch64_get_vec_u16 (cpu, vm, elem);
5820 for (i = 0; i < (full ? 8 : 4); i++)
5821 aarch64_set_vec_u32 (cpu, vd, i,
5822 aarch64_get_vec_u32 (cpu, vd, i) -
5823 (aarch64_get_vec_u32 (cpu, vs, i) * val));
5829 unsigned elem = (uimm (aarch64_get_instr (cpu), 21, 21) << 1)
5830 | uimm (aarch64_get_instr (cpu), 11, 11);
5831 uint64_t val = aarch64_get_vec_u32 (cpu, vm, elem);
5833 for (i = 0; i < (full ? 4 : 2); i++)
5834 aarch64_set_vec_u64 (cpu, vd, i,
5835 aarch64_get_vec_u64 (cpu, vd, i) -
5836 (aarch64_get_vec_u64 (cpu, vs, i) * val));
5848 do_vec_SUB (sim_cpu *cpu)
5851 instr [30] = half(0)/full(1)
5852 instr [29,24] = 10 1110
5853 instr [23,22] = size: byte(00, half(01), word (10), long (11)
5856 instr [15,10] = 10 0001
5858 instr [4, 0] = Vd. */
5860 unsigned full = uimm (aarch64_get_instr (cpu), 30, 30);
5861 unsigned vm = uimm (aarch64_get_instr (cpu), 20, 16);
5862 unsigned vn = uimm (aarch64_get_instr (cpu), 9, 5);
5863 unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
5866 NYI_assert (29, 24, 0x2E);
5867 NYI_assert (21, 21, 1);
5868 NYI_assert (15, 10, 0x21);
5870 switch (uimm (aarch64_get_instr (cpu), 23, 22))
5873 for (i = 0; i < (full ? 16 : 8); i++)
5874 aarch64_set_vec_s8 (cpu, vd, i,
5875 aarch64_get_vec_s8 (cpu, vn, i)
5876 - aarch64_get_vec_s8 (cpu, vm, i));
5880 for (i = 0; i < (full ? 8 : 4); i++)
5881 aarch64_set_vec_s16 (cpu, vd, i,
5882 aarch64_get_vec_s16 (cpu, vn, i)
5883 - aarch64_get_vec_s16 (cpu, vm, i));
5887 for (i = 0; i < (full ? 4 : 2); i++)
5888 aarch64_set_vec_s32 (cpu, vd, i,
5889 aarch64_get_vec_s32 (cpu, vn, i)
5890 - aarch64_get_vec_s32 (cpu, vm, i));
5897 for (i = 0; i < 2; i++)
5898 aarch64_set_vec_s64 (cpu, vd, i,
5899 aarch64_get_vec_s64 (cpu, vn, i)
5900 - aarch64_get_vec_s64 (cpu, vm, i));
5909 do_vec_MLS (sim_cpu *cpu)
5912 instr [30] = half(0)/full(1)
5913 instr [29,24] = 10 1110
5914 instr [23,22] = size: byte(00, half(01), word (10)
5917 instr [15,10] = 10 0101
5919 instr [4, 0] = Vd. */
5921 unsigned full = uimm (aarch64_get_instr (cpu), 30, 30);
5922 unsigned vm = uimm (aarch64_get_instr (cpu), 20, 16);
5923 unsigned vn = uimm (aarch64_get_instr (cpu), 9, 5);
5924 unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
5927 NYI_assert (29, 24, 0x2E);
5928 NYI_assert (21, 21, 1);
5929 NYI_assert (15, 10, 0x25);
5931 switch (uimm (aarch64_get_instr (cpu), 23, 22))
5934 for (i = 0; i < (full ? 16 : 8); i++)
5935 aarch64_set_vec_u8 (cpu, vd, i,
5936 (aarch64_get_vec_u8 (cpu, vn, i)
5937 * aarch64_get_vec_u8 (cpu, vm, i))
5938 - aarch64_get_vec_u8 (cpu, vd, i));
5942 for (i = 0; i < (full ? 8 : 4); i++)
5943 aarch64_set_vec_u16 (cpu, vd, i,
5944 (aarch64_get_vec_u16 (cpu, vn, i)
5945 * aarch64_get_vec_u16 (cpu, vm, i))
5946 - aarch64_get_vec_u16 (cpu, vd, i));
5950 for (i = 0; i < (full ? 4 : 2); i++)
5951 aarch64_set_vec_u32 (cpu, vd, i,
5952 (aarch64_get_vec_u32 (cpu, vn, i)
5953 * aarch64_get_vec_u32 (cpu, vm, i))
5954 - aarch64_get_vec_u32 (cpu, vd, i));
5963 do_vec_FDIV (sim_cpu *cpu)
5966 instr [30] = half(0)/full(1)
5967 instr [29,23] = 10 1110 0
5968 instr [22] = float()/double(1)
5971 instr [15,10] = 1111 11
5973 instr [4, 0] = Vd. */
5975 unsigned full = uimm (aarch64_get_instr (cpu), 30, 30);
5976 unsigned vm = uimm (aarch64_get_instr (cpu), 20, 16);
5977 unsigned vn = uimm (aarch64_get_instr (cpu), 9, 5);
5978 unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
5981 NYI_assert (29, 23, 0x5C);
5982 NYI_assert (21, 21, 1);
5983 NYI_assert (15, 10, 0x3F);
5985 if (uimm (aarch64_get_instr (cpu), 22, 22))
5990 for (i = 0; i < 2; i++)
5991 aarch64_set_vec_double (cpu, vd, i,
5992 aarch64_get_vec_double (cpu, vn, i)
5993 / aarch64_get_vec_double (cpu, vm, i));
5996 for (i = 0; i < (full ? 4 : 2); i++)
5997 aarch64_set_vec_float (cpu, vd, i,
5998 aarch64_get_vec_float (cpu, vn, i)
5999 / aarch64_get_vec_float (cpu, vm, i));
6003 do_vec_FMUL (sim_cpu *cpu)
6006 instr [30] = half(0)/full(1)
6007 instr [29,23] = 10 1110 0
6008 instr [22] = float(0)/double(1)
6011 instr [15,10] = 1101 11
6013 instr [4, 0] = Vd. */
6015 unsigned full = uimm (aarch64_get_instr (cpu), 30, 30);
6016 unsigned vm = uimm (aarch64_get_instr (cpu), 20, 16);
6017 unsigned vn = uimm (aarch64_get_instr (cpu), 9, 5);
6018 unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
6021 NYI_assert (29, 23, 0x5C);
6022 NYI_assert (21, 21, 1);
6023 NYI_assert (15, 10, 0x37);
6025 if (uimm (aarch64_get_instr (cpu), 22, 22))
6030 for (i = 0; i < 2; i++)
6031 aarch64_set_vec_double (cpu, vd, i,
6032 aarch64_get_vec_double (cpu, vn, i)
6033 * aarch64_get_vec_double (cpu, vm, i));
6036 for (i = 0; i < (full ? 4 : 2); i++)
6037 aarch64_set_vec_float (cpu, vd, i,
6038 aarch64_get_vec_float (cpu, vn, i)
6039 * aarch64_get_vec_float (cpu, vm, i));
6043 do_vec_FADDP (sim_cpu *cpu)
6046 instr [30] = half(0)/full(1)
6047 instr [29,23] = 10 1110 0
6048 instr [22] = float(0)/double(1)
6051 instr [15,10] = 1101 01
6053 instr [4, 0] = Vd. */
6055 unsigned full = uimm (aarch64_get_instr (cpu), 30, 30);
6056 unsigned vm = uimm (aarch64_get_instr (cpu), 20, 16);
6057 unsigned vn = uimm (aarch64_get_instr (cpu), 9, 5);
6058 unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
6060 NYI_assert (29, 23, 0x5C);
6061 NYI_assert (21, 21, 1);
6062 NYI_assert (15, 10, 0x35);
6064 if (uimm (aarch64_get_instr (cpu), 22, 22))
6066 /* Extract values before adding them incase vd == vn/vm. */
6067 double tmp1 = aarch64_get_vec_double (cpu, vn, 0);
6068 double tmp2 = aarch64_get_vec_double (cpu, vn, 1);
6069 double tmp3 = aarch64_get_vec_double (cpu, vm, 0);
6070 double tmp4 = aarch64_get_vec_double (cpu, vm, 1);
6075 aarch64_set_vec_double (cpu, vd, 0, tmp1 + tmp2);
6076 aarch64_set_vec_double (cpu, vd, 1, tmp3 + tmp4);
6080 /* Extract values before adding them incase vd == vn/vm. */
6081 float tmp1 = aarch64_get_vec_float (cpu, vn, 0);
6082 float tmp2 = aarch64_get_vec_float (cpu, vn, 1);
6083 float tmp5 = aarch64_get_vec_float (cpu, vm, 0);
6084 float tmp6 = aarch64_get_vec_float (cpu, vm, 1);
6088 float tmp3 = aarch64_get_vec_float (cpu, vn, 2);
6089 float tmp4 = aarch64_get_vec_float (cpu, vn, 3);
6090 float tmp7 = aarch64_get_vec_float (cpu, vm, 2);
6091 float tmp8 = aarch64_get_vec_float (cpu, vm, 3);
6093 aarch64_set_vec_float (cpu, vd, 0, tmp1 + tmp2);
6094 aarch64_set_vec_float (cpu, vd, 1, tmp3 + tmp4);
6095 aarch64_set_vec_float (cpu, vd, 2, tmp5 + tmp6);
6096 aarch64_set_vec_float (cpu, vd, 3, tmp7 + tmp8);
6100 aarch64_set_vec_float (cpu, vd, 0, tmp1 + tmp2);
6101 aarch64_set_vec_float (cpu, vd, 1, tmp5 + tmp6);
6107 do_vec_FSQRT (sim_cpu *cpu)
6110 instr[30] = half(0)/full(1)
6111 instr[29,23] = 10 1110 1
6112 instr[22] = single(0)/double(1)
6113 instr[21,10] = 10 0001 1111 10
6115 instr[4,0] = Vdest. */
6117 unsigned vn = uimm (aarch64_get_instr (cpu), 9, 5);
6118 unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
6119 unsigned full = uimm (aarch64_get_instr (cpu), 30, 30);
6122 NYI_assert (29, 23, 0x5D);
6123 NYI_assert (21, 10, 0x87E);
6125 if (uimm (aarch64_get_instr (cpu), 22, 22))
6130 for (i = 0; i < 2; i++)
6131 aarch64_set_vec_double (cpu, vd, i,
6132 sqrt (aarch64_get_vec_double (cpu, vn, i)));
6136 for (i = 0; i < (full ? 4 : 2); i++)
6137 aarch64_set_vec_float (cpu, vd, i,
6138 sqrtf (aarch64_get_vec_float (cpu, vn, i)));
6143 do_vec_FNEG (sim_cpu *cpu)
6146 instr[30] = half (0)/full (1)
6147 instr[29,23] = 10 1110 1
6148 instr[22] = single (0)/double (1)
6149 instr[21,10] = 10 0000 1111 10
6151 instr[4,0] = Vdest. */
6153 unsigned vn = uimm (aarch64_get_instr (cpu), 9, 5);
6154 unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
6155 unsigned full = uimm (aarch64_get_instr (cpu), 30, 30);
6158 NYI_assert (29, 23, 0x5D);
6159 NYI_assert (21, 10, 0x83E);
6161 if (uimm (aarch64_get_instr (cpu), 22, 22))
6166 for (i = 0; i < 2; i++)
6167 aarch64_set_vec_double (cpu, vd, i,
6168 - aarch64_get_vec_double (cpu, vn, i));
6172 for (i = 0; i < (full ? 4 : 2); i++)
6173 aarch64_set_vec_float (cpu, vd, i,
6174 - aarch64_get_vec_float (cpu, vn, i));
6179 do_vec_NOT (sim_cpu *cpu)
6182 instr[30] = half (0)/full (1)
6183 instr[29,21] = 10 1110 001
6184 instr[20,16] = 0 0000
6185 instr[15,10] = 0101 10
6189 unsigned vn = uimm (aarch64_get_instr (cpu), 9, 5);
6190 unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
6192 int full = uimm (aarch64_get_instr (cpu), 30, 30);
6194 NYI_assert (29, 10, 0xB8816);
6196 for (i = 0; i < (full ? 16 : 8); i++)
6197 aarch64_set_vec_u8 (cpu, vd, i, ~ aarch64_get_vec_u8 (cpu, vn, i));
6201 do_vec_MOV_element (sim_cpu *cpu)
6203 /* instr[31,21] = 0110 1110 000
6204 instr[20,16] = size & dest index
6206 instr[14,11] = source index
6211 unsigned vs = uimm (aarch64_get_instr (cpu), 9, 5);
6212 unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
6216 NYI_assert (31, 21, 0x370);
6217 NYI_assert (15, 15, 0);
6218 NYI_assert (10, 10, 1);
6220 if (uimm (aarch64_get_instr (cpu), 16, 16))
6223 src_index = uimm (aarch64_get_instr (cpu), 14, 11);
6224 dst_index = uimm (aarch64_get_instr (cpu), 20, 17);
6225 aarch64_set_vec_u8 (cpu, vd, dst_index,
6226 aarch64_get_vec_u8 (cpu, vs, src_index));
6228 else if (uimm (aarch64_get_instr (cpu), 17, 17))
6231 NYI_assert (11, 11, 0);
6232 src_index = uimm (aarch64_get_instr (cpu), 14, 12);
6233 dst_index = uimm (aarch64_get_instr (cpu), 20, 18);
6234 aarch64_set_vec_u16 (cpu, vd, dst_index,
6235 aarch64_get_vec_u16 (cpu, vs, src_index));
6237 else if (uimm (aarch64_get_instr (cpu), 18, 18))
6240 NYI_assert (12, 11, 0);
6241 src_index = uimm (aarch64_get_instr (cpu), 14, 13);
6242 dst_index = uimm (aarch64_get_instr (cpu), 20, 19);
6243 aarch64_set_vec_u32 (cpu, vd, dst_index,
6244 aarch64_get_vec_u32 (cpu, vs, src_index));
6248 NYI_assert (19, 19, 1);
6249 NYI_assert (13, 11, 0);
6250 src_index = uimm (aarch64_get_instr (cpu), 14, 14);
6251 dst_index = uimm (aarch64_get_instr (cpu), 20, 20);
6252 aarch64_set_vec_u64 (cpu, vd, dst_index,
6253 aarch64_get_vec_u64 (cpu, vs, src_index));
6258 dexAdvSIMD0 (sim_cpu *cpu)
6260 /* instr [28,25] = 0 111. */
6261 if ( uimm (aarch64_get_instr (cpu), 15, 10) == 0x07
6262 && (uimm (aarch64_get_instr (cpu), 9, 5) ==
6263 uimm (aarch64_get_instr (cpu), 20, 16)))
6265 if (uimm (aarch64_get_instr (cpu), 31, 21) == 0x075
6266 || uimm (aarch64_get_instr (cpu), 31, 21) == 0x275)
6268 do_vec_MOV_whole_vector (cpu);
6273 if (uimm (aarch64_get_instr (cpu), 29, 19) == 0x1E0)
6275 do_vec_MOV_immediate (cpu);
6279 if (uimm (aarch64_get_instr (cpu), 29, 19) == 0x5E0)
6285 if (uimm (aarch64_get_instr (cpu), 29, 19) == 0x1C0
6286 || uimm (aarch64_get_instr (cpu), 29, 19) == 0x1C1)
6288 if (uimm (aarch64_get_instr (cpu), 15, 10) == 0x03)
6290 do_vec_DUP_scalar_into_vector (cpu);
6295 switch (uimm (aarch64_get_instr (cpu), 29, 24))
6297 case 0x0E: do_vec_op1 (cpu); return;
6298 case 0x0F: do_vec_op2 (cpu); return;
6301 switch (uimm (aarch64_get_instr (cpu), 15, 10))
6303 case 0x01: do_vec_SSHR_USHR (cpu); return;
6305 case 0x12: do_vec_mls_indexed (cpu); return;
6306 case 0x29: do_vec_xtl (cpu); return;
6312 if (uimm (aarch64_get_instr (cpu), 21, 21) == 1)
6314 switch (uimm (aarch64_get_instr (cpu), 15, 10))
6317 switch (uimm (aarch64_get_instr (cpu), 23, 22))
6319 case 0: do_vec_EOR (cpu); return;
6320 case 1: do_vec_BSL (cpu); return;
6322 case 3: do_vec_bit (cpu); return;
6326 case 0x08: do_vec_sub_long (cpu); return;
6327 case 0x11: do_vec_USHL (cpu); return;
6328 case 0x16: do_vec_NOT (cpu); return;
6329 case 0x19: do_vec_max (cpu); return;
6330 case 0x1B: do_vec_min (cpu); return;
6331 case 0x21: do_vec_SUB (cpu); return;
6332 case 0x25: do_vec_MLS (cpu); return;
6333 case 0x31: do_vec_FminmaxNMP (cpu); return;
6334 case 0x35: do_vec_FADDP (cpu); return;
6335 case 0x37: do_vec_FMUL (cpu); return;
6336 case 0x3F: do_vec_FDIV (cpu); return;
6339 switch (uimm (aarch64_get_instr (cpu), 20, 16))
6341 case 0x00: do_vec_FNEG (cpu); return;
6342 case 0x01: do_vec_FSQRT (cpu); return;
6356 do_vec_compare (cpu); return;
6362 if (uimm (aarch64_get_instr (cpu), 31, 21) == 0x370)
6364 do_vec_MOV_element (cpu);
6368 switch (uimm (aarch64_get_instr (cpu), 21, 10))
6370 case 0x82E: do_vec_neg (cpu); return;
6371 case 0x87E: do_vec_sqrt (cpu); return;
6373 if (uimm (aarch64_get_instr (cpu), 15, 10) == 0x30)
6391 /* Float multiply add. */
6393 fmadds (sim_cpu *cpu)
6395 unsigned sa = uimm (aarch64_get_instr (cpu), 14, 10);
6396 unsigned sm = uimm (aarch64_get_instr (cpu), 20, 16);
6397 unsigned sn = uimm (aarch64_get_instr (cpu), 9, 5);
6398 unsigned sd = uimm (aarch64_get_instr (cpu), 4, 0);
6400 aarch64_set_FP_float (cpu, sd, aarch64_get_FP_float (cpu, sa)
6401 + aarch64_get_FP_float (cpu, sn)
6402 * aarch64_get_FP_float (cpu, sm));
6405 /* Double multiply add. */
6407 fmaddd (sim_cpu *cpu)
6409 unsigned sa = uimm (aarch64_get_instr (cpu), 14, 10);
6410 unsigned sm = uimm (aarch64_get_instr (cpu), 20, 16);
6411 unsigned sn = uimm (aarch64_get_instr (cpu), 9, 5);
6412 unsigned sd = uimm (aarch64_get_instr (cpu), 4, 0);
6414 aarch64_set_FP_double (cpu, sd, aarch64_get_FP_double (cpu, sa)
6415 + aarch64_get_FP_double (cpu, sn)
6416 * aarch64_get_FP_double (cpu, sm));
6419 /* Float multiply subtract. */
6421 fmsubs (sim_cpu *cpu)
6423 unsigned sa = uimm (aarch64_get_instr (cpu), 14, 10);
6424 unsigned sm = uimm (aarch64_get_instr (cpu), 20, 16);
6425 unsigned sn = uimm (aarch64_get_instr (cpu), 9, 5);
6426 unsigned sd = uimm (aarch64_get_instr (cpu), 4, 0);
6428 aarch64_set_FP_float (cpu, sd, aarch64_get_FP_float (cpu, sa)
6429 - aarch64_get_FP_float (cpu, sn)
6430 * aarch64_get_FP_float (cpu, sm));
6433 /* Double multiply subtract. */
6435 fmsubd (sim_cpu *cpu)
6437 unsigned sa = uimm (aarch64_get_instr (cpu), 14, 10);
6438 unsigned sm = uimm (aarch64_get_instr (cpu), 20, 16);
6439 unsigned sn = uimm (aarch64_get_instr (cpu), 9, 5);
6440 unsigned sd = uimm (aarch64_get_instr (cpu), 4, 0);
6442 aarch64_set_FP_double (cpu, sd, aarch64_get_FP_double (cpu, sa)
6443 - aarch64_get_FP_double (cpu, sn)
6444 * aarch64_get_FP_double (cpu, sm));
6447 /* Float negative multiply add. */
6449 fnmadds (sim_cpu *cpu)
6451 unsigned sa = uimm (aarch64_get_instr (cpu), 14, 10);
6452 unsigned sm = uimm (aarch64_get_instr (cpu), 20, 16);
6453 unsigned sn = uimm (aarch64_get_instr (cpu), 9, 5);
6454 unsigned sd = uimm (aarch64_get_instr (cpu), 4, 0);
6456 aarch64_set_FP_float (cpu, sd, - aarch64_get_FP_float (cpu, sa)
6457 + (- aarch64_get_FP_float (cpu, sn))
6458 * aarch64_get_FP_float (cpu, sm));
6461 /* Double negative multiply add. */
6463 fnmaddd (sim_cpu *cpu)
6465 unsigned sa = uimm (aarch64_get_instr (cpu), 14, 10);
6466 unsigned sm = uimm (aarch64_get_instr (cpu), 20, 16);
6467 unsigned sn = uimm (aarch64_get_instr (cpu), 9, 5);
6468 unsigned sd = uimm (aarch64_get_instr (cpu), 4, 0);
6470 aarch64_set_FP_double (cpu, sd, - aarch64_get_FP_double (cpu, sa)
6471 + (- aarch64_get_FP_double (cpu, sn))
6472 * aarch64_get_FP_double (cpu, sm));
6475 /* Float negative multiply subtract. */
6477 fnmsubs (sim_cpu *cpu)
6479 unsigned sa = uimm (aarch64_get_instr (cpu), 14, 10);
6480 unsigned sm = uimm (aarch64_get_instr (cpu), 20, 16);
6481 unsigned sn = uimm (aarch64_get_instr (cpu), 9, 5);
6482 unsigned sd = uimm (aarch64_get_instr (cpu), 4, 0);
6484 aarch64_set_FP_float (cpu, sd, - aarch64_get_FP_float (cpu, sa)
6485 + aarch64_get_FP_float (cpu, sn)
6486 * aarch64_get_FP_float (cpu, sm));
6489 /* Double negative multiply subtract. */
6491 fnmsubd (sim_cpu *cpu)
6493 unsigned sa = uimm (aarch64_get_instr (cpu), 14, 10);
6494 unsigned sm = uimm (aarch64_get_instr (cpu), 20, 16);
6495 unsigned sn = uimm (aarch64_get_instr (cpu), 9, 5);
6496 unsigned sd = uimm (aarch64_get_instr (cpu), 4, 0);
6498 aarch64_set_FP_double (cpu, sd, - aarch64_get_FP_double (cpu, sa)
6499 + aarch64_get_FP_double (cpu, sn)
6500 * aarch64_get_FP_double (cpu, sm));
6504 dexSimpleFPDataProc3Source (sim_cpu *cpu)
6506 /* instr[31] ==> M : 0 ==> OK, 1 ==> UNALLOC
6508 instr[29] ==> S : 0 ==> OK, 1 ==> UNALLOC
6511 instr[23,22] ==> type : 0 ==> single, 01 ==> double, 1x ==> UNALLOC
6512 instr[21] ==> o1 : 0 ==> unnegated, 1 ==> negated
6513 instr[15] ==> o2 : 0 ==> ADD, 1 ==> SUB */
6515 uint32_t M_S = (uimm (aarch64_get_instr (cpu), 31, 31) << 1)
6516 | uimm (aarch64_get_instr (cpu), 29, 29);
6517 /* dispatch on combined type:o1:o2. */
6518 uint32_t dispatch = (uimm (aarch64_get_instr (cpu), 23, 21) << 1)
6519 | uimm (aarch64_get_instr (cpu), 15, 15);
6526 case 0: fmadds (cpu); return;
6527 case 1: fmsubs (cpu); return;
6528 case 2: fnmadds (cpu); return;
6529 case 3: fnmsubs (cpu); return;
6530 case 4: fmaddd (cpu); return;
6531 case 5: fmsubd (cpu); return;
6532 case 6: fnmaddd (cpu); return;
6533 case 7: fnmsubd (cpu); return;
6535 /* type > 1 is currently unallocated. */
6541 dexSimpleFPFixedConvert (sim_cpu *cpu)
6547 dexSimpleFPCondCompare (sim_cpu *cpu)
6556 fadds (sim_cpu *cpu)
6558 unsigned sm = uimm (aarch64_get_instr (cpu), 20, 16);
6559 unsigned sn = uimm (aarch64_get_instr (cpu), 9, 5);
6560 unsigned sd = uimm (aarch64_get_instr (cpu), 4, 0);
6562 aarch64_set_FP_float (cpu, sd, aarch64_get_FP_float (cpu, sn)
6563 + aarch64_get_FP_float (cpu, sm));
6568 faddd (sim_cpu *cpu)
6570 unsigned sm = uimm (aarch64_get_instr (cpu), 20, 16);
6571 unsigned sn = uimm (aarch64_get_instr (cpu), 9, 5);
6572 unsigned sd = uimm (aarch64_get_instr (cpu), 4, 0);
6574 aarch64_set_FP_double (cpu, sd, aarch64_get_FP_double (cpu, sn)
6575 + aarch64_get_FP_double (cpu, sm));
6580 fdivs (sim_cpu *cpu)
6582 unsigned sm = uimm (aarch64_get_instr (cpu), 20, 16);
6583 unsigned sn = uimm (aarch64_get_instr (cpu), 9, 5);
6584 unsigned sd = uimm (aarch64_get_instr (cpu), 4, 0);
6586 aarch64_set_FP_float (cpu, sd, aarch64_get_FP_float (cpu, sn)
6587 / aarch64_get_FP_float (cpu, sm));
6590 /* Double divide. */
6592 fdivd (sim_cpu *cpu)
6594 unsigned sm = uimm (aarch64_get_instr (cpu), 20, 16);
6595 unsigned sn = uimm (aarch64_get_instr (cpu), 9, 5);
6596 unsigned sd = uimm (aarch64_get_instr (cpu), 4, 0);
6598 aarch64_set_FP_double (cpu, sd, aarch64_get_FP_double (cpu, sn)
6599 / aarch64_get_FP_double (cpu, sm));
6602 /* Float multiply. */
6604 fmuls (sim_cpu *cpu)
6606 unsigned sm = uimm (aarch64_get_instr (cpu), 20, 16);
6607 unsigned sn = uimm (aarch64_get_instr (cpu), 9, 5);
6608 unsigned sd = uimm (aarch64_get_instr (cpu), 4, 0);
6610 aarch64_set_FP_float (cpu, sd, aarch64_get_FP_float (cpu, sn)
6611 * aarch64_get_FP_float (cpu, sm));
6614 /* Double multiply. */
6616 fmuld (sim_cpu *cpu)
6618 unsigned sm = uimm (aarch64_get_instr (cpu), 20, 16);
6619 unsigned sn = uimm (aarch64_get_instr (cpu), 9, 5);
6620 unsigned sd = uimm (aarch64_get_instr (cpu), 4, 0);
6622 aarch64_set_FP_double (cpu, sd, aarch64_get_FP_double (cpu, sn)
6623 * aarch64_get_FP_double (cpu, sm));
6626 /* Float negate and multiply. */
6628 fnmuls (sim_cpu *cpu)
6630 unsigned sm = uimm (aarch64_get_instr (cpu), 20, 16);
6631 unsigned sn = uimm (aarch64_get_instr (cpu), 9, 5);
6632 unsigned sd = uimm (aarch64_get_instr (cpu), 4, 0);
6634 aarch64_set_FP_float (cpu, sd, - (aarch64_get_FP_float (cpu, sn)
6635 * aarch64_get_FP_float (cpu, sm)));
6638 /* Double negate and multiply. */
6640 fnmuld (sim_cpu *cpu)
6642 unsigned sm = uimm (aarch64_get_instr (cpu), 20, 16);
6643 unsigned sn = uimm (aarch64_get_instr (cpu), 9, 5);
6644 unsigned sd = uimm (aarch64_get_instr (cpu), 4, 0);
6646 aarch64_set_FP_double (cpu, sd, - (aarch64_get_FP_double (cpu, sn)
6647 * aarch64_get_FP_double (cpu, sm)));
6650 /* Float subtract. */
6652 fsubs (sim_cpu *cpu)
6654 unsigned sm = uimm (aarch64_get_instr (cpu), 20, 16);
6655 unsigned sn = uimm (aarch64_get_instr (cpu), 9, 5);
6656 unsigned sd = uimm (aarch64_get_instr (cpu), 4, 0);
6658 aarch64_set_FP_float (cpu, sd, aarch64_get_FP_float (cpu, sn)
6659 - aarch64_get_FP_float (cpu, sm));
6662 /* Double subtract. */
6664 fsubd (sim_cpu *cpu)
6666 unsigned sm = uimm (aarch64_get_instr (cpu), 20, 16);
6667 unsigned sn = uimm (aarch64_get_instr (cpu), 9, 5);
6668 unsigned sd = uimm (aarch64_get_instr (cpu), 4, 0);
6670 aarch64_set_FP_double (cpu, sd, aarch64_get_FP_double (cpu, sn)
6671 - aarch64_get_FP_double (cpu, sm));
6675 do_FMINNM (sim_cpu *cpu)
6677 /* instr[31,23] = 0 0011 1100
6678 instr[22] = float(0)/double(1)
6681 instr[15,10] = 01 1110
6685 unsigned sm = uimm (aarch64_get_instr (cpu), 20, 16);
6686 unsigned sn = uimm (aarch64_get_instr (cpu), 9, 5);
6687 unsigned sd = uimm (aarch64_get_instr (cpu), 4, 0);
6689 NYI_assert (31, 23, 0x03C);
6690 NYI_assert (15, 10, 0x1E);
6692 if (uimm (aarch64_get_instr (cpu), 22, 22))
6693 aarch64_set_FP_double (cpu, sd,
6694 dminnm (aarch64_get_FP_double (cpu, sn),
6695 aarch64_get_FP_double (cpu, sm)));
6697 aarch64_set_FP_float (cpu, sd,
6698 fminnm (aarch64_get_FP_float (cpu, sn),
6699 aarch64_get_FP_float (cpu, sm)));
6703 do_FMAXNM (sim_cpu *cpu)
6705 /* instr[31,23] = 0 0011 1100
6706 instr[22] = float(0)/double(1)
6709 instr[15,10] = 01 1010
6713 unsigned sm = uimm (aarch64_get_instr (cpu), 20, 16);
6714 unsigned sn = uimm (aarch64_get_instr (cpu), 9, 5);
6715 unsigned sd = uimm (aarch64_get_instr (cpu), 4, 0);
6717 NYI_assert (31, 23, 0x03C);
6718 NYI_assert (15, 10, 0x1A);
6720 if (uimm (aarch64_get_instr (cpu), 22, 22))
6721 aarch64_set_FP_double (cpu, sd,
6722 dmaxnm (aarch64_get_FP_double (cpu, sn),
6723 aarch64_get_FP_double (cpu, sm)));
6725 aarch64_set_FP_float (cpu, sd,
6726 fmaxnm (aarch64_get_FP_float (cpu, sn),
6727 aarch64_get_FP_float (cpu, sm)));
6731 dexSimpleFPDataProc2Source (sim_cpu *cpu)
6733 /* instr[31] ==> M : 0 ==> OK, 1 ==> UNALLOC
6735 instr[29] ==> S : 0 ==> OK, 1 ==> UNALLOC
6738 instr[23,22] ==> type : 0 ==> single, 01 ==> double, 1x ==> UNALLOC
6741 instr[15,12] ==> opcode : 0000 ==> FMUL, 0001 ==> FDIV
6742 0010 ==> FADD, 0011 ==> FSUB,
6743 0100 ==> FMAX, 0101 ==> FMIN
6744 0110 ==> FMAXNM, 0111 ==> FMINNM
6745 1000 ==> FNMUL, ow ==> UNALLOC
6750 uint32_t M_S = (uimm (aarch64_get_instr (cpu), 31, 31) << 1)
6751 | uimm (aarch64_get_instr (cpu), 29, 29);
6752 uint32_t type = uimm (aarch64_get_instr (cpu), 23, 22);
6753 /* Dispatch on opcode. */
6754 uint32_t dispatch = uimm (aarch64_get_instr (cpu), 15, 12);
6765 case 0: fmuld (cpu); return;
6766 case 1: fdivd (cpu); return;
6767 case 2: faddd (cpu); return;
6768 case 3: fsubd (cpu); return;
6769 case 6: do_FMAXNM (cpu); return;
6770 case 7: do_FMINNM (cpu); return;
6771 case 8: fnmuld (cpu); return;
6773 /* Have not yet implemented fmax and fmin. */
6781 else /* type == 0 => floats. */
6784 case 0: fmuls (cpu); return;
6785 case 1: fdivs (cpu); return;
6786 case 2: fadds (cpu); return;
6787 case 3: fsubs (cpu); return;
6788 case 6: do_FMAXNM (cpu); return;
6789 case 7: do_FMINNM (cpu); return;
6790 case 8: fnmuls (cpu); return;
6802 dexSimpleFPCondSelect (sim_cpu *cpu)
6805 instr[31,23] = 0 0011 1100
6806 instr[22] = 0=>single 1=>double
6813 unsigned sm = uimm (aarch64_get_instr (cpu), 20, 16);
6814 unsigned sn = uimm (aarch64_get_instr (cpu), 9, 5);
6815 unsigned sd = uimm (aarch64_get_instr (cpu), 4, 0);
6816 uint32_t set = testConditionCode (cpu, uimm (aarch64_get_instr (cpu), 15, 12));
6818 NYI_assert (31, 23, 0x03C);
6819 NYI_assert (11, 10, 0x3);
6821 if (uimm (aarch64_get_instr (cpu), 22, 22))
6822 aarch64_set_FP_double (cpu, sd, set ? sn : sm);
6824 aarch64_set_FP_float (cpu, sd, set ? sn : sm);
6827 /* Store 32 bit unscaled signed 9 bit. */
6829 fsturs (sim_cpu *cpu, int32_t offset)
6831 unsigned int rn = uimm (aarch64_get_instr (cpu), 9, 5);
6832 unsigned int st = uimm (aarch64_get_instr (cpu), 4, 0);
6834 aarch64_set_mem_float (cpu, aarch64_get_reg_u64 (cpu, st, 1) + offset,
6835 aarch64_get_FP_float (cpu, rn));
6838 /* Store 64 bit unscaled signed 9 bit. */
6840 fsturd (sim_cpu *cpu, int32_t offset)
6842 unsigned int rn = uimm (aarch64_get_instr (cpu), 9, 5);
6843 unsigned int st = uimm (aarch64_get_instr (cpu), 4, 0);
6845 aarch64_set_mem_double (cpu, aarch64_get_reg_u64 (cpu, st, 1) + offset,
6846 aarch64_get_FP_double (cpu, rn));
6849 /* Store 128 bit unscaled signed 9 bit. */
6851 fsturq (sim_cpu *cpu, int32_t offset)
6853 unsigned int rn = uimm (aarch64_get_instr (cpu), 9, 5);
6854 unsigned int st = uimm (aarch64_get_instr (cpu), 4, 0);
6857 aarch64_get_FP_long_double (cpu, rn, & a);
6858 aarch64_set_mem_long_double (cpu,
6859 aarch64_get_reg_u64 (cpu, st, 1)
6863 /* TODO FP move register. */
6865 /* 32 bit fp to fp move register. */
6867 ffmovs (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_float (cpu, st, aarch64_get_FP_float (cpu, rn));
6875 /* 64 bit fp to fp move register. */
6877 ffmovd (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_FP_double (cpu, st, aarch64_get_FP_double (cpu, rn));
6885 /* 32 bit GReg to Vec move register. */
6887 fgmovs (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_u32 (cpu, st, 0, aarch64_get_reg_u32 (cpu, rn, NO_SP));
6895 /* 64 bit g to fp move register. */
6897 fgmovd (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_vec_u64 (cpu, st, 0, aarch64_get_reg_u64 (cpu, rn, NO_SP));
6905 /* 32 bit fp to g move register. */
6907 gfmovs (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_u32 (cpu, rn, 0));
6915 /* 64 bit fp to g move register. */
6917 gfmovd (sim_cpu *cpu)
6919 unsigned int rn = uimm (aarch64_get_instr (cpu), 9, 5);
6920 unsigned int st = uimm (aarch64_get_instr (cpu), 4, 0);
6922 aarch64_set_reg_u64 (cpu, st, NO_SP, aarch64_get_vec_u64 (cpu, rn, 0));
6925 /* FP move immediate
6927 These install an immediate 8 bit value in the target register
6928 where the 8 bits comprise 1 sign bit, 4 bits of fraction and a 3
6932 fmovs (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 float f = fp_immediate_for_encoding_32 (imm);
6938 aarch64_set_FP_float (cpu, sd, f);
6942 fmovd (sim_cpu *cpu)
6944 unsigned int sd = uimm (aarch64_get_instr (cpu), 4, 0);
6945 uint32_t imm = uimm (aarch64_get_instr (cpu), 20, 13);
6946 double d = fp_immediate_for_encoding_64 (imm);
6948 aarch64_set_FP_double (cpu, sd, d);
6952 dexSimpleFPImmediate (sim_cpu *cpu)
6954 /* instr[31,23] == 00111100
6955 instr[22] == type : single(0)/double(1)
6957 instr[20,13] == imm8
6959 instr[9,5] == imm5 : 00000 ==> PK, ow ==> UNALLOC
6961 uint32_t imm5 = uimm (aarch64_get_instr (cpu), 9, 5);
6963 NYI_assert (31, 23, 0x3C);
6968 if (uimm (aarch64_get_instr (cpu), 22, 22))
6974 /* TODO specific decode and execute for group Load Store. */
6976 /* TODO FP load/store single register (unscaled offset). */
6978 /* TODO load 8 bit unscaled signed 9 bit. */
6979 /* TODO load 16 bit unscaled signed 9 bit. */
6981 /* Load 32 bit unscaled signed 9 bit. */
6983 fldurs (sim_cpu *cpu, int32_t offset)
6985 unsigned int rn = uimm (aarch64_get_instr (cpu), 9, 5);
6986 unsigned int st = uimm (aarch64_get_instr (cpu), 4, 0);
6988 aarch64_set_FP_float (cpu, st, aarch64_get_mem_float
6989 (cpu, aarch64_get_reg_u64 (cpu, rn, SP_OK) + offset));
6992 /* Load 64 bit unscaled signed 9 bit. */
6994 fldurd (sim_cpu *cpu, int32_t offset)
6996 unsigned int rn = uimm (aarch64_get_instr (cpu), 9, 5);
6997 unsigned int st = uimm (aarch64_get_instr (cpu), 4, 0);
6999 aarch64_set_FP_double (cpu, st, aarch64_get_mem_double
7000 (cpu, aarch64_get_reg_u64 (cpu, rn, SP_OK) + offset));
7003 /* Load 128 bit unscaled signed 9 bit. */
7005 fldurq (sim_cpu *cpu, int32_t offset)
7007 unsigned int rn = uimm (aarch64_get_instr (cpu), 9, 5);
7008 unsigned int st = uimm (aarch64_get_instr (cpu), 4, 0);
7010 uint64_t addr = aarch64_get_reg_u64 (cpu, rn, SP_OK) + offset;
7012 aarch64_get_mem_long_double (cpu, addr, & a);
7013 aarch64_set_FP_long_double (cpu, st, a);
7016 /* TODO store 8 bit unscaled signed 9 bit. */
7017 /* TODO store 16 bit unscaled signed 9 bit. */
7022 /* Float absolute value. */
7024 fabss (sim_cpu *cpu)
7026 unsigned sn = uimm (aarch64_get_instr (cpu), 9, 5);
7027 unsigned sd = uimm (aarch64_get_instr (cpu), 4, 0);
7028 float value = aarch64_get_FP_float (cpu, sn);
7030 aarch64_set_FP_float (cpu, sd, fabsf (value));
7033 /* Double absolute value. */
7035 fabcpu (sim_cpu *cpu)
7037 unsigned sn = uimm (aarch64_get_instr (cpu), 9, 5);
7038 unsigned sd = uimm (aarch64_get_instr (cpu), 4, 0);
7039 double value = aarch64_get_FP_double (cpu, sn);
7041 aarch64_set_FP_double (cpu, sd, fabs (value));
7044 /* Float negative value. */
7046 fnegs (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_float (cpu, sd, - aarch64_get_FP_float (cpu, sn));
7054 /* Double negative value. */
7056 fnegd (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_double (cpu, sd, - aarch64_get_FP_double (cpu, sn));
7064 /* Float square root. */
7066 fsqrts (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_float (cpu, sd, sqrt (aarch64_get_FP_float (cpu, sn)));
7074 /* Double square root. */
7076 fsqrtd (sim_cpu *cpu)
7078 unsigned sn = uimm (aarch64_get_instr (cpu), 9, 5);
7079 unsigned sd = uimm (aarch64_get_instr (cpu), 4, 0);
7081 aarch64_set_FP_double (cpu, sd,
7082 sqrt (aarch64_get_FP_double (cpu, sn)));
7085 /* Convert double to float. */
7087 fcvtds (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_float (cpu, sd, (float) aarch64_get_FP_double (cpu, sn));
7095 /* Convert float to double. */
7097 fcvtcpu (sim_cpu *cpu)
7099 unsigned sn = uimm (aarch64_get_instr (cpu), 9, 5);
7100 unsigned sd = uimm (aarch64_get_instr (cpu), 4, 0);
7102 aarch64_set_FP_double (cpu, sd, (double) aarch64_get_FP_float (cpu, sn));
7106 do_FRINT (sim_cpu *cpu)
7108 /* instr[31,23] = 0001 1110 0
7109 instr[22] = single(0)/double(1)
7111 instr[17,15] = rounding mode
7112 instr[14,10] = 10000
7114 instr[4,0] = dest */
7117 unsigned rs = uimm (aarch64_get_instr (cpu), 9, 5);
7118 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
7119 unsigned int rmode = uimm (aarch64_get_instr (cpu), 17, 15);
7121 NYI_assert (31, 23, 0x03C);
7122 NYI_assert (21, 18, 0x9);
7123 NYI_assert (14, 10, 0x10);
7125 if (rmode == 6 || rmode == 7)
7126 /* FIXME: Add support for rmode == 6 exactness check. */
7127 rmode = uimm (aarch64_get_FPSR (cpu), 23, 22);
7129 if (uimm (aarch64_get_instr (cpu), 22, 22))
7131 double val = aarch64_get_FP_double (cpu, rs);
7135 case 0: /* mode N: nearest or even. */
7137 double rval = round (val);
7139 if (val - rval == 0.5)
7141 if (((rval / 2.0) * 2.0) != rval)
7145 aarch64_set_FP_double (cpu, rd, round (val));
7149 case 1: /* mode P: towards +inf. */
7151 aarch64_set_FP_double (cpu, rd, trunc (val));
7153 aarch64_set_FP_double (cpu, rd, round (val));
7156 case 2: /* mode M: towards -inf. */
7158 aarch64_set_FP_double (cpu, rd, round (val));
7160 aarch64_set_FP_double (cpu, rd, trunc (val));
7163 case 3: /* mode Z: towards 0. */
7164 aarch64_set_FP_double (cpu, rd, trunc (val));
7167 case 4: /* mode A: away from 0. */
7168 aarch64_set_FP_double (cpu, rd, round (val));
7171 case 6: /* mode X: use FPCR with exactness check. */
7172 case 7: /* mode I: use FPCR mode. */
7180 val = aarch64_get_FP_float (cpu, rs);
7184 case 0: /* mode N: nearest or even. */
7186 float rval = roundf (val);
7188 if (val - rval == 0.5)
7190 if (((rval / 2.0) * 2.0) != rval)
7194 aarch64_set_FP_float (cpu, rd, rval);
7198 case 1: /* mode P: towards +inf. */
7200 aarch64_set_FP_float (cpu, rd, truncf (val));
7202 aarch64_set_FP_float (cpu, rd, roundf (val));
7205 case 2: /* mode M: towards -inf. */
7207 aarch64_set_FP_float (cpu, rd, truncf (val));
7209 aarch64_set_FP_float (cpu, rd, roundf (val));
7212 case 3: /* mode Z: towards 0. */
7213 aarch64_set_FP_float (cpu, rd, truncf (val));
7216 case 4: /* mode A: away from 0. */
7217 aarch64_set_FP_float (cpu, rd, roundf (val));
7220 case 6: /* mode X: use FPCR with exactness check. */
7221 case 7: /* mode I: use FPCR mode. */
7230 dexSimpleFPDataProc1Source (sim_cpu *cpu)
7232 /* instr[31] ==> M : 0 ==> OK, 1 ==> UNALLOC
7234 instr[29] ==> S : 0 ==> OK, 1 ==> UNALLOC
7237 instr[23,22] ==> type : 00 ==> source is single,
7238 01 ==> source is double
7240 11 ==> UNALLOC or source is half
7242 instr[20,15] ==> opcode : with type 00 or 01
7243 000000 ==> FMOV, 000001 ==> FABS,
7244 000010 ==> FNEG, 000011 ==> FSQRT,
7245 000100 ==> UNALLOC, 000101 ==> FCVT,(to single/double)
7246 000110 ==> UNALLOC, 000111 ==> FCVT (to half)
7247 001000 ==> FRINTN, 001001 ==> FRINTP,
7248 001010 ==> FRINTM, 001011 ==> FRINTZ,
7249 001100 ==> FRINTA, 001101 ==> UNALLOC
7250 001110 ==> FRINTX, 001111 ==> FRINTI
7252 000100 ==> FCVT (half-to-single)
7253 000101 ==> FCVT (half-to-double)
7254 instr[14,10] = 10000. */
7256 uint32_t M_S = (uimm (aarch64_get_instr (cpu), 31, 31) << 1)
7257 | uimm (aarch64_get_instr (cpu), 29, 29);
7258 uint32_t type = uimm (aarch64_get_instr (cpu), 23, 22);
7259 uint32_t opcode = uimm (aarch64_get_instr (cpu), 20, 15);
7266 if (opcode == 4 || opcode == 5)
7318 case 8: /* FRINTN etc. */
7328 case 7: /* FCVT double/single to half precision. */
7337 /* 32 bit signed int to float. */
7339 scvtf32 (sim_cpu *cpu)
7341 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
7342 unsigned sd = uimm (aarch64_get_instr (cpu), 4, 0);
7344 aarch64_set_FP_float
7345 (cpu, sd, (float) aarch64_get_reg_s32 (cpu, rn, NO_SP));
7348 /* signed int to float. */
7350 scvtf (sim_cpu *cpu)
7352 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
7353 unsigned sd = uimm (aarch64_get_instr (cpu), 4, 0);
7355 aarch64_set_FP_float
7356 (cpu, sd, (float) aarch64_get_reg_s64 (cpu, rn, NO_SP));
7359 /* 32 bit signed int to double. */
7361 scvtd32 (sim_cpu *cpu)
7363 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
7364 unsigned sd = uimm (aarch64_get_instr (cpu), 4, 0);
7366 aarch64_set_FP_double
7367 (cpu, sd, (double) aarch64_get_reg_s32 (cpu, rn, NO_SP));
7370 /* signed int to double. */
7372 scvtd (sim_cpu *cpu)
7374 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
7375 unsigned sd = uimm (aarch64_get_instr (cpu), 4, 0);
7377 aarch64_set_FP_double
7378 (cpu, sd, (double) aarch64_get_reg_s64 (cpu, rn, NO_SP));
7381 static const float FLOAT_INT_MAX = (float) INT_MAX;
7382 static const float FLOAT_INT_MIN = (float) INT_MIN;
7383 static const double DOUBLE_INT_MAX = (double) INT_MAX;
7384 static const double DOUBLE_INT_MIN = (double) INT_MIN;
7385 static const float FLOAT_LONG_MAX = (float) LONG_MAX;
7386 static const float FLOAT_LONG_MIN = (float) LONG_MIN;
7387 static const double DOUBLE_LONG_MAX = (double) LONG_MAX;
7388 static const double DOUBLE_LONG_MIN = (double) LONG_MIN;
7390 /* Check for FP exception conditions:
7393 Out of Range raises IO and IX and saturates value
7394 Denormal raises ID and IX and sets to zero. */
7395 #define RAISE_EXCEPTIONS(F, VALUE, FTYPE, ITYPE) \
7398 switch (fpclassify (F)) \
7402 aarch64_set_FPSR (cpu, IO); \
7404 VALUE = ITYPE##_MAX; \
7406 VALUE = ITYPE##_MIN; \
7410 if (F >= FTYPE##_##ITYPE##_MAX) \
7412 aarch64_set_FPSR_bits (cpu, IO | IX, IO | IX); \
7413 VALUE = ITYPE##_MAX; \
7415 else if (F <= FTYPE##_##ITYPE##_MIN) \
7417 aarch64_set_FPSR_bits (cpu, IO | IX, IO | IX); \
7418 VALUE = ITYPE##_MIN; \
7422 case FP_SUBNORMAL: \
7423 aarch64_set_FPSR_bits (cpu, IO | IX | ID, IX | ID); \
7435 /* 32 bit convert float to signed int truncate towards zero. */
7437 fcvtszs32 (sim_cpu *cpu)
7439 unsigned sn = uimm (aarch64_get_instr (cpu), 9, 5);
7440 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
7441 /* TODO : check that this rounds toward zero. */
7442 float f = aarch64_get_FP_float (cpu, sn);
7443 int32_t value = (int32_t) f;
7445 RAISE_EXCEPTIONS (f, value, FLOAT, INT);
7447 /* Avoid sign extension to 64 bit. */
7448 aarch64_set_reg_u64 (cpu, rd, NO_SP, (uint32_t) value);
7451 /* 64 bit convert float to signed int truncate towards zero. */
7453 fcvtszs (sim_cpu *cpu)
7455 unsigned sn = uimm (aarch64_get_instr (cpu), 9, 5);
7456 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
7457 float f = aarch64_get_FP_float (cpu, sn);
7458 int64_t value = (int64_t) f;
7460 RAISE_EXCEPTIONS (f, value, FLOAT, LONG);
7462 aarch64_set_reg_s64 (cpu, rd, NO_SP, value);
7465 /* 32 bit convert double to signed int truncate towards zero. */
7467 fcvtszd32 (sim_cpu *cpu)
7469 unsigned sn = uimm (aarch64_get_instr (cpu), 9, 5);
7470 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
7471 /* TODO : check that this rounds toward zero. */
7472 double d = aarch64_get_FP_double (cpu, sn);
7473 int32_t value = (int32_t) d;
7475 RAISE_EXCEPTIONS (d, value, DOUBLE, INT);
7477 /* Avoid sign extension to 64 bit. */
7478 aarch64_set_reg_u64 (cpu, rd, NO_SP, (uint32_t) value);
7481 /* 64 bit convert double to signed int truncate towards zero. */
7483 fcvtszd (sim_cpu *cpu)
7485 unsigned sn = uimm (aarch64_get_instr (cpu), 9, 5);
7486 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
7487 /* TODO : check that this rounds toward zero. */
7488 double d = aarch64_get_FP_double (cpu, sn);
7491 value = (int64_t) d;
7493 RAISE_EXCEPTIONS (d, value, DOUBLE, LONG);
7495 aarch64_set_reg_s64 (cpu, rd, NO_SP, value);
7499 do_fcvtzu (sim_cpu *cpu)
7501 /* instr[31] = size: 32-bit (0), 64-bit (1)
7502 instr[30,23] = 00111100
7503 instr[22] = type: single (0)/ double (1)
7504 instr[21] = enable (0)/disable(1) precision
7505 instr[20,16] = 11001
7506 instr[15,10] = precision
7510 unsigned rs = uimm (aarch64_get_instr (cpu), 9, 5);
7511 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
7513 NYI_assert (30, 23, 0x3C);
7514 NYI_assert (20, 16, 0x19);
7516 if (uimm (aarch64_get_instr (cpu), 21, 21) != 1)
7517 /* Convert to fixed point. */
7520 if (uimm (aarch64_get_instr (cpu), 31, 31))
7522 /* Convert to unsigned 64-bit integer. */
7523 if (uimm (aarch64_get_instr (cpu), 22, 22))
7525 double d = aarch64_get_FP_double (cpu, rs);
7526 uint64_t value = (uint64_t) d;
7528 /* Do not raise an exception if we have reached ULONG_MAX. */
7529 if (value != (1UL << 63))
7530 RAISE_EXCEPTIONS (d, value, DOUBLE, LONG);
7532 aarch64_set_reg_u64 (cpu, rd, NO_SP, value);
7536 float f = aarch64_get_FP_float (cpu, rs);
7537 uint64_t value = (uint64_t) f;
7539 /* Do not raise an exception if we have reached ULONG_MAX. */
7540 if (value != (1UL << 63))
7541 RAISE_EXCEPTIONS (f, value, FLOAT, LONG);
7543 aarch64_set_reg_u64 (cpu, rd, NO_SP, value);
7550 /* Convert to unsigned 32-bit integer. */
7551 if (uimm (aarch64_get_instr (cpu), 22, 22))
7553 double d = aarch64_get_FP_double (cpu, rs);
7555 value = (uint32_t) d;
7556 /* Do not raise an exception if we have reached UINT_MAX. */
7557 if (value != (1UL << 31))
7558 RAISE_EXCEPTIONS (d, value, DOUBLE, INT);
7562 float f = aarch64_get_FP_float (cpu, rs);
7564 value = (uint32_t) f;
7565 /* Do not raise an exception if we have reached UINT_MAX. */
7566 if (value != (1UL << 31))
7567 RAISE_EXCEPTIONS (f, value, FLOAT, INT);
7570 aarch64_set_reg_u64 (cpu, rd, NO_SP, value);
7575 do_UCVTF (sim_cpu *cpu)
7577 /* instr[31] = size: 32-bit (0), 64-bit (1)
7578 instr[30,23] = 001 1110 0
7579 instr[22] = type: single (0)/ double (1)
7580 instr[21] = enable (0)/disable(1) precision
7581 instr[20,16] = 0 0011
7582 instr[15,10] = precision
7586 unsigned rs = uimm (aarch64_get_instr (cpu), 9, 5);
7587 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
7589 NYI_assert (30, 23, 0x3C);
7590 NYI_assert (20, 16, 0x03);
7592 if (uimm (aarch64_get_instr (cpu), 21, 21) != 1)
7595 /* FIXME: Add exception raising. */
7596 if (uimm (aarch64_get_instr (cpu), 31, 31))
7598 uint64_t value = aarch64_get_reg_u64 (cpu, rs, NO_SP);
7600 if (uimm (aarch64_get_instr (cpu), 22, 22))
7601 aarch64_set_FP_double (cpu, rd, (double) value);
7603 aarch64_set_FP_float (cpu, rd, (float) value);
7607 uint32_t value = aarch64_get_reg_u32 (cpu, rs, NO_SP);
7609 if (uimm (aarch64_get_instr (cpu), 22, 22))
7610 aarch64_set_FP_double (cpu, rd, (double) value);
7612 aarch64_set_FP_float (cpu, rd, (float) value);
7617 float_vector_move (sim_cpu *cpu)
7619 /* instr[31,17] == 100 1111 0101 0111
7620 instr[16] ==> direction 0=> to GR, 1=> from GR
7622 instr[9,5] ==> source
7623 instr[4,0] ==> dest. */
7625 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
7626 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
7628 NYI_assert (31, 17, 0x4F57);
7630 if (uimm (aarch64_get_instr (cpu), 15, 10) != 0)
7633 if (uimm (aarch64_get_instr (cpu), 16, 16))
7634 aarch64_set_vec_u64 (cpu, rd, 1, aarch64_get_reg_u64 (cpu, rn, NO_SP));
7636 aarch64_set_reg_u64 (cpu, rd, NO_SP, aarch64_get_vec_u64 (cpu, rn, 1));
7640 dexSimpleFPIntegerConvert (sim_cpu *cpu)
7642 /* instr[31] = size : 0 ==> 32 bit, 1 ==> 64 bit
7644 instr[29] = S : 0 ==> OK, 1 ==> UNALLOC
7647 instr[23,22] = type : 00 ==> single, 01 ==> double, 1x ==> UNALLOC
7649 instr[20,19] = rmode
7650 instr[18,16] = opcode
7651 instr[15,10] = 10 0000 */
7653 uint32_t rmode_opcode;
7659 if (uimm (aarch64_get_instr (cpu), 31, 17) == 0x4F57)
7661 float_vector_move (cpu);
7665 size = uimm (aarch64_get_instr (cpu), 31, 31);
7666 S = uimm (aarch64_get_instr (cpu), 29, 29);
7670 type = uimm (aarch64_get_instr (cpu), 23, 22);
7674 rmode_opcode = uimm (aarch64_get_instr (cpu), 20, 16);
7675 size_type = (size << 1) | type; /* 0==32f, 1==32d, 2==64f, 3==64d. */
7677 switch (rmode_opcode)
7679 case 2: /* SCVTF. */
7682 case 0: scvtf32 (cpu); return;
7683 case 1: scvtd32 (cpu); return;
7684 case 2: scvtf (cpu); return;
7685 case 3: scvtd (cpu); return;
7690 case 6: /* FMOV GR, Vec. */
7693 case 0: gfmovs (cpu); return;
7694 case 3: gfmovd (cpu); return;
7695 default: HALT_UNALLOC;
7698 case 7: /* FMOV vec, GR. */
7701 case 0: fgmovs (cpu); return;
7702 case 3: fgmovd (cpu); return;
7703 default: HALT_UNALLOC;
7706 case 24: /* FCVTZS. */
7709 case 0: fcvtszs32 (cpu); return;
7710 case 1: fcvtszd32 (cpu); return;
7711 case 2: fcvtszs (cpu); return;
7712 case 3: fcvtszd (cpu); return;
7713 default: HALT_UNREACHABLE;
7716 case 25: do_fcvtzu (cpu); return;
7717 case 3: do_UCVTF (cpu); return;
7719 case 0: /* FCVTNS. */
7720 case 1: /* FCVTNU. */
7721 case 4: /* FCVTAS. */
7722 case 5: /* FCVTAU. */
7723 case 8: /* FCVPTS. */
7724 case 9: /* FCVTPU. */
7725 case 16: /* FCVTMS. */
7726 case 17: /* FCVTMU. */
7733 set_flags_for_float_compare (sim_cpu *cpu, float fvalue1, float fvalue2)
7737 if (isnan (fvalue1) || isnan (fvalue2))
7741 float result = fvalue1 - fvalue2;
7745 else if (result < 0)
7747 else /* (result > 0). */
7751 aarch64_set_CPSR (cpu, flags);
7755 fcmps (sim_cpu *cpu)
7757 unsigned sm = uimm (aarch64_get_instr (cpu), 20, 16);
7758 unsigned sn = uimm (aarch64_get_instr (cpu), 9, 5);
7760 float fvalue1 = aarch64_get_FP_float (cpu, sn);
7761 float fvalue2 = aarch64_get_FP_float (cpu, sm);
7763 set_flags_for_float_compare (cpu, fvalue1, fvalue2);
7766 /* Float compare to zero -- Invalid Operation exception
7767 only on signaling NaNs. */
7769 fcmpzs (sim_cpu *cpu)
7771 unsigned sn = uimm (aarch64_get_instr (cpu), 9, 5);
7772 float fvalue1 = aarch64_get_FP_float (cpu, sn);
7774 set_flags_for_float_compare (cpu, fvalue1, 0.0f);
7777 /* Float compare -- Invalid Operation exception on all NaNs. */
7779 fcmpes (sim_cpu *cpu)
7781 unsigned sm = uimm (aarch64_get_instr (cpu), 20, 16);
7782 unsigned sn = uimm (aarch64_get_instr (cpu), 9, 5);
7784 float fvalue1 = aarch64_get_FP_float (cpu, sn);
7785 float fvalue2 = aarch64_get_FP_float (cpu, sm);
7787 set_flags_for_float_compare (cpu, fvalue1, fvalue2);
7790 /* Float compare to zero -- Invalid Operation exception on all NaNs. */
7792 fcmpzes (sim_cpu *cpu)
7794 unsigned sn = uimm (aarch64_get_instr (cpu), 9, 5);
7795 float fvalue1 = aarch64_get_FP_float (cpu, sn);
7797 set_flags_for_float_compare (cpu, fvalue1, 0.0f);
7801 set_flags_for_double_compare (sim_cpu *cpu, double dval1, double dval2)
7805 if (isnan (dval1) || isnan (dval2))
7809 double result = dval1 - dval2;
7813 else if (result < 0)
7815 else /* (result > 0). */
7819 aarch64_set_CPSR (cpu, flags);
7822 /* Double compare -- Invalid Operation exception only on signaling NaNs. */
7824 fcmpd (sim_cpu *cpu)
7826 unsigned sm = uimm (aarch64_get_instr (cpu), 20, 16);
7827 unsigned sn = uimm (aarch64_get_instr (cpu), 9, 5);
7829 double dvalue1 = aarch64_get_FP_double (cpu, sn);
7830 double dvalue2 = aarch64_get_FP_double (cpu, sm);
7832 set_flags_for_double_compare (cpu, dvalue1, dvalue2);
7835 /* Double compare to zero -- Invalid Operation exception
7836 only on signaling NaNs. */
7838 fcmpzd (sim_cpu *cpu)
7840 unsigned sn = uimm (aarch64_get_instr (cpu), 9, 5);
7841 double dvalue1 = aarch64_get_FP_double (cpu, sn);
7843 set_flags_for_double_compare (cpu, dvalue1, 0.0);
7846 /* Double compare -- Invalid Operation exception on all NaNs. */
7848 fcmped (sim_cpu *cpu)
7850 unsigned sm = uimm (aarch64_get_instr (cpu), 20, 16);
7851 unsigned sn = uimm (aarch64_get_instr (cpu), 9, 5);
7853 double dvalue1 = aarch64_get_FP_double (cpu, sn);
7854 double dvalue2 = aarch64_get_FP_double (cpu, sm);
7856 set_flags_for_double_compare (cpu, dvalue1, dvalue2);
7859 /* Double compare to zero -- Invalid Operation exception on all NaNs. */
7861 fcmpzed (sim_cpu *cpu)
7863 unsigned sn = uimm (aarch64_get_instr (cpu), 9, 5);
7864 double dvalue1 = aarch64_get_FP_double (cpu, sn);
7866 set_flags_for_double_compare (cpu, dvalue1, 0.0);
7870 dexSimpleFPCompare (sim_cpu *cpu)
7872 /* assert instr[28,25] == 1111
7873 instr[30:24:21:13,10] = 0011000
7874 instr[31] = M : 0 ==> OK, 1 ==> UNALLOC
7875 instr[29] ==> S : 0 ==> OK, 1 ==> UNALLOC
7876 instr[23,22] ==> type : 0 ==> single, 01 ==> double, 1x ==> UNALLOC
7877 instr[15,14] ==> op : 00 ==> OK, ow ==> UNALLOC
7878 instr[4,0] ==> opcode2 : 00000 ==> FCMP, 10000 ==> FCMPE,
7879 01000 ==> FCMPZ, 11000 ==> FCMPEZ,
7882 uint32_t M_S = (uimm (aarch64_get_instr (cpu), 31, 31) << 1)
7883 | uimm (aarch64_get_instr (cpu), 29, 29);
7884 uint32_t type = uimm (aarch64_get_instr (cpu), 23, 22);
7885 uint32_t op = uimm (aarch64_get_instr (cpu), 15, 14);
7886 uint32_t op2_2_0 = uimm (aarch64_get_instr (cpu), 2, 0);
7900 /* dispatch on type and top 2 bits of opcode. */
7901 dispatch = (type << 2) | uimm (aarch64_get_instr (cpu), 4, 3);
7905 case 0: fcmps (cpu); return;
7906 case 1: fcmpzs (cpu); return;
7907 case 2: fcmpes (cpu); return;
7908 case 3: fcmpzes (cpu); return;
7909 case 4: fcmpd (cpu); return;
7910 case 5: fcmpzd (cpu); return;
7911 case 6: fcmped (cpu); return;
7912 case 7: fcmpzed (cpu); return;
7913 default: HALT_UNREACHABLE;
7918 do_scalar_FADDP (sim_cpu *cpu)
7920 /* instr [31,23] = 011111100
7921 instr [22] = single(0)/double(1)
7922 instr [21,10] = 1100 0011 0110
7924 instr [4,0] = Fd. */
7926 unsigned Fn = uimm (aarch64_get_instr (cpu), 9, 5);
7927 unsigned Fd = uimm (aarch64_get_instr (cpu), 4, 0);
7929 NYI_assert (31, 23, 0x0FC);
7930 NYI_assert (21, 10, 0xC36);
7932 if (uimm (aarch64_get_instr (cpu), 22, 22))
7934 double val1 = aarch64_get_vec_double (cpu, Fn, 0);
7935 double val2 = aarch64_get_vec_double (cpu, Fn, 1);
7937 aarch64_set_FP_double (cpu, Fd, val1 + val2);
7941 float val1 = aarch64_get_vec_float (cpu, Fn, 0);
7942 float val2 = aarch64_get_vec_float (cpu, Fn, 1);
7944 aarch64_set_FP_float (cpu, Fd, val1 + val2);
7948 /* Floating point absolute difference. */
7951 do_scalar_FABD (sim_cpu *cpu)
7953 /* instr [31,23] = 0111 1110 1
7954 instr [22] = float(0)/double(1)
7957 instr [15,10] = 1101 01
7959 instr [4, 0] = Rd. */
7961 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
7962 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
7963 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
7965 NYI_assert (31, 23, 0x0FD);
7966 NYI_assert (21, 21, 1);
7967 NYI_assert (15, 10, 0x35);
7969 if (uimm (aarch64_get_instr (cpu), 22, 22))
7970 aarch64_set_FP_double (cpu, rd,
7971 fabs (aarch64_get_FP_double (cpu, rn)
7972 - aarch64_get_FP_double (cpu, rm)));
7974 aarch64_set_FP_float (cpu, rd,
7975 fabsf (aarch64_get_FP_float (cpu, rn)
7976 - aarch64_get_FP_float (cpu, rm)));
7980 do_scalar_CMGT (sim_cpu *cpu)
7982 /* instr [31,21] = 0101 1110 111
7984 instr [15,10] = 00 1101
7986 instr [4, 0] = Rd. */
7988 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
7989 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
7990 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
7992 NYI_assert (31, 21, 0x2F7);
7993 NYI_assert (15, 10, 0x0D);
7995 aarch64_set_vec_u64 (cpu, rd, 0,
7996 aarch64_get_vec_u64 (cpu, rn, 0) >
7997 aarch64_get_vec_u64 (cpu, rm, 0) ? -1L : 0L);
8001 do_scalar_USHR (sim_cpu *cpu)
8003 /* instr [31,23] = 0111 1111 0
8004 instr [22,16] = shift amount
8005 instr [15,10] = 0000 01
8007 instr [4, 0] = Rd. */
8009 unsigned amount = 128 - uimm (aarch64_get_instr (cpu), 22, 16);
8010 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
8011 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
8013 NYI_assert (31, 23, 0x0FE);
8014 NYI_assert (15, 10, 0x01);
8016 aarch64_set_vec_u64 (cpu, rd, 0,
8017 aarch64_get_vec_u64 (cpu, rn, 0) >> amount);
8021 do_scalar_SHL (sim_cpu *cpu)
8023 /* instr [31,23] = 0111 1101 0
8024 instr [22,16] = shift amount
8025 instr [15,10] = 0101 01
8027 instr [4, 0] = Rd. */
8029 unsigned amount = uimm (aarch64_get_instr (cpu), 22, 16) - 64;
8030 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
8031 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
8033 NYI_assert (31, 23, 0x0BE);
8034 NYI_assert (15, 10, 0x15);
8036 if (uimm (aarch64_get_instr (cpu), 22, 22) == 0)
8039 aarch64_set_vec_u64 (cpu, rd, 0,
8040 aarch64_get_vec_u64 (cpu, rn, 0) << amount);
8043 /* FCMEQ FCMGT FCMGE. */
8045 do_scalar_FCM (sim_cpu *cpu)
8047 /* instr [31,30] = 01
8049 instr [28,24] = 1 1110
8054 instr [15,12] = 1110
8058 instr [4, 0] = Rd. */
8060 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
8061 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
8062 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
8063 unsigned EUac = (uimm (aarch64_get_instr (cpu), 23, 23) << 2)
8064 | (uimm (aarch64_get_instr (cpu), 29, 29) << 1)
8065 | uimm (aarch64_get_instr (cpu), 11, 11);
8070 NYI_assert (31, 30, 1);
8071 NYI_assert (28, 24, 0x1E);
8072 NYI_assert (21, 21, 1);
8073 NYI_assert (15, 12, 0xE);
8074 NYI_assert (10, 10, 1);
8076 if (uimm (aarch64_get_instr (cpu), 22, 22))
8078 double val1 = aarch64_get_FP_double (cpu, rn);
8079 double val2 = aarch64_get_FP_double (cpu, rm);
8084 result = val1 == val2;
8092 result = val1 >= val2;
8100 result = val1 > val2;
8107 aarch64_set_vec_u32 (cpu, rd, 0, result ? -1 : 0);
8111 val1 = aarch64_get_FP_float (cpu, rn);
8112 val2 = aarch64_get_FP_float (cpu, rm);
8117 result = val1 == val2;
8121 val1 = fabsf (val1);
8122 val2 = fabsf (val2);
8125 result = val1 >= val2;
8129 val1 = fabsf (val1);
8130 val2 = fabsf (val2);
8133 result = val1 > val2;
8140 aarch64_set_vec_u32 (cpu, rd, 0, result ? -1 : 0);
8143 /* An alias of DUP. */
8145 do_scalar_MOV (sim_cpu *cpu)
8147 /* instr [31,21] = 0101 1110 000
8148 instr [20,16] = imm5
8149 instr [15,10] = 0000 01
8151 instr [4, 0] = Rd. */
8153 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
8154 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
8157 NYI_assert (31, 21, 0x2F0);
8158 NYI_assert (15, 10, 0x01);
8160 if (uimm (aarch64_get_instr (cpu), 16, 16))
8163 index = uimm (aarch64_get_instr (cpu), 20, 17);
8165 (cpu, rd, 0, aarch64_get_vec_u8 (cpu, rn, index));
8167 else if (uimm (aarch64_get_instr (cpu), 17, 17))
8170 index = uimm (aarch64_get_instr (cpu), 20, 18);
8172 (cpu, rd, 0, aarch64_get_vec_u16 (cpu, rn, index));
8174 else if (uimm (aarch64_get_instr (cpu), 18, 18))
8177 index = uimm (aarch64_get_instr (cpu), 20, 19);
8179 (cpu, rd, 0, aarch64_get_vec_u32 (cpu, rn, index));
8181 else if (uimm (aarch64_get_instr (cpu), 19, 19))
8184 index = uimm (aarch64_get_instr (cpu), 20, 20);
8186 (cpu, rd, 0, aarch64_get_vec_u64 (cpu, rn, index));
8193 do_double_add (sim_cpu *cpu)
8195 /* instr [28,25] = 1111. */
8202 switch (uimm (aarch64_get_instr (cpu), 31, 23))
8205 switch (uimm (aarch64_get_instr (cpu), 15, 10))
8207 case 0x01: do_scalar_MOV (cpu); return;
8208 case 0x39: do_scalar_FCM (cpu); return;
8209 case 0x3B: do_scalar_FCM (cpu); return;
8213 case 0xBE: do_scalar_SHL (cpu); return;
8216 switch (uimm (aarch64_get_instr (cpu), 15, 10))
8218 case 0x36: do_scalar_FADDP (cpu); return;
8219 case 0x39: do_scalar_FCM (cpu); return;
8220 case 0x3B: do_scalar_FCM (cpu); return;
8225 switch (uimm (aarch64_get_instr (cpu), 15, 10))
8227 case 0x0D: do_scalar_CMGT (cpu); return;
8228 case 0x35: do_scalar_FABD (cpu); return;
8229 case 0x39: do_scalar_FCM (cpu); return;
8230 case 0x3B: do_scalar_FCM (cpu); return;
8235 case 0xFE: do_scalar_USHR (cpu); return;
8240 /* instr [31,21] = 0101 1110 111
8242 instr [15,10] = 1000 01
8244 instr [4,0] = Fd. */
8245 if (uimm (aarch64_get_instr (cpu), 31, 21) != 0x2F7
8246 || uimm (aarch64_get_instr (cpu), 15, 10) != 0x21)
8249 Fd = uimm (aarch64_get_instr (cpu), 4, 0);
8250 Fm = uimm (aarch64_get_instr (cpu), 9, 5);
8251 Fn = uimm (aarch64_get_instr (cpu), 20, 16);
8253 val1 = aarch64_get_FP_double (cpu, Fm);
8254 val2 = aarch64_get_FP_double (cpu, Fn);
8256 aarch64_set_FP_double (cpu, Fd, val1 + val2);
8260 dexAdvSIMD1 (sim_cpu *cpu)
8262 /* instr [28,25] = 1 111. */
8264 /* we are currently only interested in the basic
8265 scalar fp routines which all have bit 30 = 0. */
8266 if (uimm (aarch64_get_instr (cpu), 30, 30))
8267 do_double_add (cpu);
8269 /* instr[24] is set for FP data processing 3-source and clear for
8270 all other basic scalar fp instruction groups. */
8271 else if (uimm (aarch64_get_instr (cpu), 24, 24))
8272 dexSimpleFPDataProc3Source (cpu);
8274 /* instr[21] is clear for floating <-> fixed conversions and set for
8275 all other basic scalar fp instruction groups. */
8276 else if (!uimm (aarch64_get_instr (cpu), 21, 21))
8277 dexSimpleFPFixedConvert (cpu);
8279 /* instr[11,10] : 01 ==> cond compare, 10 ==> Data Proc 2 Source
8280 11 ==> cond select, 00 ==> other. */
8282 switch (uimm (aarch64_get_instr (cpu), 11, 10))
8284 case 1: dexSimpleFPCondCompare (cpu); return;
8285 case 2: dexSimpleFPDataProc2Source (cpu); return;
8286 case 3: dexSimpleFPCondSelect (cpu); return;
8289 /* Now an ordered cascade of tests.
8290 FP immediate has aarch64_get_instr (cpu)[12] == 1.
8291 FP compare has aarch64_get_instr (cpu)[13] == 1.
8292 FP Data Proc 1 Source has aarch64_get_instr (cpu)[14] == 1.
8293 FP floating <--> integer conversions has aarch64_get_instr (cpu)[15] == 0. */
8294 if (uimm (aarch64_get_instr (cpu), 12, 12))
8295 dexSimpleFPImmediate (cpu);
8297 else if (uimm (aarch64_get_instr (cpu), 13, 13))
8298 dexSimpleFPCompare (cpu);
8300 else if (uimm (aarch64_get_instr (cpu), 14, 14))
8301 dexSimpleFPDataProc1Source (cpu);
8303 else if (!uimm (aarch64_get_instr (cpu), 15, 15))
8304 dexSimpleFPIntegerConvert (cpu);
8307 /* If we get here then instr[15] == 1 which means UNALLOC. */
8312 /* PC relative addressing. */
8315 pcadr (sim_cpu *cpu)
8317 /* instr[31] = op : 0 ==> ADR, 1 ==> ADRP
8318 instr[30,29] = immlo
8319 instr[23,5] = immhi. */
8321 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
8322 uint32_t isPage = uimm (aarch64_get_instr (cpu), 31, 31);
8323 union { int64_t u64; uint64_t s64; } imm;
8326 imm.s64 = simm64 (aarch64_get_instr (cpu), 23, 5);
8328 offset = (offset << 2) | uimm (aarch64_get_instr (cpu), 30, 29);
8330 address = aarch64_get_PC (cpu);
8338 aarch64_set_reg_u64 (cpu, rd, NO_SP, address + offset);
8341 /* Specific decode and execute for group Data Processing Immediate. */
8344 dexPCRelAddressing (sim_cpu *cpu)
8346 /* assert instr[28,24] = 10000. */
8350 /* Immediate logical.
8351 The bimm32/64 argument is constructed by replicating a 2, 4, 8,
8352 16, 32 or 64 bit sequence pulled out at decode and possibly
8355 N.B. the output register (dest) can normally be Xn or SP
8356 the exception occurs for flag setting instructions which may
8357 only use Xn for the output (dest). The input register can
8360 /* 32 bit and immediate. */
8362 and32 (sim_cpu *cpu, uint32_t bimm)
8364 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
8365 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
8367 aarch64_set_reg_u64 (cpu, rd, SP_OK,
8368 aarch64_get_reg_u32 (cpu, rn, NO_SP) & bimm);
8371 /* 64 bit and immediate. */
8373 and64 (sim_cpu *cpu, uint64_t bimm)
8375 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
8376 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
8378 aarch64_set_reg_u64 (cpu, rd, SP_OK,
8379 aarch64_get_reg_u64 (cpu, rn, NO_SP) & bimm);
8382 /* 32 bit and immediate set flags. */
8384 ands32 (sim_cpu *cpu, uint32_t bimm)
8386 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
8387 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
8389 uint32_t value1 = aarch64_get_reg_u32 (cpu, rn, NO_SP);
8390 uint32_t value2 = bimm;
8392 aarch64_set_reg_u64 (cpu, rd, NO_SP, value1 & value2);
8393 set_flags_for_binop32 (cpu, value1 & value2);
8396 /* 64 bit and immediate set flags. */
8398 ands64 (sim_cpu *cpu, uint64_t bimm)
8400 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
8401 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
8403 uint64_t value1 = aarch64_get_reg_u64 (cpu, rn, NO_SP);
8404 uint64_t value2 = bimm;
8406 aarch64_set_reg_u64 (cpu, rd, NO_SP, value1 & value2);
8407 set_flags_for_binop64 (cpu, value1 & value2);
8410 /* 32 bit exclusive or immediate. */
8412 eor32 (sim_cpu *cpu, uint32_t bimm)
8414 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
8415 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
8417 aarch64_set_reg_u64 (cpu, rd, SP_OK,
8418 aarch64_get_reg_u32 (cpu, rn, NO_SP) ^ bimm);
8421 /* 64 bit exclusive or immediate. */
8423 eor64 (sim_cpu *cpu, uint64_t bimm)
8425 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
8426 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
8428 aarch64_set_reg_u64 (cpu, rd, SP_OK,
8429 aarch64_get_reg_u64 (cpu, rn, NO_SP) ^ bimm);
8432 /* 32 bit or immediate. */
8434 orr32 (sim_cpu *cpu, uint32_t bimm)
8436 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
8437 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
8439 aarch64_set_reg_u64 (cpu, rd, SP_OK,
8440 aarch64_get_reg_u32 (cpu, rn, NO_SP) | bimm);
8443 /* 64 bit or immediate. */
8445 orr64 (sim_cpu *cpu, uint64_t bimm)
8447 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
8448 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
8450 aarch64_set_reg_u64 (cpu, rd, SP_OK,
8451 aarch64_get_reg_u64 (cpu, rn, NO_SP) | bimm);
8454 /* Logical shifted register.
8455 These allow an optional LSL, ASR, LSR or ROR to the second source
8456 register with a count up to the register bit count.
8457 N.B register args may not be SP. */
8459 /* 32 bit AND shifted register. */
8461 and32_shift (sim_cpu *cpu, Shift shift, uint32_t count)
8463 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
8464 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
8465 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
8468 (cpu, rd, NO_SP, aarch64_get_reg_u32 (cpu, rn, NO_SP)
8469 & shifted32 (aarch64_get_reg_u32 (cpu, rm, NO_SP), shift, count));
8472 /* 64 bit AND shifted register. */
8474 and64_shift (sim_cpu *cpu, Shift shift, uint32_t count)
8476 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
8477 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
8478 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
8481 (cpu, rd, NO_SP, aarch64_get_reg_u64 (cpu, rn, NO_SP)
8482 & shifted64 (aarch64_get_reg_u64 (cpu, rm, NO_SP), shift, count));
8485 /* 32 bit AND shifted register setting flags. */
8487 ands32_shift (sim_cpu *cpu, Shift shift, uint32_t count)
8489 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
8490 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
8491 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
8493 uint32_t value1 = aarch64_get_reg_u32 (cpu, rn, NO_SP);
8494 uint32_t value2 = shifted32 (aarch64_get_reg_u32 (cpu, rm, NO_SP),
8497 aarch64_set_reg_u64 (cpu, rd, NO_SP, value1 & value2);
8498 set_flags_for_binop32 (cpu, value1 & value2);
8501 /* 64 bit AND shifted register setting flags. */
8503 ands64_shift (sim_cpu *cpu, Shift shift, uint32_t count)
8505 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
8506 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
8507 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
8509 uint64_t value1 = aarch64_get_reg_u64 (cpu, rn, NO_SP);
8510 uint64_t value2 = shifted64 (aarch64_get_reg_u64 (cpu, rm, NO_SP),
8513 aarch64_set_reg_u64 (cpu, rd, NO_SP, value1 & value2);
8514 set_flags_for_binop64 (cpu, value1 & value2);
8517 /* 32 bit BIC shifted register. */
8519 bic32_shift (sim_cpu *cpu, Shift shift, uint32_t count)
8521 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
8522 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
8523 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
8526 (cpu, rd, NO_SP, aarch64_get_reg_u32 (cpu, rn, NO_SP)
8527 & ~ shifted32 (aarch64_get_reg_u32 (cpu, rm, NO_SP), shift, count));
8530 /* 64 bit BIC shifted register. */
8532 bic64_shift (sim_cpu *cpu, Shift shift, uint32_t count)
8534 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
8535 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
8536 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
8539 (cpu, rd, NO_SP, aarch64_get_reg_u64 (cpu, rn, NO_SP)
8540 & ~ shifted64 (aarch64_get_reg_u64 (cpu, rm, NO_SP), shift, count));
8543 /* 32 bit BIC shifted register setting flags. */
8545 bics32_shift (sim_cpu *cpu, Shift shift, uint32_t count)
8547 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
8548 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
8549 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
8551 uint32_t value1 = aarch64_get_reg_u32 (cpu, rn, NO_SP);
8552 uint32_t value2 = ~ shifted32 (aarch64_get_reg_u32 (cpu, rm, NO_SP),
8555 aarch64_set_reg_u64 (cpu, rd, NO_SP, value1 & value2);
8556 set_flags_for_binop32 (cpu, value1 & value2);
8559 /* 64 bit BIC shifted register setting flags. */
8561 bics64_shift (sim_cpu *cpu, Shift shift, uint32_t count)
8563 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
8564 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
8565 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
8567 uint64_t value1 = aarch64_get_reg_u64 (cpu, rn, NO_SP);
8568 uint64_t value2 = ~ shifted64 (aarch64_get_reg_u64 (cpu, rm, NO_SP),
8571 aarch64_set_reg_u64 (cpu, rd, NO_SP, value1 & value2);
8572 set_flags_for_binop64 (cpu, value1 & value2);
8575 /* 32 bit EON shifted register. */
8577 eon32_shift (sim_cpu *cpu, Shift shift, uint32_t count)
8579 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
8580 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
8581 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
8584 (cpu, rd, NO_SP, aarch64_get_reg_u32 (cpu, rn, NO_SP)
8585 ^ ~ shifted32 (aarch64_get_reg_u32 (cpu, rm, NO_SP), shift, count));
8588 /* 64 bit EON shifted register. */
8590 eon64_shift (sim_cpu *cpu, Shift shift, uint32_t count)
8592 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
8593 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
8594 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
8597 (cpu, rd, NO_SP, aarch64_get_reg_u64 (cpu, rn, NO_SP)
8598 ^ ~ shifted64 (aarch64_get_reg_u64 (cpu, rm, NO_SP), shift, count));
8601 /* 32 bit EOR shifted register. */
8603 eor32_shift (sim_cpu *cpu, Shift shift, uint32_t count)
8605 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
8606 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
8607 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
8610 (cpu, rd, NO_SP, aarch64_get_reg_u32 (cpu, rn, NO_SP)
8611 ^ shifted32 (aarch64_get_reg_u32 (cpu, rm, NO_SP), shift, count));
8614 /* 64 bit EOR shifted register. */
8616 eor64_shift (sim_cpu *cpu, Shift shift, uint32_t count)
8618 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
8619 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
8620 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
8623 (cpu, rd, NO_SP, aarch64_get_reg_u64 (cpu, rn, NO_SP)
8624 ^ shifted64 (aarch64_get_reg_u64 (cpu, rm, NO_SP), shift, count));
8627 /* 32 bit ORR shifted register. */
8629 orr32_shift (sim_cpu *cpu, Shift shift, uint32_t count)
8631 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
8632 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
8633 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
8636 (cpu, rd, NO_SP, aarch64_get_reg_u32 (cpu, rn, NO_SP)
8637 | shifted32 (aarch64_get_reg_u32 (cpu, rm, NO_SP), shift, count));
8640 /* 64 bit ORR shifted register. */
8642 orr64_shift (sim_cpu *cpu, Shift shift, uint32_t count)
8644 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
8645 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
8646 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
8649 (cpu, rd, NO_SP, aarch64_get_reg_u64 (cpu, rn, NO_SP)
8650 | shifted64 (aarch64_get_reg_u64 (cpu, rm, NO_SP), shift, count));
8653 /* 32 bit ORN shifted register. */
8655 orn32_shift (sim_cpu *cpu, Shift shift, uint32_t count)
8657 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
8658 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
8659 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
8662 (cpu, rd, NO_SP, aarch64_get_reg_u32 (cpu, rn, NO_SP)
8663 | ~ shifted32 (aarch64_get_reg_u32 (cpu, rm, NO_SP), shift, count));
8666 /* 64 bit ORN shifted register. */
8668 orn64_shift (sim_cpu *cpu, Shift shift, uint32_t count)
8670 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
8671 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
8672 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
8675 (cpu, rd, NO_SP, aarch64_get_reg_u64 (cpu, rn, NO_SP)
8676 | ~ shifted64 (aarch64_get_reg_u64 (cpu, rm, NO_SP), shift, count));
8680 dexLogicalImmediate (sim_cpu *cpu)
8682 /* assert instr[28,23] = 1001000
8683 instr[31] = size : 0 ==> 32 bit, 1 ==> 64 bit
8684 instr[30,29] = op : 0 ==> AND, 1 ==> ORR, 2 ==> EOR, 3 ==> ANDS
8685 instr[22] = N : used to construct immediate mask
8691 /* 32 bit operations must have N = 0 or else we have an UNALLOC. */
8692 uint32_t size = uimm (aarch64_get_instr (cpu), 31, 31);
8693 uint32_t N = uimm (aarch64_get_instr (cpu), 22, 22);
8694 /* uint32_t immr = uimm (aarch64_get_instr (cpu), 21, 16);. */
8695 /* uint32_t imms = uimm (aarch64_get_instr (cpu), 15, 10);. */
8696 uint32_t index = uimm (aarch64_get_instr (cpu), 22, 10);
8697 uint64_t bimm64 = LITable [index];
8698 uint32_t dispatch = uimm (aarch64_get_instr (cpu), 30, 29);
8708 uint32_t bimm = (uint32_t) bimm64;
8712 case 0: and32 (cpu, bimm); return;
8713 case 1: orr32 (cpu, bimm); return;
8714 case 2: eor32 (cpu, bimm); return;
8715 case 3: ands32 (cpu, bimm); return;
8722 case 0: and64 (cpu, bimm64); return;
8723 case 1: orr64 (cpu, bimm64); return;
8724 case 2: eor64 (cpu, bimm64); return;
8725 case 3: ands64 (cpu, bimm64); return;
8732 The uimm argument is a 16 bit value to be inserted into the
8733 target register the pos argument locates the 16 bit word in the
8734 dest register i.e. it is in {0, 1} for 32 bit and {0, 1, 2,
8736 N.B register arg may not be SP so it should be.
8737 accessed using the setGZRegisterXXX accessors. */
8739 /* 32 bit move 16 bit immediate zero remaining shorts. */
8741 movz32 (sim_cpu *cpu, uint32_t val, uint32_t pos)
8743 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
8745 aarch64_set_reg_u64 (cpu, rd, NO_SP, val << (pos * 16));
8748 /* 64 bit move 16 bit immediate zero remaining shorts. */
8750 movz64 (sim_cpu *cpu, uint32_t val, uint32_t pos)
8752 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
8754 aarch64_set_reg_u64 (cpu, rd, NO_SP, ((uint64_t) val) << (pos * 16));
8757 /* 32 bit move 16 bit immediate negated. */
8759 movn32 (sim_cpu *cpu, uint32_t val, uint32_t pos)
8761 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
8763 aarch64_set_reg_u64 (cpu, rd, NO_SP, ((val << (pos * 16)) ^ 0xffffffffU));
8766 /* 64 bit move 16 bit immediate negated. */
8768 movn64 (sim_cpu *cpu, uint32_t val, uint32_t pos)
8770 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
8773 (cpu, rd, NO_SP, ((((uint64_t) val) << (pos * 16))
8774 ^ 0xffffffffffffffffULL));
8777 /* 32 bit move 16 bit immediate keep remaining shorts. */
8779 movk32 (sim_cpu *cpu, uint32_t val, uint32_t pos)
8781 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
8782 uint32_t current = aarch64_get_reg_u32 (cpu, rd, NO_SP);
8783 uint32_t value = val << (pos * 16);
8784 uint32_t mask = ~(0xffffU << (pos * 16));
8786 aarch64_set_reg_u64 (cpu, rd, NO_SP, (value | (current & mask)));
8789 /* 64 bit move 16 it immediate keep remaining shorts. */
8791 movk64 (sim_cpu *cpu, uint32_t val, uint32_t pos)
8793 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
8794 uint64_t current = aarch64_get_reg_u64 (cpu, rd, NO_SP);
8795 uint64_t value = (uint64_t) val << (pos * 16);
8796 uint64_t mask = ~(0xffffULL << (pos * 16));
8798 aarch64_set_reg_u64 (cpu, rd, NO_SP, (value | (current & mask)));
8802 dexMoveWideImmediate (sim_cpu *cpu)
8804 /* assert instr[28:23] = 100101
8805 instr[31] = size : 0 ==> 32 bit, 1 ==> 64 bit
8806 instr[30,29] = op : 0 ==> MOVN, 1 ==> UNALLOC, 2 ==> MOVZ, 3 ==> MOVK
8807 instr[22,21] = shift : 00 == LSL#0, 01 = LSL#16, 10 = LSL#32, 11 = LSL#48
8808 instr[20,5] = uimm16
8811 /* N.B. the (multiple of 16) shift is applied by the called routine,
8812 we just pass the multiplier. */
8815 uint32_t size = uimm (aarch64_get_instr (cpu), 31, 31);
8816 uint32_t op = uimm (aarch64_get_instr (cpu), 30, 29);
8817 uint32_t shift = uimm (aarch64_get_instr (cpu), 22, 21);
8819 /* 32 bit can only shift 0 or 1 lot of 16.
8820 anything else is an unallocated instruction. */
8821 if (size == 0 && (shift > 1))
8827 imm = uimm (aarch64_get_instr (cpu), 20, 5);
8832 movn32 (cpu, imm, shift);
8834 movz32 (cpu, imm, shift);
8836 movk32 (cpu, imm, shift);
8841 movn64 (cpu, imm, shift);
8843 movz64 (cpu, imm, shift);
8845 movk64 (cpu, imm, shift);
8849 /* Bitfield operations.
8850 These take a pair of bit positions r and s which are in {0..31}
8851 or {0..63} depending on the instruction word size.
8852 N.B register args may not be SP. */
8854 /* OK, we start with ubfm which just needs to pick
8855 some bits out of source zero the rest and write
8856 the result to dest. Just need two logical shifts. */
8858 /* 32 bit bitfield move, left and right of affected zeroed
8859 if r <= s Wd<s-r:0> = Wn<s:r> else Wd<32+s-r,32-r> = Wn<s:0>. */
8861 ubfm32 (sim_cpu *cpu, uint32_t r, uint32_t s)
8864 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
8865 uint32_t value = aarch64_get_reg_u32 (cpu, rn, NO_SP);
8867 /* Pick either s+1-r or s+1 consecutive bits out of the original word. */
8870 /* 31:...:s:xxx:r:...:0 ==> 31:...:s-r:xxx:0.
8871 We want only bits s:xxx:r at the bottom of the word
8872 so we LSL bit s up to bit 31 i.e. by 31 - s
8873 and then we LSR to bring bit 31 down to bit s - r
8874 i.e. by 31 + r - s. */
8876 value >>= 31 + r - s;
8880 /* 31:...:s:xxx:0 ==> 31:...:31-(r-1)+s:xxx:31-(r-1):...:0
8881 We want only bits s:xxx:0 starting at it 31-(r-1)
8882 so we LSL bit s up to bit 31 i.e. by 31 - s
8883 and then we LSL to bring bit 31 down to 31-(r-1)+s
8884 i.e. by r - (s + 1). */
8886 value >>= r - (s + 1);
8889 rd = uimm (aarch64_get_instr (cpu), 4, 0);
8890 aarch64_set_reg_u64 (cpu, rd, NO_SP, value);
8893 /* 64 bit bitfield move, left and right of affected zeroed
8894 if r <= s Wd<s-r:0> = Wn<s:r> else Wd<64+s-r,64-r> = Wn<s:0>. */
8896 ubfm (sim_cpu *cpu, uint32_t r, uint32_t s)
8899 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
8900 uint64_t value = aarch64_get_reg_u64 (cpu, rn, NO_SP);
8904 /* 63:...:s:xxx:r:...:0 ==> 63:...:s-r:xxx:0.
8905 We want only bits s:xxx:r at the bottom of the word.
8906 So we LSL bit s up to bit 63 i.e. by 63 - s
8907 and then we LSR to bring bit 63 down to bit s - r
8908 i.e. by 63 + r - s. */
8910 value >>= 63 + r - s;
8914 /* 63:...:s:xxx:0 ==> 63:...:63-(r-1)+s:xxx:63-(r-1):...:0.
8915 We want only bits s:xxx:0 starting at it 63-(r-1).
8916 So we LSL bit s up to bit 63 i.e. by 63 - s
8917 and then we LSL to bring bit 63 down to 63-(r-1)+s
8918 i.e. by r - (s + 1). */
8920 value >>= r - (s + 1);
8923 rd = uimm (aarch64_get_instr (cpu), 4, 0);
8924 aarch64_set_reg_u64 (cpu, rd, NO_SP, value);
8927 /* The signed versions need to insert sign bits
8928 on the left of the inserted bit field. so we do
8929 much the same as the unsigned version except we
8930 use an arithmetic shift right -- this just means
8931 we need to operate on signed values. */
8933 /* 32 bit bitfield move, left of affected sign-extended, right zeroed. */
8934 /* If r <= s Wd<s-r:0> = Wn<s:r> else Wd<32+s-r,32-r> = Wn<s:0>. */
8936 sbfm32 (sim_cpu *cpu, uint32_t r, uint32_t s)
8939 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
8940 /* as per ubfm32 but use an ASR instead of an LSR. */
8941 int32_t value = aarch64_get_reg_s32 (cpu, rn, NO_SP);
8946 value >>= 31 + r - s;
8951 value >>= r - (s + 1);
8954 rd = uimm (aarch64_get_instr (cpu), 4, 0);
8955 aarch64_set_reg_u64 (cpu, rd, NO_SP, (uint32_t) value);
8958 /* 64 bit bitfield move, left of affected sign-extended, right zeroed. */
8959 /* If r <= s Wd<s-r:0> = Wn<s:r> else Wd<64+s-r,64-r> = Wn<s:0>. */
8961 sbfm (sim_cpu *cpu, uint32_t r, uint32_t s)
8964 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
8965 /* acpu per ubfm but use an ASR instead of an LSR. */
8966 int64_t value = aarch64_get_reg_s64 (cpu, rn, NO_SP);
8971 value >>= 63 + r - s;
8976 value >>= r - (s + 1);
8979 rd = uimm (aarch64_get_instr (cpu), 4, 0);
8980 aarch64_set_reg_s64 (cpu, rd, NO_SP, value);
8983 /* Finally, these versions leave non-affected bits
8984 as is. so we need to generate the bits as per
8985 ubfm and also generate a mask to pick the
8986 bits from the original and computed values. */
8988 /* 32 bit bitfield move, non-affected bits left as is.
8989 If r <= s Wd<s-r:0> = Wn<s:r> else Wd<32+s-r,32-r> = Wn<s:0>. */
8991 bfm32 (sim_cpu *cpu, uint32_t r, uint32_t s)
8993 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
8994 uint32_t value = aarch64_get_reg_u32 (cpu, rn, NO_SP);
8999 /* Pick either s+1-r or s+1 consecutive bits out of the original word. */
9002 /* 31:...:s:xxx:r:...:0 ==> 31:...:s-r:xxx:0.
9003 We want only bits s:xxx:r at the bottom of the word
9004 so we LSL bit s up to bit 31 i.e. by 31 - s
9005 and then we LSR to bring bit 31 down to bit s - r
9006 i.e. by 31 + r - s. */
9008 value >>= 31 + r - s;
9009 /* the mask must include the same bits. */
9011 mask >>= 31 + r - s;
9015 /* 31:...:s:xxx:0 ==> 31:...:31-(r-1)+s:xxx:31-(r-1):...:0.
9016 We want only bits s:xxx:0 starting at it 31-(r-1)
9017 so we LSL bit s up to bit 31 i.e. by 31 - s
9018 and then we LSL to bring bit 31 down to 31-(r-1)+s
9019 i.e. by r - (s + 1). */
9021 value >>= r - (s + 1);
9022 /* The mask must include the same bits. */
9024 mask >>= r - (s + 1);
9027 rd = uimm (aarch64_get_instr (cpu), 4, 0);
9028 value2 = aarch64_get_reg_u32 (cpu, rd, NO_SP);
9034 (cpu, rd, NO_SP, (aarch64_get_reg_u32 (cpu, rd, NO_SP) & ~mask) | value);
9037 /* 64 bit bitfield move, non-affected bits left as is.
9038 If r <= s Wd<s-r:0> = Wn<s:r> else Wd<64+s-r,64-r> = Wn<s:0>. */
9040 bfm (sim_cpu *cpu, uint32_t r, uint32_t s)
9043 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
9044 uint64_t value = aarch64_get_reg_u64 (cpu, rn, NO_SP);
9045 uint64_t mask = 0xffffffffffffffffULL;
9049 /* 63:...:s:xxx:r:...:0 ==> 63:...:s-r:xxx:0.
9050 We want only bits s:xxx:r at the bottom of the word
9051 so we LSL bit s up to bit 63 i.e. by 63 - s
9052 and then we LSR to bring bit 63 down to bit s - r
9053 i.e. by 63 + r - s. */
9055 value >>= 63 + r - s;
9056 /* The mask must include the same bits. */
9058 mask >>= 63 + r - s;
9062 /* 63:...:s:xxx:0 ==> 63:...:63-(r-1)+s:xxx:63-(r-1):...:0
9063 We want only bits s:xxx:0 starting at it 63-(r-1)
9064 so we LSL bit s up to bit 63 i.e. by 63 - s
9065 and then we LSL to bring bit 63 down to 63-(r-1)+s
9066 i.e. by r - (s + 1). */
9068 value >>= r - (s + 1);
9069 /* The mask must include the same bits. */
9071 mask >>= r - (s + 1);
9074 rd = uimm (aarch64_get_instr (cpu), 4, 0);
9076 (cpu, rd, NO_SP, (aarch64_get_reg_u64 (cpu, rd, NO_SP) & ~mask) | value);
9080 dexBitfieldImmediate (sim_cpu *cpu)
9082 /* assert instr[28:23] = 100110
9083 instr[31] = size : 0 ==> 32 bit, 1 ==> 64 bit
9084 instr[30,29] = op : 0 ==> SBFM, 1 ==> BFM, 2 ==> UBFM, 3 ==> UNALLOC
9085 instr[22] = N : must be 0 for 32 bit, 1 for 64 bit ow UNALLOC
9086 instr[21,16] = immr : 0xxxxx for 32 bit, xxxxxx for 64 bit
9087 instr[15,10] = imms : 0xxxxx for 32 bit, xxxxxx for 64 bit
9091 /* 32 bit operations must have N = 0 or else we have an UNALLOC. */
9094 uint32_t size = uimm (aarch64_get_instr (cpu), 31, 31);
9095 uint32_t N = uimm (aarch64_get_instr (cpu), 22, 22);
9096 /* 32 bit operations must have immr[5] = 0 and imms[5] = 0. */
9097 /* or else we have an UNALLOC. */
9098 uint32_t immr = uimm (aarch64_get_instr (cpu), 21, 16);
9103 if (!size && uimm (immr, 5, 5))
9106 imms = uimm (aarch64_get_instr (cpu), 15, 10);
9107 if (!size && uimm (imms, 5, 5))
9110 /* Switch on combined size and op. */
9111 dispatch = uimm (aarch64_get_instr (cpu), 31, 29);
9114 case 0: sbfm32 (cpu, immr, imms); return;
9115 case 1: bfm32 (cpu, immr, imms); return;
9116 case 2: ubfm32 (cpu, immr, imms); return;
9117 case 4: sbfm (cpu, immr, imms); return;
9118 case 5: bfm (cpu, immr, imms); return;
9119 case 6: ubfm (cpu, immr, imms); return;
9120 default: HALT_UNALLOC;
9125 do_EXTR_32 (sim_cpu *cpu)
9127 /* instr[31:21] = 00010011100
9129 instr[15,10] = imms : 0xxxxx for 32 bit
9132 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
9133 unsigned imms = uimm (aarch64_get_instr (cpu), 15, 10) & 31;
9134 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
9135 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
9139 val1 = aarch64_get_reg_u32 (cpu, rm, NO_SP);
9141 val2 = aarch64_get_reg_u32 (cpu, rn, NO_SP);
9142 val2 <<= (32 - imms);
9144 aarch64_set_reg_u64 (cpu, rd, NO_SP, val1 | val2);
9148 do_EXTR_64 (sim_cpu *cpu)
9150 /* instr[31:21] = 10010011100
9155 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
9156 unsigned imms = uimm (aarch64_get_instr (cpu), 15, 10) & 63;
9157 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
9158 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
9161 val = aarch64_get_reg_u64 (cpu, rm, NO_SP);
9163 val |= (aarch64_get_reg_u64 (cpu, rn, NO_SP) << (64 - imms));
9165 aarch64_set_reg_u64 (cpu, rd, NO_SP, val);
9169 dexExtractImmediate (sim_cpu *cpu)
9171 /* assert instr[28:23] = 100111
9172 instr[31] = size : 0 ==> 32 bit, 1 ==> 64 bit
9173 instr[30,29] = op21 : 0 ==> EXTR, 1,2,3 ==> UNALLOC
9174 instr[22] = N : must be 0 for 32 bit, 1 for 64 bit or UNALLOC
9175 instr[21] = op0 : must be 0 or UNALLOC
9177 instr[15,10] = imms : 0xxxxx for 32 bit, xxxxxx for 64 bit
9181 /* 32 bit operations must have N = 0 or else we have an UNALLOC. */
9182 /* 64 bit operations must have N = 1 or else we have an UNALLOC. */
9184 uint32_t size = uimm (aarch64_get_instr (cpu), 31, 31);
9185 uint32_t N = uimm (aarch64_get_instr (cpu), 22, 22);
9186 /* 32 bit operations must have imms[5] = 0
9187 or else we have an UNALLOC. */
9188 uint32_t imms = uimm (aarch64_get_instr (cpu), 15, 10);
9193 if (!size && uimm (imms, 5, 5))
9196 /* Switch on combined size and op. */
9197 dispatch = uimm (aarch64_get_instr (cpu), 31, 29);
9202 else if (dispatch == 4)
9205 else if (dispatch == 1)
9212 dexDPImm (sim_cpu *cpu)
9214 /* uint32_t group = dispatchGroup (aarch64_get_instr (cpu));
9215 assert group == GROUP_DPIMM_1000 || grpoup == GROUP_DPIMM_1001
9216 bits [25,23] of a DPImm are the secondary dispatch vector. */
9217 uint32_t group2 = dispatchDPImm (aarch64_get_instr (cpu));
9221 case DPIMM_PCADR_000:
9222 case DPIMM_PCADR_001:
9223 dexPCRelAddressing (cpu);
9226 case DPIMM_ADDSUB_010:
9227 case DPIMM_ADDSUB_011:
9228 dexAddSubtractImmediate (cpu);
9232 dexLogicalImmediate (cpu);
9236 dexMoveWideImmediate (cpu);
9239 case DPIMM_BITF_110:
9240 dexBitfieldImmediate (cpu);
9243 case DPIMM_EXTR_111:
9244 dexExtractImmediate (cpu);
9248 /* Should never reach here. */
9254 dexLoadUnscaledImmediate (sim_cpu *cpu)
9256 /* instr[29,24] == 111_00
9262 instr[20,12] = simm9
9263 instr[9,5] = rn may be SP. */
9264 /* unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0); */
9265 uint32_t V = uimm (aarch64_get_instr (cpu), 26, 26);
9266 uint32_t dispatch = ( (uimm (aarch64_get_instr (cpu), 31, 30) << 2)
9267 | uimm (aarch64_get_instr (cpu), 23, 22));
9268 int32_t imm = simm32 (aarch64_get_instr (cpu), 20, 12);
9272 /* GReg operations. */
9275 case 0: sturb (cpu, imm); return;
9276 case 1: ldurb32 (cpu, imm); return;
9277 case 2: ldursb64 (cpu, imm); return;
9278 case 3: ldursb32 (cpu, imm); return;
9279 case 4: sturh (cpu, imm); return;
9280 case 5: ldurh32 (cpu, imm); return;
9281 case 6: ldursh64 (cpu, imm); return;
9282 case 7: ldursh32 (cpu, imm); return;
9283 case 8: stur32 (cpu, imm); return;
9284 case 9: ldur32 (cpu, imm); return;
9285 case 10: ldursw (cpu, imm); return;
9286 case 12: stur64 (cpu, imm); return;
9287 case 13: ldur64 (cpu, imm); return;
9300 /* FReg operations. */
9303 case 2: fsturq (cpu, imm); return;
9304 case 3: fldurq (cpu, imm); return;
9305 case 8: fsturs (cpu, imm); return;
9306 case 9: fldurs (cpu, imm); return;
9307 case 12: fsturd (cpu, imm); return;
9308 case 13: fldurd (cpu, imm); return;
9310 case 0: /* STUR 8 bit FP. */
9311 case 1: /* LDUR 8 bit FP. */
9312 case 4: /* STUR 16 bit FP. */
9313 case 5: /* LDUR 8 bit FP. */
9327 /* N.B. A preliminary note regarding all the ldrs<x>32
9330 The signed value loaded by these instructions is cast to unsigned
9331 before being assigned to aarch64_get_reg_u64 (cpu, N) i.e. to the
9332 64 bit element of the GReg union. this performs a 32 bit sign extension
9333 (as required) but avoids 64 bit sign extension, thus ensuring that the
9334 top half of the register word is zero. this is what the spec demands
9335 when a 32 bit load occurs. */
9337 /* 32 bit load sign-extended byte scaled unsigned 12 bit. */
9339 ldrsb32_abs (sim_cpu *cpu, uint32_t offset)
9341 unsigned int rn = uimm (aarch64_get_instr (cpu), 9, 5);
9342 unsigned int rt = uimm (aarch64_get_instr (cpu), 4, 0);
9344 /* The target register may not be SP but the source may be
9345 there is no scaling required for a byte load. */
9346 uint64_t address = aarch64_get_reg_u64 (cpu, rn, SP_OK) + offset;
9347 aarch64_set_reg_u64 (cpu, rt, NO_SP,
9348 (int64_t) aarch64_get_mem_s8 (cpu, address));
9351 /* 32 bit load sign-extended byte scaled or unscaled zero-
9352 or sign-extended 32-bit register offset. */
9354 ldrsb32_scale_ext (sim_cpu *cpu, Scaling scaling, Extension extension)
9356 unsigned int rm = uimm (aarch64_get_instr (cpu), 20, 16);
9357 unsigned int rn = uimm (aarch64_get_instr (cpu), 9, 5);
9358 unsigned int rt = uimm (aarch64_get_instr (cpu), 4, 0);
9360 /* rn may reference SP, rm and rt must reference ZR. */
9362 uint64_t address = aarch64_get_reg_u64 (cpu, rn, SP_OK);
9363 int64_t displacement = extend (aarch64_get_reg_u32 (cpu, rm, NO_SP),
9366 /* There is no scaling required for a byte load. */
9368 (cpu, rt, NO_SP, (int64_t) aarch64_get_mem_s8 (cpu, address
9372 /* 32 bit load sign-extended byte unscaled signed 9 bit with
9373 pre- or post-writeback. */
9375 ldrsb32_wb (sim_cpu *cpu, int32_t offset, WriteBack wb)
9378 unsigned int rn = uimm (aarch64_get_instr (cpu), 9, 5);
9379 unsigned int rt = uimm (aarch64_get_instr (cpu), 4, 0);
9381 if (rn == rt && wb != NoWriteBack)
9384 address = aarch64_get_reg_u64 (cpu, rn, SP_OK);
9389 aarch64_set_reg_u64 (cpu, rt, NO_SP,
9390 (int64_t) aarch64_get_mem_s8 (cpu, address));
9395 if (wb != NoWriteBack)
9396 aarch64_set_reg_u64 (cpu, rn, NO_SP, address);
9399 /* 8 bit store scaled. */
9401 fstrb_abs (sim_cpu *cpu, uint32_t offset)
9403 unsigned st = uimm (aarch64_get_instr (cpu), 4, 0);
9404 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
9406 aarch64_set_mem_u8 (cpu,
9407 aarch64_get_reg_u64 (cpu, rn, SP_OK) + offset,
9408 aarch64_get_vec_u8 (cpu, st, 0));
9411 /* 8 bit store scaled or unscaled zero- or
9412 sign-extended 8-bit register offset. */
9414 fstrb_scale_ext (sim_cpu *cpu, Scaling scaling, Extension extension)
9416 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
9417 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
9418 unsigned st = uimm (aarch64_get_instr (cpu), 4, 0);
9420 uint64_t address = aarch64_get_reg_u64 (cpu, rn, SP_OK);
9421 int64_t extended = extend (aarch64_get_reg_u32 (cpu, rm, NO_SP),
9423 uint64_t displacement = OPT_SCALE (extended, 32, scaling);
9426 (cpu, address + displacement, aarch64_get_vec_u8 (cpu, st, 0));
9429 /* 16 bit store scaled. */
9431 fstrh_abs (sim_cpu *cpu, uint32_t offset)
9433 unsigned st = uimm (aarch64_get_instr (cpu), 4, 0);
9434 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
9438 aarch64_get_reg_u64 (cpu, rn, SP_OK) + SCALE (offset, 16),
9439 aarch64_get_vec_u16 (cpu, st, 0));
9442 /* 16 bit store scaled or unscaled zero-
9443 or sign-extended 16-bit register offset. */
9445 fstrh_scale_ext (sim_cpu *cpu, Scaling scaling, Extension extension)
9447 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
9448 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
9449 unsigned st = uimm (aarch64_get_instr (cpu), 4, 0);
9451 uint64_t address = aarch64_get_reg_u64 (cpu, rn, SP_OK);
9452 int64_t extended = extend (aarch64_get_reg_u32 (cpu, rm, NO_SP),
9454 uint64_t displacement = OPT_SCALE (extended, 32, scaling);
9457 (cpu, address + displacement, aarch64_get_vec_u16 (cpu, st, 0));
9460 /* 32 bit store scaled unsigned 12 bit. */
9462 fstrs_abs (sim_cpu *cpu, uint32_t offset)
9464 unsigned st = uimm (aarch64_get_instr (cpu), 4, 0);
9465 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
9467 aarch64_set_mem_float
9469 aarch64_get_reg_u64 (cpu, rn, SP_OK) + SCALE (offset, 32),
9470 aarch64_get_FP_float (cpu, st));
9473 /* 32 bit store unscaled signed 9 bit with pre- or post-writeback. */
9475 fstrs_wb (sim_cpu *cpu, int32_t offset, WriteBack wb)
9477 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
9478 unsigned st = uimm (aarch64_get_instr (cpu), 4, 0);
9480 uint64_t address = aarch64_get_reg_u64 (cpu, rn, SP_OK);
9485 aarch64_set_mem_float (cpu, address, aarch64_get_FP_float (cpu, st));
9490 if (wb != NoWriteBack)
9491 aarch64_set_reg_u64 (cpu, rn, SP_OK, address);
9494 /* 32 bit store scaled or unscaled zero-
9495 or sign-extended 32-bit register offset. */
9497 fstrs_scale_ext (sim_cpu *cpu, Scaling scaling, Extension extension)
9499 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
9500 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
9501 unsigned st = uimm (aarch64_get_instr (cpu), 4, 0);
9503 uint64_t address = aarch64_get_reg_u64 (cpu, rn, SP_OK);
9504 int64_t extended = extend (aarch64_get_reg_u32 (cpu, rm, NO_SP),
9506 uint64_t displacement = OPT_SCALE (extended, 32, scaling);
9508 aarch64_set_mem_float
9509 (cpu, address + displacement, aarch64_get_FP_float (cpu, st));
9512 /* 64 bit store scaled unsigned 12 bit. */
9514 fstrd_abs (sim_cpu *cpu, uint32_t offset)
9516 unsigned st = uimm (aarch64_get_instr (cpu), 4, 0);
9517 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
9519 aarch64_set_mem_double
9521 aarch64_get_reg_u64 (cpu, rn, SP_OK) + SCALE (offset, 64),
9522 aarch64_get_FP_double (cpu, st));
9525 /* 64 bit store unscaled signed 9 bit with pre- or post-writeback. */
9527 fstrd_wb (sim_cpu *cpu, int32_t offset, WriteBack wb)
9529 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
9530 unsigned st = uimm (aarch64_get_instr (cpu), 4, 0);
9532 uint64_t address = aarch64_get_reg_u64 (cpu, rn, SP_OK);
9537 aarch64_set_mem_double (cpu, address, aarch64_get_FP_double (cpu, st));
9542 if (wb != NoWriteBack)
9543 aarch64_set_reg_u64 (cpu, rn, SP_OK, address);
9546 /* 64 bit store scaled or unscaled zero-
9547 or sign-extended 32-bit register offset. */
9549 fstrd_scale_ext (sim_cpu *cpu, Scaling scaling, Extension extension)
9551 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
9552 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
9553 unsigned st = uimm (aarch64_get_instr (cpu), 4, 0);
9555 uint64_t address = aarch64_get_reg_u64 (cpu, rn, SP_OK);
9556 int64_t extended = extend (aarch64_get_reg_u32 (cpu, rm, NO_SP),
9558 uint64_t displacement = OPT_SCALE (extended, 64, scaling);
9560 aarch64_set_mem_double
9561 (cpu, address + displacement, aarch64_get_FP_double (cpu, st));
9564 /* 128 bit store scaled unsigned 12 bit. */
9566 fstrq_abs (sim_cpu *cpu, uint32_t offset)
9569 unsigned st = uimm (aarch64_get_instr (cpu), 4, 0);
9570 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
9573 aarch64_get_FP_long_double (cpu, st, & a);
9575 addr = aarch64_get_reg_u64 (cpu, rn, SP_OK) + SCALE (offset, 128);
9576 aarch64_set_mem_long_double (cpu, addr, a);
9579 /* 128 bit store unscaled signed 9 bit with pre- or post-writeback. */
9581 fstrq_wb (sim_cpu *cpu, int32_t offset, WriteBack wb)
9584 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
9585 unsigned st = uimm (aarch64_get_instr (cpu), 4, 0);
9586 uint64_t address = aarch64_get_reg_u64 (cpu, rn, SP_OK);
9591 aarch64_get_FP_long_double (cpu, st, & a);
9592 aarch64_set_mem_long_double (cpu, address, a);
9597 if (wb != NoWriteBack)
9598 aarch64_set_reg_u64 (cpu, rn, SP_OK, address);
9601 /* 128 bit store scaled or unscaled zero-
9602 or sign-extended 32-bit register offset. */
9604 fstrq_scale_ext (sim_cpu *cpu, Scaling scaling, Extension extension)
9606 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
9607 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
9608 unsigned st = uimm (aarch64_get_instr (cpu), 4, 0);
9610 uint64_t address = aarch64_get_reg_u64 (cpu, rn, SP_OK);
9611 int64_t extended = extend (aarch64_get_reg_u32 (cpu, rm, NO_SP),
9613 uint64_t displacement = OPT_SCALE (extended, 128, scaling);
9617 aarch64_get_FP_long_double (cpu, st, & a);
9618 aarch64_set_mem_long_double (cpu, address + displacement, a);
9622 dexLoadImmediatePrePost (sim_cpu *cpu)
9624 /* instr[29,24] == 111_00
9630 instr[20,12] = simm9
9631 instr[11] = wb : 0 ==> Post, 1 ==> Pre
9632 instr[9,5] = rn may be SP. */
9633 /* unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0); */
9634 uint32_t V = uimm (aarch64_get_instr (cpu), 26, 26);
9635 uint32_t dispatch = ( (uimm (aarch64_get_instr (cpu), 31, 30) << 2)
9636 | uimm (aarch64_get_instr (cpu), 23, 22));
9637 int32_t imm = simm32 (aarch64_get_instr (cpu), 20, 12);
9638 WriteBack wb = writeback (aarch64_get_instr (cpu), 11);
9642 /* GReg operations. */
9645 case 0: strb_wb (cpu, imm, wb); return;
9646 case 1: ldrb32_wb (cpu, imm, wb); return;
9647 case 2: ldrsb_wb (cpu, imm, wb); return;
9648 case 3: ldrsb32_wb (cpu, imm, wb); return;
9649 case 4: strh_wb (cpu, imm, wb); return;
9650 case 5: ldrh32_wb (cpu, imm, wb); return;
9651 case 6: ldrsh64_wb (cpu, imm, wb); return;
9652 case 7: ldrsh32_wb (cpu, imm, wb); return;
9653 case 8: str32_wb (cpu, imm, wb); return;
9654 case 9: ldr32_wb (cpu, imm, wb); return;
9655 case 10: ldrsw_wb (cpu, imm, wb); return;
9656 case 12: str_wb (cpu, imm, wb); return;
9657 case 13: ldr_wb (cpu, imm, wb); return;
9667 /* FReg operations. */
9670 case 2: fstrq_wb (cpu, imm, wb); return;
9671 case 3: fldrq_wb (cpu, imm, wb); return;
9672 case 8: fstrs_wb (cpu, imm, wb); return;
9673 case 9: fldrs_wb (cpu, imm, wb); return;
9674 case 12: fstrd_wb (cpu, imm, wb); return;
9675 case 13: fldrd_wb (cpu, imm, wb); return;
9677 case 0: /* STUR 8 bit FP. */
9678 case 1: /* LDUR 8 bit FP. */
9679 case 4: /* STUR 16 bit FP. */
9680 case 5: /* LDUR 8 bit FP. */
9695 dexLoadRegisterOffset (sim_cpu *cpu)
9697 /* instr[31,30] = size
9704 instr[15,13] = option : 010 ==> UXTW, 011 ==> UXTX/LSL,
9705 110 ==> SXTW, 111 ==> SXTX,
9712 uint32_t V = uimm (aarch64_get_instr (cpu), 26,26);
9713 uint32_t dispatch = ( (uimm (aarch64_get_instr (cpu), 31, 30) << 2)
9714 | uimm (aarch64_get_instr (cpu), 23, 22));
9715 Scaling scale = scaling (aarch64_get_instr (cpu), 12);
9716 Extension extensionType = extension (aarch64_get_instr (cpu), 13);
9718 /* Check for illegal extension types. */
9719 if (uimm (extensionType, 1, 1) == 0)
9722 if (extensionType == UXTX || extensionType == SXTX)
9723 extensionType = NoExtension;
9727 /* GReg operations. */
9730 case 0: strb_scale_ext (cpu, scale, extensionType); return;
9731 case 1: ldrb32_scale_ext (cpu, scale, extensionType); return;
9732 case 2: ldrsb_scale_ext (cpu, scale, extensionType); return;
9733 case 3: ldrsb32_scale_ext (cpu, scale, extensionType); return;
9734 case 4: strh_scale_ext (cpu, scale, extensionType); return;
9735 case 5: ldrh32_scale_ext (cpu, scale, extensionType); return;
9736 case 6: ldrsh_scale_ext (cpu, scale, extensionType); return;
9737 case 7: ldrsh32_scale_ext (cpu, scale, extensionType); return;
9738 case 8: str32_scale_ext (cpu, scale, extensionType); return;
9739 case 9: ldr32_scale_ext (cpu, scale, extensionType); return;
9740 case 10: ldrsw_scale_ext (cpu, scale, extensionType); return;
9741 case 12: str_scale_ext (cpu, scale, extensionType); return;
9742 case 13: ldr_scale_ext (cpu, scale, extensionType); return;
9743 case 14: prfm_scale_ext (cpu, scale, extensionType); return;
9752 /* FReg operations. */
9755 case 1: /* LDUR 8 bit FP. */
9757 case 3: fldrq_scale_ext (cpu, scale, extensionType); return;
9758 case 5: /* LDUR 8 bit FP. */
9760 case 9: fldrs_scale_ext (cpu, scale, extensionType); return;
9761 case 13: fldrd_scale_ext (cpu, scale, extensionType); return;
9763 case 0: fstrb_scale_ext (cpu, scale, extensionType); return;
9764 case 2: fstrq_scale_ext (cpu, scale, extensionType); return;
9765 case 4: fstrh_scale_ext (cpu, scale, extensionType); return;
9766 case 8: fstrs_scale_ext (cpu, scale, extensionType); return;
9767 case 12: fstrd_scale_ext (cpu, scale, extensionType); return;
9781 dexLoadUnsignedImmediate (sim_cpu *cpu)
9783 /* assert instr[29,24] == 111_01
9787 instr[21,10] = uimm12 : unsigned immediate offset
9788 instr[9,5] = rn may be SP. */
9789 /* unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0); */
9790 uint32_t V = uimm (aarch64_get_instr (cpu), 26,26);
9791 uint32_t dispatch = ( (uimm (aarch64_get_instr (cpu), 31, 30) << 2)
9792 | uimm (aarch64_get_instr (cpu), 23, 22));
9793 uint32_t imm = uimm (aarch64_get_instr (cpu), 21, 10);
9797 /* GReg operations. */
9800 case 0: strb_abs (cpu, imm); return;
9801 case 1: ldrb32_abs (cpu, imm); return;
9802 case 2: ldrsb_abs (cpu, imm); return;
9803 case 3: ldrsb32_abs (cpu, imm); return;
9804 case 4: strh_abs (cpu, imm); return;
9805 case 5: ldrh32_abs (cpu, imm); return;
9806 case 6: ldrsh_abs (cpu, imm); return;
9807 case 7: ldrsh32_abs (cpu, imm); return;
9808 case 8: str32_abs (cpu, imm); return;
9809 case 9: ldr32_abs (cpu, imm); return;
9810 case 10: ldrsw_abs (cpu, imm); return;
9811 case 12: str_abs (cpu, imm); return;
9812 case 13: ldr_abs (cpu, imm); return;
9813 case 14: prfm_abs (cpu, imm); return;
9822 /* FReg operations. */
9825 case 3: fldrq_abs (cpu, imm); return;
9826 case 9: fldrs_abs (cpu, imm); return;
9827 case 13: fldrd_abs (cpu, imm); return;
9829 case 0: fstrb_abs (cpu, imm); return;
9830 case 2: fstrq_abs (cpu, imm); return;
9831 case 4: fstrh_abs (cpu, imm); return;
9832 case 8: fstrs_abs (cpu, imm); return;
9833 case 12: fstrd_abs (cpu, imm); return;
9835 case 1: /* LDR 8 bit FP. */
9836 case 5: /* LDR 8 bit FP. */
9851 dexLoadExclusive (sim_cpu *cpu)
9853 /* assert instr[29:24] = 001000;
9855 instr[23] = 0 if exclusive
9856 instr[22] = L : 1 if load, 0 if store
9857 instr[21] = 1 if pair
9859 instr[15] = o0 : 1 if ordered
9864 switch (uimm (aarch64_get_instr (cpu), 22, 21))
9866 case 2: ldxr (cpu); return;
9867 case 0: stxr (cpu); return;
9873 dexLoadOther (sim_cpu *cpu)
9877 /* instr[29,25] = 111_0
9878 instr[24] == 0 ==> dispatch, 1 ==> ldst reg unsigned immediate
9879 instr[21:11,10] is the secondary dispatch. */
9880 if (uimm (aarch64_get_instr (cpu), 24, 24))
9882 dexLoadUnsignedImmediate (cpu);
9886 dispatch = ( (uimm (aarch64_get_instr (cpu), 21, 21) << 2)
9887 | uimm (aarch64_get_instr (cpu), 11, 10));
9890 case 0: dexLoadUnscaledImmediate (cpu); return;
9891 case 1: dexLoadImmediatePrePost (cpu); return;
9892 case 3: dexLoadImmediatePrePost (cpu); return;
9893 case 6: dexLoadRegisterOffset (cpu); return;
9905 store_pair_u32 (sim_cpu *cpu, int32_t offset, WriteBack wb)
9907 unsigned rn = uimm (aarch64_get_instr (cpu), 14, 10);
9908 unsigned rd = uimm (aarch64_get_instr (cpu), 9, 5);
9909 unsigned rm = uimm (aarch64_get_instr (cpu), 4, 0);
9910 uint64_t address = aarch64_get_reg_u64 (cpu, rd, SP_OK);
9912 if ((rn == rd || rm == rd) && wb != NoWriteBack)
9913 HALT_UNALLOC; /* ??? */
9920 aarch64_set_mem_u32 (cpu, address,
9921 aarch64_get_reg_u32 (cpu, rm, NO_SP));
9922 aarch64_set_mem_u32 (cpu, address + 4,
9923 aarch64_get_reg_u32 (cpu, rn, NO_SP));
9928 if (wb != NoWriteBack)
9929 aarch64_set_reg_u64 (cpu, rd, SP_OK, address);
9933 store_pair_u64 (sim_cpu *cpu, int32_t offset, WriteBack wb)
9935 unsigned rn = uimm (aarch64_get_instr (cpu), 14, 10);
9936 unsigned rd = uimm (aarch64_get_instr (cpu), 9, 5);
9937 unsigned rm = uimm (aarch64_get_instr (cpu), 4, 0);
9938 uint64_t address = aarch64_get_reg_u64 (cpu, rd, SP_OK);
9940 if ((rn == rd || rm == rd) && wb != NoWriteBack)
9941 HALT_UNALLOC; /* ??? */
9948 aarch64_set_mem_u64 (cpu, address,
9949 aarch64_get_reg_u64 (cpu, rm, SP_OK));
9950 aarch64_set_mem_u64 (cpu, address + 8,
9951 aarch64_get_reg_u64 (cpu, rn, SP_OK));
9956 if (wb != NoWriteBack)
9957 aarch64_set_reg_u64 (cpu, rd, SP_OK, address);
9961 load_pair_u32 (sim_cpu *cpu, int32_t offset, WriteBack wb)
9963 unsigned rn = uimm (aarch64_get_instr (cpu), 14, 10);
9964 unsigned rd = uimm (aarch64_get_instr (cpu), 9, 5);
9965 unsigned rm = uimm (aarch64_get_instr (cpu), 4, 0);
9966 uint64_t address = aarch64_get_reg_u64 (cpu, rd, SP_OK);
9968 /* treat this as unalloc to make sure we don't do it. */
9977 aarch64_set_reg_u64 (cpu, rm, SP_OK, aarch64_get_mem_u32 (cpu, address));
9978 aarch64_set_reg_u64 (cpu, rn, SP_OK, aarch64_get_mem_u32 (cpu, address + 4));
9983 if (wb != NoWriteBack)
9984 aarch64_set_reg_u64 (cpu, rd, SP_OK, address);
9988 load_pair_s32 (sim_cpu *cpu, int32_t offset, WriteBack wb)
9990 unsigned rn = uimm (aarch64_get_instr (cpu), 14, 10);
9991 unsigned rd = uimm (aarch64_get_instr (cpu), 9, 5);
9992 unsigned rm = uimm (aarch64_get_instr (cpu), 4, 0);
9993 uint64_t address = aarch64_get_reg_u64 (cpu, rd, SP_OK);
9995 /* Treat this as unalloc to make sure we don't do it. */
10004 aarch64_set_reg_s64 (cpu, rm, SP_OK, aarch64_get_mem_s32 (cpu, address));
10005 aarch64_set_reg_s64 (cpu, rn, SP_OK, aarch64_get_mem_s32 (cpu, address + 4));
10010 if (wb != NoWriteBack)
10011 aarch64_set_reg_u64 (cpu, rd, SP_OK, address);
10015 load_pair_u64 (sim_cpu *cpu, int32_t offset, WriteBack wb)
10017 unsigned rn = uimm (aarch64_get_instr (cpu), 14, 10);
10018 unsigned rd = uimm (aarch64_get_instr (cpu), 9, 5);
10019 unsigned rm = uimm (aarch64_get_instr (cpu), 4, 0);
10020 uint64_t address = aarch64_get_reg_u64 (cpu, rd, SP_OK);
10022 /* Treat this as unalloc to make sure we don't do it. */
10031 aarch64_set_reg_u64 (cpu, rm, SP_OK, aarch64_get_mem_u64 (cpu, address));
10032 aarch64_set_reg_u64 (cpu, rn, SP_OK, aarch64_get_mem_u64 (cpu, address + 8));
10037 if (wb != NoWriteBack)
10038 aarch64_set_reg_u64 (cpu, rd, SP_OK, address);
10042 dex_load_store_pair_gr (sim_cpu *cpu)
10044 /* instr[31,30] = size (10=> 64-bit, 01=> signed 32-bit, 00=> 32-bit)
10045 instr[29,25] = instruction encoding: 101_0
10046 instr[26] = V : 1 if fp 0 if gp
10047 instr[24,23] = addressing mode (10=> offset, 01=> post, 11=> pre)
10048 instr[22] = load/store (1=> load)
10049 instr[21,15] = signed, scaled, offset
10052 instr[ 4, 0] = Rm. */
10054 uint32_t dispatch = ((uimm (aarch64_get_instr (cpu), 31, 30) << 3)
10055 | uimm (aarch64_get_instr (cpu), 24, 22));
10056 int32_t offset = simm32 (aarch64_get_instr (cpu), 21, 15);
10060 case 2: store_pair_u32 (cpu, offset, Post); return;
10061 case 3: load_pair_u32 (cpu, offset, Post); return;
10062 case 4: store_pair_u32 (cpu, offset, NoWriteBack); return;
10063 case 5: load_pair_u32 (cpu, offset, NoWriteBack); return;
10064 case 6: store_pair_u32 (cpu, offset, Pre); return;
10065 case 7: load_pair_u32 (cpu, offset, Pre); return;
10067 case 11: load_pair_s32 (cpu, offset, Post); return;
10068 case 13: load_pair_s32 (cpu, offset, NoWriteBack); return;
10069 case 15: load_pair_s32 (cpu, offset, Pre); return;
10071 case 18: store_pair_u64 (cpu, offset, Post); return;
10072 case 19: load_pair_u64 (cpu, offset, Post); return;
10073 case 20: store_pair_u64 (cpu, offset, NoWriteBack); return;
10074 case 21: load_pair_u64 (cpu, offset, NoWriteBack); return;
10075 case 22: store_pair_u64 (cpu, offset, Pre); return;
10076 case 23: load_pair_u64 (cpu, offset, Pre); return;
10084 store_pair_float (sim_cpu *cpu, int32_t offset, WriteBack wb)
10086 unsigned rn = uimm (aarch64_get_instr (cpu), 14, 10);
10087 unsigned rd = uimm (aarch64_get_instr (cpu), 9, 5);
10088 unsigned rm = uimm (aarch64_get_instr (cpu), 4, 0);
10089 uint64_t address = aarch64_get_reg_u64 (cpu, rd, SP_OK);
10096 aarch64_set_mem_float (cpu, address, aarch64_get_FP_float (cpu, rm));
10097 aarch64_set_mem_float (cpu, address + 4, aarch64_get_FP_float (cpu, rn));
10102 if (wb != NoWriteBack)
10103 aarch64_set_reg_u64 (cpu, rd, SP_OK, address);
10107 store_pair_double (sim_cpu *cpu, int32_t offset, WriteBack wb)
10109 unsigned rn = uimm (aarch64_get_instr (cpu), 14, 10);
10110 unsigned rd = uimm (aarch64_get_instr (cpu), 9, 5);
10111 unsigned rm = uimm (aarch64_get_instr (cpu), 4, 0);
10112 uint64_t address = aarch64_get_reg_u64 (cpu, rd, SP_OK);
10119 aarch64_set_mem_double (cpu, address, aarch64_get_FP_double (cpu, rm));
10120 aarch64_set_mem_double (cpu, address + 8, aarch64_get_FP_double (cpu, rn));
10125 if (wb != NoWriteBack)
10126 aarch64_set_reg_u64 (cpu, rd, SP_OK, address);
10130 store_pair_long_double (sim_cpu *cpu, int32_t offset, WriteBack wb)
10133 unsigned rn = uimm (aarch64_get_instr (cpu), 14, 10);
10134 unsigned rd = uimm (aarch64_get_instr (cpu), 9, 5);
10135 unsigned rm = uimm (aarch64_get_instr (cpu), 4, 0);
10136 uint64_t address = aarch64_get_reg_u64 (cpu, rd, SP_OK);
10143 aarch64_get_FP_long_double (cpu, rm, & a);
10144 aarch64_set_mem_long_double (cpu, address, a);
10145 aarch64_get_FP_long_double (cpu, rn, & a);
10146 aarch64_set_mem_long_double (cpu, address + 16, a);
10151 if (wb != NoWriteBack)
10152 aarch64_set_reg_u64 (cpu, rd, SP_OK, address);
10156 load_pair_float (sim_cpu *cpu, int32_t offset, WriteBack wb)
10158 unsigned rn = uimm (aarch64_get_instr (cpu), 14, 10);
10159 unsigned rd = uimm (aarch64_get_instr (cpu), 9, 5);
10160 unsigned rm = uimm (aarch64_get_instr (cpu), 4, 0);
10161 uint64_t address = aarch64_get_reg_u64 (cpu, rd, SP_OK);
10171 aarch64_set_FP_float (cpu, rm, aarch64_get_mem_float (cpu, address));
10172 aarch64_set_FP_float (cpu, rn, aarch64_get_mem_float (cpu, address + 4));
10177 if (wb != NoWriteBack)
10178 aarch64_set_reg_u64 (cpu, rd, SP_OK, address);
10182 load_pair_double (sim_cpu *cpu, int32_t offset, WriteBack wb)
10184 unsigned rn = uimm (aarch64_get_instr (cpu), 14, 10);
10185 unsigned rd = uimm (aarch64_get_instr (cpu), 9, 5);
10186 unsigned rm = uimm (aarch64_get_instr (cpu), 4, 0);
10187 uint64_t address = aarch64_get_reg_u64 (cpu, rd, SP_OK);
10197 aarch64_set_FP_double (cpu, rm, aarch64_get_mem_double (cpu, address));
10198 aarch64_set_FP_double (cpu, rn, aarch64_get_mem_double (cpu, address + 8));
10203 if (wb != NoWriteBack)
10204 aarch64_set_reg_u64 (cpu, rd, SP_OK, address);
10208 load_pair_long_double (sim_cpu *cpu, int32_t offset, WriteBack wb)
10211 unsigned rn = uimm (aarch64_get_instr (cpu), 14, 10);
10212 unsigned rd = uimm (aarch64_get_instr (cpu), 9, 5);
10213 unsigned rm = uimm (aarch64_get_instr (cpu), 4, 0);
10214 uint64_t address = aarch64_get_reg_u64 (cpu, rd, SP_OK);
10224 aarch64_get_mem_long_double (cpu, address, & a);
10225 aarch64_set_FP_long_double (cpu, rm, a);
10226 aarch64_get_mem_long_double (cpu, address + 16, & a);
10227 aarch64_set_FP_long_double (cpu, rn, a);
10232 if (wb != NoWriteBack)
10233 aarch64_set_reg_u64 (cpu, rd, SP_OK, address);
10237 dex_load_store_pair_fp (sim_cpu *cpu)
10239 /* instr[31,30] = size (10=> 128-bit, 01=> 64-bit, 00=> 32-bit)
10240 instr[29,25] = instruction encoding
10241 instr[24,23] = addressing mode (10=> offset, 01=> post, 11=> pre)
10242 instr[22] = load/store (1=> load)
10243 instr[21,15] = signed, scaled, offset
10246 instr[ 4, 0] = Rm */
10248 uint32_t dispatch = ((uimm (aarch64_get_instr (cpu), 31, 30) << 3)
10249 | uimm (aarch64_get_instr (cpu), 24, 22));
10250 int32_t offset = simm32 (aarch64_get_instr (cpu), 21, 15);
10254 case 2: store_pair_float (cpu, offset, Post); return;
10255 case 3: load_pair_float (cpu, offset, Post); return;
10256 case 4: store_pair_float (cpu, offset, NoWriteBack); return;
10257 case 5: load_pair_float (cpu, offset, NoWriteBack); return;
10258 case 6: store_pair_float (cpu, offset, Pre); return;
10259 case 7: load_pair_float (cpu, offset, Pre); return;
10261 case 10: store_pair_double (cpu, offset, Post); return;
10262 case 11: load_pair_double (cpu, offset, Post); return;
10263 case 12: store_pair_double (cpu, offset, NoWriteBack); return;
10264 case 13: load_pair_double (cpu, offset, NoWriteBack); return;
10265 case 14: store_pair_double (cpu, offset, Pre); return;
10266 case 15: load_pair_double (cpu, offset, Pre); return;
10268 case 18: store_pair_long_double (cpu, offset, Post); return;
10269 case 19: load_pair_long_double (cpu, offset, Post); return;
10270 case 20: store_pair_long_double (cpu, offset, NoWriteBack); return;
10271 case 21: load_pair_long_double (cpu, offset, NoWriteBack); return;
10272 case 22: store_pair_long_double (cpu, offset, Pre); return;
10273 case 23: load_pair_long_double (cpu, offset, Pre); return;
10280 static inline unsigned
10281 vec_reg (unsigned v, unsigned o)
10283 return (v + o) & 0x3F;
10286 /* Load multiple N-element structures to N consecutive registers. */
10288 vec_load (sim_cpu *cpu, uint64_t address, unsigned N)
10290 int all = uimm (aarch64_get_instr (cpu), 30, 30);
10291 unsigned size = uimm (aarch64_get_instr (cpu), 11, 10);
10292 unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
10297 case 0: /* 8-bit operations. */
10299 for (i = 0; i < (16 * N); i++)
10300 aarch64_set_vec_u8 (cpu, vec_reg (vd, i >> 4), i & 15,
10301 aarch64_get_mem_u8 (cpu, address + i));
10303 for (i = 0; i < (8 * N); i++)
10304 aarch64_set_vec_u8 (cpu, vec_reg (vd, i >> 3), i & 7,
10305 aarch64_get_mem_u8 (cpu, address + i));
10308 case 1: /* 16-bit operations. */
10310 for (i = 0; i < (8 * N); i++)
10311 aarch64_set_vec_u16 (cpu, vec_reg (vd, i >> 3), i & 7,
10312 aarch64_get_mem_u16 (cpu, address + i * 2));
10314 for (i = 0; i < (4 * N); i++)
10315 aarch64_set_vec_u16 (cpu, vec_reg (vd, i >> 2), i & 3,
10316 aarch64_get_mem_u16 (cpu, address + i * 2));
10319 case 2: /* 32-bit operations. */
10321 for (i = 0; i < (4 * N); i++)
10322 aarch64_set_vec_u32 (cpu, vec_reg (vd, i >> 2), i & 3,
10323 aarch64_get_mem_u32 (cpu, address + i * 4));
10325 for (i = 0; i < (2 * N); i++)
10326 aarch64_set_vec_u32 (cpu, vec_reg (vd, i >> 1), i & 1,
10327 aarch64_get_mem_u32 (cpu, address + i * 4));
10330 case 3: /* 64-bit operations. */
10332 for (i = 0; i < (2 * N); i++)
10333 aarch64_set_vec_u64 (cpu, vec_reg (vd, i >> 1), i & 1,
10334 aarch64_get_mem_u64 (cpu, address + i * 8));
10336 for (i = 0; i < N; i++)
10337 aarch64_set_vec_u64 (cpu, vec_reg (vd, i), 0,
10338 aarch64_get_mem_u64 (cpu, address + i * 8));
10346 /* LD4: load multiple 4-element to four consecutive registers. */
10348 LD4 (sim_cpu *cpu, uint64_t address)
10350 vec_load (cpu, address, 4);
10353 /* LD3: load multiple 3-element structures to three consecutive registers. */
10355 LD3 (sim_cpu *cpu, uint64_t address)
10357 vec_load (cpu, address, 3);
10360 /* LD2: load multiple 2-element structures to two consecutive registers. */
10362 LD2 (sim_cpu *cpu, uint64_t address)
10364 vec_load (cpu, address, 2);
10367 /* Load multiple 1-element structures into one register. */
10369 LD1_1 (sim_cpu *cpu, uint64_t address)
10371 int all = uimm (aarch64_get_instr (cpu), 30, 30);
10372 unsigned size = uimm (aarch64_get_instr (cpu), 11, 10);
10373 unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
10379 /* LD1 {Vd.16b}, addr, #16 */
10380 /* LD1 {Vd.8b}, addr, #8 */
10381 for (i = 0; i < (all ? 16 : 8); i++)
10382 aarch64_set_vec_u8 (cpu, vd, i,
10383 aarch64_get_mem_u8 (cpu, address + i));
10387 /* LD1 {Vd.8h}, addr, #16 */
10388 /* LD1 {Vd.4h}, addr, #8 */
10389 for (i = 0; i < (all ? 8 : 4); i++)
10390 aarch64_set_vec_u16 (cpu, vd, i,
10391 aarch64_get_mem_u16 (cpu, address + i * 2));
10395 /* LD1 {Vd.4s}, addr, #16 */
10396 /* LD1 {Vd.2s}, addr, #8 */
10397 for (i = 0; i < (all ? 4 : 2); i++)
10398 aarch64_set_vec_u32 (cpu, vd, i,
10399 aarch64_get_mem_u32 (cpu, address + i * 4));
10403 /* LD1 {Vd.2d}, addr, #16 */
10404 /* LD1 {Vd.1d}, addr, #8 */
10405 for (i = 0; i < (all ? 2 : 1); i++)
10406 aarch64_set_vec_u64 (cpu, vd, i,
10407 aarch64_get_mem_u64 (cpu, address + i * 8));
10415 /* Load multiple 1-element structures into two registers. */
10417 LD1_2 (sim_cpu *cpu, uint64_t address)
10419 /* FIXME: This algorithm is *exactly* the same as the LD2 version.
10420 So why have two different instructions ? There must be something
10421 wrong somewhere. */
10422 vec_load (cpu, address, 2);
10425 /* Load multiple 1-element structures into three registers. */
10427 LD1_3 (sim_cpu *cpu, uint64_t address)
10429 /* FIXME: This algorithm is *exactly* the same as the LD3 version.
10430 So why have two different instructions ? There must be something
10431 wrong somewhere. */
10432 vec_load (cpu, address, 3);
10435 /* Load multiple 1-element structures into four registers. */
10437 LD1_4 (sim_cpu *cpu, uint64_t address)
10439 /* FIXME: This algorithm is *exactly* the same as the LD4 version.
10440 So why have two different instructions ? There must be something
10441 wrong somewhere. */
10442 vec_load (cpu, address, 4);
10445 /* Store multiple N-element structures to N consecutive registers. */
10447 vec_store (sim_cpu *cpu, uint64_t address, unsigned N)
10449 int all = uimm (aarch64_get_instr (cpu), 30, 30);
10450 unsigned size = uimm (aarch64_get_instr (cpu), 11, 10);
10451 unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
10456 case 0: /* 8-bit operations. */
10458 for (i = 0; i < (16 * N); i++)
10461 aarch64_get_vec_u8 (cpu, vec_reg (vd, i >> 4), i & 15));
10463 for (i = 0; i < (8 * N); i++)
10466 aarch64_get_vec_u8 (cpu, vec_reg (vd, i >> 3), i & 7));
10469 case 1: /* 16-bit operations. */
10471 for (i = 0; i < (8 * N); i++)
10472 aarch64_set_mem_u16
10473 (cpu, address + i * 2,
10474 aarch64_get_vec_u16 (cpu, vec_reg (vd, i >> 3), i & 7));
10476 for (i = 0; i < (4 * N); i++)
10477 aarch64_set_mem_u16
10478 (cpu, address + i * 2,
10479 aarch64_get_vec_u16 (cpu, vec_reg (vd, i >> 2), i & 3));
10482 case 2: /* 32-bit operations. */
10484 for (i = 0; i < (4 * N); i++)
10485 aarch64_set_mem_u32
10486 (cpu, address + i * 4,
10487 aarch64_get_vec_u32 (cpu, vec_reg (vd, i >> 2), i & 3));
10489 for (i = 0; i < (2 * N); i++)
10490 aarch64_set_mem_u32
10491 (cpu, address + i * 4,
10492 aarch64_get_vec_u32 (cpu, vec_reg (vd, i >> 1), i & 1));
10495 case 3: /* 64-bit operations. */
10497 for (i = 0; i < (2 * N); i++)
10498 aarch64_set_mem_u64
10499 (cpu, address + i * 8,
10500 aarch64_get_vec_u64 (cpu, vec_reg (vd, i >> 1), i & 1));
10502 for (i = 0; i < N; i++)
10503 aarch64_set_mem_u64
10504 (cpu, address + i * 8,
10505 aarch64_get_vec_u64 (cpu, vec_reg (vd, i), 0));
10513 /* Store multiple 4-element structure to four consecutive registers. */
10515 ST4 (sim_cpu *cpu, uint64_t address)
10517 vec_store (cpu, address, 4);
10520 /* Store multiple 3-element structures to three consecutive registers. */
10522 ST3 (sim_cpu *cpu, uint64_t address)
10524 vec_store (cpu, address, 3);
10527 /* Store multiple 2-element structures to two consecutive registers. */
10529 ST2 (sim_cpu *cpu, uint64_t address)
10531 vec_store (cpu, address, 2);
10534 /* Store multiple 1-element structures into one register. */
10536 ST1_1 (sim_cpu *cpu, uint64_t address)
10538 int all = uimm (aarch64_get_instr (cpu), 30, 30);
10539 unsigned size = uimm (aarch64_get_instr (cpu), 11, 10);
10540 unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
10546 for (i = 0; i < (all ? 16 : 8); i++)
10547 aarch64_set_mem_u8 (cpu, address + i,
10548 aarch64_get_vec_u8 (cpu, vd, i));
10552 for (i = 0; i < (all ? 8 : 4); i++)
10553 aarch64_set_mem_u16 (cpu, address + i * 2,
10554 aarch64_get_vec_u16 (cpu, vd, i));
10558 for (i = 0; i < (all ? 4 : 2); i++)
10559 aarch64_set_mem_u32 (cpu, address + i * 4,
10560 aarch64_get_vec_u32 (cpu, vd, i));
10564 for (i = 0; i < (all ? 2 : 1); i++)
10565 aarch64_set_mem_u64 (cpu, address + i * 8,
10566 aarch64_get_vec_u64 (cpu, vd, i));
10574 /* Store multiple 1-element structures into two registers. */
10576 ST1_2 (sim_cpu *cpu, uint64_t address)
10578 /* FIXME: This algorithm is *exactly* the same as the ST2 version.
10579 So why have two different instructions ? There must be
10580 something wrong somewhere. */
10581 vec_store (cpu, address, 2);
10584 /* Store multiple 1-element structures into three registers. */
10586 ST1_3 (sim_cpu *cpu, uint64_t address)
10588 /* FIXME: This algorithm is *exactly* the same as the ST3 version.
10589 So why have two different instructions ? There must be
10590 something wrong somewhere. */
10591 vec_store (cpu, address, 3);
10594 /* Store multiple 1-element structures into four registers. */
10596 ST1_4 (sim_cpu *cpu, uint64_t address)
10598 /* FIXME: This algorithm is *exactly* the same as the ST4 version.
10599 So why have two different instructions ? There must be
10600 something wrong somewhere. */
10601 vec_store (cpu, address, 4);
10605 do_vec_LDnR (sim_cpu *cpu, uint64_t address)
10608 instr[30] = element selector 0=>half, 1=>all elements
10609 instr[29,24] = 00 1101
10610 instr[23] = 0=>simple, 1=>post
10612 instr[21] = width: LD1R-or-LD3R (0) / LD2R-or-LD4R (1)
10613 instr[20,16] = 0 0000 (simple), Vinc (reg-post-inc, no SP),
10614 11111 (immediate post inc)
10616 instr[13] = width: LD1R-or-LD2R (0) / LD3R-or-LD4R (1)
10618 instr[11,10] = element size 00=> byte(b), 01=> half(h),
10619 10=> word(s), 11=> double(d)
10620 instr[9,5] = address
10623 unsigned full = uimm (aarch64_get_instr (cpu), 30, 30);
10624 unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
10625 unsigned size = uimm (aarch64_get_instr (cpu), 11, 10);
10628 NYI_assert (29, 24, 0x0D);
10629 NYI_assert (22, 22, 1);
10630 NYI_assert (15, 14, 3);
10631 NYI_assert (12, 12, 0);
10633 switch ((uimm (aarch64_get_instr (cpu), 13, 13) << 1)
10634 | uimm (aarch64_get_instr (cpu), 21, 21))
10636 case 0: /* LD1R. */
10641 uint8_t val = aarch64_get_mem_u8 (cpu, address);
10642 for (i = 0; i < (full ? 16 : 8); i++)
10643 aarch64_set_vec_u8 (cpu, vd, i, val);
10649 uint16_t val = aarch64_get_mem_u16 (cpu, address);
10650 for (i = 0; i < (full ? 8 : 4); i++)
10651 aarch64_set_vec_u16 (cpu, vd, i, val);
10657 uint32_t val = aarch64_get_mem_u32 (cpu, address);
10658 for (i = 0; i < (full ? 4 : 2); i++)
10659 aarch64_set_vec_u32 (cpu, vd, i, val);
10665 uint64_t val = aarch64_get_mem_u64 (cpu, address);
10666 for (i = 0; i < (full ? 2 : 1); i++)
10667 aarch64_set_vec_u64 (cpu, vd, i, val);
10676 case 1: /* LD2R. */
10681 uint8_t val1 = aarch64_get_mem_u8 (cpu, address);
10682 uint8_t val2 = aarch64_get_mem_u8 (cpu, address + 1);
10684 for (i = 0; i < (full ? 16 : 8); i++)
10686 aarch64_set_vec_u8 (cpu, vd, 0, val1);
10687 aarch64_set_vec_u8 (cpu, vd + 1, 0, val2);
10694 uint16_t val1 = aarch64_get_mem_u16 (cpu, address);
10695 uint16_t val2 = aarch64_get_mem_u16 (cpu, address + 2);
10697 for (i = 0; i < (full ? 8 : 4); i++)
10699 aarch64_set_vec_u16 (cpu, vd, 0, val1);
10700 aarch64_set_vec_u16 (cpu, vd + 1, 0, val2);
10707 uint32_t val1 = aarch64_get_mem_u32 (cpu, address);
10708 uint32_t val2 = aarch64_get_mem_u32 (cpu, address + 4);
10710 for (i = 0; i < (full ? 4 : 2); i++)
10712 aarch64_set_vec_u32 (cpu, vd, 0, val1);
10713 aarch64_set_vec_u32 (cpu, vd + 1, 0, val2);
10720 uint64_t val1 = aarch64_get_mem_u64 (cpu, address);
10721 uint64_t val2 = aarch64_get_mem_u64 (cpu, address + 8);
10723 for (i = 0; i < (full ? 2 : 1); i++)
10725 aarch64_set_vec_u64 (cpu, vd, 0, val1);
10726 aarch64_set_vec_u64 (cpu, vd + 1, 0, val2);
10736 case 2: /* LD3R. */
10741 uint8_t val1 = aarch64_get_mem_u8 (cpu, address);
10742 uint8_t val2 = aarch64_get_mem_u8 (cpu, address + 1);
10743 uint8_t val3 = aarch64_get_mem_u8 (cpu, address + 2);
10745 for (i = 0; i < (full ? 16 : 8); i++)
10747 aarch64_set_vec_u8 (cpu, vd, 0, val1);
10748 aarch64_set_vec_u8 (cpu, vd + 1, 0, val2);
10749 aarch64_set_vec_u8 (cpu, vd + 2, 0, val3);
10756 uint32_t val1 = aarch64_get_mem_u16 (cpu, address);
10757 uint32_t val2 = aarch64_get_mem_u16 (cpu, address + 2);
10758 uint32_t val3 = aarch64_get_mem_u16 (cpu, address + 4);
10760 for (i = 0; i < (full ? 8 : 4); i++)
10762 aarch64_set_vec_u16 (cpu, vd, 0, val1);
10763 aarch64_set_vec_u16 (cpu, vd + 1, 0, val2);
10764 aarch64_set_vec_u16 (cpu, vd + 2, 0, val3);
10771 uint32_t val1 = aarch64_get_mem_u32 (cpu, address);
10772 uint32_t val2 = aarch64_get_mem_u32 (cpu, address + 4);
10773 uint32_t val3 = aarch64_get_mem_u32 (cpu, address + 8);
10775 for (i = 0; i < (full ? 4 : 2); i++)
10777 aarch64_set_vec_u32 (cpu, vd, 0, val1);
10778 aarch64_set_vec_u32 (cpu, vd + 1, 0, val2);
10779 aarch64_set_vec_u32 (cpu, vd + 2, 0, val3);
10786 uint64_t val1 = aarch64_get_mem_u64 (cpu, address);
10787 uint64_t val2 = aarch64_get_mem_u64 (cpu, address + 8);
10788 uint64_t val3 = aarch64_get_mem_u64 (cpu, address + 16);
10790 for (i = 0; i < (full ? 2 : 1); i++)
10792 aarch64_set_vec_u64 (cpu, vd, 0, val1);
10793 aarch64_set_vec_u64 (cpu, vd + 1, 0, val2);
10794 aarch64_set_vec_u64 (cpu, vd + 2, 0, val3);
10804 case 3: /* LD4R. */
10809 uint8_t val1 = aarch64_get_mem_u8 (cpu, address);
10810 uint8_t val2 = aarch64_get_mem_u8 (cpu, address + 1);
10811 uint8_t val3 = aarch64_get_mem_u8 (cpu, address + 2);
10812 uint8_t val4 = aarch64_get_mem_u8 (cpu, address + 3);
10814 for (i = 0; i < (full ? 16 : 8); i++)
10816 aarch64_set_vec_u8 (cpu, vd, 0, val1);
10817 aarch64_set_vec_u8 (cpu, vd + 1, 0, val2);
10818 aarch64_set_vec_u8 (cpu, vd + 2, 0, val3);
10819 aarch64_set_vec_u8 (cpu, vd + 3, 0, val4);
10826 uint32_t val1 = aarch64_get_mem_u16 (cpu, address);
10827 uint32_t val2 = aarch64_get_mem_u16 (cpu, address + 2);
10828 uint32_t val3 = aarch64_get_mem_u16 (cpu, address + 4);
10829 uint32_t val4 = aarch64_get_mem_u16 (cpu, address + 6);
10831 for (i = 0; i < (full ? 8 : 4); i++)
10833 aarch64_set_vec_u16 (cpu, vd, 0, val1);
10834 aarch64_set_vec_u16 (cpu, vd + 1, 0, val2);
10835 aarch64_set_vec_u16 (cpu, vd + 2, 0, val3);
10836 aarch64_set_vec_u16 (cpu, vd + 3, 0, val4);
10843 uint32_t val1 = aarch64_get_mem_u32 (cpu, address);
10844 uint32_t val2 = aarch64_get_mem_u32 (cpu, address + 4);
10845 uint32_t val3 = aarch64_get_mem_u32 (cpu, address + 8);
10846 uint32_t val4 = aarch64_get_mem_u32 (cpu, address + 12);
10848 for (i = 0; i < (full ? 4 : 2); i++)
10850 aarch64_set_vec_u32 (cpu, vd, 0, val1);
10851 aarch64_set_vec_u32 (cpu, vd + 1, 0, val2);
10852 aarch64_set_vec_u32 (cpu, vd + 2, 0, val3);
10853 aarch64_set_vec_u32 (cpu, vd + 3, 0, val4);
10860 uint64_t val1 = aarch64_get_mem_u64 (cpu, address);
10861 uint64_t val2 = aarch64_get_mem_u64 (cpu, address + 8);
10862 uint64_t val3 = aarch64_get_mem_u64 (cpu, address + 16);
10863 uint64_t val4 = aarch64_get_mem_u64 (cpu, address + 24);
10865 for (i = 0; i < (full ? 2 : 1); i++)
10867 aarch64_set_vec_u64 (cpu, vd, 0, val1);
10868 aarch64_set_vec_u64 (cpu, vd + 1, 0, val2);
10869 aarch64_set_vec_u64 (cpu, vd + 2, 0, val3);
10870 aarch64_set_vec_u64 (cpu, vd + 3, 0, val4);
10886 do_vec_load_store (sim_cpu *cpu)
10888 /* {LD|ST}<N> {Vd..Vd+N}, vaddr
10891 instr[30] = element selector 0=>half, 1=>all elements
10892 instr[29,25] = 00110
10894 instr[23] = 0=>simple, 1=>post
10895 instr[22] = 0=>store, 1=>load
10896 instr[21] = 0 (LDn) / small(0)-large(1) selector (LDnR)
10897 instr[20,16] = 00000 (simple), Vinc (reg-post-inc, no SP),
10898 11111 (immediate post inc)
10899 instr[15,12] = elements and destinations. eg for load:
10900 0000=>LD4 => load multiple 4-element to
10901 four consecutive registers
10902 0100=>LD3 => load multiple 3-element to
10903 three consecutive registers
10904 1000=>LD2 => load multiple 2-element to
10905 two consecutive registers
10906 0010=>LD1 => load multiple 1-element to
10907 four consecutive registers
10908 0110=>LD1 => load multiple 1-element to
10909 three consecutive registers
10910 1010=>LD1 => load multiple 1-element to
10911 two consecutive registers
10912 0111=>LD1 => load multiple 1-element to
10916 instr[11,10] = element size 00=> byte(b), 01=> half(h),
10917 10=> word(s), 11=> double(d)
10918 instr[9,5] = Vn, can be SP
10927 if (uimm (aarch64_get_instr (cpu), 31, 31) != 0
10928 || uimm (aarch64_get_instr (cpu), 29, 25) != 0x06)
10931 type = uimm (aarch64_get_instr (cpu), 15, 12);
10932 if (type != 0xE && type != 0xE && uimm (aarch64_get_instr (cpu), 21, 21) != 0)
10935 post = uimm (aarch64_get_instr (cpu), 23, 23);
10936 load = uimm (aarch64_get_instr (cpu), 22, 22);
10937 vn = uimm (aarch64_get_instr (cpu), 9, 5);
10938 address = aarch64_get_reg_u64 (cpu, vn, SP_OK);
10942 unsigned vm = uimm (aarch64_get_instr (cpu), 20, 16);
10946 unsigned sizeof_operation;
10950 case 0: sizeof_operation = 32; break;
10951 case 4: sizeof_operation = 24; break;
10952 case 8: sizeof_operation = 16; break;
10955 sizeof_operation = uimm (aarch64_get_instr (cpu), 21, 21) ? 2 : 1;
10956 sizeof_operation <<= uimm (aarch64_get_instr (cpu), 11, 10);
10960 sizeof_operation = uimm (aarch64_get_instr (cpu), 21, 21) ? 8 : 4;
10961 sizeof_operation <<= uimm (aarch64_get_instr (cpu), 11, 10);
10965 /* One register, immediate offset variant. */
10966 sizeof_operation = 8;
10970 /* Two registers, immediate offset variant. */
10971 sizeof_operation = 16;
10975 /* Three registers, immediate offset variant. */
10976 sizeof_operation = 24;
10980 /* Four registers, immediate offset variant. */
10981 sizeof_operation = 32;
10988 if (uimm (aarch64_get_instr (cpu), 30, 30))
10989 sizeof_operation *= 2;
10991 aarch64_set_reg_u64 (cpu, vn, SP_OK, address + sizeof_operation);
10994 aarch64_set_reg_u64 (cpu, vn, SP_OK,
10995 address + aarch64_get_reg_u64 (cpu, vm, NO_SP));
10999 NYI_assert (20, 16, 0);
11006 case 0: LD4 (cpu, address); return;
11007 case 4: LD3 (cpu, address); return;
11008 case 8: LD2 (cpu, address); return;
11009 case 2: LD1_4 (cpu, address); return;
11010 case 6: LD1_3 (cpu, address); return;
11011 case 10: LD1_2 (cpu, address); return;
11012 case 7: LD1_1 (cpu, address); return;
11015 case 0xC: do_vec_LDnR (cpu, address); return;
11025 case 0: ST4 (cpu, address); return;
11026 case 4: ST3 (cpu, address); return;
11027 case 8: ST2 (cpu, address); return;
11028 case 2: ST1_4 (cpu, address); return;
11029 case 6: ST1_3 (cpu, address); return;
11030 case 10: ST1_2 (cpu, address); return;
11031 case 7: ST1_1 (cpu, address); return;
11038 dexLdSt (sim_cpu *cpu)
11040 /* uint32_t group = dispatchGroup (aarch64_get_instr (cpu));
11041 assert group == GROUP_LDST_0100 || group == GROUP_LDST_0110 ||
11042 group == GROUP_LDST_1100 || group == GROUP_LDST_1110
11043 bits [29,28:26] of a LS are the secondary dispatch vector. */
11044 uint32_t group2 = dispatchLS (aarch64_get_instr (cpu));
11049 dexLoadExclusive (cpu); return;
11053 dexLoadLiteral (cpu); return;
11057 dexLoadOther (cpu); return;
11059 case LS_ADVSIMD_001:
11060 do_vec_load_store (cpu); return;
11063 dex_load_store_pair_gr (cpu); return;
11066 dex_load_store_pair_fp (cpu); return;
11069 /* Should never reach here. */
11074 /* Specific decode and execute for group Data Processing Register. */
11077 dexLogicalShiftedRegister (sim_cpu *cpu)
11079 /* assert instr[28:24] = 01010
11080 instr[31] = size : 0 ==> 32 bit, 1 ==> 64 bit
11081 instr[30,29:21] = op,N : 000 ==> AND, 001 ==> BIC,
11082 010 ==> ORR, 011 ==> ORN
11083 100 ==> EOR, 101 ==> EON,
11084 110 ==> ANDS, 111 ==> BICS
11085 instr[23,22] = shift : 0 ==> LSL, 1 ==> LSR, 2 ==> ASR, 3 ==> ROR
11086 instr[15,10] = count : must be 0xxxxx for 32 bit
11090 /* unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16); */
11093 uint32_t size = uimm (aarch64_get_instr (cpu), 31, 31);
11095 /* 32 bit operations must have count[5] = 0. */
11096 /* or else we have an UNALLOC. */
11097 uint32_t count = uimm (aarch64_get_instr (cpu), 15, 10);
11099 if (!size && uimm (count, 5, 5))
11102 shiftType = shift (aarch64_get_instr (cpu), 22);
11104 /* dispatch on size:op:N i.e aarch64_get_instr (cpu)[31,29:21]. */
11105 dispatch = ( (uimm (aarch64_get_instr (cpu), 31, 29) << 1)
11106 | uimm (aarch64_get_instr (cpu), 21, 21));
11110 case 0: and32_shift (cpu, shiftType, count); return;
11111 case 1: bic32_shift (cpu, shiftType, count); return;
11112 case 2: orr32_shift (cpu, shiftType, count); return;
11113 case 3: orn32_shift (cpu, shiftType, count); return;
11114 case 4: eor32_shift (cpu, shiftType, count); return;
11115 case 5: eon32_shift (cpu, shiftType, count); return;
11116 case 6: ands32_shift (cpu, shiftType, count); return;
11117 case 7: bics32_shift (cpu, shiftType, count); return;
11118 case 8: and64_shift (cpu, shiftType, count); return;
11119 case 9: bic64_shift (cpu, shiftType, count); return;
11120 case 10:orr64_shift (cpu, shiftType, count); return;
11121 case 11:orn64_shift (cpu, shiftType, count); return;
11122 case 12:eor64_shift (cpu, shiftType, count); return;
11123 case 13:eon64_shift (cpu, shiftType, count); return;
11124 case 14:ands64_shift (cpu, shiftType, count); return;
11125 case 15:bics64_shift (cpu, shiftType, count); return;
11126 default: HALT_UNALLOC;
11130 /* 32 bit conditional select. */
11132 csel32 (sim_cpu *cpu, CondCode cc)
11134 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
11135 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
11136 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
11138 aarch64_set_reg_u64 (cpu, rd, NO_SP,
11139 testConditionCode (cpu, cc)
11140 ? aarch64_get_reg_u32 (cpu, rn, NO_SP)
11141 : aarch64_get_reg_u32 (cpu, rm, NO_SP));
11144 /* 64 bit conditional select. */
11146 csel64 (sim_cpu *cpu, CondCode cc)
11148 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
11149 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
11150 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
11152 aarch64_set_reg_u64 (cpu, rd, NO_SP,
11153 testConditionCode (cpu, cc)
11154 ? aarch64_get_reg_u64 (cpu, rn, NO_SP)
11155 : aarch64_get_reg_u64 (cpu, rm, NO_SP));
11158 /* 32 bit conditional increment. */
11160 csinc32 (sim_cpu *cpu, CondCode cc)
11162 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
11163 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
11164 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
11166 aarch64_set_reg_u64 (cpu, rd, NO_SP,
11167 testConditionCode (cpu, cc)
11168 ? aarch64_get_reg_u32 (cpu, rn, NO_SP)
11169 : aarch64_get_reg_u32 (cpu, rm, NO_SP) + 1);
11172 /* 64 bit conditional increment. */
11174 csinc64 (sim_cpu *cpu, CondCode cc)
11176 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
11177 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
11178 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
11180 aarch64_set_reg_u64 (cpu, rd, NO_SP,
11181 testConditionCode (cpu, cc)
11182 ? aarch64_get_reg_u64 (cpu, rn, NO_SP)
11183 : aarch64_get_reg_u64 (cpu, rm, NO_SP) + 1);
11186 /* 32 bit conditional invert. */
11188 csinv32 (sim_cpu *cpu, CondCode cc)
11190 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
11191 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
11192 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
11194 aarch64_set_reg_u64 (cpu, rd, NO_SP,
11195 testConditionCode (cpu, cc)
11196 ? aarch64_get_reg_u32 (cpu, rn, NO_SP)
11197 : ~ aarch64_get_reg_u32 (cpu, rm, NO_SP));
11200 /* 64 bit conditional invert. */
11202 csinv64 (sim_cpu *cpu, CondCode cc)
11204 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
11205 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
11206 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
11208 aarch64_set_reg_u64 (cpu, rd, NO_SP,
11209 testConditionCode (cpu, cc)
11210 ? aarch64_get_reg_u64 (cpu, rn, NO_SP)
11211 : ~ aarch64_get_reg_u64 (cpu, rm, NO_SP));
11214 /* 32 bit conditional negate. */
11216 csneg32 (sim_cpu *cpu, CondCode cc)
11218 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
11219 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
11220 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
11222 aarch64_set_reg_u64 (cpu, rd, NO_SP,
11223 testConditionCode (cpu, cc)
11224 ? aarch64_get_reg_u32 (cpu, rn, NO_SP)
11225 : - aarch64_get_reg_u32 (cpu, rm, NO_SP));
11228 /* 64 bit conditional negate. */
11230 csneg64 (sim_cpu *cpu, CondCode cc)
11232 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
11233 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
11234 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
11236 aarch64_set_reg_u64 (cpu, rd, NO_SP,
11237 testConditionCode (cpu, cc)
11238 ? aarch64_get_reg_u64 (cpu, rn, NO_SP)
11239 : - aarch64_get_reg_u64 (cpu, rm, NO_SP));
11243 dexCondSelect (sim_cpu *cpu)
11245 /* assert instr[28,21] = 11011011
11246 instr[31] = size : 0 ==> 32 bit, 1 ==> 64 bit
11247 instr[30:11,10] = op : 000 ==> CSEL, 001 ==> CSINC,
11248 100 ==> CSINV, 101 ==> CSNEG,
11250 instr[29] = S : 0 ==> ok, 1 ==> UNALLOC
11251 instr[15,12] = cond
11252 instr[29] = S : 0 ==> ok, 1 ==> UNALLOC */
11256 uint32_t S = uimm (aarch64_get_instr (cpu), 29, 29);
11257 uint32_t op2 = uimm (aarch64_get_instr (cpu), 11, 10);
11265 cc = condcode (aarch64_get_instr (cpu), 12);
11266 dispatch = ((uimm (aarch64_get_instr (cpu), 31, 30) << 1) | op2);
11270 case 0: csel32 (cpu, cc); return;
11271 case 1: csinc32 (cpu, cc); return;
11272 case 2: csinv32 (cpu, cc); return;
11273 case 3: csneg32 (cpu, cc); return;
11274 case 4: csel64 (cpu, cc); return;
11275 case 5: csinc64 (cpu, cc); return;
11276 case 6: csinv64 (cpu, cc); return;
11277 case 7: csneg64 (cpu, cc); return;
11278 default: HALT_UNALLOC;
11282 /* Some helpers for counting leading 1 or 0 bits. */
11284 /* Counts the number of leading bits which are the same
11285 in a 32 bit value in the range 1 to 32. */
11287 leading32 (uint32_t value)
11289 int32_t mask= 0xffff0000;
11290 uint32_t count= 16; /* Counts number of bits set in mask. */
11291 uint32_t lo = 1; /* Lower bound for number of sign bits. */
11292 uint32_t hi = 32; /* Upper bound for number of sign bits. */
11294 while (lo + 1 < hi)
11296 int32_t test = (value & mask);
11298 if (test == 0 || test == mask)
11301 count = (lo + hi) / 2;
11302 mask >>= (count - lo);
11307 count = (lo + hi) / 2;
11308 mask <<= hi - count;
11317 test = (value & mask);
11319 if (test == 0 || test == mask)
11328 /* Counts the number of leading bits which are the same
11329 in a 64 bit value in the range 1 to 64. */
11331 leading64 (uint64_t value)
11333 int64_t mask= 0xffffffff00000000LL;
11334 uint64_t count = 32; /* Counts number of bits set in mask. */
11335 uint64_t lo = 1; /* Lower bound for number of sign bits. */
11336 uint64_t hi = 64; /* Upper bound for number of sign bits. */
11338 while (lo + 1 < hi)
11340 int64_t test = (value & mask);
11342 if (test == 0 || test == mask)
11345 count = (lo + hi) / 2;
11346 mask >>= (count - lo);
11351 count = (lo + hi) / 2;
11352 mask <<= hi - count;
11361 test = (value & mask);
11363 if (test == 0 || test == mask)
11372 /* Bit operations. */
11373 /* N.B register args may not be SP. */
11375 /* 32 bit count leading sign bits. */
11377 cls32 (sim_cpu *cpu)
11379 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
11380 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
11382 /* N.B. the result needs to exclude the leading bit. */
11383 aarch64_set_reg_u64
11384 (cpu, rd, NO_SP, leading32 (aarch64_get_reg_u32 (cpu, rn, NO_SP)) - 1);
11387 /* 64 bit count leading sign bits. */
11389 cls64 (sim_cpu *cpu)
11391 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
11392 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
11394 /* N.B. the result needs to exclude the leading bit. */
11395 aarch64_set_reg_u64
11396 (cpu, rd, NO_SP, leading64 (aarch64_get_reg_u64 (cpu, rn, NO_SP)) - 1);
11399 /* 32 bit count leading zero bits. */
11401 clz32 (sim_cpu *cpu)
11403 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
11404 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
11405 uint32_t value = aarch64_get_reg_u32 (cpu, rn, NO_SP);
11407 /* if the sign (top) bit is set then the count is 0. */
11408 if (pick32 (value, 31, 31))
11409 aarch64_set_reg_u64 (cpu, rd, NO_SP, 0L);
11411 aarch64_set_reg_u64 (cpu, rd, NO_SP, leading32 (value));
11414 /* 64 bit count leading zero bits. */
11416 clz64 (sim_cpu *cpu)
11418 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
11419 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
11420 uint64_t value = aarch64_get_reg_u64 (cpu, rn, NO_SP);
11422 /* if the sign (top) bit is set then the count is 0. */
11423 if (pick64 (value, 63, 63))
11424 aarch64_set_reg_u64 (cpu, rd, NO_SP, 0L);
11426 aarch64_set_reg_u64 (cpu, rd, NO_SP, leading64 (value));
11429 /* 32 bit reverse bits. */
11431 rbit32 (sim_cpu *cpu)
11433 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
11434 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
11435 uint32_t value = aarch64_get_reg_u32 (cpu, rn, NO_SP);
11436 uint32_t result = 0;
11439 for (i = 0; i < 32; i++)
11442 result |= (value & 1);
11445 aarch64_set_reg_u64 (cpu, rd, NO_SP, result);
11448 /* 64 bit reverse bits. */
11450 rbit64 (sim_cpu *cpu)
11452 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
11453 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
11454 uint64_t value = aarch64_get_reg_u64 (cpu, rn, NO_SP);
11455 uint64_t result = 0;
11458 for (i = 0; i < 64; i++)
11461 result |= (value & 1UL);
11464 aarch64_set_reg_u64 (cpu, rd, NO_SP, result);
11467 /* 32 bit reverse bytes. */
11469 rev32 (sim_cpu *cpu)
11471 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
11472 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
11473 uint32_t value = aarch64_get_reg_u32 (cpu, rn, NO_SP);
11474 uint32_t result = 0;
11477 for (i = 0; i < 4; i++)
11480 result |= (value & 0xff);
11483 aarch64_set_reg_u64 (cpu, rd, NO_SP, result);
11486 /* 64 bit reverse bytes. */
11488 rev64 (sim_cpu *cpu)
11490 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
11491 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
11492 uint64_t value = aarch64_get_reg_u64 (cpu, rn, NO_SP);
11493 uint64_t result = 0;
11496 for (i = 0; i < 8; i++)
11499 result |= (value & 0xffULL);
11502 aarch64_set_reg_u64 (cpu, rd, NO_SP, result);
11505 /* 32 bit reverse shorts. */
11506 /* N.B.this reverses the order of the bytes in each half word. */
11508 revh32 (sim_cpu *cpu)
11510 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
11511 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
11512 uint32_t value = aarch64_get_reg_u32 (cpu, rn, NO_SP);
11513 uint32_t result = 0;
11516 for (i = 0; i < 2; i++)
11519 result |= (value & 0x00ff00ff);
11522 aarch64_set_reg_u64 (cpu, rd, NO_SP, result);
11525 /* 64 bit reverse shorts. */
11526 /* N.B.this reverses the order of the bytes in each half word. */
11528 revh64 (sim_cpu *cpu)
11530 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
11531 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
11532 uint64_t value = aarch64_get_reg_u64 (cpu, rn, NO_SP);
11533 uint64_t result = 0;
11536 for (i = 0; i < 2; i++)
11539 result |= (value & 0x00ff00ff00ff00ffULL);
11542 aarch64_set_reg_u64 (cpu, rd, NO_SP, result);
11546 dexDataProc1Source (sim_cpu *cpu)
11548 /* assert instr[30] == 1
11549 aarch64_get_instr (cpu)[28,21] == 111010110
11550 instr[31] = size : 0 ==> 32 bit, 1 ==> 64 bit
11551 instr[29] = S : 0 ==> ok, 1 ==> UNALLOC
11552 instr[20,16] = opcode2 : 00000 ==> ok, ow ==> UNALLOC
11553 instr[15,10] = opcode : 000000 ==> RBIT, 000001 ==> REV16,
11554 000010 ==> REV, 000011 ==> UNALLOC
11555 000100 ==> CLZ, 000101 ==> CLS
11557 instr[9,5] = rn : may not be SP
11558 instr[4,0] = rd : may not be SP. */
11560 uint32_t S = uimm (aarch64_get_instr (cpu), 29, 29);
11561 uint32_t opcode2 = uimm (aarch64_get_instr (cpu), 20, 16);
11562 uint32_t opcode = uimm (aarch64_get_instr (cpu), 15, 10);
11563 uint32_t dispatch = ((uimm (aarch64_get_instr (cpu), 31, 31) << 3) | opcode);
11576 case 0: rbit32 (cpu); return;
11577 case 1: revh32 (cpu); return;
11578 case 2: rev32 (cpu); return;
11579 case 4: clz32 (cpu); return;
11580 case 5: cls32 (cpu); return;
11581 case 8: rbit64 (cpu); return;
11582 case 9: revh64 (cpu); return;
11583 case 10:rev32 (cpu); return;
11584 case 11:rev64 (cpu); return;
11585 case 12:clz64 (cpu); return;
11586 case 13:cls64 (cpu); return;
11587 default: HALT_UNALLOC;
11592 Shifts by count supplied in register.
11593 N.B register args may not be SP.
11594 These all use the shifted auxiliary function for
11595 simplicity and clarity. Writing the actual shift
11596 inline would avoid a branch and so be faster but
11597 would also necessitate getting signs right. */
11599 /* 32 bit arithmetic shift right. */
11601 asrv32 (sim_cpu *cpu)
11603 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
11604 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
11605 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
11607 aarch64_set_reg_u64
11609 shifted32 (aarch64_get_reg_u32 (cpu, rn, NO_SP), ASR,
11610 (aarch64_get_reg_u32 (cpu, rm, NO_SP) & 0x1f)));
11613 /* 64 bit arithmetic shift right. */
11615 asrv64 (sim_cpu *cpu)
11617 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
11618 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
11619 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
11621 aarch64_set_reg_u64
11623 shifted64 (aarch64_get_reg_u64 (cpu, rn, NO_SP), ASR,
11624 (aarch64_get_reg_u64 (cpu, rm, NO_SP) & 0x3f)));
11627 /* 32 bit logical shift left. */
11629 lslv32 (sim_cpu *cpu)
11631 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
11632 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
11633 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
11635 aarch64_set_reg_u64
11637 shifted32 (aarch64_get_reg_u32 (cpu, rn, NO_SP), LSL,
11638 (aarch64_get_reg_u32 (cpu, rm, NO_SP) & 0x1f)));
11641 /* 64 bit arithmetic shift left. */
11643 lslv64 (sim_cpu *cpu)
11645 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
11646 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
11647 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
11649 aarch64_set_reg_u64
11651 shifted64 (aarch64_get_reg_u64 (cpu, rn, NO_SP), LSL,
11652 (aarch64_get_reg_u64 (cpu, rm, NO_SP) & 0x3f)));
11655 /* 32 bit logical shift right. */
11657 lsrv32 (sim_cpu *cpu)
11659 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
11660 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
11661 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
11663 aarch64_set_reg_u64
11665 shifted32 (aarch64_get_reg_u32 (cpu, rn, NO_SP), LSR,
11666 (aarch64_get_reg_u32 (cpu, rm, NO_SP) & 0x1f)));
11669 /* 64 bit logical shift right. */
11671 lsrv64 (sim_cpu *cpu)
11673 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
11674 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
11675 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
11677 aarch64_set_reg_u64
11679 shifted64 (aarch64_get_reg_u64 (cpu, rn, NO_SP), LSR,
11680 (aarch64_get_reg_u64 (cpu, rm, NO_SP) & 0x3f)));
11683 /* 32 bit rotate right. */
11685 rorv32 (sim_cpu *cpu)
11687 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
11688 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
11689 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
11691 aarch64_set_reg_u64
11693 shifted32 (aarch64_get_reg_u32 (cpu, rn, NO_SP), ROR,
11694 (aarch64_get_reg_u32 (cpu, rm, NO_SP) & 0x1f)));
11697 /* 64 bit rotate right. */
11699 rorv64 (sim_cpu *cpu)
11701 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
11702 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
11703 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
11705 aarch64_set_reg_u64
11707 shifted64 (aarch64_get_reg_u64 (cpu, rn, NO_SP), ROR,
11708 (aarch64_get_reg_u64 (cpu, rm, NO_SP) & 0x3f)));
11714 /* 32 bit signed divide. */
11716 cpuiv32 (sim_cpu *cpu)
11718 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
11719 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
11720 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
11721 /* N.B. the pseudo-code does the divide using 64 bit data. */
11722 /* TODO : check that this rounds towards zero as required. */
11723 int64_t dividend = aarch64_get_reg_s32 (cpu, rn, NO_SP);
11724 int64_t divisor = aarch64_get_reg_s32 (cpu, rm, NO_SP);
11726 aarch64_set_reg_s64 (cpu, rd, NO_SP,
11727 divisor ? ((int32_t) (dividend / divisor)) : 0);
11730 /* 64 bit signed divide. */
11732 cpuiv64 (sim_cpu *cpu)
11734 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
11735 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
11736 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
11738 /* TODO : check that this rounds towards zero as required. */
11739 int64_t divisor = aarch64_get_reg_s64 (cpu, rm, NO_SP);
11741 aarch64_set_reg_s64
11743 divisor ? (aarch64_get_reg_s64 (cpu, rn, NO_SP) / divisor) : 0);
11746 /* 32 bit unsigned divide. */
11748 udiv32 (sim_cpu *cpu)
11750 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
11751 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
11752 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
11754 /* N.B. the pseudo-code does the divide using 64 bit data. */
11755 uint64_t dividend = aarch64_get_reg_u32 (cpu, rn, NO_SP);
11756 uint64_t divisor = aarch64_get_reg_u32 (cpu, rm, NO_SP);
11758 aarch64_set_reg_u64 (cpu, rd, NO_SP,
11759 divisor ? (uint32_t) (dividend / divisor) : 0);
11762 /* 64 bit unsigned divide. */
11764 udiv64 (sim_cpu *cpu)
11766 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
11767 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
11768 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
11770 /* TODO : check that this rounds towards zero as required. */
11771 uint64_t divisor = aarch64_get_reg_u64 (cpu, rm, NO_SP);
11773 aarch64_set_reg_u64
11775 divisor ? (aarch64_get_reg_u64 (cpu, rn, NO_SP) / divisor) : 0);
11779 dexDataProc2Source (sim_cpu *cpu)
11781 /* assert instr[30] == 0
11782 instr[28,21] == 11010110
11783 instr[31] = size : 0 ==> 32 bit, 1 ==> 64 bit
11784 instr[29] = S : 0 ==> ok, 1 ==> UNALLOC
11785 instr[15,10] = opcode : 000010 ==> UDIV, 000011 ==> CPUIV,
11786 001000 ==> LSLV, 001001 ==> LSRV
11787 001010 ==> ASRV, 001011 ==> RORV
11791 uint32_t S = uimm (aarch64_get_instr (cpu), 29, 29);
11792 uint32_t opcode = uimm (aarch64_get_instr (cpu), 15, 10);
11800 dispatch = ( (uimm (aarch64_get_instr (cpu), 31, 31) << 3)
11801 | (uimm (opcode, 3, 3) << 2)
11802 | uimm (opcode, 1, 0));
11805 case 2: udiv32 (cpu); return;
11806 case 3: cpuiv32 (cpu); return;
11807 case 4: lslv32 (cpu); return;
11808 case 5: lsrv32 (cpu); return;
11809 case 6: asrv32 (cpu); return;
11810 case 7: rorv32 (cpu); return;
11811 case 10: udiv64 (cpu); return;
11812 case 11: cpuiv64 (cpu); return;
11813 case 12: lslv64 (cpu); return;
11814 case 13: lsrv64 (cpu); return;
11815 case 14: asrv64 (cpu); return;
11816 case 15: rorv64 (cpu); return;
11817 default: HALT_UNALLOC;
11824 /* 32 bit multiply and add. */
11826 madd32 (sim_cpu *cpu)
11828 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
11829 unsigned ra = uimm (aarch64_get_instr (cpu), 14, 10);
11830 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
11831 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
11833 aarch64_set_reg_u64 (cpu, rd, NO_SP,
11834 aarch64_get_reg_u32 (cpu, ra, NO_SP)
11835 + aarch64_get_reg_u32 (cpu, rn, NO_SP)
11836 * aarch64_get_reg_u32 (cpu, rm, NO_SP));
11839 /* 64 bit multiply and add. */
11841 madd64 (sim_cpu *cpu)
11843 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
11844 unsigned ra = uimm (aarch64_get_instr (cpu), 14, 10);
11845 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
11846 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
11848 aarch64_set_reg_u64 (cpu, rd, NO_SP,
11849 aarch64_get_reg_u64 (cpu, ra, NO_SP)
11850 + aarch64_get_reg_u64 (cpu, rn, NO_SP)
11851 * aarch64_get_reg_u64 (cpu, rm, NO_SP));
11854 /* 32 bit multiply and sub. */
11856 msub32 (sim_cpu *cpu)
11858 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
11859 unsigned ra = uimm (aarch64_get_instr (cpu), 14, 10);
11860 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
11861 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
11863 aarch64_set_reg_u64 (cpu, rd, NO_SP,
11864 aarch64_get_reg_u32 (cpu, ra, NO_SP)
11865 - aarch64_get_reg_u32 (cpu, rn, NO_SP)
11866 * aarch64_get_reg_u32 (cpu, rm, NO_SP));
11869 /* 64 bit multiply and sub. */
11871 msub64 (sim_cpu *cpu)
11873 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
11874 unsigned ra = uimm (aarch64_get_instr (cpu), 14, 10);
11875 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
11876 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
11878 aarch64_set_reg_u64 (cpu, rd, NO_SP,
11879 aarch64_get_reg_u64 (cpu, ra, NO_SP)
11880 - aarch64_get_reg_u64 (cpu, rn, NO_SP)
11881 * aarch64_get_reg_u64 (cpu, rm, NO_SP));
11884 /* Signed multiply add long -- source, source2 : 32 bit, source3 : 64 bit. */
11886 smaddl (sim_cpu *cpu)
11888 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
11889 unsigned ra = uimm (aarch64_get_instr (cpu), 14, 10);
11890 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
11891 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
11893 /* N.B. we need to multiply the signed 32 bit values in rn, rm to
11894 obtain a 64 bit product. */
11895 aarch64_set_reg_s64
11897 aarch64_get_reg_s64 (cpu, ra, NO_SP)
11898 + ((int64_t) aarch64_get_reg_s32 (cpu, rn, NO_SP))
11899 * ((int64_t) aarch64_get_reg_s32 (cpu, rm, NO_SP)));
11902 /* Signed multiply sub long -- source, source2 : 32 bit, source3 : 64 bit. */
11904 smsubl (sim_cpu *cpu)
11906 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
11907 unsigned ra = uimm (aarch64_get_instr (cpu), 14, 10);
11908 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
11909 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
11911 /* N.B. we need to multiply the signed 32 bit values in rn, rm to
11912 obtain a 64 bit product. */
11913 aarch64_set_reg_s64
11915 aarch64_get_reg_s64 (cpu, ra, NO_SP)
11916 - ((int64_t) aarch64_get_reg_s32 (cpu, rn, NO_SP))
11917 * ((int64_t) aarch64_get_reg_s32 (cpu, rm, NO_SP)));
11920 /* Integer Multiply/Divide. */
11922 /* First some macros and a helper function. */
11923 /* Macros to test or access elements of 64 bit words. */
11925 /* Mask used to access lo 32 bits of 64 bit unsigned int. */
11926 #define LOW_WORD_MASK ((1ULL << 32) - 1)
11927 /* Return the lo 32 bit word of a 64 bit unsigned int as a 64 bit unsigned int. */
11928 #define lowWordToU64(_value_u64) ((_value_u64) & LOW_WORD_MASK)
11929 /* Return the hi 32 bit word of a 64 bit unsigned int as a 64 bit unsigned int. */
11930 #define highWordToU64(_value_u64) ((_value_u64) >> 32)
11932 /* Offset of sign bit in 64 bit signed integger. */
11933 #define SIGN_SHIFT_U64 63
11934 /* The sign bit itself -- also identifies the minimum negative int value. */
11935 #define SIGN_BIT_U64 (1UL << SIGN_SHIFT_U64)
11936 /* Return true if a 64 bit signed int presented as an unsigned int is the
11937 most negative value. */
11938 #define isMinimumU64(_value_u64) ((_value_u64) == SIGN_BIT_U64)
11939 /* Return true (non-zero) if a 64 bit signed int presented as an unsigned
11940 int has its sign bit set to false. */
11941 #define isSignSetU64(_value_u64) ((_value_u64) & SIGN_BIT_U64)
11942 /* Return 1L or -1L according to whether a 64 bit signed int presented as
11943 an unsigned int has its sign bit set or not. */
11944 #define signOfU64(_value_u64) (1L + (((value_u64) >> SIGN_SHIFT_U64) * -2L)
11945 /* Clear the sign bit of a 64 bit signed int presented as an unsigned int. */
11946 #define clearSignU64(_value_u64) ((_value_u64) &= ~SIGN_BIT_U64)
11948 /* Multiply two 64 bit ints and return.
11949 the hi 64 bits of the 128 bit product. */
11952 mul64hi (uint64_t value1, uint64_t value2)
11954 uint64_t resultmid1;
11956 uint64_t value1_lo = lowWordToU64 (value1);
11957 uint64_t value1_hi = highWordToU64 (value1) ;
11958 uint64_t value2_lo = lowWordToU64 (value2);
11959 uint64_t value2_hi = highWordToU64 (value2);
11961 /* Cross-multiply and collect results. */
11963 uint64_t xproductlo = value1_lo * value2_lo;
11964 uint64_t xproductmid1 = value1_lo * value2_hi;
11965 uint64_t xproductmid2 = value1_hi * value2_lo;
11966 uint64_t xproducthi = value1_hi * value2_hi;
11967 uint64_t carry = 0;
11968 /* Start accumulating 64 bit results. */
11969 /* Drop bottom half of lowest cross-product. */
11970 uint64_t resultmid = xproductlo >> 32;
11971 /* Add in middle products. */
11972 resultmid = resultmid + xproductmid1;
11974 /* Check for overflow. */
11975 if (resultmid < xproductmid1)
11976 /* Carry over 1 into top cross-product. */
11979 resultmid1 = resultmid + xproductmid2;
11981 /* Check for overflow. */
11982 if (resultmid1 < xproductmid2)
11983 /* Carry over 1 into top cross-product. */
11986 /* Drop lowest 32 bits of middle cross-product. */
11987 result = resultmid1 >> 32;
11989 /* Add top cross-product plus and any carry. */
11990 result += xproducthi + carry;
11995 /* Signed multiply high, source, source2 :
11996 64 bit, dest <-- high 64-bit of result. */
11998 smulh (sim_cpu *cpu)
12002 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
12003 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
12004 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
12005 GReg ra = greg (aarch64_get_instr (cpu), 10);
12006 int64_t value1 = aarch64_get_reg_u64 (cpu, rn, NO_SP);
12007 int64_t value2 = aarch64_get_reg_u64 (cpu, rm, NO_SP);
12010 int64_t signum = 1;
12015 /* Convert to unsigned and use the unsigned mul64hi routine
12016 the fix the sign up afterwards. */
12037 uresult = mul64hi (uvalue1, uvalue2);
12041 aarch64_set_reg_s64 (cpu, rd, NO_SP, result);
12044 /* Unsigned multiply add long -- source, source2 :
12045 32 bit, source3 : 64 bit. */
12047 umaddl (sim_cpu *cpu)
12049 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
12050 unsigned ra = uimm (aarch64_get_instr (cpu), 14, 10);
12051 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
12052 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
12054 /* N.B. we need to multiply the signed 32 bit values in rn, rm to
12055 obtain a 64 bit product. */
12056 aarch64_set_reg_u64
12058 aarch64_get_reg_u64 (cpu, ra, NO_SP)
12059 + ((uint64_t) aarch64_get_reg_u32 (cpu, rn, NO_SP))
12060 * ((uint64_t) aarch64_get_reg_u32 (cpu, rm, NO_SP)));
12063 /* Unsigned multiply sub long -- source, source2 : 32 bit, source3 : 64 bit. */
12065 umsubl (sim_cpu *cpu)
12067 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
12068 unsigned ra = uimm (aarch64_get_instr (cpu), 14, 10);
12069 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
12070 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
12072 /* N.B. we need to multiply the signed 32 bit values in rn, rm to
12073 obtain a 64 bit product. */
12074 aarch64_set_reg_u64
12076 aarch64_get_reg_u64 (cpu, ra, NO_SP)
12077 - ((uint64_t) aarch64_get_reg_u32 (cpu, rn, NO_SP))
12078 * ((uint64_t) aarch64_get_reg_u32 (cpu, rm, NO_SP)));
12081 /* Unsigned multiply high, source, source2 :
12082 64 bit, dest <-- high 64-bit of result. */
12084 umulh (sim_cpu *cpu)
12086 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
12087 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
12088 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
12089 GReg ra = greg (aarch64_get_instr (cpu), 10);
12094 aarch64_set_reg_u64 (cpu, rd, NO_SP,
12095 mul64hi (aarch64_get_reg_u64 (cpu, rn, NO_SP),
12096 aarch64_get_reg_u64 (cpu, rm, NO_SP)));
12100 dexDataProc3Source (sim_cpu *cpu)
12102 /* assert instr[28,24] == 11011. */
12103 /* instr[31] = size : 0 ==> 32 bit, 1 ==> 64 bit (for rd at least)
12104 instr[30,29] = op54 : 00 ==> ok, ow ==> UNALLOC
12105 instr[23,21] = op31 : 111 ==> UNALLOC, o2 ==> ok
12106 instr[15] = o0 : 0/1 ==> ok
12107 instr[23,21:15] ==> op : 0000 ==> MADD, 0001 ==> MSUB, (32/64 bit)
12108 0010 ==> SMADDL, 0011 ==> SMSUBL, (64 bit only)
12109 0100 ==> SMULH, (64 bit only)
12110 1010 ==> UMADDL, 1011 ==> UNSUBL, (64 bit only)
12111 1100 ==> UMULH (64 bit only)
12115 uint32_t size = uimm (aarch64_get_instr (cpu), 31, 31);
12116 uint32_t op54 = uimm (aarch64_get_instr (cpu), 30, 29);
12117 uint32_t op31 = uimm (aarch64_get_instr (cpu), 23, 21);
12118 uint32_t o0 = uimm (aarch64_get_instr (cpu), 15, 15);
12135 dispatch = (op31 << 1) | o0;
12139 case 0: madd64 (cpu); return;
12140 case 1: msub64 (cpu); return;
12141 case 2: smaddl (cpu); return;
12142 case 3: smsubl (cpu); return;
12143 case 4: smulh (cpu); return;
12144 case 10: umaddl (cpu); return;
12145 case 11: umsubl (cpu); return;
12146 case 12: umulh (cpu); return;
12147 default: HALT_UNALLOC;
12152 dexDPReg (sim_cpu *cpu)
12154 /* uint32_t group = dispatchGroup (aarch64_get_instr (cpu));
12155 assert group == GROUP_DPREG_0101 || group == GROUP_DPREG_1101
12156 bits [28:24:21] of a DPReg are the secondary dispatch vector. */
12157 uint32_t group2 = dispatchDPReg (aarch64_get_instr (cpu));
12161 case DPREG_LOG_000:
12162 case DPREG_LOG_001:
12163 dexLogicalShiftedRegister (cpu); return;
12165 case DPREG_ADDSHF_010:
12166 dexAddSubtractShiftedRegister (cpu); return;
12168 case DPREG_ADDEXT_011:
12169 dexAddSubtractExtendedRegister (cpu); return;
12171 case DPREG_ADDCOND_100:
12173 /* This set bundles a variety of different operations. */
12175 /* 1) add/sub w carry. */
12176 uint32_t mask1 = 0x1FE00000U;
12177 uint32_t val1 = 0x1A000000U;
12178 /* 2) cond compare register/immediate. */
12179 uint32_t mask2 = 0x1FE00000U;
12180 uint32_t val2 = 0x1A400000U;
12181 /* 3) cond select. */
12182 uint32_t mask3 = 0x1FE00000U;
12183 uint32_t val3 = 0x1A800000U;
12184 /* 4) data proc 1/2 source. */
12185 uint32_t mask4 = 0x1FE00000U;
12186 uint32_t val4 = 0x1AC00000U;
12188 if ((aarch64_get_instr (cpu) & mask1) == val1)
12189 dexAddSubtractWithCarry (cpu);
12191 else if ((aarch64_get_instr (cpu) & mask2) == val2)
12194 else if ((aarch64_get_instr (cpu) & mask3) == val3)
12195 dexCondSelect (cpu);
12197 else if ((aarch64_get_instr (cpu) & mask4) == val4)
12199 /* Bit 30 is clear for data proc 2 source
12200 and set for data proc 1 source. */
12201 if (aarch64_get_instr (cpu) & (1U << 30))
12202 dexDataProc1Source (cpu);
12204 dexDataProc2Source (cpu);
12208 /* Should not reach here. */
12214 case DPREG_3SRC_110:
12215 dexDataProc3Source (cpu); return;
12217 case DPREG_UNALLOC_101:
12220 case DPREG_3SRC_111:
12221 dexDataProc3Source (cpu); return;
12224 /* Should never reach here. */
12229 /* Unconditional Branch immediate.
12230 Offset is a PC-relative byte offset in the range +/- 128MiB.
12231 The offset is assumed to be raw from the decode i.e. the
12232 simulator is expected to scale them from word offsets to byte. */
12234 /* Unconditional branch. */
12236 buc (sim_cpu *cpu, int32_t offset)
12238 aarch64_set_next_PC_by_offset (cpu, offset);
12241 static unsigned stack_depth = 0;
12243 /* Unconditional branch and link -- writes return PC to LR. */
12245 bl (sim_cpu *cpu, int32_t offset)
12247 aarch64_save_LR (cpu);
12248 aarch64_set_next_PC_by_offset (cpu, offset);
12250 if (TRACE_BRANCH_P (cpu))
12254 " %*scall %" PRIx64 " [%s]"
12255 " [args: %" PRIx64 " %" PRIx64 " %" PRIx64 "]",
12256 stack_depth, " ", aarch64_get_next_PC (cpu),
12257 aarch64_get_func (aarch64_get_next_PC (cpu)),
12258 aarch64_get_reg_u64 (cpu, 0, NO_SP),
12259 aarch64_get_reg_u64 (cpu, 1, NO_SP),
12260 aarch64_get_reg_u64 (cpu, 2, NO_SP)
12265 /* Unconditional Branch register.
12266 Branch/return address is in source register. */
12268 /* Unconditional branch. */
12272 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
12273 aarch64_set_next_PC (cpu, aarch64_get_reg_u64 (cpu, rn, NO_SP));
12276 /* Unconditional branch and link -- writes return PC to LR. */
12280 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
12282 /* The pseudo code in the spec says we update LR before fetching.
12283 the value from the rn. */
12284 aarch64_save_LR (cpu);
12285 aarch64_set_next_PC (cpu, aarch64_get_reg_u64 (cpu, rn, NO_SP));
12287 if (TRACE_BRANCH_P (cpu))
12291 " %*scall %" PRIx64 " [%s]"
12292 " [args: %" PRIx64 " %" PRIx64 " %" PRIx64 "]",
12293 stack_depth, " ", aarch64_get_next_PC (cpu),
12294 aarch64_get_func (aarch64_get_next_PC (cpu)),
12295 aarch64_get_reg_u64 (cpu, 0, NO_SP),
12296 aarch64_get_reg_u64 (cpu, 1, NO_SP),
12297 aarch64_get_reg_u64 (cpu, 2, NO_SP)
12302 /* Return -- assembler will default source to LR this is functionally
12303 equivalent to br but, presumably, unlike br it side effects the
12304 branch predictor. */
12308 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
12309 aarch64_set_next_PC (cpu, aarch64_get_reg_u64 (cpu, rn, NO_SP));
12311 if (TRACE_BRANCH_P (cpu))
12314 " %*sreturn [result: %" PRIx64 "]",
12315 stack_depth, " ", aarch64_get_reg_u64 (cpu, 0, NO_SP));
12320 /* NOP -- we implement this and call it from the decode in case we
12321 want to intercept it later. */
12328 /* Data synchronization barrier. */
12335 /* Data memory barrier. */
12342 /* Instruction synchronization barrier. */
12350 dexBranchImmediate (sim_cpu *cpu)
12352 /* assert instr[30,26] == 00101
12353 instr[31] ==> 0 == B, 1 == BL
12354 instr[25,0] == imm26 branch offset counted in words. */
12356 uint32_t top = uimm (aarch64_get_instr (cpu), 31, 31);
12357 /* We have a 26 byte signed word offset which we need to pass to the
12358 execute routine as a signed byte offset. */
12359 int32_t offset = simm32 (aarch64_get_instr (cpu), 25, 0) << 2;
12367 /* Control Flow. */
12369 /* Conditional branch
12371 Offset is a PC-relative byte offset in the range +/- 1MiB pos is
12372 a bit position in the range 0 .. 63
12374 cc is a CondCode enum value as pulled out of the decode
12376 N.B. any offset register (source) can only be Xn or Wn. */
12379 bcc (sim_cpu *cpu, int32_t offset, CondCode cc)
12381 /* the test returns TRUE if CC is met. */
12382 if (testConditionCode (cpu, cc))
12383 aarch64_set_next_PC_by_offset (cpu, offset);
12386 /* 32 bit branch on register non-zero. */
12388 cbnz32 (sim_cpu *cpu, int32_t offset)
12390 unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
12392 if (aarch64_get_reg_u32 (cpu, rt, NO_SP) != 0)
12393 aarch64_set_next_PC_by_offset (cpu, offset);
12396 /* 64 bit branch on register zero. */
12398 cbnz (sim_cpu *cpu, int32_t offset)
12400 unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
12402 if (aarch64_get_reg_u64 (cpu, rt, NO_SP) != 0)
12403 aarch64_set_next_PC_by_offset (cpu, offset);
12406 /* 32 bit branch on register non-zero. */
12408 cbz32 (sim_cpu *cpu, int32_t offset)
12410 unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
12412 if (aarch64_get_reg_u32 (cpu, rt, NO_SP) == 0)
12413 aarch64_set_next_PC_by_offset (cpu, offset);
12416 /* 64 bit branch on register zero. */
12418 cbz (sim_cpu *cpu, int32_t offset)
12420 unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
12422 if (aarch64_get_reg_u64 (cpu, rt, NO_SP) == 0)
12423 aarch64_set_next_PC_by_offset (cpu, offset);
12426 /* Branch on register bit test non-zero -- one size fits all. */
12428 tbnz (sim_cpu *cpu, uint32_t pos, int32_t offset)
12430 unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
12432 if (aarch64_get_reg_u64 (cpu, rt, NO_SP) & (1 << pos))
12433 aarch64_set_next_PC_by_offset (cpu, offset);
12436 /* branch on register bit test zero -- one size fits all. */
12438 tbz (sim_cpu *cpu, uint32_t pos, int32_t offset)
12440 unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
12442 if (!(aarch64_get_reg_u64 (cpu, rt, NO_SP) & (1 << pos)))
12443 aarch64_set_next_PC_by_offset (cpu, offset);
12447 dexCompareBranchImmediate (sim_cpu *cpu)
12449 /* instr[30,25] = 01 1010
12450 instr[31] = size : 0 ==> 32, 1 ==> 64
12451 instr[24] = op : 0 ==> CBZ, 1 ==> CBNZ
12452 instr[23,5] = simm19 branch offset counted in words
12455 uint32_t size = uimm (aarch64_get_instr (cpu), 31, 31);
12456 uint32_t op = uimm (aarch64_get_instr (cpu), 24, 24);
12457 int32_t offset = simm32 (aarch64_get_instr (cpu), 23, 5) << 2;
12462 cbz32 (cpu, offset);
12464 cbnz32 (cpu, offset);
12471 cbnz (cpu, offset);
12476 dexTestBranchImmediate (sim_cpu *cpu)
12478 /* instr[31] = b5 : bit 5 of test bit idx
12479 instr[30,25] = 01 1011
12480 instr[24] = op : 0 ==> TBZ, 1 == TBNZ
12481 instr[23,19] = b40 : bits 4 to 0 of test bit idx
12482 instr[18,5] = simm14 : signed offset counted in words
12483 instr[4,0] = uimm5 */
12485 uint32_t pos = ((uimm (aarch64_get_instr (cpu), 31, 31) << 4)
12486 | uimm (aarch64_get_instr (cpu), 23,19));
12487 int32_t offset = simm32 (aarch64_get_instr (cpu), 18, 5) << 2;
12489 NYI_assert (30, 25, 0x1b);
12491 if (uimm (aarch64_get_instr (cpu), 24, 24) == 0)
12492 tbz (cpu, pos, offset);
12494 tbnz (cpu, pos, offset);
12498 dexCondBranchImmediate (sim_cpu *cpu)
12500 /* instr[31,25] = 010 1010
12501 instr[24] = op1; op => 00 ==> B.cond
12502 instr[23,5] = simm19 : signed offset counted in words
12504 instr[3,0] = cond */
12508 uint32_t op = ((uimm (aarch64_get_instr (cpu), 24, 24) << 1)
12509 | uimm (aarch64_get_instr (cpu), 4, 4));
12511 NYI_assert (31, 25, 0x2a);
12516 offset = simm32 (aarch64_get_instr (cpu), 23, 5) << 2;
12517 cc = condcode (aarch64_get_instr (cpu), 0);
12519 bcc (cpu, offset, cc);
12523 dexBranchRegister (sim_cpu *cpu)
12525 /* instr[31,25] = 110 1011
12526 instr[24,21] = op : 0 ==> BR, 1 => BLR, 2 => RET, 3 => ERET, 4 => DRPS
12527 instr[20,16] = op2 : must be 11111
12528 instr[15,10] = op3 : must be 000000
12529 instr[4,0] = op2 : must be 11111. */
12531 uint32_t op = uimm (aarch64_get_instr (cpu), 24, 21);
12532 uint32_t op2 = uimm (aarch64_get_instr (cpu), 20, 16);
12533 uint32_t op3 = uimm (aarch64_get_instr (cpu), 15, 10);
12534 uint32_t op4 = uimm (aarch64_get_instr (cpu), 4, 0);
12536 NYI_assert (31, 25, 0x6b);
12538 if (op2 != 0x1F || op3 != 0 || op4 != 0)
12552 /* ERET and DRPS accept 0b11111 for rn = aarch64_get_instr (cpu)[4,0]. */
12553 /* anything else is unallocated. */
12554 uint32_t rn = greg (aarch64_get_instr (cpu), 0);
12559 if (op == 4 || op == 5)
12566 /* FIXME: We should get the Angel SWI values from ../../libgloss/aarch64/svc.h
12567 but this may not be available. So instead we define the values we need
12569 #define AngelSVC_Reason_Open 0x01
12570 #define AngelSVC_Reason_Close 0x02
12571 #define AngelSVC_Reason_Write 0x05
12572 #define AngelSVC_Reason_Read 0x06
12573 #define AngelSVC_Reason_IsTTY 0x09
12574 #define AngelSVC_Reason_Seek 0x0A
12575 #define AngelSVC_Reason_FLen 0x0C
12576 #define AngelSVC_Reason_Remove 0x0E
12577 #define AngelSVC_Reason_Rename 0x0F
12578 #define AngelSVC_Reason_Clock 0x10
12579 #define AngelSVC_Reason_Time 0x11
12580 #define AngelSVC_Reason_System 0x12
12581 #define AngelSVC_Reason_Errno 0x13
12582 #define AngelSVC_Reason_GetCmdLine 0x15
12583 #define AngelSVC_Reason_HeapInfo 0x16
12584 #define AngelSVC_Reason_ReportException 0x18
12585 #define AngelSVC_Reason_Elapsed 0x30
12589 handle_halt (sim_cpu *cpu, uint32_t val)
12591 uint64_t result = 0;
12595 TRACE_SYSCALL (cpu, " HLT [0x%x]", val);
12596 sim_engine_halt (CPU_STATE (cpu), cpu, NULL, aarch64_get_PC (cpu),
12597 sim_stopped, SIM_SIGTRAP);
12600 /* We have encountered an Angel SVC call. See if we can process it. */
12601 switch (aarch64_get_reg_u32 (cpu, 0, NO_SP))
12603 case AngelSVC_Reason_HeapInfo:
12605 /* Get the values. */
12606 uint64_t stack_top = aarch64_get_stack_start (cpu);
12607 uint64_t heap_base = aarch64_get_heap_start (cpu);
12609 /* Get the pointer */
12610 uint64_t ptr = aarch64_get_reg_u64 (cpu, 1, SP_OK);
12611 ptr = aarch64_get_mem_u64 (cpu, ptr);
12613 /* Fill in the memory block. */
12614 /* Start addr of heap. */
12615 aarch64_set_mem_u64 (cpu, ptr + 0, heap_base);
12616 /* End addr of heap. */
12617 aarch64_set_mem_u64 (cpu, ptr + 8, stack_top);
12618 /* Lowest stack addr. */
12619 aarch64_set_mem_u64 (cpu, ptr + 16, heap_base);
12620 /* Initial stack addr. */
12621 aarch64_set_mem_u64 (cpu, ptr + 24, stack_top);
12623 TRACE_SYSCALL (cpu, " AngelSVC: Get Heap Info");
12627 case AngelSVC_Reason_Open:
12629 /* Get the pointer */
12630 /* uint64_t ptr = aarch64_get_reg_u64 (cpu, 1, SP_OK);. */
12631 /* FIXME: For now we just assume that we will only be asked
12632 to open the standard file descriptors. */
12636 TRACE_SYSCALL (cpu, " AngelSVC: Open file %d", fd - 1);
12640 case AngelSVC_Reason_Close:
12642 uint64_t fh = aarch64_get_reg_u64 (cpu, 1, SP_OK);
12643 TRACE_SYSCALL (cpu, " AngelSVC: Close file %d", (int) fh);
12648 case AngelSVC_Reason_Errno:
12650 TRACE_SYSCALL (cpu, " AngelSVC: Get Errno");
12653 case AngelSVC_Reason_Clock:
12655 #ifdef CLOCKS_PER_SEC
12656 (CLOCKS_PER_SEC >= 100)
12657 ? (clock () / (CLOCKS_PER_SEC / 100))
12658 : ((clock () * 100) / CLOCKS_PER_SEC)
12660 /* Presume unix... clock() returns microseconds. */
12664 TRACE_SYSCALL (cpu, " AngelSVC: Get Clock");
12667 case AngelSVC_Reason_GetCmdLine:
12669 /* Get the pointer */
12670 uint64_t ptr = aarch64_get_reg_u64 (cpu, 1, SP_OK);
12671 ptr = aarch64_get_mem_u64 (cpu, ptr);
12673 /* FIXME: No command line for now. */
12674 aarch64_set_mem_u64 (cpu, ptr, 0);
12675 TRACE_SYSCALL (cpu, " AngelSVC: Get Command Line");
12679 case AngelSVC_Reason_IsTTY:
12681 TRACE_SYSCALL (cpu, " AngelSVC: IsTTY ?");
12684 case AngelSVC_Reason_Write:
12686 /* Get the pointer */
12687 uint64_t ptr = aarch64_get_reg_u64 (cpu, 1, SP_OK);
12688 /* Get the write control block. */
12689 uint64_t fd = aarch64_get_mem_u64 (cpu, ptr);
12690 uint64_t buf = aarch64_get_mem_u64 (cpu, ptr + 8);
12691 uint64_t len = aarch64_get_mem_u64 (cpu, ptr + 16);
12693 TRACE_SYSCALL (cpu, "write of %" PRIx64 " bytes from %"
12694 PRIx64 " on descriptor %" PRIx64,
12699 TRACE_SYSCALL (cpu,
12700 " AngelSVC: Write: Suspiciously long write: %ld",
12702 sim_engine_halt (CPU_STATE (cpu), cpu, NULL, aarch64_get_PC (cpu),
12703 sim_stopped, SIM_SIGBUS);
12707 printf ("%.*s", (int) len, aarch64_get_mem_ptr (cpu, buf));
12711 TRACE (cpu, 0, "\n");
12712 sim_io_eprintf (CPU_STATE (cpu), "%.*s",
12713 (int) len, aarch64_get_mem_ptr (cpu, buf));
12714 TRACE (cpu, 0, "\n");
12718 TRACE_SYSCALL (cpu,
12719 " AngelSVC: Write: Unexpected file handle: %d",
12721 sim_engine_halt (CPU_STATE (cpu), cpu, NULL, aarch64_get_PC (cpu),
12722 sim_stopped, SIM_SIGABRT);
12727 case AngelSVC_Reason_ReportException:
12729 /* Get the pointer */
12730 uint64_t ptr = aarch64_get_reg_u64 (cpu, 1, SP_OK);
12731 /*ptr = aarch64_get_mem_u64 (cpu, ptr);. */
12732 uint64_t type = aarch64_get_mem_u64 (cpu, ptr);
12733 uint64_t state = aarch64_get_mem_u64 (cpu, ptr + 8);
12735 TRACE_SYSCALL (cpu,
12736 "Angel Exception: type 0x%" PRIx64 " state %" PRIx64,
12739 if (type == 0x20026)
12740 sim_engine_halt (CPU_STATE (cpu), cpu, NULL, aarch64_get_PC (cpu),
12741 sim_exited, state);
12743 sim_engine_halt (CPU_STATE (cpu), cpu, NULL, aarch64_get_PC (cpu),
12744 sim_stopped, SIM_SIGINT);
12748 case AngelSVC_Reason_Read:
12749 case AngelSVC_Reason_FLen:
12750 case AngelSVC_Reason_Seek:
12751 case AngelSVC_Reason_Remove:
12752 case AngelSVC_Reason_Time:
12753 case AngelSVC_Reason_System:
12754 case AngelSVC_Reason_Rename:
12755 case AngelSVC_Reason_Elapsed:
12757 TRACE_SYSCALL (cpu, " HLT [Unknown angel %x]",
12758 aarch64_get_reg_u32 (cpu, 0, NO_SP));
12759 sim_engine_halt (CPU_STATE (cpu), cpu, NULL, aarch64_get_PC (cpu),
12760 sim_stopped, SIM_SIGTRAP);
12763 aarch64_set_reg_u64 (cpu, 0, NO_SP, result);
12767 dexExcpnGen (sim_cpu *cpu)
12769 /* instr[31:24] = 11010100
12770 instr[23,21] = opc : 000 ==> GEN EXCPN, 001 ==> BRK
12771 010 ==> HLT, 101 ==> DBG GEN EXCPN
12772 instr[20,5] = imm16
12773 instr[4,2] = opc2 000 ==> OK, ow ==> UNALLOC
12774 instr[1,0] = LL : discriminates opc */
12776 uint32_t opc = uimm (aarch64_get_instr (cpu), 23, 21);
12777 uint32_t imm16 = uimm (aarch64_get_instr (cpu), 20, 5);
12778 uint32_t opc2 = uimm (aarch64_get_instr (cpu), 4, 2);
12781 NYI_assert (31, 24, 0xd4);
12786 LL = uimm (aarch64_get_instr (cpu), 1, 0);
12788 /* We only implement HLT and BRK for now. */
12789 if (opc == 1 && LL == 0)
12791 TRACE_EVENTS (cpu, " BRK [0x%x]", imm16);
12792 sim_engine_halt (CPU_STATE (cpu), cpu, NULL, aarch64_get_PC (cpu),
12793 sim_exited, aarch64_get_reg_s32 (cpu, R0, SP_OK));
12796 if (opc == 2 && LL == 0)
12797 handle_halt (cpu, imm16);
12799 else if (opc == 0 || opc == 5)
12806 /* Stub for accessing system registers.
12807 We implement support for the DCZID register since this is used
12808 by the C library's memset function. */
12811 system_get (sim_cpu *cpu, unsigned op0, unsigned op1, unsigned crn,
12812 unsigned crm, unsigned op2)
12814 if (crn == 0 && op1 == 3 && crm == 0 && op2 == 7)
12815 /* DCZID_EL0 - the Data Cache Zero ID register.
12816 We do not support DC ZVA at the moment, so
12817 we return a value with the disable bit set. */
12818 return ((uint64_t) 1) << 4;
12824 do_mrs (sim_cpu *cpu)
12826 /* instr[31:20] = 1101 01010 0011
12833 unsigned sys_op0 = uimm (aarch64_get_instr (cpu), 19, 19) + 2;
12834 unsigned sys_op1 = uimm (aarch64_get_instr (cpu), 18, 16);
12835 unsigned sys_crn = uimm (aarch64_get_instr (cpu), 15, 12);
12836 unsigned sys_crm = uimm (aarch64_get_instr (cpu), 11, 8);
12837 unsigned sys_op2 = uimm (aarch64_get_instr (cpu), 7, 5);
12838 unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
12840 aarch64_set_reg_u64 (cpu, rt, NO_SP,
12841 system_get (cpu, sys_op0, sys_op1, sys_crn, sys_crm, sys_op2));
12845 dexSystem (sim_cpu *cpu)
12847 /* instr[31:22] = 1101 01010 0
12854 instr[4,0] = uimm5 */
12856 /* We are interested in HINT, DSB, DMB and ISB
12858 Hint #0 encodes NOOP (this is the only hint we care about)
12859 L == 0, op0 == 0, op1 = 011, CRn = 0010, Rt = 11111,
12860 CRm op2 != 0000 000 OR CRm op2 == 0000 000 || CRm op > 0000 101
12862 DSB, DMB, ISB are data store barrier, data memory barrier and
12863 instruction store barrier, respectively, where
12865 L == 0, op0 == 0, op1 = 011, CRn = 0011, Rt = 11111,
12866 op2 : DSB ==> 100, DMB ==> 101, ISB ==> 110
12867 CRm<3:2> ==> domain, CRm<1:0> ==> types,
12868 domain : 00 ==> OuterShareable, 01 ==> Nonshareable,
12869 10 ==> InerShareable, 11 ==> FullSystem
12870 types : 01 ==> Reads, 10 ==> Writes,
12871 11 ==> All, 00 ==> All (domain == FullSystem). */
12873 unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
12874 uint32_t l_op0_op1_crn = uimm (aarch64_get_instr (cpu), 21, 12);
12876 NYI_assert (31, 22, 0x354);
12878 switch (l_op0_op1_crn)
12883 /* NOP has CRm != 0000 OR. */
12884 /* (CRm == 0000 AND (op2 == 000 OR op2 > 101)). */
12885 uint32_t crm = uimm (aarch64_get_instr (cpu), 11, 8);
12886 uint32_t op2 = uimm (aarch64_get_instr (cpu), 7, 5);
12888 if (crm != 0 || (op2 == 0 || op2 > 5))
12890 /* Actually call nop method so we can reimplement it later. */
12899 uint32_t op2 = uimm (aarch64_get_instr (cpu), 7, 5);
12904 case 4: dsb (cpu); return;
12905 case 5: dmb (cpu); return;
12906 case 6: isb (cpu); return;
12908 default: HALT_UNALLOC;
12913 /* MRS Wt, sys-reg. */
12919 /* MRS Xt, sys-reg. */
12924 /* DC <type>, x<n>. */
12929 /* if (uimm (aarch64_get_instr (cpu), 21, 20) == 0x1)
12930 MRS Xt, sys-reg. */
12937 dexBr (sim_cpu *cpu)
12939 /* uint32_t group = dispatchGroup (aarch64_get_instr (cpu));
12940 assert group == GROUP_BREXSYS_1010 || group == GROUP_BREXSYS_1011
12941 bits [31,29] of a BrExSys are the secondary dispatch vector. */
12942 uint32_t group2 = dispatchBrExSys (aarch64_get_instr (cpu));
12947 return dexBranchImmediate (cpu);
12949 case BR_IMMCMP_001:
12950 /* Compare has bit 25 clear while test has it set. */
12951 if (!uimm (aarch64_get_instr (cpu), 25, 25))
12952 dexCompareBranchImmediate (cpu);
12954 dexTestBranchImmediate (cpu);
12957 case BR_IMMCOND_010:
12958 /* This is a conditional branch if bit 25 is clear otherwise
12960 if (!uimm (aarch64_get_instr (cpu), 25, 25))
12961 dexCondBranchImmediate (cpu);
12966 case BR_UNALLOC_011:
12970 dexBranchImmediate (cpu);
12973 case BR_IMMCMP_101:
12974 /* Compare has bit 25 clear while test has it set. */
12975 if (!uimm (aarch64_get_instr (cpu), 25, 25))
12976 dexCompareBranchImmediate (cpu);
12978 dexTestBranchImmediate (cpu);
12982 /* Unconditional branch reg has bit 25 set. */
12983 if (uimm (aarch64_get_instr (cpu), 25, 25))
12984 dexBranchRegister (cpu);
12986 /* This includes both Excpn Gen, System and unalloc operations.
12987 We need to decode the Excpn Gen operation BRK so we can plant
12988 debugger entry points.
12989 Excpn Gen operations have aarch64_get_instr (cpu)[24] = 0.
12990 we need to decode at least one of the System operations NOP
12991 which is an alias for HINT #0.
12992 System operations have aarch64_get_instr (cpu)[24,22] = 100. */
12993 else if (uimm (aarch64_get_instr (cpu), 24, 24) == 0)
12996 else if (uimm (aarch64_get_instr (cpu), 24, 22) == 4)
13004 case BR_UNALLOC_111:
13008 /* Should never reach here. */
13014 aarch64_decode_and_execute (sim_cpu *cpu, uint64_t pc)
13016 /* We need to check if gdb wants an in here. */
13017 /* checkBreak (cpu);. */
13019 uint64_t group = dispatchGroup (aarch64_get_instr (cpu));
13023 case GROUP_PSEUDO_0000: dexPseudo (cpu); break;
13024 case GROUP_LDST_0100: dexLdSt (cpu); break;
13025 case GROUP_DPREG_0101: dexDPReg (cpu); break;
13026 case GROUP_LDST_0110: dexLdSt (cpu); break;
13027 case GROUP_ADVSIMD_0111: dexAdvSIMD0 (cpu); break;
13028 case GROUP_DPIMM_1000: dexDPImm (cpu); break;
13029 case GROUP_DPIMM_1001: dexDPImm (cpu); break;
13030 case GROUP_BREXSYS_1010: dexBr (cpu); break;
13031 case GROUP_BREXSYS_1011: dexBr (cpu); break;
13032 case GROUP_LDST_1100: dexLdSt (cpu); break;
13033 case GROUP_DPREG_1101: dexDPReg (cpu); break;
13034 case GROUP_LDST_1110: dexLdSt (cpu); break;
13035 case GROUP_ADVSIMD_1111: dexAdvSIMD1 (cpu); break;
13037 case GROUP_UNALLOC_0001:
13038 case GROUP_UNALLOC_0010:
13039 case GROUP_UNALLOC_0011:
13043 /* Should never reach here. */
13049 aarch64_step (sim_cpu *cpu)
13051 uint64_t pc = aarch64_get_PC (cpu);
13053 if (pc == TOP_LEVEL_RETURN_PC)
13056 aarch64_set_next_PC (cpu, pc + 4);
13057 aarch64_get_instr (cpu) = aarch64_get_mem_u32 (cpu, pc);
13059 TRACE_INSN (cpu, " pc = %" PRIx64 " instr = %08x", pc,
13060 aarch64_get_instr (cpu));
13061 TRACE_DISASM (cpu, pc);
13063 aarch64_decode_and_execute (cpu, pc);
13069 aarch64_run (SIM_DESC sd)
13071 sim_cpu *cpu = STATE_CPU (sd, 0);
13073 while (aarch64_step (cpu))
13074 aarch64_update_PC (cpu);
13076 sim_engine_halt (sd, NULL, NULL, aarch64_get_PC (cpu),
13077 sim_exited, aarch64_get_reg_s32 (cpu, R0, SP_OK));
13081 aarch64_init (sim_cpu *cpu, uint64_t pc)
13083 uint64_t sp = aarch64_get_stack_start (cpu);
13085 /* Install SP, FP and PC and set LR to -20
13086 so we can detect a top-level return. */
13087 aarch64_set_reg_u64 (cpu, SP, SP_OK, sp);
13088 aarch64_set_reg_u64 (cpu, FP, SP_OK, sp);
13089 aarch64_set_reg_u64 (cpu, LR, SP_OK, TOP_LEVEL_RETURN_PC);
13090 aarch64_set_next_PC (cpu, pc);
13091 aarch64_update_PC (cpu);
13092 aarch64_init_LIT_table ();