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 if (! TRACE_ANY_P (cpu)) \
65 fprintf (stderr, "SIM Error: Unimplemented instruction: "); \
66 trace_disasm (CPU_STATE (cpu), cpu, aarch64_get_PC (cpu)); \
68 sim_engine_halt (CPU_STATE (cpu), cpu, NULL, aarch64_get_PC (cpu),\
69 sim_stopped, SIM_SIGABRT); \
73 #define NYI_assert(HI, LO, EXPECTED) \
76 if (uimm (aarch64_get_instr (cpu), (HI), (LO)) != (EXPECTED)) \
81 /* Space saver macro. */
82 #define INSTR(HIGH, LOW) uimm (aarch64_get_instr (cpu), (HIGH), (LOW))
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 8 bit with unsigned 12 bit offset. */
558 fldrb_abs (sim_cpu *cpu, uint32_t offset)
560 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
561 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
562 uint64_t addr = aarch64_get_reg_u64 (cpu, rn, SP_OK) + offset;
564 aarch64_set_vec_u8 (cpu, rd, 0, aarch64_get_mem_u32 (cpu, addr));
567 /* Load 16 bit scaled unsigned 12 bit. */
569 fldrh_abs (sim_cpu *cpu, uint32_t offset)
571 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
572 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
573 uint64_t addr = aarch64_get_reg_u64 (cpu, rn, SP_OK) + SCALE (offset, 16);
575 aarch64_set_vec_u16 (cpu, rd, 0, aarch64_get_mem_u16 (cpu, addr));
578 /* Load 32 bit scaled unsigned 12 bit. */
580 fldrs_abs (sim_cpu *cpu, uint32_t offset)
582 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
583 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
584 uint64_t addr = aarch64_get_reg_u64 (cpu, rn, SP_OK) + SCALE (offset, 32);
586 aarch64_set_vec_u32 (cpu, rd, 0, aarch64_get_mem_u32 (cpu, addr));
589 /* Load 64 bit scaled unsigned 12 bit. */
591 fldrd_abs (sim_cpu *cpu, uint32_t offset)
593 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
594 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
595 uint64_t addr = aarch64_get_reg_u64 (cpu, rn, SP_OK) + SCALE (offset, 64);
597 aarch64_set_vec_u64 (cpu, rd, 0, aarch64_get_mem_u64 (cpu, addr));
600 /* Load 128 bit scaled unsigned 12 bit. */
602 fldrq_abs (sim_cpu *cpu, uint32_t offset)
604 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
605 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
606 uint64_t addr = aarch64_get_reg_u64 (cpu, rn, SP_OK) + SCALE (offset, 128);
608 aarch64_set_vec_u64 (cpu, rd, 0, aarch64_get_mem_u64 (cpu, addr));
609 aarch64_set_vec_u64 (cpu, rd, 1, aarch64_get_mem_u64 (cpu, addr + 8));
612 /* Load 32 bit scaled or unscaled zero- or sign-extended
613 32-bit register offset. */
615 fldrs_scale_ext (sim_cpu *cpu, Scaling scaling, Extension extension)
617 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
618 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
619 unsigned st = uimm (aarch64_get_instr (cpu), 4, 0);
620 uint64_t address = aarch64_get_reg_u64 (cpu, rn, SP_OK);
621 int64_t extended = extend (aarch64_get_reg_u32 (cpu, rm, NO_SP), extension);
622 uint64_t displacement = OPT_SCALE (extended, 32, scaling);
624 aarch64_set_vec_u32 (cpu, st, 0, aarch64_get_mem_u32
625 (cpu, address + displacement));
628 /* Load 64 bit unscaled signed 9 bit with pre- or post-writeback. */
630 fldrd_wb (sim_cpu *cpu, int32_t offset, WriteBack wb)
632 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
633 unsigned st = uimm (aarch64_get_instr (cpu), 4, 0);
634 uint64_t address = aarch64_get_reg_u64 (cpu, rn, SP_OK);
639 aarch64_set_vec_u64 (cpu, st, 0, aarch64_get_mem_u64 (cpu, address));
644 if (wb != NoWriteBack)
645 aarch64_set_reg_u64 (cpu, rn, SP_OK, address);
648 /* Load 64 bit scaled or unscaled zero- or sign-extended 32-bit register offset. */
650 fldrd_scale_ext (sim_cpu *cpu, Scaling scaling, Extension extension)
652 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
653 int64_t extended = extend (aarch64_get_reg_u32 (cpu, rm, NO_SP), extension);
654 uint64_t displacement = OPT_SCALE (extended, 64, scaling);
656 fldrd_wb (cpu, displacement, NoWriteBack);
659 /* Load 128 bit unscaled signed 9 bit with pre- or post-writeback. */
661 fldrq_wb (sim_cpu *cpu, int32_t offset, WriteBack wb)
664 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
665 unsigned st = uimm (aarch64_get_instr (cpu), 4, 0);
666 uint64_t address = aarch64_get_reg_u64 (cpu, rn, SP_OK);
671 aarch64_get_mem_long_double (cpu, address, & a);
672 aarch64_set_FP_long_double (cpu, st, a);
677 if (wb != NoWriteBack)
678 aarch64_set_reg_u64 (cpu, rn, SP_OK, address);
681 /* Load 128 bit scaled or unscaled zero- or sign-extended 32-bit register offset */
683 fldrq_scale_ext (sim_cpu *cpu, Scaling scaling, Extension extension)
685 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
686 int64_t extended = extend (aarch64_get_reg_u32 (cpu, rm, NO_SP), extension);
687 uint64_t displacement = OPT_SCALE (extended, 128, scaling);
689 fldrq_wb (cpu, displacement, NoWriteBack);
694 load-store single register
695 There are four addressing modes available here which all employ a
696 64 bit source (base) register.
698 N.B. the base register (source) can be the stack pointer.
699 The secondary source register (source2)can only be an Xn register.
701 Scaled, 12-bit, unsigned immediate offset, without pre- and
703 Unscaled, 9-bit, signed immediate offset with pre- or post-index
705 scaled or unscaled 64-bit register offset.
706 scaled or unscaled 32-bit extended register offset.
708 All offsets are assumed to be raw from the decode i.e. the
709 simulator is expected to adjust scaled offsets based on the
710 accessed data size with register or extended register offset
711 versions the same applies except that in the latter case the
712 operation may also require a sign extend.
714 A separate method is provided for each possible addressing mode. */
716 /* 32 bit load 32 bit scaled unsigned 12 bit */
718 ldr32_abs (sim_cpu *cpu, uint32_t offset)
720 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
721 unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
723 /* The target register may not be SP but the source may be. */
724 aarch64_set_reg_u64 (cpu, rt, NO_SP, aarch64_get_mem_u32
725 (cpu, aarch64_get_reg_u64 (cpu, rn, SP_OK)
726 + SCALE (offset, 32)));
729 /* 32 bit load 32 bit unscaled signed 9 bit with pre- or post-writeback. */
731 ldr32_wb (sim_cpu *cpu, int32_t offset, WriteBack wb)
733 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
734 unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
737 if (rn == rt && wb != NoWriteBack)
740 address = aarch64_get_reg_u64 (cpu, rn, SP_OK);
745 aarch64_set_reg_u64 (cpu, rt, NO_SP, aarch64_get_mem_u32 (cpu, address));
750 if (wb != NoWriteBack)
751 aarch64_set_reg_u64 (cpu, rn, SP_OK, address);
754 /* 32 bit load 32 bit scaled or unscaled
755 zero- or sign-extended 32-bit register offset */
757 ldr32_scale_ext (sim_cpu *cpu, Scaling scaling, Extension extension)
759 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
760 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
761 unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
762 /* rn may reference SP, rm and rt must reference ZR */
764 uint64_t address = aarch64_get_reg_u64 (cpu, rn, SP_OK);
765 int64_t extended = extend (aarch64_get_reg_u32 (cpu, rm, NO_SP), extension);
766 uint64_t displacement = OPT_SCALE (extended, 32, scaling);
768 aarch64_set_reg_u64 (cpu, rt, NO_SP,
769 aarch64_get_mem_u32 (cpu, address + displacement));
772 /* 64 bit load 64 bit scaled unsigned 12 bit */
774 ldr_abs (sim_cpu *cpu, uint32_t offset)
776 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
777 unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
779 /* The target register may not be SP but the source may be. */
780 aarch64_set_reg_u64 (cpu, rt, NO_SP, aarch64_get_mem_u64
781 (cpu, aarch64_get_reg_u64 (cpu, rn, SP_OK)
782 + SCALE (offset, 64)));
785 /* 64 bit load 64 bit unscaled signed 9 bit with pre- or post-writeback. */
787 ldr_wb (sim_cpu *cpu, int32_t offset, WriteBack wb)
789 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
790 unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
793 if (rn == rt && wb != NoWriteBack)
796 address = aarch64_get_reg_u64 (cpu, rn, SP_OK);
801 aarch64_set_reg_u64 (cpu, rt, NO_SP, aarch64_get_mem_u64 (cpu, address));
806 if (wb != NoWriteBack)
807 aarch64_set_reg_u64 (cpu, rn, SP_OK, address);
810 /* 64 bit load 64 bit scaled or unscaled zero-
811 or sign-extended 32-bit register offset. */
813 ldr_scale_ext (sim_cpu *cpu, Scaling scaling, Extension extension)
815 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
816 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
817 unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
818 /* rn may reference SP, rm and rt must reference ZR */
820 uint64_t address = aarch64_get_reg_u64 (cpu, rn, SP_OK);
821 int64_t extended = extend (aarch64_get_reg_u32 (cpu, rm, NO_SP), extension);
822 uint64_t displacement = OPT_SCALE (extended, 64, scaling);
824 aarch64_set_reg_u64 (cpu, rt, NO_SP,
825 aarch64_get_mem_u64 (cpu, address + displacement));
828 /* 32 bit load zero-extended byte scaled unsigned 12 bit. */
830 ldrb32_abs (sim_cpu *cpu, uint32_t offset)
832 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
833 unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
835 /* The target register may not be SP but the source may be
836 there is no scaling required for a byte load. */
837 aarch64_set_reg_u64 (cpu, rt, NO_SP,
839 (cpu, aarch64_get_reg_u64 (cpu, rn, SP_OK) + offset));
842 /* 32 bit load zero-extended byte unscaled signed 9 bit with pre- or post-writeback. */
844 ldrb32_wb (sim_cpu *cpu, int32_t offset, WriteBack wb)
846 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
847 unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
850 if (rn == rt && wb != NoWriteBack)
853 address = aarch64_get_reg_u64 (cpu, rn, SP_OK);
858 aarch64_set_reg_u64 (cpu, rt, NO_SP, aarch64_get_mem_u8 (cpu, address));
863 if (wb != NoWriteBack)
864 aarch64_set_reg_u64 (cpu, rn, SP_OK, address);
867 /* 32 bit load zero-extended byte scaled or unscaled zero-
868 or sign-extended 32-bit register offset. */
870 ldrb32_scale_ext (sim_cpu *cpu, Scaling scaling, Extension extension)
872 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
873 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
874 unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
875 /* rn may reference SP, rm and rt must reference ZR */
877 uint64_t address = aarch64_get_reg_u64 (cpu, rn, SP_OK);
878 int64_t displacement = extend (aarch64_get_reg_u32 (cpu, rm, NO_SP),
881 /* There is no scaling required for a byte load. */
882 aarch64_set_reg_u64 (cpu, rt, NO_SP,
883 aarch64_get_mem_u8 (cpu, address + displacement));
886 /* 64 bit load sign-extended byte unscaled signed 9 bit
887 with pre- or post-writeback. */
889 ldrsb_wb (sim_cpu *cpu, int32_t offset, WriteBack wb)
891 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
892 unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
895 if (rn == rt && wb != NoWriteBack)
898 address = aarch64_get_reg_u64 (cpu, rn, SP_OK);
903 aarch64_set_reg_u64 (cpu, rt, NO_SP, aarch64_get_mem_s8 (cpu, address));
908 if (wb != NoWriteBack)
909 aarch64_set_reg_u64 (cpu, rn, SP_OK, address);
912 /* 64 bit load sign-extended byte scaled unsigned 12 bit. */
914 ldrsb_abs (sim_cpu *cpu, uint32_t offset)
916 ldrsb_wb (cpu, offset, NoWriteBack);
919 /* 64 bit load sign-extended byte scaled or unscaled zero-
920 or sign-extended 32-bit register offset. */
922 ldrsb_scale_ext (sim_cpu *cpu, Scaling scaling, Extension extension)
924 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
925 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
926 unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
927 /* rn may reference SP, rm and rt must reference ZR */
929 uint64_t address = aarch64_get_reg_u64 (cpu, rn, SP_OK);
930 int64_t displacement = extend (aarch64_get_reg_u32 (cpu, rm, NO_SP),
932 /* There is no scaling required for a byte load. */
933 aarch64_set_reg_u64 (cpu, rt, NO_SP,
934 aarch64_get_mem_s8 (cpu, address + displacement));
937 /* 32 bit load zero-extended short scaled unsigned 12 bit. */
939 ldrh32_abs (sim_cpu *cpu, uint32_t offset)
941 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
942 unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
944 /* The target register may not be SP but the source may be. */
945 aarch64_set_reg_u64 (cpu, rt, NO_SP, aarch64_get_mem_u16
946 (cpu, aarch64_get_reg_u64 (cpu, rn, SP_OK)
947 + SCALE (offset, 16)));
950 /* 32 bit load zero-extended short unscaled signed 9 bit
951 with pre- or post-writeback. */
953 ldrh32_wb (sim_cpu *cpu, int32_t offset, WriteBack wb)
955 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
956 unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
959 if (rn == rt && wb != NoWriteBack)
962 address = aarch64_get_reg_u64 (cpu, rn, SP_OK);
967 aarch64_set_reg_u64 (cpu, rt, NO_SP, aarch64_get_mem_u16 (cpu, address));
972 if (wb != NoWriteBack)
973 aarch64_set_reg_u64 (cpu, rn, SP_OK, address);
976 /* 32 bit load zero-extended short scaled or unscaled zero-
977 or sign-extended 32-bit register offset. */
979 ldrh32_scale_ext (sim_cpu *cpu, Scaling scaling, Extension extension)
981 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
982 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
983 unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
984 /* rn may reference SP, rm and rt must reference ZR */
986 uint64_t address = aarch64_get_reg_u64 (cpu, rn, SP_OK);
987 int64_t extended = extend (aarch64_get_reg_u32 (cpu, rm, NO_SP), extension);
988 uint64_t displacement = OPT_SCALE (extended, 16, scaling);
990 aarch64_set_reg_u64 (cpu, rt, NO_SP,
991 aarch64_get_mem_u16 (cpu, address + displacement));
994 /* 32 bit load sign-extended short scaled unsigned 12 bit. */
996 ldrsh32_abs (sim_cpu *cpu, uint32_t offset)
998 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
999 unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
1001 /* The target register may not be SP but the source may be. */
1002 aarch64_set_reg_u64 (cpu, rt, NO_SP, (uint32_t) aarch64_get_mem_s16
1004 aarch64_get_reg_u64 (cpu, rn, SP_OK)
1005 + SCALE (offset, 16)));
1008 /* 32 bit load sign-extended short unscaled signed 9 bit
1009 with pre- or post-writeback. */
1011 ldrsh32_wb (sim_cpu *cpu, int32_t offset, WriteBack wb)
1013 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
1014 unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
1017 if (rn == rt && wb != NoWriteBack)
1020 address = aarch64_get_reg_u64 (cpu, rn, SP_OK);
1025 aarch64_set_reg_u64 (cpu, rt, NO_SP,
1026 (uint32_t) aarch64_get_mem_s16 (cpu, address));
1031 if (wb != NoWriteBack)
1032 aarch64_set_reg_u64 (cpu, rn, SP_OK, address);
1035 /* 32 bit load sign-extended short scaled or unscaled zero-
1036 or sign-extended 32-bit register offset. */
1038 ldrsh32_scale_ext (sim_cpu *cpu, Scaling scaling, Extension extension)
1040 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
1041 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
1042 unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
1043 /* rn may reference SP, rm and rt must reference ZR */
1045 uint64_t address = aarch64_get_reg_u64 (cpu, rn, SP_OK);
1046 int64_t extended = extend (aarch64_get_reg_u32 (cpu, rm, NO_SP), extension);
1047 uint64_t displacement = OPT_SCALE (extended, 16, scaling);
1049 aarch64_set_reg_u64 (cpu, rt, NO_SP,
1050 (uint32_t) aarch64_get_mem_s16
1051 (cpu, address + displacement));
1054 /* 64 bit load sign-extended short scaled unsigned 12 bit. */
1056 ldrsh_abs (sim_cpu *cpu, uint32_t offset)
1058 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
1059 unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
1061 /* The target register may not be SP but the source may be. */
1062 aarch64_set_reg_u64 (cpu, rt, NO_SP, aarch64_get_mem_s16
1063 (cpu, aarch64_get_reg_u64 (cpu, rn, SP_OK)
1064 + SCALE (offset, 16)));
1067 /* 64 bit load sign-extended short unscaled signed 9 bit
1068 with pre- or post-writeback. */
1070 ldrsh64_wb (sim_cpu *cpu, int32_t offset, WriteBack wb)
1072 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
1073 unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
1076 if (rn == rt && wb != NoWriteBack)
1079 address = aarch64_get_reg_u64 (cpu, rn, SP_OK);
1084 aarch64_set_reg_u64 (cpu, rt, NO_SP, aarch64_get_mem_s16 (cpu, address));
1089 if (wb != NoWriteBack)
1090 aarch64_set_reg_u64 (cpu, rn, SP_OK, address);
1093 /* 64 bit load sign-extended short scaled or unscaled zero-
1094 or sign-extended 32-bit register offset. */
1096 ldrsh_scale_ext (sim_cpu *cpu, Scaling scaling, Extension extension)
1098 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
1099 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
1100 unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
1101 /* rn may reference SP, rm and rt must reference ZR */
1103 uint64_t address = aarch64_get_reg_u64 (cpu, rn, SP_OK);
1104 int64_t extended = extend (aarch64_get_reg_u32 (cpu, rm, NO_SP), extension);
1105 uint64_t displacement = OPT_SCALE (extended, 16, scaling);
1107 aarch64_set_reg_u64 (cpu, rt, NO_SP,
1108 aarch64_get_mem_s16 (cpu, address + displacement));
1111 /* 64 bit load sign-extended 32 bit scaled unsigned 12 bit. */
1113 ldrsw_abs (sim_cpu *cpu, uint32_t offset)
1115 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
1116 unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
1118 /* The target register may not be SP but the source may be. */
1119 return aarch64_set_reg_s64 (cpu, rt, NO_SP, aarch64_get_mem_s32
1120 (cpu, aarch64_get_reg_u64 (cpu, rn, SP_OK)
1121 + SCALE (offset, 32)));
1124 /* 64 bit load sign-extended 32 bit unscaled signed 9 bit
1125 with pre- or post-writeback. */
1127 ldrsw_wb (sim_cpu *cpu, int32_t offset, WriteBack wb)
1129 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
1130 unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
1133 if (rn == rt && wb != NoWriteBack)
1136 address = aarch64_get_reg_u64 (cpu, rn, SP_OK);
1141 aarch64_set_reg_s64 (cpu, rt, NO_SP, aarch64_get_mem_s32 (cpu, address));
1146 if (wb != NoWriteBack)
1147 aarch64_set_reg_u64 (cpu, rn, SP_OK, address);
1150 /* 64 bit load sign-extended 32 bit scaled or unscaled zero-
1151 or sign-extended 32-bit register offset. */
1153 ldrsw_scale_ext (sim_cpu *cpu, Scaling scaling, Extension extension)
1155 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
1156 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
1157 unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
1158 /* rn may reference SP, rm and rt must reference ZR */
1160 uint64_t address = aarch64_get_reg_u64 (cpu, rn, SP_OK);
1161 int64_t extended = extend (aarch64_get_reg_u32 (cpu, rm, NO_SP), extension);
1162 uint64_t displacement = OPT_SCALE (extended, 32, scaling);
1164 aarch64_set_reg_s64 (cpu, rt, NO_SP,
1165 aarch64_get_mem_s32 (cpu, address + displacement));
1168 /* N.B. with stores the value in source is written to the
1169 address identified by source2 modified by source3/offset. */
1171 /* 32 bit store scaled unsigned 12 bit. */
1173 str32_abs (sim_cpu *cpu, uint32_t offset)
1175 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
1176 unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
1178 /* The target register may not be SP but the source may be. */
1179 aarch64_set_mem_u32 (cpu, (aarch64_get_reg_u64 (cpu, rn, SP_OK)
1180 + SCALE (offset, 32)),
1181 aarch64_get_reg_u32 (cpu, rt, NO_SP));
1184 /* 32 bit store unscaled signed 9 bit with pre- or post-writeback. */
1186 str32_wb (sim_cpu *cpu, int32_t offset, WriteBack wb)
1188 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
1189 unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
1192 if (rn == rt && wb != NoWriteBack)
1195 address = aarch64_get_reg_u64 (cpu, rn, SP_OK);
1199 aarch64_set_mem_u32 (cpu, address, aarch64_get_reg_u32 (cpu, rt, NO_SP));
1204 if (wb != NoWriteBack)
1205 aarch64_set_reg_u64 (cpu, rn, SP_OK, address);
1208 /* 32 bit store scaled or unscaled zero- or
1209 sign-extended 32-bit register offset. */
1211 str32_scale_ext (sim_cpu *cpu, Scaling scaling, Extension extension)
1213 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
1214 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
1215 unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
1217 uint64_t address = aarch64_get_reg_u64 (cpu, rn, SP_OK);
1218 int64_t extended = extend (aarch64_get_reg_u32 (cpu, rm, NO_SP), extension);
1219 uint64_t displacement = OPT_SCALE (extended, 32, scaling);
1221 aarch64_set_mem_u32 (cpu, address + displacement,
1222 aarch64_get_reg_u64 (cpu, rt, NO_SP));
1225 /* 64 bit store scaled unsigned 12 bit. */
1227 str_abs (sim_cpu *cpu, uint32_t offset)
1229 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
1230 unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
1232 aarch64_set_mem_u64 (cpu,
1233 aarch64_get_reg_u64 (cpu, rn, SP_OK)
1234 + SCALE (offset, 64),
1235 aarch64_get_reg_u64 (cpu, rt, NO_SP));
1238 /* 64 bit store unscaled signed 9 bit with pre- or post-writeback. */
1240 str_wb (sim_cpu *cpu, int32_t offset, WriteBack wb)
1242 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
1243 unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
1246 if (rn == rt && wb != NoWriteBack)
1249 address = aarch64_get_reg_u64 (cpu, rn, SP_OK);
1254 aarch64_set_mem_u64 (cpu, address, aarch64_get_reg_u64 (cpu, rt, NO_SP));
1259 if (wb != NoWriteBack)
1260 aarch64_set_reg_u64 (cpu, rn, SP_OK, address);
1263 /* 64 bit store scaled or unscaled zero-
1264 or sign-extended 32-bit register offset. */
1266 str_scale_ext (sim_cpu *cpu, Scaling scaling, Extension extension)
1268 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
1269 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
1270 unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
1271 /* rn may reference SP, rm and rt must reference ZR */
1273 uint64_t address = aarch64_get_reg_u64 (cpu, rn, SP_OK);
1274 int64_t extended = extend (aarch64_get_reg_u32 (cpu, rm, NO_SP),
1276 uint64_t displacement = OPT_SCALE (extended, 64, scaling);
1278 aarch64_set_mem_u64 (cpu, address + displacement,
1279 aarch64_get_reg_u64 (cpu, rt, NO_SP));
1282 /* 32 bit store byte scaled unsigned 12 bit. */
1284 strb_abs (sim_cpu *cpu, uint32_t offset)
1286 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
1287 unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
1289 /* The target register may not be SP but the source may be.
1290 There is no scaling required for a byte load. */
1291 aarch64_set_mem_u8 (cpu,
1292 aarch64_get_reg_u64 (cpu, rn, SP_OK) + offset,
1293 aarch64_get_reg_u8 (cpu, rt, NO_SP));
1296 /* 32 bit store byte unscaled signed 9 bit with pre- or post-writeback. */
1298 strb_wb (sim_cpu *cpu, int32_t offset, WriteBack wb)
1300 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
1301 unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
1304 if (rn == rt && wb != NoWriteBack)
1307 address = aarch64_get_reg_u64 (cpu, rn, SP_OK);
1312 aarch64_set_mem_u8 (cpu, address, aarch64_get_reg_u8 (cpu, rt, NO_SP));
1317 if (wb != NoWriteBack)
1318 aarch64_set_reg_u64 (cpu, rn, SP_OK, address);
1321 /* 32 bit store byte scaled or unscaled zero-
1322 or sign-extended 32-bit register offset. */
1324 strb_scale_ext (sim_cpu *cpu, Scaling scaling, Extension extension)
1326 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
1327 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
1328 unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
1329 /* rn may reference SP, rm and rt must reference ZR */
1331 uint64_t address = aarch64_get_reg_u64 (cpu, rn, SP_OK);
1332 int64_t displacement = extend (aarch64_get_reg_u32 (cpu, rm, NO_SP),
1335 /* There is no scaling required for a byte load. */
1336 aarch64_set_mem_u8 (cpu, address + displacement,
1337 aarch64_get_reg_u8 (cpu, rt, NO_SP));
1340 /* 32 bit store short scaled unsigned 12 bit. */
1342 strh_abs (sim_cpu *cpu, uint32_t offset)
1344 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
1345 unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
1347 /* The target register may not be SP but the source may be. */
1348 aarch64_set_mem_u16 (cpu, aarch64_get_reg_u64 (cpu, rn, SP_OK)
1349 + SCALE (offset, 16),
1350 aarch64_get_reg_u16 (cpu, rt, NO_SP));
1353 /* 32 bit store short unscaled signed 9 bit with pre- or post-writeback. */
1355 strh_wb (sim_cpu *cpu, int32_t offset, WriteBack wb)
1357 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
1358 unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
1361 if (rn == rt && wb != NoWriteBack)
1364 address = aarch64_get_reg_u64 (cpu, rn, SP_OK);
1369 aarch64_set_mem_u16 (cpu, address, aarch64_get_reg_u16 (cpu, rt, NO_SP));
1374 if (wb != NoWriteBack)
1375 aarch64_set_reg_u64 (cpu, rn, SP_OK, address);
1378 /* 32 bit store short scaled or unscaled zero-
1379 or sign-extended 32-bit register offset. */
1381 strh_scale_ext (sim_cpu *cpu, Scaling scaling, Extension extension)
1383 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
1384 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
1385 unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
1386 /* rn may reference SP, rm and rt must reference ZR */
1388 uint64_t address = aarch64_get_reg_u64 (cpu, rn, SP_OK);
1389 int64_t extended = extend (aarch64_get_reg_u32 (cpu, rm, NO_SP), extension);
1390 uint64_t displacement = OPT_SCALE (extended, 16, scaling);
1392 aarch64_set_mem_u16 (cpu, address + displacement,
1393 aarch64_get_reg_u16 (cpu, rt, NO_SP));
1396 /* Prefetch unsigned 12 bit. */
1398 prfm_abs (sim_cpu *cpu, uint32_t offset)
1400 /* instr[4,0] = prfop : 00000 ==> PLDL1KEEP, 00001 ==> PLDL1STRM,
1401 00010 ==> PLDL2KEEP, 00001 ==> PLDL2STRM,
1402 00100 ==> PLDL3KEEP, 00101 ==> PLDL3STRM,
1403 10000 ==> PSTL1KEEP, 10001 ==> PSTL1STRM,
1404 10010 ==> PSTL2KEEP, 10001 ==> PSTL2STRM,
1405 10100 ==> PSTL3KEEP, 10101 ==> PSTL3STRM,
1407 PrfOp prfop = prfop (aarch64_get_instr (cpu), 4, 0);
1408 uint64_t address = aarch64_get_reg_u64 (cpu, rn, SP_OK)
1409 + SCALE (offset, 64). */
1411 /* TODO : implement prefetch of address. */
1414 /* Prefetch scaled or unscaled zero- or sign-extended 32-bit register offset. */
1416 prfm_scale_ext (sim_cpu *cpu, Scaling scaling, Extension extension)
1418 /* instr[4,0] = prfop : 00000 ==> PLDL1KEEP, 00001 ==> PLDL1STRM,
1419 00010 ==> PLDL2KEEP, 00001 ==> PLDL2STRM,
1420 00100 ==> PLDL3KEEP, 00101 ==> PLDL3STRM,
1421 10000 ==> PSTL1KEEP, 10001 ==> PSTL1STRM,
1422 10010 ==> PSTL2KEEP, 10001 ==> PSTL2STRM,
1423 10100 ==> PSTL3KEEP, 10101 ==> PSTL3STRM,
1425 rn may reference SP, rm may only reference ZR
1426 PrfOp prfop = prfop (aarch64_get_instr (cpu), 4, 0);
1427 uint64_t base = aarch64_get_reg_u64 (cpu, rn, SP_OK);
1428 int64_t extended = extend (aarch64_get_reg_u32 (cpu, rm, NO_SP),
1430 uint64_t displacement = OPT_SCALE (extended, 64, scaling);
1431 uint64_t address = base + displacement. */
1433 /* TODO : implement prefetch of address */
1436 /* 64 bit pc-relative prefetch. */
1438 prfm_pcrel (sim_cpu *cpu, int32_t offset)
1440 /* instr[4,0] = prfop : 00000 ==> PLDL1KEEP, 00001 ==> PLDL1STRM,
1441 00010 ==> PLDL2KEEP, 00001 ==> PLDL2STRM,
1442 00100 ==> PLDL3KEEP, 00101 ==> PLDL3STRM,
1443 10000 ==> PSTL1KEEP, 10001 ==> PSTL1STRM,
1444 10010 ==> PSTL2KEEP, 10001 ==> PSTL2STRM,
1445 10100 ==> PSTL3KEEP, 10101 ==> PSTL3STRM,
1447 PrfOp prfop = prfop (aarch64_get_instr (cpu), 4, 0);
1448 uint64_t address = aarch64_get_PC (cpu) + offset. */
1450 /* TODO : implement this */
1453 /* Load-store exclusive. */
1458 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
1459 unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
1460 uint64_t address = aarch64_get_reg_u64 (cpu, rn, SP_OK);
1461 int size = uimm (aarch64_get_instr (cpu), 31, 30);
1462 /* int ordered = uimm (aarch64_get_instr (cpu), 15, 15); */
1463 /* int exclusive = ! uimm (aarch64_get_instr (cpu), 23, 23); */
1468 aarch64_set_reg_u64 (cpu, rt, NO_SP, aarch64_get_mem_u8 (cpu, address));
1471 aarch64_set_reg_u64 (cpu, rt, NO_SP, aarch64_get_mem_u16 (cpu, address));
1474 aarch64_set_reg_u64 (cpu, rt, NO_SP, aarch64_get_mem_u32 (cpu, address));
1477 aarch64_set_reg_u64 (cpu, rt, NO_SP, aarch64_get_mem_u64 (cpu, address));
1485 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
1486 unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
1487 unsigned rs = uimm (aarch64_get_instr (cpu), 20, 16);
1488 uint64_t address = aarch64_get_reg_u64 (cpu, rn, SP_OK);
1489 int size = uimm (aarch64_get_instr (cpu), 31, 30);
1490 uint64_t data = aarch64_get_reg_u64 (cpu, rt, NO_SP);
1494 case 0: aarch64_set_mem_u8 (cpu, address, data); break;
1495 case 1: aarch64_set_mem_u16 (cpu, address, data); break;
1496 case 2: aarch64_set_mem_u32 (cpu, address, data); break;
1497 case 3: aarch64_set_mem_u64 (cpu, address, data); break;
1500 aarch64_set_reg_u64 (cpu, rs, NO_SP, 0); /* Always exclusive... */
1504 dexLoadLiteral (sim_cpu *cpu)
1506 /* instr[29,27] == 011
1508 instr[31,30:26] = opc: 000 ==> LDRW, 001 ==> FLDRS
1509 010 ==> LDRX, 011 ==> FLDRD
1510 100 ==> LDRSW, 101 ==> FLDRQ
1511 110 ==> PRFM, 111 ==> UNALLOC
1512 instr[26] ==> V : 0 ==> GReg, 1 ==> FReg
1513 instr[23, 5] == simm19 */
1515 /* unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0); */
1516 uint32_t dispatch = ( (uimm (aarch64_get_instr (cpu), 31, 30) << 1)
1517 | uimm (aarch64_get_instr (cpu), 26, 26));
1518 int32_t imm = simm32 (aarch64_get_instr (cpu), 23, 5);
1522 case 0: ldr32_pcrel (cpu, imm); break;
1523 case 1: fldrs_pcrel (cpu, imm); break;
1524 case 2: ldr_pcrel (cpu, imm); break;
1525 case 3: fldrd_pcrel (cpu, imm); break;
1526 case 4: ldrsw_pcrel (cpu, imm); break;
1527 case 5: fldrq_pcrel (cpu, imm); break;
1528 case 6: prfm_pcrel (cpu, imm); break;
1535 /* Immediate arithmetic
1536 The aimm argument is a 12 bit unsigned value or a 12 bit unsigned
1537 value left shifted by 12 bits (done at decode).
1539 N.B. the register args (dest, source) can normally be Xn or SP.
1540 the exception occurs for flag setting instructions which may
1541 only use Xn for the output (dest). */
1543 /* 32 bit add immediate. */
1545 add32 (sim_cpu *cpu, uint32_t aimm)
1547 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
1548 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
1550 aarch64_set_reg_u64 (cpu, rd, SP_OK,
1551 aarch64_get_reg_u32 (cpu, rn, SP_OK) + aimm);
1554 /* 64 bit add immediate. */
1556 add64 (sim_cpu *cpu, uint32_t aimm)
1558 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
1559 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
1561 aarch64_set_reg_u64 (cpu, rd, SP_OK,
1562 aarch64_get_reg_u64 (cpu, rn, SP_OK) + aimm);
1566 set_flags_for_add32 (sim_cpu *cpu, int32_t value1, int32_t value2)
1568 int32_t result = value1 + value2;
1569 int64_t sresult = (int64_t) value1 + (int64_t) value2;
1570 uint64_t uresult = (uint64_t)(uint32_t) value1
1571 + (uint64_t)(uint32_t) value2;
1577 if (result & (1 << 31))
1580 if (uresult != result)
1583 if (sresult != result)
1586 aarch64_set_CPSR (cpu, flags);
1590 set_flags_for_add64 (sim_cpu *cpu, uint64_t value1, uint64_t value2)
1592 int64_t sval1 = value1;
1593 int64_t sval2 = value2;
1594 uint64_t result = value1 + value2;
1595 int64_t sresult = sval1 + sval2;
1601 if (result & (1ULL << 63))
1608 /* Negative plus a negative. Overflow happens if
1609 the result is greater than either of the operands. */
1610 if (sresult > sval1 || sresult > sval2)
1613 /* else Negative plus a positive. Overflow cannot happen. */
1615 else /* value1 is +ve. */
1619 /* Overflow can only occur if we computed "0 - MININT". */
1620 if (sval1 == 0 && sval2 == (1LL << 63))
1625 /* Postive plus positive - overflow has happened if the
1626 result is smaller than either of the operands. */
1627 if (result < value1 || result < value2)
1632 aarch64_set_CPSR (cpu, flags);
1635 #define NEG(a) (((a) & signbit) == signbit)
1636 #define POS(a) (((a) & signbit) == 0)
1639 set_flags_for_sub32 (sim_cpu *cpu, uint32_t value1, uint32_t value2)
1641 uint32_t result = value1 - value2;
1643 uint32_t signbit = 1U << 31;
1651 if ( (NEG (value1) && POS (value2))
1652 || (NEG (value1) && POS (result))
1653 || (POS (value2) && POS (result)))
1656 if ( (NEG (value1) && POS (value2) && POS (result))
1657 || (POS (value1) && NEG (value2) && NEG (result)))
1660 aarch64_set_CPSR (cpu, flags);
1664 set_flags_for_sub64 (sim_cpu *cpu, uint64_t value1, uint64_t value2)
1666 uint64_t result = value1 - value2;
1668 uint64_t signbit = 1ULL << 63;
1676 if ( (NEG (value1) && POS (value2))
1677 || (NEG (value1) && POS (result))
1678 || (POS (value2) && POS (result)))
1681 if ( (NEG (value1) && POS (value2) && POS (result))
1682 || (POS (value1) && NEG (value2) && NEG (result)))
1685 aarch64_set_CPSR (cpu, flags);
1689 set_flags_for_binop32 (sim_cpu *cpu, uint32_t result)
1698 if (result & (1 << 31))
1703 aarch64_set_CPSR (cpu, flags);
1707 set_flags_for_binop64 (sim_cpu *cpu, uint64_t result)
1716 if (result & (1ULL << 63))
1721 aarch64_set_CPSR (cpu, flags);
1724 /* 32 bit add immediate set flags. */
1726 adds32 (sim_cpu *cpu, uint32_t aimm)
1728 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
1729 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
1730 /* TODO : do we need to worry about signs here? */
1731 int32_t value1 = aarch64_get_reg_s32 (cpu, rn, SP_OK);
1733 aarch64_set_reg_u64 (cpu, rd, NO_SP, value1 + aimm);
1734 set_flags_for_add32 (cpu, value1, aimm);
1737 /* 64 bit add immediate set flags. */
1739 adds64 (sim_cpu *cpu, uint32_t aimm)
1741 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
1742 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
1743 uint64_t value1 = aarch64_get_reg_u64 (cpu, rn, SP_OK);
1744 uint64_t value2 = aimm;
1746 aarch64_set_reg_u64 (cpu, rd, NO_SP, value1 + value2);
1747 set_flags_for_add64 (cpu, value1, value2);
1750 /* 32 bit sub immediate. */
1752 sub32 (sim_cpu *cpu, uint32_t aimm)
1754 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
1755 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
1757 aarch64_set_reg_u64 (cpu, rd, SP_OK,
1758 aarch64_get_reg_u32 (cpu, rn, SP_OK) - aimm);
1761 /* 64 bit sub immediate. */
1763 sub64 (sim_cpu *cpu, uint32_t aimm)
1765 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
1766 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
1768 aarch64_set_reg_u64 (cpu, rd, SP_OK,
1769 aarch64_get_reg_u64 (cpu, rn, SP_OK) - aimm);
1772 /* 32 bit sub immediate set flags. */
1774 subs32 (sim_cpu *cpu, uint32_t aimm)
1776 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
1777 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
1778 uint32_t value1 = aarch64_get_reg_u64 (cpu, rn, SP_OK);
1779 uint32_t value2 = aimm;
1781 aarch64_set_reg_u64 (cpu, rd, NO_SP, value1 - value2);
1782 set_flags_for_sub32 (cpu, value1, value2);
1785 /* 64 bit sub immediate set flags. */
1787 subs64 (sim_cpu *cpu, uint32_t aimm)
1789 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
1790 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
1791 uint64_t value1 = aarch64_get_reg_u64 (cpu, rn, SP_OK);
1792 uint32_t value2 = aimm;
1794 aarch64_set_reg_u64 (cpu, rd, NO_SP, value1 - value2);
1795 set_flags_for_sub64 (cpu, value1, value2);
1798 /* Data Processing Register. */
1800 /* First two helpers to perform the shift operations. */
1802 static inline uint32_t
1803 shifted32 (uint32_t value, Shift shift, uint32_t count)
1809 return (value << count);
1811 return (value >> count);
1814 int32_t svalue = value;
1815 return (svalue >> count);
1819 uint32_t top = value >> count;
1820 uint32_t bottom = value << (32 - count);
1821 return (bottom | top);
1826 static inline uint64_t
1827 shifted64 (uint64_t value, Shift shift, uint32_t count)
1833 return (value << count);
1835 return (value >> count);
1838 int64_t svalue = value;
1839 return (svalue >> count);
1843 uint64_t top = value >> count;
1844 uint64_t bottom = value << (64 - count);
1845 return (bottom | top);
1850 /* Arithmetic shifted register.
1851 These allow an optional LSL, ASR or LSR to the second source
1852 register with a count up to the register bit count.
1854 N.B register args may not be SP. */
1856 /* 32 bit ADD shifted register. */
1858 add32_shift (sim_cpu *cpu, Shift shift, uint32_t count)
1860 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
1861 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
1862 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
1864 aarch64_set_reg_u64 (cpu, rd, NO_SP,
1865 aarch64_get_reg_u32 (cpu, rn, NO_SP)
1866 + shifted32 (aarch64_get_reg_u32 (cpu, rm, NO_SP),
1870 /* 64 bit ADD shifted register. */
1872 add64_shift (sim_cpu *cpu, Shift shift, uint32_t count)
1874 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
1875 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
1876 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
1878 aarch64_set_reg_u64 (cpu, rd, NO_SP,
1879 aarch64_get_reg_u64 (cpu, rn, NO_SP)
1880 + shifted64 (aarch64_get_reg_u64 (cpu, rm, NO_SP),
1884 /* 32 bit ADD shifted register setting flags. */
1886 adds32_shift (sim_cpu *cpu, Shift shift, uint32_t count)
1888 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
1889 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
1890 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
1892 uint32_t value1 = aarch64_get_reg_u32 (cpu, rn, NO_SP);
1893 uint32_t value2 = shifted32 (aarch64_get_reg_u32 (cpu, rm, NO_SP),
1896 aarch64_set_reg_u64 (cpu, rd, NO_SP, value1 + value2);
1897 set_flags_for_add32 (cpu, value1, value2);
1900 /* 64 bit ADD shifted register setting flags. */
1902 adds64_shift (sim_cpu *cpu, Shift shift, uint32_t count)
1904 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
1905 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
1906 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
1908 uint64_t value1 = aarch64_get_reg_u64 (cpu, rn, NO_SP);
1909 uint64_t value2 = shifted64 (aarch64_get_reg_u64 (cpu, rm, NO_SP),
1912 aarch64_set_reg_u64 (cpu, rd, NO_SP, value1 + value2);
1913 set_flags_for_add64 (cpu, value1, value2);
1916 /* 32 bit SUB shifted register. */
1918 sub32_shift (sim_cpu *cpu, Shift shift, uint32_t count)
1920 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
1921 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
1922 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
1924 aarch64_set_reg_u64 (cpu, rd, NO_SP,
1925 aarch64_get_reg_u32 (cpu, rn, NO_SP)
1926 - shifted32 (aarch64_get_reg_u32 (cpu, rm, NO_SP),
1930 /* 64 bit SUB shifted register. */
1932 sub64_shift (sim_cpu *cpu, Shift shift, uint32_t count)
1934 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
1935 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
1936 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
1938 aarch64_set_reg_u64 (cpu, rd, NO_SP,
1939 aarch64_get_reg_u64 (cpu, rn, NO_SP)
1940 - shifted64 (aarch64_get_reg_u64 (cpu, rm, NO_SP),
1944 /* 32 bit SUB shifted register setting flags. */
1946 subs32_shift (sim_cpu *cpu, Shift shift, uint32_t count)
1948 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
1949 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
1950 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
1952 uint32_t value1 = aarch64_get_reg_u32 (cpu, rn, NO_SP);
1953 uint32_t value2 = shifted32 (aarch64_get_reg_u32 (cpu, rm, NO_SP),
1956 aarch64_set_reg_u64 (cpu, rd, NO_SP, value1 - value2);
1957 set_flags_for_sub32 (cpu, value1, value2);
1960 /* 64 bit SUB shifted register setting flags. */
1962 subs64_shift (sim_cpu *cpu, Shift shift, uint32_t count)
1964 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
1965 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
1966 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
1968 uint64_t value1 = aarch64_get_reg_u64 (cpu, rn, NO_SP);
1969 uint64_t value2 = shifted64 (aarch64_get_reg_u64 (cpu, rm, NO_SP),
1972 aarch64_set_reg_u64 (cpu, rd, NO_SP, value1 - value2);
1973 set_flags_for_sub64 (cpu, value1, value2);
1976 /* First a couple more helpers to fetch the
1977 relevant source register element either
1978 sign or zero extended as required by the
1982 extreg32 (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: /* Fall through. */
1989 case UXTX: return aarch64_get_reg_u32 (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: /* Fall through. */
1993 case SXTX: /* Fall through. */
1994 default: return aarch64_get_reg_s32 (cpu, lo, NO_SP);
1999 extreg64 (sim_cpu *cpu, unsigned int lo, Extension extension)
2003 case UXTB: return aarch64_get_reg_u8 (cpu, lo, NO_SP);
2004 case UXTH: return aarch64_get_reg_u16 (cpu, lo, NO_SP);
2005 case UXTW: return aarch64_get_reg_u32 (cpu, lo, NO_SP);
2006 case UXTX: return aarch64_get_reg_u64 (cpu, lo, NO_SP);
2007 case SXTB: return aarch64_get_reg_s8 (cpu, lo, NO_SP);
2008 case SXTH: return aarch64_get_reg_s16 (cpu, lo, NO_SP);
2009 case SXTW: return aarch64_get_reg_s32 (cpu, lo, NO_SP);
2011 default: return aarch64_get_reg_s64 (cpu, lo, NO_SP);
2015 /* Arithmetic extending register
2016 These allow an optional sign extension of some portion of the
2017 second source register followed by an optional left shift of
2018 between 1 and 4 bits (i.e. a shift of 0-4 bits???)
2020 N.B output (dest) and first input arg (source) may normally be Xn
2021 or SP. However, for flag setting operations dest can only be
2022 Xn. Second input registers are always Xn. */
2024 /* 32 bit ADD extending register. */
2026 add32_ext (sim_cpu *cpu, Extension extension, uint32_t shift)
2028 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
2029 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
2030 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
2032 aarch64_set_reg_u64 (cpu, rd, SP_OK,
2033 aarch64_get_reg_u32 (cpu, rn, SP_OK)
2034 + (extreg32 (cpu, rm, extension) << shift));
2037 /* 64 bit ADD extending register.
2038 N.B. This subsumes the case with 64 bit source2 and UXTX #n or LSL #0. */
2040 add64_ext (sim_cpu *cpu, Extension extension, uint32_t shift)
2042 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
2043 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
2044 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
2046 aarch64_set_reg_u64 (cpu, rd, SP_OK,
2047 aarch64_get_reg_u64 (cpu, rn, SP_OK)
2048 + (extreg64 (cpu, rm, extension) << shift));
2051 /* 32 bit ADD extending register setting flags. */
2053 adds32_ext (sim_cpu *cpu, Extension extension, uint32_t shift)
2055 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
2056 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
2057 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
2059 uint32_t value1 = aarch64_get_reg_u32 (cpu, rn, SP_OK);
2060 uint32_t value2 = extreg32 (cpu, rm, extension) << shift;
2062 aarch64_set_reg_u64 (cpu, rd, NO_SP, value1 + value2);
2063 set_flags_for_add32 (cpu, value1, value2);
2066 /* 64 bit ADD extending register setting flags */
2067 /* N.B. this subsumes the case with 64 bit source2 and UXTX #n or LSL #0 */
2069 adds64_ext (sim_cpu *cpu, Extension extension, uint32_t shift)
2071 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
2072 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
2073 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
2075 uint64_t value1 = aarch64_get_reg_u64 (cpu, rn, SP_OK);
2076 uint64_t value2 = extreg64 (cpu, rm, extension) << shift;
2078 aarch64_set_reg_u64 (cpu, rd, NO_SP, value1 + value2);
2079 set_flags_for_add64 (cpu, value1, value2);
2082 /* 32 bit SUB extending register. */
2084 sub32_ext (sim_cpu *cpu, Extension extension, uint32_t shift)
2086 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
2087 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
2088 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
2090 aarch64_set_reg_u64 (cpu, rd, SP_OK,
2091 aarch64_get_reg_u32 (cpu, rn, SP_OK)
2092 - (extreg32 (cpu, rm, extension) << shift));
2095 /* 64 bit SUB extending register. */
2096 /* N.B. this subsumes the case with 64 bit source2 and UXTX #n or LSL #0. */
2098 sub64_ext (sim_cpu *cpu, Extension extension, uint32_t shift)
2100 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
2101 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
2102 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
2104 aarch64_set_reg_u64 (cpu, rd, SP_OK,
2105 aarch64_get_reg_u64 (cpu, rn, SP_OK)
2106 - (extreg64 (cpu, rm, extension) << shift));
2109 /* 32 bit SUB extending register setting flags. */
2111 subs32_ext (sim_cpu *cpu, Extension extension, uint32_t shift)
2113 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
2114 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
2115 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
2117 uint32_t value1 = aarch64_get_reg_u32 (cpu, rn, SP_OK);
2118 uint32_t value2 = extreg32 (cpu, rm, extension) << shift;
2120 aarch64_set_reg_u64 (cpu, rd, NO_SP, value1 - value2);
2121 set_flags_for_sub32 (cpu, value1, value2);
2124 /* 64 bit SUB extending register setting flags */
2125 /* N.B. this subsumes the case with 64 bit source2 and UXTX #n or LSL #0 */
2127 subs64_ext (sim_cpu *cpu, Extension extension, uint32_t shift)
2129 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
2130 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
2131 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
2133 uint64_t value1 = aarch64_get_reg_u64 (cpu, rn, SP_OK);
2134 uint64_t value2 = extreg64 (cpu, rm, extension) << shift;
2136 aarch64_set_reg_u64 (cpu, rd, NO_SP, value1 - value2);
2137 set_flags_for_sub64 (cpu, value1, value2);
2141 dexAddSubtractImmediate (sim_cpu *cpu)
2143 /* instr[31] = size : 0 ==> 32 bit, 1 ==> 64 bit
2144 instr[30] = op : 0 ==> ADD, 1 ==> SUB
2145 instr[29] = set : 0 ==> no flags, 1 ==> set flags
2146 instr[28,24] = 10001
2147 instr[23,22] = shift : 00 == LSL#0, 01 = LSL#12 1x = UNALLOC
2148 instr[21,10] = uimm12
2152 /* N.B. the shift is applied at decode before calling the add/sub routine. */
2153 uint32_t shift = uimm (aarch64_get_instr (cpu), 23, 22);
2154 uint32_t imm = uimm (aarch64_get_instr (cpu), 21, 10);
2155 uint32_t dispatch = uimm (aarch64_get_instr (cpu), 31, 29);
2157 NYI_assert (28, 24, 0x11);
2167 case 0: add32 (cpu, imm); break;
2168 case 1: adds32 (cpu, imm); break;
2169 case 2: sub32 (cpu, imm); break;
2170 case 3: subs32 (cpu, imm); break;
2171 case 4: add64 (cpu, imm); break;
2172 case 5: adds64 (cpu, imm); break;
2173 case 6: sub64 (cpu, imm); break;
2174 case 7: subs64 (cpu, imm); break;
2179 dexAddSubtractShiftedRegister (sim_cpu *cpu)
2181 /* instr[31] = size : 0 ==> 32 bit, 1 ==> 64 bit
2182 instr[30,29] = op : 00 ==> ADD, 01 ==> ADDS, 10 ==> SUB, 11 ==> SUBS
2183 instr[28,24] = 01011
2184 instr[23,22] = shift : 0 ==> LSL, 1 ==> LSR, 2 ==> ASR, 3 ==> UNALLOC
2187 instr[15,10] = count : must be 0xxxxx for 32 bit
2191 uint32_t size = uimm (aarch64_get_instr (cpu), 31, 31);
2192 /* 32 bit operations must have count[5] = 0
2193 or else we have an UNALLOC. */
2194 uint32_t count = uimm (aarch64_get_instr (cpu), 15, 10);
2195 /* Shift encoded as ROR is unallocated. */
2196 Shift shiftType = shift (aarch64_get_instr (cpu), 22);
2197 /* Dispatch on size:op i.e aarch64_get_instr (cpu)[31,29]. */
2198 uint32_t dispatch = uimm (aarch64_get_instr (cpu), 31, 29);
2200 NYI_assert (28, 24, 0x0B);
2201 NYI_assert (21, 21, 0);
2203 if (shiftType == ROR)
2206 if (!size && uimm (count, 5, 5))
2211 case 0: add32_shift (cpu, shiftType, count); break;
2212 case 1: adds32_shift (cpu, shiftType, count); break;
2213 case 2: sub32_shift (cpu, shiftType, count); break;
2214 case 3: subs32_shift (cpu, shiftType, count); break;
2215 case 4: add64_shift (cpu, shiftType, count); break;
2216 case 5: adds64_shift (cpu, shiftType, count); break;
2217 case 6: sub64_shift (cpu, shiftType, count); break;
2218 case 7: subs64_shift (cpu, shiftType, count); break;
2223 dexAddSubtractExtendedRegister (sim_cpu *cpu)
2225 /* instr[31] = size : 0 ==> 32 bit, 1 ==> 64 bit
2226 instr[30] = op : 0 ==> ADD, 1 ==> SUB
2227 instr[29] = set? : 0 ==> no flags, 1 ==> set flags
2228 instr[28,24] = 01011
2229 instr[23,22] = opt : 0 ==> ok, 1,2,3 ==> UNALLOC
2232 instr[15,13] = option : 000 ==> UXTB, 001 ==> UXTH,
2233 000 ==> LSL|UXTW, 001 ==> UXTZ,
2234 000 ==> SXTB, 001 ==> SXTH,
2235 000 ==> SXTW, 001 ==> SXTX,
2236 instr[12,10] = shift : 0,1,2,3,4 ==> ok, 5,6,7 ==> UNALLOC
2240 Extension extensionType = extension (aarch64_get_instr (cpu), 13);
2241 uint32_t shift = uimm (aarch64_get_instr (cpu), 12, 10);
2242 /* dispatch on size:op:set? i.e aarch64_get_instr (cpu)[31,29] */
2243 uint32_t dispatch = uimm (aarch64_get_instr (cpu), 31, 29);
2245 NYI_assert (28, 24, 0x0B);
2246 NYI_assert (21, 21, 1);
2248 /* Shift may not exceed 4. */
2254 case 0: add32_ext (cpu, extensionType, shift); break;
2255 case 1: adds32_ext (cpu, extensionType, shift); break;
2256 case 2: sub32_ext (cpu, extensionType, shift); break;
2257 case 3: subs32_ext (cpu, extensionType, shift); break;
2258 case 4: add64_ext (cpu, extensionType, shift); break;
2259 case 5: adds64_ext (cpu, extensionType, shift); break;
2260 case 6: sub64_ext (cpu, extensionType, shift); break;
2261 case 7: subs64_ext (cpu, extensionType, shift); break;
2265 /* Conditional data processing
2266 Condition register is implicit 3rd source. */
2268 /* 32 bit add with carry. */
2269 /* N.B register args may not be SP. */
2272 adc32 (sim_cpu *cpu)
2274 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
2275 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
2276 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
2278 aarch64_set_reg_u64 (cpu, rd, NO_SP,
2279 aarch64_get_reg_u32 (cpu, rn, NO_SP)
2280 + aarch64_get_reg_u32 (cpu, rm, NO_SP)
2284 /* 64 bit add with carry */
2286 adc64 (sim_cpu *cpu)
2288 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
2289 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
2290 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
2292 aarch64_set_reg_u64 (cpu, rd, NO_SP,
2293 aarch64_get_reg_u64 (cpu, rn, NO_SP)
2294 + aarch64_get_reg_u64 (cpu, rm, NO_SP)
2298 /* 32 bit add with carry setting flags. */
2300 adcs32 (sim_cpu *cpu)
2302 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
2303 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
2304 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
2306 uint32_t value1 = aarch64_get_reg_u32 (cpu, rn, NO_SP);
2307 uint32_t value2 = aarch64_get_reg_u32 (cpu, rm, NO_SP);
2308 uint32_t carry = IS_SET (C);
2310 aarch64_set_reg_u64 (cpu, rd, NO_SP, value1 + value2 + carry);
2311 set_flags_for_add32 (cpu, value1, value2 + carry);
2314 /* 64 bit add with carry setting flags. */
2316 adcs64 (sim_cpu *cpu)
2318 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
2319 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
2320 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
2322 uint64_t value1 = aarch64_get_reg_u64 (cpu, rn, NO_SP);
2323 uint64_t value2 = aarch64_get_reg_u64 (cpu, rm, NO_SP);
2324 uint64_t carry = IS_SET (C);
2326 aarch64_set_reg_u64 (cpu, rd, NO_SP, value1 + value2 + carry);
2327 set_flags_for_add64 (cpu, value1, value2 + carry);
2330 /* 32 bit sub with carry. */
2332 sbc32 (sim_cpu *cpu)
2334 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
2335 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5); /* ngc iff rn == 31. */
2336 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
2338 aarch64_set_reg_u64 (cpu, rd, NO_SP,
2339 aarch64_get_reg_u32 (cpu, rn, NO_SP)
2340 - aarch64_get_reg_u32 (cpu, rm, NO_SP)
2344 /* 64 bit sub with carry */
2346 sbc64 (sim_cpu *cpu)
2348 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
2349 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
2350 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
2352 aarch64_set_reg_u64 (cpu, rd, NO_SP,
2353 aarch64_get_reg_u64 (cpu, rn, NO_SP)
2354 - aarch64_get_reg_u64 (cpu, rm, NO_SP)
2358 /* 32 bit sub with carry setting flags */
2360 sbcs32 (sim_cpu *cpu)
2362 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
2363 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
2364 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
2366 uint32_t value1 = aarch64_get_reg_u32 (cpu, rn, NO_SP);
2367 uint32_t value2 = aarch64_get_reg_u32 (cpu, rm, NO_SP);
2368 uint32_t carry = IS_SET (C);
2369 uint32_t result = value1 - value2 + 1 - carry;
2371 aarch64_set_reg_u64 (cpu, rd, NO_SP, result);
2372 set_flags_for_sub32 (cpu, value1, value2 + 1 - carry);
2375 /* 64 bit sub with carry setting flags */
2377 sbcs64 (sim_cpu *cpu)
2379 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
2380 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
2381 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
2383 uint64_t value1 = aarch64_get_reg_u64 (cpu, rn, NO_SP);
2384 uint64_t value2 = aarch64_get_reg_u64 (cpu, rm, NO_SP);
2385 uint64_t carry = IS_SET (C);
2386 uint64_t result = value1 - value2 + 1 - carry;
2388 aarch64_set_reg_u64 (cpu, rd, NO_SP, result);
2389 set_flags_for_sub64 (cpu, value1, value2 + 1 - carry);
2393 dexAddSubtractWithCarry (sim_cpu *cpu)
2395 /* instr[31] = size : 0 ==> 32 bit, 1 ==> 64 bit
2396 instr[30] = op : 0 ==> ADC, 1 ==> SBC
2397 instr[29] = set? : 0 ==> no flags, 1 ==> set flags
2398 instr[28,21] = 1 1010 000
2400 instr[15,10] = op2 : 00000 ==> ok, ow ==> UNALLOC
2404 uint32_t op2 = uimm (aarch64_get_instr (cpu), 15, 10);
2405 /* Dispatch on size:op:set? i.e aarch64_get_instr (cpu)[31,29] */
2406 uint32_t dispatch = uimm (aarch64_get_instr (cpu), 31, 29);
2408 NYI_assert (28, 21, 0xD0);
2415 case 0: adc32 (cpu); break;
2416 case 1: adcs32 (cpu); break;
2417 case 2: sbc32 (cpu); break;
2418 case 3: sbcs32 (cpu); break;
2419 case 4: adc64 (cpu); break;
2420 case 5: adcs64 (cpu); break;
2421 case 6: sbc64 (cpu); break;
2422 case 7: sbcs64 (cpu); break;
2427 testConditionCode (sim_cpu *cpu, CondCode cc)
2429 /* This should be reduceable to branchless logic
2430 by some careful testing of bits in CC followed
2431 by the requisite masking and combining of bits
2432 from the flag register.
2434 For now we do it with a switch. */
2439 case EQ: res = IS_SET (Z); break;
2440 case NE: res = IS_CLEAR (Z); break;
2441 case CS: res = IS_SET (C); break;
2442 case CC: res = IS_CLEAR (C); break;
2443 case MI: res = IS_SET (N); break;
2444 case PL: res = IS_CLEAR (N); break;
2445 case VS: res = IS_SET (V); break;
2446 case VC: res = IS_CLEAR (V); break;
2447 case HI: res = IS_SET (C) && IS_CLEAR (Z); break;
2448 case LS: res = IS_CLEAR (C) || IS_SET (Z); break;
2449 case GE: res = IS_SET (N) == IS_SET (V); break;
2450 case LT: res = IS_SET (N) != IS_SET (V); break;
2451 case GT: res = IS_CLEAR (Z) && (IS_SET (N) == IS_SET (V)); break;
2452 case LE: res = IS_SET (Z) || (IS_SET (N) != IS_SET (V)); break;
2463 CondCompare (sim_cpu *cpu) /* aka: ccmp and ccmn */
2465 /* instr[31] = size : 0 ==> 32 bit, 1 ==> 64 bit
2466 instr[30] = compare with positive (1) or negative value (0)
2467 instr[29,21] = 1 1101 0010
2468 instr[20,16] = Rm or const
2470 instr[11] = compare reg (0) or const (1)
2474 instr[3,0] = value for CPSR bits if the comparison does not take place. */
2479 NYI_assert (29, 21, 0x1d2);
2480 NYI_assert (10, 10, 0);
2481 NYI_assert (4, 4, 0);
2483 if (! testConditionCode (cpu, uimm (aarch64_get_instr (cpu), 15, 12)))
2485 aarch64_set_CPSR (cpu, uimm (aarch64_get_instr (cpu), 3, 0));
2489 negate = uimm (aarch64_get_instr (cpu), 30, 30) ? 1 : -1;
2490 rm = uimm (aarch64_get_instr (cpu), 20, 16);
2491 rn = uimm (aarch64_get_instr (cpu), 9, 5);
2493 if (uimm (aarch64_get_instr (cpu), 31, 31))
2495 if (uimm (aarch64_get_instr (cpu), 11, 11))
2496 set_flags_for_sub64 (cpu, aarch64_get_reg_u64 (cpu, rn, SP_OK),
2497 negate * (uint64_t) rm);
2499 set_flags_for_sub64 (cpu, aarch64_get_reg_u64 (cpu, rn, SP_OK),
2500 negate * aarch64_get_reg_u64 (cpu, rm, SP_OK));
2504 if (uimm (aarch64_get_instr (cpu), 11, 11))
2505 set_flags_for_sub32 (cpu, aarch64_get_reg_u32 (cpu, rn, SP_OK),
2508 set_flags_for_sub32 (cpu, aarch64_get_reg_u32 (cpu, rn, SP_OK),
2509 negate * aarch64_get_reg_u32 (cpu, rm, SP_OK));
2514 do_vec_MOV_whole_vector (sim_cpu *cpu)
2516 /* MOV Vd.T, Vs.T (alias for ORR Vd.T, Vn.T, Vm.T where Vn == Vm)
2519 instr[30] = half(0)/full(1)
2520 instr[29,21] = 001110101
2522 instr[15,10] = 000111
2526 unsigned vs = uimm (aarch64_get_instr (cpu), 9, 5);
2527 unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
2529 NYI_assert (29, 21, 0x075);
2530 NYI_assert (15, 10, 0x07);
2532 if (uimm (aarch64_get_instr (cpu), 20, 16) != vs)
2535 if (uimm (aarch64_get_instr (cpu), 30, 30))
2536 aarch64_set_vec_u64 (cpu, vd, 1, aarch64_get_vec_u64 (cpu, vs, 1));
2538 aarch64_set_vec_u64 (cpu, vd, 0, aarch64_get_vec_u64 (cpu, vs, 0));
2542 do_vec_MOV_into_scalar (sim_cpu *cpu)
2545 instr[30] = word(0)/long(1)
2546 instr[29,21] = 00 1110 000
2547 instr[20,18] = element size and index
2548 instr[17,10] = 00 0011 11
2549 instr[9,5] = V source
2550 instr[4,0] = R dest */
2552 unsigned vs = uimm (aarch64_get_instr (cpu), 9, 5);
2553 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
2555 NYI_assert (29, 21, 0x070);
2556 NYI_assert (17, 10, 0x0F);
2558 switch (uimm (aarch64_get_instr (cpu), 20, 18))
2561 aarch64_set_reg_u64 (cpu, rd, NO_SP, aarch64_get_vec_u64 (cpu, vs, 0));
2565 aarch64_set_reg_u64 (cpu, rd, NO_SP, aarch64_get_vec_u64 (cpu, vs, 1));
2572 aarch64_set_reg_u64 (cpu, rd, NO_SP, aarch64_get_vec_u32
2573 (cpu, vs, uimm (aarch64_get_instr (cpu), 20, 19)));
2582 do_vec_INS (sim_cpu *cpu)
2584 /* instr[31,21] = 01001110000
2585 instr[20,16] = element size and index
2586 instr[15,10] = 000111
2587 instr[9,5] = W source
2588 instr[4,0] = V dest */
2591 unsigned rs = uimm (aarch64_get_instr (cpu), 9, 5);
2592 unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
2594 NYI_assert (31, 21, 0x270);
2595 NYI_assert (15, 10, 0x07);
2597 if (uimm (aarch64_get_instr (cpu), 16, 16))
2599 index = uimm (aarch64_get_instr (cpu), 20, 17);
2600 aarch64_set_vec_u8 (cpu, vd, index,
2601 aarch64_get_reg_u8 (cpu, rs, NO_SP));
2603 else if (uimm (aarch64_get_instr (cpu), 17, 17))
2605 index = uimm (aarch64_get_instr (cpu), 20, 18);
2606 aarch64_set_vec_u16 (cpu, vd, index,
2607 aarch64_get_reg_u16 (cpu, rs, NO_SP));
2609 else if (uimm (aarch64_get_instr (cpu), 18, 18))
2611 index = uimm (aarch64_get_instr (cpu), 20, 19);
2612 aarch64_set_vec_u32 (cpu, vd, index,
2613 aarch64_get_reg_u32 (cpu, rs, NO_SP));
2615 else if (uimm (aarch64_get_instr (cpu), 19, 19))
2617 index = uimm (aarch64_get_instr (cpu), 20, 20);
2618 aarch64_set_vec_u64 (cpu, vd, index,
2619 aarch64_get_reg_u64 (cpu, rs, NO_SP));
2626 do_vec_DUP_vector_into_vector (sim_cpu *cpu)
2629 instr[30] = half(0)/full(1)
2630 instr[29,21] = 00 1110 000
2631 instr[20,16] = element size and index
2632 instr[15,10] = 0000 01
2633 instr[9,5] = V source
2634 instr[4,0] = V dest. */
2636 unsigned full = uimm (aarch64_get_instr (cpu), 30, 30);
2637 unsigned vs = uimm (aarch64_get_instr (cpu), 9, 5);
2638 unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
2641 NYI_assert (29, 21, 0x070);
2642 NYI_assert (15, 10, 0x01);
2644 if (uimm (aarch64_get_instr (cpu), 16, 16))
2646 index = uimm (aarch64_get_instr (cpu), 20, 17);
2648 for (i = 0; i < (full ? 16 : 8); i++)
2649 aarch64_set_vec_u8 (cpu, vd, i, aarch64_get_vec_u8 (cpu, vs, index));
2651 else if (uimm (aarch64_get_instr (cpu), 17, 17))
2653 index = uimm (aarch64_get_instr (cpu), 20, 18);
2655 for (i = 0; i < (full ? 8 : 4); i++)
2656 aarch64_set_vec_u16 (cpu, vd, i, aarch64_get_vec_u16 (cpu, vs, index));
2658 else if (uimm (aarch64_get_instr (cpu), 18, 18))
2660 index = uimm (aarch64_get_instr (cpu), 20, 19);
2662 for (i = 0; i < (full ? 4 : 2); i++)
2663 aarch64_set_vec_u32 (cpu, vd, i, aarch64_get_vec_u32 (cpu, vs, index));
2667 if (uimm (aarch64_get_instr (cpu), 19, 19) == 0)
2673 index = uimm (aarch64_get_instr (cpu), 20, 20);
2675 for (i = 0; i < 2; i++)
2676 aarch64_set_vec_u64 (cpu, vd, i, aarch64_get_vec_u64 (cpu, vs, index));
2681 do_vec_TBL (sim_cpu *cpu)
2684 instr[30] = half(0)/full(1)
2685 instr[29,21] = 00 1110 000
2688 instr[14,13] = vec length
2690 instr[9,5] = V start
2691 instr[4,0] = V dest */
2693 int full = uimm (aarch64_get_instr (cpu), 30, 30);
2694 int len = uimm (aarch64_get_instr (cpu), 14, 13) + 1;
2695 unsigned vm = uimm (aarch64_get_instr (cpu), 20, 16);
2696 unsigned vn = uimm (aarch64_get_instr (cpu), 9, 5);
2697 unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
2700 NYI_assert (29, 21, 0x070);
2701 NYI_assert (12, 10, 0);
2703 for (i = 0; i < (full ? 16 : 8); i++)
2705 unsigned int selector = aarch64_get_vec_u8 (cpu, vm, i);
2709 val = aarch64_get_vec_u8 (cpu, vn, selector);
2710 else if (selector < 32)
2711 val = len < 2 ? 0 : aarch64_get_vec_u8 (cpu, vn + 1, selector - 16);
2712 else if (selector < 48)
2713 val = len < 3 ? 0 : aarch64_get_vec_u8 (cpu, vn + 2, selector - 32);
2714 else if (selector < 64)
2715 val = len < 4 ? 0 : aarch64_get_vec_u8 (cpu, vn + 3, selector - 48);
2719 aarch64_set_vec_u8 (cpu, vd, i, val);
2724 do_vec_TRN (sim_cpu *cpu)
2727 instr[30] = half(0)/full(1)
2728 instr[29,24] = 00 1110
2733 instr[14] = TRN1 (0) / TRN2 (1)
2735 instr[9,5] = V source
2736 instr[4,0] = V dest. */
2738 int full = uimm (aarch64_get_instr (cpu), 30, 30);
2739 int second = uimm (aarch64_get_instr (cpu), 14, 14);
2740 unsigned vm = uimm (aarch64_get_instr (cpu), 20, 16);
2741 unsigned vn = uimm (aarch64_get_instr (cpu), 9, 5);
2742 unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
2745 NYI_assert (29, 24, 0x0E);
2746 NYI_assert (13, 10, 0xA);
2748 switch (uimm (aarch64_get_instr (cpu), 23, 22))
2751 for (i = 0; i < (full ? 8 : 4); i++)
2755 aarch64_get_vec_u8 (cpu, second ? vm : vn, i * 2));
2757 (cpu, vd, 1 * 2 + 1,
2758 aarch64_get_vec_u8 (cpu, second ? vn : vm, i * 2 + 1));
2763 for (i = 0; i < (full ? 4 : 2); i++)
2767 aarch64_get_vec_u16 (cpu, second ? vm : vn, i * 2));
2769 (cpu, vd, 1 * 2 + 1,
2770 aarch64_get_vec_u16 (cpu, second ? vn : vm, i * 2 + 1));
2776 (cpu, vd, 0, aarch64_get_vec_u32 (cpu, second ? vm : vn, 0));
2778 (cpu, vd, 1, aarch64_get_vec_u32 (cpu, second ? vn : vm, 1));
2780 (cpu, vd, 2, aarch64_get_vec_u32 (cpu, second ? vm : vn, 2));
2782 (cpu, vd, 3, aarch64_get_vec_u32 (cpu, second ? vn : vm, 3));
2789 aarch64_set_vec_u64 (cpu, vd, 0,
2790 aarch64_get_vec_u64 (cpu, second ? vm : vn, 0));
2791 aarch64_set_vec_u64 (cpu, vd, 1,
2792 aarch64_get_vec_u64 (cpu, second ? vn : vm, 1));
2798 do_vec_DUP_scalar_into_vector (sim_cpu *cpu)
2801 instr[30] = 0=> zero top 64-bits, 1=> duplicate into top 64-bits
2802 [must be 1 for 64-bit xfer]
2803 instr[29,20] = 00 1110 0000
2804 instr[19,16] = element size: 0001=> 8-bits, 0010=> 16-bits,
2805 0100=> 32-bits. 1000=>64-bits
2806 instr[15,10] = 0000 11
2807 instr[9,5] = W source
2808 instr[4,0] = V dest. */
2811 unsigned Vd = uimm (aarch64_get_instr (cpu), 4, 0);
2812 unsigned Rs = uimm (aarch64_get_instr (cpu), 9, 5);
2813 int both = uimm (aarch64_get_instr (cpu), 30, 30);
2815 NYI_assert (29, 20, 0x0E0);
2816 NYI_assert (15, 10, 0x03);
2818 switch (uimm (aarch64_get_instr (cpu), 19, 16))
2821 for (i = 0; i < (both ? 16 : 8); i++)
2822 aarch64_set_vec_u8 (cpu, Vd, i, aarch64_get_reg_u8 (cpu, Rs, NO_SP));
2826 for (i = 0; i < (both ? 8 : 4); i++)
2827 aarch64_set_vec_u16 (cpu, Vd, i, aarch64_get_reg_u16 (cpu, Rs, NO_SP));
2831 for (i = 0; i < (both ? 4 : 2); i++)
2832 aarch64_set_vec_u32 (cpu, Vd, i, aarch64_get_reg_u32 (cpu, Rs, NO_SP));
2838 aarch64_set_vec_u64 (cpu, Vd, 0, aarch64_get_reg_u64 (cpu, Rs, NO_SP));
2839 aarch64_set_vec_u64 (cpu, Vd, 1, aarch64_get_reg_u64 (cpu, Rs, NO_SP));
2848 do_vec_UZP (sim_cpu *cpu)
2851 instr[30] = half(0)/full(1)
2852 instr[29,24] = 00 1110
2853 instr[23,22] = size: byte(00), half(01), word (10), long (11)
2857 instr[14] = lower (0) / upper (1)
2862 int full = uimm (aarch64_get_instr (cpu), 30, 30);
2863 int upper = uimm (aarch64_get_instr (cpu), 14, 14);
2865 unsigned vm = uimm (aarch64_get_instr (cpu), 20, 16);
2866 unsigned vn = uimm (aarch64_get_instr (cpu), 9, 5);
2867 unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
2869 uint64_t val_m1 = aarch64_get_vec_u64 (cpu, vm, 0);
2870 uint64_t val_m2 = aarch64_get_vec_u64 (cpu, vm, 1);
2871 uint64_t val_n1 = aarch64_get_vec_u64 (cpu, vn, 0);
2872 uint64_t val_n2 = aarch64_get_vec_u64 (cpu, vn, 1);
2877 uint64_t input1 = upper ? val_n1 : val_m1;
2878 uint64_t input2 = upper ? val_n2 : val_m2;
2881 NYI_assert (29, 24, 0x0E);
2882 NYI_assert (21, 21, 0);
2883 NYI_assert (15, 15, 0);
2884 NYI_assert (13, 10, 6);
2886 switch (uimm (aarch64_get_instr (cpu), 23, 23))
2889 for (i = 0; i < 8; i++)
2891 val1 |= (input1 >> (i * 8)) & (0xFFULL << (i * 8));
2892 val2 |= (input2 >> (i * 8)) & (0xFFULL << (i * 8));
2897 for (i = 0; i < 4; i++)
2899 val1 |= (input1 >> (i * 16)) & (0xFFFFULL << (i * 16));
2900 val2 |= (input2 >> (i * 16)) & (0xFFFFULL << (i * 16));
2905 val1 = ((input1 & 0xFFFFFFFF) | ((input1 >> 32) & 0xFFFFFFFF00000000ULL));
2906 val2 = ((input2 & 0xFFFFFFFF) | ((input2 >> 32) & 0xFFFFFFFF00000000ULL));
2914 aarch64_set_vec_u64 (cpu, vd, 0, val1);
2916 aarch64_set_vec_u64 (cpu, vd, 1, val2);
2920 do_vec_ZIP (sim_cpu *cpu)
2923 instr[30] = half(0)/full(1)
2924 instr[29,24] = 00 1110
2925 instr[23,22] = size: byte(00), hald(01), word (10), long (11)
2929 instr[14] = lower (0) / upper (1)
2934 int full = uimm (aarch64_get_instr (cpu), 30, 30);
2935 int upper = uimm (aarch64_get_instr (cpu), 14, 14);
2937 unsigned vm = uimm (aarch64_get_instr (cpu), 20, 16);
2938 unsigned vn = uimm (aarch64_get_instr (cpu), 9, 5);
2939 unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
2941 uint64_t val_m1 = aarch64_get_vec_u64 (cpu, vm, 0);
2942 uint64_t val_m2 = aarch64_get_vec_u64 (cpu, vm, 1);
2943 uint64_t val_n1 = aarch64_get_vec_u64 (cpu, vn, 0);
2944 uint64_t val_n2 = aarch64_get_vec_u64 (cpu, vn, 1);
2949 uint64_t input1 = upper ? val_n1 : val_m1;
2950 uint64_t input2 = upper ? val_n2 : val_m2;
2952 NYI_assert (29, 24, 0x0E);
2953 NYI_assert (21, 21, 0);
2954 NYI_assert (15, 15, 0);
2955 NYI_assert (13, 10, 0xE);
2957 switch (uimm (aarch64_get_instr (cpu), 23, 23))
2961 ((input1 << 0) & (0xFF << 0))
2962 | ((input2 << 8) & (0xFF << 8))
2963 | ((input1 << 8) & (0xFF << 16))
2964 | ((input2 << 16) & (0xFF << 24))
2965 | ((input1 << 16) & (0xFFULL << 32))
2966 | ((input2 << 24) & (0xFFULL << 40))
2967 | ((input1 << 24) & (0xFFULL << 48))
2968 | ((input2 << 32) & (0xFFULL << 56));
2971 ((input1 >> 32) & (0xFF << 0))
2972 | ((input2 >> 24) & (0xFF << 8))
2973 | ((input1 >> 24) & (0xFF << 16))
2974 | ((input2 >> 16) & (0xFF << 24))
2975 | ((input1 >> 16) & (0xFFULL << 32))
2976 | ((input2 >> 8) & (0xFFULL << 40))
2977 | ((input1 >> 8) & (0xFFULL << 48))
2978 | ((input2 >> 0) & (0xFFULL << 56));
2983 ((input1 << 0) & (0xFFFF << 0))
2984 | ((input2 << 16) & (0xFFFF << 16))
2985 | ((input1 << 16) & (0xFFFFULL << 32))
2986 | ((input2 << 32) & (0xFFFFULL << 48));
2989 ((input1 >> 32) & (0xFFFF << 0))
2990 | ((input2 >> 16) & (0xFFFF << 16))
2991 | ((input1 >> 16) & (0xFFFFULL << 32))
2992 | ((input2 >> 0) & (0xFFFFULL << 48));
2996 val1 = (input1 & 0xFFFFFFFFULL) | (input2 << 32);
2997 val2 = (input2 & 0xFFFFFFFFULL) | (input1 << 32);
3006 aarch64_set_vec_u64 (cpu, vd, 0, val1);
3008 aarch64_set_vec_u64 (cpu, vd, 1, val2);
3011 /* Floating point immediates are encoded in 8 bits.
3012 fpimm[7] = sign bit.
3013 fpimm[6:4] = signed exponent.
3014 fpimm[3:0] = fraction (assuming leading 1).
3015 i.e. F = s * 1.f * 2^(e - b). */
3018 fp_immediate_for_encoding_32 (uint32_t imm8)
3021 uint32_t s, e, f, i;
3023 s = (imm8 >> 7) & 0x1;
3024 e = (imm8 >> 4) & 0x7;
3027 /* The fp value is s * n/16 * 2r where n is 16+e. */
3028 u = (16.0 + f) / 16.0;
3030 /* N.B. exponent is signed. */
3035 for (i = 0; i <= epos; i++)
3042 for (i = 0; i < eneg; i++)
3053 fp_immediate_for_encoding_64 (uint32_t imm8)
3056 uint32_t s, e, f, i;
3058 s = (imm8 >> 7) & 0x1;
3059 e = (imm8 >> 4) & 0x7;
3062 /* The fp value is s * n/16 * 2r where n is 16+e. */
3063 u = (16.0 + f) / 16.0;
3065 /* N.B. exponent is signed. */
3070 for (i = 0; i <= epos; i++)
3077 for (i = 0; i < eneg; i++)
3088 do_vec_MOV_immediate (sim_cpu *cpu)
3091 instr[30] = full/half selector
3092 instr[29,19] = 00111100000
3093 instr[18,16] = high 3 bits of uimm8
3094 instr[15,12] = size & shift:
3096 0010 => 32-bit + LSL#8
3097 0100 => 32-bit + LSL#16
3098 0110 => 32-bit + LSL#24
3099 1010 => 16-bit + LSL#8
3101 1101 => 32-bit + MSL#16
3102 1100 => 32-bit + MSL#8
3106 instr[9,5] = low 5-bits of uimm8
3109 int full = uimm (aarch64_get_instr (cpu), 30, 30);
3110 unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
3111 unsigned val = uimm (aarch64_get_instr (cpu), 18, 16) << 5
3112 | uimm (aarch64_get_instr (cpu), 9, 5);
3115 NYI_assert (29, 19, 0x1E0);
3116 NYI_assert (11, 10, 1);
3118 switch (uimm (aarch64_get_instr (cpu), 15, 12))
3120 case 0x0: /* 32-bit, no shift. */
3121 case 0x2: /* 32-bit, shift by 8. */
3122 case 0x4: /* 32-bit, shift by 16. */
3123 case 0x6: /* 32-bit, shift by 24. */
3124 val <<= (8 * uimm (aarch64_get_instr (cpu), 14, 13));
3125 for (i = 0; i < (full ? 4 : 2); i++)
3126 aarch64_set_vec_u32 (cpu, vd, i, val);
3129 case 0xa: /* 16-bit, shift by 8. */
3132 case 0x8: /* 16-bit, no shift. */
3133 for (i = 0; i < (full ? 8 : 4); i++)
3134 aarch64_set_vec_u16 (cpu, vd, i, val);
3136 case 0xd: /* 32-bit, mask shift by 16. */
3140 case 0xc: /* 32-bit, mask shift by 8. */
3143 for (i = 0; i < (full ? 4 : 2); i++)
3144 aarch64_set_vec_u32 (cpu, vd, i, val);
3147 case 0xe: /* 8-bit, no shift. */
3148 for (i = 0; i < (full ? 16 : 8); i++)
3149 aarch64_set_vec_u8 (cpu, vd, i, val);
3152 case 0xf: /* FMOV Vs.{2|4}S, #fpimm. */
3154 float u = fp_immediate_for_encoding_32 (val);
3155 for (i = 0; i < (full ? 4 : 2); i++)
3156 aarch64_set_vec_float (cpu, vd, i, u);
3166 do_vec_MVNI (sim_cpu *cpu)
3169 instr[30] = full/half selector
3170 instr[29,19] = 10111100000
3171 instr[18,16] = high 3 bits of uimm8
3172 instr[15,12] = selector
3174 instr[9,5] = low 5-bits of uimm8
3177 int full = uimm (aarch64_get_instr (cpu), 30, 30);
3178 unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
3179 unsigned val = uimm (aarch64_get_instr (cpu), 18, 16) << 5
3180 | uimm (aarch64_get_instr (cpu), 9, 5);
3183 NYI_assert (29, 19, 0x5E0);
3184 NYI_assert (11, 10, 1);
3186 switch (uimm (aarch64_get_instr (cpu), 15, 12))
3188 case 0x0: /* 32-bit, no shift. */
3189 case 0x2: /* 32-bit, shift by 8. */
3190 case 0x4: /* 32-bit, shift by 16. */
3191 case 0x6: /* 32-bit, shift by 24. */
3192 val <<= (8 * uimm (aarch64_get_instr (cpu), 14, 13));
3194 for (i = 0; i < (full ? 4 : 2); i++)
3195 aarch64_set_vec_u32 (cpu, vd, i, val);
3198 case 0xa: /* 16-bit, 8 bit shift. */
3200 case 0x8: /* 16-bit, no shift. */
3202 for (i = 0; i < (full ? 8 : 4); i++)
3203 aarch64_set_vec_u16 (cpu, vd, i, val);
3206 case 0xd: /* 32-bit, mask shift by 16. */
3209 case 0xc: /* 32-bit, mask shift by 8. */
3213 for (i = 0; i < (full ? 4 : 2); i++)
3214 aarch64_set_vec_u32 (cpu, vd, i, val);
3217 case 0xE: /* MOVI Dn, #mask64 */
3221 for (i = 0; i < 8; i++)
3223 mask |= (0xF << (i * 4));
3224 aarch64_set_vec_u64 (cpu, vd, 0, mask);
3225 aarch64_set_vec_u64 (cpu, vd, 1, 0);
3229 case 0xf: /* FMOV Vd.2D, #fpimm. */
3231 double u = fp_immediate_for_encoding_64 (val);
3236 aarch64_set_vec_double (cpu, vd, 0, u);
3237 aarch64_set_vec_double (cpu, vd, 1, u);
3246 #define ABS(A) ((A) < 0 ? - (A) : (A))
3249 do_vec_ABS (sim_cpu *cpu)
3252 instr[30] = half(0)/full(1)
3253 instr[29,24] = 00 1110
3254 instr[23,22] = size: 00=> 8-bit, 01=> 16-bit, 10=> 32-bit, 11=> 64-bit
3255 instr[21,10] = 10 0000 1011 10
3259 unsigned vn = uimm (aarch64_get_instr (cpu), 9, 5);
3260 unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
3261 unsigned full = uimm (aarch64_get_instr (cpu), 30, 30);
3264 NYI_assert (29, 24, 0x0E);
3265 NYI_assert (21, 10, 0x82E);
3267 switch (uimm (aarch64_get_instr (cpu), 23, 22))
3270 for (i = 0; i < (full ? 16 : 8); i++)
3271 aarch64_set_vec_s8 (cpu, vd, i,
3272 ABS (aarch64_get_vec_s8 (cpu, vn, i)));
3276 for (i = 0; i < (full ? 8 : 4); i++)
3277 aarch64_set_vec_s16 (cpu, vd, i,
3278 ABS (aarch64_get_vec_s16 (cpu, vn, i)));
3282 for (i = 0; i < (full ? 4 : 2); i++)
3283 aarch64_set_vec_s32 (cpu, vd, i,
3284 ABS (aarch64_get_vec_s32 (cpu, vn, i)));
3290 for (i = 0; i < 2; i++)
3291 aarch64_set_vec_s64 (cpu, vd, i,
3292 ABS (aarch64_get_vec_s64 (cpu, vn, i)));
3298 do_vec_ADDV (sim_cpu *cpu)
3301 instr[30] = full/half selector
3302 instr[29,24] = 00 1110
3303 instr[23,22] = size: 00=> 8-bit, 01=> 16-bit, 10=> 32-bit, 11=> 64-bit
3304 instr[21,10] = 11 0001 1011 10
3308 unsigned vm = uimm (aarch64_get_instr (cpu), 9, 5);
3309 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
3312 int full = uimm (aarch64_get_instr (cpu), 30, 30);
3314 NYI_assert (29, 24, 0x0E);
3315 NYI_assert (21, 10, 0xC6E);
3317 switch (uimm (aarch64_get_instr (cpu), 23, 22))
3320 for (i = 0; i < (full ? 16 : 8); i++)
3321 val += aarch64_get_vec_u8 (cpu, vm, i);
3322 aarch64_set_reg_u64 (cpu, rd, NO_SP, val);
3326 for (i = 0; i < (full ? 8 : 4); i++)
3327 val += aarch64_get_vec_u16 (cpu, vm, i);
3328 aarch64_set_reg_u64 (cpu, rd, NO_SP, val);
3332 for (i = 0; i < (full ? 4 : 2); i++)
3333 val += aarch64_get_vec_u32 (cpu, vm, i);
3334 aarch64_set_reg_u64 (cpu, rd, NO_SP, val);
3340 val = aarch64_get_vec_u64 (cpu, vm, 0);
3341 val += aarch64_get_vec_u64 (cpu, vm, 1);
3342 aarch64_set_reg_u64 (cpu, rd, NO_SP, val);
3348 do_vec_ins_2 (sim_cpu *cpu)
3350 /* instr[31,21] = 01001110000
3351 instr[20,18] = size & element selector
3353 instr[13] = direction: to vec(0), from vec (1)
3359 unsigned vm = uimm (aarch64_get_instr (cpu), 9, 5);
3360 unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
3362 NYI_assert (31, 21, 0x270);
3363 NYI_assert (17, 14, 0);
3364 NYI_assert (12, 10, 7);
3366 if (uimm (aarch64_get_instr (cpu), 13, 13) == 1)
3368 if (uimm (aarch64_get_instr (cpu), 18, 18) == 1)
3371 elem = uimm (aarch64_get_instr (cpu), 20, 19);
3372 aarch64_set_reg_u64 (cpu, vd, NO_SP,
3373 aarch64_get_vec_u32 (cpu, vm, elem));
3378 if (uimm (aarch64_get_instr (cpu), 19, 19) != 1)
3381 elem = uimm (aarch64_get_instr (cpu), 20, 20);
3382 aarch64_set_reg_u64 (cpu, vd, NO_SP,
3383 aarch64_get_vec_u64 (cpu, vm, elem));
3388 if (uimm (aarch64_get_instr (cpu), 18, 18) == 1)
3391 elem = uimm (aarch64_get_instr (cpu), 20, 19);
3392 aarch64_set_vec_u32 (cpu, vd, elem,
3393 aarch64_get_reg_u32 (cpu, vm, NO_SP));
3398 if (uimm (aarch64_get_instr (cpu), 19, 19) != 1)
3401 elem = uimm (aarch64_get_instr (cpu), 20, 20);
3402 aarch64_set_vec_u64 (cpu, vd, elem,
3403 aarch64_get_reg_u64 (cpu, vm, NO_SP));
3409 do_vec_mull (sim_cpu *cpu)
3412 instr[30] = lower(0)/upper(1) selector
3413 instr[29] = signed(0)/unsigned(1)
3414 instr[28,24] = 0 1110
3415 instr[23,22] = size: 8-bit (00), 16-bit (01), 32-bit (10)
3418 instr[15,10] = 11 0000
3422 int unsign = uimm (aarch64_get_instr (cpu), 29, 29);
3423 int bias = uimm (aarch64_get_instr (cpu), 30, 30);
3424 unsigned vm = uimm (aarch64_get_instr (cpu), 20, 16);
3425 unsigned vn = uimm (aarch64_get_instr (cpu), 9, 5);
3426 unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
3429 NYI_assert (28, 24, 0x0E);
3430 NYI_assert (15, 10, 0x30);
3432 switch (uimm (aarch64_get_instr (cpu), 23, 22))
3438 for (i = 0; i < 8; i++)
3439 aarch64_set_vec_u16 (cpu, vd, i,
3440 aarch64_get_vec_u8 (cpu, vn, i + bias)
3441 * aarch64_get_vec_u8 (cpu, vm, i + bias));
3443 for (i = 0; i < 8; i++)
3444 aarch64_set_vec_s16 (cpu, vd, i,
3445 aarch64_get_vec_s8 (cpu, vn, i + bias)
3446 * aarch64_get_vec_s8 (cpu, vm, i + bias));
3453 for (i = 0; i < 4; i++)
3454 aarch64_set_vec_u32 (cpu, vd, i,
3455 aarch64_get_vec_u16 (cpu, vn, i + bias)
3456 * aarch64_get_vec_u16 (cpu, vm, i + bias));
3458 for (i = 0; i < 4; i++)
3459 aarch64_set_vec_s32 (cpu, vd, i,
3460 aarch64_get_vec_s16 (cpu, vn, i + bias)
3461 * aarch64_get_vec_s16 (cpu, vm, i + bias));
3468 for (i = 0; i < 2; i++)
3469 aarch64_set_vec_u64 (cpu, vd, i,
3470 (uint64_t) aarch64_get_vec_u32 (cpu, vn,
3472 * (uint64_t) aarch64_get_vec_u32 (cpu, vm,
3475 for (i = 0; i < 2; i++)
3476 aarch64_set_vec_s64 (cpu, vd, i,
3477 aarch64_get_vec_s32 (cpu, vn, i + bias)
3478 * aarch64_get_vec_s32 (cpu, vm, i + bias));
3487 do_vec_fadd (sim_cpu *cpu)
3490 instr[30] = half(0)/full(1)
3491 instr[29,24] = 001110
3492 instr[23] = FADD(0)/FSUB(1)
3493 instr[22] = float (0)/double(1)
3496 instr[15,10] = 110101
3500 unsigned vm = uimm (aarch64_get_instr (cpu), 20, 16);
3501 unsigned vn = uimm (aarch64_get_instr (cpu), 9, 5);
3502 unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
3504 int full = uimm (aarch64_get_instr (cpu), 30, 30);
3506 NYI_assert (29, 24, 0x0E);
3507 NYI_assert (21, 21, 1);
3508 NYI_assert (15, 10, 0x35);
3510 if (uimm (aarch64_get_instr (cpu), 23, 23))
3512 if (uimm (aarch64_get_instr (cpu), 22, 22))
3517 for (i = 0; i < 2; i++)
3518 aarch64_set_vec_double (cpu, vd, i,
3519 aarch64_get_vec_double (cpu, vn, i)
3520 - aarch64_get_vec_double (cpu, vm, i));
3524 for (i = 0; i < (full ? 4 : 2); i++)
3525 aarch64_set_vec_float (cpu, vd, i,
3526 aarch64_get_vec_float (cpu, vn, i)
3527 - aarch64_get_vec_float (cpu, vm, i));
3532 if (uimm (aarch64_get_instr (cpu), 22, 22))
3537 for (i = 0; i < 2; i++)
3538 aarch64_set_vec_double (cpu, vd, i,
3539 aarch64_get_vec_double (cpu, vm, i)
3540 + aarch64_get_vec_double (cpu, vn, i));
3544 for (i = 0; i < (full ? 4 : 2); i++)
3545 aarch64_set_vec_float (cpu, vd, i,
3546 aarch64_get_vec_float (cpu, vm, i)
3547 + aarch64_get_vec_float (cpu, vn, i));
3553 do_vec_add (sim_cpu *cpu)
3556 instr[30] = full/half selector
3557 instr[29,24] = 001110
3558 instr[23,22] = size: 00=> 8-bit, 01=> 16-bit, 10=> 32-bit, 11=> 64-bit
3561 instr[15,10] = 100001
3565 unsigned vm = uimm (aarch64_get_instr (cpu), 20, 16);
3566 unsigned vn = uimm (aarch64_get_instr (cpu), 9, 5);
3567 unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
3569 int full = uimm (aarch64_get_instr (cpu), 30, 30);
3571 NYI_assert (29, 24, 0x0E);
3572 NYI_assert (21, 21, 1);
3573 NYI_assert (15, 10, 0x21);
3575 switch (uimm (aarch64_get_instr (cpu), 23, 22))
3578 for (i = 0; i < (full ? 16 : 8); i++)
3579 aarch64_set_vec_u8 (cpu, vd, i, aarch64_get_vec_u8 (cpu, vn, i)
3580 + aarch64_get_vec_u8 (cpu, vm, i));
3584 for (i = 0; i < (full ? 8 : 4); i++)
3585 aarch64_set_vec_u16 (cpu, vd, i, aarch64_get_vec_u16 (cpu, vn, i)
3586 + aarch64_get_vec_u16 (cpu, vm, i));
3590 for (i = 0; i < (full ? 4 : 2); i++)
3591 aarch64_set_vec_u32 (cpu, vd, i, aarch64_get_vec_u32 (cpu, vn, i)
3592 + aarch64_get_vec_u32 (cpu, vm, i));
3598 aarch64_set_vec_u64 (cpu, vd, 0, aarch64_get_vec_u64 (cpu, vn, 0)
3599 + aarch64_get_vec_u64 (cpu, vm, 0));
3600 aarch64_set_vec_u64 (cpu, vd, 1,
3601 aarch64_get_vec_u64 (cpu, vn, 1)
3602 + aarch64_get_vec_u64 (cpu, vm, 1));
3608 do_vec_mul (sim_cpu *cpu)
3611 instr[30] = full/half selector
3612 instr[29,24] = 00 1110
3613 instr[23,22] = size: 00=> 8-bit, 01=> 16-bit, 10=> 32-bit
3616 instr[15,10] = 10 0111
3620 unsigned vm = uimm (aarch64_get_instr (cpu), 20, 16);
3621 unsigned vn = uimm (aarch64_get_instr (cpu), 9, 5);
3622 unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
3624 int full = uimm (aarch64_get_instr (cpu), 30, 30);
3626 NYI_assert (29, 24, 0x0E);
3627 NYI_assert (21, 21, 1);
3628 NYI_assert (15, 10, 0x27);
3630 switch (uimm (aarch64_get_instr (cpu), 23, 22))
3633 for (i = 0; i < (full ? 16 : 8); i++)
3635 uint16_t val = aarch64_get_vec_u8 (cpu, vn, i);
3636 val *= aarch64_get_vec_u8 (cpu, vm, i);
3638 aarch64_set_vec_u16 (cpu, vd, i, val);
3643 for (i = 0; i < (full ? 8 : 4); i++)
3645 uint32_t val = aarch64_get_vec_u16 (cpu, vn, i);
3646 val *= aarch64_get_vec_u16 (cpu, vm, i);
3648 aarch64_set_vec_u32 (cpu, vd, i, val);
3653 for (i = 0; i < (full ? 4 : 2); i++)
3655 uint64_t val = aarch64_get_vec_u32 (cpu, vn, i);
3656 val *= aarch64_get_vec_u32 (cpu, vm, i);
3658 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);
3731 fmaxnm (float a, float b)
3733 if (fpclassify (a) == FP_NORMAL)
3735 if (fpclassify (b) == FP_NORMAL)
3736 return a > b ? a : b;
3739 else if (fpclassify (b) == FP_NORMAL)
3745 fminnm (float a, float b)
3747 if (fpclassify (a) == FP_NORMAL)
3749 if (fpclassify (b) == FP_NORMAL)
3750 return a < b ? a : b;
3753 else if (fpclassify (b) == FP_NORMAL)
3759 dmaxnm (double a, double b)
3761 if (fpclassify (a) == FP_NORMAL)
3763 if (fpclassify (b) == FP_NORMAL)
3764 return a > b ? a : b;
3767 else if (fpclassify (b) == FP_NORMAL)
3773 dminnm (double a, double b)
3775 if (fpclassify (a) == FP_NORMAL)
3777 if (fpclassify (b) == FP_NORMAL)
3778 return a < b ? a : b;
3781 else if (fpclassify (b) == FP_NORMAL)
3787 do_vec_FminmaxNMP (sim_cpu *cpu)
3789 /* aarch64_get_instr (cpu)[31] = 0
3790 aarch64_get_instr (cpu)[30] = half (0)/full (1)
3791 aarch64_get_instr (cpu)[29,24] = 10 1110
3792 aarch64_get_instr (cpu)[23] = max(0)/min(1)
3793 aarch64_get_instr (cpu)[22] = float (0)/double (1)
3794 aarch64_get_instr (cpu)[21] = 1
3795 aarch64_get_instr (cpu)[20,16] = Vn
3796 aarch64_get_instr (cpu)[15,10] = 1100 01
3797 aarch64_get_instr (cpu)[9,5] = Vm
3798 aarch64_get_instr (cpu)[4.0] = Vd. */
3800 unsigned vm = uimm (aarch64_get_instr (cpu), 20, 16);
3801 unsigned vn = uimm (aarch64_get_instr (cpu), 9, 5);
3802 unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
3803 int full = uimm (aarch64_get_instr (cpu), 30, 30);
3805 NYI_assert (29, 24, 0x2E);
3806 NYI_assert (21, 21, 1);
3807 NYI_assert (15, 10, 0x31);
3809 if (uimm (aarch64_get_instr (cpu), 22, 22))
3811 double (* fn)(double, double) = uimm (aarch64_get_instr (cpu), 23, 23)
3816 aarch64_set_vec_double (cpu, vd, 0,
3817 fn (aarch64_get_vec_double (cpu, vn, 0),
3818 aarch64_get_vec_double (cpu, vn, 1)));
3819 aarch64_set_vec_double (cpu, vd, 0,
3820 fn (aarch64_get_vec_double (cpu, vm, 0),
3821 aarch64_get_vec_double (cpu, vm, 1)));
3825 float (* fn)(float, float) = uimm (aarch64_get_instr (cpu), 23, 23)
3828 aarch64_set_vec_float (cpu, vd, 0,
3829 fn (aarch64_get_vec_float (cpu, vn, 0),
3830 aarch64_get_vec_float (cpu, vn, 1)));
3832 aarch64_set_vec_float (cpu, vd, 1,
3833 fn (aarch64_get_vec_float (cpu, vn, 2),
3834 aarch64_get_vec_float (cpu, vn, 3)));
3836 aarch64_set_vec_float (cpu, vd, (full ? 2 : 1),
3837 fn (aarch64_get_vec_float (cpu, vm, 0),
3838 aarch64_get_vec_float (cpu, vm, 1)));
3840 aarch64_set_vec_float (cpu, vd, 3,
3841 fn (aarch64_get_vec_float (cpu, vm, 2),
3842 aarch64_get_vec_float (cpu, vm, 3)));
3847 do_vec_AND (sim_cpu *cpu)
3850 instr[30] = half (0)/full (1)
3851 instr[29,21] = 001110001
3853 instr[15,10] = 000111
3857 unsigned vm = uimm (aarch64_get_instr (cpu), 20, 16);
3858 unsigned vn = uimm (aarch64_get_instr (cpu), 9, 5);
3859 unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
3861 int full = uimm (aarch64_get_instr (cpu), 30, 30);
3863 NYI_assert (29, 21, 0x071);
3864 NYI_assert (15, 10, 0x07);
3866 for (i = 0; i < (full ? 4 : 2); i++)
3867 aarch64_set_vec_u32 (cpu, vd, i,
3868 aarch64_get_vec_u32 (cpu, vn, i)
3869 & aarch64_get_vec_u32 (cpu, vm, i));
3873 do_vec_BSL (sim_cpu *cpu)
3876 instr[30] = half (0)/full (1)
3877 instr[29,21] = 101110011
3879 instr[15,10] = 000111
3883 unsigned vm = uimm (aarch64_get_instr (cpu), 20, 16);
3884 unsigned vn = uimm (aarch64_get_instr (cpu), 9, 5);
3885 unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
3887 int full = uimm (aarch64_get_instr (cpu), 30, 30);
3889 NYI_assert (29, 21, 0x173);
3890 NYI_assert (15, 10, 0x07);
3892 for (i = 0; i < (full ? 16 : 8); i++)
3893 aarch64_set_vec_u8 (cpu, vd, i,
3894 ( aarch64_get_vec_u8 (cpu, vd, i)
3895 & aarch64_get_vec_u8 (cpu, vn, i))
3896 | ((~ aarch64_get_vec_u8 (cpu, vd, i))
3897 & aarch64_get_vec_u8 (cpu, vm, i)));
3901 do_vec_EOR (sim_cpu *cpu)
3904 instr[30] = half (0)/full (1)
3905 instr[29,21] = 10 1110 001
3907 instr[15,10] = 000111
3911 unsigned vm = uimm (aarch64_get_instr (cpu), 20, 16);
3912 unsigned vn = uimm (aarch64_get_instr (cpu), 9, 5);
3913 unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
3915 int full = uimm (aarch64_get_instr (cpu), 30, 30);
3917 NYI_assert (29, 21, 0x171);
3918 NYI_assert (15, 10, 0x07);
3920 for (i = 0; i < (full ? 4 : 2); i++)
3921 aarch64_set_vec_u32 (cpu, vd, i,
3922 aarch64_get_vec_u32 (cpu, vn, i)
3923 ^ aarch64_get_vec_u32 (cpu, vm, i));
3927 do_vec_bit (sim_cpu *cpu)
3930 instr[30] = half (0)/full (1)
3931 instr[29,23] = 10 1110 1
3932 instr[22] = BIT (0) / BIF (1)
3935 instr[15,10] = 0001 11
3939 unsigned vm = uimm (aarch64_get_instr (cpu), 20, 16);
3940 unsigned vn = uimm (aarch64_get_instr (cpu), 9, 5);
3941 unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
3942 unsigned full = uimm (aarch64_get_instr (cpu), 30, 30);
3943 unsigned test_false = uimm (aarch64_get_instr (cpu), 22, 22);
3946 NYI_assert (29, 23, 0x5D);
3947 NYI_assert (21, 21, 1);
3948 NYI_assert (15, 10, 0x07);
3952 for (i = 0; i < (full ? 16 : 8); i++)
3953 if (aarch64_get_vec_u32 (cpu, vn, i) == 0)
3954 aarch64_set_vec_u32 (cpu, vd, i, aarch64_get_vec_u32 (cpu, vm, i));
3958 for (i = 0; i < (full ? 16 : 8); i++)
3959 if (aarch64_get_vec_u32 (cpu, vn, i) != 0)
3960 aarch64_set_vec_u32 (cpu, vd, i, aarch64_get_vec_u32 (cpu, vm, i));
3965 do_vec_ORN (sim_cpu *cpu)
3968 instr[30] = half (0)/full (1)
3969 instr[29,21] = 00 1110 111
3971 instr[15,10] = 00 0111
3975 unsigned vm = uimm (aarch64_get_instr (cpu), 20, 16);
3976 unsigned vn = uimm (aarch64_get_instr (cpu), 9, 5);
3977 unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
3979 int full = uimm (aarch64_get_instr (cpu), 30, 30);
3981 NYI_assert (29, 21, 0x077);
3982 NYI_assert (15, 10, 0x07);
3984 for (i = 0; i < (full ? 16 : 8); i++)
3985 aarch64_set_vec_u8 (cpu, vd, i,
3986 aarch64_get_vec_u8 (cpu, vn, i)
3987 | ~ aarch64_get_vec_u8 (cpu, vm, i));
3991 do_vec_ORR (sim_cpu *cpu)
3994 instr[30] = half (0)/full (1)
3995 instr[29,21] = 00 1110 101
3997 instr[15,10] = 0001 11
4001 unsigned vm = uimm (aarch64_get_instr (cpu), 20, 16);
4002 unsigned vn = uimm (aarch64_get_instr (cpu), 9, 5);
4003 unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
4005 int full = uimm (aarch64_get_instr (cpu), 30, 30);
4007 NYI_assert (29, 21, 0x075);
4008 NYI_assert (15, 10, 0x07);
4010 for (i = 0; i < (full ? 16 : 8); i++)
4011 aarch64_set_vec_u8 (cpu, vd, i,
4012 aarch64_get_vec_u8 (cpu, vn, i)
4013 | aarch64_get_vec_u8 (cpu, vm, i));
4017 do_vec_BIC (sim_cpu *cpu)
4020 instr[30] = half (0)/full (1)
4021 instr[29,21] = 00 1110 011
4023 instr[15,10] = 00 0111
4027 unsigned vm = uimm (aarch64_get_instr (cpu), 20, 16);
4028 unsigned vn = uimm (aarch64_get_instr (cpu), 9, 5);
4029 unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
4031 int full = uimm (aarch64_get_instr (cpu), 30, 30);
4033 NYI_assert (29, 21, 0x073);
4034 NYI_assert (15, 10, 0x07);
4036 for (i = 0; i < (full ? 16 : 8); i++)
4037 aarch64_set_vec_u8 (cpu, vd, i,
4038 aarch64_get_vec_u8 (cpu, vn, i)
4039 & ~ aarch64_get_vec_u8 (cpu, vm, i));
4043 do_vec_XTN (sim_cpu *cpu)
4046 instr[30] = first part (0)/ second part (1)
4047 instr[29,24] = 00 1110
4048 instr[23,22] = size: byte(00), half(01), word (10)
4049 instr[21,10] = 1000 0100 1010
4053 unsigned vs = uimm (aarch64_get_instr (cpu), 9, 5);
4054 unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
4055 unsigned bias = uimm (aarch64_get_instr (cpu), 30, 30);
4058 NYI_assert (29, 24, 0x0E);
4059 NYI_assert (21, 10, 0x84A);
4061 switch (uimm (aarch64_get_instr (cpu), 23, 22))
4065 for (i = 0; i < 8; i++)
4066 aarch64_set_vec_u8 (cpu, vd, i + 8,
4067 aarch64_get_vec_u16 (cpu, vs, i) >> 8);
4069 for (i = 0; i < 8; i++)
4070 aarch64_set_vec_u8 (cpu, vd, i, aarch64_get_vec_u16 (cpu, vs, i));
4075 for (i = 0; i < 4; i++)
4076 aarch64_set_vec_u16 (cpu, vd, i + 4,
4077 aarch64_get_vec_u32 (cpu, vs, i) >> 16);
4079 for (i = 0; i < 4; i++)
4080 aarch64_set_vec_u16 (cpu, vd, i, aarch64_get_vec_u32 (cpu, vs, i));
4085 for (i = 0; i < 2; i++)
4086 aarch64_set_vec_u32 (cpu, vd, i + 4,
4087 aarch64_get_vec_u64 (cpu, vs, i) >> 32);
4089 for (i = 0; i < 2; i++)
4090 aarch64_set_vec_u32 (cpu, vd, i, aarch64_get_vec_u64 (cpu, vs, i));
4096 do_vec_maxv (sim_cpu *cpu)
4099 instr[30] = half(0)/full(1)
4100 instr[29] = signed (0)/unsigned(1)
4101 instr[28,24] = 0 1110
4102 instr[23,22] = size: byte(00), half(01), word (10)
4104 instr[20,17] = 1 000
4105 instr[16] = max(0)/min(1)
4106 instr[15,10] = 1010 10
4107 instr[9,5] = V source
4108 instr[4.0] = R dest. */
4110 unsigned vs = uimm (aarch64_get_instr (cpu), 9, 5);
4111 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
4112 unsigned full = uimm (aarch64_get_instr (cpu), 30, 30);
4115 NYI_assert (28, 24, 0x0E);
4116 NYI_assert (21, 21, 1);
4117 NYI_assert (20, 17, 8);
4118 NYI_assert (15, 10, 0x2A);
4120 switch ((uimm (aarch64_get_instr (cpu), 29, 29) << 1)
4121 | uimm (aarch64_get_instr (cpu), 16, 16))
4123 case 0: /* SMAXV. */
4126 switch (uimm (aarch64_get_instr (cpu), 23, 22))
4129 smax = aarch64_get_vec_s8 (cpu, vs, 0);
4130 for (i = 1; i < (full ? 16 : 8); i++)
4131 smax = max (smax, aarch64_get_vec_s8 (cpu, vs, i));
4134 smax = aarch64_get_vec_s16 (cpu, vs, 0);
4135 for (i = 1; i < (full ? 8 : 4); i++)
4136 smax = max (smax, aarch64_get_vec_s16 (cpu, vs, i));
4139 smax = aarch64_get_vec_s32 (cpu, vs, 0);
4140 for (i = 1; i < (full ? 4 : 2); i++)
4141 smax = max (smax, aarch64_get_vec_s32 (cpu, vs, i));
4146 aarch64_set_reg_s64 (cpu, rd, NO_SP, smax);
4150 case 1: /* SMINV. */
4153 switch (uimm (aarch64_get_instr (cpu), 23, 22))
4156 smin = aarch64_get_vec_s8 (cpu, vs, 0);
4157 for (i = 1; i < (full ? 16 : 8); i++)
4158 smin = min (smin, aarch64_get_vec_s8 (cpu, vs, i));
4161 smin = aarch64_get_vec_s16 (cpu, vs, 0);
4162 for (i = 1; i < (full ? 8 : 4); i++)
4163 smin = min (smin, aarch64_get_vec_s16 (cpu, vs, i));
4166 smin = aarch64_get_vec_s32 (cpu, vs, 0);
4167 for (i = 1; i < (full ? 4 : 2); i++)
4168 smin = min (smin, aarch64_get_vec_s32 (cpu, vs, i));
4174 aarch64_set_reg_s64 (cpu, rd, NO_SP, smin);
4178 case 2: /* UMAXV. */
4181 switch (uimm (aarch64_get_instr (cpu), 23, 22))
4184 umax = aarch64_get_vec_u8 (cpu, vs, 0);
4185 for (i = 1; i < (full ? 16 : 8); i++)
4186 umax = max (umax, aarch64_get_vec_u8 (cpu, vs, i));
4189 umax = aarch64_get_vec_u16 (cpu, vs, 0);
4190 for (i = 1; i < (full ? 8 : 4); i++)
4191 umax = max (umax, aarch64_get_vec_u16 (cpu, vs, i));
4194 umax = aarch64_get_vec_u32 (cpu, vs, 0);
4195 for (i = 1; i < (full ? 4 : 2); i++)
4196 umax = max (umax, aarch64_get_vec_u32 (cpu, vs, i));
4202 aarch64_set_reg_u64 (cpu, rd, NO_SP, umax);
4206 case 3: /* UMINV. */
4209 switch (uimm (aarch64_get_instr (cpu), 23, 22))
4212 umin = aarch64_get_vec_u8 (cpu, vs, 0);
4213 for (i = 1; i < (full ? 16 : 8); i++)
4214 umin = min (umin, aarch64_get_vec_u8 (cpu, vs, i));
4217 umin = aarch64_get_vec_u16 (cpu, vs, 0);
4218 for (i = 1; i < (full ? 8 : 4); i++)
4219 umin = min (umin, aarch64_get_vec_u16 (cpu, vs, i));
4222 umin = aarch64_get_vec_u32 (cpu, vs, 0);
4223 for (i = 1; i < (full ? 4 : 2); i++)
4224 umin = min (umin, aarch64_get_vec_u32 (cpu, vs, i));
4230 aarch64_set_reg_u64 (cpu, rd, NO_SP, umin);
4237 do_vec_fminmaxV (sim_cpu *cpu)
4239 /* instr[31,24] = 0110 1110
4240 instr[23] = max(0)/min(1)
4241 instr[22,14] = 011 0000 11
4242 instr[13,12] = nm(00)/normal(11)
4244 instr[9,5] = V source
4245 instr[4.0] = R dest. */
4247 unsigned vs = uimm (aarch64_get_instr (cpu), 9, 5);
4248 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
4250 float res = aarch64_get_vec_float (cpu, vs, 0);
4252 NYI_assert (31, 24, 0x6E);
4253 NYI_assert (22, 14, 0x0C3);
4254 NYI_assert (11, 10, 2);
4256 if (uimm (aarch64_get_instr (cpu), 23, 23))
4258 switch (uimm (aarch64_get_instr (cpu), 13, 12))
4260 case 0: /* FMNINNMV. */
4261 for (i = 1; i < 4; i++)
4262 res = fminnm (res, aarch64_get_vec_float (cpu, vs, i));
4265 case 3: /* FMINV. */
4266 for (i = 1; i < 4; i++)
4267 res = min (res, aarch64_get_vec_float (cpu, vs, i));
4276 switch (uimm (aarch64_get_instr (cpu), 13, 12))
4278 case 0: /* FMNAXNMV. */
4279 for (i = 1; i < 4; i++)
4280 res = fmaxnm (res, aarch64_get_vec_float (cpu, vs, i));
4283 case 3: /* FMAXV. */
4284 for (i = 1; i < 4; i++)
4285 res = max (res, aarch64_get_vec_float (cpu, vs, i));
4293 aarch64_set_FP_float (cpu, rd, res);
4297 do_vec_Fminmax (sim_cpu *cpu)
4300 instr[30] = half(0)/full(1)
4301 instr[29,24] = 00 1110
4302 instr[23] = max(0)/min(1)
4303 instr[22] = float(0)/double(1)
4307 instr[13,12] = nm(00)/normal(11)
4312 unsigned vm = uimm (aarch64_get_instr (cpu), 20, 16);
4313 unsigned vn = uimm (aarch64_get_instr (cpu), 9, 5);
4314 unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
4315 unsigned full = uimm (aarch64_get_instr (cpu), 30, 30);
4316 unsigned min = uimm (aarch64_get_instr (cpu), 23, 23);
4319 NYI_assert (29, 24, 0x0E);
4320 NYI_assert (21, 21, 1);
4321 NYI_assert (15, 14, 3);
4322 NYI_assert (11, 10, 1);
4324 if (uimm (aarch64_get_instr (cpu), 22, 22))
4326 double (* func)(double, double);
4331 if (uimm (aarch64_get_instr (cpu), 13, 12) == 0)
4332 func = min ? dminnm : dmaxnm;
4333 else if (uimm (aarch64_get_instr (cpu), 13, 12) == 3)
4334 func = min ? fmin : fmax;
4338 for (i = 0; i < 2; i++)
4339 aarch64_set_vec_double (cpu, vd, i,
4340 func (aarch64_get_vec_double (cpu, vn, i),
4341 aarch64_get_vec_double (cpu, vm, i)));
4345 float (* func)(float, float);
4347 if (uimm (aarch64_get_instr (cpu), 13, 12) == 0)
4348 func = min ? fminnm : fmaxnm;
4349 else if (uimm (aarch64_get_instr (cpu), 13, 12) == 3)
4350 func = min ? fminf : fmaxf;
4354 for (i = 0; i < (full ? 4 : 2); i++)
4355 aarch64_set_vec_float (cpu, vd, i,
4356 func (aarch64_get_vec_float (cpu, vn, i),
4357 aarch64_get_vec_float (cpu, vm, i)));
4362 do_vec_SCVTF (sim_cpu *cpu)
4366 instr[29,23] = 00 1110 0
4367 instr[22] = float(0)/double(1)
4368 instr[21,10] = 10 0001 1101 10
4372 unsigned vn = uimm (aarch64_get_instr (cpu), 9, 5);
4373 unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
4374 unsigned full = uimm (aarch64_get_instr (cpu), 30, 30);
4375 unsigned size = uimm (aarch64_get_instr (cpu), 22, 22);
4378 NYI_assert (29, 23, 0x1C);
4379 NYI_assert (21, 10, 0x876);
4386 for (i = 0; i < 2; i++)
4388 double val = (double) aarch64_get_vec_u64 (cpu, vn, i);
4389 aarch64_set_vec_double (cpu, vd, i, val);
4394 for (i = 0; i < (full ? 4 : 2); i++)
4396 float val = (float) aarch64_get_vec_u32 (cpu, vn, i);
4397 aarch64_set_vec_float (cpu, vd, i, val);
4402 #define VEC_CMP(SOURCE, CMP) \
4408 for (i = 0; i < (full ? 16 : 8); i++) \
4409 aarch64_set_vec_u8 (cpu, vd, i, \
4410 aarch64_get_vec_##SOURCE##8 (cpu, vn, i) \
4412 aarch64_get_vec_##SOURCE##8 (cpu, vm, i) \
4416 for (i = 0; i < (full ? 8 : 4); i++) \
4417 aarch64_set_vec_u16 (cpu, vd, i, \
4418 aarch64_get_vec_##SOURCE##16 (cpu, vn, i) \
4420 aarch64_get_vec_##SOURCE##16 (cpu, vm, i) \
4424 for (i = 0; i < (full ? 4 : 2); i++) \
4425 aarch64_set_vec_u32 (cpu, vd, i, \
4426 aarch64_get_vec_##SOURCE##32 (cpu, vn, i) \
4428 aarch64_get_vec_##SOURCE##32 (cpu, vm, i) \
4434 for (i = 0; i < 2; i++) \
4435 aarch64_set_vec_u64 (cpu, vd, i, \
4436 aarch64_get_vec_##SOURCE##64 (cpu, vn, i) \
4438 aarch64_get_vec_##SOURCE##64 (cpu, vm, i) \
4445 #define VEC_CMP0(SOURCE, CMP) \
4451 for (i = 0; i < (full ? 16 : 8); i++) \
4452 aarch64_set_vec_u8 (cpu, vd, i, \
4453 aarch64_get_vec_##SOURCE##8 (cpu, vn, i) \
4457 for (i = 0; i < (full ? 8 : 4); i++) \
4458 aarch64_set_vec_u16 (cpu, vd, i, \
4459 aarch64_get_vec_##SOURCE##16 (cpu, vn, i) \
4463 for (i = 0; i < (full ? 4 : 2); i++) \
4464 aarch64_set_vec_u32 (cpu, vd, i, \
4465 aarch64_get_vec_##SOURCE##32 (cpu, vn, i) \
4471 for (i = 0; i < 2; i++) \
4472 aarch64_set_vec_u64 (cpu, vd, i, \
4473 aarch64_get_vec_##SOURCE##64 (cpu, vn, i) \
4474 CMP 0 ? -1ULL : 0); \
4480 #define VEC_FCMP0(CMP) \
4485 if (uimm (aarch64_get_instr (cpu), 22, 22)) \
4489 for (i = 0; i < 2; i++) \
4490 aarch64_set_vec_u64 (cpu, vd, i, \
4491 aarch64_get_vec_double (cpu, vn, i) \
4492 CMP 0.0 ? -1 : 0); \
4496 for (i = 0; i < (full ? 4 : 2); i++) \
4497 aarch64_set_vec_u32 (cpu, vd, i, \
4498 aarch64_get_vec_float (cpu, vn, i) \
4499 CMP 0.0 ? -1 : 0); \
4505 #define VEC_FCMP(CMP) \
4508 if (uimm (aarch64_get_instr (cpu), 22, 22)) \
4512 for (i = 0; i < 2; i++) \
4513 aarch64_set_vec_u64 (cpu, vd, i, \
4514 aarch64_get_vec_double (cpu, vn, i) \
4516 aarch64_get_vec_double (cpu, vm, i) \
4521 for (i = 0; i < (full ? 4 : 2); i++) \
4522 aarch64_set_vec_u32 (cpu, vd, i, \
4523 aarch64_get_vec_float (cpu, vn, i) \
4525 aarch64_get_vec_float (cpu, vm, i) \
4533 do_vec_compare (sim_cpu *cpu)
4536 instr[30] = half(0)/full(1)
4537 instr[29] = part-of-comparison-type
4538 instr[28,24] = 0 1110
4539 instr[23,22] = size of integer compares: byte(00), half(01), word (10), long (11)
4540 type of float compares: single (-0) / double (-1)
4542 instr[20,16] = Vm or 00000 (compare vs 0)
4543 instr[15,10] = part-of-comparison-type
4547 int full = uimm (aarch64_get_instr (cpu), 30, 30);
4548 int size = uimm (aarch64_get_instr (cpu), 23, 22);
4549 unsigned vm = uimm (aarch64_get_instr (cpu), 20, 16);
4550 unsigned vn = uimm (aarch64_get_instr (cpu), 9, 5);
4551 unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
4554 NYI_assert (28, 24, 0x0E);
4555 NYI_assert (21, 21, 1);
4557 if ((uimm (aarch64_get_instr (cpu), 11, 11)
4558 && uimm (aarch64_get_instr (cpu), 14, 14))
4559 || ((uimm (aarch64_get_instr (cpu), 11, 11) == 0
4560 && uimm (aarch64_get_instr (cpu), 10, 10) == 0)))
4562 /* A compare vs 0. */
4565 if (uimm (aarch64_get_instr (cpu), 15, 10) == 0x2A)
4567 else if (uimm (aarch64_get_instr (cpu), 15, 10) == 0x32
4568 || uimm (aarch64_get_instr (cpu), 15, 10) == 0x3E)
4569 do_vec_fminmaxV (cpu);
4570 else if (uimm (aarch64_get_instr (cpu), 29, 23) == 0x1C
4571 && uimm (aarch64_get_instr (cpu), 21, 10) == 0x876)
4579 if (uimm (aarch64_get_instr (cpu), 14, 14))
4581 /* A floating point compare. */
4582 unsigned decode = (uimm (aarch64_get_instr (cpu), 29, 29) << 5)
4583 | (uimm (aarch64_get_instr (cpu), 23, 23) << 4)
4584 | uimm (aarch64_get_instr (cpu), 13, 10);
4586 NYI_assert (15, 15, 1);
4590 case /* 0b010010: GT#0 */ 0x12: VEC_FCMP0 (>);
4591 case /* 0b110010: GE#0 */ 0x32: VEC_FCMP0 (>=);
4592 case /* 0b010110: EQ#0 */ 0x16: VEC_FCMP0 (==);
4593 case /* 0b110110: LE#0 */ 0x36: VEC_FCMP0 (<=);
4594 case /* 0b011010: LT#0 */ 0x1A: VEC_FCMP0 (<);
4595 case /* 0b111001: GT */ 0x39: VEC_FCMP (>);
4596 case /* 0b101001: GE */ 0x29: VEC_FCMP (>=);
4597 case /* 0b001001: EQ */ 0x09: VEC_FCMP (==);
4605 unsigned decode = (uimm (aarch64_get_instr (cpu), 29, 29) << 6)
4606 | uimm (aarch64_get_instr (cpu), 15, 10);
4610 case 0x0D: /* 0001101 GT */ VEC_CMP (s, > );
4611 case 0x0F: /* 0001111 GE */ VEC_CMP (s, >= );
4612 case 0x22: /* 0100010 GT #0 */ VEC_CMP0 (s, > );
4613 case 0x26: /* 0100110 EQ #0 */ VEC_CMP0 (s, == );
4614 case 0x2A: /* 0101010 LT #0 */ VEC_CMP0 (s, < );
4615 case 0x4D: /* 1001101 HI */ VEC_CMP (u, > );
4616 case 0x4F: /* 1001111 HS */ VEC_CMP (u, >= );
4617 case 0x62: /* 1100010 GE #0 */ VEC_CMP0 (s, >= );
4618 case 0x63: /* 1100011 EQ */ VEC_CMP (u, == );
4619 case 0x66: /* 1100110 LE #0 */ VEC_CMP0 (s, <= );
4629 do_vec_SSHL (sim_cpu *cpu)
4632 instr[30] = first part (0)/ second part (1)
4633 instr[29,24] = 00 1110
4634 instr[23,22] = size: byte(00), half(01), word (10), long (11)
4637 instr[15,10] = 0100 01
4641 unsigned full = uimm (aarch64_get_instr (cpu), 30, 30);
4642 unsigned vm = uimm (aarch64_get_instr (cpu), 20, 16);
4643 unsigned vn = uimm (aarch64_get_instr (cpu), 9, 5);
4644 unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
4648 NYI_assert (29, 24, 0x0E);
4649 NYI_assert (21, 21, 1);
4650 NYI_assert (15, 10, 0x11);
4652 /* FIXME: What is a signed shift left in this context ?. */
4654 switch (uimm (aarch64_get_instr (cpu), 23, 22))
4657 for (i = 0; i < (full ? 16 : 8); i++)
4659 shift = aarch64_get_vec_s8 (cpu, vm, i);
4661 aarch64_set_vec_s8 (cpu, vd, i, aarch64_get_vec_s8 (cpu, vn, i)
4664 aarch64_set_vec_s8 (cpu, vd, i, aarch64_get_vec_s8 (cpu, vn, i)
4670 for (i = 0; i < (full ? 8 : 4); i++)
4672 shift = aarch64_get_vec_s8 (cpu, vm, i);
4674 aarch64_set_vec_s16 (cpu, vd, i, aarch64_get_vec_s16 (cpu, vn, i)
4677 aarch64_set_vec_s16 (cpu, vd, i, aarch64_get_vec_s16 (cpu, vn, i)
4683 for (i = 0; i < (full ? 4 : 2); i++)
4685 shift = aarch64_get_vec_s8 (cpu, vm, i);
4687 aarch64_set_vec_s32 (cpu, vd, i, aarch64_get_vec_s32 (cpu, vn, i)
4690 aarch64_set_vec_s32 (cpu, vd, i, aarch64_get_vec_s32 (cpu, vn, i)
4698 for (i = 0; i < 2; i++)
4700 shift = aarch64_get_vec_s8 (cpu, vm, i);
4702 aarch64_set_vec_s64 (cpu, vd, i, aarch64_get_vec_s64 (cpu, vn, i)
4705 aarch64_set_vec_s64 (cpu, vd, i, aarch64_get_vec_s64 (cpu, vn, i)
4713 do_vec_USHL (sim_cpu *cpu)
4716 instr[30] = first part (0)/ second part (1)
4717 instr[29,24] = 10 1110
4718 instr[23,22] = size: byte(00), half(01), word (10), long (11)
4721 instr[15,10] = 0100 01
4725 unsigned full = uimm (aarch64_get_instr (cpu), 30, 30);
4726 unsigned vm = uimm (aarch64_get_instr (cpu), 20, 16);
4727 unsigned vn = uimm (aarch64_get_instr (cpu), 9, 5);
4728 unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
4732 NYI_assert (29, 24, 0x2E);
4733 NYI_assert (15, 10, 0x11);
4735 switch (uimm (aarch64_get_instr (cpu), 23, 22))
4738 for (i = 0; i < (full ? 16 : 8); i++)
4740 shift = aarch64_get_vec_s8 (cpu, vm, i);
4742 aarch64_set_vec_u8 (cpu, vd, i, aarch64_get_vec_u8 (cpu, vn, i)
4745 aarch64_set_vec_u8 (cpu, vd, i, aarch64_get_vec_u8 (cpu, vn, i)
4751 for (i = 0; i < (full ? 8 : 4); i++)
4753 shift = aarch64_get_vec_s8 (cpu, vm, i);
4755 aarch64_set_vec_u16 (cpu, vd, i, aarch64_get_vec_u16 (cpu, vn, i)
4758 aarch64_set_vec_u16 (cpu, vd, i, aarch64_get_vec_u16 (cpu, vn, i)
4764 for (i = 0; i < (full ? 4 : 2); i++)
4766 shift = aarch64_get_vec_s8 (cpu, vm, i);
4768 aarch64_set_vec_u32 (cpu, vd, i, aarch64_get_vec_u32 (cpu, vn, i)
4771 aarch64_set_vec_u32 (cpu, vd, i, aarch64_get_vec_u32 (cpu, vn, i)
4779 for (i = 0; i < 2; i++)
4781 shift = aarch64_get_vec_s8 (cpu, vm, i);
4783 aarch64_set_vec_u64 (cpu, vd, i, aarch64_get_vec_u64 (cpu, vn, i)
4786 aarch64_set_vec_u64 (cpu, vd, i, aarch64_get_vec_u64 (cpu, vn, i)
4794 do_vec_FMLA (sim_cpu *cpu)
4797 instr[30] = full/half selector
4798 instr[29,23] = 0011100
4799 instr[22] = size: 0=>float, 1=>double
4802 instr[15,10] = 1100 11
4806 unsigned vm = uimm (aarch64_get_instr (cpu), 20, 16);
4807 unsigned vn = uimm (aarch64_get_instr (cpu), 9, 5);
4808 unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
4810 int full = uimm (aarch64_get_instr (cpu), 30, 30);
4812 NYI_assert (29, 23, 0x1C);
4813 NYI_assert (21, 21, 1);
4814 NYI_assert (15, 10, 0x33);
4816 if (uimm (aarch64_get_instr (cpu), 22, 22))
4820 for (i = 0; i < 2; i++)
4821 aarch64_set_vec_double (cpu, vd, i,
4822 aarch64_get_vec_double (cpu, vn, i) *
4823 aarch64_get_vec_double (cpu, vm, i) +
4824 aarch64_get_vec_double (cpu, vd, i));
4828 for (i = 0; i < (full ? 4 : 2); i++)
4829 aarch64_set_vec_float (cpu, vd, i,
4830 aarch64_get_vec_float (cpu, vn, i) *
4831 aarch64_get_vec_float (cpu, vm, i) +
4832 aarch64_get_vec_float (cpu, vd, i));
4837 do_vec_max (sim_cpu *cpu)
4840 instr[30] = full/half selector
4841 instr[29] = SMAX (0) / UMAX (1)
4842 instr[28,24] = 0 1110
4843 instr[23,22] = size: 00=> 8-bit, 01=> 16-bit, 10=> 32-bit
4846 instr[15,10] = 0110 01
4850 unsigned vm = uimm (aarch64_get_instr (cpu), 20, 16);
4851 unsigned vn = uimm (aarch64_get_instr (cpu), 9, 5);
4852 unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
4854 int full = uimm (aarch64_get_instr (cpu), 30, 30);
4856 NYI_assert (28, 24, 0x0E);
4857 NYI_assert (21, 21, 1);
4858 NYI_assert (15, 10, 0x19);
4860 if (uimm (aarch64_get_instr (cpu), 29, 29))
4862 switch (uimm (aarch64_get_instr (cpu), 23, 22))
4865 for (i = 0; i < (full ? 16 : 8); i++)
4866 aarch64_set_vec_u8 (cpu, vd, i,
4867 aarch64_get_vec_u8 (cpu, vn, i)
4868 > aarch64_get_vec_u8 (cpu, vm, i)
4869 ? aarch64_get_vec_u8 (cpu, vn, i)
4870 : aarch64_get_vec_u8 (cpu, vm, i));
4874 for (i = 0; i < (full ? 8 : 4); i++)
4875 aarch64_set_vec_u16 (cpu, vd, i,
4876 aarch64_get_vec_u16 (cpu, vn, i)
4877 > aarch64_get_vec_u16 (cpu, vm, i)
4878 ? aarch64_get_vec_u16 (cpu, vn, i)
4879 : aarch64_get_vec_u16 (cpu, vm, i));
4883 for (i = 0; i < (full ? 4 : 2); i++)
4884 aarch64_set_vec_u32 (cpu, vd, i,
4885 aarch64_get_vec_u32 (cpu, vn, i)
4886 > aarch64_get_vec_u32 (cpu, vm, i)
4887 ? aarch64_get_vec_u32 (cpu, vn, i)
4888 : aarch64_get_vec_u32 (cpu, vm, i));
4897 switch (uimm (aarch64_get_instr (cpu), 23, 22))
4900 for (i = 0; i < (full ? 16 : 8); i++)
4901 aarch64_set_vec_s8 (cpu, vd, i,
4902 aarch64_get_vec_s8 (cpu, vn, i)
4903 > aarch64_get_vec_s8 (cpu, vm, i)
4904 ? aarch64_get_vec_s8 (cpu, vn, i)
4905 : aarch64_get_vec_s8 (cpu, vm, i));
4909 for (i = 0; i < (full ? 8 : 4); i++)
4910 aarch64_set_vec_s16 (cpu, vd, i,
4911 aarch64_get_vec_s16 (cpu, vn, i)
4912 > aarch64_get_vec_s16 (cpu, vm, i)
4913 ? aarch64_get_vec_s16 (cpu, vn, i)
4914 : aarch64_get_vec_s16 (cpu, vm, i));
4918 for (i = 0; i < (full ? 4 : 2); i++)
4919 aarch64_set_vec_s32 (cpu, vd, i,
4920 aarch64_get_vec_s32 (cpu, vn, i)
4921 > aarch64_get_vec_s32 (cpu, vm, i)
4922 ? aarch64_get_vec_s32 (cpu, vn, i)
4923 : aarch64_get_vec_s32 (cpu, vm, i));
4933 do_vec_min (sim_cpu *cpu)
4936 instr[30] = full/half selector
4937 instr[29] = SMIN (0) / UMIN (1)
4938 instr[28,24] = 0 1110
4939 instr[23,22] = size: 00=> 8-bit, 01=> 16-bit, 10=> 32-bit
4942 instr[15,10] = 0110 11
4946 unsigned vm = uimm (aarch64_get_instr (cpu), 20, 16);
4947 unsigned vn = uimm (aarch64_get_instr (cpu), 9, 5);
4948 unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
4950 int full = uimm (aarch64_get_instr (cpu), 30, 30);
4952 NYI_assert (28, 24, 0x0E);
4953 NYI_assert (21, 21, 1);
4954 NYI_assert (15, 10, 0x1B);
4956 if (uimm (aarch64_get_instr (cpu), 29, 29))
4958 switch (uimm (aarch64_get_instr (cpu), 23, 22))
4961 for (i = 0; i < (full ? 16 : 8); i++)
4962 aarch64_set_vec_u8 (cpu, vd, i,
4963 aarch64_get_vec_u8 (cpu, vn, i)
4964 < aarch64_get_vec_u8 (cpu, vm, i)
4965 ? aarch64_get_vec_u8 (cpu, vn, i)
4966 : aarch64_get_vec_u8 (cpu, vm, i));
4970 for (i = 0; i < (full ? 8 : 4); i++)
4971 aarch64_set_vec_u16 (cpu, vd, i,
4972 aarch64_get_vec_u16 (cpu, vn, i)
4973 < aarch64_get_vec_u16 (cpu, vm, i)
4974 ? aarch64_get_vec_u16 (cpu, vn, i)
4975 : aarch64_get_vec_u16 (cpu, vm, i));
4979 for (i = 0; i < (full ? 4 : 2); i++)
4980 aarch64_set_vec_u32 (cpu, vd, i,
4981 aarch64_get_vec_u32 (cpu, vn, i)
4982 < aarch64_get_vec_u32 (cpu, vm, i)
4983 ? aarch64_get_vec_u32 (cpu, vn, i)
4984 : aarch64_get_vec_u32 (cpu, vm, i));
4993 switch (uimm (aarch64_get_instr (cpu), 23, 22))
4996 for (i = 0; i < (full ? 16 : 8); i++)
4997 aarch64_set_vec_s8 (cpu, vd, i,
4998 aarch64_get_vec_s8 (cpu, vn, i)
4999 < aarch64_get_vec_s8 (cpu, vm, i)
5000 ? aarch64_get_vec_s8 (cpu, vn, i)
5001 : aarch64_get_vec_s8 (cpu, vm, i));
5005 for (i = 0; i < (full ? 8 : 4); i++)
5006 aarch64_set_vec_s16 (cpu, vd, i,
5007 aarch64_get_vec_s16 (cpu, vn, i)
5008 < aarch64_get_vec_s16 (cpu, vm, i)
5009 ? aarch64_get_vec_s16 (cpu, vn, i)
5010 : aarch64_get_vec_s16 (cpu, vm, i));
5014 for (i = 0; i < (full ? 4 : 2); i++)
5015 aarch64_set_vec_s32 (cpu, vd, i,
5016 aarch64_get_vec_s32 (cpu, vn, i)
5017 < aarch64_get_vec_s32 (cpu, vm, i)
5018 ? aarch64_get_vec_s32 (cpu, vn, i)
5019 : aarch64_get_vec_s32 (cpu, vm, i));
5029 do_vec_sub_long (sim_cpu *cpu)
5032 instr[30] = lower (0) / upper (1)
5033 instr[29] = signed (0) / unsigned (1)
5034 instr[28,24] = 0 1110
5035 instr[23,22] = size: bytes (00), half (01), word (10)
5038 instr[15,10] = 0010 00
5040 instr[4,0] = V dest. */
5042 unsigned size = uimm (aarch64_get_instr (cpu), 23, 22);
5043 unsigned vm = uimm (aarch64_get_instr (cpu), 20, 16);
5044 unsigned vn = uimm (aarch64_get_instr (cpu), 9, 5);
5045 unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
5049 NYI_assert (28, 24, 0x0E);
5050 NYI_assert (21, 21, 1);
5051 NYI_assert (15, 10, 0x08);
5056 switch (uimm (aarch64_get_instr (cpu), 30, 29))
5058 case 2: /* SSUBL2. */
5060 case 0: /* SSUBL. */
5065 for (i = 0; i < 8; i++)
5066 aarch64_set_vec_s16 (cpu, vd, i,
5067 aarch64_get_vec_s8 (cpu, vn, i + bias)
5068 - aarch64_get_vec_s8 (cpu, vm, i + bias));
5073 for (i = 0; i < 4; i++)
5074 aarch64_set_vec_s32 (cpu, vd, i,
5075 aarch64_get_vec_s16 (cpu, vn, i + bias)
5076 - aarch64_get_vec_s16 (cpu, vm, i + bias));
5080 for (i = 0; i < 2; i++)
5081 aarch64_set_vec_s64 (cpu, vd, i,
5082 aarch64_get_vec_s32 (cpu, vn, i + bias)
5083 - aarch64_get_vec_s32 (cpu, vm, i + bias));
5091 case 3: /* USUBL2. */
5093 case 1: /* USUBL. */
5098 for (i = 0; i < 8; i++)
5099 aarch64_set_vec_u16 (cpu, vd, i,
5100 aarch64_get_vec_u8 (cpu, vn, i + bias)
5101 - aarch64_get_vec_u8 (cpu, vm, i + bias));
5106 for (i = 0; i < 4; i++)
5107 aarch64_set_vec_u32 (cpu, vd, i,
5108 aarch64_get_vec_u16 (cpu, vn, i + bias)
5109 - aarch64_get_vec_u16 (cpu, vm, i + bias));
5113 for (i = 0; i < 2; i++)
5114 aarch64_set_vec_u64 (cpu, vd, i,
5115 aarch64_get_vec_u32 (cpu, vn, i + bias)
5116 - aarch64_get_vec_u32 (cpu, vm, i + bias));
5127 do_vec_ADDP (sim_cpu *cpu)
5130 instr[30] = half(0)/full(1)
5131 instr[29,24] = 00 1110
5132 instr[23,22] = size: bytes (00), half (01), word (10), long (11)
5135 instr[15,10] = 1011 11
5137 instr[4,0] = V dest. */
5141 unsigned full = uimm (aarch64_get_instr (cpu), 30, 30);
5142 unsigned size = uimm (aarch64_get_instr (cpu), 23, 22);
5143 unsigned vm = uimm (aarch64_get_instr (cpu), 20, 16);
5144 unsigned vn = uimm (aarch64_get_instr (cpu), 9, 5);
5145 unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
5148 NYI_assert (29, 24, 0x0E);
5149 NYI_assert (21, 21, 1);
5150 NYI_assert (15, 10, 0x2F);
5152 /* Make copies of the source registers in case vd == vn/vm. */
5153 copy_vn = cpu->fr[vn];
5154 copy_vm = cpu->fr[vm];
5159 range = full ? 8 : 4;
5160 for (i = 0; i < range; i++)
5162 aarch64_set_vec_u8 (cpu, vd, i,
5163 copy_vn.b[i * 2] + copy_vn.b[i * 2 + 1]);
5164 aarch64_set_vec_u8 (cpu, vd, i + range,
5165 copy_vm.b[i * 2] + copy_vm.b[i * 2 + 1]);
5170 range = full ? 4 : 2;
5171 for (i = 0; i < range; i++)
5173 aarch64_set_vec_u16 (cpu, vd, i,
5174 copy_vn.h[i * 2] + copy_vn.h[i * 2 + 1]);
5175 aarch64_set_vec_u16 (cpu, vd, i + range,
5176 copy_vm.h[i * 2] + copy_vm.h[i * 2 + 1]);
5181 range = full ? 2 : 1;
5182 for (i = 0; i < range; i++)
5184 aarch64_set_vec_u32 (cpu, vd, i,
5185 copy_vn.w[i * 2] + copy_vn.w[i * 2 + 1]);
5186 aarch64_set_vec_u32 (cpu, vd, i + range,
5187 copy_vm.w[i * 2] + copy_vm.w[i * 2 + 1]);
5194 aarch64_set_vec_u64 (cpu, vd, 0, copy_vn.v[0] + copy_vn.v[1]);
5195 aarch64_set_vec_u64 (cpu, vd, 1, copy_vm.v[0] + copy_vm.v[1]);
5201 do_vec_UMOV (sim_cpu *cpu)
5204 instr[30] = 32-bit(0)/64-bit(1)
5205 instr[29,21] = 00 1110 000
5206 insrt[20,16] = size & index
5207 instr[15,10] = 0011 11
5208 instr[9,5] = V source
5209 instr[4,0] = R dest. */
5211 unsigned vs = uimm (aarch64_get_instr (cpu), 9, 5);
5212 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
5215 NYI_assert (29, 21, 0x070);
5216 NYI_assert (15, 10, 0x0F);
5218 if (uimm (aarch64_get_instr (cpu), 16, 16))
5220 /* Byte transfer. */
5221 index = uimm (aarch64_get_instr (cpu), 20, 17);
5222 aarch64_set_reg_u64 (cpu, rd, NO_SP,
5223 aarch64_get_vec_u8 (cpu, vs, index));
5225 else if (uimm (aarch64_get_instr (cpu), 17, 17))
5227 index = uimm (aarch64_get_instr (cpu), 20, 18);
5228 aarch64_set_reg_u64 (cpu, rd, NO_SP,
5229 aarch64_get_vec_u16 (cpu, vs, index));
5231 else if (uimm (aarch64_get_instr (cpu), 18, 18))
5233 index = uimm (aarch64_get_instr (cpu), 20, 19);
5234 aarch64_set_reg_u64 (cpu, rd, NO_SP,
5235 aarch64_get_vec_u32 (cpu, vs, index));
5239 if (uimm (aarch64_get_instr (cpu), 30, 30) != 1)
5242 index = uimm (aarch64_get_instr (cpu), 20, 20);
5243 aarch64_set_reg_u64 (cpu, rd, NO_SP,
5244 aarch64_get_vec_u64 (cpu, vs, index));
5249 do_vec_FABS (sim_cpu *cpu)
5252 instr[30] = half(0)/full(1)
5253 instr[29,23] = 00 1110 1
5254 instr[22] = float(0)/double(1)
5255 instr[21,16] = 10 0000
5256 instr[15,10] = 1111 10
5260 unsigned vn = uimm (aarch64_get_instr (cpu), 9, 5);
5261 unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
5262 unsigned full = uimm (aarch64_get_instr (cpu), 30, 30);
5265 NYI_assert (29, 23, 0x1D);
5266 NYI_assert (21, 10, 0x83E);
5268 if (uimm (aarch64_get_instr (cpu), 22, 22))
5273 for (i = 0; i < 2; i++)
5274 aarch64_set_vec_double (cpu, vd, i,
5275 fabs (aarch64_get_vec_double (cpu, vn, i)));
5279 for (i = 0; i < (full ? 4 : 2); i++)
5280 aarch64_set_vec_float (cpu, vd, i,
5281 fabsf (aarch64_get_vec_float (cpu, vn, i)));
5286 do_vec_FCVTZS (sim_cpu *cpu)
5289 instr[30] = half (0) / all (1)
5290 instr[29,23] = 00 1110 1
5291 instr[22] = single (0) / double (1)
5292 instr[21,10] = 10 0001 1011 10
5296 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
5297 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
5298 unsigned full = uimm (aarch64_get_instr (cpu), 30, 30);
5301 NYI_assert (31, 31, 0);
5302 NYI_assert (29, 23, 0x1D);
5303 NYI_assert (21, 10, 0x86E);
5305 if (uimm (aarch64_get_instr (cpu), 22, 22))
5310 for (i = 0; i < 2; i++)
5311 aarch64_set_vec_s64 (cpu, rd, i,
5312 (int64_t) aarch64_get_vec_double (cpu, rn, i));
5315 for (i = 0; i < (full ? 4 : 2); i++)
5316 aarch64_set_vec_s32 (cpu, rd, i,
5317 (int32_t) aarch64_get_vec_float (cpu, rn, i));
5321 do_vec_op1 (sim_cpu *cpu)
5324 instr[30] = half/full
5325 instr[29,24] = 00 1110
5328 instr[15,10] = sub-opcode
5331 NYI_assert (29, 24, 0x0E);
5333 if (uimm (aarch64_get_instr (cpu), 21, 21) == 0)
5335 if (uimm (aarch64_get_instr (cpu), 23, 22) == 0)
5337 if (uimm (aarch64_get_instr (cpu), 30, 30) == 1
5338 && uimm (aarch64_get_instr (cpu), 17, 14) == 0
5339 && uimm (aarch64_get_instr (cpu), 12, 10) == 7)
5340 return do_vec_ins_2 (cpu);
5342 switch (uimm (aarch64_get_instr (cpu), 15, 10))
5344 case 0x01: do_vec_DUP_vector_into_vector (cpu); return;
5345 case 0x03: do_vec_DUP_scalar_into_vector (cpu); return;
5346 case 0x07: do_vec_INS (cpu); return;
5347 case 0x0A: do_vec_TRN (cpu); return;
5350 if (uimm (aarch64_get_instr (cpu), 17, 16) == 0)
5352 do_vec_MOV_into_scalar (cpu);
5361 do_vec_TBL (cpu); return;
5365 do_vec_UZP (cpu); return;
5369 do_vec_ZIP (cpu); return;
5376 switch (uimm (aarch64_get_instr (cpu), 13, 10))
5378 case 0x6: do_vec_UZP (cpu); return;
5379 case 0xE: do_vec_ZIP (cpu); return;
5380 case 0xA: do_vec_TRN (cpu); return;
5381 case 0xF: do_vec_UMOV (cpu); return;
5386 switch (uimm (aarch64_get_instr (cpu), 15, 10))
5389 switch (uimm (aarch64_get_instr (cpu), 23, 21))
5391 case 1: do_vec_AND (cpu); return;
5392 case 3: do_vec_BIC (cpu); return;
5393 case 5: do_vec_ORR (cpu); return;
5394 case 7: do_vec_ORN (cpu); return;
5398 case 0x08: do_vec_sub_long (cpu); return;
5399 case 0x0a: do_vec_XTN (cpu); return;
5400 case 0x11: do_vec_SSHL (cpu); return;
5401 case 0x19: do_vec_max (cpu); return;
5402 case 0x1B: do_vec_min (cpu); return;
5403 case 0x21: do_vec_add (cpu); return;
5404 case 0x25: do_vec_MLA (cpu); return;
5405 case 0x27: do_vec_mul (cpu); return;
5406 case 0x2F: do_vec_ADDP (cpu); return;
5407 case 0x30: do_vec_mull (cpu); return;
5408 case 0x33: do_vec_FMLA (cpu); return;
5409 case 0x35: do_vec_fadd (cpu); return;
5412 switch (uimm (aarch64_get_instr (cpu), 20, 16))
5414 case 0x00: do_vec_ABS (cpu); return;
5415 case 0x01: do_vec_FCVTZS (cpu); return;
5416 case 0x11: do_vec_ADDV (cpu); return;
5422 do_vec_Fminmax (cpu); return;
5434 do_vec_compare (cpu); return;
5437 do_vec_FABS (cpu); return;
5445 do_vec_xtl (sim_cpu *cpu)
5448 instr[30,29] = SXTL (00), UXTL (01), SXTL2 (10), UXTL2 (11)
5449 instr[28,22] = 0 1111 00
5450 instr[21,16] = size & shift (USHLL, SSHLL, USHLL2, SSHLL2)
5451 instr[15,10] = 1010 01
5452 instr[9,5] = V source
5453 instr[4,0] = V dest. */
5455 unsigned vs = uimm (aarch64_get_instr (cpu), 9, 5);
5456 unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
5457 unsigned i, shift, bias = 0;
5459 NYI_assert (28, 22, 0x3C);
5460 NYI_assert (15, 10, 0x29);
5462 switch (uimm (aarch64_get_instr (cpu), 30, 29))
5464 case 2: /* SXTL2, SSHLL2. */
5466 case 0: /* SXTL, SSHLL. */
5467 if (uimm (aarch64_get_instr (cpu), 21, 21))
5469 shift = uimm (aarch64_get_instr (cpu), 20, 16);
5471 (cpu, vd, 0, aarch64_get_vec_s32 (cpu, vs, bias) << shift);
5473 (cpu, vd, 1, aarch64_get_vec_s32 (cpu, vs, bias + 1) << shift);
5475 else if (uimm (aarch64_get_instr (cpu), 20, 20))
5477 shift = uimm (aarch64_get_instr (cpu), 19, 16);
5479 for (i = 0; i < 4; i++)
5481 (cpu, vd, i, aarch64_get_vec_s16 (cpu, vs, i + bias) << shift);
5485 NYI_assert (19, 19, 1);
5487 shift = uimm (aarch64_get_instr (cpu), 18, 16);
5489 for (i = 0; i < 8; i++)
5491 (cpu, vd, i, aarch64_get_vec_s8 (cpu, vs, i + bias) << shift);
5495 case 3: /* UXTL2, USHLL2. */
5497 case 1: /* UXTL, USHLL. */
5498 if (uimm (aarch64_get_instr (cpu), 21, 21))
5500 shift = uimm (aarch64_get_instr (cpu), 20, 16);
5502 (cpu, vd, 0, aarch64_get_vec_u32 (cpu, vs, bias) << shift);
5504 (cpu, vd, 1, aarch64_get_vec_u32 (cpu, vs, bias + 1) << shift);
5506 else if (uimm (aarch64_get_instr (cpu), 20, 20))
5508 shift = uimm (aarch64_get_instr (cpu), 19, 16);
5510 for (i = 0; i < 4; i++)
5512 (cpu, vd, i, aarch64_get_vec_u16 (cpu, vs, i + bias) << shift);
5516 NYI_assert (19, 19, 1);
5518 shift = uimm (aarch64_get_instr (cpu), 18, 16);
5520 for (i = 0; i < 8; i++)
5522 (cpu, vd, i, aarch64_get_vec_u8 (cpu, vs, i + bias) << shift);
5529 do_vec_SHL (sim_cpu *cpu)
5532 instr [30] = half(0)/full(1)
5533 instr [29,23] = 001 1110
5534 instr [22,16] = size and shift amount
5535 instr [15,10] = 01 0101
5537 instr [4, 0] = Vd. */
5540 int full = uimm (aarch64_get_instr (cpu), 30, 30);
5541 unsigned vs = uimm (aarch64_get_instr (cpu), 9, 5);
5542 unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
5545 NYI_assert (29, 23, 0x1E);
5546 NYI_assert (15, 10, 0x15);
5548 if (uimm (aarch64_get_instr (cpu), 22, 22))
5550 shift = uimm (aarch64_get_instr (cpu), 21, 16);
5555 for (i = 0; i < 2; i++)
5557 uint64_t val = aarch64_get_vec_u64 (cpu, vs, i);
5558 aarch64_set_vec_u64 (cpu, vd, i, val << shift);
5564 if (uimm (aarch64_get_instr (cpu), 21, 21))
5566 shift = uimm (aarch64_get_instr (cpu), 20, 16);
5568 for (i = 0; i < (full ? 4 : 2); i++)
5570 uint32_t val = aarch64_get_vec_u32 (cpu, vs, i);
5571 aarch64_set_vec_u32 (cpu, vd, i, val << shift);
5577 if (uimm (aarch64_get_instr (cpu), 20, 20))
5579 shift = uimm (aarch64_get_instr (cpu), 19, 16);
5581 for (i = 0; i < (full ? 8 : 4); i++)
5583 uint16_t val = aarch64_get_vec_u16 (cpu, vs, i);
5584 aarch64_set_vec_u16 (cpu, vd, i, val << shift);
5590 if (uimm (aarch64_get_instr (cpu), 19, 19) == 0)
5593 shift = uimm (aarch64_get_instr (cpu), 18, 16);
5595 for (i = 0; i < (full ? 16 : 8); i++)
5597 uint8_t val = aarch64_get_vec_u8 (cpu, vs, i);
5598 aarch64_set_vec_u8 (cpu, vd, i, val << shift);
5603 do_vec_SSHR_USHR (sim_cpu *cpu)
5606 instr [30] = half(0)/full(1)
5607 instr [29] = signed(0)/unsigned(1)
5608 instr [28,23] = 0 1111 0
5609 instr [22,16] = size and shift amount
5610 instr [15,10] = 0000 01
5612 instr [4, 0] = Vd. */
5614 int full = INSTR (30, 30);
5615 int sign = ! INSTR (29, 29);
5616 unsigned shift = INSTR (22, 16);
5617 unsigned vs = INSTR (9, 5);
5618 unsigned vd = INSTR (4, 0);
5621 NYI_assert (28, 23, 0x1E);
5622 NYI_assert (15, 10, 0x01);
5624 if (uimm (aarch64_get_instr (cpu), 22, 22))
5626 shift = 128 - shift;
5632 for (i = 0; i < 2; i++)
5634 int64_t val = aarch64_get_vec_s64 (cpu, vs, i);
5635 aarch64_set_vec_s64 (cpu, vd, i, val >> shift);
5638 for (i = 0; i < 2; i++)
5640 uint64_t val = aarch64_get_vec_u64 (cpu, vs, i);
5641 aarch64_set_vec_u64 (cpu, vd, i, val >> shift);
5647 if (uimm (aarch64_get_instr (cpu), 21, 21))
5652 for (i = 0; i < (full ? 4 : 2); i++)
5654 int32_t val = aarch64_get_vec_s32 (cpu, vs, i);
5655 aarch64_set_vec_s32 (cpu, vd, i, val >> shift);
5658 for (i = 0; i < (full ? 4 : 2); i++)
5660 uint32_t val = aarch64_get_vec_u32 (cpu, vs, i);
5661 aarch64_set_vec_u32 (cpu, vd, i, val >> shift);
5667 if (uimm (aarch64_get_instr (cpu), 20, 20))
5672 for (i = 0; i < (full ? 8 : 4); i++)
5674 int16_t val = aarch64_get_vec_s16 (cpu, vs, i);
5675 aarch64_set_vec_s16 (cpu, vd, i, val >> shift);
5678 for (i = 0; i < (full ? 8 : 4); i++)
5680 uint16_t val = aarch64_get_vec_u16 (cpu, vs, i);
5681 aarch64_set_vec_u16 (cpu, vd, i, val >> shift);
5687 if (uimm (aarch64_get_instr (cpu), 19, 19) == 0)
5693 for (i = 0; i < (full ? 16 : 8); i++)
5695 int8_t val = aarch64_get_vec_s8 (cpu, vs, i);
5696 aarch64_set_vec_s8 (cpu, vd, i, val >> shift);
5699 for (i = 0; i < (full ? 16 : 8); i++)
5701 uint8_t val = aarch64_get_vec_u8 (cpu, vs, i);
5702 aarch64_set_vec_u8 (cpu, vd, i, val >> shift);
5707 do_vec_MUL_by_element (sim_cpu *cpu)
5710 instr[30] = half/full
5711 instr[29,24] = 00 1111
5722 unsigned full = uimm (aarch64_get_instr (cpu), 30, 30);
5723 unsigned L = uimm (aarch64_get_instr (cpu), 21, 21);
5724 unsigned H = uimm (aarch64_get_instr (cpu), 11, 11);
5725 unsigned vn = uimm (aarch64_get_instr (cpu), 9, 5);
5726 unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
5727 unsigned size = uimm (aarch64_get_instr (cpu), 23, 22);
5732 NYI_assert (29, 24, 0x0F);
5733 NYI_assert (15, 12, 0x8);
5734 NYI_assert (10, 10, 0);
5740 /* 16 bit products. */
5745 index = (H << 2) | (L << 1) | uimm (aarch64_get_instr (cpu), 20, 20);
5746 vm = uimm (aarch64_get_instr (cpu), 19, 16);
5747 element2 = aarch64_get_vec_u16 (cpu, vm, index);
5749 for (e = 0; e < (full ? 8 : 4); e ++)
5751 element1 = aarch64_get_vec_u16 (cpu, vn, e);
5752 product = element1 * element2;
5753 aarch64_set_vec_u16 (cpu, vd, e, product);
5760 /* 32 bit products. */
5765 index = (H << 1) | L;
5766 vm = uimm (aarch64_get_instr (cpu), 20, 16);
5767 element2 = aarch64_get_vec_u32 (cpu, vm, index);
5769 for (e = 0; e < (full ? 4 : 2); e ++)
5771 element1 = aarch64_get_vec_u32 (cpu, vn, e);
5772 product = element1 * element2;
5773 aarch64_set_vec_u32 (cpu, vd, e, product);
5784 do_vec_op2 (sim_cpu *cpu)
5787 instr[30] = half/full
5788 instr[29,24] = 00 1111
5790 instr[22,16] = element size & index
5791 instr[15,10] = sub-opcode
5795 NYI_assert (29, 24, 0x0F);
5797 if (uimm (aarch64_get_instr (cpu), 23, 23) != 0)
5799 switch (uimm (aarch64_get_instr (cpu), 15, 10))
5802 case 0x22: do_vec_MUL_by_element (cpu); return;
5808 switch (uimm (aarch64_get_instr (cpu), 15, 10))
5810 case 0x01: do_vec_SSHR_USHR (cpu); return;
5811 case 0x15: do_vec_SHL (cpu); return;
5813 case 0x22: do_vec_MUL_by_element (cpu); return;
5814 case 0x29: do_vec_xtl (cpu); return;
5821 do_vec_neg (sim_cpu *cpu)
5824 instr[30] = full(1)/half(0)
5825 instr[29,24] = 10 1110
5826 instr[23,22] = size: byte(00), half (01), word (10), long (11)
5827 instr[21,10] = 1000 0010 1110
5831 int full = uimm (aarch64_get_instr (cpu), 30, 30);
5832 unsigned vs = uimm (aarch64_get_instr (cpu), 9, 5);
5833 unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
5836 NYI_assert (29, 24, 0x2E);
5837 NYI_assert (21, 10, 0x82E);
5839 switch (uimm (aarch64_get_instr (cpu), 23, 22))
5842 for (i = 0; i < (full ? 16 : 8); i++)
5843 aarch64_set_vec_s8 (cpu, vd, i, - aarch64_get_vec_s8 (cpu, vs, i));
5847 for (i = 0; i < (full ? 8 : 4); i++)
5848 aarch64_set_vec_s16 (cpu, vd, i, - aarch64_get_vec_s16 (cpu, vs, i));
5852 for (i = 0; i < (full ? 4 : 2); i++)
5853 aarch64_set_vec_s32 (cpu, vd, i, - aarch64_get_vec_s32 (cpu, vs, i));
5859 for (i = 0; i < 2; i++)
5860 aarch64_set_vec_s64 (cpu, vd, i, - aarch64_get_vec_s64 (cpu, vs, i));
5866 do_vec_sqrt (sim_cpu *cpu)
5869 instr[30] = full(1)/half(0)
5870 instr[29,23] = 101 1101
5871 instr[22] = single(0)/double(1)
5872 instr[21,10] = 1000 0111 1110
5876 int full = uimm (aarch64_get_instr (cpu), 30, 30);
5877 unsigned vs = uimm (aarch64_get_instr (cpu), 9, 5);
5878 unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
5881 NYI_assert (29, 23, 0x5B);
5882 NYI_assert (21, 10, 0x87E);
5884 if (uimm (aarch64_get_instr (cpu), 22, 22) == 0)
5885 for (i = 0; i < (full ? 4 : 2); i++)
5886 aarch64_set_vec_float (cpu, vd, i,
5887 sqrtf (aarch64_get_vec_float (cpu, vs, i)));
5889 for (i = 0; i < 2; i++)
5890 aarch64_set_vec_double (cpu, vd, i,
5891 sqrt (aarch64_get_vec_double (cpu, vs, i)));
5895 do_vec_mls_indexed (sim_cpu *cpu)
5898 instr[30] = half(0)/full(1)
5899 instr[29,24] = 10 1111
5900 instr[23,22] = 16-bit(01)/32-bit(10)
5901 instr[21,20+11] = index (if 16-bit)
5902 instr[21+11] = index (if 32-bit)
5905 instr[11] = part of index
5910 int full = uimm (aarch64_get_instr (cpu), 30, 30);
5911 unsigned vs = uimm (aarch64_get_instr (cpu), 9, 5);
5912 unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
5913 unsigned vm = uimm (aarch64_get_instr (cpu), 20, 16);
5916 NYI_assert (15, 12, 4);
5917 NYI_assert (10, 10, 0);
5919 switch (uimm (aarch64_get_instr (cpu), 23, 22))
5929 elem = (uimm (aarch64_get_instr (cpu), 21, 20) << 1)
5930 | uimm (aarch64_get_instr (cpu), 11, 11);
5931 val = aarch64_get_vec_u16 (cpu, vm, elem);
5933 for (i = 0; i < (full ? 8 : 4); i++)
5934 aarch64_set_vec_u32 (cpu, vd, i,
5935 aarch64_get_vec_u32 (cpu, vd, i) -
5936 (aarch64_get_vec_u32 (cpu, vs, i) * val));
5942 unsigned elem = (uimm (aarch64_get_instr (cpu), 21, 21) << 1)
5943 | uimm (aarch64_get_instr (cpu), 11, 11);
5944 uint64_t val = aarch64_get_vec_u32 (cpu, vm, elem);
5946 for (i = 0; i < (full ? 4 : 2); i++)
5947 aarch64_set_vec_u64 (cpu, vd, i,
5948 aarch64_get_vec_u64 (cpu, vd, i) -
5949 (aarch64_get_vec_u64 (cpu, vs, i) * val));
5961 do_vec_SUB (sim_cpu *cpu)
5964 instr [30] = half(0)/full(1)
5965 instr [29,24] = 10 1110
5966 instr [23,22] = size: byte(00, half(01), word (10), long (11)
5969 instr [15,10] = 10 0001
5971 instr [4, 0] = Vd. */
5973 unsigned full = uimm (aarch64_get_instr (cpu), 30, 30);
5974 unsigned vm = uimm (aarch64_get_instr (cpu), 20, 16);
5975 unsigned vn = uimm (aarch64_get_instr (cpu), 9, 5);
5976 unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
5979 NYI_assert (29, 24, 0x2E);
5980 NYI_assert (21, 21, 1);
5981 NYI_assert (15, 10, 0x21);
5983 switch (uimm (aarch64_get_instr (cpu), 23, 22))
5986 for (i = 0; i < (full ? 16 : 8); i++)
5987 aarch64_set_vec_s8 (cpu, vd, i,
5988 aarch64_get_vec_s8 (cpu, vn, i)
5989 - aarch64_get_vec_s8 (cpu, vm, i));
5993 for (i = 0; i < (full ? 8 : 4); i++)
5994 aarch64_set_vec_s16 (cpu, vd, i,
5995 aarch64_get_vec_s16 (cpu, vn, i)
5996 - aarch64_get_vec_s16 (cpu, vm, i));
6000 for (i = 0; i < (full ? 4 : 2); i++)
6001 aarch64_set_vec_s32 (cpu, vd, i,
6002 aarch64_get_vec_s32 (cpu, vn, i)
6003 - aarch64_get_vec_s32 (cpu, vm, i));
6010 for (i = 0; i < 2; i++)
6011 aarch64_set_vec_s64 (cpu, vd, i,
6012 aarch64_get_vec_s64 (cpu, vn, i)
6013 - aarch64_get_vec_s64 (cpu, vm, i));
6019 do_vec_MLS (sim_cpu *cpu)
6022 instr [30] = half(0)/full(1)
6023 instr [29,24] = 10 1110
6024 instr [23,22] = size: byte(00, half(01), word (10)
6027 instr [15,10] = 10 0101
6029 instr [4, 0] = Vd. */
6031 unsigned full = uimm (aarch64_get_instr (cpu), 30, 30);
6032 unsigned vm = uimm (aarch64_get_instr (cpu), 20, 16);
6033 unsigned vn = uimm (aarch64_get_instr (cpu), 9, 5);
6034 unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
6037 NYI_assert (29, 24, 0x2E);
6038 NYI_assert (21, 21, 1);
6039 NYI_assert (15, 10, 0x25);
6041 switch (uimm (aarch64_get_instr (cpu), 23, 22))
6044 for (i = 0; i < (full ? 16 : 8); i++)
6045 aarch64_set_vec_u8 (cpu, vd, i,
6046 (aarch64_get_vec_u8 (cpu, vn, i)
6047 * aarch64_get_vec_u8 (cpu, vm, i))
6048 - aarch64_get_vec_u8 (cpu, vd, i));
6052 for (i = 0; i < (full ? 8 : 4); i++)
6053 aarch64_set_vec_u16 (cpu, vd, i,
6054 (aarch64_get_vec_u16 (cpu, vn, i)
6055 * aarch64_get_vec_u16 (cpu, vm, i))
6056 - aarch64_get_vec_u16 (cpu, vd, i));
6060 for (i = 0; i < (full ? 4 : 2); i++)
6061 aarch64_set_vec_u32 (cpu, vd, i,
6062 (aarch64_get_vec_u32 (cpu, vn, i)
6063 * aarch64_get_vec_u32 (cpu, vm, i))
6064 - aarch64_get_vec_u32 (cpu, vd, i));
6073 do_vec_FDIV (sim_cpu *cpu)
6076 instr [30] = half(0)/full(1)
6077 instr [29,23] = 10 1110 0
6078 instr [22] = float()/double(1)
6081 instr [15,10] = 1111 11
6083 instr [4, 0] = Vd. */
6085 unsigned full = uimm (aarch64_get_instr (cpu), 30, 30);
6086 unsigned vm = uimm (aarch64_get_instr (cpu), 20, 16);
6087 unsigned vn = uimm (aarch64_get_instr (cpu), 9, 5);
6088 unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
6091 NYI_assert (29, 23, 0x5C);
6092 NYI_assert (21, 21, 1);
6093 NYI_assert (15, 10, 0x3F);
6095 if (uimm (aarch64_get_instr (cpu), 22, 22))
6100 for (i = 0; i < 2; i++)
6101 aarch64_set_vec_double (cpu, vd, i,
6102 aarch64_get_vec_double (cpu, vn, i)
6103 / aarch64_get_vec_double (cpu, vm, i));
6106 for (i = 0; i < (full ? 4 : 2); i++)
6107 aarch64_set_vec_float (cpu, vd, i,
6108 aarch64_get_vec_float (cpu, vn, i)
6109 / aarch64_get_vec_float (cpu, vm, i));
6113 do_vec_FMUL (sim_cpu *cpu)
6116 instr [30] = half(0)/full(1)
6117 instr [29,23] = 10 1110 0
6118 instr [22] = float(0)/double(1)
6121 instr [15,10] = 1101 11
6123 instr [4, 0] = Vd. */
6125 unsigned full = uimm (aarch64_get_instr (cpu), 30, 30);
6126 unsigned vm = uimm (aarch64_get_instr (cpu), 20, 16);
6127 unsigned vn = uimm (aarch64_get_instr (cpu), 9, 5);
6128 unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
6131 NYI_assert (29, 23, 0x5C);
6132 NYI_assert (21, 21, 1);
6133 NYI_assert (15, 10, 0x37);
6135 if (uimm (aarch64_get_instr (cpu), 22, 22))
6140 for (i = 0; i < 2; i++)
6141 aarch64_set_vec_double (cpu, vd, i,
6142 aarch64_get_vec_double (cpu, vn, i)
6143 * aarch64_get_vec_double (cpu, vm, i));
6146 for (i = 0; i < (full ? 4 : 2); i++)
6147 aarch64_set_vec_float (cpu, vd, i,
6148 aarch64_get_vec_float (cpu, vn, i)
6149 * aarch64_get_vec_float (cpu, vm, i));
6153 do_vec_FADDP (sim_cpu *cpu)
6156 instr [30] = half(0)/full(1)
6157 instr [29,23] = 10 1110 0
6158 instr [22] = float(0)/double(1)
6161 instr [15,10] = 1101 01
6163 instr [4, 0] = Vd. */
6165 unsigned full = uimm (aarch64_get_instr (cpu), 30, 30);
6166 unsigned vm = uimm (aarch64_get_instr (cpu), 20, 16);
6167 unsigned vn = uimm (aarch64_get_instr (cpu), 9, 5);
6168 unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
6170 NYI_assert (29, 23, 0x5C);
6171 NYI_assert (21, 21, 1);
6172 NYI_assert (15, 10, 0x35);
6174 if (uimm (aarch64_get_instr (cpu), 22, 22))
6176 /* Extract values before adding them incase vd == vn/vm. */
6177 double tmp1 = aarch64_get_vec_double (cpu, vn, 0);
6178 double tmp2 = aarch64_get_vec_double (cpu, vn, 1);
6179 double tmp3 = aarch64_get_vec_double (cpu, vm, 0);
6180 double tmp4 = aarch64_get_vec_double (cpu, vm, 1);
6185 aarch64_set_vec_double (cpu, vd, 0, tmp1 + tmp2);
6186 aarch64_set_vec_double (cpu, vd, 1, tmp3 + tmp4);
6190 /* Extract values before adding them incase vd == vn/vm. */
6191 float tmp1 = aarch64_get_vec_float (cpu, vn, 0);
6192 float tmp2 = aarch64_get_vec_float (cpu, vn, 1);
6193 float tmp5 = aarch64_get_vec_float (cpu, vm, 0);
6194 float tmp6 = aarch64_get_vec_float (cpu, vm, 1);
6198 float tmp3 = aarch64_get_vec_float (cpu, vn, 2);
6199 float tmp4 = aarch64_get_vec_float (cpu, vn, 3);
6200 float tmp7 = aarch64_get_vec_float (cpu, vm, 2);
6201 float tmp8 = aarch64_get_vec_float (cpu, vm, 3);
6203 aarch64_set_vec_float (cpu, vd, 0, tmp1 + tmp2);
6204 aarch64_set_vec_float (cpu, vd, 1, tmp3 + tmp4);
6205 aarch64_set_vec_float (cpu, vd, 2, tmp5 + tmp6);
6206 aarch64_set_vec_float (cpu, vd, 3, tmp7 + tmp8);
6210 aarch64_set_vec_float (cpu, vd, 0, tmp1 + tmp2);
6211 aarch64_set_vec_float (cpu, vd, 1, tmp5 + tmp6);
6217 do_vec_FSQRT (sim_cpu *cpu)
6220 instr[30] = half(0)/full(1)
6221 instr[29,23] = 10 1110 1
6222 instr[22] = single(0)/double(1)
6223 instr[21,10] = 10 0001 1111 10
6225 instr[4,0] = Vdest. */
6227 unsigned vn = uimm (aarch64_get_instr (cpu), 9, 5);
6228 unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
6229 unsigned full = uimm (aarch64_get_instr (cpu), 30, 30);
6232 NYI_assert (29, 23, 0x5D);
6233 NYI_assert (21, 10, 0x87E);
6235 if (uimm (aarch64_get_instr (cpu), 22, 22))
6240 for (i = 0; i < 2; i++)
6241 aarch64_set_vec_double (cpu, vd, i,
6242 sqrt (aarch64_get_vec_double (cpu, vn, i)));
6246 for (i = 0; i < (full ? 4 : 2); i++)
6247 aarch64_set_vec_float (cpu, vd, i,
6248 sqrtf (aarch64_get_vec_float (cpu, vn, i)));
6253 do_vec_FNEG (sim_cpu *cpu)
6256 instr[30] = half (0)/full (1)
6257 instr[29,23] = 10 1110 1
6258 instr[22] = single (0)/double (1)
6259 instr[21,10] = 10 0000 1111 10
6261 instr[4,0] = Vdest. */
6263 unsigned vn = uimm (aarch64_get_instr (cpu), 9, 5);
6264 unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
6265 unsigned full = uimm (aarch64_get_instr (cpu), 30, 30);
6268 NYI_assert (29, 23, 0x5D);
6269 NYI_assert (21, 10, 0x83E);
6271 if (uimm (aarch64_get_instr (cpu), 22, 22))
6276 for (i = 0; i < 2; i++)
6277 aarch64_set_vec_double (cpu, vd, i,
6278 - aarch64_get_vec_double (cpu, vn, i));
6282 for (i = 0; i < (full ? 4 : 2); i++)
6283 aarch64_set_vec_float (cpu, vd, i,
6284 - aarch64_get_vec_float (cpu, vn, i));
6289 do_vec_NOT (sim_cpu *cpu)
6292 instr[30] = half (0)/full (1)
6293 instr[29,10] = 10 1110 0010 0000 0101 10
6297 unsigned vn = uimm (aarch64_get_instr (cpu), 9, 5);
6298 unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
6300 int full = uimm (aarch64_get_instr (cpu), 30, 30);
6302 NYI_assert (29, 10, 0xB8816);
6304 for (i = 0; i < (full ? 16 : 8); i++)
6305 aarch64_set_vec_u8 (cpu, vd, i, ~ aarch64_get_vec_u8 (cpu, vn, i));
6309 clz (uint64_t val, unsigned size)
6314 mask <<= (size - 1);
6329 do_vec_CLZ (sim_cpu *cpu)
6332 instr[30] = half (0)/full (1)
6333 instr[29,24] = 10 1110
6335 instr[21,10] = 10 0000 0100 10
6339 unsigned vn = INSTR (9, 5);
6340 unsigned vd = INSTR (4, 0);
6342 int full = INSTR (30,30);
6344 NYI_assert (29, 24, 0x2E);
6345 NYI_assert (21, 10, 0x812);
6347 switch (INSTR (23, 22))
6350 for (i = 0; i < (full ? 16 : 8); i++)
6351 aarch64_set_vec_u8 (cpu, vd, i, clz (aarch64_get_vec_u8 (cpu, vn, i), 8));
6354 for (i = 0; i < (full ? 8 : 4); i++)
6355 aarch64_set_vec_u16 (cpu, vd, i, clz (aarch64_get_vec_u16 (cpu, vn, i), 16));
6358 for (i = 0; i < (full ? 4 : 2); i++)
6359 aarch64_set_vec_u32 (cpu, vd, i, clz (aarch64_get_vec_u32 (cpu, vn, i), 32));
6364 aarch64_set_vec_u64 (cpu, vd, 0, clz (aarch64_get_vec_u64 (cpu, vn, 0), 64));
6365 aarch64_set_vec_u64 (cpu, vd, 1, clz (aarch64_get_vec_u64 (cpu, vn, 1), 64));
6371 do_vec_MOV_element (sim_cpu *cpu)
6373 /* instr[31,21] = 0110 1110 000
6374 instr[20,16] = size & dest index
6376 instr[14,11] = source index
6381 unsigned vs = uimm (aarch64_get_instr (cpu), 9, 5);
6382 unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
6386 NYI_assert (31, 21, 0x370);
6387 NYI_assert (15, 15, 0);
6388 NYI_assert (10, 10, 1);
6390 if (uimm (aarch64_get_instr (cpu), 16, 16))
6393 src_index = uimm (aarch64_get_instr (cpu), 14, 11);
6394 dst_index = uimm (aarch64_get_instr (cpu), 20, 17);
6395 aarch64_set_vec_u8 (cpu, vd, dst_index,
6396 aarch64_get_vec_u8 (cpu, vs, src_index));
6398 else if (uimm (aarch64_get_instr (cpu), 17, 17))
6401 NYI_assert (11, 11, 0);
6402 src_index = uimm (aarch64_get_instr (cpu), 14, 12);
6403 dst_index = uimm (aarch64_get_instr (cpu), 20, 18);
6404 aarch64_set_vec_u16 (cpu, vd, dst_index,
6405 aarch64_get_vec_u16 (cpu, vs, src_index));
6407 else if (uimm (aarch64_get_instr (cpu), 18, 18))
6410 NYI_assert (12, 11, 0);
6411 src_index = uimm (aarch64_get_instr (cpu), 14, 13);
6412 dst_index = uimm (aarch64_get_instr (cpu), 20, 19);
6413 aarch64_set_vec_u32 (cpu, vd, dst_index,
6414 aarch64_get_vec_u32 (cpu, vs, src_index));
6418 NYI_assert (19, 19, 1);
6419 NYI_assert (13, 11, 0);
6420 src_index = uimm (aarch64_get_instr (cpu), 14, 14);
6421 dst_index = uimm (aarch64_get_instr (cpu), 20, 20);
6422 aarch64_set_vec_u64 (cpu, vd, dst_index,
6423 aarch64_get_vec_u64 (cpu, vs, src_index));
6428 dexAdvSIMD0 (sim_cpu *cpu)
6430 /* instr [28,25] = 0 111. */
6431 if ( uimm (aarch64_get_instr (cpu), 15, 10) == 0x07
6432 && (uimm (aarch64_get_instr (cpu), 9, 5) ==
6433 uimm (aarch64_get_instr (cpu), 20, 16)))
6435 if (uimm (aarch64_get_instr (cpu), 31, 21) == 0x075
6436 || uimm (aarch64_get_instr (cpu), 31, 21) == 0x275)
6438 do_vec_MOV_whole_vector (cpu);
6443 if (uimm (aarch64_get_instr (cpu), 29, 19) == 0x1E0)
6445 do_vec_MOV_immediate (cpu);
6449 if (uimm (aarch64_get_instr (cpu), 29, 19) == 0x5E0)
6455 if (uimm (aarch64_get_instr (cpu), 29, 19) == 0x1C0
6456 || uimm (aarch64_get_instr (cpu), 29, 19) == 0x1C1)
6458 if (uimm (aarch64_get_instr (cpu), 15, 10) == 0x03)
6460 do_vec_DUP_scalar_into_vector (cpu);
6465 switch (uimm (aarch64_get_instr (cpu), 29, 24))
6467 case 0x0E: do_vec_op1 (cpu); return;
6468 case 0x0F: do_vec_op2 (cpu); return;
6471 switch (uimm (aarch64_get_instr (cpu), 15, 10))
6473 case 0x01: do_vec_SSHR_USHR (cpu); return;
6475 case 0x12: do_vec_mls_indexed (cpu); return;
6476 case 0x29: do_vec_xtl (cpu); return;
6482 if (uimm (aarch64_get_instr (cpu), 21, 21) == 1)
6484 switch (uimm (aarch64_get_instr (cpu), 15, 10))
6487 switch (uimm (aarch64_get_instr (cpu), 23, 22))
6489 case 0: do_vec_EOR (cpu); return;
6490 case 1: do_vec_BSL (cpu); return;
6492 case 3: do_vec_bit (cpu); return;
6496 case 0x08: do_vec_sub_long (cpu); return;
6497 case 0x11: do_vec_USHL (cpu); return;
6498 case 0x12: do_vec_CLZ (cpu); return;
6499 case 0x16: do_vec_NOT (cpu); return;
6500 case 0x19: do_vec_max (cpu); return;
6501 case 0x1B: do_vec_min (cpu); return;
6502 case 0x21: do_vec_SUB (cpu); return;
6503 case 0x25: do_vec_MLS (cpu); return;
6504 case 0x31: do_vec_FminmaxNMP (cpu); return;
6505 case 0x35: do_vec_FADDP (cpu); return;
6506 case 0x37: do_vec_FMUL (cpu); return;
6507 case 0x3F: do_vec_FDIV (cpu); return;
6510 switch (uimm (aarch64_get_instr (cpu), 20, 16))
6512 case 0x00: do_vec_FNEG (cpu); return;
6513 case 0x01: do_vec_FSQRT (cpu); return;
6527 do_vec_compare (cpu); return;
6534 if (uimm (aarch64_get_instr (cpu), 31, 21) == 0x370)
6536 do_vec_MOV_element (cpu);
6540 switch (uimm (aarch64_get_instr (cpu), 21, 10))
6542 case 0x82E: do_vec_neg (cpu); return;
6543 case 0x87E: do_vec_sqrt (cpu); return;
6545 if (uimm (aarch64_get_instr (cpu), 15, 10) == 0x30)
6563 /* Float multiply add. */
6565 fmadds (sim_cpu *cpu)
6567 unsigned sa = uimm (aarch64_get_instr (cpu), 14, 10);
6568 unsigned sm = uimm (aarch64_get_instr (cpu), 20, 16);
6569 unsigned sn = uimm (aarch64_get_instr (cpu), 9, 5);
6570 unsigned sd = uimm (aarch64_get_instr (cpu), 4, 0);
6572 aarch64_set_FP_float (cpu, sd, aarch64_get_FP_float (cpu, sa)
6573 + aarch64_get_FP_float (cpu, sn)
6574 * aarch64_get_FP_float (cpu, sm));
6577 /* Double multiply add. */
6579 fmaddd (sim_cpu *cpu)
6581 unsigned sa = uimm (aarch64_get_instr (cpu), 14, 10);
6582 unsigned sm = uimm (aarch64_get_instr (cpu), 20, 16);
6583 unsigned sn = uimm (aarch64_get_instr (cpu), 9, 5);
6584 unsigned sd = uimm (aarch64_get_instr (cpu), 4, 0);
6586 aarch64_set_FP_double (cpu, sd, aarch64_get_FP_double (cpu, sa)
6587 + aarch64_get_FP_double (cpu, sn)
6588 * aarch64_get_FP_double (cpu, sm));
6591 /* Float multiply subtract. */
6593 fmsubs (sim_cpu *cpu)
6595 unsigned sa = uimm (aarch64_get_instr (cpu), 14, 10);
6596 unsigned sm = uimm (aarch64_get_instr (cpu), 20, 16);
6597 unsigned sn = uimm (aarch64_get_instr (cpu), 9, 5);
6598 unsigned sd = uimm (aarch64_get_instr (cpu), 4, 0);
6600 aarch64_set_FP_float (cpu, sd, aarch64_get_FP_float (cpu, sa)
6601 - aarch64_get_FP_float (cpu, sn)
6602 * aarch64_get_FP_float (cpu, sm));
6605 /* Double multiply subtract. */
6607 fmsubd (sim_cpu *cpu)
6609 unsigned sa = uimm (aarch64_get_instr (cpu), 14, 10);
6610 unsigned sm = uimm (aarch64_get_instr (cpu), 20, 16);
6611 unsigned sn = uimm (aarch64_get_instr (cpu), 9, 5);
6612 unsigned sd = uimm (aarch64_get_instr (cpu), 4, 0);
6614 aarch64_set_FP_double (cpu, sd, aarch64_get_FP_double (cpu, sa)
6615 - aarch64_get_FP_double (cpu, sn)
6616 * aarch64_get_FP_double (cpu, sm));
6619 /* Float negative multiply add. */
6621 fnmadds (sim_cpu *cpu)
6623 unsigned sa = uimm (aarch64_get_instr (cpu), 14, 10);
6624 unsigned sm = uimm (aarch64_get_instr (cpu), 20, 16);
6625 unsigned sn = uimm (aarch64_get_instr (cpu), 9, 5);
6626 unsigned sd = uimm (aarch64_get_instr (cpu), 4, 0);
6628 aarch64_set_FP_float (cpu, sd, - aarch64_get_FP_float (cpu, sa)
6629 + (- aarch64_get_FP_float (cpu, sn))
6630 * aarch64_get_FP_float (cpu, sm));
6633 /* Double negative multiply add. */
6635 fnmaddd (sim_cpu *cpu)
6637 unsigned sa = uimm (aarch64_get_instr (cpu), 14, 10);
6638 unsigned sm = uimm (aarch64_get_instr (cpu), 20, 16);
6639 unsigned sn = uimm (aarch64_get_instr (cpu), 9, 5);
6640 unsigned sd = uimm (aarch64_get_instr (cpu), 4, 0);
6642 aarch64_set_FP_double (cpu, sd, - aarch64_get_FP_double (cpu, sa)
6643 + (- aarch64_get_FP_double (cpu, sn))
6644 * aarch64_get_FP_double (cpu, sm));
6647 /* Float negative multiply subtract. */
6649 fnmsubs (sim_cpu *cpu)
6651 unsigned sa = uimm (aarch64_get_instr (cpu), 14, 10);
6652 unsigned sm = uimm (aarch64_get_instr (cpu), 20, 16);
6653 unsigned sn = uimm (aarch64_get_instr (cpu), 9, 5);
6654 unsigned sd = uimm (aarch64_get_instr (cpu), 4, 0);
6656 aarch64_set_FP_float (cpu, sd, - aarch64_get_FP_float (cpu, sa)
6657 + aarch64_get_FP_float (cpu, sn)
6658 * aarch64_get_FP_float (cpu, sm));
6661 /* Double negative multiply subtract. */
6663 fnmsubd (sim_cpu *cpu)
6665 unsigned sa = uimm (aarch64_get_instr (cpu), 14, 10);
6666 unsigned sm = uimm (aarch64_get_instr (cpu), 20, 16);
6667 unsigned sn = uimm (aarch64_get_instr (cpu), 9, 5);
6668 unsigned sd = uimm (aarch64_get_instr (cpu), 4, 0);
6670 aarch64_set_FP_double (cpu, sd, - aarch64_get_FP_double (cpu, sa)
6671 + aarch64_get_FP_double (cpu, sn)
6672 * aarch64_get_FP_double (cpu, sm));
6676 dexSimpleFPDataProc3Source (sim_cpu *cpu)
6678 /* instr[31] ==> M : 0 ==> OK, 1 ==> UNALLOC
6680 instr[29] ==> S : 0 ==> OK, 1 ==> UNALLOC
6683 instr[23,22] ==> type : 0 ==> single, 01 ==> double, 1x ==> UNALLOC
6684 instr[21] ==> o1 : 0 ==> unnegated, 1 ==> negated
6685 instr[15] ==> o2 : 0 ==> ADD, 1 ==> SUB */
6687 uint32_t M_S = (uimm (aarch64_get_instr (cpu), 31, 31) << 1)
6688 | uimm (aarch64_get_instr (cpu), 29, 29);
6689 /* dispatch on combined type:o1:o2. */
6690 uint32_t dispatch = (uimm (aarch64_get_instr (cpu), 23, 21) << 1)
6691 | uimm (aarch64_get_instr (cpu), 15, 15);
6698 case 0: fmadds (cpu); return;
6699 case 1: fmsubs (cpu); return;
6700 case 2: fnmadds (cpu); return;
6701 case 3: fnmsubs (cpu); return;
6702 case 4: fmaddd (cpu); return;
6703 case 5: fmsubd (cpu); return;
6704 case 6: fnmaddd (cpu); return;
6705 case 7: fnmsubd (cpu); return;
6707 /* type > 1 is currently unallocated. */
6713 dexSimpleFPFixedConvert (sim_cpu *cpu)
6719 dexSimpleFPCondCompare (sim_cpu *cpu)
6721 /* instr [31,23] = 0001 1110 0
6725 instr [15,12] = condition
6729 instr [3,0] = nzcv */
6731 unsigned rm = INSTR (20, 16);
6732 unsigned rn = INSTR (9, 5);
6734 NYI_assert (31, 23, 0x3C);
6735 NYI_assert (11, 10, 0x1);
6736 NYI_assert (4, 4, 0);
6738 if (! testConditionCode (cpu, INSTR (15, 12)))
6740 aarch64_set_CPSR (cpu, INSTR (3, 0));
6746 /* Double precision. */
6747 double val1 = aarch64_get_vec_double (cpu, rn, 0);
6748 double val2 = aarch64_get_vec_double (cpu, rm, 0);
6750 /* FIXME: Check for NaNs. */
6752 aarch64_set_CPSR (cpu, (Z | C));
6753 else if (val1 < val2)
6754 aarch64_set_CPSR (cpu, N);
6755 else /* val1 > val2 */
6756 aarch64_set_CPSR (cpu, C);
6760 /* Single precision. */
6761 float val1 = aarch64_get_vec_float (cpu, rn, 0);
6762 float val2 = aarch64_get_vec_float (cpu, rm, 0);
6764 /* FIXME: Check for NaNs. */
6766 aarch64_set_CPSR (cpu, (Z | C));
6767 else if (val1 < val2)
6768 aarch64_set_CPSR (cpu, N);
6769 else /* val1 > val2 */
6770 aarch64_set_CPSR (cpu, C);
6778 fadds (sim_cpu *cpu)
6780 unsigned sm = uimm (aarch64_get_instr (cpu), 20, 16);
6781 unsigned sn = uimm (aarch64_get_instr (cpu), 9, 5);
6782 unsigned sd = uimm (aarch64_get_instr (cpu), 4, 0);
6784 aarch64_set_FP_float (cpu, sd, aarch64_get_FP_float (cpu, sn)
6785 + aarch64_get_FP_float (cpu, sm));
6790 faddd (sim_cpu *cpu)
6792 unsigned sm = uimm (aarch64_get_instr (cpu), 20, 16);
6793 unsigned sn = uimm (aarch64_get_instr (cpu), 9, 5);
6794 unsigned sd = uimm (aarch64_get_instr (cpu), 4, 0);
6796 aarch64_set_FP_double (cpu, sd, aarch64_get_FP_double (cpu, sn)
6797 + aarch64_get_FP_double (cpu, sm));
6802 fdivs (sim_cpu *cpu)
6804 unsigned sm = uimm (aarch64_get_instr (cpu), 20, 16);
6805 unsigned sn = uimm (aarch64_get_instr (cpu), 9, 5);
6806 unsigned sd = uimm (aarch64_get_instr (cpu), 4, 0);
6808 aarch64_set_FP_float (cpu, sd, aarch64_get_FP_float (cpu, sn)
6809 / aarch64_get_FP_float (cpu, sm));
6812 /* Double divide. */
6814 fdivd (sim_cpu *cpu)
6816 unsigned sm = uimm (aarch64_get_instr (cpu), 20, 16);
6817 unsigned sn = uimm (aarch64_get_instr (cpu), 9, 5);
6818 unsigned sd = uimm (aarch64_get_instr (cpu), 4, 0);
6820 aarch64_set_FP_double (cpu, sd, aarch64_get_FP_double (cpu, sn)
6821 / aarch64_get_FP_double (cpu, sm));
6824 /* Float multiply. */
6826 fmuls (sim_cpu *cpu)
6828 unsigned sm = uimm (aarch64_get_instr (cpu), 20, 16);
6829 unsigned sn = uimm (aarch64_get_instr (cpu), 9, 5);
6830 unsigned sd = uimm (aarch64_get_instr (cpu), 4, 0);
6832 aarch64_set_FP_float (cpu, sd, aarch64_get_FP_float (cpu, sn)
6833 * aarch64_get_FP_float (cpu, sm));
6836 /* Double multiply. */
6838 fmuld (sim_cpu *cpu)
6840 unsigned sm = uimm (aarch64_get_instr (cpu), 20, 16);
6841 unsigned sn = uimm (aarch64_get_instr (cpu), 9, 5);
6842 unsigned sd = uimm (aarch64_get_instr (cpu), 4, 0);
6844 aarch64_set_FP_double (cpu, sd, aarch64_get_FP_double (cpu, sn)
6845 * aarch64_get_FP_double (cpu, sm));
6848 /* Float negate and multiply. */
6850 fnmuls (sim_cpu *cpu)
6852 unsigned sm = uimm (aarch64_get_instr (cpu), 20, 16);
6853 unsigned sn = uimm (aarch64_get_instr (cpu), 9, 5);
6854 unsigned sd = uimm (aarch64_get_instr (cpu), 4, 0);
6856 aarch64_set_FP_float (cpu, sd, - (aarch64_get_FP_float (cpu, sn)
6857 * aarch64_get_FP_float (cpu, sm)));
6860 /* Double negate and multiply. */
6862 fnmuld (sim_cpu *cpu)
6864 unsigned sm = uimm (aarch64_get_instr (cpu), 20, 16);
6865 unsigned sn = uimm (aarch64_get_instr (cpu), 9, 5);
6866 unsigned sd = uimm (aarch64_get_instr (cpu), 4, 0);
6868 aarch64_set_FP_double (cpu, sd, - (aarch64_get_FP_double (cpu, sn)
6869 * aarch64_get_FP_double (cpu, sm)));
6872 /* Float subtract. */
6874 fsubs (sim_cpu *cpu)
6876 unsigned sm = uimm (aarch64_get_instr (cpu), 20, 16);
6877 unsigned sn = uimm (aarch64_get_instr (cpu), 9, 5);
6878 unsigned sd = uimm (aarch64_get_instr (cpu), 4, 0);
6880 aarch64_set_FP_float (cpu, sd, aarch64_get_FP_float (cpu, sn)
6881 - aarch64_get_FP_float (cpu, sm));
6884 /* Double subtract. */
6886 fsubd (sim_cpu *cpu)
6888 unsigned sm = uimm (aarch64_get_instr (cpu), 20, 16);
6889 unsigned sn = uimm (aarch64_get_instr (cpu), 9, 5);
6890 unsigned sd = uimm (aarch64_get_instr (cpu), 4, 0);
6892 aarch64_set_FP_double (cpu, sd, aarch64_get_FP_double (cpu, sn)
6893 - aarch64_get_FP_double (cpu, sm));
6897 do_FMINNM (sim_cpu *cpu)
6899 /* instr[31,23] = 0 0011 1100
6900 instr[22] = float(0)/double(1)
6903 instr[15,10] = 01 1110
6907 unsigned sm = uimm (aarch64_get_instr (cpu), 20, 16);
6908 unsigned sn = uimm (aarch64_get_instr (cpu), 9, 5);
6909 unsigned sd = uimm (aarch64_get_instr (cpu), 4, 0);
6911 NYI_assert (31, 23, 0x03C);
6912 NYI_assert (15, 10, 0x1E);
6914 if (uimm (aarch64_get_instr (cpu), 22, 22))
6915 aarch64_set_FP_double (cpu, sd,
6916 dminnm (aarch64_get_FP_double (cpu, sn),
6917 aarch64_get_FP_double (cpu, sm)));
6919 aarch64_set_FP_float (cpu, sd,
6920 fminnm (aarch64_get_FP_float (cpu, sn),
6921 aarch64_get_FP_float (cpu, sm)));
6925 do_FMAXNM (sim_cpu *cpu)
6927 /* instr[31,23] = 0 0011 1100
6928 instr[22] = float(0)/double(1)
6931 instr[15,10] = 01 1010
6935 unsigned sm = uimm (aarch64_get_instr (cpu), 20, 16);
6936 unsigned sn = uimm (aarch64_get_instr (cpu), 9, 5);
6937 unsigned sd = uimm (aarch64_get_instr (cpu), 4, 0);
6939 NYI_assert (31, 23, 0x03C);
6940 NYI_assert (15, 10, 0x1A);
6942 if (uimm (aarch64_get_instr (cpu), 22, 22))
6943 aarch64_set_FP_double (cpu, sd,
6944 dmaxnm (aarch64_get_FP_double (cpu, sn),
6945 aarch64_get_FP_double (cpu, sm)));
6947 aarch64_set_FP_float (cpu, sd,
6948 fmaxnm (aarch64_get_FP_float (cpu, sn),
6949 aarch64_get_FP_float (cpu, sm)));
6953 dexSimpleFPDataProc2Source (sim_cpu *cpu)
6955 /* instr[31] ==> M : 0 ==> OK, 1 ==> UNALLOC
6957 instr[29] ==> S : 0 ==> OK, 1 ==> UNALLOC
6960 instr[23,22] ==> type : 0 ==> single, 01 ==> double, 1x ==> UNALLOC
6963 instr[15,12] ==> opcode : 0000 ==> FMUL, 0001 ==> FDIV
6964 0010 ==> FADD, 0011 ==> FSUB,
6965 0100 ==> FMAX, 0101 ==> FMIN
6966 0110 ==> FMAXNM, 0111 ==> FMINNM
6967 1000 ==> FNMUL, ow ==> UNALLOC
6972 uint32_t M_S = (uimm (aarch64_get_instr (cpu), 31, 31) << 1)
6973 | uimm (aarch64_get_instr (cpu), 29, 29);
6974 uint32_t type = uimm (aarch64_get_instr (cpu), 23, 22);
6975 /* Dispatch on opcode. */
6976 uint32_t dispatch = uimm (aarch64_get_instr (cpu), 15, 12);
6987 case 0: fmuld (cpu); return;
6988 case 1: fdivd (cpu); return;
6989 case 2: faddd (cpu); return;
6990 case 3: fsubd (cpu); return;
6991 case 6: do_FMAXNM (cpu); return;
6992 case 7: do_FMINNM (cpu); return;
6993 case 8: fnmuld (cpu); return;
6995 /* Have not yet implemented fmax and fmin. */
7003 else /* type == 0 => floats. */
7006 case 0: fmuls (cpu); return;
7007 case 1: fdivs (cpu); return;
7008 case 2: fadds (cpu); return;
7009 case 3: fsubs (cpu); return;
7010 case 6: do_FMAXNM (cpu); return;
7011 case 7: do_FMINNM (cpu); return;
7012 case 8: fnmuls (cpu); return;
7024 dexSimpleFPCondSelect (sim_cpu *cpu)
7027 instr[31,23] = 0 0011 1100
7028 instr[22] = 0=>single 1=>double
7035 unsigned sm = uimm (aarch64_get_instr (cpu), 20, 16);
7036 unsigned sn = uimm (aarch64_get_instr (cpu), 9, 5);
7037 unsigned sd = uimm (aarch64_get_instr (cpu), 4, 0);
7038 uint32_t set = testConditionCode (cpu, uimm (aarch64_get_instr (cpu), 15, 12));
7040 NYI_assert (31, 23, 0x03C);
7041 NYI_assert (11, 10, 0x3);
7043 if (uimm (aarch64_get_instr (cpu), 22, 22))
7044 aarch64_set_FP_double (cpu, sd, set ? sn : sm);
7046 aarch64_set_FP_float (cpu, sd, set ? sn : sm);
7049 /* Store 32 bit unscaled signed 9 bit. */
7051 fsturs (sim_cpu *cpu, int32_t offset)
7053 unsigned int rn = uimm (aarch64_get_instr (cpu), 9, 5);
7054 unsigned int st = uimm (aarch64_get_instr (cpu), 4, 0);
7056 aarch64_set_mem_u32 (cpu, aarch64_get_reg_u64 (cpu, st, 1) + offset,
7057 aarch64_get_vec_u32 (cpu, rn, 0));
7060 /* Store 64 bit unscaled signed 9 bit. */
7062 fsturd (sim_cpu *cpu, int32_t offset)
7064 unsigned int rn = uimm (aarch64_get_instr (cpu), 9, 5);
7065 unsigned int st = uimm (aarch64_get_instr (cpu), 4, 0);
7067 aarch64_set_mem_u64 (cpu, aarch64_get_reg_u64 (cpu, st, 1) + offset,
7068 aarch64_get_vec_u64 (cpu, rn, 0));
7071 /* Store 128 bit unscaled signed 9 bit. */
7073 fsturq (sim_cpu *cpu, int32_t offset)
7075 unsigned int rn = uimm (aarch64_get_instr (cpu), 9, 5);
7076 unsigned int st = uimm (aarch64_get_instr (cpu), 4, 0);
7079 aarch64_get_FP_long_double (cpu, rn, & a);
7080 aarch64_set_mem_long_double (cpu,
7081 aarch64_get_reg_u64 (cpu, st, 1)
7085 /* TODO FP move register. */
7087 /* 32 bit fp to fp move register. */
7089 ffmovs (sim_cpu *cpu)
7091 unsigned int rn = uimm (aarch64_get_instr (cpu), 9, 5);
7092 unsigned int st = uimm (aarch64_get_instr (cpu), 4, 0);
7094 aarch64_set_FP_float (cpu, st, aarch64_get_FP_float (cpu, rn));
7097 /* 64 bit fp to fp move register. */
7099 ffmovd (sim_cpu *cpu)
7101 unsigned int rn = uimm (aarch64_get_instr (cpu), 9, 5);
7102 unsigned int st = uimm (aarch64_get_instr (cpu), 4, 0);
7104 aarch64_set_FP_double (cpu, st, aarch64_get_FP_double (cpu, rn));
7107 /* 32 bit GReg to Vec move register. */
7109 fgmovs (sim_cpu *cpu)
7111 unsigned int rn = uimm (aarch64_get_instr (cpu), 9, 5);
7112 unsigned int st = uimm (aarch64_get_instr (cpu), 4, 0);
7114 aarch64_set_vec_u32 (cpu, st, 0, aarch64_get_reg_u32 (cpu, rn, NO_SP));
7117 /* 64 bit g to fp move register. */
7119 fgmovd (sim_cpu *cpu)
7121 unsigned int rn = uimm (aarch64_get_instr (cpu), 9, 5);
7122 unsigned int st = uimm (aarch64_get_instr (cpu), 4, 0);
7124 aarch64_set_vec_u64 (cpu, st, 0, aarch64_get_reg_u64 (cpu, rn, NO_SP));
7127 /* 32 bit fp to g move register. */
7129 gfmovs (sim_cpu *cpu)
7131 unsigned int rn = uimm (aarch64_get_instr (cpu), 9, 5);
7132 unsigned int st = uimm (aarch64_get_instr (cpu), 4, 0);
7134 aarch64_set_reg_u64 (cpu, st, NO_SP, aarch64_get_vec_u32 (cpu, rn, 0));
7137 /* 64 bit fp to g move register. */
7139 gfmovd (sim_cpu *cpu)
7141 unsigned int rn = uimm (aarch64_get_instr (cpu), 9, 5);
7142 unsigned int st = uimm (aarch64_get_instr (cpu), 4, 0);
7144 aarch64_set_reg_u64 (cpu, st, NO_SP, aarch64_get_vec_u64 (cpu, rn, 0));
7147 /* FP move immediate
7149 These install an immediate 8 bit value in the target register
7150 where the 8 bits comprise 1 sign bit, 4 bits of fraction and a 3
7154 fmovs (sim_cpu *cpu)
7156 unsigned int sd = uimm (aarch64_get_instr (cpu), 4, 0);
7157 uint32_t imm = uimm (aarch64_get_instr (cpu), 20, 13);
7158 float f = fp_immediate_for_encoding_32 (imm);
7160 aarch64_set_FP_float (cpu, sd, f);
7164 fmovd (sim_cpu *cpu)
7166 unsigned int sd = uimm (aarch64_get_instr (cpu), 4, 0);
7167 uint32_t imm = uimm (aarch64_get_instr (cpu), 20, 13);
7168 double d = fp_immediate_for_encoding_64 (imm);
7170 aarch64_set_FP_double (cpu, sd, d);
7174 dexSimpleFPImmediate (sim_cpu *cpu)
7176 /* instr[31,23] == 00111100
7177 instr[22] == type : single(0)/double(1)
7179 instr[20,13] == imm8
7181 instr[9,5] == imm5 : 00000 ==> PK, ow ==> UNALLOC
7183 uint32_t imm5 = uimm (aarch64_get_instr (cpu), 9, 5);
7185 NYI_assert (31, 23, 0x3C);
7190 if (uimm (aarch64_get_instr (cpu), 22, 22))
7196 /* TODO specific decode and execute for group Load Store. */
7198 /* TODO FP load/store single register (unscaled offset). */
7200 /* TODO load 8 bit unscaled signed 9 bit. */
7201 /* TODO load 16 bit unscaled signed 9 bit. */
7203 /* Load 32 bit unscaled signed 9 bit. */
7205 fldurs (sim_cpu *cpu, int32_t offset)
7207 unsigned int rn = uimm (aarch64_get_instr (cpu), 9, 5);
7208 unsigned int st = uimm (aarch64_get_instr (cpu), 4, 0);
7210 aarch64_set_vec_u32 (cpu, st, 0, aarch64_get_mem_u32
7211 (cpu, aarch64_get_reg_u64 (cpu, rn, SP_OK) + offset));
7214 /* Load 64 bit unscaled signed 9 bit. */
7216 fldurd (sim_cpu *cpu, int32_t offset)
7218 unsigned int rn = uimm (aarch64_get_instr (cpu), 9, 5);
7219 unsigned int st = uimm (aarch64_get_instr (cpu), 4, 0);
7221 aarch64_set_vec_u64 (cpu, st, 0, aarch64_get_mem_u64
7222 (cpu, aarch64_get_reg_u64 (cpu, rn, SP_OK) + offset));
7225 /* Load 128 bit unscaled signed 9 bit. */
7227 fldurq (sim_cpu *cpu, int32_t offset)
7229 unsigned int rn = uimm (aarch64_get_instr (cpu), 9, 5);
7230 unsigned int st = uimm (aarch64_get_instr (cpu), 4, 0);
7232 uint64_t addr = aarch64_get_reg_u64 (cpu, rn, SP_OK) + offset;
7234 aarch64_get_mem_long_double (cpu, addr, & a);
7235 aarch64_set_FP_long_double (cpu, st, a);
7238 /* TODO store 8 bit unscaled signed 9 bit. */
7239 /* TODO store 16 bit unscaled signed 9 bit. */
7244 /* Float absolute value. */
7246 fabss (sim_cpu *cpu)
7248 unsigned sn = uimm (aarch64_get_instr (cpu), 9, 5);
7249 unsigned sd = uimm (aarch64_get_instr (cpu), 4, 0);
7250 float value = aarch64_get_FP_float (cpu, sn);
7252 aarch64_set_FP_float (cpu, sd, fabsf (value));
7255 /* Double absolute value. */
7257 fabcpu (sim_cpu *cpu)
7259 unsigned sn = uimm (aarch64_get_instr (cpu), 9, 5);
7260 unsigned sd = uimm (aarch64_get_instr (cpu), 4, 0);
7261 double value = aarch64_get_FP_double (cpu, sn);
7263 aarch64_set_FP_double (cpu, sd, fabs (value));
7266 /* Float negative value. */
7268 fnegs (sim_cpu *cpu)
7270 unsigned sn = uimm (aarch64_get_instr (cpu), 9, 5);
7271 unsigned sd = uimm (aarch64_get_instr (cpu), 4, 0);
7273 aarch64_set_FP_float (cpu, sd, - aarch64_get_FP_float (cpu, sn));
7276 /* Double negative value. */
7278 fnegd (sim_cpu *cpu)
7280 unsigned sn = uimm (aarch64_get_instr (cpu), 9, 5);
7281 unsigned sd = uimm (aarch64_get_instr (cpu), 4, 0);
7283 aarch64_set_FP_double (cpu, sd, - aarch64_get_FP_double (cpu, sn));
7286 /* Float square root. */
7288 fsqrts (sim_cpu *cpu)
7290 unsigned sn = uimm (aarch64_get_instr (cpu), 9, 5);
7291 unsigned sd = uimm (aarch64_get_instr (cpu), 4, 0);
7293 aarch64_set_FP_float (cpu, sd, sqrt (aarch64_get_FP_float (cpu, sn)));
7296 /* Double square root. */
7298 fsqrtd (sim_cpu *cpu)
7300 unsigned sn = uimm (aarch64_get_instr (cpu), 9, 5);
7301 unsigned sd = uimm (aarch64_get_instr (cpu), 4, 0);
7303 aarch64_set_FP_double (cpu, sd,
7304 sqrt (aarch64_get_FP_double (cpu, sn)));
7307 /* Convert double to float. */
7309 fcvtds (sim_cpu *cpu)
7311 unsigned sn = uimm (aarch64_get_instr (cpu), 9, 5);
7312 unsigned sd = uimm (aarch64_get_instr (cpu), 4, 0);
7314 aarch64_set_FP_float (cpu, sd, (float) aarch64_get_FP_double (cpu, sn));
7317 /* Convert float to double. */
7319 fcvtcpu (sim_cpu *cpu)
7321 unsigned sn = uimm (aarch64_get_instr (cpu), 9, 5);
7322 unsigned sd = uimm (aarch64_get_instr (cpu), 4, 0);
7324 aarch64_set_FP_double (cpu, sd, (double) aarch64_get_FP_float (cpu, sn));
7328 do_FRINT (sim_cpu *cpu)
7330 /* instr[31,23] = 0001 1110 0
7331 instr[22] = single(0)/double(1)
7333 instr[17,15] = rounding mode
7334 instr[14,10] = 10000
7336 instr[4,0] = dest */
7339 unsigned rs = uimm (aarch64_get_instr (cpu), 9, 5);
7340 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
7341 unsigned int rmode = uimm (aarch64_get_instr (cpu), 17, 15);
7343 NYI_assert (31, 23, 0x03C);
7344 NYI_assert (21, 18, 0x9);
7345 NYI_assert (14, 10, 0x10);
7347 if (rmode == 6 || rmode == 7)
7348 /* FIXME: Add support for rmode == 6 exactness check. */
7349 rmode = uimm (aarch64_get_FPSR (cpu), 23, 22);
7351 if (uimm (aarch64_get_instr (cpu), 22, 22))
7353 double val = aarch64_get_FP_double (cpu, rs);
7357 case 0: /* mode N: nearest or even. */
7359 double rval = round (val);
7361 if (val - rval == 0.5)
7363 if (((rval / 2.0) * 2.0) != rval)
7367 aarch64_set_FP_double (cpu, rd, round (val));
7371 case 1: /* mode P: towards +inf. */
7373 aarch64_set_FP_double (cpu, rd, trunc (val));
7375 aarch64_set_FP_double (cpu, rd, round (val));
7378 case 2: /* mode M: towards -inf. */
7380 aarch64_set_FP_double (cpu, rd, round (val));
7382 aarch64_set_FP_double (cpu, rd, trunc (val));
7385 case 3: /* mode Z: towards 0. */
7386 aarch64_set_FP_double (cpu, rd, trunc (val));
7389 case 4: /* mode A: away from 0. */
7390 aarch64_set_FP_double (cpu, rd, round (val));
7393 case 6: /* mode X: use FPCR with exactness check. */
7394 case 7: /* mode I: use FPCR mode. */
7402 val = aarch64_get_FP_float (cpu, rs);
7406 case 0: /* mode N: nearest or even. */
7408 float rval = roundf (val);
7410 if (val - rval == 0.5)
7412 if (((rval / 2.0) * 2.0) != rval)
7416 aarch64_set_FP_float (cpu, rd, rval);
7420 case 1: /* mode P: towards +inf. */
7422 aarch64_set_FP_float (cpu, rd, truncf (val));
7424 aarch64_set_FP_float (cpu, rd, roundf (val));
7427 case 2: /* mode M: towards -inf. */
7429 aarch64_set_FP_float (cpu, rd, truncf (val));
7431 aarch64_set_FP_float (cpu, rd, roundf (val));
7434 case 3: /* mode Z: towards 0. */
7435 aarch64_set_FP_float (cpu, rd, truncf (val));
7438 case 4: /* mode A: away from 0. */
7439 aarch64_set_FP_float (cpu, rd, roundf (val));
7442 case 6: /* mode X: use FPCR with exactness check. */
7443 case 7: /* mode I: use FPCR mode. */
7451 /* Convert half to float. */
7453 do_FCVT_half_to_single (sim_cpu * cpu)
7455 unsigned rn = INSTR (9, 5);
7456 unsigned rd = INSTR (4, 0);
7458 NYI_assert (31, 10, 0x7B890);
7460 aarch64_set_FP_float (cpu, rd, (float) aarch64_get_FP_half (cpu, rn));
7463 /* Convert half to float. */
7465 do_FCVT_half_to_double (sim_cpu * cpu)
7467 unsigned rn = INSTR (9, 5);
7468 unsigned rd = INSTR (4, 0);
7470 NYI_assert (31, 10, 0x7B8B0);
7472 aarch64_set_FP_double (cpu, rd, (double) aarch64_get_FP_half (cpu, rn));
7476 do_FCVT_single_to_half (sim_cpu * cpu)
7478 unsigned rn = INSTR (9, 5);
7479 unsigned rd = INSTR (4, 0);
7481 NYI_assert (31, 10, 0x788F0);
7483 aarch64_set_FP_half (cpu, rd, aarch64_get_FP_float (cpu, rn));
7486 /* Convert half to float. */
7488 do_FCVT_double_to_half (sim_cpu * cpu)
7490 unsigned rn = INSTR (9, 5);
7491 unsigned rd = INSTR (4, 0);
7493 NYI_assert (31, 10, 0x798F0);
7495 aarch64_set_FP_half (cpu, rd, (float) aarch64_get_FP_double (cpu, rn));
7499 dexSimpleFPDataProc1Source (sim_cpu *cpu)
7501 /* instr[31] ==> M : 0 ==> OK, 1 ==> UNALLOC
7503 instr[29] ==> S : 0 ==> OK, 1 ==> UNALLOC
7506 instr[23,22] ==> type : 00 ==> source is single,
7507 01 ==> source is double
7509 11 ==> UNALLOC or source is half
7511 instr[20,15] ==> opcode : with type 00 or 01
7512 000000 ==> FMOV, 000001 ==> FABS,
7513 000010 ==> FNEG, 000011 ==> FSQRT,
7514 000100 ==> UNALLOC, 000101 ==> FCVT,(to single/double)
7515 000110 ==> UNALLOC, 000111 ==> FCVT (to half)
7516 001000 ==> FRINTN, 001001 ==> FRINTP,
7517 001010 ==> FRINTM, 001011 ==> FRINTZ,
7518 001100 ==> FRINTA, 001101 ==> UNALLOC
7519 001110 ==> FRINTX, 001111 ==> FRINTI
7521 000100 ==> FCVT (half-to-single)
7522 000101 ==> FCVT (half-to-double)
7523 instr[14,10] = 10000. */
7525 uint32_t M_S = (uimm (aarch64_get_instr (cpu), 31, 31) << 1)
7526 | uimm (aarch64_get_instr (cpu), 29, 29);
7527 uint32_t type = uimm (aarch64_get_instr (cpu), 23, 22);
7528 uint32_t opcode = uimm (aarch64_get_instr (cpu), 20, 15);
7536 do_FCVT_half_to_single (cpu);
7537 else if (opcode == 5)
7538 do_FCVT_half_to_double (cpu);
7590 case 8: /* FRINTN etc. */
7602 do_FCVT_double_to_half (cpu);
7604 do_FCVT_single_to_half (cpu);
7615 /* 32 bit signed int to float. */
7617 scvtf32 (sim_cpu *cpu)
7619 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
7620 unsigned sd = uimm (aarch64_get_instr (cpu), 4, 0);
7622 aarch64_set_FP_float
7623 (cpu, sd, (float) aarch64_get_reg_s32 (cpu, rn, NO_SP));
7626 /* signed int to float. */
7628 scvtf (sim_cpu *cpu)
7630 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
7631 unsigned sd = uimm (aarch64_get_instr (cpu), 4, 0);
7633 aarch64_set_FP_float
7634 (cpu, sd, (float) aarch64_get_reg_s64 (cpu, rn, NO_SP));
7637 /* 32 bit signed int to double. */
7639 scvtd32 (sim_cpu *cpu)
7641 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
7642 unsigned sd = uimm (aarch64_get_instr (cpu), 4, 0);
7644 aarch64_set_FP_double
7645 (cpu, sd, (double) aarch64_get_reg_s32 (cpu, rn, NO_SP));
7648 /* signed int to double. */
7650 scvtd (sim_cpu *cpu)
7652 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
7653 unsigned sd = uimm (aarch64_get_instr (cpu), 4, 0);
7655 aarch64_set_FP_double
7656 (cpu, sd, (double) aarch64_get_reg_s64 (cpu, rn, NO_SP));
7659 static const float FLOAT_INT_MAX = (float) INT_MAX;
7660 static const float FLOAT_INT_MIN = (float) INT_MIN;
7661 static const double DOUBLE_INT_MAX = (double) INT_MAX;
7662 static const double DOUBLE_INT_MIN = (double) INT_MIN;
7663 static const float FLOAT_LONG_MAX = (float) LONG_MAX;
7664 static const float FLOAT_LONG_MIN = (float) LONG_MIN;
7665 static const double DOUBLE_LONG_MAX = (double) LONG_MAX;
7666 static const double DOUBLE_LONG_MIN = (double) LONG_MIN;
7668 /* Check for FP exception conditions:
7671 Out of Range raises IO and IX and saturates value
7672 Denormal raises ID and IX and sets to zero. */
7673 #define RAISE_EXCEPTIONS(F, VALUE, FTYPE, ITYPE) \
7676 switch (fpclassify (F)) \
7680 aarch64_set_FPSR (cpu, IO); \
7682 VALUE = ITYPE##_MAX; \
7684 VALUE = ITYPE##_MIN; \
7688 if (F >= FTYPE##_##ITYPE##_MAX) \
7690 aarch64_set_FPSR_bits (cpu, IO | IX, IO | IX); \
7691 VALUE = ITYPE##_MAX; \
7693 else if (F <= FTYPE##_##ITYPE##_MIN) \
7695 aarch64_set_FPSR_bits (cpu, IO | IX, IO | IX); \
7696 VALUE = ITYPE##_MIN; \
7700 case FP_SUBNORMAL: \
7701 aarch64_set_FPSR_bits (cpu, IO | IX | ID, IX | ID); \
7713 /* 32 bit convert float to signed int truncate towards zero. */
7715 fcvtszs32 (sim_cpu *cpu)
7717 unsigned sn = uimm (aarch64_get_instr (cpu), 9, 5);
7718 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
7719 /* TODO : check that this rounds toward zero. */
7720 float f = aarch64_get_FP_float (cpu, sn);
7721 int32_t value = (int32_t) f;
7723 RAISE_EXCEPTIONS (f, value, FLOAT, INT);
7725 /* Avoid sign extension to 64 bit. */
7726 aarch64_set_reg_u64 (cpu, rd, NO_SP, (uint32_t) value);
7729 /* 64 bit convert float to signed int truncate towards zero. */
7731 fcvtszs (sim_cpu *cpu)
7733 unsigned sn = uimm (aarch64_get_instr (cpu), 9, 5);
7734 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
7735 float f = aarch64_get_FP_float (cpu, sn);
7736 int64_t value = (int64_t) f;
7738 RAISE_EXCEPTIONS (f, value, FLOAT, LONG);
7740 aarch64_set_reg_s64 (cpu, rd, NO_SP, value);
7743 /* 32 bit convert double to signed int truncate towards zero. */
7745 fcvtszd32 (sim_cpu *cpu)
7747 unsigned sn = uimm (aarch64_get_instr (cpu), 9, 5);
7748 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
7749 /* TODO : check that this rounds toward zero. */
7750 double d = aarch64_get_FP_double (cpu, sn);
7751 int32_t value = (int32_t) d;
7753 RAISE_EXCEPTIONS (d, value, DOUBLE, INT);
7755 /* Avoid sign extension to 64 bit. */
7756 aarch64_set_reg_u64 (cpu, rd, NO_SP, (uint32_t) value);
7759 /* 64 bit convert double to signed int truncate towards zero. */
7761 fcvtszd (sim_cpu *cpu)
7763 unsigned sn = uimm (aarch64_get_instr (cpu), 9, 5);
7764 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
7765 /* TODO : check that this rounds toward zero. */
7766 double d = aarch64_get_FP_double (cpu, sn);
7769 value = (int64_t) d;
7771 RAISE_EXCEPTIONS (d, value, DOUBLE, LONG);
7773 aarch64_set_reg_s64 (cpu, rd, NO_SP, value);
7777 do_fcvtzu (sim_cpu *cpu)
7779 /* instr[31] = size: 32-bit (0), 64-bit (1)
7780 instr[30,23] = 00111100
7781 instr[22] = type: single (0)/ double (1)
7782 instr[21] = enable (0)/disable(1) precision
7783 instr[20,16] = 11001
7784 instr[15,10] = precision
7788 unsigned rs = uimm (aarch64_get_instr (cpu), 9, 5);
7789 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
7791 NYI_assert (30, 23, 0x3C);
7792 NYI_assert (20, 16, 0x19);
7794 if (uimm (aarch64_get_instr (cpu), 21, 21) != 1)
7795 /* Convert to fixed point. */
7798 if (uimm (aarch64_get_instr (cpu), 31, 31))
7800 /* Convert to unsigned 64-bit integer. */
7801 if (uimm (aarch64_get_instr (cpu), 22, 22))
7803 double d = aarch64_get_FP_double (cpu, rs);
7804 uint64_t value = (uint64_t) d;
7806 /* Do not raise an exception if we have reached ULONG_MAX. */
7807 if (value != (1UL << 63))
7808 RAISE_EXCEPTIONS (d, value, DOUBLE, LONG);
7810 aarch64_set_reg_u64 (cpu, rd, NO_SP, value);
7814 float f = aarch64_get_FP_float (cpu, rs);
7815 uint64_t value = (uint64_t) f;
7817 /* Do not raise an exception if we have reached ULONG_MAX. */
7818 if (value != (1UL << 63))
7819 RAISE_EXCEPTIONS (f, value, FLOAT, LONG);
7821 aarch64_set_reg_u64 (cpu, rd, NO_SP, value);
7828 /* Convert to unsigned 32-bit integer. */
7829 if (uimm (aarch64_get_instr (cpu), 22, 22))
7831 double d = aarch64_get_FP_double (cpu, rs);
7833 value = (uint32_t) d;
7834 /* Do not raise an exception if we have reached UINT_MAX. */
7835 if (value != (1UL << 31))
7836 RAISE_EXCEPTIONS (d, value, DOUBLE, INT);
7840 float f = aarch64_get_FP_float (cpu, rs);
7842 value = (uint32_t) f;
7843 /* Do not raise an exception if we have reached UINT_MAX. */
7844 if (value != (1UL << 31))
7845 RAISE_EXCEPTIONS (f, value, FLOAT, INT);
7848 aarch64_set_reg_u64 (cpu, rd, NO_SP, value);
7853 do_UCVTF (sim_cpu *cpu)
7855 /* instr[31] = size: 32-bit (0), 64-bit (1)
7856 instr[30,23] = 001 1110 0
7857 instr[22] = type: single (0)/ double (1)
7858 instr[21] = enable (0)/disable(1) precision
7859 instr[20,16] = 0 0011
7860 instr[15,10] = precision
7864 unsigned rs = uimm (aarch64_get_instr (cpu), 9, 5);
7865 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
7867 NYI_assert (30, 23, 0x3C);
7868 NYI_assert (20, 16, 0x03);
7870 if (uimm (aarch64_get_instr (cpu), 21, 21) != 1)
7873 /* FIXME: Add exception raising. */
7874 if (uimm (aarch64_get_instr (cpu), 31, 31))
7876 uint64_t value = aarch64_get_reg_u64 (cpu, rs, NO_SP);
7878 if (uimm (aarch64_get_instr (cpu), 22, 22))
7879 aarch64_set_FP_double (cpu, rd, (double) value);
7881 aarch64_set_FP_float (cpu, rd, (float) value);
7885 uint32_t value = aarch64_get_reg_u32 (cpu, rs, NO_SP);
7887 if (uimm (aarch64_get_instr (cpu), 22, 22))
7888 aarch64_set_FP_double (cpu, rd, (double) value);
7890 aarch64_set_FP_float (cpu, rd, (float) value);
7895 float_vector_move (sim_cpu *cpu)
7897 /* instr[31,17] == 100 1111 0101 0111
7898 instr[16] ==> direction 0=> to GR, 1=> from GR
7900 instr[9,5] ==> source
7901 instr[4,0] ==> dest. */
7903 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
7904 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
7906 NYI_assert (31, 17, 0x4F57);
7908 if (uimm (aarch64_get_instr (cpu), 15, 10) != 0)
7911 if (uimm (aarch64_get_instr (cpu), 16, 16))
7912 aarch64_set_vec_u64 (cpu, rd, 1, aarch64_get_reg_u64 (cpu, rn, NO_SP));
7914 aarch64_set_reg_u64 (cpu, rd, NO_SP, aarch64_get_vec_u64 (cpu, rn, 1));
7918 dexSimpleFPIntegerConvert (sim_cpu *cpu)
7920 /* instr[31] = size : 0 ==> 32 bit, 1 ==> 64 bit
7922 instr[29] = S : 0 ==> OK, 1 ==> UNALLOC
7925 instr[23,22] = type : 00 ==> single, 01 ==> double, 1x ==> UNALLOC
7927 instr[20,19] = rmode
7928 instr[18,16] = opcode
7929 instr[15,10] = 10 0000 */
7931 uint32_t rmode_opcode;
7937 if (uimm (aarch64_get_instr (cpu), 31, 17) == 0x4F57)
7939 float_vector_move (cpu);
7943 size = uimm (aarch64_get_instr (cpu), 31, 31);
7944 S = uimm (aarch64_get_instr (cpu), 29, 29);
7948 type = uimm (aarch64_get_instr (cpu), 23, 22);
7952 rmode_opcode = uimm (aarch64_get_instr (cpu), 20, 16);
7953 size_type = (size << 1) | type; /* 0==32f, 1==32d, 2==64f, 3==64d. */
7955 switch (rmode_opcode)
7957 case 2: /* SCVTF. */
7960 case 0: scvtf32 (cpu); return;
7961 case 1: scvtd32 (cpu); return;
7962 case 2: scvtf (cpu); return;
7963 case 3: scvtd (cpu); return;
7966 case 6: /* FMOV GR, Vec. */
7969 case 0: gfmovs (cpu); return;
7970 case 3: gfmovd (cpu); return;
7971 default: HALT_UNALLOC;
7974 case 7: /* FMOV vec, GR. */
7977 case 0: fgmovs (cpu); return;
7978 case 3: fgmovd (cpu); return;
7979 default: HALT_UNALLOC;
7982 case 24: /* FCVTZS. */
7985 case 0: fcvtszs32 (cpu); return;
7986 case 1: fcvtszd32 (cpu); return;
7987 case 2: fcvtszs (cpu); return;
7988 case 3: fcvtszd (cpu); return;
7991 case 25: do_fcvtzu (cpu); return;
7992 case 3: do_UCVTF (cpu); return;
7994 case 0: /* FCVTNS. */
7995 case 1: /* FCVTNU. */
7996 case 4: /* FCVTAS. */
7997 case 5: /* FCVTAU. */
7998 case 8: /* FCVPTS. */
7999 case 9: /* FCVTPU. */
8000 case 16: /* FCVTMS. */
8001 case 17: /* FCVTMU. */
8008 set_flags_for_float_compare (sim_cpu *cpu, float fvalue1, float fvalue2)
8012 if (isnan (fvalue1) || isnan (fvalue2))
8016 float result = fvalue1 - fvalue2;
8020 else if (result < 0)
8022 else /* (result > 0). */
8026 aarch64_set_CPSR (cpu, flags);
8030 fcmps (sim_cpu *cpu)
8032 unsigned sm = uimm (aarch64_get_instr (cpu), 20, 16);
8033 unsigned sn = uimm (aarch64_get_instr (cpu), 9, 5);
8035 float fvalue1 = aarch64_get_FP_float (cpu, sn);
8036 float fvalue2 = aarch64_get_FP_float (cpu, sm);
8038 set_flags_for_float_compare (cpu, fvalue1, fvalue2);
8041 /* Float compare to zero -- Invalid Operation exception
8042 only on signaling NaNs. */
8044 fcmpzs (sim_cpu *cpu)
8046 unsigned sn = uimm (aarch64_get_instr (cpu), 9, 5);
8047 float fvalue1 = aarch64_get_FP_float (cpu, sn);
8049 set_flags_for_float_compare (cpu, fvalue1, 0.0f);
8052 /* Float compare -- Invalid Operation exception on all NaNs. */
8054 fcmpes (sim_cpu *cpu)
8056 unsigned sm = uimm (aarch64_get_instr (cpu), 20, 16);
8057 unsigned sn = uimm (aarch64_get_instr (cpu), 9, 5);
8059 float fvalue1 = aarch64_get_FP_float (cpu, sn);
8060 float fvalue2 = aarch64_get_FP_float (cpu, sm);
8062 set_flags_for_float_compare (cpu, fvalue1, fvalue2);
8065 /* Float compare to zero -- Invalid Operation exception on all NaNs. */
8067 fcmpzes (sim_cpu *cpu)
8069 unsigned sn = uimm (aarch64_get_instr (cpu), 9, 5);
8070 float fvalue1 = aarch64_get_FP_float (cpu, sn);
8072 set_flags_for_float_compare (cpu, fvalue1, 0.0f);
8076 set_flags_for_double_compare (sim_cpu *cpu, double dval1, double dval2)
8080 if (isnan (dval1) || isnan (dval2))
8084 double result = dval1 - dval2;
8088 else if (result < 0)
8090 else /* (result > 0). */
8094 aarch64_set_CPSR (cpu, flags);
8097 /* Double compare -- Invalid Operation exception only on signaling NaNs. */
8099 fcmpd (sim_cpu *cpu)
8101 unsigned sm = uimm (aarch64_get_instr (cpu), 20, 16);
8102 unsigned sn = uimm (aarch64_get_instr (cpu), 9, 5);
8104 double dvalue1 = aarch64_get_FP_double (cpu, sn);
8105 double dvalue2 = aarch64_get_FP_double (cpu, sm);
8107 set_flags_for_double_compare (cpu, dvalue1, dvalue2);
8110 /* Double compare to zero -- Invalid Operation exception
8111 only on signaling NaNs. */
8113 fcmpzd (sim_cpu *cpu)
8115 unsigned sn = uimm (aarch64_get_instr (cpu), 9, 5);
8116 double dvalue1 = aarch64_get_FP_double (cpu, sn);
8118 set_flags_for_double_compare (cpu, dvalue1, 0.0);
8121 /* Double compare -- Invalid Operation exception on all NaNs. */
8123 fcmped (sim_cpu *cpu)
8125 unsigned sm = uimm (aarch64_get_instr (cpu), 20, 16);
8126 unsigned sn = uimm (aarch64_get_instr (cpu), 9, 5);
8128 double dvalue1 = aarch64_get_FP_double (cpu, sn);
8129 double dvalue2 = aarch64_get_FP_double (cpu, sm);
8131 set_flags_for_double_compare (cpu, dvalue1, dvalue2);
8134 /* Double compare to zero -- Invalid Operation exception on all NaNs. */
8136 fcmpzed (sim_cpu *cpu)
8138 unsigned sn = uimm (aarch64_get_instr (cpu), 9, 5);
8139 double dvalue1 = aarch64_get_FP_double (cpu, sn);
8141 set_flags_for_double_compare (cpu, dvalue1, 0.0);
8145 dexSimpleFPCompare (sim_cpu *cpu)
8147 /* assert instr[28,25] == 1111
8148 instr[30:24:21:13,10] = 0011000
8149 instr[31] = M : 0 ==> OK, 1 ==> UNALLOC
8150 instr[29] ==> S : 0 ==> OK, 1 ==> UNALLOC
8151 instr[23,22] ==> type : 0 ==> single, 01 ==> double, 1x ==> UNALLOC
8152 instr[15,14] ==> op : 00 ==> OK, ow ==> UNALLOC
8153 instr[4,0] ==> opcode2 : 00000 ==> FCMP, 10000 ==> FCMPE,
8154 01000 ==> FCMPZ, 11000 ==> FCMPEZ,
8157 uint32_t M_S = (uimm (aarch64_get_instr (cpu), 31, 31) << 1)
8158 | uimm (aarch64_get_instr (cpu), 29, 29);
8159 uint32_t type = uimm (aarch64_get_instr (cpu), 23, 22);
8160 uint32_t op = uimm (aarch64_get_instr (cpu), 15, 14);
8161 uint32_t op2_2_0 = uimm (aarch64_get_instr (cpu), 2, 0);
8175 /* dispatch on type and top 2 bits of opcode. */
8176 dispatch = (type << 2) | uimm (aarch64_get_instr (cpu), 4, 3);
8180 case 0: fcmps (cpu); return;
8181 case 1: fcmpzs (cpu); return;
8182 case 2: fcmpes (cpu); return;
8183 case 3: fcmpzes (cpu); return;
8184 case 4: fcmpd (cpu); return;
8185 case 5: fcmpzd (cpu); return;
8186 case 6: fcmped (cpu); return;
8187 case 7: fcmpzed (cpu); return;
8192 do_scalar_FADDP (sim_cpu *cpu)
8194 /* instr [31,23] = 011111100
8195 instr [22] = single(0)/double(1)
8196 instr [21,10] = 1100 0011 0110
8198 instr [4,0] = Fd. */
8200 unsigned Fn = uimm (aarch64_get_instr (cpu), 9, 5);
8201 unsigned Fd = uimm (aarch64_get_instr (cpu), 4, 0);
8203 NYI_assert (31, 23, 0x0FC);
8204 NYI_assert (21, 10, 0xC36);
8206 if (uimm (aarch64_get_instr (cpu), 22, 22))
8208 double val1 = aarch64_get_vec_double (cpu, Fn, 0);
8209 double val2 = aarch64_get_vec_double (cpu, Fn, 1);
8211 aarch64_set_FP_double (cpu, Fd, val1 + val2);
8215 float val1 = aarch64_get_vec_float (cpu, Fn, 0);
8216 float val2 = aarch64_get_vec_float (cpu, Fn, 1);
8218 aarch64_set_FP_float (cpu, Fd, val1 + val2);
8222 /* Floating point absolute difference. */
8225 do_scalar_FABD (sim_cpu *cpu)
8227 /* instr [31,23] = 0111 1110 1
8228 instr [22] = float(0)/double(1)
8231 instr [15,10] = 1101 01
8233 instr [4, 0] = Rd. */
8235 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
8236 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
8237 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
8239 NYI_assert (31, 23, 0x0FD);
8240 NYI_assert (21, 21, 1);
8241 NYI_assert (15, 10, 0x35);
8243 if (uimm (aarch64_get_instr (cpu), 22, 22))
8244 aarch64_set_FP_double (cpu, rd,
8245 fabs (aarch64_get_FP_double (cpu, rn)
8246 - aarch64_get_FP_double (cpu, rm)));
8248 aarch64_set_FP_float (cpu, rd,
8249 fabsf (aarch64_get_FP_float (cpu, rn)
8250 - aarch64_get_FP_float (cpu, rm)));
8254 do_scalar_CMGT (sim_cpu *cpu)
8256 /* instr [31,21] = 0101 1110 111
8258 instr [15,10] = 00 1101
8260 instr [4, 0] = Rd. */
8262 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
8263 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
8264 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
8266 NYI_assert (31, 21, 0x2F7);
8267 NYI_assert (15, 10, 0x0D);
8269 aarch64_set_vec_u64 (cpu, rd, 0,
8270 aarch64_get_vec_u64 (cpu, rn, 0) >
8271 aarch64_get_vec_u64 (cpu, rm, 0) ? -1L : 0L);
8275 do_scalar_USHR (sim_cpu *cpu)
8277 /* instr [31,23] = 0111 1111 0
8278 instr [22,16] = shift amount
8279 instr [15,10] = 0000 01
8281 instr [4, 0] = Rd. */
8283 unsigned amount = 128 - INSTR (22, 16);
8284 unsigned rn = INSTR (9, 5);
8285 unsigned rd = INSTR (4, 0);
8287 NYI_assert (31, 23, 0x0FE);
8288 NYI_assert (15, 10, 0x01);
8290 aarch64_set_vec_u64 (cpu, rd, 0,
8291 aarch64_get_vec_u64 (cpu, rn, 0) >> amount);
8295 do_scalar_SSHL (sim_cpu *cpu)
8297 /* instr [31,21] = 0101 1110 111
8299 instr [15,10] = 0100 01
8301 instr [4, 0] = Rd. */
8303 unsigned rm = INSTR (20, 16);
8304 unsigned rn = INSTR (9, 5);
8305 unsigned rd = INSTR (4, 0);
8306 signed int shift = aarch64_get_vec_s8 (cpu, rm, 0);
8308 NYI_assert (31, 21, 0x2F7);
8309 NYI_assert (15, 10, 0x11);
8312 aarch64_set_vec_s64 (cpu, rd, 0,
8313 aarch64_get_vec_s64 (cpu, rn, 0) << shift);
8315 aarch64_set_vec_s64 (cpu, rd, 0,
8316 aarch64_get_vec_s64 (cpu, rn, 0) >> - shift);
8320 do_scalar_shift (sim_cpu *cpu)
8322 /* instr [31,23] = 0101 1111 0
8323 instr [22,16] = shift amount
8324 instr [15,10] = 0101 01 [SHL]
8325 instr [15,10] = 0000 01 [SSHR]
8327 instr [4, 0] = Rd. */
8329 unsigned rn = INSTR (9, 5);
8330 unsigned rd = INSTR (4, 0);
8333 NYI_assert (31, 23, 0x0BE);
8335 if (INSTR (22, 22) == 0)
8338 switch (INSTR (15, 10))
8340 case 0x01: /* SSHR */
8341 amount = 128 - INSTR (22, 16);
8342 aarch64_set_vec_s64 (cpu, rd, 0,
8343 aarch64_get_vec_s64 (cpu, rn, 0) >> amount);
8345 case 0x15: /* SHL */
8346 amount = INSTR (22, 16) - 64;
8347 aarch64_set_vec_u64 (cpu, rd, 0,
8348 aarch64_get_vec_u64 (cpu, rn, 0) << amount);
8355 /* FCMEQ FCMGT FCMGE. */
8357 do_scalar_FCM (sim_cpu *cpu)
8359 /* instr [31,30] = 01
8361 instr [28,24] = 1 1110
8366 instr [15,12] = 1110
8370 instr [4, 0] = Rd. */
8372 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
8373 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
8374 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
8375 unsigned EUac = (uimm (aarch64_get_instr (cpu), 23, 23) << 2)
8376 | (uimm (aarch64_get_instr (cpu), 29, 29) << 1)
8377 | uimm (aarch64_get_instr (cpu), 11, 11);
8382 NYI_assert (31, 30, 1);
8383 NYI_assert (28, 24, 0x1E);
8384 NYI_assert (21, 21, 1);
8385 NYI_assert (15, 12, 0xE);
8386 NYI_assert (10, 10, 1);
8388 if (uimm (aarch64_get_instr (cpu), 22, 22))
8390 double val1 = aarch64_get_FP_double (cpu, rn);
8391 double val2 = aarch64_get_FP_double (cpu, rm);
8396 result = val1 == val2;
8404 result = val1 >= val2;
8412 result = val1 > val2;
8419 aarch64_set_vec_u32 (cpu, rd, 0, result ? -1 : 0);
8423 val1 = aarch64_get_FP_float (cpu, rn);
8424 val2 = aarch64_get_FP_float (cpu, rm);
8429 result = val1 == val2;
8433 val1 = fabsf (val1);
8434 val2 = fabsf (val2);
8437 result = val1 >= val2;
8441 val1 = fabsf (val1);
8442 val2 = fabsf (val2);
8445 result = val1 > val2;
8452 aarch64_set_vec_u32 (cpu, rd, 0, result ? -1 : 0);
8455 /* An alias of DUP. */
8457 do_scalar_MOV (sim_cpu *cpu)
8459 /* instr [31,21] = 0101 1110 000
8460 instr [20,16] = imm5
8461 instr [15,10] = 0000 01
8463 instr [4, 0] = Rd. */
8465 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
8466 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
8469 NYI_assert (31, 21, 0x2F0);
8470 NYI_assert (15, 10, 0x01);
8472 if (uimm (aarch64_get_instr (cpu), 16, 16))
8475 index = uimm (aarch64_get_instr (cpu), 20, 17);
8477 (cpu, rd, 0, aarch64_get_vec_u8 (cpu, rn, index));
8479 else if (uimm (aarch64_get_instr (cpu), 17, 17))
8482 index = uimm (aarch64_get_instr (cpu), 20, 18);
8484 (cpu, rd, 0, aarch64_get_vec_u16 (cpu, rn, index));
8486 else if (uimm (aarch64_get_instr (cpu), 18, 18))
8489 index = uimm (aarch64_get_instr (cpu), 20, 19);
8491 (cpu, rd, 0, aarch64_get_vec_u32 (cpu, rn, index));
8493 else if (uimm (aarch64_get_instr (cpu), 19, 19))
8496 index = uimm (aarch64_get_instr (cpu), 20, 20);
8498 (cpu, rd, 0, aarch64_get_vec_u64 (cpu, rn, index));
8505 do_scalar_NEG (sim_cpu *cpu)
8507 /* instr [31,10] = 0111 1110 1110 0000 1011 10
8509 instr [4, 0] = Rd. */
8511 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
8512 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
8514 NYI_assert (31, 10, 0x1FB82E);
8516 aarch64_set_vec_u64 (cpu, rd, 0, - aarch64_get_vec_u64 (cpu, rn, 0));
8520 do_scalar_USHL (sim_cpu *cpu)
8522 /* instr [31,21] = 0111 1110 111
8524 instr [15,10] = 0100 01
8526 instr [4, 0] = Rd. */
8528 unsigned rm = INSTR (20, 16);
8529 unsigned rn = INSTR (9, 5);
8530 unsigned rd = INSTR (4, 0);
8531 signed int shift = aarch64_get_vec_s8 (cpu, rm, 0);
8533 NYI_assert (31, 21, 0x3F7);
8534 NYI_assert (15, 10, 0x11);
8537 aarch64_set_vec_u64 (cpu, rd, 0, aarch64_get_vec_u64 (cpu, rn, 0) << shift);
8539 aarch64_set_vec_u64 (cpu, rd, 0, aarch64_get_vec_u64 (cpu, rn, 0) >> - shift);
8543 do_double_add (sim_cpu *cpu)
8545 /* instr [31,21] = 0101 1110 111
8547 instr [15,10] = 1000 01
8549 instr [4,0] = Fd. */
8556 NYI_assert (31, 21, 0x2F7);
8557 NYI_assert (15, 10, 0x21);
8561 Fn = INSTR (20, 16);
8563 val1 = aarch64_get_FP_double (cpu, Fm);
8564 val2 = aarch64_get_FP_double (cpu, Fn);
8566 aarch64_set_FP_double (cpu, Fd, val1 + val2);
8570 do_scalar_vec (sim_cpu *cpu)
8572 /* instr [30] = 1. */
8573 /* instr [28,25] = 1111. */
8574 switch (uimm (aarch64_get_instr (cpu), 31, 23))
8577 switch (uimm (aarch64_get_instr (cpu), 15, 10))
8579 case 0x01: do_scalar_MOV (cpu); return;
8580 case 0x39: do_scalar_FCM (cpu); return;
8581 case 0x3B: do_scalar_FCM (cpu); return;
8585 case 0xBE: do_scalar_shift (cpu); return;
8588 switch (uimm (aarch64_get_instr (cpu), 15, 10))
8590 case 0x36: do_scalar_FADDP (cpu); return;
8591 case 0x39: do_scalar_FCM (cpu); return;
8592 case 0x3B: do_scalar_FCM (cpu); return;
8597 switch (uimm (aarch64_get_instr (cpu), 15, 10))
8599 case 0x0D: do_scalar_CMGT (cpu); return;
8600 case 0x11: do_scalar_USHL (cpu); return;
8601 case 0x2E: do_scalar_NEG (cpu); return;
8602 case 0x35: do_scalar_FABD (cpu); return;
8603 case 0x39: do_scalar_FCM (cpu); return;
8604 case 0x3B: do_scalar_FCM (cpu); return;
8609 case 0xFE: do_scalar_USHR (cpu); return;
8612 switch (INSTR (15, 10))
8614 case 0x21: do_double_add (cpu); return;
8615 case 0x11: do_scalar_SSHL (cpu); return;
8626 dexAdvSIMD1 (sim_cpu *cpu)
8628 /* instr [28,25] = 1 111. */
8630 /* We are currently only interested in the basic
8631 scalar fp routines which all have bit 30 = 0. */
8632 if (uimm (aarch64_get_instr (cpu), 30, 30))
8633 do_scalar_vec (cpu);
8635 /* instr[24] is set for FP data processing 3-source and clear for
8636 all other basic scalar fp instruction groups. */
8637 else if (uimm (aarch64_get_instr (cpu), 24, 24))
8638 dexSimpleFPDataProc3Source (cpu);
8640 /* instr[21] is clear for floating <-> fixed conversions and set for
8641 all other basic scalar fp instruction groups. */
8642 else if (!uimm (aarch64_get_instr (cpu), 21, 21))
8643 dexSimpleFPFixedConvert (cpu);
8645 /* instr[11,10] : 01 ==> cond compare, 10 ==> Data Proc 2 Source
8646 11 ==> cond select, 00 ==> other. */
8648 switch (uimm (aarch64_get_instr (cpu), 11, 10))
8650 case 1: dexSimpleFPCondCompare (cpu); return;
8651 case 2: dexSimpleFPDataProc2Source (cpu); return;
8652 case 3: dexSimpleFPCondSelect (cpu); return;
8655 /* Now an ordered cascade of tests.
8656 FP immediate has aarch64_get_instr (cpu)[12] == 1.
8657 FP compare has aarch64_get_instr (cpu)[13] == 1.
8658 FP Data Proc 1 Source has aarch64_get_instr (cpu)[14] == 1.
8659 FP floating <--> integer conversions has aarch64_get_instr (cpu)[15] == 0. */
8660 if (uimm (aarch64_get_instr (cpu), 12, 12))
8661 dexSimpleFPImmediate (cpu);
8663 else if (uimm (aarch64_get_instr (cpu), 13, 13))
8664 dexSimpleFPCompare (cpu);
8666 else if (uimm (aarch64_get_instr (cpu), 14, 14))
8667 dexSimpleFPDataProc1Source (cpu);
8669 else if (!uimm (aarch64_get_instr (cpu), 15, 15))
8670 dexSimpleFPIntegerConvert (cpu);
8673 /* If we get here then instr[15] == 1 which means UNALLOC. */
8678 /* PC relative addressing. */
8681 pcadr (sim_cpu *cpu)
8683 /* instr[31] = op : 0 ==> ADR, 1 ==> ADRP
8684 instr[30,29] = immlo
8685 instr[23,5] = immhi. */
8687 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
8688 uint32_t isPage = uimm (aarch64_get_instr (cpu), 31, 31);
8689 union { int64_t u64; uint64_t s64; } imm;
8692 imm.s64 = simm64 (aarch64_get_instr (cpu), 23, 5);
8694 offset = (offset << 2) | uimm (aarch64_get_instr (cpu), 30, 29);
8696 address = aarch64_get_PC (cpu);
8704 aarch64_set_reg_u64 (cpu, rd, NO_SP, address + offset);
8707 /* Specific decode and execute for group Data Processing Immediate. */
8710 dexPCRelAddressing (sim_cpu *cpu)
8712 /* assert instr[28,24] = 10000. */
8716 /* Immediate logical.
8717 The bimm32/64 argument is constructed by replicating a 2, 4, 8,
8718 16, 32 or 64 bit sequence pulled out at decode and possibly
8721 N.B. the output register (dest) can normally be Xn or SP
8722 the exception occurs for flag setting instructions which may
8723 only use Xn for the output (dest). The input register can
8726 /* 32 bit and immediate. */
8728 and32 (sim_cpu *cpu, uint32_t bimm)
8730 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
8731 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
8733 aarch64_set_reg_u64 (cpu, rd, SP_OK,
8734 aarch64_get_reg_u32 (cpu, rn, NO_SP) & bimm);
8737 /* 64 bit and immediate. */
8739 and64 (sim_cpu *cpu, uint64_t bimm)
8741 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
8742 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
8744 aarch64_set_reg_u64 (cpu, rd, SP_OK,
8745 aarch64_get_reg_u64 (cpu, rn, NO_SP) & bimm);
8748 /* 32 bit and immediate set flags. */
8750 ands32 (sim_cpu *cpu, uint32_t bimm)
8752 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
8753 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
8755 uint32_t value1 = aarch64_get_reg_u32 (cpu, rn, NO_SP);
8756 uint32_t value2 = bimm;
8758 aarch64_set_reg_u64 (cpu, rd, NO_SP, value1 & value2);
8759 set_flags_for_binop32 (cpu, value1 & value2);
8762 /* 64 bit and immediate set flags. */
8764 ands64 (sim_cpu *cpu, uint64_t bimm)
8766 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
8767 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
8769 uint64_t value1 = aarch64_get_reg_u64 (cpu, rn, NO_SP);
8770 uint64_t value2 = bimm;
8772 aarch64_set_reg_u64 (cpu, rd, NO_SP, value1 & value2);
8773 set_flags_for_binop64 (cpu, value1 & value2);
8776 /* 32 bit exclusive or immediate. */
8778 eor32 (sim_cpu *cpu, uint32_t bimm)
8780 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
8781 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
8783 aarch64_set_reg_u64 (cpu, rd, SP_OK,
8784 aarch64_get_reg_u32 (cpu, rn, NO_SP) ^ bimm);
8787 /* 64 bit exclusive or immediate. */
8789 eor64 (sim_cpu *cpu, uint64_t bimm)
8791 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
8792 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
8794 aarch64_set_reg_u64 (cpu, rd, SP_OK,
8795 aarch64_get_reg_u64 (cpu, rn, NO_SP) ^ bimm);
8798 /* 32 bit or immediate. */
8800 orr32 (sim_cpu *cpu, uint32_t bimm)
8802 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
8803 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
8805 aarch64_set_reg_u64 (cpu, rd, SP_OK,
8806 aarch64_get_reg_u32 (cpu, rn, NO_SP) | bimm);
8809 /* 64 bit or immediate. */
8811 orr64 (sim_cpu *cpu, uint64_t bimm)
8813 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
8814 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
8816 aarch64_set_reg_u64 (cpu, rd, SP_OK,
8817 aarch64_get_reg_u64 (cpu, rn, NO_SP) | bimm);
8820 /* Logical shifted register.
8821 These allow an optional LSL, ASR, LSR or ROR to the second source
8822 register with a count up to the register bit count.
8823 N.B register args may not be SP. */
8825 /* 32 bit AND shifted register. */
8827 and32_shift (sim_cpu *cpu, Shift shift, uint32_t count)
8829 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
8830 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
8831 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
8834 (cpu, rd, NO_SP, aarch64_get_reg_u32 (cpu, rn, NO_SP)
8835 & shifted32 (aarch64_get_reg_u32 (cpu, rm, NO_SP), shift, count));
8838 /* 64 bit AND shifted register. */
8840 and64_shift (sim_cpu *cpu, Shift shift, uint32_t count)
8842 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
8843 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
8844 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
8847 (cpu, rd, NO_SP, aarch64_get_reg_u64 (cpu, rn, NO_SP)
8848 & shifted64 (aarch64_get_reg_u64 (cpu, rm, NO_SP), shift, count));
8851 /* 32 bit AND shifted register setting flags. */
8853 ands32_shift (sim_cpu *cpu, Shift shift, uint32_t count)
8855 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
8856 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
8857 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
8859 uint32_t value1 = aarch64_get_reg_u32 (cpu, rn, NO_SP);
8860 uint32_t value2 = shifted32 (aarch64_get_reg_u32 (cpu, rm, NO_SP),
8863 aarch64_set_reg_u64 (cpu, rd, NO_SP, value1 & value2);
8864 set_flags_for_binop32 (cpu, value1 & value2);
8867 /* 64 bit AND shifted register setting flags. */
8869 ands64_shift (sim_cpu *cpu, Shift shift, uint32_t count)
8871 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
8872 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
8873 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
8875 uint64_t value1 = aarch64_get_reg_u64 (cpu, rn, NO_SP);
8876 uint64_t value2 = shifted64 (aarch64_get_reg_u64 (cpu, rm, NO_SP),
8879 aarch64_set_reg_u64 (cpu, rd, NO_SP, value1 & value2);
8880 set_flags_for_binop64 (cpu, value1 & value2);
8883 /* 32 bit BIC shifted register. */
8885 bic32_shift (sim_cpu *cpu, Shift shift, uint32_t count)
8887 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
8888 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
8889 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
8892 (cpu, rd, NO_SP, aarch64_get_reg_u32 (cpu, rn, NO_SP)
8893 & ~ shifted32 (aarch64_get_reg_u32 (cpu, rm, NO_SP), shift, count));
8896 /* 64 bit BIC shifted register. */
8898 bic64_shift (sim_cpu *cpu, Shift shift, uint32_t count)
8900 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
8901 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
8902 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
8905 (cpu, rd, NO_SP, aarch64_get_reg_u64 (cpu, rn, NO_SP)
8906 & ~ shifted64 (aarch64_get_reg_u64 (cpu, rm, NO_SP), shift, count));
8909 /* 32 bit BIC shifted register setting flags. */
8911 bics32_shift (sim_cpu *cpu, Shift shift, uint32_t count)
8913 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
8914 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
8915 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
8917 uint32_t value1 = aarch64_get_reg_u32 (cpu, rn, NO_SP);
8918 uint32_t value2 = ~ shifted32 (aarch64_get_reg_u32 (cpu, rm, NO_SP),
8921 aarch64_set_reg_u64 (cpu, rd, NO_SP, value1 & value2);
8922 set_flags_for_binop32 (cpu, value1 & value2);
8925 /* 64 bit BIC shifted register setting flags. */
8927 bics64_shift (sim_cpu *cpu, Shift shift, uint32_t count)
8929 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
8930 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
8931 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
8933 uint64_t value1 = aarch64_get_reg_u64 (cpu, rn, NO_SP);
8934 uint64_t value2 = ~ shifted64 (aarch64_get_reg_u64 (cpu, rm, NO_SP),
8937 aarch64_set_reg_u64 (cpu, rd, NO_SP, value1 & value2);
8938 set_flags_for_binop64 (cpu, value1 & value2);
8941 /* 32 bit EON shifted register. */
8943 eon32_shift (sim_cpu *cpu, Shift shift, uint32_t count)
8945 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
8946 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
8947 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
8950 (cpu, rd, NO_SP, aarch64_get_reg_u32 (cpu, rn, NO_SP)
8951 ^ ~ shifted32 (aarch64_get_reg_u32 (cpu, rm, NO_SP), shift, count));
8954 /* 64 bit EON shifted register. */
8956 eon64_shift (sim_cpu *cpu, Shift shift, uint32_t count)
8958 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
8959 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
8960 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
8963 (cpu, rd, NO_SP, aarch64_get_reg_u64 (cpu, rn, NO_SP)
8964 ^ ~ shifted64 (aarch64_get_reg_u64 (cpu, rm, NO_SP), shift, count));
8967 /* 32 bit EOR shifted register. */
8969 eor32_shift (sim_cpu *cpu, Shift shift, uint32_t count)
8971 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
8972 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
8973 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
8976 (cpu, rd, NO_SP, aarch64_get_reg_u32 (cpu, rn, NO_SP)
8977 ^ shifted32 (aarch64_get_reg_u32 (cpu, rm, NO_SP), shift, count));
8980 /* 64 bit EOR shifted register. */
8982 eor64_shift (sim_cpu *cpu, Shift shift, uint32_t count)
8984 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
8985 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
8986 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
8989 (cpu, rd, NO_SP, aarch64_get_reg_u64 (cpu, rn, NO_SP)
8990 ^ shifted64 (aarch64_get_reg_u64 (cpu, rm, NO_SP), shift, count));
8993 /* 32 bit ORR shifted register. */
8995 orr32_shift (sim_cpu *cpu, Shift shift, uint32_t count)
8997 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
8998 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
8999 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
9002 (cpu, rd, NO_SP, aarch64_get_reg_u32 (cpu, rn, NO_SP)
9003 | shifted32 (aarch64_get_reg_u32 (cpu, rm, NO_SP), shift, count));
9006 /* 64 bit ORR shifted register. */
9008 orr64_shift (sim_cpu *cpu, Shift shift, uint32_t count)
9010 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
9011 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
9012 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
9015 (cpu, rd, NO_SP, aarch64_get_reg_u64 (cpu, rn, NO_SP)
9016 | shifted64 (aarch64_get_reg_u64 (cpu, rm, NO_SP), shift, count));
9019 /* 32 bit ORN shifted register. */
9021 orn32_shift (sim_cpu *cpu, Shift shift, uint32_t count)
9023 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
9024 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
9025 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
9028 (cpu, rd, NO_SP, aarch64_get_reg_u32 (cpu, rn, NO_SP)
9029 | ~ shifted32 (aarch64_get_reg_u32 (cpu, rm, NO_SP), shift, count));
9032 /* 64 bit ORN shifted register. */
9034 orn64_shift (sim_cpu *cpu, Shift shift, uint32_t count)
9036 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
9037 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
9038 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
9041 (cpu, rd, NO_SP, aarch64_get_reg_u64 (cpu, rn, NO_SP)
9042 | ~ shifted64 (aarch64_get_reg_u64 (cpu, rm, NO_SP), shift, count));
9046 dexLogicalImmediate (sim_cpu *cpu)
9048 /* assert instr[28,23] = 1001000
9049 instr[31] = size : 0 ==> 32 bit, 1 ==> 64 bit
9050 instr[30,29] = op : 0 ==> AND, 1 ==> ORR, 2 ==> EOR, 3 ==> ANDS
9051 instr[22] = N : used to construct immediate mask
9057 /* 32 bit operations must have N = 0 or else we have an UNALLOC. */
9058 uint32_t size = uimm (aarch64_get_instr (cpu), 31, 31);
9059 uint32_t N = uimm (aarch64_get_instr (cpu), 22, 22);
9060 /* uint32_t immr = uimm (aarch64_get_instr (cpu), 21, 16);. */
9061 /* uint32_t imms = uimm (aarch64_get_instr (cpu), 15, 10);. */
9062 uint32_t index = uimm (aarch64_get_instr (cpu), 22, 10);
9063 uint64_t bimm64 = LITable [index];
9064 uint32_t dispatch = uimm (aarch64_get_instr (cpu), 30, 29);
9074 uint32_t bimm = (uint32_t) bimm64;
9078 case 0: and32 (cpu, bimm); return;
9079 case 1: orr32 (cpu, bimm); return;
9080 case 2: eor32 (cpu, bimm); return;
9081 case 3: ands32 (cpu, bimm); return;
9088 case 0: and64 (cpu, bimm64); return;
9089 case 1: orr64 (cpu, bimm64); return;
9090 case 2: eor64 (cpu, bimm64); return;
9091 case 3: ands64 (cpu, bimm64); return;
9098 The uimm argument is a 16 bit value to be inserted into the
9099 target register the pos argument locates the 16 bit word in the
9100 dest register i.e. it is in {0, 1} for 32 bit and {0, 1, 2,
9102 N.B register arg may not be SP so it should be.
9103 accessed using the setGZRegisterXXX accessors. */
9105 /* 32 bit move 16 bit immediate zero remaining shorts. */
9107 movz32 (sim_cpu *cpu, uint32_t val, uint32_t pos)
9109 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
9111 aarch64_set_reg_u64 (cpu, rd, NO_SP, val << (pos * 16));
9114 /* 64 bit move 16 bit immediate zero remaining shorts. */
9116 movz64 (sim_cpu *cpu, uint32_t val, uint32_t pos)
9118 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
9120 aarch64_set_reg_u64 (cpu, rd, NO_SP, ((uint64_t) val) << (pos * 16));
9123 /* 32 bit move 16 bit immediate negated. */
9125 movn32 (sim_cpu *cpu, uint32_t val, uint32_t pos)
9127 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
9129 aarch64_set_reg_u64 (cpu, rd, NO_SP, ((val << (pos * 16)) ^ 0xffffffffU));
9132 /* 64 bit move 16 bit immediate negated. */
9134 movn64 (sim_cpu *cpu, uint32_t val, uint32_t pos)
9136 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
9139 (cpu, rd, NO_SP, ((((uint64_t) val) << (pos * 16))
9140 ^ 0xffffffffffffffffULL));
9143 /* 32 bit move 16 bit immediate keep remaining shorts. */
9145 movk32 (sim_cpu *cpu, uint32_t val, uint32_t pos)
9147 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
9148 uint32_t current = aarch64_get_reg_u32 (cpu, rd, NO_SP);
9149 uint32_t value = val << (pos * 16);
9150 uint32_t mask = ~(0xffffU << (pos * 16));
9152 aarch64_set_reg_u64 (cpu, rd, NO_SP, (value | (current & mask)));
9155 /* 64 bit move 16 it immediate keep remaining shorts. */
9157 movk64 (sim_cpu *cpu, uint32_t val, uint32_t pos)
9159 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
9160 uint64_t current = aarch64_get_reg_u64 (cpu, rd, NO_SP);
9161 uint64_t value = (uint64_t) val << (pos * 16);
9162 uint64_t mask = ~(0xffffULL << (pos * 16));
9164 aarch64_set_reg_u64 (cpu, rd, NO_SP, (value | (current & mask)));
9168 dexMoveWideImmediate (sim_cpu *cpu)
9170 /* assert instr[28:23] = 100101
9171 instr[31] = size : 0 ==> 32 bit, 1 ==> 64 bit
9172 instr[30,29] = op : 0 ==> MOVN, 1 ==> UNALLOC, 2 ==> MOVZ, 3 ==> MOVK
9173 instr[22,21] = shift : 00 == LSL#0, 01 = LSL#16, 10 = LSL#32, 11 = LSL#48
9174 instr[20,5] = uimm16
9177 /* N.B. the (multiple of 16) shift is applied by the called routine,
9178 we just pass the multiplier. */
9181 uint32_t size = uimm (aarch64_get_instr (cpu), 31, 31);
9182 uint32_t op = uimm (aarch64_get_instr (cpu), 30, 29);
9183 uint32_t shift = uimm (aarch64_get_instr (cpu), 22, 21);
9185 /* 32 bit can only shift 0 or 1 lot of 16.
9186 anything else is an unallocated instruction. */
9187 if (size == 0 && (shift > 1))
9193 imm = uimm (aarch64_get_instr (cpu), 20, 5);
9198 movn32 (cpu, imm, shift);
9200 movz32 (cpu, imm, shift);
9202 movk32 (cpu, imm, shift);
9207 movn64 (cpu, imm, shift);
9209 movz64 (cpu, imm, shift);
9211 movk64 (cpu, imm, shift);
9215 /* Bitfield operations.
9216 These take a pair of bit positions r and s which are in {0..31}
9217 or {0..63} depending on the instruction word size.
9218 N.B register args may not be SP. */
9220 /* OK, we start with ubfm which just needs to pick
9221 some bits out of source zero the rest and write
9222 the result to dest. Just need two logical shifts. */
9224 /* 32 bit bitfield move, left and right of affected zeroed
9225 if r <= s Wd<s-r:0> = Wn<s:r> else Wd<32+s-r,32-r> = Wn<s:0>. */
9227 ubfm32 (sim_cpu *cpu, uint32_t r, uint32_t s)
9230 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
9231 uint32_t value = aarch64_get_reg_u32 (cpu, rn, NO_SP);
9233 /* Pick either s+1-r or s+1 consecutive bits out of the original word. */
9236 /* 31:...:s:xxx:r:...:0 ==> 31:...:s-r:xxx:0.
9237 We want only bits s:xxx:r at the bottom of the word
9238 so we LSL bit s up to bit 31 i.e. by 31 - s
9239 and then we LSR to bring bit 31 down to bit s - r
9240 i.e. by 31 + r - s. */
9242 value >>= 31 + r - s;
9246 /* 31:...:s:xxx:0 ==> 31:...:31-(r-1)+s:xxx:31-(r-1):...:0
9247 We want only bits s:xxx:0 starting at it 31-(r-1)
9248 so we LSL bit s up to bit 31 i.e. by 31 - s
9249 and then we LSL to bring bit 31 down to 31-(r-1)+s
9250 i.e. by r - (s + 1). */
9252 value >>= r - (s + 1);
9255 rd = uimm (aarch64_get_instr (cpu), 4, 0);
9256 aarch64_set_reg_u64 (cpu, rd, NO_SP, value);
9259 /* 64 bit bitfield move, left and right of affected zeroed
9260 if r <= s Wd<s-r:0> = Wn<s:r> else Wd<64+s-r,64-r> = Wn<s:0>. */
9262 ubfm (sim_cpu *cpu, uint32_t r, uint32_t s)
9265 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
9266 uint64_t value = aarch64_get_reg_u64 (cpu, rn, NO_SP);
9270 /* 63:...:s:xxx:r:...:0 ==> 63:...:s-r:xxx:0.
9271 We want only bits s:xxx:r at the bottom of the word.
9272 So we LSL bit s up to bit 63 i.e. by 63 - s
9273 and then we LSR to bring bit 63 down to bit s - r
9274 i.e. by 63 + r - s. */
9276 value >>= 63 + r - s;
9280 /* 63:...:s:xxx:0 ==> 63:...:63-(r-1)+s:xxx:63-(r-1):...:0.
9281 We want only bits s:xxx:0 starting at it 63-(r-1).
9282 So we LSL bit s up to bit 63 i.e. by 63 - s
9283 and then we LSL to bring bit 63 down to 63-(r-1)+s
9284 i.e. by r - (s + 1). */
9286 value >>= r - (s + 1);
9289 rd = uimm (aarch64_get_instr (cpu), 4, 0);
9290 aarch64_set_reg_u64 (cpu, rd, NO_SP, value);
9293 /* The signed versions need to insert sign bits
9294 on the left of the inserted bit field. so we do
9295 much the same as the unsigned version except we
9296 use an arithmetic shift right -- this just means
9297 we need to operate on signed values. */
9299 /* 32 bit bitfield move, left of affected sign-extended, right zeroed. */
9300 /* If r <= s Wd<s-r:0> = Wn<s:r> else Wd<32+s-r,32-r> = Wn<s:0>. */
9302 sbfm32 (sim_cpu *cpu, uint32_t r, uint32_t s)
9305 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
9306 /* as per ubfm32 but use an ASR instead of an LSR. */
9307 int32_t value = aarch64_get_reg_s32 (cpu, rn, NO_SP);
9312 value >>= 31 + r - s;
9317 value >>= r - (s + 1);
9320 rd = uimm (aarch64_get_instr (cpu), 4, 0);
9321 aarch64_set_reg_u64 (cpu, rd, NO_SP, (uint32_t) value);
9324 /* 64 bit bitfield move, left of affected sign-extended, right zeroed. */
9325 /* If r <= s Wd<s-r:0> = Wn<s:r> else Wd<64+s-r,64-r> = Wn<s:0>. */
9327 sbfm (sim_cpu *cpu, uint32_t r, uint32_t s)
9330 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
9331 /* acpu per ubfm but use an ASR instead of an LSR. */
9332 int64_t value = aarch64_get_reg_s64 (cpu, rn, NO_SP);
9337 value >>= 63 + r - s;
9342 value >>= r - (s + 1);
9345 rd = uimm (aarch64_get_instr (cpu), 4, 0);
9346 aarch64_set_reg_s64 (cpu, rd, NO_SP, value);
9349 /* Finally, these versions leave non-affected bits
9350 as is. so we need to generate the bits as per
9351 ubfm and also generate a mask to pick the
9352 bits from the original and computed values. */
9354 /* 32 bit bitfield move, non-affected bits left as is.
9355 If r <= s Wd<s-r:0> = Wn<s:r> else Wd<32+s-r,32-r> = Wn<s:0>. */
9357 bfm32 (sim_cpu *cpu, uint32_t r, uint32_t s)
9359 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
9360 uint32_t value = aarch64_get_reg_u32 (cpu, rn, NO_SP);
9365 /* Pick either s+1-r or s+1 consecutive bits out of the original word. */
9368 /* 31:...:s:xxx:r:...:0 ==> 31:...:s-r:xxx:0.
9369 We want only bits s:xxx:r at the bottom of the word
9370 so we LSL bit s up to bit 31 i.e. by 31 - s
9371 and then we LSR to bring bit 31 down to bit s - r
9372 i.e. by 31 + r - s. */
9374 value >>= 31 + r - s;
9375 /* the mask must include the same bits. */
9377 mask >>= 31 + r - s;
9381 /* 31:...:s:xxx:0 ==> 31:...:31-(r-1)+s:xxx:31-(r-1):...:0.
9382 We want only bits s:xxx:0 starting at it 31-(r-1)
9383 so we LSL bit s up to bit 31 i.e. by 31 - s
9384 and then we LSL to bring bit 31 down to 31-(r-1)+s
9385 i.e. by r - (s + 1). */
9387 value >>= r - (s + 1);
9388 /* The mask must include the same bits. */
9390 mask >>= r - (s + 1);
9393 rd = uimm (aarch64_get_instr (cpu), 4, 0);
9394 value2 = aarch64_get_reg_u32 (cpu, rd, NO_SP);
9400 (cpu, rd, NO_SP, (aarch64_get_reg_u32 (cpu, rd, NO_SP) & ~mask) | value);
9403 /* 64 bit bitfield move, non-affected bits left as is.
9404 If r <= s Wd<s-r:0> = Wn<s:r> else Wd<64+s-r,64-r> = Wn<s:0>. */
9406 bfm (sim_cpu *cpu, uint32_t r, uint32_t s)
9409 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
9410 uint64_t value = aarch64_get_reg_u64 (cpu, rn, NO_SP);
9411 uint64_t mask = 0xffffffffffffffffULL;
9415 /* 63:...:s:xxx:r:...:0 ==> 63:...:s-r:xxx:0.
9416 We want only bits s:xxx:r at the bottom of the word
9417 so we LSL bit s up to bit 63 i.e. by 63 - s
9418 and then we LSR to bring bit 63 down to bit s - r
9419 i.e. by 63 + r - s. */
9421 value >>= 63 + r - s;
9422 /* The mask must include the same bits. */
9424 mask >>= 63 + r - s;
9428 /* 63:...:s:xxx:0 ==> 63:...:63-(r-1)+s:xxx:63-(r-1):...:0
9429 We want only bits s:xxx:0 starting at it 63-(r-1)
9430 so we LSL bit s up to bit 63 i.e. by 63 - s
9431 and then we LSL to bring bit 63 down to 63-(r-1)+s
9432 i.e. by r - (s + 1). */
9434 value >>= r - (s + 1);
9435 /* The mask must include the same bits. */
9437 mask >>= r - (s + 1);
9440 rd = uimm (aarch64_get_instr (cpu), 4, 0);
9442 (cpu, rd, NO_SP, (aarch64_get_reg_u64 (cpu, rd, NO_SP) & ~mask) | value);
9446 dexBitfieldImmediate (sim_cpu *cpu)
9448 /* assert instr[28:23] = 100110
9449 instr[31] = size : 0 ==> 32 bit, 1 ==> 64 bit
9450 instr[30,29] = op : 0 ==> SBFM, 1 ==> BFM, 2 ==> UBFM, 3 ==> UNALLOC
9451 instr[22] = N : must be 0 for 32 bit, 1 for 64 bit ow UNALLOC
9452 instr[21,16] = immr : 0xxxxx for 32 bit, xxxxxx for 64 bit
9453 instr[15,10] = imms : 0xxxxx for 32 bit, xxxxxx for 64 bit
9457 /* 32 bit operations must have N = 0 or else we have an UNALLOC. */
9460 uint32_t size = uimm (aarch64_get_instr (cpu), 31, 31);
9461 uint32_t N = uimm (aarch64_get_instr (cpu), 22, 22);
9462 /* 32 bit operations must have immr[5] = 0 and imms[5] = 0. */
9463 /* or else we have an UNALLOC. */
9464 uint32_t immr = uimm (aarch64_get_instr (cpu), 21, 16);
9469 if (!size && uimm (immr, 5, 5))
9472 imms = uimm (aarch64_get_instr (cpu), 15, 10);
9473 if (!size && uimm (imms, 5, 5))
9476 /* Switch on combined size and op. */
9477 dispatch = uimm (aarch64_get_instr (cpu), 31, 29);
9480 case 0: sbfm32 (cpu, immr, imms); return;
9481 case 1: bfm32 (cpu, immr, imms); return;
9482 case 2: ubfm32 (cpu, immr, imms); return;
9483 case 4: sbfm (cpu, immr, imms); return;
9484 case 5: bfm (cpu, immr, imms); return;
9485 case 6: ubfm (cpu, immr, imms); return;
9486 default: HALT_UNALLOC;
9491 do_EXTR_32 (sim_cpu *cpu)
9493 /* instr[31:21] = 00010011100
9495 instr[15,10] = imms : 0xxxxx for 32 bit
9498 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
9499 unsigned imms = uimm (aarch64_get_instr (cpu), 15, 10) & 31;
9500 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
9501 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
9505 val1 = aarch64_get_reg_u32 (cpu, rm, NO_SP);
9507 val2 = aarch64_get_reg_u32 (cpu, rn, NO_SP);
9508 val2 <<= (32 - imms);
9510 aarch64_set_reg_u64 (cpu, rd, NO_SP, val1 | val2);
9514 do_EXTR_64 (sim_cpu *cpu)
9516 /* instr[31:21] = 10010011100
9521 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
9522 unsigned imms = uimm (aarch64_get_instr (cpu), 15, 10) & 63;
9523 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
9524 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
9527 val = aarch64_get_reg_u64 (cpu, rm, NO_SP);
9529 val |= (aarch64_get_reg_u64 (cpu, rn, NO_SP) << (64 - imms));
9531 aarch64_set_reg_u64 (cpu, rd, NO_SP, val);
9535 dexExtractImmediate (sim_cpu *cpu)
9537 /* assert instr[28:23] = 100111
9538 instr[31] = size : 0 ==> 32 bit, 1 ==> 64 bit
9539 instr[30,29] = op21 : 0 ==> EXTR, 1,2,3 ==> UNALLOC
9540 instr[22] = N : must be 0 for 32 bit, 1 for 64 bit or UNALLOC
9541 instr[21] = op0 : must be 0 or UNALLOC
9543 instr[15,10] = imms : 0xxxxx for 32 bit, xxxxxx for 64 bit
9547 /* 32 bit operations must have N = 0 or else we have an UNALLOC. */
9548 /* 64 bit operations must have N = 1 or else we have an UNALLOC. */
9550 uint32_t size = uimm (aarch64_get_instr (cpu), 31, 31);
9551 uint32_t N = uimm (aarch64_get_instr (cpu), 22, 22);
9552 /* 32 bit operations must have imms[5] = 0
9553 or else we have an UNALLOC. */
9554 uint32_t imms = uimm (aarch64_get_instr (cpu), 15, 10);
9559 if (!size && uimm (imms, 5, 5))
9562 /* Switch on combined size and op. */
9563 dispatch = uimm (aarch64_get_instr (cpu), 31, 29);
9568 else if (dispatch == 4)
9571 else if (dispatch == 1)
9578 dexDPImm (sim_cpu *cpu)
9580 /* uint32_t group = dispatchGroup (aarch64_get_instr (cpu));
9581 assert group == GROUP_DPIMM_1000 || grpoup == GROUP_DPIMM_1001
9582 bits [25,23] of a DPImm are the secondary dispatch vector. */
9583 uint32_t group2 = dispatchDPImm (aarch64_get_instr (cpu));
9587 case DPIMM_PCADR_000:
9588 case DPIMM_PCADR_001:
9589 dexPCRelAddressing (cpu);
9592 case DPIMM_ADDSUB_010:
9593 case DPIMM_ADDSUB_011:
9594 dexAddSubtractImmediate (cpu);
9598 dexLogicalImmediate (cpu);
9602 dexMoveWideImmediate (cpu);
9605 case DPIMM_BITF_110:
9606 dexBitfieldImmediate (cpu);
9609 case DPIMM_EXTR_111:
9610 dexExtractImmediate (cpu);
9614 /* Should never reach here. */
9620 dexLoadUnscaledImmediate (sim_cpu *cpu)
9622 /* instr[29,24] == 111_00
9628 instr[20,12] = simm9
9629 instr[9,5] = rn may be SP. */
9630 /* unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0); */
9631 uint32_t V = uimm (aarch64_get_instr (cpu), 26, 26);
9632 uint32_t dispatch = ( (uimm (aarch64_get_instr (cpu), 31, 30) << 2)
9633 | uimm (aarch64_get_instr (cpu), 23, 22));
9634 int32_t imm = simm32 (aarch64_get_instr (cpu), 20, 12);
9638 /* GReg operations. */
9641 case 0: sturb (cpu, imm); return;
9642 case 1: ldurb32 (cpu, imm); return;
9643 case 2: ldursb64 (cpu, imm); return;
9644 case 3: ldursb32 (cpu, imm); return;
9645 case 4: sturh (cpu, imm); return;
9646 case 5: ldurh32 (cpu, imm); return;
9647 case 6: ldursh64 (cpu, imm); return;
9648 case 7: ldursh32 (cpu, imm); return;
9649 case 8: stur32 (cpu, imm); return;
9650 case 9: ldur32 (cpu, imm); return;
9651 case 10: ldursw (cpu, imm); return;
9652 case 12: stur64 (cpu, imm); return;
9653 case 13: ldur64 (cpu, imm); return;
9666 /* FReg operations. */
9669 case 2: fsturq (cpu, imm); return;
9670 case 3: fldurq (cpu, imm); return;
9671 case 8: fsturs (cpu, imm); return;
9672 case 9: fldurs (cpu, imm); return;
9673 case 12: fsturd (cpu, imm); return;
9674 case 13: fldurd (cpu, imm); return;
9676 case 0: /* STUR 8 bit FP. */
9677 case 1: /* LDUR 8 bit FP. */
9678 case 4: /* STUR 16 bit FP. */
9679 case 5: /* LDUR 8 bit FP. */
9693 /* N.B. A preliminary note regarding all the ldrs<x>32
9696 The signed value loaded by these instructions is cast to unsigned
9697 before being assigned to aarch64_get_reg_u64 (cpu, N) i.e. to the
9698 64 bit element of the GReg union. this performs a 32 bit sign extension
9699 (as required) but avoids 64 bit sign extension, thus ensuring that the
9700 top half of the register word is zero. this is what the spec demands
9701 when a 32 bit load occurs. */
9703 /* 32 bit load sign-extended byte scaled unsigned 12 bit. */
9705 ldrsb32_abs (sim_cpu *cpu, uint32_t offset)
9707 unsigned int rn = uimm (aarch64_get_instr (cpu), 9, 5);
9708 unsigned int rt = uimm (aarch64_get_instr (cpu), 4, 0);
9710 /* The target register may not be SP but the source may be
9711 there is no scaling required for a byte load. */
9712 uint64_t address = aarch64_get_reg_u64 (cpu, rn, SP_OK) + offset;
9713 aarch64_set_reg_u64 (cpu, rt, NO_SP,
9714 (int64_t) aarch64_get_mem_s8 (cpu, address));
9717 /* 32 bit load sign-extended byte scaled or unscaled zero-
9718 or sign-extended 32-bit register offset. */
9720 ldrsb32_scale_ext (sim_cpu *cpu, Scaling scaling, Extension extension)
9722 unsigned int rm = uimm (aarch64_get_instr (cpu), 20, 16);
9723 unsigned int rn = uimm (aarch64_get_instr (cpu), 9, 5);
9724 unsigned int rt = uimm (aarch64_get_instr (cpu), 4, 0);
9726 /* rn may reference SP, rm and rt must reference ZR. */
9728 uint64_t address = aarch64_get_reg_u64 (cpu, rn, SP_OK);
9729 int64_t displacement = extend (aarch64_get_reg_u32 (cpu, rm, NO_SP),
9732 /* There is no scaling required for a byte load. */
9734 (cpu, rt, NO_SP, (int64_t) aarch64_get_mem_s8 (cpu, address
9738 /* 32 bit load sign-extended byte unscaled signed 9 bit with
9739 pre- or post-writeback. */
9741 ldrsb32_wb (sim_cpu *cpu, int32_t offset, WriteBack wb)
9744 unsigned int rn = uimm (aarch64_get_instr (cpu), 9, 5);
9745 unsigned int rt = uimm (aarch64_get_instr (cpu), 4, 0);
9747 if (rn == rt && wb != NoWriteBack)
9750 address = aarch64_get_reg_u64 (cpu, rn, SP_OK);
9755 aarch64_set_reg_u64 (cpu, rt, NO_SP,
9756 (int64_t) aarch64_get_mem_s8 (cpu, address));
9761 if (wb != NoWriteBack)
9762 aarch64_set_reg_u64 (cpu, rn, NO_SP, address);
9765 /* 8 bit store scaled. */
9767 fstrb_abs (sim_cpu *cpu, uint32_t offset)
9769 unsigned st = uimm (aarch64_get_instr (cpu), 4, 0);
9770 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
9772 aarch64_set_mem_u8 (cpu,
9773 aarch64_get_reg_u64 (cpu, rn, SP_OK) + offset,
9774 aarch64_get_vec_u8 (cpu, st, 0));
9777 /* 8 bit store scaled or unscaled zero- or
9778 sign-extended 8-bit register offset. */
9780 fstrb_scale_ext (sim_cpu *cpu, Scaling scaling, Extension extension)
9782 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
9783 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
9784 unsigned st = uimm (aarch64_get_instr (cpu), 4, 0);
9786 uint64_t address = aarch64_get_reg_u64 (cpu, rn, SP_OK);
9787 int64_t extended = extend (aarch64_get_reg_u32 (cpu, rm, NO_SP),
9789 uint64_t displacement = OPT_SCALE (extended, 32, scaling);
9792 (cpu, address + displacement, aarch64_get_vec_u8 (cpu, st, 0));
9795 /* 16 bit store scaled. */
9797 fstrh_abs (sim_cpu *cpu, uint32_t offset)
9799 unsigned st = uimm (aarch64_get_instr (cpu), 4, 0);
9800 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
9804 aarch64_get_reg_u64 (cpu, rn, SP_OK) + SCALE (offset, 16),
9805 aarch64_get_vec_u16 (cpu, st, 0));
9808 /* 16 bit store scaled or unscaled zero-
9809 or sign-extended 16-bit register offset. */
9811 fstrh_scale_ext (sim_cpu *cpu, Scaling scaling, Extension extension)
9813 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
9814 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
9815 unsigned st = uimm (aarch64_get_instr (cpu), 4, 0);
9817 uint64_t address = aarch64_get_reg_u64 (cpu, rn, SP_OK);
9818 int64_t extended = extend (aarch64_get_reg_u32 (cpu, rm, NO_SP),
9820 uint64_t displacement = OPT_SCALE (extended, 32, scaling);
9823 (cpu, address + displacement, aarch64_get_vec_u16 (cpu, st, 0));
9826 /* 32 bit store scaled unsigned 12 bit. */
9828 fstrs_abs (sim_cpu *cpu, uint32_t offset)
9830 unsigned st = uimm (aarch64_get_instr (cpu), 4, 0);
9831 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
9835 aarch64_get_reg_u64 (cpu, rn, SP_OK) + SCALE (offset, 32),
9836 aarch64_get_vec_u32 (cpu, st, 0));
9839 /* 32 bit store unscaled signed 9 bit with pre- or post-writeback. */
9841 fstrs_wb (sim_cpu *cpu, int32_t offset, WriteBack wb)
9843 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
9844 unsigned st = uimm (aarch64_get_instr (cpu), 4, 0);
9846 uint64_t address = aarch64_get_reg_u64 (cpu, rn, SP_OK);
9851 aarch64_set_mem_u32 (cpu, address, aarch64_get_vec_u32 (cpu, st, 0));
9856 if (wb != NoWriteBack)
9857 aarch64_set_reg_u64 (cpu, rn, SP_OK, address);
9860 /* 32 bit store scaled or unscaled zero-
9861 or sign-extended 32-bit register offset. */
9863 fstrs_scale_ext (sim_cpu *cpu, Scaling scaling, Extension extension)
9865 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
9866 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
9867 unsigned st = uimm (aarch64_get_instr (cpu), 4, 0);
9869 uint64_t address = aarch64_get_reg_u64 (cpu, rn, SP_OK);
9870 int64_t extended = extend (aarch64_get_reg_u32 (cpu, rm, NO_SP),
9872 uint64_t displacement = OPT_SCALE (extended, 32, scaling);
9875 (cpu, address + displacement, aarch64_get_vec_u32 (cpu, st, 0));
9878 /* 64 bit store scaled unsigned 12 bit. */
9880 fstrd_abs (sim_cpu *cpu, uint32_t offset)
9882 unsigned st = uimm (aarch64_get_instr (cpu), 4, 0);
9883 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
9887 aarch64_get_reg_u64 (cpu, rn, SP_OK) + SCALE (offset, 64),
9888 aarch64_get_vec_u64 (cpu, st, 0));
9891 /* 64 bit store unscaled signed 9 bit with pre- or post-writeback. */
9893 fstrd_wb (sim_cpu *cpu, int32_t offset, WriteBack wb)
9895 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
9896 unsigned st = uimm (aarch64_get_instr (cpu), 4, 0);
9898 uint64_t address = aarch64_get_reg_u64 (cpu, rn, SP_OK);
9903 aarch64_set_mem_u64 (cpu, address, aarch64_get_vec_u64 (cpu, st, 0));
9908 if (wb != NoWriteBack)
9909 aarch64_set_reg_u64 (cpu, rn, SP_OK, address);
9912 /* 64 bit store scaled or unscaled zero-
9913 or sign-extended 32-bit register offset. */
9915 fstrd_scale_ext (sim_cpu *cpu, Scaling scaling, Extension extension)
9917 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
9918 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
9919 unsigned st = uimm (aarch64_get_instr (cpu), 4, 0);
9921 uint64_t address = aarch64_get_reg_u64 (cpu, rn, SP_OK);
9922 int64_t extended = extend (aarch64_get_reg_u32 (cpu, rm, NO_SP),
9924 uint64_t displacement = OPT_SCALE (extended, 64, scaling);
9927 (cpu, address + displacement, aarch64_get_vec_u64 (cpu, st, 0));
9930 /* 128 bit store scaled unsigned 12 bit. */
9932 fstrq_abs (sim_cpu *cpu, uint32_t offset)
9935 unsigned st = uimm (aarch64_get_instr (cpu), 4, 0);
9936 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
9939 aarch64_get_FP_long_double (cpu, st, & a);
9941 addr = aarch64_get_reg_u64 (cpu, rn, SP_OK) + SCALE (offset, 128);
9942 aarch64_set_mem_long_double (cpu, addr, a);
9945 /* 128 bit store unscaled signed 9 bit with pre- or post-writeback. */
9947 fstrq_wb (sim_cpu *cpu, int32_t offset, WriteBack wb)
9950 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
9951 unsigned st = uimm (aarch64_get_instr (cpu), 4, 0);
9952 uint64_t address = aarch64_get_reg_u64 (cpu, rn, SP_OK);
9957 aarch64_get_FP_long_double (cpu, st, & a);
9958 aarch64_set_mem_long_double (cpu, address, a);
9963 if (wb != NoWriteBack)
9964 aarch64_set_reg_u64 (cpu, rn, SP_OK, address);
9967 /* 128 bit store scaled or unscaled zero-
9968 or sign-extended 32-bit register offset. */
9970 fstrq_scale_ext (sim_cpu *cpu, Scaling scaling, Extension extension)
9972 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
9973 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
9974 unsigned st = uimm (aarch64_get_instr (cpu), 4, 0);
9976 uint64_t address = aarch64_get_reg_u64 (cpu, rn, SP_OK);
9977 int64_t extended = extend (aarch64_get_reg_u32 (cpu, rm, NO_SP),
9979 uint64_t displacement = OPT_SCALE (extended, 128, scaling);
9983 aarch64_get_FP_long_double (cpu, st, & a);
9984 aarch64_set_mem_long_double (cpu, address + displacement, a);
9988 dexLoadImmediatePrePost (sim_cpu *cpu)
9990 /* instr[29,24] == 111_00
9996 instr[20,12] = simm9
9997 instr[11] = wb : 0 ==> Post, 1 ==> Pre
9998 instr[9,5] = rn may be SP. */
9999 /* unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0); */
10000 uint32_t V = uimm (aarch64_get_instr (cpu), 26, 26);
10001 uint32_t dispatch = ( (uimm (aarch64_get_instr (cpu), 31, 30) << 2)
10002 | uimm (aarch64_get_instr (cpu), 23, 22));
10003 int32_t imm = simm32 (aarch64_get_instr (cpu), 20, 12);
10004 WriteBack wb = writeback (aarch64_get_instr (cpu), 11);
10008 /* GReg operations. */
10011 case 0: strb_wb (cpu, imm, wb); return;
10012 case 1: ldrb32_wb (cpu, imm, wb); return;
10013 case 2: ldrsb_wb (cpu, imm, wb); return;
10014 case 3: ldrsb32_wb (cpu, imm, wb); return;
10015 case 4: strh_wb (cpu, imm, wb); return;
10016 case 5: ldrh32_wb (cpu, imm, wb); return;
10017 case 6: ldrsh64_wb (cpu, imm, wb); return;
10018 case 7: ldrsh32_wb (cpu, imm, wb); return;
10019 case 8: str32_wb (cpu, imm, wb); return;
10020 case 9: ldr32_wb (cpu, imm, wb); return;
10021 case 10: ldrsw_wb (cpu, imm, wb); return;
10022 case 12: str_wb (cpu, imm, wb); return;
10023 case 13: ldr_wb (cpu, imm, wb); return;
10033 /* FReg operations. */
10036 case 2: fstrq_wb (cpu, imm, wb); return;
10037 case 3: fldrq_wb (cpu, imm, wb); return;
10038 case 8: fstrs_wb (cpu, imm, wb); return;
10039 case 9: fldrs_wb (cpu, imm, wb); return;
10040 case 12: fstrd_wb (cpu, imm, wb); return;
10041 case 13: fldrd_wb (cpu, imm, wb); return;
10043 case 0: /* STUR 8 bit FP. */
10044 case 1: /* LDUR 8 bit FP. */
10045 case 4: /* STUR 16 bit FP. */
10046 case 5: /* LDUR 8 bit FP. */
10061 dexLoadRegisterOffset (sim_cpu *cpu)
10063 /* instr[31,30] = size
10070 instr[15,13] = option : 010 ==> UXTW, 011 ==> UXTX/LSL,
10071 110 ==> SXTW, 111 ==> SXTX,
10076 instr[4,0] = rt. */
10078 uint32_t V = uimm (aarch64_get_instr (cpu), 26,26);
10079 uint32_t dispatch = ( (uimm (aarch64_get_instr (cpu), 31, 30) << 2)
10080 | uimm (aarch64_get_instr (cpu), 23, 22));
10081 Scaling scale = scaling (aarch64_get_instr (cpu), 12);
10082 Extension extensionType = extension (aarch64_get_instr (cpu), 13);
10084 /* Check for illegal extension types. */
10085 if (uimm (extensionType, 1, 1) == 0)
10088 if (extensionType == UXTX || extensionType == SXTX)
10089 extensionType = NoExtension;
10093 /* GReg operations. */
10096 case 0: strb_scale_ext (cpu, scale, extensionType); return;
10097 case 1: ldrb32_scale_ext (cpu, scale, extensionType); return;
10098 case 2: ldrsb_scale_ext (cpu, scale, extensionType); return;
10099 case 3: ldrsb32_scale_ext (cpu, scale, extensionType); return;
10100 case 4: strh_scale_ext (cpu, scale, extensionType); return;
10101 case 5: ldrh32_scale_ext (cpu, scale, extensionType); return;
10102 case 6: ldrsh_scale_ext (cpu, scale, extensionType); return;
10103 case 7: ldrsh32_scale_ext (cpu, scale, extensionType); return;
10104 case 8: str32_scale_ext (cpu, scale, extensionType); return;
10105 case 9: ldr32_scale_ext (cpu, scale, extensionType); return;
10106 case 10: ldrsw_scale_ext (cpu, scale, extensionType); return;
10107 case 12: str_scale_ext (cpu, scale, extensionType); return;
10108 case 13: ldr_scale_ext (cpu, scale, extensionType); return;
10109 case 14: prfm_scale_ext (cpu, scale, extensionType); return;
10118 /* FReg operations. */
10121 case 1: /* LDUR 8 bit FP. */
10123 case 3: fldrq_scale_ext (cpu, scale, extensionType); return;
10124 case 5: /* LDUR 8 bit FP. */
10126 case 9: fldrs_scale_ext (cpu, scale, extensionType); return;
10127 case 13: fldrd_scale_ext (cpu, scale, extensionType); return;
10129 case 0: fstrb_scale_ext (cpu, scale, extensionType); return;
10130 case 2: fstrq_scale_ext (cpu, scale, extensionType); return;
10131 case 4: fstrh_scale_ext (cpu, scale, extensionType); return;
10132 case 8: fstrs_scale_ext (cpu, scale, extensionType); return;
10133 case 12: fstrd_scale_ext (cpu, scale, extensionType); return;
10147 dexLoadUnsignedImmediate (sim_cpu *cpu)
10149 /* instr[29,24] == 111_01
10150 instr[31,30] = size
10153 instr[21,10] = uimm12 : unsigned immediate offset
10154 instr[9,5] = rn may be SP.
10155 instr[4,0] = rt. */
10157 uint32_t V = uimm (aarch64_get_instr (cpu), 26,26);
10158 uint32_t dispatch = ( (uimm (aarch64_get_instr (cpu), 31, 30) << 2)
10159 | uimm (aarch64_get_instr (cpu), 23, 22));
10160 uint32_t imm = uimm (aarch64_get_instr (cpu), 21, 10);
10164 /* GReg operations. */
10167 case 0: strb_abs (cpu, imm); return;
10168 case 1: ldrb32_abs (cpu, imm); return;
10169 case 2: ldrsb_abs (cpu, imm); return;
10170 case 3: ldrsb32_abs (cpu, imm); return;
10171 case 4: strh_abs (cpu, imm); return;
10172 case 5: ldrh32_abs (cpu, imm); return;
10173 case 6: ldrsh_abs (cpu, imm); return;
10174 case 7: ldrsh32_abs (cpu, imm); return;
10175 case 8: str32_abs (cpu, imm); return;
10176 case 9: ldr32_abs (cpu, imm); return;
10177 case 10: ldrsw_abs (cpu, imm); return;
10178 case 12: str_abs (cpu, imm); return;
10179 case 13: ldr_abs (cpu, imm); return;
10180 case 14: prfm_abs (cpu, imm); return;
10189 /* FReg operations. */
10192 case 0: fstrb_abs (cpu, imm); return;
10193 case 4: fstrh_abs (cpu, imm); return;
10194 case 8: fstrs_abs (cpu, imm); return;
10195 case 12: fstrd_abs (cpu, imm); return;
10196 case 2: fstrq_abs (cpu, imm); return;
10198 case 1: fldrb_abs (cpu, imm); return;
10199 case 5: fldrh_abs (cpu, imm); return;
10200 case 9: fldrs_abs (cpu, imm); return;
10201 case 13: fldrd_abs (cpu, imm); return;
10202 case 3: fldrq_abs (cpu, imm); return;
10216 dexLoadExclusive (sim_cpu *cpu)
10218 /* assert instr[29:24] = 001000;
10219 instr[31,30] = size
10220 instr[23] = 0 if exclusive
10221 instr[22] = L : 1 if load, 0 if store
10222 instr[21] = 1 if pair
10224 instr[15] = o0 : 1 if ordered
10227 instr[4.0] = Rt. */
10229 switch (uimm (aarch64_get_instr (cpu), 22, 21))
10231 case 2: ldxr (cpu); return;
10232 case 0: stxr (cpu); return;
10238 dexLoadOther (sim_cpu *cpu)
10242 /* instr[29,25] = 111_0
10243 instr[24] == 0 ==> dispatch, 1 ==> ldst reg unsigned immediate
10244 instr[21:11,10] is the secondary dispatch. */
10245 if (uimm (aarch64_get_instr (cpu), 24, 24))
10247 dexLoadUnsignedImmediate (cpu);
10251 dispatch = ( (uimm (aarch64_get_instr (cpu), 21, 21) << 2)
10252 | uimm (aarch64_get_instr (cpu), 11, 10));
10255 case 0: dexLoadUnscaledImmediate (cpu); return;
10256 case 1: dexLoadImmediatePrePost (cpu); return;
10257 case 3: dexLoadImmediatePrePost (cpu); return;
10258 case 6: dexLoadRegisterOffset (cpu); return;
10270 store_pair_u32 (sim_cpu *cpu, int32_t offset, WriteBack wb)
10272 unsigned rn = uimm (aarch64_get_instr (cpu), 14, 10);
10273 unsigned rd = uimm (aarch64_get_instr (cpu), 9, 5);
10274 unsigned rm = uimm (aarch64_get_instr (cpu), 4, 0);
10275 uint64_t address = aarch64_get_reg_u64 (cpu, rd, SP_OK);
10277 if ((rn == rd || rm == rd) && wb != NoWriteBack)
10278 HALT_UNALLOC; /* ??? */
10285 aarch64_set_mem_u32 (cpu, address,
10286 aarch64_get_reg_u32 (cpu, rm, NO_SP));
10287 aarch64_set_mem_u32 (cpu, address + 4,
10288 aarch64_get_reg_u32 (cpu, rn, NO_SP));
10293 if (wb != NoWriteBack)
10294 aarch64_set_reg_u64 (cpu, rd, SP_OK, address);
10298 store_pair_u64 (sim_cpu *cpu, int32_t offset, WriteBack wb)
10300 unsigned rn = uimm (aarch64_get_instr (cpu), 14, 10);
10301 unsigned rd = uimm (aarch64_get_instr (cpu), 9, 5);
10302 unsigned rm = uimm (aarch64_get_instr (cpu), 4, 0);
10303 uint64_t address = aarch64_get_reg_u64 (cpu, rd, SP_OK);
10305 if ((rn == rd || rm == rd) && wb != NoWriteBack)
10306 HALT_UNALLOC; /* ??? */
10313 aarch64_set_mem_u64 (cpu, address,
10314 aarch64_get_reg_u64 (cpu, rm, SP_OK));
10315 aarch64_set_mem_u64 (cpu, address + 8,
10316 aarch64_get_reg_u64 (cpu, rn, SP_OK));
10321 if (wb != NoWriteBack)
10322 aarch64_set_reg_u64 (cpu, rd, SP_OK, address);
10326 load_pair_u32 (sim_cpu *cpu, int32_t offset, WriteBack wb)
10328 unsigned rn = uimm (aarch64_get_instr (cpu), 14, 10);
10329 unsigned rd = uimm (aarch64_get_instr (cpu), 9, 5);
10330 unsigned rm = uimm (aarch64_get_instr (cpu), 4, 0);
10331 uint64_t address = aarch64_get_reg_u64 (cpu, rd, SP_OK);
10333 /* treat this as unalloc to make sure we don't do it. */
10342 aarch64_set_reg_u64 (cpu, rm, SP_OK, aarch64_get_mem_u32 (cpu, address));
10343 aarch64_set_reg_u64 (cpu, rn, SP_OK, aarch64_get_mem_u32 (cpu, address + 4));
10348 if (wb != NoWriteBack)
10349 aarch64_set_reg_u64 (cpu, rd, SP_OK, address);
10353 load_pair_s32 (sim_cpu *cpu, int32_t offset, WriteBack wb)
10355 unsigned rn = uimm (aarch64_get_instr (cpu), 14, 10);
10356 unsigned rd = uimm (aarch64_get_instr (cpu), 9, 5);
10357 unsigned rm = uimm (aarch64_get_instr (cpu), 4, 0);
10358 uint64_t address = aarch64_get_reg_u64 (cpu, rd, SP_OK);
10360 /* Treat this as unalloc to make sure we don't do it. */
10369 aarch64_set_reg_s64 (cpu, rm, SP_OK, aarch64_get_mem_s32 (cpu, address));
10370 aarch64_set_reg_s64 (cpu, rn, SP_OK, aarch64_get_mem_s32 (cpu, address + 4));
10375 if (wb != NoWriteBack)
10376 aarch64_set_reg_u64 (cpu, rd, SP_OK, address);
10380 load_pair_u64 (sim_cpu *cpu, int32_t offset, WriteBack wb)
10382 unsigned rn = uimm (aarch64_get_instr (cpu), 14, 10);
10383 unsigned rd = uimm (aarch64_get_instr (cpu), 9, 5);
10384 unsigned rm = uimm (aarch64_get_instr (cpu), 4, 0);
10385 uint64_t address = aarch64_get_reg_u64 (cpu, rd, SP_OK);
10387 /* Treat this as unalloc to make sure we don't do it. */
10396 aarch64_set_reg_u64 (cpu, rm, SP_OK, aarch64_get_mem_u64 (cpu, address));
10397 aarch64_set_reg_u64 (cpu, rn, SP_OK, aarch64_get_mem_u64 (cpu, address + 8));
10402 if (wb != NoWriteBack)
10403 aarch64_set_reg_u64 (cpu, rd, SP_OK, address);
10407 dex_load_store_pair_gr (sim_cpu *cpu)
10409 /* instr[31,30] = size (10=> 64-bit, 01=> signed 32-bit, 00=> 32-bit)
10410 instr[29,25] = instruction encoding: 101_0
10411 instr[26] = V : 1 if fp 0 if gp
10412 instr[24,23] = addressing mode (10=> offset, 01=> post, 11=> pre)
10413 instr[22] = load/store (1=> load)
10414 instr[21,15] = signed, scaled, offset
10417 instr[ 4, 0] = Rm. */
10419 uint32_t dispatch = ((uimm (aarch64_get_instr (cpu), 31, 30) << 3)
10420 | uimm (aarch64_get_instr (cpu), 24, 22));
10421 int32_t offset = simm32 (aarch64_get_instr (cpu), 21, 15);
10425 case 2: store_pair_u32 (cpu, offset, Post); return;
10426 case 3: load_pair_u32 (cpu, offset, Post); return;
10427 case 4: store_pair_u32 (cpu, offset, NoWriteBack); return;
10428 case 5: load_pair_u32 (cpu, offset, NoWriteBack); return;
10429 case 6: store_pair_u32 (cpu, offset, Pre); return;
10430 case 7: load_pair_u32 (cpu, offset, Pre); return;
10432 case 11: load_pair_s32 (cpu, offset, Post); return;
10433 case 13: load_pair_s32 (cpu, offset, NoWriteBack); return;
10434 case 15: load_pair_s32 (cpu, offset, Pre); return;
10436 case 18: store_pair_u64 (cpu, offset, Post); return;
10437 case 19: load_pair_u64 (cpu, offset, Post); return;
10438 case 20: store_pair_u64 (cpu, offset, NoWriteBack); return;
10439 case 21: load_pair_u64 (cpu, offset, NoWriteBack); return;
10440 case 22: store_pair_u64 (cpu, offset, Pre); return;
10441 case 23: load_pair_u64 (cpu, offset, Pre); return;
10449 store_pair_float (sim_cpu *cpu, int32_t offset, WriteBack wb)
10451 unsigned rn = uimm (aarch64_get_instr (cpu), 14, 10);
10452 unsigned rd = uimm (aarch64_get_instr (cpu), 9, 5);
10453 unsigned rm = uimm (aarch64_get_instr (cpu), 4, 0);
10454 uint64_t address = aarch64_get_reg_u64 (cpu, rd, SP_OK);
10461 aarch64_set_mem_u32 (cpu, address, aarch64_get_vec_u32 (cpu, rm, 0));
10462 aarch64_set_mem_u32 (cpu, address + 4, aarch64_get_vec_u32 (cpu, rn, 0));
10467 if (wb != NoWriteBack)
10468 aarch64_set_reg_u64 (cpu, rd, SP_OK, address);
10472 store_pair_double (sim_cpu *cpu, int32_t offset, WriteBack wb)
10474 unsigned rn = uimm (aarch64_get_instr (cpu), 14, 10);
10475 unsigned rd = uimm (aarch64_get_instr (cpu), 9, 5);
10476 unsigned rm = uimm (aarch64_get_instr (cpu), 4, 0);
10477 uint64_t address = aarch64_get_reg_u64 (cpu, rd, SP_OK);
10484 aarch64_set_mem_u64 (cpu, address, aarch64_get_vec_u64 (cpu, rm, 0));
10485 aarch64_set_mem_u64 (cpu, address + 8, aarch64_get_vec_u64 (cpu, rn, 0));
10490 if (wb != NoWriteBack)
10491 aarch64_set_reg_u64 (cpu, rd, SP_OK, address);
10495 store_pair_long_double (sim_cpu *cpu, int32_t offset, WriteBack wb)
10498 unsigned rn = uimm (aarch64_get_instr (cpu), 14, 10);
10499 unsigned rd = uimm (aarch64_get_instr (cpu), 9, 5);
10500 unsigned rm = uimm (aarch64_get_instr (cpu), 4, 0);
10501 uint64_t address = aarch64_get_reg_u64 (cpu, rd, SP_OK);
10508 aarch64_get_FP_long_double (cpu, rm, & a);
10509 aarch64_set_mem_long_double (cpu, address, a);
10510 aarch64_get_FP_long_double (cpu, rn, & a);
10511 aarch64_set_mem_long_double (cpu, address + 16, a);
10516 if (wb != NoWriteBack)
10517 aarch64_set_reg_u64 (cpu, rd, SP_OK, address);
10521 load_pair_float (sim_cpu *cpu, int32_t offset, WriteBack wb)
10523 unsigned rn = uimm (aarch64_get_instr (cpu), 14, 10);
10524 unsigned rd = uimm (aarch64_get_instr (cpu), 9, 5);
10525 unsigned rm = uimm (aarch64_get_instr (cpu), 4, 0);
10526 uint64_t address = aarch64_get_reg_u64 (cpu, rd, SP_OK);
10536 aarch64_set_vec_u32 (cpu, rm, 0, aarch64_get_mem_u32 (cpu, address));
10537 aarch64_set_vec_u32 (cpu, rn, 0, aarch64_get_mem_u32 (cpu, address + 4));
10542 if (wb != NoWriteBack)
10543 aarch64_set_reg_u64 (cpu, rd, SP_OK, address);
10547 load_pair_double (sim_cpu *cpu, int32_t offset, WriteBack wb)
10549 unsigned rn = uimm (aarch64_get_instr (cpu), 14, 10);
10550 unsigned rd = uimm (aarch64_get_instr (cpu), 9, 5);
10551 unsigned rm = uimm (aarch64_get_instr (cpu), 4, 0);
10552 uint64_t address = aarch64_get_reg_u64 (cpu, rd, SP_OK);
10562 aarch64_set_vec_u64 (cpu, rm, 0, aarch64_get_mem_u64 (cpu, address));
10563 aarch64_set_vec_u64 (cpu, rn, 0, aarch64_get_mem_u64 (cpu, address + 8));
10568 if (wb != NoWriteBack)
10569 aarch64_set_reg_u64 (cpu, rd, SP_OK, address);
10573 load_pair_long_double (sim_cpu *cpu, int32_t offset, WriteBack wb)
10576 unsigned rn = uimm (aarch64_get_instr (cpu), 14, 10);
10577 unsigned rd = uimm (aarch64_get_instr (cpu), 9, 5);
10578 unsigned rm = uimm (aarch64_get_instr (cpu), 4, 0);
10579 uint64_t address = aarch64_get_reg_u64 (cpu, rd, SP_OK);
10589 aarch64_get_mem_long_double (cpu, address, & a);
10590 aarch64_set_FP_long_double (cpu, rm, a);
10591 aarch64_get_mem_long_double (cpu, address + 16, & a);
10592 aarch64_set_FP_long_double (cpu, rn, a);
10597 if (wb != NoWriteBack)
10598 aarch64_set_reg_u64 (cpu, rd, SP_OK, address);
10602 dex_load_store_pair_fp (sim_cpu *cpu)
10604 /* instr[31,30] = size (10=> 128-bit, 01=> 64-bit, 00=> 32-bit)
10605 instr[29,25] = instruction encoding
10606 instr[24,23] = addressing mode (10=> offset, 01=> post, 11=> pre)
10607 instr[22] = load/store (1=> load)
10608 instr[21,15] = signed, scaled, offset
10611 instr[ 4, 0] = Rm */
10613 uint32_t dispatch = ((uimm (aarch64_get_instr (cpu), 31, 30) << 3)
10614 | uimm (aarch64_get_instr (cpu), 24, 22));
10615 int32_t offset = simm32 (aarch64_get_instr (cpu), 21, 15);
10619 case 2: store_pair_float (cpu, offset, Post); return;
10620 case 3: load_pair_float (cpu, offset, Post); return;
10621 case 4: store_pair_float (cpu, offset, NoWriteBack); return;
10622 case 5: load_pair_float (cpu, offset, NoWriteBack); return;
10623 case 6: store_pair_float (cpu, offset, Pre); return;
10624 case 7: load_pair_float (cpu, offset, Pre); return;
10626 case 10: store_pair_double (cpu, offset, Post); return;
10627 case 11: load_pair_double (cpu, offset, Post); return;
10628 case 12: store_pair_double (cpu, offset, NoWriteBack); return;
10629 case 13: load_pair_double (cpu, offset, NoWriteBack); return;
10630 case 14: store_pair_double (cpu, offset, Pre); return;
10631 case 15: load_pair_double (cpu, offset, Pre); return;
10633 case 18: store_pair_long_double (cpu, offset, Post); return;
10634 case 19: load_pair_long_double (cpu, offset, Post); return;
10635 case 20: store_pair_long_double (cpu, offset, NoWriteBack); return;
10636 case 21: load_pair_long_double (cpu, offset, NoWriteBack); return;
10637 case 22: store_pair_long_double (cpu, offset, Pre); return;
10638 case 23: load_pair_long_double (cpu, offset, Pre); return;
10645 static inline unsigned
10646 vec_reg (unsigned v, unsigned o)
10648 return (v + o) & 0x3F;
10651 /* Load multiple N-element structures to N consecutive registers. */
10653 vec_load (sim_cpu *cpu, uint64_t address, unsigned N)
10655 int all = uimm (aarch64_get_instr (cpu), 30, 30);
10656 unsigned size = uimm (aarch64_get_instr (cpu), 11, 10);
10657 unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
10662 case 0: /* 8-bit operations. */
10664 for (i = 0; i < (16 * N); i++)
10665 aarch64_set_vec_u8 (cpu, vec_reg (vd, i >> 4), i & 15,
10666 aarch64_get_mem_u8 (cpu, address + i));
10668 for (i = 0; i < (8 * N); i++)
10669 aarch64_set_vec_u8 (cpu, vec_reg (vd, i >> 3), i & 7,
10670 aarch64_get_mem_u8 (cpu, address + i));
10673 case 1: /* 16-bit operations. */
10675 for (i = 0; i < (8 * N); i++)
10676 aarch64_set_vec_u16 (cpu, vec_reg (vd, i >> 3), i & 7,
10677 aarch64_get_mem_u16 (cpu, address + i * 2));
10679 for (i = 0; i < (4 * N); i++)
10680 aarch64_set_vec_u16 (cpu, vec_reg (vd, i >> 2), i & 3,
10681 aarch64_get_mem_u16 (cpu, address + i * 2));
10684 case 2: /* 32-bit operations. */
10686 for (i = 0; i < (4 * N); i++)
10687 aarch64_set_vec_u32 (cpu, vec_reg (vd, i >> 2), i & 3,
10688 aarch64_get_mem_u32 (cpu, address + i * 4));
10690 for (i = 0; i < (2 * N); i++)
10691 aarch64_set_vec_u32 (cpu, vec_reg (vd, i >> 1), i & 1,
10692 aarch64_get_mem_u32 (cpu, address + i * 4));
10695 case 3: /* 64-bit operations. */
10697 for (i = 0; i < (2 * N); i++)
10698 aarch64_set_vec_u64 (cpu, vec_reg (vd, i >> 1), i & 1,
10699 aarch64_get_mem_u64 (cpu, address + i * 8));
10701 for (i = 0; i < N; i++)
10702 aarch64_set_vec_u64 (cpu, vec_reg (vd, i), 0,
10703 aarch64_get_mem_u64 (cpu, address + i * 8));
10708 /* LD4: load multiple 4-element to four consecutive registers. */
10710 LD4 (sim_cpu *cpu, uint64_t address)
10712 vec_load (cpu, address, 4);
10715 /* LD3: load multiple 3-element structures to three consecutive registers. */
10717 LD3 (sim_cpu *cpu, uint64_t address)
10719 vec_load (cpu, address, 3);
10722 /* LD2: load multiple 2-element structures to two consecutive registers. */
10724 LD2 (sim_cpu *cpu, uint64_t address)
10726 vec_load (cpu, address, 2);
10729 /* Load multiple 1-element structures into one register. */
10731 LD1_1 (sim_cpu *cpu, uint64_t address)
10733 int all = uimm (aarch64_get_instr (cpu), 30, 30);
10734 unsigned size = uimm (aarch64_get_instr (cpu), 11, 10);
10735 unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
10741 /* LD1 {Vd.16b}, addr, #16 */
10742 /* LD1 {Vd.8b}, addr, #8 */
10743 for (i = 0; i < (all ? 16 : 8); i++)
10744 aarch64_set_vec_u8 (cpu, vd, i,
10745 aarch64_get_mem_u8 (cpu, address + i));
10749 /* LD1 {Vd.8h}, addr, #16 */
10750 /* LD1 {Vd.4h}, addr, #8 */
10751 for (i = 0; i < (all ? 8 : 4); i++)
10752 aarch64_set_vec_u16 (cpu, vd, i,
10753 aarch64_get_mem_u16 (cpu, address + i * 2));
10757 /* LD1 {Vd.4s}, addr, #16 */
10758 /* LD1 {Vd.2s}, addr, #8 */
10759 for (i = 0; i < (all ? 4 : 2); i++)
10760 aarch64_set_vec_u32 (cpu, vd, i,
10761 aarch64_get_mem_u32 (cpu, address + i * 4));
10765 /* LD1 {Vd.2d}, addr, #16 */
10766 /* LD1 {Vd.1d}, addr, #8 */
10767 for (i = 0; i < (all ? 2 : 1); i++)
10768 aarch64_set_vec_u64 (cpu, vd, i,
10769 aarch64_get_mem_u64 (cpu, address + i * 8));
10774 /* Load multiple 1-element structures into two registers. */
10776 LD1_2 (sim_cpu *cpu, uint64_t address)
10778 /* FIXME: This algorithm is *exactly* the same as the LD2 version.
10779 So why have two different instructions ? There must be something
10780 wrong somewhere. */
10781 vec_load (cpu, address, 2);
10784 /* Load multiple 1-element structures into three registers. */
10786 LD1_3 (sim_cpu *cpu, uint64_t address)
10788 /* FIXME: This algorithm is *exactly* the same as the LD3 version.
10789 So why have two different instructions ? There must be something
10790 wrong somewhere. */
10791 vec_load (cpu, address, 3);
10794 /* Load multiple 1-element structures into four registers. */
10796 LD1_4 (sim_cpu *cpu, uint64_t address)
10798 /* FIXME: This algorithm is *exactly* the same as the LD4 version.
10799 So why have two different instructions ? There must be something
10800 wrong somewhere. */
10801 vec_load (cpu, address, 4);
10804 /* Store multiple N-element structures to N consecutive registers. */
10806 vec_store (sim_cpu *cpu, uint64_t address, unsigned N)
10808 int all = uimm (aarch64_get_instr (cpu), 30, 30);
10809 unsigned size = uimm (aarch64_get_instr (cpu), 11, 10);
10810 unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
10815 case 0: /* 8-bit operations. */
10817 for (i = 0; i < (16 * N); i++)
10820 aarch64_get_vec_u8 (cpu, vec_reg (vd, i >> 4), i & 15));
10822 for (i = 0; i < (8 * N); i++)
10825 aarch64_get_vec_u8 (cpu, vec_reg (vd, i >> 3), i & 7));
10828 case 1: /* 16-bit operations. */
10830 for (i = 0; i < (8 * N); i++)
10831 aarch64_set_mem_u16
10832 (cpu, address + i * 2,
10833 aarch64_get_vec_u16 (cpu, vec_reg (vd, i >> 3), i & 7));
10835 for (i = 0; i < (4 * N); i++)
10836 aarch64_set_mem_u16
10837 (cpu, address + i * 2,
10838 aarch64_get_vec_u16 (cpu, vec_reg (vd, i >> 2), i & 3));
10841 case 2: /* 32-bit operations. */
10843 for (i = 0; i < (4 * N); i++)
10844 aarch64_set_mem_u32
10845 (cpu, address + i * 4,
10846 aarch64_get_vec_u32 (cpu, vec_reg (vd, i >> 2), i & 3));
10848 for (i = 0; i < (2 * N); i++)
10849 aarch64_set_mem_u32
10850 (cpu, address + i * 4,
10851 aarch64_get_vec_u32 (cpu, vec_reg (vd, i >> 1), i & 1));
10854 case 3: /* 64-bit operations. */
10856 for (i = 0; i < (2 * N); i++)
10857 aarch64_set_mem_u64
10858 (cpu, address + i * 8,
10859 aarch64_get_vec_u64 (cpu, vec_reg (vd, i >> 1), i & 1));
10861 for (i = 0; i < N; i++)
10862 aarch64_set_mem_u64
10863 (cpu, address + i * 8,
10864 aarch64_get_vec_u64 (cpu, vec_reg (vd, i), 0));
10869 /* Store multiple 4-element structure to four consecutive registers. */
10871 ST4 (sim_cpu *cpu, uint64_t address)
10873 vec_store (cpu, address, 4);
10876 /* Store multiple 3-element structures to three consecutive registers. */
10878 ST3 (sim_cpu *cpu, uint64_t address)
10880 vec_store (cpu, address, 3);
10883 /* Store multiple 2-element structures to two consecutive registers. */
10885 ST2 (sim_cpu *cpu, uint64_t address)
10887 vec_store (cpu, address, 2);
10890 /* Store multiple 1-element structures into one register. */
10892 ST1_1 (sim_cpu *cpu, uint64_t address)
10894 int all = uimm (aarch64_get_instr (cpu), 30, 30);
10895 unsigned size = uimm (aarch64_get_instr (cpu), 11, 10);
10896 unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
10902 for (i = 0; i < (all ? 16 : 8); i++)
10903 aarch64_set_mem_u8 (cpu, address + i,
10904 aarch64_get_vec_u8 (cpu, vd, i));
10908 for (i = 0; i < (all ? 8 : 4); i++)
10909 aarch64_set_mem_u16 (cpu, address + i * 2,
10910 aarch64_get_vec_u16 (cpu, vd, i));
10914 for (i = 0; i < (all ? 4 : 2); i++)
10915 aarch64_set_mem_u32 (cpu, address + i * 4,
10916 aarch64_get_vec_u32 (cpu, vd, i));
10920 for (i = 0; i < (all ? 2 : 1); i++)
10921 aarch64_set_mem_u64 (cpu, address + i * 8,
10922 aarch64_get_vec_u64 (cpu, vd, i));
10927 /* Store multiple 1-element structures into two registers. */
10929 ST1_2 (sim_cpu *cpu, uint64_t address)
10931 /* FIXME: This algorithm is *exactly* the same as the ST2 version.
10932 So why have two different instructions ? There must be
10933 something wrong somewhere. */
10934 vec_store (cpu, address, 2);
10937 /* Store multiple 1-element structures into three registers. */
10939 ST1_3 (sim_cpu *cpu, uint64_t address)
10941 /* FIXME: This algorithm is *exactly* the same as the ST3 version.
10942 So why have two different instructions ? There must be
10943 something wrong somewhere. */
10944 vec_store (cpu, address, 3);
10947 /* Store multiple 1-element structures into four registers. */
10949 ST1_4 (sim_cpu *cpu, uint64_t address)
10951 /* FIXME: This algorithm is *exactly* the same as the ST4 version.
10952 So why have two different instructions ? There must be
10953 something wrong somewhere. */
10954 vec_store (cpu, address, 4);
10958 do_vec_LDnR (sim_cpu *cpu, uint64_t address)
10961 instr[30] = element selector 0=>half, 1=>all elements
10962 instr[29,24] = 00 1101
10963 instr[23] = 0=>simple, 1=>post
10965 instr[21] = width: LD1R-or-LD3R (0) / LD2R-or-LD4R (1)
10966 instr[20,16] = 0 0000 (simple), Vinc (reg-post-inc, no SP),
10967 11111 (immediate post inc)
10969 instr[13] = width: LD1R-or-LD2R (0) / LD3R-or-LD4R (1)
10971 instr[11,10] = element size 00=> byte(b), 01=> half(h),
10972 10=> word(s), 11=> double(d)
10973 instr[9,5] = address
10976 unsigned full = uimm (aarch64_get_instr (cpu), 30, 30);
10977 unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
10978 unsigned size = uimm (aarch64_get_instr (cpu), 11, 10);
10981 NYI_assert (29, 24, 0x0D);
10982 NYI_assert (22, 22, 1);
10983 NYI_assert (15, 14, 3);
10984 NYI_assert (12, 12, 0);
10986 switch ((uimm (aarch64_get_instr (cpu), 13, 13) << 1)
10987 | uimm (aarch64_get_instr (cpu), 21, 21))
10989 case 0: /* LD1R. */
10994 uint8_t val = aarch64_get_mem_u8 (cpu, address);
10995 for (i = 0; i < (full ? 16 : 8); i++)
10996 aarch64_set_vec_u8 (cpu, vd, i, val);
11002 uint16_t val = aarch64_get_mem_u16 (cpu, address);
11003 for (i = 0; i < (full ? 8 : 4); i++)
11004 aarch64_set_vec_u16 (cpu, vd, i, val);
11010 uint32_t val = aarch64_get_mem_u32 (cpu, address);
11011 for (i = 0; i < (full ? 4 : 2); i++)
11012 aarch64_set_vec_u32 (cpu, vd, i, val);
11018 uint64_t val = aarch64_get_mem_u64 (cpu, address);
11019 for (i = 0; i < (full ? 2 : 1); i++)
11020 aarch64_set_vec_u64 (cpu, vd, i, val);
11029 case 1: /* LD2R. */
11034 uint8_t val1 = aarch64_get_mem_u8 (cpu, address);
11035 uint8_t val2 = aarch64_get_mem_u8 (cpu, address + 1);
11037 for (i = 0; i < (full ? 16 : 8); i++)
11039 aarch64_set_vec_u8 (cpu, vd, 0, val1);
11040 aarch64_set_vec_u8 (cpu, vd + 1, 0, val2);
11047 uint16_t val1 = aarch64_get_mem_u16 (cpu, address);
11048 uint16_t val2 = aarch64_get_mem_u16 (cpu, address + 2);
11050 for (i = 0; i < (full ? 8 : 4); i++)
11052 aarch64_set_vec_u16 (cpu, vd, 0, val1);
11053 aarch64_set_vec_u16 (cpu, vd + 1, 0, val2);
11060 uint32_t val1 = aarch64_get_mem_u32 (cpu, address);
11061 uint32_t val2 = aarch64_get_mem_u32 (cpu, address + 4);
11063 for (i = 0; i < (full ? 4 : 2); i++)
11065 aarch64_set_vec_u32 (cpu, vd, 0, val1);
11066 aarch64_set_vec_u32 (cpu, vd + 1, 0, val2);
11073 uint64_t val1 = aarch64_get_mem_u64 (cpu, address);
11074 uint64_t val2 = aarch64_get_mem_u64 (cpu, address + 8);
11076 for (i = 0; i < (full ? 2 : 1); i++)
11078 aarch64_set_vec_u64 (cpu, vd, 0, val1);
11079 aarch64_set_vec_u64 (cpu, vd + 1, 0, val2);
11089 case 2: /* LD3R. */
11094 uint8_t val1 = aarch64_get_mem_u8 (cpu, address);
11095 uint8_t val2 = aarch64_get_mem_u8 (cpu, address + 1);
11096 uint8_t val3 = aarch64_get_mem_u8 (cpu, address + 2);
11098 for (i = 0; i < (full ? 16 : 8); i++)
11100 aarch64_set_vec_u8 (cpu, vd, 0, val1);
11101 aarch64_set_vec_u8 (cpu, vd + 1, 0, val2);
11102 aarch64_set_vec_u8 (cpu, vd + 2, 0, val3);
11109 uint32_t val1 = aarch64_get_mem_u16 (cpu, address);
11110 uint32_t val2 = aarch64_get_mem_u16 (cpu, address + 2);
11111 uint32_t val3 = aarch64_get_mem_u16 (cpu, address + 4);
11113 for (i = 0; i < (full ? 8 : 4); i++)
11115 aarch64_set_vec_u16 (cpu, vd, 0, val1);
11116 aarch64_set_vec_u16 (cpu, vd + 1, 0, val2);
11117 aarch64_set_vec_u16 (cpu, vd + 2, 0, val3);
11124 uint32_t val1 = aarch64_get_mem_u32 (cpu, address);
11125 uint32_t val2 = aarch64_get_mem_u32 (cpu, address + 4);
11126 uint32_t val3 = aarch64_get_mem_u32 (cpu, address + 8);
11128 for (i = 0; i < (full ? 4 : 2); i++)
11130 aarch64_set_vec_u32 (cpu, vd, 0, val1);
11131 aarch64_set_vec_u32 (cpu, vd + 1, 0, val2);
11132 aarch64_set_vec_u32 (cpu, vd + 2, 0, val3);
11139 uint64_t val1 = aarch64_get_mem_u64 (cpu, address);
11140 uint64_t val2 = aarch64_get_mem_u64 (cpu, address + 8);
11141 uint64_t val3 = aarch64_get_mem_u64 (cpu, address + 16);
11143 for (i = 0; i < (full ? 2 : 1); i++)
11145 aarch64_set_vec_u64 (cpu, vd, 0, val1);
11146 aarch64_set_vec_u64 (cpu, vd + 1, 0, val2);
11147 aarch64_set_vec_u64 (cpu, vd + 2, 0, val3);
11157 case 3: /* LD4R. */
11162 uint8_t val1 = aarch64_get_mem_u8 (cpu, address);
11163 uint8_t val2 = aarch64_get_mem_u8 (cpu, address + 1);
11164 uint8_t val3 = aarch64_get_mem_u8 (cpu, address + 2);
11165 uint8_t val4 = aarch64_get_mem_u8 (cpu, address + 3);
11167 for (i = 0; i < (full ? 16 : 8); i++)
11169 aarch64_set_vec_u8 (cpu, vd, 0, val1);
11170 aarch64_set_vec_u8 (cpu, vd + 1, 0, val2);
11171 aarch64_set_vec_u8 (cpu, vd + 2, 0, val3);
11172 aarch64_set_vec_u8 (cpu, vd + 3, 0, val4);
11179 uint32_t val1 = aarch64_get_mem_u16 (cpu, address);
11180 uint32_t val2 = aarch64_get_mem_u16 (cpu, address + 2);
11181 uint32_t val3 = aarch64_get_mem_u16 (cpu, address + 4);
11182 uint32_t val4 = aarch64_get_mem_u16 (cpu, address + 6);
11184 for (i = 0; i < (full ? 8 : 4); i++)
11186 aarch64_set_vec_u16 (cpu, vd, 0, val1);
11187 aarch64_set_vec_u16 (cpu, vd + 1, 0, val2);
11188 aarch64_set_vec_u16 (cpu, vd + 2, 0, val3);
11189 aarch64_set_vec_u16 (cpu, vd + 3, 0, val4);
11196 uint32_t val1 = aarch64_get_mem_u32 (cpu, address);
11197 uint32_t val2 = aarch64_get_mem_u32 (cpu, address + 4);
11198 uint32_t val3 = aarch64_get_mem_u32 (cpu, address + 8);
11199 uint32_t val4 = aarch64_get_mem_u32 (cpu, address + 12);
11201 for (i = 0; i < (full ? 4 : 2); i++)
11203 aarch64_set_vec_u32 (cpu, vd, 0, val1);
11204 aarch64_set_vec_u32 (cpu, vd + 1, 0, val2);
11205 aarch64_set_vec_u32 (cpu, vd + 2, 0, val3);
11206 aarch64_set_vec_u32 (cpu, vd + 3, 0, val4);
11213 uint64_t val1 = aarch64_get_mem_u64 (cpu, address);
11214 uint64_t val2 = aarch64_get_mem_u64 (cpu, address + 8);
11215 uint64_t val3 = aarch64_get_mem_u64 (cpu, address + 16);
11216 uint64_t val4 = aarch64_get_mem_u64 (cpu, address + 24);
11218 for (i = 0; i < (full ? 2 : 1); i++)
11220 aarch64_set_vec_u64 (cpu, vd, 0, val1);
11221 aarch64_set_vec_u64 (cpu, vd + 1, 0, val2);
11222 aarch64_set_vec_u64 (cpu, vd + 2, 0, val3);
11223 aarch64_set_vec_u64 (cpu, vd + 3, 0, val4);
11239 do_vec_load_store (sim_cpu *cpu)
11241 /* {LD|ST}<N> {Vd..Vd+N}, vaddr
11244 instr[30] = element selector 0=>half, 1=>all elements
11245 instr[29,25] = 00110
11247 instr[23] = 0=>simple, 1=>post
11248 instr[22] = 0=>store, 1=>load
11249 instr[21] = 0 (LDn) / small(0)-large(1) selector (LDnR)
11250 instr[20,16] = 00000 (simple), Vinc (reg-post-inc, no SP),
11251 11111 (immediate post inc)
11252 instr[15,12] = elements and destinations. eg for load:
11253 0000=>LD4 => load multiple 4-element to
11254 four consecutive registers
11255 0100=>LD3 => load multiple 3-element to
11256 three consecutive registers
11257 1000=>LD2 => load multiple 2-element to
11258 two consecutive registers
11259 0010=>LD1 => load multiple 1-element to
11260 four consecutive registers
11261 0110=>LD1 => load multiple 1-element to
11262 three consecutive registers
11263 1010=>LD1 => load multiple 1-element to
11264 two consecutive registers
11265 0111=>LD1 => load multiple 1-element to
11269 instr[11,10] = element size 00=> byte(b), 01=> half(h),
11270 10=> word(s), 11=> double(d)
11271 instr[9,5] = Vn, can be SP
11280 if (uimm (aarch64_get_instr (cpu), 31, 31) != 0
11281 || uimm (aarch64_get_instr (cpu), 29, 25) != 0x06)
11284 type = uimm (aarch64_get_instr (cpu), 15, 12);
11285 if (type != 0xE && type != 0xE && uimm (aarch64_get_instr (cpu), 21, 21) != 0)
11288 post = uimm (aarch64_get_instr (cpu), 23, 23);
11289 load = uimm (aarch64_get_instr (cpu), 22, 22);
11290 vn = uimm (aarch64_get_instr (cpu), 9, 5);
11291 address = aarch64_get_reg_u64 (cpu, vn, SP_OK);
11295 unsigned vm = uimm (aarch64_get_instr (cpu), 20, 16);
11299 unsigned sizeof_operation;
11303 case 0: sizeof_operation = 32; break;
11304 case 4: sizeof_operation = 24; break;
11305 case 8: sizeof_operation = 16; break;
11308 sizeof_operation = uimm (aarch64_get_instr (cpu), 21, 21) ? 2 : 1;
11309 sizeof_operation <<= uimm (aarch64_get_instr (cpu), 11, 10);
11313 sizeof_operation = uimm (aarch64_get_instr (cpu), 21, 21) ? 8 : 4;
11314 sizeof_operation <<= uimm (aarch64_get_instr (cpu), 11, 10);
11318 /* One register, immediate offset variant. */
11319 sizeof_operation = 8;
11323 /* Two registers, immediate offset variant. */
11324 sizeof_operation = 16;
11328 /* Three registers, immediate offset variant. */
11329 sizeof_operation = 24;
11333 /* Four registers, immediate offset variant. */
11334 sizeof_operation = 32;
11341 if (uimm (aarch64_get_instr (cpu), 30, 30))
11342 sizeof_operation *= 2;
11344 aarch64_set_reg_u64 (cpu, vn, SP_OK, address + sizeof_operation);
11347 aarch64_set_reg_u64 (cpu, vn, SP_OK,
11348 address + aarch64_get_reg_u64 (cpu, vm, NO_SP));
11352 NYI_assert (20, 16, 0);
11359 case 0: LD4 (cpu, address); return;
11360 case 4: LD3 (cpu, address); return;
11361 case 8: LD2 (cpu, address); return;
11362 case 2: LD1_4 (cpu, address); return;
11363 case 6: LD1_3 (cpu, address); return;
11364 case 10: LD1_2 (cpu, address); return;
11365 case 7: LD1_1 (cpu, address); return;
11368 case 0xC: do_vec_LDnR (cpu, address); return;
11378 case 0: ST4 (cpu, address); return;
11379 case 4: ST3 (cpu, address); return;
11380 case 8: ST2 (cpu, address); return;
11381 case 2: ST1_4 (cpu, address); return;
11382 case 6: ST1_3 (cpu, address); return;
11383 case 10: ST1_2 (cpu, address); return;
11384 case 7: ST1_1 (cpu, address); return;
11391 dexLdSt (sim_cpu *cpu)
11393 /* uint32_t group = dispatchGroup (aarch64_get_instr (cpu));
11394 assert group == GROUP_LDST_0100 || group == GROUP_LDST_0110 ||
11395 group == GROUP_LDST_1100 || group == GROUP_LDST_1110
11396 bits [29,28:26] of a LS are the secondary dispatch vector. */
11397 uint32_t group2 = dispatchLS (aarch64_get_instr (cpu));
11402 dexLoadExclusive (cpu); return;
11406 dexLoadLiteral (cpu); return;
11410 dexLoadOther (cpu); return;
11412 case LS_ADVSIMD_001:
11413 do_vec_load_store (cpu); return;
11416 dex_load_store_pair_gr (cpu); return;
11419 dex_load_store_pair_fp (cpu); return;
11422 /* Should never reach here. */
11427 /* Specific decode and execute for group Data Processing Register. */
11430 dexLogicalShiftedRegister (sim_cpu *cpu)
11432 /* assert instr[28:24] = 01010
11433 instr[31] = size : 0 ==> 32 bit, 1 ==> 64 bit
11434 instr[30,29:21] = op,N : 000 ==> AND, 001 ==> BIC,
11435 010 ==> ORR, 011 ==> ORN
11436 100 ==> EOR, 101 ==> EON,
11437 110 ==> ANDS, 111 ==> BICS
11438 instr[23,22] = shift : 0 ==> LSL, 1 ==> LSR, 2 ==> ASR, 3 ==> ROR
11439 instr[15,10] = count : must be 0xxxxx for 32 bit
11443 /* unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16); */
11446 uint32_t size = uimm (aarch64_get_instr (cpu), 31, 31);
11448 /* 32 bit operations must have count[5] = 0. */
11449 /* or else we have an UNALLOC. */
11450 uint32_t count = uimm (aarch64_get_instr (cpu), 15, 10);
11452 if (!size && uimm (count, 5, 5))
11455 shiftType = shift (aarch64_get_instr (cpu), 22);
11457 /* dispatch on size:op:N i.e aarch64_get_instr (cpu)[31,29:21]. */
11458 dispatch = ( (uimm (aarch64_get_instr (cpu), 31, 29) << 1)
11459 | uimm (aarch64_get_instr (cpu), 21, 21));
11463 case 0: and32_shift (cpu, shiftType, count); return;
11464 case 1: bic32_shift (cpu, shiftType, count); return;
11465 case 2: orr32_shift (cpu, shiftType, count); return;
11466 case 3: orn32_shift (cpu, shiftType, count); return;
11467 case 4: eor32_shift (cpu, shiftType, count); return;
11468 case 5: eon32_shift (cpu, shiftType, count); return;
11469 case 6: ands32_shift (cpu, shiftType, count); return;
11470 case 7: bics32_shift (cpu, shiftType, count); return;
11471 case 8: and64_shift (cpu, shiftType, count); return;
11472 case 9: bic64_shift (cpu, shiftType, count); return;
11473 case 10:orr64_shift (cpu, shiftType, count); return;
11474 case 11:orn64_shift (cpu, shiftType, count); return;
11475 case 12:eor64_shift (cpu, shiftType, count); return;
11476 case 13:eon64_shift (cpu, shiftType, count); return;
11477 case 14:ands64_shift (cpu, shiftType, count); return;
11478 case 15:bics64_shift (cpu, shiftType, count); return;
11479 default: HALT_UNALLOC;
11483 /* 32 bit conditional select. */
11485 csel32 (sim_cpu *cpu, CondCode cc)
11487 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
11488 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
11489 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
11491 aarch64_set_reg_u64 (cpu, rd, NO_SP,
11492 testConditionCode (cpu, cc)
11493 ? aarch64_get_reg_u32 (cpu, rn, NO_SP)
11494 : aarch64_get_reg_u32 (cpu, rm, NO_SP));
11497 /* 64 bit conditional select. */
11499 csel64 (sim_cpu *cpu, CondCode cc)
11501 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
11502 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
11503 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
11505 aarch64_set_reg_u64 (cpu, rd, NO_SP,
11506 testConditionCode (cpu, cc)
11507 ? aarch64_get_reg_u64 (cpu, rn, NO_SP)
11508 : aarch64_get_reg_u64 (cpu, rm, NO_SP));
11511 /* 32 bit conditional increment. */
11513 csinc32 (sim_cpu *cpu, CondCode cc)
11515 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
11516 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
11517 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
11519 aarch64_set_reg_u64 (cpu, rd, NO_SP,
11520 testConditionCode (cpu, cc)
11521 ? aarch64_get_reg_u32 (cpu, rn, NO_SP)
11522 : aarch64_get_reg_u32 (cpu, rm, NO_SP) + 1);
11525 /* 64 bit conditional increment. */
11527 csinc64 (sim_cpu *cpu, CondCode cc)
11529 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
11530 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
11531 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
11533 aarch64_set_reg_u64 (cpu, rd, NO_SP,
11534 testConditionCode (cpu, cc)
11535 ? aarch64_get_reg_u64 (cpu, rn, NO_SP)
11536 : aarch64_get_reg_u64 (cpu, rm, NO_SP) + 1);
11539 /* 32 bit conditional invert. */
11541 csinv32 (sim_cpu *cpu, CondCode cc)
11543 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
11544 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
11545 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
11547 aarch64_set_reg_u64 (cpu, rd, NO_SP,
11548 testConditionCode (cpu, cc)
11549 ? aarch64_get_reg_u32 (cpu, rn, NO_SP)
11550 : ~ aarch64_get_reg_u32 (cpu, rm, NO_SP));
11553 /* 64 bit conditional invert. */
11555 csinv64 (sim_cpu *cpu, CondCode cc)
11557 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
11558 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
11559 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
11561 aarch64_set_reg_u64 (cpu, rd, NO_SP,
11562 testConditionCode (cpu, cc)
11563 ? aarch64_get_reg_u64 (cpu, rn, NO_SP)
11564 : ~ aarch64_get_reg_u64 (cpu, rm, NO_SP));
11567 /* 32 bit conditional negate. */
11569 csneg32 (sim_cpu *cpu, CondCode cc)
11571 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
11572 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
11573 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
11575 aarch64_set_reg_u64 (cpu, rd, NO_SP,
11576 testConditionCode (cpu, cc)
11577 ? aarch64_get_reg_u32 (cpu, rn, NO_SP)
11578 : - aarch64_get_reg_u32 (cpu, rm, NO_SP));
11581 /* 64 bit conditional negate. */
11583 csneg64 (sim_cpu *cpu, CondCode cc)
11585 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
11586 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
11587 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
11589 aarch64_set_reg_u64 (cpu, rd, NO_SP,
11590 testConditionCode (cpu, cc)
11591 ? aarch64_get_reg_u64 (cpu, rn, NO_SP)
11592 : - aarch64_get_reg_u64 (cpu, rm, NO_SP));
11596 dexCondSelect (sim_cpu *cpu)
11598 /* assert instr[28,21] = 11011011
11599 instr[31] = size : 0 ==> 32 bit, 1 ==> 64 bit
11600 instr[30:11,10] = op : 000 ==> CSEL, 001 ==> CSINC,
11601 100 ==> CSINV, 101 ==> CSNEG,
11603 instr[29] = S : 0 ==> ok, 1 ==> UNALLOC
11604 instr[15,12] = cond
11605 instr[29] = S : 0 ==> ok, 1 ==> UNALLOC */
11609 uint32_t S = uimm (aarch64_get_instr (cpu), 29, 29);
11610 uint32_t op2 = uimm (aarch64_get_instr (cpu), 11, 10);
11618 cc = condcode (aarch64_get_instr (cpu), 12);
11619 dispatch = ((uimm (aarch64_get_instr (cpu), 31, 30) << 1) | op2);
11623 case 0: csel32 (cpu, cc); return;
11624 case 1: csinc32 (cpu, cc); return;
11625 case 2: csinv32 (cpu, cc); return;
11626 case 3: csneg32 (cpu, cc); return;
11627 case 4: csel64 (cpu, cc); return;
11628 case 5: csinc64 (cpu, cc); return;
11629 case 6: csinv64 (cpu, cc); return;
11630 case 7: csneg64 (cpu, cc); return;
11631 default: HALT_UNALLOC;
11635 /* Some helpers for counting leading 1 or 0 bits. */
11637 /* Counts the number of leading bits which are the same
11638 in a 32 bit value in the range 1 to 32. */
11640 leading32 (uint32_t value)
11642 int32_t mask= 0xffff0000;
11643 uint32_t count= 16; /* Counts number of bits set in mask. */
11644 uint32_t lo = 1; /* Lower bound for number of sign bits. */
11645 uint32_t hi = 32; /* Upper bound for number of sign bits. */
11647 while (lo + 1 < hi)
11649 int32_t test = (value & mask);
11651 if (test == 0 || test == mask)
11654 count = (lo + hi) / 2;
11655 mask >>= (count - lo);
11660 count = (lo + hi) / 2;
11661 mask <<= hi - count;
11670 test = (value & mask);
11672 if (test == 0 || test == mask)
11681 /* Counts the number of leading bits which are the same
11682 in a 64 bit value in the range 1 to 64. */
11684 leading64 (uint64_t value)
11686 int64_t mask= 0xffffffff00000000LL;
11687 uint64_t count = 32; /* Counts number of bits set in mask. */
11688 uint64_t lo = 1; /* Lower bound for number of sign bits. */
11689 uint64_t hi = 64; /* Upper bound for number of sign bits. */
11691 while (lo + 1 < hi)
11693 int64_t test = (value & mask);
11695 if (test == 0 || test == mask)
11698 count = (lo + hi) / 2;
11699 mask >>= (count - lo);
11704 count = (lo + hi) / 2;
11705 mask <<= hi - count;
11714 test = (value & mask);
11716 if (test == 0 || test == mask)
11725 /* Bit operations. */
11726 /* N.B register args may not be SP. */
11728 /* 32 bit count leading sign bits. */
11730 cls32 (sim_cpu *cpu)
11732 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
11733 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
11735 /* N.B. the result needs to exclude the leading bit. */
11736 aarch64_set_reg_u64
11737 (cpu, rd, NO_SP, leading32 (aarch64_get_reg_u32 (cpu, rn, NO_SP)) - 1);
11740 /* 64 bit count leading sign bits. */
11742 cls64 (sim_cpu *cpu)
11744 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
11745 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
11747 /* N.B. the result needs to exclude the leading bit. */
11748 aarch64_set_reg_u64
11749 (cpu, rd, NO_SP, leading64 (aarch64_get_reg_u64 (cpu, rn, NO_SP)) - 1);
11752 /* 32 bit count leading zero bits. */
11754 clz32 (sim_cpu *cpu)
11756 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
11757 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
11758 uint32_t value = aarch64_get_reg_u32 (cpu, rn, NO_SP);
11760 /* if the sign (top) bit is set then the count is 0. */
11761 if (pick32 (value, 31, 31))
11762 aarch64_set_reg_u64 (cpu, rd, NO_SP, 0L);
11764 aarch64_set_reg_u64 (cpu, rd, NO_SP, leading32 (value));
11767 /* 64 bit count leading zero bits. */
11769 clz64 (sim_cpu *cpu)
11771 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
11772 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
11773 uint64_t value = aarch64_get_reg_u64 (cpu, rn, NO_SP);
11775 /* if the sign (top) bit is set then the count is 0. */
11776 if (pick64 (value, 63, 63))
11777 aarch64_set_reg_u64 (cpu, rd, NO_SP, 0L);
11779 aarch64_set_reg_u64 (cpu, rd, NO_SP, leading64 (value));
11782 /* 32 bit reverse bits. */
11784 rbit32 (sim_cpu *cpu)
11786 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
11787 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
11788 uint32_t value = aarch64_get_reg_u32 (cpu, rn, NO_SP);
11789 uint32_t result = 0;
11792 for (i = 0; i < 32; i++)
11795 result |= (value & 1);
11798 aarch64_set_reg_u64 (cpu, rd, NO_SP, result);
11801 /* 64 bit reverse bits. */
11803 rbit64 (sim_cpu *cpu)
11805 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
11806 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
11807 uint64_t value = aarch64_get_reg_u64 (cpu, rn, NO_SP);
11808 uint64_t result = 0;
11811 for (i = 0; i < 64; i++)
11814 result |= (value & 1UL);
11817 aarch64_set_reg_u64 (cpu, rd, NO_SP, result);
11820 /* 32 bit reverse bytes. */
11822 rev32 (sim_cpu *cpu)
11824 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
11825 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
11826 uint32_t value = aarch64_get_reg_u32 (cpu, rn, NO_SP);
11827 uint32_t result = 0;
11830 for (i = 0; i < 4; i++)
11833 result |= (value & 0xff);
11836 aarch64_set_reg_u64 (cpu, rd, NO_SP, result);
11839 /* 64 bit reverse bytes. */
11841 rev64 (sim_cpu *cpu)
11843 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
11844 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
11845 uint64_t value = aarch64_get_reg_u64 (cpu, rn, NO_SP);
11846 uint64_t result = 0;
11849 for (i = 0; i < 8; i++)
11852 result |= (value & 0xffULL);
11855 aarch64_set_reg_u64 (cpu, rd, NO_SP, result);
11858 /* 32 bit reverse shorts. */
11859 /* N.B.this reverses the order of the bytes in each half word. */
11861 revh32 (sim_cpu *cpu)
11863 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
11864 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
11865 uint32_t value = aarch64_get_reg_u32 (cpu, rn, NO_SP);
11866 uint32_t result = 0;
11869 for (i = 0; i < 2; i++)
11872 result |= (value & 0x00ff00ff);
11875 aarch64_set_reg_u64 (cpu, rd, NO_SP, result);
11878 /* 64 bit reverse shorts. */
11879 /* N.B.this reverses the order of the bytes in each half word. */
11881 revh64 (sim_cpu *cpu)
11883 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
11884 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
11885 uint64_t value = aarch64_get_reg_u64 (cpu, rn, NO_SP);
11886 uint64_t result = 0;
11889 for (i = 0; i < 2; i++)
11892 result |= (value & 0x00ff00ff00ff00ffULL);
11895 aarch64_set_reg_u64 (cpu, rd, NO_SP, result);
11899 dexDataProc1Source (sim_cpu *cpu)
11901 /* assert instr[30] == 1
11902 aarch64_get_instr (cpu)[28,21] == 111010110
11903 instr[31] = size : 0 ==> 32 bit, 1 ==> 64 bit
11904 instr[29] = S : 0 ==> ok, 1 ==> UNALLOC
11905 instr[20,16] = opcode2 : 00000 ==> ok, ow ==> UNALLOC
11906 instr[15,10] = opcode : 000000 ==> RBIT, 000001 ==> REV16,
11907 000010 ==> REV, 000011 ==> UNALLOC
11908 000100 ==> CLZ, 000101 ==> CLS
11910 instr[9,5] = rn : may not be SP
11911 instr[4,0] = rd : may not be SP. */
11913 uint32_t S = uimm (aarch64_get_instr (cpu), 29, 29);
11914 uint32_t opcode2 = uimm (aarch64_get_instr (cpu), 20, 16);
11915 uint32_t opcode = uimm (aarch64_get_instr (cpu), 15, 10);
11916 uint32_t dispatch = ((uimm (aarch64_get_instr (cpu), 31, 31) << 3) | opcode);
11929 case 0: rbit32 (cpu); return;
11930 case 1: revh32 (cpu); return;
11931 case 2: rev32 (cpu); return;
11932 case 4: clz32 (cpu); return;
11933 case 5: cls32 (cpu); return;
11934 case 8: rbit64 (cpu); return;
11935 case 9: revh64 (cpu); return;
11936 case 10:rev32 (cpu); return;
11937 case 11:rev64 (cpu); return;
11938 case 12:clz64 (cpu); return;
11939 case 13:cls64 (cpu); return;
11940 default: HALT_UNALLOC;
11945 Shifts by count supplied in register.
11946 N.B register args may not be SP.
11947 These all use the shifted auxiliary function for
11948 simplicity and clarity. Writing the actual shift
11949 inline would avoid a branch and so be faster but
11950 would also necessitate getting signs right. */
11952 /* 32 bit arithmetic shift right. */
11954 asrv32 (sim_cpu *cpu)
11956 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
11957 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
11958 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
11960 aarch64_set_reg_u64
11962 shifted32 (aarch64_get_reg_u32 (cpu, rn, NO_SP), ASR,
11963 (aarch64_get_reg_u32 (cpu, rm, NO_SP) & 0x1f)));
11966 /* 64 bit arithmetic shift right. */
11968 asrv64 (sim_cpu *cpu)
11970 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
11971 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
11972 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
11974 aarch64_set_reg_u64
11976 shifted64 (aarch64_get_reg_u64 (cpu, rn, NO_SP), ASR,
11977 (aarch64_get_reg_u64 (cpu, rm, NO_SP) & 0x3f)));
11980 /* 32 bit logical shift left. */
11982 lslv32 (sim_cpu *cpu)
11984 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
11985 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
11986 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
11988 aarch64_set_reg_u64
11990 shifted32 (aarch64_get_reg_u32 (cpu, rn, NO_SP), LSL,
11991 (aarch64_get_reg_u32 (cpu, rm, NO_SP) & 0x1f)));
11994 /* 64 bit arithmetic shift left. */
11996 lslv64 (sim_cpu *cpu)
11998 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
11999 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
12000 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
12002 aarch64_set_reg_u64
12004 shifted64 (aarch64_get_reg_u64 (cpu, rn, NO_SP), LSL,
12005 (aarch64_get_reg_u64 (cpu, rm, NO_SP) & 0x3f)));
12008 /* 32 bit logical shift right. */
12010 lsrv32 (sim_cpu *cpu)
12012 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
12013 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
12014 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
12016 aarch64_set_reg_u64
12018 shifted32 (aarch64_get_reg_u32 (cpu, rn, NO_SP), LSR,
12019 (aarch64_get_reg_u32 (cpu, rm, NO_SP) & 0x1f)));
12022 /* 64 bit logical shift right. */
12024 lsrv64 (sim_cpu *cpu)
12026 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
12027 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
12028 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
12030 aarch64_set_reg_u64
12032 shifted64 (aarch64_get_reg_u64 (cpu, rn, NO_SP), LSR,
12033 (aarch64_get_reg_u64 (cpu, rm, NO_SP) & 0x3f)));
12036 /* 32 bit rotate right. */
12038 rorv32 (sim_cpu *cpu)
12040 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
12041 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
12042 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
12044 aarch64_set_reg_u64
12046 shifted32 (aarch64_get_reg_u32 (cpu, rn, NO_SP), ROR,
12047 (aarch64_get_reg_u32 (cpu, rm, NO_SP) & 0x1f)));
12050 /* 64 bit rotate right. */
12052 rorv64 (sim_cpu *cpu)
12054 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
12055 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
12056 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
12058 aarch64_set_reg_u64
12060 shifted64 (aarch64_get_reg_u64 (cpu, rn, NO_SP), ROR,
12061 (aarch64_get_reg_u64 (cpu, rm, NO_SP) & 0x3f)));
12067 /* 32 bit signed divide. */
12069 cpuiv32 (sim_cpu *cpu)
12071 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
12072 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
12073 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
12074 /* N.B. the pseudo-code does the divide using 64 bit data. */
12075 /* TODO : check that this rounds towards zero as required. */
12076 int64_t dividend = aarch64_get_reg_s32 (cpu, rn, NO_SP);
12077 int64_t divisor = aarch64_get_reg_s32 (cpu, rm, NO_SP);
12079 aarch64_set_reg_s64 (cpu, rd, NO_SP,
12080 divisor ? ((int32_t) (dividend / divisor)) : 0);
12083 /* 64 bit signed divide. */
12085 cpuiv64 (sim_cpu *cpu)
12087 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
12088 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
12089 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
12091 /* TODO : check that this rounds towards zero as required. */
12092 int64_t divisor = aarch64_get_reg_s64 (cpu, rm, NO_SP);
12094 aarch64_set_reg_s64
12096 divisor ? (aarch64_get_reg_s64 (cpu, rn, NO_SP) / divisor) : 0);
12099 /* 32 bit unsigned divide. */
12101 udiv32 (sim_cpu *cpu)
12103 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
12104 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
12105 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
12107 /* N.B. the pseudo-code does the divide using 64 bit data. */
12108 uint64_t dividend = aarch64_get_reg_u32 (cpu, rn, NO_SP);
12109 uint64_t divisor = aarch64_get_reg_u32 (cpu, rm, NO_SP);
12111 aarch64_set_reg_u64 (cpu, rd, NO_SP,
12112 divisor ? (uint32_t) (dividend / divisor) : 0);
12115 /* 64 bit unsigned divide. */
12117 udiv64 (sim_cpu *cpu)
12119 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
12120 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
12121 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
12123 /* TODO : check that this rounds towards zero as required. */
12124 uint64_t divisor = aarch64_get_reg_u64 (cpu, rm, NO_SP);
12126 aarch64_set_reg_u64
12128 divisor ? (aarch64_get_reg_u64 (cpu, rn, NO_SP) / divisor) : 0);
12132 dexDataProc2Source (sim_cpu *cpu)
12134 /* assert instr[30] == 0
12135 instr[28,21] == 11010110
12136 instr[31] = size : 0 ==> 32 bit, 1 ==> 64 bit
12137 instr[29] = S : 0 ==> ok, 1 ==> UNALLOC
12138 instr[15,10] = opcode : 000010 ==> UDIV, 000011 ==> CPUIV,
12139 001000 ==> LSLV, 001001 ==> LSRV
12140 001010 ==> ASRV, 001011 ==> RORV
12144 uint32_t S = uimm (aarch64_get_instr (cpu), 29, 29);
12145 uint32_t opcode = uimm (aarch64_get_instr (cpu), 15, 10);
12153 dispatch = ( (uimm (aarch64_get_instr (cpu), 31, 31) << 3)
12154 | (uimm (opcode, 3, 3) << 2)
12155 | uimm (opcode, 1, 0));
12158 case 2: udiv32 (cpu); return;
12159 case 3: cpuiv32 (cpu); return;
12160 case 4: lslv32 (cpu); return;
12161 case 5: lsrv32 (cpu); return;
12162 case 6: asrv32 (cpu); return;
12163 case 7: rorv32 (cpu); return;
12164 case 10: udiv64 (cpu); return;
12165 case 11: cpuiv64 (cpu); return;
12166 case 12: lslv64 (cpu); return;
12167 case 13: lsrv64 (cpu); return;
12168 case 14: asrv64 (cpu); return;
12169 case 15: rorv64 (cpu); return;
12170 default: HALT_UNALLOC;
12177 /* 32 bit multiply and add. */
12179 madd32 (sim_cpu *cpu)
12181 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
12182 unsigned ra = uimm (aarch64_get_instr (cpu), 14, 10);
12183 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
12184 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
12186 aarch64_set_reg_u64 (cpu, rd, NO_SP,
12187 aarch64_get_reg_u32 (cpu, ra, NO_SP)
12188 + aarch64_get_reg_u32 (cpu, rn, NO_SP)
12189 * aarch64_get_reg_u32 (cpu, rm, NO_SP));
12192 /* 64 bit multiply and add. */
12194 madd64 (sim_cpu *cpu)
12196 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
12197 unsigned ra = uimm (aarch64_get_instr (cpu), 14, 10);
12198 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
12199 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
12201 aarch64_set_reg_u64 (cpu, rd, NO_SP,
12202 aarch64_get_reg_u64 (cpu, ra, NO_SP)
12203 + aarch64_get_reg_u64 (cpu, rn, NO_SP)
12204 * aarch64_get_reg_u64 (cpu, rm, NO_SP));
12207 /* 32 bit multiply and sub. */
12209 msub32 (sim_cpu *cpu)
12211 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
12212 unsigned ra = uimm (aarch64_get_instr (cpu), 14, 10);
12213 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
12214 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
12216 aarch64_set_reg_u64 (cpu, rd, NO_SP,
12217 aarch64_get_reg_u32 (cpu, ra, NO_SP)
12218 - aarch64_get_reg_u32 (cpu, rn, NO_SP)
12219 * aarch64_get_reg_u32 (cpu, rm, NO_SP));
12222 /* 64 bit multiply and sub. */
12224 msub64 (sim_cpu *cpu)
12226 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
12227 unsigned ra = uimm (aarch64_get_instr (cpu), 14, 10);
12228 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
12229 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
12231 aarch64_set_reg_u64 (cpu, rd, NO_SP,
12232 aarch64_get_reg_u64 (cpu, ra, NO_SP)
12233 - aarch64_get_reg_u64 (cpu, rn, NO_SP)
12234 * aarch64_get_reg_u64 (cpu, rm, NO_SP));
12237 /* Signed multiply add long -- source, source2 : 32 bit, source3 : 64 bit. */
12239 smaddl (sim_cpu *cpu)
12241 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
12242 unsigned ra = uimm (aarch64_get_instr (cpu), 14, 10);
12243 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
12244 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
12246 /* N.B. we need to multiply the signed 32 bit values in rn, rm to
12247 obtain a 64 bit product. */
12248 aarch64_set_reg_s64
12250 aarch64_get_reg_s64 (cpu, ra, NO_SP)
12251 + ((int64_t) aarch64_get_reg_s32 (cpu, rn, NO_SP))
12252 * ((int64_t) aarch64_get_reg_s32 (cpu, rm, NO_SP)));
12255 /* Signed multiply sub long -- source, source2 : 32 bit, source3 : 64 bit. */
12257 smsubl (sim_cpu *cpu)
12259 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
12260 unsigned ra = uimm (aarch64_get_instr (cpu), 14, 10);
12261 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
12262 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
12264 /* N.B. we need to multiply the signed 32 bit values in rn, rm to
12265 obtain a 64 bit product. */
12266 aarch64_set_reg_s64
12268 aarch64_get_reg_s64 (cpu, ra, NO_SP)
12269 - ((int64_t) aarch64_get_reg_s32 (cpu, rn, NO_SP))
12270 * ((int64_t) aarch64_get_reg_s32 (cpu, rm, NO_SP)));
12273 /* Integer Multiply/Divide. */
12275 /* First some macros and a helper function. */
12276 /* Macros to test or access elements of 64 bit words. */
12278 /* Mask used to access lo 32 bits of 64 bit unsigned int. */
12279 #define LOW_WORD_MASK ((1ULL << 32) - 1)
12280 /* Return the lo 32 bit word of a 64 bit unsigned int as a 64 bit unsigned int. */
12281 #define lowWordToU64(_value_u64) ((_value_u64) & LOW_WORD_MASK)
12282 /* Return the hi 32 bit word of a 64 bit unsigned int as a 64 bit unsigned int. */
12283 #define highWordToU64(_value_u64) ((_value_u64) >> 32)
12285 /* Offset of sign bit in 64 bit signed integger. */
12286 #define SIGN_SHIFT_U64 63
12287 /* The sign bit itself -- also identifies the minimum negative int value. */
12288 #define SIGN_BIT_U64 (1UL << SIGN_SHIFT_U64)
12289 /* Return true if a 64 bit signed int presented as an unsigned int is the
12290 most negative value. */
12291 #define isMinimumU64(_value_u64) ((_value_u64) == SIGN_BIT_U64)
12292 /* Return true (non-zero) if a 64 bit signed int presented as an unsigned
12293 int has its sign bit set to false. */
12294 #define isSignSetU64(_value_u64) ((_value_u64) & SIGN_BIT_U64)
12295 /* Return 1L or -1L according to whether a 64 bit signed int presented as
12296 an unsigned int has its sign bit set or not. */
12297 #define signOfU64(_value_u64) (1L + (((value_u64) >> SIGN_SHIFT_U64) * -2L)
12298 /* Clear the sign bit of a 64 bit signed int presented as an unsigned int. */
12299 #define clearSignU64(_value_u64) ((_value_u64) &= ~SIGN_BIT_U64)
12301 /* Multiply two 64 bit ints and return.
12302 the hi 64 bits of the 128 bit product. */
12305 mul64hi (uint64_t value1, uint64_t value2)
12307 uint64_t resultmid1;
12309 uint64_t value1_lo = lowWordToU64 (value1);
12310 uint64_t value1_hi = highWordToU64 (value1) ;
12311 uint64_t value2_lo = lowWordToU64 (value2);
12312 uint64_t value2_hi = highWordToU64 (value2);
12314 /* Cross-multiply and collect results. */
12316 uint64_t xproductlo = value1_lo * value2_lo;
12317 uint64_t xproductmid1 = value1_lo * value2_hi;
12318 uint64_t xproductmid2 = value1_hi * value2_lo;
12319 uint64_t xproducthi = value1_hi * value2_hi;
12320 uint64_t carry = 0;
12321 /* Start accumulating 64 bit results. */
12322 /* Drop bottom half of lowest cross-product. */
12323 uint64_t resultmid = xproductlo >> 32;
12324 /* Add in middle products. */
12325 resultmid = resultmid + xproductmid1;
12327 /* Check for overflow. */
12328 if (resultmid < xproductmid1)
12329 /* Carry over 1 into top cross-product. */
12332 resultmid1 = resultmid + xproductmid2;
12334 /* Check for overflow. */
12335 if (resultmid1 < xproductmid2)
12336 /* Carry over 1 into top cross-product. */
12339 /* Drop lowest 32 bits of middle cross-product. */
12340 result = resultmid1 >> 32;
12342 /* Add top cross-product plus and any carry. */
12343 result += xproducthi + carry;
12348 /* Signed multiply high, source, source2 :
12349 64 bit, dest <-- high 64-bit of result. */
12351 smulh (sim_cpu *cpu)
12355 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
12356 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
12357 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
12358 GReg ra = greg (aarch64_get_instr (cpu), 10);
12359 int64_t value1 = aarch64_get_reg_u64 (cpu, rn, NO_SP);
12360 int64_t value2 = aarch64_get_reg_u64 (cpu, rm, NO_SP);
12363 int64_t signum = 1;
12368 /* Convert to unsigned and use the unsigned mul64hi routine
12369 the fix the sign up afterwards. */
12390 uresult = mul64hi (uvalue1, uvalue2);
12394 aarch64_set_reg_s64 (cpu, rd, NO_SP, result);
12397 /* Unsigned multiply add long -- source, source2 :
12398 32 bit, source3 : 64 bit. */
12400 umaddl (sim_cpu *cpu)
12402 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
12403 unsigned ra = uimm (aarch64_get_instr (cpu), 14, 10);
12404 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
12405 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
12407 /* N.B. we need to multiply the signed 32 bit values in rn, rm to
12408 obtain a 64 bit product. */
12409 aarch64_set_reg_u64
12411 aarch64_get_reg_u64 (cpu, ra, NO_SP)
12412 + ((uint64_t) aarch64_get_reg_u32 (cpu, rn, NO_SP))
12413 * ((uint64_t) aarch64_get_reg_u32 (cpu, rm, NO_SP)));
12416 /* Unsigned multiply sub long -- source, source2 : 32 bit, source3 : 64 bit. */
12418 umsubl (sim_cpu *cpu)
12420 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
12421 unsigned ra = uimm (aarch64_get_instr (cpu), 14, 10);
12422 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
12423 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
12425 /* N.B. we need to multiply the signed 32 bit values in rn, rm to
12426 obtain a 64 bit product. */
12427 aarch64_set_reg_u64
12429 aarch64_get_reg_u64 (cpu, ra, NO_SP)
12430 - ((uint64_t) aarch64_get_reg_u32 (cpu, rn, NO_SP))
12431 * ((uint64_t) aarch64_get_reg_u32 (cpu, rm, NO_SP)));
12434 /* Unsigned multiply high, source, source2 :
12435 64 bit, dest <-- high 64-bit of result. */
12437 umulh (sim_cpu *cpu)
12439 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
12440 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
12441 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
12442 GReg ra = greg (aarch64_get_instr (cpu), 10);
12447 aarch64_set_reg_u64 (cpu, rd, NO_SP,
12448 mul64hi (aarch64_get_reg_u64 (cpu, rn, NO_SP),
12449 aarch64_get_reg_u64 (cpu, rm, NO_SP)));
12453 dexDataProc3Source (sim_cpu *cpu)
12455 /* assert instr[28,24] == 11011. */
12456 /* instr[31] = size : 0 ==> 32 bit, 1 ==> 64 bit (for rd at least)
12457 instr[30,29] = op54 : 00 ==> ok, ow ==> UNALLOC
12458 instr[23,21] = op31 : 111 ==> UNALLOC, o2 ==> ok
12459 instr[15] = o0 : 0/1 ==> ok
12460 instr[23,21:15] ==> op : 0000 ==> MADD, 0001 ==> MSUB, (32/64 bit)
12461 0010 ==> SMADDL, 0011 ==> SMSUBL, (64 bit only)
12462 0100 ==> SMULH, (64 bit only)
12463 1010 ==> UMADDL, 1011 ==> UNSUBL, (64 bit only)
12464 1100 ==> UMULH (64 bit only)
12468 uint32_t size = uimm (aarch64_get_instr (cpu), 31, 31);
12469 uint32_t op54 = uimm (aarch64_get_instr (cpu), 30, 29);
12470 uint32_t op31 = uimm (aarch64_get_instr (cpu), 23, 21);
12471 uint32_t o0 = uimm (aarch64_get_instr (cpu), 15, 15);
12488 dispatch = (op31 << 1) | o0;
12492 case 0: madd64 (cpu); return;
12493 case 1: msub64 (cpu); return;
12494 case 2: smaddl (cpu); return;
12495 case 3: smsubl (cpu); return;
12496 case 4: smulh (cpu); return;
12497 case 10: umaddl (cpu); return;
12498 case 11: umsubl (cpu); return;
12499 case 12: umulh (cpu); return;
12500 default: HALT_UNALLOC;
12505 dexDPReg (sim_cpu *cpu)
12507 /* uint32_t group = dispatchGroup (aarch64_get_instr (cpu));
12508 assert group == GROUP_DPREG_0101 || group == GROUP_DPREG_1101
12509 bits [28:24:21] of a DPReg are the secondary dispatch vector. */
12510 uint32_t group2 = dispatchDPReg (aarch64_get_instr (cpu));
12514 case DPREG_LOG_000:
12515 case DPREG_LOG_001:
12516 dexLogicalShiftedRegister (cpu); return;
12518 case DPREG_ADDSHF_010:
12519 dexAddSubtractShiftedRegister (cpu); return;
12521 case DPREG_ADDEXT_011:
12522 dexAddSubtractExtendedRegister (cpu); return;
12524 case DPREG_ADDCOND_100:
12526 /* This set bundles a variety of different operations. */
12528 /* 1) add/sub w carry. */
12529 uint32_t mask1 = 0x1FE00000U;
12530 uint32_t val1 = 0x1A000000U;
12531 /* 2) cond compare register/immediate. */
12532 uint32_t mask2 = 0x1FE00000U;
12533 uint32_t val2 = 0x1A400000U;
12534 /* 3) cond select. */
12535 uint32_t mask3 = 0x1FE00000U;
12536 uint32_t val3 = 0x1A800000U;
12537 /* 4) data proc 1/2 source. */
12538 uint32_t mask4 = 0x1FE00000U;
12539 uint32_t val4 = 0x1AC00000U;
12541 if ((aarch64_get_instr (cpu) & mask1) == val1)
12542 dexAddSubtractWithCarry (cpu);
12544 else if ((aarch64_get_instr (cpu) & mask2) == val2)
12547 else if ((aarch64_get_instr (cpu) & mask3) == val3)
12548 dexCondSelect (cpu);
12550 else if ((aarch64_get_instr (cpu) & mask4) == val4)
12552 /* Bit 30 is clear for data proc 2 source
12553 and set for data proc 1 source. */
12554 if (aarch64_get_instr (cpu) & (1U << 30))
12555 dexDataProc1Source (cpu);
12557 dexDataProc2Source (cpu);
12561 /* Should not reach here. */
12567 case DPREG_3SRC_110:
12568 dexDataProc3Source (cpu); return;
12570 case DPREG_UNALLOC_101:
12573 case DPREG_3SRC_111:
12574 dexDataProc3Source (cpu); return;
12577 /* Should never reach here. */
12582 /* Unconditional Branch immediate.
12583 Offset is a PC-relative byte offset in the range +/- 128MiB.
12584 The offset is assumed to be raw from the decode i.e. the
12585 simulator is expected to scale them from word offsets to byte. */
12587 /* Unconditional branch. */
12589 buc (sim_cpu *cpu, int32_t offset)
12591 aarch64_set_next_PC_by_offset (cpu, offset);
12594 static unsigned stack_depth = 0;
12596 /* Unconditional branch and link -- writes return PC to LR. */
12598 bl (sim_cpu *cpu, int32_t offset)
12600 aarch64_save_LR (cpu);
12601 aarch64_set_next_PC_by_offset (cpu, offset);
12603 if (TRACE_BRANCH_P (cpu))
12607 " %*scall %" PRIx64 " [%s]"
12608 " [args: %" PRIx64 " %" PRIx64 " %" PRIx64 "]",
12609 stack_depth, " ", aarch64_get_next_PC (cpu),
12610 aarch64_get_func (aarch64_get_next_PC (cpu)),
12611 aarch64_get_reg_u64 (cpu, 0, NO_SP),
12612 aarch64_get_reg_u64 (cpu, 1, NO_SP),
12613 aarch64_get_reg_u64 (cpu, 2, NO_SP)
12618 /* Unconditional Branch register.
12619 Branch/return address is in source register. */
12621 /* Unconditional branch. */
12625 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
12626 aarch64_set_next_PC (cpu, aarch64_get_reg_u64 (cpu, rn, NO_SP));
12629 /* Unconditional branch and link -- writes return PC to LR. */
12633 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
12635 /* The pseudo code in the spec says we update LR before fetching.
12636 the value from the rn. */
12637 aarch64_save_LR (cpu);
12638 aarch64_set_next_PC (cpu, aarch64_get_reg_u64 (cpu, rn, NO_SP));
12640 if (TRACE_BRANCH_P (cpu))
12644 " %*scall %" PRIx64 " [%s]"
12645 " [args: %" PRIx64 " %" PRIx64 " %" PRIx64 "]",
12646 stack_depth, " ", aarch64_get_next_PC (cpu),
12647 aarch64_get_func (aarch64_get_next_PC (cpu)),
12648 aarch64_get_reg_u64 (cpu, 0, NO_SP),
12649 aarch64_get_reg_u64 (cpu, 1, NO_SP),
12650 aarch64_get_reg_u64 (cpu, 2, NO_SP)
12655 /* Return -- assembler will default source to LR this is functionally
12656 equivalent to br but, presumably, unlike br it side effects the
12657 branch predictor. */
12661 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
12662 aarch64_set_next_PC (cpu, aarch64_get_reg_u64 (cpu, rn, NO_SP));
12664 if (TRACE_BRANCH_P (cpu))
12667 " %*sreturn [result: %" PRIx64 "]",
12668 stack_depth, " ", aarch64_get_reg_u64 (cpu, 0, NO_SP));
12673 /* NOP -- we implement this and call it from the decode in case we
12674 want to intercept it later. */
12681 /* Data synchronization barrier. */
12688 /* Data memory barrier. */
12695 /* Instruction synchronization barrier. */
12703 dexBranchImmediate (sim_cpu *cpu)
12705 /* assert instr[30,26] == 00101
12706 instr[31] ==> 0 == B, 1 == BL
12707 instr[25,0] == imm26 branch offset counted in words. */
12709 uint32_t top = uimm (aarch64_get_instr (cpu), 31, 31);
12710 /* We have a 26 byte signed word offset which we need to pass to the
12711 execute routine as a signed byte offset. */
12712 int32_t offset = simm32 (aarch64_get_instr (cpu), 25, 0) << 2;
12720 /* Control Flow. */
12722 /* Conditional branch
12724 Offset is a PC-relative byte offset in the range +/- 1MiB pos is
12725 a bit position in the range 0 .. 63
12727 cc is a CondCode enum value as pulled out of the decode
12729 N.B. any offset register (source) can only be Xn or Wn. */
12732 bcc (sim_cpu *cpu, int32_t offset, CondCode cc)
12734 /* the test returns TRUE if CC is met. */
12735 if (testConditionCode (cpu, cc))
12736 aarch64_set_next_PC_by_offset (cpu, offset);
12739 /* 32 bit branch on register non-zero. */
12741 cbnz32 (sim_cpu *cpu, int32_t offset)
12743 unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
12745 if (aarch64_get_reg_u32 (cpu, rt, NO_SP) != 0)
12746 aarch64_set_next_PC_by_offset (cpu, offset);
12749 /* 64 bit branch on register zero. */
12751 cbnz (sim_cpu *cpu, int32_t offset)
12753 unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
12755 if (aarch64_get_reg_u64 (cpu, rt, NO_SP) != 0)
12756 aarch64_set_next_PC_by_offset (cpu, offset);
12759 /* 32 bit branch on register non-zero. */
12761 cbz32 (sim_cpu *cpu, int32_t offset)
12763 unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
12765 if (aarch64_get_reg_u32 (cpu, rt, NO_SP) == 0)
12766 aarch64_set_next_PC_by_offset (cpu, offset);
12769 /* 64 bit branch on register zero. */
12771 cbz (sim_cpu *cpu, int32_t offset)
12773 unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
12775 if (aarch64_get_reg_u64 (cpu, rt, NO_SP) == 0)
12776 aarch64_set_next_PC_by_offset (cpu, offset);
12779 /* Branch on register bit test non-zero -- one size fits all. */
12781 tbnz (sim_cpu *cpu, uint32_t pos, int32_t offset)
12783 unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
12785 if (aarch64_get_reg_u64 (cpu, rt, NO_SP) & (1 << pos))
12786 aarch64_set_next_PC_by_offset (cpu, offset);
12789 /* branch on register bit test zero -- one size fits all. */
12791 tbz (sim_cpu *cpu, uint32_t pos, int32_t offset)
12793 unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
12795 if (!(aarch64_get_reg_u64 (cpu, rt, NO_SP) & (1 << pos)))
12796 aarch64_set_next_PC_by_offset (cpu, offset);
12800 dexCompareBranchImmediate (sim_cpu *cpu)
12802 /* instr[30,25] = 01 1010
12803 instr[31] = size : 0 ==> 32, 1 ==> 64
12804 instr[24] = op : 0 ==> CBZ, 1 ==> CBNZ
12805 instr[23,5] = simm19 branch offset counted in words
12808 uint32_t size = uimm (aarch64_get_instr (cpu), 31, 31);
12809 uint32_t op = uimm (aarch64_get_instr (cpu), 24, 24);
12810 int32_t offset = simm32 (aarch64_get_instr (cpu), 23, 5) << 2;
12815 cbz32 (cpu, offset);
12817 cbnz32 (cpu, offset);
12824 cbnz (cpu, offset);
12829 dexTestBranchImmediate (sim_cpu *cpu)
12831 /* instr[31] = b5 : bit 5 of test bit idx
12832 instr[30,25] = 01 1011
12833 instr[24] = op : 0 ==> TBZ, 1 == TBNZ
12834 instr[23,19] = b40 : bits 4 to 0 of test bit idx
12835 instr[18,5] = simm14 : signed offset counted in words
12836 instr[4,0] = uimm5 */
12838 uint32_t pos = ((uimm (aarch64_get_instr (cpu), 31, 31) << 4)
12839 | uimm (aarch64_get_instr (cpu), 23,19));
12840 int32_t offset = simm32 (aarch64_get_instr (cpu), 18, 5) << 2;
12842 NYI_assert (30, 25, 0x1b);
12844 if (uimm (aarch64_get_instr (cpu), 24, 24) == 0)
12845 tbz (cpu, pos, offset);
12847 tbnz (cpu, pos, offset);
12851 dexCondBranchImmediate (sim_cpu *cpu)
12853 /* instr[31,25] = 010 1010
12854 instr[24] = op1; op => 00 ==> B.cond
12855 instr[23,5] = simm19 : signed offset counted in words
12857 instr[3,0] = cond */
12861 uint32_t op = ((uimm (aarch64_get_instr (cpu), 24, 24) << 1)
12862 | uimm (aarch64_get_instr (cpu), 4, 4));
12864 NYI_assert (31, 25, 0x2a);
12869 offset = simm32 (aarch64_get_instr (cpu), 23, 5) << 2;
12870 cc = condcode (aarch64_get_instr (cpu), 0);
12872 bcc (cpu, offset, cc);
12876 dexBranchRegister (sim_cpu *cpu)
12878 /* instr[31,25] = 110 1011
12879 instr[24,21] = op : 0 ==> BR, 1 => BLR, 2 => RET, 3 => ERET, 4 => DRPS
12880 instr[20,16] = op2 : must be 11111
12881 instr[15,10] = op3 : must be 000000
12882 instr[4,0] = op2 : must be 11111. */
12884 uint32_t op = uimm (aarch64_get_instr (cpu), 24, 21);
12885 uint32_t op2 = uimm (aarch64_get_instr (cpu), 20, 16);
12886 uint32_t op3 = uimm (aarch64_get_instr (cpu), 15, 10);
12887 uint32_t op4 = uimm (aarch64_get_instr (cpu), 4, 0);
12889 NYI_assert (31, 25, 0x6b);
12891 if (op2 != 0x1F || op3 != 0 || op4 != 0)
12905 /* ERET and DRPS accept 0b11111 for rn = aarch64_get_instr (cpu)[4,0]. */
12906 /* anything else is unallocated. */
12907 uint32_t rn = greg (aarch64_get_instr (cpu), 0);
12912 if (op == 4 || op == 5)
12919 /* FIXME: We should get the Angel SWI values from ../../libgloss/aarch64/svc.h
12920 but this may not be available. So instead we define the values we need
12922 #define AngelSVC_Reason_Open 0x01
12923 #define AngelSVC_Reason_Close 0x02
12924 #define AngelSVC_Reason_Write 0x05
12925 #define AngelSVC_Reason_Read 0x06
12926 #define AngelSVC_Reason_IsTTY 0x09
12927 #define AngelSVC_Reason_Seek 0x0A
12928 #define AngelSVC_Reason_FLen 0x0C
12929 #define AngelSVC_Reason_Remove 0x0E
12930 #define AngelSVC_Reason_Rename 0x0F
12931 #define AngelSVC_Reason_Clock 0x10
12932 #define AngelSVC_Reason_Time 0x11
12933 #define AngelSVC_Reason_System 0x12
12934 #define AngelSVC_Reason_Errno 0x13
12935 #define AngelSVC_Reason_GetCmdLine 0x15
12936 #define AngelSVC_Reason_HeapInfo 0x16
12937 #define AngelSVC_Reason_ReportException 0x18
12938 #define AngelSVC_Reason_Elapsed 0x30
12942 handle_halt (sim_cpu *cpu, uint32_t val)
12944 uint64_t result = 0;
12948 TRACE_SYSCALL (cpu, " HLT [0x%x]", val);
12949 sim_engine_halt (CPU_STATE (cpu), cpu, NULL, aarch64_get_PC (cpu),
12950 sim_stopped, SIM_SIGTRAP);
12953 /* We have encountered an Angel SVC call. See if we can process it. */
12954 switch (aarch64_get_reg_u32 (cpu, 0, NO_SP))
12956 case AngelSVC_Reason_HeapInfo:
12958 /* Get the values. */
12959 uint64_t stack_top = aarch64_get_stack_start (cpu);
12960 uint64_t heap_base = aarch64_get_heap_start (cpu);
12962 /* Get the pointer */
12963 uint64_t ptr = aarch64_get_reg_u64 (cpu, 1, SP_OK);
12964 ptr = aarch64_get_mem_u64 (cpu, ptr);
12966 /* Fill in the memory block. */
12967 /* Start addr of heap. */
12968 aarch64_set_mem_u64 (cpu, ptr + 0, heap_base);
12969 /* End addr of heap. */
12970 aarch64_set_mem_u64 (cpu, ptr + 8, stack_top);
12971 /* Lowest stack addr. */
12972 aarch64_set_mem_u64 (cpu, ptr + 16, heap_base);
12973 /* Initial stack addr. */
12974 aarch64_set_mem_u64 (cpu, ptr + 24, stack_top);
12976 TRACE_SYSCALL (cpu, " AngelSVC: Get Heap Info");
12980 case AngelSVC_Reason_Open:
12982 /* Get the pointer */
12983 /* uint64_t ptr = aarch64_get_reg_u64 (cpu, 1, SP_OK);. */
12984 /* FIXME: For now we just assume that we will only be asked
12985 to open the standard file descriptors. */
12989 TRACE_SYSCALL (cpu, " AngelSVC: Open file %d", fd - 1);
12993 case AngelSVC_Reason_Close:
12995 uint64_t fh = aarch64_get_reg_u64 (cpu, 1, SP_OK);
12996 TRACE_SYSCALL (cpu, " AngelSVC: Close file %d", (int) fh);
13001 case AngelSVC_Reason_Errno:
13003 TRACE_SYSCALL (cpu, " AngelSVC: Get Errno");
13006 case AngelSVC_Reason_Clock:
13008 #ifdef CLOCKS_PER_SEC
13009 (CLOCKS_PER_SEC >= 100)
13010 ? (clock () / (CLOCKS_PER_SEC / 100))
13011 : ((clock () * 100) / CLOCKS_PER_SEC)
13013 /* Presume unix... clock() returns microseconds. */
13017 TRACE_SYSCALL (cpu, " AngelSVC: Get Clock");
13020 case AngelSVC_Reason_GetCmdLine:
13022 /* Get the pointer */
13023 uint64_t ptr = aarch64_get_reg_u64 (cpu, 1, SP_OK);
13024 ptr = aarch64_get_mem_u64 (cpu, ptr);
13026 /* FIXME: No command line for now. */
13027 aarch64_set_mem_u64 (cpu, ptr, 0);
13028 TRACE_SYSCALL (cpu, " AngelSVC: Get Command Line");
13032 case AngelSVC_Reason_IsTTY:
13034 TRACE_SYSCALL (cpu, " AngelSVC: IsTTY ?");
13037 case AngelSVC_Reason_Write:
13039 /* Get the pointer */
13040 uint64_t ptr = aarch64_get_reg_u64 (cpu, 1, SP_OK);
13041 /* Get the write control block. */
13042 uint64_t fd = aarch64_get_mem_u64 (cpu, ptr);
13043 uint64_t buf = aarch64_get_mem_u64 (cpu, ptr + 8);
13044 uint64_t len = aarch64_get_mem_u64 (cpu, ptr + 16);
13046 TRACE_SYSCALL (cpu, "write of %" PRIx64 " bytes from %"
13047 PRIx64 " on descriptor %" PRIx64,
13052 TRACE_SYSCALL (cpu,
13053 " AngelSVC: Write: Suspiciously long write: %ld",
13055 sim_engine_halt (CPU_STATE (cpu), cpu, NULL, aarch64_get_PC (cpu),
13056 sim_stopped, SIM_SIGBUS);
13060 printf ("%.*s", (int) len, aarch64_get_mem_ptr (cpu, buf));
13064 TRACE (cpu, 0, "\n");
13065 sim_io_eprintf (CPU_STATE (cpu), "%.*s",
13066 (int) len, aarch64_get_mem_ptr (cpu, buf));
13067 TRACE (cpu, 0, "\n");
13071 TRACE_SYSCALL (cpu,
13072 " AngelSVC: Write: Unexpected file handle: %d",
13074 sim_engine_halt (CPU_STATE (cpu), cpu, NULL, aarch64_get_PC (cpu),
13075 sim_stopped, SIM_SIGABRT);
13080 case AngelSVC_Reason_ReportException:
13082 /* Get the pointer */
13083 uint64_t ptr = aarch64_get_reg_u64 (cpu, 1, SP_OK);
13084 /*ptr = aarch64_get_mem_u64 (cpu, ptr);. */
13085 uint64_t type = aarch64_get_mem_u64 (cpu, ptr);
13086 uint64_t state = aarch64_get_mem_u64 (cpu, ptr + 8);
13088 TRACE_SYSCALL (cpu,
13089 "Angel Exception: type 0x%" PRIx64 " state %" PRIx64,
13092 if (type == 0x20026)
13093 sim_engine_halt (CPU_STATE (cpu), cpu, NULL, aarch64_get_PC (cpu),
13094 sim_exited, state);
13096 sim_engine_halt (CPU_STATE (cpu), cpu, NULL, aarch64_get_PC (cpu),
13097 sim_stopped, SIM_SIGINT);
13101 case AngelSVC_Reason_Read:
13102 case AngelSVC_Reason_FLen:
13103 case AngelSVC_Reason_Seek:
13104 case AngelSVC_Reason_Remove:
13105 case AngelSVC_Reason_Time:
13106 case AngelSVC_Reason_System:
13107 case AngelSVC_Reason_Rename:
13108 case AngelSVC_Reason_Elapsed:
13110 TRACE_SYSCALL (cpu, " HLT [Unknown angel %x]",
13111 aarch64_get_reg_u32 (cpu, 0, NO_SP));
13112 sim_engine_halt (CPU_STATE (cpu), cpu, NULL, aarch64_get_PC (cpu),
13113 sim_stopped, SIM_SIGTRAP);
13116 aarch64_set_reg_u64 (cpu, 0, NO_SP, result);
13120 dexExcpnGen (sim_cpu *cpu)
13122 /* instr[31:24] = 11010100
13123 instr[23,21] = opc : 000 ==> GEN EXCPN, 001 ==> BRK
13124 010 ==> HLT, 101 ==> DBG GEN EXCPN
13125 instr[20,5] = imm16
13126 instr[4,2] = opc2 000 ==> OK, ow ==> UNALLOC
13127 instr[1,0] = LL : discriminates opc */
13129 uint32_t opc = uimm (aarch64_get_instr (cpu), 23, 21);
13130 uint32_t imm16 = uimm (aarch64_get_instr (cpu), 20, 5);
13131 uint32_t opc2 = uimm (aarch64_get_instr (cpu), 4, 2);
13134 NYI_assert (31, 24, 0xd4);
13139 LL = uimm (aarch64_get_instr (cpu), 1, 0);
13141 /* We only implement HLT and BRK for now. */
13142 if (opc == 1 && LL == 0)
13144 TRACE_EVENTS (cpu, " BRK [0x%x]", imm16);
13145 sim_engine_halt (CPU_STATE (cpu), cpu, NULL, aarch64_get_PC (cpu),
13146 sim_exited, aarch64_get_reg_s32 (cpu, R0, SP_OK));
13149 if (opc == 2 && LL == 0)
13150 handle_halt (cpu, imm16);
13152 else if (opc == 0 || opc == 5)
13159 /* Stub for accessing system registers. */
13162 system_get (sim_cpu *cpu, unsigned op0, unsigned op1, unsigned crn,
13163 unsigned crm, unsigned op2)
13165 if (crn == 0 && op1 == 3 && crm == 0 && op2 == 7)
13166 /* DCZID_EL0 - the Data Cache Zero ID register.
13167 We do not support DC ZVA at the moment, so
13168 we return a value with the disable bit set.
13169 We implement support for the DCZID register since
13170 it is used by the C library's memset function. */
13171 return ((uint64_t) 1) << 4;
13173 if (crn == 0 && op1 == 3 && crm == 0 && op2 == 1)
13174 /* Cache Type Register. */
13175 return 0x80008000UL;
13177 if (crn == 13 && op1 == 3 && crm == 0 && op2 == 2)
13178 /* TPIDR_EL0 - thread pointer id. */
13179 return aarch64_get_thread_id (cpu);
13181 if (op1 == 3 && crm == 4 && op2 == 0)
13182 return aarch64_get_FPCR (cpu);
13184 if (op1 == 3 && crm == 4 && op2 == 1)
13185 return aarch64_get_FPSR (cpu);
13187 else if (op1 == 3 && crm == 2 && op2 == 0)
13188 return aarch64_get_CPSR (cpu);
13194 system_set (sim_cpu *cpu, unsigned op0, unsigned op1, unsigned crn,
13195 unsigned crm, unsigned op2, uint64_t val)
13197 if (op1 == 3 && crm == 4 && op2 == 0)
13198 aarch64_set_FPCR (cpu, val);
13200 else if (op1 == 3 && crm == 4 && op2 == 1)
13201 aarch64_set_FPSR (cpu, val);
13203 else if (op1 == 3 && crm == 2 && op2 == 0)
13204 aarch64_set_CPSR (cpu, val);
13211 do_mrs (sim_cpu *cpu)
13213 /* instr[31:20] = 1101 0101 0001 1
13220 unsigned sys_op0 = uimm (aarch64_get_instr (cpu), 19, 19) + 2;
13221 unsigned sys_op1 = uimm (aarch64_get_instr (cpu), 18, 16);
13222 unsigned sys_crn = uimm (aarch64_get_instr (cpu), 15, 12);
13223 unsigned sys_crm = uimm (aarch64_get_instr (cpu), 11, 8);
13224 unsigned sys_op2 = uimm (aarch64_get_instr (cpu), 7, 5);
13225 unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
13227 aarch64_set_reg_u64 (cpu, rt, NO_SP,
13228 system_get (cpu, sys_op0, sys_op1, sys_crn, sys_crm, sys_op2));
13232 do_MSR_immediate (sim_cpu *cpu)
13234 /* instr[31:19] = 1101 0101 0000 0
13236 instr[15,12] = 0100
13239 instr[4,0] = 1 1111 */
13241 unsigned op1 = uimm (aarch64_get_instr (cpu), 18, 16);
13242 /*unsigned crm = uimm (aarch64_get_instr (cpu), 11, 8);*/
13243 unsigned op2 = uimm (aarch64_get_instr (cpu), 7, 5);
13245 NYI_assert (31, 19, 0x1AA0);
13246 NYI_assert (15, 12, 0x4);
13247 NYI_assert (4, 0, 0x1F);
13252 HALT_NYI; /* set SPSel. */
13259 HALT_NYI; /* set DAIFset. */
13261 HALT_NYI; /* set DAIFclr. */
13270 do_MSR_reg (sim_cpu *cpu)
13272 /* instr[31:20] = 1101 0101 0001
13280 unsigned sys_op0 = uimm (aarch64_get_instr (cpu), 19, 19) + 2;
13281 unsigned sys_op1 = uimm (aarch64_get_instr (cpu), 18, 16);
13282 unsigned sys_crn = uimm (aarch64_get_instr (cpu), 15, 12);
13283 unsigned sys_crm = uimm (aarch64_get_instr (cpu), 11, 8);
13284 unsigned sys_op2 = uimm (aarch64_get_instr (cpu), 7, 5);
13285 unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
13287 NYI_assert (31, 20, 0xD51);
13289 system_set (cpu, sys_op0, sys_op1, sys_crn, sys_crm, sys_op2,
13290 aarch64_get_reg_u64 (cpu, rt, NO_SP));
13294 do_SYS (sim_cpu * cpu)
13296 /* instr[31,19] = 1101 0101 0000 1
13302 NYI_assert (31, 19, 0x1AA1);
13304 /* FIXME: For now we just silently accept system ops. */
13308 dexSystem (sim_cpu *cpu)
13310 /* instr[31:22] = 1101 01010 0
13317 instr[4,0] = uimm5 */
13319 /* We are interested in HINT, DSB, DMB and ISB
13321 Hint #0 encodes NOOP (this is the only hint we care about)
13322 L == 0, op0 == 0, op1 = 011, CRn = 0010, Rt = 11111,
13323 CRm op2 != 0000 000 OR CRm op2 == 0000 000 || CRm op > 0000 101
13325 DSB, DMB, ISB are data store barrier, data memory barrier and
13326 instruction store barrier, respectively, where
13328 L == 0, op0 == 0, op1 = 011, CRn = 0011, Rt = 11111,
13329 op2 : DSB ==> 100, DMB ==> 101, ISB ==> 110
13330 CRm<3:2> ==> domain, CRm<1:0> ==> types,
13331 domain : 00 ==> OuterShareable, 01 ==> Nonshareable,
13332 10 ==> InerShareable, 11 ==> FullSystem
13333 types : 01 ==> Reads, 10 ==> Writes,
13334 11 ==> All, 00 ==> All (domain == FullSystem). */
13336 unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
13338 NYI_assert (31, 22, 0x354);
13340 switch (INSTR (21, 12))
13345 /* NOP has CRm != 0000 OR. */
13346 /* (CRm == 0000 AND (op2 == 000 OR op2 > 101)). */
13347 uint32_t crm = uimm (aarch64_get_instr (cpu), 11, 8);
13348 uint32_t op2 = uimm (aarch64_get_instr (cpu), 7, 5);
13350 if (crm != 0 || (op2 == 0 || op2 > 5))
13352 /* Actually call nop method so we can reimplement it later. */
13361 uint32_t op2 = uimm (aarch64_get_instr (cpu), 7, 5);
13366 case 4: dsb (cpu); return;
13367 case 5: dmb (cpu); return;
13368 case 6: isb (cpu); return;
13369 default: HALT_UNALLOC;
13380 do_SYS (cpu); /* DC is an alias of SYS. */
13384 if (uimm (aarch64_get_instr (cpu), 21, 20) == 0x1)
13386 else if (INSTR (21, 19) == 0 && INSTR (15, 12) == 0x4)
13387 do_MSR_immediate (cpu);
13395 dexBr (sim_cpu *cpu)
13397 /* uint32_t group = dispatchGroup (aarch64_get_instr (cpu));
13398 assert group == GROUP_BREXSYS_1010 || group == GROUP_BREXSYS_1011
13399 bits [31,29] of a BrExSys are the secondary dispatch vector. */
13400 uint32_t group2 = dispatchBrExSys (aarch64_get_instr (cpu));
13405 return dexBranchImmediate (cpu);
13407 case BR_IMMCMP_001:
13408 /* Compare has bit 25 clear while test has it set. */
13409 if (!uimm (aarch64_get_instr (cpu), 25, 25))
13410 dexCompareBranchImmediate (cpu);
13412 dexTestBranchImmediate (cpu);
13415 case BR_IMMCOND_010:
13416 /* This is a conditional branch if bit 25 is clear otherwise
13418 if (!uimm (aarch64_get_instr (cpu), 25, 25))
13419 dexCondBranchImmediate (cpu);
13424 case BR_UNALLOC_011:
13428 dexBranchImmediate (cpu);
13431 case BR_IMMCMP_101:
13432 /* Compare has bit 25 clear while test has it set. */
13433 if (!uimm (aarch64_get_instr (cpu), 25, 25))
13434 dexCompareBranchImmediate (cpu);
13436 dexTestBranchImmediate (cpu);
13440 /* Unconditional branch reg has bit 25 set. */
13441 if (uimm (aarch64_get_instr (cpu), 25, 25))
13442 dexBranchRegister (cpu);
13444 /* This includes both Excpn Gen, System and unalloc operations.
13445 We need to decode the Excpn Gen operation BRK so we can plant
13446 debugger entry points.
13447 Excpn Gen operations have aarch64_get_instr (cpu)[24] = 0.
13448 we need to decode at least one of the System operations NOP
13449 which is an alias for HINT #0.
13450 System operations have aarch64_get_instr (cpu)[24,22] = 100. */
13451 else if (uimm (aarch64_get_instr (cpu), 24, 24) == 0)
13454 else if (uimm (aarch64_get_instr (cpu), 24, 22) == 4)
13462 case BR_UNALLOC_111:
13466 /* Should never reach here. */
13472 aarch64_decode_and_execute (sim_cpu *cpu, uint64_t pc)
13474 /* We need to check if gdb wants an in here. */
13475 /* checkBreak (cpu);. */
13477 uint64_t group = dispatchGroup (aarch64_get_instr (cpu));
13481 case GROUP_PSEUDO_0000: dexPseudo (cpu); break;
13482 case GROUP_LDST_0100: dexLdSt (cpu); break;
13483 case GROUP_DPREG_0101: dexDPReg (cpu); break;
13484 case GROUP_LDST_0110: dexLdSt (cpu); break;
13485 case GROUP_ADVSIMD_0111: dexAdvSIMD0 (cpu); break;
13486 case GROUP_DPIMM_1000: dexDPImm (cpu); break;
13487 case GROUP_DPIMM_1001: dexDPImm (cpu); break;
13488 case GROUP_BREXSYS_1010: dexBr (cpu); break;
13489 case GROUP_BREXSYS_1011: dexBr (cpu); break;
13490 case GROUP_LDST_1100: dexLdSt (cpu); break;
13491 case GROUP_DPREG_1101: dexDPReg (cpu); break;
13492 case GROUP_LDST_1110: dexLdSt (cpu); break;
13493 case GROUP_ADVSIMD_1111: dexAdvSIMD1 (cpu); break;
13495 case GROUP_UNALLOC_0001:
13496 case GROUP_UNALLOC_0010:
13497 case GROUP_UNALLOC_0011:
13501 /* Should never reach here. */
13507 aarch64_step (sim_cpu *cpu)
13509 uint64_t pc = aarch64_get_PC (cpu);
13511 if (pc == TOP_LEVEL_RETURN_PC)
13514 aarch64_set_next_PC (cpu, pc + 4);
13515 aarch64_get_instr (cpu) = aarch64_get_mem_u32 (cpu, pc);
13517 TRACE_INSN (cpu, " pc = %" PRIx64 " instr = %08x", pc,
13518 aarch64_get_instr (cpu));
13519 TRACE_DISASM (cpu, pc);
13521 aarch64_decode_and_execute (cpu, pc);
13527 aarch64_run (SIM_DESC sd)
13529 sim_cpu *cpu = STATE_CPU (sd, 0);
13531 while (aarch64_step (cpu))
13532 aarch64_update_PC (cpu);
13534 sim_engine_halt (sd, NULL, NULL, aarch64_get_PC (cpu),
13535 sim_exited, aarch64_get_reg_s32 (cpu, R0, SP_OK));
13539 aarch64_init (sim_cpu *cpu, uint64_t pc)
13541 uint64_t sp = aarch64_get_stack_start (cpu);
13543 /* Install SP, FP and PC and set LR to -20
13544 so we can detect a top-level return. */
13545 aarch64_set_reg_u64 (cpu, SP, SP_OK, sp);
13546 aarch64_set_reg_u64 (cpu, FP, SP_OK, sp);
13547 aarch64_set_reg_u64 (cpu, LR, SP_OK, TOP_LEVEL_RETURN_PC);
13548 aarch64_set_next_PC (cpu, pc);
13549 aarch64_update_PC (cpu);
13550 aarch64_init_LIT_table ();