1 /* simulator.c -- Interface for the AArch64 simulator.
3 Copyright (C) 2015-2016 Free Software Foundation, Inc.
5 Contributed by Red Hat.
7 This file is part of GDB.
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 3 of the License, or
12 (at your option) any later version.
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with this program. If not, see <http://www.gnu.org/licenses/>. */
26 #include <sys/types.h>
31 #include "simulator.h"
38 #define TST(_flag) (aarch64_test_CPSR_bit (cpu, _flag))
39 #define IS_SET(_X) ( TST (( _X )))
40 #define IS_CLEAR(_X) (!TST (( _X )))
42 #define HALT_UNALLOC \
45 TRACE_DISASM (cpu, aarch64_get_PC (cpu)); \
47 "Unallocated instruction detected at sim line %d," \
48 " exe addr %" PRIx64, \
49 __LINE__, aarch64_get_PC (cpu)); \
50 sim_engine_halt (CPU_STATE (cpu), cpu, NULL, aarch64_get_PC (cpu),\
51 sim_stopped, SIM_SIGILL); \
58 TRACE_DISASM (cpu, aarch64_get_PC (cpu)); \
60 "Unimplemented instruction detected at sim line %d," \
61 " exe addr %" PRIx64, \
62 __LINE__, aarch64_get_PC (cpu)); \
63 sim_engine_halt (CPU_STATE (cpu), cpu, NULL, aarch64_get_PC (cpu),\
64 sim_stopped, SIM_SIGABRT); \
68 #define NYI_assert(HI, LO, EXPECTED) \
71 if (uimm (aarch64_get_instr (cpu), (HI), (LO)) != (EXPECTED)) \
76 #define HALT_UNREACHABLE \
79 TRACE_EVENTS (cpu, "ISE: unreachable code point"); \
80 sim_engine_abort (NULL, cpu, aarch64_get_PC (cpu), "Internal Error"); \
84 /* Helper functions used by expandLogicalImmediate. */
86 /* for i = 1, ... N result<i-1> = 1 other bits are zero */
87 static inline uint64_t
90 return (N == 64 ? (uint64_t)-1UL : ((1UL << N) - 1));
93 /* result<0> to val<N> */
94 static inline uint64_t
95 pickbit (uint64_t val, int N)
97 return pickbits64 (val, N, N);
101 expand_logical_immediate (uint32_t S, uint32_t R, uint32_t N)
107 /* The immediate value is S+1 bits to 1, left rotated by SIMDsize - R
108 (in other words, right rotated by R), then replicated. */
112 mask = 0xffffffffffffffffull;
118 case 0x00 ... 0x1f: /* 0xxxxx */ simd_size = 32; break;
119 case 0x20 ... 0x2f: /* 10xxxx */ simd_size = 16; S &= 0xf; break;
120 case 0x30 ... 0x37: /* 110xxx */ simd_size = 8; S &= 0x7; break;
121 case 0x38 ... 0x3b: /* 1110xx */ simd_size = 4; S &= 0x3; break;
122 case 0x3c ... 0x3d: /* 11110x */ simd_size = 2; S &= 0x1; break;
125 mask = (1ull << simd_size) - 1;
126 /* Top bits are IGNORED. */
130 /* NOTE: if S = simd_size - 1 we get 0xf..f which is rejected. */
131 if (S == simd_size - 1)
134 /* S+1 consecutive bits to 1. */
135 /* NOTE: S can't be 63 due to detection above. */
136 imm = (1ull << (S + 1)) - 1;
138 /* Rotate to the left by simd_size - R. */
140 imm = ((imm << (simd_size - R)) & mask) | (imm >> R);
142 /* Replicate the value according to SIMD size. */
145 case 2: imm = (imm << 2) | imm;
146 case 4: imm = (imm << 4) | imm;
147 case 8: imm = (imm << 8) | imm;
148 case 16: imm = (imm << 16) | imm;
149 case 32: imm = (imm << 32) | imm;
157 /* Instr[22,10] encodes N immr and imms. we want a lookup table
158 for each possible combination i.e. 13 bits worth of int entries. */
159 #define LI_TABLE_SIZE (1 << 13)
160 static uint64_t LITable[LI_TABLE_SIZE];
163 aarch64_init_LIT_table (void)
167 for (index = 0; index < LI_TABLE_SIZE; index++)
169 uint32_t N = uimm (index, 12, 12);
170 uint32_t immr = uimm (index, 11, 6);
171 uint32_t imms = uimm (index, 5, 0);
173 LITable [index] = expand_logical_immediate (imms, immr, N);
178 dexNotify (sim_cpu *cpu)
180 /* instr[14,0] == type : 0 ==> method entry, 1 ==> method reentry
181 2 ==> exit Java, 3 ==> start next bytecode. */
182 uint32_t type = uimm (aarch64_get_instr (cpu), 14, 0);
184 TRACE_EVENTS (cpu, "Notify Insn encountered, type = 0x%x", type);
189 /* aarch64_notifyMethodEntry (aarch64_get_reg_u64 (cpu, R23, 0),
190 aarch64_get_reg_u64 (cpu, R22, 0)); */
193 /* aarch64_notifyMethodReentry (aarch64_get_reg_u64 (cpu, R23, 0),
194 aarch64_get_reg_u64 (cpu, R22, 0)); */
197 /* aarch64_notifyMethodExit (); */
200 /* aarch64_notifyBCStart (aarch64_get_reg_u64 (cpu, R23, 0),
201 aarch64_get_reg_u64 (cpu, R22, 0)); */
206 /* secondary decode within top level groups */
209 dexPseudo (sim_cpu *cpu)
211 /* assert instr[28,27] = 00
213 We provide 2 pseudo instructions:
215 HALT stops execution of the simulator causing an immediate
216 return to the x86 code which entered it.
218 CALLOUT initiates recursive entry into x86 code. A register
219 argument holds the address of the x86 routine. Immediate
220 values in the instruction identify the number of general
221 purpose and floating point register arguments to be passed
222 and the type of any value to be returned. */
224 uint32_t PSEUDO_HALT = 0xE0000000U;
225 uint32_t PSEUDO_CALLOUT = 0x00018000U;
226 uint32_t PSEUDO_CALLOUTR = 0x00018001U;
227 uint32_t PSEUDO_NOTIFY = 0x00014000U;
230 if (aarch64_get_instr (cpu) == PSEUDO_HALT)
232 TRACE_EVENTS (cpu, " Pseudo Halt Instruction");
233 sim_engine_halt (CPU_STATE (cpu), cpu, NULL, aarch64_get_PC (cpu),
234 sim_stopped, SIM_SIGTRAP);
237 dispatch = uimm (aarch64_get_instr (cpu), 31, 15);
239 /* We do not handle callouts at the moment. */
240 if (dispatch == PSEUDO_CALLOUT || dispatch == PSEUDO_CALLOUTR)
242 TRACE_EVENTS (cpu, " Callout");
243 sim_engine_halt (CPU_STATE (cpu), cpu, NULL, aarch64_get_PC (cpu),
244 sim_stopped, SIM_SIGABRT);
247 else if (dispatch == PSEUDO_NOTIFY)
254 /* Load-store single register (unscaled offset)
255 These instructions employ a base register plus an unscaled signed
258 N.B. the base register (source) can be Xn or SP. all other
259 registers may not be SP. */
261 /* 32 bit load 32 bit unscaled signed 9 bit. */
263 ldur32 (sim_cpu *cpu, int32_t offset)
265 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
266 unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
268 aarch64_set_reg_u64 (cpu, rt, NO_SP, aarch64_get_mem_u32
269 (cpu, aarch64_get_reg_u64 (cpu, rn, SP_OK)
273 /* 64 bit load 64 bit unscaled signed 9 bit. */
275 ldur64 (sim_cpu *cpu, int32_t offset)
277 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
278 unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
280 aarch64_set_reg_u64 (cpu, rt, NO_SP, aarch64_get_mem_u64
281 (cpu, aarch64_get_reg_u64 (cpu, rn, SP_OK)
285 /* 32 bit load zero-extended byte unscaled signed 9 bit. */
287 ldurb32 (sim_cpu *cpu, int32_t offset)
289 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
290 unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
292 aarch64_set_reg_u64 (cpu, rt, NO_SP, aarch64_get_mem_u8
293 (cpu, aarch64_get_reg_u64 (cpu, rn, SP_OK)
297 /* 32 bit load sign-extended byte unscaled signed 9 bit. */
299 ldursb32 (sim_cpu *cpu, int32_t offset)
301 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
302 unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
304 aarch64_set_reg_u64 (cpu, rt, NO_SP, (uint32_t) aarch64_get_mem_s8
305 (cpu, aarch64_get_reg_u64 (cpu, rn, SP_OK)
309 /* 64 bit load sign-extended byte unscaled signed 9 bit. */
311 ldursb64 (sim_cpu *cpu, int32_t offset)
313 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
314 unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
316 aarch64_set_reg_s64 (cpu, rt, NO_SP, aarch64_get_mem_s8
317 (cpu, aarch64_get_reg_u64 (cpu, rn, SP_OK)
321 /* 32 bit load zero-extended short unscaled signed 9 bit */
323 ldurh32 (sim_cpu *cpu, int32_t offset)
325 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
326 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
328 aarch64_set_reg_u64 (cpu, rd, NO_SP, aarch64_get_mem_u16
329 (cpu, aarch64_get_reg_u64 (cpu, rn, SP_OK)
333 /* 32 bit load sign-extended short unscaled signed 9 bit */
335 ldursh32 (sim_cpu *cpu, int32_t offset)
337 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
338 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
340 aarch64_set_reg_u64 (cpu, rd, NO_SP, (uint32_t) aarch64_get_mem_s16
341 (cpu, aarch64_get_reg_u64 (cpu, rn, SP_OK)
345 /* 64 bit load sign-extended short unscaled signed 9 bit */
347 ldursh64 (sim_cpu *cpu, int32_t offset)
349 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
350 unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
352 aarch64_set_reg_s64 (cpu, rt, NO_SP, aarch64_get_mem_s16
353 (cpu, aarch64_get_reg_u64 (cpu, rn, SP_OK)
357 /* 64 bit load sign-extended word unscaled signed 9 bit */
359 ldursw (sim_cpu *cpu, int32_t offset)
361 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
362 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
364 aarch64_set_reg_u64 (cpu, rd, NO_SP, (uint32_t) aarch64_get_mem_s32
365 (cpu, aarch64_get_reg_u64 (cpu, rn, SP_OK)
369 /* N.B. with stores the value in source is written to the address
370 identified by source2 modified by offset. */
372 /* 32 bit store 32 bit unscaled signed 9 bit. */
374 stur32 (sim_cpu *cpu, int32_t offset)
376 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
377 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
379 aarch64_set_mem_u32 (cpu,
380 aarch64_get_reg_u64 (cpu, rn, SP_OK) + offset,
381 aarch64_get_reg_u32 (cpu, rd, NO_SP));
384 /* 64 bit store 64 bit unscaled signed 9 bit */
386 stur64 (sim_cpu *cpu, int32_t offset)
388 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
389 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
391 aarch64_set_mem_u64 (cpu,
392 aarch64_get_reg_u64 (cpu, rn, SP_OK) + offset,
393 aarch64_get_reg_u64 (cpu, rd, NO_SP));
396 /* 32 bit store byte unscaled signed 9 bit */
398 sturb (sim_cpu *cpu, int32_t offset)
400 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
401 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
403 aarch64_set_mem_u8 (cpu,
404 aarch64_get_reg_u64 (cpu, rn, SP_OK) + offset,
405 aarch64_get_reg_u8 (cpu, rd, NO_SP));
408 /* 32 bit store short unscaled signed 9 bit */
410 sturh (sim_cpu *cpu, int32_t offset)
412 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
413 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
415 aarch64_set_mem_u16 (cpu,
416 aarch64_get_reg_u64 (cpu, rn, SP_OK) + offset,
417 aarch64_get_reg_u16 (cpu, rd, NO_SP));
420 /* Load single register pc-relative label
421 Offset is a signed 19 bit immediate count in words
424 /* 32 bit pc-relative load */
426 ldr32_pcrel (sim_cpu *cpu, int32_t offset)
428 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
430 aarch64_set_reg_u64 (cpu, rd, NO_SP,
432 (cpu, aarch64_get_PC (cpu) + offset * 4));
435 /* 64 bit pc-relative load */
437 ldr_pcrel (sim_cpu *cpu, int32_t offset)
439 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
441 aarch64_set_reg_u64 (cpu, rd, NO_SP,
443 (cpu, aarch64_get_PC (cpu) + offset * 4));
446 /* sign extended 32 bit pc-relative load */
448 ldrsw_pcrel (sim_cpu *cpu, int32_t offset)
450 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
452 aarch64_set_reg_u64 (cpu, rd, NO_SP,
454 (cpu, aarch64_get_PC (cpu) + offset * 4));
457 /* float pc-relative load */
459 fldrs_pcrel (sim_cpu *cpu, int32_t offset)
461 unsigned int rd = uimm (aarch64_get_instr (cpu), 4, 0);
463 aarch64_set_FP_float (cpu, rd,
464 aarch64_get_mem_float
465 (cpu, aarch64_get_PC (cpu) + offset * 4));
468 /* double pc-relative load */
470 fldrd_pcrel (sim_cpu *cpu, int32_t offset)
472 unsigned int st = uimm (aarch64_get_instr (cpu), 4, 0);
474 aarch64_set_FP_double (cpu, st,
475 aarch64_get_mem_double
476 (cpu, aarch64_get_PC (cpu) + offset * 4));
479 /* long double pc-relative load. */
481 fldrq_pcrel (sim_cpu *cpu, int32_t offset)
483 unsigned int st = uimm (aarch64_get_instr (cpu), 4, 0);
484 uint64_t addr = aarch64_get_PC (cpu) + offset * 4;
487 aarch64_get_mem_long_double (cpu, addr, & a);
488 aarch64_set_FP_long_double (cpu, st, a);
491 /* This can be used to scale an offset by applying
492 the requisite shift. the second argument is either
495 #define SCALE(_offset, _elementSize) \
496 ((_offset) << ScaleShift ## _elementSize)
498 /* This can be used to optionally scale a register derived offset
499 by applying the requisite shift as indicated by the Scaling
500 argument. the second argument is either Byte, Short, Word
501 or Long. The third argument is either Scaled or Unscaled.
502 N.B. when _Scaling is Scaled the shift gets ANDed with
503 all 1s while when it is Unscaled it gets ANDed with 0. */
505 #define OPT_SCALE(_offset, _elementType, _Scaling) \
506 ((_offset) << (_Scaling ? ScaleShift ## _elementType : 0))
508 /* This can be used to zero or sign extend a 32 bit register derived
509 value to a 64 bit value. the first argument must be the value as
510 a uint32_t and the second must be either UXTW or SXTW. The result
511 is returned as an int64_t. */
513 static inline int64_t
514 extend (uint32_t value, Extension extension)
522 /* A branchless variant of this ought to be possible. */
523 if (extension == UXTW || extension == NoExtension)
530 /* Scalar Floating Point
532 FP load/store single register (4 addressing modes)
534 N.B. the base register (source) can be the stack pointer.
535 The secondary source register (source2) can only be an Xn register. */
537 /* Load 32 bit unscaled signed 9 bit with pre- or post-writeback. */
539 fldrs_wb (sim_cpu *cpu, int32_t offset, WriteBack wb)
541 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
542 unsigned st = uimm (aarch64_get_instr (cpu), 4, 0);
543 uint64_t address = aarch64_get_reg_u64 (cpu, rn, SP_OK);
548 aarch64_set_FP_float (cpu, st, aarch64_get_mem_float (cpu, address));
552 if (wb != NoWriteBack)
553 aarch64_set_reg_u64 (cpu, rn, SP_OK, address);
556 /* Load 32 bit scaled unsigned 12 bit. */
558 fldrs_abs (sim_cpu *cpu, uint32_t offset)
560 unsigned st = uimm (aarch64_get_instr (cpu), 4, 0);
561 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
563 aarch64_set_FP_float (cpu, st,
564 aarch64_get_mem_float
565 (cpu, aarch64_get_reg_u64 (cpu, rn, SP_OK)
566 + SCALE (offset, 32)));
569 /* Load 32 bit scaled or unscaled zero- or sign-extended
570 32-bit register offset. */
572 fldrs_scale_ext (sim_cpu *cpu, Scaling scaling, Extension extension)
574 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
575 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
576 unsigned st = uimm (aarch64_get_instr (cpu), 4, 0);
577 uint64_t address = aarch64_get_reg_u64 (cpu, rn, SP_OK);
578 int64_t extended = extend (aarch64_get_reg_u32 (cpu, rm, NO_SP), extension);
579 uint64_t displacement = OPT_SCALE (extended, 32, scaling);
581 aarch64_set_FP_float (cpu, st,
582 aarch64_get_mem_float
583 (cpu, address + displacement));
586 /* Load 64 bit unscaled signed 9 bit with pre- or post-writeback. */
588 fldrd_wb (sim_cpu *cpu, int32_t offset, WriteBack wb)
590 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
591 unsigned st = uimm (aarch64_get_instr (cpu), 4, 0);
592 uint64_t address = aarch64_get_reg_u64 (cpu, rn, SP_OK);
597 aarch64_set_FP_double (cpu, st, aarch64_get_mem_double (cpu, address));
602 if (wb != NoWriteBack)
603 aarch64_set_reg_u64 (cpu, rn, SP_OK, address);
606 /* Load 64 bit scaled unsigned 12 bit. */
608 fldrd_abs (sim_cpu *cpu, uint32_t offset)
610 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
611 unsigned st = uimm (aarch64_get_instr (cpu), 4, 0);
612 uint64_t address = aarch64_get_reg_u64 (cpu, rn, SP_OK) + SCALE (offset, 64);
614 aarch64_set_FP_double (cpu, st, aarch64_get_mem_double (cpu, address));
617 /* Load 64 bit scaled or unscaled zero- or sign-extended 32-bit register offset. */
619 fldrd_scale_ext (sim_cpu *cpu, Scaling scaling, Extension extension)
621 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
622 int64_t extended = extend (aarch64_get_reg_u32 (cpu, rm, NO_SP), extension);
623 uint64_t displacement = OPT_SCALE (extended, 64, scaling);
625 fldrd_wb (cpu, displacement, NoWriteBack);
628 /* Load 128 bit unscaled signed 9 bit with pre- or post-writeback. */
630 fldrq_wb (sim_cpu *cpu, int32_t offset, WriteBack wb)
633 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
634 unsigned st = uimm (aarch64_get_instr (cpu), 4, 0);
635 uint64_t address = aarch64_get_reg_u64 (cpu, rn, SP_OK);
640 aarch64_get_mem_long_double (cpu, address, & a);
641 aarch64_set_FP_long_double (cpu, st, a);
646 if (wb != NoWriteBack)
647 aarch64_set_reg_u64 (cpu, rn, SP_OK, address);
650 /* Load 128 bit scaled unsigned 12 bit. */
652 fldrq_abs (sim_cpu *cpu, uint32_t offset)
655 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
656 unsigned st = uimm (aarch64_get_instr (cpu), 4, 0);
657 uint64_t address = aarch64_get_reg_u64 (cpu, rn, SP_OK) + SCALE (offset, 128);
659 aarch64_get_mem_long_double (cpu, address, & a);
660 aarch64_set_FP_long_double (cpu, st, a);
663 /* Load 128 bit scaled or unscaled zero- or sign-extended 32-bit register offset */
665 fldrq_scale_ext (sim_cpu *cpu, Scaling scaling, Extension extension)
667 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
668 int64_t extended = extend (aarch64_get_reg_u32 (cpu, rm, NO_SP), extension);
669 uint64_t displacement = OPT_SCALE (extended, 128, scaling);
671 fldrq_wb (cpu, displacement, NoWriteBack);
676 load-store single register
677 There are four addressing modes available here which all employ a
678 64 bit source (base) register.
680 N.B. the base register (source) can be the stack pointer.
681 The secondary source register (source2)can only be an Xn register.
683 Scaled, 12-bit, unsigned immediate offset, without pre- and
685 Unscaled, 9-bit, signed immediate offset with pre- or post-index
687 scaled or unscaled 64-bit register offset.
688 scaled or unscaled 32-bit extended register offset.
690 All offsets are assumed to be raw from the decode i.e. the
691 simulator is expected to adjust scaled offsets based on the
692 accessed data size with register or extended register offset
693 versions the same applies except that in the latter case the
694 operation may also require a sign extend.
696 A separate method is provided for each possible addressing mode. */
698 /* 32 bit load 32 bit scaled unsigned 12 bit */
700 ldr32_abs (sim_cpu *cpu, uint32_t offset)
702 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
703 unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
705 /* The target register may not be SP but the source may be. */
706 aarch64_set_reg_u64 (cpu, rt, NO_SP, aarch64_get_mem_u32
707 (cpu, aarch64_get_reg_u64 (cpu, rn, SP_OK)
708 + SCALE (offset, 32)));
711 /* 32 bit load 32 bit unscaled signed 9 bit with pre- or post-writeback. */
713 ldr32_wb (sim_cpu *cpu, int32_t offset, WriteBack wb)
715 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
716 unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
719 if (rn == rt && wb != NoWriteBack)
722 address = aarch64_get_reg_u64 (cpu, rn, SP_OK);
727 aarch64_set_reg_u64 (cpu, rt, NO_SP, aarch64_get_mem_u32 (cpu, address));
732 if (wb != NoWriteBack)
733 aarch64_set_reg_u64 (cpu, rn, SP_OK, address);
736 /* 32 bit load 32 bit scaled or unscaled
737 zero- or sign-extended 32-bit register offset */
739 ldr32_scale_ext (sim_cpu *cpu, Scaling scaling, Extension extension)
741 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
742 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
743 unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
744 /* rn may reference SP, rm and rt must reference ZR */
746 uint64_t address = aarch64_get_reg_u64 (cpu, rn, SP_OK);
747 int64_t extended = extend (aarch64_get_reg_u32 (cpu, rm, NO_SP), extension);
748 uint64_t displacement = OPT_SCALE (extended, 32, scaling);
750 aarch64_set_reg_u64 (cpu, rt, NO_SP,
751 aarch64_get_mem_u32 (cpu, address + displacement));
754 /* 64 bit load 64 bit scaled unsigned 12 bit */
756 ldr_abs (sim_cpu *cpu, uint32_t offset)
758 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
759 unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
761 /* The target register may not be SP but the source may be. */
762 aarch64_set_reg_u64 (cpu, rt, NO_SP, aarch64_get_mem_u64
763 (cpu, aarch64_get_reg_u64 (cpu, rn, SP_OK)
764 + SCALE (offset, 64)));
767 /* 64 bit load 64 bit unscaled signed 9 bit with pre- or post-writeback. */
769 ldr_wb (sim_cpu *cpu, int32_t offset, WriteBack wb)
771 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
772 unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
775 if (rn == rt && wb != NoWriteBack)
778 address = aarch64_get_reg_u64 (cpu, rn, SP_OK);
783 aarch64_set_reg_u64 (cpu, rt, NO_SP, aarch64_get_mem_u64 (cpu, address));
788 if (wb != NoWriteBack)
789 aarch64_set_reg_u64 (cpu, rn, SP_OK, address);
792 /* 64 bit load 64 bit scaled or unscaled zero-
793 or sign-extended 32-bit register offset. */
795 ldr_scale_ext (sim_cpu *cpu, Scaling scaling, Extension extension)
797 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
798 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
799 unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
800 /* rn may reference SP, rm and rt must reference ZR */
802 uint64_t address = aarch64_get_reg_u64 (cpu, rn, SP_OK);
803 int64_t extended = extend (aarch64_get_reg_u32 (cpu, rm, NO_SP), extension);
804 uint64_t displacement = OPT_SCALE (extended, 64, scaling);
806 aarch64_set_reg_u64 (cpu, rt, NO_SP,
807 aarch64_get_mem_u64 (cpu, address + displacement));
810 /* 32 bit load zero-extended byte scaled unsigned 12 bit. */
812 ldrb32_abs (sim_cpu *cpu, uint32_t offset)
814 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
815 unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
817 /* The target register may not be SP but the source may be
818 there is no scaling required for a byte load. */
819 aarch64_set_reg_u64 (cpu, rt, NO_SP,
821 (cpu, aarch64_get_reg_u64 (cpu, rn, SP_OK) + offset));
824 /* 32 bit load zero-extended byte unscaled signed 9 bit with pre- or post-writeback. */
826 ldrb32_wb (sim_cpu *cpu, int32_t offset, WriteBack wb)
828 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
829 unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
832 if (rn == rt && wb != NoWriteBack)
835 address = aarch64_get_reg_u64 (cpu, rn, SP_OK);
840 aarch64_set_reg_u64 (cpu, rt, NO_SP, aarch64_get_mem_u8 (cpu, address));
845 if (wb != NoWriteBack)
846 aarch64_set_reg_u64 (cpu, rn, SP_OK, address);
849 /* 32 bit load zero-extended byte scaled or unscaled zero-
850 or sign-extended 32-bit register offset. */
852 ldrb32_scale_ext (sim_cpu *cpu, Scaling scaling, Extension extension)
854 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
855 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
856 unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
857 /* rn may reference SP, rm and rt must reference ZR */
859 uint64_t address = aarch64_get_reg_u64 (cpu, rn, SP_OK);
860 int64_t displacement = extend (aarch64_get_reg_u32 (cpu, rm, NO_SP),
863 /* There is no scaling required for a byte load. */
864 aarch64_set_reg_u64 (cpu, rt, NO_SP,
865 aarch64_get_mem_u8 (cpu, address + displacement));
868 /* 64 bit load sign-extended byte unscaled signed 9 bit
869 with pre- or post-writeback. */
871 ldrsb_wb (sim_cpu *cpu, int32_t offset, WriteBack wb)
873 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
874 unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
877 if (rn == rt && wb != NoWriteBack)
880 address = aarch64_get_reg_u64 (cpu, rn, SP_OK);
885 aarch64_set_reg_u64 (cpu, rt, NO_SP, aarch64_get_mem_s8 (cpu, address));
890 if (wb != NoWriteBack)
891 aarch64_set_reg_u64 (cpu, rn, SP_OK, address);
894 /* 64 bit load sign-extended byte scaled unsigned 12 bit. */
896 ldrsb_abs (sim_cpu *cpu, uint32_t offset)
898 ldrsb_wb (cpu, offset, NoWriteBack);
901 /* 64 bit load sign-extended byte scaled or unscaled zero-
902 or sign-extended 32-bit register offset. */
904 ldrsb_scale_ext (sim_cpu *cpu, Scaling scaling, Extension extension)
906 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
907 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
908 unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
909 /* rn may reference SP, rm and rt must reference ZR */
911 uint64_t address = aarch64_get_reg_u64 (cpu, rn, SP_OK);
912 int64_t displacement = extend (aarch64_get_reg_u32 (cpu, rm, NO_SP),
914 /* There is no scaling required for a byte load. */
915 aarch64_set_reg_u64 (cpu, rt, NO_SP,
916 aarch64_get_mem_s8 (cpu, address + displacement));
919 /* 32 bit load zero-extended short scaled unsigned 12 bit. */
921 ldrh32_abs (sim_cpu *cpu, uint32_t offset)
923 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
924 unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
926 /* The target register may not be SP but the source may be. */
927 aarch64_set_reg_u64 (cpu, rt, NO_SP, aarch64_get_mem_u16
928 (cpu, aarch64_get_reg_u64 (cpu, rn, SP_OK)
929 + SCALE (offset, 16)));
932 /* 32 bit load zero-extended short unscaled signed 9 bit
933 with pre- or post-writeback. */
935 ldrh32_wb (sim_cpu *cpu, int32_t offset, WriteBack wb)
937 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
938 unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
941 if (rn == rt && wb != NoWriteBack)
944 address = aarch64_get_reg_u64 (cpu, rn, SP_OK);
949 aarch64_set_reg_u64 (cpu, rt, NO_SP, aarch64_get_mem_u16 (cpu, address));
954 if (wb != NoWriteBack)
955 aarch64_set_reg_u64 (cpu, rn, SP_OK, address);
958 /* 32 bit load zero-extended short scaled or unscaled zero-
959 or sign-extended 32-bit register offset. */
961 ldrh32_scale_ext (sim_cpu *cpu, Scaling scaling, Extension extension)
963 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
964 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
965 unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
966 /* rn may reference SP, rm and rt must reference ZR */
968 uint64_t address = aarch64_get_reg_u64 (cpu, rn, SP_OK);
969 int64_t extended = extend (aarch64_get_reg_u32 (cpu, rm, NO_SP), extension);
970 uint64_t displacement = OPT_SCALE (extended, 16, scaling);
972 aarch64_set_reg_u64 (cpu, rt, NO_SP,
973 aarch64_get_mem_u16 (cpu, address + displacement));
976 /* 32 bit load sign-extended short scaled unsigned 12 bit. */
978 ldrsh32_abs (sim_cpu *cpu, uint32_t offset)
980 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
981 unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
983 /* The target register may not be SP but the source may be. */
984 aarch64_set_reg_u64 (cpu, rt, NO_SP, (uint32_t) aarch64_get_mem_s16
986 aarch64_get_reg_u64 (cpu, rn, SP_OK)
987 + SCALE (offset, 16)));
990 /* 32 bit load sign-extended short unscaled signed 9 bit
991 with pre- or post-writeback. */
993 ldrsh32_wb (sim_cpu *cpu, int32_t offset, WriteBack wb)
995 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
996 unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
999 if (rn == rt && wb != NoWriteBack)
1002 address = aarch64_get_reg_u64 (cpu, rn, SP_OK);
1007 aarch64_set_reg_u64 (cpu, rt, NO_SP,
1008 (uint32_t) aarch64_get_mem_s16 (cpu, address));
1013 if (wb != NoWriteBack)
1014 aarch64_set_reg_u64 (cpu, rn, SP_OK, address);
1017 /* 32 bit load sign-extended short scaled or unscaled zero-
1018 or sign-extended 32-bit register offset. */
1020 ldrsh32_scale_ext (sim_cpu *cpu, Scaling scaling, Extension extension)
1022 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
1023 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
1024 unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
1025 /* rn may reference SP, rm and rt must reference ZR */
1027 uint64_t address = aarch64_get_reg_u64 (cpu, rn, SP_OK);
1028 int64_t extended = extend (aarch64_get_reg_u32 (cpu, rm, NO_SP), extension);
1029 uint64_t displacement = OPT_SCALE (extended, 16, scaling);
1031 aarch64_set_reg_u64 (cpu, rt, NO_SP,
1032 (uint32_t) aarch64_get_mem_s16
1033 (cpu, address + displacement));
1036 /* 64 bit load sign-extended short scaled unsigned 12 bit. */
1038 ldrsh_abs (sim_cpu *cpu, uint32_t offset)
1040 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
1041 unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
1043 /* The target register may not be SP but the source may be. */
1044 aarch64_set_reg_u64 (cpu, rt, NO_SP, aarch64_get_mem_s16
1045 (cpu, aarch64_get_reg_u64 (cpu, rn, SP_OK)
1046 + SCALE (offset, 16)));
1049 /* 64 bit load sign-extended short unscaled signed 9 bit
1050 with pre- or post-writeback. */
1052 ldrsh64_wb (sim_cpu *cpu, int32_t offset, WriteBack wb)
1054 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
1055 unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
1058 if (rn == rt && wb != NoWriteBack)
1061 address = aarch64_get_reg_u64 (cpu, rn, SP_OK);
1066 aarch64_set_reg_u64 (cpu, rt, NO_SP, aarch64_get_mem_s16 (cpu, address));
1071 if (wb != NoWriteBack)
1072 aarch64_set_reg_u64 (cpu, rn, SP_OK, address);
1075 /* 64 bit load sign-extended short scaled or unscaled zero-
1076 or sign-extended 32-bit register offset. */
1078 ldrsh_scale_ext (sim_cpu *cpu, Scaling scaling, Extension extension)
1080 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
1081 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
1082 unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
1083 /* rn may reference SP, rm and rt must reference ZR */
1085 uint64_t address = aarch64_get_reg_u64 (cpu, rn, SP_OK);
1086 int64_t extended = extend (aarch64_get_reg_u32 (cpu, rm, NO_SP), extension);
1087 uint64_t displacement = OPT_SCALE (extended, 16, scaling);
1089 aarch64_set_reg_u64 (cpu, rt, NO_SP,
1090 aarch64_get_mem_s16 (cpu, address + displacement));
1093 /* 64 bit load sign-extended 32 bit scaled unsigned 12 bit. */
1095 ldrsw_abs (sim_cpu *cpu, uint32_t offset)
1097 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
1098 unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
1100 /* The target register may not be SP but the source may be. */
1101 return aarch64_set_reg_s64 (cpu, rt, NO_SP, aarch64_get_mem_s32
1102 (cpu, aarch64_get_reg_u64 (cpu, rn, SP_OK)
1103 + SCALE (offset, 32)));
1106 /* 64 bit load sign-extended 32 bit unscaled signed 9 bit
1107 with pre- or post-writeback. */
1109 ldrsw_wb (sim_cpu *cpu, int32_t offset, WriteBack wb)
1111 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
1112 unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
1115 if (rn == rt && wb != NoWriteBack)
1118 address = aarch64_get_reg_u64 (cpu, rn, SP_OK);
1123 aarch64_set_reg_s64 (cpu, rt, NO_SP, aarch64_get_mem_s32 (cpu, address));
1128 if (wb != NoWriteBack)
1129 aarch64_set_reg_u64 (cpu, rn, SP_OK, address);
1132 /* 64 bit load sign-extended 32 bit scaled or unscaled zero-
1133 or sign-extended 32-bit register offset. */
1135 ldrsw_scale_ext (sim_cpu *cpu, Scaling scaling, Extension extension)
1137 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
1138 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
1139 unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
1140 /* rn may reference SP, rm and rt must reference ZR */
1142 uint64_t address = aarch64_get_reg_u64 (cpu, rn, SP_OK);
1143 int64_t extended = extend (aarch64_get_reg_u32 (cpu, rm, NO_SP), extension);
1144 uint64_t displacement = OPT_SCALE (extended, 32, scaling);
1146 aarch64_set_reg_s64 (cpu, rt, NO_SP,
1147 aarch64_get_mem_s32 (cpu, address + displacement));
1150 /* N.B. with stores the value in source is written to the
1151 address identified by source2 modified by source3/offset. */
1153 /* 32 bit store scaled unsigned 12 bit. */
1155 str32_abs (sim_cpu *cpu, uint32_t offset)
1157 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
1158 unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
1160 /* The target register may not be SP but the source may be. */
1161 aarch64_set_mem_u32 (cpu, (aarch64_get_reg_u64 (cpu, rn, SP_OK)
1162 + SCALE (offset, 32)),
1163 aarch64_get_reg_u32 (cpu, rt, NO_SP));
1166 /* 32 bit store unscaled signed 9 bit with pre- or post-writeback. */
1168 str32_wb (sim_cpu *cpu, int32_t offset, WriteBack wb)
1170 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
1171 unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
1174 if (rn == rt && wb != NoWriteBack)
1177 address = aarch64_get_reg_u64 (cpu, rn, SP_OK);
1181 aarch64_set_mem_u32 (cpu, address, aarch64_get_reg_u32 (cpu, rt, NO_SP));
1186 if (wb != NoWriteBack)
1187 aarch64_set_reg_u64 (cpu, rn, SP_OK, address);
1190 /* 32 bit store scaled or unscaled zero- or
1191 sign-extended 32-bit register offset. */
1193 str32_scale_ext (sim_cpu *cpu, Scaling scaling, Extension extension)
1195 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
1196 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
1197 unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
1199 uint64_t address = aarch64_get_reg_u64 (cpu, rn, SP_OK);
1200 int64_t extended = extend (aarch64_get_reg_u32 (cpu, rm, NO_SP), extension);
1201 uint64_t displacement = OPT_SCALE (extended, 32, scaling);
1203 aarch64_set_mem_u32 (cpu, address + displacement,
1204 aarch64_get_reg_u64 (cpu, rt, NO_SP));
1207 /* 64 bit store scaled unsigned 12 bit. */
1209 str_abs (sim_cpu *cpu, uint32_t offset)
1211 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
1212 unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
1214 aarch64_set_mem_u64 (cpu,
1215 aarch64_get_reg_u64 (cpu, rn, SP_OK)
1216 + SCALE (offset, 64),
1217 aarch64_get_reg_u64 (cpu, rt, NO_SP));
1220 /* 64 bit store unscaled signed 9 bit with pre- or post-writeback. */
1222 str_wb (sim_cpu *cpu, int32_t offset, WriteBack wb)
1224 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
1225 unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
1228 if (rn == rt && wb != NoWriteBack)
1231 address = aarch64_get_reg_u64 (cpu, rn, SP_OK);
1236 aarch64_set_mem_u64 (cpu, address, aarch64_get_reg_u64 (cpu, rt, NO_SP));
1241 if (wb != NoWriteBack)
1242 aarch64_set_reg_u64 (cpu, rn, SP_OK, address);
1245 /* 64 bit store scaled or unscaled zero-
1246 or sign-extended 32-bit register offset. */
1248 str_scale_ext (sim_cpu *cpu, Scaling scaling, Extension extension)
1250 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
1251 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
1252 unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
1253 /* rn may reference SP, rm and rt must reference ZR */
1255 uint64_t address = aarch64_get_reg_u64 (cpu, rn, SP_OK);
1256 int64_t extended = extend (aarch64_get_reg_u32 (cpu, rm, NO_SP),
1258 uint64_t displacement = OPT_SCALE (extended, 64, scaling);
1260 aarch64_set_mem_u64 (cpu, address + displacement,
1261 aarch64_get_reg_u64 (cpu, rt, NO_SP));
1264 /* 32 bit store byte scaled unsigned 12 bit. */
1266 strb_abs (sim_cpu *cpu, uint32_t offset)
1268 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
1269 unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
1271 /* The target register may not be SP but the source may be.
1272 There is no scaling required for a byte load. */
1273 aarch64_set_mem_u8 (cpu,
1274 aarch64_get_reg_u64 (cpu, rn, SP_OK) + offset,
1275 aarch64_get_reg_u8 (cpu, rt, NO_SP));
1278 /* 32 bit store byte unscaled signed 9 bit with pre- or post-writeback. */
1280 strb_wb (sim_cpu *cpu, int32_t offset, WriteBack wb)
1282 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
1283 unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
1286 if (rn == rt && wb != NoWriteBack)
1289 address = aarch64_get_reg_u64 (cpu, rn, SP_OK);
1294 aarch64_set_mem_u8 (cpu, address, aarch64_get_reg_u8 (cpu, rt, NO_SP));
1299 if (wb != NoWriteBack)
1300 aarch64_set_reg_u64 (cpu, rn, SP_OK, address);
1303 /* 32 bit store byte scaled or unscaled zero-
1304 or sign-extended 32-bit register offset. */
1306 strb_scale_ext (sim_cpu *cpu, Scaling scaling, Extension extension)
1308 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
1309 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
1310 unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
1311 /* rn may reference SP, rm and rt must reference ZR */
1313 uint64_t address = aarch64_get_reg_u64 (cpu, rn, SP_OK);
1314 int64_t displacement = extend (aarch64_get_reg_u32 (cpu, rm, NO_SP),
1317 /* There is no scaling required for a byte load. */
1318 aarch64_set_mem_u8 (cpu, address + displacement,
1319 aarch64_get_reg_u8 (cpu, rt, NO_SP));
1322 /* 32 bit store short scaled unsigned 12 bit. */
1324 strh_abs (sim_cpu *cpu, uint32_t offset)
1326 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
1327 unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
1329 /* The target register may not be SP but the source may be. */
1330 aarch64_set_mem_u16 (cpu, aarch64_get_reg_u64 (cpu, rn, SP_OK)
1331 + SCALE (offset, 16),
1332 aarch64_get_reg_u16 (cpu, rt, NO_SP));
1335 /* 32 bit store short unscaled signed 9 bit with pre- or post-writeback. */
1337 strh_wb (sim_cpu *cpu, int32_t offset, WriteBack wb)
1339 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
1340 unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
1343 if (rn == rt && wb != NoWriteBack)
1346 address = aarch64_get_reg_u64 (cpu, rn, SP_OK);
1351 aarch64_set_mem_u16 (cpu, address, aarch64_get_reg_u16 (cpu, rt, NO_SP));
1356 if (wb != NoWriteBack)
1357 aarch64_set_reg_u64 (cpu, rn, SP_OK, address);
1360 /* 32 bit store short scaled or unscaled zero-
1361 or sign-extended 32-bit register offset. */
1363 strh_scale_ext (sim_cpu *cpu, Scaling scaling, Extension extension)
1365 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
1366 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
1367 unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
1368 /* rn may reference SP, rm and rt must reference ZR */
1370 uint64_t address = aarch64_get_reg_u64 (cpu, rn, SP_OK);
1371 int64_t extended = extend (aarch64_get_reg_u32 (cpu, rm, NO_SP), extension);
1372 uint64_t displacement = OPT_SCALE (extended, 16, scaling);
1374 aarch64_set_mem_u16 (cpu, address + displacement,
1375 aarch64_get_reg_u16 (cpu, rt, NO_SP));
1378 /* Prefetch unsigned 12 bit. */
1380 prfm_abs (sim_cpu *cpu, uint32_t offset)
1382 /* instr[4,0] = prfop : 00000 ==> PLDL1KEEP, 00001 ==> PLDL1STRM,
1383 00010 ==> PLDL2KEEP, 00001 ==> PLDL2STRM,
1384 00100 ==> PLDL3KEEP, 00101 ==> PLDL3STRM,
1385 10000 ==> PSTL1KEEP, 10001 ==> PSTL1STRM,
1386 10010 ==> PSTL2KEEP, 10001 ==> PSTL2STRM,
1387 10100 ==> PSTL3KEEP, 10101 ==> PSTL3STRM,
1389 PrfOp prfop = prfop (aarch64_get_instr (cpu), 4, 0);
1390 uint64_t address = aarch64_get_reg_u64 (cpu, rn, SP_OK)
1391 + SCALE (offset, 64). */
1393 /* TODO : implement prefetch of address. */
1396 /* Prefetch scaled or unscaled zero- or sign-extended 32-bit register offset. */
1398 prfm_scale_ext (sim_cpu *cpu, Scaling scaling, Extension extension)
1400 /* instr[4,0] = prfop : 00000 ==> PLDL1KEEP, 00001 ==> PLDL1STRM,
1401 00010 ==> PLDL2KEEP, 00001 ==> PLDL2STRM,
1402 00100 ==> PLDL3KEEP, 00101 ==> PLDL3STRM,
1403 10000 ==> PSTL1KEEP, 10001 ==> PSTL1STRM,
1404 10010 ==> PSTL2KEEP, 10001 ==> PSTL2STRM,
1405 10100 ==> PSTL3KEEP, 10101 ==> PSTL3STRM,
1407 rn may reference SP, rm may only reference ZR
1408 PrfOp prfop = prfop (aarch64_get_instr (cpu), 4, 0);
1409 uint64_t base = aarch64_get_reg_u64 (cpu, rn, SP_OK);
1410 int64_t extended = extend (aarch64_get_reg_u32 (cpu, rm, NO_SP),
1412 uint64_t displacement = OPT_SCALE (extended, 64, scaling);
1413 uint64_t address = base + displacement. */
1415 /* TODO : implement prefetch of address */
1418 /* 64 bit pc-relative prefetch. */
1420 prfm_pcrel (sim_cpu *cpu, int32_t offset)
1422 /* instr[4,0] = prfop : 00000 ==> PLDL1KEEP, 00001 ==> PLDL1STRM,
1423 00010 ==> PLDL2KEEP, 00001 ==> PLDL2STRM,
1424 00100 ==> PLDL3KEEP, 00101 ==> PLDL3STRM,
1425 10000 ==> PSTL1KEEP, 10001 ==> PSTL1STRM,
1426 10010 ==> PSTL2KEEP, 10001 ==> PSTL2STRM,
1427 10100 ==> PSTL3KEEP, 10101 ==> PSTL3STRM,
1429 PrfOp prfop = prfop (aarch64_get_instr (cpu), 4, 0);
1430 uint64_t address = aarch64_get_PC (cpu) + offset. */
1432 /* TODO : implement this */
1435 /* Load-store exclusive. */
1440 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
1441 unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
1442 uint64_t address = aarch64_get_reg_u64 (cpu, rn, SP_OK);
1443 int size = uimm (aarch64_get_instr (cpu), 31, 30);
1444 /* int ordered = uimm (aarch64_get_instr (cpu), 15, 15); */
1445 /* int exclusive = ! uimm (aarch64_get_instr (cpu), 23, 23); */
1450 aarch64_set_reg_u64 (cpu, rt, NO_SP, aarch64_get_mem_u8 (cpu, address));
1453 aarch64_set_reg_u64 (cpu, rt, NO_SP, aarch64_get_mem_u16 (cpu, address));
1456 aarch64_set_reg_u64 (cpu, rt, NO_SP, aarch64_get_mem_u32 (cpu, address));
1459 aarch64_set_reg_u64 (cpu, rt, NO_SP, aarch64_get_mem_u64 (cpu, address));
1469 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
1470 unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
1471 unsigned rs = uimm (aarch64_get_instr (cpu), 20, 16);
1472 uint64_t address = aarch64_get_reg_u64 (cpu, rn, SP_OK);
1473 int size = uimm (aarch64_get_instr (cpu), 31, 30);
1474 uint64_t data = aarch64_get_reg_u64 (cpu, rt, NO_SP);
1478 case 0: aarch64_set_mem_u8 (cpu, address, data); break;
1479 case 1: aarch64_set_mem_u16 (cpu, address, data); break;
1480 case 2: aarch64_set_mem_u32 (cpu, address, data); break;
1481 case 3: aarch64_set_mem_u64 (cpu, address, data); break;
1482 default: HALT_UNALLOC;
1485 aarch64_set_reg_u64 (cpu, rs, NO_SP, 0); /* Always exclusive... */
1489 dexLoadLiteral (sim_cpu *cpu)
1491 /* instr[29,27] == 011
1493 instr[31,30:26] = opc: 000 ==> LDRW, 001 ==> FLDRS
1494 010 ==> LDRX, 011 ==> FLDRD
1495 100 ==> LDRSW, 101 ==> FLDRQ
1496 110 ==> PRFM, 111 ==> UNALLOC
1497 instr[26] ==> V : 0 ==> GReg, 1 ==> FReg
1498 instr[23, 5] == simm19 */
1500 /* unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0); */
1501 uint32_t dispatch = ( (uimm (aarch64_get_instr (cpu), 31, 30) << 1)
1502 | uimm (aarch64_get_instr (cpu), 26, 26));
1503 int32_t imm = simm32 (aarch64_get_instr (cpu), 23, 5);
1507 case 0: ldr32_pcrel (cpu, imm); break;
1508 case 1: fldrs_pcrel (cpu, imm); break;
1509 case 2: ldr_pcrel (cpu, imm); break;
1510 case 3: fldrd_pcrel (cpu, imm); break;
1511 case 4: ldrsw_pcrel (cpu, imm); break;
1512 case 5: fldrq_pcrel (cpu, imm); break;
1513 case 6: prfm_pcrel (cpu, imm); break;
1520 /* Immediate arithmetic
1521 The aimm argument is a 12 bit unsigned value or a 12 bit unsigned
1522 value left shifted by 12 bits (done at decode).
1524 N.B. the register args (dest, source) can normally be Xn or SP.
1525 the exception occurs for flag setting instructions which may
1526 only use Xn for the output (dest). */
1528 /* 32 bit add immediate. */
1530 add32 (sim_cpu *cpu, uint32_t aimm)
1532 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
1533 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
1535 aarch64_set_reg_u64 (cpu, rd, SP_OK,
1536 aarch64_get_reg_u32 (cpu, rn, SP_OK) + aimm);
1539 /* 64 bit add immediate. */
1541 add64 (sim_cpu *cpu, uint32_t aimm)
1543 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
1544 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
1546 aarch64_set_reg_u64 (cpu, rd, SP_OK,
1547 aarch64_get_reg_u64 (cpu, rn, SP_OK) + aimm);
1551 set_flags_for_add32 (sim_cpu *cpu, int32_t value1, int32_t value2)
1553 int32_t result = value1 + value2;
1554 int64_t sresult = (int64_t) value1 + (int64_t) value2;
1555 uint64_t uresult = (uint64_t)(uint32_t) value1
1556 + (uint64_t)(uint32_t) value2;
1562 if (result & (1 << 31))
1565 if (uresult != result)
1568 if (sresult != result)
1571 aarch64_set_CPSR (cpu, flags);
1575 set_flags_for_add64 (sim_cpu *cpu, uint64_t value1, uint64_t value2)
1577 int64_t sval1 = value1;
1578 int64_t sval2 = value2;
1579 uint64_t result = value1 + value2;
1580 int64_t sresult = sval1 + sval2;
1586 if (result & (1ULL << 63))
1593 /* Negative plus a negative. Overflow happens if
1594 the result is greater than either of the operands. */
1595 if (sresult > sval1 || sresult > sval2)
1598 /* else Negative plus a positive. Overflow cannot happen. */
1600 else /* value1 is +ve. */
1604 /* Overflow can only occur if we computed "0 - MININT". */
1605 if (sval1 == 0 && sval2 == (1LL << 63))
1610 /* Postive plus positive - overflow has happened if the
1611 result is smaller than either of the operands. */
1612 if (result < value1 || result < value2)
1617 aarch64_set_CPSR (cpu, flags);
1620 #define NEG(a) (((a) & signbit) == signbit)
1621 #define POS(a) (((a) & signbit) == 0)
1624 set_flags_for_sub32 (sim_cpu *cpu, uint32_t value1, uint32_t value2)
1626 uint32_t result = value1 - value2;
1628 uint32_t signbit = 1ULL << 31;
1636 if ( (NEG (value1) && POS (value2))
1637 || (NEG (value1) && POS (result))
1638 || (POS (value2) && POS (result)))
1641 if ( (NEG (value1) && POS (value2) && POS (result))
1642 || (POS (value1) && NEG (value2) && NEG (result)))
1645 aarch64_set_CPSR (cpu, flags);
1649 set_flags_for_sub64 (sim_cpu *cpu, uint64_t value1, uint64_t value2)
1651 uint64_t result = value1 - value2;
1653 uint64_t signbit = 1ULL << 63;
1661 if ( (NEG (value1) && POS (value2))
1662 || (NEG (value1) && POS (result))
1663 || (POS (value2) && POS (result)))
1666 if ( (NEG (value1) && POS (value2) && POS (result))
1667 || (POS (value1) && NEG (value2) && NEG (result)))
1670 aarch64_set_CPSR (cpu, flags);
1674 set_flags_for_binop32 (sim_cpu *cpu, uint32_t result)
1683 if (result & (1 << 31))
1688 aarch64_set_CPSR (cpu, flags);
1692 set_flags_for_binop64 (sim_cpu *cpu, uint64_t result)
1701 if (result & (1ULL << 63))
1706 aarch64_set_CPSR (cpu, flags);
1709 /* 32 bit add immediate set flags. */
1711 adds32 (sim_cpu *cpu, uint32_t aimm)
1713 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
1714 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
1715 /* TODO : do we need to worry about signs here? */
1716 int32_t value1 = aarch64_get_reg_s32 (cpu, rn, SP_OK);
1718 aarch64_set_reg_u64 (cpu, rd, NO_SP, value1 + aimm);
1719 set_flags_for_add32 (cpu, value1, aimm);
1722 /* 64 bit add immediate set flags. */
1724 adds64 (sim_cpu *cpu, uint32_t aimm)
1726 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
1727 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
1728 uint64_t value1 = aarch64_get_reg_u64 (cpu, rn, SP_OK);
1729 uint64_t value2 = aimm;
1731 aarch64_set_reg_u64 (cpu, rd, NO_SP, value1 + value2);
1732 set_flags_for_add64 (cpu, value1, value2);
1735 /* 32 bit sub immediate. */
1737 sub32 (sim_cpu *cpu, uint32_t aimm)
1739 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
1740 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
1742 aarch64_set_reg_u64 (cpu, rd, SP_OK,
1743 aarch64_get_reg_u32 (cpu, rn, SP_OK) - aimm);
1746 /* 64 bit sub immediate. */
1748 sub64 (sim_cpu *cpu, uint32_t aimm)
1750 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
1751 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
1753 aarch64_set_reg_u64 (cpu, rd, SP_OK,
1754 aarch64_get_reg_u64 (cpu, rn, SP_OK) - aimm);
1757 /* 32 bit sub immediate set flags. */
1759 subs32 (sim_cpu *cpu, uint32_t aimm)
1761 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
1762 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
1763 uint32_t value1 = aarch64_get_reg_u64 (cpu, rn, SP_OK);
1764 uint32_t value2 = aimm;
1766 aarch64_set_reg_u64 (cpu, rd, NO_SP, value1 - value2);
1767 set_flags_for_sub32 (cpu, value1, value2);
1770 /* 64 bit sub immediate set flags. */
1772 subs64 (sim_cpu *cpu, uint32_t aimm)
1774 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
1775 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
1776 uint64_t value1 = aarch64_get_reg_u64 (cpu, rn, SP_OK);
1777 uint32_t value2 = aimm;
1779 aarch64_set_reg_u64 (cpu, rd, NO_SP, value1 - value2);
1780 set_flags_for_sub64 (cpu, value1, value2);
1783 /* Data Processing Register. */
1785 /* First two helpers to perform the shift operations. */
1787 static inline uint32_t
1788 shifted32 (uint32_t value, Shift shift, uint32_t count)
1794 return (value << count);
1796 return (value >> count);
1799 int32_t svalue = value;
1800 return (svalue >> count);
1804 uint32_t top = value >> count;
1805 uint32_t bottom = value << (32 - count);
1806 return (bottom | top);
1811 static inline uint64_t
1812 shifted64 (uint64_t value, Shift shift, uint32_t count)
1818 return (value << count);
1820 return (value >> count);
1823 int64_t svalue = value;
1824 return (svalue >> count);
1828 uint64_t top = value >> count;
1829 uint64_t bottom = value << (64 - count);
1830 return (bottom | top);
1835 /* Arithmetic shifted register.
1836 These allow an optional LSL, ASR or LSR to the second source
1837 register with a count up to the register bit count.
1839 N.B register args may not be SP. */
1841 /* 32 bit ADD shifted register. */
1843 add32_shift (sim_cpu *cpu, Shift shift, uint32_t count)
1845 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
1846 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
1847 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
1849 aarch64_set_reg_u64 (cpu, rd, NO_SP,
1850 aarch64_get_reg_u32 (cpu, rn, NO_SP)
1851 + shifted32 (aarch64_get_reg_u32 (cpu, rm, NO_SP),
1855 /* 64 bit ADD shifted register. */
1857 add64_shift (sim_cpu *cpu, Shift shift, uint32_t count)
1859 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
1860 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
1861 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
1863 aarch64_set_reg_u64 (cpu, rd, NO_SP,
1864 aarch64_get_reg_u64 (cpu, rn, NO_SP)
1865 + shifted64 (aarch64_get_reg_u64 (cpu, rm, NO_SP),
1869 /* 32 bit ADD shifted register setting flags. */
1871 adds32_shift (sim_cpu *cpu, Shift shift, uint32_t count)
1873 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
1874 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
1875 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
1877 uint32_t value1 = aarch64_get_reg_u32 (cpu, rn, NO_SP);
1878 uint32_t value2 = shifted32 (aarch64_get_reg_u32 (cpu, rm, NO_SP),
1881 aarch64_set_reg_u64 (cpu, rd, NO_SP, value1 + value2);
1882 set_flags_for_add32 (cpu, value1, value2);
1885 /* 64 bit ADD shifted register setting flags. */
1887 adds64_shift (sim_cpu *cpu, Shift shift, uint32_t count)
1889 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
1890 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
1891 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
1893 uint64_t value1 = aarch64_get_reg_u64 (cpu, rn, NO_SP);
1894 uint64_t value2 = shifted64 (aarch64_get_reg_u64 (cpu, rm, NO_SP),
1897 aarch64_set_reg_u64 (cpu, rd, NO_SP, value1 + value2);
1898 set_flags_for_add64 (cpu, value1, value2);
1901 /* 32 bit SUB shifted register. */
1903 sub32_shift (sim_cpu *cpu, Shift shift, uint32_t count)
1905 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
1906 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
1907 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
1909 aarch64_set_reg_u64 (cpu, rd, NO_SP,
1910 aarch64_get_reg_u32 (cpu, rn, NO_SP)
1911 - shifted32 (aarch64_get_reg_u32 (cpu, rm, NO_SP),
1915 /* 64 bit SUB shifted register. */
1917 sub64_shift (sim_cpu *cpu, Shift shift, uint32_t count)
1919 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
1920 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
1921 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
1923 aarch64_set_reg_u64 (cpu, rd, NO_SP,
1924 aarch64_get_reg_u64 (cpu, rn, NO_SP)
1925 - shifted64 (aarch64_get_reg_u64 (cpu, rm, NO_SP),
1929 /* 32 bit SUB shifted register setting flags. */
1931 subs32_shift (sim_cpu *cpu, Shift shift, uint32_t count)
1933 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
1934 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
1935 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
1937 uint32_t value1 = aarch64_get_reg_u32 (cpu, rn, NO_SP);
1938 uint32_t value2 = shifted32 (aarch64_get_reg_u32 (cpu, rm, NO_SP),
1941 aarch64_set_reg_u64 (cpu, rd, NO_SP, value1 - value2);
1942 set_flags_for_sub32 (cpu, value1, value2);
1945 /* 64 bit SUB shifted register setting flags. */
1947 subs64_shift (sim_cpu *cpu, Shift shift, uint32_t count)
1949 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
1950 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
1951 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
1953 uint64_t value1 = aarch64_get_reg_u64 (cpu, rn, NO_SP);
1954 uint64_t value2 = shifted64 (aarch64_get_reg_u64 (cpu, rm, NO_SP),
1957 aarch64_set_reg_u64 (cpu, rd, NO_SP, value1 - value2);
1958 set_flags_for_sub64 (cpu, value1, value2);
1961 /* First a couple more helpers to fetch the
1962 relevant source register element either
1963 sign or zero extended as required by the
1967 extreg32 (sim_cpu *cpu, unsigned int lo, Extension extension)
1971 case UXTB: return aarch64_get_reg_u8 (cpu, lo, NO_SP);
1972 case UXTH: return aarch64_get_reg_u16 (cpu, lo, NO_SP);
1973 case UXTW: /* Fall through. */
1974 case UXTX: return aarch64_get_reg_u32 (cpu, lo, NO_SP);
1975 case SXTB: return aarch64_get_reg_s8 (cpu, lo, NO_SP);
1976 case SXTH: return aarch64_get_reg_s16 (cpu, lo, NO_SP);
1977 case SXTW: /* Fall through. */
1978 case SXTX: /* Fall through. */
1979 default: return aarch64_get_reg_s32 (cpu, lo, NO_SP);
1984 extreg64 (sim_cpu *cpu, unsigned int lo, Extension extension)
1988 case UXTB: return aarch64_get_reg_u8 (cpu, lo, NO_SP);
1989 case UXTH: return aarch64_get_reg_u16 (cpu, lo, NO_SP);
1990 case UXTW: return aarch64_get_reg_u32 (cpu, lo, NO_SP);
1991 case UXTX: return aarch64_get_reg_u64 (cpu, lo, NO_SP);
1992 case SXTB: return aarch64_get_reg_s8 (cpu, lo, NO_SP);
1993 case SXTH: return aarch64_get_reg_s16 (cpu, lo, NO_SP);
1994 case SXTW: return aarch64_get_reg_s32 (cpu, lo, NO_SP);
1996 default: return aarch64_get_reg_s64 (cpu, lo, NO_SP);
2000 /* Arithmetic extending register
2001 These allow an optional sign extension of some portion of the
2002 second source register followed by an optional left shift of
2003 between 1 and 4 bits (i.e. a shift of 0-4 bits???)
2005 N.B output (dest) and first input arg (source) may normally be Xn
2006 or SP. However, for flag setting operations dest can only be
2007 Xn. Second input registers are always Xn. */
2009 /* 32 bit ADD extending register. */
2011 add32_ext (sim_cpu *cpu, Extension extension, uint32_t shift)
2013 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
2014 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
2015 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
2017 aarch64_set_reg_u64 (cpu, rd, SP_OK,
2018 aarch64_get_reg_u32 (cpu, rn, SP_OK)
2019 + (extreg32 (cpu, rm, extension) << shift));
2022 /* 64 bit ADD extending register.
2023 N.B. This subsumes the case with 64 bit source2 and UXTX #n or LSL #0. */
2025 add64_ext (sim_cpu *cpu, Extension extension, uint32_t shift)
2027 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
2028 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
2029 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
2031 aarch64_set_reg_u64 (cpu, rd, SP_OK,
2032 aarch64_get_reg_u64 (cpu, rn, SP_OK)
2033 + (extreg64 (cpu, rm, extension) << shift));
2036 /* 32 bit ADD extending register setting flags. */
2038 adds32_ext (sim_cpu *cpu, Extension extension, uint32_t shift)
2040 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
2041 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
2042 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
2044 uint32_t value1 = aarch64_get_reg_u32 (cpu, rn, SP_OK);
2045 uint32_t value2 = extreg32 (cpu, rm, extension) << shift;
2047 aarch64_set_reg_u64 (cpu, rd, NO_SP, value1 + value2);
2048 set_flags_for_add32 (cpu, value1, value2);
2051 /* 64 bit ADD extending register setting flags */
2052 /* N.B. this subsumes the case with 64 bit source2 and UXTX #n or LSL #0 */
2054 adds64_ext (sim_cpu *cpu, Extension extension, uint32_t shift)
2056 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
2057 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
2058 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
2060 uint64_t value1 = aarch64_get_reg_u64 (cpu, rn, SP_OK);
2061 uint64_t value2 = extreg64 (cpu, rm, extension) << shift;
2063 aarch64_set_reg_u64 (cpu, rd, NO_SP, value1 + value2);
2064 set_flags_for_add64 (cpu, value1, value2);
2067 /* 32 bit SUB extending register. */
2069 sub32_ext (sim_cpu *cpu, Extension extension, uint32_t shift)
2071 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
2072 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
2073 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
2075 aarch64_set_reg_u64 (cpu, rd, SP_OK,
2076 aarch64_get_reg_u32 (cpu, rn, SP_OK)
2077 - (extreg32 (cpu, rm, extension) << shift));
2080 /* 64 bit SUB extending register. */
2081 /* N.B. this subsumes the case with 64 bit source2 and UXTX #n or LSL #0. */
2083 sub64_ext (sim_cpu *cpu, Extension extension, uint32_t shift)
2085 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
2086 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
2087 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
2089 aarch64_set_reg_u64 (cpu, rd, SP_OK,
2090 aarch64_get_reg_u64 (cpu, rn, SP_OK)
2091 - (extreg64 (cpu, rm, extension) << shift));
2094 /* 32 bit SUB extending register setting flags. */
2096 subs32_ext (sim_cpu *cpu, Extension extension, uint32_t shift)
2098 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
2099 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
2100 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
2102 uint32_t value1 = aarch64_get_reg_u32 (cpu, rn, SP_OK);
2103 uint32_t value2 = extreg32 (cpu, rm, extension) << shift;
2105 aarch64_set_reg_u64 (cpu, rd, NO_SP, value1 - value2);
2106 set_flags_for_sub32 (cpu, value1, value2);
2109 /* 64 bit SUB extending register setting flags */
2110 /* N.B. this subsumes the case with 64 bit source2 and UXTX #n or LSL #0 */
2112 subs64_ext (sim_cpu *cpu, Extension extension, uint32_t shift)
2114 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
2115 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
2116 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
2118 uint64_t value1 = aarch64_get_reg_u64 (cpu, rn, SP_OK);
2119 uint64_t value2 = extreg64 (cpu, rm, extension) << shift;
2121 aarch64_set_reg_u64 (cpu, rd, NO_SP, value1 - value2);
2122 set_flags_for_sub64 (cpu, value1, value2);
2126 dexAddSubtractImmediate (sim_cpu *cpu)
2128 /* instr[31] = size : 0 ==> 32 bit, 1 ==> 64 bit
2129 instr[30] = op : 0 ==> ADD, 1 ==> SUB
2130 instr[29] = set : 0 ==> no flags, 1 ==> set flags
2131 instr[28,24] = 10001
2132 instr[23,22] = shift : 00 == LSL#0, 01 = LSL#12 1x = UNALLOC
2133 instr[21,10] = uimm12
2137 /* N.B. the shift is applied at decode before calling the add/sub routine. */
2138 uint32_t shift = uimm (aarch64_get_instr (cpu), 23, 22);
2139 uint32_t imm = uimm (aarch64_get_instr (cpu), 21, 10);
2140 uint32_t dispatch = uimm (aarch64_get_instr (cpu), 31, 29);
2142 NYI_assert (28, 24, 0x11);
2152 case 0: add32 (cpu, imm); break;
2153 case 1: adds32 (cpu, imm); break;
2154 case 2: sub32 (cpu, imm); break;
2155 case 3: subs32 (cpu, imm); break;
2156 case 4: add64 (cpu, imm); break;
2157 case 5: adds64 (cpu, imm); break;
2158 case 6: sub64 (cpu, imm); break;
2159 case 7: subs64 (cpu, imm); break;
2166 dexAddSubtractShiftedRegister (sim_cpu *cpu)
2168 /* instr[31] = size : 0 ==> 32 bit, 1 ==> 64 bit
2169 instr[30,29] = op : 00 ==> ADD, 01 ==> ADDS, 10 ==> SUB, 11 ==> SUBS
2170 instr[28,24] = 01011
2171 instr[23,22] = shift : 0 ==> LSL, 1 ==> LSR, 2 ==> ASR, 3 ==> UNALLOC
2174 instr[15,10] = count : must be 0xxxxx for 32 bit
2178 uint32_t size = uimm (aarch64_get_instr (cpu), 31, 31);
2179 /* 32 bit operations must have count[5] = 0
2180 or else we have an UNALLOC. */
2181 uint32_t count = uimm (aarch64_get_instr (cpu), 15, 10);
2182 /* Shift encoded as ROR is unallocated. */
2183 Shift shiftType = shift (aarch64_get_instr (cpu), 22);
2184 /* Dispatch on size:op i.e aarch64_get_instr (cpu)[31,29]. */
2185 uint32_t dispatch = uimm (aarch64_get_instr (cpu), 31, 29);
2187 NYI_assert (28, 24, 0x0B);
2188 NYI_assert (21, 21, 0);
2190 if (shiftType == ROR)
2193 if (!size && uimm (count, 5, 5))
2198 case 0: add32_shift (cpu, shiftType, count); break;
2199 case 1: adds32_shift (cpu, shiftType, count); break;
2200 case 2: sub32_shift (cpu, shiftType, count); break;
2201 case 3: subs32_shift (cpu, shiftType, count); break;
2202 case 4: add64_shift (cpu, shiftType, count); break;
2203 case 5: adds64_shift (cpu, shiftType, count); break;
2204 case 6: sub64_shift (cpu, shiftType, count); break;
2205 case 7: subs64_shift (cpu, shiftType, count); break;
2212 dexAddSubtractExtendedRegister (sim_cpu *cpu)
2214 /* instr[31] = size : 0 ==> 32 bit, 1 ==> 64 bit
2215 instr[30] = op : 0 ==> ADD, 1 ==> SUB
2216 instr[29] = set? : 0 ==> no flags, 1 ==> set flags
2217 instr[28,24] = 01011
2218 instr[23,22] = opt : 0 ==> ok, 1,2,3 ==> UNALLOC
2221 instr[15,13] = option : 000 ==> UXTB, 001 ==> UXTH,
2222 000 ==> LSL|UXTW, 001 ==> UXTZ,
2223 000 ==> SXTB, 001 ==> SXTH,
2224 000 ==> SXTW, 001 ==> SXTX,
2225 instr[12,10] = shift : 0,1,2,3,4 ==> ok, 5,6,7 ==> UNALLOC
2229 Extension extensionType = extension (aarch64_get_instr (cpu), 13);
2230 uint32_t shift = uimm (aarch64_get_instr (cpu), 12, 10);
2231 /* dispatch on size:op:set? i.e aarch64_get_instr (cpu)[31,29] */
2232 uint32_t dispatch = uimm (aarch64_get_instr (cpu), 31, 29);
2234 NYI_assert (28, 24, 0x0B);
2235 NYI_assert (21, 21, 1);
2237 /* Shift may not exceed 4. */
2243 case 0: add32_ext (cpu, extensionType, shift); break;
2244 case 1: adds32_ext (cpu, extensionType, shift); break;
2245 case 2: sub32_ext (cpu, extensionType, shift); break;
2246 case 3: subs32_ext (cpu, extensionType, shift); break;
2247 case 4: add64_ext (cpu, extensionType, shift); break;
2248 case 5: adds64_ext (cpu, extensionType, shift); break;
2249 case 6: sub64_ext (cpu, extensionType, shift); break;
2250 case 7: subs64_ext (cpu, extensionType, shift); break;
2251 default: HALT_UNALLOC;
2255 /* Conditional data processing
2256 Condition register is implicit 3rd source. */
2258 /* 32 bit add with carry. */
2259 /* N.B register args may not be SP. */
2262 adc32 (sim_cpu *cpu)
2264 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
2265 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
2266 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
2268 aarch64_set_reg_u64 (cpu, rd, NO_SP,
2269 aarch64_get_reg_u32 (cpu, rn, NO_SP)
2270 + aarch64_get_reg_u32 (cpu, rm, NO_SP)
2274 /* 64 bit add with carry */
2276 adc64 (sim_cpu *cpu)
2278 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
2279 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
2280 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
2282 aarch64_set_reg_u64 (cpu, rd, NO_SP,
2283 aarch64_get_reg_u64 (cpu, rn, NO_SP)
2284 + aarch64_get_reg_u64 (cpu, rm, NO_SP)
2288 /* 32 bit add with carry setting flags. */
2290 adcs32 (sim_cpu *cpu)
2292 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
2293 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
2294 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
2296 uint32_t value1 = aarch64_get_reg_u32 (cpu, rn, NO_SP);
2297 uint32_t value2 = aarch64_get_reg_u32 (cpu, rm, NO_SP);
2298 uint32_t carry = IS_SET (C);
2300 aarch64_set_reg_u64 (cpu, rd, NO_SP, value1 + value2 + carry);
2301 set_flags_for_add32 (cpu, value1, value2 + carry);
2304 /* 64 bit add with carry setting flags. */
2306 adcs64 (sim_cpu *cpu)
2308 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
2309 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
2310 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
2312 uint64_t value1 = aarch64_get_reg_u64 (cpu, rn, NO_SP);
2313 uint64_t value2 = aarch64_get_reg_u64 (cpu, rm, NO_SP);
2314 uint64_t carry = IS_SET (C);
2316 aarch64_set_reg_u64 (cpu, rd, NO_SP, value1 + value2 + carry);
2317 set_flags_for_add64 (cpu, value1, value2 + carry);
2320 /* 32 bit sub with carry. */
2322 sbc32 (sim_cpu *cpu)
2324 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
2325 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
2326 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
2328 aarch64_set_reg_u64 (cpu, rd, NO_SP,
2329 aarch64_get_reg_u32 (cpu, rn, NO_SP)
2330 - aarch64_get_reg_u32 (cpu, rm, NO_SP)
2334 /* 64 bit sub with carry */
2336 sbc64 (sim_cpu *cpu)
2338 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
2339 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
2340 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
2342 aarch64_set_reg_u64 (cpu, rd, NO_SP,
2343 aarch64_get_reg_u64 (cpu, rn, NO_SP)
2344 - aarch64_get_reg_u64 (cpu, rm, NO_SP)
2348 /* 32 bit sub with carry setting flags */
2350 sbcs32 (sim_cpu *cpu)
2352 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
2353 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
2354 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
2356 uint32_t value1 = aarch64_get_reg_u32 (cpu, rn, NO_SP);
2357 uint32_t value2 = aarch64_get_reg_u32 (cpu, rm, NO_SP);
2358 uint32_t carry = IS_SET (C);
2359 uint32_t result = value1 - value2 + 1 - carry;
2361 aarch64_set_reg_u64 (cpu, rd, NO_SP, result);
2362 set_flags_for_sub32 (cpu, value1, value2 + 1 - carry);
2365 /* 64 bit sub with carry setting flags */
2367 sbcs64 (sim_cpu *cpu)
2369 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
2370 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
2371 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
2373 uint64_t value1 = aarch64_get_reg_u64 (cpu, rn, NO_SP);
2374 uint64_t value2 = aarch64_get_reg_u64 (cpu, rm, NO_SP);
2375 uint64_t carry = IS_SET (C);
2376 uint64_t result = value1 - value2 + 1 - carry;
2378 aarch64_set_reg_u64 (cpu, rd, NO_SP, result);
2379 set_flags_for_sub64 (cpu, value1, value2 + 1 - carry);
2383 dexAddSubtractWithCarry (sim_cpu *cpu)
2385 /* instr[31] = size : 0 ==> 32 bit, 1 ==> 64 bit
2386 instr[30] = op : 0 ==> ADC, 1 ==> SBC
2387 instr[29] = set? : 0 ==> no flags, 1 ==> set flags
2388 instr[28,21] = 1 1010 000
2390 instr[15,10] = op2 : 00000 ==> ok, ow ==> UNALLOC
2394 uint32_t op2 = uimm (aarch64_get_instr (cpu), 15, 10);
2395 /* Dispatch on size:op:set? i.e aarch64_get_instr (cpu)[31,29] */
2396 uint32_t dispatch = uimm (aarch64_get_instr (cpu), 31, 29);
2398 NYI_assert (28, 21, 0xD0);
2405 case 0: adc32 (cpu); break;
2406 case 1: adcs32 (cpu); break;
2407 case 2: sbc32 (cpu); break;
2408 case 3: sbcs32 (cpu); break;
2409 case 4: adc64 (cpu); break;
2410 case 5: adcs64 (cpu); break;
2411 case 6: sbc64 (cpu); break;
2412 case 7: sbcs64 (cpu); break;
2413 default: HALT_UNALLOC;
2418 testConditionCode (sim_cpu *cpu, CondCode cc)
2420 /* This should be reduceable to branchless logic
2421 by some careful testing of bits in CC followed
2422 by the requisite masking and combining of bits
2423 from the flag register.
2425 For now we do it with a switch. */
2430 case EQ: res = IS_SET (Z); break;
2431 case NE: res = IS_CLEAR (Z); break;
2432 case CS: res = IS_SET (C); break;
2433 case CC: res = IS_CLEAR (C); break;
2434 case MI: res = IS_SET (N); break;
2435 case PL: res = IS_CLEAR (N); break;
2436 case VS: res = IS_SET (V); break;
2437 case VC: res = IS_CLEAR (V); break;
2438 case HI: res = IS_SET (C) && IS_CLEAR (Z); break;
2439 case LS: res = IS_CLEAR (C) || IS_SET (Z); break;
2440 case GE: res = IS_SET (N) == IS_SET (V); break;
2441 case LT: res = IS_SET (N) != IS_SET (V); break;
2442 case GT: res = IS_CLEAR (Z) && (IS_SET (N) == IS_SET (V)); break;
2443 case LE: res = IS_SET (Z) || (IS_SET (N) != IS_SET (V)); break;
2454 CondCompare (sim_cpu *cpu) /* aka: ccmp and ccmn */
2456 /* instr[31] = size : 0 ==> 32 bit, 1 ==> 64 bit
2457 instr[30] = compare with positive (0) or negative value (1)
2458 instr[29,21] = 1 1101 0010
2459 instr[20,16] = Rm or const
2461 instr[11] = compare reg (0) or const (1)
2465 instr[3,0] = value for CPSR bits if the comparison does not take place. */
2470 NYI_assert (29, 21, 0x1d2);
2471 NYI_assert (10, 10, 0);
2472 NYI_assert (4, 4, 0);
2474 if (! testConditionCode (cpu, uimm (aarch64_get_instr (cpu), 15, 12)))
2476 aarch64_set_CPSR (cpu, uimm (aarch64_get_instr (cpu), 3, 0));
2480 negate = uimm (aarch64_get_instr (cpu), 30, 30) ? -1 : 1;
2481 rm = uimm (aarch64_get_instr (cpu), 20, 16);
2482 rn = uimm (aarch64_get_instr (cpu), 9, 5);
2484 if (uimm (aarch64_get_instr (cpu), 31, 31))
2486 if (uimm (aarch64_get_instr (cpu), 11, 11))
2487 set_flags_for_sub64 (cpu, aarch64_get_reg_u64 (cpu, rn, SP_OK),
2488 negate * (uint64_t) rm);
2490 set_flags_for_sub64 (cpu, aarch64_get_reg_u64 (cpu, rn, SP_OK),
2491 negate * aarch64_get_reg_u64 (cpu, rm, SP_OK));
2495 if (uimm (aarch64_get_instr (cpu), 11, 11))
2496 set_flags_for_sub32 (cpu, aarch64_get_reg_u32 (cpu, rn, SP_OK),
2499 set_flags_for_sub32 (cpu, aarch64_get_reg_u32 (cpu, rn, SP_OK),
2500 negate * aarch64_get_reg_u32 (cpu, rm, SP_OK));
2505 do_vec_MOV_whole_vector (sim_cpu *cpu)
2507 /* MOV Vd.T, Vs.T (alias for ORR Vd.T, Vn.T, Vm.T where Vn == Vm)
2510 instr[30] = half(0)/full(1)
2511 instr[29,21] = 001110101
2513 instr[15,10] = 000111
2517 unsigned vs = uimm (aarch64_get_instr (cpu), 9, 5);
2518 unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
2520 NYI_assert (29, 21, 0x075);
2521 NYI_assert (15, 10, 0x07);
2523 if (uimm (aarch64_get_instr (cpu), 20, 16) != vs)
2526 if (uimm (aarch64_get_instr (cpu), 30, 30))
2527 aarch64_set_vec_u64 (cpu, vd, 1, aarch64_get_vec_u64 (cpu, vs, 1));
2529 aarch64_set_vec_u64 (cpu, vd, 0, aarch64_get_vec_u64 (cpu, vs, 0));
2533 do_vec_MOV_into_scalar (sim_cpu *cpu)
2536 instr[30] = word(0)/long(1)
2537 instr[29,21] = 00 1110 000
2538 instr[20,18] = element size and index
2539 instr[17,10] = 00 0011 11
2540 instr[9,5] = V source
2541 instr[4,0] = R dest */
2543 unsigned vs = uimm (aarch64_get_instr (cpu), 9, 5);
2544 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
2546 NYI_assert (29, 21, 0x070);
2547 NYI_assert (17, 10, 0x0F);
2549 switch (uimm (aarch64_get_instr (cpu), 20, 18))
2552 aarch64_set_reg_u64 (cpu, rd, NO_SP, aarch64_get_vec_u64 (cpu, vs, 0));
2556 aarch64_set_reg_u64 (cpu, rd, NO_SP, aarch64_get_vec_u64 (cpu, vs, 1));
2563 aarch64_set_reg_u64 (cpu, rd, NO_SP, aarch64_get_vec_u32
2564 (cpu, vs, uimm (aarch64_get_instr (cpu), 20, 19)));
2573 do_vec_INS (sim_cpu *cpu)
2575 /* instr[31,21] = 01001110000
2576 instr[20,16] = element size and index
2577 instr[15,10] = 000111
2578 instr[9,5] = W source
2579 instr[4,0] = V dest */
2582 unsigned rs = uimm (aarch64_get_instr (cpu), 9, 5);
2583 unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
2585 NYI_assert (31, 21, 0x270);
2586 NYI_assert (15, 10, 0x07);
2588 if (uimm (aarch64_get_instr (cpu), 16, 16))
2590 index = uimm (aarch64_get_instr (cpu), 20, 17);
2591 aarch64_set_vec_u8 (cpu, vd, index,
2592 aarch64_get_reg_u8 (cpu, rs, NO_SP));
2594 else if (uimm (aarch64_get_instr (cpu), 17, 17))
2596 index = uimm (aarch64_get_instr (cpu), 20, 18);
2597 aarch64_set_vec_u16 (cpu, vd, index,
2598 aarch64_get_reg_u16 (cpu, rs, NO_SP));
2600 else if (uimm (aarch64_get_instr (cpu), 18, 18))
2602 index = uimm (aarch64_get_instr (cpu), 20, 19);
2603 aarch64_set_vec_u32 (cpu, vd, index,
2604 aarch64_get_reg_u32 (cpu, rs, NO_SP));
2606 else if (uimm (aarch64_get_instr (cpu), 19, 19))
2608 index = uimm (aarch64_get_instr (cpu), 20, 20);
2609 aarch64_set_vec_u64 (cpu, vd, index,
2610 aarch64_get_reg_u64 (cpu, rs, NO_SP));
2617 do_vec_DUP_vector_into_vector (sim_cpu *cpu)
2620 instr[30] = half(0)/full(1)
2621 instr[29,21] = 00 1110 000
2622 instr[20,16] = element size and index
2623 instr[15,10] = 0000 01
2624 instr[9,5] = V source
2625 instr[4,0] = V dest. */
2627 unsigned full = uimm (aarch64_get_instr (cpu), 30, 30);
2628 unsigned vs = uimm (aarch64_get_instr (cpu), 9, 5);
2629 unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
2632 NYI_assert (29, 21, 0x070);
2633 NYI_assert (15, 10, 0x01);
2635 if (uimm (aarch64_get_instr (cpu), 16, 16))
2637 index = uimm (aarch64_get_instr (cpu), 20, 17);
2639 for (i = 0; i < (full ? 16 : 8); i++)
2640 aarch64_set_vec_u8 (cpu, vd, i, aarch64_get_vec_u8 (cpu, vs, index));
2642 else if (uimm (aarch64_get_instr (cpu), 17, 17))
2644 index = uimm (aarch64_get_instr (cpu), 20, 18);
2646 for (i = 0; i < (full ? 8 : 4); i++)
2647 aarch64_set_vec_u16 (cpu, vd, i, aarch64_get_vec_u16 (cpu, vs, index));
2649 else if (uimm (aarch64_get_instr (cpu), 18, 18))
2651 index = uimm (aarch64_get_instr (cpu), 20, 19);
2653 for (i = 0; i < (full ? 4 : 2); i++)
2654 aarch64_set_vec_u32 (cpu, vd, i, aarch64_get_vec_u32 (cpu, vs, index));
2658 if (uimm (aarch64_get_instr (cpu), 19, 19) == 0)
2664 index = uimm (aarch64_get_instr (cpu), 20, 20);
2666 for (i = 0; i < 2; i++)
2667 aarch64_set_vec_u64 (cpu, vd, i, aarch64_get_vec_u64 (cpu, vs, index));
2672 do_vec_TBL (sim_cpu *cpu)
2675 instr[30] = half(0)/full(1)
2676 instr[29,21] = 00 1110 000
2679 instr[14,13] = vec length
2681 instr[9,5] = V start
2682 instr[4,0] = V dest */
2684 int full = uimm (aarch64_get_instr (cpu), 30, 30);
2685 int len = uimm (aarch64_get_instr (cpu), 14, 13) + 1;
2686 unsigned vm = uimm (aarch64_get_instr (cpu), 20, 16);
2687 unsigned vn = uimm (aarch64_get_instr (cpu), 9, 5);
2688 unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
2691 NYI_assert (29, 21, 0x070);
2692 NYI_assert (12, 10, 0);
2694 for (i = 0; i < (full ? 16 : 8); i++)
2696 unsigned int selector = aarch64_get_vec_u8 (cpu, vm, i);
2700 val = aarch64_get_vec_u8 (cpu, vn, selector);
2701 else if (selector < 32)
2702 val = len < 2 ? 0 : aarch64_get_vec_u8 (cpu, vn + 1, selector - 16);
2703 else if (selector < 48)
2704 val = len < 3 ? 0 : aarch64_get_vec_u8 (cpu, vn + 2, selector - 32);
2705 else if (selector < 64)
2706 val = len < 4 ? 0 : aarch64_get_vec_u8 (cpu, vn + 3, selector - 48);
2710 aarch64_set_vec_u8 (cpu, vd, i, val);
2715 do_vec_TRN (sim_cpu *cpu)
2718 instr[30] = half(0)/full(1)
2719 instr[29,24] = 00 1110
2724 instr[14] = TRN1 (0) / TRN2 (1)
2726 instr[9,5] = V source
2727 instr[4,0] = V dest. */
2729 int full = uimm (aarch64_get_instr (cpu), 30, 30);
2730 int second = uimm (aarch64_get_instr (cpu), 14, 14);
2731 unsigned vm = uimm (aarch64_get_instr (cpu), 20, 16);
2732 unsigned vn = uimm (aarch64_get_instr (cpu), 9, 5);
2733 unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
2736 NYI_assert (29, 24, 0x0E);
2737 NYI_assert (13, 10, 0xA);
2739 switch (uimm (aarch64_get_instr (cpu), 23, 22))
2742 for (i = 0; i < (full ? 8 : 4); i++)
2746 aarch64_get_vec_u8 (cpu, second ? vm : vn, i * 2));
2748 (cpu, vd, 1 * 2 + 1,
2749 aarch64_get_vec_u8 (cpu, second ? vn : vm, i * 2 + 1));
2754 for (i = 0; i < (full ? 4 : 2); i++)
2758 aarch64_get_vec_u16 (cpu, second ? vm : vn, i * 2));
2760 (cpu, vd, 1 * 2 + 1,
2761 aarch64_get_vec_u16 (cpu, second ? vn : vm, i * 2 + 1));
2767 (cpu, vd, 0, aarch64_get_vec_u32 (cpu, second ? vm : vn, 0));
2769 (cpu, vd, 1, aarch64_get_vec_u32 (cpu, second ? vn : vm, 1));
2771 (cpu, vd, 2, aarch64_get_vec_u32 (cpu, second ? vm : vn, 2));
2773 (cpu, vd, 3, aarch64_get_vec_u32 (cpu, second ? vn : vm, 3));
2780 aarch64_set_vec_u64 (cpu, vd, 0,
2781 aarch64_get_vec_u64 (cpu, second ? vm : vn, 0));
2782 aarch64_set_vec_u64 (cpu, vd, 1,
2783 aarch64_get_vec_u64 (cpu, second ? vn : vm, 1));
2792 do_vec_DUP_scalar_into_vector (sim_cpu *cpu)
2795 instr[30] = 0=> zero top 64-bits, 1=> duplicate into top 64-bits
2796 [must be 1 for 64-bit xfer]
2797 instr[29,20] = 00 1110 0000
2798 instr[19,16] = element size: 0001=> 8-bits, 0010=> 16-bits,
2799 0100=> 32-bits. 1000=>64-bits
2800 instr[15,10] = 0000 11
2801 instr[9,5] = W source
2802 instr[4,0] = V dest. */
2805 unsigned Vd = uimm (aarch64_get_instr (cpu), 4, 0);
2806 unsigned Rs = uimm (aarch64_get_instr (cpu), 9, 5);
2807 int both = uimm (aarch64_get_instr (cpu), 30, 30);
2809 NYI_assert (29, 20, 0x0E0);
2810 NYI_assert (15, 10, 0x03);
2812 switch (uimm (aarch64_get_instr (cpu), 19, 16))
2815 for (i = 0; i < (both ? 16 : 8); i++)
2816 aarch64_set_vec_u8 (cpu, Vd, i, aarch64_get_reg_u8 (cpu, Rs, NO_SP));
2820 for (i = 0; i < (both ? 8 : 4); i++)
2821 aarch64_set_vec_u16 (cpu, Vd, i, aarch64_get_reg_u16 (cpu, Rs, NO_SP));
2825 for (i = 0; i < (both ? 4 : 2); i++)
2826 aarch64_set_vec_u32 (cpu, Vd, i, aarch64_get_reg_u32 (cpu, Rs, NO_SP));
2832 aarch64_set_vec_u64 (cpu, Vd, 0, aarch64_get_reg_u64 (cpu, Rs, NO_SP));
2833 aarch64_set_vec_u64 (cpu, Vd, 1, aarch64_get_reg_u64 (cpu, Rs, NO_SP));
2842 do_vec_UZP (sim_cpu *cpu)
2845 instr[30] = half(0)/full(1)
2846 instr[29,24] = 00 1110
2847 instr[23,22] = size: byte(00), half(01), word (10), long (11)
2851 instr[14] = lower (0) / upper (1)
2856 int full = uimm (aarch64_get_instr (cpu), 30, 30);
2857 int upper = uimm (aarch64_get_instr (cpu), 14, 14);
2859 unsigned vm = uimm (aarch64_get_instr (cpu), 20, 16);
2860 unsigned vn = uimm (aarch64_get_instr (cpu), 9, 5);
2861 unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
2863 uint64_t val_m1 = aarch64_get_vec_u64 (cpu, vm, 0);
2864 uint64_t val_m2 = aarch64_get_vec_u64 (cpu, vm, 1);
2865 uint64_t val_n1 = aarch64_get_vec_u64 (cpu, vn, 0);
2866 uint64_t val_n2 = aarch64_get_vec_u64 (cpu, vn, 1);
2871 uint64_t input1 = upper ? val_n1 : val_m1;
2872 uint64_t input2 = upper ? val_n2 : val_m2;
2875 NYI_assert (29, 24, 0x0E);
2876 NYI_assert (21, 21, 0);
2877 NYI_assert (15, 15, 0);
2878 NYI_assert (13, 10, 6);
2880 switch (uimm (aarch64_get_instr (cpu), 23, 23))
2883 for (i = 0; i < 8; i++)
2885 val1 |= (input1 >> (i * 8)) & (0xFFULL << (i * 8));
2886 val2 |= (input2 >> (i * 8)) & (0xFFULL << (i * 8));
2891 for (i = 0; i < 4; i++)
2893 val1 |= (input1 >> (i * 16)) & (0xFFFFULL << (i * 16));
2894 val2 |= (input2 >> (i * 16)) & (0xFFFFULL << (i * 16));
2899 val1 = ((input1 & 0xFFFFFFFF) | ((input1 >> 32) & 0xFFFFFFFF00000000ULL));
2900 val2 = ((input2 & 0xFFFFFFFF) | ((input2 >> 32) & 0xFFFFFFFF00000000ULL));
2908 aarch64_set_vec_u64 (cpu, vd, 0, val1);
2910 aarch64_set_vec_u64 (cpu, vd, 1, val2);
2914 do_vec_ZIP (sim_cpu *cpu)
2917 instr[30] = half(0)/full(1)
2918 instr[29,24] = 00 1110
2919 instr[23,22] = size: byte(00), hald(01), word (10), long (11)
2923 instr[14] = lower (0) / upper (1)
2928 int full = uimm (aarch64_get_instr (cpu), 30, 30);
2929 int upper = uimm (aarch64_get_instr (cpu), 14, 14);
2931 unsigned vm = uimm (aarch64_get_instr (cpu), 20, 16);
2932 unsigned vn = uimm (aarch64_get_instr (cpu), 9, 5);
2933 unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
2935 uint64_t val_m1 = aarch64_get_vec_u64 (cpu, vm, 0);
2936 uint64_t val_m2 = aarch64_get_vec_u64 (cpu, vm, 1);
2937 uint64_t val_n1 = aarch64_get_vec_u64 (cpu, vn, 0);
2938 uint64_t val_n2 = aarch64_get_vec_u64 (cpu, vn, 1);
2943 uint64_t input1 = upper ? val_n1 : val_m1;
2944 uint64_t input2 = upper ? val_n2 : val_m2;
2946 NYI_assert (29, 24, 0x0E);
2947 NYI_assert (21, 21, 0);
2948 NYI_assert (15, 15, 0);
2949 NYI_assert (13, 10, 0xE);
2951 switch (uimm (aarch64_get_instr (cpu), 23, 23))
2955 ((input1 << 0) & (0xFF << 0))
2956 | ((input2 << 8) & (0xFF << 8))
2957 | ((input1 << 8) & (0xFF << 16))
2958 | ((input2 << 16) & (0xFF << 24))
2959 | ((input1 << 16) & (0xFFULL << 32))
2960 | ((input2 << 24) & (0xFFULL << 40))
2961 | ((input1 << 24) & (0xFFULL << 48))
2962 | ((input2 << 32) & (0xFFULL << 56));
2965 ((input1 >> 32) & (0xFF << 0))
2966 | ((input2 >> 24) & (0xFF << 8))
2967 | ((input1 >> 24) & (0xFF << 16))
2968 | ((input2 >> 16) & (0xFF << 24))
2969 | ((input1 >> 16) & (0xFFULL << 32))
2970 | ((input2 >> 8) & (0xFFULL << 40))
2971 | ((input1 >> 8) & (0xFFULL << 48))
2972 | ((input2 >> 0) & (0xFFULL << 56));
2977 ((input1 << 0) & (0xFFFF << 0))
2978 | ((input2 << 16) & (0xFFFF << 16))
2979 | ((input1 << 16) & (0xFFFFULL << 32))
2980 | ((input2 << 32) & (0xFFFFULL << 48));
2983 ((input1 >> 32) & (0xFFFF << 0))
2984 | ((input2 >> 16) & (0xFFFF << 16))
2985 | ((input1 >> 16) & (0xFFFFULL << 32))
2986 | ((input2 >> 0) & (0xFFFFULL << 48));
2990 val1 = (input1 & 0xFFFFFFFFULL) | (input2 << 32);
2991 val2 = (input2 & 0xFFFFFFFFULL) | (input1 << 32);
3000 aarch64_set_vec_u64 (cpu, vd, 0, val1);
3002 aarch64_set_vec_u64 (cpu, vd, 1, val2);
3005 /* Floating point immediates are encoded in 8 bits.
3006 fpimm[7] = sign bit.
3007 fpimm[6:4] = signed exponent.
3008 fpimm[3:0] = fraction (assuming leading 1).
3009 i.e. F = s * 1.f * 2^(e - b). */
3012 fp_immediate_for_encoding_32 (uint32_t imm8)
3015 uint32_t s, e, f, i;
3017 s = (imm8 >> 7) & 0x1;
3018 e = (imm8 >> 4) & 0x7;
3021 /* The fp value is s * n/16 * 2r where n is 16+e. */
3022 u = (16.0 + f) / 16.0;
3024 /* N.B. exponent is signed. */
3029 for (i = 0; i <= epos; i++)
3036 for (i = 0; i < eneg; i++)
3047 fp_immediate_for_encoding_64 (uint32_t imm8)
3050 uint32_t s, e, f, i;
3052 s = (imm8 >> 7) & 0x1;
3053 e = (imm8 >> 4) & 0x7;
3056 /* The fp value is s * n/16 * 2r where n is 16+e. */
3057 u = (16.0 + f) / 16.0;
3059 /* N.B. exponent is signed. */
3064 for (i = 0; i <= epos; i++)
3071 for (i = 0; i < eneg; i++)
3082 do_vec_MOV_immediate (sim_cpu *cpu)
3085 instr[30] = full/half selector
3086 instr[29,19] = 00111100000
3087 instr[18,16] = high 3 bits of uimm8
3088 instr[15,12] = size & shift:
3090 0010 => 32-bit + LSL#8
3091 0100 => 32-bit + LSL#16
3092 0110 => 32-bit + LSL#24
3093 1010 => 16-bit + LSL#8
3095 1101 => 32-bit + MSL#16
3096 1100 => 32-bit + MSL#8
3100 instr[9,5] = low 5-bits of uimm8
3103 int full = uimm (aarch64_get_instr (cpu), 30, 30);
3104 unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
3105 unsigned val = uimm (aarch64_get_instr (cpu), 18, 16) << 5
3106 | uimm (aarch64_get_instr (cpu), 9, 5);
3109 NYI_assert (29, 19, 0x1E0);
3110 NYI_assert (11, 10, 1);
3112 switch (uimm (aarch64_get_instr (cpu), 15, 12))
3114 case 0x0: /* 32-bit, no shift. */
3115 case 0x2: /* 32-bit, shift by 8. */
3116 case 0x4: /* 32-bit, shift by 16. */
3117 case 0x6: /* 32-bit, shift by 24. */
3118 val <<= (8 * uimm (aarch64_get_instr (cpu), 14, 13));
3119 for (i = 0; i < (full ? 4 : 2); i++)
3120 aarch64_set_vec_u32 (cpu, vd, i, val);
3123 case 0xa: /* 16-bit, shift by 8. */
3126 case 0x8: /* 16-bit, no shift. */
3127 for (i = 0; i < (full ? 8 : 4); i++)
3128 aarch64_set_vec_u16 (cpu, vd, i, val);
3130 case 0xd: /* 32-bit, mask shift by 16. */
3134 case 0xc: /* 32-bit, mask shift by 8. */
3137 for (i = 0; i < (full ? 4 : 2); i++)
3138 aarch64_set_vec_u32 (cpu, vd, i, val);
3141 case 0xe: /* 8-bit, no shift. */
3142 for (i = 0; i < (full ? 16 : 8); i++)
3143 aarch64_set_vec_u8 (cpu, vd, i, val);
3146 case 0xf: /* FMOV Vs.{2|4}S, #fpimm. */
3148 float u = fp_immediate_for_encoding_32 (val);
3149 for (i = 0; i < (full ? 4 : 2); i++)
3150 aarch64_set_vec_float (cpu, vd, i, u);
3160 do_vec_MVNI (sim_cpu *cpu)
3163 instr[30] = full/half selector
3164 instr[29,19] = 10111100000
3165 instr[18,16] = high 3 bits of uimm8
3166 instr[15,12] = selector
3168 instr[9,5] = low 5-bits of uimm8
3171 int full = uimm (aarch64_get_instr (cpu), 30, 30);
3172 unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
3173 unsigned val = uimm (aarch64_get_instr (cpu), 18, 16) << 5
3174 | uimm (aarch64_get_instr (cpu), 9, 5);
3177 NYI_assert (29, 19, 0x5E0);
3178 NYI_assert (11, 10, 1);
3180 switch (uimm (aarch64_get_instr (cpu), 15, 12))
3182 case 0x0: /* 32-bit, no shift. */
3183 case 0x2: /* 32-bit, shift by 8. */
3184 case 0x4: /* 32-bit, shift by 16. */
3185 case 0x6: /* 32-bit, shift by 24. */
3186 val <<= (8 * uimm (aarch64_get_instr (cpu), 14, 13));
3188 for (i = 0; i < (full ? 4 : 2); i++)
3189 aarch64_set_vec_u32 (cpu, vd, i, val);
3192 case 0xa: /* 16-bit, 8 bit shift. */
3194 case 0x8: /* 16-bit, no shift. */
3196 for (i = 0; i < (full ? 8 : 4); i++)
3197 aarch64_set_vec_u16 (cpu, vd, i, val);
3200 case 0xd: /* 32-bit, mask shift by 16. */
3203 case 0xc: /* 32-bit, mask shift by 8. */
3207 for (i = 0; i < (full ? 4 : 2); i++)
3208 aarch64_set_vec_u32 (cpu, vd, i, val);
3211 case 0xE: /* MOVI Dn, #mask64 */
3215 for (i = 0; i < 8; i++)
3217 mask |= (0xF << (i * 4));
3218 aarch64_set_vec_u64 (cpu, vd, 0, mask);
3219 aarch64_set_vec_u64 (cpu, vd, 1, 0);
3223 case 0xf: /* FMOV Vd.2D, #fpimm. */
3225 double u = fp_immediate_for_encoding_64 (val);
3230 aarch64_set_vec_double (cpu, vd, 0, u);
3231 aarch64_set_vec_double (cpu, vd, 1, u);
3240 #define ABS(A) ((A) < 0 ? - (A) : (A))
3243 do_vec_ABS (sim_cpu *cpu)
3246 instr[30] = half(0)/full(1)
3247 instr[29,24] = 00 1110
3248 instr[23,22] = size: 00=> 8-bit, 01=> 16-bit, 10=> 32-bit, 11=> 64-bit
3249 instr[21,10] = 10 0000 1011 10
3253 unsigned vn = uimm (aarch64_get_instr (cpu), 9, 5);
3254 unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
3255 unsigned full = uimm (aarch64_get_instr (cpu), 30, 30);
3258 NYI_assert (29, 24, 0x0E);
3259 NYI_assert (21, 10, 0x82E);
3261 switch (uimm (aarch64_get_instr (cpu), 23, 22))
3264 for (i = 0; i < (full ? 16 : 8); i++)
3265 aarch64_set_vec_s8 (cpu, vd, i,
3266 ABS (aarch64_get_vec_s8 (cpu, vn, i)));
3270 for (i = 0; i < (full ? 8 : 4); i++)
3271 aarch64_set_vec_s16 (cpu, vd, i,
3272 ABS (aarch64_get_vec_s16 (cpu, vn, i)));
3276 for (i = 0; i < (full ? 4 : 2); i++)
3277 aarch64_set_vec_s32 (cpu, vd, i,
3278 ABS (aarch64_get_vec_s32 (cpu, vn, i)));
3284 for (i = 0; i < 2; i++)
3285 aarch64_set_vec_s64 (cpu, vd, i,
3286 ABS (aarch64_get_vec_s64 (cpu, vn, i)));
3292 do_vec_ADDV (sim_cpu *cpu)
3295 instr[30] = full/half selector
3296 instr[29,24] = 00 1110
3297 instr[23,22] = size: 00=> 8-bit, 01=> 16-bit, 10=> 32-bit, 11=> 64-bit
3298 instr[21,10] = 11 0001 1011 10
3302 unsigned vm = uimm (aarch64_get_instr (cpu), 9, 5);
3303 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
3306 int full = uimm (aarch64_get_instr (cpu), 30, 30);
3308 NYI_assert (29, 24, 0x0E);
3309 NYI_assert (21, 10, 0xC6E);
3311 switch (uimm (aarch64_get_instr (cpu), 23, 22))
3314 for (i = 0; i < (full ? 16 : 8); i++)
3315 val += aarch64_get_vec_u8 (cpu, vm, i);
3316 aarch64_set_reg_u64 (cpu, rd, NO_SP, val);
3320 for (i = 0; i < (full ? 8 : 4); i++)
3321 val += aarch64_get_vec_u16 (cpu, vm, i);
3322 aarch64_set_reg_u64 (cpu, rd, NO_SP, val);
3326 for (i = 0; i < (full ? 4 : 2); i++)
3327 val += aarch64_get_vec_u32 (cpu, vm, i);
3328 aarch64_set_reg_u64 (cpu, rd, NO_SP, val);
3334 val = aarch64_get_vec_u64 (cpu, vm, 0);
3335 val += aarch64_get_vec_u64 (cpu, vm, 1);
3336 aarch64_set_reg_u64 (cpu, rd, NO_SP, val);
3345 do_vec_ins_2 (sim_cpu *cpu)
3347 /* instr[31,21] = 01001110000
3348 instr[20,18] = size & element selector
3350 instr[13] = direction: to vec(0), from vec (1)
3356 unsigned vm = uimm (aarch64_get_instr (cpu), 9, 5);
3357 unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
3359 NYI_assert (31, 21, 0x270);
3360 NYI_assert (17, 14, 0);
3361 NYI_assert (12, 10, 7);
3363 if (uimm (aarch64_get_instr (cpu), 13, 13) == 1)
3365 if (uimm (aarch64_get_instr (cpu), 18, 18) == 1)
3368 elem = uimm (aarch64_get_instr (cpu), 20, 19);
3369 aarch64_set_reg_u64 (cpu, vd, NO_SP,
3370 aarch64_get_vec_u32 (cpu, vm, elem));
3375 if (uimm (aarch64_get_instr (cpu), 19, 19) != 1)
3378 elem = uimm (aarch64_get_instr (cpu), 20, 20);
3379 aarch64_set_reg_u64 (cpu, vd, NO_SP,
3380 aarch64_get_vec_u64 (cpu, vm, elem));
3385 if (uimm (aarch64_get_instr (cpu), 18, 18) == 1)
3388 elem = uimm (aarch64_get_instr (cpu), 20, 19);
3389 aarch64_set_vec_u32 (cpu, vd, elem,
3390 aarch64_get_reg_u32 (cpu, vm, NO_SP));
3395 if (uimm (aarch64_get_instr (cpu), 19, 19) != 1)
3398 elem = uimm (aarch64_get_instr (cpu), 20, 20);
3399 aarch64_set_vec_u64 (cpu, vd, elem,
3400 aarch64_get_reg_u64 (cpu, vm, NO_SP));
3406 do_vec_mull (sim_cpu *cpu)
3409 instr[30] = lower(0)/upper(1) selector
3410 instr[29] = signed(0)/unsigned(1)
3411 instr[28,24] = 0 1110
3412 instr[23,22] = size: 8-bit (00), 16-bit (01), 32-bit (10)
3415 instr[15,10] = 11 0000
3419 int unsign = uimm (aarch64_get_instr (cpu), 29, 29);
3420 int bias = uimm (aarch64_get_instr (cpu), 30, 30);
3421 unsigned vm = uimm (aarch64_get_instr (cpu), 20, 16);
3422 unsigned vn = uimm (aarch64_get_instr (cpu), 9, 5);
3423 unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
3426 NYI_assert (28, 24, 0x0E);
3427 NYI_assert (15, 10, 0x30);
3429 switch (uimm (aarch64_get_instr (cpu), 23, 22))
3435 for (i = 0; i < 8; i++)
3436 aarch64_set_vec_u16 (cpu, vd, i,
3437 aarch64_get_vec_u8 (cpu, vn, i + bias)
3438 * aarch64_get_vec_u8 (cpu, vm, i + bias));
3440 for (i = 0; i < 8; i++)
3441 aarch64_set_vec_s16 (cpu, vd, i,
3442 aarch64_get_vec_s8 (cpu, vn, i + bias)
3443 * aarch64_get_vec_s8 (cpu, vm, i + bias));
3450 for (i = 0; i < 4; i++)
3451 aarch64_set_vec_u32 (cpu, vd, i,
3452 aarch64_get_vec_u16 (cpu, vn, i + bias)
3453 * aarch64_get_vec_u16 (cpu, vm, i + bias));
3455 for (i = 0; i < 4; i++)
3456 aarch64_set_vec_s32 (cpu, vd, i,
3457 aarch64_get_vec_s16 (cpu, vn, i + bias)
3458 * aarch64_get_vec_s16 (cpu, vm, i + bias));
3465 for (i = 0; i < 2; i++)
3466 aarch64_set_vec_u64 (cpu, vd, i,
3467 (uint64_t) aarch64_get_vec_u32 (cpu, vn,
3469 * (uint64_t) aarch64_get_vec_u32 (cpu, vm,
3472 for (i = 0; i < 2; i++)
3473 aarch64_set_vec_s64 (cpu, vd, i,
3474 aarch64_get_vec_s32 (cpu, vn, i + bias)
3475 * aarch64_get_vec_s32 (cpu, vm, i + bias));
3485 do_vec_fadd (sim_cpu *cpu)
3488 instr[30] = half(0)/full(1)
3489 instr[29,24] = 001110
3490 instr[23] = FADD(0)/FSUB(1)
3491 instr[22] = float (0)/double(1)
3494 instr[15,10] = 110101
3498 unsigned vm = uimm (aarch64_get_instr (cpu), 20, 16);
3499 unsigned vn = uimm (aarch64_get_instr (cpu), 9, 5);
3500 unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
3502 int full = uimm (aarch64_get_instr (cpu), 30, 30);
3504 NYI_assert (29, 24, 0x0E);
3505 NYI_assert (21, 21, 1);
3506 NYI_assert (15, 10, 0x35);
3508 if (uimm (aarch64_get_instr (cpu), 23, 23))
3510 if (uimm (aarch64_get_instr (cpu), 22, 22))
3515 for (i = 0; i < 2; i++)
3516 aarch64_set_vec_double (cpu, vd, i,
3517 aarch64_get_vec_double (cpu, vn, i)
3518 - aarch64_get_vec_double (cpu, vm, i));
3522 for (i = 0; i < (full ? 4 : 2); i++)
3523 aarch64_set_vec_float (cpu, vd, i,
3524 aarch64_get_vec_float (cpu, vn, i)
3525 - aarch64_get_vec_float (cpu, vm, i));
3530 if (uimm (aarch64_get_instr (cpu), 22, 22))
3535 for (i = 0; i < 2; i++)
3536 aarch64_set_vec_double (cpu, vd, i,
3537 aarch64_get_vec_double (cpu, vm, i)
3538 + aarch64_get_vec_double (cpu, vn, i));
3542 for (i = 0; i < (full ? 4 : 2); i++)
3543 aarch64_set_vec_float (cpu, vd, i,
3544 aarch64_get_vec_float (cpu, vm, i)
3545 + aarch64_get_vec_float (cpu, vn, i));
3551 do_vec_add (sim_cpu *cpu)
3554 instr[30] = full/half selector
3555 instr[29,24] = 001110
3556 instr[23,22] = size: 00=> 8-bit, 01=> 16-bit, 10=> 32-bit, 11=> 64-bit
3559 instr[15,10] = 100001
3563 unsigned vm = uimm (aarch64_get_instr (cpu), 20, 16);
3564 unsigned vn = uimm (aarch64_get_instr (cpu), 9, 5);
3565 unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
3567 int full = uimm (aarch64_get_instr (cpu), 30, 30);
3569 NYI_assert (29, 24, 0x0E);
3570 NYI_assert (21, 21, 1);
3571 NYI_assert (15, 10, 0x21);
3573 switch (uimm (aarch64_get_instr (cpu), 23, 22))
3576 for (i = 0; i < (full ? 16 : 8); i++)
3577 aarch64_set_vec_u8 (cpu, vd, i, aarch64_get_vec_u8 (cpu, vn, i)
3578 + aarch64_get_vec_u8 (cpu, vm, i));
3582 for (i = 0; i < (full ? 8 : 4); i++)
3583 aarch64_set_vec_u16 (cpu, vd, i, aarch64_get_vec_u16 (cpu, vn, i)
3584 + aarch64_get_vec_u16 (cpu, vm, i));
3588 for (i = 0; i < (full ? 4 : 2); i++)
3589 aarch64_set_vec_u32 (cpu, vd, i, aarch64_get_vec_u32 (cpu, vn, i)
3590 + aarch64_get_vec_u32 (cpu, vm, i));
3596 aarch64_set_vec_u64 (cpu, vd, 0, aarch64_get_vec_u64 (cpu, vn, 0)
3597 + aarch64_get_vec_u64 (cpu, vm, 0));
3598 aarch64_set_vec_u64 (cpu, vd, 1,
3599 aarch64_get_vec_u64 (cpu, vn, 1)
3600 + aarch64_get_vec_u64 (cpu, vm, 1));
3609 do_vec_mul (sim_cpu *cpu)
3612 instr[30] = full/half selector
3613 instr[29,24] = 00 1110
3614 instr[23,22] = size: 00=> 8-bit, 01=> 16-bit, 10=> 32-bit
3617 instr[15,10] = 10 0111
3621 unsigned vm = uimm (aarch64_get_instr (cpu), 20, 16);
3622 unsigned vn = uimm (aarch64_get_instr (cpu), 9, 5);
3623 unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
3625 int full = uimm (aarch64_get_instr (cpu), 30, 30);
3627 NYI_assert (29, 24, 0x0E);
3628 NYI_assert (21, 21, 1);
3629 NYI_assert (15, 10, 0x27);
3631 switch (uimm (aarch64_get_instr (cpu), 23, 22))
3634 for (i = 0; i < (full ? 16 : 8); i++)
3636 uint16_t val = aarch64_get_vec_u8 (cpu, vn, i);
3637 val *= aarch64_get_vec_u8 (cpu, vm, i);
3639 aarch64_set_vec_u16 (cpu, vd, i, val);
3644 for (i = 0; i < (full ? 8 : 4); i++)
3646 uint32_t val = aarch64_get_vec_u16 (cpu, vn, i);
3647 val *= aarch64_get_vec_u16 (cpu, vm, i);
3649 aarch64_set_vec_u32 (cpu, vd, i, val);
3654 for (i = 0; i < (full ? 4 : 2); i++)
3656 uint64_t val = aarch64_get_vec_u32 (cpu, vn, i);
3657 val *= aarch64_get_vec_u32 (cpu, vm, i);
3659 aarch64_set_vec_u64 (cpu, vd, i, val);
3670 do_vec_MLA (sim_cpu *cpu)
3673 instr[30] = full/half selector
3674 instr[29,24] = 00 1110
3675 instr[23,22] = size: 00=> 8-bit, 01=> 16-bit, 10=> 32-bit
3678 instr[15,10] = 1001 01
3682 unsigned vm = uimm (aarch64_get_instr (cpu), 20, 16);
3683 unsigned vn = uimm (aarch64_get_instr (cpu), 9, 5);
3684 unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
3686 int full = uimm (aarch64_get_instr (cpu), 30, 30);
3688 NYI_assert (29, 24, 0x0E);
3689 NYI_assert (21, 21, 1);
3690 NYI_assert (15, 10, 0x25);
3692 switch (uimm (aarch64_get_instr (cpu), 23, 22))
3695 for (i = 0; i < (full ? 16 : 8); i++)
3697 uint16_t val = aarch64_get_vec_u8 (cpu, vn, i);
3698 val *= aarch64_get_vec_u8 (cpu, vm, i);
3699 val += aarch64_get_vec_u8 (cpu, vd, i);
3701 aarch64_set_vec_u16 (cpu, vd, i, val);
3706 for (i = 0; i < (full ? 8 : 4); i++)
3708 uint32_t val = aarch64_get_vec_u16 (cpu, vn, i);
3709 val *= aarch64_get_vec_u16 (cpu, vm, i);
3710 val += aarch64_get_vec_u16 (cpu, vd, i);
3712 aarch64_set_vec_u32 (cpu, vd, i, val);
3717 for (i = 0; i < (full ? 4 : 2); i++)
3719 uint64_t val = aarch64_get_vec_u32 (cpu, vn, i);
3720 val *= aarch64_get_vec_u32 (cpu, vm, i);
3721 val += aarch64_get_vec_u32 (cpu, vd, i);
3723 aarch64_set_vec_u64 (cpu, vd, i, val);
3734 fmaxnm (float a, float b)
3736 if (fpclassify (a) == FP_NORMAL)
3738 if (fpclassify (b) == FP_NORMAL)
3739 return a > b ? a : b;
3742 else if (fpclassify (b) == FP_NORMAL)
3748 fminnm (float a, float b)
3750 if (fpclassify (a) == FP_NORMAL)
3752 if (fpclassify (b) == FP_NORMAL)
3753 return a < b ? a : b;
3756 else if (fpclassify (b) == FP_NORMAL)
3762 dmaxnm (double a, double b)
3764 if (fpclassify (a) == FP_NORMAL)
3766 if (fpclassify (b) == FP_NORMAL)
3767 return a > b ? a : b;
3770 else if (fpclassify (b) == FP_NORMAL)
3776 dminnm (double a, double b)
3778 if (fpclassify (a) == FP_NORMAL)
3780 if (fpclassify (b) == FP_NORMAL)
3781 return a < b ? a : b;
3784 else if (fpclassify (b) == FP_NORMAL)
3790 do_vec_FminmaxNMP (sim_cpu *cpu)
3792 /* aarch64_get_instr (cpu)[31] = 0
3793 aarch64_get_instr (cpu)[30] = half (0)/full (1)
3794 aarch64_get_instr (cpu)[29,24] = 10 1110
3795 aarch64_get_instr (cpu)[23] = max(0)/min(1)
3796 aarch64_get_instr (cpu)[22] = float (0)/double (1)
3797 aarch64_get_instr (cpu)[21] = 1
3798 aarch64_get_instr (cpu)[20,16] = Vn
3799 aarch64_get_instr (cpu)[15,10] = 1100 01
3800 aarch64_get_instr (cpu)[9,5] = Vm
3801 aarch64_get_instr (cpu)[4.0] = Vd. */
3803 unsigned vm = uimm (aarch64_get_instr (cpu), 20, 16);
3804 unsigned vn = uimm (aarch64_get_instr (cpu), 9, 5);
3805 unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
3806 int full = uimm (aarch64_get_instr (cpu), 30, 30);
3808 NYI_assert (29, 24, 0x2E);
3809 NYI_assert (21, 21, 1);
3810 NYI_assert (15, 10, 0x31);
3812 if (uimm (aarch64_get_instr (cpu), 22, 22))
3814 double (* fn)(double, double) = uimm (aarch64_get_instr (cpu), 23, 23)
3819 aarch64_set_vec_double (cpu, vd, 0,
3820 fn (aarch64_get_vec_double (cpu, vn, 0),
3821 aarch64_get_vec_double (cpu, vn, 1)));
3822 aarch64_set_vec_double (cpu, vd, 0,
3823 fn (aarch64_get_vec_double (cpu, vm, 0),
3824 aarch64_get_vec_double (cpu, vm, 1)));
3828 float (* fn)(float, float) = uimm (aarch64_get_instr (cpu), 23, 23)
3831 aarch64_set_vec_float (cpu, vd, 0,
3832 fn (aarch64_get_vec_float (cpu, vn, 0),
3833 aarch64_get_vec_float (cpu, vn, 1)));
3835 aarch64_set_vec_float (cpu, vd, 1,
3836 fn (aarch64_get_vec_float (cpu, vn, 2),
3837 aarch64_get_vec_float (cpu, vn, 3)));
3839 aarch64_set_vec_float (cpu, vd, (full ? 2 : 1),
3840 fn (aarch64_get_vec_float (cpu, vm, 0),
3841 aarch64_get_vec_float (cpu, vm, 1)));
3843 aarch64_set_vec_float (cpu, vd, 3,
3844 fn (aarch64_get_vec_float (cpu, vm, 2),
3845 aarch64_get_vec_float (cpu, vm, 3)));
3850 do_vec_AND (sim_cpu *cpu)
3853 instr[30] = half (0)/full (1)
3854 instr[29,21] = 001110001
3856 instr[15,10] = 000111
3860 unsigned vm = uimm (aarch64_get_instr (cpu), 20, 16);
3861 unsigned vn = uimm (aarch64_get_instr (cpu), 9, 5);
3862 unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
3864 int full = uimm (aarch64_get_instr (cpu), 30, 30);
3866 NYI_assert (29, 21, 0x071);
3867 NYI_assert (15, 10, 0x07);
3869 for (i = 0; i < (full ? 4 : 2); i++)
3870 aarch64_set_vec_u32 (cpu, vd, i,
3871 aarch64_get_vec_u32 (cpu, vn, i)
3872 & aarch64_get_vec_u32 (cpu, vm, i));
3876 do_vec_BSL (sim_cpu *cpu)
3879 instr[30] = half (0)/full (1)
3880 instr[29,21] = 101110011
3882 instr[15,10] = 000111
3886 unsigned vm = uimm (aarch64_get_instr (cpu), 20, 16);
3887 unsigned vn = uimm (aarch64_get_instr (cpu), 9, 5);
3888 unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
3890 int full = uimm (aarch64_get_instr (cpu), 30, 30);
3892 NYI_assert (29, 21, 0x173);
3893 NYI_assert (15, 10, 0x07);
3895 for (i = 0; i < (full ? 16 : 8); i++)
3896 aarch64_set_vec_u8 (cpu, vd, i,
3897 ( aarch64_get_vec_u8 (cpu, vd, i)
3898 & aarch64_get_vec_u8 (cpu, vn, i))
3899 | ((~ aarch64_get_vec_u8 (cpu, vd, i))
3900 & aarch64_get_vec_u8 (cpu, vm, i)));
3904 do_vec_EOR (sim_cpu *cpu)
3907 instr[30] = half (0)/full (1)
3908 instr[29,21] = 10 1110 001
3910 instr[15,10] = 000111
3914 unsigned vm = uimm (aarch64_get_instr (cpu), 20, 16);
3915 unsigned vn = uimm (aarch64_get_instr (cpu), 9, 5);
3916 unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
3918 int full = uimm (aarch64_get_instr (cpu), 30, 30);
3920 NYI_assert (29, 21, 0x171);
3921 NYI_assert (15, 10, 0x07);
3923 for (i = 0; i < (full ? 4 : 2); i++)
3924 aarch64_set_vec_u32 (cpu, vd, i,
3925 aarch64_get_vec_u32 (cpu, vn, i)
3926 ^ aarch64_get_vec_u32 (cpu, vm, i));
3930 do_vec_bit (sim_cpu *cpu)
3933 instr[30] = half (0)/full (1)
3934 instr[29,23] = 10 1110 1
3935 instr[22] = BIT (0) / BIF (1)
3938 instr[15,10] = 0001 11
3942 unsigned vm = uimm (aarch64_get_instr (cpu), 20, 16);
3943 unsigned vn = uimm (aarch64_get_instr (cpu), 9, 5);
3944 unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
3945 unsigned full = uimm (aarch64_get_instr (cpu), 30, 30);
3946 unsigned test_false = uimm (aarch64_get_instr (cpu), 22, 22);
3949 NYI_assert (29, 23, 0x5D);
3950 NYI_assert (21, 21, 1);
3951 NYI_assert (15, 10, 0x07);
3955 for (i = 0; i < (full ? 16 : 8); i++)
3956 if (aarch64_get_vec_u32 (cpu, vn, i) == 0)
3957 aarch64_set_vec_u32 (cpu, vd, i, aarch64_get_vec_u32 (cpu, vm, i));
3961 for (i = 0; i < (full ? 16 : 8); i++)
3962 if (aarch64_get_vec_u32 (cpu, vn, i) != 0)
3963 aarch64_set_vec_u32 (cpu, vd, i, aarch64_get_vec_u32 (cpu, vm, i));
3968 do_vec_ORN (sim_cpu *cpu)
3971 instr[30] = half (0)/full (1)
3972 instr[29,21] = 00 1110 111
3974 instr[15,10] = 00 0111
3978 unsigned vm = uimm (aarch64_get_instr (cpu), 20, 16);
3979 unsigned vn = uimm (aarch64_get_instr (cpu), 9, 5);
3980 unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
3982 int full = uimm (aarch64_get_instr (cpu), 30, 30);
3984 NYI_assert (29, 21, 0x077);
3985 NYI_assert (15, 10, 0x07);
3987 for (i = 0; i < (full ? 16 : 8); i++)
3988 aarch64_set_vec_u8 (cpu, vd, i,
3989 aarch64_get_vec_u8 (cpu, vn, i)
3990 | ~ aarch64_get_vec_u8 (cpu, vm, i));
3994 do_vec_ORR (sim_cpu *cpu)
3997 instr[30] = half (0)/full (1)
3998 instr[29,21] = 00 1110 101
4000 instr[15,10] = 0001 11
4004 unsigned vm = uimm (aarch64_get_instr (cpu), 20, 16);
4005 unsigned vn = uimm (aarch64_get_instr (cpu), 9, 5);
4006 unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
4008 int full = uimm (aarch64_get_instr (cpu), 30, 30);
4010 NYI_assert (29, 21, 0x075);
4011 NYI_assert (15, 10, 0x07);
4013 for (i = 0; i < (full ? 16 : 8); i++)
4014 aarch64_set_vec_u8 (cpu, vd, i,
4015 aarch64_get_vec_u8 (cpu, vn, i)
4016 | aarch64_get_vec_u8 (cpu, vm, i));
4020 do_vec_BIC (sim_cpu *cpu)
4023 instr[30] = half (0)/full (1)
4024 instr[29,21] = 00 1110 011
4026 instr[15,10] = 00 0111
4030 unsigned vm = uimm (aarch64_get_instr (cpu), 20, 16);
4031 unsigned vn = uimm (aarch64_get_instr (cpu), 9, 5);
4032 unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
4034 int full = uimm (aarch64_get_instr (cpu), 30, 30);
4036 NYI_assert (29, 21, 0x073);
4037 NYI_assert (15, 10, 0x07);
4039 for (i = 0; i < (full ? 16 : 8); i++)
4040 aarch64_set_vec_u8 (cpu, vd, i,
4041 aarch64_get_vec_u8 (cpu, vn, i)
4042 & ~ aarch64_get_vec_u8 (cpu, vm, i));
4046 do_vec_XTN (sim_cpu *cpu)
4049 instr[30] = first part (0)/ second part (1)
4050 instr[29,24] = 00 1110
4051 instr[23,22] = size: byte(00), half(01), word (10)
4052 instr[21,10] = 1000 0100 1010
4056 unsigned vs = uimm (aarch64_get_instr (cpu), 9, 5);
4057 unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
4058 unsigned bias = uimm (aarch64_get_instr (cpu), 30, 30);
4061 NYI_assert (29, 24, 0x0E);
4062 NYI_assert (21, 10, 0x84A);
4064 switch (uimm (aarch64_get_instr (cpu), 23, 22))
4068 for (i = 0; i < 8; i++)
4069 aarch64_set_vec_u8 (cpu, vd, i + 8,
4070 aarch64_get_vec_u16 (cpu, vs, i) >> 8);
4072 for (i = 0; i < 8; i++)
4073 aarch64_set_vec_u8 (cpu, vd, i, aarch64_get_vec_u16 (cpu, vs, i));
4078 for (i = 0; i < 4; i++)
4079 aarch64_set_vec_u16 (cpu, vd, i + 4,
4080 aarch64_get_vec_u32 (cpu, vs, i) >> 16);
4082 for (i = 0; i < 4; i++)
4083 aarch64_set_vec_u16 (cpu, vd, i, aarch64_get_vec_u32 (cpu, vs, i));
4088 for (i = 0; i < 2; i++)
4089 aarch64_set_vec_u32 (cpu, vd, i + 4,
4090 aarch64_get_vec_u64 (cpu, vs, i) >> 32);
4092 for (i = 0; i < 2; i++)
4093 aarch64_set_vec_u32 (cpu, vd, i, aarch64_get_vec_u64 (cpu, vs, i));
4102 do_vec_maxv (sim_cpu *cpu)
4105 instr[30] = half(0)/full(1)
4106 instr[29] = signed (0)/unsigned(1)
4107 instr[28,24] = 0 1110
4108 instr[23,22] = size: byte(00), half(01), word (10)
4110 instr[20,17] = 1 000
4111 instr[16] = max(0)/min(1)
4112 instr[15,10] = 1010 10
4113 instr[9,5] = V source
4114 instr[4.0] = R dest. */
4116 unsigned vs = uimm (aarch64_get_instr (cpu), 9, 5);
4117 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
4118 unsigned full = uimm (aarch64_get_instr (cpu), 30, 30);
4121 NYI_assert (28, 24, 0x0E);
4122 NYI_assert (21, 21, 1);
4123 NYI_assert (20, 17, 8);
4124 NYI_assert (15, 10, 0x2A);
4126 switch ((uimm (aarch64_get_instr (cpu), 29, 29) << 1)
4127 | uimm (aarch64_get_instr (cpu), 16, 16))
4129 case 0: /* SMAXV. */
4132 switch (uimm (aarch64_get_instr (cpu), 23, 22))
4135 smax = aarch64_get_vec_s8 (cpu, vs, 0);
4136 for (i = 1; i < (full ? 16 : 8); i++)
4137 smax = max (smax, aarch64_get_vec_s8 (cpu, vs, i));
4140 smax = aarch64_get_vec_s16 (cpu, vs, 0);
4141 for (i = 1; i < (full ? 8 : 4); i++)
4142 smax = max (smax, aarch64_get_vec_s16 (cpu, vs, i));
4145 smax = aarch64_get_vec_s32 (cpu, vs, 0);
4146 for (i = 1; i < (full ? 4 : 2); i++)
4147 smax = max (smax, aarch64_get_vec_s32 (cpu, vs, i));
4153 aarch64_set_reg_s64 (cpu, rd, NO_SP, smax);
4157 case 1: /* SMINV. */
4160 switch (uimm (aarch64_get_instr (cpu), 23, 22))
4163 smin = aarch64_get_vec_s8 (cpu, vs, 0);
4164 for (i = 1; i < (full ? 16 : 8); i++)
4165 smin = min (smin, aarch64_get_vec_s8 (cpu, vs, i));
4168 smin = aarch64_get_vec_s16 (cpu, vs, 0);
4169 for (i = 1; i < (full ? 8 : 4); i++)
4170 smin = min (smin, aarch64_get_vec_s16 (cpu, vs, i));
4173 smin = aarch64_get_vec_s32 (cpu, vs, 0);
4174 for (i = 1; i < (full ? 4 : 2); i++)
4175 smin = min (smin, aarch64_get_vec_s32 (cpu, vs, i));
4181 aarch64_set_reg_s64 (cpu, rd, NO_SP, smin);
4185 case 2: /* UMAXV. */
4188 switch (uimm (aarch64_get_instr (cpu), 23, 22))
4191 umax = aarch64_get_vec_u8 (cpu, vs, 0);
4192 for (i = 1; i < (full ? 16 : 8); i++)
4193 umax = max (umax, aarch64_get_vec_u8 (cpu, vs, i));
4196 umax = aarch64_get_vec_u16 (cpu, vs, 0);
4197 for (i = 1; i < (full ? 8 : 4); i++)
4198 umax = max (umax, aarch64_get_vec_u16 (cpu, vs, i));
4201 umax = aarch64_get_vec_u32 (cpu, vs, 0);
4202 for (i = 1; i < (full ? 4 : 2); i++)
4203 umax = max (umax, aarch64_get_vec_u32 (cpu, vs, i));
4209 aarch64_set_reg_u64 (cpu, rd, NO_SP, umax);
4213 case 3: /* UMINV. */
4216 switch (uimm (aarch64_get_instr (cpu), 23, 22))
4219 umin = aarch64_get_vec_u8 (cpu, vs, 0);
4220 for (i = 1; i < (full ? 16 : 8); i++)
4221 umin = min (umin, aarch64_get_vec_u8 (cpu, vs, i));
4224 umin = aarch64_get_vec_u16 (cpu, vs, 0);
4225 for (i = 1; i < (full ? 8 : 4); i++)
4226 umin = min (umin, aarch64_get_vec_u16 (cpu, vs, i));
4229 umin = aarch64_get_vec_u32 (cpu, vs, 0);
4230 for (i = 1; i < (full ? 4 : 2); i++)
4231 umin = min (umin, aarch64_get_vec_u32 (cpu, vs, i));
4237 aarch64_set_reg_u64 (cpu, rd, NO_SP, umin);
4247 do_vec_fminmaxV (sim_cpu *cpu)
4249 /* instr[31,24] = 0110 1110
4250 instr[23] = max(0)/min(1)
4251 instr[22,14] = 011 0000 11
4252 instr[13,12] = nm(00)/normal(11)
4254 instr[9,5] = V source
4255 instr[4.0] = R dest. */
4257 unsigned vs = uimm (aarch64_get_instr (cpu), 9, 5);
4258 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
4260 float res = aarch64_get_vec_float (cpu, vs, 0);
4262 NYI_assert (31, 24, 0x6E);
4263 NYI_assert (22, 14, 0x0C3);
4264 NYI_assert (11, 10, 2);
4266 if (uimm (aarch64_get_instr (cpu), 23, 23))
4268 switch (uimm (aarch64_get_instr (cpu), 13, 12))
4270 case 0: /* FMNINNMV. */
4271 for (i = 1; i < 4; i++)
4272 res = fminnm (res, aarch64_get_vec_float (cpu, vs, i));
4275 case 3: /* FMINV. */
4276 for (i = 1; i < 4; i++)
4277 res = min (res, aarch64_get_vec_float (cpu, vs, i));
4286 switch (uimm (aarch64_get_instr (cpu), 13, 12))
4288 case 0: /* FMNAXNMV. */
4289 for (i = 1; i < 4; i++)
4290 res = fmaxnm (res, aarch64_get_vec_float (cpu, vs, i));
4293 case 3: /* FMAXV. */
4294 for (i = 1; i < 4; i++)
4295 res = max (res, aarch64_get_vec_float (cpu, vs, i));
4303 aarch64_set_FP_float (cpu, rd, res);
4307 do_vec_Fminmax (sim_cpu *cpu)
4310 instr[30] = half(0)/full(1)
4311 instr[29,24] = 00 1110
4312 instr[23] = max(0)/min(1)
4313 instr[22] = float(0)/double(1)
4317 instr[13,12] = nm(00)/normal(11)
4322 unsigned vm = uimm (aarch64_get_instr (cpu), 20, 16);
4323 unsigned vn = uimm (aarch64_get_instr (cpu), 9, 5);
4324 unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
4325 unsigned full = uimm (aarch64_get_instr (cpu), 30, 30);
4326 unsigned min = uimm (aarch64_get_instr (cpu), 23, 23);
4329 NYI_assert (29, 24, 0x0E);
4330 NYI_assert (21, 21, 1);
4331 NYI_assert (15, 14, 3);
4332 NYI_assert (11, 10, 1);
4334 if (uimm (aarch64_get_instr (cpu), 22, 22))
4336 double (* func)(double, double);
4341 if (uimm (aarch64_get_instr (cpu), 13, 12) == 0)
4342 func = min ? dminnm : dmaxnm;
4343 else if (uimm (aarch64_get_instr (cpu), 13, 12) == 3)
4344 func = min ? fmin : fmax;
4348 for (i = 0; i < 2; i++)
4349 aarch64_set_vec_double (cpu, vd, i,
4350 func (aarch64_get_vec_double (cpu, vn, i),
4351 aarch64_get_vec_double (cpu, vm, i)));
4355 float (* func)(float, float);
4357 if (uimm (aarch64_get_instr (cpu), 13, 12) == 0)
4358 func = min ? fminnm : fmaxnm;
4359 else if (uimm (aarch64_get_instr (cpu), 13, 12) == 3)
4360 func = min ? fminf : fmaxf;
4364 for (i = 0; i < (full ? 4 : 2); i++)
4365 aarch64_set_vec_float (cpu, vd, i,
4366 func (aarch64_get_vec_float (cpu, vn, i),
4367 aarch64_get_vec_float (cpu, vm, i)));
4372 do_vec_SCVTF (sim_cpu *cpu)
4376 instr[29,23] = 00 1110 0
4377 instr[22] = float(0)/double(1)
4378 instr[21,10] = 10 0001 1101 10
4382 unsigned vn = uimm (aarch64_get_instr (cpu), 9, 5);
4383 unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
4384 unsigned full = uimm (aarch64_get_instr (cpu), 30, 30);
4385 unsigned size = uimm (aarch64_get_instr (cpu), 22, 22);
4388 NYI_assert (29, 23, 0x1C);
4389 NYI_assert (21, 10, 0x876);
4396 for (i = 0; i < 2; i++)
4398 double val = (double) aarch64_get_vec_u64 (cpu, vn, i);
4399 aarch64_set_vec_double (cpu, vd, i, val);
4404 for (i = 0; i < (full ? 4 : 2); i++)
4406 float val = (float) aarch64_get_vec_u32 (cpu, vn, i);
4407 aarch64_set_vec_float (cpu, vd, i, val);
4412 #define VEC_CMP(SOURCE, CMP) \
4418 for (i = 0; i < (full ? 16 : 8); i++) \
4419 aarch64_set_vec_u8 (cpu, vd, i, \
4420 aarch64_get_vec_##SOURCE##8 (cpu, vn, i) \
4422 aarch64_get_vec_##SOURCE##8 (cpu, vm, i) \
4426 for (i = 0; i < (full ? 8 : 4); i++) \
4427 aarch64_set_vec_u16 (cpu, vd, i, \
4428 aarch64_get_vec_##SOURCE##16 (cpu, vn, i) \
4430 aarch64_get_vec_##SOURCE##16 (cpu, vm, i) \
4434 for (i = 0; i < (full ? 4 : 2); i++) \
4435 aarch64_set_vec_u32 (cpu, vd, i, \
4436 aarch64_get_vec_##SOURCE##32 (cpu, vn, i) \
4438 aarch64_get_vec_##SOURCE##32 (cpu, vm, i) \
4444 for (i = 0; i < 2; i++) \
4445 aarch64_set_vec_u64 (cpu, vd, i, \
4446 aarch64_get_vec_##SOURCE##64 (cpu, vn, i) \
4448 aarch64_get_vec_##SOURCE##64 (cpu, vm, i) \
4457 #define VEC_CMP0(SOURCE, CMP) \
4463 for (i = 0; i < (full ? 16 : 8); i++) \
4464 aarch64_set_vec_u8 (cpu, vd, i, \
4465 aarch64_get_vec_##SOURCE##8 (cpu, vn, i) \
4469 for (i = 0; i < (full ? 8 : 4); i++) \
4470 aarch64_set_vec_u16 (cpu, vd, i, \
4471 aarch64_get_vec_##SOURCE##16 (cpu, vn, i) \
4475 for (i = 0; i < (full ? 4 : 2); i++) \
4476 aarch64_set_vec_u32 (cpu, vd, i, \
4477 aarch64_get_vec_##SOURCE##32 (cpu, vn, i) \
4483 for (i = 0; i < 2; i++) \
4484 aarch64_set_vec_u64 (cpu, vd, i, \
4485 aarch64_get_vec_##SOURCE##64 (cpu, vn, i) \
4486 CMP 0 ? -1ULL : 0); \
4494 #define VEC_FCMP0(CMP) \
4499 if (uimm (aarch64_get_instr (cpu), 22, 22)) \
4503 for (i = 0; i < 2; i++) \
4504 aarch64_set_vec_u64 (cpu, vd, i, \
4505 aarch64_get_vec_double (cpu, vn, i) \
4506 CMP 0.0 ? -1 : 0); \
4510 for (i = 0; i < (full ? 4 : 2); i++) \
4511 aarch64_set_vec_u32 (cpu, vd, i, \
4512 aarch64_get_vec_float (cpu, vn, i) \
4513 CMP 0.0 ? -1 : 0); \
4519 #define VEC_FCMP(CMP) \
4522 if (uimm (aarch64_get_instr (cpu), 22, 22)) \
4526 for (i = 0; i < 2; i++) \
4527 aarch64_set_vec_u64 (cpu, vd, i, \
4528 aarch64_get_vec_double (cpu, vn, i) \
4530 aarch64_get_vec_double (cpu, vm, i) \
4535 for (i = 0; i < (full ? 4 : 2); i++) \
4536 aarch64_set_vec_u32 (cpu, vd, i, \
4537 aarch64_get_vec_float (cpu, vn, i) \
4539 aarch64_get_vec_float (cpu, vm, i) \
4547 do_vec_compare (sim_cpu *cpu)
4550 instr[30] = half(0)/full(1)
4551 instr[29] = part-of-comparison-type
4552 instr[28,24] = 0 1110
4553 instr[23,22] = size of integer compares: byte(00), half(01), word (10), long (11)
4554 type of float compares: single (-0) / double (-1)
4556 instr[20,16] = Vm or 00000 (compare vs 0)
4557 instr[15,10] = part-of-comparison-type
4561 int full = uimm (aarch64_get_instr (cpu), 30, 30);
4562 int size = uimm (aarch64_get_instr (cpu), 23, 22);
4563 unsigned vm = uimm (aarch64_get_instr (cpu), 20, 16);
4564 unsigned vn = uimm (aarch64_get_instr (cpu), 9, 5);
4565 unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
4568 NYI_assert (28, 24, 0x0E);
4569 NYI_assert (21, 21, 1);
4571 if ((uimm (aarch64_get_instr (cpu), 11, 11)
4572 && uimm (aarch64_get_instr (cpu), 14, 14))
4573 || ((uimm (aarch64_get_instr (cpu), 11, 11) == 0
4574 && uimm (aarch64_get_instr (cpu), 10, 10) == 0)))
4576 /* A compare vs 0. */
4579 if (uimm (aarch64_get_instr (cpu), 15, 10) == 0x2A)
4581 else if (uimm (aarch64_get_instr (cpu), 15, 10) == 0x32
4582 || uimm (aarch64_get_instr (cpu), 15, 10) == 0x3E)
4583 do_vec_fminmaxV (cpu);
4584 else if (uimm (aarch64_get_instr (cpu), 29, 23) == 0x1C
4585 && uimm (aarch64_get_instr (cpu), 21, 10) == 0x876)
4593 if (uimm (aarch64_get_instr (cpu), 14, 14))
4595 /* A floating point compare. */
4596 unsigned decode = (uimm (aarch64_get_instr (cpu), 29, 29) << 5)
4597 | (uimm (aarch64_get_instr (cpu), 23, 23) << 4)
4598 | uimm (aarch64_get_instr (cpu), 13, 10);
4600 NYI_assert (15, 15, 1);
4604 case /* 0b010010: GT#0 */ 0x12: VEC_FCMP0 (>);
4605 case /* 0b110010: GE#0 */ 0x32: VEC_FCMP0 (>=);
4606 case /* 0b010110: EQ#0 */ 0x16: VEC_FCMP0 (==);
4607 case /* 0b110110: LE#0 */ 0x36: VEC_FCMP0 (<=);
4608 case /* 0b011010: LT#0 */ 0x1A: VEC_FCMP0 (<);
4609 case /* 0b111001: GT */ 0x39: VEC_FCMP (>);
4610 case /* 0b101001: GE */ 0x29: VEC_FCMP (>=);
4611 case /* 0b001001: EQ */ 0x09: VEC_FCMP (==);
4619 unsigned decode = (uimm (aarch64_get_instr (cpu), 29, 29) << 6)
4620 | uimm (aarch64_get_instr (cpu), 15, 10);
4624 case 0x0D: /* 0001101 GT */ VEC_CMP (s, > );
4625 case 0x0F: /* 0001111 GE */ VEC_CMP (s, >= );
4626 case 0x22: /* 0100010 GT #0 */ VEC_CMP0 (s, > );
4627 case 0x26: /* 0100110 EQ #0 */ VEC_CMP0 (s, == );
4628 case 0x2A: /* 0101010 LT #0 */ VEC_CMP0 (s, < );
4629 case 0x4D: /* 1001101 HI */ VEC_CMP (u, > );
4630 case 0x4F: /* 1001111 HS */ VEC_CMP (u, >= );
4631 case 0x62: /* 1100010 GE #0 */ VEC_CMP0 (s, >= );
4632 case 0x63: /* 1100011 EQ */ VEC_CMP (u, == );
4633 case 0x66: /* 1100110 LE #0 */ VEC_CMP0 (s, <= );
4643 do_vec_SSHL (sim_cpu *cpu)
4646 instr[30] = first part (0)/ second part (1)
4647 instr[29,24] = 00 1110
4648 instr[23,22] = size: byte(00), half(01), word (10), long (11)
4651 instr[15,10] = 0100 01
4655 unsigned full = uimm (aarch64_get_instr (cpu), 30, 30);
4656 unsigned vm = uimm (aarch64_get_instr (cpu), 20, 16);
4657 unsigned vn = uimm (aarch64_get_instr (cpu), 9, 5);
4658 unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
4661 NYI_assert (29, 24, 0x0E);
4662 NYI_assert (21, 21, 1);
4663 NYI_assert (15, 10, 0x11);
4665 /* FIXME: What is a signed shift left in this context ?. */
4667 switch (uimm (aarch64_get_instr (cpu), 23, 22))
4670 for (i = 0; i < (full ? 16 : 8); i++)
4671 aarch64_set_vec_s8 (cpu, vd, i, aarch64_get_vec_s8 (cpu, vn, i)
4672 << aarch64_get_vec_s8 (cpu, vm, i));
4676 for (i = 0; i < (full ? 8 : 4); i++)
4677 aarch64_set_vec_s16 (cpu, vd, i, aarch64_get_vec_s16 (cpu, vn, i)
4678 << aarch64_get_vec_s16 (cpu, vm, i));
4682 for (i = 0; i < (full ? 4 : 2); i++)
4683 aarch64_set_vec_s32 (cpu, vd, i, aarch64_get_vec_s32 (cpu, vn, i)
4684 << aarch64_get_vec_s32 (cpu, vm, i));
4690 for (i = 0; i < 2; i++)
4691 aarch64_set_vec_s64 (cpu, vd, i, aarch64_get_vec_s64 (cpu, vn, i)
4692 << aarch64_get_vec_s64 (cpu, vm, i));
4701 do_vec_USHL (sim_cpu *cpu)
4704 instr[30] = first part (0)/ second part (1)
4705 instr[29,24] = 10 1110
4706 instr[23,22] = size: byte(00), half(01), word (10), long (11)
4709 instr[15,10] = 0100 01
4713 unsigned full = uimm (aarch64_get_instr (cpu), 30, 30);
4714 unsigned vm = uimm (aarch64_get_instr (cpu), 20, 16);
4715 unsigned vn = uimm (aarch64_get_instr (cpu), 9, 5);
4716 unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
4719 NYI_assert (29, 24, 0x2E);
4720 NYI_assert (15, 10, 0x11);
4722 switch (uimm (aarch64_get_instr (cpu), 23, 22))
4725 for (i = 0; i < (full ? 16 : 8); i++)
4726 aarch64_set_vec_u8 (cpu, vd, i, aarch64_get_vec_u8 (cpu, vn, i)
4727 << aarch64_get_vec_u8 (cpu, vm, i));
4731 for (i = 0; i < (full ? 8 : 4); i++)
4732 aarch64_set_vec_u16 (cpu, vd, i, aarch64_get_vec_u16 (cpu, vn, i)
4733 << aarch64_get_vec_u16 (cpu, vm, i));
4737 for (i = 0; i < (full ? 4 : 2); i++)
4738 aarch64_set_vec_u32 (cpu, vd, i, aarch64_get_vec_u32 (cpu, vn, i)
4739 << aarch64_get_vec_u32 (cpu, vm, i));
4745 for (i = 0; i < 2; i++)
4746 aarch64_set_vec_u64 (cpu, vd, i, aarch64_get_vec_u64 (cpu, vn, i)
4747 << aarch64_get_vec_u64 (cpu, vm, i));
4756 do_vec_FMLA (sim_cpu *cpu)
4759 instr[30] = full/half selector
4760 instr[29,23] = 0011100
4761 instr[22] = size: 0=>float, 1=>double
4764 instr[15,10] = 1100 11
4768 unsigned vm = uimm (aarch64_get_instr (cpu), 20, 16);
4769 unsigned vn = uimm (aarch64_get_instr (cpu), 9, 5);
4770 unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
4772 int full = uimm (aarch64_get_instr (cpu), 30, 30);
4774 NYI_assert (29, 23, 0x1C);
4775 NYI_assert (21, 21, 1);
4776 NYI_assert (15, 10, 0x33);
4778 if (uimm (aarch64_get_instr (cpu), 22, 22))
4782 for (i = 0; i < 2; i++)
4783 aarch64_set_vec_double (cpu, vd, i,
4784 aarch64_get_vec_double (cpu, vn, i) *
4785 aarch64_get_vec_double (cpu, vm, i) +
4786 aarch64_get_vec_double (cpu, vd, i));
4790 for (i = 0; i < (full ? 4 : 2); i++)
4791 aarch64_set_vec_float (cpu, vd, i,
4792 aarch64_get_vec_float (cpu, vn, i) *
4793 aarch64_get_vec_float (cpu, vm, i) +
4794 aarch64_get_vec_float (cpu, vd, i));
4799 do_vec_max (sim_cpu *cpu)
4802 instr[30] = full/half selector
4803 instr[29] = SMAX (0) / UMAX (1)
4804 instr[28,24] = 0 1110
4805 instr[23,22] = size: 00=> 8-bit, 01=> 16-bit, 10=> 32-bit
4808 instr[15,10] = 0110 01
4812 unsigned vm = uimm (aarch64_get_instr (cpu), 20, 16);
4813 unsigned vn = uimm (aarch64_get_instr (cpu), 9, 5);
4814 unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
4816 int full = uimm (aarch64_get_instr (cpu), 30, 30);
4818 NYI_assert (28, 24, 0x0E);
4819 NYI_assert (21, 21, 1);
4820 NYI_assert (15, 10, 0x19);
4822 if (uimm (aarch64_get_instr (cpu), 29, 29))
4824 switch (uimm (aarch64_get_instr (cpu), 23, 22))
4827 for (i = 0; i < (full ? 16 : 8); i++)
4828 aarch64_set_vec_u8 (cpu, vd, i,
4829 aarch64_get_vec_u8 (cpu, vn, i)
4830 > aarch64_get_vec_u8 (cpu, vm, i)
4831 ? aarch64_get_vec_u8 (cpu, vn, i)
4832 : aarch64_get_vec_u8 (cpu, vm, i));
4836 for (i = 0; i < (full ? 8 : 4); i++)
4837 aarch64_set_vec_u16 (cpu, vd, i,
4838 aarch64_get_vec_u16 (cpu, vn, i)
4839 > aarch64_get_vec_u16 (cpu, vm, i)
4840 ? aarch64_get_vec_u16 (cpu, vn, i)
4841 : aarch64_get_vec_u16 (cpu, vm, i));
4845 for (i = 0; i < (full ? 4 : 2); i++)
4846 aarch64_set_vec_u32 (cpu, vd, i,
4847 aarch64_get_vec_u32 (cpu, vn, i)
4848 > aarch64_get_vec_u32 (cpu, vm, i)
4849 ? aarch64_get_vec_u32 (cpu, vn, i)
4850 : aarch64_get_vec_u32 (cpu, vm, i));
4860 switch (uimm (aarch64_get_instr (cpu), 23, 22))
4863 for (i = 0; i < (full ? 16 : 8); i++)
4864 aarch64_set_vec_s8 (cpu, vd, i,
4865 aarch64_get_vec_s8 (cpu, vn, i)
4866 > aarch64_get_vec_s8 (cpu, vm, i)
4867 ? aarch64_get_vec_s8 (cpu, vn, i)
4868 : aarch64_get_vec_s8 (cpu, vm, i));
4872 for (i = 0; i < (full ? 8 : 4); i++)
4873 aarch64_set_vec_s16 (cpu, vd, i,
4874 aarch64_get_vec_s16 (cpu, vn, i)
4875 > aarch64_get_vec_s16 (cpu, vm, i)
4876 ? aarch64_get_vec_s16 (cpu, vn, i)
4877 : aarch64_get_vec_s16 (cpu, vm, i));
4881 for (i = 0; i < (full ? 4 : 2); i++)
4882 aarch64_set_vec_s32 (cpu, vd, i,
4883 aarch64_get_vec_s32 (cpu, vn, i)
4884 > aarch64_get_vec_s32 (cpu, vm, i)
4885 ? aarch64_get_vec_s32 (cpu, vn, i)
4886 : aarch64_get_vec_s32 (cpu, vm, i));
4897 do_vec_min (sim_cpu *cpu)
4900 instr[30] = full/half selector
4901 instr[29] = SMIN (0) / UMIN (1)
4902 instr[28,24] = 0 1110
4903 instr[23,22] = size: 00=> 8-bit, 01=> 16-bit, 10=> 32-bit
4906 instr[15,10] = 0110 11
4910 unsigned vm = uimm (aarch64_get_instr (cpu), 20, 16);
4911 unsigned vn = uimm (aarch64_get_instr (cpu), 9, 5);
4912 unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
4914 int full = uimm (aarch64_get_instr (cpu), 30, 30);
4916 NYI_assert (28, 24, 0x0E);
4917 NYI_assert (21, 21, 1);
4918 NYI_assert (15, 10, 0x1B);
4920 if (uimm (aarch64_get_instr (cpu), 29, 29))
4922 switch (uimm (aarch64_get_instr (cpu), 23, 22))
4925 for (i = 0; i < (full ? 16 : 8); i++)
4926 aarch64_set_vec_u8 (cpu, vd, i,
4927 aarch64_get_vec_u8 (cpu, vn, i)
4928 < aarch64_get_vec_u8 (cpu, vm, i)
4929 ? aarch64_get_vec_u8 (cpu, vn, i)
4930 : aarch64_get_vec_u8 (cpu, vm, i));
4934 for (i = 0; i < (full ? 8 : 4); i++)
4935 aarch64_set_vec_u16 (cpu, vd, i,
4936 aarch64_get_vec_u16 (cpu, vn, i)
4937 < aarch64_get_vec_u16 (cpu, vm, i)
4938 ? aarch64_get_vec_u16 (cpu, vn, i)
4939 : aarch64_get_vec_u16 (cpu, vm, i));
4943 for (i = 0; i < (full ? 4 : 2); i++)
4944 aarch64_set_vec_u32 (cpu, vd, i,
4945 aarch64_get_vec_u32 (cpu, vn, i)
4946 < aarch64_get_vec_u32 (cpu, vm, i)
4947 ? aarch64_get_vec_u32 (cpu, vn, i)
4948 : aarch64_get_vec_u32 (cpu, vm, i));
4958 switch (uimm (aarch64_get_instr (cpu), 23, 22))
4961 for (i = 0; i < (full ? 16 : 8); i++)
4962 aarch64_set_vec_s8 (cpu, vd, i,
4963 aarch64_get_vec_s8 (cpu, vn, i)
4964 < aarch64_get_vec_s8 (cpu, vm, i)
4965 ? aarch64_get_vec_s8 (cpu, vn, i)
4966 : aarch64_get_vec_s8 (cpu, vm, i));
4970 for (i = 0; i < (full ? 8 : 4); i++)
4971 aarch64_set_vec_s16 (cpu, vd, i,
4972 aarch64_get_vec_s16 (cpu, vn, i)
4973 < aarch64_get_vec_s16 (cpu, vm, i)
4974 ? aarch64_get_vec_s16 (cpu, vn, i)
4975 : aarch64_get_vec_s16 (cpu, vm, i));
4979 for (i = 0; i < (full ? 4 : 2); i++)
4980 aarch64_set_vec_s32 (cpu, vd, i,
4981 aarch64_get_vec_s32 (cpu, vn, i)
4982 < aarch64_get_vec_s32 (cpu, vm, i)
4983 ? aarch64_get_vec_s32 (cpu, vn, i)
4984 : aarch64_get_vec_s32 (cpu, vm, i));
4995 do_vec_sub_long (sim_cpu *cpu)
4998 instr[30] = lower (0) / upper (1)
4999 instr[29] = signed (0) / unsigned (1)
5000 instr[28,24] = 0 1110
5001 instr[23,22] = size: bytes (00), half (01), word (10)
5004 instr[15,10] = 0010 00
5006 instr[4,0] = V dest. */
5008 unsigned size = uimm (aarch64_get_instr (cpu), 23, 22);
5009 unsigned vm = uimm (aarch64_get_instr (cpu), 20, 16);
5010 unsigned vn = uimm (aarch64_get_instr (cpu), 9, 5);
5011 unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
5015 NYI_assert (28, 24, 0x0E);
5016 NYI_assert (21, 21, 1);
5017 NYI_assert (15, 10, 0x08);
5022 switch (uimm (aarch64_get_instr (cpu), 30, 29))
5024 case 2: /* SSUBL2. */
5026 case 0: /* SSUBL. */
5031 for (i = 0; i < 8; i++)
5032 aarch64_set_vec_s16 (cpu, vd, i,
5033 aarch64_get_vec_s8 (cpu, vn, i + bias)
5034 - aarch64_get_vec_s8 (cpu, vm, i + bias));
5039 for (i = 0; i < 4; i++)
5040 aarch64_set_vec_s32 (cpu, vd, i,
5041 aarch64_get_vec_s16 (cpu, vn, i + bias)
5042 - aarch64_get_vec_s16 (cpu, vm, i + bias));
5046 for (i = 0; i < 2; i++)
5047 aarch64_set_vec_s64 (cpu, vd, i,
5048 aarch64_get_vec_s32 (cpu, vn, i + bias)
5049 - aarch64_get_vec_s32 (cpu, vm, i + bias));
5057 case 3: /* USUBL2. */
5059 case 1: /* USUBL. */
5064 for (i = 0; i < 8; i++)
5065 aarch64_set_vec_u16 (cpu, vd, i,
5066 aarch64_get_vec_u8 (cpu, vn, i + bias)
5067 - aarch64_get_vec_u8 (cpu, vm, i + bias));
5072 for (i = 0; i < 4; i++)
5073 aarch64_set_vec_u32 (cpu, vd, i,
5074 aarch64_get_vec_u16 (cpu, vn, i + bias)
5075 - aarch64_get_vec_u16 (cpu, vm, i + bias));
5079 for (i = 0; i < 2; i++)
5080 aarch64_set_vec_u64 (cpu, vd, i,
5081 aarch64_get_vec_u32 (cpu, vn, i + bias)
5082 - aarch64_get_vec_u32 (cpu, vm, i + bias));
5092 #define DO_ADDP(FN) \
5095 for (i = 0; i < range; i++) \
5097 aarch64_set_vec_##FN (cpu, vd, i, \
5098 aarch64_get_vec_##FN (cpu, vn, i * 2) \
5099 + aarch64_get_vec_##FN (cpu, vn, i * 2 + 1)); \
5100 aarch64_set_vec_##FN (cpu, vd, i + range, \
5101 aarch64_get_vec_##FN (cpu, vm, i * 2) \
5102 + aarch64_get_vec_##FN (cpu, vm, i * 2 + 1)); \
5108 do_vec_ADDP (sim_cpu *cpu)
5111 instr[30] = half(0)/full(1)
5112 instr[29,24] = 00 1110
5113 instr[23,22] = size: bytes (00), half (01), word (10), long (11)
5116 instr[15,10] = 1011 11
5118 instr[4,0] = V dest. */
5120 unsigned full = uimm (aarch64_get_instr (cpu), 30, 30);
5121 unsigned size = uimm (aarch64_get_instr (cpu), 23, 22);
5122 unsigned vm = uimm (aarch64_get_instr (cpu), 20, 16);
5123 unsigned vn = uimm (aarch64_get_instr (cpu), 9, 5);
5124 unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
5127 NYI_assert (29, 24, 0x0E);
5128 NYI_assert (21, 21, 1);
5129 NYI_assert (15, 10, 0x2F);
5134 range = full ? 8 : 4;
5139 range = full ? 4 : 2;
5144 range = full ? 2 : 1;
5161 do_vec_UMOV (sim_cpu *cpu)
5164 instr[30] = 32-bit(0)/64-bit(1)
5165 instr[29,21] = 00 1110 000
5166 insrt[20,16] = size & index
5167 instr[15,10] = 0011 11
5168 instr[9,5] = V source
5169 instr[4,0] = R dest. */
5171 unsigned vs = uimm (aarch64_get_instr (cpu), 9, 5);
5172 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
5175 NYI_assert (29, 21, 0x070);
5176 NYI_assert (15, 10, 0x0F);
5178 if (uimm (aarch64_get_instr (cpu), 16, 16))
5180 /* Byte transfer. */
5181 index = uimm (aarch64_get_instr (cpu), 20, 17);
5182 aarch64_set_reg_u64 (cpu, rd, NO_SP,
5183 aarch64_get_vec_u8 (cpu, vs, index));
5185 else if (uimm (aarch64_get_instr (cpu), 17, 17))
5187 index = uimm (aarch64_get_instr (cpu), 20, 18);
5188 aarch64_set_reg_u64 (cpu, rd, NO_SP,
5189 aarch64_get_vec_u16 (cpu, vs, index));
5191 else if (uimm (aarch64_get_instr (cpu), 18, 18))
5193 index = uimm (aarch64_get_instr (cpu), 20, 19);
5194 aarch64_set_reg_u64 (cpu, rd, NO_SP,
5195 aarch64_get_vec_u32 (cpu, vs, index));
5199 if (uimm (aarch64_get_instr (cpu), 30, 30) != 1)
5202 index = uimm (aarch64_get_instr (cpu), 20, 20);
5203 aarch64_set_reg_u64 (cpu, rd, NO_SP,
5204 aarch64_get_vec_u64 (cpu, vs, index));
5209 do_vec_FABS (sim_cpu *cpu)
5212 instr[30] = half(0)/full(1)
5213 instr[29,23] = 00 1110 1
5214 instr[22] = float(0)/double(1)
5215 instr[21,16] = 10 0000
5216 instr[15,10] = 1111 10
5220 unsigned vn = uimm (aarch64_get_instr (cpu), 9, 5);
5221 unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
5222 unsigned full = uimm (aarch64_get_instr (cpu), 30, 30);
5225 NYI_assert (29, 23, 0x1D);
5226 NYI_assert (21, 10, 0x83E);
5228 if (uimm (aarch64_get_instr (cpu), 22, 22))
5233 for (i = 0; i < 2; i++)
5234 aarch64_set_vec_double (cpu, vd, i,
5235 fabs (aarch64_get_vec_double (cpu, vn, i)));
5239 for (i = 0; i < (full ? 4 : 2); i++)
5240 aarch64_set_vec_float (cpu, vd, i,
5241 fabsf (aarch64_get_vec_float (cpu, vn, i)));
5246 do_vec_FCVTZS (sim_cpu *cpu)
5249 instr[30] = half (0) / all (1)
5250 instr[29,23] = 00 1110 1
5251 instr[22] = single (0) / double (1)
5252 instr[21,10] = 10 0001 1011 10
5256 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
5257 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
5258 unsigned full = uimm (aarch64_get_instr (cpu), 30, 30);
5261 NYI_assert (31, 31, 0);
5262 NYI_assert (29, 23, 0x1D);
5263 NYI_assert (21, 10, 0x86E);
5265 if (uimm (aarch64_get_instr (cpu), 22, 22))
5270 for (i = 0; i < 2; i++)
5271 aarch64_set_vec_s64 (cpu, rd, i,
5272 (int64_t) aarch64_get_vec_double (cpu, rn, i));
5275 for (i = 0; i < (full ? 4 : 2); i++)
5276 aarch64_set_vec_s32 (cpu, rd, i,
5277 (int32_t) aarch64_get_vec_float (cpu, rn, i));
5281 do_vec_op1 (sim_cpu *cpu)
5284 instr[30] = half/full
5285 instr[29,24] = 00 1110
5288 instr[15,10] = sub-opcode
5291 NYI_assert (29, 24, 0x0E);
5293 if (uimm (aarch64_get_instr (cpu), 21, 21) == 0)
5295 if (uimm (aarch64_get_instr (cpu), 23, 22) == 0)
5297 if (uimm (aarch64_get_instr (cpu), 30, 30) == 1
5298 && uimm (aarch64_get_instr (cpu), 17, 14) == 0
5299 && uimm (aarch64_get_instr (cpu), 12, 10) == 7)
5300 return do_vec_ins_2 (cpu);
5302 switch (uimm (aarch64_get_instr (cpu), 15, 10))
5304 case 0x01: do_vec_DUP_vector_into_vector (cpu); return;
5305 case 0x03: do_vec_DUP_scalar_into_vector (cpu); return;
5306 case 0x07: do_vec_INS (cpu); return;
5307 case 0x0A: do_vec_TRN (cpu); return;
5310 if (uimm (aarch64_get_instr (cpu), 17, 16) == 0)
5312 do_vec_MOV_into_scalar (cpu);
5321 do_vec_TBL (cpu); return;
5325 do_vec_UZP (cpu); return;
5329 do_vec_ZIP (cpu); return;
5336 switch (uimm (aarch64_get_instr (cpu), 13, 10))
5338 case 0x6: do_vec_UZP (cpu); return;
5339 case 0xE: do_vec_ZIP (cpu); return;
5340 case 0xA: do_vec_TRN (cpu); return;
5341 case 0xF: do_vec_UMOV (cpu); return;
5346 switch (uimm (aarch64_get_instr (cpu), 15, 10))
5349 switch (uimm (aarch64_get_instr (cpu), 23, 21))
5351 case 1: do_vec_AND (cpu); return;
5352 case 3: do_vec_BIC (cpu); return;
5353 case 5: do_vec_ORR (cpu); return;
5354 case 7: do_vec_ORN (cpu); return;
5358 case 0x08: do_vec_sub_long (cpu); return;
5359 case 0x0a: do_vec_XTN (cpu); return;
5360 case 0x11: do_vec_SSHL (cpu); return;
5361 case 0x19: do_vec_max (cpu); return;
5362 case 0x1B: do_vec_min (cpu); return;
5363 case 0x21: do_vec_add (cpu); return;
5364 case 0x25: do_vec_MLA (cpu); return;
5365 case 0x27: do_vec_mul (cpu); return;
5366 case 0x2F: do_vec_ADDP (cpu); return;
5367 case 0x30: do_vec_mull (cpu); return;
5368 case 0x33: do_vec_FMLA (cpu); return;
5369 case 0x35: do_vec_fadd (cpu); return;
5372 switch (uimm (aarch64_get_instr (cpu), 20, 16))
5374 case 0x00: do_vec_ABS (cpu); return;
5375 case 0x01: do_vec_FCVTZS (cpu); return;
5376 case 0x11: do_vec_ADDV (cpu); return;
5382 do_vec_Fminmax (cpu); return;
5394 do_vec_compare (cpu); return;
5397 do_vec_FABS (cpu); return;
5405 do_vec_xtl (sim_cpu *cpu)
5408 instr[30,29] = SXTL (00), UXTL (01), SXTL2 (10), UXTL2 (11)
5409 instr[28,22] = 0 1111 00
5410 instr[21,16] = size & shift (USHLL, SSHLL, USHLL2, SSHLL2)
5411 instr[15,10] = 1010 01
5412 instr[9,5] = V source
5413 instr[4,0] = V dest. */
5415 unsigned vs = uimm (aarch64_get_instr (cpu), 9, 5);
5416 unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
5417 unsigned i, shift, bias = 0;
5419 NYI_assert (28, 22, 0x3C);
5420 NYI_assert (15, 10, 0x29);
5422 switch (uimm (aarch64_get_instr (cpu), 30, 29))
5424 case 2: /* SXTL2, SSHLL2. */
5426 case 0: /* SXTL, SSHLL. */
5427 if (uimm (aarch64_get_instr (cpu), 21, 21))
5429 shift = uimm (aarch64_get_instr (cpu), 20, 16);
5431 (cpu, vd, 0, aarch64_get_vec_s32 (cpu, vs, bias) << shift);
5433 (cpu, vd, 1, aarch64_get_vec_s32 (cpu, vs, bias + 1) << shift);
5435 else if (uimm (aarch64_get_instr (cpu), 20, 20))
5437 shift = uimm (aarch64_get_instr (cpu), 19, 16);
5439 for (i = 0; i < 4; i++)
5441 (cpu, vd, i, aarch64_get_vec_s16 (cpu, vs, i + bias) << shift);
5445 NYI_assert (19, 19, 1);
5447 shift = uimm (aarch64_get_instr (cpu), 18, 16);
5449 for (i = 0; i < 8; i++)
5451 (cpu, vd, i, aarch64_get_vec_s8 (cpu, vs, i + bias) << shift);
5455 case 3: /* UXTL2, USHLL2. */
5457 case 1: /* UXTL, USHLL. */
5458 if (uimm (aarch64_get_instr (cpu), 21, 21))
5460 shift = uimm (aarch64_get_instr (cpu), 20, 16);
5462 (cpu, vd, 0, aarch64_get_vec_u32 (cpu, vs, bias) << shift);
5464 (cpu, vd, 1, aarch64_get_vec_u32 (cpu, vs, bias + 1) << shift);
5466 else if (uimm (aarch64_get_instr (cpu), 20, 20))
5468 shift = uimm (aarch64_get_instr (cpu), 19, 16);
5470 for (i = 0; i < 4; i++)
5472 (cpu, vd, i, aarch64_get_vec_u16 (cpu, vs, i + bias) << shift);
5476 NYI_assert (19, 19, 1);
5478 shift = uimm (aarch64_get_instr (cpu), 18, 16);
5480 for (i = 0; i < 8; i++)
5482 (cpu, vd, i, aarch64_get_vec_u8 (cpu, vs, i + bias) << shift);
5492 do_vec_SHL (sim_cpu *cpu)
5495 instr [30] = half(0)/full(1)
5496 instr [29,23] = 001 1110
5497 instr [22,16] = size and shift amount
5498 instr [15,10] = 01 0101
5500 instr [4, 0] = Vd. */
5503 int full = uimm (aarch64_get_instr (cpu), 30, 30);
5504 unsigned vs = uimm (aarch64_get_instr (cpu), 9, 5);
5505 unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
5508 NYI_assert (29, 23, 0x1E);
5509 NYI_assert (15, 10, 0x15);
5511 if (uimm (aarch64_get_instr (cpu), 22, 22))
5513 shift = uimm (aarch64_get_instr (cpu), 21, 16) - 1;
5518 for (i = 0; i < 2; i++)
5520 uint64_t val = aarch64_get_vec_u64 (cpu, vs, i);
5521 aarch64_set_vec_u64 (cpu, vd, i, val << shift);
5527 if (uimm (aarch64_get_instr (cpu), 21, 21))
5529 shift = uimm (aarch64_get_instr (cpu), 20, 16) - 1;
5531 for (i = 0; i < (full ? 4 : 2); i++)
5533 uint32_t val = aarch64_get_vec_u32 (cpu, vs, i);
5534 aarch64_set_vec_u32 (cpu, vd, i, val << shift);
5540 if (uimm (aarch64_get_instr (cpu), 20, 20))
5542 shift = uimm (aarch64_get_instr (cpu), 19, 16) - 1;
5544 for (i = 0; i < (full ? 8 : 4); i++)
5546 uint16_t val = aarch64_get_vec_u16 (cpu, vs, i);
5547 aarch64_set_vec_u16 (cpu, vd, i, val << shift);
5553 if (uimm (aarch64_get_instr (cpu), 19, 19) == 0)
5556 shift = uimm (aarch64_get_instr (cpu), 18, 16) - 1;
5558 for (i = 0; i < (full ? 16 : 8); i++)
5560 uint8_t val = aarch64_get_vec_u8 (cpu, vs, i);
5561 aarch64_set_vec_u8 (cpu, vd, i, val << shift);
5566 do_vec_SSHR_USHR (sim_cpu *cpu)
5569 instr [30] = half(0)/full(1)
5570 instr [29] = signed(0)/unsigned(1)
5571 instr [28,23] = 01 1110
5572 instr [22,16] = size and shift amount
5573 instr [15,10] = 0000 01
5575 instr [4, 0] = Vd. */
5578 int full = uimm (aarch64_get_instr (cpu), 30, 30);
5579 int sign = uimm (aarch64_get_instr (cpu), 29, 29);
5580 unsigned vs = uimm (aarch64_get_instr (cpu), 9, 5);
5581 unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
5584 NYI_assert (28, 23, 0x1E);
5585 NYI_assert (15, 10, 0x01);
5587 if (uimm (aarch64_get_instr (cpu), 22, 22))
5589 shift = uimm (aarch64_get_instr (cpu), 21, 16);
5595 for (i = 0; i < 2; i++)
5597 int64_t val = aarch64_get_vec_s64 (cpu, vs, i);
5598 aarch64_set_vec_s64 (cpu, vd, i, val >> shift);
5601 for (i = 0; i < 2; i++)
5603 uint64_t val = aarch64_get_vec_u64 (cpu, vs, i);
5604 aarch64_set_vec_u64 (cpu, vd, i, val >> shift);
5610 if (uimm (aarch64_get_instr (cpu), 21, 21))
5612 shift = uimm (aarch64_get_instr (cpu), 20, 16);
5615 for (i = 0; i < (full ? 4 : 2); i++)
5617 int32_t val = aarch64_get_vec_s32 (cpu, vs, i);
5618 aarch64_set_vec_s32 (cpu, vd, i, val >> shift);
5621 for (i = 0; i < (full ? 4 : 2); i++)
5623 uint32_t val = aarch64_get_vec_u32 (cpu, vs, i);
5624 aarch64_set_vec_u32 (cpu, vd, i, val >> shift);
5630 if (uimm (aarch64_get_instr (cpu), 20, 20))
5632 shift = uimm (aarch64_get_instr (cpu), 19, 16);
5635 for (i = 0; i < (full ? 8 : 4); i++)
5637 int16_t val = aarch64_get_vec_s16 (cpu, vs, i);
5638 aarch64_set_vec_s16 (cpu, vd, i, val >> shift);
5641 for (i = 0; i < (full ? 8 : 4); i++)
5643 uint16_t val = aarch64_get_vec_u16 (cpu, vs, i);
5644 aarch64_set_vec_u16 (cpu, vd, i, val >> shift);
5650 if (uimm (aarch64_get_instr (cpu), 19, 19) == 0)
5653 shift = uimm (aarch64_get_instr (cpu), 18, 16);
5656 for (i = 0; i < (full ? 16 : 8); i++)
5658 int8_t val = aarch64_get_vec_s8 (cpu, vs, i);
5659 aarch64_set_vec_s8 (cpu, vd, i, val >> shift);
5662 for (i = 0; i < (full ? 16 : 8); i++)
5664 uint8_t val = aarch64_get_vec_u8 (cpu, vs, i);
5665 aarch64_set_vec_u8 (cpu, vd, i, val >> shift);
5670 do_vec_op2 (sim_cpu *cpu)
5673 instr[30] = half/full
5674 instr[29,24] = 00 1111
5676 instr[22,16] = element size & index
5677 instr[15,10] = sub-opcode
5681 NYI_assert (29, 24, 0x0F);
5683 if (uimm (aarch64_get_instr (cpu), 23, 23) != 0)
5686 switch (uimm (aarch64_get_instr (cpu), 15, 10))
5688 case 0x01: do_vec_SSHR_USHR (cpu); return;
5689 case 0x15: do_vec_SHL (cpu); return;
5690 case 0x29: do_vec_xtl (cpu); return;
5696 do_vec_neg (sim_cpu *cpu)
5699 instr[30] = full(1)/half(0)
5700 instr[29,24] = 10 1110
5701 instr[23,22] = size: byte(00), half (01), word (10), long (11)
5702 instr[21,10] = 1000 0010 1110
5706 int full = uimm (aarch64_get_instr (cpu), 30, 30);
5707 unsigned vs = uimm (aarch64_get_instr (cpu), 9, 5);
5708 unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
5711 NYI_assert (29, 24, 0x2E);
5712 NYI_assert (21, 10, 0x82E);
5714 switch (uimm (aarch64_get_instr (cpu), 23, 22))
5717 for (i = 0; i < (full ? 16 : 8); i++)
5718 aarch64_set_vec_s8 (cpu, vd, i, - aarch64_get_vec_s8 (cpu, vs, i));
5722 for (i = 0; i < (full ? 8 : 4); i++)
5723 aarch64_set_vec_s16 (cpu, vd, i, - aarch64_get_vec_s16 (cpu, vs, i));
5727 for (i = 0; i < (full ? 4 : 2); i++)
5728 aarch64_set_vec_s32 (cpu, vd, i, - aarch64_get_vec_s32 (cpu, vs, i));
5734 for (i = 0; i < 2; i++)
5735 aarch64_set_vec_s64 (cpu, vd, i, - aarch64_get_vec_s64 (cpu, vs, i));
5744 do_vec_sqrt (sim_cpu *cpu)
5747 instr[30] = full(1)/half(0)
5748 instr[29,23] = 101 1101
5749 instr[22] = single(0)/double(1)
5750 instr[21,10] = 1000 0111 1110
5754 int full = uimm (aarch64_get_instr (cpu), 30, 30);
5755 unsigned vs = uimm (aarch64_get_instr (cpu), 9, 5);
5756 unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
5759 NYI_assert (29, 23, 0x5B);
5760 NYI_assert (21, 10, 0x87E);
5762 if (uimm (aarch64_get_instr (cpu), 22, 22) == 0)
5763 for (i = 0; i < (full ? 4 : 2); i++)
5764 aarch64_set_vec_float (cpu, vd, i,
5765 sqrtf (aarch64_get_vec_float (cpu, vs, i)));
5767 for (i = 0; i < 2; i++)
5768 aarch64_set_vec_double (cpu, vd, i,
5769 sqrt (aarch64_get_vec_double (cpu, vs, i)));
5773 do_vec_mls_indexed (sim_cpu *cpu)
5776 instr[30] = half(0)/full(1)
5777 instr[29,24] = 10 1111
5778 instr[23,22] = 16-bit(01)/32-bit(10)
5779 instr[21,20+11] = index (if 16-bit)
5780 instr[21+11] = index (if 32-bit)
5783 instr[11] = part of index
5788 int full = uimm (aarch64_get_instr (cpu), 30, 30);
5789 unsigned vs = uimm (aarch64_get_instr (cpu), 9, 5);
5790 unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
5791 unsigned vm = uimm (aarch64_get_instr (cpu), 20, 16);
5794 NYI_assert (15, 12, 4);
5795 NYI_assert (10, 10, 0);
5797 switch (uimm (aarch64_get_instr (cpu), 23, 22))
5807 elem = (uimm (aarch64_get_instr (cpu), 21, 20) << 1)
5808 | uimm (aarch64_get_instr (cpu), 11, 11);
5809 val = aarch64_get_vec_u16 (cpu, vm, elem);
5811 for (i = 0; i < (full ? 8 : 4); i++)
5812 aarch64_set_vec_u32 (cpu, vd, i,
5813 aarch64_get_vec_u32 (cpu, vd, i) -
5814 (aarch64_get_vec_u32 (cpu, vs, i) * val));
5820 unsigned elem = (uimm (aarch64_get_instr (cpu), 21, 21) << 1)
5821 | uimm (aarch64_get_instr (cpu), 11, 11);
5822 uint64_t val = aarch64_get_vec_u32 (cpu, vm, elem);
5824 for (i = 0; i < (full ? 4 : 2); i++)
5825 aarch64_set_vec_u64 (cpu, vd, i,
5826 aarch64_get_vec_u64 (cpu, vd, i) -
5827 (aarch64_get_vec_u64 (cpu, vs, i) * val));
5839 do_vec_SUB (sim_cpu *cpu)
5842 instr [30] = half(0)/full(1)
5843 instr [29,24] = 10 1110
5844 instr [23,22] = size: byte(00, half(01), word (10), long (11)
5847 instr [15,10] = 10 0001
5849 instr [4, 0] = Vd. */
5851 unsigned full = uimm (aarch64_get_instr (cpu), 30, 30);
5852 unsigned vm = uimm (aarch64_get_instr (cpu), 20, 16);
5853 unsigned vn = uimm (aarch64_get_instr (cpu), 9, 5);
5854 unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
5857 NYI_assert (29, 24, 0x2E);
5858 NYI_assert (21, 21, 1);
5859 NYI_assert (15, 10, 0x21);
5861 switch (uimm (aarch64_get_instr (cpu), 23, 22))
5864 for (i = 0; i < (full ? 16 : 8); i++)
5865 aarch64_set_vec_s8 (cpu, vd, i,
5866 aarch64_get_vec_s8 (cpu, vn, i)
5867 - aarch64_get_vec_s8 (cpu, vm, i));
5871 for (i = 0; i < (full ? 8 : 4); i++)
5872 aarch64_set_vec_s16 (cpu, vd, i,
5873 aarch64_get_vec_s16 (cpu, vn, i)
5874 - aarch64_get_vec_s16 (cpu, vm, i));
5878 for (i = 0; i < (full ? 4 : 2); i++)
5879 aarch64_set_vec_s32 (cpu, vd, i,
5880 aarch64_get_vec_s32 (cpu, vn, i)
5881 - aarch64_get_vec_s32 (cpu, vm, i));
5888 for (i = 0; i < 2; i++)
5889 aarch64_set_vec_s64 (cpu, vd, i,
5890 aarch64_get_vec_s64 (cpu, vn, i)
5891 - aarch64_get_vec_s64 (cpu, vm, i));
5900 do_vec_MLS (sim_cpu *cpu)
5903 instr [30] = half(0)/full(1)
5904 instr [29,24] = 10 1110
5905 instr [23,22] = size: byte(00, half(01), word (10)
5908 instr [15,10] = 10 0101
5910 instr [4, 0] = Vd. */
5912 unsigned full = uimm (aarch64_get_instr (cpu), 30, 30);
5913 unsigned vm = uimm (aarch64_get_instr (cpu), 20, 16);
5914 unsigned vn = uimm (aarch64_get_instr (cpu), 9, 5);
5915 unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
5918 NYI_assert (29, 24, 0x2E);
5919 NYI_assert (21, 21, 1);
5920 NYI_assert (15, 10, 0x25);
5922 switch (uimm (aarch64_get_instr (cpu), 23, 22))
5925 for (i = 0; i < (full ? 16 : 8); i++)
5926 aarch64_set_vec_u8 (cpu, vd, i,
5927 (aarch64_get_vec_u8 (cpu, vn, i)
5928 * aarch64_get_vec_u8 (cpu, vm, i))
5929 - aarch64_get_vec_u8 (cpu, vd, i));
5933 for (i = 0; i < (full ? 8 : 4); i++)
5934 aarch64_set_vec_u16 (cpu, vd, i,
5935 (aarch64_get_vec_u16 (cpu, vn, i)
5936 * aarch64_get_vec_u16 (cpu, vm, i))
5937 - aarch64_get_vec_u16 (cpu, vd, i));
5941 for (i = 0; i < (full ? 4 : 2); i++)
5942 aarch64_set_vec_u32 (cpu, vd, i,
5943 (aarch64_get_vec_u32 (cpu, vn, i)
5944 * aarch64_get_vec_u32 (cpu, vm, i))
5945 - aarch64_get_vec_u32 (cpu, vd, i));
5954 do_vec_FDIV (sim_cpu *cpu)
5957 instr [30] = half(0)/full(1)
5958 instr [29,23] = 10 1110 0
5959 instr [22] = float()/double(1)
5962 instr [15,10] = 1111 11
5964 instr [4, 0] = Vd. */
5966 unsigned full = uimm (aarch64_get_instr (cpu), 30, 30);
5967 unsigned vm = uimm (aarch64_get_instr (cpu), 20, 16);
5968 unsigned vn = uimm (aarch64_get_instr (cpu), 9, 5);
5969 unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
5972 NYI_assert (29, 23, 0x5C);
5973 NYI_assert (21, 21, 1);
5974 NYI_assert (15, 10, 0x3F);
5976 if (uimm (aarch64_get_instr (cpu), 22, 22))
5981 for (i = 0; i < 2; i++)
5982 aarch64_set_vec_double (cpu, vd, i,
5983 aarch64_get_vec_double (cpu, vn, i)
5984 / aarch64_get_vec_double (cpu, vm, i));
5987 for (i = 0; i < (full ? 4 : 2); i++)
5988 aarch64_set_vec_float (cpu, vd, i,
5989 aarch64_get_vec_float (cpu, vn, i)
5990 / aarch64_get_vec_float (cpu, vm, i));
5994 do_vec_FMUL (sim_cpu *cpu)
5997 instr [30] = half(0)/full(1)
5998 instr [29,23] = 10 1110 0
5999 instr [22] = float(0)/double(1)
6002 instr [15,10] = 1101 11
6004 instr [4, 0] = Vd. */
6006 unsigned full = uimm (aarch64_get_instr (cpu), 30, 30);
6007 unsigned vm = uimm (aarch64_get_instr (cpu), 20, 16);
6008 unsigned vn = uimm (aarch64_get_instr (cpu), 9, 5);
6009 unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
6012 NYI_assert (29, 23, 0x5C);
6013 NYI_assert (21, 21, 1);
6014 NYI_assert (15, 10, 0x37);
6016 if (uimm (aarch64_get_instr (cpu), 22, 22))
6021 for (i = 0; i < 2; i++)
6022 aarch64_set_vec_double (cpu, vd, i,
6023 aarch64_get_vec_double (cpu, vn, i)
6024 * aarch64_get_vec_double (cpu, vm, i));
6027 for (i = 0; i < (full ? 4 : 2); i++)
6028 aarch64_set_vec_float (cpu, vd, i,
6029 aarch64_get_vec_float (cpu, vn, i)
6030 * aarch64_get_vec_float (cpu, vm, i));
6034 do_vec_FADDP (sim_cpu *cpu)
6037 instr [30] = half(0)/full(1)
6038 instr [29,23] = 10 1110 0
6039 instr [22] = float(0)/double(1)
6042 instr [15,10] = 1101 01
6044 instr [4, 0] = Vd. */
6046 unsigned full = uimm (aarch64_get_instr (cpu), 30, 30);
6047 unsigned vm = uimm (aarch64_get_instr (cpu), 20, 16);
6048 unsigned vn = uimm (aarch64_get_instr (cpu), 9, 5);
6049 unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
6051 NYI_assert (29, 23, 0x5C);
6052 NYI_assert (21, 21, 1);
6053 NYI_assert (15, 10, 0x35);
6055 if (uimm (aarch64_get_instr (cpu), 22, 22))
6060 aarch64_set_vec_double (cpu, vd, 0, aarch64_get_vec_double (cpu, vn, 0)
6061 + aarch64_get_vec_double (cpu, vn, 1));
6062 aarch64_set_vec_double (cpu, vd, 1, aarch64_get_vec_double (cpu, vm, 0)
6063 + aarch64_get_vec_double (cpu, vm, 1));
6067 aarch64_set_vec_float (cpu, vd, 0, aarch64_get_vec_float (cpu, vn, 0)
6068 + aarch64_get_vec_float (cpu, vn, 1));
6070 aarch64_set_vec_float (cpu, vd, 1, aarch64_get_vec_float (cpu, vn, 2)
6071 + aarch64_get_vec_float (cpu, vn, 3));
6072 aarch64_set_vec_float (cpu, vd, full ? 2 : 1,
6073 aarch64_get_vec_float (cpu, vm, 0)
6074 + aarch64_get_vec_float (cpu, vm, 1));
6076 aarch64_set_vec_float (cpu, vd, 3,
6077 aarch64_get_vec_float (cpu, vm, 2)
6078 + aarch64_get_vec_float (cpu, vm, 3));
6083 do_vec_FSQRT (sim_cpu *cpu)
6086 instr[30] = half(0)/full(1)
6087 instr[29,23] = 10 1110 1
6088 instr[22] = single(0)/double(1)
6089 instr[21,10] = 10 0001 1111 10
6091 instr[4,0] = Vdest. */
6093 unsigned vn = uimm (aarch64_get_instr (cpu), 9, 5);
6094 unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
6095 unsigned full = uimm (aarch64_get_instr (cpu), 30, 30);
6098 NYI_assert (29, 23, 0x5D);
6099 NYI_assert (21, 10, 0x87E);
6101 if (uimm (aarch64_get_instr (cpu), 22, 22))
6106 for (i = 0; i < 2; i++)
6107 aarch64_set_vec_double (cpu, vd, i,
6108 sqrt (aarch64_get_vec_double (cpu, vn, i)));
6112 for (i = 0; i < (full ? 4 : 2); i++)
6113 aarch64_set_vec_float (cpu, vd, i,
6114 sqrtf (aarch64_get_vec_float (cpu, vn, i)));
6119 do_vec_FNEG (sim_cpu *cpu)
6122 instr[30] = half (0)/full (1)
6123 instr[29,23] = 10 1110 1
6124 instr[22] = single (0)/double (1)
6125 instr[21,10] = 10 0000 1111 10
6127 instr[4,0] = Vdest. */
6129 unsigned vn = uimm (aarch64_get_instr (cpu), 9, 5);
6130 unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
6131 unsigned full = uimm (aarch64_get_instr (cpu), 30, 30);
6134 NYI_assert (29, 23, 0x5D);
6135 NYI_assert (21, 10, 0x83E);
6137 if (uimm (aarch64_get_instr (cpu), 22, 22))
6142 for (i = 0; i < 2; i++)
6143 aarch64_set_vec_double (cpu, vd, i,
6144 - aarch64_get_vec_double (cpu, vn, i));
6148 for (i = 0; i < (full ? 4 : 2); i++)
6149 aarch64_set_vec_float (cpu, vd, i,
6150 - aarch64_get_vec_float (cpu, vn, i));
6155 do_vec_NOT (sim_cpu *cpu)
6158 instr[30] = half (0)/full (1)
6159 instr[29,21] = 10 1110 001
6160 instr[20,16] = 0 0000
6161 instr[15,10] = 0101 10
6165 unsigned vn = uimm (aarch64_get_instr (cpu), 9, 5);
6166 unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
6168 int full = uimm (aarch64_get_instr (cpu), 30, 30);
6170 NYI_assert (29, 10, 0xB8816);
6172 for (i = 0; i < (full ? 16 : 8); i++)
6173 aarch64_set_vec_u8 (cpu, vd, i, ~ aarch64_get_vec_u8 (cpu, vn, i));
6177 do_vec_MOV_element (sim_cpu *cpu)
6179 /* instr[31,21] = 0110 1110 000
6180 instr[20,16] = size & dest index
6182 instr[14,11] = source index
6187 unsigned vs = uimm (aarch64_get_instr (cpu), 9, 5);
6188 unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
6192 NYI_assert (31, 21, 0x370);
6193 NYI_assert (15, 15, 0);
6194 NYI_assert (10, 10, 1);
6196 if (uimm (aarch64_get_instr (cpu), 16, 16))
6199 src_index = uimm (aarch64_get_instr (cpu), 14, 11);
6200 dst_index = uimm (aarch64_get_instr (cpu), 20, 17);
6201 aarch64_set_vec_u8 (cpu, vd, dst_index,
6202 aarch64_get_vec_u8 (cpu, vs, src_index));
6204 else if (uimm (aarch64_get_instr (cpu), 17, 17))
6207 NYI_assert (11, 11, 0);
6208 src_index = uimm (aarch64_get_instr (cpu), 14, 12);
6209 dst_index = uimm (aarch64_get_instr (cpu), 20, 18);
6210 aarch64_set_vec_u16 (cpu, vd, dst_index,
6211 aarch64_get_vec_u16 (cpu, vs, src_index));
6213 else if (uimm (aarch64_get_instr (cpu), 18, 18))
6216 NYI_assert (12, 11, 0);
6217 src_index = uimm (aarch64_get_instr (cpu), 14, 13);
6218 dst_index = uimm (aarch64_get_instr (cpu), 20, 19);
6219 aarch64_set_vec_u32 (cpu, vd, dst_index,
6220 aarch64_get_vec_u32 (cpu, vs, src_index));
6224 NYI_assert (19, 19, 1);
6225 NYI_assert (13, 11, 0);
6226 src_index = uimm (aarch64_get_instr (cpu), 14, 14);
6227 dst_index = uimm (aarch64_get_instr (cpu), 20, 20);
6228 aarch64_set_vec_u64 (cpu, vd, dst_index,
6229 aarch64_get_vec_u64 (cpu, vs, src_index));
6234 dexAdvSIMD0 (sim_cpu *cpu)
6236 /* instr [28,25] = 0 111. */
6237 if ( uimm (aarch64_get_instr (cpu), 15, 10) == 0x07
6238 && (uimm (aarch64_get_instr (cpu), 9, 5) ==
6239 uimm (aarch64_get_instr (cpu), 20, 16)))
6241 if (uimm (aarch64_get_instr (cpu), 31, 21) == 0x075
6242 || uimm (aarch64_get_instr (cpu), 31, 21) == 0x275)
6244 do_vec_MOV_whole_vector (cpu);
6249 if (uimm (aarch64_get_instr (cpu), 29, 19) == 0x1E0)
6251 do_vec_MOV_immediate (cpu);
6255 if (uimm (aarch64_get_instr (cpu), 29, 19) == 0x5E0)
6261 if (uimm (aarch64_get_instr (cpu), 29, 19) == 0x1C0
6262 || uimm (aarch64_get_instr (cpu), 29, 19) == 0x1C1)
6264 if (uimm (aarch64_get_instr (cpu), 15, 10) == 0x03)
6266 do_vec_DUP_scalar_into_vector (cpu);
6271 switch (uimm (aarch64_get_instr (cpu), 29, 24))
6273 case 0x0E: do_vec_op1 (cpu); return;
6274 case 0x0F: do_vec_op2 (cpu); return;
6277 switch (uimm (aarch64_get_instr (cpu), 15, 10))
6279 case 0x01: do_vec_SSHR_USHR (cpu); return;
6281 case 0x12: do_vec_mls_indexed (cpu); return;
6282 case 0x29: do_vec_xtl (cpu); return;
6288 if (uimm (aarch64_get_instr (cpu), 21, 21) == 1)
6290 switch (uimm (aarch64_get_instr (cpu), 15, 10))
6293 switch (uimm (aarch64_get_instr (cpu), 23, 22))
6295 case 0: do_vec_EOR (cpu); return;
6296 case 1: do_vec_BSL (cpu); return;
6298 case 3: do_vec_bit (cpu); return;
6302 case 0x08: do_vec_sub_long (cpu); return;
6303 case 0x11: do_vec_USHL (cpu); return;
6304 case 0x16: do_vec_NOT (cpu); return;
6305 case 0x19: do_vec_max (cpu); return;
6306 case 0x1B: do_vec_min (cpu); return;
6307 case 0x21: do_vec_SUB (cpu); return;
6308 case 0x25: do_vec_MLS (cpu); return;
6309 case 0x31: do_vec_FminmaxNMP (cpu); return;
6310 case 0x35: do_vec_FADDP (cpu); return;
6311 case 0x37: do_vec_FMUL (cpu); return;
6312 case 0x3F: do_vec_FDIV (cpu); return;
6315 switch (uimm (aarch64_get_instr (cpu), 20, 16))
6317 case 0x00: do_vec_FNEG (cpu); return;
6318 case 0x01: do_vec_FSQRT (cpu); return;
6332 do_vec_compare (cpu); return;
6338 if (uimm (aarch64_get_instr (cpu), 31, 21) == 0x370)
6340 do_vec_MOV_element (cpu);
6344 switch (uimm (aarch64_get_instr (cpu), 21, 10))
6346 case 0x82E: do_vec_neg (cpu); return;
6347 case 0x87E: do_vec_sqrt (cpu); return;
6349 if (uimm (aarch64_get_instr (cpu), 15, 10) == 0x30)
6367 /* Float multiply add. */
6369 fmadds (sim_cpu *cpu)
6371 unsigned sa = uimm (aarch64_get_instr (cpu), 14, 10);
6372 unsigned sm = uimm (aarch64_get_instr (cpu), 20, 16);
6373 unsigned sn = uimm (aarch64_get_instr (cpu), 9, 5);
6374 unsigned sd = uimm (aarch64_get_instr (cpu), 4, 0);
6376 aarch64_set_FP_float (cpu, sd, aarch64_get_FP_float (cpu, sa)
6377 + aarch64_get_FP_float (cpu, sn)
6378 * aarch64_get_FP_float (cpu, sm));
6381 /* Double multiply add. */
6383 fmaddd (sim_cpu *cpu)
6385 unsigned sa = uimm (aarch64_get_instr (cpu), 14, 10);
6386 unsigned sm = uimm (aarch64_get_instr (cpu), 20, 16);
6387 unsigned sn = uimm (aarch64_get_instr (cpu), 9, 5);
6388 unsigned sd = uimm (aarch64_get_instr (cpu), 4, 0);
6390 aarch64_set_FP_double (cpu, sd, aarch64_get_FP_double (cpu, sa)
6391 + aarch64_get_FP_double (cpu, sn)
6392 * aarch64_get_FP_double (cpu, sm));
6395 /* Float multiply subtract. */
6397 fmsubs (sim_cpu *cpu)
6399 unsigned sa = uimm (aarch64_get_instr (cpu), 14, 10);
6400 unsigned sm = uimm (aarch64_get_instr (cpu), 20, 16);
6401 unsigned sn = uimm (aarch64_get_instr (cpu), 9, 5);
6402 unsigned sd = uimm (aarch64_get_instr (cpu), 4, 0);
6404 aarch64_set_FP_float (cpu, sd, aarch64_get_FP_float (cpu, sa)
6405 - aarch64_get_FP_float (cpu, sn)
6406 * aarch64_get_FP_float (cpu, sm));
6409 /* Double multiply subtract. */
6411 fmsubd (sim_cpu *cpu)
6413 unsigned sa = uimm (aarch64_get_instr (cpu), 14, 10);
6414 unsigned sm = uimm (aarch64_get_instr (cpu), 20, 16);
6415 unsigned sn = uimm (aarch64_get_instr (cpu), 9, 5);
6416 unsigned sd = uimm (aarch64_get_instr (cpu), 4, 0);
6418 aarch64_set_FP_double (cpu, sd, aarch64_get_FP_double (cpu, sa)
6419 - aarch64_get_FP_double (cpu, sn)
6420 * aarch64_get_FP_double (cpu, sm));
6423 /* Float negative multiply add. */
6425 fnmadds (sim_cpu *cpu)
6427 unsigned sa = uimm (aarch64_get_instr (cpu), 14, 10);
6428 unsigned sm = uimm (aarch64_get_instr (cpu), 20, 16);
6429 unsigned sn = uimm (aarch64_get_instr (cpu), 9, 5);
6430 unsigned sd = uimm (aarch64_get_instr (cpu), 4, 0);
6432 aarch64_set_FP_float (cpu, sd, - aarch64_get_FP_float (cpu, sa)
6433 + (- aarch64_get_FP_float (cpu, sn))
6434 * aarch64_get_FP_float (cpu, sm));
6437 /* Double negative multiply add. */
6439 fnmaddd (sim_cpu *cpu)
6441 unsigned sa = uimm (aarch64_get_instr (cpu), 14, 10);
6442 unsigned sm = uimm (aarch64_get_instr (cpu), 20, 16);
6443 unsigned sn = uimm (aarch64_get_instr (cpu), 9, 5);
6444 unsigned sd = uimm (aarch64_get_instr (cpu), 4, 0);
6446 aarch64_set_FP_double (cpu, sd, - aarch64_get_FP_double (cpu, sa)
6447 + (- aarch64_get_FP_double (cpu, sn))
6448 * aarch64_get_FP_double (cpu, sm));
6451 /* Float negative multiply subtract. */
6453 fnmsubs (sim_cpu *cpu)
6455 unsigned sa = uimm (aarch64_get_instr (cpu), 14, 10);
6456 unsigned sm = uimm (aarch64_get_instr (cpu), 20, 16);
6457 unsigned sn = uimm (aarch64_get_instr (cpu), 9, 5);
6458 unsigned sd = uimm (aarch64_get_instr (cpu), 4, 0);
6460 aarch64_set_FP_float (cpu, sd, - aarch64_get_FP_float (cpu, sa)
6461 + aarch64_get_FP_float (cpu, sn)
6462 * aarch64_get_FP_float (cpu, sm));
6465 /* Double negative multiply subtract. */
6467 fnmsubd (sim_cpu *cpu)
6469 unsigned sa = uimm (aarch64_get_instr (cpu), 14, 10);
6470 unsigned sm = uimm (aarch64_get_instr (cpu), 20, 16);
6471 unsigned sn = uimm (aarch64_get_instr (cpu), 9, 5);
6472 unsigned sd = uimm (aarch64_get_instr (cpu), 4, 0);
6474 aarch64_set_FP_double (cpu, sd, - aarch64_get_FP_double (cpu, sa)
6475 + aarch64_get_FP_double (cpu, sn)
6476 * aarch64_get_FP_double (cpu, sm));
6480 dexSimpleFPDataProc3Source (sim_cpu *cpu)
6482 /* instr[31] ==> M : 0 ==> OK, 1 ==> UNALLOC
6484 instr[29] ==> S : 0 ==> OK, 1 ==> UNALLOC
6487 instr[23,22] ==> type : 0 ==> single, 01 ==> double, 1x ==> UNALLOC
6488 instr[21] ==> o1 : 0 ==> unnegated, 1 ==> negated
6489 instr[15] ==> o2 : 0 ==> ADD, 1 ==> SUB */
6491 uint32_t M_S = (uimm (aarch64_get_instr (cpu), 31, 31) << 1)
6492 | uimm (aarch64_get_instr (cpu), 29, 29);
6493 /* dispatch on combined type:o1:o2. */
6494 uint32_t dispatch = (uimm (aarch64_get_instr (cpu), 23, 21) << 1)
6495 | uimm (aarch64_get_instr (cpu), 15, 15);
6502 case 0: fmadds (cpu); return;
6503 case 1: fmsubs (cpu); return;
6504 case 2: fnmadds (cpu); return;
6505 case 3: fnmsubs (cpu); return;
6506 case 4: fmaddd (cpu); return;
6507 case 5: fmsubd (cpu); return;
6508 case 6: fnmaddd (cpu); return;
6509 case 7: fnmsubd (cpu); return;
6511 /* type > 1 is currently unallocated. */
6517 dexSimpleFPFixedConvert (sim_cpu *cpu)
6523 dexSimpleFPCondCompare (sim_cpu *cpu)
6532 fadds (sim_cpu *cpu)
6534 unsigned sm = uimm (aarch64_get_instr (cpu), 20, 16);
6535 unsigned sn = uimm (aarch64_get_instr (cpu), 9, 5);
6536 unsigned sd = uimm (aarch64_get_instr (cpu), 4, 0);
6538 aarch64_set_FP_float (cpu, sd, aarch64_get_FP_float (cpu, sn)
6539 + aarch64_get_FP_float (cpu, sm));
6544 faddd (sim_cpu *cpu)
6546 unsigned sm = uimm (aarch64_get_instr (cpu), 20, 16);
6547 unsigned sn = uimm (aarch64_get_instr (cpu), 9, 5);
6548 unsigned sd = uimm (aarch64_get_instr (cpu), 4, 0);
6550 aarch64_set_FP_double (cpu, sd, aarch64_get_FP_double (cpu, sn)
6551 + aarch64_get_FP_double (cpu, sm));
6556 fdivs (sim_cpu *cpu)
6558 unsigned sm = uimm (aarch64_get_instr (cpu), 20, 16);
6559 unsigned sn = uimm (aarch64_get_instr (cpu), 9, 5);
6560 unsigned sd = uimm (aarch64_get_instr (cpu), 4, 0);
6562 aarch64_set_FP_float (cpu, sd, aarch64_get_FP_float (cpu, sn)
6563 / aarch64_get_FP_float (cpu, sm));
6566 /* Double divide. */
6568 fdivd (sim_cpu *cpu)
6570 unsigned sm = uimm (aarch64_get_instr (cpu), 20, 16);
6571 unsigned sn = uimm (aarch64_get_instr (cpu), 9, 5);
6572 unsigned sd = uimm (aarch64_get_instr (cpu), 4, 0);
6574 aarch64_set_FP_double (cpu, sd, aarch64_get_FP_double (cpu, sn)
6575 / aarch64_get_FP_double (cpu, sm));
6578 /* Float multiply. */
6580 fmuls (sim_cpu *cpu)
6582 unsigned sm = uimm (aarch64_get_instr (cpu), 20, 16);
6583 unsigned sn = uimm (aarch64_get_instr (cpu), 9, 5);
6584 unsigned sd = uimm (aarch64_get_instr (cpu), 4, 0);
6586 aarch64_set_FP_float (cpu, sd, aarch64_get_FP_float (cpu, sn)
6587 * aarch64_get_FP_float (cpu, sm));
6590 /* Double multiply. */
6592 fmuld (sim_cpu *cpu)
6594 unsigned sm = uimm (aarch64_get_instr (cpu), 20, 16);
6595 unsigned sn = uimm (aarch64_get_instr (cpu), 9, 5);
6596 unsigned sd = uimm (aarch64_get_instr (cpu), 4, 0);
6598 aarch64_set_FP_double (cpu, sd, aarch64_get_FP_double (cpu, sn)
6599 * aarch64_get_FP_double (cpu, sm));
6602 /* Float negate and multiply. */
6604 fnmuls (sim_cpu *cpu)
6606 unsigned sm = uimm (aarch64_get_instr (cpu), 20, 16);
6607 unsigned sn = uimm (aarch64_get_instr (cpu), 9, 5);
6608 unsigned sd = uimm (aarch64_get_instr (cpu), 4, 0);
6610 aarch64_set_FP_float (cpu, sd, - (aarch64_get_FP_float (cpu, sn)
6611 * aarch64_get_FP_float (cpu, sm)));
6614 /* Double negate and multiply. */
6616 fnmuld (sim_cpu *cpu)
6618 unsigned sm = uimm (aarch64_get_instr (cpu), 20, 16);
6619 unsigned sn = uimm (aarch64_get_instr (cpu), 9, 5);
6620 unsigned sd = uimm (aarch64_get_instr (cpu), 4, 0);
6622 aarch64_set_FP_double (cpu, sd, - (aarch64_get_FP_double (cpu, sn)
6623 * aarch64_get_FP_double (cpu, sm)));
6626 /* Float subtract. */
6628 fsubs (sim_cpu *cpu)
6630 unsigned sm = uimm (aarch64_get_instr (cpu), 20, 16);
6631 unsigned sn = uimm (aarch64_get_instr (cpu), 9, 5);
6632 unsigned sd = uimm (aarch64_get_instr (cpu), 4, 0);
6634 aarch64_set_FP_float (cpu, sd, aarch64_get_FP_float (cpu, sn)
6635 - aarch64_get_FP_float (cpu, sm));
6638 /* Double subtract. */
6640 fsubd (sim_cpu *cpu)
6642 unsigned sm = uimm (aarch64_get_instr (cpu), 20, 16);
6643 unsigned sn = uimm (aarch64_get_instr (cpu), 9, 5);
6644 unsigned sd = uimm (aarch64_get_instr (cpu), 4, 0);
6646 aarch64_set_FP_double (cpu, sd, aarch64_get_FP_double (cpu, sn)
6647 - aarch64_get_FP_double (cpu, sm));
6651 do_FMINNM (sim_cpu *cpu)
6653 /* instr[31,23] = 0 0011 1100
6654 instr[22] = float(0)/double(1)
6657 instr[15,10] = 01 1110
6661 unsigned sm = uimm (aarch64_get_instr (cpu), 20, 16);
6662 unsigned sn = uimm (aarch64_get_instr (cpu), 9, 5);
6663 unsigned sd = uimm (aarch64_get_instr (cpu), 4, 0);
6665 NYI_assert (31, 23, 0x03C);
6666 NYI_assert (15, 10, 0x1E);
6668 if (uimm (aarch64_get_instr (cpu), 22, 22))
6669 aarch64_set_FP_double (cpu, sd,
6670 dminnm (aarch64_get_FP_double (cpu, sn),
6671 aarch64_get_FP_double (cpu, sm)));
6673 aarch64_set_FP_float (cpu, sd,
6674 fminnm (aarch64_get_FP_float (cpu, sn),
6675 aarch64_get_FP_float (cpu, sm)));
6679 do_FMAXNM (sim_cpu *cpu)
6681 /* instr[31,23] = 0 0011 1100
6682 instr[22] = float(0)/double(1)
6685 instr[15,10] = 01 1010
6689 unsigned sm = uimm (aarch64_get_instr (cpu), 20, 16);
6690 unsigned sn = uimm (aarch64_get_instr (cpu), 9, 5);
6691 unsigned sd = uimm (aarch64_get_instr (cpu), 4, 0);
6693 NYI_assert (31, 23, 0x03C);
6694 NYI_assert (15, 10, 0x1A);
6696 if (uimm (aarch64_get_instr (cpu), 22, 22))
6697 aarch64_set_FP_double (cpu, sd,
6698 dmaxnm (aarch64_get_FP_double (cpu, sn),
6699 aarch64_get_FP_double (cpu, sm)));
6701 aarch64_set_FP_float (cpu, sd,
6702 fmaxnm (aarch64_get_FP_float (cpu, sn),
6703 aarch64_get_FP_float (cpu, sm)));
6707 dexSimpleFPDataProc2Source (sim_cpu *cpu)
6709 /* instr[31] ==> M : 0 ==> OK, 1 ==> UNALLOC
6711 instr[29] ==> S : 0 ==> OK, 1 ==> UNALLOC
6714 instr[23,22] ==> type : 0 ==> single, 01 ==> double, 1x ==> UNALLOC
6717 instr[15,12] ==> opcode : 0000 ==> FMUL, 0001 ==> FDIV
6718 0010 ==> FADD, 0011 ==> FSUB,
6719 0100 ==> FMAX, 0101 ==> FMIN
6720 0110 ==> FMAXNM, 0111 ==> FMINNM
6721 1000 ==> FNMUL, ow ==> UNALLOC
6726 uint32_t M_S = (uimm (aarch64_get_instr (cpu), 31, 31) << 1)
6727 | uimm (aarch64_get_instr (cpu), 29, 29);
6728 uint32_t type = uimm (aarch64_get_instr (cpu), 23, 22);
6729 /* Dispatch on opcode. */
6730 uint32_t dispatch = uimm (aarch64_get_instr (cpu), 15, 12);
6741 case 0: fmuld (cpu); return;
6742 case 1: fdivd (cpu); return;
6743 case 2: faddd (cpu); return;
6744 case 3: fsubd (cpu); return;
6745 case 6: do_FMAXNM (cpu); return;
6746 case 7: do_FMINNM (cpu); return;
6747 case 8: fnmuld (cpu); return;
6749 /* Have not yet implemented fmax and fmin. */
6757 else /* type == 0 => floats. */
6760 case 0: fmuls (cpu); return;
6761 case 1: fdivs (cpu); return;
6762 case 2: fadds (cpu); return;
6763 case 3: fsubs (cpu); return;
6764 case 6: do_FMAXNM (cpu); return;
6765 case 7: do_FMINNM (cpu); return;
6766 case 8: fnmuls (cpu); return;
6778 dexSimpleFPCondSelect (sim_cpu *cpu)
6781 instr[31,23] = 0 0011 1100
6782 instr[22] = 0=>single 1=>double
6789 unsigned sm = uimm (aarch64_get_instr (cpu), 20, 16);
6790 unsigned sn = uimm (aarch64_get_instr (cpu), 9, 5);
6791 unsigned sd = uimm (aarch64_get_instr (cpu), 4, 0);
6792 uint32_t set = testConditionCode (cpu, uimm (aarch64_get_instr (cpu), 15, 12));
6794 NYI_assert (31, 23, 0x03C);
6795 NYI_assert (11, 10, 0x3);
6797 if (uimm (aarch64_get_instr (cpu), 22, 22))
6798 aarch64_set_FP_double (cpu, sd, set ? sn : sm);
6800 aarch64_set_FP_float (cpu, sd, set ? sn : sm);
6803 /* Store 32 bit unscaled signed 9 bit. */
6805 fsturs (sim_cpu *cpu, int32_t offset)
6807 unsigned int rn = uimm (aarch64_get_instr (cpu), 9, 5);
6808 unsigned int st = uimm (aarch64_get_instr (cpu), 4, 0);
6810 aarch64_set_mem_float (cpu, aarch64_get_reg_u64 (cpu, st, 1) + offset,
6811 aarch64_get_FP_float (cpu, rn));
6814 /* Store 64 bit unscaled signed 9 bit. */
6816 fsturd (sim_cpu *cpu, int32_t offset)
6818 unsigned int rn = uimm (aarch64_get_instr (cpu), 9, 5);
6819 unsigned int st = uimm (aarch64_get_instr (cpu), 4, 0);
6821 aarch64_set_mem_double (cpu, aarch64_get_reg_u64 (cpu, st, 1) + offset,
6822 aarch64_get_FP_double (cpu, rn));
6825 /* Store 128 bit unscaled signed 9 bit. */
6827 fsturq (sim_cpu *cpu, int32_t offset)
6829 unsigned int rn = uimm (aarch64_get_instr (cpu), 9, 5);
6830 unsigned int st = uimm (aarch64_get_instr (cpu), 4, 0);
6833 aarch64_get_FP_long_double (cpu, rn, & a);
6834 aarch64_set_mem_long_double (cpu,
6835 aarch64_get_reg_u64 (cpu, st, 1)
6839 /* TODO FP move register. */
6841 /* 32 bit fp to fp move register. */
6843 ffmovs (sim_cpu *cpu)
6845 unsigned int rn = uimm (aarch64_get_instr (cpu), 9, 5);
6846 unsigned int st = uimm (aarch64_get_instr (cpu), 4, 0);
6848 aarch64_set_FP_float (cpu, st, aarch64_get_FP_float (cpu, rn));
6851 /* 64 bit fp to fp move register. */
6853 ffmovd (sim_cpu *cpu)
6855 unsigned int rn = uimm (aarch64_get_instr (cpu), 9, 5);
6856 unsigned int st = uimm (aarch64_get_instr (cpu), 4, 0);
6858 aarch64_set_FP_double (cpu, st, aarch64_get_FP_double (cpu, rn));
6861 /* 32 bit GReg to Vec move register. */
6863 fgmovs (sim_cpu *cpu)
6865 unsigned int rn = uimm (aarch64_get_instr (cpu), 9, 5);
6866 unsigned int st = uimm (aarch64_get_instr (cpu), 4, 0);
6868 aarch64_set_vec_u32 (cpu, st, 0, aarch64_get_reg_u32 (cpu, rn, NO_SP));
6871 /* 64 bit g to fp move register. */
6873 fgmovd (sim_cpu *cpu)
6875 unsigned int rn = uimm (aarch64_get_instr (cpu), 9, 5);
6876 unsigned int st = uimm (aarch64_get_instr (cpu), 4, 0);
6878 aarch64_set_vec_u64 (cpu, st, 0, aarch64_get_reg_u64 (cpu, rn, NO_SP));
6881 /* 32 bit fp to g move register. */
6883 gfmovs (sim_cpu *cpu)
6885 unsigned int rn = uimm (aarch64_get_instr (cpu), 9, 5);
6886 unsigned int st = uimm (aarch64_get_instr (cpu), 4, 0);
6888 aarch64_set_reg_u64 (cpu, st, NO_SP, aarch64_get_vec_u32 (cpu, rn, 0));
6891 /* 64 bit fp to g move register. */
6893 gfmovd (sim_cpu *cpu)
6895 unsigned int rn = uimm (aarch64_get_instr (cpu), 9, 5);
6896 unsigned int st = uimm (aarch64_get_instr (cpu), 4, 0);
6898 aarch64_set_reg_u64 (cpu, st, NO_SP, aarch64_get_vec_u64 (cpu, rn, 0));
6901 /* FP move immediate
6903 These install an immediate 8 bit value in the target register
6904 where the 8 bits comprise 1 sign bit, 4 bits of fraction and a 3
6908 fmovs (sim_cpu *cpu)
6910 unsigned int sd = uimm (aarch64_get_instr (cpu), 4, 0);
6911 uint32_t imm = uimm (aarch64_get_instr (cpu), 20, 13);
6912 float f = fp_immediate_for_encoding_32 (imm);
6914 aarch64_set_FP_float (cpu, sd, f);
6918 fmovd (sim_cpu *cpu)
6920 unsigned int sd = uimm (aarch64_get_instr (cpu), 4, 0);
6921 uint32_t imm = uimm (aarch64_get_instr (cpu), 20, 13);
6922 double d = fp_immediate_for_encoding_64 (imm);
6924 aarch64_set_FP_double (cpu, sd, d);
6928 dexSimpleFPImmediate (sim_cpu *cpu)
6930 /* instr[31,23] == 00111100
6931 instr[22] == type : single(0)/double(1)
6933 instr[20,13] == imm8
6935 instr[9,5] == imm5 : 00000 ==> PK, ow ==> UNALLOC
6937 uint32_t imm5 = uimm (aarch64_get_instr (cpu), 9, 5);
6939 NYI_assert (31, 23, 0x3C);
6944 if (uimm (aarch64_get_instr (cpu), 22, 22))
6950 /* TODO specific decode and execute for group Load Store. */
6952 /* TODO FP load/store single register (unscaled offset). */
6954 /* TODO load 8 bit unscaled signed 9 bit. */
6955 /* TODO load 16 bit unscaled signed 9 bit. */
6957 /* Load 32 bit unscaled signed 9 bit. */
6959 fldurs (sim_cpu *cpu, int32_t offset)
6961 unsigned int rn = uimm (aarch64_get_instr (cpu), 9, 5);
6962 unsigned int st = uimm (aarch64_get_instr (cpu), 4, 0);
6964 aarch64_set_FP_float (cpu, st, aarch64_get_mem_float
6965 (cpu, aarch64_get_reg_u64 (cpu, rn, SP_OK) + offset));
6968 /* Load 64 bit unscaled signed 9 bit. */
6970 fldurd (sim_cpu *cpu, int32_t offset)
6972 unsigned int rn = uimm (aarch64_get_instr (cpu), 9, 5);
6973 unsigned int st = uimm (aarch64_get_instr (cpu), 4, 0);
6975 aarch64_set_FP_double (cpu, st, aarch64_get_mem_double
6976 (cpu, aarch64_get_reg_u64 (cpu, rn, SP_OK) + offset));
6979 /* Load 128 bit unscaled signed 9 bit. */
6981 fldurq (sim_cpu *cpu, int32_t offset)
6983 unsigned int rn = uimm (aarch64_get_instr (cpu), 9, 5);
6984 unsigned int st = uimm (aarch64_get_instr (cpu), 4, 0);
6986 uint64_t addr = aarch64_get_reg_u64 (cpu, rn, SP_OK) + offset;
6988 aarch64_get_mem_long_double (cpu, addr, & a);
6989 aarch64_set_FP_long_double (cpu, st, a);
6992 /* TODO store 8 bit unscaled signed 9 bit. */
6993 /* TODO store 16 bit unscaled signed 9 bit. */
6998 /* Float absolute value. */
7000 fabss (sim_cpu *cpu)
7002 unsigned sn = uimm (aarch64_get_instr (cpu), 9, 5);
7003 unsigned sd = uimm (aarch64_get_instr (cpu), 4, 0);
7004 float value = aarch64_get_FP_float (cpu, sn);
7006 aarch64_set_FP_float (cpu, sd, fabsf (value));
7009 /* Double absolute value. */
7011 fabcpu (sim_cpu *cpu)
7013 unsigned sn = uimm (aarch64_get_instr (cpu), 9, 5);
7014 unsigned sd = uimm (aarch64_get_instr (cpu), 4, 0);
7015 double value = aarch64_get_FP_double (cpu, sn);
7017 aarch64_set_FP_double (cpu, sd, fabs (value));
7020 /* Float negative value. */
7022 fnegs (sim_cpu *cpu)
7024 unsigned sn = uimm (aarch64_get_instr (cpu), 9, 5);
7025 unsigned sd = uimm (aarch64_get_instr (cpu), 4, 0);
7027 aarch64_set_FP_float (cpu, sd, - aarch64_get_FP_float (cpu, sn));
7030 /* Double negative value. */
7032 fnegd (sim_cpu *cpu)
7034 unsigned sn = uimm (aarch64_get_instr (cpu), 9, 5);
7035 unsigned sd = uimm (aarch64_get_instr (cpu), 4, 0);
7037 aarch64_set_FP_double (cpu, sd, - aarch64_get_FP_double (cpu, sn));
7040 /* Float square root. */
7042 fsqrts (sim_cpu *cpu)
7044 unsigned sn = uimm (aarch64_get_instr (cpu), 9, 5);
7045 unsigned sd = uimm (aarch64_get_instr (cpu), 4, 0);
7047 aarch64_set_FP_float (cpu, sd, sqrt (aarch64_get_FP_float (cpu, sn)));
7050 /* Double square root. */
7052 fsqrtd (sim_cpu *cpu)
7054 unsigned sn = uimm (aarch64_get_instr (cpu), 9, 5);
7055 unsigned sd = uimm (aarch64_get_instr (cpu), 4, 0);
7057 aarch64_set_FP_double (cpu, sd,
7058 sqrt (aarch64_get_FP_double (cpu, sn)));
7061 /* Convert double to float. */
7063 fcvtds (sim_cpu *cpu)
7065 unsigned sn = uimm (aarch64_get_instr (cpu), 9, 5);
7066 unsigned sd = uimm (aarch64_get_instr (cpu), 4, 0);
7068 aarch64_set_FP_float (cpu, sd, (float) aarch64_get_FP_double (cpu, sn));
7071 /* Convert float to double. */
7073 fcvtcpu (sim_cpu *cpu)
7075 unsigned sn = uimm (aarch64_get_instr (cpu), 9, 5);
7076 unsigned sd = uimm (aarch64_get_instr (cpu), 4, 0);
7078 aarch64_set_FP_double (cpu, sd, (double) aarch64_get_FP_float (cpu, sn));
7082 do_FRINT (sim_cpu *cpu)
7084 /* instr[31,23] = 0001 1110 0
7085 instr[22] = single(0)/double(1)
7087 instr[17,15] = rounding mode
7088 instr[14,10] = 10000
7090 instr[4,0] = dest */
7093 unsigned rs = uimm (aarch64_get_instr (cpu), 9, 5);
7094 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
7095 unsigned int rmode = uimm (aarch64_get_instr (cpu), 17, 15);
7097 NYI_assert (31, 23, 0x03C);
7098 NYI_assert (21, 18, 0x9);
7099 NYI_assert (14, 10, 0x10);
7101 if (rmode == 6 || rmode == 7)
7102 /* FIXME: Add support for rmode == 6 exactness check. */
7103 rmode = uimm (aarch64_get_FPSR (cpu), 23, 22);
7105 if (uimm (aarch64_get_instr (cpu), 22, 22))
7107 double val = aarch64_get_FP_double (cpu, rs);
7111 case 0: /* mode N: nearest or even. */
7113 double rval = round (val);
7115 if (val - rval == 0.5)
7117 if (((rval / 2.0) * 2.0) != rval)
7121 aarch64_set_FP_double (cpu, rd, round (val));
7125 case 1: /* mode P: towards +inf. */
7127 aarch64_set_FP_double (cpu, rd, trunc (val));
7129 aarch64_set_FP_double (cpu, rd, round (val));
7132 case 2: /* mode M: towards -inf. */
7134 aarch64_set_FP_double (cpu, rd, round (val));
7136 aarch64_set_FP_double (cpu, rd, trunc (val));
7139 case 3: /* mode Z: towards 0. */
7140 aarch64_set_FP_double (cpu, rd, trunc (val));
7143 case 4: /* mode A: away from 0. */
7144 aarch64_set_FP_double (cpu, rd, round (val));
7147 case 6: /* mode X: use FPCR with exactness check. */
7148 case 7: /* mode I: use FPCR mode. */
7156 val = aarch64_get_FP_float (cpu, rs);
7160 case 0: /* mode N: nearest or even. */
7162 float rval = roundf (val);
7164 if (val - rval == 0.5)
7166 if (((rval / 2.0) * 2.0) != rval)
7170 aarch64_set_FP_float (cpu, rd, rval);
7174 case 1: /* mode P: towards +inf. */
7176 aarch64_set_FP_float (cpu, rd, truncf (val));
7178 aarch64_set_FP_float (cpu, rd, roundf (val));
7181 case 2: /* mode M: towards -inf. */
7183 aarch64_set_FP_float (cpu, rd, truncf (val));
7185 aarch64_set_FP_float (cpu, rd, roundf (val));
7188 case 3: /* mode Z: towards 0. */
7189 aarch64_set_FP_float (cpu, rd, truncf (val));
7192 case 4: /* mode A: away from 0. */
7193 aarch64_set_FP_float (cpu, rd, roundf (val));
7196 case 6: /* mode X: use FPCR with exactness check. */
7197 case 7: /* mode I: use FPCR mode. */
7206 dexSimpleFPDataProc1Source (sim_cpu *cpu)
7208 /* instr[31] ==> M : 0 ==> OK, 1 ==> UNALLOC
7210 instr[29] ==> S : 0 ==> OK, 1 ==> UNALLOC
7213 instr[23,22] ==> type : 00 ==> source is single,
7214 01 ==> source is double
7216 11 ==> UNALLOC or source is half
7218 instr[20,15] ==> opcode : with type 00 or 01
7219 000000 ==> FMOV, 000001 ==> FABS,
7220 000010 ==> FNEG, 000011 ==> FSQRT,
7221 000100 ==> UNALLOC, 000101 ==> FCVT,(to single/double)
7222 000110 ==> UNALLOC, 000111 ==> FCVT (to half)
7223 001000 ==> FRINTN, 001001 ==> FRINTP,
7224 001010 ==> FRINTM, 001011 ==> FRINTZ,
7225 001100 ==> FRINTA, 001101 ==> UNALLOC
7226 001110 ==> FRINTX, 001111 ==> FRINTI
7228 000100 ==> FCVT (half-to-single)
7229 000101 ==> FCVT (half-to-double)
7230 instr[14,10] = 10000. */
7232 uint32_t M_S = (uimm (aarch64_get_instr (cpu), 31, 31) << 1)
7233 | uimm (aarch64_get_instr (cpu), 29, 29);
7234 uint32_t type = uimm (aarch64_get_instr (cpu), 23, 22);
7235 uint32_t opcode = uimm (aarch64_get_instr (cpu), 20, 15);
7242 if (opcode == 4 || opcode == 5)
7294 case 8: /* FRINTN etc. */
7304 case 7: /* FCVT double/single to half precision. */
7313 /* 32 bit signed int to float. */
7315 scvtf32 (sim_cpu *cpu)
7317 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
7318 unsigned sd = uimm (aarch64_get_instr (cpu), 4, 0);
7320 aarch64_set_FP_float
7321 (cpu, sd, (float) aarch64_get_reg_s32 (cpu, rn, NO_SP));
7324 /* signed int to float. */
7326 scvtf (sim_cpu *cpu)
7328 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
7329 unsigned sd = uimm (aarch64_get_instr (cpu), 4, 0);
7331 aarch64_set_FP_float
7332 (cpu, sd, (float) aarch64_get_reg_s64 (cpu, rn, NO_SP));
7335 /* 32 bit signed int to double. */
7337 scvtd32 (sim_cpu *cpu)
7339 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
7340 unsigned sd = uimm (aarch64_get_instr (cpu), 4, 0);
7342 aarch64_set_FP_double
7343 (cpu, sd, (double) aarch64_get_reg_s32 (cpu, rn, NO_SP));
7346 /* signed int to double. */
7348 scvtd (sim_cpu *cpu)
7350 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
7351 unsigned sd = uimm (aarch64_get_instr (cpu), 4, 0);
7353 aarch64_set_FP_double
7354 (cpu, sd, (double) aarch64_get_reg_s64 (cpu, rn, NO_SP));
7357 static const float FLOAT_INT_MAX = (float) INT_MAX;
7358 static const float FLOAT_INT_MIN = (float) INT_MIN;
7359 static const double DOUBLE_INT_MAX = (double) INT_MAX;
7360 static const double DOUBLE_INT_MIN = (double) INT_MIN;
7361 static const float FLOAT_LONG_MAX = (float) LONG_MAX;
7362 static const float FLOAT_LONG_MIN = (float) LONG_MIN;
7363 static const double DOUBLE_LONG_MAX = (double) LONG_MAX;
7364 static const double DOUBLE_LONG_MIN = (double) LONG_MIN;
7366 /* Check for FP exception conditions:
7369 Out of Range raises IO and IX and saturates value
7370 Denormal raises ID and IX and sets to zero. */
7371 #define RAISE_EXCEPTIONS(F, VALUE, FTYPE, ITYPE) \
7374 switch (fpclassify (F)) \
7378 aarch64_set_FPSR (cpu, IO); \
7380 VALUE = ITYPE##_MAX; \
7382 VALUE = ITYPE##_MIN; \
7386 if (F >= FTYPE##_##ITYPE##_MAX) \
7388 aarch64_set_FPSR_bits (cpu, IO | IX, IO | IX); \
7389 VALUE = ITYPE##_MAX; \
7391 else if (F <= FTYPE##_##ITYPE##_MIN) \
7393 aarch64_set_FPSR_bits (cpu, IO | IX, IO | IX); \
7394 VALUE = ITYPE##_MIN; \
7398 case FP_SUBNORMAL: \
7399 aarch64_set_FPSR_bits (cpu, IO | IX | ID, IX | ID); \
7411 /* 32 bit convert float to signed int truncate towards zero. */
7413 fcvtszs32 (sim_cpu *cpu)
7415 unsigned sn = uimm (aarch64_get_instr (cpu), 9, 5);
7416 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
7417 /* TODO : check that this rounds toward zero. */
7418 float f = aarch64_get_FP_float (cpu, sn);
7419 int32_t value = (int32_t) f;
7421 RAISE_EXCEPTIONS (f, value, FLOAT, INT);
7423 /* Avoid sign extension to 64 bit. */
7424 aarch64_set_reg_u64 (cpu, rd, NO_SP, (uint32_t) value);
7427 /* 64 bit convert float to signed int truncate towards zero. */
7429 fcvtszs (sim_cpu *cpu)
7431 unsigned sn = uimm (aarch64_get_instr (cpu), 9, 5);
7432 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
7433 float f = aarch64_get_FP_float (cpu, sn);
7434 int64_t value = (int64_t) f;
7436 RAISE_EXCEPTIONS (f, value, FLOAT, LONG);
7438 aarch64_set_reg_s64 (cpu, rd, NO_SP, value);
7441 /* 32 bit convert double to signed int truncate towards zero. */
7443 fcvtszd32 (sim_cpu *cpu)
7445 unsigned sn = uimm (aarch64_get_instr (cpu), 9, 5);
7446 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
7447 /* TODO : check that this rounds toward zero. */
7448 double d = aarch64_get_FP_double (cpu, sn);
7449 int32_t value = (int32_t) d;
7451 RAISE_EXCEPTIONS (d, value, DOUBLE, INT);
7453 /* Avoid sign extension to 64 bit. */
7454 aarch64_set_reg_u64 (cpu, rd, NO_SP, (uint32_t) value);
7457 /* 64 bit convert double to signed int truncate towards zero. */
7459 fcvtszd (sim_cpu *cpu)
7461 unsigned sn = uimm (aarch64_get_instr (cpu), 9, 5);
7462 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
7463 /* TODO : check that this rounds toward zero. */
7464 double d = aarch64_get_FP_double (cpu, sn);
7467 value = (int64_t) d;
7469 RAISE_EXCEPTIONS (d, value, DOUBLE, LONG);
7471 aarch64_set_reg_s64 (cpu, rd, NO_SP, value);
7475 do_fcvtzu (sim_cpu *cpu)
7477 /* instr[31] = size: 32-bit (0), 64-bit (1)
7478 instr[30,23] = 00111100
7479 instr[22] = type: single (0)/ double (1)
7480 instr[21] = enable (0)/disable(1) precision
7481 instr[20,16] = 11001
7482 instr[15,10] = precision
7486 unsigned rs = uimm (aarch64_get_instr (cpu), 9, 5);
7487 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
7489 NYI_assert (30, 23, 0x3C);
7490 NYI_assert (20, 16, 0x19);
7492 if (uimm (aarch64_get_instr (cpu), 21, 21) != 1)
7493 /* Convert to fixed point. */
7496 if (uimm (aarch64_get_instr (cpu), 31, 31))
7498 /* Convert to unsigned 64-bit integer. */
7499 if (uimm (aarch64_get_instr (cpu), 22, 22))
7501 double d = aarch64_get_FP_double (cpu, rs);
7502 uint64_t value = (uint64_t) d;
7504 /* Do not raise an exception if we have reached ULONG_MAX. */
7505 if (value != (1UL << 63))
7506 RAISE_EXCEPTIONS (d, value, DOUBLE, LONG);
7508 aarch64_set_reg_u64 (cpu, rd, NO_SP, value);
7512 float f = aarch64_get_FP_float (cpu, rs);
7513 uint64_t value = (uint64_t) f;
7515 /* Do not raise an exception if we have reached ULONG_MAX. */
7516 if (value != (1UL << 63))
7517 RAISE_EXCEPTIONS (f, value, FLOAT, LONG);
7519 aarch64_set_reg_u64 (cpu, rd, NO_SP, value);
7526 /* Convert to unsigned 32-bit integer. */
7527 if (uimm (aarch64_get_instr (cpu), 22, 22))
7529 double d = aarch64_get_FP_double (cpu, rs);
7531 value = (uint32_t) d;
7532 /* Do not raise an exception if we have reached UINT_MAX. */
7533 if (value != (1UL << 31))
7534 RAISE_EXCEPTIONS (d, value, DOUBLE, INT);
7538 float f = aarch64_get_FP_float (cpu, rs);
7540 value = (uint32_t) f;
7541 /* Do not raise an exception if we have reached UINT_MAX. */
7542 if (value != (1UL << 31))
7543 RAISE_EXCEPTIONS (f, value, FLOAT, INT);
7546 aarch64_set_reg_u64 (cpu, rd, NO_SP, value);
7551 do_UCVTF (sim_cpu *cpu)
7553 /* instr[31] = size: 32-bit (0), 64-bit (1)
7554 instr[30,23] = 001 1110 0
7555 instr[22] = type: single (0)/ double (1)
7556 instr[21] = enable (0)/disable(1) precision
7557 instr[20,16] = 0 0011
7558 instr[15,10] = precision
7562 unsigned rs = uimm (aarch64_get_instr (cpu), 9, 5);
7563 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
7565 NYI_assert (30, 23, 0x3C);
7566 NYI_assert (20, 16, 0x03);
7568 if (uimm (aarch64_get_instr (cpu), 21, 21) != 1)
7571 /* FIXME: Add exception raising. */
7572 if (uimm (aarch64_get_instr (cpu), 31, 31))
7574 uint64_t value = aarch64_get_reg_u64 (cpu, rs, NO_SP);
7576 if (uimm (aarch64_get_instr (cpu), 22, 22))
7577 aarch64_set_FP_double (cpu, rd, (double) value);
7579 aarch64_set_FP_float (cpu, rd, (float) value);
7583 uint32_t value = aarch64_get_reg_u32 (cpu, rs, NO_SP);
7585 if (uimm (aarch64_get_instr (cpu), 22, 22))
7586 aarch64_set_FP_double (cpu, rd, (double) value);
7588 aarch64_set_FP_float (cpu, rd, (float) value);
7593 float_vector_move (sim_cpu *cpu)
7595 /* instr[31,17] == 100 1111 0101 0111
7596 instr[16] ==> direction 0=> to GR, 1=> from GR
7598 instr[9,5] ==> source
7599 instr[4,0] ==> dest. */
7601 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
7602 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
7604 NYI_assert (31, 17, 0x4F57);
7606 if (uimm (aarch64_get_instr (cpu), 15, 10) != 0)
7609 if (uimm (aarch64_get_instr (cpu), 16, 16))
7610 aarch64_set_vec_u64 (cpu, rd, 1, aarch64_get_reg_u64 (cpu, rn, NO_SP));
7612 aarch64_set_reg_u64 (cpu, rd, NO_SP, aarch64_get_vec_u64 (cpu, rn, 1));
7616 dexSimpleFPIntegerConvert (sim_cpu *cpu)
7618 /* instr[31] = size : 0 ==> 32 bit, 1 ==> 64 bit
7620 instr[29] = S : 0 ==> OK, 1 ==> UNALLOC
7623 instr[23,22] = type : 00 ==> single, 01 ==> double, 1x ==> UNALLOC
7625 instr[20,19] = rmode
7626 instr[18,16] = opcode
7627 instr[15,10] = 10 0000 */
7629 uint32_t rmode_opcode;
7635 if (uimm (aarch64_get_instr (cpu), 31, 17) == 0x4F57)
7637 float_vector_move (cpu);
7641 size = uimm (aarch64_get_instr (cpu), 31, 31);
7642 S = uimm (aarch64_get_instr (cpu), 29, 29);
7646 type = uimm (aarch64_get_instr (cpu), 23, 22);
7650 rmode_opcode = uimm (aarch64_get_instr (cpu), 20, 16);
7651 size_type = (size << 1) | type; /* 0==32f, 1==32d, 2==64f, 3==64d. */
7653 switch (rmode_opcode)
7655 case 2: /* SCVTF. */
7658 case 0: scvtf32 (cpu); return;
7659 case 1: scvtd32 (cpu); return;
7660 case 2: scvtf (cpu); return;
7661 case 3: scvtd (cpu); return;
7666 case 6: /* FMOV GR, Vec. */
7669 case 0: gfmovs (cpu); return;
7670 case 3: gfmovd (cpu); return;
7671 default: HALT_UNALLOC;
7674 case 7: /* FMOV vec, GR. */
7677 case 0: fgmovs (cpu); return;
7678 case 3: fgmovd (cpu); return;
7679 default: HALT_UNALLOC;
7682 case 24: /* FCVTZS. */
7685 case 0: fcvtszs32 (cpu); return;
7686 case 1: fcvtszd32 (cpu); return;
7687 case 2: fcvtszs (cpu); return;
7688 case 3: fcvtszd (cpu); return;
7689 default: HALT_UNREACHABLE;
7692 case 25: do_fcvtzu (cpu); return;
7693 case 3: do_UCVTF (cpu); return;
7695 case 0: /* FCVTNS. */
7696 case 1: /* FCVTNU. */
7697 case 4: /* FCVTAS. */
7698 case 5: /* FCVTAU. */
7699 case 8: /* FCVPTS. */
7700 case 9: /* FCVTPU. */
7701 case 16: /* FCVTMS. */
7702 case 17: /* FCVTMU. */
7709 set_flags_for_float_compare (sim_cpu *cpu, float fvalue1, float fvalue2)
7713 if (isnan (fvalue1) || isnan (fvalue2))
7717 float result = fvalue1 - fvalue2;
7721 else if (result < 0)
7723 else /* (result > 0). */
7727 aarch64_set_CPSR (cpu, flags);
7731 fcmps (sim_cpu *cpu)
7733 unsigned sm = uimm (aarch64_get_instr (cpu), 20, 16);
7734 unsigned sn = uimm (aarch64_get_instr (cpu), 9, 5);
7736 float fvalue1 = aarch64_get_FP_float (cpu, sn);
7737 float fvalue2 = aarch64_get_FP_float (cpu, sm);
7739 set_flags_for_float_compare (cpu, fvalue1, fvalue2);
7742 /* Float compare to zero -- Invalid Operation exception
7743 only on signaling NaNs. */
7745 fcmpzs (sim_cpu *cpu)
7747 unsigned sn = uimm (aarch64_get_instr (cpu), 9, 5);
7748 float fvalue1 = aarch64_get_FP_float (cpu, sn);
7750 set_flags_for_float_compare (cpu, fvalue1, 0.0f);
7753 /* Float compare -- Invalid Operation exception on all NaNs. */
7755 fcmpes (sim_cpu *cpu)
7757 unsigned sm = uimm (aarch64_get_instr (cpu), 20, 16);
7758 unsigned sn = uimm (aarch64_get_instr (cpu), 9, 5);
7760 float fvalue1 = aarch64_get_FP_float (cpu, sn);
7761 float fvalue2 = aarch64_get_FP_float (cpu, sm);
7763 set_flags_for_float_compare (cpu, fvalue1, fvalue2);
7766 /* Float compare to zero -- Invalid Operation exception on all NaNs. */
7768 fcmpzes (sim_cpu *cpu)
7770 unsigned sn = uimm (aarch64_get_instr (cpu), 9, 5);
7771 float fvalue1 = aarch64_get_FP_float (cpu, sn);
7773 set_flags_for_float_compare (cpu, fvalue1, 0.0f);
7777 set_flags_for_double_compare (sim_cpu *cpu, double dval1, double dval2)
7781 if (isnan (dval1) || isnan (dval2))
7785 double result = dval1 - dval2;
7789 else if (result < 0)
7791 else /* (result > 0). */
7795 aarch64_set_CPSR (cpu, flags);
7798 /* Double compare -- Invalid Operation exception only on signaling NaNs. */
7800 fcmpd (sim_cpu *cpu)
7802 unsigned sm = uimm (aarch64_get_instr (cpu), 20, 16);
7803 unsigned sn = uimm (aarch64_get_instr (cpu), 9, 5);
7805 double dvalue1 = aarch64_get_FP_double (cpu, sn);
7806 double dvalue2 = aarch64_get_FP_double (cpu, sm);
7808 set_flags_for_double_compare (cpu, dvalue1, dvalue2);
7811 /* Double compare to zero -- Invalid Operation exception
7812 only on signaling NaNs. */
7814 fcmpzd (sim_cpu *cpu)
7816 unsigned sn = uimm (aarch64_get_instr (cpu), 9, 5);
7817 double dvalue1 = aarch64_get_FP_double (cpu, sn);
7819 set_flags_for_double_compare (cpu, dvalue1, 0.0);
7822 /* Double compare -- Invalid Operation exception on all NaNs. */
7824 fcmped (sim_cpu *cpu)
7826 unsigned sm = uimm (aarch64_get_instr (cpu), 20, 16);
7827 unsigned sn = uimm (aarch64_get_instr (cpu), 9, 5);
7829 double dvalue1 = aarch64_get_FP_double (cpu, sn);
7830 double dvalue2 = aarch64_get_FP_double (cpu, sm);
7832 set_flags_for_double_compare (cpu, dvalue1, dvalue2);
7835 /* Double compare to zero -- Invalid Operation exception on all NaNs. */
7837 fcmpzed (sim_cpu *cpu)
7839 unsigned sn = uimm (aarch64_get_instr (cpu), 9, 5);
7840 double dvalue1 = aarch64_get_FP_double (cpu, sn);
7842 set_flags_for_double_compare (cpu, dvalue1, 0.0);
7846 dexSimpleFPCompare (sim_cpu *cpu)
7848 /* assert instr[28,25] == 1111
7849 instr[30:24:21:13,10] = 0011000
7850 instr[31] = M : 0 ==> OK, 1 ==> UNALLOC
7851 instr[29] ==> S : 0 ==> OK, 1 ==> UNALLOC
7852 instr[23,22] ==> type : 0 ==> single, 01 ==> double, 1x ==> UNALLOC
7853 instr[15,14] ==> op : 00 ==> OK, ow ==> UNALLOC
7854 instr[4,0] ==> opcode2 : 00000 ==> FCMP, 10000 ==> FCMPE,
7855 01000 ==> FCMPZ, 11000 ==> FCMPEZ,
7858 uint32_t M_S = (uimm (aarch64_get_instr (cpu), 31, 31) << 1)
7859 | uimm (aarch64_get_instr (cpu), 29, 29);
7860 uint32_t type = uimm (aarch64_get_instr (cpu), 23, 22);
7861 uint32_t op = uimm (aarch64_get_instr (cpu), 15, 14);
7862 uint32_t op2_2_0 = uimm (aarch64_get_instr (cpu), 2, 0);
7876 /* dispatch on type and top 2 bits of opcode. */
7877 dispatch = (type << 2) | uimm (aarch64_get_instr (cpu), 4, 3);
7881 case 0: fcmps (cpu); return;
7882 case 1: fcmpzs (cpu); return;
7883 case 2: fcmpes (cpu); return;
7884 case 3: fcmpzes (cpu); return;
7885 case 4: fcmpd (cpu); return;
7886 case 5: fcmpzd (cpu); return;
7887 case 6: fcmped (cpu); return;
7888 case 7: fcmpzed (cpu); return;
7889 default: HALT_UNREACHABLE;
7894 do_scalar_FADDP (sim_cpu *cpu)
7896 /* instr [31,23] = 011111100
7897 instr [22] = single(0)/double(1)
7898 instr [21,10] = 1100 0011 0110
7900 instr [4,0] = Fd. */
7902 unsigned Fn = uimm (aarch64_get_instr (cpu), 9, 5);
7903 unsigned Fd = uimm (aarch64_get_instr (cpu), 4, 0);
7905 NYI_assert (31, 23, 0x0FC);
7906 NYI_assert (21, 10, 0xC36);
7908 if (uimm (aarch64_get_instr (cpu), 22, 22))
7910 double val1 = aarch64_get_vec_double (cpu, Fn, 0);
7911 double val2 = aarch64_get_vec_double (cpu, Fn, 1);
7913 aarch64_set_FP_double (cpu, Fd, val1 + val2);
7917 float val1 = aarch64_get_vec_float (cpu, Fn, 0);
7918 float val2 = aarch64_get_vec_float (cpu, Fn, 1);
7920 aarch64_set_FP_float (cpu, Fd, val1 + val2);
7924 /* Floating point absolute difference. */
7927 do_scalar_FABD (sim_cpu *cpu)
7929 /* instr [31,23] = 0111 1110 1
7930 instr [22] = float(0)/double(1)
7933 instr [15,10] = 1101 01
7935 instr [4, 0] = Rd. */
7937 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
7938 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
7939 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
7941 NYI_assert (31, 23, 0x0FD);
7942 NYI_assert (21, 21, 1);
7943 NYI_assert (15, 10, 0x35);
7945 if (uimm (aarch64_get_instr (cpu), 22, 22))
7946 aarch64_set_FP_double (cpu, rd,
7947 fabs (aarch64_get_FP_double (cpu, rn)
7948 - aarch64_get_FP_double (cpu, rm)));
7950 aarch64_set_FP_float (cpu, rd,
7951 fabsf (aarch64_get_FP_float (cpu, rn)
7952 - aarch64_get_FP_float (cpu, rm)));
7956 do_scalar_CMGT (sim_cpu *cpu)
7958 /* instr [31,21] = 0101 1110 111
7960 instr [15,10] = 00 1101
7962 instr [4, 0] = Rd. */
7964 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
7965 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
7966 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
7968 NYI_assert (31, 21, 0x2F7);
7969 NYI_assert (15, 10, 0x0D);
7971 aarch64_set_vec_u64 (cpu, rd, 0,
7972 aarch64_get_vec_u64 (cpu, rn, 0) >
7973 aarch64_get_vec_u64 (cpu, rm, 0) ? -1L : 0L);
7977 do_scalar_USHR (sim_cpu *cpu)
7979 /* instr [31,23] = 0111 1111 0
7980 instr [22,16] = shift amount
7981 instr [15,10] = 0000 01
7983 instr [4, 0] = Rd. */
7985 unsigned amount = 128 - uimm (aarch64_get_instr (cpu), 22, 16);
7986 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
7987 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
7989 NYI_assert (31, 23, 0x0FE);
7990 NYI_assert (15, 10, 0x01);
7992 aarch64_set_vec_u64 (cpu, rd, 0,
7993 aarch64_get_vec_u64 (cpu, rn, 0) >> amount);
7997 do_scalar_SHL (sim_cpu *cpu)
7999 /* instr [31,23] = 0111 1101 0
8000 instr [22,16] = shift amount
8001 instr [15,10] = 0101 01
8003 instr [4, 0] = Rd. */
8005 unsigned amount = uimm (aarch64_get_instr (cpu), 22, 16) - 64;
8006 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
8007 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
8009 NYI_assert (31, 23, 0x0BE);
8010 NYI_assert (15, 10, 0x15);
8012 if (uimm (aarch64_get_instr (cpu), 22, 22) == 0)
8015 aarch64_set_vec_u64 (cpu, rd, 0,
8016 aarch64_get_vec_u64 (cpu, rn, 0) << amount);
8019 /* FCMEQ FCMGT FCMGE. */
8021 do_scalar_FCM (sim_cpu *cpu)
8023 /* instr [31,30] = 01
8025 instr [28,24] = 1 1110
8030 instr [15,12] = 1110
8034 instr [4, 0] = Rd. */
8036 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
8037 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
8038 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
8039 unsigned EUac = (uimm (aarch64_get_instr (cpu), 23, 23) << 2)
8040 | (uimm (aarch64_get_instr (cpu), 29, 29) << 1)
8041 | uimm (aarch64_get_instr (cpu), 11, 11);
8046 NYI_assert (31, 30, 1);
8047 NYI_assert (28, 24, 0x1E);
8048 NYI_assert (21, 21, 1);
8049 NYI_assert (15, 12, 0xE);
8050 NYI_assert (10, 10, 1);
8052 if (uimm (aarch64_get_instr (cpu), 22, 22))
8054 double val1 = aarch64_get_FP_double (cpu, rn);
8055 double val2 = aarch64_get_FP_double (cpu, rm);
8060 result = val1 == val2;
8068 result = val1 >= val2;
8076 result = val1 > val2;
8083 aarch64_set_vec_u32 (cpu, rd, 0, result ? -1 : 0);
8087 val1 = aarch64_get_FP_float (cpu, rn);
8088 val2 = aarch64_get_FP_float (cpu, rm);
8093 result = val1 == val2;
8097 val1 = fabsf (val1);
8098 val2 = fabsf (val2);
8101 result = val1 >= val2;
8105 val1 = fabsf (val1);
8106 val2 = fabsf (val2);
8109 result = val1 > val2;
8116 aarch64_set_vec_u32 (cpu, rd, 0, result ? -1 : 0);
8119 /* An alias of DUP. */
8121 do_scalar_MOV (sim_cpu *cpu)
8123 /* instr [31,21] = 0101 1110 000
8124 instr [20,16] = imm5
8125 instr [15,10] = 0000 01
8127 instr [4, 0] = Rd. */
8129 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
8130 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
8133 NYI_assert (31, 21, 0x2F0);
8134 NYI_assert (15, 10, 0x01);
8136 if (uimm (aarch64_get_instr (cpu), 16, 16))
8139 index = uimm (aarch64_get_instr (cpu), 20, 17);
8141 (cpu, rd, 0, aarch64_get_vec_u8 (cpu, rn, index));
8143 else if (uimm (aarch64_get_instr (cpu), 17, 17))
8146 index = uimm (aarch64_get_instr (cpu), 20, 18);
8148 (cpu, rd, 0, aarch64_get_vec_u16 (cpu, rn, index));
8150 else if (uimm (aarch64_get_instr (cpu), 18, 18))
8153 index = uimm (aarch64_get_instr (cpu), 20, 19);
8155 (cpu, rd, 0, aarch64_get_vec_u32 (cpu, rn, index));
8157 else if (uimm (aarch64_get_instr (cpu), 19, 19))
8160 index = uimm (aarch64_get_instr (cpu), 20, 20);
8162 (cpu, rd, 0, aarch64_get_vec_u64 (cpu, rn, index));
8169 do_double_add (sim_cpu *cpu)
8171 /* instr [28,25] = 1111. */
8178 switch (uimm (aarch64_get_instr (cpu), 31, 23))
8181 switch (uimm (aarch64_get_instr (cpu), 15, 10))
8183 case 0x01: do_scalar_MOV (cpu); return;
8184 case 0x39: do_scalar_FCM (cpu); return;
8185 case 0x3B: do_scalar_FCM (cpu); return;
8189 case 0xBE: do_scalar_SHL (cpu); return;
8192 switch (uimm (aarch64_get_instr (cpu), 15, 10))
8194 case 0x36: do_scalar_FADDP (cpu); return;
8195 case 0x39: do_scalar_FCM (cpu); return;
8196 case 0x3B: do_scalar_FCM (cpu); return;
8201 switch (uimm (aarch64_get_instr (cpu), 15, 10))
8203 case 0x0D: do_scalar_CMGT (cpu); return;
8204 case 0x35: do_scalar_FABD (cpu); return;
8205 case 0x39: do_scalar_FCM (cpu); return;
8206 case 0x3B: do_scalar_FCM (cpu); return;
8211 case 0xFE: do_scalar_USHR (cpu); return;
8216 /* instr [31,21] = 0101 1110 111
8218 instr [15,10] = 1000 01
8220 instr [4,0] = Fd. */
8221 if (uimm (aarch64_get_instr (cpu), 31, 21) != 0x2F7
8222 || uimm (aarch64_get_instr (cpu), 15, 10) != 0x21)
8225 Fd = uimm (aarch64_get_instr (cpu), 4, 0);
8226 Fm = uimm (aarch64_get_instr (cpu), 9, 5);
8227 Fn = uimm (aarch64_get_instr (cpu), 20, 16);
8229 val1 = aarch64_get_FP_double (cpu, Fm);
8230 val2 = aarch64_get_FP_double (cpu, Fn);
8232 aarch64_set_FP_double (cpu, Fd, val1 + val2);
8236 dexAdvSIMD1 (sim_cpu *cpu)
8238 /* instr [28,25] = 1 111. */
8240 /* we are currently only interested in the basic
8241 scalar fp routines which all have bit 30 = 0. */
8242 if (uimm (aarch64_get_instr (cpu), 30, 30))
8243 do_double_add (cpu);
8245 /* instr[24] is set for FP data processing 3-source and clear for
8246 all other basic scalar fp instruction groups. */
8247 else if (uimm (aarch64_get_instr (cpu), 24, 24))
8248 dexSimpleFPDataProc3Source (cpu);
8250 /* instr[21] is clear for floating <-> fixed conversions and set for
8251 all other basic scalar fp instruction groups. */
8252 else if (!uimm (aarch64_get_instr (cpu), 21, 21))
8253 dexSimpleFPFixedConvert (cpu);
8255 /* instr[11,10] : 01 ==> cond compare, 10 ==> Data Proc 2 Source
8256 11 ==> cond select, 00 ==> other. */
8258 switch (uimm (aarch64_get_instr (cpu), 11, 10))
8260 case 1: dexSimpleFPCondCompare (cpu); return;
8261 case 2: dexSimpleFPDataProc2Source (cpu); return;
8262 case 3: dexSimpleFPCondSelect (cpu); return;
8265 /* Now an ordered cascade of tests.
8266 FP immediate has aarch64_get_instr (cpu)[12] == 1.
8267 FP compare has aarch64_get_instr (cpu)[13] == 1.
8268 FP Data Proc 1 Source has aarch64_get_instr (cpu)[14] == 1.
8269 FP floating <--> integer conversions has aarch64_get_instr (cpu)[15] == 0. */
8270 if (uimm (aarch64_get_instr (cpu), 12, 12))
8271 dexSimpleFPImmediate (cpu);
8273 else if (uimm (aarch64_get_instr (cpu), 13, 13))
8274 dexSimpleFPCompare (cpu);
8276 else if (uimm (aarch64_get_instr (cpu), 14, 14))
8277 dexSimpleFPDataProc1Source (cpu);
8279 else if (!uimm (aarch64_get_instr (cpu), 15, 15))
8280 dexSimpleFPIntegerConvert (cpu);
8283 /* If we get here then instr[15] == 1 which means UNALLOC. */
8288 /* PC relative addressing. */
8291 pcadr (sim_cpu *cpu)
8293 /* instr[31] = op : 0 ==> ADR, 1 ==> ADRP
8294 instr[30,29] = immlo
8295 instr[23,5] = immhi. */
8297 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
8298 uint32_t isPage = uimm (aarch64_get_instr (cpu), 31, 31);
8299 union { int64_t u64; uint64_t s64; } imm;
8302 imm.s64 = simm64 (aarch64_get_instr (cpu), 23, 5);
8304 offset = (offset << 2) | uimm (aarch64_get_instr (cpu), 30, 29);
8306 address = aarch64_get_PC (cpu);
8314 aarch64_set_reg_u64 (cpu, rd, NO_SP, address + offset);
8317 /* Specific decode and execute for group Data Processing Immediate. */
8320 dexPCRelAddressing (sim_cpu *cpu)
8322 /* assert instr[28,24] = 10000. */
8326 /* Immediate logical.
8327 The bimm32/64 argument is constructed by replicating a 2, 4, 8,
8328 16, 32 or 64 bit sequence pulled out at decode and possibly
8331 N.B. the output register (dest) can normally be Xn or SP
8332 the exception occurs for flag setting instructions which may
8333 only use Xn for the output (dest). The input register can
8336 /* 32 bit and immediate. */
8338 and32 (sim_cpu *cpu, uint32_t bimm)
8340 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
8341 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
8343 aarch64_set_reg_u64 (cpu, rd, SP_OK,
8344 aarch64_get_reg_u32 (cpu, rn, NO_SP) & bimm);
8347 /* 64 bit and immediate. */
8349 and64 (sim_cpu *cpu, uint64_t bimm)
8351 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
8352 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
8354 aarch64_set_reg_u64 (cpu, rd, SP_OK,
8355 aarch64_get_reg_u64 (cpu, rn, NO_SP) & bimm);
8358 /* 32 bit and immediate set flags. */
8360 ands32 (sim_cpu *cpu, uint32_t bimm)
8362 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
8363 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
8365 uint32_t value1 = aarch64_get_reg_u32 (cpu, rn, NO_SP);
8366 uint32_t value2 = bimm;
8368 aarch64_set_reg_u64 (cpu, rd, NO_SP, value1 & value2);
8369 set_flags_for_binop32 (cpu, value1 & value2);
8372 /* 64 bit and immediate set flags. */
8374 ands64 (sim_cpu *cpu, uint64_t bimm)
8376 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
8377 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
8379 uint64_t value1 = aarch64_get_reg_u64 (cpu, rn, NO_SP);
8380 uint64_t value2 = bimm;
8382 aarch64_set_reg_u64 (cpu, rd, NO_SP, value1 & value2);
8383 set_flags_for_binop64 (cpu, value1 & value2);
8386 /* 32 bit exclusive or immediate. */
8388 eor32 (sim_cpu *cpu, uint32_t bimm)
8390 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
8391 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
8393 aarch64_set_reg_u64 (cpu, rd, SP_OK,
8394 aarch64_get_reg_u32 (cpu, rn, NO_SP) ^ bimm);
8397 /* 64 bit exclusive or immediate. */
8399 eor64 (sim_cpu *cpu, uint64_t bimm)
8401 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
8402 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
8404 aarch64_set_reg_u64 (cpu, rd, SP_OK,
8405 aarch64_get_reg_u64 (cpu, rn, NO_SP) ^ bimm);
8408 /* 32 bit or immediate. */
8410 orr32 (sim_cpu *cpu, uint32_t bimm)
8412 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
8413 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
8415 aarch64_set_reg_u64 (cpu, rd, SP_OK,
8416 aarch64_get_reg_u32 (cpu, rn, NO_SP) | bimm);
8419 /* 64 bit or immediate. */
8421 orr64 (sim_cpu *cpu, uint64_t bimm)
8423 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
8424 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
8426 aarch64_set_reg_u64 (cpu, rd, SP_OK,
8427 aarch64_get_reg_u64 (cpu, rn, NO_SP) | bimm);
8430 /* Logical shifted register.
8431 These allow an optional LSL, ASR, LSR or ROR to the second source
8432 register with a count up to the register bit count.
8433 N.B register args may not be SP. */
8435 /* 32 bit AND shifted register. */
8437 and32_shift (sim_cpu *cpu, Shift shift, uint32_t count)
8439 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
8440 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
8441 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
8444 (cpu, rd, NO_SP, aarch64_get_reg_u32 (cpu, rn, NO_SP)
8445 & shifted32 (aarch64_get_reg_u32 (cpu, rm, NO_SP), shift, count));
8448 /* 64 bit AND shifted register. */
8450 and64_shift (sim_cpu *cpu, Shift shift, uint32_t count)
8452 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
8453 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
8454 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
8457 (cpu, rd, NO_SP, aarch64_get_reg_u64 (cpu, rn, NO_SP)
8458 & shifted64 (aarch64_get_reg_u64 (cpu, rm, NO_SP), shift, count));
8461 /* 32 bit AND shifted register setting flags. */
8463 ands32_shift (sim_cpu *cpu, Shift shift, uint32_t count)
8465 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
8466 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
8467 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
8469 uint32_t value1 = aarch64_get_reg_u32 (cpu, rn, NO_SP);
8470 uint32_t value2 = shifted32 (aarch64_get_reg_u32 (cpu, rm, NO_SP),
8473 aarch64_set_reg_u64 (cpu, rd, NO_SP, value1 & value2);
8474 set_flags_for_binop32 (cpu, value1 & value2);
8477 /* 64 bit AND shifted register setting flags. */
8479 ands64_shift (sim_cpu *cpu, Shift shift, uint32_t count)
8481 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
8482 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
8483 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
8485 uint64_t value1 = aarch64_get_reg_u64 (cpu, rn, NO_SP);
8486 uint64_t value2 = shifted64 (aarch64_get_reg_u64 (cpu, rm, NO_SP),
8489 aarch64_set_reg_u64 (cpu, rd, NO_SP, value1 & value2);
8490 set_flags_for_binop64 (cpu, value1 & value2);
8493 /* 32 bit BIC shifted register. */
8495 bic32_shift (sim_cpu *cpu, Shift shift, uint32_t count)
8497 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
8498 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
8499 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
8502 (cpu, rd, NO_SP, aarch64_get_reg_u32 (cpu, rn, NO_SP)
8503 & ~ shifted32 (aarch64_get_reg_u32 (cpu, rm, NO_SP), shift, count));
8506 /* 64 bit BIC shifted register. */
8508 bic64_shift (sim_cpu *cpu, Shift shift, uint32_t count)
8510 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
8511 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
8512 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
8515 (cpu, rd, NO_SP, aarch64_get_reg_u64 (cpu, rn, NO_SP)
8516 & ~ shifted64 (aarch64_get_reg_u64 (cpu, rm, NO_SP), shift, count));
8519 /* 32 bit BIC shifted register setting flags. */
8521 bics32_shift (sim_cpu *cpu, Shift shift, uint32_t count)
8523 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
8524 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
8525 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
8527 uint32_t value1 = aarch64_get_reg_u32 (cpu, rn, NO_SP);
8528 uint32_t value2 = ~ shifted32 (aarch64_get_reg_u32 (cpu, rm, NO_SP),
8531 aarch64_set_reg_u64 (cpu, rd, NO_SP, value1 & value2);
8532 set_flags_for_binop32 (cpu, value1 & value2);
8535 /* 64 bit BIC shifted register setting flags. */
8537 bics64_shift (sim_cpu *cpu, Shift shift, uint32_t count)
8539 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
8540 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
8541 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
8543 uint64_t value1 = aarch64_get_reg_u64 (cpu, rn, NO_SP);
8544 uint64_t value2 = ~ shifted64 (aarch64_get_reg_u64 (cpu, rm, NO_SP),
8547 aarch64_set_reg_u64 (cpu, rd, NO_SP, value1 & value2);
8548 set_flags_for_binop64 (cpu, value1 & value2);
8551 /* 32 bit EON shifted register. */
8553 eon32_shift (sim_cpu *cpu, Shift shift, uint32_t count)
8555 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
8556 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
8557 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
8560 (cpu, rd, NO_SP, aarch64_get_reg_u32 (cpu, rn, NO_SP)
8561 ^ ~ shifted32 (aarch64_get_reg_u32 (cpu, rm, NO_SP), shift, count));
8564 /* 64 bit EON shifted register. */
8566 eon64_shift (sim_cpu *cpu, Shift shift, uint32_t count)
8568 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
8569 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
8570 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
8573 (cpu, rd, NO_SP, aarch64_get_reg_u64 (cpu, rn, NO_SP)
8574 ^ ~ shifted64 (aarch64_get_reg_u64 (cpu, rm, NO_SP), shift, count));
8577 /* 32 bit EOR shifted register. */
8579 eor32_shift (sim_cpu *cpu, Shift shift, uint32_t count)
8581 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
8582 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
8583 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
8586 (cpu, rd, NO_SP, aarch64_get_reg_u32 (cpu, rn, NO_SP)
8587 ^ shifted32 (aarch64_get_reg_u32 (cpu, rm, NO_SP), shift, count));
8590 /* 64 bit EOR shifted register. */
8592 eor64_shift (sim_cpu *cpu, Shift shift, uint32_t count)
8594 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
8595 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
8596 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
8599 (cpu, rd, NO_SP, aarch64_get_reg_u64 (cpu, rn, NO_SP)
8600 ^ shifted64 (aarch64_get_reg_u64 (cpu, rm, NO_SP), shift, count));
8603 /* 32 bit ORR shifted register. */
8605 orr32_shift (sim_cpu *cpu, Shift shift, uint32_t count)
8607 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
8608 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
8609 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
8612 (cpu, rd, NO_SP, aarch64_get_reg_u32 (cpu, rn, NO_SP)
8613 | shifted32 (aarch64_get_reg_u32 (cpu, rm, NO_SP), shift, count));
8616 /* 64 bit ORR shifted register. */
8618 orr64_shift (sim_cpu *cpu, Shift shift, uint32_t count)
8620 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
8621 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
8622 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
8625 (cpu, rd, NO_SP, aarch64_get_reg_u64 (cpu, rn, NO_SP)
8626 | shifted64 (aarch64_get_reg_u64 (cpu, rm, NO_SP), shift, count));
8629 /* 32 bit ORN shifted register. */
8631 orn32_shift (sim_cpu *cpu, Shift shift, uint32_t count)
8633 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
8634 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
8635 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
8638 (cpu, rd, NO_SP, aarch64_get_reg_u32 (cpu, rn, NO_SP)
8639 | ~ shifted32 (aarch64_get_reg_u32 (cpu, rm, NO_SP), shift, count));
8642 /* 64 bit ORN shifted register. */
8644 orn64_shift (sim_cpu *cpu, Shift shift, uint32_t count)
8646 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
8647 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
8648 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
8651 (cpu, rd, NO_SP, aarch64_get_reg_u64 (cpu, rn, NO_SP)
8652 | ~ shifted64 (aarch64_get_reg_u64 (cpu, rm, NO_SP), shift, count));
8656 dexLogicalImmediate (sim_cpu *cpu)
8658 /* assert instr[28,23] = 1001000
8659 instr[31] = size : 0 ==> 32 bit, 1 ==> 64 bit
8660 instr[30,29] = op : 0 ==> AND, 1 ==> ORR, 2 ==> EOR, 3 ==> ANDS
8661 instr[22] = N : used to construct immediate mask
8667 /* 32 bit operations must have N = 0 or else we have an UNALLOC. */
8668 uint32_t size = uimm (aarch64_get_instr (cpu), 31, 31);
8669 uint32_t N = uimm (aarch64_get_instr (cpu), 22, 22);
8670 /* uint32_t immr = uimm (aarch64_get_instr (cpu), 21, 16);. */
8671 /* uint32_t imms = uimm (aarch64_get_instr (cpu), 15, 10);. */
8672 uint32_t index = uimm (aarch64_get_instr (cpu), 22, 10);
8673 uint64_t bimm64 = LITable [index];
8674 uint32_t dispatch = uimm (aarch64_get_instr (cpu), 30, 29);
8684 uint32_t bimm = (uint32_t) bimm64;
8688 case 0: and32 (cpu, bimm); return;
8689 case 1: orr32 (cpu, bimm); return;
8690 case 2: eor32 (cpu, bimm); return;
8691 case 3: ands32 (cpu, bimm); return;
8698 case 0: and64 (cpu, bimm64); return;
8699 case 1: orr64 (cpu, bimm64); return;
8700 case 2: eor64 (cpu, bimm64); return;
8701 case 3: ands64 (cpu, bimm64); return;
8708 The uimm argument is a 16 bit value to be inserted into the
8709 target register the pos argument locates the 16 bit word in the
8710 dest register i.e. it is in {0, 1} for 32 bit and {0, 1, 2,
8712 N.B register arg may not be SP so it should be.
8713 accessed using the setGZRegisterXXX accessors. */
8715 /* 32 bit move 16 bit immediate zero remaining shorts. */
8717 movz32 (sim_cpu *cpu, uint32_t val, uint32_t pos)
8719 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
8721 aarch64_set_reg_u64 (cpu, rd, NO_SP, val << (pos * 16));
8724 /* 64 bit move 16 bit immediate zero remaining shorts. */
8726 movz64 (sim_cpu *cpu, uint32_t val, uint32_t pos)
8728 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
8730 aarch64_set_reg_u64 (cpu, rd, NO_SP, ((uint64_t) val) << (pos * 16));
8733 /* 32 bit move 16 bit immediate negated. */
8735 movn32 (sim_cpu *cpu, uint32_t val, uint32_t pos)
8737 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
8739 aarch64_set_reg_u64 (cpu, rd, NO_SP, ((val << (pos * 16)) ^ 0xffffffffU));
8742 /* 64 bit move 16 bit immediate negated. */
8744 movn64 (sim_cpu *cpu, uint32_t val, uint32_t pos)
8746 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
8749 (cpu, rd, NO_SP, ((((uint64_t) val) << (pos * 16))
8750 ^ 0xffffffffffffffffULL));
8753 /* 32 bit move 16 bit immediate keep remaining shorts. */
8755 movk32 (sim_cpu *cpu, uint32_t val, uint32_t pos)
8757 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
8758 uint32_t current = aarch64_get_reg_u32 (cpu, rd, NO_SP);
8759 uint32_t value = val << (pos * 16);
8760 uint32_t mask = ~(0xffffU << (pos * 16));
8762 aarch64_set_reg_u64 (cpu, rd, NO_SP, (value | (current & mask)));
8765 /* 64 bit move 16 it immediate keep remaining shorts. */
8767 movk64 (sim_cpu *cpu, uint32_t val, uint32_t pos)
8769 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
8770 uint64_t current = aarch64_get_reg_u64 (cpu, rd, NO_SP);
8771 uint64_t value = (uint64_t) val << (pos * 16);
8772 uint64_t mask = ~(0xffffULL << (pos * 16));
8774 aarch64_set_reg_u64 (cpu, rd, NO_SP, (value | (current & mask)));
8778 dexMoveWideImmediate (sim_cpu *cpu)
8780 /* assert instr[28:23] = 100101
8781 instr[31] = size : 0 ==> 32 bit, 1 ==> 64 bit
8782 instr[30,29] = op : 0 ==> MOVN, 1 ==> UNALLOC, 2 ==> MOVZ, 3 ==> MOVK
8783 instr[22,21] = shift : 00 == LSL#0, 01 = LSL#16, 10 = LSL#32, 11 = LSL#48
8784 instr[20,5] = uimm16
8787 /* N.B. the (multiple of 16) shift is applied by the called routine,
8788 we just pass the multiplier. */
8791 uint32_t size = uimm (aarch64_get_instr (cpu), 31, 31);
8792 uint32_t op = uimm (aarch64_get_instr (cpu), 30, 29);
8793 uint32_t shift = uimm (aarch64_get_instr (cpu), 22, 21);
8795 /* 32 bit can only shift 0 or 1 lot of 16.
8796 anything else is an unallocated instruction. */
8797 if (size == 0 && (shift > 1))
8803 imm = uimm (aarch64_get_instr (cpu), 20, 5);
8808 movn32 (cpu, imm, shift);
8810 movz32 (cpu, imm, shift);
8812 movk32 (cpu, imm, shift);
8817 movn64 (cpu, imm, shift);
8819 movz64 (cpu, imm, shift);
8821 movk64 (cpu, imm, shift);
8825 /* Bitfield operations.
8826 These take a pair of bit positions r and s which are in {0..31}
8827 or {0..63} depending on the instruction word size.
8828 N.B register args may not be SP. */
8830 /* OK, we start with ubfm which just needs to pick
8831 some bits out of source zero the rest and write
8832 the result to dest. Just need two logical shifts. */
8834 /* 32 bit bitfield move, left and right of affected zeroed
8835 if r <= s Wd<s-r:0> = Wn<s:r> else Wd<32+s-r,32-r> = Wn<s:0>. */
8837 ubfm32 (sim_cpu *cpu, uint32_t r, uint32_t s)
8840 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
8841 uint32_t value = aarch64_get_reg_u32 (cpu, rn, NO_SP);
8843 /* Pick either s+1-r or s+1 consecutive bits out of the original word. */
8846 /* 31:...:s:xxx:r:...:0 ==> 31:...:s-r:xxx:0.
8847 We want only bits s:xxx:r at the bottom of the word
8848 so we LSL bit s up to bit 31 i.e. by 31 - s
8849 and then we LSR to bring bit 31 down to bit s - r
8850 i.e. by 31 + r - s. */
8852 value >>= 31 + r - s;
8856 /* 31:...:s:xxx:0 ==> 31:...:31-(r-1)+s:xxx:31-(r-1):...:0
8857 We want only bits s:xxx:0 starting at it 31-(r-1)
8858 so we LSL bit s up to bit 31 i.e. by 31 - s
8859 and then we LSL to bring bit 31 down to 31-(r-1)+s
8860 i.e. by r - (s + 1). */
8862 value >>= r - (s + 1);
8865 rd = uimm (aarch64_get_instr (cpu), 4, 0);
8866 aarch64_set_reg_u64 (cpu, rd, NO_SP, value);
8869 /* 64 bit bitfield move, left and right of affected zeroed
8870 if r <= s Wd<s-r:0> = Wn<s:r> else Wd<64+s-r,64-r> = Wn<s:0>. */
8872 ubfm (sim_cpu *cpu, uint32_t r, uint32_t s)
8875 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
8876 uint64_t value = aarch64_get_reg_u64 (cpu, rn, NO_SP);
8880 /* 63:...:s:xxx:r:...:0 ==> 63:...:s-r:xxx:0.
8881 We want only bits s:xxx:r at the bottom of the word.
8882 So we LSL bit s up to bit 63 i.e. by 63 - s
8883 and then we LSR to bring bit 63 down to bit s - r
8884 i.e. by 63 + r - s. */
8886 value >>= 63 + r - s;
8890 /* 63:...:s:xxx:0 ==> 63:...:63-(r-1)+s:xxx:63-(r-1):...:0.
8891 We want only bits s:xxx:0 starting at it 63-(r-1).
8892 So we LSL bit s up to bit 63 i.e. by 63 - s
8893 and then we LSL to bring bit 63 down to 63-(r-1)+s
8894 i.e. by r - (s + 1). */
8896 value >>= r - (s + 1);
8899 rd = uimm (aarch64_get_instr (cpu), 4, 0);
8900 aarch64_set_reg_u64 (cpu, rd, NO_SP, value);
8903 /* The signed versions need to insert sign bits
8904 on the left of the inserted bit field. so we do
8905 much the same as the unsigned version except we
8906 use an arithmetic shift right -- this just means
8907 we need to operate on signed values. */
8909 /* 32 bit bitfield move, left of affected sign-extended, right zeroed. */
8910 /* If r <= s Wd<s-r:0> = Wn<s:r> else Wd<32+s-r,32-r> = Wn<s:0>. */
8912 sbfm32 (sim_cpu *cpu, uint32_t r, uint32_t s)
8915 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
8916 /* as per ubfm32 but use an ASR instead of an LSR. */
8917 int32_t value = aarch64_get_reg_s32 (cpu, rn, NO_SP);
8922 value >>= 31 + r - s;
8927 value >>= r - (s + 1);
8930 rd = uimm (aarch64_get_instr (cpu), 4, 0);
8931 aarch64_set_reg_u64 (cpu, rd, NO_SP, (uint32_t) value);
8934 /* 64 bit bitfield move, left of affected sign-extended, right zeroed. */
8935 /* If r <= s Wd<s-r:0> = Wn<s:r> else Wd<64+s-r,64-r> = Wn<s:0>. */
8937 sbfm (sim_cpu *cpu, uint32_t r, uint32_t s)
8940 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
8941 /* acpu per ubfm but use an ASR instead of an LSR. */
8942 int64_t value = aarch64_get_reg_s64 (cpu, rn, NO_SP);
8947 value >>= 63 + r - s;
8952 value >>= r - (s + 1);
8955 rd = uimm (aarch64_get_instr (cpu), 4, 0);
8956 aarch64_set_reg_s64 (cpu, rd, NO_SP, value);
8959 /* Finally, these versions leave non-affected bits
8960 as is. so we need to generate the bits as per
8961 ubfm and also generate a mask to pick the
8962 bits from the original and computed values. */
8964 /* 32 bit bitfield move, non-affected bits left as is.
8965 If r <= s Wd<s-r:0> = Wn<s:r> else Wd<32+s-r,32-r> = Wn<s:0>. */
8967 bfm32 (sim_cpu *cpu, uint32_t r, uint32_t s)
8969 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
8970 uint32_t value = aarch64_get_reg_u32 (cpu, rn, NO_SP);
8975 /* Pick either s+1-r or s+1 consecutive bits out of the original word. */
8978 /* 31:...:s:xxx:r:...:0 ==> 31:...:s-r:xxx:0.
8979 We want only bits s:xxx:r at the bottom of the word
8980 so we LSL bit s up to bit 31 i.e. by 31 - s
8981 and then we LSR to bring bit 31 down to bit s - r
8982 i.e. by 31 + r - s. */
8984 value >>= 31 + r - s;
8985 /* the mask must include the same bits. */
8987 mask >>= 31 + r - s;
8991 /* 31:...:s:xxx:0 ==> 31:...:31-(r-1)+s:xxx:31-(r-1):...:0.
8992 We want only bits s:xxx:0 starting at it 31-(r-1)
8993 so we LSL bit s up to bit 31 i.e. by 31 - s
8994 and then we LSL to bring bit 31 down to 31-(r-1)+s
8995 i.e. by r - (s + 1). */
8997 value >>= r - (s + 1);
8998 /* The mask must include the same bits. */
9000 mask >>= r - (s + 1);
9003 rd = uimm (aarch64_get_instr (cpu), 4, 0);
9004 value2 = aarch64_get_reg_u32 (cpu, rd, NO_SP);
9010 (cpu, rd, NO_SP, (aarch64_get_reg_u32 (cpu, rd, NO_SP) & ~mask) | value);
9013 /* 64 bit bitfield move, non-affected bits left as is.
9014 If r <= s Wd<s-r:0> = Wn<s:r> else Wd<64+s-r,64-r> = Wn<s:0>. */
9016 bfm (sim_cpu *cpu, uint32_t r, uint32_t s)
9019 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
9020 uint64_t value = aarch64_get_reg_u64 (cpu, rn, NO_SP);
9021 uint64_t mask = 0xffffffffffffffffULL;
9025 /* 63:...:s:xxx:r:...:0 ==> 63:...:s-r:xxx:0.
9026 We want only bits s:xxx:r at the bottom of the word
9027 so we LSL bit s up to bit 63 i.e. by 63 - s
9028 and then we LSR to bring bit 63 down to bit s - r
9029 i.e. by 63 + r - s. */
9031 value >>= 63 + r - s;
9032 /* The mask must include the same bits. */
9034 mask >>= 63 + r - s;
9038 /* 63:...:s:xxx:0 ==> 63:...:63-(r-1)+s:xxx:63-(r-1):...:0
9039 We want only bits s:xxx:0 starting at it 63-(r-1)
9040 so we LSL bit s up to bit 63 i.e. by 63 - s
9041 and then we LSL to bring bit 63 down to 63-(r-1)+s
9042 i.e. by r - (s + 1). */
9044 value >>= r - (s + 1);
9045 /* The mask must include the same bits. */
9047 mask >>= r - (s + 1);
9050 rd = uimm (aarch64_get_instr (cpu), 4, 0);
9052 (cpu, rd, NO_SP, (aarch64_get_reg_u64 (cpu, rd, NO_SP) & ~mask) | value);
9056 dexBitfieldImmediate (sim_cpu *cpu)
9058 /* assert instr[28:23] = 100110
9059 instr[31] = size : 0 ==> 32 bit, 1 ==> 64 bit
9060 instr[30,29] = op : 0 ==> SBFM, 1 ==> BFM, 2 ==> UBFM, 3 ==> UNALLOC
9061 instr[22] = N : must be 0 for 32 bit, 1 for 64 bit ow UNALLOC
9062 instr[21,16] = immr : 0xxxxx for 32 bit, xxxxxx for 64 bit
9063 instr[15,10] = imms : 0xxxxx for 32 bit, xxxxxx for 64 bit
9067 /* 32 bit operations must have N = 0 or else we have an UNALLOC. */
9070 uint32_t size = uimm (aarch64_get_instr (cpu), 31, 31);
9071 uint32_t N = uimm (aarch64_get_instr (cpu), 22, 22);
9072 /* 32 bit operations must have immr[5] = 0 and imms[5] = 0. */
9073 /* or else we have an UNALLOC. */
9074 uint32_t immr = uimm (aarch64_get_instr (cpu), 21, 16);
9079 if (!size && uimm (immr, 5, 5))
9082 imms = uimm (aarch64_get_instr (cpu), 15, 10);
9083 if (!size && uimm (imms, 5, 5))
9086 /* Switch on combined size and op. */
9087 dispatch = uimm (aarch64_get_instr (cpu), 31, 29);
9090 case 0: sbfm32 (cpu, immr, imms); return;
9091 case 1: bfm32 (cpu, immr, imms); return;
9092 case 2: ubfm32 (cpu, immr, imms); return;
9093 case 4: sbfm (cpu, immr, imms); return;
9094 case 5: bfm (cpu, immr, imms); return;
9095 case 6: ubfm (cpu, immr, imms); return;
9096 default: HALT_UNALLOC;
9101 do_EXTR_32 (sim_cpu *cpu)
9103 /* instr[31:21] = 00010011100
9105 instr[15,10] = imms : 0xxxxx for 32 bit
9108 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
9109 unsigned imms = uimm (aarch64_get_instr (cpu), 15, 10) & 31;
9110 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
9111 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
9115 val1 = aarch64_get_reg_u32 (cpu, rm, NO_SP);
9117 val2 = aarch64_get_reg_u32 (cpu, rn, NO_SP);
9118 val2 <<= (32 - imms);
9120 aarch64_set_reg_u64 (cpu, rd, NO_SP, val1 | val2);
9124 do_EXTR_64 (sim_cpu *cpu)
9126 /* instr[31:21] = 10010011100
9131 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
9132 unsigned imms = uimm (aarch64_get_instr (cpu), 15, 10) & 63;
9133 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
9134 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
9137 val = aarch64_get_reg_u64 (cpu, rm, NO_SP);
9139 val |= (aarch64_get_reg_u64 (cpu, rn, NO_SP) << (64 - imms));
9141 aarch64_set_reg_u64 (cpu, rd, NO_SP, val);
9145 dexExtractImmediate (sim_cpu *cpu)
9147 /* assert instr[28:23] = 100111
9148 instr[31] = size : 0 ==> 32 bit, 1 ==> 64 bit
9149 instr[30,29] = op21 : 0 ==> EXTR, 1,2,3 ==> UNALLOC
9150 instr[22] = N : must be 0 for 32 bit, 1 for 64 bit or UNALLOC
9151 instr[21] = op0 : must be 0 or UNALLOC
9153 instr[15,10] = imms : 0xxxxx for 32 bit, xxxxxx for 64 bit
9157 /* 32 bit operations must have N = 0 or else we have an UNALLOC. */
9158 /* 64 bit operations must have N = 1 or else we have an UNALLOC. */
9160 uint32_t size = uimm (aarch64_get_instr (cpu), 31, 31);
9161 uint32_t N = uimm (aarch64_get_instr (cpu), 22, 22);
9162 /* 32 bit operations must have imms[5] = 0
9163 or else we have an UNALLOC. */
9164 uint32_t imms = uimm (aarch64_get_instr (cpu), 15, 10);
9169 if (!size && uimm (imms, 5, 5))
9172 /* Switch on combined size and op. */
9173 dispatch = uimm (aarch64_get_instr (cpu), 31, 29);
9178 else if (dispatch == 4)
9181 else if (dispatch == 1)
9188 dexDPImm (sim_cpu *cpu)
9190 /* uint32_t group = dispatchGroup (aarch64_get_instr (cpu));
9191 assert group == GROUP_DPIMM_1000 || grpoup == GROUP_DPIMM_1001
9192 bits [25,23] of a DPImm are the secondary dispatch vector. */
9193 uint32_t group2 = dispatchDPImm (aarch64_get_instr (cpu));
9197 case DPIMM_PCADR_000:
9198 case DPIMM_PCADR_001:
9199 dexPCRelAddressing (cpu);
9202 case DPIMM_ADDSUB_010:
9203 case DPIMM_ADDSUB_011:
9204 dexAddSubtractImmediate (cpu);
9208 dexLogicalImmediate (cpu);
9212 dexMoveWideImmediate (cpu);
9215 case DPIMM_BITF_110:
9216 dexBitfieldImmediate (cpu);
9219 case DPIMM_EXTR_111:
9220 dexExtractImmediate (cpu);
9224 /* Should never reach here. */
9230 dexLoadUnscaledImmediate (sim_cpu *cpu)
9232 /* instr[29,24] == 111_00
9238 instr[20,12] = simm9
9239 instr[9,5] = rn may be SP. */
9240 /* unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0); */
9241 uint32_t V = uimm (aarch64_get_instr (cpu), 26, 26);
9242 uint32_t dispatch = ( (uimm (aarch64_get_instr (cpu), 31, 30) << 2)
9243 | uimm (aarch64_get_instr (cpu), 23, 22));
9244 int32_t imm = simm32 (aarch64_get_instr (cpu), 20, 12);
9248 /* GReg operations. */
9251 case 0: sturb (cpu, imm); return;
9252 case 1: ldurb32 (cpu, imm); return;
9253 case 2: ldursb64 (cpu, imm); return;
9254 case 3: ldursb32 (cpu, imm); return;
9255 case 4: sturh (cpu, imm); return;
9256 case 5: ldurh32 (cpu, imm); return;
9257 case 6: ldursh64 (cpu, imm); return;
9258 case 7: ldursh32 (cpu, imm); return;
9259 case 8: stur32 (cpu, imm); return;
9260 case 9: ldur32 (cpu, imm); return;
9261 case 10: ldursw (cpu, imm); return;
9262 case 12: stur64 (cpu, imm); return;
9263 case 13: ldur64 (cpu, imm); return;
9276 /* FReg operations. */
9279 case 2: fsturq (cpu, imm); return;
9280 case 3: fldurq (cpu, imm); return;
9281 case 8: fsturs (cpu, imm); return;
9282 case 9: fldurs (cpu, imm); return;
9283 case 12: fsturd (cpu, imm); return;
9284 case 13: fldurd (cpu, imm); return;
9286 case 0: /* STUR 8 bit FP. */
9287 case 1: /* LDUR 8 bit FP. */
9288 case 4: /* STUR 16 bit FP. */
9289 case 5: /* LDUR 8 bit FP. */
9303 /* N.B. A preliminary note regarding all the ldrs<x>32
9306 The signed value loaded by these instructions is cast to unsigned
9307 before being assigned to aarch64_get_reg_u64 (cpu, N) i.e. to the
9308 64 bit element of the GReg union. this performs a 32 bit sign extension
9309 (as required) but avoids 64 bit sign extension, thus ensuring that the
9310 top half of the register word is zero. this is what the spec demands
9311 when a 32 bit load occurs. */
9313 /* 32 bit load sign-extended byte scaled unsigned 12 bit. */
9315 ldrsb32_abs (sim_cpu *cpu, uint32_t offset)
9317 unsigned int rn = uimm (aarch64_get_instr (cpu), 9, 5);
9318 unsigned int rt = uimm (aarch64_get_instr (cpu), 4, 0);
9320 /* The target register may not be SP but the source may be
9321 there is no scaling required for a byte load. */
9322 uint64_t address = aarch64_get_reg_u64 (cpu, rn, SP_OK) + offset;
9323 aarch64_set_reg_u64 (cpu, rt, NO_SP,
9324 (int64_t) aarch64_get_mem_s8 (cpu, address));
9327 /* 32 bit load sign-extended byte scaled or unscaled zero-
9328 or sign-extended 32-bit register offset. */
9330 ldrsb32_scale_ext (sim_cpu *cpu, Scaling scaling, Extension extension)
9332 unsigned int rm = uimm (aarch64_get_instr (cpu), 20, 16);
9333 unsigned int rn = uimm (aarch64_get_instr (cpu), 9, 5);
9334 unsigned int rt = uimm (aarch64_get_instr (cpu), 4, 0);
9336 /* rn may reference SP, rm and rt must reference ZR. */
9338 uint64_t address = aarch64_get_reg_u64 (cpu, rn, SP_OK);
9339 int64_t displacement = extend (aarch64_get_reg_u32 (cpu, rm, NO_SP),
9342 /* There is no scaling required for a byte load. */
9344 (cpu, rt, NO_SP, (int64_t) aarch64_get_mem_s8 (cpu, address
9348 /* 32 bit load sign-extended byte unscaled signed 9 bit with
9349 pre- or post-writeback. */
9351 ldrsb32_wb (sim_cpu *cpu, int32_t offset, WriteBack wb)
9354 unsigned int rn = uimm (aarch64_get_instr (cpu), 9, 5);
9355 unsigned int rt = uimm (aarch64_get_instr (cpu), 4, 0);
9357 if (rn == rt && wb != NoWriteBack)
9360 address = aarch64_get_reg_u64 (cpu, rn, SP_OK);
9365 aarch64_set_reg_u64 (cpu, rt, NO_SP,
9366 (int64_t) aarch64_get_mem_s8 (cpu, address));
9371 if (wb != NoWriteBack)
9372 aarch64_set_reg_u64 (cpu, rn, NO_SP, address);
9375 /* 8 bit store scaled. */
9377 fstrb_abs (sim_cpu *cpu, uint32_t offset)
9379 unsigned st = uimm (aarch64_get_instr (cpu), 4, 0);
9380 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
9382 aarch64_set_mem_u8 (cpu,
9383 aarch64_get_reg_u64 (cpu, rn, SP_OK) + offset,
9384 aarch64_get_vec_u8 (cpu, st, 0));
9387 /* 8 bit store scaled or unscaled zero- or
9388 sign-extended 8-bit register offset. */
9390 fstrb_scale_ext (sim_cpu *cpu, Scaling scaling, Extension extension)
9392 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
9393 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
9394 unsigned st = uimm (aarch64_get_instr (cpu), 4, 0);
9396 uint64_t address = aarch64_get_reg_u64 (cpu, rn, SP_OK);
9397 int64_t extended = extend (aarch64_get_reg_u32 (cpu, rm, NO_SP),
9399 uint64_t displacement = OPT_SCALE (extended, 32, scaling);
9402 (cpu, address + displacement, aarch64_get_vec_u8 (cpu, st, 0));
9405 /* 16 bit store scaled. */
9407 fstrh_abs (sim_cpu *cpu, uint32_t offset)
9409 unsigned st = uimm (aarch64_get_instr (cpu), 4, 0);
9410 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
9414 aarch64_get_reg_u64 (cpu, rn, SP_OK) + SCALE (offset, 16),
9415 aarch64_get_vec_u16 (cpu, st, 0));
9418 /* 16 bit store scaled or unscaled zero-
9419 or sign-extended 16-bit register offset. */
9421 fstrh_scale_ext (sim_cpu *cpu, Scaling scaling, Extension extension)
9423 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
9424 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
9425 unsigned st = uimm (aarch64_get_instr (cpu), 4, 0);
9427 uint64_t address = aarch64_get_reg_u64 (cpu, rn, SP_OK);
9428 int64_t extended = extend (aarch64_get_reg_u32 (cpu, rm, NO_SP),
9430 uint64_t displacement = OPT_SCALE (extended, 32, scaling);
9433 (cpu, address + displacement, aarch64_get_vec_u16 (cpu, st, 0));
9436 /* 32 bit store scaled unsigned 12 bit. */
9438 fstrs_abs (sim_cpu *cpu, uint32_t offset)
9440 unsigned st = uimm (aarch64_get_instr (cpu), 4, 0);
9441 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
9443 aarch64_set_mem_float
9445 aarch64_get_reg_u64 (cpu, rn, SP_OK) + SCALE (offset, 32),
9446 aarch64_get_FP_float (cpu, st));
9449 /* 32 bit store unscaled signed 9 bit with pre- or post-writeback. */
9451 fstrs_wb (sim_cpu *cpu, int32_t offset, WriteBack wb)
9453 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
9454 unsigned st = uimm (aarch64_get_instr (cpu), 4, 0);
9456 uint64_t address = aarch64_get_reg_u64 (cpu, rn, SP_OK);
9461 aarch64_set_mem_float (cpu, address, aarch64_get_FP_float (cpu, st));
9466 if (wb != NoWriteBack)
9467 aarch64_set_reg_u64 (cpu, rn, SP_OK, address);
9470 /* 32 bit store scaled or unscaled zero-
9471 or sign-extended 32-bit register offset. */
9473 fstrs_scale_ext (sim_cpu *cpu, Scaling scaling, Extension extension)
9475 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
9476 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
9477 unsigned st = uimm (aarch64_get_instr (cpu), 4, 0);
9479 uint64_t address = aarch64_get_reg_u64 (cpu, rn, SP_OK);
9480 int64_t extended = extend (aarch64_get_reg_u32 (cpu, rm, NO_SP),
9482 uint64_t displacement = OPT_SCALE (extended, 32, scaling);
9484 aarch64_set_mem_float
9485 (cpu, address + displacement, aarch64_get_FP_float (cpu, st));
9488 /* 64 bit store scaled unsigned 12 bit. */
9490 fstrd_abs (sim_cpu *cpu, uint32_t offset)
9492 unsigned st = uimm (aarch64_get_instr (cpu), 4, 0);
9493 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
9495 aarch64_set_mem_double
9497 aarch64_get_reg_u64 (cpu, rn, SP_OK) + SCALE (offset, 64),
9498 aarch64_get_FP_double (cpu, st));
9501 /* 64 bit store unscaled signed 9 bit with pre- or post-writeback. */
9503 fstrd_wb (sim_cpu *cpu, int32_t offset, WriteBack wb)
9505 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
9506 unsigned st = uimm (aarch64_get_instr (cpu), 4, 0);
9508 uint64_t address = aarch64_get_reg_u64 (cpu, rn, SP_OK);
9513 aarch64_set_mem_double (cpu, address, aarch64_get_FP_double (cpu, st));
9518 if (wb != NoWriteBack)
9519 aarch64_set_reg_u64 (cpu, rn, SP_OK, address);
9522 /* 64 bit store scaled or unscaled zero-
9523 or sign-extended 32-bit register offset. */
9525 fstrd_scale_ext (sim_cpu *cpu, Scaling scaling, Extension extension)
9527 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
9528 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
9529 unsigned st = uimm (aarch64_get_instr (cpu), 4, 0);
9531 uint64_t address = aarch64_get_reg_u64 (cpu, rn, SP_OK);
9532 int64_t extended = extend (aarch64_get_reg_u32 (cpu, rm, NO_SP),
9534 uint64_t displacement = OPT_SCALE (extended, 64, scaling);
9536 aarch64_set_mem_double
9537 (cpu, address + displacement, aarch64_get_FP_double (cpu, st));
9540 /* 128 bit store scaled unsigned 12 bit. */
9542 fstrq_abs (sim_cpu *cpu, uint32_t offset)
9545 unsigned st = uimm (aarch64_get_instr (cpu), 4, 0);
9546 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
9549 aarch64_get_FP_long_double (cpu, st, & a);
9551 addr = aarch64_get_reg_u64 (cpu, rn, SP_OK) + SCALE (offset, 128);
9552 aarch64_set_mem_long_double (cpu, addr, a);
9555 /* 128 bit store unscaled signed 9 bit with pre- or post-writeback. */
9557 fstrq_wb (sim_cpu *cpu, int32_t offset, WriteBack wb)
9560 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
9561 unsigned st = uimm (aarch64_get_instr (cpu), 4, 0);
9562 uint64_t address = aarch64_get_reg_u64 (cpu, rn, SP_OK);
9567 aarch64_get_FP_long_double (cpu, st, & a);
9568 aarch64_set_mem_long_double (cpu, address, a);
9573 if (wb != NoWriteBack)
9574 aarch64_set_reg_u64 (cpu, rn, SP_OK, address);
9577 /* 128 bit store scaled or unscaled zero-
9578 or sign-extended 32-bit register offset. */
9580 fstrq_scale_ext (sim_cpu *cpu, Scaling scaling, Extension extension)
9582 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
9583 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
9584 unsigned st = uimm (aarch64_get_instr (cpu), 4, 0);
9586 uint64_t address = aarch64_get_reg_u64 (cpu, rn, SP_OK);
9587 int64_t extended = extend (aarch64_get_reg_u32 (cpu, rm, NO_SP),
9589 uint64_t displacement = OPT_SCALE (extended, 128, scaling);
9593 aarch64_get_FP_long_double (cpu, st, & a);
9594 aarch64_set_mem_long_double (cpu, address + displacement, a);
9598 dexLoadImmediatePrePost (sim_cpu *cpu)
9600 /* instr[29,24] == 111_00
9606 instr[20,12] = simm9
9607 instr[11] = wb : 0 ==> Post, 1 ==> Pre
9608 instr[9,5] = rn may be SP. */
9609 /* unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0); */
9610 uint32_t V = uimm (aarch64_get_instr (cpu), 26, 26);
9611 uint32_t dispatch = ( (uimm (aarch64_get_instr (cpu), 31, 30) << 2)
9612 | uimm (aarch64_get_instr (cpu), 23, 22));
9613 int32_t imm = simm32 (aarch64_get_instr (cpu), 20, 12);
9614 WriteBack wb = writeback (aarch64_get_instr (cpu), 11);
9618 /* GReg operations. */
9621 case 0: strb_wb (cpu, imm, wb); return;
9622 case 1: ldrb32_wb (cpu, imm, wb); return;
9623 case 2: ldrsb_wb (cpu, imm, wb); return;
9624 case 3: ldrsb32_wb (cpu, imm, wb); return;
9625 case 4: strh_wb (cpu, imm, wb); return;
9626 case 5: ldrh32_wb (cpu, imm, wb); return;
9627 case 6: ldrsh64_wb (cpu, imm, wb); return;
9628 case 7: ldrsh32_wb (cpu, imm, wb); return;
9629 case 8: str32_wb (cpu, imm, wb); return;
9630 case 9: ldr32_wb (cpu, imm, wb); return;
9631 case 10: ldrsw_wb (cpu, imm, wb); return;
9632 case 12: str_wb (cpu, imm, wb); return;
9633 case 13: ldr_wb (cpu, imm, wb); return;
9643 /* FReg operations. */
9646 case 2: fstrq_wb (cpu, imm, wb); return;
9647 case 3: fldrq_wb (cpu, imm, wb); return;
9648 case 8: fstrs_wb (cpu, imm, wb); return;
9649 case 9: fldrs_wb (cpu, imm, wb); return;
9650 case 12: fstrd_wb (cpu, imm, wb); return;
9651 case 13: fldrd_wb (cpu, imm, wb); return;
9653 case 0: /* STUR 8 bit FP. */
9654 case 1: /* LDUR 8 bit FP. */
9655 case 4: /* STUR 16 bit FP. */
9656 case 5: /* LDUR 8 bit FP. */
9671 dexLoadRegisterOffset (sim_cpu *cpu)
9673 /* instr[31,30] = size
9680 instr[15,13] = option : 010 ==> UXTW, 011 ==> UXTX/LSL,
9681 110 ==> SXTW, 111 ==> SXTX,
9688 uint32_t V = uimm (aarch64_get_instr (cpu), 26,26);
9689 uint32_t dispatch = ( (uimm (aarch64_get_instr (cpu), 31, 30) << 2)
9690 | uimm (aarch64_get_instr (cpu), 23, 22));
9691 Scaling scale = scaling (aarch64_get_instr (cpu), 12);
9692 Extension extensionType = extension (aarch64_get_instr (cpu), 13);
9694 /* Check for illegal extension types. */
9695 if (uimm (extensionType, 1, 1) == 0)
9698 if (extensionType == UXTX || extensionType == SXTX)
9699 extensionType = NoExtension;
9703 /* GReg operations. */
9706 case 0: strb_scale_ext (cpu, scale, extensionType); return;
9707 case 1: ldrb32_scale_ext (cpu, scale, extensionType); return;
9708 case 2: ldrsb_scale_ext (cpu, scale, extensionType); return;
9709 case 3: ldrsb32_scale_ext (cpu, scale, extensionType); return;
9710 case 4: strh_scale_ext (cpu, scale, extensionType); return;
9711 case 5: ldrh32_scale_ext (cpu, scale, extensionType); return;
9712 case 6: ldrsh_scale_ext (cpu, scale, extensionType); return;
9713 case 7: ldrsh32_scale_ext (cpu, scale, extensionType); return;
9714 case 8: str32_scale_ext (cpu, scale, extensionType); return;
9715 case 9: ldr32_scale_ext (cpu, scale, extensionType); return;
9716 case 10: ldrsw_scale_ext (cpu, scale, extensionType); return;
9717 case 12: str_scale_ext (cpu, scale, extensionType); return;
9718 case 13: ldr_scale_ext (cpu, scale, extensionType); return;
9719 case 14: prfm_scale_ext (cpu, scale, extensionType); return;
9728 /* FReg operations. */
9731 case 1: /* LDUR 8 bit FP. */
9733 case 3: fldrq_scale_ext (cpu, scale, extensionType); return;
9734 case 5: /* LDUR 8 bit FP. */
9736 case 9: fldrs_scale_ext (cpu, scale, extensionType); return;
9737 case 13: fldrd_scale_ext (cpu, scale, extensionType); return;
9739 case 0: fstrb_scale_ext (cpu, scale, extensionType); return;
9740 case 2: fstrq_scale_ext (cpu, scale, extensionType); return;
9741 case 4: fstrh_scale_ext (cpu, scale, extensionType); return;
9742 case 8: fstrs_scale_ext (cpu, scale, extensionType); return;
9743 case 12: fstrd_scale_ext (cpu, scale, extensionType); return;
9757 dexLoadUnsignedImmediate (sim_cpu *cpu)
9759 /* assert instr[29,24] == 111_01
9763 instr[21,10] = uimm12 : unsigned immediate offset
9764 instr[9,5] = rn may be SP. */
9765 /* unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0); */
9766 uint32_t V = uimm (aarch64_get_instr (cpu), 26,26);
9767 uint32_t dispatch = ( (uimm (aarch64_get_instr (cpu), 31, 30) << 2)
9768 | uimm (aarch64_get_instr (cpu), 23, 22));
9769 uint32_t imm = uimm (aarch64_get_instr (cpu), 21, 10);
9773 /* GReg operations. */
9776 case 0: strb_abs (cpu, imm); return;
9777 case 1: ldrb32_abs (cpu, imm); return;
9778 case 2: ldrsb_abs (cpu, imm); return;
9779 case 3: ldrsb32_abs (cpu, imm); return;
9780 case 4: strh_abs (cpu, imm); return;
9781 case 5: ldrh32_abs (cpu, imm); return;
9782 case 6: ldrsh_abs (cpu, imm); return;
9783 case 7: ldrsh32_abs (cpu, imm); return;
9784 case 8: str32_abs (cpu, imm); return;
9785 case 9: ldr32_abs (cpu, imm); return;
9786 case 10: ldrsw_abs (cpu, imm); return;
9787 case 12: str_abs (cpu, imm); return;
9788 case 13: ldr_abs (cpu, imm); return;
9789 case 14: prfm_abs (cpu, imm); return;
9798 /* FReg operations. */
9801 case 3: fldrq_abs (cpu, imm); return;
9802 case 9: fldrs_abs (cpu, imm); return;
9803 case 13: fldrd_abs (cpu, imm); return;
9805 case 0: fstrb_abs (cpu, imm); return;
9806 case 2: fstrq_abs (cpu, imm); return;
9807 case 4: fstrh_abs (cpu, imm); return;
9808 case 8: fstrs_abs (cpu, imm); return;
9809 case 12: fstrd_abs (cpu, imm); return;
9811 case 1: /* LDR 8 bit FP. */
9812 case 5: /* LDR 8 bit FP. */
9827 dexLoadExclusive (sim_cpu *cpu)
9829 /* assert instr[29:24] = 001000;
9831 instr[23] = 0 if exclusive
9832 instr[22] = L : 1 if load, 0 if store
9833 instr[21] = 1 if pair
9835 instr[15] = o0 : 1 if ordered
9840 switch (uimm (aarch64_get_instr (cpu), 22, 21))
9842 case 2: ldxr (cpu); return;
9843 case 0: stxr (cpu); return;
9849 dexLoadOther (sim_cpu *cpu)
9853 /* instr[29,25] = 111_0
9854 instr[24] == 0 ==> dispatch, 1 ==> ldst reg unsigned immediate
9855 instr[21:11,10] is the secondary dispatch. */
9856 if (uimm (aarch64_get_instr (cpu), 24, 24))
9858 dexLoadUnsignedImmediate (cpu);
9862 dispatch = ( (uimm (aarch64_get_instr (cpu), 21, 21) << 2)
9863 | uimm (aarch64_get_instr (cpu), 11, 10));
9866 case 0: dexLoadUnscaledImmediate (cpu); return;
9867 case 1: dexLoadImmediatePrePost (cpu); return;
9868 case 3: dexLoadImmediatePrePost (cpu); return;
9869 case 6: dexLoadRegisterOffset (cpu); return;
9881 store_pair_u32 (sim_cpu *cpu, int32_t offset, WriteBack wb)
9883 unsigned rn = uimm (aarch64_get_instr (cpu), 14, 10);
9884 unsigned rd = uimm (aarch64_get_instr (cpu), 9, 5);
9885 unsigned rm = uimm (aarch64_get_instr (cpu), 4, 0);
9886 uint64_t address = aarch64_get_reg_u64 (cpu, rd, SP_OK);
9888 if ((rn == rd || rm == rd) && wb != NoWriteBack)
9889 HALT_UNALLOC; /* ??? */
9896 aarch64_set_mem_u32 (cpu, address,
9897 aarch64_get_reg_u32 (cpu, rm, NO_SP));
9898 aarch64_set_mem_u32 (cpu, address + 4,
9899 aarch64_get_reg_u32 (cpu, rn, NO_SP));
9904 if (wb != NoWriteBack)
9905 aarch64_set_reg_u64 (cpu, rd, SP_OK, address);
9909 store_pair_u64 (sim_cpu *cpu, int32_t offset, WriteBack wb)
9911 unsigned rn = uimm (aarch64_get_instr (cpu), 14, 10);
9912 unsigned rd = uimm (aarch64_get_instr (cpu), 9, 5);
9913 unsigned rm = uimm (aarch64_get_instr (cpu), 4, 0);
9914 uint64_t address = aarch64_get_reg_u64 (cpu, rd, SP_OK);
9916 if ((rn == rd || rm == rd) && wb != NoWriteBack)
9917 HALT_UNALLOC; /* ??? */
9924 aarch64_set_mem_u64 (cpu, address,
9925 aarch64_get_reg_u64 (cpu, rm, SP_OK));
9926 aarch64_set_mem_u64 (cpu, address + 8,
9927 aarch64_get_reg_u64 (cpu, rn, SP_OK));
9932 if (wb != NoWriteBack)
9933 aarch64_set_reg_u64 (cpu, rd, SP_OK, address);
9937 load_pair_u32 (sim_cpu *cpu, int32_t offset, WriteBack wb)
9939 unsigned rn = uimm (aarch64_get_instr (cpu), 14, 10);
9940 unsigned rd = uimm (aarch64_get_instr (cpu), 9, 5);
9941 unsigned rm = uimm (aarch64_get_instr (cpu), 4, 0);
9942 uint64_t address = aarch64_get_reg_u64 (cpu, rd, SP_OK);
9944 /* treat this as unalloc to make sure we don't do it. */
9953 aarch64_set_reg_u64 (cpu, rm, SP_OK, aarch64_get_mem_u32 (cpu, address));
9954 aarch64_set_reg_u64 (cpu, rn, SP_OK, aarch64_get_mem_u32 (cpu, address + 4));
9959 if (wb != NoWriteBack)
9960 aarch64_set_reg_u64 (cpu, rd, SP_OK, address);
9964 load_pair_s32 (sim_cpu *cpu, int32_t offset, WriteBack wb)
9966 unsigned rn = uimm (aarch64_get_instr (cpu), 14, 10);
9967 unsigned rd = uimm (aarch64_get_instr (cpu), 9, 5);
9968 unsigned rm = uimm (aarch64_get_instr (cpu), 4, 0);
9969 uint64_t address = aarch64_get_reg_u64 (cpu, rd, SP_OK);
9971 /* Treat this as unalloc to make sure we don't do it. */
9980 aarch64_set_reg_s64 (cpu, rm, SP_OK, aarch64_get_mem_s32 (cpu, address));
9981 aarch64_set_reg_s64 (cpu, rn, SP_OK, aarch64_get_mem_s32 (cpu, address + 4));
9986 if (wb != NoWriteBack)
9987 aarch64_set_reg_u64 (cpu, rd, SP_OK, address);
9991 load_pair_u64 (sim_cpu *cpu, int32_t offset, WriteBack wb)
9993 unsigned rn = uimm (aarch64_get_instr (cpu), 14, 10);
9994 unsigned rd = uimm (aarch64_get_instr (cpu), 9, 5);
9995 unsigned rm = uimm (aarch64_get_instr (cpu), 4, 0);
9996 uint64_t address = aarch64_get_reg_u64 (cpu, rd, SP_OK);
9998 /* Treat this as unalloc to make sure we don't do it. */
10007 aarch64_set_reg_u64 (cpu, rm, SP_OK, aarch64_get_mem_u64 (cpu, address));
10008 aarch64_set_reg_u64 (cpu, rn, SP_OK, aarch64_get_mem_u64 (cpu, address + 8));
10013 if (wb != NoWriteBack)
10014 aarch64_set_reg_u64 (cpu, rd, SP_OK, address);
10018 dex_load_store_pair_gr (sim_cpu *cpu)
10020 /* instr[31,30] = size (10=> 64-bit, 01=> signed 32-bit, 00=> 32-bit)
10021 instr[29,25] = instruction encoding: 101_0
10022 instr[26] = V : 1 if fp 0 if gp
10023 instr[24,23] = addressing mode (10=> offset, 01=> post, 11=> pre)
10024 instr[22] = load/store (1=> load)
10025 instr[21,15] = signed, scaled, offset
10028 instr[ 4, 0] = Rm. */
10030 uint32_t dispatch = ((uimm (aarch64_get_instr (cpu), 31, 30) << 3)
10031 | uimm (aarch64_get_instr (cpu), 24, 22));
10032 int32_t offset = simm32 (aarch64_get_instr (cpu), 21, 15);
10036 case 2: store_pair_u32 (cpu, offset, Post); return;
10037 case 3: load_pair_u32 (cpu, offset, Post); return;
10038 case 4: store_pair_u32 (cpu, offset, NoWriteBack); return;
10039 case 5: load_pair_u32 (cpu, offset, NoWriteBack); return;
10040 case 6: store_pair_u32 (cpu, offset, Pre); return;
10041 case 7: load_pair_u32 (cpu, offset, Pre); return;
10043 case 11: load_pair_s32 (cpu, offset, Post); return;
10044 case 13: load_pair_s32 (cpu, offset, NoWriteBack); return;
10045 case 15: load_pair_s32 (cpu, offset, Pre); return;
10047 case 18: store_pair_u64 (cpu, offset, Post); return;
10048 case 19: load_pair_u64 (cpu, offset, Post); return;
10049 case 20: store_pair_u64 (cpu, offset, NoWriteBack); return;
10050 case 21: load_pair_u64 (cpu, offset, NoWriteBack); return;
10051 case 22: store_pair_u64 (cpu, offset, Pre); return;
10052 case 23: load_pair_u64 (cpu, offset, Pre); return;
10060 store_pair_float (sim_cpu *cpu, int32_t offset, WriteBack wb)
10062 unsigned rn = uimm (aarch64_get_instr (cpu), 14, 10);
10063 unsigned rd = uimm (aarch64_get_instr (cpu), 9, 5);
10064 unsigned rm = uimm (aarch64_get_instr (cpu), 4, 0);
10065 uint64_t address = aarch64_get_reg_u64 (cpu, rd, SP_OK);
10072 aarch64_set_mem_float (cpu, address, aarch64_get_FP_float (cpu, rm));
10073 aarch64_set_mem_float (cpu, address + 4, aarch64_get_FP_float (cpu, rn));
10078 if (wb != NoWriteBack)
10079 aarch64_set_reg_u64 (cpu, rd, SP_OK, address);
10083 store_pair_double (sim_cpu *cpu, int32_t offset, WriteBack wb)
10085 unsigned rn = uimm (aarch64_get_instr (cpu), 14, 10);
10086 unsigned rd = uimm (aarch64_get_instr (cpu), 9, 5);
10087 unsigned rm = uimm (aarch64_get_instr (cpu), 4, 0);
10088 uint64_t address = aarch64_get_reg_u64 (cpu, rd, SP_OK);
10095 aarch64_set_mem_double (cpu, address, aarch64_get_FP_double (cpu, rm));
10096 aarch64_set_mem_double (cpu, address + 8, aarch64_get_FP_double (cpu, rn));
10101 if (wb != NoWriteBack)
10102 aarch64_set_reg_u64 (cpu, rd, SP_OK, address);
10106 store_pair_long_double (sim_cpu *cpu, int32_t offset, WriteBack wb)
10109 unsigned rn = uimm (aarch64_get_instr (cpu), 14, 10);
10110 unsigned rd = uimm (aarch64_get_instr (cpu), 9, 5);
10111 unsigned rm = uimm (aarch64_get_instr (cpu), 4, 0);
10112 uint64_t address = aarch64_get_reg_u64 (cpu, rd, SP_OK);
10119 aarch64_get_FP_long_double (cpu, rm, & a);
10120 aarch64_set_mem_long_double (cpu, address, a);
10121 aarch64_get_FP_long_double (cpu, rn, & a);
10122 aarch64_set_mem_long_double (cpu, address + 16, a);
10127 if (wb != NoWriteBack)
10128 aarch64_set_reg_u64 (cpu, rd, SP_OK, address);
10132 load_pair_float (sim_cpu *cpu, int32_t offset, WriteBack wb)
10134 unsigned rn = uimm (aarch64_get_instr (cpu), 14, 10);
10135 unsigned rd = uimm (aarch64_get_instr (cpu), 9, 5);
10136 unsigned rm = uimm (aarch64_get_instr (cpu), 4, 0);
10137 uint64_t address = aarch64_get_reg_u64 (cpu, rd, SP_OK);
10147 aarch64_set_FP_float (cpu, rm, aarch64_get_mem_float (cpu, address));
10148 aarch64_set_FP_float (cpu, rn, aarch64_get_mem_float (cpu, address + 4));
10153 if (wb != NoWriteBack)
10154 aarch64_set_reg_u64 (cpu, rd, SP_OK, address);
10158 load_pair_double (sim_cpu *cpu, int32_t offset, WriteBack wb)
10160 unsigned rn = uimm (aarch64_get_instr (cpu), 14, 10);
10161 unsigned rd = uimm (aarch64_get_instr (cpu), 9, 5);
10162 unsigned rm = uimm (aarch64_get_instr (cpu), 4, 0);
10163 uint64_t address = aarch64_get_reg_u64 (cpu, rd, SP_OK);
10173 aarch64_set_FP_double (cpu, rm, aarch64_get_mem_double (cpu, address));
10174 aarch64_set_FP_double (cpu, rn, aarch64_get_mem_double (cpu, address + 8));
10179 if (wb != NoWriteBack)
10180 aarch64_set_reg_u64 (cpu, rd, SP_OK, address);
10184 load_pair_long_double (sim_cpu *cpu, int32_t offset, WriteBack wb)
10187 unsigned rn = uimm (aarch64_get_instr (cpu), 14, 10);
10188 unsigned rd = uimm (aarch64_get_instr (cpu), 9, 5);
10189 unsigned rm = uimm (aarch64_get_instr (cpu), 4, 0);
10190 uint64_t address = aarch64_get_reg_u64 (cpu, rd, SP_OK);
10200 aarch64_get_mem_long_double (cpu, address, & a);
10201 aarch64_set_FP_long_double (cpu, rm, a);
10202 aarch64_get_mem_long_double (cpu, address + 16, & a);
10203 aarch64_set_FP_long_double (cpu, rn, a);
10208 if (wb != NoWriteBack)
10209 aarch64_set_reg_u64 (cpu, rd, SP_OK, address);
10213 dex_load_store_pair_fp (sim_cpu *cpu)
10215 /* instr[31,30] = size (10=> 128-bit, 01=> 64-bit, 00=> 32-bit)
10216 instr[29,25] = instruction encoding
10217 instr[24,23] = addressing mode (10=> offset, 01=> post, 11=> pre)
10218 instr[22] = load/store (1=> load)
10219 instr[21,15] = signed, scaled, offset
10222 instr[ 4, 0] = Rm */
10224 uint32_t dispatch = ((uimm (aarch64_get_instr (cpu), 31, 30) << 3)
10225 | uimm (aarch64_get_instr (cpu), 24, 22));
10226 int32_t offset = simm32 (aarch64_get_instr (cpu), 21, 15);
10230 case 2: store_pair_float (cpu, offset, Post); return;
10231 case 3: load_pair_float (cpu, offset, Post); return;
10232 case 4: store_pair_float (cpu, offset, NoWriteBack); return;
10233 case 5: load_pair_float (cpu, offset, NoWriteBack); return;
10234 case 6: store_pair_float (cpu, offset, Pre); return;
10235 case 7: load_pair_float (cpu, offset, Pre); return;
10237 case 10: store_pair_double (cpu, offset, Post); return;
10238 case 11: load_pair_double (cpu, offset, Post); return;
10239 case 12: store_pair_double (cpu, offset, NoWriteBack); return;
10240 case 13: load_pair_double (cpu, offset, NoWriteBack); return;
10241 case 14: store_pair_double (cpu, offset, Pre); return;
10242 case 15: load_pair_double (cpu, offset, Pre); return;
10244 case 18: store_pair_long_double (cpu, offset, Post); return;
10245 case 19: load_pair_long_double (cpu, offset, Post); return;
10246 case 20: store_pair_long_double (cpu, offset, NoWriteBack); return;
10247 case 21: load_pair_long_double (cpu, offset, NoWriteBack); return;
10248 case 22: store_pair_long_double (cpu, offset, Pre); return;
10249 case 23: load_pair_long_double (cpu, offset, Pre); return;
10256 static inline unsigned
10257 vec_reg (unsigned v, unsigned o)
10259 return (v + o) & 0x3F;
10262 /* Load multiple N-element structures to N consecutive registers. */
10264 vec_load (sim_cpu *cpu, uint64_t address, unsigned N)
10266 int all = uimm (aarch64_get_instr (cpu), 30, 30);
10267 unsigned size = uimm (aarch64_get_instr (cpu), 11, 10);
10268 unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
10273 case 0: /* 8-bit operations. */
10275 for (i = 0; i < (16 * N); i++)
10276 aarch64_set_vec_u8 (cpu, vec_reg (vd, i >> 4), i & 15,
10277 aarch64_get_mem_u8 (cpu, address + i));
10279 for (i = 0; i < (8 * N); i++)
10280 aarch64_set_vec_u8 (cpu, vec_reg (vd, i >> 3), i & 7,
10281 aarch64_get_mem_u8 (cpu, address + i));
10284 case 1: /* 16-bit operations. */
10286 for (i = 0; i < (8 * N); i++)
10287 aarch64_set_vec_u16 (cpu, vec_reg (vd, i >> 3), i & 7,
10288 aarch64_get_mem_u16 (cpu, address + i * 2));
10290 for (i = 0; i < (4 * N); i++)
10291 aarch64_set_vec_u16 (cpu, vec_reg (vd, i >> 2), i & 3,
10292 aarch64_get_mem_u16 (cpu, address + i * 2));
10295 case 2: /* 32-bit operations. */
10297 for (i = 0; i < (4 * N); i++)
10298 aarch64_set_vec_u32 (cpu, vec_reg (vd, i >> 2), i & 3,
10299 aarch64_get_mem_u32 (cpu, address + i * 4));
10301 for (i = 0; i < (2 * N); i++)
10302 aarch64_set_vec_u32 (cpu, vec_reg (vd, i >> 1), i & 1,
10303 aarch64_get_mem_u32 (cpu, address + i * 4));
10306 case 3: /* 64-bit operations. */
10308 for (i = 0; i < (2 * N); i++)
10309 aarch64_set_vec_u64 (cpu, vec_reg (vd, i >> 1), i & 1,
10310 aarch64_get_mem_u64 (cpu, address + i * 8));
10312 for (i = 0; i < N; i++)
10313 aarch64_set_vec_u64 (cpu, vec_reg (vd, i), 0,
10314 aarch64_get_mem_u64 (cpu, address + i * 8));
10322 /* LD4: load multiple 4-element to four consecutive registers. */
10324 LD4 (sim_cpu *cpu, uint64_t address)
10326 vec_load (cpu, address, 4);
10329 /* LD3: load multiple 3-element structures to three consecutive registers. */
10331 LD3 (sim_cpu *cpu, uint64_t address)
10333 vec_load (cpu, address, 3);
10336 /* LD2: load multiple 2-element structures to two consecutive registers. */
10338 LD2 (sim_cpu *cpu, uint64_t address)
10340 vec_load (cpu, address, 2);
10343 /* Load multiple 1-element structures into one register. */
10345 LD1_1 (sim_cpu *cpu, uint64_t address)
10347 int all = uimm (aarch64_get_instr (cpu), 30, 30);
10348 unsigned size = uimm (aarch64_get_instr (cpu), 11, 10);
10349 unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
10355 /* LD1 {Vd.16b}, addr, #16 */
10356 /* LD1 {Vd.8b}, addr, #8 */
10357 for (i = 0; i < (all ? 16 : 8); i++)
10358 aarch64_set_vec_u8 (cpu, vd, i,
10359 aarch64_get_mem_u8 (cpu, address + i));
10363 /* LD1 {Vd.8h}, addr, #16 */
10364 /* LD1 {Vd.4h}, addr, #8 */
10365 for (i = 0; i < (all ? 8 : 4); i++)
10366 aarch64_set_vec_u16 (cpu, vd, i,
10367 aarch64_get_mem_u16 (cpu, address + i * 2));
10371 /* LD1 {Vd.4s}, addr, #16 */
10372 /* LD1 {Vd.2s}, addr, #8 */
10373 for (i = 0; i < (all ? 4 : 2); i++)
10374 aarch64_set_vec_u32 (cpu, vd, i,
10375 aarch64_get_mem_u32 (cpu, address + i * 4));
10379 /* LD1 {Vd.2d}, addr, #16 */
10380 /* LD1 {Vd.1d}, addr, #8 */
10381 for (i = 0; i < (all ? 2 : 1); i++)
10382 aarch64_set_vec_u64 (cpu, vd, i,
10383 aarch64_get_mem_u64 (cpu, address + i * 8));
10391 /* Load multiple 1-element structures into two registers. */
10393 LD1_2 (sim_cpu *cpu, uint64_t address)
10395 /* FIXME: This algorithm is *exactly* the same as the LD2 version.
10396 So why have two different instructions ? There must be something
10397 wrong somewhere. */
10398 vec_load (cpu, address, 2);
10401 /* Load multiple 1-element structures into three registers. */
10403 LD1_3 (sim_cpu *cpu, uint64_t address)
10405 /* FIXME: This algorithm is *exactly* the same as the LD3 version.
10406 So why have two different instructions ? There must be something
10407 wrong somewhere. */
10408 vec_load (cpu, address, 3);
10411 /* Load multiple 1-element structures into four registers. */
10413 LD1_4 (sim_cpu *cpu, uint64_t address)
10415 /* FIXME: This algorithm is *exactly* the same as the LD4 version.
10416 So why have two different instructions ? There must be something
10417 wrong somewhere. */
10418 vec_load (cpu, address, 4);
10421 /* Store multiple N-element structures to N consecutive registers. */
10423 vec_store (sim_cpu *cpu, uint64_t address, unsigned N)
10425 int all = uimm (aarch64_get_instr (cpu), 30, 30);
10426 unsigned size = uimm (aarch64_get_instr (cpu), 11, 10);
10427 unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
10432 case 0: /* 8-bit operations. */
10434 for (i = 0; i < (16 * N); i++)
10437 aarch64_get_vec_u8 (cpu, vec_reg (vd, i >> 4), i & 15));
10439 for (i = 0; i < (8 * N); i++)
10442 aarch64_get_vec_u8 (cpu, vec_reg (vd, i >> 3), i & 7));
10445 case 1: /* 16-bit operations. */
10447 for (i = 0; i < (8 * N); i++)
10448 aarch64_set_mem_u16
10449 (cpu, address + i * 2,
10450 aarch64_get_vec_u16 (cpu, vec_reg (vd, i >> 3), i & 7));
10452 for (i = 0; i < (4 * N); i++)
10453 aarch64_set_mem_u16
10454 (cpu, address + i * 2,
10455 aarch64_get_vec_u16 (cpu, vec_reg (vd, i >> 2), i & 3));
10458 case 2: /* 32-bit operations. */
10460 for (i = 0; i < (4 * N); i++)
10461 aarch64_set_mem_u32
10462 (cpu, address + i * 4,
10463 aarch64_get_vec_u32 (cpu, vec_reg (vd, i >> 2), i & 3));
10465 for (i = 0; i < (2 * N); i++)
10466 aarch64_set_mem_u32
10467 (cpu, address + i * 4,
10468 aarch64_get_vec_u32 (cpu, vec_reg (vd, i >> 1), i & 1));
10471 case 3: /* 64-bit operations. */
10473 for (i = 0; i < (2 * N); i++)
10474 aarch64_set_mem_u64
10475 (cpu, address + i * 8,
10476 aarch64_get_vec_u64 (cpu, vec_reg (vd, i >> 1), i & 1));
10478 for (i = 0; i < N; i++)
10479 aarch64_set_mem_u64
10480 (cpu, address + i * 8,
10481 aarch64_get_vec_u64 (cpu, vec_reg (vd, i), 0));
10489 /* Store multiple 4-element structure to four consecutive registers. */
10491 ST4 (sim_cpu *cpu, uint64_t address)
10493 vec_store (cpu, address, 4);
10496 /* Store multiple 3-element structures to three consecutive registers. */
10498 ST3 (sim_cpu *cpu, uint64_t address)
10500 vec_store (cpu, address, 3);
10503 /* Store multiple 2-element structures to two consecutive registers. */
10505 ST2 (sim_cpu *cpu, uint64_t address)
10507 vec_store (cpu, address, 2);
10510 /* Store multiple 1-element structures into one register. */
10512 ST1_1 (sim_cpu *cpu, uint64_t address)
10514 int all = uimm (aarch64_get_instr (cpu), 30, 30);
10515 unsigned size = uimm (aarch64_get_instr (cpu), 11, 10);
10516 unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
10522 for (i = 0; i < (all ? 16 : 8); i++)
10523 aarch64_set_mem_u8 (cpu, address + i,
10524 aarch64_get_vec_u8 (cpu, vd, i));
10528 for (i = 0; i < (all ? 8 : 4); i++)
10529 aarch64_set_mem_u16 (cpu, address + i * 2,
10530 aarch64_get_vec_u16 (cpu, vd, i));
10534 for (i = 0; i < (all ? 4 : 2); i++)
10535 aarch64_set_mem_u32 (cpu, address + i * 4,
10536 aarch64_get_vec_u32 (cpu, vd, i));
10540 for (i = 0; i < (all ? 2 : 1); i++)
10541 aarch64_set_mem_u64 (cpu, address + i * 8,
10542 aarch64_get_vec_u64 (cpu, vd, i));
10550 /* Store multiple 1-element structures into two registers. */
10552 ST1_2 (sim_cpu *cpu, uint64_t address)
10554 /* FIXME: This algorithm is *exactly* the same as the ST2 version.
10555 So why have two different instructions ? There must be
10556 something wrong somewhere. */
10557 vec_store (cpu, address, 2);
10560 /* Store multiple 1-element structures into three registers. */
10562 ST1_3 (sim_cpu *cpu, uint64_t address)
10564 /* FIXME: This algorithm is *exactly* the same as the ST3 version.
10565 So why have two different instructions ? There must be
10566 something wrong somewhere. */
10567 vec_store (cpu, address, 3);
10570 /* Store multiple 1-element structures into four registers. */
10572 ST1_4 (sim_cpu *cpu, uint64_t address)
10574 /* FIXME: This algorithm is *exactly* the same as the ST4 version.
10575 So why have two different instructions ? There must be
10576 something wrong somewhere. */
10577 vec_store (cpu, address, 4);
10581 do_vec_LDnR (sim_cpu *cpu, uint64_t address)
10584 instr[30] = element selector 0=>half, 1=>all elements
10585 instr[29,24] = 00 1101
10586 instr[23] = 0=>simple, 1=>post
10588 instr[21] = width: LD1R-or-LD3R (0) / LD2R-or-LD4R (1)
10589 instr[20,16] = 0 0000 (simple), Vinc (reg-post-inc, no SP),
10590 11111 (immediate post inc)
10592 instr[13] = width: LD1R-or-LD2R (0) / LD3R-or-LD4R (1)
10594 instr[11,10] = element size 00=> byte(b), 01=> half(h),
10595 10=> word(s), 11=> double(d)
10596 instr[9,5] = address
10599 unsigned full = uimm (aarch64_get_instr (cpu), 30, 30);
10600 unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
10601 unsigned size = uimm (aarch64_get_instr (cpu), 11, 10);
10604 NYI_assert (29, 24, 0x0D);
10605 NYI_assert (22, 22, 1);
10606 NYI_assert (15, 14, 3);
10607 NYI_assert (12, 12, 0);
10609 switch ((uimm (aarch64_get_instr (cpu), 13, 13) << 1)
10610 | uimm (aarch64_get_instr (cpu), 21, 21))
10612 case 0: /* LD1R. */
10617 uint8_t val = aarch64_get_mem_u8 (cpu, address);
10618 for (i = 0; i < (full ? 16 : 8); i++)
10619 aarch64_set_vec_u8 (cpu, vd, i, val);
10625 uint16_t val = aarch64_get_mem_u16 (cpu, address);
10626 for (i = 0; i < (full ? 8 : 4); i++)
10627 aarch64_set_vec_u16 (cpu, vd, i, val);
10633 uint32_t val = aarch64_get_mem_u32 (cpu, address);
10634 for (i = 0; i < (full ? 4 : 2); i++)
10635 aarch64_set_vec_u32 (cpu, vd, i, val);
10641 uint64_t val = aarch64_get_mem_u64 (cpu, address);
10642 for (i = 0; i < (full ? 2 : 1); i++)
10643 aarch64_set_vec_u64 (cpu, vd, i, val);
10652 case 1: /* LD2R. */
10657 uint8_t val1 = aarch64_get_mem_u8 (cpu, address);
10658 uint8_t val2 = aarch64_get_mem_u8 (cpu, address + 1);
10660 for (i = 0; i < (full ? 16 : 8); i++)
10662 aarch64_set_vec_u8 (cpu, vd, 0, val1);
10663 aarch64_set_vec_u8 (cpu, vd + 1, 0, val2);
10670 uint16_t val1 = aarch64_get_mem_u16 (cpu, address);
10671 uint16_t val2 = aarch64_get_mem_u16 (cpu, address + 2);
10673 for (i = 0; i < (full ? 8 : 4); i++)
10675 aarch64_set_vec_u16 (cpu, vd, 0, val1);
10676 aarch64_set_vec_u16 (cpu, vd + 1, 0, val2);
10683 uint32_t val1 = aarch64_get_mem_u32 (cpu, address);
10684 uint32_t val2 = aarch64_get_mem_u32 (cpu, address + 4);
10686 for (i = 0; i < (full ? 4 : 2); i++)
10688 aarch64_set_vec_u32 (cpu, vd, 0, val1);
10689 aarch64_set_vec_u32 (cpu, vd + 1, 0, val2);
10696 uint64_t val1 = aarch64_get_mem_u64 (cpu, address);
10697 uint64_t val2 = aarch64_get_mem_u64 (cpu, address + 8);
10699 for (i = 0; i < (full ? 2 : 1); i++)
10701 aarch64_set_vec_u64 (cpu, vd, 0, val1);
10702 aarch64_set_vec_u64 (cpu, vd + 1, 0, val2);
10712 case 2: /* LD3R. */
10717 uint8_t val1 = aarch64_get_mem_u8 (cpu, address);
10718 uint8_t val2 = aarch64_get_mem_u8 (cpu, address + 1);
10719 uint8_t val3 = aarch64_get_mem_u8 (cpu, address + 2);
10721 for (i = 0; i < (full ? 16 : 8); i++)
10723 aarch64_set_vec_u8 (cpu, vd, 0, val1);
10724 aarch64_set_vec_u8 (cpu, vd + 1, 0, val2);
10725 aarch64_set_vec_u8 (cpu, vd + 2, 0, val3);
10732 uint32_t val1 = aarch64_get_mem_u16 (cpu, address);
10733 uint32_t val2 = aarch64_get_mem_u16 (cpu, address + 2);
10734 uint32_t val3 = aarch64_get_mem_u16 (cpu, address + 4);
10736 for (i = 0; i < (full ? 8 : 4); i++)
10738 aarch64_set_vec_u16 (cpu, vd, 0, val1);
10739 aarch64_set_vec_u16 (cpu, vd + 1, 0, val2);
10740 aarch64_set_vec_u16 (cpu, vd + 2, 0, val3);
10747 uint32_t val1 = aarch64_get_mem_u32 (cpu, address);
10748 uint32_t val2 = aarch64_get_mem_u32 (cpu, address + 4);
10749 uint32_t val3 = aarch64_get_mem_u32 (cpu, address + 8);
10751 for (i = 0; i < (full ? 4 : 2); i++)
10753 aarch64_set_vec_u32 (cpu, vd, 0, val1);
10754 aarch64_set_vec_u32 (cpu, vd + 1, 0, val2);
10755 aarch64_set_vec_u32 (cpu, vd + 2, 0, val3);
10762 uint64_t val1 = aarch64_get_mem_u64 (cpu, address);
10763 uint64_t val2 = aarch64_get_mem_u64 (cpu, address + 8);
10764 uint64_t val3 = aarch64_get_mem_u64 (cpu, address + 16);
10766 for (i = 0; i < (full ? 2 : 1); i++)
10768 aarch64_set_vec_u64 (cpu, vd, 0, val1);
10769 aarch64_set_vec_u64 (cpu, vd + 1, 0, val2);
10770 aarch64_set_vec_u64 (cpu, vd + 2, 0, val3);
10780 case 3: /* LD4R. */
10785 uint8_t val1 = aarch64_get_mem_u8 (cpu, address);
10786 uint8_t val2 = aarch64_get_mem_u8 (cpu, address + 1);
10787 uint8_t val3 = aarch64_get_mem_u8 (cpu, address + 2);
10788 uint8_t val4 = aarch64_get_mem_u8 (cpu, address + 3);
10790 for (i = 0; i < (full ? 16 : 8); i++)
10792 aarch64_set_vec_u8 (cpu, vd, 0, val1);
10793 aarch64_set_vec_u8 (cpu, vd + 1, 0, val2);
10794 aarch64_set_vec_u8 (cpu, vd + 2, 0, val3);
10795 aarch64_set_vec_u8 (cpu, vd + 3, 0, val4);
10802 uint32_t val1 = aarch64_get_mem_u16 (cpu, address);
10803 uint32_t val2 = aarch64_get_mem_u16 (cpu, address + 2);
10804 uint32_t val3 = aarch64_get_mem_u16 (cpu, address + 4);
10805 uint32_t val4 = aarch64_get_mem_u16 (cpu, address + 6);
10807 for (i = 0; i < (full ? 8 : 4); i++)
10809 aarch64_set_vec_u16 (cpu, vd, 0, val1);
10810 aarch64_set_vec_u16 (cpu, vd + 1, 0, val2);
10811 aarch64_set_vec_u16 (cpu, vd + 2, 0, val3);
10812 aarch64_set_vec_u16 (cpu, vd + 3, 0, val4);
10819 uint32_t val1 = aarch64_get_mem_u32 (cpu, address);
10820 uint32_t val2 = aarch64_get_mem_u32 (cpu, address + 4);
10821 uint32_t val3 = aarch64_get_mem_u32 (cpu, address + 8);
10822 uint32_t val4 = aarch64_get_mem_u32 (cpu, address + 12);
10824 for (i = 0; i < (full ? 4 : 2); i++)
10826 aarch64_set_vec_u32 (cpu, vd, 0, val1);
10827 aarch64_set_vec_u32 (cpu, vd + 1, 0, val2);
10828 aarch64_set_vec_u32 (cpu, vd + 2, 0, val3);
10829 aarch64_set_vec_u32 (cpu, vd + 3, 0, val4);
10836 uint64_t val1 = aarch64_get_mem_u64 (cpu, address);
10837 uint64_t val2 = aarch64_get_mem_u64 (cpu, address + 8);
10838 uint64_t val3 = aarch64_get_mem_u64 (cpu, address + 16);
10839 uint64_t val4 = aarch64_get_mem_u64 (cpu, address + 24);
10841 for (i = 0; i < (full ? 2 : 1); i++)
10843 aarch64_set_vec_u64 (cpu, vd, 0, val1);
10844 aarch64_set_vec_u64 (cpu, vd + 1, 0, val2);
10845 aarch64_set_vec_u64 (cpu, vd + 2, 0, val3);
10846 aarch64_set_vec_u64 (cpu, vd + 3, 0, val4);
10862 do_vec_load_store (sim_cpu *cpu)
10864 /* {LD|ST}<N> {Vd..Vd+N}, vaddr
10867 instr[30] = element selector 0=>half, 1=>all elements
10868 instr[29,25] = 00110
10870 instr[23] = 0=>simple, 1=>post
10871 instr[22] = 0=>store, 1=>load
10872 instr[21] = 0 (LDn) / small(0)-large(1) selector (LDnR)
10873 instr[20,16] = 00000 (simple), Vinc (reg-post-inc, no SP),
10874 11111 (immediate post inc)
10875 instr[15,12] = elements and destinations. eg for load:
10876 0000=>LD4 => load multiple 4-element to
10877 four consecutive registers
10878 0100=>LD3 => load multiple 3-element to
10879 three consecutive registers
10880 1000=>LD2 => load multiple 2-element to
10881 two consecutive registers
10882 0010=>LD1 => load multiple 1-element to
10883 four consecutive registers
10884 0110=>LD1 => load multiple 1-element to
10885 three consecutive registers
10886 1010=>LD1 => load multiple 1-element to
10887 two consecutive registers
10888 0111=>LD1 => load multiple 1-element to
10892 instr[11,10] = element size 00=> byte(b), 01=> half(h),
10893 10=> word(s), 11=> double(d)
10894 instr[9,5] = Vn, can be SP
10903 if (uimm (aarch64_get_instr (cpu), 31, 31) != 0
10904 || uimm (aarch64_get_instr (cpu), 29, 25) != 0x06)
10907 type = uimm (aarch64_get_instr (cpu), 15, 12);
10908 if (type != 0xE && type != 0xE && uimm (aarch64_get_instr (cpu), 21, 21) != 0)
10911 post = uimm (aarch64_get_instr (cpu), 23, 23);
10912 load = uimm (aarch64_get_instr (cpu), 22, 22);
10913 vn = uimm (aarch64_get_instr (cpu), 9, 5);
10914 address = aarch64_get_reg_u64 (cpu, vn, SP_OK);
10918 unsigned vm = uimm (aarch64_get_instr (cpu), 20, 16);
10922 unsigned sizeof_operation;
10926 case 0: sizeof_operation = 32; break;
10927 case 4: sizeof_operation = 24; break;
10928 case 8: sizeof_operation = 16; break;
10931 sizeof_operation = uimm (aarch64_get_instr (cpu), 21, 21) ? 2 : 1;
10932 sizeof_operation <<= uimm (aarch64_get_instr (cpu), 11, 10);
10936 sizeof_operation = uimm (aarch64_get_instr (cpu), 21, 21) ? 8 : 4;
10937 sizeof_operation <<= uimm (aarch64_get_instr (cpu), 11, 10);
10944 sizeof_operation = 2 << uimm (aarch64_get_instr (cpu), 11, 10);
10951 if (uimm (aarch64_get_instr (cpu), 30, 30))
10952 sizeof_operation *= 2;
10954 aarch64_set_reg_u64 (cpu, vn, SP_OK, address + sizeof_operation);
10957 aarch64_set_reg_u64 (cpu, vn, SP_OK,
10958 address + aarch64_get_reg_u64 (cpu, vm, NO_SP));
10962 NYI_assert (20, 16, 0);
10969 case 0: LD4 (cpu, address); return;
10970 case 4: LD3 (cpu, address); return;
10971 case 8: LD2 (cpu, address); return;
10972 case 2: LD1_4 (cpu, address); return;
10973 case 6: LD1_3 (cpu, address); return;
10974 case 10: LD1_2 (cpu, address); return;
10975 case 7: LD1_1 (cpu, address); return;
10978 case 0xC: do_vec_LDnR (cpu, address); return;
10988 case 0: ST4 (cpu, address); return;
10989 case 4: ST3 (cpu, address); return;
10990 case 8: ST2 (cpu, address); return;
10991 case 2: ST1_4 (cpu, address); return;
10992 case 6: ST1_3 (cpu, address); return;
10993 case 10: ST1_2 (cpu, address); return;
10994 case 7: ST1_1 (cpu, address); return;
11001 dexLdSt (sim_cpu *cpu)
11003 /* uint32_t group = dispatchGroup (aarch64_get_instr (cpu));
11004 assert group == GROUP_LDST_0100 || group == GROUP_LDST_0110 ||
11005 group == GROUP_LDST_1100 || group == GROUP_LDST_1110
11006 bits [29,28:26] of a LS are the secondary dispatch vector. */
11007 uint32_t group2 = dispatchLS (aarch64_get_instr (cpu));
11012 dexLoadExclusive (cpu); return;
11016 dexLoadLiteral (cpu); return;
11020 dexLoadOther (cpu); return;
11022 case LS_ADVSIMD_001:
11023 do_vec_load_store (cpu); return;
11026 dex_load_store_pair_gr (cpu); return;
11029 dex_load_store_pair_fp (cpu); return;
11032 /* Should never reach here. */
11037 /* Specific decode and execute for group Data Processing Register. */
11040 dexLogicalShiftedRegister (sim_cpu *cpu)
11042 /* assert instr[28:24] = 01010
11043 instr[31] = size : 0 ==> 32 bit, 1 ==> 64 bit
11044 instr[30,29:21] = op,N : 000 ==> AND, 001 ==> BIC,
11045 010 ==> ORR, 011 ==> ORN
11046 100 ==> EOR, 101 ==> EON,
11047 110 ==> ANDS, 111 ==> BICS
11048 instr[23,22] = shift : 0 ==> LSL, 1 ==> LSR, 2 ==> ASR, 3 ==> ROR
11049 instr[15,10] = count : must be 0xxxxx for 32 bit
11053 /* unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16); */
11056 uint32_t size = uimm (aarch64_get_instr (cpu), 31, 31);
11058 /* 32 bit operations must have count[5] = 0. */
11059 /* or else we have an UNALLOC. */
11060 uint32_t count = uimm (aarch64_get_instr (cpu), 15, 10);
11062 if (!size && uimm (count, 5, 5))
11065 shiftType = shift (aarch64_get_instr (cpu), 22);
11067 /* dispatch on size:op:N i.e aarch64_get_instr (cpu)[31,29:21]. */
11068 dispatch = ( (uimm (aarch64_get_instr (cpu), 31, 29) << 1)
11069 | uimm (aarch64_get_instr (cpu), 21, 21));
11073 case 0: and32_shift (cpu, shiftType, count); return;
11074 case 1: bic32_shift (cpu, shiftType, count); return;
11075 case 2: orr32_shift (cpu, shiftType, count); return;
11076 case 3: orn32_shift (cpu, shiftType, count); return;
11077 case 4: eor32_shift (cpu, shiftType, count); return;
11078 case 5: eon32_shift (cpu, shiftType, count); return;
11079 case 6: ands32_shift (cpu, shiftType, count); return;
11080 case 7: bics32_shift (cpu, shiftType, count); return;
11081 case 8: and64_shift (cpu, shiftType, count); return;
11082 case 9: bic64_shift (cpu, shiftType, count); return;
11083 case 10:orr64_shift (cpu, shiftType, count); return;
11084 case 11:orn64_shift (cpu, shiftType, count); return;
11085 case 12:eor64_shift (cpu, shiftType, count); return;
11086 case 13:eon64_shift (cpu, shiftType, count); return;
11087 case 14:ands64_shift (cpu, shiftType, count); return;
11088 case 15:bics64_shift (cpu, shiftType, count); return;
11089 default: HALT_UNALLOC;
11093 /* 32 bit conditional select. */
11095 csel32 (sim_cpu *cpu, CondCode cc)
11097 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
11098 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
11099 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
11101 aarch64_set_reg_u64 (cpu, rd, NO_SP,
11102 testConditionCode (cpu, cc)
11103 ? aarch64_get_reg_u32 (cpu, rn, NO_SP)
11104 : aarch64_get_reg_u32 (cpu, rm, NO_SP));
11107 /* 64 bit conditional select. */
11109 csel64 (sim_cpu *cpu, CondCode cc)
11111 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
11112 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
11113 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
11115 aarch64_set_reg_u64 (cpu, rd, NO_SP,
11116 testConditionCode (cpu, cc)
11117 ? aarch64_get_reg_u64 (cpu, rn, NO_SP)
11118 : aarch64_get_reg_u64 (cpu, rm, NO_SP));
11121 /* 32 bit conditional increment. */
11123 csinc32 (sim_cpu *cpu, CondCode cc)
11125 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
11126 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
11127 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
11129 aarch64_set_reg_u64 (cpu, rd, NO_SP,
11130 testConditionCode (cpu, cc)
11131 ? aarch64_get_reg_u32 (cpu, rn, NO_SP)
11132 : aarch64_get_reg_u32 (cpu, rm, NO_SP) + 1);
11135 /* 64 bit conditional increment. */
11137 csinc64 (sim_cpu *cpu, CondCode cc)
11139 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
11140 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
11141 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
11143 aarch64_set_reg_u64 (cpu, rd, NO_SP,
11144 testConditionCode (cpu, cc)
11145 ? aarch64_get_reg_u64 (cpu, rn, NO_SP)
11146 : aarch64_get_reg_u64 (cpu, rm, NO_SP) + 1);
11149 /* 32 bit conditional invert. */
11151 csinv32 (sim_cpu *cpu, CondCode cc)
11153 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
11154 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
11155 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
11157 aarch64_set_reg_u64 (cpu, rd, NO_SP,
11158 testConditionCode (cpu, cc)
11159 ? aarch64_get_reg_u32 (cpu, rn, NO_SP)
11160 : ~ aarch64_get_reg_u32 (cpu, rm, NO_SP));
11163 /* 64 bit conditional invert. */
11165 csinv64 (sim_cpu *cpu, CondCode cc)
11167 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
11168 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
11169 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
11171 aarch64_set_reg_u64 (cpu, rd, NO_SP,
11172 testConditionCode (cpu, cc)
11173 ? aarch64_get_reg_u64 (cpu, rn, NO_SP)
11174 : ~ aarch64_get_reg_u64 (cpu, rm, NO_SP));
11177 /* 32 bit conditional negate. */
11179 csneg32 (sim_cpu *cpu, CondCode cc)
11181 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
11182 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
11183 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
11185 aarch64_set_reg_u64 (cpu, rd, NO_SP,
11186 testConditionCode (cpu, cc)
11187 ? aarch64_get_reg_u32 (cpu, rn, NO_SP)
11188 : - aarch64_get_reg_u32 (cpu, rm, NO_SP));
11191 /* 64 bit conditional negate. */
11193 csneg64 (sim_cpu *cpu, CondCode cc)
11195 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
11196 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
11197 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
11199 aarch64_set_reg_u64 (cpu, rd, NO_SP,
11200 testConditionCode (cpu, cc)
11201 ? aarch64_get_reg_u64 (cpu, rn, NO_SP)
11202 : - aarch64_get_reg_u64 (cpu, rm, NO_SP));
11206 dexCondSelect (sim_cpu *cpu)
11208 /* assert instr[28,21] = 11011011
11209 instr[31] = size : 0 ==> 32 bit, 1 ==> 64 bit
11210 instr[30:11,10] = op : 000 ==> CSEL, 001 ==> CSINC,
11211 100 ==> CSINV, 101 ==> CSNEG,
11213 instr[29] = S : 0 ==> ok, 1 ==> UNALLOC
11214 instr[15,12] = cond
11215 instr[29] = S : 0 ==> ok, 1 ==> UNALLOC */
11219 uint32_t S = uimm (aarch64_get_instr (cpu), 29, 29);
11220 uint32_t op2 = uimm (aarch64_get_instr (cpu), 11, 10);
11228 cc = condcode (aarch64_get_instr (cpu), 12);
11229 dispatch = ((uimm (aarch64_get_instr (cpu), 31, 30) << 1) | op2);
11233 case 0: csel32 (cpu, cc); return;
11234 case 1: csinc32 (cpu, cc); return;
11235 case 2: csinv32 (cpu, cc); return;
11236 case 3: csneg32 (cpu, cc); return;
11237 case 4: csel64 (cpu, cc); return;
11238 case 5: csinc64 (cpu, cc); return;
11239 case 6: csinv64 (cpu, cc); return;
11240 case 7: csneg64 (cpu, cc); return;
11241 default: HALT_UNALLOC;
11245 /* Some helpers for counting leading 1 or 0 bits. */
11247 /* Counts the number of leading bits which are the same
11248 in a 32 bit value in the range 1 to 32. */
11250 leading32 (uint32_t value)
11252 int32_t mask= 0xffff0000;
11253 uint32_t count= 16; /* Counts number of bits set in mask. */
11254 uint32_t lo = 1; /* Lower bound for number of sign bits. */
11255 uint32_t hi = 32; /* Upper bound for number of sign bits. */
11257 while (lo + 1 < hi)
11259 int32_t test = (value & mask);
11261 if (test == 0 || test == mask)
11264 count = (lo + hi) / 2;
11265 mask >>= (count - lo);
11270 count = (lo + hi) / 2;
11271 mask <<= hi - count;
11280 test = (value & mask);
11282 if (test == 0 || test == mask)
11291 /* Counts the number of leading bits which are the same
11292 in a 64 bit value in the range 1 to 64. */
11294 leading64 (uint64_t value)
11296 int64_t mask= 0xffffffff00000000LL;
11297 uint64_t count = 32; /* Counts number of bits set in mask. */
11298 uint64_t lo = 1; /* Lower bound for number of sign bits. */
11299 uint64_t hi = 64; /* Upper bound for number of sign bits. */
11301 while (lo + 1 < hi)
11303 int64_t test = (value & mask);
11305 if (test == 0 || test == mask)
11308 count = (lo + hi) / 2;
11309 mask >>= (count - lo);
11314 count = (lo + hi) / 2;
11315 mask <<= hi - count;
11324 test = (value & mask);
11326 if (test == 0 || test == mask)
11335 /* Bit operations. */
11336 /* N.B register args may not be SP. */
11338 /* 32 bit count leading sign bits. */
11340 cls32 (sim_cpu *cpu)
11342 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
11343 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
11345 /* N.B. the result needs to exclude the leading bit. */
11346 aarch64_set_reg_u64
11347 (cpu, rd, NO_SP, leading32 (aarch64_get_reg_u32 (cpu, rn, NO_SP)) - 1);
11350 /* 64 bit count leading sign bits. */
11352 cls64 (sim_cpu *cpu)
11354 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
11355 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
11357 /* N.B. the result needs to exclude the leading bit. */
11358 aarch64_set_reg_u64
11359 (cpu, rd, NO_SP, leading64 (aarch64_get_reg_u64 (cpu, rn, NO_SP)) - 1);
11362 /* 32 bit count leading zero bits. */
11364 clz32 (sim_cpu *cpu)
11366 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
11367 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
11368 uint32_t value = aarch64_get_reg_u32 (cpu, rn, NO_SP);
11370 /* if the sign (top) bit is set then the count is 0. */
11371 if (pick32 (value, 31, 31))
11372 aarch64_set_reg_u64 (cpu, rd, NO_SP, 0L);
11374 aarch64_set_reg_u64 (cpu, rd, NO_SP, leading32 (value));
11377 /* 64 bit count leading zero bits. */
11379 clz64 (sim_cpu *cpu)
11381 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
11382 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
11383 uint64_t value = aarch64_get_reg_u64 (cpu, rn, NO_SP);
11385 /* if the sign (top) bit is set then the count is 0. */
11386 if (pick64 (value, 63, 63))
11387 aarch64_set_reg_u64 (cpu, rd, NO_SP, 0L);
11389 aarch64_set_reg_u64 (cpu, rd, NO_SP, leading64 (value));
11392 /* 32 bit reverse bits. */
11394 rbit32 (sim_cpu *cpu)
11396 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
11397 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
11398 uint32_t value = aarch64_get_reg_u32 (cpu, rn, NO_SP);
11399 uint32_t result = 0;
11402 for (i = 0; i < 32; i++)
11405 result |= (value & 1);
11408 aarch64_set_reg_u64 (cpu, rd, NO_SP, result);
11411 /* 64 bit reverse bits. */
11413 rbit64 (sim_cpu *cpu)
11415 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
11416 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
11417 uint64_t value = aarch64_get_reg_u64 (cpu, rn, NO_SP);
11418 uint64_t result = 0;
11421 for (i = 0; i < 64; i++)
11424 result |= (value & 1L);
11427 aarch64_set_reg_u64 (cpu, rd, NO_SP, result);
11430 /* 32 bit reverse bytes. */
11432 rev32 (sim_cpu *cpu)
11434 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
11435 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
11436 uint32_t value = aarch64_get_reg_u32 (cpu, rn, NO_SP);
11437 uint32_t result = 0;
11440 for (i = 0; i < 4; i++)
11443 result |= (value & 0xff);
11446 aarch64_set_reg_u64 (cpu, rd, NO_SP, result);
11449 /* 64 bit reverse bytes. */
11451 rev64 (sim_cpu *cpu)
11453 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
11454 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
11455 uint64_t value = aarch64_get_reg_u64 (cpu, rn, NO_SP);
11456 uint64_t result = 0;
11459 for (i = 0; i < 8; i++)
11462 result |= (value & 0xffULL);
11465 aarch64_set_reg_u64 (cpu, rd, NO_SP, result);
11468 /* 32 bit reverse shorts. */
11469 /* N.B.this reverses the order of the bytes in each half word. */
11471 revh32 (sim_cpu *cpu)
11473 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
11474 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
11475 uint32_t value = aarch64_get_reg_u32 (cpu, rn, NO_SP);
11476 uint32_t result = 0;
11479 for (i = 0; i < 2; i++)
11482 result |= (value & 0x00ff00ff);
11485 aarch64_set_reg_u64 (cpu, rd, NO_SP, result);
11488 /* 64 bit reverse shorts. */
11489 /* N.B.this reverses the order of the bytes in each half word. */
11491 revh64 (sim_cpu *cpu)
11493 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
11494 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
11495 uint64_t value = aarch64_get_reg_u64 (cpu, rn, NO_SP);
11496 uint64_t result = 0;
11499 for (i = 0; i < 2; i++)
11502 result |= (value & 0x00ff00ff00ff00ffULL);
11505 aarch64_set_reg_u64 (cpu, rd, NO_SP, result);
11509 dexDataProc1Source (sim_cpu *cpu)
11511 /* assert instr[30] == 1
11512 aarch64_get_instr (cpu)[28,21] == 111010110
11513 instr[31] = size : 0 ==> 32 bit, 1 ==> 64 bit
11514 instr[29] = S : 0 ==> ok, 1 ==> UNALLOC
11515 instr[20,16] = opcode2 : 00000 ==> ok, ow ==> UNALLOC
11516 instr[15,10] = opcode : 000000 ==> RBIT, 000001 ==> REV16,
11517 000010 ==> REV, 000011 ==> UNALLOC
11518 000100 ==> CLZ, 000101 ==> CLS
11520 instr[9,5] = rn : may not be SP
11521 instr[4,0] = rd : may not be SP. */
11523 uint32_t S = uimm (aarch64_get_instr (cpu), 29, 29);
11524 uint32_t opcode2 = uimm (aarch64_get_instr (cpu), 20, 16);
11525 uint32_t opcode = uimm (aarch64_get_instr (cpu), 15, 10);
11526 uint32_t dispatch = ((uimm (aarch64_get_instr (cpu), 31, 31) << 3) | opcode);
11539 case 0: rbit32 (cpu); return;
11540 case 1: revh32 (cpu); return;
11541 case 2: rev32 (cpu); return;
11542 case 4: clz32 (cpu); return;
11543 case 5: cls32 (cpu); return;
11544 case 8: rbit64 (cpu); return;
11545 case 9: revh64 (cpu); return;
11546 case 10:rev32 (cpu); return;
11547 case 11:rev64 (cpu); return;
11548 case 12:clz64 (cpu); return;
11549 case 13:cls64 (cpu); return;
11550 default: HALT_UNALLOC;
11555 Shifts by count supplied in register.
11556 N.B register args may not be SP.
11557 These all use the shifted auxiliary function for
11558 simplicity and clarity. Writing the actual shift
11559 inline would avoid a branch and so be faster but
11560 would also necessitate getting signs right. */
11562 /* 32 bit arithmetic shift right. */
11564 asrv32 (sim_cpu *cpu)
11566 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
11567 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
11568 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
11570 aarch64_set_reg_u64
11572 shifted32 (aarch64_get_reg_u32 (cpu, rn, NO_SP), ASR,
11573 (aarch64_get_reg_u32 (cpu, rm, NO_SP) & 0x1f)));
11576 /* 64 bit arithmetic shift right. */
11578 asrv64 (sim_cpu *cpu)
11580 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
11581 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
11582 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
11584 aarch64_set_reg_u64
11586 shifted64 (aarch64_get_reg_u64 (cpu, rn, NO_SP), ASR,
11587 (aarch64_get_reg_u64 (cpu, rm, NO_SP) & 0x3f)));
11590 /* 32 bit logical shift left. */
11592 lslv32 (sim_cpu *cpu)
11594 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
11595 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
11596 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
11598 aarch64_set_reg_u64
11600 shifted32 (aarch64_get_reg_u32 (cpu, rn, NO_SP), LSL,
11601 (aarch64_get_reg_u32 (cpu, rm, NO_SP) & 0x1f)));
11604 /* 64 bit arithmetic shift left. */
11606 lslv64 (sim_cpu *cpu)
11608 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
11609 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
11610 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
11612 aarch64_set_reg_u64
11614 shifted64 (aarch64_get_reg_u64 (cpu, rn, NO_SP), LSL,
11615 (aarch64_get_reg_u64 (cpu, rm, NO_SP) & 0x3f)));
11618 /* 32 bit logical shift right. */
11620 lsrv32 (sim_cpu *cpu)
11622 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
11623 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
11624 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
11626 aarch64_set_reg_u64
11628 shifted32 (aarch64_get_reg_u32 (cpu, rn, NO_SP), LSR,
11629 (aarch64_get_reg_u32 (cpu, rm, NO_SP) & 0x1f)));
11632 /* 64 bit logical shift right. */
11634 lsrv64 (sim_cpu *cpu)
11636 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
11637 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
11638 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
11640 aarch64_set_reg_u64
11642 shifted64 (aarch64_get_reg_u64 (cpu, rn, NO_SP), LSR,
11643 (aarch64_get_reg_u64 (cpu, rm, NO_SP) & 0x3f)));
11646 /* 32 bit rotate right. */
11648 rorv32 (sim_cpu *cpu)
11650 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
11651 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
11652 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
11654 aarch64_set_reg_u64
11656 shifted32 (aarch64_get_reg_u32 (cpu, rn, NO_SP), ROR,
11657 (aarch64_get_reg_u32 (cpu, rm, NO_SP) & 0x1f)));
11660 /* 64 bit rotate right. */
11662 rorv64 (sim_cpu *cpu)
11664 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
11665 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
11666 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
11668 aarch64_set_reg_u64
11670 shifted64 (aarch64_get_reg_u64 (cpu, rn, NO_SP), ROR,
11671 (aarch64_get_reg_u64 (cpu, rm, NO_SP) & 0x3f)));
11677 /* 32 bit signed divide. */
11679 cpuiv32 (sim_cpu *cpu)
11681 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
11682 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
11683 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
11684 /* N.B. the pseudo-code does the divide using 64 bit data. */
11685 /* TODO : check that this rounds towards zero as required. */
11686 int64_t dividend = aarch64_get_reg_s32 (cpu, rn, NO_SP);
11687 int64_t divisor = aarch64_get_reg_s32 (cpu, rm, NO_SP);
11689 aarch64_set_reg_s64 (cpu, rd, NO_SP,
11690 divisor ? ((int32_t) (dividend / divisor)) : 0);
11693 /* 64 bit signed divide. */
11695 cpuiv64 (sim_cpu *cpu)
11697 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
11698 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
11699 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
11701 /* TODO : check that this rounds towards zero as required. */
11702 int64_t divisor = aarch64_get_reg_s64 (cpu, rm, NO_SP);
11704 aarch64_set_reg_s64
11706 divisor ? (aarch64_get_reg_s64 (cpu, rn, NO_SP) / divisor) : 0);
11709 /* 32 bit unsigned divide. */
11711 udiv32 (sim_cpu *cpu)
11713 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
11714 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
11715 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
11717 /* N.B. the pseudo-code does the divide using 64 bit data. */
11718 uint64_t dividend = aarch64_get_reg_u32 (cpu, rn, NO_SP);
11719 uint64_t divisor = aarch64_get_reg_u32 (cpu, rm, NO_SP);
11721 aarch64_set_reg_u64 (cpu, rd, NO_SP,
11722 divisor ? (uint32_t) (dividend / divisor) : 0);
11725 /* 64 bit unsigned divide. */
11727 udiv64 (sim_cpu *cpu)
11729 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
11730 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
11731 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
11733 /* TODO : check that this rounds towards zero as required. */
11734 uint64_t divisor = aarch64_get_reg_u64 (cpu, rm, NO_SP);
11736 aarch64_set_reg_u64
11738 divisor ? (aarch64_get_reg_u64 (cpu, rn, NO_SP) / divisor) : 0);
11742 dexDataProc2Source (sim_cpu *cpu)
11744 /* assert instr[30] == 0
11745 instr[28,21] == 11010110
11746 instr[31] = size : 0 ==> 32 bit, 1 ==> 64 bit
11747 instr[29] = S : 0 ==> ok, 1 ==> UNALLOC
11748 instr[15,10] = opcode : 000010 ==> UDIV, 000011 ==> CPUIV,
11749 001000 ==> LSLV, 001001 ==> LSRV
11750 001010 ==> ASRV, 001011 ==> RORV
11754 uint32_t S = uimm (aarch64_get_instr (cpu), 29, 29);
11755 uint32_t opcode = uimm (aarch64_get_instr (cpu), 15, 10);
11763 dispatch = ( (uimm (aarch64_get_instr (cpu), 31, 31) << 3)
11764 | (uimm (opcode, 3, 3) << 2)
11765 | uimm (opcode, 1, 0));
11768 case 2: udiv32 (cpu); return;
11769 case 3: cpuiv32 (cpu); return;
11770 case 4: lslv32 (cpu); return;
11771 case 5: lsrv32 (cpu); return;
11772 case 6: asrv32 (cpu); return;
11773 case 7: rorv32 (cpu); return;
11774 case 10: udiv64 (cpu); return;
11775 case 11: cpuiv64 (cpu); return;
11776 case 12: lslv64 (cpu); return;
11777 case 13: lsrv64 (cpu); return;
11778 case 14: asrv64 (cpu); return;
11779 case 15: rorv64 (cpu); return;
11780 default: HALT_UNALLOC;
11787 /* 32 bit multiply and add. */
11789 madd32 (sim_cpu *cpu)
11791 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
11792 unsigned ra = uimm (aarch64_get_instr (cpu), 14, 10);
11793 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
11794 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
11796 aarch64_set_reg_u64 (cpu, rd, NO_SP,
11797 aarch64_get_reg_u32 (cpu, ra, NO_SP)
11798 + aarch64_get_reg_u32 (cpu, rn, NO_SP)
11799 * aarch64_get_reg_u32 (cpu, rm, NO_SP));
11802 /* 64 bit multiply and add. */
11804 madd64 (sim_cpu *cpu)
11806 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
11807 unsigned ra = uimm (aarch64_get_instr (cpu), 14, 10);
11808 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
11809 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
11811 aarch64_set_reg_u64 (cpu, rd, NO_SP,
11812 aarch64_get_reg_u64 (cpu, ra, NO_SP)
11813 + aarch64_get_reg_u64 (cpu, rn, NO_SP)
11814 * aarch64_get_reg_u64 (cpu, rm, NO_SP));
11817 /* 32 bit multiply and sub. */
11819 msub32 (sim_cpu *cpu)
11821 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
11822 unsigned ra = uimm (aarch64_get_instr (cpu), 14, 10);
11823 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
11824 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
11826 aarch64_set_reg_u64 (cpu, rd, NO_SP,
11827 aarch64_get_reg_u32 (cpu, ra, NO_SP)
11828 - aarch64_get_reg_u32 (cpu, rn, NO_SP)
11829 * aarch64_get_reg_u32 (cpu, rm, NO_SP));
11832 /* 64 bit multiply and sub. */
11834 msub64 (sim_cpu *cpu)
11836 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
11837 unsigned ra = uimm (aarch64_get_instr (cpu), 14, 10);
11838 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
11839 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
11841 aarch64_set_reg_u64 (cpu, rd, NO_SP,
11842 aarch64_get_reg_u64 (cpu, ra, NO_SP)
11843 - aarch64_get_reg_u64 (cpu, rn, NO_SP)
11844 * aarch64_get_reg_u64 (cpu, rm, NO_SP));
11847 /* Signed multiply add long -- source, source2 : 32 bit, source3 : 64 bit. */
11849 smaddl (sim_cpu *cpu)
11851 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
11852 unsigned ra = uimm (aarch64_get_instr (cpu), 14, 10);
11853 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
11854 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
11856 /* N.B. we need to multiply the signed 32 bit values in rn, rm to
11857 obtain a 64 bit product. */
11858 aarch64_set_reg_s64
11860 aarch64_get_reg_s64 (cpu, ra, NO_SP)
11861 + ((int64_t) aarch64_get_reg_s32 (cpu, rn, NO_SP))
11862 * ((int64_t) aarch64_get_reg_s32 (cpu, rm, NO_SP)));
11865 /* Signed multiply sub long -- source, source2 : 32 bit, source3 : 64 bit. */
11867 smsubl (sim_cpu *cpu)
11869 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
11870 unsigned ra = uimm (aarch64_get_instr (cpu), 14, 10);
11871 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
11872 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
11874 /* N.B. we need to multiply the signed 32 bit values in rn, rm to
11875 obtain a 64 bit product. */
11876 aarch64_set_reg_s64
11878 aarch64_get_reg_s64 (cpu, ra, NO_SP)
11879 - ((int64_t) aarch64_get_reg_s32 (cpu, rn, NO_SP))
11880 * ((int64_t) aarch64_get_reg_s32 (cpu, rm, NO_SP)));
11883 /* Integer Multiply/Divide. */
11885 /* First some macros and a helper function. */
11886 /* Macros to test or access elements of 64 bit words. */
11888 /* Mask used to access lo 32 bits of 64 bit unsigned int. */
11889 #define LOW_WORD_MASK ((1ULL << 32) - 1)
11890 /* Return the lo 32 bit word of a 64 bit unsigned int as a 64 bit unsigned int. */
11891 #define lowWordToU64(_value_u64) ((_value_u64) & LOW_WORD_MASK)
11892 /* Return the hi 32 bit word of a 64 bit unsigned int as a 64 bit unsigned int. */
11893 #define highWordToU64(_value_u64) ((_value_u64) >> 32)
11895 /* Offset of sign bit in 64 bit signed integger. */
11896 #define SIGN_SHIFT_U64 63
11897 /* The sign bit itself -- also identifies the minimum negative int value. */
11898 #define SIGN_BIT_U64 (1UL << SIGN_SHIFT_U64)
11899 /* Return true if a 64 bit signed int presented as an unsigned int is the
11900 most negative value. */
11901 #define isMinimumU64(_value_u64) ((_value_u64) == SIGN_BIT_U64)
11902 /* Return true (non-zero) if a 64 bit signed int presented as an unsigned
11903 int has its sign bit set to false. */
11904 #define isSignSetU64(_value_u64) ((_value_u64) & SIGN_BIT_U64)
11905 /* Return 1L or -1L according to whether a 64 bit signed int presented as
11906 an unsigned int has its sign bit set or not. */
11907 #define signOfU64(_value_u64) (1L + (((value_u64) >> SIGN_SHIFT_U64) * -2L)
11908 /* Clear the sign bit of a 64 bit signed int presented as an unsigned int. */
11909 #define clearSignU64(_value_u64) ((_value_u64) &= ~SIGN_BIT_U64)
11911 /* Multiply two 64 bit ints and return.
11912 the hi 64 bits of the 128 bit product. */
11915 mul64hi (uint64_t value1, uint64_t value2)
11917 uint64_t resultmid1;
11919 uint64_t value1_lo = lowWordToU64 (value1);
11920 uint64_t value1_hi = highWordToU64 (value1) ;
11921 uint64_t value2_lo = lowWordToU64 (value2);
11922 uint64_t value2_hi = highWordToU64 (value2);
11924 /* Cross-multiply and collect results. */
11926 uint64_t xproductlo = value1_lo * value2_lo;
11927 uint64_t xproductmid1 = value1_lo * value2_hi;
11928 uint64_t xproductmid2 = value1_hi * value2_lo;
11929 uint64_t xproducthi = value1_hi * value2_hi;
11930 uint64_t carry = 0;
11931 /* Start accumulating 64 bit results. */
11932 /* Drop bottom half of lowest cross-product. */
11933 uint64_t resultmid = xproductlo >> 32;
11934 /* Add in middle products. */
11935 resultmid = resultmid + xproductmid1;
11937 /* Check for overflow. */
11938 if (resultmid < xproductmid1)
11939 /* Carry over 1 into top cross-product. */
11942 resultmid1 = resultmid + xproductmid2;
11944 /* Check for overflow. */
11945 if (resultmid1 < xproductmid2)
11946 /* Carry over 1 into top cross-product. */
11949 /* Drop lowest 32 bits of middle cross-product. */
11950 result = resultmid1 >> 32;
11952 /* Add top cross-product plus and any carry. */
11953 result += xproducthi + carry;
11958 /* Signed multiply high, source, source2 :
11959 64 bit, dest <-- high 64-bit of result. */
11961 smulh (sim_cpu *cpu)
11965 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
11966 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
11967 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
11968 GReg ra = greg (aarch64_get_instr (cpu), 10);
11969 int64_t value1 = aarch64_get_reg_u64 (cpu, rn, NO_SP);
11970 int64_t value2 = aarch64_get_reg_u64 (cpu, rm, NO_SP);
11973 int64_t signum = 1;
11978 /* Convert to unsigned and use the unsigned mul64hi routine
11979 the fix the sign up afterwards. */
12000 uresult = mul64hi (uvalue1, uvalue2);
12004 aarch64_set_reg_s64 (cpu, rd, NO_SP, result);
12007 /* Unsigned multiply add long -- source, source2 :
12008 32 bit, source3 : 64 bit. */
12010 umaddl (sim_cpu *cpu)
12012 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
12013 unsigned ra = uimm (aarch64_get_instr (cpu), 14, 10);
12014 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
12015 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
12017 /* N.B. we need to multiply the signed 32 bit values in rn, rm to
12018 obtain a 64 bit product. */
12019 aarch64_set_reg_u64
12021 aarch64_get_reg_u64 (cpu, ra, NO_SP)
12022 + ((uint64_t) aarch64_get_reg_u32 (cpu, rn, NO_SP))
12023 * ((uint64_t) aarch64_get_reg_u32 (cpu, rm, NO_SP)));
12026 /* Unsigned multiply sub long -- source, source2 : 32 bit, source3 : 64 bit. */
12028 umsubl (sim_cpu *cpu)
12030 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
12031 unsigned ra = uimm (aarch64_get_instr (cpu), 14, 10);
12032 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
12033 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
12035 /* N.B. we need to multiply the signed 32 bit values in rn, rm to
12036 obtain a 64 bit product. */
12037 aarch64_set_reg_u64
12039 aarch64_get_reg_u64 (cpu, ra, NO_SP)
12040 - ((uint64_t) aarch64_get_reg_u32 (cpu, rn, NO_SP))
12041 * ((uint64_t) aarch64_get_reg_u32 (cpu, rm, NO_SP)));
12044 /* Unsigned multiply high, source, source2 :
12045 64 bit, dest <-- high 64-bit of result. */
12047 umulh (sim_cpu *cpu)
12049 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
12050 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
12051 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
12052 GReg ra = greg (aarch64_get_instr (cpu), 10);
12057 aarch64_set_reg_u64 (cpu, rd, NO_SP,
12058 mul64hi (aarch64_get_reg_u64 (cpu, rn, NO_SP),
12059 aarch64_get_reg_u64 (cpu, rm, NO_SP)));
12063 dexDataProc3Source (sim_cpu *cpu)
12065 /* assert instr[28,24] == 11011. */
12066 /* instr[31] = size : 0 ==> 32 bit, 1 ==> 64 bit (for rd at least)
12067 instr[30,29] = op54 : 00 ==> ok, ow ==> UNALLOC
12068 instr[23,21] = op31 : 111 ==> UNALLOC, o2 ==> ok
12069 instr[15] = o0 : 0/1 ==> ok
12070 instr[23,21:15] ==> op : 0000 ==> MADD, 0001 ==> MSUB, (32/64 bit)
12071 0010 ==> SMADDL, 0011 ==> SMSUBL, (64 bit only)
12072 0100 ==> SMULH, (64 bit only)
12073 1010 ==> UMADDL, 1011 ==> UNSUBL, (64 bit only)
12074 1100 ==> UMULH (64 bit only)
12078 uint32_t size = uimm (aarch64_get_instr (cpu), 31, 31);
12079 uint32_t op54 = uimm (aarch64_get_instr (cpu), 30, 29);
12080 uint32_t op31 = uimm (aarch64_get_instr (cpu), 23, 21);
12081 uint32_t o0 = uimm (aarch64_get_instr (cpu), 15, 15);
12098 dispatch = (op31 << 1) | o0;
12102 case 0: madd64 (cpu); return;
12103 case 1: msub64 (cpu); return;
12104 case 2: smaddl (cpu); return;
12105 case 3: smsubl (cpu); return;
12106 case 4: smulh (cpu); return;
12107 case 10: umaddl (cpu); return;
12108 case 11: umsubl (cpu); return;
12109 case 12: umulh (cpu); return;
12110 default: HALT_UNALLOC;
12115 dexDPReg (sim_cpu *cpu)
12117 /* uint32_t group = dispatchGroup (aarch64_get_instr (cpu));
12118 assert group == GROUP_DPREG_0101 || group == GROUP_DPREG_1101
12119 bits [28:24:21] of a DPReg are the secondary dispatch vector. */
12120 uint32_t group2 = dispatchDPReg (aarch64_get_instr (cpu));
12124 case DPREG_LOG_000:
12125 case DPREG_LOG_001:
12126 dexLogicalShiftedRegister (cpu); return;
12128 case DPREG_ADDSHF_010:
12129 dexAddSubtractShiftedRegister (cpu); return;
12131 case DPREG_ADDEXT_011:
12132 dexAddSubtractExtendedRegister (cpu); return;
12134 case DPREG_ADDCOND_100:
12136 /* This set bundles a variety of different operations. */
12138 /* 1) add/sub w carry. */
12139 uint32_t mask1 = 0x1FE00000U;
12140 uint32_t val1 = 0x1A000000U;
12141 /* 2) cond compare register/immediate. */
12142 uint32_t mask2 = 0x1FE00000U;
12143 uint32_t val2 = 0x1A400000U;
12144 /* 3) cond select. */
12145 uint32_t mask3 = 0x1FE00000U;
12146 uint32_t val3 = 0x1A800000U;
12147 /* 4) data proc 1/2 source. */
12148 uint32_t mask4 = 0x1FE00000U;
12149 uint32_t val4 = 0x1AC00000U;
12151 if ((aarch64_get_instr (cpu) & mask1) == val1)
12152 dexAddSubtractWithCarry (cpu);
12154 else if ((aarch64_get_instr (cpu) & mask2) == val2)
12157 else if ((aarch64_get_instr (cpu) & mask3) == val3)
12158 dexCondSelect (cpu);
12160 else if ((aarch64_get_instr (cpu) & mask4) == val4)
12162 /* Bit 30 is clear for data proc 2 source
12163 and set for data proc 1 source. */
12164 if (aarch64_get_instr (cpu) & (1U << 30))
12165 dexDataProc1Source (cpu);
12167 dexDataProc2Source (cpu);
12171 /* Should not reach here. */
12177 case DPREG_3SRC_110:
12178 dexDataProc3Source (cpu); return;
12180 case DPREG_UNALLOC_101:
12183 case DPREG_3SRC_111:
12184 dexDataProc3Source (cpu); return;
12187 /* Should never reach here. */
12192 /* Unconditional Branch immediate.
12193 Offset is a PC-relative byte offset in the range +/- 128MiB.
12194 The offset is assumed to be raw from the decode i.e. the
12195 simulator is expected to scale them from word offsets to byte. */
12197 /* Unconditional branch. */
12199 buc (sim_cpu *cpu, int32_t offset)
12201 aarch64_set_next_PC_by_offset (cpu, offset);
12204 static unsigned stack_depth = 0;
12206 /* Unconditional branch and link -- writes return PC to LR. */
12208 bl (sim_cpu *cpu, int32_t offset)
12210 aarch64_save_LR (cpu);
12211 aarch64_set_next_PC_by_offset (cpu, offset);
12213 if (TRACE_BRANCH_P (cpu))
12217 " %*scall %" PRIx64 " [%s]"
12218 " [args: %" PRIx64 " %" PRIx64 " %" PRIx64 "]",
12219 stack_depth, " ", aarch64_get_next_PC (cpu),
12220 aarch64_get_func (aarch64_get_next_PC (cpu)),
12221 aarch64_get_reg_u64 (cpu, 0, NO_SP),
12222 aarch64_get_reg_u64 (cpu, 1, NO_SP),
12223 aarch64_get_reg_u64 (cpu, 2, NO_SP)
12228 /* Unconditional Branch register.
12229 Branch/return address is in source register. */
12231 /* Unconditional branch. */
12235 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
12236 aarch64_set_next_PC (cpu, aarch64_get_reg_u64 (cpu, rn, NO_SP));
12239 /* Unconditional branch and link -- writes return PC to LR. */
12243 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
12245 /* The pseudo code in the spec says we update LR before fetching.
12246 the value from the rn. */
12247 aarch64_save_LR (cpu);
12248 aarch64_set_next_PC (cpu, aarch64_get_reg_u64 (cpu, rn, NO_SP));
12250 if (TRACE_BRANCH_P (cpu))
12254 " %*scall %" PRIx64 " [%s]"
12255 " [args: %" PRIx64 " %" PRIx64 " %" PRIx64 "]",
12256 stack_depth, " ", aarch64_get_next_PC (cpu),
12257 aarch64_get_func (aarch64_get_next_PC (cpu)),
12258 aarch64_get_reg_u64 (cpu, 0, NO_SP),
12259 aarch64_get_reg_u64 (cpu, 1, NO_SP),
12260 aarch64_get_reg_u64 (cpu, 2, NO_SP)
12265 /* Return -- assembler will default source to LR this is functionally
12266 equivalent to br but, presumably, unlike br it side effects the
12267 branch predictor. */
12271 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
12272 aarch64_set_next_PC (cpu, aarch64_get_reg_u64 (cpu, rn, NO_SP));
12274 if (TRACE_BRANCH_P (cpu))
12277 " %*sreturn [result: %" PRIx64 "]",
12278 stack_depth, " ", aarch64_get_reg_u64 (cpu, 0, NO_SP));
12283 /* NOP -- we implement this and call it from the decode in case we
12284 want to intercept it later. */
12291 /* Data synchronization barrier. */
12298 /* Data memory barrier. */
12305 /* Instruction synchronization barrier. */
12313 dexBranchImmediate (sim_cpu *cpu)
12315 /* assert instr[30,26] == 00101
12316 instr[31] ==> 0 == B, 1 == BL
12317 instr[25,0] == imm26 branch offset counted in words. */
12319 uint32_t top = uimm (aarch64_get_instr (cpu), 31, 31);
12320 /* We have a 26 byte signed word offset which we need to pass to the
12321 execute routine as a signed byte offset. */
12322 int32_t offset = simm32 (aarch64_get_instr (cpu), 25, 0) << 2;
12330 /* Control Flow. */
12332 /* Conditional branch
12334 Offset is a PC-relative byte offset in the range +/- 1MiB pos is
12335 a bit position in the range 0 .. 63
12337 cc is a CondCode enum value as pulled out of the decode
12339 N.B. any offset register (source) can only be Xn or Wn. */
12342 bcc (sim_cpu *cpu, int32_t offset, CondCode cc)
12344 /* the test returns TRUE if CC is met. */
12345 if (testConditionCode (cpu, cc))
12346 aarch64_set_next_PC_by_offset (cpu, offset);
12349 /* 32 bit branch on register non-zero. */
12351 cbnz32 (sim_cpu *cpu, int32_t offset)
12353 unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
12355 if (aarch64_get_reg_u32 (cpu, rt, NO_SP) != 0)
12356 aarch64_set_next_PC_by_offset (cpu, offset);
12359 /* 64 bit branch on register zero. */
12361 cbnz (sim_cpu *cpu, int32_t offset)
12363 unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
12365 if (aarch64_get_reg_u64 (cpu, rt, NO_SP) != 0)
12366 aarch64_set_next_PC_by_offset (cpu, offset);
12369 /* 32 bit branch on register non-zero. */
12371 cbz32 (sim_cpu *cpu, int32_t offset)
12373 unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
12375 if (aarch64_get_reg_u32 (cpu, rt, NO_SP) == 0)
12376 aarch64_set_next_PC_by_offset (cpu, offset);
12379 /* 64 bit branch on register zero. */
12381 cbz (sim_cpu *cpu, int32_t offset)
12383 unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
12385 if (aarch64_get_reg_u64 (cpu, rt, NO_SP) == 0)
12386 aarch64_set_next_PC_by_offset (cpu, offset);
12389 /* Branch on register bit test non-zero -- one size fits all. */
12391 tbnz (sim_cpu *cpu, uint32_t pos, int32_t offset)
12393 unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
12395 if (aarch64_get_reg_u64 (cpu, rt, NO_SP) & (1 << pos))
12396 aarch64_set_next_PC_by_offset (cpu, offset);
12399 /* branch on register bit test zero -- one size fits all. */
12401 tbz (sim_cpu *cpu, uint32_t pos, int32_t offset)
12403 unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
12405 if (!(aarch64_get_reg_u64 (cpu, rt, NO_SP) & (1 << pos)))
12406 aarch64_set_next_PC_by_offset (cpu, offset);
12410 dexCompareBranchImmediate (sim_cpu *cpu)
12412 /* instr[30,25] = 01 1010
12413 instr[31] = size : 0 ==> 32, 1 ==> 64
12414 instr[24] = op : 0 ==> CBZ, 1 ==> CBNZ
12415 instr[23,5] = simm19 branch offset counted in words
12418 uint32_t size = uimm (aarch64_get_instr (cpu), 31, 31);
12419 uint32_t op = uimm (aarch64_get_instr (cpu), 24, 24);
12420 int32_t offset = simm32 (aarch64_get_instr (cpu), 23, 5) << 2;
12425 cbz32 (cpu, offset);
12427 cbnz32 (cpu, offset);
12434 cbnz (cpu, offset);
12439 dexTestBranchImmediate (sim_cpu *cpu)
12441 /* instr[31] = b5 : bit 5 of test bit idx
12442 instr[30,25] = 01 1011
12443 instr[24] = op : 0 ==> TBZ, 1 == TBNZ
12444 instr[23,19] = b40 : bits 4 to 0 of test bit idx
12445 instr[18,5] = simm14 : signed offset counted in words
12446 instr[4,0] = uimm5 */
12448 uint32_t pos = ((uimm (aarch64_get_instr (cpu), 31, 31) << 4)
12449 | uimm (aarch64_get_instr (cpu), 23,19));
12450 int32_t offset = simm32 (aarch64_get_instr (cpu), 18, 5) << 2;
12452 NYI_assert (30, 25, 0x1b);
12454 if (uimm (aarch64_get_instr (cpu), 24, 24) == 0)
12455 tbz (cpu, pos, offset);
12457 tbnz (cpu, pos, offset);
12461 dexCondBranchImmediate (sim_cpu *cpu)
12463 /* instr[31,25] = 010 1010
12464 instr[24] = op1; op => 00 ==> B.cond
12465 instr[23,5] = simm19 : signed offset counted in words
12467 instr[3,0] = cond */
12471 uint32_t op = ((uimm (aarch64_get_instr (cpu), 24, 24) << 1)
12472 | uimm (aarch64_get_instr (cpu), 4, 4));
12474 NYI_assert (31, 25, 0x2a);
12479 offset = simm32 (aarch64_get_instr (cpu), 23, 5) << 2;
12480 cc = condcode (aarch64_get_instr (cpu), 0);
12482 bcc (cpu, offset, cc);
12486 dexBranchRegister (sim_cpu *cpu)
12488 /* instr[31,25] = 110 1011
12489 instr[24,21] = op : 0 ==> BR, 1 => BLR, 2 => RET, 3 => ERET, 4 => DRPS
12490 instr[20,16] = op2 : must be 11111
12491 instr[15,10] = op3 : must be 000000
12492 instr[4,0] = op2 : must be 11111. */
12494 uint32_t op = uimm (aarch64_get_instr (cpu), 24, 21);
12495 uint32_t op2 = uimm (aarch64_get_instr (cpu), 20, 16);
12496 uint32_t op3 = uimm (aarch64_get_instr (cpu), 15, 10);
12497 uint32_t op4 = uimm (aarch64_get_instr (cpu), 4, 0);
12499 NYI_assert (31, 25, 0x6b);
12501 if (op2 != 0x1F || op3 != 0 || op4 != 0)
12515 /* ERET and DRPS accept 0b11111 for rn = aarch64_get_instr (cpu)[4,0]. */
12516 /* anything else is unallocated. */
12517 uint32_t rn = greg (aarch64_get_instr (cpu), 0);
12522 if (op == 4 || op == 5)
12529 /* FIXME: We should get the Angel SWI values from ../../libgloss/aarch64/svc.h
12530 but this may not be available. So instead we define the values we need
12532 #define AngelSVC_Reason_Open 0x01
12533 #define AngelSVC_Reason_Close 0x02
12534 #define AngelSVC_Reason_Write 0x05
12535 #define AngelSVC_Reason_Read 0x06
12536 #define AngelSVC_Reason_IsTTY 0x09
12537 #define AngelSVC_Reason_Seek 0x0A
12538 #define AngelSVC_Reason_FLen 0x0C
12539 #define AngelSVC_Reason_Remove 0x0E
12540 #define AngelSVC_Reason_Rename 0x0F
12541 #define AngelSVC_Reason_Clock 0x10
12542 #define AngelSVC_Reason_Time 0x11
12543 #define AngelSVC_Reason_System 0x12
12544 #define AngelSVC_Reason_Errno 0x13
12545 #define AngelSVC_Reason_GetCmdLine 0x15
12546 #define AngelSVC_Reason_HeapInfo 0x16
12547 #define AngelSVC_Reason_ReportException 0x18
12548 #define AngelSVC_Reason_Elapsed 0x30
12552 handle_halt (sim_cpu *cpu, uint32_t val)
12554 uint64_t result = 0;
12558 TRACE_SYSCALL (cpu, " HLT [0x%x]", val);
12559 sim_engine_halt (CPU_STATE (cpu), cpu, NULL, aarch64_get_PC (cpu),
12560 sim_stopped, SIM_SIGTRAP);
12563 /* We have encountered an Angel SVC call. See if we can process it. */
12564 switch (aarch64_get_reg_u32 (cpu, 0, NO_SP))
12566 case AngelSVC_Reason_HeapInfo:
12568 /* Get the values. */
12569 uint64_t stack_top = aarch64_get_stack_start (cpu);
12570 uint64_t heap_base = aarch64_get_heap_start (cpu);
12572 /* Get the pointer */
12573 uint64_t ptr = aarch64_get_reg_u64 (cpu, 1, SP_OK);
12574 ptr = aarch64_get_mem_u64 (cpu, ptr);
12576 /* Fill in the memory block. */
12577 /* Start addr of heap. */
12578 aarch64_set_mem_u64 (cpu, ptr + 0, heap_base);
12579 /* End addr of heap. */
12580 aarch64_set_mem_u64 (cpu, ptr + 8, stack_top);
12581 /* Lowest stack addr. */
12582 aarch64_set_mem_u64 (cpu, ptr + 16, heap_base);
12583 /* Initial stack addr. */
12584 aarch64_set_mem_u64 (cpu, ptr + 24, stack_top);
12586 TRACE_SYSCALL (cpu, " AngelSVC: Get Heap Info");
12590 case AngelSVC_Reason_Open:
12592 /* Get the pointer */
12593 /* uint64_t ptr = aarch64_get_reg_u64 (cpu, 1, SP_OK);. */
12594 /* FIXME: For now we just assume that we will only be asked
12595 to open the standard file descriptors. */
12599 TRACE_SYSCALL (cpu, " AngelSVC: Open file %d", fd - 1);
12603 case AngelSVC_Reason_Close:
12605 uint64_t fh = aarch64_get_reg_u64 (cpu, 1, SP_OK);
12606 TRACE_SYSCALL (cpu, " AngelSVC: Close file %d", (int) fh);
12611 case AngelSVC_Reason_Errno:
12613 TRACE_SYSCALL (cpu, " AngelSVC: Get Errno");
12616 case AngelSVC_Reason_Clock:
12618 #ifdef CLOCKS_PER_SEC
12619 (CLOCKS_PER_SEC >= 100)
12620 ? (clock () / (CLOCKS_PER_SEC / 100))
12621 : ((clock () * 100) / CLOCKS_PER_SEC)
12623 /* Presume unix... clock() returns microseconds. */
12627 TRACE_SYSCALL (cpu, " AngelSVC: Get Clock");
12630 case AngelSVC_Reason_GetCmdLine:
12632 /* Get the pointer */
12633 uint64_t ptr = aarch64_get_reg_u64 (cpu, 1, SP_OK);
12634 ptr = aarch64_get_mem_u64 (cpu, ptr);
12636 /* FIXME: No command line for now. */
12637 aarch64_set_mem_u64 (cpu, ptr, 0);
12638 TRACE_SYSCALL (cpu, " AngelSVC: Get Command Line");
12642 case AngelSVC_Reason_IsTTY:
12644 TRACE_SYSCALL (cpu, " AngelSVC: IsTTY ?");
12647 case AngelSVC_Reason_Write:
12649 /* Get the pointer */
12650 uint64_t ptr = aarch64_get_reg_u64 (cpu, 1, SP_OK);
12651 /* Get the write control block. */
12652 uint64_t fd = aarch64_get_mem_u64 (cpu, ptr);
12653 uint64_t buf = aarch64_get_mem_u64 (cpu, ptr + 8);
12654 uint64_t len = aarch64_get_mem_u64 (cpu, ptr + 16);
12656 TRACE_SYSCALL (cpu, "write of %" PRIx64 " bytes from %"
12657 PRIx64 " on descriptor %" PRIx64,
12662 TRACE_SYSCALL (cpu,
12663 " AngelSVC: Write: Suspiciously long write: %ld",
12665 sim_engine_halt (CPU_STATE (cpu), cpu, NULL, aarch64_get_PC (cpu),
12666 sim_stopped, SIM_SIGBUS);
12670 printf ("%.*s", (int) len, aarch64_get_mem_ptr (cpu, buf));
12674 TRACE (cpu, 0, "\n");
12675 sim_io_eprintf (CPU_STATE (cpu), "%.*s",
12676 (int) len, aarch64_get_mem_ptr (cpu, buf));
12677 TRACE (cpu, 0, "\n");
12681 TRACE_SYSCALL (cpu,
12682 " AngelSVC: Write: Unexpected file handle: %d",
12684 sim_engine_halt (CPU_STATE (cpu), cpu, NULL, aarch64_get_PC (cpu),
12685 sim_stopped, SIM_SIGABRT);
12690 case AngelSVC_Reason_ReportException:
12692 /* Get the pointer */
12693 uint64_t ptr = aarch64_get_reg_u64 (cpu, 1, SP_OK);
12694 /*ptr = aarch64_get_mem_u64 (cpu, ptr);. */
12695 uint64_t type = aarch64_get_mem_u64 (cpu, ptr);
12696 uint64_t state = aarch64_get_mem_u64 (cpu, ptr + 8);
12698 TRACE_SYSCALL (cpu,
12699 "Angel Exception: type 0x%" PRIx64 " state %" PRIx64,
12702 if (type == 0x20026)
12703 sim_engine_halt (CPU_STATE (cpu), cpu, NULL, aarch64_get_PC (cpu),
12704 sim_exited, state);
12706 sim_engine_halt (CPU_STATE (cpu), cpu, NULL, aarch64_get_PC (cpu),
12707 sim_stopped, SIM_SIGINT);
12711 case AngelSVC_Reason_Read:
12712 case AngelSVC_Reason_FLen:
12713 case AngelSVC_Reason_Seek:
12714 case AngelSVC_Reason_Remove:
12715 case AngelSVC_Reason_Time:
12716 case AngelSVC_Reason_System:
12717 case AngelSVC_Reason_Rename:
12718 case AngelSVC_Reason_Elapsed:
12720 TRACE_SYSCALL (cpu, " HLT [Unknown angel %x]",
12721 aarch64_get_reg_u32 (cpu, 0, NO_SP));
12722 sim_engine_halt (CPU_STATE (cpu), cpu, NULL, aarch64_get_PC (cpu),
12723 sim_stopped, SIM_SIGTRAP);
12726 aarch64_set_reg_u64 (cpu, 0, NO_SP, result);
12730 dexExcpnGen (sim_cpu *cpu)
12732 /* instr[31:24] = 11010100
12733 instr[23,21] = opc : 000 ==> GEN EXCPN, 001 ==> BRK
12734 010 ==> HLT, 101 ==> DBG GEN EXCPN
12735 instr[20,5] = imm16
12736 instr[4,2] = opc2 000 ==> OK, ow ==> UNALLOC
12737 instr[1,0] = LL : discriminates opc */
12739 uint32_t opc = uimm (aarch64_get_instr (cpu), 23, 21);
12740 uint32_t imm16 = uimm (aarch64_get_instr (cpu), 20, 5);
12741 uint32_t opc2 = uimm (aarch64_get_instr (cpu), 4, 2);
12744 NYI_assert (31, 24, 0xd4);
12749 LL = uimm (aarch64_get_instr (cpu), 1, 0);
12751 /* We only implement HLT and BRK for now. */
12752 if (opc == 1 && LL == 0)
12754 TRACE_EVENTS (cpu, " BRK [0x%x]", imm16);
12755 sim_engine_halt (CPU_STATE (cpu), cpu, NULL, aarch64_get_PC (cpu),
12756 sim_exited, aarch64_get_reg_s32 (cpu, R0, SP_OK));
12759 if (opc == 2 && LL == 0)
12760 handle_halt (cpu, imm16);
12762 else if (opc == 0 || opc == 5)
12769 /* Stub for accessing system registers.
12770 We implement support for the DCZID register since this is used
12771 by the C library's memset function. */
12774 system_get (sim_cpu *cpu, unsigned op0, unsigned op1, unsigned crn,
12775 unsigned crm, unsigned op2)
12777 if (crn == 0 && op1 == 3 && crm == 0 && op2 == 7)
12778 /* DCZID_EL0 - the Data Cache Zero ID register.
12779 We do not support DC ZVA at the moment, so
12780 we return a value with the disable bit set. */
12781 return ((uint64_t) 1) << 4;
12787 do_mrs (sim_cpu *cpu)
12789 /* instr[31:20] = 1101 01010 0011
12796 unsigned sys_op0 = uimm (aarch64_get_instr (cpu), 19, 19) + 2;
12797 unsigned sys_op1 = uimm (aarch64_get_instr (cpu), 18, 16);
12798 unsigned sys_crn = uimm (aarch64_get_instr (cpu), 15, 12);
12799 unsigned sys_crm = uimm (aarch64_get_instr (cpu), 11, 8);
12800 unsigned sys_op2 = uimm (aarch64_get_instr (cpu), 7, 5);
12801 unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
12803 aarch64_set_reg_u64 (cpu, rt, NO_SP,
12804 system_get (cpu, sys_op0, sys_op1, sys_crn, sys_crm, sys_op2));
12808 dexSystem (sim_cpu *cpu)
12810 /* instr[31:22] = 1101 01010 0
12817 instr[4,0] = uimm5 */
12819 /* We are interested in HINT, DSB, DMB and ISB
12821 Hint #0 encodes NOOP (this is the only hint we care about)
12822 L == 0, op0 == 0, op1 = 011, CRn = 0010, Rt = 11111,
12823 CRm op2 != 0000 000 OR CRm op2 == 0000 000 || CRm op > 0000 101
12825 DSB, DMB, ISB are data store barrier, data memory barrier and
12826 instruction store barrier, respectively, where
12828 L == 0, op0 == 0, op1 = 011, CRn = 0011, Rt = 11111,
12829 op2 : DSB ==> 100, DMB ==> 101, ISB ==> 110
12830 CRm<3:2> ==> domain, CRm<1:0> ==> types,
12831 domain : 00 ==> OuterShareable, 01 ==> Nonshareable,
12832 10 ==> InerShareable, 11 ==> FullSystem
12833 types : 01 ==> Reads, 10 ==> Writes,
12834 11 ==> All, 00 ==> All (domain == FullSystem). */
12836 unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
12837 uint32_t l_op0_op1_crn = uimm (aarch64_get_instr (cpu), 21, 12);
12839 NYI_assert (31, 22, 0x354);
12841 switch (l_op0_op1_crn)
12846 /* NOP has CRm != 0000 OR. */
12847 /* (CRm == 0000 AND (op2 == 000 OR op2 > 101)). */
12848 uint32_t crm = uimm (aarch64_get_instr (cpu), 11, 8);
12849 uint32_t op2 = uimm (aarch64_get_instr (cpu), 7, 5);
12851 if (crm != 0 || (op2 == 0 || op2 > 5))
12853 /* Actually call nop method so we can reimplement it later. */
12862 uint32_t op2 = uimm (aarch64_get_instr (cpu), 7, 5);
12867 case 4: dsb (cpu); return;
12868 case 5: dmb (cpu); return;
12869 case 6: isb (cpu); return;
12871 default: HALT_UNALLOC;
12876 /* MRS Wt, sys-reg. */
12882 /* MRS Xt, sys-reg. */
12887 /* DC <type>, x<n>. */
12892 /* if (uimm (aarch64_get_instr (cpu), 21, 20) == 0x1)
12893 MRS Xt, sys-reg. */
12900 dexBr (sim_cpu *cpu)
12902 /* uint32_t group = dispatchGroup (aarch64_get_instr (cpu));
12903 assert group == GROUP_BREXSYS_1010 || group == GROUP_BREXSYS_1011
12904 bits [31,29] of a BrExSys are the secondary dispatch vector. */
12905 uint32_t group2 = dispatchBrExSys (aarch64_get_instr (cpu));
12910 return dexBranchImmediate (cpu);
12912 case BR_IMMCMP_001:
12913 /* Compare has bit 25 clear while test has it set. */
12914 if (!uimm (aarch64_get_instr (cpu), 25, 25))
12915 dexCompareBranchImmediate (cpu);
12917 dexTestBranchImmediate (cpu);
12920 case BR_IMMCOND_010:
12921 /* This is a conditional branch if bit 25 is clear otherwise
12923 if (!uimm (aarch64_get_instr (cpu), 25, 25))
12924 dexCondBranchImmediate (cpu);
12929 case BR_UNALLOC_011:
12933 dexBranchImmediate (cpu);
12936 case BR_IMMCMP_101:
12937 /* Compare has bit 25 clear while test has it set. */
12938 if (!uimm (aarch64_get_instr (cpu), 25, 25))
12939 dexCompareBranchImmediate (cpu);
12941 dexTestBranchImmediate (cpu);
12945 /* Unconditional branch reg has bit 25 set. */
12946 if (uimm (aarch64_get_instr (cpu), 25, 25))
12947 dexBranchRegister (cpu);
12949 /* This includes both Excpn Gen, System and unalloc operations.
12950 We need to decode the Excpn Gen operation BRK so we can plant
12951 debugger entry points.
12952 Excpn Gen operations have aarch64_get_instr (cpu)[24] = 0.
12953 we need to decode at least one of the System operations NOP
12954 which is an alias for HINT #0.
12955 System operations have aarch64_get_instr (cpu)[24,22] = 100. */
12956 else if (uimm (aarch64_get_instr (cpu), 24, 24) == 0)
12959 else if (uimm (aarch64_get_instr (cpu), 24, 22) == 4)
12967 case BR_UNALLOC_111:
12971 /* Should never reach here. */
12977 aarch64_decode_and_execute (sim_cpu *cpu, uint64_t pc)
12979 /* We need to check if gdb wants an in here. */
12980 /* checkBreak (cpu);. */
12982 uint64_t group = dispatchGroup (aarch64_get_instr (cpu));
12986 case GROUP_PSEUDO_0000: dexPseudo (cpu); break;
12987 case GROUP_LDST_0100: dexLdSt (cpu); break;
12988 case GROUP_DPREG_0101: dexDPReg (cpu); break;
12989 case GROUP_LDST_0110: dexLdSt (cpu); break;
12990 case GROUP_ADVSIMD_0111: dexAdvSIMD0 (cpu); break;
12991 case GROUP_DPIMM_1000: dexDPImm (cpu); break;
12992 case GROUP_DPIMM_1001: dexDPImm (cpu); break;
12993 case GROUP_BREXSYS_1010: dexBr (cpu); break;
12994 case GROUP_BREXSYS_1011: dexBr (cpu); break;
12995 case GROUP_LDST_1100: dexLdSt (cpu); break;
12996 case GROUP_DPREG_1101: dexDPReg (cpu); break;
12997 case GROUP_LDST_1110: dexLdSt (cpu); break;
12998 case GROUP_ADVSIMD_1111: dexAdvSIMD1 (cpu); break;
13000 case GROUP_UNALLOC_0001:
13001 case GROUP_UNALLOC_0010:
13002 case GROUP_UNALLOC_0011:
13006 /* Should never reach here. */
13012 aarch64_step (sim_cpu *cpu)
13014 uint64_t pc = aarch64_get_PC (cpu);
13016 if (pc == TOP_LEVEL_RETURN_PC)
13019 aarch64_set_next_PC (cpu, pc + 4);
13020 aarch64_get_instr (cpu) = aarch64_get_mem_u32 (cpu, pc);
13022 TRACE_INSN (cpu, " pc = %" PRIx64 " instr = %x", pc,
13023 aarch64_get_instr (cpu));
13024 TRACE_DISASM (cpu, pc);
13026 aarch64_decode_and_execute (cpu, pc);
13032 aarch64_run (SIM_DESC sd)
13034 sim_cpu *cpu = STATE_CPU (sd, 0);
13036 while (aarch64_step (cpu))
13037 aarch64_update_PC (cpu);
13039 sim_engine_halt (sd, NULL, NULL, aarch64_get_PC (cpu),
13040 sim_exited, aarch64_get_reg_s32 (cpu, R0, SP_OK));
13044 aarch64_init (sim_cpu *cpu, uint64_t pc)
13046 uint64_t sp = aarch64_get_stack_start (cpu);
13048 /* Install SP, FP and PC and set LR to -20
13049 so we can detect a top-level return. */
13050 aarch64_set_reg_u64 (cpu, SP, SP_OK, sp);
13051 aarch64_set_reg_u64 (cpu, FP, SP_OK, sp);
13052 aarch64_set_reg_u64 (cpu, LR, SP_OK, TOP_LEVEL_RETURN_PC);
13053 aarch64_set_next_PC (cpu, pc);
13054 aarch64_update_PC (cpu);
13055 aarch64_init_LIT_table ();