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 )) ? 1 : 0)
40 #define IS_CLEAR(_X) (TST (( _X )) ? 0 : 1)
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_vec_u32 (cpu, rd, 0,
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_vec_u64 (cpu, st, 0,
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_vec_u32 (cpu, st, 0, aarch64_get_mem_u32 (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_vec_u32 (cpu, st, 0, aarch64_get_mem_u32
564 (cpu, aarch64_get_reg_u64 (cpu, rn, SP_OK)
565 + SCALE (offset, 32)));
568 /* Load 32 bit scaled or unscaled zero- or sign-extended
569 32-bit register offset. */
571 fldrs_scale_ext (sim_cpu *cpu, Scaling scaling, Extension extension)
573 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
574 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
575 unsigned st = uimm (aarch64_get_instr (cpu), 4, 0);
576 uint64_t address = aarch64_get_reg_u64 (cpu, rn, SP_OK);
577 int64_t extended = extend (aarch64_get_reg_u32 (cpu, rm, NO_SP), extension);
578 uint64_t displacement = OPT_SCALE (extended, 32, scaling);
580 aarch64_set_vec_u32 (cpu, st, 0, aarch64_get_mem_u32
581 (cpu, address + displacement));
584 /* Load 64 bit unscaled signed 9 bit with pre- or post-writeback. */
586 fldrd_wb (sim_cpu *cpu, int32_t offset, WriteBack wb)
588 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
589 unsigned st = uimm (aarch64_get_instr (cpu), 4, 0);
590 uint64_t address = aarch64_get_reg_u64 (cpu, rn, SP_OK);
595 aarch64_set_vec_u64 (cpu, st, 0, aarch64_get_mem_u64 (cpu, address));
600 if (wb != NoWriteBack)
601 aarch64_set_reg_u64 (cpu, rn, SP_OK, address);
604 /* Load 64 bit scaled unsigned 12 bit. */
606 fldrd_abs (sim_cpu *cpu, uint32_t offset)
608 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
609 unsigned st = uimm (aarch64_get_instr (cpu), 4, 0);
610 uint64_t address = aarch64_get_reg_u64 (cpu, rn, SP_OK) + SCALE (offset, 64);
612 aarch64_set_vec_u64 (cpu, st, 0, aarch64_get_mem_u64 (cpu, address));
615 /* Load 64 bit scaled or unscaled zero- or sign-extended 32-bit register offset. */
617 fldrd_scale_ext (sim_cpu *cpu, Scaling scaling, Extension extension)
619 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
620 int64_t extended = extend (aarch64_get_reg_u32 (cpu, rm, NO_SP), extension);
621 uint64_t displacement = OPT_SCALE (extended, 64, scaling);
623 fldrd_wb (cpu, displacement, NoWriteBack);
626 /* Load 128 bit unscaled signed 9 bit with pre- or post-writeback. */
628 fldrq_wb (sim_cpu *cpu, int32_t offset, WriteBack wb)
631 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
632 unsigned st = uimm (aarch64_get_instr (cpu), 4, 0);
633 uint64_t address = aarch64_get_reg_u64 (cpu, rn, SP_OK);
638 aarch64_get_mem_long_double (cpu, address, & a);
639 aarch64_set_FP_long_double (cpu, st, a);
644 if (wb != NoWriteBack)
645 aarch64_set_reg_u64 (cpu, rn, SP_OK, address);
648 /* Load 128 bit scaled unsigned 12 bit. */
650 fldrq_abs (sim_cpu *cpu, uint32_t offset)
653 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
654 unsigned st = uimm (aarch64_get_instr (cpu), 4, 0);
655 uint64_t address = aarch64_get_reg_u64 (cpu, rn, SP_OK) + SCALE (offset, 128);
657 aarch64_get_mem_long_double (cpu, address, & a);
658 aarch64_set_FP_long_double (cpu, st, a);
661 /* Load 128 bit scaled or unscaled zero- or sign-extended 32-bit register offset */
663 fldrq_scale_ext (sim_cpu *cpu, Scaling scaling, Extension extension)
665 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
666 int64_t extended = extend (aarch64_get_reg_u32 (cpu, rm, NO_SP), extension);
667 uint64_t displacement = OPT_SCALE (extended, 128, scaling);
669 fldrq_wb (cpu, displacement, NoWriteBack);
674 load-store single register
675 There are four addressing modes available here which all employ a
676 64 bit source (base) register.
678 N.B. the base register (source) can be the stack pointer.
679 The secondary source register (source2)can only be an Xn register.
681 Scaled, 12-bit, unsigned immediate offset, without pre- and
683 Unscaled, 9-bit, signed immediate offset with pre- or post-index
685 scaled or unscaled 64-bit register offset.
686 scaled or unscaled 32-bit extended register offset.
688 All offsets are assumed to be raw from the decode i.e. the
689 simulator is expected to adjust scaled offsets based on the
690 accessed data size with register or extended register offset
691 versions the same applies except that in the latter case the
692 operation may also require a sign extend.
694 A separate method is provided for each possible addressing mode. */
696 /* 32 bit load 32 bit scaled unsigned 12 bit */
698 ldr32_abs (sim_cpu *cpu, uint32_t offset)
700 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
701 unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
703 /* The target register may not be SP but the source may be. */
704 aarch64_set_reg_u64 (cpu, rt, NO_SP, aarch64_get_mem_u32
705 (cpu, aarch64_get_reg_u64 (cpu, rn, SP_OK)
706 + SCALE (offset, 32)));
709 /* 32 bit load 32 bit unscaled signed 9 bit with pre- or post-writeback. */
711 ldr32_wb (sim_cpu *cpu, int32_t offset, WriteBack wb)
713 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
714 unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
717 if (rn == rt && wb != NoWriteBack)
720 address = aarch64_get_reg_u64 (cpu, rn, SP_OK);
725 aarch64_set_reg_u64 (cpu, rt, NO_SP, aarch64_get_mem_u32 (cpu, address));
730 if (wb != NoWriteBack)
731 aarch64_set_reg_u64 (cpu, rn, SP_OK, address);
734 /* 32 bit load 32 bit scaled or unscaled
735 zero- or sign-extended 32-bit register offset */
737 ldr32_scale_ext (sim_cpu *cpu, Scaling scaling, Extension extension)
739 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
740 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
741 unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
742 /* rn may reference SP, rm and rt must reference ZR */
744 uint64_t address = aarch64_get_reg_u64 (cpu, rn, SP_OK);
745 int64_t extended = extend (aarch64_get_reg_u32 (cpu, rm, NO_SP), extension);
746 uint64_t displacement = OPT_SCALE (extended, 32, scaling);
748 aarch64_set_reg_u64 (cpu, rt, NO_SP,
749 aarch64_get_mem_u32 (cpu, address + displacement));
752 /* 64 bit load 64 bit scaled unsigned 12 bit */
754 ldr_abs (sim_cpu *cpu, uint32_t offset)
756 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
757 unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
759 /* The target register may not be SP but the source may be. */
760 aarch64_set_reg_u64 (cpu, rt, NO_SP, aarch64_get_mem_u64
761 (cpu, aarch64_get_reg_u64 (cpu, rn, SP_OK)
762 + SCALE (offset, 64)));
765 /* 64 bit load 64 bit unscaled signed 9 bit with pre- or post-writeback. */
767 ldr_wb (sim_cpu *cpu, int32_t offset, WriteBack wb)
769 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
770 unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
773 if (rn == rt && wb != NoWriteBack)
776 address = aarch64_get_reg_u64 (cpu, rn, SP_OK);
781 aarch64_set_reg_u64 (cpu, rt, NO_SP, aarch64_get_mem_u64 (cpu, address));
786 if (wb != NoWriteBack)
787 aarch64_set_reg_u64 (cpu, rn, SP_OK, address);
790 /* 64 bit load 64 bit scaled or unscaled zero-
791 or sign-extended 32-bit register offset. */
793 ldr_scale_ext (sim_cpu *cpu, Scaling scaling, Extension extension)
795 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
796 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
797 unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
798 /* rn may reference SP, rm and rt must reference ZR */
800 uint64_t address = aarch64_get_reg_u64 (cpu, rn, SP_OK);
801 int64_t extended = extend (aarch64_get_reg_u32 (cpu, rm, NO_SP), extension);
802 uint64_t displacement = OPT_SCALE (extended, 64, scaling);
804 aarch64_set_reg_u64 (cpu, rt, NO_SP,
805 aarch64_get_mem_u64 (cpu, address + displacement));
808 /* 32 bit load zero-extended byte scaled unsigned 12 bit. */
810 ldrb32_abs (sim_cpu *cpu, uint32_t offset)
812 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
813 unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
815 /* The target register may not be SP but the source may be
816 there is no scaling required for a byte load. */
817 aarch64_set_reg_u64 (cpu, rt, NO_SP,
819 (cpu, aarch64_get_reg_u64 (cpu, rn, SP_OK) + offset));
822 /* 32 bit load zero-extended byte unscaled signed 9 bit with pre- or post-writeback. */
824 ldrb32_wb (sim_cpu *cpu, int32_t offset, WriteBack wb)
826 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
827 unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
830 if (rn == rt && wb != NoWriteBack)
833 address = aarch64_get_reg_u64 (cpu, rn, SP_OK);
838 aarch64_set_reg_u64 (cpu, rt, NO_SP, aarch64_get_mem_u8 (cpu, address));
843 if (wb != NoWriteBack)
844 aarch64_set_reg_u64 (cpu, rn, SP_OK, address);
847 /* 32 bit load zero-extended byte scaled or unscaled zero-
848 or sign-extended 32-bit register offset. */
850 ldrb32_scale_ext (sim_cpu *cpu, Scaling scaling, Extension extension)
852 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
853 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
854 unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
855 /* rn may reference SP, rm and rt must reference ZR */
857 uint64_t address = aarch64_get_reg_u64 (cpu, rn, SP_OK);
858 int64_t displacement = extend (aarch64_get_reg_u32 (cpu, rm, NO_SP),
861 /* There is no scaling required for a byte load. */
862 aarch64_set_reg_u64 (cpu, rt, NO_SP,
863 aarch64_get_mem_u8 (cpu, address + displacement));
866 /* 64 bit load sign-extended byte unscaled signed 9 bit
867 with pre- or post-writeback. */
869 ldrsb_wb (sim_cpu *cpu, int32_t offset, WriteBack wb)
871 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
872 unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
875 if (rn == rt && wb != NoWriteBack)
878 address = aarch64_get_reg_u64 (cpu, rn, SP_OK);
883 aarch64_set_reg_u64 (cpu, rt, NO_SP, aarch64_get_mem_s8 (cpu, address));
888 if (wb != NoWriteBack)
889 aarch64_set_reg_u64 (cpu, rn, SP_OK, address);
892 /* 64 bit load sign-extended byte scaled unsigned 12 bit. */
894 ldrsb_abs (sim_cpu *cpu, uint32_t offset)
896 ldrsb_wb (cpu, offset, NoWriteBack);
899 /* 64 bit load sign-extended byte scaled or unscaled zero-
900 or sign-extended 32-bit register offset. */
902 ldrsb_scale_ext (sim_cpu *cpu, Scaling scaling, Extension extension)
904 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
905 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
906 unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
907 /* rn may reference SP, rm and rt must reference ZR */
909 uint64_t address = aarch64_get_reg_u64 (cpu, rn, SP_OK);
910 int64_t displacement = extend (aarch64_get_reg_u32 (cpu, rm, NO_SP),
912 /* There is no scaling required for a byte load. */
913 aarch64_set_reg_u64 (cpu, rt, NO_SP,
914 aarch64_get_mem_s8 (cpu, address + displacement));
917 /* 32 bit load zero-extended short scaled unsigned 12 bit. */
919 ldrh32_abs (sim_cpu *cpu, uint32_t offset)
921 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
922 unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
924 /* The target register may not be SP but the source may be. */
925 aarch64_set_reg_u64 (cpu, rt, NO_SP, aarch64_get_mem_u16
926 (cpu, aarch64_get_reg_u64 (cpu, rn, SP_OK)
927 + SCALE (offset, 16)));
930 /* 32 bit load zero-extended short unscaled signed 9 bit
931 with pre- or post-writeback. */
933 ldrh32_wb (sim_cpu *cpu, int32_t offset, WriteBack wb)
935 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
936 unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
939 if (rn == rt && wb != NoWriteBack)
942 address = aarch64_get_reg_u64 (cpu, rn, SP_OK);
947 aarch64_set_reg_u64 (cpu, rt, NO_SP, aarch64_get_mem_u16 (cpu, address));
952 if (wb != NoWriteBack)
953 aarch64_set_reg_u64 (cpu, rn, SP_OK, address);
956 /* 32 bit load zero-extended short scaled or unscaled zero-
957 or sign-extended 32-bit register offset. */
959 ldrh32_scale_ext (sim_cpu *cpu, Scaling scaling, Extension extension)
961 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
962 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
963 unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
964 /* rn may reference SP, rm and rt must reference ZR */
966 uint64_t address = aarch64_get_reg_u64 (cpu, rn, SP_OK);
967 int64_t extended = extend (aarch64_get_reg_u32 (cpu, rm, NO_SP), extension);
968 uint64_t displacement = OPT_SCALE (extended, 16, scaling);
970 aarch64_set_reg_u64 (cpu, rt, NO_SP,
971 aarch64_get_mem_u16 (cpu, address + displacement));
974 /* 32 bit load sign-extended short scaled unsigned 12 bit. */
976 ldrsh32_abs (sim_cpu *cpu, uint32_t offset)
978 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
979 unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
981 /* The target register may not be SP but the source may be. */
982 aarch64_set_reg_u64 (cpu, rt, NO_SP, (uint32_t) aarch64_get_mem_s16
984 aarch64_get_reg_u64 (cpu, rn, SP_OK)
985 + SCALE (offset, 16)));
988 /* 32 bit load sign-extended short unscaled signed 9 bit
989 with pre- or post-writeback. */
991 ldrsh32_wb (sim_cpu *cpu, int32_t offset, WriteBack wb)
993 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
994 unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
997 if (rn == rt && wb != NoWriteBack)
1000 address = aarch64_get_reg_u64 (cpu, rn, SP_OK);
1005 aarch64_set_reg_u64 (cpu, rt, NO_SP,
1006 (uint32_t) aarch64_get_mem_s16 (cpu, address));
1011 if (wb != NoWriteBack)
1012 aarch64_set_reg_u64 (cpu, rn, SP_OK, address);
1015 /* 32 bit load sign-extended short scaled or unscaled zero-
1016 or sign-extended 32-bit register offset. */
1018 ldrsh32_scale_ext (sim_cpu *cpu, Scaling scaling, Extension extension)
1020 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
1021 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
1022 unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
1023 /* rn may reference SP, rm and rt must reference ZR */
1025 uint64_t address = aarch64_get_reg_u64 (cpu, rn, SP_OK);
1026 int64_t extended = extend (aarch64_get_reg_u32 (cpu, rm, NO_SP), extension);
1027 uint64_t displacement = OPT_SCALE (extended, 16, scaling);
1029 aarch64_set_reg_u64 (cpu, rt, NO_SP,
1030 (uint32_t) aarch64_get_mem_s16
1031 (cpu, address + displacement));
1034 /* 64 bit load sign-extended short scaled unsigned 12 bit. */
1036 ldrsh_abs (sim_cpu *cpu, uint32_t offset)
1038 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
1039 unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
1041 /* The target register may not be SP but the source may be. */
1042 aarch64_set_reg_u64 (cpu, rt, NO_SP, aarch64_get_mem_s16
1043 (cpu, aarch64_get_reg_u64 (cpu, rn, SP_OK)
1044 + SCALE (offset, 16)));
1047 /* 64 bit load sign-extended short unscaled signed 9 bit
1048 with pre- or post-writeback. */
1050 ldrsh64_wb (sim_cpu *cpu, int32_t offset, WriteBack wb)
1052 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
1053 unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
1056 if (rn == rt && wb != NoWriteBack)
1059 address = aarch64_get_reg_u64 (cpu, rn, SP_OK);
1064 aarch64_set_reg_u64 (cpu, rt, NO_SP, aarch64_get_mem_s16 (cpu, address));
1069 if (wb != NoWriteBack)
1070 aarch64_set_reg_u64 (cpu, rn, SP_OK, address);
1073 /* 64 bit load sign-extended short scaled or unscaled zero-
1074 or sign-extended 32-bit register offset. */
1076 ldrsh_scale_ext (sim_cpu *cpu, Scaling scaling, Extension extension)
1078 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
1079 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
1080 unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
1081 /* rn may reference SP, rm and rt must reference ZR */
1083 uint64_t address = aarch64_get_reg_u64 (cpu, rn, SP_OK);
1084 int64_t extended = extend (aarch64_get_reg_u32 (cpu, rm, NO_SP), extension);
1085 uint64_t displacement = OPT_SCALE (extended, 16, scaling);
1087 aarch64_set_reg_u64 (cpu, rt, NO_SP,
1088 aarch64_get_mem_s16 (cpu, address + displacement));
1091 /* 64 bit load sign-extended 32 bit scaled unsigned 12 bit. */
1093 ldrsw_abs (sim_cpu *cpu, uint32_t offset)
1095 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
1096 unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
1098 /* The target register may not be SP but the source may be. */
1099 return aarch64_set_reg_s64 (cpu, rt, NO_SP, aarch64_get_mem_s32
1100 (cpu, aarch64_get_reg_u64 (cpu, rn, SP_OK)
1101 + SCALE (offset, 32)));
1104 /* 64 bit load sign-extended 32 bit unscaled signed 9 bit
1105 with pre- or post-writeback. */
1107 ldrsw_wb (sim_cpu *cpu, int32_t offset, WriteBack wb)
1109 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
1110 unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
1113 if (rn == rt && wb != NoWriteBack)
1116 address = aarch64_get_reg_u64 (cpu, rn, SP_OK);
1121 aarch64_set_reg_s64 (cpu, rt, NO_SP, aarch64_get_mem_s32 (cpu, address));
1126 if (wb != NoWriteBack)
1127 aarch64_set_reg_u64 (cpu, rn, SP_OK, address);
1130 /* 64 bit load sign-extended 32 bit scaled or unscaled zero-
1131 or sign-extended 32-bit register offset. */
1133 ldrsw_scale_ext (sim_cpu *cpu, Scaling scaling, Extension extension)
1135 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
1136 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
1137 unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
1138 /* rn may reference SP, rm and rt must reference ZR */
1140 uint64_t address = aarch64_get_reg_u64 (cpu, rn, SP_OK);
1141 int64_t extended = extend (aarch64_get_reg_u32 (cpu, rm, NO_SP), extension);
1142 uint64_t displacement = OPT_SCALE (extended, 32, scaling);
1144 aarch64_set_reg_s64 (cpu, rt, NO_SP,
1145 aarch64_get_mem_s32 (cpu, address + displacement));
1148 /* N.B. with stores the value in source is written to the
1149 address identified by source2 modified by source3/offset. */
1151 /* 32 bit store scaled unsigned 12 bit. */
1153 str32_abs (sim_cpu *cpu, uint32_t offset)
1155 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
1156 unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
1158 /* The target register may not be SP but the source may be. */
1159 aarch64_set_mem_u32 (cpu, (aarch64_get_reg_u64 (cpu, rn, SP_OK)
1160 + SCALE (offset, 32)),
1161 aarch64_get_reg_u32 (cpu, rt, NO_SP));
1164 /* 32 bit store unscaled signed 9 bit with pre- or post-writeback. */
1166 str32_wb (sim_cpu *cpu, int32_t offset, WriteBack wb)
1168 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
1169 unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
1172 if (rn == rt && wb != NoWriteBack)
1175 address = aarch64_get_reg_u64 (cpu, rn, SP_OK);
1179 aarch64_set_mem_u32 (cpu, address, aarch64_get_reg_u32 (cpu, rt, NO_SP));
1184 if (wb != NoWriteBack)
1185 aarch64_set_reg_u64 (cpu, rn, SP_OK, address);
1188 /* 32 bit store scaled or unscaled zero- or
1189 sign-extended 32-bit register offset. */
1191 str32_scale_ext (sim_cpu *cpu, Scaling scaling, Extension extension)
1193 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
1194 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
1195 unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
1197 uint64_t address = aarch64_get_reg_u64 (cpu, rn, SP_OK);
1198 int64_t extended = extend (aarch64_get_reg_u32 (cpu, rm, NO_SP), extension);
1199 uint64_t displacement = OPT_SCALE (extended, 32, scaling);
1201 aarch64_set_mem_u32 (cpu, address + displacement,
1202 aarch64_get_reg_u64 (cpu, rt, NO_SP));
1205 /* 64 bit store scaled unsigned 12 bit. */
1207 str_abs (sim_cpu *cpu, uint32_t offset)
1209 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
1210 unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
1212 aarch64_set_mem_u64 (cpu,
1213 aarch64_get_reg_u64 (cpu, rn, SP_OK)
1214 + SCALE (offset, 64),
1215 aarch64_get_reg_u64 (cpu, rt, NO_SP));
1218 /* 64 bit store unscaled signed 9 bit with pre- or post-writeback. */
1220 str_wb (sim_cpu *cpu, int32_t offset, WriteBack wb)
1222 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
1223 unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
1226 if (rn == rt && wb != NoWriteBack)
1229 address = aarch64_get_reg_u64 (cpu, rn, SP_OK);
1234 aarch64_set_mem_u64 (cpu, address, aarch64_get_reg_u64 (cpu, rt, NO_SP));
1239 if (wb != NoWriteBack)
1240 aarch64_set_reg_u64 (cpu, rn, SP_OK, address);
1243 /* 64 bit store scaled or unscaled zero-
1244 or sign-extended 32-bit register offset. */
1246 str_scale_ext (sim_cpu *cpu, Scaling scaling, Extension extension)
1248 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
1249 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
1250 unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
1251 /* rn may reference SP, rm and rt must reference ZR */
1253 uint64_t address = aarch64_get_reg_u64 (cpu, rn, SP_OK);
1254 int64_t extended = extend (aarch64_get_reg_u32 (cpu, rm, NO_SP),
1256 uint64_t displacement = OPT_SCALE (extended, 64, scaling);
1258 aarch64_set_mem_u64 (cpu, address + displacement,
1259 aarch64_get_reg_u64 (cpu, rt, NO_SP));
1262 /* 32 bit store byte scaled unsigned 12 bit. */
1264 strb_abs (sim_cpu *cpu, uint32_t offset)
1266 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
1267 unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
1269 /* The target register may not be SP but the source may be.
1270 There is no scaling required for a byte load. */
1271 aarch64_set_mem_u8 (cpu,
1272 aarch64_get_reg_u64 (cpu, rn, SP_OK) + offset,
1273 aarch64_get_reg_u8 (cpu, rt, NO_SP));
1276 /* 32 bit store byte unscaled signed 9 bit with pre- or post-writeback. */
1278 strb_wb (sim_cpu *cpu, int32_t offset, WriteBack wb)
1280 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
1281 unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
1284 if (rn == rt && wb != NoWriteBack)
1287 address = aarch64_get_reg_u64 (cpu, rn, SP_OK);
1292 aarch64_set_mem_u8 (cpu, address, aarch64_get_reg_u8 (cpu, rt, NO_SP));
1297 if (wb != NoWriteBack)
1298 aarch64_set_reg_u64 (cpu, rn, SP_OK, address);
1301 /* 32 bit store byte scaled or unscaled zero-
1302 or sign-extended 32-bit register offset. */
1304 strb_scale_ext (sim_cpu *cpu, Scaling scaling, Extension extension)
1306 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
1307 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
1308 unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
1309 /* rn may reference SP, rm and rt must reference ZR */
1311 uint64_t address = aarch64_get_reg_u64 (cpu, rn, SP_OK);
1312 int64_t displacement = extend (aarch64_get_reg_u32 (cpu, rm, NO_SP),
1315 /* There is no scaling required for a byte load. */
1316 aarch64_set_mem_u8 (cpu, address + displacement,
1317 aarch64_get_reg_u8 (cpu, rt, NO_SP));
1320 /* 32 bit store short scaled unsigned 12 bit. */
1322 strh_abs (sim_cpu *cpu, uint32_t offset)
1324 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
1325 unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
1327 /* The target register may not be SP but the source may be. */
1328 aarch64_set_mem_u16 (cpu, aarch64_get_reg_u64 (cpu, rn, SP_OK)
1329 + SCALE (offset, 16),
1330 aarch64_get_reg_u16 (cpu, rt, NO_SP));
1333 /* 32 bit store short unscaled signed 9 bit with pre- or post-writeback. */
1335 strh_wb (sim_cpu *cpu, int32_t offset, WriteBack wb)
1337 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
1338 unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
1341 if (rn == rt && wb != NoWriteBack)
1344 address = aarch64_get_reg_u64 (cpu, rn, SP_OK);
1349 aarch64_set_mem_u16 (cpu, address, aarch64_get_reg_u16 (cpu, rt, NO_SP));
1354 if (wb != NoWriteBack)
1355 aarch64_set_reg_u64 (cpu, rn, SP_OK, address);
1358 /* 32 bit store short scaled or unscaled zero-
1359 or sign-extended 32-bit register offset. */
1361 strh_scale_ext (sim_cpu *cpu, Scaling scaling, Extension extension)
1363 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
1364 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
1365 unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
1366 /* rn may reference SP, rm and rt must reference ZR */
1368 uint64_t address = aarch64_get_reg_u64 (cpu, rn, SP_OK);
1369 int64_t extended = extend (aarch64_get_reg_u32 (cpu, rm, NO_SP), extension);
1370 uint64_t displacement = OPT_SCALE (extended, 16, scaling);
1372 aarch64_set_mem_u16 (cpu, address + displacement,
1373 aarch64_get_reg_u16 (cpu, rt, NO_SP));
1376 /* Prefetch unsigned 12 bit. */
1378 prfm_abs (sim_cpu *cpu, uint32_t offset)
1380 /* instr[4,0] = prfop : 00000 ==> PLDL1KEEP, 00001 ==> PLDL1STRM,
1381 00010 ==> PLDL2KEEP, 00001 ==> PLDL2STRM,
1382 00100 ==> PLDL3KEEP, 00101 ==> PLDL3STRM,
1383 10000 ==> PSTL1KEEP, 10001 ==> PSTL1STRM,
1384 10010 ==> PSTL2KEEP, 10001 ==> PSTL2STRM,
1385 10100 ==> PSTL3KEEP, 10101 ==> PSTL3STRM,
1387 PrfOp prfop = prfop (aarch64_get_instr (cpu), 4, 0);
1388 uint64_t address = aarch64_get_reg_u64 (cpu, rn, SP_OK)
1389 + SCALE (offset, 64). */
1391 /* TODO : implement prefetch of address. */
1394 /* Prefetch scaled or unscaled zero- or sign-extended 32-bit register offset. */
1396 prfm_scale_ext (sim_cpu *cpu, Scaling scaling, Extension extension)
1398 /* instr[4,0] = prfop : 00000 ==> PLDL1KEEP, 00001 ==> PLDL1STRM,
1399 00010 ==> PLDL2KEEP, 00001 ==> PLDL2STRM,
1400 00100 ==> PLDL3KEEP, 00101 ==> PLDL3STRM,
1401 10000 ==> PSTL1KEEP, 10001 ==> PSTL1STRM,
1402 10010 ==> PSTL2KEEP, 10001 ==> PSTL2STRM,
1403 10100 ==> PSTL3KEEP, 10101 ==> PSTL3STRM,
1405 rn may reference SP, rm may only reference ZR
1406 PrfOp prfop = prfop (aarch64_get_instr (cpu), 4, 0);
1407 uint64_t base = aarch64_get_reg_u64 (cpu, rn, SP_OK);
1408 int64_t extended = extend (aarch64_get_reg_u32 (cpu, rm, NO_SP),
1410 uint64_t displacement = OPT_SCALE (extended, 64, scaling);
1411 uint64_t address = base + displacement. */
1413 /* TODO : implement prefetch of address */
1416 /* 64 bit pc-relative prefetch. */
1418 prfm_pcrel (sim_cpu *cpu, int32_t offset)
1420 /* instr[4,0] = prfop : 00000 ==> PLDL1KEEP, 00001 ==> PLDL1STRM,
1421 00010 ==> PLDL2KEEP, 00001 ==> PLDL2STRM,
1422 00100 ==> PLDL3KEEP, 00101 ==> PLDL3STRM,
1423 10000 ==> PSTL1KEEP, 10001 ==> PSTL1STRM,
1424 10010 ==> PSTL2KEEP, 10001 ==> PSTL2STRM,
1425 10100 ==> PSTL3KEEP, 10101 ==> PSTL3STRM,
1427 PrfOp prfop = prfop (aarch64_get_instr (cpu), 4, 0);
1428 uint64_t address = aarch64_get_PC (cpu) + offset. */
1430 /* TODO : implement this */
1433 /* Load-store exclusive. */
1438 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
1439 unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
1440 uint64_t address = aarch64_get_reg_u64 (cpu, rn, SP_OK);
1441 int size = uimm (aarch64_get_instr (cpu), 31, 30);
1442 /* int ordered = uimm (aarch64_get_instr (cpu), 15, 15); */
1443 /* int exclusive = ! uimm (aarch64_get_instr (cpu), 23, 23); */
1448 aarch64_set_reg_u64 (cpu, rt, NO_SP, aarch64_get_mem_u8 (cpu, address));
1451 aarch64_set_reg_u64 (cpu, rt, NO_SP, aarch64_get_mem_u16 (cpu, address));
1454 aarch64_set_reg_u64 (cpu, rt, NO_SP, aarch64_get_mem_u32 (cpu, address));
1457 aarch64_set_reg_u64 (cpu, rt, NO_SP, aarch64_get_mem_u64 (cpu, address));
1467 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
1468 unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
1469 unsigned rs = uimm (aarch64_get_instr (cpu), 20, 16);
1470 uint64_t address = aarch64_get_reg_u64 (cpu, rn, SP_OK);
1471 int size = uimm (aarch64_get_instr (cpu), 31, 30);
1472 uint64_t data = aarch64_get_reg_u64 (cpu, rt, NO_SP);
1476 case 0: aarch64_set_mem_u8 (cpu, address, data); break;
1477 case 1: aarch64_set_mem_u16 (cpu, address, data); break;
1478 case 2: aarch64_set_mem_u32 (cpu, address, data); break;
1479 case 3: aarch64_set_mem_u64 (cpu, address, data); break;
1480 default: HALT_UNALLOC;
1483 aarch64_set_reg_u64 (cpu, rs, NO_SP, 0); /* Always exclusive... */
1487 dexLoadLiteral (sim_cpu *cpu)
1489 /* instr[29,27] == 011
1491 instr[31,30:26] = opc: 000 ==> LDRW, 001 ==> FLDRS
1492 010 ==> LDRX, 011 ==> FLDRD
1493 100 ==> LDRSW, 101 ==> FLDRQ
1494 110 ==> PRFM, 111 ==> UNALLOC
1495 instr[26] ==> V : 0 ==> GReg, 1 ==> FReg
1496 instr[23, 5] == simm19 */
1498 /* unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0); */
1499 uint32_t dispatch = ( (uimm (aarch64_get_instr (cpu), 31, 30) << 1)
1500 | uimm (aarch64_get_instr (cpu), 26, 26));
1501 int32_t imm = simm32 (aarch64_get_instr (cpu), 23, 5);
1505 case 0: ldr32_pcrel (cpu, imm); break;
1506 case 1: fldrs_pcrel (cpu, imm); break;
1507 case 2: ldr_pcrel (cpu, imm); break;
1508 case 3: fldrd_pcrel (cpu, imm); break;
1509 case 4: ldrsw_pcrel (cpu, imm); break;
1510 case 5: fldrq_pcrel (cpu, imm); break;
1511 case 6: prfm_pcrel (cpu, imm); break;
1518 /* Immediate arithmetic
1519 The aimm argument is a 12 bit unsigned value or a 12 bit unsigned
1520 value left shifted by 12 bits (done at decode).
1522 N.B. the register args (dest, source) can normally be Xn or SP.
1523 the exception occurs for flag setting instructions which may
1524 only use Xn for the output (dest). */
1526 /* 32 bit add immediate. */
1528 add32 (sim_cpu *cpu, uint32_t aimm)
1530 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
1531 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
1533 aarch64_set_reg_u64 (cpu, rd, SP_OK,
1534 aarch64_get_reg_u32 (cpu, rn, SP_OK) + aimm);
1537 /* 64 bit add immediate. */
1539 add64 (sim_cpu *cpu, uint32_t aimm)
1541 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
1542 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
1544 aarch64_set_reg_u64 (cpu, rd, SP_OK,
1545 aarch64_get_reg_u64 (cpu, rn, SP_OK) + aimm);
1549 set_flags_for_add32 (sim_cpu *cpu, int32_t value1, int32_t value2)
1551 int32_t result = value1 + value2;
1552 int64_t sresult = (int64_t) value1 + (int64_t) value2;
1553 uint64_t uresult = (uint64_t)(uint32_t) value1
1554 + (uint64_t)(uint32_t) value2;
1560 if (result & (1 << 31))
1563 if (uresult != result)
1566 if (sresult != result)
1569 aarch64_set_CPSR (cpu, flags);
1573 set_flags_for_add64 (sim_cpu *cpu, uint64_t value1, uint64_t value2)
1575 int64_t sval1 = value1;
1576 int64_t sval2 = value2;
1577 uint64_t result = value1 + value2;
1578 int64_t sresult = sval1 + sval2;
1584 if (result & (1ULL << 63))
1591 /* Negative plus a negative. Overflow happens if
1592 the result is greater than either of the operands. */
1593 if (sresult > sval1 || sresult > sval2)
1596 /* else Negative plus a positive. Overflow cannot happen. */
1598 else /* value1 is +ve. */
1602 /* Overflow can only occur if we computed "0 - MININT". */
1603 if (sval1 == 0 && sval2 == (1LL << 63))
1608 /* Postive plus positive - overflow has happened if the
1609 result is smaller than either of the operands. */
1610 if (result < value1 || result < value2)
1615 aarch64_set_CPSR (cpu, flags);
1618 #define NEG(a) (((a) & signbit) == signbit)
1619 #define POS(a) (((a) & signbit) == 0)
1622 set_flags_for_sub32 (sim_cpu *cpu, uint32_t value1, uint32_t value2)
1624 uint32_t result = value1 - value2;
1626 uint32_t signbit = 1U << 31;
1634 if ( (NEG (value1) && POS (value2))
1635 || (NEG (value1) && POS (result))
1636 || (POS (value2) && POS (result)))
1639 if ( (NEG (value1) && POS (value2) && POS (result))
1640 || (POS (value1) && NEG (value2) && NEG (result)))
1643 aarch64_set_CPSR (cpu, flags);
1647 set_flags_for_sub64 (sim_cpu *cpu, uint64_t value1, uint64_t value2)
1649 uint64_t result = value1 - value2;
1651 uint64_t signbit = 1ULL << 63;
1659 if ( (NEG (value1) && POS (value2))
1660 || (NEG (value1) && POS (result))
1661 || (POS (value2) && POS (result)))
1664 if ( (NEG (value1) && POS (value2) && POS (result))
1665 || (POS (value1) && NEG (value2) && NEG (result)))
1668 aarch64_set_CPSR (cpu, flags);
1672 set_flags_for_binop32 (sim_cpu *cpu, uint32_t result)
1681 if (result & (1 << 31))
1686 aarch64_set_CPSR (cpu, flags);
1690 set_flags_for_binop64 (sim_cpu *cpu, uint64_t result)
1699 if (result & (1ULL << 63))
1704 aarch64_set_CPSR (cpu, flags);
1707 /* 32 bit add immediate set flags. */
1709 adds32 (sim_cpu *cpu, uint32_t aimm)
1711 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
1712 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
1713 /* TODO : do we need to worry about signs here? */
1714 int32_t value1 = aarch64_get_reg_s32 (cpu, rn, SP_OK);
1716 aarch64_set_reg_u64 (cpu, rd, NO_SP, value1 + aimm);
1717 set_flags_for_add32 (cpu, value1, aimm);
1720 /* 64 bit add immediate set flags. */
1722 adds64 (sim_cpu *cpu, uint32_t aimm)
1724 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
1725 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
1726 uint64_t value1 = aarch64_get_reg_u64 (cpu, rn, SP_OK);
1727 uint64_t value2 = aimm;
1729 aarch64_set_reg_u64 (cpu, rd, NO_SP, value1 + value2);
1730 set_flags_for_add64 (cpu, value1, value2);
1733 /* 32 bit sub immediate. */
1735 sub32 (sim_cpu *cpu, uint32_t aimm)
1737 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
1738 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
1740 aarch64_set_reg_u64 (cpu, rd, SP_OK,
1741 aarch64_get_reg_u32 (cpu, rn, SP_OK) - aimm);
1744 /* 64 bit sub immediate. */
1746 sub64 (sim_cpu *cpu, uint32_t aimm)
1748 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
1749 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
1751 aarch64_set_reg_u64 (cpu, rd, SP_OK,
1752 aarch64_get_reg_u64 (cpu, rn, SP_OK) - aimm);
1755 /* 32 bit sub immediate set flags. */
1757 subs32 (sim_cpu *cpu, uint32_t aimm)
1759 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
1760 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
1761 uint32_t value1 = aarch64_get_reg_u64 (cpu, rn, SP_OK);
1762 uint32_t value2 = aimm;
1764 aarch64_set_reg_u64 (cpu, rd, NO_SP, value1 - value2);
1765 set_flags_for_sub32 (cpu, value1, value2);
1768 /* 64 bit sub immediate set flags. */
1770 subs64 (sim_cpu *cpu, uint32_t aimm)
1772 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
1773 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
1774 uint64_t value1 = aarch64_get_reg_u64 (cpu, rn, SP_OK);
1775 uint32_t value2 = aimm;
1777 aarch64_set_reg_u64 (cpu, rd, NO_SP, value1 - value2);
1778 set_flags_for_sub64 (cpu, value1, value2);
1781 /* Data Processing Register. */
1783 /* First two helpers to perform the shift operations. */
1785 static inline uint32_t
1786 shifted32 (uint32_t value, Shift shift, uint32_t count)
1792 return (value << count);
1794 return (value >> count);
1797 int32_t svalue = value;
1798 return (svalue >> count);
1802 uint32_t top = value >> count;
1803 uint32_t bottom = value << (32 - count);
1804 return (bottom | top);
1809 static inline uint64_t
1810 shifted64 (uint64_t value, Shift shift, uint32_t count)
1816 return (value << count);
1818 return (value >> count);
1821 int64_t svalue = value;
1822 return (svalue >> count);
1826 uint64_t top = value >> count;
1827 uint64_t bottom = value << (64 - count);
1828 return (bottom | top);
1833 /* Arithmetic shifted register.
1834 These allow an optional LSL, ASR or LSR to the second source
1835 register with a count up to the register bit count.
1837 N.B register args may not be SP. */
1839 /* 32 bit ADD shifted register. */
1841 add32_shift (sim_cpu *cpu, Shift shift, uint32_t count)
1843 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
1844 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
1845 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
1847 aarch64_set_reg_u64 (cpu, rd, NO_SP,
1848 aarch64_get_reg_u32 (cpu, rn, NO_SP)
1849 + shifted32 (aarch64_get_reg_u32 (cpu, rm, NO_SP),
1853 /* 64 bit ADD shifted register. */
1855 add64_shift (sim_cpu *cpu, Shift shift, uint32_t count)
1857 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
1858 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
1859 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
1861 aarch64_set_reg_u64 (cpu, rd, NO_SP,
1862 aarch64_get_reg_u64 (cpu, rn, NO_SP)
1863 + shifted64 (aarch64_get_reg_u64 (cpu, rm, NO_SP),
1867 /* 32 bit ADD shifted register setting flags. */
1869 adds32_shift (sim_cpu *cpu, Shift shift, uint32_t count)
1871 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
1872 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
1873 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
1875 uint32_t value1 = aarch64_get_reg_u32 (cpu, rn, NO_SP);
1876 uint32_t value2 = shifted32 (aarch64_get_reg_u32 (cpu, rm, NO_SP),
1879 aarch64_set_reg_u64 (cpu, rd, NO_SP, value1 + value2);
1880 set_flags_for_add32 (cpu, value1, value2);
1883 /* 64 bit ADD shifted register setting flags. */
1885 adds64_shift (sim_cpu *cpu, Shift shift, uint32_t count)
1887 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
1888 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
1889 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
1891 uint64_t value1 = aarch64_get_reg_u64 (cpu, rn, NO_SP);
1892 uint64_t value2 = shifted64 (aarch64_get_reg_u64 (cpu, rm, NO_SP),
1895 aarch64_set_reg_u64 (cpu, rd, NO_SP, value1 + value2);
1896 set_flags_for_add64 (cpu, value1, value2);
1899 /* 32 bit SUB shifted register. */
1901 sub32_shift (sim_cpu *cpu, Shift shift, uint32_t count)
1903 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
1904 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
1905 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
1907 aarch64_set_reg_u64 (cpu, rd, NO_SP,
1908 aarch64_get_reg_u32 (cpu, rn, NO_SP)
1909 - shifted32 (aarch64_get_reg_u32 (cpu, rm, NO_SP),
1913 /* 64 bit SUB shifted register. */
1915 sub64_shift (sim_cpu *cpu, Shift shift, uint32_t count)
1917 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
1918 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
1919 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
1921 aarch64_set_reg_u64 (cpu, rd, NO_SP,
1922 aarch64_get_reg_u64 (cpu, rn, NO_SP)
1923 - shifted64 (aarch64_get_reg_u64 (cpu, rm, NO_SP),
1927 /* 32 bit SUB shifted register setting flags. */
1929 subs32_shift (sim_cpu *cpu, Shift shift, uint32_t count)
1931 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
1932 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
1933 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
1935 uint32_t value1 = aarch64_get_reg_u32 (cpu, rn, NO_SP);
1936 uint32_t value2 = shifted32 (aarch64_get_reg_u32 (cpu, rm, NO_SP),
1939 aarch64_set_reg_u64 (cpu, rd, NO_SP, value1 - value2);
1940 set_flags_for_sub32 (cpu, value1, value2);
1943 /* 64 bit SUB shifted register setting flags. */
1945 subs64_shift (sim_cpu *cpu, Shift shift, uint32_t count)
1947 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
1948 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
1949 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
1951 uint64_t value1 = aarch64_get_reg_u64 (cpu, rn, NO_SP);
1952 uint64_t value2 = shifted64 (aarch64_get_reg_u64 (cpu, rm, NO_SP),
1955 aarch64_set_reg_u64 (cpu, rd, NO_SP, value1 - value2);
1956 set_flags_for_sub64 (cpu, value1, value2);
1959 /* First a couple more helpers to fetch the
1960 relevant source register element either
1961 sign or zero extended as required by the
1965 extreg32 (sim_cpu *cpu, unsigned int lo, Extension extension)
1969 case UXTB: return aarch64_get_reg_u8 (cpu, lo, NO_SP);
1970 case UXTH: return aarch64_get_reg_u16 (cpu, lo, NO_SP);
1971 case UXTW: /* Fall through. */
1972 case UXTX: return aarch64_get_reg_u32 (cpu, lo, NO_SP);
1973 case SXTB: return aarch64_get_reg_s8 (cpu, lo, NO_SP);
1974 case SXTH: return aarch64_get_reg_s16 (cpu, lo, NO_SP);
1975 case SXTW: /* Fall through. */
1976 case SXTX: /* Fall through. */
1977 default: return aarch64_get_reg_s32 (cpu, lo, NO_SP);
1982 extreg64 (sim_cpu *cpu, unsigned int lo, Extension extension)
1986 case UXTB: return aarch64_get_reg_u8 (cpu, lo, NO_SP);
1987 case UXTH: return aarch64_get_reg_u16 (cpu, lo, NO_SP);
1988 case UXTW: return aarch64_get_reg_u32 (cpu, lo, NO_SP);
1989 case UXTX: return aarch64_get_reg_u64 (cpu, lo, NO_SP);
1990 case SXTB: return aarch64_get_reg_s8 (cpu, lo, NO_SP);
1991 case SXTH: return aarch64_get_reg_s16 (cpu, lo, NO_SP);
1992 case SXTW: return aarch64_get_reg_s32 (cpu, lo, NO_SP);
1994 default: return aarch64_get_reg_s64 (cpu, lo, NO_SP);
1998 /* Arithmetic extending register
1999 These allow an optional sign extension of some portion of the
2000 second source register followed by an optional left shift of
2001 between 1 and 4 bits (i.e. a shift of 0-4 bits???)
2003 N.B output (dest) and first input arg (source) may normally be Xn
2004 or SP. However, for flag setting operations dest can only be
2005 Xn. Second input registers are always Xn. */
2007 /* 32 bit ADD extending register. */
2009 add32_ext (sim_cpu *cpu, Extension extension, uint32_t shift)
2011 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
2012 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
2013 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
2015 aarch64_set_reg_u64 (cpu, rd, SP_OK,
2016 aarch64_get_reg_u32 (cpu, rn, SP_OK)
2017 + (extreg32 (cpu, rm, extension) << shift));
2020 /* 64 bit ADD extending register.
2021 N.B. This subsumes the case with 64 bit source2 and UXTX #n or LSL #0. */
2023 add64_ext (sim_cpu *cpu, Extension extension, uint32_t shift)
2025 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
2026 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
2027 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
2029 aarch64_set_reg_u64 (cpu, rd, SP_OK,
2030 aarch64_get_reg_u64 (cpu, rn, SP_OK)
2031 + (extreg64 (cpu, rm, extension) << shift));
2034 /* 32 bit ADD extending register setting flags. */
2036 adds32_ext (sim_cpu *cpu, Extension extension, uint32_t shift)
2038 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
2039 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
2040 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
2042 uint32_t value1 = aarch64_get_reg_u32 (cpu, rn, SP_OK);
2043 uint32_t value2 = extreg32 (cpu, rm, extension) << shift;
2045 aarch64_set_reg_u64 (cpu, rd, NO_SP, value1 + value2);
2046 set_flags_for_add32 (cpu, value1, value2);
2049 /* 64 bit ADD extending register setting flags */
2050 /* N.B. this subsumes the case with 64 bit source2 and UXTX #n or LSL #0 */
2052 adds64_ext (sim_cpu *cpu, Extension extension, uint32_t shift)
2054 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
2055 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
2056 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
2058 uint64_t value1 = aarch64_get_reg_u64 (cpu, rn, SP_OK);
2059 uint64_t value2 = extreg64 (cpu, rm, extension) << shift;
2061 aarch64_set_reg_u64 (cpu, rd, NO_SP, value1 + value2);
2062 set_flags_for_add64 (cpu, value1, value2);
2065 /* 32 bit SUB extending register. */
2067 sub32_ext (sim_cpu *cpu, Extension extension, uint32_t shift)
2069 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
2070 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
2071 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
2073 aarch64_set_reg_u64 (cpu, rd, SP_OK,
2074 aarch64_get_reg_u32 (cpu, rn, SP_OK)
2075 - (extreg32 (cpu, rm, extension) << shift));
2078 /* 64 bit SUB extending register. */
2079 /* N.B. this subsumes the case with 64 bit source2 and UXTX #n or LSL #0. */
2081 sub64_ext (sim_cpu *cpu, Extension extension, uint32_t shift)
2083 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
2084 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
2085 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
2087 aarch64_set_reg_u64 (cpu, rd, SP_OK,
2088 aarch64_get_reg_u64 (cpu, rn, SP_OK)
2089 - (extreg64 (cpu, rm, extension) << shift));
2092 /* 32 bit SUB extending register setting flags. */
2094 subs32_ext (sim_cpu *cpu, Extension extension, uint32_t shift)
2096 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
2097 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
2098 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
2100 uint32_t value1 = aarch64_get_reg_u32 (cpu, rn, SP_OK);
2101 uint32_t value2 = extreg32 (cpu, rm, extension) << shift;
2103 aarch64_set_reg_u64 (cpu, rd, NO_SP, value1 - value2);
2104 set_flags_for_sub32 (cpu, value1, value2);
2107 /* 64 bit SUB extending register setting flags */
2108 /* N.B. this subsumes the case with 64 bit source2 and UXTX #n or LSL #0 */
2110 subs64_ext (sim_cpu *cpu, Extension extension, uint32_t shift)
2112 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
2113 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
2114 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
2116 uint64_t value1 = aarch64_get_reg_u64 (cpu, rn, SP_OK);
2117 uint64_t value2 = extreg64 (cpu, rm, extension) << shift;
2119 aarch64_set_reg_u64 (cpu, rd, NO_SP, value1 - value2);
2120 set_flags_for_sub64 (cpu, value1, value2);
2124 dexAddSubtractImmediate (sim_cpu *cpu)
2126 /* instr[31] = size : 0 ==> 32 bit, 1 ==> 64 bit
2127 instr[30] = op : 0 ==> ADD, 1 ==> SUB
2128 instr[29] = set : 0 ==> no flags, 1 ==> set flags
2129 instr[28,24] = 10001
2130 instr[23,22] = shift : 00 == LSL#0, 01 = LSL#12 1x = UNALLOC
2131 instr[21,10] = uimm12
2135 /* N.B. the shift is applied at decode before calling the add/sub routine. */
2136 uint32_t shift = uimm (aarch64_get_instr (cpu), 23, 22);
2137 uint32_t imm = uimm (aarch64_get_instr (cpu), 21, 10);
2138 uint32_t dispatch = uimm (aarch64_get_instr (cpu), 31, 29);
2140 NYI_assert (28, 24, 0x11);
2150 case 0: add32 (cpu, imm); break;
2151 case 1: adds32 (cpu, imm); break;
2152 case 2: sub32 (cpu, imm); break;
2153 case 3: subs32 (cpu, imm); break;
2154 case 4: add64 (cpu, imm); break;
2155 case 5: adds64 (cpu, imm); break;
2156 case 6: sub64 (cpu, imm); break;
2157 case 7: subs64 (cpu, imm); break;
2164 dexAddSubtractShiftedRegister (sim_cpu *cpu)
2166 /* instr[31] = size : 0 ==> 32 bit, 1 ==> 64 bit
2167 instr[30,29] = op : 00 ==> ADD, 01 ==> ADDS, 10 ==> SUB, 11 ==> SUBS
2168 instr[28,24] = 01011
2169 instr[23,22] = shift : 0 ==> LSL, 1 ==> LSR, 2 ==> ASR, 3 ==> UNALLOC
2172 instr[15,10] = count : must be 0xxxxx for 32 bit
2176 uint32_t size = uimm (aarch64_get_instr (cpu), 31, 31);
2177 /* 32 bit operations must have count[5] = 0
2178 or else we have an UNALLOC. */
2179 uint32_t count = uimm (aarch64_get_instr (cpu), 15, 10);
2180 /* Shift encoded as ROR is unallocated. */
2181 Shift shiftType = shift (aarch64_get_instr (cpu), 22);
2182 /* Dispatch on size:op i.e aarch64_get_instr (cpu)[31,29]. */
2183 uint32_t dispatch = uimm (aarch64_get_instr (cpu), 31, 29);
2185 NYI_assert (28, 24, 0x0B);
2186 NYI_assert (21, 21, 0);
2188 if (shiftType == ROR)
2191 if (!size && uimm (count, 5, 5))
2196 case 0: add32_shift (cpu, shiftType, count); break;
2197 case 1: adds32_shift (cpu, shiftType, count); break;
2198 case 2: sub32_shift (cpu, shiftType, count); break;
2199 case 3: subs32_shift (cpu, shiftType, count); break;
2200 case 4: add64_shift (cpu, shiftType, count); break;
2201 case 5: adds64_shift (cpu, shiftType, count); break;
2202 case 6: sub64_shift (cpu, shiftType, count); break;
2203 case 7: subs64_shift (cpu, shiftType, count); break;
2210 dexAddSubtractExtendedRegister (sim_cpu *cpu)
2212 /* instr[31] = size : 0 ==> 32 bit, 1 ==> 64 bit
2213 instr[30] = op : 0 ==> ADD, 1 ==> SUB
2214 instr[29] = set? : 0 ==> no flags, 1 ==> set flags
2215 instr[28,24] = 01011
2216 instr[23,22] = opt : 0 ==> ok, 1,2,3 ==> UNALLOC
2219 instr[15,13] = option : 000 ==> UXTB, 001 ==> UXTH,
2220 000 ==> LSL|UXTW, 001 ==> UXTZ,
2221 000 ==> SXTB, 001 ==> SXTH,
2222 000 ==> SXTW, 001 ==> SXTX,
2223 instr[12,10] = shift : 0,1,2,3,4 ==> ok, 5,6,7 ==> UNALLOC
2227 Extension extensionType = extension (aarch64_get_instr (cpu), 13);
2228 uint32_t shift = uimm (aarch64_get_instr (cpu), 12, 10);
2229 /* dispatch on size:op:set? i.e aarch64_get_instr (cpu)[31,29] */
2230 uint32_t dispatch = uimm (aarch64_get_instr (cpu), 31, 29);
2232 NYI_assert (28, 24, 0x0B);
2233 NYI_assert (21, 21, 1);
2235 /* Shift may not exceed 4. */
2241 case 0: add32_ext (cpu, extensionType, shift); break;
2242 case 1: adds32_ext (cpu, extensionType, shift); break;
2243 case 2: sub32_ext (cpu, extensionType, shift); break;
2244 case 3: subs32_ext (cpu, extensionType, shift); break;
2245 case 4: add64_ext (cpu, extensionType, shift); break;
2246 case 5: adds64_ext (cpu, extensionType, shift); break;
2247 case 6: sub64_ext (cpu, extensionType, shift); break;
2248 case 7: subs64_ext (cpu, extensionType, shift); break;
2249 default: HALT_UNALLOC;
2253 /* Conditional data processing
2254 Condition register is implicit 3rd source. */
2256 /* 32 bit add with carry. */
2257 /* N.B register args may not be SP. */
2260 adc32 (sim_cpu *cpu)
2262 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
2263 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
2264 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
2266 aarch64_set_reg_u64 (cpu, rd, NO_SP,
2267 aarch64_get_reg_u32 (cpu, rn, NO_SP)
2268 + aarch64_get_reg_u32 (cpu, rm, NO_SP)
2272 /* 64 bit add with carry */
2274 adc64 (sim_cpu *cpu)
2276 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
2277 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
2278 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
2280 aarch64_set_reg_u64 (cpu, rd, NO_SP,
2281 aarch64_get_reg_u64 (cpu, rn, NO_SP)
2282 + aarch64_get_reg_u64 (cpu, rm, NO_SP)
2286 /* 32 bit add with carry setting flags. */
2288 adcs32 (sim_cpu *cpu)
2290 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
2291 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
2292 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
2294 uint32_t value1 = aarch64_get_reg_u32 (cpu, rn, NO_SP);
2295 uint32_t value2 = aarch64_get_reg_u32 (cpu, rm, NO_SP);
2296 uint32_t carry = IS_SET (C);
2298 aarch64_set_reg_u64 (cpu, rd, NO_SP, value1 + value2 + carry);
2299 set_flags_for_add32 (cpu, value1, value2 + carry);
2302 /* 64 bit add with carry setting flags. */
2304 adcs64 (sim_cpu *cpu)
2306 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
2307 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
2308 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
2310 uint64_t value1 = aarch64_get_reg_u64 (cpu, rn, NO_SP);
2311 uint64_t value2 = aarch64_get_reg_u64 (cpu, rm, NO_SP);
2312 uint64_t carry = IS_SET (C);
2314 aarch64_set_reg_u64 (cpu, rd, NO_SP, value1 + value2 + carry);
2315 set_flags_for_add64 (cpu, value1, value2 + carry);
2318 /* 32 bit sub with carry. */
2320 sbc32 (sim_cpu *cpu)
2322 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
2323 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5); /* ngc iff rn == 31. */
2324 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
2326 aarch64_set_reg_u64 (cpu, rd, NO_SP,
2327 aarch64_get_reg_u32 (cpu, rn, NO_SP)
2328 - aarch64_get_reg_u32 (cpu, rm, NO_SP)
2332 /* 64 bit sub with carry */
2334 sbc64 (sim_cpu *cpu)
2336 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
2337 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
2338 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
2340 aarch64_set_reg_u64 (cpu, rd, NO_SP,
2341 aarch64_get_reg_u64 (cpu, rn, NO_SP)
2342 - aarch64_get_reg_u64 (cpu, rm, NO_SP)
2346 /* 32 bit sub with carry setting flags */
2348 sbcs32 (sim_cpu *cpu)
2350 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
2351 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
2352 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
2354 uint32_t value1 = aarch64_get_reg_u32 (cpu, rn, NO_SP);
2355 uint32_t value2 = aarch64_get_reg_u32 (cpu, rm, NO_SP);
2356 uint32_t carry = IS_SET (C);
2357 uint32_t result = value1 - value2 + 1 - carry;
2359 aarch64_set_reg_u64 (cpu, rd, NO_SP, result);
2360 set_flags_for_sub32 (cpu, value1, value2 + 1 - carry);
2363 /* 64 bit sub with carry setting flags */
2365 sbcs64 (sim_cpu *cpu)
2367 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
2368 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
2369 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
2371 uint64_t value1 = aarch64_get_reg_u64 (cpu, rn, NO_SP);
2372 uint64_t value2 = aarch64_get_reg_u64 (cpu, rm, NO_SP);
2373 uint64_t carry = IS_SET (C);
2374 uint64_t result = value1 - value2 + 1 - carry;
2376 aarch64_set_reg_u64 (cpu, rd, NO_SP, result);
2377 set_flags_for_sub64 (cpu, value1, value2 + 1 - carry);
2381 dexAddSubtractWithCarry (sim_cpu *cpu)
2383 /* instr[31] = size : 0 ==> 32 bit, 1 ==> 64 bit
2384 instr[30] = op : 0 ==> ADC, 1 ==> SBC
2385 instr[29] = set? : 0 ==> no flags, 1 ==> set flags
2386 instr[28,21] = 1 1010 000
2388 instr[15,10] = op2 : 00000 ==> ok, ow ==> UNALLOC
2392 uint32_t op2 = uimm (aarch64_get_instr (cpu), 15, 10);
2393 /* Dispatch on size:op:set? i.e aarch64_get_instr (cpu)[31,29] */
2394 uint32_t dispatch = uimm (aarch64_get_instr (cpu), 31, 29);
2396 NYI_assert (28, 21, 0xD0);
2403 case 0: adc32 (cpu); break;
2404 case 1: adcs32 (cpu); break;
2405 case 2: sbc32 (cpu); break;
2406 case 3: sbcs32 (cpu); break;
2407 case 4: adc64 (cpu); break;
2408 case 5: adcs64 (cpu); break;
2409 case 6: sbc64 (cpu); break;
2410 case 7: sbcs64 (cpu); break;
2411 default: HALT_UNALLOC;
2416 testConditionCode (sim_cpu *cpu, CondCode cc)
2418 /* This should be reduceable to branchless logic
2419 by some careful testing of bits in CC followed
2420 by the requisite masking and combining of bits
2421 from the flag register.
2423 For now we do it with a switch. */
2428 case EQ: res = IS_SET (Z); break;
2429 case NE: res = IS_CLEAR (Z); break;
2430 case CS: res = IS_SET (C); break;
2431 case CC: res = IS_CLEAR (C); break;
2432 case MI: res = IS_SET (N); break;
2433 case PL: res = IS_CLEAR (N); break;
2434 case VS: res = IS_SET (V); break;
2435 case VC: res = IS_CLEAR (V); break;
2436 case HI: res = IS_SET (C) && IS_CLEAR (Z); break;
2437 case LS: res = IS_CLEAR (C) || IS_SET (Z); break;
2438 case GE: res = IS_SET (N) == IS_SET (V); break;
2439 case LT: res = IS_SET (N) != IS_SET (V); break;
2440 case GT: res = IS_CLEAR (Z) && (IS_SET (N) == IS_SET (V)); break;
2441 case LE: res = IS_SET (Z) || (IS_SET (N) != IS_SET (V)); break;
2452 CondCompare (sim_cpu *cpu) /* aka: ccmp and ccmn */
2454 /* instr[31] = size : 0 ==> 32 bit, 1 ==> 64 bit
2455 instr[30] = compare with positive (1) or negative value (0)
2456 instr[29,21] = 1 1101 0010
2457 instr[20,16] = Rm or const
2459 instr[11] = compare reg (0) or const (1)
2463 instr[3,0] = value for CPSR bits if the comparison does not take place. */
2468 NYI_assert (29, 21, 0x1d2);
2469 NYI_assert (10, 10, 0);
2470 NYI_assert (4, 4, 0);
2472 if (! testConditionCode (cpu, uimm (aarch64_get_instr (cpu), 15, 12)))
2474 aarch64_set_CPSR (cpu, uimm (aarch64_get_instr (cpu), 3, 0));
2478 negate = uimm (aarch64_get_instr (cpu), 30, 30) ? 1 : -1;
2479 rm = uimm (aarch64_get_instr (cpu), 20, 16);
2480 rn = uimm (aarch64_get_instr (cpu), 9, 5);
2482 if (uimm (aarch64_get_instr (cpu), 31, 31))
2484 if (uimm (aarch64_get_instr (cpu), 11, 11))
2485 set_flags_for_sub64 (cpu, aarch64_get_reg_u64 (cpu, rn, SP_OK),
2486 negate * (uint64_t) rm);
2488 set_flags_for_sub64 (cpu, aarch64_get_reg_u64 (cpu, rn, SP_OK),
2489 negate * aarch64_get_reg_u64 (cpu, rm, SP_OK));
2493 if (uimm (aarch64_get_instr (cpu), 11, 11))
2494 set_flags_for_sub32 (cpu, aarch64_get_reg_u32 (cpu, rn, SP_OK),
2497 set_flags_for_sub32 (cpu, aarch64_get_reg_u32 (cpu, rn, SP_OK),
2498 negate * aarch64_get_reg_u32 (cpu, rm, SP_OK));
2503 do_vec_MOV_whole_vector (sim_cpu *cpu)
2505 /* MOV Vd.T, Vs.T (alias for ORR Vd.T, Vn.T, Vm.T where Vn == Vm)
2508 instr[30] = half(0)/full(1)
2509 instr[29,21] = 001110101
2511 instr[15,10] = 000111
2515 unsigned vs = uimm (aarch64_get_instr (cpu), 9, 5);
2516 unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
2518 NYI_assert (29, 21, 0x075);
2519 NYI_assert (15, 10, 0x07);
2521 if (uimm (aarch64_get_instr (cpu), 20, 16) != vs)
2524 if (uimm (aarch64_get_instr (cpu), 30, 30))
2525 aarch64_set_vec_u64 (cpu, vd, 1, aarch64_get_vec_u64 (cpu, vs, 1));
2527 aarch64_set_vec_u64 (cpu, vd, 0, aarch64_get_vec_u64 (cpu, vs, 0));
2531 do_vec_MOV_into_scalar (sim_cpu *cpu)
2534 instr[30] = word(0)/long(1)
2535 instr[29,21] = 00 1110 000
2536 instr[20,18] = element size and index
2537 instr[17,10] = 00 0011 11
2538 instr[9,5] = V source
2539 instr[4,0] = R dest */
2541 unsigned vs = uimm (aarch64_get_instr (cpu), 9, 5);
2542 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
2544 NYI_assert (29, 21, 0x070);
2545 NYI_assert (17, 10, 0x0F);
2547 switch (uimm (aarch64_get_instr (cpu), 20, 18))
2550 aarch64_set_reg_u64 (cpu, rd, NO_SP, aarch64_get_vec_u64 (cpu, vs, 0));
2554 aarch64_set_reg_u64 (cpu, rd, NO_SP, aarch64_get_vec_u64 (cpu, vs, 1));
2561 aarch64_set_reg_u64 (cpu, rd, NO_SP, aarch64_get_vec_u32
2562 (cpu, vs, uimm (aarch64_get_instr (cpu), 20, 19)));
2571 do_vec_INS (sim_cpu *cpu)
2573 /* instr[31,21] = 01001110000
2574 instr[20,16] = element size and index
2575 instr[15,10] = 000111
2576 instr[9,5] = W source
2577 instr[4,0] = V dest */
2580 unsigned rs = uimm (aarch64_get_instr (cpu), 9, 5);
2581 unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
2583 NYI_assert (31, 21, 0x270);
2584 NYI_assert (15, 10, 0x07);
2586 if (uimm (aarch64_get_instr (cpu), 16, 16))
2588 index = uimm (aarch64_get_instr (cpu), 20, 17);
2589 aarch64_set_vec_u8 (cpu, vd, index,
2590 aarch64_get_reg_u8 (cpu, rs, NO_SP));
2592 else if (uimm (aarch64_get_instr (cpu), 17, 17))
2594 index = uimm (aarch64_get_instr (cpu), 20, 18);
2595 aarch64_set_vec_u16 (cpu, vd, index,
2596 aarch64_get_reg_u16 (cpu, rs, NO_SP));
2598 else if (uimm (aarch64_get_instr (cpu), 18, 18))
2600 index = uimm (aarch64_get_instr (cpu), 20, 19);
2601 aarch64_set_vec_u32 (cpu, vd, index,
2602 aarch64_get_reg_u32 (cpu, rs, NO_SP));
2604 else if (uimm (aarch64_get_instr (cpu), 19, 19))
2606 index = uimm (aarch64_get_instr (cpu), 20, 20);
2607 aarch64_set_vec_u64 (cpu, vd, index,
2608 aarch64_get_reg_u64 (cpu, rs, NO_SP));
2615 do_vec_DUP_vector_into_vector (sim_cpu *cpu)
2618 instr[30] = half(0)/full(1)
2619 instr[29,21] = 00 1110 000
2620 instr[20,16] = element size and index
2621 instr[15,10] = 0000 01
2622 instr[9,5] = V source
2623 instr[4,0] = V dest. */
2625 unsigned full = uimm (aarch64_get_instr (cpu), 30, 30);
2626 unsigned vs = uimm (aarch64_get_instr (cpu), 9, 5);
2627 unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
2630 NYI_assert (29, 21, 0x070);
2631 NYI_assert (15, 10, 0x01);
2633 if (uimm (aarch64_get_instr (cpu), 16, 16))
2635 index = uimm (aarch64_get_instr (cpu), 20, 17);
2637 for (i = 0; i < (full ? 16 : 8); i++)
2638 aarch64_set_vec_u8 (cpu, vd, i, aarch64_get_vec_u8 (cpu, vs, index));
2640 else if (uimm (aarch64_get_instr (cpu), 17, 17))
2642 index = uimm (aarch64_get_instr (cpu), 20, 18);
2644 for (i = 0; i < (full ? 8 : 4); i++)
2645 aarch64_set_vec_u16 (cpu, vd, i, aarch64_get_vec_u16 (cpu, vs, index));
2647 else if (uimm (aarch64_get_instr (cpu), 18, 18))
2649 index = uimm (aarch64_get_instr (cpu), 20, 19);
2651 for (i = 0; i < (full ? 4 : 2); i++)
2652 aarch64_set_vec_u32 (cpu, vd, i, aarch64_get_vec_u32 (cpu, vs, index));
2656 if (uimm (aarch64_get_instr (cpu), 19, 19) == 0)
2662 index = uimm (aarch64_get_instr (cpu), 20, 20);
2664 for (i = 0; i < 2; i++)
2665 aarch64_set_vec_u64 (cpu, vd, i, aarch64_get_vec_u64 (cpu, vs, index));
2670 do_vec_TBL (sim_cpu *cpu)
2673 instr[30] = half(0)/full(1)
2674 instr[29,21] = 00 1110 000
2677 instr[14,13] = vec length
2679 instr[9,5] = V start
2680 instr[4,0] = V dest */
2682 int full = uimm (aarch64_get_instr (cpu), 30, 30);
2683 int len = uimm (aarch64_get_instr (cpu), 14, 13) + 1;
2684 unsigned vm = uimm (aarch64_get_instr (cpu), 20, 16);
2685 unsigned vn = uimm (aarch64_get_instr (cpu), 9, 5);
2686 unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
2689 NYI_assert (29, 21, 0x070);
2690 NYI_assert (12, 10, 0);
2692 for (i = 0; i < (full ? 16 : 8); i++)
2694 unsigned int selector = aarch64_get_vec_u8 (cpu, vm, i);
2698 val = aarch64_get_vec_u8 (cpu, vn, selector);
2699 else if (selector < 32)
2700 val = len < 2 ? 0 : aarch64_get_vec_u8 (cpu, vn + 1, selector - 16);
2701 else if (selector < 48)
2702 val = len < 3 ? 0 : aarch64_get_vec_u8 (cpu, vn + 2, selector - 32);
2703 else if (selector < 64)
2704 val = len < 4 ? 0 : aarch64_get_vec_u8 (cpu, vn + 3, selector - 48);
2708 aarch64_set_vec_u8 (cpu, vd, i, val);
2713 do_vec_TRN (sim_cpu *cpu)
2716 instr[30] = half(0)/full(1)
2717 instr[29,24] = 00 1110
2722 instr[14] = TRN1 (0) / TRN2 (1)
2724 instr[9,5] = V source
2725 instr[4,0] = V dest. */
2727 int full = uimm (aarch64_get_instr (cpu), 30, 30);
2728 int second = uimm (aarch64_get_instr (cpu), 14, 14);
2729 unsigned vm = uimm (aarch64_get_instr (cpu), 20, 16);
2730 unsigned vn = uimm (aarch64_get_instr (cpu), 9, 5);
2731 unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
2734 NYI_assert (29, 24, 0x0E);
2735 NYI_assert (13, 10, 0xA);
2737 switch (uimm (aarch64_get_instr (cpu), 23, 22))
2740 for (i = 0; i < (full ? 8 : 4); i++)
2744 aarch64_get_vec_u8 (cpu, second ? vm : vn, i * 2));
2746 (cpu, vd, 1 * 2 + 1,
2747 aarch64_get_vec_u8 (cpu, second ? vn : vm, i * 2 + 1));
2752 for (i = 0; i < (full ? 4 : 2); i++)
2756 aarch64_get_vec_u16 (cpu, second ? vm : vn, i * 2));
2758 (cpu, vd, 1 * 2 + 1,
2759 aarch64_get_vec_u16 (cpu, second ? vn : vm, i * 2 + 1));
2765 (cpu, vd, 0, aarch64_get_vec_u32 (cpu, second ? vm : vn, 0));
2767 (cpu, vd, 1, aarch64_get_vec_u32 (cpu, second ? vn : vm, 1));
2769 (cpu, vd, 2, aarch64_get_vec_u32 (cpu, second ? vm : vn, 2));
2771 (cpu, vd, 3, aarch64_get_vec_u32 (cpu, second ? vn : vm, 3));
2778 aarch64_set_vec_u64 (cpu, vd, 0,
2779 aarch64_get_vec_u64 (cpu, second ? vm : vn, 0));
2780 aarch64_set_vec_u64 (cpu, vd, 1,
2781 aarch64_get_vec_u64 (cpu, second ? vn : vm, 1));
2790 do_vec_DUP_scalar_into_vector (sim_cpu *cpu)
2793 instr[30] = 0=> zero top 64-bits, 1=> duplicate into top 64-bits
2794 [must be 1 for 64-bit xfer]
2795 instr[29,20] = 00 1110 0000
2796 instr[19,16] = element size: 0001=> 8-bits, 0010=> 16-bits,
2797 0100=> 32-bits. 1000=>64-bits
2798 instr[15,10] = 0000 11
2799 instr[9,5] = W source
2800 instr[4,0] = V dest. */
2803 unsigned Vd = uimm (aarch64_get_instr (cpu), 4, 0);
2804 unsigned Rs = uimm (aarch64_get_instr (cpu), 9, 5);
2805 int both = uimm (aarch64_get_instr (cpu), 30, 30);
2807 NYI_assert (29, 20, 0x0E0);
2808 NYI_assert (15, 10, 0x03);
2810 switch (uimm (aarch64_get_instr (cpu), 19, 16))
2813 for (i = 0; i < (both ? 16 : 8); i++)
2814 aarch64_set_vec_u8 (cpu, Vd, i, aarch64_get_reg_u8 (cpu, Rs, NO_SP));
2818 for (i = 0; i < (both ? 8 : 4); i++)
2819 aarch64_set_vec_u16 (cpu, Vd, i, aarch64_get_reg_u16 (cpu, Rs, NO_SP));
2823 for (i = 0; i < (both ? 4 : 2); i++)
2824 aarch64_set_vec_u32 (cpu, Vd, i, aarch64_get_reg_u32 (cpu, Rs, NO_SP));
2830 aarch64_set_vec_u64 (cpu, Vd, 0, aarch64_get_reg_u64 (cpu, Rs, NO_SP));
2831 aarch64_set_vec_u64 (cpu, Vd, 1, aarch64_get_reg_u64 (cpu, Rs, NO_SP));
2840 do_vec_UZP (sim_cpu *cpu)
2843 instr[30] = half(0)/full(1)
2844 instr[29,24] = 00 1110
2845 instr[23,22] = size: byte(00), half(01), word (10), long (11)
2849 instr[14] = lower (0) / upper (1)
2854 int full = uimm (aarch64_get_instr (cpu), 30, 30);
2855 int upper = uimm (aarch64_get_instr (cpu), 14, 14);
2857 unsigned vm = uimm (aarch64_get_instr (cpu), 20, 16);
2858 unsigned vn = uimm (aarch64_get_instr (cpu), 9, 5);
2859 unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
2861 uint64_t val_m1 = aarch64_get_vec_u64 (cpu, vm, 0);
2862 uint64_t val_m2 = aarch64_get_vec_u64 (cpu, vm, 1);
2863 uint64_t val_n1 = aarch64_get_vec_u64 (cpu, vn, 0);
2864 uint64_t val_n2 = aarch64_get_vec_u64 (cpu, vn, 1);
2869 uint64_t input1 = upper ? val_n1 : val_m1;
2870 uint64_t input2 = upper ? val_n2 : val_m2;
2873 NYI_assert (29, 24, 0x0E);
2874 NYI_assert (21, 21, 0);
2875 NYI_assert (15, 15, 0);
2876 NYI_assert (13, 10, 6);
2878 switch (uimm (aarch64_get_instr (cpu), 23, 23))
2881 for (i = 0; i < 8; i++)
2883 val1 |= (input1 >> (i * 8)) & (0xFFULL << (i * 8));
2884 val2 |= (input2 >> (i * 8)) & (0xFFULL << (i * 8));
2889 for (i = 0; i < 4; i++)
2891 val1 |= (input1 >> (i * 16)) & (0xFFFFULL << (i * 16));
2892 val2 |= (input2 >> (i * 16)) & (0xFFFFULL << (i * 16));
2897 val1 = ((input1 & 0xFFFFFFFF) | ((input1 >> 32) & 0xFFFFFFFF00000000ULL));
2898 val2 = ((input2 & 0xFFFFFFFF) | ((input2 >> 32) & 0xFFFFFFFF00000000ULL));
2906 aarch64_set_vec_u64 (cpu, vd, 0, val1);
2908 aarch64_set_vec_u64 (cpu, vd, 1, val2);
2912 do_vec_ZIP (sim_cpu *cpu)
2915 instr[30] = half(0)/full(1)
2916 instr[29,24] = 00 1110
2917 instr[23,22] = size: byte(00), hald(01), word (10), long (11)
2921 instr[14] = lower (0) / upper (1)
2926 int full = uimm (aarch64_get_instr (cpu), 30, 30);
2927 int upper = uimm (aarch64_get_instr (cpu), 14, 14);
2929 unsigned vm = uimm (aarch64_get_instr (cpu), 20, 16);
2930 unsigned vn = uimm (aarch64_get_instr (cpu), 9, 5);
2931 unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
2933 uint64_t val_m1 = aarch64_get_vec_u64 (cpu, vm, 0);
2934 uint64_t val_m2 = aarch64_get_vec_u64 (cpu, vm, 1);
2935 uint64_t val_n1 = aarch64_get_vec_u64 (cpu, vn, 0);
2936 uint64_t val_n2 = aarch64_get_vec_u64 (cpu, vn, 1);
2941 uint64_t input1 = upper ? val_n1 : val_m1;
2942 uint64_t input2 = upper ? val_n2 : val_m2;
2944 NYI_assert (29, 24, 0x0E);
2945 NYI_assert (21, 21, 0);
2946 NYI_assert (15, 15, 0);
2947 NYI_assert (13, 10, 0xE);
2949 switch (uimm (aarch64_get_instr (cpu), 23, 23))
2953 ((input1 << 0) & (0xFF << 0))
2954 | ((input2 << 8) & (0xFF << 8))
2955 | ((input1 << 8) & (0xFF << 16))
2956 | ((input2 << 16) & (0xFF << 24))
2957 | ((input1 << 16) & (0xFFULL << 32))
2958 | ((input2 << 24) & (0xFFULL << 40))
2959 | ((input1 << 24) & (0xFFULL << 48))
2960 | ((input2 << 32) & (0xFFULL << 56));
2963 ((input1 >> 32) & (0xFF << 0))
2964 | ((input2 >> 24) & (0xFF << 8))
2965 | ((input1 >> 24) & (0xFF << 16))
2966 | ((input2 >> 16) & (0xFF << 24))
2967 | ((input1 >> 16) & (0xFFULL << 32))
2968 | ((input2 >> 8) & (0xFFULL << 40))
2969 | ((input1 >> 8) & (0xFFULL << 48))
2970 | ((input2 >> 0) & (0xFFULL << 56));
2975 ((input1 << 0) & (0xFFFF << 0))
2976 | ((input2 << 16) & (0xFFFF << 16))
2977 | ((input1 << 16) & (0xFFFFULL << 32))
2978 | ((input2 << 32) & (0xFFFFULL << 48));
2981 ((input1 >> 32) & (0xFFFF << 0))
2982 | ((input2 >> 16) & (0xFFFF << 16))
2983 | ((input1 >> 16) & (0xFFFFULL << 32))
2984 | ((input2 >> 0) & (0xFFFFULL << 48));
2988 val1 = (input1 & 0xFFFFFFFFULL) | (input2 << 32);
2989 val2 = (input2 & 0xFFFFFFFFULL) | (input1 << 32);
2998 aarch64_set_vec_u64 (cpu, vd, 0, val1);
3000 aarch64_set_vec_u64 (cpu, vd, 1, val2);
3003 /* Floating point immediates are encoded in 8 bits.
3004 fpimm[7] = sign bit.
3005 fpimm[6:4] = signed exponent.
3006 fpimm[3:0] = fraction (assuming leading 1).
3007 i.e. F = s * 1.f * 2^(e - b). */
3010 fp_immediate_for_encoding_32 (uint32_t imm8)
3013 uint32_t s, e, f, i;
3015 s = (imm8 >> 7) & 0x1;
3016 e = (imm8 >> 4) & 0x7;
3019 /* The fp value is s * n/16 * 2r where n is 16+e. */
3020 u = (16.0 + f) / 16.0;
3022 /* N.B. exponent is signed. */
3027 for (i = 0; i <= epos; i++)
3034 for (i = 0; i < eneg; i++)
3045 fp_immediate_for_encoding_64 (uint32_t imm8)
3048 uint32_t s, e, f, i;
3050 s = (imm8 >> 7) & 0x1;
3051 e = (imm8 >> 4) & 0x7;
3054 /* The fp value is s * n/16 * 2r where n is 16+e. */
3055 u = (16.0 + f) / 16.0;
3057 /* N.B. exponent is signed. */
3062 for (i = 0; i <= epos; i++)
3069 for (i = 0; i < eneg; i++)
3080 do_vec_MOV_immediate (sim_cpu *cpu)
3083 instr[30] = full/half selector
3084 instr[29,19] = 00111100000
3085 instr[18,16] = high 3 bits of uimm8
3086 instr[15,12] = size & shift:
3088 0010 => 32-bit + LSL#8
3089 0100 => 32-bit + LSL#16
3090 0110 => 32-bit + LSL#24
3091 1010 => 16-bit + LSL#8
3093 1101 => 32-bit + MSL#16
3094 1100 => 32-bit + MSL#8
3098 instr[9,5] = low 5-bits of uimm8
3101 int full = uimm (aarch64_get_instr (cpu), 30, 30);
3102 unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
3103 unsigned val = uimm (aarch64_get_instr (cpu), 18, 16) << 5
3104 | uimm (aarch64_get_instr (cpu), 9, 5);
3107 NYI_assert (29, 19, 0x1E0);
3108 NYI_assert (11, 10, 1);
3110 switch (uimm (aarch64_get_instr (cpu), 15, 12))
3112 case 0x0: /* 32-bit, no shift. */
3113 case 0x2: /* 32-bit, shift by 8. */
3114 case 0x4: /* 32-bit, shift by 16. */
3115 case 0x6: /* 32-bit, shift by 24. */
3116 val <<= (8 * uimm (aarch64_get_instr (cpu), 14, 13));
3117 for (i = 0; i < (full ? 4 : 2); i++)
3118 aarch64_set_vec_u32 (cpu, vd, i, val);
3121 case 0xa: /* 16-bit, shift by 8. */
3124 case 0x8: /* 16-bit, no shift. */
3125 for (i = 0; i < (full ? 8 : 4); i++)
3126 aarch64_set_vec_u16 (cpu, vd, i, val);
3128 case 0xd: /* 32-bit, mask shift by 16. */
3132 case 0xc: /* 32-bit, mask shift by 8. */
3135 for (i = 0; i < (full ? 4 : 2); i++)
3136 aarch64_set_vec_u32 (cpu, vd, i, val);
3139 case 0xe: /* 8-bit, no shift. */
3140 for (i = 0; i < (full ? 16 : 8); i++)
3141 aarch64_set_vec_u8 (cpu, vd, i, val);
3144 case 0xf: /* FMOV Vs.{2|4}S, #fpimm. */
3146 float u = fp_immediate_for_encoding_32 (val);
3147 for (i = 0; i < (full ? 4 : 2); i++)
3148 aarch64_set_vec_float (cpu, vd, i, u);
3158 do_vec_MVNI (sim_cpu *cpu)
3161 instr[30] = full/half selector
3162 instr[29,19] = 10111100000
3163 instr[18,16] = high 3 bits of uimm8
3164 instr[15,12] = selector
3166 instr[9,5] = low 5-bits of uimm8
3169 int full = uimm (aarch64_get_instr (cpu), 30, 30);
3170 unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
3171 unsigned val = uimm (aarch64_get_instr (cpu), 18, 16) << 5
3172 | uimm (aarch64_get_instr (cpu), 9, 5);
3175 NYI_assert (29, 19, 0x5E0);
3176 NYI_assert (11, 10, 1);
3178 switch (uimm (aarch64_get_instr (cpu), 15, 12))
3180 case 0x0: /* 32-bit, no shift. */
3181 case 0x2: /* 32-bit, shift by 8. */
3182 case 0x4: /* 32-bit, shift by 16. */
3183 case 0x6: /* 32-bit, shift by 24. */
3184 val <<= (8 * uimm (aarch64_get_instr (cpu), 14, 13));
3186 for (i = 0; i < (full ? 4 : 2); i++)
3187 aarch64_set_vec_u32 (cpu, vd, i, val);
3190 case 0xa: /* 16-bit, 8 bit shift. */
3192 case 0x8: /* 16-bit, no shift. */
3194 for (i = 0; i < (full ? 8 : 4); i++)
3195 aarch64_set_vec_u16 (cpu, vd, i, val);
3198 case 0xd: /* 32-bit, mask shift by 16. */
3201 case 0xc: /* 32-bit, mask shift by 8. */
3205 for (i = 0; i < (full ? 4 : 2); i++)
3206 aarch64_set_vec_u32 (cpu, vd, i, val);
3209 case 0xE: /* MOVI Dn, #mask64 */
3213 for (i = 0; i < 8; i++)
3215 mask |= (0xF << (i * 4));
3216 aarch64_set_vec_u64 (cpu, vd, 0, mask);
3217 aarch64_set_vec_u64 (cpu, vd, 1, 0);
3221 case 0xf: /* FMOV Vd.2D, #fpimm. */
3223 double u = fp_immediate_for_encoding_64 (val);
3228 aarch64_set_vec_double (cpu, vd, 0, u);
3229 aarch64_set_vec_double (cpu, vd, 1, u);
3238 #define ABS(A) ((A) < 0 ? - (A) : (A))
3241 do_vec_ABS (sim_cpu *cpu)
3244 instr[30] = half(0)/full(1)
3245 instr[29,24] = 00 1110
3246 instr[23,22] = size: 00=> 8-bit, 01=> 16-bit, 10=> 32-bit, 11=> 64-bit
3247 instr[21,10] = 10 0000 1011 10
3251 unsigned vn = uimm (aarch64_get_instr (cpu), 9, 5);
3252 unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
3253 unsigned full = uimm (aarch64_get_instr (cpu), 30, 30);
3256 NYI_assert (29, 24, 0x0E);
3257 NYI_assert (21, 10, 0x82E);
3259 switch (uimm (aarch64_get_instr (cpu), 23, 22))
3262 for (i = 0; i < (full ? 16 : 8); i++)
3263 aarch64_set_vec_s8 (cpu, vd, i,
3264 ABS (aarch64_get_vec_s8 (cpu, vn, i)));
3268 for (i = 0; i < (full ? 8 : 4); i++)
3269 aarch64_set_vec_s16 (cpu, vd, i,
3270 ABS (aarch64_get_vec_s16 (cpu, vn, i)));
3274 for (i = 0; i < (full ? 4 : 2); i++)
3275 aarch64_set_vec_s32 (cpu, vd, i,
3276 ABS (aarch64_get_vec_s32 (cpu, vn, i)));
3282 for (i = 0; i < 2; i++)
3283 aarch64_set_vec_s64 (cpu, vd, i,
3284 ABS (aarch64_get_vec_s64 (cpu, vn, i)));
3290 do_vec_ADDV (sim_cpu *cpu)
3293 instr[30] = full/half selector
3294 instr[29,24] = 00 1110
3295 instr[23,22] = size: 00=> 8-bit, 01=> 16-bit, 10=> 32-bit, 11=> 64-bit
3296 instr[21,10] = 11 0001 1011 10
3300 unsigned vm = uimm (aarch64_get_instr (cpu), 9, 5);
3301 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
3304 int full = uimm (aarch64_get_instr (cpu), 30, 30);
3306 NYI_assert (29, 24, 0x0E);
3307 NYI_assert (21, 10, 0xC6E);
3309 switch (uimm (aarch64_get_instr (cpu), 23, 22))
3312 for (i = 0; i < (full ? 16 : 8); i++)
3313 val += aarch64_get_vec_u8 (cpu, vm, i);
3314 aarch64_set_reg_u64 (cpu, rd, NO_SP, val);
3318 for (i = 0; i < (full ? 8 : 4); i++)
3319 val += aarch64_get_vec_u16 (cpu, vm, i);
3320 aarch64_set_reg_u64 (cpu, rd, NO_SP, val);
3324 for (i = 0; i < (full ? 4 : 2); i++)
3325 val += aarch64_get_vec_u32 (cpu, vm, i);
3326 aarch64_set_reg_u64 (cpu, rd, NO_SP, val);
3332 val = aarch64_get_vec_u64 (cpu, vm, 0);
3333 val += aarch64_get_vec_u64 (cpu, vm, 1);
3334 aarch64_set_reg_u64 (cpu, rd, NO_SP, val);
3343 do_vec_ins_2 (sim_cpu *cpu)
3345 /* instr[31,21] = 01001110000
3346 instr[20,18] = size & element selector
3348 instr[13] = direction: to vec(0), from vec (1)
3354 unsigned vm = uimm (aarch64_get_instr (cpu), 9, 5);
3355 unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
3357 NYI_assert (31, 21, 0x270);
3358 NYI_assert (17, 14, 0);
3359 NYI_assert (12, 10, 7);
3361 if (uimm (aarch64_get_instr (cpu), 13, 13) == 1)
3363 if (uimm (aarch64_get_instr (cpu), 18, 18) == 1)
3366 elem = uimm (aarch64_get_instr (cpu), 20, 19);
3367 aarch64_set_reg_u64 (cpu, vd, NO_SP,
3368 aarch64_get_vec_u32 (cpu, vm, elem));
3373 if (uimm (aarch64_get_instr (cpu), 19, 19) != 1)
3376 elem = uimm (aarch64_get_instr (cpu), 20, 20);
3377 aarch64_set_reg_u64 (cpu, vd, NO_SP,
3378 aarch64_get_vec_u64 (cpu, vm, elem));
3383 if (uimm (aarch64_get_instr (cpu), 18, 18) == 1)
3386 elem = uimm (aarch64_get_instr (cpu), 20, 19);
3387 aarch64_set_vec_u32 (cpu, vd, elem,
3388 aarch64_get_reg_u32 (cpu, vm, NO_SP));
3393 if (uimm (aarch64_get_instr (cpu), 19, 19) != 1)
3396 elem = uimm (aarch64_get_instr (cpu), 20, 20);
3397 aarch64_set_vec_u64 (cpu, vd, elem,
3398 aarch64_get_reg_u64 (cpu, vm, NO_SP));
3404 do_vec_mull (sim_cpu *cpu)
3407 instr[30] = lower(0)/upper(1) selector
3408 instr[29] = signed(0)/unsigned(1)
3409 instr[28,24] = 0 1110
3410 instr[23,22] = size: 8-bit (00), 16-bit (01), 32-bit (10)
3413 instr[15,10] = 11 0000
3417 int unsign = uimm (aarch64_get_instr (cpu), 29, 29);
3418 int bias = uimm (aarch64_get_instr (cpu), 30, 30);
3419 unsigned vm = uimm (aarch64_get_instr (cpu), 20, 16);
3420 unsigned vn = uimm (aarch64_get_instr (cpu), 9, 5);
3421 unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
3424 NYI_assert (28, 24, 0x0E);
3425 NYI_assert (15, 10, 0x30);
3427 switch (uimm (aarch64_get_instr (cpu), 23, 22))
3433 for (i = 0; i < 8; i++)
3434 aarch64_set_vec_u16 (cpu, vd, i,
3435 aarch64_get_vec_u8 (cpu, vn, i + bias)
3436 * aarch64_get_vec_u8 (cpu, vm, i + bias));
3438 for (i = 0; i < 8; i++)
3439 aarch64_set_vec_s16 (cpu, vd, i,
3440 aarch64_get_vec_s8 (cpu, vn, i + bias)
3441 * aarch64_get_vec_s8 (cpu, vm, i + bias));
3448 for (i = 0; i < 4; i++)
3449 aarch64_set_vec_u32 (cpu, vd, i,
3450 aarch64_get_vec_u16 (cpu, vn, i + bias)
3451 * aarch64_get_vec_u16 (cpu, vm, i + bias));
3453 for (i = 0; i < 4; i++)
3454 aarch64_set_vec_s32 (cpu, vd, i,
3455 aarch64_get_vec_s16 (cpu, vn, i + bias)
3456 * aarch64_get_vec_s16 (cpu, vm, i + bias));
3463 for (i = 0; i < 2; i++)
3464 aarch64_set_vec_u64 (cpu, vd, i,
3465 (uint64_t) aarch64_get_vec_u32 (cpu, vn,
3467 * (uint64_t) aarch64_get_vec_u32 (cpu, vm,
3470 for (i = 0; i < 2; i++)
3471 aarch64_set_vec_s64 (cpu, vd, i,
3472 aarch64_get_vec_s32 (cpu, vn, i + bias)
3473 * aarch64_get_vec_s32 (cpu, vm, i + bias));
3483 do_vec_fadd (sim_cpu *cpu)
3486 instr[30] = half(0)/full(1)
3487 instr[29,24] = 001110
3488 instr[23] = FADD(0)/FSUB(1)
3489 instr[22] = float (0)/double(1)
3492 instr[15,10] = 110101
3496 unsigned vm = uimm (aarch64_get_instr (cpu), 20, 16);
3497 unsigned vn = uimm (aarch64_get_instr (cpu), 9, 5);
3498 unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
3500 int full = uimm (aarch64_get_instr (cpu), 30, 30);
3502 NYI_assert (29, 24, 0x0E);
3503 NYI_assert (21, 21, 1);
3504 NYI_assert (15, 10, 0x35);
3506 if (uimm (aarch64_get_instr (cpu), 23, 23))
3508 if (uimm (aarch64_get_instr (cpu), 22, 22))
3513 for (i = 0; i < 2; i++)
3514 aarch64_set_vec_double (cpu, vd, i,
3515 aarch64_get_vec_double (cpu, vn, i)
3516 - aarch64_get_vec_double (cpu, vm, i));
3520 for (i = 0; i < (full ? 4 : 2); i++)
3521 aarch64_set_vec_float (cpu, vd, i,
3522 aarch64_get_vec_float (cpu, vn, i)
3523 - aarch64_get_vec_float (cpu, vm, i));
3528 if (uimm (aarch64_get_instr (cpu), 22, 22))
3533 for (i = 0; i < 2; i++)
3534 aarch64_set_vec_double (cpu, vd, i,
3535 aarch64_get_vec_double (cpu, vm, i)
3536 + aarch64_get_vec_double (cpu, vn, i));
3540 for (i = 0; i < (full ? 4 : 2); i++)
3541 aarch64_set_vec_float (cpu, vd, i,
3542 aarch64_get_vec_float (cpu, vm, i)
3543 + aarch64_get_vec_float (cpu, vn, i));
3549 do_vec_add (sim_cpu *cpu)
3552 instr[30] = full/half selector
3553 instr[29,24] = 001110
3554 instr[23,22] = size: 00=> 8-bit, 01=> 16-bit, 10=> 32-bit, 11=> 64-bit
3557 instr[15,10] = 100001
3561 unsigned vm = uimm (aarch64_get_instr (cpu), 20, 16);
3562 unsigned vn = uimm (aarch64_get_instr (cpu), 9, 5);
3563 unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
3565 int full = uimm (aarch64_get_instr (cpu), 30, 30);
3567 NYI_assert (29, 24, 0x0E);
3568 NYI_assert (21, 21, 1);
3569 NYI_assert (15, 10, 0x21);
3571 switch (uimm (aarch64_get_instr (cpu), 23, 22))
3574 for (i = 0; i < (full ? 16 : 8); i++)
3575 aarch64_set_vec_u8 (cpu, vd, i, aarch64_get_vec_u8 (cpu, vn, i)
3576 + aarch64_get_vec_u8 (cpu, vm, i));
3580 for (i = 0; i < (full ? 8 : 4); i++)
3581 aarch64_set_vec_u16 (cpu, vd, i, aarch64_get_vec_u16 (cpu, vn, i)
3582 + aarch64_get_vec_u16 (cpu, vm, i));
3586 for (i = 0; i < (full ? 4 : 2); i++)
3587 aarch64_set_vec_u32 (cpu, vd, i, aarch64_get_vec_u32 (cpu, vn, i)
3588 + aarch64_get_vec_u32 (cpu, vm, i));
3594 aarch64_set_vec_u64 (cpu, vd, 0, aarch64_get_vec_u64 (cpu, vn, 0)
3595 + aarch64_get_vec_u64 (cpu, vm, 0));
3596 aarch64_set_vec_u64 (cpu, vd, 1,
3597 aarch64_get_vec_u64 (cpu, vn, 1)
3598 + aarch64_get_vec_u64 (cpu, vm, 1));
3607 do_vec_mul (sim_cpu *cpu)
3610 instr[30] = full/half selector
3611 instr[29,24] = 00 1110
3612 instr[23,22] = size: 00=> 8-bit, 01=> 16-bit, 10=> 32-bit
3615 instr[15,10] = 10 0111
3619 unsigned vm = uimm (aarch64_get_instr (cpu), 20, 16);
3620 unsigned vn = uimm (aarch64_get_instr (cpu), 9, 5);
3621 unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
3623 int full = uimm (aarch64_get_instr (cpu), 30, 30);
3625 NYI_assert (29, 24, 0x0E);
3626 NYI_assert (21, 21, 1);
3627 NYI_assert (15, 10, 0x27);
3629 switch (uimm (aarch64_get_instr (cpu), 23, 22))
3632 for (i = 0; i < (full ? 16 : 8); i++)
3634 uint16_t val = aarch64_get_vec_u8 (cpu, vn, i);
3635 val *= aarch64_get_vec_u8 (cpu, vm, i);
3637 aarch64_set_vec_u16 (cpu, vd, i, val);
3642 for (i = 0; i < (full ? 8 : 4); i++)
3644 uint32_t val = aarch64_get_vec_u16 (cpu, vn, i);
3645 val *= aarch64_get_vec_u16 (cpu, vm, i);
3647 aarch64_set_vec_u32 (cpu, vd, i, val);
3652 for (i = 0; i < (full ? 4 : 2); i++)
3654 uint64_t val = aarch64_get_vec_u32 (cpu, vn, i);
3655 val *= aarch64_get_vec_u32 (cpu, vm, i);
3657 aarch64_set_vec_u64 (cpu, vd, i, val);
3668 do_vec_MLA (sim_cpu *cpu)
3671 instr[30] = full/half selector
3672 instr[29,24] = 00 1110
3673 instr[23,22] = size: 00=> 8-bit, 01=> 16-bit, 10=> 32-bit
3676 instr[15,10] = 1001 01
3680 unsigned vm = uimm (aarch64_get_instr (cpu), 20, 16);
3681 unsigned vn = uimm (aarch64_get_instr (cpu), 9, 5);
3682 unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
3684 int full = uimm (aarch64_get_instr (cpu), 30, 30);
3686 NYI_assert (29, 24, 0x0E);
3687 NYI_assert (21, 21, 1);
3688 NYI_assert (15, 10, 0x25);
3690 switch (uimm (aarch64_get_instr (cpu), 23, 22))
3693 for (i = 0; i < (full ? 16 : 8); i++)
3695 uint16_t val = aarch64_get_vec_u8 (cpu, vn, i);
3696 val *= aarch64_get_vec_u8 (cpu, vm, i);
3697 val += aarch64_get_vec_u8 (cpu, vd, i);
3699 aarch64_set_vec_u16 (cpu, vd, i, val);
3704 for (i = 0; i < (full ? 8 : 4); i++)
3706 uint32_t val = aarch64_get_vec_u16 (cpu, vn, i);
3707 val *= aarch64_get_vec_u16 (cpu, vm, i);
3708 val += aarch64_get_vec_u16 (cpu, vd, i);
3710 aarch64_set_vec_u32 (cpu, vd, i, val);
3715 for (i = 0; i < (full ? 4 : 2); i++)
3717 uint64_t val = aarch64_get_vec_u32 (cpu, vn, i);
3718 val *= aarch64_get_vec_u32 (cpu, vm, i);
3719 val += aarch64_get_vec_u32 (cpu, vd, i);
3721 aarch64_set_vec_u64 (cpu, vd, i, val);
3732 fmaxnm (float a, float b)
3734 if (fpclassify (a) == FP_NORMAL)
3736 if (fpclassify (b) == FP_NORMAL)
3737 return a > b ? a : b;
3740 else if (fpclassify (b) == FP_NORMAL)
3746 fminnm (float a, float b)
3748 if (fpclassify (a) == FP_NORMAL)
3750 if (fpclassify (b) == FP_NORMAL)
3751 return a < b ? a : b;
3754 else if (fpclassify (b) == FP_NORMAL)
3760 dmaxnm (double a, double b)
3762 if (fpclassify (a) == FP_NORMAL)
3764 if (fpclassify (b) == FP_NORMAL)
3765 return a > b ? a : b;
3768 else if (fpclassify (b) == FP_NORMAL)
3774 dminnm (double a, double b)
3776 if (fpclassify (a) == FP_NORMAL)
3778 if (fpclassify (b) == FP_NORMAL)
3779 return a < b ? a : b;
3782 else if (fpclassify (b) == FP_NORMAL)
3788 do_vec_FminmaxNMP (sim_cpu *cpu)
3790 /* aarch64_get_instr (cpu)[31] = 0
3791 aarch64_get_instr (cpu)[30] = half (0)/full (1)
3792 aarch64_get_instr (cpu)[29,24] = 10 1110
3793 aarch64_get_instr (cpu)[23] = max(0)/min(1)
3794 aarch64_get_instr (cpu)[22] = float (0)/double (1)
3795 aarch64_get_instr (cpu)[21] = 1
3796 aarch64_get_instr (cpu)[20,16] = Vn
3797 aarch64_get_instr (cpu)[15,10] = 1100 01
3798 aarch64_get_instr (cpu)[9,5] = Vm
3799 aarch64_get_instr (cpu)[4.0] = Vd. */
3801 unsigned vm = uimm (aarch64_get_instr (cpu), 20, 16);
3802 unsigned vn = uimm (aarch64_get_instr (cpu), 9, 5);
3803 unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
3804 int full = uimm (aarch64_get_instr (cpu), 30, 30);
3806 NYI_assert (29, 24, 0x2E);
3807 NYI_assert (21, 21, 1);
3808 NYI_assert (15, 10, 0x31);
3810 if (uimm (aarch64_get_instr (cpu), 22, 22))
3812 double (* fn)(double, double) = uimm (aarch64_get_instr (cpu), 23, 23)
3817 aarch64_set_vec_double (cpu, vd, 0,
3818 fn (aarch64_get_vec_double (cpu, vn, 0),
3819 aarch64_get_vec_double (cpu, vn, 1)));
3820 aarch64_set_vec_double (cpu, vd, 0,
3821 fn (aarch64_get_vec_double (cpu, vm, 0),
3822 aarch64_get_vec_double (cpu, vm, 1)));
3826 float (* fn)(float, float) = uimm (aarch64_get_instr (cpu), 23, 23)
3829 aarch64_set_vec_float (cpu, vd, 0,
3830 fn (aarch64_get_vec_float (cpu, vn, 0),
3831 aarch64_get_vec_float (cpu, vn, 1)));
3833 aarch64_set_vec_float (cpu, vd, 1,
3834 fn (aarch64_get_vec_float (cpu, vn, 2),
3835 aarch64_get_vec_float (cpu, vn, 3)));
3837 aarch64_set_vec_float (cpu, vd, (full ? 2 : 1),
3838 fn (aarch64_get_vec_float (cpu, vm, 0),
3839 aarch64_get_vec_float (cpu, vm, 1)));
3841 aarch64_set_vec_float (cpu, vd, 3,
3842 fn (aarch64_get_vec_float (cpu, vm, 2),
3843 aarch64_get_vec_float (cpu, vm, 3)));
3848 do_vec_AND (sim_cpu *cpu)
3851 instr[30] = half (0)/full (1)
3852 instr[29,21] = 001110001
3854 instr[15,10] = 000111
3858 unsigned vm = uimm (aarch64_get_instr (cpu), 20, 16);
3859 unsigned vn = uimm (aarch64_get_instr (cpu), 9, 5);
3860 unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
3862 int full = uimm (aarch64_get_instr (cpu), 30, 30);
3864 NYI_assert (29, 21, 0x071);
3865 NYI_assert (15, 10, 0x07);
3867 for (i = 0; i < (full ? 4 : 2); i++)
3868 aarch64_set_vec_u32 (cpu, vd, i,
3869 aarch64_get_vec_u32 (cpu, vn, i)
3870 & aarch64_get_vec_u32 (cpu, vm, i));
3874 do_vec_BSL (sim_cpu *cpu)
3877 instr[30] = half (0)/full (1)
3878 instr[29,21] = 101110011
3880 instr[15,10] = 000111
3884 unsigned vm = uimm (aarch64_get_instr (cpu), 20, 16);
3885 unsigned vn = uimm (aarch64_get_instr (cpu), 9, 5);
3886 unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
3888 int full = uimm (aarch64_get_instr (cpu), 30, 30);
3890 NYI_assert (29, 21, 0x173);
3891 NYI_assert (15, 10, 0x07);
3893 for (i = 0; i < (full ? 16 : 8); i++)
3894 aarch64_set_vec_u8 (cpu, vd, i,
3895 ( aarch64_get_vec_u8 (cpu, vd, i)
3896 & aarch64_get_vec_u8 (cpu, vn, i))
3897 | ((~ aarch64_get_vec_u8 (cpu, vd, i))
3898 & aarch64_get_vec_u8 (cpu, vm, i)));
3902 do_vec_EOR (sim_cpu *cpu)
3905 instr[30] = half (0)/full (1)
3906 instr[29,21] = 10 1110 001
3908 instr[15,10] = 000111
3912 unsigned vm = uimm (aarch64_get_instr (cpu), 20, 16);
3913 unsigned vn = uimm (aarch64_get_instr (cpu), 9, 5);
3914 unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
3916 int full = uimm (aarch64_get_instr (cpu), 30, 30);
3918 NYI_assert (29, 21, 0x171);
3919 NYI_assert (15, 10, 0x07);
3921 for (i = 0; i < (full ? 4 : 2); i++)
3922 aarch64_set_vec_u32 (cpu, vd, i,
3923 aarch64_get_vec_u32 (cpu, vn, i)
3924 ^ aarch64_get_vec_u32 (cpu, vm, i));
3928 do_vec_bit (sim_cpu *cpu)
3931 instr[30] = half (0)/full (1)
3932 instr[29,23] = 10 1110 1
3933 instr[22] = BIT (0) / BIF (1)
3936 instr[15,10] = 0001 11
3940 unsigned vm = uimm (aarch64_get_instr (cpu), 20, 16);
3941 unsigned vn = uimm (aarch64_get_instr (cpu), 9, 5);
3942 unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
3943 unsigned full = uimm (aarch64_get_instr (cpu), 30, 30);
3944 unsigned test_false = uimm (aarch64_get_instr (cpu), 22, 22);
3947 NYI_assert (29, 23, 0x5D);
3948 NYI_assert (21, 21, 1);
3949 NYI_assert (15, 10, 0x07);
3953 for (i = 0; i < (full ? 16 : 8); i++)
3954 if (aarch64_get_vec_u32 (cpu, vn, i) == 0)
3955 aarch64_set_vec_u32 (cpu, vd, i, aarch64_get_vec_u32 (cpu, vm, i));
3959 for (i = 0; i < (full ? 16 : 8); i++)
3960 if (aarch64_get_vec_u32 (cpu, vn, i) != 0)
3961 aarch64_set_vec_u32 (cpu, vd, i, aarch64_get_vec_u32 (cpu, vm, i));
3966 do_vec_ORN (sim_cpu *cpu)
3969 instr[30] = half (0)/full (1)
3970 instr[29,21] = 00 1110 111
3972 instr[15,10] = 00 0111
3976 unsigned vm = uimm (aarch64_get_instr (cpu), 20, 16);
3977 unsigned vn = uimm (aarch64_get_instr (cpu), 9, 5);
3978 unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
3980 int full = uimm (aarch64_get_instr (cpu), 30, 30);
3982 NYI_assert (29, 21, 0x077);
3983 NYI_assert (15, 10, 0x07);
3985 for (i = 0; i < (full ? 16 : 8); i++)
3986 aarch64_set_vec_u8 (cpu, vd, i,
3987 aarch64_get_vec_u8 (cpu, vn, i)
3988 | ~ aarch64_get_vec_u8 (cpu, vm, i));
3992 do_vec_ORR (sim_cpu *cpu)
3995 instr[30] = half (0)/full (1)
3996 instr[29,21] = 00 1110 101
3998 instr[15,10] = 0001 11
4002 unsigned vm = uimm (aarch64_get_instr (cpu), 20, 16);
4003 unsigned vn = uimm (aarch64_get_instr (cpu), 9, 5);
4004 unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
4006 int full = uimm (aarch64_get_instr (cpu), 30, 30);
4008 NYI_assert (29, 21, 0x075);
4009 NYI_assert (15, 10, 0x07);
4011 for (i = 0; i < (full ? 16 : 8); i++)
4012 aarch64_set_vec_u8 (cpu, vd, i,
4013 aarch64_get_vec_u8 (cpu, vn, i)
4014 | aarch64_get_vec_u8 (cpu, vm, i));
4018 do_vec_BIC (sim_cpu *cpu)
4021 instr[30] = half (0)/full (1)
4022 instr[29,21] = 00 1110 011
4024 instr[15,10] = 00 0111
4028 unsigned vm = uimm (aarch64_get_instr (cpu), 20, 16);
4029 unsigned vn = uimm (aarch64_get_instr (cpu), 9, 5);
4030 unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
4032 int full = uimm (aarch64_get_instr (cpu), 30, 30);
4034 NYI_assert (29, 21, 0x073);
4035 NYI_assert (15, 10, 0x07);
4037 for (i = 0; i < (full ? 16 : 8); i++)
4038 aarch64_set_vec_u8 (cpu, vd, i,
4039 aarch64_get_vec_u8 (cpu, vn, i)
4040 & ~ aarch64_get_vec_u8 (cpu, vm, i));
4044 do_vec_XTN (sim_cpu *cpu)
4047 instr[30] = first part (0)/ second part (1)
4048 instr[29,24] = 00 1110
4049 instr[23,22] = size: byte(00), half(01), word (10)
4050 instr[21,10] = 1000 0100 1010
4054 unsigned vs = uimm (aarch64_get_instr (cpu), 9, 5);
4055 unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
4056 unsigned bias = uimm (aarch64_get_instr (cpu), 30, 30);
4059 NYI_assert (29, 24, 0x0E);
4060 NYI_assert (21, 10, 0x84A);
4062 switch (uimm (aarch64_get_instr (cpu), 23, 22))
4066 for (i = 0; i < 8; i++)
4067 aarch64_set_vec_u8 (cpu, vd, i + 8,
4068 aarch64_get_vec_u16 (cpu, vs, i) >> 8);
4070 for (i = 0; i < 8; i++)
4071 aarch64_set_vec_u8 (cpu, vd, i, aarch64_get_vec_u16 (cpu, vs, i));
4076 for (i = 0; i < 4; i++)
4077 aarch64_set_vec_u16 (cpu, vd, i + 4,
4078 aarch64_get_vec_u32 (cpu, vs, i) >> 16);
4080 for (i = 0; i < 4; i++)
4081 aarch64_set_vec_u16 (cpu, vd, i, aarch64_get_vec_u32 (cpu, vs, i));
4086 for (i = 0; i < 2; i++)
4087 aarch64_set_vec_u32 (cpu, vd, i + 4,
4088 aarch64_get_vec_u64 (cpu, vs, i) >> 32);
4090 for (i = 0; i < 2; i++)
4091 aarch64_set_vec_u32 (cpu, vd, i, aarch64_get_vec_u64 (cpu, vs, i));
4100 do_vec_maxv (sim_cpu *cpu)
4103 instr[30] = half(0)/full(1)
4104 instr[29] = signed (0)/unsigned(1)
4105 instr[28,24] = 0 1110
4106 instr[23,22] = size: byte(00), half(01), word (10)
4108 instr[20,17] = 1 000
4109 instr[16] = max(0)/min(1)
4110 instr[15,10] = 1010 10
4111 instr[9,5] = V source
4112 instr[4.0] = R dest. */
4114 unsigned vs = uimm (aarch64_get_instr (cpu), 9, 5);
4115 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
4116 unsigned full = uimm (aarch64_get_instr (cpu), 30, 30);
4119 NYI_assert (28, 24, 0x0E);
4120 NYI_assert (21, 21, 1);
4121 NYI_assert (20, 17, 8);
4122 NYI_assert (15, 10, 0x2A);
4124 switch ((uimm (aarch64_get_instr (cpu), 29, 29) << 1)
4125 | uimm (aarch64_get_instr (cpu), 16, 16))
4127 case 0: /* SMAXV. */
4130 switch (uimm (aarch64_get_instr (cpu), 23, 22))
4133 smax = aarch64_get_vec_s8 (cpu, vs, 0);
4134 for (i = 1; i < (full ? 16 : 8); i++)
4135 smax = max (smax, aarch64_get_vec_s8 (cpu, vs, i));
4138 smax = aarch64_get_vec_s16 (cpu, vs, 0);
4139 for (i = 1; i < (full ? 8 : 4); i++)
4140 smax = max (smax, aarch64_get_vec_s16 (cpu, vs, i));
4143 smax = aarch64_get_vec_s32 (cpu, vs, 0);
4144 for (i = 1; i < (full ? 4 : 2); i++)
4145 smax = max (smax, aarch64_get_vec_s32 (cpu, vs, i));
4151 aarch64_set_reg_s64 (cpu, rd, NO_SP, smax);
4155 case 1: /* SMINV. */
4158 switch (uimm (aarch64_get_instr (cpu), 23, 22))
4161 smin = aarch64_get_vec_s8 (cpu, vs, 0);
4162 for (i = 1; i < (full ? 16 : 8); i++)
4163 smin = min (smin, aarch64_get_vec_s8 (cpu, vs, i));
4166 smin = aarch64_get_vec_s16 (cpu, vs, 0);
4167 for (i = 1; i < (full ? 8 : 4); i++)
4168 smin = min (smin, aarch64_get_vec_s16 (cpu, vs, i));
4171 smin = aarch64_get_vec_s32 (cpu, vs, 0);
4172 for (i = 1; i < (full ? 4 : 2); i++)
4173 smin = min (smin, aarch64_get_vec_s32 (cpu, vs, i));
4179 aarch64_set_reg_s64 (cpu, rd, NO_SP, smin);
4183 case 2: /* UMAXV. */
4186 switch (uimm (aarch64_get_instr (cpu), 23, 22))
4189 umax = aarch64_get_vec_u8 (cpu, vs, 0);
4190 for (i = 1; i < (full ? 16 : 8); i++)
4191 umax = max (umax, aarch64_get_vec_u8 (cpu, vs, i));
4194 umax = aarch64_get_vec_u16 (cpu, vs, 0);
4195 for (i = 1; i < (full ? 8 : 4); i++)
4196 umax = max (umax, aarch64_get_vec_u16 (cpu, vs, i));
4199 umax = aarch64_get_vec_u32 (cpu, vs, 0);
4200 for (i = 1; i < (full ? 4 : 2); i++)
4201 umax = max (umax, aarch64_get_vec_u32 (cpu, vs, i));
4207 aarch64_set_reg_u64 (cpu, rd, NO_SP, umax);
4211 case 3: /* UMINV. */
4214 switch (uimm (aarch64_get_instr (cpu), 23, 22))
4217 umin = aarch64_get_vec_u8 (cpu, vs, 0);
4218 for (i = 1; i < (full ? 16 : 8); i++)
4219 umin = min (umin, aarch64_get_vec_u8 (cpu, vs, i));
4222 umin = aarch64_get_vec_u16 (cpu, vs, 0);
4223 for (i = 1; i < (full ? 8 : 4); i++)
4224 umin = min (umin, aarch64_get_vec_u16 (cpu, vs, i));
4227 umin = aarch64_get_vec_u32 (cpu, vs, 0);
4228 for (i = 1; i < (full ? 4 : 2); i++)
4229 umin = min (umin, aarch64_get_vec_u32 (cpu, vs, i));
4235 aarch64_set_reg_u64 (cpu, rd, NO_SP, umin);
4245 do_vec_fminmaxV (sim_cpu *cpu)
4247 /* instr[31,24] = 0110 1110
4248 instr[23] = max(0)/min(1)
4249 instr[22,14] = 011 0000 11
4250 instr[13,12] = nm(00)/normal(11)
4252 instr[9,5] = V source
4253 instr[4.0] = R dest. */
4255 unsigned vs = uimm (aarch64_get_instr (cpu), 9, 5);
4256 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
4258 float res = aarch64_get_vec_float (cpu, vs, 0);
4260 NYI_assert (31, 24, 0x6E);
4261 NYI_assert (22, 14, 0x0C3);
4262 NYI_assert (11, 10, 2);
4264 if (uimm (aarch64_get_instr (cpu), 23, 23))
4266 switch (uimm (aarch64_get_instr (cpu), 13, 12))
4268 case 0: /* FMNINNMV. */
4269 for (i = 1; i < 4; i++)
4270 res = fminnm (res, aarch64_get_vec_float (cpu, vs, i));
4273 case 3: /* FMINV. */
4274 for (i = 1; i < 4; i++)
4275 res = min (res, aarch64_get_vec_float (cpu, vs, i));
4284 switch (uimm (aarch64_get_instr (cpu), 13, 12))
4286 case 0: /* FMNAXNMV. */
4287 for (i = 1; i < 4; i++)
4288 res = fmaxnm (res, aarch64_get_vec_float (cpu, vs, i));
4291 case 3: /* FMAXV. */
4292 for (i = 1; i < 4; i++)
4293 res = max (res, aarch64_get_vec_float (cpu, vs, i));
4301 aarch64_set_FP_float (cpu, rd, res);
4305 do_vec_Fminmax (sim_cpu *cpu)
4308 instr[30] = half(0)/full(1)
4309 instr[29,24] = 00 1110
4310 instr[23] = max(0)/min(1)
4311 instr[22] = float(0)/double(1)
4315 instr[13,12] = nm(00)/normal(11)
4320 unsigned vm = uimm (aarch64_get_instr (cpu), 20, 16);
4321 unsigned vn = uimm (aarch64_get_instr (cpu), 9, 5);
4322 unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
4323 unsigned full = uimm (aarch64_get_instr (cpu), 30, 30);
4324 unsigned min = uimm (aarch64_get_instr (cpu), 23, 23);
4327 NYI_assert (29, 24, 0x0E);
4328 NYI_assert (21, 21, 1);
4329 NYI_assert (15, 14, 3);
4330 NYI_assert (11, 10, 1);
4332 if (uimm (aarch64_get_instr (cpu), 22, 22))
4334 double (* func)(double, double);
4339 if (uimm (aarch64_get_instr (cpu), 13, 12) == 0)
4340 func = min ? dminnm : dmaxnm;
4341 else if (uimm (aarch64_get_instr (cpu), 13, 12) == 3)
4342 func = min ? fmin : fmax;
4346 for (i = 0; i < 2; i++)
4347 aarch64_set_vec_double (cpu, vd, i,
4348 func (aarch64_get_vec_double (cpu, vn, i),
4349 aarch64_get_vec_double (cpu, vm, i)));
4353 float (* func)(float, float);
4355 if (uimm (aarch64_get_instr (cpu), 13, 12) == 0)
4356 func = min ? fminnm : fmaxnm;
4357 else if (uimm (aarch64_get_instr (cpu), 13, 12) == 3)
4358 func = min ? fminf : fmaxf;
4362 for (i = 0; i < (full ? 4 : 2); i++)
4363 aarch64_set_vec_float (cpu, vd, i,
4364 func (aarch64_get_vec_float (cpu, vn, i),
4365 aarch64_get_vec_float (cpu, vm, i)));
4370 do_vec_SCVTF (sim_cpu *cpu)
4374 instr[29,23] = 00 1110 0
4375 instr[22] = float(0)/double(1)
4376 instr[21,10] = 10 0001 1101 10
4380 unsigned vn = uimm (aarch64_get_instr (cpu), 9, 5);
4381 unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
4382 unsigned full = uimm (aarch64_get_instr (cpu), 30, 30);
4383 unsigned size = uimm (aarch64_get_instr (cpu), 22, 22);
4386 NYI_assert (29, 23, 0x1C);
4387 NYI_assert (21, 10, 0x876);
4394 for (i = 0; i < 2; i++)
4396 double val = (double) aarch64_get_vec_u64 (cpu, vn, i);
4397 aarch64_set_vec_double (cpu, vd, i, val);
4402 for (i = 0; i < (full ? 4 : 2); i++)
4404 float val = (float) aarch64_get_vec_u32 (cpu, vn, i);
4405 aarch64_set_vec_float (cpu, vd, i, val);
4410 #define VEC_CMP(SOURCE, CMP) \
4416 for (i = 0; i < (full ? 16 : 8); i++) \
4417 aarch64_set_vec_u8 (cpu, vd, i, \
4418 aarch64_get_vec_##SOURCE##8 (cpu, vn, i) \
4420 aarch64_get_vec_##SOURCE##8 (cpu, vm, i) \
4424 for (i = 0; i < (full ? 8 : 4); i++) \
4425 aarch64_set_vec_u16 (cpu, vd, i, \
4426 aarch64_get_vec_##SOURCE##16 (cpu, vn, i) \
4428 aarch64_get_vec_##SOURCE##16 (cpu, vm, i) \
4432 for (i = 0; i < (full ? 4 : 2); i++) \
4433 aarch64_set_vec_u32 (cpu, vd, i, \
4434 aarch64_get_vec_##SOURCE##32 (cpu, vn, i) \
4436 aarch64_get_vec_##SOURCE##32 (cpu, vm, i) \
4442 for (i = 0; i < 2; i++) \
4443 aarch64_set_vec_u64 (cpu, vd, i, \
4444 aarch64_get_vec_##SOURCE##64 (cpu, vn, i) \
4446 aarch64_get_vec_##SOURCE##64 (cpu, vm, i) \
4455 #define VEC_CMP0(SOURCE, CMP) \
4461 for (i = 0; i < (full ? 16 : 8); i++) \
4462 aarch64_set_vec_u8 (cpu, vd, i, \
4463 aarch64_get_vec_##SOURCE##8 (cpu, vn, i) \
4467 for (i = 0; i < (full ? 8 : 4); i++) \
4468 aarch64_set_vec_u16 (cpu, vd, i, \
4469 aarch64_get_vec_##SOURCE##16 (cpu, vn, i) \
4473 for (i = 0; i < (full ? 4 : 2); i++) \
4474 aarch64_set_vec_u32 (cpu, vd, i, \
4475 aarch64_get_vec_##SOURCE##32 (cpu, vn, i) \
4481 for (i = 0; i < 2; i++) \
4482 aarch64_set_vec_u64 (cpu, vd, i, \
4483 aarch64_get_vec_##SOURCE##64 (cpu, vn, i) \
4484 CMP 0 ? -1ULL : 0); \
4492 #define VEC_FCMP0(CMP) \
4497 if (uimm (aarch64_get_instr (cpu), 22, 22)) \
4501 for (i = 0; i < 2; i++) \
4502 aarch64_set_vec_u64 (cpu, vd, i, \
4503 aarch64_get_vec_double (cpu, vn, i) \
4504 CMP 0.0 ? -1 : 0); \
4508 for (i = 0; i < (full ? 4 : 2); i++) \
4509 aarch64_set_vec_u32 (cpu, vd, i, \
4510 aarch64_get_vec_float (cpu, vn, i) \
4511 CMP 0.0 ? -1 : 0); \
4517 #define VEC_FCMP(CMP) \
4520 if (uimm (aarch64_get_instr (cpu), 22, 22)) \
4524 for (i = 0; i < 2; i++) \
4525 aarch64_set_vec_u64 (cpu, vd, i, \
4526 aarch64_get_vec_double (cpu, vn, i) \
4528 aarch64_get_vec_double (cpu, vm, i) \
4533 for (i = 0; i < (full ? 4 : 2); i++) \
4534 aarch64_set_vec_u32 (cpu, vd, i, \
4535 aarch64_get_vec_float (cpu, vn, i) \
4537 aarch64_get_vec_float (cpu, vm, i) \
4545 do_vec_compare (sim_cpu *cpu)
4548 instr[30] = half(0)/full(1)
4549 instr[29] = part-of-comparison-type
4550 instr[28,24] = 0 1110
4551 instr[23,22] = size of integer compares: byte(00), half(01), word (10), long (11)
4552 type of float compares: single (-0) / double (-1)
4554 instr[20,16] = Vm or 00000 (compare vs 0)
4555 instr[15,10] = part-of-comparison-type
4559 int full = uimm (aarch64_get_instr (cpu), 30, 30);
4560 int size = uimm (aarch64_get_instr (cpu), 23, 22);
4561 unsigned vm = uimm (aarch64_get_instr (cpu), 20, 16);
4562 unsigned vn = uimm (aarch64_get_instr (cpu), 9, 5);
4563 unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
4566 NYI_assert (28, 24, 0x0E);
4567 NYI_assert (21, 21, 1);
4569 if ((uimm (aarch64_get_instr (cpu), 11, 11)
4570 && uimm (aarch64_get_instr (cpu), 14, 14))
4571 || ((uimm (aarch64_get_instr (cpu), 11, 11) == 0
4572 && uimm (aarch64_get_instr (cpu), 10, 10) == 0)))
4574 /* A compare vs 0. */
4577 if (uimm (aarch64_get_instr (cpu), 15, 10) == 0x2A)
4579 else if (uimm (aarch64_get_instr (cpu), 15, 10) == 0x32
4580 || uimm (aarch64_get_instr (cpu), 15, 10) == 0x3E)
4581 do_vec_fminmaxV (cpu);
4582 else if (uimm (aarch64_get_instr (cpu), 29, 23) == 0x1C
4583 && uimm (aarch64_get_instr (cpu), 21, 10) == 0x876)
4591 if (uimm (aarch64_get_instr (cpu), 14, 14))
4593 /* A floating point compare. */
4594 unsigned decode = (uimm (aarch64_get_instr (cpu), 29, 29) << 5)
4595 | (uimm (aarch64_get_instr (cpu), 23, 23) << 4)
4596 | uimm (aarch64_get_instr (cpu), 13, 10);
4598 NYI_assert (15, 15, 1);
4602 case /* 0b010010: GT#0 */ 0x12: VEC_FCMP0 (>);
4603 case /* 0b110010: GE#0 */ 0x32: VEC_FCMP0 (>=);
4604 case /* 0b010110: EQ#0 */ 0x16: VEC_FCMP0 (==);
4605 case /* 0b110110: LE#0 */ 0x36: VEC_FCMP0 (<=);
4606 case /* 0b011010: LT#0 */ 0x1A: VEC_FCMP0 (<);
4607 case /* 0b111001: GT */ 0x39: VEC_FCMP (>);
4608 case /* 0b101001: GE */ 0x29: VEC_FCMP (>=);
4609 case /* 0b001001: EQ */ 0x09: VEC_FCMP (==);
4617 unsigned decode = (uimm (aarch64_get_instr (cpu), 29, 29) << 6)
4618 | uimm (aarch64_get_instr (cpu), 15, 10);
4622 case 0x0D: /* 0001101 GT */ VEC_CMP (s, > );
4623 case 0x0F: /* 0001111 GE */ VEC_CMP (s, >= );
4624 case 0x22: /* 0100010 GT #0 */ VEC_CMP0 (s, > );
4625 case 0x26: /* 0100110 EQ #0 */ VEC_CMP0 (s, == );
4626 case 0x2A: /* 0101010 LT #0 */ VEC_CMP0 (s, < );
4627 case 0x4D: /* 1001101 HI */ VEC_CMP (u, > );
4628 case 0x4F: /* 1001111 HS */ VEC_CMP (u, >= );
4629 case 0x62: /* 1100010 GE #0 */ VEC_CMP0 (s, >= );
4630 case 0x63: /* 1100011 EQ */ VEC_CMP (u, == );
4631 case 0x66: /* 1100110 LE #0 */ VEC_CMP0 (s, <= );
4641 do_vec_SSHL (sim_cpu *cpu)
4644 instr[30] = first part (0)/ second part (1)
4645 instr[29,24] = 00 1110
4646 instr[23,22] = size: byte(00), half(01), word (10), long (11)
4649 instr[15,10] = 0100 01
4653 unsigned full = uimm (aarch64_get_instr (cpu), 30, 30);
4654 unsigned vm = uimm (aarch64_get_instr (cpu), 20, 16);
4655 unsigned vn = uimm (aarch64_get_instr (cpu), 9, 5);
4656 unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
4659 NYI_assert (29, 24, 0x0E);
4660 NYI_assert (21, 21, 1);
4661 NYI_assert (15, 10, 0x11);
4663 /* FIXME: What is a signed shift left in this context ?. */
4665 switch (uimm (aarch64_get_instr (cpu), 23, 22))
4668 for (i = 0; i < (full ? 16 : 8); i++)
4669 aarch64_set_vec_s8 (cpu, vd, i, aarch64_get_vec_s8 (cpu, vn, i)
4670 << aarch64_get_vec_s8 (cpu, vm, i));
4674 for (i = 0; i < (full ? 8 : 4); i++)
4675 aarch64_set_vec_s16 (cpu, vd, i, aarch64_get_vec_s16 (cpu, vn, i)
4676 << aarch64_get_vec_s16 (cpu, vm, i));
4680 for (i = 0; i < (full ? 4 : 2); i++)
4681 aarch64_set_vec_s32 (cpu, vd, i, aarch64_get_vec_s32 (cpu, vn, i)
4682 << aarch64_get_vec_s32 (cpu, vm, i));
4688 for (i = 0; i < 2; i++)
4689 aarch64_set_vec_s64 (cpu, vd, i, aarch64_get_vec_s64 (cpu, vn, i)
4690 << aarch64_get_vec_s64 (cpu, vm, i));
4699 do_vec_USHL (sim_cpu *cpu)
4702 instr[30] = first part (0)/ second part (1)
4703 instr[29,24] = 10 1110
4704 instr[23,22] = size: byte(00), half(01), word (10), long (11)
4707 instr[15,10] = 0100 01
4711 unsigned full = uimm (aarch64_get_instr (cpu), 30, 30);
4712 unsigned vm = uimm (aarch64_get_instr (cpu), 20, 16);
4713 unsigned vn = uimm (aarch64_get_instr (cpu), 9, 5);
4714 unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
4717 NYI_assert (29, 24, 0x2E);
4718 NYI_assert (15, 10, 0x11);
4720 switch (uimm (aarch64_get_instr (cpu), 23, 22))
4723 for (i = 0; i < (full ? 16 : 8); i++)
4724 aarch64_set_vec_u8 (cpu, vd, i, aarch64_get_vec_u8 (cpu, vn, i)
4725 << aarch64_get_vec_u8 (cpu, vm, i));
4729 for (i = 0; i < (full ? 8 : 4); i++)
4730 aarch64_set_vec_u16 (cpu, vd, i, aarch64_get_vec_u16 (cpu, vn, i)
4731 << aarch64_get_vec_u16 (cpu, vm, i));
4735 for (i = 0; i < (full ? 4 : 2); i++)
4736 aarch64_set_vec_u32 (cpu, vd, i, aarch64_get_vec_u32 (cpu, vn, i)
4737 << aarch64_get_vec_u32 (cpu, vm, i));
4743 for (i = 0; i < 2; i++)
4744 aarch64_set_vec_u64 (cpu, vd, i, aarch64_get_vec_u64 (cpu, vn, i)
4745 << aarch64_get_vec_u64 (cpu, vm, i));
4754 do_vec_FMLA (sim_cpu *cpu)
4757 instr[30] = full/half selector
4758 instr[29,23] = 0011100
4759 instr[22] = size: 0=>float, 1=>double
4762 instr[15,10] = 1100 11
4766 unsigned vm = uimm (aarch64_get_instr (cpu), 20, 16);
4767 unsigned vn = uimm (aarch64_get_instr (cpu), 9, 5);
4768 unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
4770 int full = uimm (aarch64_get_instr (cpu), 30, 30);
4772 NYI_assert (29, 23, 0x1C);
4773 NYI_assert (21, 21, 1);
4774 NYI_assert (15, 10, 0x33);
4776 if (uimm (aarch64_get_instr (cpu), 22, 22))
4780 for (i = 0; i < 2; i++)
4781 aarch64_set_vec_double (cpu, vd, i,
4782 aarch64_get_vec_double (cpu, vn, i) *
4783 aarch64_get_vec_double (cpu, vm, i) +
4784 aarch64_get_vec_double (cpu, vd, i));
4788 for (i = 0; i < (full ? 4 : 2); i++)
4789 aarch64_set_vec_float (cpu, vd, i,
4790 aarch64_get_vec_float (cpu, vn, i) *
4791 aarch64_get_vec_float (cpu, vm, i) +
4792 aarch64_get_vec_float (cpu, vd, i));
4797 do_vec_max (sim_cpu *cpu)
4800 instr[30] = full/half selector
4801 instr[29] = SMAX (0) / UMAX (1)
4802 instr[28,24] = 0 1110
4803 instr[23,22] = size: 00=> 8-bit, 01=> 16-bit, 10=> 32-bit
4806 instr[15,10] = 0110 01
4810 unsigned vm = uimm (aarch64_get_instr (cpu), 20, 16);
4811 unsigned vn = uimm (aarch64_get_instr (cpu), 9, 5);
4812 unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
4814 int full = uimm (aarch64_get_instr (cpu), 30, 30);
4816 NYI_assert (28, 24, 0x0E);
4817 NYI_assert (21, 21, 1);
4818 NYI_assert (15, 10, 0x19);
4820 if (uimm (aarch64_get_instr (cpu), 29, 29))
4822 switch (uimm (aarch64_get_instr (cpu), 23, 22))
4825 for (i = 0; i < (full ? 16 : 8); i++)
4826 aarch64_set_vec_u8 (cpu, vd, i,
4827 aarch64_get_vec_u8 (cpu, vn, i)
4828 > aarch64_get_vec_u8 (cpu, vm, i)
4829 ? aarch64_get_vec_u8 (cpu, vn, i)
4830 : aarch64_get_vec_u8 (cpu, vm, i));
4834 for (i = 0; i < (full ? 8 : 4); i++)
4835 aarch64_set_vec_u16 (cpu, vd, i,
4836 aarch64_get_vec_u16 (cpu, vn, i)
4837 > aarch64_get_vec_u16 (cpu, vm, i)
4838 ? aarch64_get_vec_u16 (cpu, vn, i)
4839 : aarch64_get_vec_u16 (cpu, vm, i));
4843 for (i = 0; i < (full ? 4 : 2); i++)
4844 aarch64_set_vec_u32 (cpu, vd, i,
4845 aarch64_get_vec_u32 (cpu, vn, i)
4846 > aarch64_get_vec_u32 (cpu, vm, i)
4847 ? aarch64_get_vec_u32 (cpu, vn, i)
4848 : aarch64_get_vec_u32 (cpu, vm, i));
4858 switch (uimm (aarch64_get_instr (cpu), 23, 22))
4861 for (i = 0; i < (full ? 16 : 8); i++)
4862 aarch64_set_vec_s8 (cpu, vd, i,
4863 aarch64_get_vec_s8 (cpu, vn, i)
4864 > aarch64_get_vec_s8 (cpu, vm, i)
4865 ? aarch64_get_vec_s8 (cpu, vn, i)
4866 : aarch64_get_vec_s8 (cpu, vm, i));
4870 for (i = 0; i < (full ? 8 : 4); i++)
4871 aarch64_set_vec_s16 (cpu, vd, i,
4872 aarch64_get_vec_s16 (cpu, vn, i)
4873 > aarch64_get_vec_s16 (cpu, vm, i)
4874 ? aarch64_get_vec_s16 (cpu, vn, i)
4875 : aarch64_get_vec_s16 (cpu, vm, i));
4879 for (i = 0; i < (full ? 4 : 2); i++)
4880 aarch64_set_vec_s32 (cpu, vd, i,
4881 aarch64_get_vec_s32 (cpu, vn, i)
4882 > aarch64_get_vec_s32 (cpu, vm, i)
4883 ? aarch64_get_vec_s32 (cpu, vn, i)
4884 : aarch64_get_vec_s32 (cpu, vm, i));
4895 do_vec_min (sim_cpu *cpu)
4898 instr[30] = full/half selector
4899 instr[29] = SMIN (0) / UMIN (1)
4900 instr[28,24] = 0 1110
4901 instr[23,22] = size: 00=> 8-bit, 01=> 16-bit, 10=> 32-bit
4904 instr[15,10] = 0110 11
4908 unsigned vm = uimm (aarch64_get_instr (cpu), 20, 16);
4909 unsigned vn = uimm (aarch64_get_instr (cpu), 9, 5);
4910 unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
4912 int full = uimm (aarch64_get_instr (cpu), 30, 30);
4914 NYI_assert (28, 24, 0x0E);
4915 NYI_assert (21, 21, 1);
4916 NYI_assert (15, 10, 0x1B);
4918 if (uimm (aarch64_get_instr (cpu), 29, 29))
4920 switch (uimm (aarch64_get_instr (cpu), 23, 22))
4923 for (i = 0; i < (full ? 16 : 8); i++)
4924 aarch64_set_vec_u8 (cpu, vd, i,
4925 aarch64_get_vec_u8 (cpu, vn, i)
4926 < aarch64_get_vec_u8 (cpu, vm, i)
4927 ? aarch64_get_vec_u8 (cpu, vn, i)
4928 : aarch64_get_vec_u8 (cpu, vm, i));
4932 for (i = 0; i < (full ? 8 : 4); i++)
4933 aarch64_set_vec_u16 (cpu, vd, i,
4934 aarch64_get_vec_u16 (cpu, vn, i)
4935 < aarch64_get_vec_u16 (cpu, vm, i)
4936 ? aarch64_get_vec_u16 (cpu, vn, i)
4937 : aarch64_get_vec_u16 (cpu, vm, i));
4941 for (i = 0; i < (full ? 4 : 2); i++)
4942 aarch64_set_vec_u32 (cpu, vd, i,
4943 aarch64_get_vec_u32 (cpu, vn, i)
4944 < aarch64_get_vec_u32 (cpu, vm, i)
4945 ? aarch64_get_vec_u32 (cpu, vn, i)
4946 : aarch64_get_vec_u32 (cpu, vm, i));
4956 switch (uimm (aarch64_get_instr (cpu), 23, 22))
4959 for (i = 0; i < (full ? 16 : 8); i++)
4960 aarch64_set_vec_s8 (cpu, vd, i,
4961 aarch64_get_vec_s8 (cpu, vn, i)
4962 < aarch64_get_vec_s8 (cpu, vm, i)
4963 ? aarch64_get_vec_s8 (cpu, vn, i)
4964 : aarch64_get_vec_s8 (cpu, vm, i));
4968 for (i = 0; i < (full ? 8 : 4); i++)
4969 aarch64_set_vec_s16 (cpu, vd, i,
4970 aarch64_get_vec_s16 (cpu, vn, i)
4971 < aarch64_get_vec_s16 (cpu, vm, i)
4972 ? aarch64_get_vec_s16 (cpu, vn, i)
4973 : aarch64_get_vec_s16 (cpu, vm, i));
4977 for (i = 0; i < (full ? 4 : 2); i++)
4978 aarch64_set_vec_s32 (cpu, vd, i,
4979 aarch64_get_vec_s32 (cpu, vn, i)
4980 < aarch64_get_vec_s32 (cpu, vm, i)
4981 ? aarch64_get_vec_s32 (cpu, vn, i)
4982 : aarch64_get_vec_s32 (cpu, vm, i));
4993 do_vec_sub_long (sim_cpu *cpu)
4996 instr[30] = lower (0) / upper (1)
4997 instr[29] = signed (0) / unsigned (1)
4998 instr[28,24] = 0 1110
4999 instr[23,22] = size: bytes (00), half (01), word (10)
5002 instr[15,10] = 0010 00
5004 instr[4,0] = V dest. */
5006 unsigned size = uimm (aarch64_get_instr (cpu), 23, 22);
5007 unsigned vm = uimm (aarch64_get_instr (cpu), 20, 16);
5008 unsigned vn = uimm (aarch64_get_instr (cpu), 9, 5);
5009 unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
5013 NYI_assert (28, 24, 0x0E);
5014 NYI_assert (21, 21, 1);
5015 NYI_assert (15, 10, 0x08);
5020 switch (uimm (aarch64_get_instr (cpu), 30, 29))
5022 case 2: /* SSUBL2. */
5024 case 0: /* SSUBL. */
5029 for (i = 0; i < 8; i++)
5030 aarch64_set_vec_s16 (cpu, vd, i,
5031 aarch64_get_vec_s8 (cpu, vn, i + bias)
5032 - aarch64_get_vec_s8 (cpu, vm, i + bias));
5037 for (i = 0; i < 4; i++)
5038 aarch64_set_vec_s32 (cpu, vd, i,
5039 aarch64_get_vec_s16 (cpu, vn, i + bias)
5040 - aarch64_get_vec_s16 (cpu, vm, i + bias));
5044 for (i = 0; i < 2; i++)
5045 aarch64_set_vec_s64 (cpu, vd, i,
5046 aarch64_get_vec_s32 (cpu, vn, i + bias)
5047 - aarch64_get_vec_s32 (cpu, vm, i + bias));
5055 case 3: /* USUBL2. */
5057 case 1: /* USUBL. */
5062 for (i = 0; i < 8; i++)
5063 aarch64_set_vec_u16 (cpu, vd, i,
5064 aarch64_get_vec_u8 (cpu, vn, i + bias)
5065 - aarch64_get_vec_u8 (cpu, vm, i + bias));
5070 for (i = 0; i < 4; i++)
5071 aarch64_set_vec_u32 (cpu, vd, i,
5072 aarch64_get_vec_u16 (cpu, vn, i + bias)
5073 - aarch64_get_vec_u16 (cpu, vm, i + bias));
5077 for (i = 0; i < 2; i++)
5078 aarch64_set_vec_u64 (cpu, vd, i,
5079 aarch64_get_vec_u32 (cpu, vn, i + bias)
5080 - aarch64_get_vec_u32 (cpu, vm, i + bias));
5091 do_vec_ADDP (sim_cpu *cpu)
5094 instr[30] = half(0)/full(1)
5095 instr[29,24] = 00 1110
5096 instr[23,22] = size: bytes (00), half (01), word (10), long (11)
5099 instr[15,10] = 1011 11
5101 instr[4,0] = V dest. */
5105 unsigned full = uimm (aarch64_get_instr (cpu), 30, 30);
5106 unsigned size = uimm (aarch64_get_instr (cpu), 23, 22);
5107 unsigned vm = uimm (aarch64_get_instr (cpu), 20, 16);
5108 unsigned vn = uimm (aarch64_get_instr (cpu), 9, 5);
5109 unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
5112 NYI_assert (29, 24, 0x0E);
5113 NYI_assert (21, 21, 1);
5114 NYI_assert (15, 10, 0x2F);
5116 /* Make copies of the source registers in case vd == vn/vm. */
5117 copy_vn = cpu->fr[vn];
5118 copy_vm = cpu->fr[vm];
5123 range = full ? 8 : 4;
5124 for (i = 0; i < range; i++)
5126 aarch64_set_vec_u8 (cpu, vd, i,
5127 copy_vn.b[i * 2] + copy_vn.b[i * 2 + 1]);
5128 aarch64_set_vec_u8 (cpu, vd, i + range,
5129 copy_vm.b[i * 2] + copy_vm.b[i * 2 + 1]);
5134 range = full ? 4 : 2;
5135 for (i = 0; i < range; i++)
5137 aarch64_set_vec_u16 (cpu, vd, i,
5138 copy_vn.h[i * 2] + copy_vn.h[i * 2 + 1]);
5139 aarch64_set_vec_u16 (cpu, vd, i + range,
5140 copy_vm.h[i * 2] + copy_vm.h[i * 2 + 1]);
5145 range = full ? 2 : 1;
5146 for (i = 0; i < range; i++)
5148 aarch64_set_vec_u32 (cpu, vd, i,
5149 copy_vn.w[i * 2] + copy_vn.w[i * 2 + 1]);
5150 aarch64_set_vec_u32 (cpu, vd, i + range,
5151 copy_vm.w[i * 2] + copy_vm.w[i * 2 + 1]);
5158 aarch64_set_vec_u64 (cpu, vd, 0, copy_vn.v[0] + copy_vn.v[1]);
5159 aarch64_set_vec_u64 (cpu, vd, 1, copy_vm.v[0] + copy_vm.v[1]);
5168 do_vec_UMOV (sim_cpu *cpu)
5171 instr[30] = 32-bit(0)/64-bit(1)
5172 instr[29,21] = 00 1110 000
5173 insrt[20,16] = size & index
5174 instr[15,10] = 0011 11
5175 instr[9,5] = V source
5176 instr[4,0] = R dest. */
5178 unsigned vs = uimm (aarch64_get_instr (cpu), 9, 5);
5179 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
5182 NYI_assert (29, 21, 0x070);
5183 NYI_assert (15, 10, 0x0F);
5185 if (uimm (aarch64_get_instr (cpu), 16, 16))
5187 /* Byte transfer. */
5188 index = uimm (aarch64_get_instr (cpu), 20, 17);
5189 aarch64_set_reg_u64 (cpu, rd, NO_SP,
5190 aarch64_get_vec_u8 (cpu, vs, index));
5192 else if (uimm (aarch64_get_instr (cpu), 17, 17))
5194 index = uimm (aarch64_get_instr (cpu), 20, 18);
5195 aarch64_set_reg_u64 (cpu, rd, NO_SP,
5196 aarch64_get_vec_u16 (cpu, vs, index));
5198 else if (uimm (aarch64_get_instr (cpu), 18, 18))
5200 index = uimm (aarch64_get_instr (cpu), 20, 19);
5201 aarch64_set_reg_u64 (cpu, rd, NO_SP,
5202 aarch64_get_vec_u32 (cpu, vs, index));
5206 if (uimm (aarch64_get_instr (cpu), 30, 30) != 1)
5209 index = uimm (aarch64_get_instr (cpu), 20, 20);
5210 aarch64_set_reg_u64 (cpu, rd, NO_SP,
5211 aarch64_get_vec_u64 (cpu, vs, index));
5216 do_vec_FABS (sim_cpu *cpu)
5219 instr[30] = half(0)/full(1)
5220 instr[29,23] = 00 1110 1
5221 instr[22] = float(0)/double(1)
5222 instr[21,16] = 10 0000
5223 instr[15,10] = 1111 10
5227 unsigned vn = uimm (aarch64_get_instr (cpu), 9, 5);
5228 unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
5229 unsigned full = uimm (aarch64_get_instr (cpu), 30, 30);
5232 NYI_assert (29, 23, 0x1D);
5233 NYI_assert (21, 10, 0x83E);
5235 if (uimm (aarch64_get_instr (cpu), 22, 22))
5240 for (i = 0; i < 2; i++)
5241 aarch64_set_vec_double (cpu, vd, i,
5242 fabs (aarch64_get_vec_double (cpu, vn, i)));
5246 for (i = 0; i < (full ? 4 : 2); i++)
5247 aarch64_set_vec_float (cpu, vd, i,
5248 fabsf (aarch64_get_vec_float (cpu, vn, i)));
5253 do_vec_FCVTZS (sim_cpu *cpu)
5256 instr[30] = half (0) / all (1)
5257 instr[29,23] = 00 1110 1
5258 instr[22] = single (0) / double (1)
5259 instr[21,10] = 10 0001 1011 10
5263 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
5264 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
5265 unsigned full = uimm (aarch64_get_instr (cpu), 30, 30);
5268 NYI_assert (31, 31, 0);
5269 NYI_assert (29, 23, 0x1D);
5270 NYI_assert (21, 10, 0x86E);
5272 if (uimm (aarch64_get_instr (cpu), 22, 22))
5277 for (i = 0; i < 2; i++)
5278 aarch64_set_vec_s64 (cpu, rd, i,
5279 (int64_t) aarch64_get_vec_double (cpu, rn, i));
5282 for (i = 0; i < (full ? 4 : 2); i++)
5283 aarch64_set_vec_s32 (cpu, rd, i,
5284 (int32_t) aarch64_get_vec_float (cpu, rn, i));
5288 do_vec_op1 (sim_cpu *cpu)
5291 instr[30] = half/full
5292 instr[29,24] = 00 1110
5295 instr[15,10] = sub-opcode
5298 NYI_assert (29, 24, 0x0E);
5300 if (uimm (aarch64_get_instr (cpu), 21, 21) == 0)
5302 if (uimm (aarch64_get_instr (cpu), 23, 22) == 0)
5304 if (uimm (aarch64_get_instr (cpu), 30, 30) == 1
5305 && uimm (aarch64_get_instr (cpu), 17, 14) == 0
5306 && uimm (aarch64_get_instr (cpu), 12, 10) == 7)
5307 return do_vec_ins_2 (cpu);
5309 switch (uimm (aarch64_get_instr (cpu), 15, 10))
5311 case 0x01: do_vec_DUP_vector_into_vector (cpu); return;
5312 case 0x03: do_vec_DUP_scalar_into_vector (cpu); return;
5313 case 0x07: do_vec_INS (cpu); return;
5314 case 0x0A: do_vec_TRN (cpu); return;
5317 if (uimm (aarch64_get_instr (cpu), 17, 16) == 0)
5319 do_vec_MOV_into_scalar (cpu);
5328 do_vec_TBL (cpu); return;
5332 do_vec_UZP (cpu); return;
5336 do_vec_ZIP (cpu); return;
5343 switch (uimm (aarch64_get_instr (cpu), 13, 10))
5345 case 0x6: do_vec_UZP (cpu); return;
5346 case 0xE: do_vec_ZIP (cpu); return;
5347 case 0xA: do_vec_TRN (cpu); return;
5348 case 0xF: do_vec_UMOV (cpu); return;
5353 switch (uimm (aarch64_get_instr (cpu), 15, 10))
5356 switch (uimm (aarch64_get_instr (cpu), 23, 21))
5358 case 1: do_vec_AND (cpu); return;
5359 case 3: do_vec_BIC (cpu); return;
5360 case 5: do_vec_ORR (cpu); return;
5361 case 7: do_vec_ORN (cpu); return;
5365 case 0x08: do_vec_sub_long (cpu); return;
5366 case 0x0a: do_vec_XTN (cpu); return;
5367 case 0x11: do_vec_SSHL (cpu); return;
5368 case 0x19: do_vec_max (cpu); return;
5369 case 0x1B: do_vec_min (cpu); return;
5370 case 0x21: do_vec_add (cpu); return;
5371 case 0x25: do_vec_MLA (cpu); return;
5372 case 0x27: do_vec_mul (cpu); return;
5373 case 0x2F: do_vec_ADDP (cpu); return;
5374 case 0x30: do_vec_mull (cpu); return;
5375 case 0x33: do_vec_FMLA (cpu); return;
5376 case 0x35: do_vec_fadd (cpu); return;
5379 switch (uimm (aarch64_get_instr (cpu), 20, 16))
5381 case 0x00: do_vec_ABS (cpu); return;
5382 case 0x01: do_vec_FCVTZS (cpu); return;
5383 case 0x11: do_vec_ADDV (cpu); return;
5389 do_vec_Fminmax (cpu); return;
5401 do_vec_compare (cpu); return;
5404 do_vec_FABS (cpu); return;
5412 do_vec_xtl (sim_cpu *cpu)
5415 instr[30,29] = SXTL (00), UXTL (01), SXTL2 (10), UXTL2 (11)
5416 instr[28,22] = 0 1111 00
5417 instr[21,16] = size & shift (USHLL, SSHLL, USHLL2, SSHLL2)
5418 instr[15,10] = 1010 01
5419 instr[9,5] = V source
5420 instr[4,0] = V dest. */
5422 unsigned vs = uimm (aarch64_get_instr (cpu), 9, 5);
5423 unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
5424 unsigned i, shift, bias = 0;
5426 NYI_assert (28, 22, 0x3C);
5427 NYI_assert (15, 10, 0x29);
5429 switch (uimm (aarch64_get_instr (cpu), 30, 29))
5431 case 2: /* SXTL2, SSHLL2. */
5433 case 0: /* SXTL, SSHLL. */
5434 if (uimm (aarch64_get_instr (cpu), 21, 21))
5436 shift = uimm (aarch64_get_instr (cpu), 20, 16);
5438 (cpu, vd, 0, aarch64_get_vec_s32 (cpu, vs, bias) << shift);
5440 (cpu, vd, 1, aarch64_get_vec_s32 (cpu, vs, bias + 1) << shift);
5442 else if (uimm (aarch64_get_instr (cpu), 20, 20))
5444 shift = uimm (aarch64_get_instr (cpu), 19, 16);
5446 for (i = 0; i < 4; i++)
5448 (cpu, vd, i, aarch64_get_vec_s16 (cpu, vs, i + bias) << shift);
5452 NYI_assert (19, 19, 1);
5454 shift = uimm (aarch64_get_instr (cpu), 18, 16);
5456 for (i = 0; i < 8; i++)
5458 (cpu, vd, i, aarch64_get_vec_s8 (cpu, vs, i + bias) << shift);
5462 case 3: /* UXTL2, USHLL2. */
5464 case 1: /* UXTL, USHLL. */
5465 if (uimm (aarch64_get_instr (cpu), 21, 21))
5467 shift = uimm (aarch64_get_instr (cpu), 20, 16);
5469 (cpu, vd, 0, aarch64_get_vec_u32 (cpu, vs, bias) << shift);
5471 (cpu, vd, 1, aarch64_get_vec_u32 (cpu, vs, bias + 1) << shift);
5473 else if (uimm (aarch64_get_instr (cpu), 20, 20))
5475 shift = uimm (aarch64_get_instr (cpu), 19, 16);
5477 for (i = 0; i < 4; i++)
5479 (cpu, vd, i, aarch64_get_vec_u16 (cpu, vs, i + bias) << shift);
5483 NYI_assert (19, 19, 1);
5485 shift = uimm (aarch64_get_instr (cpu), 18, 16);
5487 for (i = 0; i < 8; i++)
5489 (cpu, vd, i, aarch64_get_vec_u8 (cpu, vs, i + bias) << shift);
5499 do_vec_SHL (sim_cpu *cpu)
5502 instr [30] = half(0)/full(1)
5503 instr [29,23] = 001 1110
5504 instr [22,16] = size and shift amount
5505 instr [15,10] = 01 0101
5507 instr [4, 0] = Vd. */
5510 int full = uimm (aarch64_get_instr (cpu), 30, 30);
5511 unsigned vs = uimm (aarch64_get_instr (cpu), 9, 5);
5512 unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
5515 NYI_assert (29, 23, 0x1E);
5516 NYI_assert (15, 10, 0x15);
5518 if (uimm (aarch64_get_instr (cpu), 22, 22))
5520 shift = uimm (aarch64_get_instr (cpu), 21, 16) - 1;
5525 for (i = 0; i < 2; i++)
5527 uint64_t val = aarch64_get_vec_u64 (cpu, vs, i);
5528 aarch64_set_vec_u64 (cpu, vd, i, val << shift);
5534 if (uimm (aarch64_get_instr (cpu), 21, 21))
5536 shift = uimm (aarch64_get_instr (cpu), 20, 16) - 1;
5538 for (i = 0; i < (full ? 4 : 2); i++)
5540 uint32_t val = aarch64_get_vec_u32 (cpu, vs, i);
5541 aarch64_set_vec_u32 (cpu, vd, i, val << shift);
5547 if (uimm (aarch64_get_instr (cpu), 20, 20))
5549 shift = uimm (aarch64_get_instr (cpu), 19, 16) - 1;
5551 for (i = 0; i < (full ? 8 : 4); i++)
5553 uint16_t val = aarch64_get_vec_u16 (cpu, vs, i);
5554 aarch64_set_vec_u16 (cpu, vd, i, val << shift);
5560 if (uimm (aarch64_get_instr (cpu), 19, 19) == 0)
5563 shift = uimm (aarch64_get_instr (cpu), 18, 16) - 1;
5565 for (i = 0; i < (full ? 16 : 8); i++)
5567 uint8_t val = aarch64_get_vec_u8 (cpu, vs, i);
5568 aarch64_set_vec_u8 (cpu, vd, i, val << shift);
5573 do_vec_SSHR_USHR (sim_cpu *cpu)
5576 instr [30] = half(0)/full(1)
5577 instr [29] = signed(0)/unsigned(1)
5578 instr [28,23] = 01 1110
5579 instr [22,16] = size and shift amount
5580 instr [15,10] = 0000 01
5582 instr [4, 0] = Vd. */
5585 int full = uimm (aarch64_get_instr (cpu), 30, 30);
5586 int sign = uimm (aarch64_get_instr (cpu), 29, 29);
5587 unsigned vs = uimm (aarch64_get_instr (cpu), 9, 5);
5588 unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
5591 NYI_assert (28, 23, 0x1E);
5592 NYI_assert (15, 10, 0x01);
5594 if (uimm (aarch64_get_instr (cpu), 22, 22))
5596 shift = uimm (aarch64_get_instr (cpu), 21, 16);
5602 for (i = 0; i < 2; i++)
5604 int64_t val = aarch64_get_vec_s64 (cpu, vs, i);
5605 aarch64_set_vec_s64 (cpu, vd, i, val >> shift);
5608 for (i = 0; i < 2; i++)
5610 uint64_t val = aarch64_get_vec_u64 (cpu, vs, i);
5611 aarch64_set_vec_u64 (cpu, vd, i, val >> shift);
5617 if (uimm (aarch64_get_instr (cpu), 21, 21))
5619 shift = uimm (aarch64_get_instr (cpu), 20, 16);
5622 for (i = 0; i < (full ? 4 : 2); i++)
5624 int32_t val = aarch64_get_vec_s32 (cpu, vs, i);
5625 aarch64_set_vec_s32 (cpu, vd, i, val >> shift);
5628 for (i = 0; i < (full ? 4 : 2); i++)
5630 uint32_t val = aarch64_get_vec_u32 (cpu, vs, i);
5631 aarch64_set_vec_u32 (cpu, vd, i, val >> shift);
5637 if (uimm (aarch64_get_instr (cpu), 20, 20))
5639 shift = uimm (aarch64_get_instr (cpu), 19, 16);
5642 for (i = 0; i < (full ? 8 : 4); i++)
5644 int16_t val = aarch64_get_vec_s16 (cpu, vs, i);
5645 aarch64_set_vec_s16 (cpu, vd, i, val >> shift);
5648 for (i = 0; i < (full ? 8 : 4); i++)
5650 uint16_t val = aarch64_get_vec_u16 (cpu, vs, i);
5651 aarch64_set_vec_u16 (cpu, vd, i, val >> shift);
5657 if (uimm (aarch64_get_instr (cpu), 19, 19) == 0)
5660 shift = uimm (aarch64_get_instr (cpu), 18, 16);
5663 for (i = 0; i < (full ? 16 : 8); i++)
5665 int8_t val = aarch64_get_vec_s8 (cpu, vs, i);
5666 aarch64_set_vec_s8 (cpu, vd, i, val >> shift);
5669 for (i = 0; i < (full ? 16 : 8); i++)
5671 uint8_t val = aarch64_get_vec_u8 (cpu, vs, i);
5672 aarch64_set_vec_u8 (cpu, vd, i, val >> shift);
5677 do_vec_MUL_by_element (sim_cpu *cpu)
5680 instr[30] = half/full
5681 instr[29,24] = 00 1111
5692 unsigned full = uimm (aarch64_get_instr (cpu), 30, 30);
5693 unsigned L = uimm (aarch64_get_instr (cpu), 21, 21);
5694 unsigned H = uimm (aarch64_get_instr (cpu), 11, 11);
5695 unsigned vn = uimm (aarch64_get_instr (cpu), 9, 5);
5696 unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
5697 unsigned size = uimm (aarch64_get_instr (cpu), 23, 22);
5702 NYI_assert (29, 24, 0x0F);
5703 NYI_assert (15, 12, 0x8);
5704 NYI_assert (10, 10, 0);
5710 /* 16 bit products. */
5715 index = (H << 2) | (L << 1) | uimm (aarch64_get_instr (cpu), 20, 20);
5716 vm = uimm (aarch64_get_instr (cpu), 19, 16);
5717 element2 = aarch64_get_vec_u16 (cpu, vm, index);
5719 for (e = 0; e < (full ? 8 : 4); e ++)
5721 element1 = aarch64_get_vec_u16 (cpu, vn, e);
5722 product = element1 * element2;
5723 aarch64_set_vec_u16 (cpu, vd, e, product);
5730 /* 32 bit products. */
5735 index = (H << 1) | L;
5736 vm = uimm (aarch64_get_instr (cpu), 20, 16);
5737 element2 = aarch64_get_vec_u32 (cpu, vm, index);
5739 for (e = 0; e < (full ? 4 : 2); e ++)
5741 element1 = aarch64_get_vec_u32 (cpu, vn, e);
5742 product = element1 * element2;
5743 aarch64_set_vec_u32 (cpu, vd, e, product);
5754 do_vec_op2 (sim_cpu *cpu)
5757 instr[30] = half/full
5758 instr[29,24] = 00 1111
5760 instr[22,16] = element size & index
5761 instr[15,10] = sub-opcode
5765 NYI_assert (29, 24, 0x0F);
5767 if (uimm (aarch64_get_instr (cpu), 23, 23) != 0)
5769 switch (uimm (aarch64_get_instr (cpu), 15, 10))
5772 case 0x22: do_vec_MUL_by_element (cpu); return;
5778 switch (uimm (aarch64_get_instr (cpu), 15, 10))
5780 case 0x01: do_vec_SSHR_USHR (cpu); return;
5781 case 0x15: do_vec_SHL (cpu); return;
5783 case 0x22: do_vec_MUL_by_element (cpu); return;
5784 case 0x29: do_vec_xtl (cpu); return;
5791 do_vec_neg (sim_cpu *cpu)
5794 instr[30] = full(1)/half(0)
5795 instr[29,24] = 10 1110
5796 instr[23,22] = size: byte(00), half (01), word (10), long (11)
5797 instr[21,10] = 1000 0010 1110
5801 int full = uimm (aarch64_get_instr (cpu), 30, 30);
5802 unsigned vs = uimm (aarch64_get_instr (cpu), 9, 5);
5803 unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
5806 NYI_assert (29, 24, 0x2E);
5807 NYI_assert (21, 10, 0x82E);
5809 switch (uimm (aarch64_get_instr (cpu), 23, 22))
5812 for (i = 0; i < (full ? 16 : 8); i++)
5813 aarch64_set_vec_s8 (cpu, vd, i, - aarch64_get_vec_s8 (cpu, vs, i));
5817 for (i = 0; i < (full ? 8 : 4); i++)
5818 aarch64_set_vec_s16 (cpu, vd, i, - aarch64_get_vec_s16 (cpu, vs, i));
5822 for (i = 0; i < (full ? 4 : 2); i++)
5823 aarch64_set_vec_s32 (cpu, vd, i, - aarch64_get_vec_s32 (cpu, vs, i));
5829 for (i = 0; i < 2; i++)
5830 aarch64_set_vec_s64 (cpu, vd, i, - aarch64_get_vec_s64 (cpu, vs, i));
5839 do_vec_sqrt (sim_cpu *cpu)
5842 instr[30] = full(1)/half(0)
5843 instr[29,23] = 101 1101
5844 instr[22] = single(0)/double(1)
5845 instr[21,10] = 1000 0111 1110
5849 int full = uimm (aarch64_get_instr (cpu), 30, 30);
5850 unsigned vs = uimm (aarch64_get_instr (cpu), 9, 5);
5851 unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
5854 NYI_assert (29, 23, 0x5B);
5855 NYI_assert (21, 10, 0x87E);
5857 if (uimm (aarch64_get_instr (cpu), 22, 22) == 0)
5858 for (i = 0; i < (full ? 4 : 2); i++)
5859 aarch64_set_vec_float (cpu, vd, i,
5860 sqrtf (aarch64_get_vec_float (cpu, vs, i)));
5862 for (i = 0; i < 2; i++)
5863 aarch64_set_vec_double (cpu, vd, i,
5864 sqrt (aarch64_get_vec_double (cpu, vs, i)));
5868 do_vec_mls_indexed (sim_cpu *cpu)
5871 instr[30] = half(0)/full(1)
5872 instr[29,24] = 10 1111
5873 instr[23,22] = 16-bit(01)/32-bit(10)
5874 instr[21,20+11] = index (if 16-bit)
5875 instr[21+11] = index (if 32-bit)
5878 instr[11] = part of index
5883 int full = uimm (aarch64_get_instr (cpu), 30, 30);
5884 unsigned vs = uimm (aarch64_get_instr (cpu), 9, 5);
5885 unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
5886 unsigned vm = uimm (aarch64_get_instr (cpu), 20, 16);
5889 NYI_assert (15, 12, 4);
5890 NYI_assert (10, 10, 0);
5892 switch (uimm (aarch64_get_instr (cpu), 23, 22))
5902 elem = (uimm (aarch64_get_instr (cpu), 21, 20) << 1)
5903 | uimm (aarch64_get_instr (cpu), 11, 11);
5904 val = aarch64_get_vec_u16 (cpu, vm, elem);
5906 for (i = 0; i < (full ? 8 : 4); i++)
5907 aarch64_set_vec_u32 (cpu, vd, i,
5908 aarch64_get_vec_u32 (cpu, vd, i) -
5909 (aarch64_get_vec_u32 (cpu, vs, i) * val));
5915 unsigned elem = (uimm (aarch64_get_instr (cpu), 21, 21) << 1)
5916 | uimm (aarch64_get_instr (cpu), 11, 11);
5917 uint64_t val = aarch64_get_vec_u32 (cpu, vm, elem);
5919 for (i = 0; i < (full ? 4 : 2); i++)
5920 aarch64_set_vec_u64 (cpu, vd, i,
5921 aarch64_get_vec_u64 (cpu, vd, i) -
5922 (aarch64_get_vec_u64 (cpu, vs, i) * val));
5934 do_vec_SUB (sim_cpu *cpu)
5937 instr [30] = half(0)/full(1)
5938 instr [29,24] = 10 1110
5939 instr [23,22] = size: byte(00, half(01), word (10), long (11)
5942 instr [15,10] = 10 0001
5944 instr [4, 0] = Vd. */
5946 unsigned full = uimm (aarch64_get_instr (cpu), 30, 30);
5947 unsigned vm = uimm (aarch64_get_instr (cpu), 20, 16);
5948 unsigned vn = uimm (aarch64_get_instr (cpu), 9, 5);
5949 unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
5952 NYI_assert (29, 24, 0x2E);
5953 NYI_assert (21, 21, 1);
5954 NYI_assert (15, 10, 0x21);
5956 switch (uimm (aarch64_get_instr (cpu), 23, 22))
5959 for (i = 0; i < (full ? 16 : 8); i++)
5960 aarch64_set_vec_s8 (cpu, vd, i,
5961 aarch64_get_vec_s8 (cpu, vn, i)
5962 - aarch64_get_vec_s8 (cpu, vm, i));
5966 for (i = 0; i < (full ? 8 : 4); i++)
5967 aarch64_set_vec_s16 (cpu, vd, i,
5968 aarch64_get_vec_s16 (cpu, vn, i)
5969 - aarch64_get_vec_s16 (cpu, vm, i));
5973 for (i = 0; i < (full ? 4 : 2); i++)
5974 aarch64_set_vec_s32 (cpu, vd, i,
5975 aarch64_get_vec_s32 (cpu, vn, i)
5976 - aarch64_get_vec_s32 (cpu, vm, i));
5983 for (i = 0; i < 2; i++)
5984 aarch64_set_vec_s64 (cpu, vd, i,
5985 aarch64_get_vec_s64 (cpu, vn, i)
5986 - aarch64_get_vec_s64 (cpu, vm, i));
5995 do_vec_MLS (sim_cpu *cpu)
5998 instr [30] = half(0)/full(1)
5999 instr [29,24] = 10 1110
6000 instr [23,22] = size: byte(00, half(01), word (10)
6003 instr [15,10] = 10 0101
6005 instr [4, 0] = Vd. */
6007 unsigned full = uimm (aarch64_get_instr (cpu), 30, 30);
6008 unsigned vm = uimm (aarch64_get_instr (cpu), 20, 16);
6009 unsigned vn = uimm (aarch64_get_instr (cpu), 9, 5);
6010 unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
6013 NYI_assert (29, 24, 0x2E);
6014 NYI_assert (21, 21, 1);
6015 NYI_assert (15, 10, 0x25);
6017 switch (uimm (aarch64_get_instr (cpu), 23, 22))
6020 for (i = 0; i < (full ? 16 : 8); i++)
6021 aarch64_set_vec_u8 (cpu, vd, i,
6022 (aarch64_get_vec_u8 (cpu, vn, i)
6023 * aarch64_get_vec_u8 (cpu, vm, i))
6024 - aarch64_get_vec_u8 (cpu, vd, i));
6028 for (i = 0; i < (full ? 8 : 4); i++)
6029 aarch64_set_vec_u16 (cpu, vd, i,
6030 (aarch64_get_vec_u16 (cpu, vn, i)
6031 * aarch64_get_vec_u16 (cpu, vm, i))
6032 - aarch64_get_vec_u16 (cpu, vd, i));
6036 for (i = 0; i < (full ? 4 : 2); i++)
6037 aarch64_set_vec_u32 (cpu, vd, i,
6038 (aarch64_get_vec_u32 (cpu, vn, i)
6039 * aarch64_get_vec_u32 (cpu, vm, i))
6040 - aarch64_get_vec_u32 (cpu, vd, i));
6049 do_vec_FDIV (sim_cpu *cpu)
6052 instr [30] = half(0)/full(1)
6053 instr [29,23] = 10 1110 0
6054 instr [22] = float()/double(1)
6057 instr [15,10] = 1111 11
6059 instr [4, 0] = Vd. */
6061 unsigned full = uimm (aarch64_get_instr (cpu), 30, 30);
6062 unsigned vm = uimm (aarch64_get_instr (cpu), 20, 16);
6063 unsigned vn = uimm (aarch64_get_instr (cpu), 9, 5);
6064 unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
6067 NYI_assert (29, 23, 0x5C);
6068 NYI_assert (21, 21, 1);
6069 NYI_assert (15, 10, 0x3F);
6071 if (uimm (aarch64_get_instr (cpu), 22, 22))
6076 for (i = 0; i < 2; i++)
6077 aarch64_set_vec_double (cpu, vd, i,
6078 aarch64_get_vec_double (cpu, vn, i)
6079 / aarch64_get_vec_double (cpu, vm, i));
6082 for (i = 0; i < (full ? 4 : 2); i++)
6083 aarch64_set_vec_float (cpu, vd, i,
6084 aarch64_get_vec_float (cpu, vn, i)
6085 / aarch64_get_vec_float (cpu, vm, i));
6089 do_vec_FMUL (sim_cpu *cpu)
6092 instr [30] = half(0)/full(1)
6093 instr [29,23] = 10 1110 0
6094 instr [22] = float(0)/double(1)
6097 instr [15,10] = 1101 11
6099 instr [4, 0] = Vd. */
6101 unsigned full = uimm (aarch64_get_instr (cpu), 30, 30);
6102 unsigned vm = uimm (aarch64_get_instr (cpu), 20, 16);
6103 unsigned vn = uimm (aarch64_get_instr (cpu), 9, 5);
6104 unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
6107 NYI_assert (29, 23, 0x5C);
6108 NYI_assert (21, 21, 1);
6109 NYI_assert (15, 10, 0x37);
6111 if (uimm (aarch64_get_instr (cpu), 22, 22))
6116 for (i = 0; i < 2; i++)
6117 aarch64_set_vec_double (cpu, vd, i,
6118 aarch64_get_vec_double (cpu, vn, i)
6119 * aarch64_get_vec_double (cpu, vm, i));
6122 for (i = 0; i < (full ? 4 : 2); i++)
6123 aarch64_set_vec_float (cpu, vd, i,
6124 aarch64_get_vec_float (cpu, vn, i)
6125 * aarch64_get_vec_float (cpu, vm, i));
6129 do_vec_FADDP (sim_cpu *cpu)
6132 instr [30] = half(0)/full(1)
6133 instr [29,23] = 10 1110 0
6134 instr [22] = float(0)/double(1)
6137 instr [15,10] = 1101 01
6139 instr [4, 0] = Vd. */
6141 unsigned full = uimm (aarch64_get_instr (cpu), 30, 30);
6142 unsigned vm = uimm (aarch64_get_instr (cpu), 20, 16);
6143 unsigned vn = uimm (aarch64_get_instr (cpu), 9, 5);
6144 unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
6146 NYI_assert (29, 23, 0x5C);
6147 NYI_assert (21, 21, 1);
6148 NYI_assert (15, 10, 0x35);
6150 if (uimm (aarch64_get_instr (cpu), 22, 22))
6152 /* Extract values before adding them incase vd == vn/vm. */
6153 double tmp1 = aarch64_get_vec_double (cpu, vn, 0);
6154 double tmp2 = aarch64_get_vec_double (cpu, vn, 1);
6155 double tmp3 = aarch64_get_vec_double (cpu, vm, 0);
6156 double tmp4 = aarch64_get_vec_double (cpu, vm, 1);
6161 aarch64_set_vec_double (cpu, vd, 0, tmp1 + tmp2);
6162 aarch64_set_vec_double (cpu, vd, 1, tmp3 + tmp4);
6166 /* Extract values before adding them incase vd == vn/vm. */
6167 float tmp1 = aarch64_get_vec_float (cpu, vn, 0);
6168 float tmp2 = aarch64_get_vec_float (cpu, vn, 1);
6169 float tmp5 = aarch64_get_vec_float (cpu, vm, 0);
6170 float tmp6 = aarch64_get_vec_float (cpu, vm, 1);
6174 float tmp3 = aarch64_get_vec_float (cpu, vn, 2);
6175 float tmp4 = aarch64_get_vec_float (cpu, vn, 3);
6176 float tmp7 = aarch64_get_vec_float (cpu, vm, 2);
6177 float tmp8 = aarch64_get_vec_float (cpu, vm, 3);
6179 aarch64_set_vec_float (cpu, vd, 0, tmp1 + tmp2);
6180 aarch64_set_vec_float (cpu, vd, 1, tmp3 + tmp4);
6181 aarch64_set_vec_float (cpu, vd, 2, tmp5 + tmp6);
6182 aarch64_set_vec_float (cpu, vd, 3, tmp7 + tmp8);
6186 aarch64_set_vec_float (cpu, vd, 0, tmp1 + tmp2);
6187 aarch64_set_vec_float (cpu, vd, 1, tmp5 + tmp6);
6193 do_vec_FSQRT (sim_cpu *cpu)
6196 instr[30] = half(0)/full(1)
6197 instr[29,23] = 10 1110 1
6198 instr[22] = single(0)/double(1)
6199 instr[21,10] = 10 0001 1111 10
6201 instr[4,0] = Vdest. */
6203 unsigned vn = uimm (aarch64_get_instr (cpu), 9, 5);
6204 unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
6205 unsigned full = uimm (aarch64_get_instr (cpu), 30, 30);
6208 NYI_assert (29, 23, 0x5D);
6209 NYI_assert (21, 10, 0x87E);
6211 if (uimm (aarch64_get_instr (cpu), 22, 22))
6216 for (i = 0; i < 2; i++)
6217 aarch64_set_vec_double (cpu, vd, i,
6218 sqrt (aarch64_get_vec_double (cpu, vn, i)));
6222 for (i = 0; i < (full ? 4 : 2); i++)
6223 aarch64_set_vec_float (cpu, vd, i,
6224 sqrtf (aarch64_get_vec_float (cpu, vn, i)));
6229 do_vec_FNEG (sim_cpu *cpu)
6232 instr[30] = half (0)/full (1)
6233 instr[29,23] = 10 1110 1
6234 instr[22] = single (0)/double (1)
6235 instr[21,10] = 10 0000 1111 10
6237 instr[4,0] = Vdest. */
6239 unsigned vn = uimm (aarch64_get_instr (cpu), 9, 5);
6240 unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
6241 unsigned full = uimm (aarch64_get_instr (cpu), 30, 30);
6244 NYI_assert (29, 23, 0x5D);
6245 NYI_assert (21, 10, 0x83E);
6247 if (uimm (aarch64_get_instr (cpu), 22, 22))
6252 for (i = 0; i < 2; i++)
6253 aarch64_set_vec_double (cpu, vd, i,
6254 - aarch64_get_vec_double (cpu, vn, i));
6258 for (i = 0; i < (full ? 4 : 2); i++)
6259 aarch64_set_vec_float (cpu, vd, i,
6260 - aarch64_get_vec_float (cpu, vn, i));
6265 do_vec_NOT (sim_cpu *cpu)
6268 instr[30] = half (0)/full (1)
6269 instr[29,21] = 10 1110 001
6270 instr[20,16] = 0 0000
6271 instr[15,10] = 0101 10
6275 unsigned vn = uimm (aarch64_get_instr (cpu), 9, 5);
6276 unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
6278 int full = uimm (aarch64_get_instr (cpu), 30, 30);
6280 NYI_assert (29, 10, 0xB8816);
6282 for (i = 0; i < (full ? 16 : 8); i++)
6283 aarch64_set_vec_u8 (cpu, vd, i, ~ aarch64_get_vec_u8 (cpu, vn, i));
6287 do_vec_MOV_element (sim_cpu *cpu)
6289 /* instr[31,21] = 0110 1110 000
6290 instr[20,16] = size & dest index
6292 instr[14,11] = source index
6297 unsigned vs = uimm (aarch64_get_instr (cpu), 9, 5);
6298 unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
6302 NYI_assert (31, 21, 0x370);
6303 NYI_assert (15, 15, 0);
6304 NYI_assert (10, 10, 1);
6306 if (uimm (aarch64_get_instr (cpu), 16, 16))
6309 src_index = uimm (aarch64_get_instr (cpu), 14, 11);
6310 dst_index = uimm (aarch64_get_instr (cpu), 20, 17);
6311 aarch64_set_vec_u8 (cpu, vd, dst_index,
6312 aarch64_get_vec_u8 (cpu, vs, src_index));
6314 else if (uimm (aarch64_get_instr (cpu), 17, 17))
6317 NYI_assert (11, 11, 0);
6318 src_index = uimm (aarch64_get_instr (cpu), 14, 12);
6319 dst_index = uimm (aarch64_get_instr (cpu), 20, 18);
6320 aarch64_set_vec_u16 (cpu, vd, dst_index,
6321 aarch64_get_vec_u16 (cpu, vs, src_index));
6323 else if (uimm (aarch64_get_instr (cpu), 18, 18))
6326 NYI_assert (12, 11, 0);
6327 src_index = uimm (aarch64_get_instr (cpu), 14, 13);
6328 dst_index = uimm (aarch64_get_instr (cpu), 20, 19);
6329 aarch64_set_vec_u32 (cpu, vd, dst_index,
6330 aarch64_get_vec_u32 (cpu, vs, src_index));
6334 NYI_assert (19, 19, 1);
6335 NYI_assert (13, 11, 0);
6336 src_index = uimm (aarch64_get_instr (cpu), 14, 14);
6337 dst_index = uimm (aarch64_get_instr (cpu), 20, 20);
6338 aarch64_set_vec_u64 (cpu, vd, dst_index,
6339 aarch64_get_vec_u64 (cpu, vs, src_index));
6344 dexAdvSIMD0 (sim_cpu *cpu)
6346 /* instr [28,25] = 0 111. */
6347 if ( uimm (aarch64_get_instr (cpu), 15, 10) == 0x07
6348 && (uimm (aarch64_get_instr (cpu), 9, 5) ==
6349 uimm (aarch64_get_instr (cpu), 20, 16)))
6351 if (uimm (aarch64_get_instr (cpu), 31, 21) == 0x075
6352 || uimm (aarch64_get_instr (cpu), 31, 21) == 0x275)
6354 do_vec_MOV_whole_vector (cpu);
6359 if (uimm (aarch64_get_instr (cpu), 29, 19) == 0x1E0)
6361 do_vec_MOV_immediate (cpu);
6365 if (uimm (aarch64_get_instr (cpu), 29, 19) == 0x5E0)
6371 if (uimm (aarch64_get_instr (cpu), 29, 19) == 0x1C0
6372 || uimm (aarch64_get_instr (cpu), 29, 19) == 0x1C1)
6374 if (uimm (aarch64_get_instr (cpu), 15, 10) == 0x03)
6376 do_vec_DUP_scalar_into_vector (cpu);
6381 switch (uimm (aarch64_get_instr (cpu), 29, 24))
6383 case 0x0E: do_vec_op1 (cpu); return;
6384 case 0x0F: do_vec_op2 (cpu); return;
6387 switch (uimm (aarch64_get_instr (cpu), 15, 10))
6389 case 0x01: do_vec_SSHR_USHR (cpu); return;
6391 case 0x12: do_vec_mls_indexed (cpu); return;
6392 case 0x29: do_vec_xtl (cpu); return;
6398 if (uimm (aarch64_get_instr (cpu), 21, 21) == 1)
6400 switch (uimm (aarch64_get_instr (cpu), 15, 10))
6403 switch (uimm (aarch64_get_instr (cpu), 23, 22))
6405 case 0: do_vec_EOR (cpu); return;
6406 case 1: do_vec_BSL (cpu); return;
6408 case 3: do_vec_bit (cpu); return;
6412 case 0x08: do_vec_sub_long (cpu); return;
6413 case 0x11: do_vec_USHL (cpu); return;
6414 case 0x16: do_vec_NOT (cpu); return;
6415 case 0x19: do_vec_max (cpu); return;
6416 case 0x1B: do_vec_min (cpu); return;
6417 case 0x21: do_vec_SUB (cpu); return;
6418 case 0x25: do_vec_MLS (cpu); return;
6419 case 0x31: do_vec_FminmaxNMP (cpu); return;
6420 case 0x35: do_vec_FADDP (cpu); return;
6421 case 0x37: do_vec_FMUL (cpu); return;
6422 case 0x3F: do_vec_FDIV (cpu); return;
6425 switch (uimm (aarch64_get_instr (cpu), 20, 16))
6427 case 0x00: do_vec_FNEG (cpu); return;
6428 case 0x01: do_vec_FSQRT (cpu); return;
6442 do_vec_compare (cpu); return;
6448 if (uimm (aarch64_get_instr (cpu), 31, 21) == 0x370)
6450 do_vec_MOV_element (cpu);
6454 switch (uimm (aarch64_get_instr (cpu), 21, 10))
6456 case 0x82E: do_vec_neg (cpu); return;
6457 case 0x87E: do_vec_sqrt (cpu); return;
6459 if (uimm (aarch64_get_instr (cpu), 15, 10) == 0x30)
6477 /* Float multiply add. */
6479 fmadds (sim_cpu *cpu)
6481 unsigned sa = uimm (aarch64_get_instr (cpu), 14, 10);
6482 unsigned sm = uimm (aarch64_get_instr (cpu), 20, 16);
6483 unsigned sn = uimm (aarch64_get_instr (cpu), 9, 5);
6484 unsigned sd = uimm (aarch64_get_instr (cpu), 4, 0);
6486 aarch64_set_FP_float (cpu, sd, aarch64_get_FP_float (cpu, sa)
6487 + aarch64_get_FP_float (cpu, sn)
6488 * aarch64_get_FP_float (cpu, sm));
6491 /* Double multiply add. */
6493 fmaddd (sim_cpu *cpu)
6495 unsigned sa = uimm (aarch64_get_instr (cpu), 14, 10);
6496 unsigned sm = uimm (aarch64_get_instr (cpu), 20, 16);
6497 unsigned sn = uimm (aarch64_get_instr (cpu), 9, 5);
6498 unsigned sd = uimm (aarch64_get_instr (cpu), 4, 0);
6500 aarch64_set_FP_double (cpu, sd, aarch64_get_FP_double (cpu, sa)
6501 + aarch64_get_FP_double (cpu, sn)
6502 * aarch64_get_FP_double (cpu, sm));
6505 /* Float multiply subtract. */
6507 fmsubs (sim_cpu *cpu)
6509 unsigned sa = uimm (aarch64_get_instr (cpu), 14, 10);
6510 unsigned sm = uimm (aarch64_get_instr (cpu), 20, 16);
6511 unsigned sn = uimm (aarch64_get_instr (cpu), 9, 5);
6512 unsigned sd = uimm (aarch64_get_instr (cpu), 4, 0);
6514 aarch64_set_FP_float (cpu, sd, aarch64_get_FP_float (cpu, sa)
6515 - aarch64_get_FP_float (cpu, sn)
6516 * aarch64_get_FP_float (cpu, sm));
6519 /* Double multiply subtract. */
6521 fmsubd (sim_cpu *cpu)
6523 unsigned sa = uimm (aarch64_get_instr (cpu), 14, 10);
6524 unsigned sm = uimm (aarch64_get_instr (cpu), 20, 16);
6525 unsigned sn = uimm (aarch64_get_instr (cpu), 9, 5);
6526 unsigned sd = uimm (aarch64_get_instr (cpu), 4, 0);
6528 aarch64_set_FP_double (cpu, sd, aarch64_get_FP_double (cpu, sa)
6529 - aarch64_get_FP_double (cpu, sn)
6530 * aarch64_get_FP_double (cpu, sm));
6533 /* Float negative multiply add. */
6535 fnmadds (sim_cpu *cpu)
6537 unsigned sa = uimm (aarch64_get_instr (cpu), 14, 10);
6538 unsigned sm = uimm (aarch64_get_instr (cpu), 20, 16);
6539 unsigned sn = uimm (aarch64_get_instr (cpu), 9, 5);
6540 unsigned sd = uimm (aarch64_get_instr (cpu), 4, 0);
6542 aarch64_set_FP_float (cpu, sd, - aarch64_get_FP_float (cpu, sa)
6543 + (- aarch64_get_FP_float (cpu, sn))
6544 * aarch64_get_FP_float (cpu, sm));
6547 /* Double negative multiply add. */
6549 fnmaddd (sim_cpu *cpu)
6551 unsigned sa = uimm (aarch64_get_instr (cpu), 14, 10);
6552 unsigned sm = uimm (aarch64_get_instr (cpu), 20, 16);
6553 unsigned sn = uimm (aarch64_get_instr (cpu), 9, 5);
6554 unsigned sd = uimm (aarch64_get_instr (cpu), 4, 0);
6556 aarch64_set_FP_double (cpu, sd, - aarch64_get_FP_double (cpu, sa)
6557 + (- aarch64_get_FP_double (cpu, sn))
6558 * aarch64_get_FP_double (cpu, sm));
6561 /* Float negative multiply subtract. */
6563 fnmsubs (sim_cpu *cpu)
6565 unsigned sa = uimm (aarch64_get_instr (cpu), 14, 10);
6566 unsigned sm = uimm (aarch64_get_instr (cpu), 20, 16);
6567 unsigned sn = uimm (aarch64_get_instr (cpu), 9, 5);
6568 unsigned sd = uimm (aarch64_get_instr (cpu), 4, 0);
6570 aarch64_set_FP_float (cpu, sd, - aarch64_get_FP_float (cpu, sa)
6571 + aarch64_get_FP_float (cpu, sn)
6572 * aarch64_get_FP_float (cpu, sm));
6575 /* Double negative multiply subtract. */
6577 fnmsubd (sim_cpu *cpu)
6579 unsigned sa = uimm (aarch64_get_instr (cpu), 14, 10);
6580 unsigned sm = uimm (aarch64_get_instr (cpu), 20, 16);
6581 unsigned sn = uimm (aarch64_get_instr (cpu), 9, 5);
6582 unsigned sd = uimm (aarch64_get_instr (cpu), 4, 0);
6584 aarch64_set_FP_double (cpu, sd, - aarch64_get_FP_double (cpu, sa)
6585 + aarch64_get_FP_double (cpu, sn)
6586 * aarch64_get_FP_double (cpu, sm));
6590 dexSimpleFPDataProc3Source (sim_cpu *cpu)
6592 /* instr[31] ==> M : 0 ==> OK, 1 ==> UNALLOC
6594 instr[29] ==> S : 0 ==> OK, 1 ==> UNALLOC
6597 instr[23,22] ==> type : 0 ==> single, 01 ==> double, 1x ==> UNALLOC
6598 instr[21] ==> o1 : 0 ==> unnegated, 1 ==> negated
6599 instr[15] ==> o2 : 0 ==> ADD, 1 ==> SUB */
6601 uint32_t M_S = (uimm (aarch64_get_instr (cpu), 31, 31) << 1)
6602 | uimm (aarch64_get_instr (cpu), 29, 29);
6603 /* dispatch on combined type:o1:o2. */
6604 uint32_t dispatch = (uimm (aarch64_get_instr (cpu), 23, 21) << 1)
6605 | uimm (aarch64_get_instr (cpu), 15, 15);
6612 case 0: fmadds (cpu); return;
6613 case 1: fmsubs (cpu); return;
6614 case 2: fnmadds (cpu); return;
6615 case 3: fnmsubs (cpu); return;
6616 case 4: fmaddd (cpu); return;
6617 case 5: fmsubd (cpu); return;
6618 case 6: fnmaddd (cpu); return;
6619 case 7: fnmsubd (cpu); return;
6621 /* type > 1 is currently unallocated. */
6627 dexSimpleFPFixedConvert (sim_cpu *cpu)
6633 dexSimpleFPCondCompare (sim_cpu *cpu)
6642 fadds (sim_cpu *cpu)
6644 unsigned sm = uimm (aarch64_get_instr (cpu), 20, 16);
6645 unsigned sn = uimm (aarch64_get_instr (cpu), 9, 5);
6646 unsigned sd = uimm (aarch64_get_instr (cpu), 4, 0);
6648 aarch64_set_FP_float (cpu, sd, aarch64_get_FP_float (cpu, sn)
6649 + aarch64_get_FP_float (cpu, sm));
6654 faddd (sim_cpu *cpu)
6656 unsigned sm = uimm (aarch64_get_instr (cpu), 20, 16);
6657 unsigned sn = uimm (aarch64_get_instr (cpu), 9, 5);
6658 unsigned sd = uimm (aarch64_get_instr (cpu), 4, 0);
6660 aarch64_set_FP_double (cpu, sd, aarch64_get_FP_double (cpu, sn)
6661 + aarch64_get_FP_double (cpu, sm));
6666 fdivs (sim_cpu *cpu)
6668 unsigned sm = uimm (aarch64_get_instr (cpu), 20, 16);
6669 unsigned sn = uimm (aarch64_get_instr (cpu), 9, 5);
6670 unsigned sd = uimm (aarch64_get_instr (cpu), 4, 0);
6672 aarch64_set_FP_float (cpu, sd, aarch64_get_FP_float (cpu, sn)
6673 / aarch64_get_FP_float (cpu, sm));
6676 /* Double divide. */
6678 fdivd (sim_cpu *cpu)
6680 unsigned sm = uimm (aarch64_get_instr (cpu), 20, 16);
6681 unsigned sn = uimm (aarch64_get_instr (cpu), 9, 5);
6682 unsigned sd = uimm (aarch64_get_instr (cpu), 4, 0);
6684 aarch64_set_FP_double (cpu, sd, aarch64_get_FP_double (cpu, sn)
6685 / aarch64_get_FP_double (cpu, sm));
6688 /* Float multiply. */
6690 fmuls (sim_cpu *cpu)
6692 unsigned sm = uimm (aarch64_get_instr (cpu), 20, 16);
6693 unsigned sn = uimm (aarch64_get_instr (cpu), 9, 5);
6694 unsigned sd = uimm (aarch64_get_instr (cpu), 4, 0);
6696 aarch64_set_FP_float (cpu, sd, aarch64_get_FP_float (cpu, sn)
6697 * aarch64_get_FP_float (cpu, sm));
6700 /* Double multiply. */
6702 fmuld (sim_cpu *cpu)
6704 unsigned sm = uimm (aarch64_get_instr (cpu), 20, 16);
6705 unsigned sn = uimm (aarch64_get_instr (cpu), 9, 5);
6706 unsigned sd = uimm (aarch64_get_instr (cpu), 4, 0);
6708 aarch64_set_FP_double (cpu, sd, aarch64_get_FP_double (cpu, sn)
6709 * aarch64_get_FP_double (cpu, sm));
6712 /* Float negate and multiply. */
6714 fnmuls (sim_cpu *cpu)
6716 unsigned sm = uimm (aarch64_get_instr (cpu), 20, 16);
6717 unsigned sn = uimm (aarch64_get_instr (cpu), 9, 5);
6718 unsigned sd = uimm (aarch64_get_instr (cpu), 4, 0);
6720 aarch64_set_FP_float (cpu, sd, - (aarch64_get_FP_float (cpu, sn)
6721 * aarch64_get_FP_float (cpu, sm)));
6724 /* Double negate and multiply. */
6726 fnmuld (sim_cpu *cpu)
6728 unsigned sm = uimm (aarch64_get_instr (cpu), 20, 16);
6729 unsigned sn = uimm (aarch64_get_instr (cpu), 9, 5);
6730 unsigned sd = uimm (aarch64_get_instr (cpu), 4, 0);
6732 aarch64_set_FP_double (cpu, sd, - (aarch64_get_FP_double (cpu, sn)
6733 * aarch64_get_FP_double (cpu, sm)));
6736 /* Float subtract. */
6738 fsubs (sim_cpu *cpu)
6740 unsigned sm = uimm (aarch64_get_instr (cpu), 20, 16);
6741 unsigned sn = uimm (aarch64_get_instr (cpu), 9, 5);
6742 unsigned sd = uimm (aarch64_get_instr (cpu), 4, 0);
6744 aarch64_set_FP_float (cpu, sd, aarch64_get_FP_float (cpu, sn)
6745 - aarch64_get_FP_float (cpu, sm));
6748 /* Double subtract. */
6750 fsubd (sim_cpu *cpu)
6752 unsigned sm = uimm (aarch64_get_instr (cpu), 20, 16);
6753 unsigned sn = uimm (aarch64_get_instr (cpu), 9, 5);
6754 unsigned sd = uimm (aarch64_get_instr (cpu), 4, 0);
6756 aarch64_set_FP_double (cpu, sd, aarch64_get_FP_double (cpu, sn)
6757 - aarch64_get_FP_double (cpu, sm));
6761 do_FMINNM (sim_cpu *cpu)
6763 /* instr[31,23] = 0 0011 1100
6764 instr[22] = float(0)/double(1)
6767 instr[15,10] = 01 1110
6771 unsigned sm = uimm (aarch64_get_instr (cpu), 20, 16);
6772 unsigned sn = uimm (aarch64_get_instr (cpu), 9, 5);
6773 unsigned sd = uimm (aarch64_get_instr (cpu), 4, 0);
6775 NYI_assert (31, 23, 0x03C);
6776 NYI_assert (15, 10, 0x1E);
6778 if (uimm (aarch64_get_instr (cpu), 22, 22))
6779 aarch64_set_FP_double (cpu, sd,
6780 dminnm (aarch64_get_FP_double (cpu, sn),
6781 aarch64_get_FP_double (cpu, sm)));
6783 aarch64_set_FP_float (cpu, sd,
6784 fminnm (aarch64_get_FP_float (cpu, sn),
6785 aarch64_get_FP_float (cpu, sm)));
6789 do_FMAXNM (sim_cpu *cpu)
6791 /* instr[31,23] = 0 0011 1100
6792 instr[22] = float(0)/double(1)
6795 instr[15,10] = 01 1010
6799 unsigned sm = uimm (aarch64_get_instr (cpu), 20, 16);
6800 unsigned sn = uimm (aarch64_get_instr (cpu), 9, 5);
6801 unsigned sd = uimm (aarch64_get_instr (cpu), 4, 0);
6803 NYI_assert (31, 23, 0x03C);
6804 NYI_assert (15, 10, 0x1A);
6806 if (uimm (aarch64_get_instr (cpu), 22, 22))
6807 aarch64_set_FP_double (cpu, sd,
6808 dmaxnm (aarch64_get_FP_double (cpu, sn),
6809 aarch64_get_FP_double (cpu, sm)));
6811 aarch64_set_FP_float (cpu, sd,
6812 fmaxnm (aarch64_get_FP_float (cpu, sn),
6813 aarch64_get_FP_float (cpu, sm)));
6817 dexSimpleFPDataProc2Source (sim_cpu *cpu)
6819 /* instr[31] ==> M : 0 ==> OK, 1 ==> UNALLOC
6821 instr[29] ==> S : 0 ==> OK, 1 ==> UNALLOC
6824 instr[23,22] ==> type : 0 ==> single, 01 ==> double, 1x ==> UNALLOC
6827 instr[15,12] ==> opcode : 0000 ==> FMUL, 0001 ==> FDIV
6828 0010 ==> FADD, 0011 ==> FSUB,
6829 0100 ==> FMAX, 0101 ==> FMIN
6830 0110 ==> FMAXNM, 0111 ==> FMINNM
6831 1000 ==> FNMUL, ow ==> UNALLOC
6836 uint32_t M_S = (uimm (aarch64_get_instr (cpu), 31, 31) << 1)
6837 | uimm (aarch64_get_instr (cpu), 29, 29);
6838 uint32_t type = uimm (aarch64_get_instr (cpu), 23, 22);
6839 /* Dispatch on opcode. */
6840 uint32_t dispatch = uimm (aarch64_get_instr (cpu), 15, 12);
6851 case 0: fmuld (cpu); return;
6852 case 1: fdivd (cpu); return;
6853 case 2: faddd (cpu); return;
6854 case 3: fsubd (cpu); return;
6855 case 6: do_FMAXNM (cpu); return;
6856 case 7: do_FMINNM (cpu); return;
6857 case 8: fnmuld (cpu); return;
6859 /* Have not yet implemented fmax and fmin. */
6867 else /* type == 0 => floats. */
6870 case 0: fmuls (cpu); return;
6871 case 1: fdivs (cpu); return;
6872 case 2: fadds (cpu); return;
6873 case 3: fsubs (cpu); return;
6874 case 6: do_FMAXNM (cpu); return;
6875 case 7: do_FMINNM (cpu); return;
6876 case 8: fnmuls (cpu); return;
6888 dexSimpleFPCondSelect (sim_cpu *cpu)
6891 instr[31,23] = 0 0011 1100
6892 instr[22] = 0=>single 1=>double
6899 unsigned sm = uimm (aarch64_get_instr (cpu), 20, 16);
6900 unsigned sn = uimm (aarch64_get_instr (cpu), 9, 5);
6901 unsigned sd = uimm (aarch64_get_instr (cpu), 4, 0);
6902 uint32_t set = testConditionCode (cpu, uimm (aarch64_get_instr (cpu), 15, 12));
6904 NYI_assert (31, 23, 0x03C);
6905 NYI_assert (11, 10, 0x3);
6907 if (uimm (aarch64_get_instr (cpu), 22, 22))
6908 aarch64_set_FP_double (cpu, sd, set ? sn : sm);
6910 aarch64_set_FP_float (cpu, sd, set ? sn : sm);
6913 /* Store 32 bit unscaled signed 9 bit. */
6915 fsturs (sim_cpu *cpu, int32_t offset)
6917 unsigned int rn = uimm (aarch64_get_instr (cpu), 9, 5);
6918 unsigned int st = uimm (aarch64_get_instr (cpu), 4, 0);
6920 aarch64_set_mem_u32 (cpu, aarch64_get_reg_u64 (cpu, st, 1) + offset,
6921 aarch64_get_vec_u32 (cpu, rn, 0));
6924 /* Store 64 bit unscaled signed 9 bit. */
6926 fsturd (sim_cpu *cpu, int32_t offset)
6928 unsigned int rn = uimm (aarch64_get_instr (cpu), 9, 5);
6929 unsigned int st = uimm (aarch64_get_instr (cpu), 4, 0);
6931 aarch64_set_mem_u64 (cpu, aarch64_get_reg_u64 (cpu, st, 1) + offset,
6932 aarch64_get_vec_u64 (cpu, rn, 0));
6935 /* Store 128 bit unscaled signed 9 bit. */
6937 fsturq (sim_cpu *cpu, int32_t offset)
6939 unsigned int rn = uimm (aarch64_get_instr (cpu), 9, 5);
6940 unsigned int st = uimm (aarch64_get_instr (cpu), 4, 0);
6943 aarch64_get_FP_long_double (cpu, rn, & a);
6944 aarch64_set_mem_long_double (cpu,
6945 aarch64_get_reg_u64 (cpu, st, 1)
6949 /* TODO FP move register. */
6951 /* 32 bit fp to fp move register. */
6953 ffmovs (sim_cpu *cpu)
6955 unsigned int rn = uimm (aarch64_get_instr (cpu), 9, 5);
6956 unsigned int st = uimm (aarch64_get_instr (cpu), 4, 0);
6958 aarch64_set_FP_float (cpu, st, aarch64_get_FP_float (cpu, rn));
6961 /* 64 bit fp to fp move register. */
6963 ffmovd (sim_cpu *cpu)
6965 unsigned int rn = uimm (aarch64_get_instr (cpu), 9, 5);
6966 unsigned int st = uimm (aarch64_get_instr (cpu), 4, 0);
6968 aarch64_set_FP_double (cpu, st, aarch64_get_FP_double (cpu, rn));
6971 /* 32 bit GReg to Vec move register. */
6973 fgmovs (sim_cpu *cpu)
6975 unsigned int rn = uimm (aarch64_get_instr (cpu), 9, 5);
6976 unsigned int st = uimm (aarch64_get_instr (cpu), 4, 0);
6978 aarch64_set_vec_u32 (cpu, st, 0, aarch64_get_reg_u32 (cpu, rn, NO_SP));
6981 /* 64 bit g to fp move register. */
6983 fgmovd (sim_cpu *cpu)
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_vec_u64 (cpu, st, 0, aarch64_get_reg_u64 (cpu, rn, NO_SP));
6991 /* 32 bit fp to g move register. */
6993 gfmovs (sim_cpu *cpu)
6995 unsigned int rn = uimm (aarch64_get_instr (cpu), 9, 5);
6996 unsigned int st = uimm (aarch64_get_instr (cpu), 4, 0);
6998 aarch64_set_reg_u64 (cpu, st, NO_SP, aarch64_get_vec_u32 (cpu, rn, 0));
7001 /* 64 bit fp to g move register. */
7003 gfmovd (sim_cpu *cpu)
7005 unsigned int rn = uimm (aarch64_get_instr (cpu), 9, 5);
7006 unsigned int st = uimm (aarch64_get_instr (cpu), 4, 0);
7008 aarch64_set_reg_u64 (cpu, st, NO_SP, aarch64_get_vec_u64 (cpu, rn, 0));
7011 /* FP move immediate
7013 These install an immediate 8 bit value in the target register
7014 where the 8 bits comprise 1 sign bit, 4 bits of fraction and a 3
7018 fmovs (sim_cpu *cpu)
7020 unsigned int sd = uimm (aarch64_get_instr (cpu), 4, 0);
7021 uint32_t imm = uimm (aarch64_get_instr (cpu), 20, 13);
7022 float f = fp_immediate_for_encoding_32 (imm);
7024 aarch64_set_FP_float (cpu, sd, f);
7028 fmovd (sim_cpu *cpu)
7030 unsigned int sd = uimm (aarch64_get_instr (cpu), 4, 0);
7031 uint32_t imm = uimm (aarch64_get_instr (cpu), 20, 13);
7032 double d = fp_immediate_for_encoding_64 (imm);
7034 aarch64_set_FP_double (cpu, sd, d);
7038 dexSimpleFPImmediate (sim_cpu *cpu)
7040 /* instr[31,23] == 00111100
7041 instr[22] == type : single(0)/double(1)
7043 instr[20,13] == imm8
7045 instr[9,5] == imm5 : 00000 ==> PK, ow ==> UNALLOC
7047 uint32_t imm5 = uimm (aarch64_get_instr (cpu), 9, 5);
7049 NYI_assert (31, 23, 0x3C);
7054 if (uimm (aarch64_get_instr (cpu), 22, 22))
7060 /* TODO specific decode and execute for group Load Store. */
7062 /* TODO FP load/store single register (unscaled offset). */
7064 /* TODO load 8 bit unscaled signed 9 bit. */
7065 /* TODO load 16 bit unscaled signed 9 bit. */
7067 /* Load 32 bit unscaled signed 9 bit. */
7069 fldurs (sim_cpu *cpu, int32_t offset)
7071 unsigned int rn = uimm (aarch64_get_instr (cpu), 9, 5);
7072 unsigned int st = uimm (aarch64_get_instr (cpu), 4, 0);
7074 aarch64_set_vec_u32 (cpu, st, 0, aarch64_get_mem_u32
7075 (cpu, aarch64_get_reg_u64 (cpu, rn, SP_OK) + offset));
7078 /* Load 64 bit unscaled signed 9 bit. */
7080 fldurd (sim_cpu *cpu, int32_t offset)
7082 unsigned int rn = uimm (aarch64_get_instr (cpu), 9, 5);
7083 unsigned int st = uimm (aarch64_get_instr (cpu), 4, 0);
7085 aarch64_set_vec_u64 (cpu, st, 0, aarch64_get_mem_u64
7086 (cpu, aarch64_get_reg_u64 (cpu, rn, SP_OK) + offset));
7089 /* Load 128 bit unscaled signed 9 bit. */
7091 fldurq (sim_cpu *cpu, int32_t offset)
7093 unsigned int rn = uimm (aarch64_get_instr (cpu), 9, 5);
7094 unsigned int st = uimm (aarch64_get_instr (cpu), 4, 0);
7096 uint64_t addr = aarch64_get_reg_u64 (cpu, rn, SP_OK) + offset;
7098 aarch64_get_mem_long_double (cpu, addr, & a);
7099 aarch64_set_FP_long_double (cpu, st, a);
7102 /* TODO store 8 bit unscaled signed 9 bit. */
7103 /* TODO store 16 bit unscaled signed 9 bit. */
7108 /* Float absolute value. */
7110 fabss (sim_cpu *cpu)
7112 unsigned sn = uimm (aarch64_get_instr (cpu), 9, 5);
7113 unsigned sd = uimm (aarch64_get_instr (cpu), 4, 0);
7114 float value = aarch64_get_FP_float (cpu, sn);
7116 aarch64_set_FP_float (cpu, sd, fabsf (value));
7119 /* Double absolute value. */
7121 fabcpu (sim_cpu *cpu)
7123 unsigned sn = uimm (aarch64_get_instr (cpu), 9, 5);
7124 unsigned sd = uimm (aarch64_get_instr (cpu), 4, 0);
7125 double value = aarch64_get_FP_double (cpu, sn);
7127 aarch64_set_FP_double (cpu, sd, fabs (value));
7130 /* Float negative value. */
7132 fnegs (sim_cpu *cpu)
7134 unsigned sn = uimm (aarch64_get_instr (cpu), 9, 5);
7135 unsigned sd = uimm (aarch64_get_instr (cpu), 4, 0);
7137 aarch64_set_FP_float (cpu, sd, - aarch64_get_FP_float (cpu, sn));
7140 /* Double negative value. */
7142 fnegd (sim_cpu *cpu)
7144 unsigned sn = uimm (aarch64_get_instr (cpu), 9, 5);
7145 unsigned sd = uimm (aarch64_get_instr (cpu), 4, 0);
7147 aarch64_set_FP_double (cpu, sd, - aarch64_get_FP_double (cpu, sn));
7150 /* Float square root. */
7152 fsqrts (sim_cpu *cpu)
7154 unsigned sn = uimm (aarch64_get_instr (cpu), 9, 5);
7155 unsigned sd = uimm (aarch64_get_instr (cpu), 4, 0);
7157 aarch64_set_FP_float (cpu, sd, sqrt (aarch64_get_FP_float (cpu, sn)));
7160 /* Double square root. */
7162 fsqrtd (sim_cpu *cpu)
7164 unsigned sn = uimm (aarch64_get_instr (cpu), 9, 5);
7165 unsigned sd = uimm (aarch64_get_instr (cpu), 4, 0);
7167 aarch64_set_FP_double (cpu, sd,
7168 sqrt (aarch64_get_FP_double (cpu, sn)));
7171 /* Convert double to float. */
7173 fcvtds (sim_cpu *cpu)
7175 unsigned sn = uimm (aarch64_get_instr (cpu), 9, 5);
7176 unsigned sd = uimm (aarch64_get_instr (cpu), 4, 0);
7178 aarch64_set_FP_float (cpu, sd, (float) aarch64_get_FP_double (cpu, sn));
7181 /* Convert float to double. */
7183 fcvtcpu (sim_cpu *cpu)
7185 unsigned sn = uimm (aarch64_get_instr (cpu), 9, 5);
7186 unsigned sd = uimm (aarch64_get_instr (cpu), 4, 0);
7188 aarch64_set_FP_double (cpu, sd, (double) aarch64_get_FP_float (cpu, sn));
7192 do_FRINT (sim_cpu *cpu)
7194 /* instr[31,23] = 0001 1110 0
7195 instr[22] = single(0)/double(1)
7197 instr[17,15] = rounding mode
7198 instr[14,10] = 10000
7200 instr[4,0] = dest */
7203 unsigned rs = uimm (aarch64_get_instr (cpu), 9, 5);
7204 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
7205 unsigned int rmode = uimm (aarch64_get_instr (cpu), 17, 15);
7207 NYI_assert (31, 23, 0x03C);
7208 NYI_assert (21, 18, 0x9);
7209 NYI_assert (14, 10, 0x10);
7211 if (rmode == 6 || rmode == 7)
7212 /* FIXME: Add support for rmode == 6 exactness check. */
7213 rmode = uimm (aarch64_get_FPSR (cpu), 23, 22);
7215 if (uimm (aarch64_get_instr (cpu), 22, 22))
7217 double val = aarch64_get_FP_double (cpu, rs);
7221 case 0: /* mode N: nearest or even. */
7223 double rval = round (val);
7225 if (val - rval == 0.5)
7227 if (((rval / 2.0) * 2.0) != rval)
7231 aarch64_set_FP_double (cpu, rd, round (val));
7235 case 1: /* mode P: towards +inf. */
7237 aarch64_set_FP_double (cpu, rd, trunc (val));
7239 aarch64_set_FP_double (cpu, rd, round (val));
7242 case 2: /* mode M: towards -inf. */
7244 aarch64_set_FP_double (cpu, rd, round (val));
7246 aarch64_set_FP_double (cpu, rd, trunc (val));
7249 case 3: /* mode Z: towards 0. */
7250 aarch64_set_FP_double (cpu, rd, trunc (val));
7253 case 4: /* mode A: away from 0. */
7254 aarch64_set_FP_double (cpu, rd, round (val));
7257 case 6: /* mode X: use FPCR with exactness check. */
7258 case 7: /* mode I: use FPCR mode. */
7266 val = aarch64_get_FP_float (cpu, rs);
7270 case 0: /* mode N: nearest or even. */
7272 float rval = roundf (val);
7274 if (val - rval == 0.5)
7276 if (((rval / 2.0) * 2.0) != rval)
7280 aarch64_set_FP_float (cpu, rd, rval);
7284 case 1: /* mode P: towards +inf. */
7286 aarch64_set_FP_float (cpu, rd, truncf (val));
7288 aarch64_set_FP_float (cpu, rd, roundf (val));
7291 case 2: /* mode M: towards -inf. */
7293 aarch64_set_FP_float (cpu, rd, truncf (val));
7295 aarch64_set_FP_float (cpu, rd, roundf (val));
7298 case 3: /* mode Z: towards 0. */
7299 aarch64_set_FP_float (cpu, rd, truncf (val));
7302 case 4: /* mode A: away from 0. */
7303 aarch64_set_FP_float (cpu, rd, roundf (val));
7306 case 6: /* mode X: use FPCR with exactness check. */
7307 case 7: /* mode I: use FPCR mode. */
7316 dexSimpleFPDataProc1Source (sim_cpu *cpu)
7318 /* instr[31] ==> M : 0 ==> OK, 1 ==> UNALLOC
7320 instr[29] ==> S : 0 ==> OK, 1 ==> UNALLOC
7323 instr[23,22] ==> type : 00 ==> source is single,
7324 01 ==> source is double
7326 11 ==> UNALLOC or source is half
7328 instr[20,15] ==> opcode : with type 00 or 01
7329 000000 ==> FMOV, 000001 ==> FABS,
7330 000010 ==> FNEG, 000011 ==> FSQRT,
7331 000100 ==> UNALLOC, 000101 ==> FCVT,(to single/double)
7332 000110 ==> UNALLOC, 000111 ==> FCVT (to half)
7333 001000 ==> FRINTN, 001001 ==> FRINTP,
7334 001010 ==> FRINTM, 001011 ==> FRINTZ,
7335 001100 ==> FRINTA, 001101 ==> UNALLOC
7336 001110 ==> FRINTX, 001111 ==> FRINTI
7338 000100 ==> FCVT (half-to-single)
7339 000101 ==> FCVT (half-to-double)
7340 instr[14,10] = 10000. */
7342 uint32_t M_S = (uimm (aarch64_get_instr (cpu), 31, 31) << 1)
7343 | uimm (aarch64_get_instr (cpu), 29, 29);
7344 uint32_t type = uimm (aarch64_get_instr (cpu), 23, 22);
7345 uint32_t opcode = uimm (aarch64_get_instr (cpu), 20, 15);
7352 if (opcode == 4 || opcode == 5)
7404 case 8: /* FRINTN etc. */
7414 case 7: /* FCVT double/single to half precision. */
7423 /* 32 bit signed int to float. */
7425 scvtf32 (sim_cpu *cpu)
7427 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
7428 unsigned sd = uimm (aarch64_get_instr (cpu), 4, 0);
7430 aarch64_set_FP_float
7431 (cpu, sd, (float) aarch64_get_reg_s32 (cpu, rn, NO_SP));
7434 /* signed int to float. */
7436 scvtf (sim_cpu *cpu)
7438 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
7439 unsigned sd = uimm (aarch64_get_instr (cpu), 4, 0);
7441 aarch64_set_FP_float
7442 (cpu, sd, (float) aarch64_get_reg_s64 (cpu, rn, NO_SP));
7445 /* 32 bit signed int to double. */
7447 scvtd32 (sim_cpu *cpu)
7449 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
7450 unsigned sd = uimm (aarch64_get_instr (cpu), 4, 0);
7452 aarch64_set_FP_double
7453 (cpu, sd, (double) aarch64_get_reg_s32 (cpu, rn, NO_SP));
7456 /* signed int to double. */
7458 scvtd (sim_cpu *cpu)
7460 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
7461 unsigned sd = uimm (aarch64_get_instr (cpu), 4, 0);
7463 aarch64_set_FP_double
7464 (cpu, sd, (double) aarch64_get_reg_s64 (cpu, rn, NO_SP));
7467 static const float FLOAT_INT_MAX = (float) INT_MAX;
7468 static const float FLOAT_INT_MIN = (float) INT_MIN;
7469 static const double DOUBLE_INT_MAX = (double) INT_MAX;
7470 static const double DOUBLE_INT_MIN = (double) INT_MIN;
7471 static const float FLOAT_LONG_MAX = (float) LONG_MAX;
7472 static const float FLOAT_LONG_MIN = (float) LONG_MIN;
7473 static const double DOUBLE_LONG_MAX = (double) LONG_MAX;
7474 static const double DOUBLE_LONG_MIN = (double) LONG_MIN;
7476 /* Check for FP exception conditions:
7479 Out of Range raises IO and IX and saturates value
7480 Denormal raises ID and IX and sets to zero. */
7481 #define RAISE_EXCEPTIONS(F, VALUE, FTYPE, ITYPE) \
7484 switch (fpclassify (F)) \
7488 aarch64_set_FPSR (cpu, IO); \
7490 VALUE = ITYPE##_MAX; \
7492 VALUE = ITYPE##_MIN; \
7496 if (F >= FTYPE##_##ITYPE##_MAX) \
7498 aarch64_set_FPSR_bits (cpu, IO | IX, IO | IX); \
7499 VALUE = ITYPE##_MAX; \
7501 else if (F <= FTYPE##_##ITYPE##_MIN) \
7503 aarch64_set_FPSR_bits (cpu, IO | IX, IO | IX); \
7504 VALUE = ITYPE##_MIN; \
7508 case FP_SUBNORMAL: \
7509 aarch64_set_FPSR_bits (cpu, IO | IX | ID, IX | ID); \
7521 /* 32 bit convert float to signed int truncate towards zero. */
7523 fcvtszs32 (sim_cpu *cpu)
7525 unsigned sn = uimm (aarch64_get_instr (cpu), 9, 5);
7526 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
7527 /* TODO : check that this rounds toward zero. */
7528 float f = aarch64_get_FP_float (cpu, sn);
7529 int32_t value = (int32_t) f;
7531 RAISE_EXCEPTIONS (f, value, FLOAT, INT);
7533 /* Avoid sign extension to 64 bit. */
7534 aarch64_set_reg_u64 (cpu, rd, NO_SP, (uint32_t) value);
7537 /* 64 bit convert float to signed int truncate towards zero. */
7539 fcvtszs (sim_cpu *cpu)
7541 unsigned sn = uimm (aarch64_get_instr (cpu), 9, 5);
7542 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
7543 float f = aarch64_get_FP_float (cpu, sn);
7544 int64_t value = (int64_t) f;
7546 RAISE_EXCEPTIONS (f, value, FLOAT, LONG);
7548 aarch64_set_reg_s64 (cpu, rd, NO_SP, value);
7551 /* 32 bit convert double to signed int truncate towards zero. */
7553 fcvtszd32 (sim_cpu *cpu)
7555 unsigned sn = uimm (aarch64_get_instr (cpu), 9, 5);
7556 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
7557 /* TODO : check that this rounds toward zero. */
7558 double d = aarch64_get_FP_double (cpu, sn);
7559 int32_t value = (int32_t) d;
7561 RAISE_EXCEPTIONS (d, value, DOUBLE, INT);
7563 /* Avoid sign extension to 64 bit. */
7564 aarch64_set_reg_u64 (cpu, rd, NO_SP, (uint32_t) value);
7567 /* 64 bit convert double to signed int truncate towards zero. */
7569 fcvtszd (sim_cpu *cpu)
7571 unsigned sn = uimm (aarch64_get_instr (cpu), 9, 5);
7572 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
7573 /* TODO : check that this rounds toward zero. */
7574 double d = aarch64_get_FP_double (cpu, sn);
7577 value = (int64_t) d;
7579 RAISE_EXCEPTIONS (d, value, DOUBLE, LONG);
7581 aarch64_set_reg_s64 (cpu, rd, NO_SP, value);
7585 do_fcvtzu (sim_cpu *cpu)
7587 /* instr[31] = size: 32-bit (0), 64-bit (1)
7588 instr[30,23] = 00111100
7589 instr[22] = type: single (0)/ double (1)
7590 instr[21] = enable (0)/disable(1) precision
7591 instr[20,16] = 11001
7592 instr[15,10] = precision
7596 unsigned rs = uimm (aarch64_get_instr (cpu), 9, 5);
7597 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
7599 NYI_assert (30, 23, 0x3C);
7600 NYI_assert (20, 16, 0x19);
7602 if (uimm (aarch64_get_instr (cpu), 21, 21) != 1)
7603 /* Convert to fixed point. */
7606 if (uimm (aarch64_get_instr (cpu), 31, 31))
7608 /* Convert to unsigned 64-bit integer. */
7609 if (uimm (aarch64_get_instr (cpu), 22, 22))
7611 double d = aarch64_get_FP_double (cpu, rs);
7612 uint64_t value = (uint64_t) d;
7614 /* Do not raise an exception if we have reached ULONG_MAX. */
7615 if (value != (1UL << 63))
7616 RAISE_EXCEPTIONS (d, value, DOUBLE, LONG);
7618 aarch64_set_reg_u64 (cpu, rd, NO_SP, value);
7622 float f = aarch64_get_FP_float (cpu, rs);
7623 uint64_t value = (uint64_t) f;
7625 /* Do not raise an exception if we have reached ULONG_MAX. */
7626 if (value != (1UL << 63))
7627 RAISE_EXCEPTIONS (f, value, FLOAT, LONG);
7629 aarch64_set_reg_u64 (cpu, rd, NO_SP, value);
7636 /* Convert to unsigned 32-bit integer. */
7637 if (uimm (aarch64_get_instr (cpu), 22, 22))
7639 double d = aarch64_get_FP_double (cpu, rs);
7641 value = (uint32_t) d;
7642 /* Do not raise an exception if we have reached UINT_MAX. */
7643 if (value != (1UL << 31))
7644 RAISE_EXCEPTIONS (d, value, DOUBLE, INT);
7648 float f = aarch64_get_FP_float (cpu, rs);
7650 value = (uint32_t) f;
7651 /* Do not raise an exception if we have reached UINT_MAX. */
7652 if (value != (1UL << 31))
7653 RAISE_EXCEPTIONS (f, value, FLOAT, INT);
7656 aarch64_set_reg_u64 (cpu, rd, NO_SP, value);
7661 do_UCVTF (sim_cpu *cpu)
7663 /* instr[31] = size: 32-bit (0), 64-bit (1)
7664 instr[30,23] = 001 1110 0
7665 instr[22] = type: single (0)/ double (1)
7666 instr[21] = enable (0)/disable(1) precision
7667 instr[20,16] = 0 0011
7668 instr[15,10] = precision
7672 unsigned rs = uimm (aarch64_get_instr (cpu), 9, 5);
7673 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
7675 NYI_assert (30, 23, 0x3C);
7676 NYI_assert (20, 16, 0x03);
7678 if (uimm (aarch64_get_instr (cpu), 21, 21) != 1)
7681 /* FIXME: Add exception raising. */
7682 if (uimm (aarch64_get_instr (cpu), 31, 31))
7684 uint64_t value = aarch64_get_reg_u64 (cpu, rs, NO_SP);
7686 if (uimm (aarch64_get_instr (cpu), 22, 22))
7687 aarch64_set_FP_double (cpu, rd, (double) value);
7689 aarch64_set_FP_float (cpu, rd, (float) value);
7693 uint32_t value = aarch64_get_reg_u32 (cpu, rs, NO_SP);
7695 if (uimm (aarch64_get_instr (cpu), 22, 22))
7696 aarch64_set_FP_double (cpu, rd, (double) value);
7698 aarch64_set_FP_float (cpu, rd, (float) value);
7703 float_vector_move (sim_cpu *cpu)
7705 /* instr[31,17] == 100 1111 0101 0111
7706 instr[16] ==> direction 0=> to GR, 1=> from GR
7708 instr[9,5] ==> source
7709 instr[4,0] ==> dest. */
7711 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
7712 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
7714 NYI_assert (31, 17, 0x4F57);
7716 if (uimm (aarch64_get_instr (cpu), 15, 10) != 0)
7719 if (uimm (aarch64_get_instr (cpu), 16, 16))
7720 aarch64_set_vec_u64 (cpu, rd, 1, aarch64_get_reg_u64 (cpu, rn, NO_SP));
7722 aarch64_set_reg_u64 (cpu, rd, NO_SP, aarch64_get_vec_u64 (cpu, rn, 1));
7726 dexSimpleFPIntegerConvert (sim_cpu *cpu)
7728 /* instr[31] = size : 0 ==> 32 bit, 1 ==> 64 bit
7730 instr[29] = S : 0 ==> OK, 1 ==> UNALLOC
7733 instr[23,22] = type : 00 ==> single, 01 ==> double, 1x ==> UNALLOC
7735 instr[20,19] = rmode
7736 instr[18,16] = opcode
7737 instr[15,10] = 10 0000 */
7739 uint32_t rmode_opcode;
7745 if (uimm (aarch64_get_instr (cpu), 31, 17) == 0x4F57)
7747 float_vector_move (cpu);
7751 size = uimm (aarch64_get_instr (cpu), 31, 31);
7752 S = uimm (aarch64_get_instr (cpu), 29, 29);
7756 type = uimm (aarch64_get_instr (cpu), 23, 22);
7760 rmode_opcode = uimm (aarch64_get_instr (cpu), 20, 16);
7761 size_type = (size << 1) | type; /* 0==32f, 1==32d, 2==64f, 3==64d. */
7763 switch (rmode_opcode)
7765 case 2: /* SCVTF. */
7768 case 0: scvtf32 (cpu); return;
7769 case 1: scvtd32 (cpu); return;
7770 case 2: scvtf (cpu); return;
7771 case 3: scvtd (cpu); return;
7776 case 6: /* FMOV GR, Vec. */
7779 case 0: gfmovs (cpu); return;
7780 case 3: gfmovd (cpu); return;
7781 default: HALT_UNALLOC;
7784 case 7: /* FMOV vec, GR. */
7787 case 0: fgmovs (cpu); return;
7788 case 3: fgmovd (cpu); return;
7789 default: HALT_UNALLOC;
7792 case 24: /* FCVTZS. */
7795 case 0: fcvtszs32 (cpu); return;
7796 case 1: fcvtszd32 (cpu); return;
7797 case 2: fcvtszs (cpu); return;
7798 case 3: fcvtszd (cpu); return;
7799 default: HALT_UNREACHABLE;
7802 case 25: do_fcvtzu (cpu); return;
7803 case 3: do_UCVTF (cpu); return;
7805 case 0: /* FCVTNS. */
7806 case 1: /* FCVTNU. */
7807 case 4: /* FCVTAS. */
7808 case 5: /* FCVTAU. */
7809 case 8: /* FCVPTS. */
7810 case 9: /* FCVTPU. */
7811 case 16: /* FCVTMS. */
7812 case 17: /* FCVTMU. */
7819 set_flags_for_float_compare (sim_cpu *cpu, float fvalue1, float fvalue2)
7823 if (isnan (fvalue1) || isnan (fvalue2))
7827 float result = fvalue1 - fvalue2;
7831 else if (result < 0)
7833 else /* (result > 0). */
7837 aarch64_set_CPSR (cpu, flags);
7841 fcmps (sim_cpu *cpu)
7843 unsigned sm = uimm (aarch64_get_instr (cpu), 20, 16);
7844 unsigned sn = uimm (aarch64_get_instr (cpu), 9, 5);
7846 float fvalue1 = aarch64_get_FP_float (cpu, sn);
7847 float fvalue2 = aarch64_get_FP_float (cpu, sm);
7849 set_flags_for_float_compare (cpu, fvalue1, fvalue2);
7852 /* Float compare to zero -- Invalid Operation exception
7853 only on signaling NaNs. */
7855 fcmpzs (sim_cpu *cpu)
7857 unsigned sn = uimm (aarch64_get_instr (cpu), 9, 5);
7858 float fvalue1 = aarch64_get_FP_float (cpu, sn);
7860 set_flags_for_float_compare (cpu, fvalue1, 0.0f);
7863 /* Float compare -- Invalid Operation exception on all NaNs. */
7865 fcmpes (sim_cpu *cpu)
7867 unsigned sm = uimm (aarch64_get_instr (cpu), 20, 16);
7868 unsigned sn = uimm (aarch64_get_instr (cpu), 9, 5);
7870 float fvalue1 = aarch64_get_FP_float (cpu, sn);
7871 float fvalue2 = aarch64_get_FP_float (cpu, sm);
7873 set_flags_for_float_compare (cpu, fvalue1, fvalue2);
7876 /* Float compare to zero -- Invalid Operation exception on all NaNs. */
7878 fcmpzes (sim_cpu *cpu)
7880 unsigned sn = uimm (aarch64_get_instr (cpu), 9, 5);
7881 float fvalue1 = aarch64_get_FP_float (cpu, sn);
7883 set_flags_for_float_compare (cpu, fvalue1, 0.0f);
7887 set_flags_for_double_compare (sim_cpu *cpu, double dval1, double dval2)
7891 if (isnan (dval1) || isnan (dval2))
7895 double result = dval1 - dval2;
7899 else if (result < 0)
7901 else /* (result > 0). */
7905 aarch64_set_CPSR (cpu, flags);
7908 /* Double compare -- Invalid Operation exception only on signaling NaNs. */
7910 fcmpd (sim_cpu *cpu)
7912 unsigned sm = uimm (aarch64_get_instr (cpu), 20, 16);
7913 unsigned sn = uimm (aarch64_get_instr (cpu), 9, 5);
7915 double dvalue1 = aarch64_get_FP_double (cpu, sn);
7916 double dvalue2 = aarch64_get_FP_double (cpu, sm);
7918 set_flags_for_double_compare (cpu, dvalue1, dvalue2);
7921 /* Double compare to zero -- Invalid Operation exception
7922 only on signaling NaNs. */
7924 fcmpzd (sim_cpu *cpu)
7926 unsigned sn = uimm (aarch64_get_instr (cpu), 9, 5);
7927 double dvalue1 = aarch64_get_FP_double (cpu, sn);
7929 set_flags_for_double_compare (cpu, dvalue1, 0.0);
7932 /* Double compare -- Invalid Operation exception on all NaNs. */
7934 fcmped (sim_cpu *cpu)
7936 unsigned sm = uimm (aarch64_get_instr (cpu), 20, 16);
7937 unsigned sn = uimm (aarch64_get_instr (cpu), 9, 5);
7939 double dvalue1 = aarch64_get_FP_double (cpu, sn);
7940 double dvalue2 = aarch64_get_FP_double (cpu, sm);
7942 set_flags_for_double_compare (cpu, dvalue1, dvalue2);
7945 /* Double compare to zero -- Invalid Operation exception on all NaNs. */
7947 fcmpzed (sim_cpu *cpu)
7949 unsigned sn = uimm (aarch64_get_instr (cpu), 9, 5);
7950 double dvalue1 = aarch64_get_FP_double (cpu, sn);
7952 set_flags_for_double_compare (cpu, dvalue1, 0.0);
7956 dexSimpleFPCompare (sim_cpu *cpu)
7958 /* assert instr[28,25] == 1111
7959 instr[30:24:21:13,10] = 0011000
7960 instr[31] = M : 0 ==> OK, 1 ==> UNALLOC
7961 instr[29] ==> S : 0 ==> OK, 1 ==> UNALLOC
7962 instr[23,22] ==> type : 0 ==> single, 01 ==> double, 1x ==> UNALLOC
7963 instr[15,14] ==> op : 00 ==> OK, ow ==> UNALLOC
7964 instr[4,0] ==> opcode2 : 00000 ==> FCMP, 10000 ==> FCMPE,
7965 01000 ==> FCMPZ, 11000 ==> FCMPEZ,
7968 uint32_t M_S = (uimm (aarch64_get_instr (cpu), 31, 31) << 1)
7969 | uimm (aarch64_get_instr (cpu), 29, 29);
7970 uint32_t type = uimm (aarch64_get_instr (cpu), 23, 22);
7971 uint32_t op = uimm (aarch64_get_instr (cpu), 15, 14);
7972 uint32_t op2_2_0 = uimm (aarch64_get_instr (cpu), 2, 0);
7986 /* dispatch on type and top 2 bits of opcode. */
7987 dispatch = (type << 2) | uimm (aarch64_get_instr (cpu), 4, 3);
7991 case 0: fcmps (cpu); return;
7992 case 1: fcmpzs (cpu); return;
7993 case 2: fcmpes (cpu); return;
7994 case 3: fcmpzes (cpu); return;
7995 case 4: fcmpd (cpu); return;
7996 case 5: fcmpzd (cpu); return;
7997 case 6: fcmped (cpu); return;
7998 case 7: fcmpzed (cpu); return;
7999 default: HALT_UNREACHABLE;
8004 do_scalar_FADDP (sim_cpu *cpu)
8006 /* instr [31,23] = 011111100
8007 instr [22] = single(0)/double(1)
8008 instr [21,10] = 1100 0011 0110
8010 instr [4,0] = Fd. */
8012 unsigned Fn = uimm (aarch64_get_instr (cpu), 9, 5);
8013 unsigned Fd = uimm (aarch64_get_instr (cpu), 4, 0);
8015 NYI_assert (31, 23, 0x0FC);
8016 NYI_assert (21, 10, 0xC36);
8018 if (uimm (aarch64_get_instr (cpu), 22, 22))
8020 double val1 = aarch64_get_vec_double (cpu, Fn, 0);
8021 double val2 = aarch64_get_vec_double (cpu, Fn, 1);
8023 aarch64_set_FP_double (cpu, Fd, val1 + val2);
8027 float val1 = aarch64_get_vec_float (cpu, Fn, 0);
8028 float val2 = aarch64_get_vec_float (cpu, Fn, 1);
8030 aarch64_set_FP_float (cpu, Fd, val1 + val2);
8034 /* Floating point absolute difference. */
8037 do_scalar_FABD (sim_cpu *cpu)
8039 /* instr [31,23] = 0111 1110 1
8040 instr [22] = float(0)/double(1)
8043 instr [15,10] = 1101 01
8045 instr [4, 0] = Rd. */
8047 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
8048 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
8049 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
8051 NYI_assert (31, 23, 0x0FD);
8052 NYI_assert (21, 21, 1);
8053 NYI_assert (15, 10, 0x35);
8055 if (uimm (aarch64_get_instr (cpu), 22, 22))
8056 aarch64_set_FP_double (cpu, rd,
8057 fabs (aarch64_get_FP_double (cpu, rn)
8058 - aarch64_get_FP_double (cpu, rm)));
8060 aarch64_set_FP_float (cpu, rd,
8061 fabsf (aarch64_get_FP_float (cpu, rn)
8062 - aarch64_get_FP_float (cpu, rm)));
8066 do_scalar_CMGT (sim_cpu *cpu)
8068 /* instr [31,21] = 0101 1110 111
8070 instr [15,10] = 00 1101
8072 instr [4, 0] = Rd. */
8074 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
8075 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
8076 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
8078 NYI_assert (31, 21, 0x2F7);
8079 NYI_assert (15, 10, 0x0D);
8081 aarch64_set_vec_u64 (cpu, rd, 0,
8082 aarch64_get_vec_u64 (cpu, rn, 0) >
8083 aarch64_get_vec_u64 (cpu, rm, 0) ? -1L : 0L);
8087 do_scalar_USHR (sim_cpu *cpu)
8089 /* instr [31,23] = 0111 1111 0
8090 instr [22,16] = shift amount
8091 instr [15,10] = 0000 01
8093 instr [4, 0] = Rd. */
8095 unsigned amount = 128 - uimm (aarch64_get_instr (cpu), 22, 16);
8096 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
8097 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
8099 NYI_assert (31, 23, 0x0FE);
8100 NYI_assert (15, 10, 0x01);
8102 aarch64_set_vec_u64 (cpu, rd, 0,
8103 aarch64_get_vec_u64 (cpu, rn, 0) >> amount);
8107 do_scalar_SHL (sim_cpu *cpu)
8109 /* instr [31,23] = 0111 1101 0
8110 instr [22,16] = shift amount
8111 instr [15,10] = 0101 01
8113 instr [4, 0] = Rd. */
8115 unsigned amount = uimm (aarch64_get_instr (cpu), 22, 16) - 64;
8116 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
8117 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
8119 NYI_assert (31, 23, 0x0BE);
8120 NYI_assert (15, 10, 0x15);
8122 if (uimm (aarch64_get_instr (cpu), 22, 22) == 0)
8125 aarch64_set_vec_u64 (cpu, rd, 0,
8126 aarch64_get_vec_u64 (cpu, rn, 0) << amount);
8129 /* FCMEQ FCMGT FCMGE. */
8131 do_scalar_FCM (sim_cpu *cpu)
8133 /* instr [31,30] = 01
8135 instr [28,24] = 1 1110
8140 instr [15,12] = 1110
8144 instr [4, 0] = Rd. */
8146 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
8147 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
8148 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
8149 unsigned EUac = (uimm (aarch64_get_instr (cpu), 23, 23) << 2)
8150 | (uimm (aarch64_get_instr (cpu), 29, 29) << 1)
8151 | uimm (aarch64_get_instr (cpu), 11, 11);
8156 NYI_assert (31, 30, 1);
8157 NYI_assert (28, 24, 0x1E);
8158 NYI_assert (21, 21, 1);
8159 NYI_assert (15, 12, 0xE);
8160 NYI_assert (10, 10, 1);
8162 if (uimm (aarch64_get_instr (cpu), 22, 22))
8164 double val1 = aarch64_get_FP_double (cpu, rn);
8165 double val2 = aarch64_get_FP_double (cpu, rm);
8170 result = val1 == val2;
8178 result = val1 >= val2;
8186 result = val1 > val2;
8193 aarch64_set_vec_u32 (cpu, rd, 0, result ? -1 : 0);
8197 val1 = aarch64_get_FP_float (cpu, rn);
8198 val2 = aarch64_get_FP_float (cpu, rm);
8203 result = val1 == val2;
8207 val1 = fabsf (val1);
8208 val2 = fabsf (val2);
8211 result = val1 >= val2;
8215 val1 = fabsf (val1);
8216 val2 = fabsf (val2);
8219 result = val1 > val2;
8226 aarch64_set_vec_u32 (cpu, rd, 0, result ? -1 : 0);
8229 /* An alias of DUP. */
8231 do_scalar_MOV (sim_cpu *cpu)
8233 /* instr [31,21] = 0101 1110 000
8234 instr [20,16] = imm5
8235 instr [15,10] = 0000 01
8237 instr [4, 0] = Rd. */
8239 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
8240 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
8243 NYI_assert (31, 21, 0x2F0);
8244 NYI_assert (15, 10, 0x01);
8246 if (uimm (aarch64_get_instr (cpu), 16, 16))
8249 index = uimm (aarch64_get_instr (cpu), 20, 17);
8251 (cpu, rd, 0, aarch64_get_vec_u8 (cpu, rn, index));
8253 else if (uimm (aarch64_get_instr (cpu), 17, 17))
8256 index = uimm (aarch64_get_instr (cpu), 20, 18);
8258 (cpu, rd, 0, aarch64_get_vec_u16 (cpu, rn, index));
8260 else if (uimm (aarch64_get_instr (cpu), 18, 18))
8263 index = uimm (aarch64_get_instr (cpu), 20, 19);
8265 (cpu, rd, 0, aarch64_get_vec_u32 (cpu, rn, index));
8267 else if (uimm (aarch64_get_instr (cpu), 19, 19))
8270 index = uimm (aarch64_get_instr (cpu), 20, 20);
8272 (cpu, rd, 0, aarch64_get_vec_u64 (cpu, rn, index));
8279 do_scalar_NEG (sim_cpu *cpu)
8281 /* instr [31,24] = 0111 1110
8283 instr [21,10] = 1000 0010 1110
8285 instr [4, 0] = Rd. */
8287 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
8288 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
8290 NYI_assert (31, 24, 0x7E);
8291 NYI_assert (21, 10, 0x82E);
8292 NYI_assert (23, 22, 3);
8294 aarch64_set_vec_u64 (cpu, rd, 0, - aarch64_get_vec_u64 (cpu, rn, 0));
8298 do_double_add (sim_cpu *cpu)
8300 /* instr [28,25] = 1111. */
8307 switch (uimm (aarch64_get_instr (cpu), 31, 23))
8310 switch (uimm (aarch64_get_instr (cpu), 15, 10))
8312 case 0x01: do_scalar_MOV (cpu); return;
8313 case 0x39: do_scalar_FCM (cpu); return;
8314 case 0x3B: do_scalar_FCM (cpu); return;
8318 case 0xBE: do_scalar_SHL (cpu); return;
8321 switch (uimm (aarch64_get_instr (cpu), 15, 10))
8323 case 0x36: do_scalar_FADDP (cpu); return;
8324 case 0x39: do_scalar_FCM (cpu); return;
8325 case 0x3B: do_scalar_FCM (cpu); return;
8330 switch (uimm (aarch64_get_instr (cpu), 15, 10))
8332 case 0x0D: do_scalar_CMGT (cpu); return;
8333 case 0x35: do_scalar_FABD (cpu); return;
8334 case 0x39: do_scalar_FCM (cpu); return;
8335 case 0x3B: do_scalar_FCM (cpu); return;
8336 case 0x2E: do_scalar_NEG (cpu); return;
8341 case 0xFE: do_scalar_USHR (cpu); return;
8346 /* instr [31,21] = 0101 1110 111
8348 instr [15,10] = 1000 01
8350 instr [4,0] = Fd. */
8351 if (uimm (aarch64_get_instr (cpu), 31, 21) != 0x2F7
8352 || uimm (aarch64_get_instr (cpu), 15, 10) != 0x21)
8355 Fd = uimm (aarch64_get_instr (cpu), 4, 0);
8356 Fm = uimm (aarch64_get_instr (cpu), 9, 5);
8357 Fn = uimm (aarch64_get_instr (cpu), 20, 16);
8359 val1 = aarch64_get_FP_double (cpu, Fm);
8360 val2 = aarch64_get_FP_double (cpu, Fn);
8362 aarch64_set_FP_double (cpu, Fd, val1 + val2);
8366 dexAdvSIMD1 (sim_cpu *cpu)
8368 /* instr [28,25] = 1 111. */
8370 /* we are currently only interested in the basic
8371 scalar fp routines which all have bit 30 = 0. */
8372 if (uimm (aarch64_get_instr (cpu), 30, 30))
8373 do_double_add (cpu);
8375 /* instr[24] is set for FP data processing 3-source and clear for
8376 all other basic scalar fp instruction groups. */
8377 else if (uimm (aarch64_get_instr (cpu), 24, 24))
8378 dexSimpleFPDataProc3Source (cpu);
8380 /* instr[21] is clear for floating <-> fixed conversions and set for
8381 all other basic scalar fp instruction groups. */
8382 else if (!uimm (aarch64_get_instr (cpu), 21, 21))
8383 dexSimpleFPFixedConvert (cpu);
8385 /* instr[11,10] : 01 ==> cond compare, 10 ==> Data Proc 2 Source
8386 11 ==> cond select, 00 ==> other. */
8388 switch (uimm (aarch64_get_instr (cpu), 11, 10))
8390 case 1: dexSimpleFPCondCompare (cpu); return;
8391 case 2: dexSimpleFPDataProc2Source (cpu); return;
8392 case 3: dexSimpleFPCondSelect (cpu); return;
8395 /* Now an ordered cascade of tests.
8396 FP immediate has aarch64_get_instr (cpu)[12] == 1.
8397 FP compare has aarch64_get_instr (cpu)[13] == 1.
8398 FP Data Proc 1 Source has aarch64_get_instr (cpu)[14] == 1.
8399 FP floating <--> integer conversions has aarch64_get_instr (cpu)[15] == 0. */
8400 if (uimm (aarch64_get_instr (cpu), 12, 12))
8401 dexSimpleFPImmediate (cpu);
8403 else if (uimm (aarch64_get_instr (cpu), 13, 13))
8404 dexSimpleFPCompare (cpu);
8406 else if (uimm (aarch64_get_instr (cpu), 14, 14))
8407 dexSimpleFPDataProc1Source (cpu);
8409 else if (!uimm (aarch64_get_instr (cpu), 15, 15))
8410 dexSimpleFPIntegerConvert (cpu);
8413 /* If we get here then instr[15] == 1 which means UNALLOC. */
8418 /* PC relative addressing. */
8421 pcadr (sim_cpu *cpu)
8423 /* instr[31] = op : 0 ==> ADR, 1 ==> ADRP
8424 instr[30,29] = immlo
8425 instr[23,5] = immhi. */
8427 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
8428 uint32_t isPage = uimm (aarch64_get_instr (cpu), 31, 31);
8429 union { int64_t u64; uint64_t s64; } imm;
8432 imm.s64 = simm64 (aarch64_get_instr (cpu), 23, 5);
8434 offset = (offset << 2) | uimm (aarch64_get_instr (cpu), 30, 29);
8436 address = aarch64_get_PC (cpu);
8444 aarch64_set_reg_u64 (cpu, rd, NO_SP, address + offset);
8447 /* Specific decode and execute for group Data Processing Immediate. */
8450 dexPCRelAddressing (sim_cpu *cpu)
8452 /* assert instr[28,24] = 10000. */
8456 /* Immediate logical.
8457 The bimm32/64 argument is constructed by replicating a 2, 4, 8,
8458 16, 32 or 64 bit sequence pulled out at decode and possibly
8461 N.B. the output register (dest) can normally be Xn or SP
8462 the exception occurs for flag setting instructions which may
8463 only use Xn for the output (dest). The input register can
8466 /* 32 bit and immediate. */
8468 and32 (sim_cpu *cpu, uint32_t bimm)
8470 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
8471 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
8473 aarch64_set_reg_u64 (cpu, rd, SP_OK,
8474 aarch64_get_reg_u32 (cpu, rn, NO_SP) & bimm);
8477 /* 64 bit and immediate. */
8479 and64 (sim_cpu *cpu, uint64_t bimm)
8481 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
8482 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
8484 aarch64_set_reg_u64 (cpu, rd, SP_OK,
8485 aarch64_get_reg_u64 (cpu, rn, NO_SP) & bimm);
8488 /* 32 bit and immediate set flags. */
8490 ands32 (sim_cpu *cpu, uint32_t bimm)
8492 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
8493 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
8495 uint32_t value1 = aarch64_get_reg_u32 (cpu, rn, NO_SP);
8496 uint32_t value2 = bimm;
8498 aarch64_set_reg_u64 (cpu, rd, NO_SP, value1 & value2);
8499 set_flags_for_binop32 (cpu, value1 & value2);
8502 /* 64 bit and immediate set flags. */
8504 ands64 (sim_cpu *cpu, uint64_t bimm)
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 = bimm;
8512 aarch64_set_reg_u64 (cpu, rd, NO_SP, value1 & value2);
8513 set_flags_for_binop64 (cpu, value1 & value2);
8516 /* 32 bit exclusive or immediate. */
8518 eor32 (sim_cpu *cpu, uint32_t bimm)
8520 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
8521 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
8523 aarch64_set_reg_u64 (cpu, rd, SP_OK,
8524 aarch64_get_reg_u32 (cpu, rn, NO_SP) ^ bimm);
8527 /* 64 bit exclusive or immediate. */
8529 eor64 (sim_cpu *cpu, uint64_t bimm)
8531 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
8532 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
8534 aarch64_set_reg_u64 (cpu, rd, SP_OK,
8535 aarch64_get_reg_u64 (cpu, rn, NO_SP) ^ bimm);
8538 /* 32 bit or immediate. */
8540 orr32 (sim_cpu *cpu, uint32_t bimm)
8542 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
8543 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
8545 aarch64_set_reg_u64 (cpu, rd, SP_OK,
8546 aarch64_get_reg_u32 (cpu, rn, NO_SP) | bimm);
8549 /* 64 bit or immediate. */
8551 orr64 (sim_cpu *cpu, uint64_t bimm)
8553 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
8554 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
8556 aarch64_set_reg_u64 (cpu, rd, SP_OK,
8557 aarch64_get_reg_u64 (cpu, rn, NO_SP) | bimm);
8560 /* Logical shifted register.
8561 These allow an optional LSL, ASR, LSR or ROR to the second source
8562 register with a count up to the register bit count.
8563 N.B register args may not be SP. */
8565 /* 32 bit AND shifted register. */
8567 and32_shift (sim_cpu *cpu, Shift shift, uint32_t count)
8569 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
8570 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
8571 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
8574 (cpu, rd, NO_SP, aarch64_get_reg_u32 (cpu, rn, NO_SP)
8575 & shifted32 (aarch64_get_reg_u32 (cpu, rm, NO_SP), shift, count));
8578 /* 64 bit AND shifted register. */
8580 and64_shift (sim_cpu *cpu, Shift shift, uint32_t count)
8582 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
8583 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
8584 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
8587 (cpu, rd, NO_SP, aarch64_get_reg_u64 (cpu, rn, NO_SP)
8588 & shifted64 (aarch64_get_reg_u64 (cpu, rm, NO_SP), shift, count));
8591 /* 32 bit AND shifted register setting flags. */
8593 ands32_shift (sim_cpu *cpu, Shift shift, uint32_t count)
8595 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
8596 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
8597 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
8599 uint32_t value1 = aarch64_get_reg_u32 (cpu, rn, NO_SP);
8600 uint32_t value2 = shifted32 (aarch64_get_reg_u32 (cpu, rm, NO_SP),
8603 aarch64_set_reg_u64 (cpu, rd, NO_SP, value1 & value2);
8604 set_flags_for_binop32 (cpu, value1 & value2);
8607 /* 64 bit AND shifted register setting flags. */
8609 ands64_shift (sim_cpu *cpu, Shift shift, uint32_t count)
8611 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
8612 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
8613 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
8615 uint64_t value1 = aarch64_get_reg_u64 (cpu, rn, NO_SP);
8616 uint64_t value2 = shifted64 (aarch64_get_reg_u64 (cpu, rm, NO_SP),
8619 aarch64_set_reg_u64 (cpu, rd, NO_SP, value1 & value2);
8620 set_flags_for_binop64 (cpu, value1 & value2);
8623 /* 32 bit BIC shifted register. */
8625 bic32_shift (sim_cpu *cpu, Shift shift, uint32_t count)
8627 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
8628 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
8629 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
8632 (cpu, rd, NO_SP, aarch64_get_reg_u32 (cpu, rn, NO_SP)
8633 & ~ shifted32 (aarch64_get_reg_u32 (cpu, rm, NO_SP), shift, count));
8636 /* 64 bit BIC shifted register. */
8638 bic64_shift (sim_cpu *cpu, Shift shift, uint32_t count)
8640 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
8641 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
8642 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
8645 (cpu, rd, NO_SP, aarch64_get_reg_u64 (cpu, rn, NO_SP)
8646 & ~ shifted64 (aarch64_get_reg_u64 (cpu, rm, NO_SP), shift, count));
8649 /* 32 bit BIC shifted register setting flags. */
8651 bics32_shift (sim_cpu *cpu, Shift shift, uint32_t count)
8653 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
8654 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
8655 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
8657 uint32_t value1 = aarch64_get_reg_u32 (cpu, rn, NO_SP);
8658 uint32_t value2 = ~ shifted32 (aarch64_get_reg_u32 (cpu, rm, NO_SP),
8661 aarch64_set_reg_u64 (cpu, rd, NO_SP, value1 & value2);
8662 set_flags_for_binop32 (cpu, value1 & value2);
8665 /* 64 bit BIC shifted register setting flags. */
8667 bics64_shift (sim_cpu *cpu, Shift shift, uint32_t count)
8669 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
8670 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
8671 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
8673 uint64_t value1 = aarch64_get_reg_u64 (cpu, rn, NO_SP);
8674 uint64_t value2 = ~ shifted64 (aarch64_get_reg_u64 (cpu, rm, NO_SP),
8677 aarch64_set_reg_u64 (cpu, rd, NO_SP, value1 & value2);
8678 set_flags_for_binop64 (cpu, value1 & value2);
8681 /* 32 bit EON shifted register. */
8683 eon32_shift (sim_cpu *cpu, Shift shift, uint32_t count)
8685 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
8686 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
8687 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
8690 (cpu, rd, NO_SP, aarch64_get_reg_u32 (cpu, rn, NO_SP)
8691 ^ ~ shifted32 (aarch64_get_reg_u32 (cpu, rm, NO_SP), shift, count));
8694 /* 64 bit EON shifted register. */
8696 eon64_shift (sim_cpu *cpu, Shift shift, uint32_t count)
8698 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
8699 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
8700 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
8703 (cpu, rd, NO_SP, aarch64_get_reg_u64 (cpu, rn, NO_SP)
8704 ^ ~ shifted64 (aarch64_get_reg_u64 (cpu, rm, NO_SP), shift, count));
8707 /* 32 bit EOR shifted register. */
8709 eor32_shift (sim_cpu *cpu, Shift shift, uint32_t count)
8711 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
8712 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
8713 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
8716 (cpu, rd, NO_SP, aarch64_get_reg_u32 (cpu, rn, NO_SP)
8717 ^ shifted32 (aarch64_get_reg_u32 (cpu, rm, NO_SP), shift, count));
8720 /* 64 bit EOR shifted register. */
8722 eor64_shift (sim_cpu *cpu, Shift shift, uint32_t count)
8724 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
8725 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
8726 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
8729 (cpu, rd, NO_SP, aarch64_get_reg_u64 (cpu, rn, NO_SP)
8730 ^ shifted64 (aarch64_get_reg_u64 (cpu, rm, NO_SP), shift, count));
8733 /* 32 bit ORR shifted register. */
8735 orr32_shift (sim_cpu *cpu, Shift shift, uint32_t count)
8737 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
8738 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
8739 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
8742 (cpu, rd, NO_SP, aarch64_get_reg_u32 (cpu, rn, NO_SP)
8743 | shifted32 (aarch64_get_reg_u32 (cpu, rm, NO_SP), shift, count));
8746 /* 64 bit ORR shifted register. */
8748 orr64_shift (sim_cpu *cpu, Shift shift, uint32_t count)
8750 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
8751 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
8752 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
8755 (cpu, rd, NO_SP, aarch64_get_reg_u64 (cpu, rn, NO_SP)
8756 | shifted64 (aarch64_get_reg_u64 (cpu, rm, NO_SP), shift, count));
8759 /* 32 bit ORN shifted register. */
8761 orn32_shift (sim_cpu *cpu, Shift shift, uint32_t count)
8763 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
8764 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
8765 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
8768 (cpu, rd, NO_SP, aarch64_get_reg_u32 (cpu, rn, NO_SP)
8769 | ~ shifted32 (aarch64_get_reg_u32 (cpu, rm, NO_SP), shift, count));
8772 /* 64 bit ORN shifted register. */
8774 orn64_shift (sim_cpu *cpu, Shift shift, uint32_t count)
8776 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
8777 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
8778 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
8781 (cpu, rd, NO_SP, aarch64_get_reg_u64 (cpu, rn, NO_SP)
8782 | ~ shifted64 (aarch64_get_reg_u64 (cpu, rm, NO_SP), shift, count));
8786 dexLogicalImmediate (sim_cpu *cpu)
8788 /* assert instr[28,23] = 1001000
8789 instr[31] = size : 0 ==> 32 bit, 1 ==> 64 bit
8790 instr[30,29] = op : 0 ==> AND, 1 ==> ORR, 2 ==> EOR, 3 ==> ANDS
8791 instr[22] = N : used to construct immediate mask
8797 /* 32 bit operations must have N = 0 or else we have an UNALLOC. */
8798 uint32_t size = uimm (aarch64_get_instr (cpu), 31, 31);
8799 uint32_t N = uimm (aarch64_get_instr (cpu), 22, 22);
8800 /* uint32_t immr = uimm (aarch64_get_instr (cpu), 21, 16);. */
8801 /* uint32_t imms = uimm (aarch64_get_instr (cpu), 15, 10);. */
8802 uint32_t index = uimm (aarch64_get_instr (cpu), 22, 10);
8803 uint64_t bimm64 = LITable [index];
8804 uint32_t dispatch = uimm (aarch64_get_instr (cpu), 30, 29);
8814 uint32_t bimm = (uint32_t) bimm64;
8818 case 0: and32 (cpu, bimm); return;
8819 case 1: orr32 (cpu, bimm); return;
8820 case 2: eor32 (cpu, bimm); return;
8821 case 3: ands32 (cpu, bimm); return;
8828 case 0: and64 (cpu, bimm64); return;
8829 case 1: orr64 (cpu, bimm64); return;
8830 case 2: eor64 (cpu, bimm64); return;
8831 case 3: ands64 (cpu, bimm64); return;
8838 The uimm argument is a 16 bit value to be inserted into the
8839 target register the pos argument locates the 16 bit word in the
8840 dest register i.e. it is in {0, 1} for 32 bit and {0, 1, 2,
8842 N.B register arg may not be SP so it should be.
8843 accessed using the setGZRegisterXXX accessors. */
8845 /* 32 bit move 16 bit immediate zero remaining shorts. */
8847 movz32 (sim_cpu *cpu, uint32_t val, uint32_t pos)
8849 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
8851 aarch64_set_reg_u64 (cpu, rd, NO_SP, val << (pos * 16));
8854 /* 64 bit move 16 bit immediate zero remaining shorts. */
8856 movz64 (sim_cpu *cpu, uint32_t val, uint32_t pos)
8858 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
8860 aarch64_set_reg_u64 (cpu, rd, NO_SP, ((uint64_t) val) << (pos * 16));
8863 /* 32 bit move 16 bit immediate negated. */
8865 movn32 (sim_cpu *cpu, uint32_t val, uint32_t pos)
8867 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
8869 aarch64_set_reg_u64 (cpu, rd, NO_SP, ((val << (pos * 16)) ^ 0xffffffffU));
8872 /* 64 bit move 16 bit immediate negated. */
8874 movn64 (sim_cpu *cpu, uint32_t val, uint32_t pos)
8876 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
8879 (cpu, rd, NO_SP, ((((uint64_t) val) << (pos * 16))
8880 ^ 0xffffffffffffffffULL));
8883 /* 32 bit move 16 bit immediate keep remaining shorts. */
8885 movk32 (sim_cpu *cpu, uint32_t val, uint32_t pos)
8887 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
8888 uint32_t current = aarch64_get_reg_u32 (cpu, rd, NO_SP);
8889 uint32_t value = val << (pos * 16);
8890 uint32_t mask = ~(0xffffU << (pos * 16));
8892 aarch64_set_reg_u64 (cpu, rd, NO_SP, (value | (current & mask)));
8895 /* 64 bit move 16 it immediate keep remaining shorts. */
8897 movk64 (sim_cpu *cpu, uint32_t val, uint32_t pos)
8899 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
8900 uint64_t current = aarch64_get_reg_u64 (cpu, rd, NO_SP);
8901 uint64_t value = (uint64_t) val << (pos * 16);
8902 uint64_t mask = ~(0xffffULL << (pos * 16));
8904 aarch64_set_reg_u64 (cpu, rd, NO_SP, (value | (current & mask)));
8908 dexMoveWideImmediate (sim_cpu *cpu)
8910 /* assert instr[28:23] = 100101
8911 instr[31] = size : 0 ==> 32 bit, 1 ==> 64 bit
8912 instr[30,29] = op : 0 ==> MOVN, 1 ==> UNALLOC, 2 ==> MOVZ, 3 ==> MOVK
8913 instr[22,21] = shift : 00 == LSL#0, 01 = LSL#16, 10 = LSL#32, 11 = LSL#48
8914 instr[20,5] = uimm16
8917 /* N.B. the (multiple of 16) shift is applied by the called routine,
8918 we just pass the multiplier. */
8921 uint32_t size = uimm (aarch64_get_instr (cpu), 31, 31);
8922 uint32_t op = uimm (aarch64_get_instr (cpu), 30, 29);
8923 uint32_t shift = uimm (aarch64_get_instr (cpu), 22, 21);
8925 /* 32 bit can only shift 0 or 1 lot of 16.
8926 anything else is an unallocated instruction. */
8927 if (size == 0 && (shift > 1))
8933 imm = uimm (aarch64_get_instr (cpu), 20, 5);
8938 movn32 (cpu, imm, shift);
8940 movz32 (cpu, imm, shift);
8942 movk32 (cpu, imm, shift);
8947 movn64 (cpu, imm, shift);
8949 movz64 (cpu, imm, shift);
8951 movk64 (cpu, imm, shift);
8955 /* Bitfield operations.
8956 These take a pair of bit positions r and s which are in {0..31}
8957 or {0..63} depending on the instruction word size.
8958 N.B register args may not be SP. */
8960 /* OK, we start with ubfm which just needs to pick
8961 some bits out of source zero the rest and write
8962 the result to dest. Just need two logical shifts. */
8964 /* 32 bit bitfield move, left and right of affected zeroed
8965 if r <= s Wd<s-r:0> = Wn<s:r> else Wd<32+s-r,32-r> = Wn<s:0>. */
8967 ubfm32 (sim_cpu *cpu, uint32_t r, uint32_t s)
8970 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
8971 uint32_t value = aarch64_get_reg_u32 (cpu, rn, NO_SP);
8973 /* Pick either s+1-r or s+1 consecutive bits out of the original word. */
8976 /* 31:...:s:xxx:r:...:0 ==> 31:...:s-r:xxx:0.
8977 We want only bits s:xxx:r at the bottom of the word
8978 so we LSL bit s up to bit 31 i.e. by 31 - s
8979 and then we LSR to bring bit 31 down to bit s - r
8980 i.e. by 31 + r - s. */
8982 value >>= 31 + r - s;
8986 /* 31:...:s:xxx:0 ==> 31:...:31-(r-1)+s:xxx:31-(r-1):...:0
8987 We want only bits s:xxx:0 starting at it 31-(r-1)
8988 so we LSL bit s up to bit 31 i.e. by 31 - s
8989 and then we LSL to bring bit 31 down to 31-(r-1)+s
8990 i.e. by r - (s + 1). */
8992 value >>= r - (s + 1);
8995 rd = uimm (aarch64_get_instr (cpu), 4, 0);
8996 aarch64_set_reg_u64 (cpu, rd, NO_SP, value);
8999 /* 64 bit bitfield move, left and right of affected zeroed
9000 if r <= s Wd<s-r:0> = Wn<s:r> else Wd<64+s-r,64-r> = Wn<s:0>. */
9002 ubfm (sim_cpu *cpu, uint32_t r, uint32_t s)
9005 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
9006 uint64_t value = aarch64_get_reg_u64 (cpu, rn, NO_SP);
9010 /* 63:...:s:xxx:r:...:0 ==> 63:...:s-r:xxx:0.
9011 We want only bits s:xxx:r at the bottom of the word.
9012 So we LSL bit s up to bit 63 i.e. by 63 - s
9013 and then we LSR to bring bit 63 down to bit s - r
9014 i.e. by 63 + r - s. */
9016 value >>= 63 + r - s;
9020 /* 63:...:s:xxx:0 ==> 63:...:63-(r-1)+s:xxx:63-(r-1):...:0.
9021 We want only bits s:xxx:0 starting at it 63-(r-1).
9022 So we LSL bit s up to bit 63 i.e. by 63 - s
9023 and then we LSL to bring bit 63 down to 63-(r-1)+s
9024 i.e. by r - (s + 1). */
9026 value >>= r - (s + 1);
9029 rd = uimm (aarch64_get_instr (cpu), 4, 0);
9030 aarch64_set_reg_u64 (cpu, rd, NO_SP, value);
9033 /* The signed versions need to insert sign bits
9034 on the left of the inserted bit field. so we do
9035 much the same as the unsigned version except we
9036 use an arithmetic shift right -- this just means
9037 we need to operate on signed values. */
9039 /* 32 bit bitfield move, left of affected sign-extended, right zeroed. */
9040 /* If r <= s Wd<s-r:0> = Wn<s:r> else Wd<32+s-r,32-r> = Wn<s:0>. */
9042 sbfm32 (sim_cpu *cpu, uint32_t r, uint32_t s)
9045 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
9046 /* as per ubfm32 but use an ASR instead of an LSR. */
9047 int32_t value = aarch64_get_reg_s32 (cpu, rn, NO_SP);
9052 value >>= 31 + r - s;
9057 value >>= r - (s + 1);
9060 rd = uimm (aarch64_get_instr (cpu), 4, 0);
9061 aarch64_set_reg_u64 (cpu, rd, NO_SP, (uint32_t) value);
9064 /* 64 bit bitfield move, left of affected sign-extended, right zeroed. */
9065 /* If r <= s Wd<s-r:0> = Wn<s:r> else Wd<64+s-r,64-r> = Wn<s:0>. */
9067 sbfm (sim_cpu *cpu, uint32_t r, uint32_t s)
9070 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
9071 /* acpu per ubfm but use an ASR instead of an LSR. */
9072 int64_t value = aarch64_get_reg_s64 (cpu, rn, NO_SP);
9077 value >>= 63 + r - s;
9082 value >>= r - (s + 1);
9085 rd = uimm (aarch64_get_instr (cpu), 4, 0);
9086 aarch64_set_reg_s64 (cpu, rd, NO_SP, value);
9089 /* Finally, these versions leave non-affected bits
9090 as is. so we need to generate the bits as per
9091 ubfm and also generate a mask to pick the
9092 bits from the original and computed values. */
9094 /* 32 bit bitfield move, non-affected bits left as is.
9095 If r <= s Wd<s-r:0> = Wn<s:r> else Wd<32+s-r,32-r> = Wn<s:0>. */
9097 bfm32 (sim_cpu *cpu, uint32_t r, uint32_t s)
9099 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
9100 uint32_t value = aarch64_get_reg_u32 (cpu, rn, NO_SP);
9105 /* Pick either s+1-r or s+1 consecutive bits out of the original word. */
9108 /* 31:...:s:xxx:r:...:0 ==> 31:...:s-r:xxx:0.
9109 We want only bits s:xxx:r at the bottom of the word
9110 so we LSL bit s up to bit 31 i.e. by 31 - s
9111 and then we LSR to bring bit 31 down to bit s - r
9112 i.e. by 31 + r - s. */
9114 value >>= 31 + r - s;
9115 /* the mask must include the same bits. */
9117 mask >>= 31 + r - s;
9121 /* 31:...:s:xxx:0 ==> 31:...:31-(r-1)+s:xxx:31-(r-1):...:0.
9122 We want only bits s:xxx:0 starting at it 31-(r-1)
9123 so we LSL bit s up to bit 31 i.e. by 31 - s
9124 and then we LSL to bring bit 31 down to 31-(r-1)+s
9125 i.e. by r - (s + 1). */
9127 value >>= r - (s + 1);
9128 /* The mask must include the same bits. */
9130 mask >>= r - (s + 1);
9133 rd = uimm (aarch64_get_instr (cpu), 4, 0);
9134 value2 = aarch64_get_reg_u32 (cpu, rd, NO_SP);
9140 (cpu, rd, NO_SP, (aarch64_get_reg_u32 (cpu, rd, NO_SP) & ~mask) | value);
9143 /* 64 bit bitfield move, non-affected bits left as is.
9144 If r <= s Wd<s-r:0> = Wn<s:r> else Wd<64+s-r,64-r> = Wn<s:0>. */
9146 bfm (sim_cpu *cpu, uint32_t r, uint32_t s)
9149 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
9150 uint64_t value = aarch64_get_reg_u64 (cpu, rn, NO_SP);
9151 uint64_t mask = 0xffffffffffffffffULL;
9155 /* 63:...:s:xxx:r:...:0 ==> 63:...:s-r:xxx:0.
9156 We want only bits s:xxx:r at the bottom of the word
9157 so we LSL bit s up to bit 63 i.e. by 63 - s
9158 and then we LSR to bring bit 63 down to bit s - r
9159 i.e. by 63 + r - s. */
9161 value >>= 63 + r - s;
9162 /* The mask must include the same bits. */
9164 mask >>= 63 + r - s;
9168 /* 63:...:s:xxx:0 ==> 63:...:63-(r-1)+s:xxx:63-(r-1):...:0
9169 We want only bits s:xxx:0 starting at it 63-(r-1)
9170 so we LSL bit s up to bit 63 i.e. by 63 - s
9171 and then we LSL to bring bit 63 down to 63-(r-1)+s
9172 i.e. by r - (s + 1). */
9174 value >>= r - (s + 1);
9175 /* The mask must include the same bits. */
9177 mask >>= r - (s + 1);
9180 rd = uimm (aarch64_get_instr (cpu), 4, 0);
9182 (cpu, rd, NO_SP, (aarch64_get_reg_u64 (cpu, rd, NO_SP) & ~mask) | value);
9186 dexBitfieldImmediate (sim_cpu *cpu)
9188 /* assert instr[28:23] = 100110
9189 instr[31] = size : 0 ==> 32 bit, 1 ==> 64 bit
9190 instr[30,29] = op : 0 ==> SBFM, 1 ==> BFM, 2 ==> UBFM, 3 ==> UNALLOC
9191 instr[22] = N : must be 0 for 32 bit, 1 for 64 bit ow UNALLOC
9192 instr[21,16] = immr : 0xxxxx for 32 bit, xxxxxx for 64 bit
9193 instr[15,10] = imms : 0xxxxx for 32 bit, xxxxxx for 64 bit
9197 /* 32 bit operations must have N = 0 or else we have an UNALLOC. */
9200 uint32_t size = uimm (aarch64_get_instr (cpu), 31, 31);
9201 uint32_t N = uimm (aarch64_get_instr (cpu), 22, 22);
9202 /* 32 bit operations must have immr[5] = 0 and imms[5] = 0. */
9203 /* or else we have an UNALLOC. */
9204 uint32_t immr = uimm (aarch64_get_instr (cpu), 21, 16);
9209 if (!size && uimm (immr, 5, 5))
9212 imms = uimm (aarch64_get_instr (cpu), 15, 10);
9213 if (!size && uimm (imms, 5, 5))
9216 /* Switch on combined size and op. */
9217 dispatch = uimm (aarch64_get_instr (cpu), 31, 29);
9220 case 0: sbfm32 (cpu, immr, imms); return;
9221 case 1: bfm32 (cpu, immr, imms); return;
9222 case 2: ubfm32 (cpu, immr, imms); return;
9223 case 4: sbfm (cpu, immr, imms); return;
9224 case 5: bfm (cpu, immr, imms); return;
9225 case 6: ubfm (cpu, immr, imms); return;
9226 default: HALT_UNALLOC;
9231 do_EXTR_32 (sim_cpu *cpu)
9233 /* instr[31:21] = 00010011100
9235 instr[15,10] = imms : 0xxxxx for 32 bit
9238 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
9239 unsigned imms = uimm (aarch64_get_instr (cpu), 15, 10) & 31;
9240 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
9241 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
9245 val1 = aarch64_get_reg_u32 (cpu, rm, NO_SP);
9247 val2 = aarch64_get_reg_u32 (cpu, rn, NO_SP);
9248 val2 <<= (32 - imms);
9250 aarch64_set_reg_u64 (cpu, rd, NO_SP, val1 | val2);
9254 do_EXTR_64 (sim_cpu *cpu)
9256 /* instr[31:21] = 10010011100
9261 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
9262 unsigned imms = uimm (aarch64_get_instr (cpu), 15, 10) & 63;
9263 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
9264 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
9267 val = aarch64_get_reg_u64 (cpu, rm, NO_SP);
9269 val |= (aarch64_get_reg_u64 (cpu, rn, NO_SP) << (64 - imms));
9271 aarch64_set_reg_u64 (cpu, rd, NO_SP, val);
9275 dexExtractImmediate (sim_cpu *cpu)
9277 /* assert instr[28:23] = 100111
9278 instr[31] = size : 0 ==> 32 bit, 1 ==> 64 bit
9279 instr[30,29] = op21 : 0 ==> EXTR, 1,2,3 ==> UNALLOC
9280 instr[22] = N : must be 0 for 32 bit, 1 for 64 bit or UNALLOC
9281 instr[21] = op0 : must be 0 or UNALLOC
9283 instr[15,10] = imms : 0xxxxx for 32 bit, xxxxxx for 64 bit
9287 /* 32 bit operations must have N = 0 or else we have an UNALLOC. */
9288 /* 64 bit operations must have N = 1 or else we have an UNALLOC. */
9290 uint32_t size = uimm (aarch64_get_instr (cpu), 31, 31);
9291 uint32_t N = uimm (aarch64_get_instr (cpu), 22, 22);
9292 /* 32 bit operations must have imms[5] = 0
9293 or else we have an UNALLOC. */
9294 uint32_t imms = uimm (aarch64_get_instr (cpu), 15, 10);
9299 if (!size && uimm (imms, 5, 5))
9302 /* Switch on combined size and op. */
9303 dispatch = uimm (aarch64_get_instr (cpu), 31, 29);
9308 else if (dispatch == 4)
9311 else if (dispatch == 1)
9318 dexDPImm (sim_cpu *cpu)
9320 /* uint32_t group = dispatchGroup (aarch64_get_instr (cpu));
9321 assert group == GROUP_DPIMM_1000 || grpoup == GROUP_DPIMM_1001
9322 bits [25,23] of a DPImm are the secondary dispatch vector. */
9323 uint32_t group2 = dispatchDPImm (aarch64_get_instr (cpu));
9327 case DPIMM_PCADR_000:
9328 case DPIMM_PCADR_001:
9329 dexPCRelAddressing (cpu);
9332 case DPIMM_ADDSUB_010:
9333 case DPIMM_ADDSUB_011:
9334 dexAddSubtractImmediate (cpu);
9338 dexLogicalImmediate (cpu);
9342 dexMoveWideImmediate (cpu);
9345 case DPIMM_BITF_110:
9346 dexBitfieldImmediate (cpu);
9349 case DPIMM_EXTR_111:
9350 dexExtractImmediate (cpu);
9354 /* Should never reach here. */
9360 dexLoadUnscaledImmediate (sim_cpu *cpu)
9362 /* instr[29,24] == 111_00
9368 instr[20,12] = simm9
9369 instr[9,5] = rn may be SP. */
9370 /* unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0); */
9371 uint32_t V = uimm (aarch64_get_instr (cpu), 26, 26);
9372 uint32_t dispatch = ( (uimm (aarch64_get_instr (cpu), 31, 30) << 2)
9373 | uimm (aarch64_get_instr (cpu), 23, 22));
9374 int32_t imm = simm32 (aarch64_get_instr (cpu), 20, 12);
9378 /* GReg operations. */
9381 case 0: sturb (cpu, imm); return;
9382 case 1: ldurb32 (cpu, imm); return;
9383 case 2: ldursb64 (cpu, imm); return;
9384 case 3: ldursb32 (cpu, imm); return;
9385 case 4: sturh (cpu, imm); return;
9386 case 5: ldurh32 (cpu, imm); return;
9387 case 6: ldursh64 (cpu, imm); return;
9388 case 7: ldursh32 (cpu, imm); return;
9389 case 8: stur32 (cpu, imm); return;
9390 case 9: ldur32 (cpu, imm); return;
9391 case 10: ldursw (cpu, imm); return;
9392 case 12: stur64 (cpu, imm); return;
9393 case 13: ldur64 (cpu, imm); return;
9406 /* FReg operations. */
9409 case 2: fsturq (cpu, imm); return;
9410 case 3: fldurq (cpu, imm); return;
9411 case 8: fsturs (cpu, imm); return;
9412 case 9: fldurs (cpu, imm); return;
9413 case 12: fsturd (cpu, imm); return;
9414 case 13: fldurd (cpu, imm); return;
9416 case 0: /* STUR 8 bit FP. */
9417 case 1: /* LDUR 8 bit FP. */
9418 case 4: /* STUR 16 bit FP. */
9419 case 5: /* LDUR 8 bit FP. */
9433 /* N.B. A preliminary note regarding all the ldrs<x>32
9436 The signed value loaded by these instructions is cast to unsigned
9437 before being assigned to aarch64_get_reg_u64 (cpu, N) i.e. to the
9438 64 bit element of the GReg union. this performs a 32 bit sign extension
9439 (as required) but avoids 64 bit sign extension, thus ensuring that the
9440 top half of the register word is zero. this is what the spec demands
9441 when a 32 bit load occurs. */
9443 /* 32 bit load sign-extended byte scaled unsigned 12 bit. */
9445 ldrsb32_abs (sim_cpu *cpu, uint32_t offset)
9447 unsigned int rn = uimm (aarch64_get_instr (cpu), 9, 5);
9448 unsigned int rt = uimm (aarch64_get_instr (cpu), 4, 0);
9450 /* The target register may not be SP but the source may be
9451 there is no scaling required for a byte load. */
9452 uint64_t address = aarch64_get_reg_u64 (cpu, rn, SP_OK) + offset;
9453 aarch64_set_reg_u64 (cpu, rt, NO_SP,
9454 (int64_t) aarch64_get_mem_s8 (cpu, address));
9457 /* 32 bit load sign-extended byte scaled or unscaled zero-
9458 or sign-extended 32-bit register offset. */
9460 ldrsb32_scale_ext (sim_cpu *cpu, Scaling scaling, Extension extension)
9462 unsigned int rm = uimm (aarch64_get_instr (cpu), 20, 16);
9463 unsigned int rn = uimm (aarch64_get_instr (cpu), 9, 5);
9464 unsigned int rt = uimm (aarch64_get_instr (cpu), 4, 0);
9466 /* rn may reference SP, rm and rt must reference ZR. */
9468 uint64_t address = aarch64_get_reg_u64 (cpu, rn, SP_OK);
9469 int64_t displacement = extend (aarch64_get_reg_u32 (cpu, rm, NO_SP),
9472 /* There is no scaling required for a byte load. */
9474 (cpu, rt, NO_SP, (int64_t) aarch64_get_mem_s8 (cpu, address
9478 /* 32 bit load sign-extended byte unscaled signed 9 bit with
9479 pre- or post-writeback. */
9481 ldrsb32_wb (sim_cpu *cpu, int32_t offset, WriteBack wb)
9484 unsigned int rn = uimm (aarch64_get_instr (cpu), 9, 5);
9485 unsigned int rt = uimm (aarch64_get_instr (cpu), 4, 0);
9487 if (rn == rt && wb != NoWriteBack)
9490 address = aarch64_get_reg_u64 (cpu, rn, SP_OK);
9495 aarch64_set_reg_u64 (cpu, rt, NO_SP,
9496 (int64_t) aarch64_get_mem_s8 (cpu, address));
9501 if (wb != NoWriteBack)
9502 aarch64_set_reg_u64 (cpu, rn, NO_SP, address);
9505 /* 8 bit store scaled. */
9507 fstrb_abs (sim_cpu *cpu, uint32_t offset)
9509 unsigned st = uimm (aarch64_get_instr (cpu), 4, 0);
9510 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
9512 aarch64_set_mem_u8 (cpu,
9513 aarch64_get_reg_u64 (cpu, rn, SP_OK) + offset,
9514 aarch64_get_vec_u8 (cpu, st, 0));
9517 /* 8 bit store scaled or unscaled zero- or
9518 sign-extended 8-bit register offset. */
9520 fstrb_scale_ext (sim_cpu *cpu, Scaling scaling, Extension extension)
9522 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
9523 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
9524 unsigned st = uimm (aarch64_get_instr (cpu), 4, 0);
9526 uint64_t address = aarch64_get_reg_u64 (cpu, rn, SP_OK);
9527 int64_t extended = extend (aarch64_get_reg_u32 (cpu, rm, NO_SP),
9529 uint64_t displacement = OPT_SCALE (extended, 32, scaling);
9532 (cpu, address + displacement, aarch64_get_vec_u8 (cpu, st, 0));
9535 /* 16 bit store scaled. */
9537 fstrh_abs (sim_cpu *cpu, uint32_t offset)
9539 unsigned st = uimm (aarch64_get_instr (cpu), 4, 0);
9540 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
9544 aarch64_get_reg_u64 (cpu, rn, SP_OK) + SCALE (offset, 16),
9545 aarch64_get_vec_u16 (cpu, st, 0));
9548 /* 16 bit store scaled or unscaled zero-
9549 or sign-extended 16-bit register offset. */
9551 fstrh_scale_ext (sim_cpu *cpu, Scaling scaling, Extension extension)
9553 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
9554 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
9555 unsigned st = uimm (aarch64_get_instr (cpu), 4, 0);
9557 uint64_t address = aarch64_get_reg_u64 (cpu, rn, SP_OK);
9558 int64_t extended = extend (aarch64_get_reg_u32 (cpu, rm, NO_SP),
9560 uint64_t displacement = OPT_SCALE (extended, 32, scaling);
9563 (cpu, address + displacement, aarch64_get_vec_u16 (cpu, st, 0));
9566 /* 32 bit store scaled unsigned 12 bit. */
9568 fstrs_abs (sim_cpu *cpu, uint32_t offset)
9570 unsigned st = uimm (aarch64_get_instr (cpu), 4, 0);
9571 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
9575 aarch64_get_reg_u64 (cpu, rn, SP_OK) + SCALE (offset, 32),
9576 aarch64_get_vec_u32 (cpu, st, 0));
9579 /* 32 bit store unscaled signed 9 bit with pre- or post-writeback. */
9581 fstrs_wb (sim_cpu *cpu, int32_t offset, WriteBack wb)
9583 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
9584 unsigned st = uimm (aarch64_get_instr (cpu), 4, 0);
9586 uint64_t address = aarch64_get_reg_u64 (cpu, rn, SP_OK);
9591 aarch64_set_mem_u32 (cpu, address, aarch64_get_vec_u32 (cpu, st, 0));
9596 if (wb != NoWriteBack)
9597 aarch64_set_reg_u64 (cpu, rn, SP_OK, address);
9600 /* 32 bit store scaled or unscaled zero-
9601 or sign-extended 32-bit register offset. */
9603 fstrs_scale_ext (sim_cpu *cpu, Scaling scaling, Extension extension)
9605 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
9606 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
9607 unsigned st = uimm (aarch64_get_instr (cpu), 4, 0);
9609 uint64_t address = aarch64_get_reg_u64 (cpu, rn, SP_OK);
9610 int64_t extended = extend (aarch64_get_reg_u32 (cpu, rm, NO_SP),
9612 uint64_t displacement = OPT_SCALE (extended, 32, scaling);
9615 (cpu, address + displacement, aarch64_get_vec_u32 (cpu, st, 0));
9618 /* 64 bit store scaled unsigned 12 bit. */
9620 fstrd_abs (sim_cpu *cpu, uint32_t offset)
9622 unsigned st = uimm (aarch64_get_instr (cpu), 4, 0);
9623 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
9627 aarch64_get_reg_u64 (cpu, rn, SP_OK) + SCALE (offset, 64),
9628 aarch64_get_vec_u64 (cpu, st, 0));
9631 /* 64 bit store unscaled signed 9 bit with pre- or post-writeback. */
9633 fstrd_wb (sim_cpu *cpu, int32_t offset, WriteBack wb)
9635 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
9636 unsigned st = uimm (aarch64_get_instr (cpu), 4, 0);
9638 uint64_t address = aarch64_get_reg_u64 (cpu, rn, SP_OK);
9643 aarch64_set_mem_u64 (cpu, address, aarch64_get_vec_u64 (cpu, st, 0));
9648 if (wb != NoWriteBack)
9649 aarch64_set_reg_u64 (cpu, rn, SP_OK, address);
9652 /* 64 bit store scaled or unscaled zero-
9653 or sign-extended 32-bit register offset. */
9655 fstrd_scale_ext (sim_cpu *cpu, Scaling scaling, Extension extension)
9657 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
9658 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
9659 unsigned st = uimm (aarch64_get_instr (cpu), 4, 0);
9661 uint64_t address = aarch64_get_reg_u64 (cpu, rn, SP_OK);
9662 int64_t extended = extend (aarch64_get_reg_u32 (cpu, rm, NO_SP),
9664 uint64_t displacement = OPT_SCALE (extended, 64, scaling);
9667 (cpu, address + displacement, aarch64_get_vec_u64 (cpu, st, 0));
9670 /* 128 bit store scaled unsigned 12 bit. */
9672 fstrq_abs (sim_cpu *cpu, uint32_t offset)
9675 unsigned st = uimm (aarch64_get_instr (cpu), 4, 0);
9676 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
9679 aarch64_get_FP_long_double (cpu, st, & a);
9681 addr = aarch64_get_reg_u64 (cpu, rn, SP_OK) + SCALE (offset, 128);
9682 aarch64_set_mem_long_double (cpu, addr, a);
9685 /* 128 bit store unscaled signed 9 bit with pre- or post-writeback. */
9687 fstrq_wb (sim_cpu *cpu, int32_t offset, WriteBack wb)
9690 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
9691 unsigned st = uimm (aarch64_get_instr (cpu), 4, 0);
9692 uint64_t address = aarch64_get_reg_u64 (cpu, rn, SP_OK);
9697 aarch64_get_FP_long_double (cpu, st, & a);
9698 aarch64_set_mem_long_double (cpu, address, a);
9703 if (wb != NoWriteBack)
9704 aarch64_set_reg_u64 (cpu, rn, SP_OK, address);
9707 /* 128 bit store scaled or unscaled zero-
9708 or sign-extended 32-bit register offset. */
9710 fstrq_scale_ext (sim_cpu *cpu, Scaling scaling, Extension extension)
9712 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
9713 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
9714 unsigned st = uimm (aarch64_get_instr (cpu), 4, 0);
9716 uint64_t address = aarch64_get_reg_u64 (cpu, rn, SP_OK);
9717 int64_t extended = extend (aarch64_get_reg_u32 (cpu, rm, NO_SP),
9719 uint64_t displacement = OPT_SCALE (extended, 128, scaling);
9723 aarch64_get_FP_long_double (cpu, st, & a);
9724 aarch64_set_mem_long_double (cpu, address + displacement, a);
9728 dexLoadImmediatePrePost (sim_cpu *cpu)
9730 /* instr[29,24] == 111_00
9736 instr[20,12] = simm9
9737 instr[11] = wb : 0 ==> Post, 1 ==> Pre
9738 instr[9,5] = rn may be SP. */
9739 /* unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0); */
9740 uint32_t V = uimm (aarch64_get_instr (cpu), 26, 26);
9741 uint32_t dispatch = ( (uimm (aarch64_get_instr (cpu), 31, 30) << 2)
9742 | uimm (aarch64_get_instr (cpu), 23, 22));
9743 int32_t imm = simm32 (aarch64_get_instr (cpu), 20, 12);
9744 WriteBack wb = writeback (aarch64_get_instr (cpu), 11);
9748 /* GReg operations. */
9751 case 0: strb_wb (cpu, imm, wb); return;
9752 case 1: ldrb32_wb (cpu, imm, wb); return;
9753 case 2: ldrsb_wb (cpu, imm, wb); return;
9754 case 3: ldrsb32_wb (cpu, imm, wb); return;
9755 case 4: strh_wb (cpu, imm, wb); return;
9756 case 5: ldrh32_wb (cpu, imm, wb); return;
9757 case 6: ldrsh64_wb (cpu, imm, wb); return;
9758 case 7: ldrsh32_wb (cpu, imm, wb); return;
9759 case 8: str32_wb (cpu, imm, wb); return;
9760 case 9: ldr32_wb (cpu, imm, wb); return;
9761 case 10: ldrsw_wb (cpu, imm, wb); return;
9762 case 12: str_wb (cpu, imm, wb); return;
9763 case 13: ldr_wb (cpu, imm, wb); return;
9773 /* FReg operations. */
9776 case 2: fstrq_wb (cpu, imm, wb); return;
9777 case 3: fldrq_wb (cpu, imm, wb); return;
9778 case 8: fstrs_wb (cpu, imm, wb); return;
9779 case 9: fldrs_wb (cpu, imm, wb); return;
9780 case 12: fstrd_wb (cpu, imm, wb); return;
9781 case 13: fldrd_wb (cpu, imm, wb); return;
9783 case 0: /* STUR 8 bit FP. */
9784 case 1: /* LDUR 8 bit FP. */
9785 case 4: /* STUR 16 bit FP. */
9786 case 5: /* LDUR 8 bit FP. */
9801 dexLoadRegisterOffset (sim_cpu *cpu)
9803 /* instr[31,30] = size
9810 instr[15,13] = option : 010 ==> UXTW, 011 ==> UXTX/LSL,
9811 110 ==> SXTW, 111 ==> SXTX,
9818 uint32_t V = uimm (aarch64_get_instr (cpu), 26,26);
9819 uint32_t dispatch = ( (uimm (aarch64_get_instr (cpu), 31, 30) << 2)
9820 | uimm (aarch64_get_instr (cpu), 23, 22));
9821 Scaling scale = scaling (aarch64_get_instr (cpu), 12);
9822 Extension extensionType = extension (aarch64_get_instr (cpu), 13);
9824 /* Check for illegal extension types. */
9825 if (uimm (extensionType, 1, 1) == 0)
9828 if (extensionType == UXTX || extensionType == SXTX)
9829 extensionType = NoExtension;
9833 /* GReg operations. */
9836 case 0: strb_scale_ext (cpu, scale, extensionType); return;
9837 case 1: ldrb32_scale_ext (cpu, scale, extensionType); return;
9838 case 2: ldrsb_scale_ext (cpu, scale, extensionType); return;
9839 case 3: ldrsb32_scale_ext (cpu, scale, extensionType); return;
9840 case 4: strh_scale_ext (cpu, scale, extensionType); return;
9841 case 5: ldrh32_scale_ext (cpu, scale, extensionType); return;
9842 case 6: ldrsh_scale_ext (cpu, scale, extensionType); return;
9843 case 7: ldrsh32_scale_ext (cpu, scale, extensionType); return;
9844 case 8: str32_scale_ext (cpu, scale, extensionType); return;
9845 case 9: ldr32_scale_ext (cpu, scale, extensionType); return;
9846 case 10: ldrsw_scale_ext (cpu, scale, extensionType); return;
9847 case 12: str_scale_ext (cpu, scale, extensionType); return;
9848 case 13: ldr_scale_ext (cpu, scale, extensionType); return;
9849 case 14: prfm_scale_ext (cpu, scale, extensionType); return;
9858 /* FReg operations. */
9861 case 1: /* LDUR 8 bit FP. */
9863 case 3: fldrq_scale_ext (cpu, scale, extensionType); return;
9864 case 5: /* LDUR 8 bit FP. */
9866 case 9: fldrs_scale_ext (cpu, scale, extensionType); return;
9867 case 13: fldrd_scale_ext (cpu, scale, extensionType); return;
9869 case 0: fstrb_scale_ext (cpu, scale, extensionType); return;
9870 case 2: fstrq_scale_ext (cpu, scale, extensionType); return;
9871 case 4: fstrh_scale_ext (cpu, scale, extensionType); return;
9872 case 8: fstrs_scale_ext (cpu, scale, extensionType); return;
9873 case 12: fstrd_scale_ext (cpu, scale, extensionType); return;
9887 dexLoadUnsignedImmediate (sim_cpu *cpu)
9889 /* assert instr[29,24] == 111_01
9893 instr[21,10] = uimm12 : unsigned immediate offset
9894 instr[9,5] = rn may be SP. */
9895 /* unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0); */
9896 uint32_t V = uimm (aarch64_get_instr (cpu), 26,26);
9897 uint32_t dispatch = ( (uimm (aarch64_get_instr (cpu), 31, 30) << 2)
9898 | uimm (aarch64_get_instr (cpu), 23, 22));
9899 uint32_t imm = uimm (aarch64_get_instr (cpu), 21, 10);
9903 /* GReg operations. */
9906 case 0: strb_abs (cpu, imm); return;
9907 case 1: ldrb32_abs (cpu, imm); return;
9908 case 2: ldrsb_abs (cpu, imm); return;
9909 case 3: ldrsb32_abs (cpu, imm); return;
9910 case 4: strh_abs (cpu, imm); return;
9911 case 5: ldrh32_abs (cpu, imm); return;
9912 case 6: ldrsh_abs (cpu, imm); return;
9913 case 7: ldrsh32_abs (cpu, imm); return;
9914 case 8: str32_abs (cpu, imm); return;
9915 case 9: ldr32_abs (cpu, imm); return;
9916 case 10: ldrsw_abs (cpu, imm); return;
9917 case 12: str_abs (cpu, imm); return;
9918 case 13: ldr_abs (cpu, imm); return;
9919 case 14: prfm_abs (cpu, imm); return;
9928 /* FReg operations. */
9931 case 3: fldrq_abs (cpu, imm); return;
9932 case 9: fldrs_abs (cpu, imm); return;
9933 case 13: fldrd_abs (cpu, imm); return;
9935 case 0: fstrb_abs (cpu, imm); return;
9936 case 2: fstrq_abs (cpu, imm); return;
9937 case 4: fstrh_abs (cpu, imm); return;
9938 case 8: fstrs_abs (cpu, imm); return;
9939 case 12: fstrd_abs (cpu, imm); return;
9941 case 1: /* LDR 8 bit FP. */
9942 case 5: /* LDR 8 bit FP. */
9957 dexLoadExclusive (sim_cpu *cpu)
9959 /* assert instr[29:24] = 001000;
9961 instr[23] = 0 if exclusive
9962 instr[22] = L : 1 if load, 0 if store
9963 instr[21] = 1 if pair
9965 instr[15] = o0 : 1 if ordered
9970 switch (uimm (aarch64_get_instr (cpu), 22, 21))
9972 case 2: ldxr (cpu); return;
9973 case 0: stxr (cpu); return;
9979 dexLoadOther (sim_cpu *cpu)
9983 /* instr[29,25] = 111_0
9984 instr[24] == 0 ==> dispatch, 1 ==> ldst reg unsigned immediate
9985 instr[21:11,10] is the secondary dispatch. */
9986 if (uimm (aarch64_get_instr (cpu), 24, 24))
9988 dexLoadUnsignedImmediate (cpu);
9992 dispatch = ( (uimm (aarch64_get_instr (cpu), 21, 21) << 2)
9993 | uimm (aarch64_get_instr (cpu), 11, 10));
9996 case 0: dexLoadUnscaledImmediate (cpu); return;
9997 case 1: dexLoadImmediatePrePost (cpu); return;
9998 case 3: dexLoadImmediatePrePost (cpu); return;
9999 case 6: dexLoadRegisterOffset (cpu); return;
10011 store_pair_u32 (sim_cpu *cpu, int32_t offset, WriteBack wb)
10013 unsigned rn = uimm (aarch64_get_instr (cpu), 14, 10);
10014 unsigned rd = uimm (aarch64_get_instr (cpu), 9, 5);
10015 unsigned rm = uimm (aarch64_get_instr (cpu), 4, 0);
10016 uint64_t address = aarch64_get_reg_u64 (cpu, rd, SP_OK);
10018 if ((rn == rd || rm == rd) && wb != NoWriteBack)
10019 HALT_UNALLOC; /* ??? */
10026 aarch64_set_mem_u32 (cpu, address,
10027 aarch64_get_reg_u32 (cpu, rm, NO_SP));
10028 aarch64_set_mem_u32 (cpu, address + 4,
10029 aarch64_get_reg_u32 (cpu, rn, NO_SP));
10034 if (wb != NoWriteBack)
10035 aarch64_set_reg_u64 (cpu, rd, SP_OK, address);
10039 store_pair_u64 (sim_cpu *cpu, int32_t offset, WriteBack wb)
10041 unsigned rn = uimm (aarch64_get_instr (cpu), 14, 10);
10042 unsigned rd = uimm (aarch64_get_instr (cpu), 9, 5);
10043 unsigned rm = uimm (aarch64_get_instr (cpu), 4, 0);
10044 uint64_t address = aarch64_get_reg_u64 (cpu, rd, SP_OK);
10046 if ((rn == rd || rm == rd) && wb != NoWriteBack)
10047 HALT_UNALLOC; /* ??? */
10054 aarch64_set_mem_u64 (cpu, address,
10055 aarch64_get_reg_u64 (cpu, rm, SP_OK));
10056 aarch64_set_mem_u64 (cpu, address + 8,
10057 aarch64_get_reg_u64 (cpu, rn, SP_OK));
10062 if (wb != NoWriteBack)
10063 aarch64_set_reg_u64 (cpu, rd, SP_OK, address);
10067 load_pair_u32 (sim_cpu *cpu, int32_t offset, WriteBack wb)
10069 unsigned rn = uimm (aarch64_get_instr (cpu), 14, 10);
10070 unsigned rd = uimm (aarch64_get_instr (cpu), 9, 5);
10071 unsigned rm = uimm (aarch64_get_instr (cpu), 4, 0);
10072 uint64_t address = aarch64_get_reg_u64 (cpu, rd, SP_OK);
10074 /* treat this as unalloc to make sure we don't do it. */
10083 aarch64_set_reg_u64 (cpu, rm, SP_OK, aarch64_get_mem_u32 (cpu, address));
10084 aarch64_set_reg_u64 (cpu, rn, SP_OK, aarch64_get_mem_u32 (cpu, address + 4));
10089 if (wb != NoWriteBack)
10090 aarch64_set_reg_u64 (cpu, rd, SP_OK, address);
10094 load_pair_s32 (sim_cpu *cpu, int32_t offset, WriteBack wb)
10096 unsigned rn = uimm (aarch64_get_instr (cpu), 14, 10);
10097 unsigned rd = uimm (aarch64_get_instr (cpu), 9, 5);
10098 unsigned rm = uimm (aarch64_get_instr (cpu), 4, 0);
10099 uint64_t address = aarch64_get_reg_u64 (cpu, rd, SP_OK);
10101 /* Treat this as unalloc to make sure we don't do it. */
10110 aarch64_set_reg_s64 (cpu, rm, SP_OK, aarch64_get_mem_s32 (cpu, address));
10111 aarch64_set_reg_s64 (cpu, rn, SP_OK, aarch64_get_mem_s32 (cpu, address + 4));
10116 if (wb != NoWriteBack)
10117 aarch64_set_reg_u64 (cpu, rd, SP_OK, address);
10121 load_pair_u64 (sim_cpu *cpu, int32_t offset, WriteBack wb)
10123 unsigned rn = uimm (aarch64_get_instr (cpu), 14, 10);
10124 unsigned rd = uimm (aarch64_get_instr (cpu), 9, 5);
10125 unsigned rm = uimm (aarch64_get_instr (cpu), 4, 0);
10126 uint64_t address = aarch64_get_reg_u64 (cpu, rd, SP_OK);
10128 /* Treat this as unalloc to make sure we don't do it. */
10137 aarch64_set_reg_u64 (cpu, rm, SP_OK, aarch64_get_mem_u64 (cpu, address));
10138 aarch64_set_reg_u64 (cpu, rn, SP_OK, aarch64_get_mem_u64 (cpu, address + 8));
10143 if (wb != NoWriteBack)
10144 aarch64_set_reg_u64 (cpu, rd, SP_OK, address);
10148 dex_load_store_pair_gr (sim_cpu *cpu)
10150 /* instr[31,30] = size (10=> 64-bit, 01=> signed 32-bit, 00=> 32-bit)
10151 instr[29,25] = instruction encoding: 101_0
10152 instr[26] = V : 1 if fp 0 if gp
10153 instr[24,23] = addressing mode (10=> offset, 01=> post, 11=> pre)
10154 instr[22] = load/store (1=> load)
10155 instr[21,15] = signed, scaled, offset
10158 instr[ 4, 0] = Rm. */
10160 uint32_t dispatch = ((uimm (aarch64_get_instr (cpu), 31, 30) << 3)
10161 | uimm (aarch64_get_instr (cpu), 24, 22));
10162 int32_t offset = simm32 (aarch64_get_instr (cpu), 21, 15);
10166 case 2: store_pair_u32 (cpu, offset, Post); return;
10167 case 3: load_pair_u32 (cpu, offset, Post); return;
10168 case 4: store_pair_u32 (cpu, offset, NoWriteBack); return;
10169 case 5: load_pair_u32 (cpu, offset, NoWriteBack); return;
10170 case 6: store_pair_u32 (cpu, offset, Pre); return;
10171 case 7: load_pair_u32 (cpu, offset, Pre); return;
10173 case 11: load_pair_s32 (cpu, offset, Post); return;
10174 case 13: load_pair_s32 (cpu, offset, NoWriteBack); return;
10175 case 15: load_pair_s32 (cpu, offset, Pre); return;
10177 case 18: store_pair_u64 (cpu, offset, Post); return;
10178 case 19: load_pair_u64 (cpu, offset, Post); return;
10179 case 20: store_pair_u64 (cpu, offset, NoWriteBack); return;
10180 case 21: load_pair_u64 (cpu, offset, NoWriteBack); return;
10181 case 22: store_pair_u64 (cpu, offset, Pre); return;
10182 case 23: load_pair_u64 (cpu, offset, Pre); return;
10190 store_pair_float (sim_cpu *cpu, int32_t offset, WriteBack wb)
10192 unsigned rn = uimm (aarch64_get_instr (cpu), 14, 10);
10193 unsigned rd = uimm (aarch64_get_instr (cpu), 9, 5);
10194 unsigned rm = uimm (aarch64_get_instr (cpu), 4, 0);
10195 uint64_t address = aarch64_get_reg_u64 (cpu, rd, SP_OK);
10202 aarch64_set_mem_u32 (cpu, address, aarch64_get_vec_u32 (cpu, rm, 0));
10203 aarch64_set_mem_u32 (cpu, address + 4, aarch64_get_vec_u32 (cpu, rn, 0));
10208 if (wb != NoWriteBack)
10209 aarch64_set_reg_u64 (cpu, rd, SP_OK, address);
10213 store_pair_double (sim_cpu *cpu, int32_t offset, WriteBack wb)
10215 unsigned rn = uimm (aarch64_get_instr (cpu), 14, 10);
10216 unsigned rd = uimm (aarch64_get_instr (cpu), 9, 5);
10217 unsigned rm = uimm (aarch64_get_instr (cpu), 4, 0);
10218 uint64_t address = aarch64_get_reg_u64 (cpu, rd, SP_OK);
10225 aarch64_set_mem_u64 (cpu, address, aarch64_get_vec_u64 (cpu, rm, 0));
10226 aarch64_set_mem_u64 (cpu, address + 8, aarch64_get_vec_u64 (cpu, rn, 0));
10231 if (wb != NoWriteBack)
10232 aarch64_set_reg_u64 (cpu, rd, SP_OK, address);
10236 store_pair_long_double (sim_cpu *cpu, int32_t offset, WriteBack wb)
10239 unsigned rn = uimm (aarch64_get_instr (cpu), 14, 10);
10240 unsigned rd = uimm (aarch64_get_instr (cpu), 9, 5);
10241 unsigned rm = uimm (aarch64_get_instr (cpu), 4, 0);
10242 uint64_t address = aarch64_get_reg_u64 (cpu, rd, SP_OK);
10249 aarch64_get_FP_long_double (cpu, rm, & a);
10250 aarch64_set_mem_long_double (cpu, address, a);
10251 aarch64_get_FP_long_double (cpu, rn, & a);
10252 aarch64_set_mem_long_double (cpu, address + 16, a);
10257 if (wb != NoWriteBack)
10258 aarch64_set_reg_u64 (cpu, rd, SP_OK, address);
10262 load_pair_float (sim_cpu *cpu, int32_t offset, WriteBack wb)
10264 unsigned rn = uimm (aarch64_get_instr (cpu), 14, 10);
10265 unsigned rd = uimm (aarch64_get_instr (cpu), 9, 5);
10266 unsigned rm = uimm (aarch64_get_instr (cpu), 4, 0);
10267 uint64_t address = aarch64_get_reg_u64 (cpu, rd, SP_OK);
10277 aarch64_set_vec_u32 (cpu, rm, 0, aarch64_get_mem_u32 (cpu, address));
10278 aarch64_set_vec_u32 (cpu, rn, 0, aarch64_get_mem_u32 (cpu, address + 4));
10283 if (wb != NoWriteBack)
10284 aarch64_set_reg_u64 (cpu, rd, SP_OK, address);
10288 load_pair_double (sim_cpu *cpu, int32_t offset, WriteBack wb)
10290 unsigned rn = uimm (aarch64_get_instr (cpu), 14, 10);
10291 unsigned rd = uimm (aarch64_get_instr (cpu), 9, 5);
10292 unsigned rm = uimm (aarch64_get_instr (cpu), 4, 0);
10293 uint64_t address = aarch64_get_reg_u64 (cpu, rd, SP_OK);
10303 aarch64_set_vec_u64 (cpu, rm, 0, aarch64_get_mem_u64 (cpu, address));
10304 aarch64_set_vec_u64 (cpu, rn, 0, aarch64_get_mem_u64 (cpu, address + 8));
10309 if (wb != NoWriteBack)
10310 aarch64_set_reg_u64 (cpu, rd, SP_OK, address);
10314 load_pair_long_double (sim_cpu *cpu, int32_t offset, WriteBack wb)
10317 unsigned rn = uimm (aarch64_get_instr (cpu), 14, 10);
10318 unsigned rd = uimm (aarch64_get_instr (cpu), 9, 5);
10319 unsigned rm = uimm (aarch64_get_instr (cpu), 4, 0);
10320 uint64_t address = aarch64_get_reg_u64 (cpu, rd, SP_OK);
10330 aarch64_get_mem_long_double (cpu, address, & a);
10331 aarch64_set_FP_long_double (cpu, rm, a);
10332 aarch64_get_mem_long_double (cpu, address + 16, & a);
10333 aarch64_set_FP_long_double (cpu, rn, a);
10338 if (wb != NoWriteBack)
10339 aarch64_set_reg_u64 (cpu, rd, SP_OK, address);
10343 dex_load_store_pair_fp (sim_cpu *cpu)
10345 /* instr[31,30] = size (10=> 128-bit, 01=> 64-bit, 00=> 32-bit)
10346 instr[29,25] = instruction encoding
10347 instr[24,23] = addressing mode (10=> offset, 01=> post, 11=> pre)
10348 instr[22] = load/store (1=> load)
10349 instr[21,15] = signed, scaled, offset
10352 instr[ 4, 0] = Rm */
10354 uint32_t dispatch = ((uimm (aarch64_get_instr (cpu), 31, 30) << 3)
10355 | uimm (aarch64_get_instr (cpu), 24, 22));
10356 int32_t offset = simm32 (aarch64_get_instr (cpu), 21, 15);
10360 case 2: store_pair_float (cpu, offset, Post); return;
10361 case 3: load_pair_float (cpu, offset, Post); return;
10362 case 4: store_pair_float (cpu, offset, NoWriteBack); return;
10363 case 5: load_pair_float (cpu, offset, NoWriteBack); return;
10364 case 6: store_pair_float (cpu, offset, Pre); return;
10365 case 7: load_pair_float (cpu, offset, Pre); return;
10367 case 10: store_pair_double (cpu, offset, Post); return;
10368 case 11: load_pair_double (cpu, offset, Post); return;
10369 case 12: store_pair_double (cpu, offset, NoWriteBack); return;
10370 case 13: load_pair_double (cpu, offset, NoWriteBack); return;
10371 case 14: store_pair_double (cpu, offset, Pre); return;
10372 case 15: load_pair_double (cpu, offset, Pre); return;
10374 case 18: store_pair_long_double (cpu, offset, Post); return;
10375 case 19: load_pair_long_double (cpu, offset, Post); return;
10376 case 20: store_pair_long_double (cpu, offset, NoWriteBack); return;
10377 case 21: load_pair_long_double (cpu, offset, NoWriteBack); return;
10378 case 22: store_pair_long_double (cpu, offset, Pre); return;
10379 case 23: load_pair_long_double (cpu, offset, Pre); return;
10386 static inline unsigned
10387 vec_reg (unsigned v, unsigned o)
10389 return (v + o) & 0x3F;
10392 /* Load multiple N-element structures to N consecutive registers. */
10394 vec_load (sim_cpu *cpu, uint64_t address, unsigned N)
10396 int all = uimm (aarch64_get_instr (cpu), 30, 30);
10397 unsigned size = uimm (aarch64_get_instr (cpu), 11, 10);
10398 unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
10403 case 0: /* 8-bit operations. */
10405 for (i = 0; i < (16 * N); i++)
10406 aarch64_set_vec_u8 (cpu, vec_reg (vd, i >> 4), i & 15,
10407 aarch64_get_mem_u8 (cpu, address + i));
10409 for (i = 0; i < (8 * N); i++)
10410 aarch64_set_vec_u8 (cpu, vec_reg (vd, i >> 3), i & 7,
10411 aarch64_get_mem_u8 (cpu, address + i));
10414 case 1: /* 16-bit operations. */
10416 for (i = 0; i < (8 * N); i++)
10417 aarch64_set_vec_u16 (cpu, vec_reg (vd, i >> 3), i & 7,
10418 aarch64_get_mem_u16 (cpu, address + i * 2));
10420 for (i = 0; i < (4 * N); i++)
10421 aarch64_set_vec_u16 (cpu, vec_reg (vd, i >> 2), i & 3,
10422 aarch64_get_mem_u16 (cpu, address + i * 2));
10425 case 2: /* 32-bit operations. */
10427 for (i = 0; i < (4 * N); i++)
10428 aarch64_set_vec_u32 (cpu, vec_reg (vd, i >> 2), i & 3,
10429 aarch64_get_mem_u32 (cpu, address + i * 4));
10431 for (i = 0; i < (2 * N); i++)
10432 aarch64_set_vec_u32 (cpu, vec_reg (vd, i >> 1), i & 1,
10433 aarch64_get_mem_u32 (cpu, address + i * 4));
10436 case 3: /* 64-bit operations. */
10438 for (i = 0; i < (2 * N); i++)
10439 aarch64_set_vec_u64 (cpu, vec_reg (vd, i >> 1), i & 1,
10440 aarch64_get_mem_u64 (cpu, address + i * 8));
10442 for (i = 0; i < N; i++)
10443 aarch64_set_vec_u64 (cpu, vec_reg (vd, i), 0,
10444 aarch64_get_mem_u64 (cpu, address + i * 8));
10452 /* LD4: load multiple 4-element to four consecutive registers. */
10454 LD4 (sim_cpu *cpu, uint64_t address)
10456 vec_load (cpu, address, 4);
10459 /* LD3: load multiple 3-element structures to three consecutive registers. */
10461 LD3 (sim_cpu *cpu, uint64_t address)
10463 vec_load (cpu, address, 3);
10466 /* LD2: load multiple 2-element structures to two consecutive registers. */
10468 LD2 (sim_cpu *cpu, uint64_t address)
10470 vec_load (cpu, address, 2);
10473 /* Load multiple 1-element structures into one register. */
10475 LD1_1 (sim_cpu *cpu, uint64_t address)
10477 int all = uimm (aarch64_get_instr (cpu), 30, 30);
10478 unsigned size = uimm (aarch64_get_instr (cpu), 11, 10);
10479 unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
10485 /* LD1 {Vd.16b}, addr, #16 */
10486 /* LD1 {Vd.8b}, addr, #8 */
10487 for (i = 0; i < (all ? 16 : 8); i++)
10488 aarch64_set_vec_u8 (cpu, vd, i,
10489 aarch64_get_mem_u8 (cpu, address + i));
10493 /* LD1 {Vd.8h}, addr, #16 */
10494 /* LD1 {Vd.4h}, addr, #8 */
10495 for (i = 0; i < (all ? 8 : 4); i++)
10496 aarch64_set_vec_u16 (cpu, vd, i,
10497 aarch64_get_mem_u16 (cpu, address + i * 2));
10501 /* LD1 {Vd.4s}, addr, #16 */
10502 /* LD1 {Vd.2s}, addr, #8 */
10503 for (i = 0; i < (all ? 4 : 2); i++)
10504 aarch64_set_vec_u32 (cpu, vd, i,
10505 aarch64_get_mem_u32 (cpu, address + i * 4));
10509 /* LD1 {Vd.2d}, addr, #16 */
10510 /* LD1 {Vd.1d}, addr, #8 */
10511 for (i = 0; i < (all ? 2 : 1); i++)
10512 aarch64_set_vec_u64 (cpu, vd, i,
10513 aarch64_get_mem_u64 (cpu, address + i * 8));
10521 /* Load multiple 1-element structures into two registers. */
10523 LD1_2 (sim_cpu *cpu, uint64_t address)
10525 /* FIXME: This algorithm is *exactly* the same as the LD2 version.
10526 So why have two different instructions ? There must be something
10527 wrong somewhere. */
10528 vec_load (cpu, address, 2);
10531 /* Load multiple 1-element structures into three registers. */
10533 LD1_3 (sim_cpu *cpu, uint64_t address)
10535 /* FIXME: This algorithm is *exactly* the same as the LD3 version.
10536 So why have two different instructions ? There must be something
10537 wrong somewhere. */
10538 vec_load (cpu, address, 3);
10541 /* Load multiple 1-element structures into four registers. */
10543 LD1_4 (sim_cpu *cpu, uint64_t address)
10545 /* FIXME: This algorithm is *exactly* the same as the LD4 version.
10546 So why have two different instructions ? There must be something
10547 wrong somewhere. */
10548 vec_load (cpu, address, 4);
10551 /* Store multiple N-element structures to N consecutive registers. */
10553 vec_store (sim_cpu *cpu, uint64_t address, unsigned N)
10555 int all = uimm (aarch64_get_instr (cpu), 30, 30);
10556 unsigned size = uimm (aarch64_get_instr (cpu), 11, 10);
10557 unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
10562 case 0: /* 8-bit operations. */
10564 for (i = 0; i < (16 * N); i++)
10567 aarch64_get_vec_u8 (cpu, vec_reg (vd, i >> 4), i & 15));
10569 for (i = 0; i < (8 * N); i++)
10572 aarch64_get_vec_u8 (cpu, vec_reg (vd, i >> 3), i & 7));
10575 case 1: /* 16-bit operations. */
10577 for (i = 0; i < (8 * N); i++)
10578 aarch64_set_mem_u16
10579 (cpu, address + i * 2,
10580 aarch64_get_vec_u16 (cpu, vec_reg (vd, i >> 3), i & 7));
10582 for (i = 0; i < (4 * N); i++)
10583 aarch64_set_mem_u16
10584 (cpu, address + i * 2,
10585 aarch64_get_vec_u16 (cpu, vec_reg (vd, i >> 2), i & 3));
10588 case 2: /* 32-bit operations. */
10590 for (i = 0; i < (4 * N); i++)
10591 aarch64_set_mem_u32
10592 (cpu, address + i * 4,
10593 aarch64_get_vec_u32 (cpu, vec_reg (vd, i >> 2), i & 3));
10595 for (i = 0; i < (2 * N); i++)
10596 aarch64_set_mem_u32
10597 (cpu, address + i * 4,
10598 aarch64_get_vec_u32 (cpu, vec_reg (vd, i >> 1), i & 1));
10601 case 3: /* 64-bit operations. */
10603 for (i = 0; i < (2 * N); i++)
10604 aarch64_set_mem_u64
10605 (cpu, address + i * 8,
10606 aarch64_get_vec_u64 (cpu, vec_reg (vd, i >> 1), i & 1));
10608 for (i = 0; i < N; i++)
10609 aarch64_set_mem_u64
10610 (cpu, address + i * 8,
10611 aarch64_get_vec_u64 (cpu, vec_reg (vd, i), 0));
10619 /* Store multiple 4-element structure to four consecutive registers. */
10621 ST4 (sim_cpu *cpu, uint64_t address)
10623 vec_store (cpu, address, 4);
10626 /* Store multiple 3-element structures to three consecutive registers. */
10628 ST3 (sim_cpu *cpu, uint64_t address)
10630 vec_store (cpu, address, 3);
10633 /* Store multiple 2-element structures to two consecutive registers. */
10635 ST2 (sim_cpu *cpu, uint64_t address)
10637 vec_store (cpu, address, 2);
10640 /* Store multiple 1-element structures into one register. */
10642 ST1_1 (sim_cpu *cpu, uint64_t address)
10644 int all = uimm (aarch64_get_instr (cpu), 30, 30);
10645 unsigned size = uimm (aarch64_get_instr (cpu), 11, 10);
10646 unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
10652 for (i = 0; i < (all ? 16 : 8); i++)
10653 aarch64_set_mem_u8 (cpu, address + i,
10654 aarch64_get_vec_u8 (cpu, vd, i));
10658 for (i = 0; i < (all ? 8 : 4); i++)
10659 aarch64_set_mem_u16 (cpu, address + i * 2,
10660 aarch64_get_vec_u16 (cpu, vd, i));
10664 for (i = 0; i < (all ? 4 : 2); i++)
10665 aarch64_set_mem_u32 (cpu, address + i * 4,
10666 aarch64_get_vec_u32 (cpu, vd, i));
10670 for (i = 0; i < (all ? 2 : 1); i++)
10671 aarch64_set_mem_u64 (cpu, address + i * 8,
10672 aarch64_get_vec_u64 (cpu, vd, i));
10680 /* Store multiple 1-element structures into two registers. */
10682 ST1_2 (sim_cpu *cpu, uint64_t address)
10684 /* FIXME: This algorithm is *exactly* the same as the ST2 version.
10685 So why have two different instructions ? There must be
10686 something wrong somewhere. */
10687 vec_store (cpu, address, 2);
10690 /* Store multiple 1-element structures into three registers. */
10692 ST1_3 (sim_cpu *cpu, uint64_t address)
10694 /* FIXME: This algorithm is *exactly* the same as the ST3 version.
10695 So why have two different instructions ? There must be
10696 something wrong somewhere. */
10697 vec_store (cpu, address, 3);
10700 /* Store multiple 1-element structures into four registers. */
10702 ST1_4 (sim_cpu *cpu, uint64_t address)
10704 /* FIXME: This algorithm is *exactly* the same as the ST4 version.
10705 So why have two different instructions ? There must be
10706 something wrong somewhere. */
10707 vec_store (cpu, address, 4);
10711 do_vec_LDnR (sim_cpu *cpu, uint64_t address)
10714 instr[30] = element selector 0=>half, 1=>all elements
10715 instr[29,24] = 00 1101
10716 instr[23] = 0=>simple, 1=>post
10718 instr[21] = width: LD1R-or-LD3R (0) / LD2R-or-LD4R (1)
10719 instr[20,16] = 0 0000 (simple), Vinc (reg-post-inc, no SP),
10720 11111 (immediate post inc)
10722 instr[13] = width: LD1R-or-LD2R (0) / LD3R-or-LD4R (1)
10724 instr[11,10] = element size 00=> byte(b), 01=> half(h),
10725 10=> word(s), 11=> double(d)
10726 instr[9,5] = address
10729 unsigned full = uimm (aarch64_get_instr (cpu), 30, 30);
10730 unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
10731 unsigned size = uimm (aarch64_get_instr (cpu), 11, 10);
10734 NYI_assert (29, 24, 0x0D);
10735 NYI_assert (22, 22, 1);
10736 NYI_assert (15, 14, 3);
10737 NYI_assert (12, 12, 0);
10739 switch ((uimm (aarch64_get_instr (cpu), 13, 13) << 1)
10740 | uimm (aarch64_get_instr (cpu), 21, 21))
10742 case 0: /* LD1R. */
10747 uint8_t val = aarch64_get_mem_u8 (cpu, address);
10748 for (i = 0; i < (full ? 16 : 8); i++)
10749 aarch64_set_vec_u8 (cpu, vd, i, val);
10755 uint16_t val = aarch64_get_mem_u16 (cpu, address);
10756 for (i = 0; i < (full ? 8 : 4); i++)
10757 aarch64_set_vec_u16 (cpu, vd, i, val);
10763 uint32_t val = aarch64_get_mem_u32 (cpu, address);
10764 for (i = 0; i < (full ? 4 : 2); i++)
10765 aarch64_set_vec_u32 (cpu, vd, i, val);
10771 uint64_t val = aarch64_get_mem_u64 (cpu, address);
10772 for (i = 0; i < (full ? 2 : 1); i++)
10773 aarch64_set_vec_u64 (cpu, vd, i, val);
10782 case 1: /* LD2R. */
10787 uint8_t val1 = aarch64_get_mem_u8 (cpu, address);
10788 uint8_t val2 = aarch64_get_mem_u8 (cpu, address + 1);
10790 for (i = 0; i < (full ? 16 : 8); i++)
10792 aarch64_set_vec_u8 (cpu, vd, 0, val1);
10793 aarch64_set_vec_u8 (cpu, vd + 1, 0, val2);
10800 uint16_t val1 = aarch64_get_mem_u16 (cpu, address);
10801 uint16_t val2 = aarch64_get_mem_u16 (cpu, address + 2);
10803 for (i = 0; i < (full ? 8 : 4); i++)
10805 aarch64_set_vec_u16 (cpu, vd, 0, val1);
10806 aarch64_set_vec_u16 (cpu, vd + 1, 0, val2);
10813 uint32_t val1 = aarch64_get_mem_u32 (cpu, address);
10814 uint32_t val2 = aarch64_get_mem_u32 (cpu, address + 4);
10816 for (i = 0; i < (full ? 4 : 2); i++)
10818 aarch64_set_vec_u32 (cpu, vd, 0, val1);
10819 aarch64_set_vec_u32 (cpu, vd + 1, 0, val2);
10826 uint64_t val1 = aarch64_get_mem_u64 (cpu, address);
10827 uint64_t val2 = aarch64_get_mem_u64 (cpu, address + 8);
10829 for (i = 0; i < (full ? 2 : 1); i++)
10831 aarch64_set_vec_u64 (cpu, vd, 0, val1);
10832 aarch64_set_vec_u64 (cpu, vd + 1, 0, val2);
10842 case 2: /* LD3R. */
10847 uint8_t val1 = aarch64_get_mem_u8 (cpu, address);
10848 uint8_t val2 = aarch64_get_mem_u8 (cpu, address + 1);
10849 uint8_t val3 = aarch64_get_mem_u8 (cpu, address + 2);
10851 for (i = 0; i < (full ? 16 : 8); i++)
10853 aarch64_set_vec_u8 (cpu, vd, 0, val1);
10854 aarch64_set_vec_u8 (cpu, vd + 1, 0, val2);
10855 aarch64_set_vec_u8 (cpu, vd + 2, 0, val3);
10862 uint32_t val1 = aarch64_get_mem_u16 (cpu, address);
10863 uint32_t val2 = aarch64_get_mem_u16 (cpu, address + 2);
10864 uint32_t val3 = aarch64_get_mem_u16 (cpu, address + 4);
10866 for (i = 0; i < (full ? 8 : 4); i++)
10868 aarch64_set_vec_u16 (cpu, vd, 0, val1);
10869 aarch64_set_vec_u16 (cpu, vd + 1, 0, val2);
10870 aarch64_set_vec_u16 (cpu, vd + 2, 0, val3);
10877 uint32_t val1 = aarch64_get_mem_u32 (cpu, address);
10878 uint32_t val2 = aarch64_get_mem_u32 (cpu, address + 4);
10879 uint32_t val3 = aarch64_get_mem_u32 (cpu, address + 8);
10881 for (i = 0; i < (full ? 4 : 2); i++)
10883 aarch64_set_vec_u32 (cpu, vd, 0, val1);
10884 aarch64_set_vec_u32 (cpu, vd + 1, 0, val2);
10885 aarch64_set_vec_u32 (cpu, vd + 2, 0, val3);
10892 uint64_t val1 = aarch64_get_mem_u64 (cpu, address);
10893 uint64_t val2 = aarch64_get_mem_u64 (cpu, address + 8);
10894 uint64_t val3 = aarch64_get_mem_u64 (cpu, address + 16);
10896 for (i = 0; i < (full ? 2 : 1); i++)
10898 aarch64_set_vec_u64 (cpu, vd, 0, val1);
10899 aarch64_set_vec_u64 (cpu, vd + 1, 0, val2);
10900 aarch64_set_vec_u64 (cpu, vd + 2, 0, val3);
10910 case 3: /* LD4R. */
10915 uint8_t val1 = aarch64_get_mem_u8 (cpu, address);
10916 uint8_t val2 = aarch64_get_mem_u8 (cpu, address + 1);
10917 uint8_t val3 = aarch64_get_mem_u8 (cpu, address + 2);
10918 uint8_t val4 = aarch64_get_mem_u8 (cpu, address + 3);
10920 for (i = 0; i < (full ? 16 : 8); i++)
10922 aarch64_set_vec_u8 (cpu, vd, 0, val1);
10923 aarch64_set_vec_u8 (cpu, vd + 1, 0, val2);
10924 aarch64_set_vec_u8 (cpu, vd + 2, 0, val3);
10925 aarch64_set_vec_u8 (cpu, vd + 3, 0, val4);
10932 uint32_t val1 = aarch64_get_mem_u16 (cpu, address);
10933 uint32_t val2 = aarch64_get_mem_u16 (cpu, address + 2);
10934 uint32_t val3 = aarch64_get_mem_u16 (cpu, address + 4);
10935 uint32_t val4 = aarch64_get_mem_u16 (cpu, address + 6);
10937 for (i = 0; i < (full ? 8 : 4); i++)
10939 aarch64_set_vec_u16 (cpu, vd, 0, val1);
10940 aarch64_set_vec_u16 (cpu, vd + 1, 0, val2);
10941 aarch64_set_vec_u16 (cpu, vd + 2, 0, val3);
10942 aarch64_set_vec_u16 (cpu, vd + 3, 0, val4);
10949 uint32_t val1 = aarch64_get_mem_u32 (cpu, address);
10950 uint32_t val2 = aarch64_get_mem_u32 (cpu, address + 4);
10951 uint32_t val3 = aarch64_get_mem_u32 (cpu, address + 8);
10952 uint32_t val4 = aarch64_get_mem_u32 (cpu, address + 12);
10954 for (i = 0; i < (full ? 4 : 2); i++)
10956 aarch64_set_vec_u32 (cpu, vd, 0, val1);
10957 aarch64_set_vec_u32 (cpu, vd + 1, 0, val2);
10958 aarch64_set_vec_u32 (cpu, vd + 2, 0, val3);
10959 aarch64_set_vec_u32 (cpu, vd + 3, 0, val4);
10966 uint64_t val1 = aarch64_get_mem_u64 (cpu, address);
10967 uint64_t val2 = aarch64_get_mem_u64 (cpu, address + 8);
10968 uint64_t val3 = aarch64_get_mem_u64 (cpu, address + 16);
10969 uint64_t val4 = aarch64_get_mem_u64 (cpu, address + 24);
10971 for (i = 0; i < (full ? 2 : 1); i++)
10973 aarch64_set_vec_u64 (cpu, vd, 0, val1);
10974 aarch64_set_vec_u64 (cpu, vd + 1, 0, val2);
10975 aarch64_set_vec_u64 (cpu, vd + 2, 0, val3);
10976 aarch64_set_vec_u64 (cpu, vd + 3, 0, val4);
10992 do_vec_load_store (sim_cpu *cpu)
10994 /* {LD|ST}<N> {Vd..Vd+N}, vaddr
10997 instr[30] = element selector 0=>half, 1=>all elements
10998 instr[29,25] = 00110
11000 instr[23] = 0=>simple, 1=>post
11001 instr[22] = 0=>store, 1=>load
11002 instr[21] = 0 (LDn) / small(0)-large(1) selector (LDnR)
11003 instr[20,16] = 00000 (simple), Vinc (reg-post-inc, no SP),
11004 11111 (immediate post inc)
11005 instr[15,12] = elements and destinations. eg for load:
11006 0000=>LD4 => load multiple 4-element to
11007 four consecutive registers
11008 0100=>LD3 => load multiple 3-element to
11009 three consecutive registers
11010 1000=>LD2 => load multiple 2-element to
11011 two consecutive registers
11012 0010=>LD1 => load multiple 1-element to
11013 four consecutive registers
11014 0110=>LD1 => load multiple 1-element to
11015 three consecutive registers
11016 1010=>LD1 => load multiple 1-element to
11017 two consecutive registers
11018 0111=>LD1 => load multiple 1-element to
11022 instr[11,10] = element size 00=> byte(b), 01=> half(h),
11023 10=> word(s), 11=> double(d)
11024 instr[9,5] = Vn, can be SP
11033 if (uimm (aarch64_get_instr (cpu), 31, 31) != 0
11034 || uimm (aarch64_get_instr (cpu), 29, 25) != 0x06)
11037 type = uimm (aarch64_get_instr (cpu), 15, 12);
11038 if (type != 0xE && type != 0xE && uimm (aarch64_get_instr (cpu), 21, 21) != 0)
11041 post = uimm (aarch64_get_instr (cpu), 23, 23);
11042 load = uimm (aarch64_get_instr (cpu), 22, 22);
11043 vn = uimm (aarch64_get_instr (cpu), 9, 5);
11044 address = aarch64_get_reg_u64 (cpu, vn, SP_OK);
11048 unsigned vm = uimm (aarch64_get_instr (cpu), 20, 16);
11052 unsigned sizeof_operation;
11056 case 0: sizeof_operation = 32; break;
11057 case 4: sizeof_operation = 24; break;
11058 case 8: sizeof_operation = 16; break;
11061 sizeof_operation = uimm (aarch64_get_instr (cpu), 21, 21) ? 2 : 1;
11062 sizeof_operation <<= uimm (aarch64_get_instr (cpu), 11, 10);
11066 sizeof_operation = uimm (aarch64_get_instr (cpu), 21, 21) ? 8 : 4;
11067 sizeof_operation <<= uimm (aarch64_get_instr (cpu), 11, 10);
11071 /* One register, immediate offset variant. */
11072 sizeof_operation = 8;
11076 /* Two registers, immediate offset variant. */
11077 sizeof_operation = 16;
11081 /* Three registers, immediate offset variant. */
11082 sizeof_operation = 24;
11086 /* Four registers, immediate offset variant. */
11087 sizeof_operation = 32;
11094 if (uimm (aarch64_get_instr (cpu), 30, 30))
11095 sizeof_operation *= 2;
11097 aarch64_set_reg_u64 (cpu, vn, SP_OK, address + sizeof_operation);
11100 aarch64_set_reg_u64 (cpu, vn, SP_OK,
11101 address + aarch64_get_reg_u64 (cpu, vm, NO_SP));
11105 NYI_assert (20, 16, 0);
11112 case 0: LD4 (cpu, address); return;
11113 case 4: LD3 (cpu, address); return;
11114 case 8: LD2 (cpu, address); return;
11115 case 2: LD1_4 (cpu, address); return;
11116 case 6: LD1_3 (cpu, address); return;
11117 case 10: LD1_2 (cpu, address); return;
11118 case 7: LD1_1 (cpu, address); return;
11121 case 0xC: do_vec_LDnR (cpu, address); return;
11131 case 0: ST4 (cpu, address); return;
11132 case 4: ST3 (cpu, address); return;
11133 case 8: ST2 (cpu, address); return;
11134 case 2: ST1_4 (cpu, address); return;
11135 case 6: ST1_3 (cpu, address); return;
11136 case 10: ST1_2 (cpu, address); return;
11137 case 7: ST1_1 (cpu, address); return;
11144 dexLdSt (sim_cpu *cpu)
11146 /* uint32_t group = dispatchGroup (aarch64_get_instr (cpu));
11147 assert group == GROUP_LDST_0100 || group == GROUP_LDST_0110 ||
11148 group == GROUP_LDST_1100 || group == GROUP_LDST_1110
11149 bits [29,28:26] of a LS are the secondary dispatch vector. */
11150 uint32_t group2 = dispatchLS (aarch64_get_instr (cpu));
11155 dexLoadExclusive (cpu); return;
11159 dexLoadLiteral (cpu); return;
11163 dexLoadOther (cpu); return;
11165 case LS_ADVSIMD_001:
11166 do_vec_load_store (cpu); return;
11169 dex_load_store_pair_gr (cpu); return;
11172 dex_load_store_pair_fp (cpu); return;
11175 /* Should never reach here. */
11180 /* Specific decode and execute for group Data Processing Register. */
11183 dexLogicalShiftedRegister (sim_cpu *cpu)
11185 /* assert instr[28:24] = 01010
11186 instr[31] = size : 0 ==> 32 bit, 1 ==> 64 bit
11187 instr[30,29:21] = op,N : 000 ==> AND, 001 ==> BIC,
11188 010 ==> ORR, 011 ==> ORN
11189 100 ==> EOR, 101 ==> EON,
11190 110 ==> ANDS, 111 ==> BICS
11191 instr[23,22] = shift : 0 ==> LSL, 1 ==> LSR, 2 ==> ASR, 3 ==> ROR
11192 instr[15,10] = count : must be 0xxxxx for 32 bit
11196 /* unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16); */
11199 uint32_t size = uimm (aarch64_get_instr (cpu), 31, 31);
11201 /* 32 bit operations must have count[5] = 0. */
11202 /* or else we have an UNALLOC. */
11203 uint32_t count = uimm (aarch64_get_instr (cpu), 15, 10);
11205 if (!size && uimm (count, 5, 5))
11208 shiftType = shift (aarch64_get_instr (cpu), 22);
11210 /* dispatch on size:op:N i.e aarch64_get_instr (cpu)[31,29:21]. */
11211 dispatch = ( (uimm (aarch64_get_instr (cpu), 31, 29) << 1)
11212 | uimm (aarch64_get_instr (cpu), 21, 21));
11216 case 0: and32_shift (cpu, shiftType, count); return;
11217 case 1: bic32_shift (cpu, shiftType, count); return;
11218 case 2: orr32_shift (cpu, shiftType, count); return;
11219 case 3: orn32_shift (cpu, shiftType, count); return;
11220 case 4: eor32_shift (cpu, shiftType, count); return;
11221 case 5: eon32_shift (cpu, shiftType, count); return;
11222 case 6: ands32_shift (cpu, shiftType, count); return;
11223 case 7: bics32_shift (cpu, shiftType, count); return;
11224 case 8: and64_shift (cpu, shiftType, count); return;
11225 case 9: bic64_shift (cpu, shiftType, count); return;
11226 case 10:orr64_shift (cpu, shiftType, count); return;
11227 case 11:orn64_shift (cpu, shiftType, count); return;
11228 case 12:eor64_shift (cpu, shiftType, count); return;
11229 case 13:eon64_shift (cpu, shiftType, count); return;
11230 case 14:ands64_shift (cpu, shiftType, count); return;
11231 case 15:bics64_shift (cpu, shiftType, count); return;
11232 default: HALT_UNALLOC;
11236 /* 32 bit conditional select. */
11238 csel32 (sim_cpu *cpu, CondCode cc)
11240 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
11241 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
11242 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
11244 aarch64_set_reg_u64 (cpu, rd, NO_SP,
11245 testConditionCode (cpu, cc)
11246 ? aarch64_get_reg_u32 (cpu, rn, NO_SP)
11247 : aarch64_get_reg_u32 (cpu, rm, NO_SP));
11250 /* 64 bit conditional select. */
11252 csel64 (sim_cpu *cpu, CondCode cc)
11254 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
11255 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
11256 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
11258 aarch64_set_reg_u64 (cpu, rd, NO_SP,
11259 testConditionCode (cpu, cc)
11260 ? aarch64_get_reg_u64 (cpu, rn, NO_SP)
11261 : aarch64_get_reg_u64 (cpu, rm, NO_SP));
11264 /* 32 bit conditional increment. */
11266 csinc32 (sim_cpu *cpu, CondCode cc)
11268 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
11269 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
11270 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
11272 aarch64_set_reg_u64 (cpu, rd, NO_SP,
11273 testConditionCode (cpu, cc)
11274 ? aarch64_get_reg_u32 (cpu, rn, NO_SP)
11275 : aarch64_get_reg_u32 (cpu, rm, NO_SP) + 1);
11278 /* 64 bit conditional increment. */
11280 csinc64 (sim_cpu *cpu, CondCode cc)
11282 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
11283 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
11284 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
11286 aarch64_set_reg_u64 (cpu, rd, NO_SP,
11287 testConditionCode (cpu, cc)
11288 ? aarch64_get_reg_u64 (cpu, rn, NO_SP)
11289 : aarch64_get_reg_u64 (cpu, rm, NO_SP) + 1);
11292 /* 32 bit conditional invert. */
11294 csinv32 (sim_cpu *cpu, CondCode cc)
11296 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
11297 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
11298 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
11300 aarch64_set_reg_u64 (cpu, rd, NO_SP,
11301 testConditionCode (cpu, cc)
11302 ? aarch64_get_reg_u32 (cpu, rn, NO_SP)
11303 : ~ aarch64_get_reg_u32 (cpu, rm, NO_SP));
11306 /* 64 bit conditional invert. */
11308 csinv64 (sim_cpu *cpu, CondCode cc)
11310 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
11311 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
11312 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
11314 aarch64_set_reg_u64 (cpu, rd, NO_SP,
11315 testConditionCode (cpu, cc)
11316 ? aarch64_get_reg_u64 (cpu, rn, NO_SP)
11317 : ~ aarch64_get_reg_u64 (cpu, rm, NO_SP));
11320 /* 32 bit conditional negate. */
11322 csneg32 (sim_cpu *cpu, CondCode cc)
11324 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
11325 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
11326 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
11328 aarch64_set_reg_u64 (cpu, rd, NO_SP,
11329 testConditionCode (cpu, cc)
11330 ? aarch64_get_reg_u32 (cpu, rn, NO_SP)
11331 : - aarch64_get_reg_u32 (cpu, rm, NO_SP));
11334 /* 64 bit conditional negate. */
11336 csneg64 (sim_cpu *cpu, CondCode cc)
11338 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
11339 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
11340 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
11342 aarch64_set_reg_u64 (cpu, rd, NO_SP,
11343 testConditionCode (cpu, cc)
11344 ? aarch64_get_reg_u64 (cpu, rn, NO_SP)
11345 : - aarch64_get_reg_u64 (cpu, rm, NO_SP));
11349 dexCondSelect (sim_cpu *cpu)
11351 /* assert instr[28,21] = 11011011
11352 instr[31] = size : 0 ==> 32 bit, 1 ==> 64 bit
11353 instr[30:11,10] = op : 000 ==> CSEL, 001 ==> CSINC,
11354 100 ==> CSINV, 101 ==> CSNEG,
11356 instr[29] = S : 0 ==> ok, 1 ==> UNALLOC
11357 instr[15,12] = cond
11358 instr[29] = S : 0 ==> ok, 1 ==> UNALLOC */
11362 uint32_t S = uimm (aarch64_get_instr (cpu), 29, 29);
11363 uint32_t op2 = uimm (aarch64_get_instr (cpu), 11, 10);
11371 cc = condcode (aarch64_get_instr (cpu), 12);
11372 dispatch = ((uimm (aarch64_get_instr (cpu), 31, 30) << 1) | op2);
11376 case 0: csel32 (cpu, cc); return;
11377 case 1: csinc32 (cpu, cc); return;
11378 case 2: csinv32 (cpu, cc); return;
11379 case 3: csneg32 (cpu, cc); return;
11380 case 4: csel64 (cpu, cc); return;
11381 case 5: csinc64 (cpu, cc); return;
11382 case 6: csinv64 (cpu, cc); return;
11383 case 7: csneg64 (cpu, cc); return;
11384 default: HALT_UNALLOC;
11388 /* Some helpers for counting leading 1 or 0 bits. */
11390 /* Counts the number of leading bits which are the same
11391 in a 32 bit value in the range 1 to 32. */
11393 leading32 (uint32_t value)
11395 int32_t mask= 0xffff0000;
11396 uint32_t count= 16; /* Counts number of bits set in mask. */
11397 uint32_t lo = 1; /* Lower bound for number of sign bits. */
11398 uint32_t hi = 32; /* Upper bound for number of sign bits. */
11400 while (lo + 1 < hi)
11402 int32_t test = (value & mask);
11404 if (test == 0 || test == mask)
11407 count = (lo + hi) / 2;
11408 mask >>= (count - lo);
11413 count = (lo + hi) / 2;
11414 mask <<= hi - count;
11423 test = (value & mask);
11425 if (test == 0 || test == mask)
11434 /* Counts the number of leading bits which are the same
11435 in a 64 bit value in the range 1 to 64. */
11437 leading64 (uint64_t value)
11439 int64_t mask= 0xffffffff00000000LL;
11440 uint64_t count = 32; /* Counts number of bits set in mask. */
11441 uint64_t lo = 1; /* Lower bound for number of sign bits. */
11442 uint64_t hi = 64; /* Upper bound for number of sign bits. */
11444 while (lo + 1 < hi)
11446 int64_t test = (value & mask);
11448 if (test == 0 || test == mask)
11451 count = (lo + hi) / 2;
11452 mask >>= (count - lo);
11457 count = (lo + hi) / 2;
11458 mask <<= hi - count;
11467 test = (value & mask);
11469 if (test == 0 || test == mask)
11478 /* Bit operations. */
11479 /* N.B register args may not be SP. */
11481 /* 32 bit count leading sign bits. */
11483 cls32 (sim_cpu *cpu)
11485 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
11486 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
11488 /* N.B. the result needs to exclude the leading bit. */
11489 aarch64_set_reg_u64
11490 (cpu, rd, NO_SP, leading32 (aarch64_get_reg_u32 (cpu, rn, NO_SP)) - 1);
11493 /* 64 bit count leading sign bits. */
11495 cls64 (sim_cpu *cpu)
11497 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
11498 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
11500 /* N.B. the result needs to exclude the leading bit. */
11501 aarch64_set_reg_u64
11502 (cpu, rd, NO_SP, leading64 (aarch64_get_reg_u64 (cpu, rn, NO_SP)) - 1);
11505 /* 32 bit count leading zero bits. */
11507 clz32 (sim_cpu *cpu)
11509 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
11510 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
11511 uint32_t value = aarch64_get_reg_u32 (cpu, rn, NO_SP);
11513 /* if the sign (top) bit is set then the count is 0. */
11514 if (pick32 (value, 31, 31))
11515 aarch64_set_reg_u64 (cpu, rd, NO_SP, 0L);
11517 aarch64_set_reg_u64 (cpu, rd, NO_SP, leading32 (value));
11520 /* 64 bit count leading zero bits. */
11522 clz64 (sim_cpu *cpu)
11524 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
11525 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
11526 uint64_t value = aarch64_get_reg_u64 (cpu, rn, NO_SP);
11528 /* if the sign (top) bit is set then the count is 0. */
11529 if (pick64 (value, 63, 63))
11530 aarch64_set_reg_u64 (cpu, rd, NO_SP, 0L);
11532 aarch64_set_reg_u64 (cpu, rd, NO_SP, leading64 (value));
11535 /* 32 bit reverse bits. */
11537 rbit32 (sim_cpu *cpu)
11539 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
11540 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
11541 uint32_t value = aarch64_get_reg_u32 (cpu, rn, NO_SP);
11542 uint32_t result = 0;
11545 for (i = 0; i < 32; i++)
11548 result |= (value & 1);
11551 aarch64_set_reg_u64 (cpu, rd, NO_SP, result);
11554 /* 64 bit reverse bits. */
11556 rbit64 (sim_cpu *cpu)
11558 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
11559 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
11560 uint64_t value = aarch64_get_reg_u64 (cpu, rn, NO_SP);
11561 uint64_t result = 0;
11564 for (i = 0; i < 64; i++)
11567 result |= (value & 1UL);
11570 aarch64_set_reg_u64 (cpu, rd, NO_SP, result);
11573 /* 32 bit reverse bytes. */
11575 rev32 (sim_cpu *cpu)
11577 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
11578 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
11579 uint32_t value = aarch64_get_reg_u32 (cpu, rn, NO_SP);
11580 uint32_t result = 0;
11583 for (i = 0; i < 4; i++)
11586 result |= (value & 0xff);
11589 aarch64_set_reg_u64 (cpu, rd, NO_SP, result);
11592 /* 64 bit reverse bytes. */
11594 rev64 (sim_cpu *cpu)
11596 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
11597 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
11598 uint64_t value = aarch64_get_reg_u64 (cpu, rn, NO_SP);
11599 uint64_t result = 0;
11602 for (i = 0; i < 8; i++)
11605 result |= (value & 0xffULL);
11608 aarch64_set_reg_u64 (cpu, rd, NO_SP, result);
11611 /* 32 bit reverse shorts. */
11612 /* N.B.this reverses the order of the bytes in each half word. */
11614 revh32 (sim_cpu *cpu)
11616 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
11617 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
11618 uint32_t value = aarch64_get_reg_u32 (cpu, rn, NO_SP);
11619 uint32_t result = 0;
11622 for (i = 0; i < 2; i++)
11625 result |= (value & 0x00ff00ff);
11628 aarch64_set_reg_u64 (cpu, rd, NO_SP, result);
11631 /* 64 bit reverse shorts. */
11632 /* N.B.this reverses the order of the bytes in each half word. */
11634 revh64 (sim_cpu *cpu)
11636 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
11637 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
11638 uint64_t value = aarch64_get_reg_u64 (cpu, rn, NO_SP);
11639 uint64_t result = 0;
11642 for (i = 0; i < 2; i++)
11645 result |= (value & 0x00ff00ff00ff00ffULL);
11648 aarch64_set_reg_u64 (cpu, rd, NO_SP, result);
11652 dexDataProc1Source (sim_cpu *cpu)
11654 /* assert instr[30] == 1
11655 aarch64_get_instr (cpu)[28,21] == 111010110
11656 instr[31] = size : 0 ==> 32 bit, 1 ==> 64 bit
11657 instr[29] = S : 0 ==> ok, 1 ==> UNALLOC
11658 instr[20,16] = opcode2 : 00000 ==> ok, ow ==> UNALLOC
11659 instr[15,10] = opcode : 000000 ==> RBIT, 000001 ==> REV16,
11660 000010 ==> REV, 000011 ==> UNALLOC
11661 000100 ==> CLZ, 000101 ==> CLS
11663 instr[9,5] = rn : may not be SP
11664 instr[4,0] = rd : may not be SP. */
11666 uint32_t S = uimm (aarch64_get_instr (cpu), 29, 29);
11667 uint32_t opcode2 = uimm (aarch64_get_instr (cpu), 20, 16);
11668 uint32_t opcode = uimm (aarch64_get_instr (cpu), 15, 10);
11669 uint32_t dispatch = ((uimm (aarch64_get_instr (cpu), 31, 31) << 3) | opcode);
11682 case 0: rbit32 (cpu); return;
11683 case 1: revh32 (cpu); return;
11684 case 2: rev32 (cpu); return;
11685 case 4: clz32 (cpu); return;
11686 case 5: cls32 (cpu); return;
11687 case 8: rbit64 (cpu); return;
11688 case 9: revh64 (cpu); return;
11689 case 10:rev32 (cpu); return;
11690 case 11:rev64 (cpu); return;
11691 case 12:clz64 (cpu); return;
11692 case 13:cls64 (cpu); return;
11693 default: HALT_UNALLOC;
11698 Shifts by count supplied in register.
11699 N.B register args may not be SP.
11700 These all use the shifted auxiliary function for
11701 simplicity and clarity. Writing the actual shift
11702 inline would avoid a branch and so be faster but
11703 would also necessitate getting signs right. */
11705 /* 32 bit arithmetic shift right. */
11707 asrv32 (sim_cpu *cpu)
11709 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
11710 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
11711 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
11713 aarch64_set_reg_u64
11715 shifted32 (aarch64_get_reg_u32 (cpu, rn, NO_SP), ASR,
11716 (aarch64_get_reg_u32 (cpu, rm, NO_SP) & 0x1f)));
11719 /* 64 bit arithmetic shift right. */
11721 asrv64 (sim_cpu *cpu)
11723 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
11724 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
11725 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
11727 aarch64_set_reg_u64
11729 shifted64 (aarch64_get_reg_u64 (cpu, rn, NO_SP), ASR,
11730 (aarch64_get_reg_u64 (cpu, rm, NO_SP) & 0x3f)));
11733 /* 32 bit logical shift left. */
11735 lslv32 (sim_cpu *cpu)
11737 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
11738 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
11739 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
11741 aarch64_set_reg_u64
11743 shifted32 (aarch64_get_reg_u32 (cpu, rn, NO_SP), LSL,
11744 (aarch64_get_reg_u32 (cpu, rm, NO_SP) & 0x1f)));
11747 /* 64 bit arithmetic shift left. */
11749 lslv64 (sim_cpu *cpu)
11751 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
11752 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
11753 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
11755 aarch64_set_reg_u64
11757 shifted64 (aarch64_get_reg_u64 (cpu, rn, NO_SP), LSL,
11758 (aarch64_get_reg_u64 (cpu, rm, NO_SP) & 0x3f)));
11761 /* 32 bit logical shift right. */
11763 lsrv32 (sim_cpu *cpu)
11765 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
11766 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
11767 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
11769 aarch64_set_reg_u64
11771 shifted32 (aarch64_get_reg_u32 (cpu, rn, NO_SP), LSR,
11772 (aarch64_get_reg_u32 (cpu, rm, NO_SP) & 0x1f)));
11775 /* 64 bit logical shift right. */
11777 lsrv64 (sim_cpu *cpu)
11779 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
11780 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
11781 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
11783 aarch64_set_reg_u64
11785 shifted64 (aarch64_get_reg_u64 (cpu, rn, NO_SP), LSR,
11786 (aarch64_get_reg_u64 (cpu, rm, NO_SP) & 0x3f)));
11789 /* 32 bit rotate right. */
11791 rorv32 (sim_cpu *cpu)
11793 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
11794 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
11795 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
11797 aarch64_set_reg_u64
11799 shifted32 (aarch64_get_reg_u32 (cpu, rn, NO_SP), ROR,
11800 (aarch64_get_reg_u32 (cpu, rm, NO_SP) & 0x1f)));
11803 /* 64 bit rotate right. */
11805 rorv64 (sim_cpu *cpu)
11807 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
11808 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
11809 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
11811 aarch64_set_reg_u64
11813 shifted64 (aarch64_get_reg_u64 (cpu, rn, NO_SP), ROR,
11814 (aarch64_get_reg_u64 (cpu, rm, NO_SP) & 0x3f)));
11820 /* 32 bit signed divide. */
11822 cpuiv32 (sim_cpu *cpu)
11824 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
11825 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
11826 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
11827 /* N.B. the pseudo-code does the divide using 64 bit data. */
11828 /* TODO : check that this rounds towards zero as required. */
11829 int64_t dividend = aarch64_get_reg_s32 (cpu, rn, NO_SP);
11830 int64_t divisor = aarch64_get_reg_s32 (cpu, rm, NO_SP);
11832 aarch64_set_reg_s64 (cpu, rd, NO_SP,
11833 divisor ? ((int32_t) (dividend / divisor)) : 0);
11836 /* 64 bit signed divide. */
11838 cpuiv64 (sim_cpu *cpu)
11840 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
11841 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
11842 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
11844 /* TODO : check that this rounds towards zero as required. */
11845 int64_t divisor = aarch64_get_reg_s64 (cpu, rm, NO_SP);
11847 aarch64_set_reg_s64
11849 divisor ? (aarch64_get_reg_s64 (cpu, rn, NO_SP) / divisor) : 0);
11852 /* 32 bit unsigned divide. */
11854 udiv32 (sim_cpu *cpu)
11856 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
11857 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
11858 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
11860 /* N.B. the pseudo-code does the divide using 64 bit data. */
11861 uint64_t dividend = aarch64_get_reg_u32 (cpu, rn, NO_SP);
11862 uint64_t divisor = aarch64_get_reg_u32 (cpu, rm, NO_SP);
11864 aarch64_set_reg_u64 (cpu, rd, NO_SP,
11865 divisor ? (uint32_t) (dividend / divisor) : 0);
11868 /* 64 bit unsigned divide. */
11870 udiv64 (sim_cpu *cpu)
11872 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
11873 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
11874 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
11876 /* TODO : check that this rounds towards zero as required. */
11877 uint64_t divisor = aarch64_get_reg_u64 (cpu, rm, NO_SP);
11879 aarch64_set_reg_u64
11881 divisor ? (aarch64_get_reg_u64 (cpu, rn, NO_SP) / divisor) : 0);
11885 dexDataProc2Source (sim_cpu *cpu)
11887 /* assert instr[30] == 0
11888 instr[28,21] == 11010110
11889 instr[31] = size : 0 ==> 32 bit, 1 ==> 64 bit
11890 instr[29] = S : 0 ==> ok, 1 ==> UNALLOC
11891 instr[15,10] = opcode : 000010 ==> UDIV, 000011 ==> CPUIV,
11892 001000 ==> LSLV, 001001 ==> LSRV
11893 001010 ==> ASRV, 001011 ==> RORV
11897 uint32_t S = uimm (aarch64_get_instr (cpu), 29, 29);
11898 uint32_t opcode = uimm (aarch64_get_instr (cpu), 15, 10);
11906 dispatch = ( (uimm (aarch64_get_instr (cpu), 31, 31) << 3)
11907 | (uimm (opcode, 3, 3) << 2)
11908 | uimm (opcode, 1, 0));
11911 case 2: udiv32 (cpu); return;
11912 case 3: cpuiv32 (cpu); return;
11913 case 4: lslv32 (cpu); return;
11914 case 5: lsrv32 (cpu); return;
11915 case 6: asrv32 (cpu); return;
11916 case 7: rorv32 (cpu); return;
11917 case 10: udiv64 (cpu); return;
11918 case 11: cpuiv64 (cpu); return;
11919 case 12: lslv64 (cpu); return;
11920 case 13: lsrv64 (cpu); return;
11921 case 14: asrv64 (cpu); return;
11922 case 15: rorv64 (cpu); return;
11923 default: HALT_UNALLOC;
11930 /* 32 bit multiply and add. */
11932 madd32 (sim_cpu *cpu)
11934 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
11935 unsigned ra = uimm (aarch64_get_instr (cpu), 14, 10);
11936 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
11937 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
11939 aarch64_set_reg_u64 (cpu, rd, NO_SP,
11940 aarch64_get_reg_u32 (cpu, ra, NO_SP)
11941 + aarch64_get_reg_u32 (cpu, rn, NO_SP)
11942 * aarch64_get_reg_u32 (cpu, rm, NO_SP));
11945 /* 64 bit multiply and add. */
11947 madd64 (sim_cpu *cpu)
11949 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
11950 unsigned ra = uimm (aarch64_get_instr (cpu), 14, 10);
11951 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
11952 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
11954 aarch64_set_reg_u64 (cpu, rd, NO_SP,
11955 aarch64_get_reg_u64 (cpu, ra, NO_SP)
11956 + aarch64_get_reg_u64 (cpu, rn, NO_SP)
11957 * aarch64_get_reg_u64 (cpu, rm, NO_SP));
11960 /* 32 bit multiply and sub. */
11962 msub32 (sim_cpu *cpu)
11964 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
11965 unsigned ra = uimm (aarch64_get_instr (cpu), 14, 10);
11966 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
11967 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
11969 aarch64_set_reg_u64 (cpu, rd, NO_SP,
11970 aarch64_get_reg_u32 (cpu, ra, NO_SP)
11971 - aarch64_get_reg_u32 (cpu, rn, NO_SP)
11972 * aarch64_get_reg_u32 (cpu, rm, NO_SP));
11975 /* 64 bit multiply and sub. */
11977 msub64 (sim_cpu *cpu)
11979 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
11980 unsigned ra = uimm (aarch64_get_instr (cpu), 14, 10);
11981 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
11982 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
11984 aarch64_set_reg_u64 (cpu, rd, NO_SP,
11985 aarch64_get_reg_u64 (cpu, ra, NO_SP)
11986 - aarch64_get_reg_u64 (cpu, rn, NO_SP)
11987 * aarch64_get_reg_u64 (cpu, rm, NO_SP));
11990 /* Signed multiply add long -- source, source2 : 32 bit, source3 : 64 bit. */
11992 smaddl (sim_cpu *cpu)
11994 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
11995 unsigned ra = uimm (aarch64_get_instr (cpu), 14, 10);
11996 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
11997 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
11999 /* N.B. we need to multiply the signed 32 bit values in rn, rm to
12000 obtain a 64 bit product. */
12001 aarch64_set_reg_s64
12003 aarch64_get_reg_s64 (cpu, ra, NO_SP)
12004 + ((int64_t) aarch64_get_reg_s32 (cpu, rn, NO_SP))
12005 * ((int64_t) aarch64_get_reg_s32 (cpu, rm, NO_SP)));
12008 /* Signed multiply sub long -- source, source2 : 32 bit, source3 : 64 bit. */
12010 smsubl (sim_cpu *cpu)
12012 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
12013 unsigned ra = uimm (aarch64_get_instr (cpu), 14, 10);
12014 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
12015 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
12017 /* N.B. we need to multiply the signed 32 bit values in rn, rm to
12018 obtain a 64 bit product. */
12019 aarch64_set_reg_s64
12021 aarch64_get_reg_s64 (cpu, ra, NO_SP)
12022 - ((int64_t) aarch64_get_reg_s32 (cpu, rn, NO_SP))
12023 * ((int64_t) aarch64_get_reg_s32 (cpu, rm, NO_SP)));
12026 /* Integer Multiply/Divide. */
12028 /* First some macros and a helper function. */
12029 /* Macros to test or access elements of 64 bit words. */
12031 /* Mask used to access lo 32 bits of 64 bit unsigned int. */
12032 #define LOW_WORD_MASK ((1ULL << 32) - 1)
12033 /* Return the lo 32 bit word of a 64 bit unsigned int as a 64 bit unsigned int. */
12034 #define lowWordToU64(_value_u64) ((_value_u64) & LOW_WORD_MASK)
12035 /* Return the hi 32 bit word of a 64 bit unsigned int as a 64 bit unsigned int. */
12036 #define highWordToU64(_value_u64) ((_value_u64) >> 32)
12038 /* Offset of sign bit in 64 bit signed integger. */
12039 #define SIGN_SHIFT_U64 63
12040 /* The sign bit itself -- also identifies the minimum negative int value. */
12041 #define SIGN_BIT_U64 (1UL << SIGN_SHIFT_U64)
12042 /* Return true if a 64 bit signed int presented as an unsigned int is the
12043 most negative value. */
12044 #define isMinimumU64(_value_u64) ((_value_u64) == SIGN_BIT_U64)
12045 /* Return true (non-zero) if a 64 bit signed int presented as an unsigned
12046 int has its sign bit set to false. */
12047 #define isSignSetU64(_value_u64) ((_value_u64) & SIGN_BIT_U64)
12048 /* Return 1L or -1L according to whether a 64 bit signed int presented as
12049 an unsigned int has its sign bit set or not. */
12050 #define signOfU64(_value_u64) (1L + (((value_u64) >> SIGN_SHIFT_U64) * -2L)
12051 /* Clear the sign bit of a 64 bit signed int presented as an unsigned int. */
12052 #define clearSignU64(_value_u64) ((_value_u64) &= ~SIGN_BIT_U64)
12054 /* Multiply two 64 bit ints and return.
12055 the hi 64 bits of the 128 bit product. */
12058 mul64hi (uint64_t value1, uint64_t value2)
12060 uint64_t resultmid1;
12062 uint64_t value1_lo = lowWordToU64 (value1);
12063 uint64_t value1_hi = highWordToU64 (value1) ;
12064 uint64_t value2_lo = lowWordToU64 (value2);
12065 uint64_t value2_hi = highWordToU64 (value2);
12067 /* Cross-multiply and collect results. */
12069 uint64_t xproductlo = value1_lo * value2_lo;
12070 uint64_t xproductmid1 = value1_lo * value2_hi;
12071 uint64_t xproductmid2 = value1_hi * value2_lo;
12072 uint64_t xproducthi = value1_hi * value2_hi;
12073 uint64_t carry = 0;
12074 /* Start accumulating 64 bit results. */
12075 /* Drop bottom half of lowest cross-product. */
12076 uint64_t resultmid = xproductlo >> 32;
12077 /* Add in middle products. */
12078 resultmid = resultmid + xproductmid1;
12080 /* Check for overflow. */
12081 if (resultmid < xproductmid1)
12082 /* Carry over 1 into top cross-product. */
12085 resultmid1 = resultmid + xproductmid2;
12087 /* Check for overflow. */
12088 if (resultmid1 < xproductmid2)
12089 /* Carry over 1 into top cross-product. */
12092 /* Drop lowest 32 bits of middle cross-product. */
12093 result = resultmid1 >> 32;
12095 /* Add top cross-product plus and any carry. */
12096 result += xproducthi + carry;
12101 /* Signed multiply high, source, source2 :
12102 64 bit, dest <-- high 64-bit of result. */
12104 smulh (sim_cpu *cpu)
12108 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
12109 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
12110 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
12111 GReg ra = greg (aarch64_get_instr (cpu), 10);
12112 int64_t value1 = aarch64_get_reg_u64 (cpu, rn, NO_SP);
12113 int64_t value2 = aarch64_get_reg_u64 (cpu, rm, NO_SP);
12116 int64_t signum = 1;
12121 /* Convert to unsigned and use the unsigned mul64hi routine
12122 the fix the sign up afterwards. */
12143 uresult = mul64hi (uvalue1, uvalue2);
12147 aarch64_set_reg_s64 (cpu, rd, NO_SP, result);
12150 /* Unsigned multiply add long -- source, source2 :
12151 32 bit, source3 : 64 bit. */
12153 umaddl (sim_cpu *cpu)
12155 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
12156 unsigned ra = uimm (aarch64_get_instr (cpu), 14, 10);
12157 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
12158 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
12160 /* N.B. we need to multiply the signed 32 bit values in rn, rm to
12161 obtain a 64 bit product. */
12162 aarch64_set_reg_u64
12164 aarch64_get_reg_u64 (cpu, ra, NO_SP)
12165 + ((uint64_t) aarch64_get_reg_u32 (cpu, rn, NO_SP))
12166 * ((uint64_t) aarch64_get_reg_u32 (cpu, rm, NO_SP)));
12169 /* Unsigned multiply sub long -- source, source2 : 32 bit, source3 : 64 bit. */
12171 umsubl (sim_cpu *cpu)
12173 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
12174 unsigned ra = uimm (aarch64_get_instr (cpu), 14, 10);
12175 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
12176 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
12178 /* N.B. we need to multiply the signed 32 bit values in rn, rm to
12179 obtain a 64 bit product. */
12180 aarch64_set_reg_u64
12182 aarch64_get_reg_u64 (cpu, ra, NO_SP)
12183 - ((uint64_t) aarch64_get_reg_u32 (cpu, rn, NO_SP))
12184 * ((uint64_t) aarch64_get_reg_u32 (cpu, rm, NO_SP)));
12187 /* Unsigned multiply high, source, source2 :
12188 64 bit, dest <-- high 64-bit of result. */
12190 umulh (sim_cpu *cpu)
12192 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
12193 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
12194 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
12195 GReg ra = greg (aarch64_get_instr (cpu), 10);
12200 aarch64_set_reg_u64 (cpu, rd, NO_SP,
12201 mul64hi (aarch64_get_reg_u64 (cpu, rn, NO_SP),
12202 aarch64_get_reg_u64 (cpu, rm, NO_SP)));
12206 dexDataProc3Source (sim_cpu *cpu)
12208 /* assert instr[28,24] == 11011. */
12209 /* instr[31] = size : 0 ==> 32 bit, 1 ==> 64 bit (for rd at least)
12210 instr[30,29] = op54 : 00 ==> ok, ow ==> UNALLOC
12211 instr[23,21] = op31 : 111 ==> UNALLOC, o2 ==> ok
12212 instr[15] = o0 : 0/1 ==> ok
12213 instr[23,21:15] ==> op : 0000 ==> MADD, 0001 ==> MSUB, (32/64 bit)
12214 0010 ==> SMADDL, 0011 ==> SMSUBL, (64 bit only)
12215 0100 ==> SMULH, (64 bit only)
12216 1010 ==> UMADDL, 1011 ==> UNSUBL, (64 bit only)
12217 1100 ==> UMULH (64 bit only)
12221 uint32_t size = uimm (aarch64_get_instr (cpu), 31, 31);
12222 uint32_t op54 = uimm (aarch64_get_instr (cpu), 30, 29);
12223 uint32_t op31 = uimm (aarch64_get_instr (cpu), 23, 21);
12224 uint32_t o0 = uimm (aarch64_get_instr (cpu), 15, 15);
12241 dispatch = (op31 << 1) | o0;
12245 case 0: madd64 (cpu); return;
12246 case 1: msub64 (cpu); return;
12247 case 2: smaddl (cpu); return;
12248 case 3: smsubl (cpu); return;
12249 case 4: smulh (cpu); return;
12250 case 10: umaddl (cpu); return;
12251 case 11: umsubl (cpu); return;
12252 case 12: umulh (cpu); return;
12253 default: HALT_UNALLOC;
12258 dexDPReg (sim_cpu *cpu)
12260 /* uint32_t group = dispatchGroup (aarch64_get_instr (cpu));
12261 assert group == GROUP_DPREG_0101 || group == GROUP_DPREG_1101
12262 bits [28:24:21] of a DPReg are the secondary dispatch vector. */
12263 uint32_t group2 = dispatchDPReg (aarch64_get_instr (cpu));
12267 case DPREG_LOG_000:
12268 case DPREG_LOG_001:
12269 dexLogicalShiftedRegister (cpu); return;
12271 case DPREG_ADDSHF_010:
12272 dexAddSubtractShiftedRegister (cpu); return;
12274 case DPREG_ADDEXT_011:
12275 dexAddSubtractExtendedRegister (cpu); return;
12277 case DPREG_ADDCOND_100:
12279 /* This set bundles a variety of different operations. */
12281 /* 1) add/sub w carry. */
12282 uint32_t mask1 = 0x1FE00000U;
12283 uint32_t val1 = 0x1A000000U;
12284 /* 2) cond compare register/immediate. */
12285 uint32_t mask2 = 0x1FE00000U;
12286 uint32_t val2 = 0x1A400000U;
12287 /* 3) cond select. */
12288 uint32_t mask3 = 0x1FE00000U;
12289 uint32_t val3 = 0x1A800000U;
12290 /* 4) data proc 1/2 source. */
12291 uint32_t mask4 = 0x1FE00000U;
12292 uint32_t val4 = 0x1AC00000U;
12294 if ((aarch64_get_instr (cpu) & mask1) == val1)
12295 dexAddSubtractWithCarry (cpu);
12297 else if ((aarch64_get_instr (cpu) & mask2) == val2)
12300 else if ((aarch64_get_instr (cpu) & mask3) == val3)
12301 dexCondSelect (cpu);
12303 else if ((aarch64_get_instr (cpu) & mask4) == val4)
12305 /* Bit 30 is clear for data proc 2 source
12306 and set for data proc 1 source. */
12307 if (aarch64_get_instr (cpu) & (1U << 30))
12308 dexDataProc1Source (cpu);
12310 dexDataProc2Source (cpu);
12314 /* Should not reach here. */
12320 case DPREG_3SRC_110:
12321 dexDataProc3Source (cpu); return;
12323 case DPREG_UNALLOC_101:
12326 case DPREG_3SRC_111:
12327 dexDataProc3Source (cpu); return;
12330 /* Should never reach here. */
12335 /* Unconditional Branch immediate.
12336 Offset is a PC-relative byte offset in the range +/- 128MiB.
12337 The offset is assumed to be raw from the decode i.e. the
12338 simulator is expected to scale them from word offsets to byte. */
12340 /* Unconditional branch. */
12342 buc (sim_cpu *cpu, int32_t offset)
12344 aarch64_set_next_PC_by_offset (cpu, offset);
12347 static unsigned stack_depth = 0;
12349 /* Unconditional branch and link -- writes return PC to LR. */
12351 bl (sim_cpu *cpu, int32_t offset)
12353 aarch64_save_LR (cpu);
12354 aarch64_set_next_PC_by_offset (cpu, offset);
12356 if (TRACE_BRANCH_P (cpu))
12360 " %*scall %" PRIx64 " [%s]"
12361 " [args: %" PRIx64 " %" PRIx64 " %" PRIx64 "]",
12362 stack_depth, " ", aarch64_get_next_PC (cpu),
12363 aarch64_get_func (aarch64_get_next_PC (cpu)),
12364 aarch64_get_reg_u64 (cpu, 0, NO_SP),
12365 aarch64_get_reg_u64 (cpu, 1, NO_SP),
12366 aarch64_get_reg_u64 (cpu, 2, NO_SP)
12371 /* Unconditional Branch register.
12372 Branch/return address is in source register. */
12374 /* Unconditional branch. */
12378 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
12379 aarch64_set_next_PC (cpu, aarch64_get_reg_u64 (cpu, rn, NO_SP));
12382 /* Unconditional branch and link -- writes return PC to LR. */
12386 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
12388 /* The pseudo code in the spec says we update LR before fetching.
12389 the value from the rn. */
12390 aarch64_save_LR (cpu);
12391 aarch64_set_next_PC (cpu, aarch64_get_reg_u64 (cpu, rn, NO_SP));
12393 if (TRACE_BRANCH_P (cpu))
12397 " %*scall %" PRIx64 " [%s]"
12398 " [args: %" PRIx64 " %" PRIx64 " %" PRIx64 "]",
12399 stack_depth, " ", aarch64_get_next_PC (cpu),
12400 aarch64_get_func (aarch64_get_next_PC (cpu)),
12401 aarch64_get_reg_u64 (cpu, 0, NO_SP),
12402 aarch64_get_reg_u64 (cpu, 1, NO_SP),
12403 aarch64_get_reg_u64 (cpu, 2, NO_SP)
12408 /* Return -- assembler will default source to LR this is functionally
12409 equivalent to br but, presumably, unlike br it side effects the
12410 branch predictor. */
12414 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
12415 aarch64_set_next_PC (cpu, aarch64_get_reg_u64 (cpu, rn, NO_SP));
12417 if (TRACE_BRANCH_P (cpu))
12420 " %*sreturn [result: %" PRIx64 "]",
12421 stack_depth, " ", aarch64_get_reg_u64 (cpu, 0, NO_SP));
12426 /* NOP -- we implement this and call it from the decode in case we
12427 want to intercept it later. */
12434 /* Data synchronization barrier. */
12441 /* Data memory barrier. */
12448 /* Instruction synchronization barrier. */
12456 dexBranchImmediate (sim_cpu *cpu)
12458 /* assert instr[30,26] == 00101
12459 instr[31] ==> 0 == B, 1 == BL
12460 instr[25,0] == imm26 branch offset counted in words. */
12462 uint32_t top = uimm (aarch64_get_instr (cpu), 31, 31);
12463 /* We have a 26 byte signed word offset which we need to pass to the
12464 execute routine as a signed byte offset. */
12465 int32_t offset = simm32 (aarch64_get_instr (cpu), 25, 0) << 2;
12473 /* Control Flow. */
12475 /* Conditional branch
12477 Offset is a PC-relative byte offset in the range +/- 1MiB pos is
12478 a bit position in the range 0 .. 63
12480 cc is a CondCode enum value as pulled out of the decode
12482 N.B. any offset register (source) can only be Xn or Wn. */
12485 bcc (sim_cpu *cpu, int32_t offset, CondCode cc)
12487 /* the test returns TRUE if CC is met. */
12488 if (testConditionCode (cpu, cc))
12489 aarch64_set_next_PC_by_offset (cpu, offset);
12492 /* 32 bit branch on register non-zero. */
12494 cbnz32 (sim_cpu *cpu, int32_t offset)
12496 unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
12498 if (aarch64_get_reg_u32 (cpu, rt, NO_SP) != 0)
12499 aarch64_set_next_PC_by_offset (cpu, offset);
12502 /* 64 bit branch on register zero. */
12504 cbnz (sim_cpu *cpu, int32_t offset)
12506 unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
12508 if (aarch64_get_reg_u64 (cpu, rt, NO_SP) != 0)
12509 aarch64_set_next_PC_by_offset (cpu, offset);
12512 /* 32 bit branch on register non-zero. */
12514 cbz32 (sim_cpu *cpu, int32_t offset)
12516 unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
12518 if (aarch64_get_reg_u32 (cpu, rt, NO_SP) == 0)
12519 aarch64_set_next_PC_by_offset (cpu, offset);
12522 /* 64 bit branch on register zero. */
12524 cbz (sim_cpu *cpu, int32_t offset)
12526 unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
12528 if (aarch64_get_reg_u64 (cpu, rt, NO_SP) == 0)
12529 aarch64_set_next_PC_by_offset (cpu, offset);
12532 /* Branch on register bit test non-zero -- one size fits all. */
12534 tbnz (sim_cpu *cpu, uint32_t pos, int32_t offset)
12536 unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
12538 if (aarch64_get_reg_u64 (cpu, rt, NO_SP) & (1 << pos))
12539 aarch64_set_next_PC_by_offset (cpu, offset);
12542 /* branch on register bit test zero -- one size fits all. */
12544 tbz (sim_cpu *cpu, uint32_t pos, int32_t offset)
12546 unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
12548 if (!(aarch64_get_reg_u64 (cpu, rt, NO_SP) & (1 << pos)))
12549 aarch64_set_next_PC_by_offset (cpu, offset);
12553 dexCompareBranchImmediate (sim_cpu *cpu)
12555 /* instr[30,25] = 01 1010
12556 instr[31] = size : 0 ==> 32, 1 ==> 64
12557 instr[24] = op : 0 ==> CBZ, 1 ==> CBNZ
12558 instr[23,5] = simm19 branch offset counted in words
12561 uint32_t size = uimm (aarch64_get_instr (cpu), 31, 31);
12562 uint32_t op = uimm (aarch64_get_instr (cpu), 24, 24);
12563 int32_t offset = simm32 (aarch64_get_instr (cpu), 23, 5) << 2;
12568 cbz32 (cpu, offset);
12570 cbnz32 (cpu, offset);
12577 cbnz (cpu, offset);
12582 dexTestBranchImmediate (sim_cpu *cpu)
12584 /* instr[31] = b5 : bit 5 of test bit idx
12585 instr[30,25] = 01 1011
12586 instr[24] = op : 0 ==> TBZ, 1 == TBNZ
12587 instr[23,19] = b40 : bits 4 to 0 of test bit idx
12588 instr[18,5] = simm14 : signed offset counted in words
12589 instr[4,0] = uimm5 */
12591 uint32_t pos = ((uimm (aarch64_get_instr (cpu), 31, 31) << 4)
12592 | uimm (aarch64_get_instr (cpu), 23,19));
12593 int32_t offset = simm32 (aarch64_get_instr (cpu), 18, 5) << 2;
12595 NYI_assert (30, 25, 0x1b);
12597 if (uimm (aarch64_get_instr (cpu), 24, 24) == 0)
12598 tbz (cpu, pos, offset);
12600 tbnz (cpu, pos, offset);
12604 dexCondBranchImmediate (sim_cpu *cpu)
12606 /* instr[31,25] = 010 1010
12607 instr[24] = op1; op => 00 ==> B.cond
12608 instr[23,5] = simm19 : signed offset counted in words
12610 instr[3,0] = cond */
12614 uint32_t op = ((uimm (aarch64_get_instr (cpu), 24, 24) << 1)
12615 | uimm (aarch64_get_instr (cpu), 4, 4));
12617 NYI_assert (31, 25, 0x2a);
12622 offset = simm32 (aarch64_get_instr (cpu), 23, 5) << 2;
12623 cc = condcode (aarch64_get_instr (cpu), 0);
12625 bcc (cpu, offset, cc);
12629 dexBranchRegister (sim_cpu *cpu)
12631 /* instr[31,25] = 110 1011
12632 instr[24,21] = op : 0 ==> BR, 1 => BLR, 2 => RET, 3 => ERET, 4 => DRPS
12633 instr[20,16] = op2 : must be 11111
12634 instr[15,10] = op3 : must be 000000
12635 instr[4,0] = op2 : must be 11111. */
12637 uint32_t op = uimm (aarch64_get_instr (cpu), 24, 21);
12638 uint32_t op2 = uimm (aarch64_get_instr (cpu), 20, 16);
12639 uint32_t op3 = uimm (aarch64_get_instr (cpu), 15, 10);
12640 uint32_t op4 = uimm (aarch64_get_instr (cpu), 4, 0);
12642 NYI_assert (31, 25, 0x6b);
12644 if (op2 != 0x1F || op3 != 0 || op4 != 0)
12658 /* ERET and DRPS accept 0b11111 for rn = aarch64_get_instr (cpu)[4,0]. */
12659 /* anything else is unallocated. */
12660 uint32_t rn = greg (aarch64_get_instr (cpu), 0);
12665 if (op == 4 || op == 5)
12672 /* FIXME: We should get the Angel SWI values from ../../libgloss/aarch64/svc.h
12673 but this may not be available. So instead we define the values we need
12675 #define AngelSVC_Reason_Open 0x01
12676 #define AngelSVC_Reason_Close 0x02
12677 #define AngelSVC_Reason_Write 0x05
12678 #define AngelSVC_Reason_Read 0x06
12679 #define AngelSVC_Reason_IsTTY 0x09
12680 #define AngelSVC_Reason_Seek 0x0A
12681 #define AngelSVC_Reason_FLen 0x0C
12682 #define AngelSVC_Reason_Remove 0x0E
12683 #define AngelSVC_Reason_Rename 0x0F
12684 #define AngelSVC_Reason_Clock 0x10
12685 #define AngelSVC_Reason_Time 0x11
12686 #define AngelSVC_Reason_System 0x12
12687 #define AngelSVC_Reason_Errno 0x13
12688 #define AngelSVC_Reason_GetCmdLine 0x15
12689 #define AngelSVC_Reason_HeapInfo 0x16
12690 #define AngelSVC_Reason_ReportException 0x18
12691 #define AngelSVC_Reason_Elapsed 0x30
12695 handle_halt (sim_cpu *cpu, uint32_t val)
12697 uint64_t result = 0;
12701 TRACE_SYSCALL (cpu, " HLT [0x%x]", val);
12702 sim_engine_halt (CPU_STATE (cpu), cpu, NULL, aarch64_get_PC (cpu),
12703 sim_stopped, SIM_SIGTRAP);
12706 /* We have encountered an Angel SVC call. See if we can process it. */
12707 switch (aarch64_get_reg_u32 (cpu, 0, NO_SP))
12709 case AngelSVC_Reason_HeapInfo:
12711 /* Get the values. */
12712 uint64_t stack_top = aarch64_get_stack_start (cpu);
12713 uint64_t heap_base = aarch64_get_heap_start (cpu);
12715 /* Get the pointer */
12716 uint64_t ptr = aarch64_get_reg_u64 (cpu, 1, SP_OK);
12717 ptr = aarch64_get_mem_u64 (cpu, ptr);
12719 /* Fill in the memory block. */
12720 /* Start addr of heap. */
12721 aarch64_set_mem_u64 (cpu, ptr + 0, heap_base);
12722 /* End addr of heap. */
12723 aarch64_set_mem_u64 (cpu, ptr + 8, stack_top);
12724 /* Lowest stack addr. */
12725 aarch64_set_mem_u64 (cpu, ptr + 16, heap_base);
12726 /* Initial stack addr. */
12727 aarch64_set_mem_u64 (cpu, ptr + 24, stack_top);
12729 TRACE_SYSCALL (cpu, " AngelSVC: Get Heap Info");
12733 case AngelSVC_Reason_Open:
12735 /* Get the pointer */
12736 /* uint64_t ptr = aarch64_get_reg_u64 (cpu, 1, SP_OK);. */
12737 /* FIXME: For now we just assume that we will only be asked
12738 to open the standard file descriptors. */
12742 TRACE_SYSCALL (cpu, " AngelSVC: Open file %d", fd - 1);
12746 case AngelSVC_Reason_Close:
12748 uint64_t fh = aarch64_get_reg_u64 (cpu, 1, SP_OK);
12749 TRACE_SYSCALL (cpu, " AngelSVC: Close file %d", (int) fh);
12754 case AngelSVC_Reason_Errno:
12756 TRACE_SYSCALL (cpu, " AngelSVC: Get Errno");
12759 case AngelSVC_Reason_Clock:
12761 #ifdef CLOCKS_PER_SEC
12762 (CLOCKS_PER_SEC >= 100)
12763 ? (clock () / (CLOCKS_PER_SEC / 100))
12764 : ((clock () * 100) / CLOCKS_PER_SEC)
12766 /* Presume unix... clock() returns microseconds. */
12770 TRACE_SYSCALL (cpu, " AngelSVC: Get Clock");
12773 case AngelSVC_Reason_GetCmdLine:
12775 /* Get the pointer */
12776 uint64_t ptr = aarch64_get_reg_u64 (cpu, 1, SP_OK);
12777 ptr = aarch64_get_mem_u64 (cpu, ptr);
12779 /* FIXME: No command line for now. */
12780 aarch64_set_mem_u64 (cpu, ptr, 0);
12781 TRACE_SYSCALL (cpu, " AngelSVC: Get Command Line");
12785 case AngelSVC_Reason_IsTTY:
12787 TRACE_SYSCALL (cpu, " AngelSVC: IsTTY ?");
12790 case AngelSVC_Reason_Write:
12792 /* Get the pointer */
12793 uint64_t ptr = aarch64_get_reg_u64 (cpu, 1, SP_OK);
12794 /* Get the write control block. */
12795 uint64_t fd = aarch64_get_mem_u64 (cpu, ptr);
12796 uint64_t buf = aarch64_get_mem_u64 (cpu, ptr + 8);
12797 uint64_t len = aarch64_get_mem_u64 (cpu, ptr + 16);
12799 TRACE_SYSCALL (cpu, "write of %" PRIx64 " bytes from %"
12800 PRIx64 " on descriptor %" PRIx64,
12805 TRACE_SYSCALL (cpu,
12806 " AngelSVC: Write: Suspiciously long write: %ld",
12808 sim_engine_halt (CPU_STATE (cpu), cpu, NULL, aarch64_get_PC (cpu),
12809 sim_stopped, SIM_SIGBUS);
12813 printf ("%.*s", (int) len, aarch64_get_mem_ptr (cpu, buf));
12817 TRACE (cpu, 0, "\n");
12818 sim_io_eprintf (CPU_STATE (cpu), "%.*s",
12819 (int) len, aarch64_get_mem_ptr (cpu, buf));
12820 TRACE (cpu, 0, "\n");
12824 TRACE_SYSCALL (cpu,
12825 " AngelSVC: Write: Unexpected file handle: %d",
12827 sim_engine_halt (CPU_STATE (cpu), cpu, NULL, aarch64_get_PC (cpu),
12828 sim_stopped, SIM_SIGABRT);
12833 case AngelSVC_Reason_ReportException:
12835 /* Get the pointer */
12836 uint64_t ptr = aarch64_get_reg_u64 (cpu, 1, SP_OK);
12837 /*ptr = aarch64_get_mem_u64 (cpu, ptr);. */
12838 uint64_t type = aarch64_get_mem_u64 (cpu, ptr);
12839 uint64_t state = aarch64_get_mem_u64 (cpu, ptr + 8);
12841 TRACE_SYSCALL (cpu,
12842 "Angel Exception: type 0x%" PRIx64 " state %" PRIx64,
12845 if (type == 0x20026)
12846 sim_engine_halt (CPU_STATE (cpu), cpu, NULL, aarch64_get_PC (cpu),
12847 sim_exited, state);
12849 sim_engine_halt (CPU_STATE (cpu), cpu, NULL, aarch64_get_PC (cpu),
12850 sim_stopped, SIM_SIGINT);
12854 case AngelSVC_Reason_Read:
12855 case AngelSVC_Reason_FLen:
12856 case AngelSVC_Reason_Seek:
12857 case AngelSVC_Reason_Remove:
12858 case AngelSVC_Reason_Time:
12859 case AngelSVC_Reason_System:
12860 case AngelSVC_Reason_Rename:
12861 case AngelSVC_Reason_Elapsed:
12863 TRACE_SYSCALL (cpu, " HLT [Unknown angel %x]",
12864 aarch64_get_reg_u32 (cpu, 0, NO_SP));
12865 sim_engine_halt (CPU_STATE (cpu), cpu, NULL, aarch64_get_PC (cpu),
12866 sim_stopped, SIM_SIGTRAP);
12869 aarch64_set_reg_u64 (cpu, 0, NO_SP, result);
12873 dexExcpnGen (sim_cpu *cpu)
12875 /* instr[31:24] = 11010100
12876 instr[23,21] = opc : 000 ==> GEN EXCPN, 001 ==> BRK
12877 010 ==> HLT, 101 ==> DBG GEN EXCPN
12878 instr[20,5] = imm16
12879 instr[4,2] = opc2 000 ==> OK, ow ==> UNALLOC
12880 instr[1,0] = LL : discriminates opc */
12882 uint32_t opc = uimm (aarch64_get_instr (cpu), 23, 21);
12883 uint32_t imm16 = uimm (aarch64_get_instr (cpu), 20, 5);
12884 uint32_t opc2 = uimm (aarch64_get_instr (cpu), 4, 2);
12887 NYI_assert (31, 24, 0xd4);
12892 LL = uimm (aarch64_get_instr (cpu), 1, 0);
12894 /* We only implement HLT and BRK for now. */
12895 if (opc == 1 && LL == 0)
12897 TRACE_EVENTS (cpu, " BRK [0x%x]", imm16);
12898 sim_engine_halt (CPU_STATE (cpu), cpu, NULL, aarch64_get_PC (cpu),
12899 sim_exited, aarch64_get_reg_s32 (cpu, R0, SP_OK));
12902 if (opc == 2 && LL == 0)
12903 handle_halt (cpu, imm16);
12905 else if (opc == 0 || opc == 5)
12912 /* Stub for accessing system registers.
12913 We implement support for the DCZID register since this is used
12914 by the C library's memset function. */
12917 system_get (sim_cpu *cpu, unsigned op0, unsigned op1, unsigned crn,
12918 unsigned crm, unsigned op2)
12920 if (crn == 0 && op1 == 3 && crm == 0 && op2 == 7)
12921 /* DCZID_EL0 - the Data Cache Zero ID register.
12922 We do not support DC ZVA at the moment, so
12923 we return a value with the disable bit set. */
12924 return ((uint64_t) 1) << 4;
12930 do_mrs (sim_cpu *cpu)
12932 /* instr[31:20] = 1101 01010 0011
12939 unsigned sys_op0 = uimm (aarch64_get_instr (cpu), 19, 19) + 2;
12940 unsigned sys_op1 = uimm (aarch64_get_instr (cpu), 18, 16);
12941 unsigned sys_crn = uimm (aarch64_get_instr (cpu), 15, 12);
12942 unsigned sys_crm = uimm (aarch64_get_instr (cpu), 11, 8);
12943 unsigned sys_op2 = uimm (aarch64_get_instr (cpu), 7, 5);
12944 unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
12946 aarch64_set_reg_u64 (cpu, rt, NO_SP,
12947 system_get (cpu, sys_op0, sys_op1, sys_crn, sys_crm, sys_op2));
12951 dexSystem (sim_cpu *cpu)
12953 /* instr[31:22] = 1101 01010 0
12960 instr[4,0] = uimm5 */
12962 /* We are interested in HINT, DSB, DMB and ISB
12964 Hint #0 encodes NOOP (this is the only hint we care about)
12965 L == 0, op0 == 0, op1 = 011, CRn = 0010, Rt = 11111,
12966 CRm op2 != 0000 000 OR CRm op2 == 0000 000 || CRm op > 0000 101
12968 DSB, DMB, ISB are data store barrier, data memory barrier and
12969 instruction store barrier, respectively, where
12971 L == 0, op0 == 0, op1 = 011, CRn = 0011, Rt = 11111,
12972 op2 : DSB ==> 100, DMB ==> 101, ISB ==> 110
12973 CRm<3:2> ==> domain, CRm<1:0> ==> types,
12974 domain : 00 ==> OuterShareable, 01 ==> Nonshareable,
12975 10 ==> InerShareable, 11 ==> FullSystem
12976 types : 01 ==> Reads, 10 ==> Writes,
12977 11 ==> All, 00 ==> All (domain == FullSystem). */
12979 unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
12980 uint32_t l_op0_op1_crn = uimm (aarch64_get_instr (cpu), 21, 12);
12982 NYI_assert (31, 22, 0x354);
12984 switch (l_op0_op1_crn)
12989 /* NOP has CRm != 0000 OR. */
12990 /* (CRm == 0000 AND (op2 == 000 OR op2 > 101)). */
12991 uint32_t crm = uimm (aarch64_get_instr (cpu), 11, 8);
12992 uint32_t op2 = uimm (aarch64_get_instr (cpu), 7, 5);
12994 if (crm != 0 || (op2 == 0 || op2 > 5))
12996 /* Actually call nop method so we can reimplement it later. */
13005 uint32_t op2 = uimm (aarch64_get_instr (cpu), 7, 5);
13010 case 4: dsb (cpu); return;
13011 case 5: dmb (cpu); return;
13012 case 6: isb (cpu); return;
13014 default: HALT_UNALLOC;
13019 /* MRS Wt, sys-reg. */
13025 /* MRS Xt, sys-reg. */
13030 /* DC <type>, x<n>. */
13035 /* if (uimm (aarch64_get_instr (cpu), 21, 20) == 0x1)
13036 MRS Xt, sys-reg. */
13043 dexBr (sim_cpu *cpu)
13045 /* uint32_t group = dispatchGroup (aarch64_get_instr (cpu));
13046 assert group == GROUP_BREXSYS_1010 || group == GROUP_BREXSYS_1011
13047 bits [31,29] of a BrExSys are the secondary dispatch vector. */
13048 uint32_t group2 = dispatchBrExSys (aarch64_get_instr (cpu));
13053 return dexBranchImmediate (cpu);
13055 case BR_IMMCMP_001:
13056 /* Compare has bit 25 clear while test has it set. */
13057 if (!uimm (aarch64_get_instr (cpu), 25, 25))
13058 dexCompareBranchImmediate (cpu);
13060 dexTestBranchImmediate (cpu);
13063 case BR_IMMCOND_010:
13064 /* This is a conditional branch if bit 25 is clear otherwise
13066 if (!uimm (aarch64_get_instr (cpu), 25, 25))
13067 dexCondBranchImmediate (cpu);
13072 case BR_UNALLOC_011:
13076 dexBranchImmediate (cpu);
13079 case BR_IMMCMP_101:
13080 /* Compare has bit 25 clear while test has it set. */
13081 if (!uimm (aarch64_get_instr (cpu), 25, 25))
13082 dexCompareBranchImmediate (cpu);
13084 dexTestBranchImmediate (cpu);
13088 /* Unconditional branch reg has bit 25 set. */
13089 if (uimm (aarch64_get_instr (cpu), 25, 25))
13090 dexBranchRegister (cpu);
13092 /* This includes both Excpn Gen, System and unalloc operations.
13093 We need to decode the Excpn Gen operation BRK so we can plant
13094 debugger entry points.
13095 Excpn Gen operations have aarch64_get_instr (cpu)[24] = 0.
13096 we need to decode at least one of the System operations NOP
13097 which is an alias for HINT #0.
13098 System operations have aarch64_get_instr (cpu)[24,22] = 100. */
13099 else if (uimm (aarch64_get_instr (cpu), 24, 24) == 0)
13102 else if (uimm (aarch64_get_instr (cpu), 24, 22) == 4)
13110 case BR_UNALLOC_111:
13114 /* Should never reach here. */
13120 aarch64_decode_and_execute (sim_cpu *cpu, uint64_t pc)
13122 /* We need to check if gdb wants an in here. */
13123 /* checkBreak (cpu);. */
13125 uint64_t group = dispatchGroup (aarch64_get_instr (cpu));
13129 case GROUP_PSEUDO_0000: dexPseudo (cpu); break;
13130 case GROUP_LDST_0100: dexLdSt (cpu); break;
13131 case GROUP_DPREG_0101: dexDPReg (cpu); break;
13132 case GROUP_LDST_0110: dexLdSt (cpu); break;
13133 case GROUP_ADVSIMD_0111: dexAdvSIMD0 (cpu); break;
13134 case GROUP_DPIMM_1000: dexDPImm (cpu); break;
13135 case GROUP_DPIMM_1001: dexDPImm (cpu); break;
13136 case GROUP_BREXSYS_1010: dexBr (cpu); break;
13137 case GROUP_BREXSYS_1011: dexBr (cpu); break;
13138 case GROUP_LDST_1100: dexLdSt (cpu); break;
13139 case GROUP_DPREG_1101: dexDPReg (cpu); break;
13140 case GROUP_LDST_1110: dexLdSt (cpu); break;
13141 case GROUP_ADVSIMD_1111: dexAdvSIMD1 (cpu); break;
13143 case GROUP_UNALLOC_0001:
13144 case GROUP_UNALLOC_0010:
13145 case GROUP_UNALLOC_0011:
13149 /* Should never reach here. */
13155 aarch64_step (sim_cpu *cpu)
13157 uint64_t pc = aarch64_get_PC (cpu);
13159 if (pc == TOP_LEVEL_RETURN_PC)
13162 aarch64_set_next_PC (cpu, pc + 4);
13163 aarch64_get_instr (cpu) = aarch64_get_mem_u32 (cpu, pc);
13165 TRACE_INSN (cpu, " pc = %" PRIx64 " instr = %08x", pc,
13166 aarch64_get_instr (cpu));
13167 TRACE_DISASM (cpu, pc);
13169 aarch64_decode_and_execute (cpu, pc);
13175 aarch64_run (SIM_DESC sd)
13177 sim_cpu *cpu = STATE_CPU (sd, 0);
13179 while (aarch64_step (cpu))
13180 aarch64_update_PC (cpu);
13182 sim_engine_halt (sd, NULL, NULL, aarch64_get_PC (cpu),
13183 sim_exited, aarch64_get_reg_s32 (cpu, R0, SP_OK));
13187 aarch64_init (sim_cpu *cpu, uint64_t pc)
13189 uint64_t sp = aarch64_get_stack_start (cpu);
13191 /* Install SP, FP and PC and set LR to -20
13192 so we can detect a top-level return. */
13193 aarch64_set_reg_u64 (cpu, SP, SP_OK, sp);
13194 aarch64_set_reg_u64 (cpu, FP, SP_OK, sp);
13195 aarch64_set_reg_u64 (cpu, LR, SP_OK, TOP_LEVEL_RETURN_PC);
13196 aarch64_set_next_PC (cpu, pc);
13197 aarch64_update_PC (cpu);
13198 aarch64_init_LIT_table ();