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>
33 #include "simulator.h"
40 bfd_boolean disas = FALSE;
42 #define TST(_flag) (aarch64_test_CPSR_bit (cpu, _flag))
43 #define IS_SET(_X) ( TST (( _X )))
44 #define IS_CLEAR(_X) (!TST (( _X )))
46 #define HALT_UNALLOC \
49 if (TRACE_INSN_P (cpu)) \
51 aarch64_print_insn (CPU_STATE (cpu), aarch64_get_PC (cpu)); \
53 "Unallocated instruction detected at sim line %d,"\
54 " exe addr %" PRIx64, \
55 __LINE__, aarch64_get_PC (cpu)); \
57 sim_engine_halt (CPU_STATE (cpu), cpu, NULL, aarch64_get_PC (cpu),\
58 sim_stopped, SIM_SIGILL); \
65 if (TRACE_INSN_P (cpu)) \
67 aarch64_print_insn (CPU_STATE (cpu), aarch64_get_PC (cpu)); \
69 "Unimplemented instruction detected at sim line %d,"\
70 " exe addr %" PRIx64, \
71 __LINE__, aarch64_get_PC (cpu)); \
73 sim_engine_halt (CPU_STATE (cpu), cpu, NULL, aarch64_get_PC (cpu),\
74 sim_stopped, SIM_SIGABRT); \
78 #define NYI_assert(HI, LO, EXPECTED) \
81 if (uimm (aarch64_get_instr (cpu), (HI), (LO)) != (EXPECTED)) \
86 #define HALT_UNREACHABLE \
89 TRACE_EVENTS (cpu, "ISE: unreachable code point"); \
90 sim_engine_abort (NULL, cpu, aarch64_get_PC (cpu), "Internal Error"); \
94 /* Helper functions used by expandLogicalImmediate. */
96 /* for i = 1, ... N result<i-1> = 1 other bits are zero */
97 static inline uint64_t
100 return (N == 64 ? (uint64_t)-1UL : ((1UL << N) - 1));
103 /* result<0> to val<N> */
104 static inline uint64_t
105 pickbit (uint64_t val, int N)
107 return pickbits64 (val, N, N);
111 expand_logical_immediate (uint32_t S, uint32_t R, uint32_t N)
117 /* The immediate value is S+1 bits to 1, left rotated by SIMDsize - R
118 (in other words, right rotated by R), then replicated. */
122 mask = 0xffffffffffffffffull;
128 case 0x00 ... 0x1f: /* 0xxxxx */ simd_size = 32; break;
129 case 0x20 ... 0x2f: /* 10xxxx */ simd_size = 16; S &= 0xf; break;
130 case 0x30 ... 0x37: /* 110xxx */ simd_size = 8; S &= 0x7; break;
131 case 0x38 ... 0x3b: /* 1110xx */ simd_size = 4; S &= 0x3; break;
132 case 0x3c ... 0x3d: /* 11110x */ simd_size = 2; S &= 0x1; break;
135 mask = (1ull << simd_size) - 1;
136 /* Top bits are IGNORED. */
140 /* NOTE: if S = simd_size - 1 we get 0xf..f which is rejected. */
141 if (S == simd_size - 1)
144 /* S+1 consecutive bits to 1. */
145 /* NOTE: S can't be 63 due to detection above. */
146 imm = (1ull << (S + 1)) - 1;
148 /* Rotate to the left by simd_size - R. */
150 imm = ((imm << (simd_size - R)) & mask) | (imm >> R);
152 /* Replicate the value according to SIMD size. */
155 case 2: imm = (imm << 2) | imm;
156 case 4: imm = (imm << 4) | imm;
157 case 8: imm = (imm << 8) | imm;
158 case 16: imm = (imm << 16) | imm;
159 case 32: imm = (imm << 32) | imm;
167 /* Instr[22,10] encodes N immr and imms. we want a lookup table
168 for each possible combination i.e. 13 bits worth of int entries. */
169 #define LI_TABLE_SIZE (1 << 13)
170 static uint64_t LITable[LI_TABLE_SIZE];
173 aarch64_init_LIT_table (void)
177 for (index = 0; index < LI_TABLE_SIZE; index++)
179 uint32_t N = uimm (index, 12, 12);
180 uint32_t immr = uimm (index, 11, 6);
181 uint32_t imms = uimm (index, 5, 0);
183 LITable [index] = expand_logical_immediate (imms, immr, N);
188 dexNotify (sim_cpu *cpu)
190 /* instr[14,0] == type : 0 ==> method entry, 1 ==> method reentry
191 2 ==> exit Java, 3 ==> start next bytecode. */
192 uint32_t type = uimm (aarch64_get_instr (cpu), 14, 0);
194 TRACE_EVENTS (cpu, "Notify Insn encountered, type = 0x%x", type);
199 /* aarch64_notifyMethodEntry (aarch64_get_reg_u64 (cpu, R23, 0),
200 aarch64_get_reg_u64 (cpu, R22, 0)); */
203 /* aarch64_notifyMethodReentry (aarch64_get_reg_u64 (cpu, R23, 0),
204 aarch64_get_reg_u64 (cpu, R22, 0)); */
207 /* aarch64_notifyMethodExit (); */
210 /* aarch64_notifyBCStart (aarch64_get_reg_u64 (cpu, R23, 0),
211 aarch64_get_reg_u64 (cpu, R22, 0)); */
216 /* secondary decode within top level groups */
219 dexPseudo (sim_cpu *cpu)
221 /* assert instr[28,27] = 00
223 We provide 2 pseudo instructions:
225 HALT stops execution of the simulator causing an immediate
226 return to the x86 code which entered it.
228 CALLOUT initiates recursive entry into x86 code. A register
229 argument holds the address of the x86 routine. Immediate
230 values in the instruction identify the number of general
231 purpose and floating point register arguments to be passed
232 and the type of any value to be returned. */
234 uint32_t PSEUDO_HALT = 0xE0000000U;
235 uint32_t PSEUDO_CALLOUT = 0x00018000U;
236 uint32_t PSEUDO_CALLOUTR = 0x00018001U;
237 uint32_t PSEUDO_NOTIFY = 0x00014000U;
240 if (aarch64_get_instr (cpu) == PSEUDO_HALT)
242 TRACE_EVENTS (cpu, " Pseudo Halt Instruction");
243 sim_engine_halt (CPU_STATE (cpu), cpu, NULL, aarch64_get_PC (cpu),
244 sim_stopped, SIM_SIGTRAP);
247 dispatch = uimm (aarch64_get_instr (cpu), 31, 15);
249 /* We do not handle callouts at the moment. */
250 if (dispatch == PSEUDO_CALLOUT || dispatch == PSEUDO_CALLOUTR)
252 TRACE_EVENTS (cpu, " Callout");
253 sim_engine_halt (CPU_STATE (cpu), cpu, NULL, aarch64_get_PC (cpu),
254 sim_stopped, SIM_SIGABRT);
257 else if (dispatch == PSEUDO_NOTIFY)
264 /* Load-store single register (unscaled offset)
265 These instructions employ a base register plus an unscaled signed
268 N.B. the base register (source) can be Xn or SP. all other
269 registers may not be SP. */
271 /* 32 bit load 32 bit unscaled signed 9 bit. */
273 ldur32 (sim_cpu *cpu, int32_t offset)
275 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
276 unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
278 aarch64_set_reg_u64 (cpu, rt, NO_SP, aarch64_get_mem_u32
279 (cpu, aarch64_get_reg_u64 (cpu, rn, SP_OK)
283 /* 64 bit load 64 bit unscaled signed 9 bit. */
285 ldur64 (sim_cpu *cpu, int32_t offset)
287 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
288 unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
290 aarch64_set_reg_u64 (cpu, rt, NO_SP, aarch64_get_mem_u64
291 (cpu, aarch64_get_reg_u64 (cpu, rn, SP_OK)
295 /* 32 bit load zero-extended byte unscaled signed 9 bit. */
297 ldurb32 (sim_cpu *cpu, int32_t offset)
299 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
300 unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
302 aarch64_set_reg_u64 (cpu, rt, NO_SP, aarch64_get_mem_u8
303 (cpu, aarch64_get_reg_u64 (cpu, rn, SP_OK)
307 /* 32 bit load sign-extended byte unscaled signed 9 bit. */
309 ldursb32 (sim_cpu *cpu, int32_t offset)
311 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
312 unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
314 aarch64_set_reg_u64 (cpu, rt, NO_SP, (uint32_t) aarch64_get_mem_s8
315 (cpu, aarch64_get_reg_u64 (cpu, rn, SP_OK)
319 /* 64 bit load sign-extended byte unscaled signed 9 bit. */
321 ldursb64 (sim_cpu *cpu, int32_t offset)
323 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
324 unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
326 aarch64_set_reg_s64 (cpu, rt, NO_SP, aarch64_get_mem_s8
327 (cpu, aarch64_get_reg_u64 (cpu, rn, SP_OK)
331 /* 32 bit load zero-extended short unscaled signed 9 bit */
333 ldurh32 (sim_cpu *cpu, int32_t offset)
335 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
336 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
338 aarch64_set_reg_u64 (cpu, rd, NO_SP, aarch64_get_mem_u16
339 (cpu, aarch64_get_reg_u64 (cpu, rn, SP_OK)
343 /* 32 bit load sign-extended short unscaled signed 9 bit */
345 ldursh32 (sim_cpu *cpu, int32_t offset)
347 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
348 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
350 aarch64_set_reg_u64 (cpu, rd, NO_SP, (uint32_t) aarch64_get_mem_s16
351 (cpu, aarch64_get_reg_u64 (cpu, rn, SP_OK)
355 /* 64 bit load sign-extended short unscaled signed 9 bit */
357 ldursh64 (sim_cpu *cpu, int32_t offset)
359 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
360 unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
362 aarch64_set_reg_s64 (cpu, rt, NO_SP, aarch64_get_mem_s16
363 (cpu, aarch64_get_reg_u64 (cpu, rn, SP_OK)
367 /* 64 bit load sign-extended word unscaled signed 9 bit */
369 ldursw (sim_cpu *cpu, int32_t offset)
371 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
372 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
374 aarch64_set_reg_u64 (cpu, rd, NO_SP, (uint32_t) aarch64_get_mem_s32
375 (cpu, aarch64_get_reg_u64 (cpu, rn, SP_OK)
379 /* N.B. with stores the value in source is written to the address
380 identified by source2 modified by offset. */
382 /* 32 bit store 32 bit unscaled signed 9 bit. */
384 stur32 (sim_cpu *cpu, int32_t offset)
386 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
387 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
389 aarch64_set_mem_u32 (cpu,
390 aarch64_get_reg_u64 (cpu, rn, SP_OK) + offset,
391 aarch64_get_reg_u32 (cpu, rd, NO_SP));
394 /* 64 bit store 64 bit unscaled signed 9 bit */
396 stur64 (sim_cpu *cpu, int32_t offset)
398 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
399 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
401 aarch64_set_mem_u64 (cpu,
402 aarch64_get_reg_u64 (cpu, rn, SP_OK) + offset,
403 aarch64_get_reg_u64 (cpu, rd, NO_SP));
406 /* 32 bit store byte unscaled signed 9 bit */
408 sturb (sim_cpu *cpu, int32_t offset)
410 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
411 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
413 aarch64_set_mem_u8 (cpu,
414 aarch64_get_reg_u64 (cpu, rn, SP_OK) + offset,
415 aarch64_get_reg_u8 (cpu, rd, NO_SP));
418 /* 32 bit store short unscaled signed 9 bit */
420 sturh (sim_cpu *cpu, int32_t offset)
422 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
423 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
425 aarch64_set_mem_u16 (cpu,
426 aarch64_get_reg_u64 (cpu, rn, SP_OK) + offset,
427 aarch64_get_reg_u16 (cpu, rd, NO_SP));
430 /* Load single register pc-relative label
431 Offset is a signed 19 bit immediate count in words
434 /* 32 bit pc-relative load */
436 ldr32_pcrel (sim_cpu *cpu, int32_t offset)
438 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
440 aarch64_set_reg_u64 (cpu, rd, NO_SP,
442 (cpu, aarch64_get_PC (cpu) + offset * 4));
445 /* 64 bit pc-relative load */
447 ldr_pcrel (sim_cpu *cpu, int32_t offset)
449 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
451 aarch64_set_reg_u64 (cpu, rd, NO_SP,
453 (cpu, aarch64_get_PC (cpu) + offset * 4));
456 /* sign extended 32 bit pc-relative load */
458 ldrsw_pcrel (sim_cpu *cpu, int32_t offset)
460 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
462 aarch64_set_reg_u64 (cpu, rd, NO_SP,
464 (cpu, aarch64_get_PC (cpu) + offset * 4));
467 /* float pc-relative load */
469 fldrs_pcrel (sim_cpu *cpu, int32_t offset)
471 unsigned int rd = uimm (aarch64_get_instr (cpu), 4, 0);
473 aarch64_set_FP_float (cpu, rd,
474 aarch64_get_mem_float
475 (cpu, aarch64_get_PC (cpu) + offset * 4));
478 /* double pc-relative load */
480 fldrd_pcrel (sim_cpu *cpu, int32_t offset)
482 unsigned int st = uimm (aarch64_get_instr (cpu), 4, 0);
484 aarch64_set_FP_double (cpu, st,
485 aarch64_get_mem_double
486 (cpu, aarch64_get_PC (cpu) + offset * 4));
489 /* long double pc-relative load. */
491 fldrq_pcrel (sim_cpu *cpu, int32_t offset)
493 unsigned int st = uimm (aarch64_get_instr (cpu), 4, 0);
494 uint64_t addr = aarch64_get_PC (cpu) + offset * 4;
497 aarch64_get_mem_long_double (cpu, addr, & a);
498 aarch64_set_FP_long_double (cpu, st, a);
501 /* This can be used to scale an offset by applying
502 the requisite shift. the second argument is either
505 #define SCALE(_offset, _elementSize) \
506 ((_offset) << ScaleShift ## _elementSize)
508 /* This can be used to optionally scale a register derived offset
509 by applying the requisite shift as indicated by the Scaling
510 argument. the second argument is either Byte, Short, Word
511 or Long. The third argument is either Scaled or Unscaled.
512 N.B. when _Scaling is Scaled the shift gets ANDed with
513 all 1s while when it is Unscaled it gets ANDed with 0. */
515 #define OPT_SCALE(_offset, _elementType, _Scaling) \
516 ((_offset) << (_Scaling ? ScaleShift ## _elementType : 0))
518 /* This can be used to zero or sign extend a 32 bit register derived
519 value to a 64 bit value. the first argument must be the value as
520 a uint32_t and the second must be either UXTW or SXTW. The result
521 is returned as an int64_t. */
523 static inline int64_t
524 extend (uint32_t value, Extension extension)
532 /* A branchless variant of this ought to be possible. */
533 if (extension == UXTW || extension == NoExtension)
540 /* Scalar Floating Point
542 FP load/store single register (4 addressing modes)
544 N.B. the base register (source) can be the stack pointer.
545 The secondary source register (source2) can only be an Xn register. */
547 /* Load 32 bit unscaled signed 9 bit with pre- or post-writeback. */
549 fldrs_wb (sim_cpu *cpu, int32_t offset, WriteBack wb)
551 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
552 unsigned st = uimm (aarch64_get_instr (cpu), 4, 0);
553 uint64_t address = aarch64_get_reg_u64 (cpu, rn, SP_OK);
558 aarch64_set_FP_float (cpu, st, aarch64_get_mem_float (cpu, address));
562 if (wb != NoWriteBack)
563 aarch64_set_reg_u64 (cpu, rn, SP_OK, address);
566 /* Load 32 bit scaled unsigned 12 bit. */
568 fldrs_abs (sim_cpu *cpu, uint32_t offset)
570 unsigned st = uimm (aarch64_get_instr (cpu), 4, 0);
571 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
573 aarch64_set_FP_float (cpu, st,
574 aarch64_get_mem_float
575 (cpu, aarch64_get_reg_u64 (cpu, rn, SP_OK)
576 + SCALE (offset, 32)));
579 /* Load 32 bit scaled or unscaled zero- or sign-extended
580 32-bit register offset. */
582 fldrs_scale_ext (sim_cpu *cpu, Scaling scaling, Extension extension)
584 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
585 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
586 unsigned st = uimm (aarch64_get_instr (cpu), 4, 0);
587 uint64_t address = aarch64_get_reg_u64 (cpu, rn, SP_OK);
588 int64_t extended = extend (aarch64_get_reg_u32 (cpu, rm, NO_SP), extension);
589 uint64_t displacement = OPT_SCALE (extended, 32, scaling);
591 aarch64_set_FP_float (cpu, st,
592 aarch64_get_mem_float
593 (cpu, address + displacement));
596 /* Load 64 bit unscaled signed 9 bit with pre- or post-writeback. */
598 fldrd_wb (sim_cpu *cpu, int32_t offset, WriteBack wb)
600 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
601 unsigned st = uimm (aarch64_get_instr (cpu), 4, 0);
602 uint64_t address = aarch64_get_reg_u64 (cpu, rn, SP_OK);
607 aarch64_set_FP_double (cpu, st, aarch64_get_mem_double (cpu, address));
612 if (wb != NoWriteBack)
613 aarch64_set_reg_u64 (cpu, rn, SP_OK, address);
616 /* Load 64 bit scaled unsigned 12 bit. */
618 fldrd_abs (sim_cpu *cpu, uint32_t offset)
620 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
621 unsigned st = uimm (aarch64_get_instr (cpu), 4, 0);
622 uint64_t address = aarch64_get_reg_u64 (cpu, rn, SP_OK) + SCALE (offset, 64);
624 aarch64_set_FP_double (cpu, st, aarch64_get_mem_double (cpu, address));
627 /* Load 64 bit scaled or unscaled zero- or sign-extended 32-bit register offset. */
629 fldrd_scale_ext (sim_cpu *cpu, Scaling scaling, Extension extension)
631 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
632 int64_t extended = extend (aarch64_get_reg_u32 (cpu, rm, NO_SP), extension);
633 uint64_t displacement = OPT_SCALE (extended, 64, scaling);
635 fldrd_wb (cpu, displacement, NoWriteBack);
638 /* Load 128 bit unscaled signed 9 bit with pre- or post-writeback. */
640 fldrq_wb (sim_cpu *cpu, int32_t offset, WriteBack wb)
643 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
644 unsigned st = uimm (aarch64_get_instr (cpu), 4, 0);
645 uint64_t address = aarch64_get_reg_u64 (cpu, rn, SP_OK);
650 aarch64_get_mem_long_double (cpu, address, & a);
651 aarch64_set_FP_long_double (cpu, st, a);
656 if (wb != NoWriteBack)
657 aarch64_set_reg_u64 (cpu, rn, SP_OK, address);
660 /* Load 128 bit scaled unsigned 12 bit. */
662 fldrq_abs (sim_cpu *cpu, uint32_t offset)
665 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
666 unsigned st = uimm (aarch64_get_instr (cpu), 4, 0);
667 uint64_t address = aarch64_get_reg_u64 (cpu, rn, SP_OK) + SCALE (offset, 128);
669 aarch64_get_mem_long_double (cpu, address, & a);
670 aarch64_set_FP_long_double (cpu, st, a);
673 /* Load 128 bit scaled or unscaled zero- or sign-extended 32-bit register offset */
675 fldrq_scale_ext (sim_cpu *cpu, Scaling scaling, Extension extension)
677 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
678 int64_t extended = extend (aarch64_get_reg_u32 (cpu, rm, NO_SP), extension);
679 uint64_t displacement = OPT_SCALE (extended, 128, scaling);
681 fldrq_wb (cpu, displacement, NoWriteBack);
686 load-store single register
687 There are four addressing modes available here which all employ a
688 64 bit source (base) register.
690 N.B. the base register (source) can be the stack pointer.
691 The secondary source register (source2)can only be an Xn register.
693 Scaled, 12-bit, unsigned immediate offset, without pre- and
695 Unscaled, 9-bit, signed immediate offset with pre- or post-index
697 scaled or unscaled 64-bit register offset.
698 scaled or unscaled 32-bit extended register offset.
700 All offsets are assumed to be raw from the decode i.e. the
701 simulator is expected to adjust scaled offsets based on the
702 accessed data size with register or extended register offset
703 versions the same applies except that in the latter case the
704 operation may also require a sign extend.
706 A separate method is provided for each possible addressing mode. */
708 /* 32 bit load 32 bit scaled unsigned 12 bit */
710 ldr32_abs (sim_cpu *cpu, uint32_t offset)
712 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
713 unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
715 /* The target register may not be SP but the source may be. */
716 aarch64_set_reg_u64 (cpu, rt, NO_SP, aarch64_get_mem_u32
717 (cpu, aarch64_get_reg_u64 (cpu, rn, SP_OK)
718 + SCALE (offset, 32)));
721 /* 32 bit load 32 bit unscaled signed 9 bit with pre- or post-writeback. */
723 ldr32_wb (sim_cpu *cpu, int32_t offset, WriteBack wb)
725 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
726 unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
729 if (rn == rt && wb != NoWriteBack)
732 address = aarch64_get_reg_u64 (cpu, rn, SP_OK);
737 aarch64_set_reg_u64 (cpu, rt, NO_SP, aarch64_get_mem_u32 (cpu, address));
742 if (wb != NoWriteBack)
743 aarch64_set_reg_u64 (cpu, rn, SP_OK, address);
746 /* 32 bit load 32 bit scaled or unscaled
747 zero- or sign-extended 32-bit register offset */
749 ldr32_scale_ext (sim_cpu *cpu, Scaling scaling, Extension extension)
751 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
752 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
753 unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
754 /* rn may reference SP, rm and rt must reference ZR */
756 uint64_t address = aarch64_get_reg_u64 (cpu, rn, SP_OK);
757 int64_t extended = extend (aarch64_get_reg_u32 (cpu, rm, NO_SP), extension);
758 uint64_t displacement = OPT_SCALE (extended, 32, scaling);
760 aarch64_set_reg_u64 (cpu, rt, NO_SP,
761 aarch64_get_mem_u32 (cpu, address + displacement));
764 /* 64 bit load 64 bit scaled unsigned 12 bit */
766 ldr_abs (sim_cpu *cpu, uint32_t offset)
768 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
769 unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
771 /* The target register may not be SP but the source may be. */
772 aarch64_set_reg_u64 (cpu, rt, NO_SP, aarch64_get_mem_u64
773 (cpu, aarch64_get_reg_u64 (cpu, rn, SP_OK)
774 + SCALE (offset, 64)));
777 /* 64 bit load 64 bit unscaled signed 9 bit with pre- or post-writeback. */
779 ldr_wb (sim_cpu *cpu, int32_t offset, WriteBack wb)
781 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
782 unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
785 if (rn == rt && wb != NoWriteBack)
788 address = aarch64_get_reg_u64 (cpu, rn, SP_OK);
793 aarch64_set_reg_u64 (cpu, rt, NO_SP, aarch64_get_mem_u64 (cpu, address));
798 if (wb != NoWriteBack)
799 aarch64_set_reg_u64 (cpu, rn, SP_OK, address);
802 /* 64 bit load 64 bit scaled or unscaled zero-
803 or sign-extended 32-bit register offset. */
805 ldr_scale_ext (sim_cpu *cpu, Scaling scaling, Extension extension)
807 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
808 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
809 unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
810 /* rn may reference SP, rm and rt must reference ZR */
812 uint64_t address = aarch64_get_reg_u64 (cpu, rn, SP_OK);
813 int64_t extended = extend (aarch64_get_reg_u32 (cpu, rm, NO_SP), extension);
814 uint64_t displacement = OPT_SCALE (extended, 64, scaling);
816 aarch64_set_reg_u64 (cpu, rt, NO_SP,
817 aarch64_get_mem_u64 (cpu, address + displacement));
820 /* 32 bit load zero-extended byte scaled unsigned 12 bit. */
822 ldrb32_abs (sim_cpu *cpu, uint32_t offset)
824 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
825 unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
827 /* The target register may not be SP but the source may be
828 there is no scaling required for a byte load. */
829 aarch64_set_reg_u64 (cpu, rt, NO_SP,
831 (cpu, aarch64_get_reg_u64 (cpu, rn, SP_OK) + offset));
834 /* 32 bit load zero-extended byte unscaled signed 9 bit with pre- or post-writeback. */
836 ldrb32_wb (sim_cpu *cpu, int32_t offset, WriteBack wb)
838 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
839 unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
842 if (rn == rt && wb != NoWriteBack)
845 address = aarch64_get_reg_u64 (cpu, rn, SP_OK);
850 aarch64_set_reg_u64 (cpu, rt, NO_SP, aarch64_get_mem_u8 (cpu, address));
855 if (wb != NoWriteBack)
856 aarch64_set_reg_u64 (cpu, rn, SP_OK, address);
859 /* 32 bit load zero-extended byte scaled or unscaled zero-
860 or sign-extended 32-bit register offset. */
862 ldrb32_scale_ext (sim_cpu *cpu, Scaling scaling, Extension extension)
864 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
865 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
866 unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
867 /* rn may reference SP, rm and rt must reference ZR */
869 uint64_t address = aarch64_get_reg_u64 (cpu, rn, SP_OK);
870 int64_t displacement = extend (aarch64_get_reg_u32 (cpu, rm, NO_SP),
873 /* There is no scaling required for a byte load. */
874 aarch64_set_reg_u64 (cpu, rt, NO_SP,
875 aarch64_get_mem_u8 (cpu, address + displacement));
878 /* 64 bit load sign-extended byte unscaled signed 9 bit
879 with pre- or post-writeback. */
881 ldrsb_wb (sim_cpu *cpu, int32_t offset, WriteBack wb)
883 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
884 unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
887 if (rn == rt && wb != NoWriteBack)
890 address = aarch64_get_reg_u64 (cpu, rn, SP_OK);
895 aarch64_set_reg_u64 (cpu, rt, NO_SP, aarch64_get_mem_s8 (cpu, address));
900 if (wb != NoWriteBack)
901 aarch64_set_reg_u64 (cpu, rn, SP_OK, address);
904 /* 64 bit load sign-extended byte scaled unsigned 12 bit. */
906 ldrsb_abs (sim_cpu *cpu, uint32_t offset)
908 ldrsb_wb (cpu, offset, NoWriteBack);
911 /* 64 bit load sign-extended byte scaled or unscaled zero-
912 or sign-extended 32-bit register offset. */
914 ldrsb_scale_ext (sim_cpu *cpu, Scaling scaling, Extension extension)
916 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
917 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
918 unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
919 /* rn may reference SP, rm and rt must reference ZR */
921 uint64_t address = aarch64_get_reg_u64 (cpu, rn, SP_OK);
922 int64_t displacement = extend (aarch64_get_reg_u32 (cpu, rm, NO_SP),
924 /* There is no scaling required for a byte load. */
925 aarch64_set_reg_u64 (cpu, rt, NO_SP,
926 aarch64_get_mem_s8 (cpu, address + displacement));
929 /* 32 bit load zero-extended short scaled unsigned 12 bit. */
931 ldrh32_abs (sim_cpu *cpu, uint32_t offset)
933 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
934 unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
936 /* The target register may not be SP but the source may be. */
937 aarch64_set_reg_u64 (cpu, rt, NO_SP, aarch64_get_mem_u16
938 (cpu, aarch64_get_reg_u64 (cpu, rn, SP_OK)
939 + SCALE (offset, 16)));
942 /* 32 bit load zero-extended short unscaled signed 9 bit
943 with pre- or post-writeback. */
945 ldrh32_wb (sim_cpu *cpu, int32_t offset, WriteBack wb)
947 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
948 unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
951 if (rn == rt && wb != NoWriteBack)
954 address = aarch64_get_reg_u64 (cpu, rn, SP_OK);
959 aarch64_set_reg_u64 (cpu, rt, NO_SP, aarch64_get_mem_u16 (cpu, address));
964 if (wb != NoWriteBack)
965 aarch64_set_reg_u64 (cpu, rn, SP_OK, address);
968 /* 32 bit load zero-extended short scaled or unscaled zero-
969 or sign-extended 32-bit register offset. */
971 ldrh32_scale_ext (sim_cpu *cpu, Scaling scaling, Extension extension)
973 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
974 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
975 unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
976 /* rn may reference SP, rm and rt must reference ZR */
978 uint64_t address = aarch64_get_reg_u64 (cpu, rn, SP_OK);
979 int64_t extended = extend (aarch64_get_reg_u32 (cpu, rm, NO_SP), extension);
980 uint64_t displacement = OPT_SCALE (extended, 16, scaling);
982 aarch64_set_reg_u64 (cpu, rt, NO_SP,
983 aarch64_get_mem_u16 (cpu, address + displacement));
986 /* 32 bit load sign-extended short scaled unsigned 12 bit. */
988 ldrsh32_abs (sim_cpu *cpu, uint32_t offset)
990 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
991 unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
993 /* The target register may not be SP but the source may be. */
994 aarch64_set_reg_u64 (cpu, rt, NO_SP, (uint32_t) aarch64_get_mem_s16
996 aarch64_get_reg_u64 (cpu, rn, SP_OK)
997 + SCALE (offset, 16)));
1000 /* 32 bit load sign-extended short unscaled signed 9 bit
1001 with pre- or post-writeback. */
1003 ldrsh32_wb (sim_cpu *cpu, int32_t offset, WriteBack wb)
1005 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
1006 unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
1009 if (rn == rt && wb != NoWriteBack)
1012 address = aarch64_get_reg_u64 (cpu, rn, SP_OK);
1017 aarch64_set_reg_u64 (cpu, rt, NO_SP,
1018 (uint32_t) aarch64_get_mem_s16 (cpu, address));
1023 if (wb != NoWriteBack)
1024 aarch64_set_reg_u64 (cpu, rn, SP_OK, address);
1027 /* 32 bit load sign-extended short scaled or unscaled zero-
1028 or sign-extended 32-bit register offset. */
1030 ldrsh32_scale_ext (sim_cpu *cpu, Scaling scaling, Extension extension)
1032 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
1033 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
1034 unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
1035 /* rn may reference SP, rm and rt must reference ZR */
1037 uint64_t address = aarch64_get_reg_u64 (cpu, rn, SP_OK);
1038 int64_t extended = extend (aarch64_get_reg_u32 (cpu, rm, NO_SP), extension);
1039 uint64_t displacement = OPT_SCALE (extended, 16, scaling);
1041 aarch64_set_reg_u64 (cpu, rt, NO_SP,
1042 (uint32_t) aarch64_get_mem_s16
1043 (cpu, address + displacement));
1046 /* 64 bit load sign-extended short scaled unsigned 12 bit. */
1048 ldrsh_abs (sim_cpu *cpu, uint32_t offset)
1050 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
1051 unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
1053 /* The target register may not be SP but the source may be. */
1054 aarch64_set_reg_u64 (cpu, rt, NO_SP, aarch64_get_mem_s16
1055 (cpu, aarch64_get_reg_u64 (cpu, rn, SP_OK)
1056 + SCALE (offset, 16)));
1059 /* 64 bit load sign-extended short unscaled signed 9 bit
1060 with pre- or post-writeback. */
1062 ldrsh64_wb (sim_cpu *cpu, int32_t offset, WriteBack wb)
1064 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
1065 unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
1068 if (rn == rt && wb != NoWriteBack)
1071 address = aarch64_get_reg_u64 (cpu, rn, SP_OK);
1076 aarch64_set_reg_u64 (cpu, rt, NO_SP, aarch64_get_mem_s16 (cpu, address));
1081 if (wb != NoWriteBack)
1082 aarch64_set_reg_u64 (cpu, rn, SP_OK, address);
1085 /* 64 bit load sign-extended short scaled or unscaled zero-
1086 or sign-extended 32-bit register offset. */
1088 ldrsh_scale_ext (sim_cpu *cpu, Scaling scaling, Extension extension)
1090 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
1091 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
1092 unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
1093 /* rn may reference SP, rm and rt must reference ZR */
1095 uint64_t address = aarch64_get_reg_u64 (cpu, rn, SP_OK);
1096 int64_t extended = extend (aarch64_get_reg_u32 (cpu, rm, NO_SP), extension);
1097 uint64_t displacement = OPT_SCALE (extended, 16, scaling);
1099 aarch64_set_reg_u64 (cpu, rt, NO_SP,
1100 aarch64_get_mem_s16 (cpu, address + displacement));
1103 /* 64 bit load sign-extended 32 bit scaled unsigned 12 bit. */
1105 ldrsw_abs (sim_cpu *cpu, uint32_t offset)
1107 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
1108 unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
1110 /* The target register may not be SP but the source may be. */
1111 return aarch64_set_reg_s64 (cpu, rt, NO_SP, aarch64_get_mem_s32
1112 (cpu, aarch64_get_reg_u64 (cpu, rn, SP_OK)
1113 + SCALE (offset, 32)));
1116 /* 64 bit load sign-extended 32 bit unscaled signed 9 bit
1117 with pre- or post-writeback. */
1119 ldrsw_wb (sim_cpu *cpu, int32_t offset, WriteBack wb)
1121 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
1122 unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
1125 if (rn == rt && wb != NoWriteBack)
1128 address = aarch64_get_reg_u64 (cpu, rn, SP_OK);
1133 aarch64_set_reg_s64 (cpu, rt, NO_SP, aarch64_get_mem_s32 (cpu, address));
1138 if (wb != NoWriteBack)
1139 aarch64_set_reg_u64 (cpu, rn, SP_OK, address);
1142 /* 64 bit load sign-extended 32 bit scaled or unscaled zero-
1143 or sign-extended 32-bit register offset. */
1145 ldrsw_scale_ext (sim_cpu *cpu, Scaling scaling, Extension extension)
1147 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
1148 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
1149 unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
1150 /* rn may reference SP, rm and rt must reference ZR */
1152 uint64_t address = aarch64_get_reg_u64 (cpu, rn, SP_OK);
1153 int64_t extended = extend (aarch64_get_reg_u32 (cpu, rm, NO_SP), extension);
1154 uint64_t displacement = OPT_SCALE (extended, 32, scaling);
1156 aarch64_set_reg_s64 (cpu, rt, NO_SP,
1157 aarch64_get_mem_s32 (cpu, address + displacement));
1160 /* N.B. with stores the value in source is written to the
1161 address identified by source2 modified by source3/offset. */
1163 /* 32 bit store scaled unsigned 12 bit. */
1165 str32_abs (sim_cpu *cpu, uint32_t offset)
1167 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
1168 unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
1170 /* The target register may not be SP but the source may be. */
1171 aarch64_set_mem_u32 (cpu, (aarch64_get_reg_u64 (cpu, rn, SP_OK)
1172 + SCALE (offset, 32)),
1173 aarch64_get_reg_u32 (cpu, rt, NO_SP));
1176 /* 32 bit store unscaled signed 9 bit with pre- or post-writeback. */
1178 str32_wb (sim_cpu *cpu, int32_t offset, WriteBack wb)
1180 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
1181 unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
1184 if (rn == rt && wb != NoWriteBack)
1187 address = aarch64_get_reg_u64 (cpu, rn, SP_OK);
1191 aarch64_set_mem_u32 (cpu, address, aarch64_get_reg_u32 (cpu, rt, NO_SP));
1196 if (wb != NoWriteBack)
1197 aarch64_set_reg_u64 (cpu, rn, SP_OK, address);
1200 /* 32 bit store scaled or unscaled zero- or
1201 sign-extended 32-bit register offset. */
1203 str32_scale_ext (sim_cpu *cpu, Scaling scaling, Extension extension)
1205 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
1206 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
1207 unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
1209 uint64_t address = aarch64_get_reg_u64 (cpu, rn, SP_OK);
1210 int64_t extended = extend (aarch64_get_reg_u32 (cpu, rm, NO_SP), extension);
1211 uint64_t displacement = OPT_SCALE (extended, 32, scaling);
1213 aarch64_set_mem_u32 (cpu, address + displacement,
1214 aarch64_get_reg_u64 (cpu, rt, NO_SP));
1217 /* 64 bit store scaled unsigned 12 bit. */
1219 str_abs (sim_cpu *cpu, uint32_t offset)
1221 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
1222 unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
1224 aarch64_set_mem_u64 (cpu,
1225 aarch64_get_reg_u64 (cpu, rn, SP_OK)
1226 + SCALE (offset, 64),
1227 aarch64_get_reg_u64 (cpu, rt, NO_SP));
1230 /* 64 bit store unscaled signed 9 bit with pre- or post-writeback. */
1232 str_wb (sim_cpu *cpu, int32_t offset, WriteBack wb)
1234 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
1235 unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
1238 if (rn == rt && wb != NoWriteBack)
1241 address = aarch64_get_reg_u64 (cpu, rn, SP_OK);
1246 aarch64_set_mem_u64 (cpu, address, aarch64_get_reg_u64 (cpu, rt, NO_SP));
1251 if (wb != NoWriteBack)
1252 aarch64_set_reg_u64 (cpu, rn, SP_OK, address);
1255 /* 64 bit store scaled or unscaled zero-
1256 or sign-extended 32-bit register offset. */
1258 str_scale_ext (sim_cpu *cpu, Scaling scaling, Extension extension)
1260 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
1261 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
1262 unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
1263 /* rn may reference SP, rm and rt must reference ZR */
1265 uint64_t address = aarch64_get_reg_u64 (cpu, rn, SP_OK);
1266 int64_t extended = extend (aarch64_get_reg_u32 (cpu, rm, NO_SP),
1268 uint64_t displacement = OPT_SCALE (extended, 64, scaling);
1270 aarch64_set_mem_u64 (cpu, address + displacement,
1271 aarch64_get_reg_u64 (cpu, rt, NO_SP));
1274 /* 32 bit store byte scaled unsigned 12 bit. */
1276 strb_abs (sim_cpu *cpu, uint32_t offset)
1278 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
1279 unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
1281 /* The target register may not be SP but the source may be.
1282 There is no scaling required for a byte load. */
1283 aarch64_set_mem_u8 (cpu,
1284 aarch64_get_reg_u64 (cpu, rn, SP_OK) + offset,
1285 aarch64_get_reg_u8 (cpu, rt, NO_SP));
1288 /* 32 bit store byte unscaled signed 9 bit with pre- or post-writeback. */
1290 strb_wb (sim_cpu *cpu, int32_t offset, WriteBack wb)
1292 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
1293 unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
1296 if (rn == rt && wb != NoWriteBack)
1299 address = aarch64_get_reg_u64 (cpu, rn, SP_OK);
1304 aarch64_set_mem_u8 (cpu, address, aarch64_get_reg_u8 (cpu, rt, NO_SP));
1309 if (wb != NoWriteBack)
1310 aarch64_set_reg_u64 (cpu, rn, SP_OK, address);
1313 /* 32 bit store byte scaled or unscaled zero-
1314 or sign-extended 32-bit register offset. */
1316 strb_scale_ext (sim_cpu *cpu, Scaling scaling, Extension extension)
1318 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
1319 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
1320 unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
1321 /* rn may reference SP, rm and rt must reference ZR */
1323 uint64_t address = aarch64_get_reg_u64 (cpu, rn, SP_OK);
1324 int64_t displacement = extend (aarch64_get_reg_u32 (cpu, rm, NO_SP),
1327 /* There is no scaling required for a byte load. */
1328 aarch64_set_mem_u8 (cpu, address + displacement,
1329 aarch64_get_reg_u8 (cpu, rt, NO_SP));
1332 /* 32 bit store short scaled unsigned 12 bit. */
1334 strh_abs (sim_cpu *cpu, uint32_t offset)
1336 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
1337 unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
1339 /* The target register may not be SP but the source may be. */
1340 aarch64_set_mem_u16 (cpu, aarch64_get_reg_u64 (cpu, rn, SP_OK)
1341 + SCALE (offset, 16),
1342 aarch64_get_reg_u16 (cpu, rt, NO_SP));
1345 /* 32 bit store short unscaled signed 9 bit with pre- or post-writeback. */
1347 strh_wb (sim_cpu *cpu, int32_t offset, WriteBack wb)
1349 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
1350 unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
1353 if (rn == rt && wb != NoWriteBack)
1356 address = aarch64_get_reg_u64 (cpu, rn, SP_OK);
1361 aarch64_set_mem_u16 (cpu, address, aarch64_get_reg_u16 (cpu, rt, NO_SP));
1366 if (wb != NoWriteBack)
1367 aarch64_set_reg_u64 (cpu, rn, SP_OK, address);
1370 /* 32 bit store short scaled or unscaled zero-
1371 or sign-extended 32-bit register offset. */
1373 strh_scale_ext (sim_cpu *cpu, Scaling scaling, Extension extension)
1375 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
1376 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
1377 unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
1378 /* rn may reference SP, rm and rt must reference ZR */
1380 uint64_t address = aarch64_get_reg_u64 (cpu, rn, SP_OK);
1381 int64_t extended = extend (aarch64_get_reg_u32 (cpu, rm, NO_SP), extension);
1382 uint64_t displacement = OPT_SCALE (extended, 16, scaling);
1384 aarch64_set_mem_u16 (cpu, address + displacement,
1385 aarch64_get_reg_u16 (cpu, rt, NO_SP));
1388 /* Prefetch unsigned 12 bit. */
1390 prfm_abs (sim_cpu *cpu, uint32_t offset)
1392 /* instr[4,0] = prfop : 00000 ==> PLDL1KEEP, 00001 ==> PLDL1STRM,
1393 00010 ==> PLDL2KEEP, 00001 ==> PLDL2STRM,
1394 00100 ==> PLDL3KEEP, 00101 ==> PLDL3STRM,
1395 10000 ==> PSTL1KEEP, 10001 ==> PSTL1STRM,
1396 10010 ==> PSTL2KEEP, 10001 ==> PSTL2STRM,
1397 10100 ==> PSTL3KEEP, 10101 ==> PSTL3STRM,
1399 PrfOp prfop = prfop (aarch64_get_instr (cpu), 4, 0);
1400 uint64_t address = aarch64_get_reg_u64 (cpu, rn, SP_OK)
1401 + SCALE (offset, 64). */
1403 /* TODO : implement prefetch of address. */
1406 /* Prefetch scaled or unscaled zero- or sign-extended 32-bit register offset. */
1408 prfm_scale_ext (sim_cpu *cpu, Scaling scaling, Extension extension)
1410 /* instr[4,0] = prfop : 00000 ==> PLDL1KEEP, 00001 ==> PLDL1STRM,
1411 00010 ==> PLDL2KEEP, 00001 ==> PLDL2STRM,
1412 00100 ==> PLDL3KEEP, 00101 ==> PLDL3STRM,
1413 10000 ==> PSTL1KEEP, 10001 ==> PSTL1STRM,
1414 10010 ==> PSTL2KEEP, 10001 ==> PSTL2STRM,
1415 10100 ==> PSTL3KEEP, 10101 ==> PSTL3STRM,
1417 rn may reference SP, rm may only reference ZR
1418 PrfOp prfop = prfop (aarch64_get_instr (cpu), 4, 0);
1419 uint64_t base = aarch64_get_reg_u64 (cpu, rn, SP_OK);
1420 int64_t extended = extend (aarch64_get_reg_u32 (cpu, rm, NO_SP),
1422 uint64_t displacement = OPT_SCALE (extended, 64, scaling);
1423 uint64_t address = base + displacement. */
1425 /* TODO : implement prefetch of address */
1428 /* 64 bit pc-relative prefetch. */
1430 prfm_pcrel (sim_cpu *cpu, int32_t offset)
1432 /* instr[4,0] = prfop : 00000 ==> PLDL1KEEP, 00001 ==> PLDL1STRM,
1433 00010 ==> PLDL2KEEP, 00001 ==> PLDL2STRM,
1434 00100 ==> PLDL3KEEP, 00101 ==> PLDL3STRM,
1435 10000 ==> PSTL1KEEP, 10001 ==> PSTL1STRM,
1436 10010 ==> PSTL2KEEP, 10001 ==> PSTL2STRM,
1437 10100 ==> PSTL3KEEP, 10101 ==> PSTL3STRM,
1439 PrfOp prfop = prfop (aarch64_get_instr (cpu), 4, 0);
1440 uint64_t address = aarch64_get_PC (cpu) + offset. */
1442 /* TODO : implement this */
1445 /* Load-store exclusive. */
1450 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
1451 unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
1452 uint64_t address = aarch64_get_reg_u64 (cpu, rn, SP_OK);
1453 int size = uimm (aarch64_get_instr (cpu), 31, 30);
1454 /* int ordered = uimm (aarch64_get_instr (cpu), 15, 15); */
1455 /* int exclusive = ! uimm (aarch64_get_instr (cpu), 23, 23); */
1460 aarch64_set_reg_u64 (cpu, rt, NO_SP, aarch64_get_mem_u8 (cpu, address));
1463 aarch64_set_reg_u64 (cpu, rt, NO_SP, aarch64_get_mem_u16 (cpu, address));
1466 aarch64_set_reg_u64 (cpu, rt, NO_SP, aarch64_get_mem_u32 (cpu, address));
1469 aarch64_set_reg_u64 (cpu, rt, NO_SP, aarch64_get_mem_u64 (cpu, address));
1479 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
1480 unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
1481 unsigned rs = uimm (aarch64_get_instr (cpu), 20, 16);
1482 uint64_t address = aarch64_get_reg_u64 (cpu, rn, SP_OK);
1483 int size = uimm (aarch64_get_instr (cpu), 31, 30);
1484 uint64_t data = aarch64_get_reg_u64 (cpu, rt, NO_SP);
1488 case 0: aarch64_set_mem_u8 (cpu, address, data); break;
1489 case 1: aarch64_set_mem_u16 (cpu, address, data); break;
1490 case 2: aarch64_set_mem_u32 (cpu, address, data); break;
1491 case 3: aarch64_set_mem_u64 (cpu, address, data); break;
1492 default: HALT_UNALLOC;
1495 aarch64_set_reg_u64 (cpu, rs, NO_SP, 0); /* Always exclusive... */
1499 dexLoadLiteral (sim_cpu *cpu)
1501 /* instr[29,27] == 011
1503 instr[31,30:26] = opc: 000 ==> LDRW, 001 ==> FLDRS
1504 010 ==> LDRX, 011 ==> FLDRD
1505 100 ==> LDRSW, 101 ==> FLDRQ
1506 110 ==> PRFM, 111 ==> UNALLOC
1507 instr[26] ==> V : 0 ==> GReg, 1 ==> FReg
1508 instr[23, 5] == simm19 */
1510 /* unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0); */
1511 uint32_t dispatch = ( (uimm (aarch64_get_instr (cpu), 31, 30) << 1)
1512 | uimm (aarch64_get_instr (cpu), 26, 26));
1513 int32_t imm = simm32 (aarch64_get_instr (cpu), 23, 5);
1517 case 0: ldr32_pcrel (cpu, imm); break;
1518 case 1: fldrs_pcrel (cpu, imm); break;
1519 case 2: ldr_pcrel (cpu, imm); break;
1520 case 3: fldrd_pcrel (cpu, imm); break;
1521 case 4: ldrsw_pcrel (cpu, imm); break;
1522 case 5: fldrq_pcrel (cpu, imm); break;
1523 case 6: prfm_pcrel (cpu, imm); break;
1530 /* Immediate arithmetic
1531 The aimm argument is a 12 bit unsigned value or a 12 bit unsigned
1532 value left shifted by 12 bits (done at decode).
1534 N.B. the register args (dest, source) can normally be Xn or SP.
1535 the exception occurs for flag setting instructions which may
1536 only use Xn for the output (dest). */
1538 /* 32 bit add immediate. */
1540 add32 (sim_cpu *cpu, uint32_t aimm)
1542 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
1543 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
1545 aarch64_set_reg_u64 (cpu, rd, SP_OK,
1546 aarch64_get_reg_u32 (cpu, rn, SP_OK) + aimm);
1549 /* 64 bit add immediate. */
1551 add64 (sim_cpu *cpu, uint32_t aimm)
1553 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
1554 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
1556 aarch64_set_reg_u64 (cpu, rd, SP_OK,
1557 aarch64_get_reg_u64 (cpu, rn, SP_OK) + aimm);
1561 set_flags_for_add32 (sim_cpu *cpu, int32_t value1, int32_t value2)
1563 int32_t result = value1 + value2;
1564 int64_t sresult = (int64_t) value1 + (int64_t) value2;
1565 uint64_t uresult = (uint64_t)(uint32_t) value1
1566 + (uint64_t)(uint32_t) value2;
1572 if (result & (1 << 31))
1575 if (uresult != result)
1578 if (sresult != result)
1581 aarch64_set_CPSR (cpu, flags);
1585 set_flags_for_add64 (sim_cpu *cpu, uint64_t value1, uint64_t value2)
1587 int64_t sval1 = value1;
1588 int64_t sval2 = value2;
1589 uint64_t result = value1 + value2;
1590 int64_t sresult = sval1 + sval2;
1596 if (result & (1ULL << 63))
1603 /* Negative plus a negative. Overflow happens if
1604 the result is greater than either of the operands. */
1605 if (sresult > sval1 || sresult > sval2)
1608 /* else Negative plus a positive. Overflow cannot happen. */
1610 else /* value1 is +ve. */
1614 /* Overflow can only occur if we computed "0 - MININT". */
1615 if (sval1 == 0 && sval2 == (1LL << 63))
1620 /* Postive plus positive - overflow has happened if the
1621 result is smaller than either of the operands. */
1622 if (result < value1 || result < value2)
1627 aarch64_set_CPSR (cpu, flags);
1630 #define NEG(a) (((a) & signbit) == signbit)
1631 #define POS(a) (((a) & signbit) == 0)
1634 set_flags_for_sub32 (sim_cpu *cpu, uint32_t value1, uint32_t value2)
1636 uint32_t result = value1 - value2;
1638 uint32_t signbit = 1ULL << 31;
1646 if ( (NEG (value1) && POS (value2))
1647 || (NEG (value1) && POS (result))
1648 || (POS (value2) && POS (result)))
1651 if ( (NEG (value1) && POS (value2) && POS (result))
1652 || (POS (value1) && NEG (value2) && NEG (result)))
1655 aarch64_set_CPSR (cpu, flags);
1659 set_flags_for_sub64 (sim_cpu *cpu, uint64_t value1, uint64_t value2)
1661 uint64_t result = value1 - value2;
1663 uint64_t signbit = 1ULL << 63;
1671 if ( (NEG (value1) && POS (value2))
1672 || (NEG (value1) && POS (result))
1673 || (POS (value2) && POS (result)))
1676 if ( (NEG (value1) && POS (value2) && POS (result))
1677 || (POS (value1) && NEG (value2) && NEG (result)))
1680 aarch64_set_CPSR (cpu, flags);
1684 set_flags_for_binop32 (sim_cpu *cpu, uint32_t result)
1693 if (result & (1 << 31))
1698 aarch64_set_CPSR (cpu, flags);
1702 set_flags_for_binop64 (sim_cpu *cpu, uint64_t result)
1711 if (result & (1ULL << 63))
1716 aarch64_set_CPSR (cpu, flags);
1719 /* 32 bit add immediate set flags. */
1721 adds32 (sim_cpu *cpu, uint32_t aimm)
1723 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
1724 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
1725 /* TODO : do we need to worry about signs here? */
1726 int32_t value1 = aarch64_get_reg_s32 (cpu, rn, SP_OK);
1728 aarch64_set_reg_u64 (cpu, rd, NO_SP, value1 + aimm);
1729 set_flags_for_add32 (cpu, value1, aimm);
1732 /* 64 bit add immediate set flags. */
1734 adds64 (sim_cpu *cpu, uint32_t aimm)
1736 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
1737 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
1738 uint64_t value1 = aarch64_get_reg_u64 (cpu, rn, SP_OK);
1739 uint64_t value2 = aimm;
1741 aarch64_set_reg_u64 (cpu, rd, NO_SP, value1 + value2);
1742 set_flags_for_add64 (cpu, value1, value2);
1745 /* 32 bit sub immediate. */
1747 sub32 (sim_cpu *cpu, uint32_t aimm)
1749 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
1750 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
1752 aarch64_set_reg_u64 (cpu, rd, SP_OK,
1753 aarch64_get_reg_u32 (cpu, rn, SP_OK) - aimm);
1756 /* 64 bit sub immediate. */
1758 sub64 (sim_cpu *cpu, uint32_t aimm)
1760 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
1761 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
1763 aarch64_set_reg_u64 (cpu, rd, SP_OK,
1764 aarch64_get_reg_u64 (cpu, rn, SP_OK) - aimm);
1767 /* 32 bit sub immediate set flags. */
1769 subs32 (sim_cpu *cpu, uint32_t aimm)
1771 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
1772 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
1773 uint32_t value1 = aarch64_get_reg_u64 (cpu, rn, SP_OK);
1774 uint32_t value2 = aimm;
1776 aarch64_set_reg_u64 (cpu, rd, NO_SP, value1 - value2);
1777 set_flags_for_sub32 (cpu, value1, value2);
1780 /* 64 bit sub immediate set flags. */
1782 subs64 (sim_cpu *cpu, uint32_t aimm)
1784 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
1785 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
1786 uint64_t value1 = aarch64_get_reg_u64 (cpu, rn, SP_OK);
1787 uint32_t value2 = aimm;
1789 aarch64_set_reg_u64 (cpu, rd, NO_SP, value1 - value2);
1790 set_flags_for_sub64 (cpu, value1, value2);
1793 /* Data Processing Register. */
1795 /* First two helpers to perform the shift operations. */
1797 static inline uint32_t
1798 shifted32 (uint32_t value, Shift shift, uint32_t count)
1804 return (value << count);
1806 return (value >> count);
1809 int32_t svalue = value;
1810 return (svalue >> count);
1814 uint32_t top = value >> count;
1815 uint32_t bottom = value << (32 - count);
1816 return (bottom | top);
1821 static inline uint64_t
1822 shifted64 (uint64_t value, Shift shift, uint32_t count)
1828 return (value << count);
1830 return (value >> count);
1833 int64_t svalue = value;
1834 return (svalue >> count);
1838 uint64_t top = value >> count;
1839 uint64_t bottom = value << (64 - count);
1840 return (bottom | top);
1845 /* Arithmetic shifted register.
1846 These allow an optional LSL, ASR or LSR to the second source
1847 register with a count up to the register bit count.
1849 N.B register args may not be SP. */
1851 /* 32 bit ADD shifted register. */
1853 add32_shift (sim_cpu *cpu, Shift shift, uint32_t count)
1855 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
1856 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
1857 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
1859 aarch64_set_reg_u64 (cpu, rd, NO_SP,
1860 aarch64_get_reg_u32 (cpu, rn, NO_SP)
1861 + shifted32 (aarch64_get_reg_u32 (cpu, rm, NO_SP),
1865 /* 64 bit ADD shifted register. */
1867 add64_shift (sim_cpu *cpu, Shift shift, uint32_t count)
1869 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
1870 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
1871 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
1873 aarch64_set_reg_u64 (cpu, rd, NO_SP,
1874 aarch64_get_reg_u64 (cpu, rn, NO_SP)
1875 + shifted64 (aarch64_get_reg_u64 (cpu, rm, NO_SP),
1879 /* 32 bit ADD shifted register setting flags. */
1881 adds32_shift (sim_cpu *cpu, Shift shift, uint32_t count)
1883 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
1884 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
1885 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
1887 uint32_t value1 = aarch64_get_reg_u32 (cpu, rn, NO_SP);
1888 uint32_t value2 = shifted32 (aarch64_get_reg_u32 (cpu, rm, NO_SP),
1891 aarch64_set_reg_u64 (cpu, rd, NO_SP, value1 + value2);
1892 set_flags_for_add32 (cpu, value1, value2);
1895 /* 64 bit ADD shifted register setting flags. */
1897 adds64_shift (sim_cpu *cpu, Shift shift, uint32_t count)
1899 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
1900 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
1901 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
1903 uint64_t value1 = aarch64_get_reg_u64 (cpu, rn, NO_SP);
1904 uint64_t value2 = shifted64 (aarch64_get_reg_u64 (cpu, rm, NO_SP),
1907 aarch64_set_reg_u64 (cpu, rd, NO_SP, value1 + value2);
1908 set_flags_for_add64 (cpu, value1, value2);
1911 /* 32 bit SUB shifted register. */
1913 sub32_shift (sim_cpu *cpu, Shift shift, uint32_t count)
1915 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
1916 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
1917 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
1919 aarch64_set_reg_u64 (cpu, rd, NO_SP,
1920 aarch64_get_reg_u32 (cpu, rn, NO_SP)
1921 - shifted32 (aarch64_get_reg_u32 (cpu, rm, NO_SP),
1925 /* 64 bit SUB shifted register. */
1927 sub64_shift (sim_cpu *cpu, Shift shift, uint32_t count)
1929 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
1930 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
1931 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
1933 aarch64_set_reg_u64 (cpu, rd, NO_SP,
1934 aarch64_get_reg_u64 (cpu, rn, NO_SP)
1935 - shifted64 (aarch64_get_reg_u64 (cpu, rm, NO_SP),
1939 /* 32 bit SUB shifted register setting flags. */
1941 subs32_shift (sim_cpu *cpu, Shift shift, uint32_t count)
1943 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
1944 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
1945 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
1947 uint32_t value1 = aarch64_get_reg_u32 (cpu, rn, NO_SP);
1948 uint32_t value2 = shifted32 (aarch64_get_reg_u32 (cpu, rm, NO_SP),
1951 aarch64_set_reg_u64 (cpu, rd, NO_SP, value1 - value2);
1952 set_flags_for_sub32 (cpu, value1, value2);
1955 /* 64 bit SUB shifted register setting flags. */
1957 subs64_shift (sim_cpu *cpu, Shift shift, uint32_t count)
1959 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
1960 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
1961 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
1963 uint64_t value1 = aarch64_get_reg_u64 (cpu, rn, NO_SP);
1964 uint64_t value2 = shifted64 (aarch64_get_reg_u64 (cpu, rm, NO_SP),
1967 aarch64_set_reg_u64 (cpu, rd, NO_SP, value1 - value2);
1968 set_flags_for_sub64 (cpu, value1, value2);
1971 /* First a couple more helpers to fetch the
1972 relevant source register element either
1973 sign or zero extended as required by the
1977 extreg32 (sim_cpu *cpu, unsigned int lo, Extension extension)
1981 case UXTB: return aarch64_get_reg_u8 (cpu, lo, NO_SP);
1982 case UXTH: return aarch64_get_reg_u16 (cpu, lo, NO_SP);
1983 case UXTW: /* Fall through. */
1984 case UXTX: return aarch64_get_reg_u32 (cpu, lo, NO_SP);
1985 case SXTB: return aarch64_get_reg_s8 (cpu, lo, NO_SP);
1986 case SXTH: return aarch64_get_reg_s16 (cpu, lo, NO_SP);
1987 case SXTW: /* Fall through. */
1988 case SXTX: /* Fall through. */
1989 default: return aarch64_get_reg_s32 (cpu, lo, NO_SP);
1994 extreg64 (sim_cpu *cpu, unsigned int lo, Extension extension)
1998 case UXTB: return aarch64_get_reg_u8 (cpu, lo, NO_SP);
1999 case UXTH: return aarch64_get_reg_u16 (cpu, lo, NO_SP);
2000 case UXTW: return aarch64_get_reg_u32 (cpu, lo, NO_SP);
2001 case UXTX: return aarch64_get_reg_u64 (cpu, lo, NO_SP);
2002 case SXTB: return aarch64_get_reg_s8 (cpu, lo, NO_SP);
2003 case SXTH: return aarch64_get_reg_s16 (cpu, lo, NO_SP);
2004 case SXTW: return aarch64_get_reg_s32 (cpu, lo, NO_SP);
2006 default: return aarch64_get_reg_s64 (cpu, lo, NO_SP);
2010 /* Arithmetic extending register
2011 These allow an optional sign extension of some portion of the
2012 second source register followed by an optional left shift of
2013 between 1 and 4 bits (i.e. a shift of 0-4 bits???)
2015 N.B output (dest) and first input arg (source) may normally be Xn
2016 or SP. However, for flag setting operations dest can only be
2017 Xn. Second input registers are always Xn. */
2019 /* 32 bit ADD extending register. */
2021 add32_ext (sim_cpu *cpu, Extension extension, uint32_t shift)
2023 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
2024 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
2025 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
2027 aarch64_set_reg_u64 (cpu, rd, SP_OK,
2028 aarch64_get_reg_u32 (cpu, rn, SP_OK)
2029 + (extreg32 (cpu, rm, extension) << shift));
2032 /* 64 bit ADD extending register.
2033 N.B. This subsumes the case with 64 bit source2 and UXTX #n or LSL #0. */
2035 add64_ext (sim_cpu *cpu, Extension extension, uint32_t shift)
2037 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
2038 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
2039 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
2041 aarch64_set_reg_u64 (cpu, rd, SP_OK,
2042 aarch64_get_reg_u64 (cpu, rn, SP_OK)
2043 + (extreg64 (cpu, rm, extension) << shift));
2046 /* 32 bit ADD extending register setting flags. */
2048 adds32_ext (sim_cpu *cpu, Extension extension, uint32_t shift)
2050 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
2051 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
2052 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
2054 uint32_t value1 = aarch64_get_reg_u32 (cpu, rn, SP_OK);
2055 uint32_t value2 = extreg32 (cpu, rm, extension) << shift;
2057 aarch64_set_reg_u64 (cpu, rd, NO_SP, value1 + value2);
2058 set_flags_for_add32 (cpu, value1, value2);
2061 /* 64 bit ADD extending register setting flags */
2062 /* N.B. this subsumes the case with 64 bit source2 and UXTX #n or LSL #0 */
2064 adds64_ext (sim_cpu *cpu, Extension extension, uint32_t shift)
2066 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
2067 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
2068 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
2070 uint64_t value1 = aarch64_get_reg_u64 (cpu, rn, SP_OK);
2071 uint64_t value2 = extreg64 (cpu, rm, extension) << shift;
2073 aarch64_set_reg_u64 (cpu, rd, NO_SP, value1 + value2);
2074 set_flags_for_add64 (cpu, value1, value2);
2077 /* 32 bit SUB extending register. */
2079 sub32_ext (sim_cpu *cpu, Extension extension, uint32_t shift)
2081 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
2082 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
2083 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
2085 aarch64_set_reg_u64 (cpu, rd, SP_OK,
2086 aarch64_get_reg_u32 (cpu, rn, SP_OK)
2087 - (extreg32 (cpu, rm, extension) << shift));
2090 /* 64 bit SUB extending register. */
2091 /* N.B. this subsumes the case with 64 bit source2 and UXTX #n or LSL #0. */
2093 sub64_ext (sim_cpu *cpu, Extension extension, uint32_t shift)
2095 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
2096 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
2097 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
2099 aarch64_set_reg_u64 (cpu, rd, SP_OK,
2100 aarch64_get_reg_u64 (cpu, rn, SP_OK)
2101 - (extreg64 (cpu, rm, extension) << shift));
2104 /* 32 bit SUB extending register setting flags. */
2106 subs32_ext (sim_cpu *cpu, Extension extension, uint32_t shift)
2108 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
2109 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
2110 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
2112 uint32_t value1 = aarch64_get_reg_u32 (cpu, rn, SP_OK);
2113 uint32_t value2 = extreg32 (cpu, rm, extension) << shift;
2115 aarch64_set_reg_u64 (cpu, rd, NO_SP, value1 - value2);
2116 set_flags_for_sub32 (cpu, value1, value2);
2119 /* 64 bit SUB extending register setting flags */
2120 /* N.B. this subsumes the case with 64 bit source2 and UXTX #n or LSL #0 */
2122 subs64_ext (sim_cpu *cpu, Extension extension, uint32_t shift)
2124 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
2125 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
2126 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
2128 uint64_t value1 = aarch64_get_reg_u64 (cpu, rn, SP_OK);
2129 uint64_t value2 = extreg64 (cpu, rm, extension) << shift;
2131 aarch64_set_reg_u64 (cpu, rd, NO_SP, value1 - value2);
2132 set_flags_for_sub64 (cpu, value1, value2);
2136 dexAddSubtractImmediate (sim_cpu *cpu)
2138 /* instr[31] = size : 0 ==> 32 bit, 1 ==> 64 bit
2139 instr[30] = op : 0 ==> ADD, 1 ==> SUB
2140 instr[29] = set : 0 ==> no flags, 1 ==> set flags
2141 instr[28,24] = 10001
2142 instr[23,22] = shift : 00 == LSL#0, 01 = LSL#12 1x = UNALLOC
2143 instr[21,10] = uimm12
2147 /* N.B. the shift is applied at decode before calling the add/sub routine. */
2148 uint32_t shift = uimm (aarch64_get_instr (cpu), 23, 22);
2149 uint32_t imm = uimm (aarch64_get_instr (cpu), 21, 10);
2150 uint32_t dispatch = uimm (aarch64_get_instr (cpu), 31, 29);
2152 NYI_assert (28, 24, 0x11);
2162 case 0: add32 (cpu, imm); break;
2163 case 1: adds32 (cpu, imm); break;
2164 case 2: sub32 (cpu, imm); break;
2165 case 3: subs32 (cpu, imm); break;
2166 case 4: add64 (cpu, imm); break;
2167 case 5: adds64 (cpu, imm); break;
2168 case 6: sub64 (cpu, imm); break;
2169 case 7: subs64 (cpu, imm); break;
2176 dexAddSubtractShiftedRegister (sim_cpu *cpu)
2178 /* instr[31] = size : 0 ==> 32 bit, 1 ==> 64 bit
2179 instr[30,29] = op : 00 ==> ADD, 01 ==> ADDS, 10 ==> SUB, 11 ==> SUBS
2180 instr[28,24] = 01011
2181 instr[23,22] = shift : 0 ==> LSL, 1 ==> LSR, 2 ==> ASR, 3 ==> UNALLOC
2184 instr[15,10] = count : must be 0xxxxx for 32 bit
2188 uint32_t size = uimm (aarch64_get_instr (cpu), 31, 31);
2189 /* 32 bit operations must have count[5] = 0
2190 or else we have an UNALLOC. */
2191 uint32_t count = uimm (aarch64_get_instr (cpu), 15, 10);
2192 /* Shift encoded as ROR is unallocated. */
2193 Shift shiftType = shift (aarch64_get_instr (cpu), 22);
2194 /* Dispatch on size:op i.e aarch64_get_instr (cpu)[31,29]. */
2195 uint32_t dispatch = uimm (aarch64_get_instr (cpu), 31, 29);
2197 NYI_assert (28, 24, 0x0B);
2198 NYI_assert (21, 21, 0);
2200 if (shiftType == ROR)
2203 if (!size && uimm (count, 5, 5))
2208 case 0: add32_shift (cpu, shiftType, count); break;
2209 case 1: adds32_shift (cpu, shiftType, count); break;
2210 case 2: sub32_shift (cpu, shiftType, count); break;
2211 case 3: subs32_shift (cpu, shiftType, count); break;
2212 case 4: add64_shift (cpu, shiftType, count); break;
2213 case 5: adds64_shift (cpu, shiftType, count); break;
2214 case 6: sub64_shift (cpu, shiftType, count); break;
2215 case 7: subs64_shift (cpu, shiftType, count); break;
2222 dexAddSubtractExtendedRegister (sim_cpu *cpu)
2224 /* instr[31] = size : 0 ==> 32 bit, 1 ==> 64 bit
2225 instr[30] = op : 0 ==> ADD, 1 ==> SUB
2226 instr[29] = set? : 0 ==> no flags, 1 ==> set flags
2227 instr[28,24] = 01011
2228 instr[23,22] = opt : 0 ==> ok, 1,2,3 ==> UNALLOC
2231 instr[15,13] = option : 000 ==> UXTB, 001 ==> UXTH,
2232 000 ==> LSL|UXTW, 001 ==> UXTZ,
2233 000 ==> SXTB, 001 ==> SXTH,
2234 000 ==> SXTW, 001 ==> SXTX,
2235 instr[12,10] = shift : 0,1,2,3,4 ==> ok, 5,6,7 ==> UNALLOC
2239 Extension extensionType = extension (aarch64_get_instr (cpu), 13);
2240 uint32_t shift = uimm (aarch64_get_instr (cpu), 12, 10);
2241 /* dispatch on size:op:set? i.e aarch64_get_instr (cpu)[31,29] */
2242 uint32_t dispatch = uimm (aarch64_get_instr (cpu), 31, 29);
2244 NYI_assert (28, 24, 0x0B);
2245 NYI_assert (21, 21, 1);
2247 /* Shift may not exceed 4. */
2253 case 0: add32_ext (cpu, extensionType, shift); break;
2254 case 1: adds32_ext (cpu, extensionType, shift); break;
2255 case 2: sub32_ext (cpu, extensionType, shift); break;
2256 case 3: subs32_ext (cpu, extensionType, shift); break;
2257 case 4: add64_ext (cpu, extensionType, shift); break;
2258 case 5: adds64_ext (cpu, extensionType, shift); break;
2259 case 6: sub64_ext (cpu, extensionType, shift); break;
2260 case 7: subs64_ext (cpu, extensionType, shift); break;
2261 default: HALT_UNALLOC;
2265 /* Conditional data processing
2266 Condition register is implicit 3rd source. */
2268 /* 32 bit add with carry. */
2269 /* N.B register args may not be SP. */
2272 adc32 (sim_cpu *cpu)
2274 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
2275 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
2276 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
2278 aarch64_set_reg_u64 (cpu, rd, NO_SP,
2279 aarch64_get_reg_u32 (cpu, rn, NO_SP)
2280 + aarch64_get_reg_u32 (cpu, rm, NO_SP)
2284 /* 64 bit add with carry */
2286 adc64 (sim_cpu *cpu)
2288 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
2289 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
2290 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
2292 aarch64_set_reg_u64 (cpu, rd, NO_SP,
2293 aarch64_get_reg_u64 (cpu, rn, NO_SP)
2294 + aarch64_get_reg_u64 (cpu, rm, NO_SP)
2298 /* 32 bit add with carry setting flags. */
2300 adcs32 (sim_cpu *cpu)
2302 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
2303 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
2304 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
2306 uint32_t value1 = aarch64_get_reg_u32 (cpu, rn, NO_SP);
2307 uint32_t value2 = aarch64_get_reg_u32 (cpu, rm, NO_SP);
2308 uint32_t carry = IS_SET (C);
2310 aarch64_set_reg_u64 (cpu, rd, NO_SP, value1 + value2 + carry);
2311 set_flags_for_add32 (cpu, value1, value2 + carry);
2314 /* 64 bit add with carry setting flags. */
2316 adcs64 (sim_cpu *cpu)
2318 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
2319 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
2320 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
2322 uint64_t value1 = aarch64_get_reg_u64 (cpu, rn, NO_SP);
2323 uint64_t value2 = aarch64_get_reg_u64 (cpu, rm, NO_SP);
2324 uint64_t carry = IS_SET (C);
2326 aarch64_set_reg_u64 (cpu, rd, NO_SP, value1 + value2 + carry);
2327 set_flags_for_add64 (cpu, value1, value2 + carry);
2330 /* 32 bit sub with carry. */
2332 sbc32 (sim_cpu *cpu)
2334 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
2335 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
2336 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
2338 aarch64_set_reg_u64 (cpu, rd, NO_SP,
2339 aarch64_get_reg_u32 (cpu, rn, NO_SP)
2340 - aarch64_get_reg_u32 (cpu, rm, NO_SP)
2344 /* 64 bit sub with carry */
2346 sbc64 (sim_cpu *cpu)
2348 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
2349 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
2350 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
2352 aarch64_set_reg_u64 (cpu, rd, NO_SP,
2353 aarch64_get_reg_u64 (cpu, rn, NO_SP)
2354 - aarch64_get_reg_u64 (cpu, rm, NO_SP)
2358 /* 32 bit sub with carry setting flags */
2360 sbcs32 (sim_cpu *cpu)
2362 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
2363 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
2364 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
2366 uint32_t value1 = aarch64_get_reg_u32 (cpu, rn, NO_SP);
2367 uint32_t value2 = aarch64_get_reg_u32 (cpu, rm, NO_SP);
2368 uint32_t carry = IS_SET (C);
2369 uint32_t result = value1 - value2 + 1 - carry;
2371 aarch64_set_reg_u64 (cpu, rd, NO_SP, result);
2372 set_flags_for_sub32 (cpu, value1, value2 + 1 - carry);
2375 /* 64 bit sub with carry setting flags */
2377 sbcs64 (sim_cpu *cpu)
2379 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
2380 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
2381 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
2383 uint64_t value1 = aarch64_get_reg_u64 (cpu, rn, NO_SP);
2384 uint64_t value2 = aarch64_get_reg_u64 (cpu, rm, NO_SP);
2385 uint64_t carry = IS_SET (C);
2386 uint64_t result = value1 - value2 + 1 - carry;
2388 aarch64_set_reg_u64 (cpu, rd, NO_SP, result);
2389 set_flags_for_sub64 (cpu, value1, value2 + 1 - carry);
2393 dexAddSubtractWithCarry (sim_cpu *cpu)
2395 /* instr[31] = size : 0 ==> 32 bit, 1 ==> 64 bit
2396 instr[30] = op : 0 ==> ADC, 1 ==> SBC
2397 instr[29] = set? : 0 ==> no flags, 1 ==> set flags
2398 instr[28,21] = 1 1010 000
2400 instr[15,10] = op2 : 00000 ==> ok, ow ==> UNALLOC
2404 uint32_t op2 = uimm (aarch64_get_instr (cpu), 15, 10);
2405 /* Dispatch on size:op:set? i.e aarch64_get_instr (cpu)[31,29] */
2406 uint32_t dispatch = uimm (aarch64_get_instr (cpu), 31, 29);
2408 NYI_assert (28, 21, 0xD0);
2415 case 0: adc32 (cpu); break;
2416 case 1: adcs32 (cpu); break;
2417 case 2: sbc32 (cpu); break;
2418 case 3: sbcs32 (cpu); break;
2419 case 4: adc64 (cpu); break;
2420 case 5: adcs64 (cpu); break;
2421 case 6: sbc64 (cpu); break;
2422 case 7: sbcs64 (cpu); break;
2423 default: HALT_UNALLOC;
2428 testConditionCode (sim_cpu *cpu, CondCode cc)
2430 /* This should be reduceable to branchless logic
2431 by some careful testing of bits in CC followed
2432 by the requisite masking and combining of bits
2433 from the flag register.
2435 For now we do it with a switch. */
2440 case EQ: res = IS_SET (Z); break;
2441 case NE: res = IS_CLEAR (Z); break;
2442 case CS: res = IS_SET (C); break;
2443 case CC: res = IS_CLEAR (C); break;
2444 case MI: res = IS_SET (N); break;
2445 case PL: res = IS_CLEAR (N); break;
2446 case VS: res = IS_SET (V); break;
2447 case VC: res = IS_CLEAR (V); break;
2448 case HI: res = IS_SET (C) && IS_CLEAR (Z); break;
2449 case LS: res = IS_CLEAR (C) || IS_SET (Z); break;
2450 case GE: res = IS_SET (N) == IS_SET (V); break;
2451 case LT: res = IS_SET (N) != IS_SET (V); break;
2452 case GT: res = IS_CLEAR (Z) && (IS_SET (N) == IS_SET (V)); break;
2453 case LE: res = IS_SET (Z) || (IS_SET (N) != IS_SET (V)); break;
2464 CondCompare (sim_cpu *cpu) /* aka: ccmp and ccmn */
2466 /* instr[31] = size : 0 ==> 32 bit, 1 ==> 64 bit
2467 instr[30] = compare with positive (0) or negative value (1)
2468 instr[29,21] = 1 1101 0010
2469 instr[20,16] = Rm or const
2471 instr[11] = compare reg (0) or const (1)
2475 instr[3,0] = value for CPSR bits if the comparison does not take place. */
2480 NYI_assert (29, 21, 0x1d2);
2481 NYI_assert (10, 10, 0);
2482 NYI_assert (4, 4, 0);
2484 if (! testConditionCode (cpu, uimm (aarch64_get_instr (cpu), 15, 12)))
2486 aarch64_set_CPSR (cpu, uimm (aarch64_get_instr (cpu), 3, 0));
2490 negate = uimm (aarch64_get_instr (cpu), 30, 30) ? -1 : 1;
2491 rm = uimm (aarch64_get_instr (cpu), 20, 16);
2492 rn = uimm (aarch64_get_instr (cpu), 9, 5);
2494 if (uimm (aarch64_get_instr (cpu), 31, 31))
2496 if (uimm (aarch64_get_instr (cpu), 11, 11))
2497 set_flags_for_sub64 (cpu, aarch64_get_reg_u64 (cpu, rn, SP_OK),
2498 negate * (uint64_t) rm);
2500 set_flags_for_sub64 (cpu, aarch64_get_reg_u64 (cpu, rn, SP_OK),
2501 negate * aarch64_get_reg_u64 (cpu, rm, SP_OK));
2505 if (uimm (aarch64_get_instr (cpu), 11, 11))
2506 set_flags_for_sub32 (cpu, aarch64_get_reg_u32 (cpu, rn, SP_OK),
2509 set_flags_for_sub32 (cpu, aarch64_get_reg_u32 (cpu, rn, SP_OK),
2510 negate * aarch64_get_reg_u32 (cpu, rm, SP_OK));
2515 do_vec_MOV_whole_vector (sim_cpu *cpu)
2517 /* MOV Vd.T, Vs.T (alias for ORR Vd.T, Vn.T, Vm.T where Vn == Vm)
2520 instr[30] = half(0)/full(1)
2521 instr[29,21] = 001110101
2523 instr[15,10] = 000111
2527 unsigned vs = uimm (aarch64_get_instr (cpu), 9, 5);
2528 unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
2530 NYI_assert (29, 21, 0x075);
2531 NYI_assert (15, 10, 0x07);
2533 if (uimm (aarch64_get_instr (cpu), 20, 16) != vs)
2536 if (uimm (aarch64_get_instr (cpu), 30, 30))
2537 aarch64_set_vec_u64 (cpu, vd, 1, aarch64_get_vec_u64 (cpu, vs, 1));
2539 aarch64_set_vec_u64 (cpu, vd, 0, aarch64_get_vec_u64 (cpu, vs, 0));
2543 do_vec_MOV_into_scalar (sim_cpu *cpu)
2546 instr[30] = word(0)/long(1)
2547 instr[29,21] = 00 1110 000
2548 instr[20,18] = element size and index
2549 instr[17,10] = 00 0011 11
2550 instr[9,5] = V source
2551 instr[4,0] = R dest */
2553 unsigned vs = uimm (aarch64_get_instr (cpu), 9, 5);
2554 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
2556 NYI_assert (29, 21, 0x070);
2557 NYI_assert (17, 10, 0x0F);
2559 switch (uimm (aarch64_get_instr (cpu), 20, 18))
2562 aarch64_set_reg_u64 (cpu, rd, NO_SP, aarch64_get_vec_u64 (cpu, vs, 0));
2566 aarch64_set_reg_u64 (cpu, rd, NO_SP, aarch64_get_vec_u64 (cpu, vs, 1));
2573 aarch64_set_reg_u64 (cpu, rd, NO_SP, aarch64_get_vec_u32
2574 (cpu, vs, uimm (aarch64_get_instr (cpu), 20, 19)));
2583 do_vec_INS (sim_cpu *cpu)
2585 /* instr[31,21] = 01001110000
2586 instr[20,16] = element size and index
2587 instr[15,10] = 000111
2588 instr[9,5] = W source
2589 instr[4,0] = V dest */
2592 unsigned rs = uimm (aarch64_get_instr (cpu), 9, 5);
2593 unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
2595 NYI_assert (31, 21, 0x270);
2596 NYI_assert (15, 10, 0x07);
2598 if (uimm (aarch64_get_instr (cpu), 16, 16))
2600 index = uimm (aarch64_get_instr (cpu), 20, 17);
2601 aarch64_set_vec_u8 (cpu, vd, index,
2602 aarch64_get_reg_u8 (cpu, rs, NO_SP));
2604 else if (uimm (aarch64_get_instr (cpu), 17, 17))
2606 index = uimm (aarch64_get_instr (cpu), 20, 18);
2607 aarch64_set_vec_u16 (cpu, vd, index,
2608 aarch64_get_reg_u16 (cpu, rs, NO_SP));
2610 else if (uimm (aarch64_get_instr (cpu), 18, 18))
2612 index = uimm (aarch64_get_instr (cpu), 20, 19);
2613 aarch64_set_vec_u32 (cpu, vd, index,
2614 aarch64_get_reg_u32 (cpu, rs, NO_SP));
2616 else if (uimm (aarch64_get_instr (cpu), 19, 19))
2618 index = uimm (aarch64_get_instr (cpu), 20, 20);
2619 aarch64_set_vec_u64 (cpu, vd, index,
2620 aarch64_get_reg_u64 (cpu, rs, NO_SP));
2627 do_vec_DUP_vector_into_vector (sim_cpu *cpu)
2630 instr[30] = half(0)/full(1)
2631 instr[29,21] = 00 1110 000
2632 instr[20,16] = element size and index
2633 instr[15,10] = 0000 01
2634 instr[9,5] = V source
2635 instr[4,0] = V dest. */
2637 unsigned full = uimm (aarch64_get_instr (cpu), 30, 30);
2638 unsigned vs = uimm (aarch64_get_instr (cpu), 9, 5);
2639 unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
2642 NYI_assert (29, 21, 0x070);
2643 NYI_assert (15, 10, 0x01);
2645 if (uimm (aarch64_get_instr (cpu), 16, 16))
2647 index = uimm (aarch64_get_instr (cpu), 20, 17);
2649 for (i = 0; i < (full ? 16 : 8); i++)
2650 aarch64_set_vec_u8 (cpu, vd, i, aarch64_get_vec_u8 (cpu, vs, index));
2652 else if (uimm (aarch64_get_instr (cpu), 17, 17))
2654 index = uimm (aarch64_get_instr (cpu), 20, 18);
2656 for (i = 0; i < (full ? 8 : 4); i++)
2657 aarch64_set_vec_u16 (cpu, vd, i, aarch64_get_vec_u16 (cpu, vs, index));
2659 else if (uimm (aarch64_get_instr (cpu), 18, 18))
2661 index = uimm (aarch64_get_instr (cpu), 20, 19);
2663 for (i = 0; i < (full ? 4 : 2); i++)
2664 aarch64_set_vec_u32 (cpu, vd, i, aarch64_get_vec_u32 (cpu, vs, index));
2668 if (uimm (aarch64_get_instr (cpu), 19, 19) == 0)
2674 index = uimm (aarch64_get_instr (cpu), 20, 20);
2676 for (i = 0; i < 2; i++)
2677 aarch64_set_vec_u64 (cpu, vd, i, aarch64_get_vec_u64 (cpu, vs, index));
2682 do_vec_TBL (sim_cpu *cpu)
2685 instr[30] = half(0)/full(1)
2686 instr[29,21] = 00 1110 000
2689 instr[14,13] = vec length
2691 instr[9,5] = V start
2692 instr[4,0] = V dest */
2694 int full = uimm (aarch64_get_instr (cpu), 30, 30);
2695 int len = uimm (aarch64_get_instr (cpu), 14, 13) + 1;
2696 unsigned vm = uimm (aarch64_get_instr (cpu), 20, 16);
2697 unsigned vn = uimm (aarch64_get_instr (cpu), 9, 5);
2698 unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
2701 NYI_assert (29, 21, 0x070);
2702 NYI_assert (12, 10, 0);
2704 for (i = 0; i < (full ? 16 : 8); i++)
2706 unsigned int selector = aarch64_get_vec_u8 (cpu, vm, i);
2710 val = aarch64_get_vec_u8 (cpu, vn, selector);
2711 else if (selector < 32)
2712 val = len < 2 ? 0 : aarch64_get_vec_u8 (cpu, vn + 1, selector - 16);
2713 else if (selector < 48)
2714 val = len < 3 ? 0 : aarch64_get_vec_u8 (cpu, vn + 2, selector - 32);
2715 else if (selector < 64)
2716 val = len < 4 ? 0 : aarch64_get_vec_u8 (cpu, vn + 3, selector - 48);
2720 aarch64_set_vec_u8 (cpu, vd, i, val);
2725 do_vec_TRN (sim_cpu *cpu)
2728 instr[30] = half(0)/full(1)
2729 instr[29,24] = 00 1110
2734 instr[14] = TRN1 (0) / TRN2 (1)
2736 instr[9,5] = V source
2737 instr[4,0] = V dest. */
2739 int full = uimm (aarch64_get_instr (cpu), 30, 30);
2740 int second = uimm (aarch64_get_instr (cpu), 14, 14);
2741 unsigned vm = uimm (aarch64_get_instr (cpu), 20, 16);
2742 unsigned vn = uimm (aarch64_get_instr (cpu), 9, 5);
2743 unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
2746 NYI_assert (29, 24, 0x0E);
2747 NYI_assert (13, 10, 0xA);
2749 switch (uimm (aarch64_get_instr (cpu), 23, 22))
2752 for (i = 0; i < (full ? 8 : 4); i++)
2756 aarch64_get_vec_u8 (cpu, second ? vm : vn, i * 2));
2758 (cpu, vd, 1 * 2 + 1,
2759 aarch64_get_vec_u8 (cpu, second ? vn : vm, i * 2 + 1));
2764 for (i = 0; i < (full ? 4 : 2); i++)
2768 aarch64_get_vec_u16 (cpu, second ? vm : vn, i * 2));
2770 (cpu, vd, 1 * 2 + 1,
2771 aarch64_get_vec_u16 (cpu, second ? vn : vm, i * 2 + 1));
2777 (cpu, vd, 0, aarch64_get_vec_u32 (cpu, second ? vm : vn, 0));
2779 (cpu, vd, 1, aarch64_get_vec_u32 (cpu, second ? vn : vm, 1));
2781 (cpu, vd, 2, aarch64_get_vec_u32 (cpu, second ? vm : vn, 2));
2783 (cpu, vd, 3, aarch64_get_vec_u32 (cpu, second ? vn : vm, 3));
2790 aarch64_set_vec_u64 (cpu, vd, 0,
2791 aarch64_get_vec_u64 (cpu, second ? vm : vn, 0));
2792 aarch64_set_vec_u64 (cpu, vd, 1,
2793 aarch64_get_vec_u64 (cpu, second ? vn : vm, 1));
2802 do_vec_DUP_scalar_into_vector (sim_cpu *cpu)
2805 instr[30] = 0=> zero top 64-bits, 1=> duplicate into top 64-bits
2806 [must be 1 for 64-bit xfer]
2807 instr[29,20] = 00 1110 0000
2808 instr[19,16] = element size: 0001=> 8-bits, 0010=> 16-bits,
2809 0100=> 32-bits. 1000=>64-bits
2810 instr[15,10] = 0000 11
2811 instr[9,5] = W source
2812 instr[4,0] = V dest. */
2815 unsigned Vd = uimm (aarch64_get_instr (cpu), 4, 0);
2816 unsigned Rs = uimm (aarch64_get_instr (cpu), 9, 5);
2817 int both = uimm (aarch64_get_instr (cpu), 30, 30);
2819 NYI_assert (29, 20, 0x0E0);
2820 NYI_assert (15, 10, 0x03);
2822 switch (uimm (aarch64_get_instr (cpu), 19, 16))
2825 for (i = 0; i < (both ? 16 : 8); i++)
2826 aarch64_set_vec_u8 (cpu, Vd, i, aarch64_get_reg_u8 (cpu, Rs, NO_SP));
2830 for (i = 0; i < (both ? 8 : 4); i++)
2831 aarch64_set_vec_u16 (cpu, Vd, i, aarch64_get_reg_u16 (cpu, Rs, NO_SP));
2835 for (i = 0; i < (both ? 4 : 2); i++)
2836 aarch64_set_vec_u32 (cpu, Vd, i, aarch64_get_reg_u32 (cpu, Rs, NO_SP));
2842 aarch64_set_vec_u64 (cpu, Vd, 0, aarch64_get_reg_u64 (cpu, Rs, NO_SP));
2843 aarch64_set_vec_u64 (cpu, Vd, 1, aarch64_get_reg_u64 (cpu, Rs, NO_SP));
2852 do_vec_UZP (sim_cpu *cpu)
2855 instr[30] = half(0)/full(1)
2856 instr[29,24] = 00 1110
2857 instr[23,22] = size: byte(00), half(01), word (10), long (11)
2861 instr[14] = lower (0) / upper (1)
2866 int full = uimm (aarch64_get_instr (cpu), 30, 30);
2867 int upper = uimm (aarch64_get_instr (cpu), 14, 14);
2869 unsigned vm = uimm (aarch64_get_instr (cpu), 20, 16);
2870 unsigned vn = uimm (aarch64_get_instr (cpu), 9, 5);
2871 unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
2873 uint64_t val_m1 = aarch64_get_vec_u64 (cpu, vm, 0);
2874 uint64_t val_m2 = aarch64_get_vec_u64 (cpu, vm, 1);
2875 uint64_t val_n1 = aarch64_get_vec_u64 (cpu, vn, 0);
2876 uint64_t val_n2 = aarch64_get_vec_u64 (cpu, vn, 1);
2881 uint64_t input1 = upper ? val_n1 : val_m1;
2882 uint64_t input2 = upper ? val_n2 : val_m2;
2885 NYI_assert (29, 24, 0x0E);
2886 NYI_assert (21, 21, 0);
2887 NYI_assert (15, 15, 0);
2888 NYI_assert (13, 10, 6);
2890 switch (uimm (aarch64_get_instr (cpu), 23, 23))
2893 for (i = 0; i < 8; i++)
2895 val1 |= (input1 >> (i * 8)) & (0xFFULL << (i * 8));
2896 val2 |= (input2 >> (i * 8)) & (0xFFULL << (i * 8));
2901 for (i = 0; i < 4; i++)
2903 val1 |= (input1 >> (i * 16)) & (0xFFFFULL << (i * 16));
2904 val2 |= (input2 >> (i * 16)) & (0xFFFFULL << (i * 16));
2909 val1 = ((input1 & 0xFFFFFFFF) | ((input1 >> 32) & 0xFFFFFFFF00000000ULL));
2910 val2 = ((input2 & 0xFFFFFFFF) | ((input2 >> 32) & 0xFFFFFFFF00000000ULL));
2918 aarch64_set_vec_u64 (cpu, vd, 0, val1);
2920 aarch64_set_vec_u64 (cpu, vd, 1, val2);
2924 do_vec_ZIP (sim_cpu *cpu)
2927 instr[30] = half(0)/full(1)
2928 instr[29,24] = 00 1110
2929 instr[23,22] = size: byte(00), hald(01), word (10), long (11)
2933 instr[14] = lower (0) / upper (1)
2938 int full = uimm (aarch64_get_instr (cpu), 30, 30);
2939 int upper = uimm (aarch64_get_instr (cpu), 14, 14);
2941 unsigned vm = uimm (aarch64_get_instr (cpu), 20, 16);
2942 unsigned vn = uimm (aarch64_get_instr (cpu), 9, 5);
2943 unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
2945 uint64_t val_m1 = aarch64_get_vec_u64 (cpu, vm, 0);
2946 uint64_t val_m2 = aarch64_get_vec_u64 (cpu, vm, 1);
2947 uint64_t val_n1 = aarch64_get_vec_u64 (cpu, vn, 0);
2948 uint64_t val_n2 = aarch64_get_vec_u64 (cpu, vn, 1);
2953 uint64_t input1 = upper ? val_n1 : val_m1;
2954 uint64_t input2 = upper ? val_n2 : val_m2;
2956 NYI_assert (29, 24, 0x0E);
2957 NYI_assert (21, 21, 0);
2958 NYI_assert (15, 15, 0);
2959 NYI_assert (13, 10, 0xE);
2961 switch (uimm (aarch64_get_instr (cpu), 23, 23))
2965 ((input1 << 0) & (0xFF << 0))
2966 | ((input2 << 8) & (0xFF << 8))
2967 | ((input1 << 8) & (0xFF << 16))
2968 | ((input2 << 16) & (0xFF << 24))
2969 | ((input1 << 16) & (0xFFULL << 32))
2970 | ((input2 << 24) & (0xFFULL << 40))
2971 | ((input1 << 24) & (0xFFULL << 48))
2972 | ((input2 << 32) & (0xFFULL << 56));
2975 ((input1 >> 32) & (0xFF << 0))
2976 | ((input2 >> 24) & (0xFF << 8))
2977 | ((input1 >> 24) & (0xFF << 16))
2978 | ((input2 >> 16) & (0xFF << 24))
2979 | ((input1 >> 16) & (0xFFULL << 32))
2980 | ((input2 >> 8) & (0xFFULL << 40))
2981 | ((input1 >> 8) & (0xFFULL << 48))
2982 | ((input2 >> 0) & (0xFFULL << 56));
2987 ((input1 << 0) & (0xFFFF << 0))
2988 | ((input2 << 16) & (0xFFFF << 16))
2989 | ((input1 << 16) & (0xFFFFULL << 32))
2990 | ((input2 << 32) & (0xFFFFULL << 48));
2993 ((input1 >> 32) & (0xFFFF << 0))
2994 | ((input2 >> 16) & (0xFFFF << 16))
2995 | ((input1 >> 16) & (0xFFFFULL << 32))
2996 | ((input2 >> 0) & (0xFFFFULL << 48));
3000 val1 = (input1 & 0xFFFFFFFFULL) | (input2 << 32);
3001 val2 = (input2 & 0xFFFFFFFFULL) | (input1 << 32);
3010 aarch64_set_vec_u64 (cpu, vd, 0, val1);
3012 aarch64_set_vec_u64 (cpu, vd, 1, val2);
3015 /* Floating point immediates are encoded in 8 bits.
3016 fpimm[7] = sign bit.
3017 fpimm[6:4] = signed exponent.
3018 fpimm[3:0] = fraction (assuming leading 1).
3019 i.e. F = s * 1.f * 2^(e - b). */
3022 fp_immediate_for_encoding_32 (uint32_t imm8)
3025 uint32_t s, e, f, i;
3027 s = (imm8 >> 7) & 0x1;
3028 e = (imm8 >> 4) & 0x7;
3031 /* The fp value is s * n/16 * 2r where n is 16+e. */
3032 u = (16.0 + f) / 16.0;
3034 /* N.B. exponent is signed. */
3039 for (i = 0; i <= epos; i++)
3046 for (i = 0; i < eneg; i++)
3057 fp_immediate_for_encoding_64 (uint32_t imm8)
3060 uint32_t s, e, f, i;
3062 s = (imm8 >> 7) & 0x1;
3063 e = (imm8 >> 4) & 0x7;
3066 /* The fp value is s * n/16 * 2r where n is 16+e. */
3067 u = (16.0 + f) / 16.0;
3069 /* N.B. exponent is signed. */
3074 for (i = 0; i <= epos; i++)
3081 for (i = 0; i < eneg; i++)
3092 do_vec_MOV_immediate (sim_cpu *cpu)
3095 instr[30] = full/half selector
3096 instr[29,19] = 00111100000
3097 instr[18,16] = high 3 bits of uimm8
3098 instr[15,12] = size & shift:
3100 0010 => 32-bit + LSL#8
3101 0100 => 32-bit + LSL#16
3102 0110 => 32-bit + LSL#24
3103 1010 => 16-bit + LSL#8
3105 1101 => 32-bit + MSL#16
3106 1100 => 32-bit + MSL#8
3110 instr[9,5] = low 5-bits of uimm8
3113 int full = uimm (aarch64_get_instr (cpu), 30, 30);
3114 unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
3115 unsigned val = uimm (aarch64_get_instr (cpu), 18, 16) << 5
3116 | uimm (aarch64_get_instr (cpu), 9, 5);
3119 NYI_assert (29, 19, 0x1E0);
3120 NYI_assert (11, 10, 1);
3122 switch (uimm (aarch64_get_instr (cpu), 15, 12))
3124 case 0x0: /* 32-bit, no shift. */
3125 case 0x2: /* 32-bit, shift by 8. */
3126 case 0x4: /* 32-bit, shift by 16. */
3127 case 0x6: /* 32-bit, shift by 24. */
3128 val <<= (8 * uimm (aarch64_get_instr (cpu), 14, 13));
3129 for (i = 0; i < (full ? 4 : 2); i++)
3130 aarch64_set_vec_u32 (cpu, vd, i, val);
3133 case 0xa: /* 16-bit, shift by 8. */
3136 case 0x8: /* 16-bit, no shift. */
3137 for (i = 0; i < (full ? 8 : 4); i++)
3138 aarch64_set_vec_u16 (cpu, vd, i, val);
3140 case 0xd: /* 32-bit, mask shift by 16. */
3144 case 0xc: /* 32-bit, mask shift by 8. */
3147 for (i = 0; i < (full ? 4 : 2); i++)
3148 aarch64_set_vec_u32 (cpu, vd, i, val);
3151 case 0xe: /* 8-bit, no shift. */
3152 for (i = 0; i < (full ? 16 : 8); i++)
3153 aarch64_set_vec_u8 (cpu, vd, i, val);
3156 case 0xf: /* FMOV Vs.{2|4}S, #fpimm. */
3158 float u = fp_immediate_for_encoding_32 (val);
3159 for (i = 0; i < (full ? 4 : 2); i++)
3160 aarch64_set_vec_float (cpu, vd, i, u);
3170 do_vec_MVNI (sim_cpu *cpu)
3173 instr[30] = full/half selector
3174 instr[29,19] = 10111100000
3175 instr[18,16] = high 3 bits of uimm8
3176 instr[15,12] = selector
3178 instr[9,5] = low 5-bits of uimm8
3181 int full = uimm (aarch64_get_instr (cpu), 30, 30);
3182 unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
3183 unsigned val = uimm (aarch64_get_instr (cpu), 18, 16) << 5
3184 | uimm (aarch64_get_instr (cpu), 9, 5);
3187 NYI_assert (29, 19, 0x5E0);
3188 NYI_assert (11, 10, 1);
3190 switch (uimm (aarch64_get_instr (cpu), 15, 12))
3192 case 0x0: /* 32-bit, no shift. */
3193 case 0x2: /* 32-bit, shift by 8. */
3194 case 0x4: /* 32-bit, shift by 16. */
3195 case 0x6: /* 32-bit, shift by 24. */
3196 val <<= (8 * uimm (aarch64_get_instr (cpu), 14, 13));
3198 for (i = 0; i < (full ? 4 : 2); i++)
3199 aarch64_set_vec_u32 (cpu, vd, i, val);
3202 case 0xa: /* 16-bit, 8 bit shift. */
3204 case 0x8: /* 16-bit, no shift. */
3206 for (i = 0; i < (full ? 8 : 4); i++)
3207 aarch64_set_vec_u16 (cpu, vd, i, val);
3210 case 0xd: /* 32-bit, mask shift by 16. */
3213 case 0xc: /* 32-bit, mask shift by 8. */
3217 for (i = 0; i < (full ? 4 : 2); i++)
3218 aarch64_set_vec_u32 (cpu, vd, i, val);
3221 case 0xE: /* MOVI Dn, #mask64 */
3225 for (i = 0; i < 8; i++)
3227 mask |= (0xF << (i * 4));
3228 aarch64_set_vec_u64 (cpu, vd, 0, mask);
3229 aarch64_set_vec_u64 (cpu, vd, 1, 0);
3233 case 0xf: /* FMOV Vd.2D, #fpimm. */
3235 double u = fp_immediate_for_encoding_64 (val);
3240 aarch64_set_vec_double (cpu, vd, 0, u);
3241 aarch64_set_vec_double (cpu, vd, 1, u);
3250 #define ABS(A) ((A) < 0 ? - (A) : (A))
3253 do_vec_ABS (sim_cpu *cpu)
3256 instr[30] = half(0)/full(1)
3257 instr[29,24] = 00 1110
3258 instr[23,22] = size: 00=> 8-bit, 01=> 16-bit, 10=> 32-bit, 11=> 64-bit
3259 instr[21,10] = 10 0000 1011 10
3263 unsigned vn = uimm (aarch64_get_instr (cpu), 9, 5);
3264 unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
3265 unsigned full = uimm (aarch64_get_instr (cpu), 30, 30);
3268 NYI_assert (29, 24, 0x0E);
3269 NYI_assert (21, 10, 0x82E);
3271 switch (uimm (aarch64_get_instr (cpu), 23, 22))
3274 for (i = 0; i < (full ? 16 : 8); i++)
3275 aarch64_set_vec_s8 (cpu, vd, i,
3276 ABS (aarch64_get_vec_s8 (cpu, vn, i)));
3280 for (i = 0; i < (full ? 8 : 4); i++)
3281 aarch64_set_vec_s16 (cpu, vd, i,
3282 ABS (aarch64_get_vec_s16 (cpu, vn, i)));
3286 for (i = 0; i < (full ? 4 : 2); i++)
3287 aarch64_set_vec_s32 (cpu, vd, i,
3288 ABS (aarch64_get_vec_s32 (cpu, vn, i)));
3294 for (i = 0; i < 2; i++)
3295 aarch64_set_vec_s64 (cpu, vd, i,
3296 ABS (aarch64_get_vec_s64 (cpu, vn, i)));
3302 do_vec_ADDV (sim_cpu *cpu)
3305 instr[30] = full/half selector
3306 instr[29,24] = 00 1110
3307 instr[23,22] = size: 00=> 8-bit, 01=> 16-bit, 10=> 32-bit, 11=> 64-bit
3308 instr[21,10] = 11 0001 1011 10
3312 unsigned vm = uimm (aarch64_get_instr (cpu), 9, 5);
3313 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
3316 int full = uimm (aarch64_get_instr (cpu), 30, 30);
3318 NYI_assert (29, 24, 0x0E);
3319 NYI_assert (21, 10, 0xC6E);
3321 switch (uimm (aarch64_get_instr (cpu), 23, 22))
3324 for (i = 0; i < (full ? 16 : 8); i++)
3325 val += aarch64_get_vec_u8 (cpu, vm, i);
3326 aarch64_set_reg_u64 (cpu, rd, NO_SP, val);
3330 for (i = 0; i < (full ? 8 : 4); i++)
3331 val += aarch64_get_vec_u16 (cpu, vm, i);
3332 aarch64_set_reg_u64 (cpu, rd, NO_SP, val);
3336 for (i = 0; i < (full ? 4 : 2); i++)
3337 val += aarch64_get_vec_u32 (cpu, vm, i);
3338 aarch64_set_reg_u64 (cpu, rd, NO_SP, val);
3344 val = aarch64_get_vec_u64 (cpu, vm, 0);
3345 val += aarch64_get_vec_u64 (cpu, vm, 1);
3346 aarch64_set_reg_u64 (cpu, rd, NO_SP, val);
3355 do_vec_ins_2 (sim_cpu *cpu)
3357 /* instr[31,21] = 01001110000
3358 instr[20,18] = size & element selector
3360 instr[13] = direction: to vec(0), from vec (1)
3366 unsigned vm = uimm (aarch64_get_instr (cpu), 9, 5);
3367 unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
3369 NYI_assert (31, 21, 0x270);
3370 NYI_assert (17, 14, 0);
3371 NYI_assert (12, 10, 7);
3373 if (uimm (aarch64_get_instr (cpu), 13, 13) == 1)
3375 if (uimm (aarch64_get_instr (cpu), 18, 18) == 1)
3378 elem = uimm (aarch64_get_instr (cpu), 20, 19);
3379 aarch64_set_reg_u64 (cpu, vd, NO_SP,
3380 aarch64_get_vec_u32 (cpu, vm, elem));
3385 if (uimm (aarch64_get_instr (cpu), 19, 19) != 1)
3388 elem = uimm (aarch64_get_instr (cpu), 20, 20);
3389 aarch64_set_reg_u64 (cpu, vd, NO_SP,
3390 aarch64_get_vec_u64 (cpu, vm, elem));
3395 if (uimm (aarch64_get_instr (cpu), 18, 18) == 1)
3398 elem = uimm (aarch64_get_instr (cpu), 20, 19);
3399 aarch64_set_vec_u32 (cpu, vd, elem,
3400 aarch64_get_reg_u32 (cpu, vm, NO_SP));
3405 if (uimm (aarch64_get_instr (cpu), 19, 19) != 1)
3408 elem = uimm (aarch64_get_instr (cpu), 20, 20);
3409 aarch64_set_vec_u64 (cpu, vd, elem,
3410 aarch64_get_reg_u64 (cpu, vm, NO_SP));
3416 do_vec_mull (sim_cpu *cpu)
3419 instr[30] = lower(0)/upper(1) selector
3420 instr[29] = signed(0)/unsigned(1)
3421 instr[28,24] = 0 1110
3422 instr[23,22] = size: 8-bit (00), 16-bit (01), 32-bit (10)
3425 instr[15,10] = 11 0000
3429 int unsign = uimm (aarch64_get_instr (cpu), 29, 29);
3430 int bias = uimm (aarch64_get_instr (cpu), 30, 30);
3431 unsigned vm = uimm (aarch64_get_instr (cpu), 20, 16);
3432 unsigned vn = uimm (aarch64_get_instr (cpu), 9, 5);
3433 unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
3436 NYI_assert (28, 24, 0x0E);
3437 NYI_assert (15, 10, 0x30);
3439 switch (uimm (aarch64_get_instr (cpu), 23, 22))
3445 for (i = 0; i < 8; i++)
3446 aarch64_set_vec_u16 (cpu, vd, i,
3447 aarch64_get_vec_u8 (cpu, vn, i + bias)
3448 * aarch64_get_vec_u8 (cpu, vm, i + bias));
3450 for (i = 0; i < 8; i++)
3451 aarch64_set_vec_s16 (cpu, vd, i,
3452 aarch64_get_vec_s8 (cpu, vn, i + bias)
3453 * aarch64_get_vec_s8 (cpu, vm, i + bias));
3460 for (i = 0; i < 4; i++)
3461 aarch64_set_vec_u32 (cpu, vd, i,
3462 aarch64_get_vec_u16 (cpu, vn, i + bias)
3463 * aarch64_get_vec_u16 (cpu, vm, i + bias));
3465 for (i = 0; i < 4; i++)
3466 aarch64_set_vec_s32 (cpu, vd, i,
3467 aarch64_get_vec_s16 (cpu, vn, i + bias)
3468 * aarch64_get_vec_s16 (cpu, vm, i + bias));
3475 for (i = 0; i < 2; i++)
3476 aarch64_set_vec_u64 (cpu, vd, i,
3477 (uint64_t) aarch64_get_vec_u32 (cpu, vn,
3479 * (uint64_t) aarch64_get_vec_u32 (cpu, vm,
3482 for (i = 0; i < 2; i++)
3483 aarch64_set_vec_s64 (cpu, vd, i,
3484 aarch64_get_vec_s32 (cpu, vn, i + bias)
3485 * aarch64_get_vec_s32 (cpu, vm, i + bias));
3495 do_vec_fadd (sim_cpu *cpu)
3498 instr[30] = half(0)/full(1)
3499 instr[29,24] = 001110
3500 instr[23] = FADD(0)/FSUB(1)
3501 instr[22] = float (0)/double(1)
3504 instr[15,10] = 110101
3508 unsigned vm = uimm (aarch64_get_instr (cpu), 20, 16);
3509 unsigned vn = uimm (aarch64_get_instr (cpu), 9, 5);
3510 unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
3512 int full = uimm (aarch64_get_instr (cpu), 30, 30);
3514 NYI_assert (29, 24, 0x0E);
3515 NYI_assert (21, 21, 1);
3516 NYI_assert (15, 10, 0x35);
3518 if (uimm (aarch64_get_instr (cpu), 23, 23))
3520 if (uimm (aarch64_get_instr (cpu), 22, 22))
3525 for (i = 0; i < 2; i++)
3526 aarch64_set_vec_double (cpu, vd, i,
3527 aarch64_get_vec_double (cpu, vn, i)
3528 - aarch64_get_vec_double (cpu, vm, i));
3532 for (i = 0; i < (full ? 4 : 2); i++)
3533 aarch64_set_vec_float (cpu, vd, i,
3534 aarch64_get_vec_float (cpu, vn, i)
3535 - aarch64_get_vec_float (cpu, vm, i));
3540 if (uimm (aarch64_get_instr (cpu), 22, 22))
3545 for (i = 0; i < 2; i++)
3546 aarch64_set_vec_double (cpu, vd, i,
3547 aarch64_get_vec_double (cpu, vm, i)
3548 + aarch64_get_vec_double (cpu, vn, i));
3552 for (i = 0; i < (full ? 4 : 2); i++)
3553 aarch64_set_vec_float (cpu, vd, i,
3554 aarch64_get_vec_float (cpu, vm, i)
3555 + aarch64_get_vec_float (cpu, vn, i));
3561 do_vec_add (sim_cpu *cpu)
3564 instr[30] = full/half selector
3565 instr[29,24] = 001110
3566 instr[23,22] = size: 00=> 8-bit, 01=> 16-bit, 10=> 32-bit, 11=> 64-bit
3569 instr[15,10] = 100001
3573 unsigned vm = uimm (aarch64_get_instr (cpu), 20, 16);
3574 unsigned vn = uimm (aarch64_get_instr (cpu), 9, 5);
3575 unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
3577 int full = uimm (aarch64_get_instr (cpu), 30, 30);
3579 NYI_assert (29, 24, 0x0E);
3580 NYI_assert (21, 21, 1);
3581 NYI_assert (15, 10, 0x21);
3583 switch (uimm (aarch64_get_instr (cpu), 23, 22))
3586 for (i = 0; i < (full ? 16 : 8); i++)
3587 aarch64_set_vec_u8 (cpu, vd, i, aarch64_get_vec_u8 (cpu, vn, i)
3588 + aarch64_get_vec_u8 (cpu, vm, i));
3592 for (i = 0; i < (full ? 8 : 4); i++)
3593 aarch64_set_vec_u16 (cpu, vd, i, aarch64_get_vec_u16 (cpu, vn, i)
3594 + aarch64_get_vec_u16 (cpu, vm, i));
3598 for (i = 0; i < (full ? 4 : 2); i++)
3599 aarch64_set_vec_u32 (cpu, vd, i, aarch64_get_vec_u32 (cpu, vn, i)
3600 + aarch64_get_vec_u32 (cpu, vm, i));
3606 aarch64_set_vec_u64 (cpu, vd, 0, aarch64_get_vec_u64 (cpu, vn, 0)
3607 + aarch64_get_vec_u64 (cpu, vm, 0));
3608 aarch64_set_vec_u64 (cpu, vd, 1,
3609 aarch64_get_vec_u64 (cpu, vn, 1)
3610 + aarch64_get_vec_u64 (cpu, vm, 1));
3619 do_vec_mul (sim_cpu *cpu)
3622 instr[30] = full/half selector
3623 instr[29,24] = 00 1110
3624 instr[23,22] = size: 00=> 8-bit, 01=> 16-bit, 10=> 32-bit
3627 instr[15,10] = 10 0111
3631 unsigned vm = uimm (aarch64_get_instr (cpu), 20, 16);
3632 unsigned vn = uimm (aarch64_get_instr (cpu), 9, 5);
3633 unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
3635 int full = uimm (aarch64_get_instr (cpu), 30, 30);
3637 NYI_assert (29, 24, 0x0E);
3638 NYI_assert (21, 21, 1);
3639 NYI_assert (15, 10, 0x27);
3641 switch (uimm (aarch64_get_instr (cpu), 23, 22))
3644 for (i = 0; i < (full ? 16 : 8); i++)
3646 uint16_t val = aarch64_get_vec_u8 (cpu, vn, i);
3647 val *= aarch64_get_vec_u8 (cpu, vm, i);
3649 aarch64_set_vec_u16 (cpu, vd, i, val);
3654 for (i = 0; i < (full ? 8 : 4); i++)
3656 uint32_t val = aarch64_get_vec_u16 (cpu, vn, i);
3657 val *= aarch64_get_vec_u16 (cpu, vm, i);
3659 aarch64_set_vec_u32 (cpu, vd, i, val);
3664 for (i = 0; i < (full ? 4 : 2); i++)
3666 uint64_t val = aarch64_get_vec_u32 (cpu, vn, i);
3667 val *= aarch64_get_vec_u32 (cpu, vm, i);
3669 aarch64_set_vec_u64 (cpu, vd, i, val);
3680 do_vec_MLA (sim_cpu *cpu)
3683 instr[30] = full/half selector
3684 instr[29,24] = 00 1110
3685 instr[23,22] = size: 00=> 8-bit, 01=> 16-bit, 10=> 32-bit
3688 instr[15,10] = 1001 01
3692 unsigned vm = uimm (aarch64_get_instr (cpu), 20, 16);
3693 unsigned vn = uimm (aarch64_get_instr (cpu), 9, 5);
3694 unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
3696 int full = uimm (aarch64_get_instr (cpu), 30, 30);
3698 NYI_assert (29, 24, 0x0E);
3699 NYI_assert (21, 21, 1);
3700 NYI_assert (15, 10, 0x25);
3702 switch (uimm (aarch64_get_instr (cpu), 23, 22))
3705 for (i = 0; i < (full ? 16 : 8); i++)
3707 uint16_t val = aarch64_get_vec_u8 (cpu, vn, i);
3708 val *= aarch64_get_vec_u8 (cpu, vm, i);
3709 val += aarch64_get_vec_u8 (cpu, vd, i);
3711 aarch64_set_vec_u16 (cpu, vd, i, val);
3716 for (i = 0; i < (full ? 8 : 4); i++)
3718 uint32_t val = aarch64_get_vec_u16 (cpu, vn, i);
3719 val *= aarch64_get_vec_u16 (cpu, vm, i);
3720 val += aarch64_get_vec_u16 (cpu, vd, i);
3722 aarch64_set_vec_u32 (cpu, vd, i, val);
3727 for (i = 0; i < (full ? 4 : 2); i++)
3729 uint64_t val = aarch64_get_vec_u32 (cpu, vn, i);
3730 val *= aarch64_get_vec_u32 (cpu, vm, i);
3731 val += aarch64_get_vec_u32 (cpu, vd, i);
3733 aarch64_set_vec_u64 (cpu, vd, i, val);
3744 fmaxnm (float a, float b)
3746 if (fpclassify (a) == FP_NORMAL)
3748 if (fpclassify (b) == FP_NORMAL)
3749 return a > b ? a : b;
3752 else if (fpclassify (b) == FP_NORMAL)
3758 fminnm (float a, float b)
3760 if (fpclassify (a) == FP_NORMAL)
3762 if (fpclassify (b) == FP_NORMAL)
3763 return a < b ? a : b;
3766 else if (fpclassify (b) == FP_NORMAL)
3772 dmaxnm (double a, double b)
3774 if (fpclassify (a) == FP_NORMAL)
3776 if (fpclassify (b) == FP_NORMAL)
3777 return a > b ? a : b;
3780 else if (fpclassify (b) == FP_NORMAL)
3786 dminnm (double a, double b)
3788 if (fpclassify (a) == FP_NORMAL)
3790 if (fpclassify (b) == FP_NORMAL)
3791 return a < b ? a : b;
3794 else if (fpclassify (b) == FP_NORMAL)
3800 do_vec_FminmaxNMP (sim_cpu *cpu)
3802 /* aarch64_get_instr (cpu)[31] = 0
3803 aarch64_get_instr (cpu)[30] = half (0)/full (1)
3804 aarch64_get_instr (cpu)[29,24] = 10 1110
3805 aarch64_get_instr (cpu)[23] = max(0)/min(1)
3806 aarch64_get_instr (cpu)[22] = float (0)/double (1)
3807 aarch64_get_instr (cpu)[21] = 1
3808 aarch64_get_instr (cpu)[20,16] = Vn
3809 aarch64_get_instr (cpu)[15,10] = 1100 01
3810 aarch64_get_instr (cpu)[9,5] = Vm
3811 aarch64_get_instr (cpu)[4.0] = Vd. */
3813 unsigned vm = uimm (aarch64_get_instr (cpu), 20, 16);
3814 unsigned vn = uimm (aarch64_get_instr (cpu), 9, 5);
3815 unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
3816 int full = uimm (aarch64_get_instr (cpu), 30, 30);
3818 NYI_assert (29, 24, 0x2E);
3819 NYI_assert (21, 21, 1);
3820 NYI_assert (15, 10, 0x31);
3822 if (uimm (aarch64_get_instr (cpu), 22, 22))
3824 double (* fn)(double, double) = uimm (aarch64_get_instr (cpu), 23, 23)
3829 aarch64_set_vec_double (cpu, vd, 0,
3830 fn (aarch64_get_vec_double (cpu, vn, 0),
3831 aarch64_get_vec_double (cpu, vn, 1)));
3832 aarch64_set_vec_double (cpu, vd, 0,
3833 fn (aarch64_get_vec_double (cpu, vm, 0),
3834 aarch64_get_vec_double (cpu, vm, 1)));
3838 float (* fn)(float, float) = uimm (aarch64_get_instr (cpu), 23, 23)
3841 aarch64_set_vec_float (cpu, vd, 0,
3842 fn (aarch64_get_vec_float (cpu, vn, 0),
3843 aarch64_get_vec_float (cpu, vn, 1)));
3845 aarch64_set_vec_float (cpu, vd, 1,
3846 fn (aarch64_get_vec_float (cpu, vn, 2),
3847 aarch64_get_vec_float (cpu, vn, 3)));
3849 aarch64_set_vec_float (cpu, vd, (full ? 2 : 1),
3850 fn (aarch64_get_vec_float (cpu, vm, 0),
3851 aarch64_get_vec_float (cpu, vm, 1)));
3853 aarch64_set_vec_float (cpu, vd, 3,
3854 fn (aarch64_get_vec_float (cpu, vm, 2),
3855 aarch64_get_vec_float (cpu, vm, 3)));
3860 do_vec_AND (sim_cpu *cpu)
3863 instr[30] = half (0)/full (1)
3864 instr[29,21] = 001110001
3866 instr[15,10] = 000111
3870 unsigned vm = uimm (aarch64_get_instr (cpu), 20, 16);
3871 unsigned vn = uimm (aarch64_get_instr (cpu), 9, 5);
3872 unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
3874 int full = uimm (aarch64_get_instr (cpu), 30, 30);
3876 NYI_assert (29, 21, 0x071);
3877 NYI_assert (15, 10, 0x07);
3879 for (i = 0; i < (full ? 4 : 2); i++)
3880 aarch64_set_vec_u32 (cpu, vd, i,
3881 aarch64_get_vec_u32 (cpu, vn, i)
3882 & aarch64_get_vec_u32 (cpu, vm, i));
3886 do_vec_BSL (sim_cpu *cpu)
3889 instr[30] = half (0)/full (1)
3890 instr[29,21] = 101110011
3892 instr[15,10] = 000111
3896 unsigned vm = uimm (aarch64_get_instr (cpu), 20, 16);
3897 unsigned vn = uimm (aarch64_get_instr (cpu), 9, 5);
3898 unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
3900 int full = uimm (aarch64_get_instr (cpu), 30, 30);
3902 NYI_assert (29, 21, 0x173);
3903 NYI_assert (15, 10, 0x07);
3905 for (i = 0; i < (full ? 16 : 8); i++)
3906 aarch64_set_vec_u8 (cpu, vd, i,
3907 ( aarch64_get_vec_u8 (cpu, vd, i)
3908 & aarch64_get_vec_u8 (cpu, vn, i))
3909 | ((~ aarch64_get_vec_u8 (cpu, vd, i))
3910 & aarch64_get_vec_u8 (cpu, vm, i)));
3914 do_vec_EOR (sim_cpu *cpu)
3917 instr[30] = half (0)/full (1)
3918 instr[29,21] = 10 1110 001
3920 instr[15,10] = 000111
3924 unsigned vm = uimm (aarch64_get_instr (cpu), 20, 16);
3925 unsigned vn = uimm (aarch64_get_instr (cpu), 9, 5);
3926 unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
3928 int full = uimm (aarch64_get_instr (cpu), 30, 30);
3930 NYI_assert (29, 21, 0x171);
3931 NYI_assert (15, 10, 0x07);
3933 for (i = 0; i < (full ? 4 : 2); i++)
3934 aarch64_set_vec_u32 (cpu, vd, i,
3935 aarch64_get_vec_u32 (cpu, vn, i)
3936 ^ aarch64_get_vec_u32 (cpu, vm, i));
3940 do_vec_bit (sim_cpu *cpu)
3943 instr[30] = half (0)/full (1)
3944 instr[29,23] = 10 1110 1
3945 instr[22] = BIT (0) / BIF (1)
3948 instr[15,10] = 0001 11
3952 unsigned vm = uimm (aarch64_get_instr (cpu), 20, 16);
3953 unsigned vn = uimm (aarch64_get_instr (cpu), 9, 5);
3954 unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
3955 unsigned full = uimm (aarch64_get_instr (cpu), 30, 30);
3956 unsigned test_false = uimm (aarch64_get_instr (cpu), 22, 22);
3959 NYI_assert (29, 23, 0x5D);
3960 NYI_assert (21, 21, 1);
3961 NYI_assert (15, 10, 0x07);
3965 for (i = 0; i < (full ? 16 : 8); i++)
3966 if (aarch64_get_vec_u32 (cpu, vn, i) == 0)
3967 aarch64_set_vec_u32 (cpu, vd, i, aarch64_get_vec_u32 (cpu, vm, i));
3971 for (i = 0; i < (full ? 16 : 8); i++)
3972 if (aarch64_get_vec_u32 (cpu, vn, i) != 0)
3973 aarch64_set_vec_u32 (cpu, vd, i, aarch64_get_vec_u32 (cpu, vm, i));
3978 do_vec_ORN (sim_cpu *cpu)
3981 instr[30] = half (0)/full (1)
3982 instr[29,21] = 00 1110 111
3984 instr[15,10] = 00 0111
3988 unsigned vm = uimm (aarch64_get_instr (cpu), 20, 16);
3989 unsigned vn = uimm (aarch64_get_instr (cpu), 9, 5);
3990 unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
3992 int full = uimm (aarch64_get_instr (cpu), 30, 30);
3994 NYI_assert (29, 21, 0x077);
3995 NYI_assert (15, 10, 0x07);
3997 for (i = 0; i < (full ? 16 : 8); i++)
3998 aarch64_set_vec_u8 (cpu, vd, i,
3999 aarch64_get_vec_u8 (cpu, vn, i)
4000 | ~ aarch64_get_vec_u8 (cpu, vm, i));
4004 do_vec_ORR (sim_cpu *cpu)
4007 instr[30] = half (0)/full (1)
4008 instr[29,21] = 00 1110 101
4010 instr[15,10] = 0001 11
4014 unsigned vm = uimm (aarch64_get_instr (cpu), 20, 16);
4015 unsigned vn = uimm (aarch64_get_instr (cpu), 9, 5);
4016 unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
4018 int full = uimm (aarch64_get_instr (cpu), 30, 30);
4020 NYI_assert (29, 21, 0x075);
4021 NYI_assert (15, 10, 0x07);
4023 for (i = 0; i < (full ? 16 : 8); i++)
4024 aarch64_set_vec_u8 (cpu, vd, i,
4025 aarch64_get_vec_u8 (cpu, vn, i)
4026 | aarch64_get_vec_u8 (cpu, vm, i));
4030 do_vec_BIC (sim_cpu *cpu)
4033 instr[30] = half (0)/full (1)
4034 instr[29,21] = 00 1110 011
4036 instr[15,10] = 00 0111
4040 unsigned vm = uimm (aarch64_get_instr (cpu), 20, 16);
4041 unsigned vn = uimm (aarch64_get_instr (cpu), 9, 5);
4042 unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
4044 int full = uimm (aarch64_get_instr (cpu), 30, 30);
4046 NYI_assert (29, 21, 0x073);
4047 NYI_assert (15, 10, 0x07);
4049 for (i = 0; i < (full ? 16 : 8); i++)
4050 aarch64_set_vec_u8 (cpu, vd, i,
4051 aarch64_get_vec_u8 (cpu, vn, i)
4052 & ~ aarch64_get_vec_u8 (cpu, vm, i));
4056 do_vec_XTN (sim_cpu *cpu)
4059 instr[30] = first part (0)/ second part (1)
4060 instr[29,24] = 00 1110
4061 instr[23,22] = size: byte(00), half(01), word (10)
4062 instr[21,10] = 1000 0100 1010
4066 unsigned vs = uimm (aarch64_get_instr (cpu), 9, 5);
4067 unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
4068 unsigned bias = uimm (aarch64_get_instr (cpu), 30, 30);
4071 NYI_assert (29, 24, 0x0E);
4072 NYI_assert (21, 10, 0x84A);
4074 switch (uimm (aarch64_get_instr (cpu), 23, 22))
4078 for (i = 0; i < 8; i++)
4079 aarch64_set_vec_u8 (cpu, vd, i + 8,
4080 aarch64_get_vec_u16 (cpu, vs, i) >> 8);
4082 for (i = 0; i < 8; i++)
4083 aarch64_set_vec_u8 (cpu, vd, i, aarch64_get_vec_u16 (cpu, vs, i));
4088 for (i = 0; i < 4; i++)
4089 aarch64_set_vec_u16 (cpu, vd, i + 4,
4090 aarch64_get_vec_u32 (cpu, vs, i) >> 16);
4092 for (i = 0; i < 4; i++)
4093 aarch64_set_vec_u16 (cpu, vd, i, aarch64_get_vec_u32 (cpu, vs, i));
4098 for (i = 0; i < 2; i++)
4099 aarch64_set_vec_u32 (cpu, vd, i + 4,
4100 aarch64_get_vec_u64 (cpu, vs, i) >> 32);
4102 for (i = 0; i < 2; i++)
4103 aarch64_set_vec_u32 (cpu, vd, i, aarch64_get_vec_u64 (cpu, vs, i));
4112 do_vec_maxv (sim_cpu *cpu)
4115 instr[30] = half(0)/full(1)
4116 instr[29] = signed (0)/unsigned(1)
4117 instr[28,24] = 0 1110
4118 instr[23,22] = size: byte(00), half(01), word (10)
4120 instr[20,17] = 1 000
4121 instr[16] = max(0)/min(1)
4122 instr[15,10] = 1010 10
4123 instr[9,5] = V source
4124 instr[4.0] = R dest. */
4126 unsigned vs = uimm (aarch64_get_instr (cpu), 9, 5);
4127 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
4128 unsigned full = uimm (aarch64_get_instr (cpu), 30, 30);
4131 NYI_assert (28, 24, 0x0E);
4132 NYI_assert (21, 21, 1);
4133 NYI_assert (20, 17, 8);
4134 NYI_assert (15, 10, 0x2A);
4136 switch ((uimm (aarch64_get_instr (cpu), 29, 29) << 1)
4137 | uimm (aarch64_get_instr (cpu), 16, 16))
4139 case 0: /* SMAXV. */
4142 switch (uimm (aarch64_get_instr (cpu), 23, 22))
4145 smax = aarch64_get_vec_s8 (cpu, vs, 0);
4146 for (i = 1; i < (full ? 16 : 8); i++)
4147 smax = max (smax, aarch64_get_vec_s8 (cpu, vs, i));
4150 smax = aarch64_get_vec_s16 (cpu, vs, 0);
4151 for (i = 1; i < (full ? 8 : 4); i++)
4152 smax = max (smax, aarch64_get_vec_s16 (cpu, vs, i));
4155 smax = aarch64_get_vec_s32 (cpu, vs, 0);
4156 for (i = 1; i < (full ? 4 : 2); i++)
4157 smax = max (smax, aarch64_get_vec_s32 (cpu, vs, i));
4163 aarch64_set_reg_s64 (cpu, rd, NO_SP, smax);
4167 case 1: /* SMINV. */
4170 switch (uimm (aarch64_get_instr (cpu), 23, 22))
4173 smin = aarch64_get_vec_s8 (cpu, vs, 0);
4174 for (i = 1; i < (full ? 16 : 8); i++)
4175 smin = min (smin, aarch64_get_vec_s8 (cpu, vs, i));
4178 smin = aarch64_get_vec_s16 (cpu, vs, 0);
4179 for (i = 1; i < (full ? 8 : 4); i++)
4180 smin = min (smin, aarch64_get_vec_s16 (cpu, vs, i));
4183 smin = aarch64_get_vec_s32 (cpu, vs, 0);
4184 for (i = 1; i < (full ? 4 : 2); i++)
4185 smin = min (smin, aarch64_get_vec_s32 (cpu, vs, i));
4191 aarch64_set_reg_s64 (cpu, rd, NO_SP, smin);
4195 case 2: /* UMAXV. */
4198 switch (uimm (aarch64_get_instr (cpu), 23, 22))
4201 umax = aarch64_get_vec_u8 (cpu, vs, 0);
4202 for (i = 1; i < (full ? 16 : 8); i++)
4203 umax = max (umax, aarch64_get_vec_u8 (cpu, vs, i));
4206 umax = aarch64_get_vec_u16 (cpu, vs, 0);
4207 for (i = 1; i < (full ? 8 : 4); i++)
4208 umax = max (umax, aarch64_get_vec_u16 (cpu, vs, i));
4211 umax = aarch64_get_vec_u32 (cpu, vs, 0);
4212 for (i = 1; i < (full ? 4 : 2); i++)
4213 umax = max (umax, aarch64_get_vec_u32 (cpu, vs, i));
4219 aarch64_set_reg_u64 (cpu, rd, NO_SP, umax);
4223 case 3: /* UMINV. */
4226 switch (uimm (aarch64_get_instr (cpu), 23, 22))
4229 umin = aarch64_get_vec_u8 (cpu, vs, 0);
4230 for (i = 1; i < (full ? 16 : 8); i++)
4231 umin = min (umin, aarch64_get_vec_u8 (cpu, vs, i));
4234 umin = aarch64_get_vec_u16 (cpu, vs, 0);
4235 for (i = 1; i < (full ? 8 : 4); i++)
4236 umin = min (umin, aarch64_get_vec_u16 (cpu, vs, i));
4239 umin = aarch64_get_vec_u32 (cpu, vs, 0);
4240 for (i = 1; i < (full ? 4 : 2); i++)
4241 umin = min (umin, aarch64_get_vec_u32 (cpu, vs, i));
4247 aarch64_set_reg_u64 (cpu, rd, NO_SP, umin);
4257 do_vec_fminmaxV (sim_cpu *cpu)
4259 /* instr[31,24] = 0110 1110
4260 instr[23] = max(0)/min(1)
4261 instr[22,14] = 011 0000 11
4262 instr[13,12] = nm(00)/normal(11)
4264 instr[9,5] = V source
4265 instr[4.0] = R dest. */
4267 unsigned vs = uimm (aarch64_get_instr (cpu), 9, 5);
4268 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
4270 float res = aarch64_get_vec_float (cpu, vs, 0);
4272 NYI_assert (31, 24, 0x6E);
4273 NYI_assert (22, 14, 0x0C3);
4274 NYI_assert (11, 10, 2);
4276 if (uimm (aarch64_get_instr (cpu), 23, 23))
4278 switch (uimm (aarch64_get_instr (cpu), 13, 12))
4280 case 0: /* FMNINNMV. */
4281 for (i = 1; i < 4; i++)
4282 res = fminnm (res, aarch64_get_vec_float (cpu, vs, i));
4285 case 3: /* FMINV. */
4286 for (i = 1; i < 4; i++)
4287 res = min (res, aarch64_get_vec_float (cpu, vs, i));
4296 switch (uimm (aarch64_get_instr (cpu), 13, 12))
4298 case 0: /* FMNAXNMV. */
4299 for (i = 1; i < 4; i++)
4300 res = fmaxnm (res, aarch64_get_vec_float (cpu, vs, i));
4303 case 3: /* FMAXV. */
4304 for (i = 1; i < 4; i++)
4305 res = max (res, aarch64_get_vec_float (cpu, vs, i));
4313 aarch64_set_FP_float (cpu, rd, res);
4317 do_vec_Fminmax (sim_cpu *cpu)
4320 instr[30] = half(0)/full(1)
4321 instr[29,24] = 00 1110
4322 instr[23] = max(0)/min(1)
4323 instr[22] = float(0)/double(1)
4327 instr[13,12] = nm(00)/normal(11)
4332 unsigned vm = uimm (aarch64_get_instr (cpu), 20, 16);
4333 unsigned vn = uimm (aarch64_get_instr (cpu), 9, 5);
4334 unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
4335 unsigned full = uimm (aarch64_get_instr (cpu), 30, 30);
4336 unsigned min = uimm (aarch64_get_instr (cpu), 23, 23);
4339 NYI_assert (29, 24, 0x0E);
4340 NYI_assert (21, 21, 1);
4341 NYI_assert (15, 14, 3);
4342 NYI_assert (11, 10, 1);
4344 if (uimm (aarch64_get_instr (cpu), 22, 22))
4346 double (* func)(double, double);
4351 if (uimm (aarch64_get_instr (cpu), 13, 12) == 0)
4352 func = min ? dminnm : dmaxnm;
4353 else if (uimm (aarch64_get_instr (cpu), 13, 12) == 3)
4354 func = min ? fmin : fmax;
4358 for (i = 0; i < 2; i++)
4359 aarch64_set_vec_double (cpu, vd, i,
4360 func (aarch64_get_vec_double (cpu, vn, i),
4361 aarch64_get_vec_double (cpu, vm, i)));
4365 float (* func)(float, float);
4367 if (uimm (aarch64_get_instr (cpu), 13, 12) == 0)
4368 func = min ? fminnm : fmaxnm;
4369 else if (uimm (aarch64_get_instr (cpu), 13, 12) == 3)
4370 func = min ? fminf : fmaxf;
4374 for (i = 0; i < (full ? 4 : 2); i++)
4375 aarch64_set_vec_float (cpu, vd, i,
4376 func (aarch64_get_vec_float (cpu, vn, i),
4377 aarch64_get_vec_float (cpu, vm, i)));
4382 do_vec_SCVTF (sim_cpu *cpu)
4386 instr[29,23] = 00 1110 0
4387 instr[22] = float(0)/double(1)
4388 instr[21,10] = 10 0001 1101 10
4392 unsigned vn = uimm (aarch64_get_instr (cpu), 9, 5);
4393 unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
4394 unsigned full = uimm (aarch64_get_instr (cpu), 30, 30);
4395 unsigned size = uimm (aarch64_get_instr (cpu), 22, 22);
4398 NYI_assert (29, 23, 0x1C);
4399 NYI_assert (21, 10, 0x876);
4406 for (i = 0; i < 2; i++)
4408 double val = (double) aarch64_get_vec_u64 (cpu, vn, i);
4409 aarch64_set_vec_double (cpu, vd, i, val);
4414 for (i = 0; i < (full ? 4 : 2); i++)
4416 float val = (float) aarch64_get_vec_u32 (cpu, vn, i);
4417 aarch64_set_vec_float (cpu, vd, i, val);
4422 #define VEC_CMP(SOURCE, CMP) \
4428 for (i = 0; i < (full ? 16 : 8); i++) \
4429 aarch64_set_vec_u8 (cpu, vd, i, \
4430 aarch64_get_vec_##SOURCE##8 (cpu, vn, i) \
4432 aarch64_get_vec_##SOURCE##8 (cpu, vm, i) \
4436 for (i = 0; i < (full ? 8 : 4); i++) \
4437 aarch64_set_vec_u16 (cpu, vd, i, \
4438 aarch64_get_vec_##SOURCE##16 (cpu, vn, i) \
4440 aarch64_get_vec_##SOURCE##16 (cpu, vm, i) \
4444 for (i = 0; i < (full ? 4 : 2); i++) \
4445 aarch64_set_vec_u32 (cpu, vd, i, \
4446 aarch64_get_vec_##SOURCE##32 (cpu, vn, i) \
4448 aarch64_get_vec_##SOURCE##32 (cpu, vm, i) \
4454 for (i = 0; i < 2; i++) \
4455 aarch64_set_vec_u64 (cpu, vd, i, \
4456 aarch64_get_vec_##SOURCE##64 (cpu, vn, i) \
4458 aarch64_get_vec_##SOURCE##64 (cpu, vm, i) \
4467 #define VEC_CMP0(SOURCE, CMP) \
4473 for (i = 0; i < (full ? 16 : 8); i++) \
4474 aarch64_set_vec_u8 (cpu, vd, i, \
4475 aarch64_get_vec_##SOURCE##8 (cpu, vn, i) \
4479 for (i = 0; i < (full ? 8 : 4); i++) \
4480 aarch64_set_vec_u16 (cpu, vd, i, \
4481 aarch64_get_vec_##SOURCE##16 (cpu, vn, i) \
4485 for (i = 0; i < (full ? 4 : 2); i++) \
4486 aarch64_set_vec_u32 (cpu, vd, i, \
4487 aarch64_get_vec_##SOURCE##32 (cpu, vn, i) \
4493 for (i = 0; i < 2; i++) \
4494 aarch64_set_vec_u64 (cpu, vd, i, \
4495 aarch64_get_vec_##SOURCE##64 (cpu, vn, i) \
4496 CMP 0 ? -1ULL : 0); \
4504 #define VEC_FCMP0(CMP) \
4509 if (uimm (aarch64_get_instr (cpu), 22, 22)) \
4513 for (i = 0; i < 2; i++) \
4514 aarch64_set_vec_u64 (cpu, vd, i, \
4515 aarch64_get_vec_double (cpu, vn, i) \
4516 CMP 0.0 ? -1 : 0); \
4520 for (i = 0; i < (full ? 4 : 2); i++) \
4521 aarch64_set_vec_u32 (cpu, vd, i, \
4522 aarch64_get_vec_float (cpu, vn, i) \
4523 CMP 0.0 ? -1 : 0); \
4529 #define VEC_FCMP(CMP) \
4532 if (uimm (aarch64_get_instr (cpu), 22, 22)) \
4536 for (i = 0; i < 2; i++) \
4537 aarch64_set_vec_u64 (cpu, vd, i, \
4538 aarch64_get_vec_double (cpu, vn, i) \
4540 aarch64_get_vec_double (cpu, vm, i) \
4545 for (i = 0; i < (full ? 4 : 2); i++) \
4546 aarch64_set_vec_u32 (cpu, vd, i, \
4547 aarch64_get_vec_float (cpu, vn, i) \
4549 aarch64_get_vec_float (cpu, vm, i) \
4557 do_vec_compare (sim_cpu *cpu)
4560 instr[30] = half(0)/full(1)
4561 instr[29] = part-of-comparison-type
4562 instr[28,24] = 0 1110
4563 instr[23,22] = size of integer compares: byte(00), half(01), word (10), long (11)
4564 type of float compares: single (-0) / double (-1)
4566 instr[20,16] = Vm or 00000 (compare vs 0)
4567 instr[15,10] = part-of-comparison-type
4571 int full = uimm (aarch64_get_instr (cpu), 30, 30);
4572 int size = uimm (aarch64_get_instr (cpu), 23, 22);
4573 unsigned vm = uimm (aarch64_get_instr (cpu), 20, 16);
4574 unsigned vn = uimm (aarch64_get_instr (cpu), 9, 5);
4575 unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
4578 NYI_assert (28, 24, 0x0E);
4579 NYI_assert (21, 21, 1);
4581 if ((uimm (aarch64_get_instr (cpu), 11, 11)
4582 && uimm (aarch64_get_instr (cpu), 14, 14))
4583 || ((uimm (aarch64_get_instr (cpu), 11, 11) == 0
4584 && uimm (aarch64_get_instr (cpu), 10, 10) == 0)))
4586 /* A compare vs 0. */
4589 if (uimm (aarch64_get_instr (cpu), 15, 10) == 0x2A)
4591 else if (uimm (aarch64_get_instr (cpu), 15, 10) == 0x32
4592 || uimm (aarch64_get_instr (cpu), 15, 10) == 0x3E)
4593 do_vec_fminmaxV (cpu);
4594 else if (uimm (aarch64_get_instr (cpu), 29, 23) == 0x1C
4595 && uimm (aarch64_get_instr (cpu), 21, 10) == 0x876)
4603 if (uimm (aarch64_get_instr (cpu), 14, 14))
4605 /* A floating point compare. */
4606 unsigned decode = (uimm (aarch64_get_instr (cpu), 29, 29) << 5)
4607 | (uimm (aarch64_get_instr (cpu), 23, 23) << 4)
4608 | uimm (aarch64_get_instr (cpu), 13, 10);
4610 NYI_assert (15, 15, 1);
4614 case /* 0b010010: GT#0 */ 0x12: VEC_FCMP0 (>);
4615 case /* 0b110010: GE#0 */ 0x32: VEC_FCMP0 (>=);
4616 case /* 0b010110: EQ#0 */ 0x16: VEC_FCMP0 (==);
4617 case /* 0b110110: LE#0 */ 0x36: VEC_FCMP0 (<=);
4618 case /* 0b011010: LT#0 */ 0x1A: VEC_FCMP0 (<);
4619 case /* 0b111001: GT */ 0x39: VEC_FCMP (>);
4620 case /* 0b101001: GE */ 0x29: VEC_FCMP (>=);
4621 case /* 0b001001: EQ */ 0x09: VEC_FCMP (==);
4629 unsigned decode = (uimm (aarch64_get_instr (cpu), 29, 29) << 6)
4630 | uimm (aarch64_get_instr (cpu), 15, 10);
4634 case 0x0D: /* 0001101 GT */ VEC_CMP (s, > );
4635 case 0x0F: /* 0001111 GE */ VEC_CMP (s, >= );
4636 case 0x22: /* 0100010 GT #0 */ VEC_CMP0 (s, > );
4637 case 0x26: /* 0100110 EQ #0 */ VEC_CMP0 (s, == );
4638 case 0x2A: /* 0101010 LT #0 */ VEC_CMP0 (s, < );
4639 case 0x4D: /* 1001101 HI */ VEC_CMP (u, > );
4640 case 0x4F: /* 1001111 HS */ VEC_CMP (u, >= );
4641 case 0x62: /* 1100010 GE #0 */ VEC_CMP0 (s, >= );
4642 case 0x63: /* 1100011 EQ */ VEC_CMP (u, == );
4643 case 0x66: /* 1100110 LE #0 */ VEC_CMP0 (s, <= );
4653 do_vec_SSHL (sim_cpu *cpu)
4656 instr[30] = first part (0)/ second part (1)
4657 instr[29,24] = 00 1110
4658 instr[23,22] = size: byte(00), half(01), word (10), long (11)
4661 instr[15,10] = 0100 01
4665 unsigned full = uimm (aarch64_get_instr (cpu), 30, 30);
4666 unsigned vm = uimm (aarch64_get_instr (cpu), 20, 16);
4667 unsigned vn = uimm (aarch64_get_instr (cpu), 9, 5);
4668 unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
4671 NYI_assert (29, 24, 0x0E);
4672 NYI_assert (21, 21, 1);
4673 NYI_assert (15, 10, 0x11);
4675 /* FIXME: What is a signed shift left in this context ?. */
4677 switch (uimm (aarch64_get_instr (cpu), 23, 22))
4680 for (i = 0; i < (full ? 16 : 8); i++)
4681 aarch64_set_vec_s8 (cpu, vd, i, aarch64_get_vec_s8 (cpu, vn, i)
4682 << aarch64_get_vec_s8 (cpu, vm, i));
4686 for (i = 0; i < (full ? 8 : 4); i++)
4687 aarch64_set_vec_s16 (cpu, vd, i, aarch64_get_vec_s16 (cpu, vn, i)
4688 << aarch64_get_vec_s16 (cpu, vm, i));
4692 for (i = 0; i < (full ? 4 : 2); i++)
4693 aarch64_set_vec_s32 (cpu, vd, i, aarch64_get_vec_s32 (cpu, vn, i)
4694 << aarch64_get_vec_s32 (cpu, vm, i));
4700 for (i = 0; i < 2; i++)
4701 aarch64_set_vec_s64 (cpu, vd, i, aarch64_get_vec_s64 (cpu, vn, i)
4702 << aarch64_get_vec_s64 (cpu, vm, i));
4711 do_vec_USHL (sim_cpu *cpu)
4714 instr[30] = first part (0)/ second part (1)
4715 instr[29,24] = 10 1110
4716 instr[23,22] = size: byte(00), half(01), word (10), long (11)
4719 instr[15,10] = 0100 01
4723 unsigned full = uimm (aarch64_get_instr (cpu), 30, 30);
4724 unsigned vm = uimm (aarch64_get_instr (cpu), 20, 16);
4725 unsigned vn = uimm (aarch64_get_instr (cpu), 9, 5);
4726 unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
4729 NYI_assert (29, 24, 0x2E);
4730 NYI_assert (15, 10, 0x11);
4732 switch (uimm (aarch64_get_instr (cpu), 23, 22))
4735 for (i = 0; i < (full ? 16 : 8); i++)
4736 aarch64_set_vec_u8 (cpu, vd, i, aarch64_get_vec_u8 (cpu, vn, i)
4737 << aarch64_get_vec_u8 (cpu, vm, i));
4741 for (i = 0; i < (full ? 8 : 4); i++)
4742 aarch64_set_vec_u16 (cpu, vd, i, aarch64_get_vec_u16 (cpu, vn, i)
4743 << aarch64_get_vec_u16 (cpu, vm, i));
4747 for (i = 0; i < (full ? 4 : 2); i++)
4748 aarch64_set_vec_u32 (cpu, vd, i, aarch64_get_vec_u32 (cpu, vn, i)
4749 << aarch64_get_vec_u32 (cpu, vm, i));
4755 for (i = 0; i < 2; i++)
4756 aarch64_set_vec_u64 (cpu, vd, i, aarch64_get_vec_u64 (cpu, vn, i)
4757 << aarch64_get_vec_u64 (cpu, vm, i));
4766 do_vec_FMLA (sim_cpu *cpu)
4769 instr[30] = full/half selector
4770 instr[29,23] = 0011100
4771 instr[22] = size: 0=>float, 1=>double
4774 instr[15,10] = 1100 11
4778 unsigned vm = uimm (aarch64_get_instr (cpu), 20, 16);
4779 unsigned vn = uimm (aarch64_get_instr (cpu), 9, 5);
4780 unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
4782 int full = uimm (aarch64_get_instr (cpu), 30, 30);
4784 NYI_assert (29, 23, 0x1C);
4785 NYI_assert (21, 21, 1);
4786 NYI_assert (15, 10, 0x33);
4788 if (uimm (aarch64_get_instr (cpu), 22, 22))
4792 for (i = 0; i < 2; i++)
4793 aarch64_set_vec_double (cpu, vd, i,
4794 aarch64_get_vec_double (cpu, vn, i) *
4795 aarch64_get_vec_double (cpu, vm, i) +
4796 aarch64_get_vec_double (cpu, vd, i));
4800 for (i = 0; i < (full ? 4 : 2); i++)
4801 aarch64_set_vec_float (cpu, vd, i,
4802 aarch64_get_vec_float (cpu, vn, i) *
4803 aarch64_get_vec_float (cpu, vm, i) +
4804 aarch64_get_vec_float (cpu, vd, i));
4809 do_vec_max (sim_cpu *cpu)
4812 instr[30] = full/half selector
4813 instr[29] = SMAX (0) / UMAX (1)
4814 instr[28,24] = 0 1110
4815 instr[23,22] = size: 00=> 8-bit, 01=> 16-bit, 10=> 32-bit
4818 instr[15,10] = 0110 01
4822 unsigned vm = uimm (aarch64_get_instr (cpu), 20, 16);
4823 unsigned vn = uimm (aarch64_get_instr (cpu), 9, 5);
4824 unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
4826 int full = uimm (aarch64_get_instr (cpu), 30, 30);
4828 NYI_assert (28, 24, 0x0E);
4829 NYI_assert (21, 21, 1);
4830 NYI_assert (15, 10, 0x19);
4832 if (uimm (aarch64_get_instr (cpu), 29, 29))
4834 switch (uimm (aarch64_get_instr (cpu), 23, 22))
4837 for (i = 0; i < (full ? 16 : 8); i++)
4838 aarch64_set_vec_u8 (cpu, vd, i,
4839 aarch64_get_vec_u8 (cpu, vn, i)
4840 > aarch64_get_vec_u8 (cpu, vm, i)
4841 ? aarch64_get_vec_u8 (cpu, vn, i)
4842 : aarch64_get_vec_u8 (cpu, vm, i));
4846 for (i = 0; i < (full ? 8 : 4); i++)
4847 aarch64_set_vec_u16 (cpu, vd, i,
4848 aarch64_get_vec_u16 (cpu, vn, i)
4849 > aarch64_get_vec_u16 (cpu, vm, i)
4850 ? aarch64_get_vec_u16 (cpu, vn, i)
4851 : aarch64_get_vec_u16 (cpu, vm, i));
4855 for (i = 0; i < (full ? 4 : 2); i++)
4856 aarch64_set_vec_u32 (cpu, vd, i,
4857 aarch64_get_vec_u32 (cpu, vn, i)
4858 > aarch64_get_vec_u32 (cpu, vm, i)
4859 ? aarch64_get_vec_u32 (cpu, vn, i)
4860 : aarch64_get_vec_u32 (cpu, vm, i));
4870 switch (uimm (aarch64_get_instr (cpu), 23, 22))
4873 for (i = 0; i < (full ? 16 : 8); i++)
4874 aarch64_set_vec_s8 (cpu, vd, i,
4875 aarch64_get_vec_s8 (cpu, vn, i)
4876 > aarch64_get_vec_s8 (cpu, vm, i)
4877 ? aarch64_get_vec_s8 (cpu, vn, i)
4878 : aarch64_get_vec_s8 (cpu, vm, i));
4882 for (i = 0; i < (full ? 8 : 4); i++)
4883 aarch64_set_vec_s16 (cpu, vd, i,
4884 aarch64_get_vec_s16 (cpu, vn, i)
4885 > aarch64_get_vec_s16 (cpu, vm, i)
4886 ? aarch64_get_vec_s16 (cpu, vn, i)
4887 : aarch64_get_vec_s16 (cpu, vm, i));
4891 for (i = 0; i < (full ? 4 : 2); i++)
4892 aarch64_set_vec_s32 (cpu, vd, i,
4893 aarch64_get_vec_s32 (cpu, vn, i)
4894 > aarch64_get_vec_s32 (cpu, vm, i)
4895 ? aarch64_get_vec_s32 (cpu, vn, i)
4896 : aarch64_get_vec_s32 (cpu, vm, i));
4907 do_vec_min (sim_cpu *cpu)
4910 instr[30] = full/half selector
4911 instr[29] = SMIN (0) / UMIN (1)
4912 instr[28,24] = 0 1110
4913 instr[23,22] = size: 00=> 8-bit, 01=> 16-bit, 10=> 32-bit
4916 instr[15,10] = 0110 11
4920 unsigned vm = uimm (aarch64_get_instr (cpu), 20, 16);
4921 unsigned vn = uimm (aarch64_get_instr (cpu), 9, 5);
4922 unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
4924 int full = uimm (aarch64_get_instr (cpu), 30, 30);
4926 NYI_assert (28, 24, 0x0E);
4927 NYI_assert (21, 21, 1);
4928 NYI_assert (15, 10, 0x1B);
4930 if (uimm (aarch64_get_instr (cpu), 29, 29))
4932 switch (uimm (aarch64_get_instr (cpu), 23, 22))
4935 for (i = 0; i < (full ? 16 : 8); i++)
4936 aarch64_set_vec_u8 (cpu, vd, i,
4937 aarch64_get_vec_u8 (cpu, vn, i)
4938 < aarch64_get_vec_u8 (cpu, vm, i)
4939 ? aarch64_get_vec_u8 (cpu, vn, i)
4940 : aarch64_get_vec_u8 (cpu, vm, i));
4944 for (i = 0; i < (full ? 8 : 4); i++)
4945 aarch64_set_vec_u16 (cpu, vd, i,
4946 aarch64_get_vec_u16 (cpu, vn, i)
4947 < aarch64_get_vec_u16 (cpu, vm, i)
4948 ? aarch64_get_vec_u16 (cpu, vn, i)
4949 : aarch64_get_vec_u16 (cpu, vm, i));
4953 for (i = 0; i < (full ? 4 : 2); i++)
4954 aarch64_set_vec_u32 (cpu, vd, i,
4955 aarch64_get_vec_u32 (cpu, vn, i)
4956 < aarch64_get_vec_u32 (cpu, vm, i)
4957 ? aarch64_get_vec_u32 (cpu, vn, i)
4958 : aarch64_get_vec_u32 (cpu, vm, i));
4968 switch (uimm (aarch64_get_instr (cpu), 23, 22))
4971 for (i = 0; i < (full ? 16 : 8); i++)
4972 aarch64_set_vec_s8 (cpu, vd, i,
4973 aarch64_get_vec_s8 (cpu, vn, i)
4974 < aarch64_get_vec_s8 (cpu, vm, i)
4975 ? aarch64_get_vec_s8 (cpu, vn, i)
4976 : aarch64_get_vec_s8 (cpu, vm, i));
4980 for (i = 0; i < (full ? 8 : 4); i++)
4981 aarch64_set_vec_s16 (cpu, vd, i,
4982 aarch64_get_vec_s16 (cpu, vn, i)
4983 < aarch64_get_vec_s16 (cpu, vm, i)
4984 ? aarch64_get_vec_s16 (cpu, vn, i)
4985 : aarch64_get_vec_s16 (cpu, vm, i));
4989 for (i = 0; i < (full ? 4 : 2); i++)
4990 aarch64_set_vec_s32 (cpu, vd, i,
4991 aarch64_get_vec_s32 (cpu, vn, i)
4992 < aarch64_get_vec_s32 (cpu, vm, i)
4993 ? aarch64_get_vec_s32 (cpu, vn, i)
4994 : aarch64_get_vec_s32 (cpu, vm, i));
5005 do_vec_sub_long (sim_cpu *cpu)
5008 instr[30] = lower (0) / upper (1)
5009 instr[29] = signed (0) / unsigned (1)
5010 instr[28,24] = 0 1110
5011 instr[23,22] = size: bytes (00), half (01), word (10)
5014 instr[15,10] = 0010 00
5016 instr[4,0] = V dest. */
5018 unsigned size = uimm (aarch64_get_instr (cpu), 23, 22);
5019 unsigned vm = uimm (aarch64_get_instr (cpu), 20, 16);
5020 unsigned vn = uimm (aarch64_get_instr (cpu), 9, 5);
5021 unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
5025 NYI_assert (28, 24, 0x0E);
5026 NYI_assert (21, 21, 1);
5027 NYI_assert (15, 10, 0x08);
5032 switch (uimm (aarch64_get_instr (cpu), 30, 29))
5034 case 2: /* SSUBL2. */
5036 case 0: /* SSUBL. */
5041 for (i = 0; i < 8; i++)
5042 aarch64_set_vec_s16 (cpu, vd, i,
5043 aarch64_get_vec_s8 (cpu, vn, i + bias)
5044 - aarch64_get_vec_s8 (cpu, vm, i + bias));
5049 for (i = 0; i < 4; i++)
5050 aarch64_set_vec_s32 (cpu, vd, i,
5051 aarch64_get_vec_s16 (cpu, vn, i + bias)
5052 - aarch64_get_vec_s16 (cpu, vm, i + bias));
5056 for (i = 0; i < 2; i++)
5057 aarch64_set_vec_s64 (cpu, vd, i,
5058 aarch64_get_vec_s32 (cpu, vn, i + bias)
5059 - aarch64_get_vec_s32 (cpu, vm, i + bias));
5067 case 3: /* USUBL2. */
5069 case 1: /* USUBL. */
5074 for (i = 0; i < 8; i++)
5075 aarch64_set_vec_u16 (cpu, vd, i,
5076 aarch64_get_vec_u8 (cpu, vn, i + bias)
5077 - aarch64_get_vec_u8 (cpu, vm, i + bias));
5082 for (i = 0; i < 4; i++)
5083 aarch64_set_vec_u32 (cpu, vd, i,
5084 aarch64_get_vec_u16 (cpu, vn, i + bias)
5085 - aarch64_get_vec_u16 (cpu, vm, i + bias));
5089 for (i = 0; i < 2; i++)
5090 aarch64_set_vec_u64 (cpu, vd, i,
5091 aarch64_get_vec_u32 (cpu, vn, i + bias)
5092 - aarch64_get_vec_u32 (cpu, vm, i + bias));
5102 #define DO_ADDP(FN) \
5105 for (i = 0; i < range; i++) \
5107 aarch64_set_vec_##FN (cpu, vd, i, \
5108 aarch64_get_vec_##FN (cpu, vn, i * 2) \
5109 + aarch64_get_vec_##FN (cpu, vn, i * 2 + 1)); \
5110 aarch64_set_vec_##FN (cpu, vd, i + range, \
5111 aarch64_get_vec_##FN (cpu, vm, i * 2) \
5112 + aarch64_get_vec_##FN (cpu, vm, i * 2 + 1)); \
5118 do_vec_ADDP (sim_cpu *cpu)
5121 instr[30] = half(0)/full(1)
5122 instr[29,24] = 00 1110
5123 instr[23,22] = size: bytes (00), half (01), word (10), long (11)
5126 instr[15,10] = 1011 11
5128 instr[4,0] = V dest. */
5130 unsigned full = uimm (aarch64_get_instr (cpu), 30, 30);
5131 unsigned size = uimm (aarch64_get_instr (cpu), 23, 22);
5132 unsigned vm = uimm (aarch64_get_instr (cpu), 20, 16);
5133 unsigned vn = uimm (aarch64_get_instr (cpu), 9, 5);
5134 unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
5137 NYI_assert (29, 24, 0x0E);
5138 NYI_assert (21, 21, 1);
5139 NYI_assert (15, 10, 0x2F);
5144 range = full ? 8 : 4;
5149 range = full ? 4 : 2;
5154 range = full ? 2 : 1;
5171 do_vec_UMOV (sim_cpu *cpu)
5174 instr[30] = 32-bit(0)/64-bit(1)
5175 instr[29,21] = 00 1110 000
5176 insrt[20,16] = size & index
5177 instr[15,10] = 0011 11
5178 instr[9,5] = V source
5179 instr[4,0] = R dest. */
5181 unsigned vs = uimm (aarch64_get_instr (cpu), 9, 5);
5182 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
5185 NYI_assert (29, 21, 0x070);
5186 NYI_assert (15, 10, 0x0F);
5188 if (uimm (aarch64_get_instr (cpu), 16, 16))
5190 /* Byte transfer. */
5191 index = uimm (aarch64_get_instr (cpu), 20, 17);
5192 aarch64_set_reg_u64 (cpu, rd, NO_SP,
5193 aarch64_get_vec_u8 (cpu, vs, index));
5195 else if (uimm (aarch64_get_instr (cpu), 17, 17))
5197 index = uimm (aarch64_get_instr (cpu), 20, 18);
5198 aarch64_set_reg_u64 (cpu, rd, NO_SP,
5199 aarch64_get_vec_u16 (cpu, vs, index));
5201 else if (uimm (aarch64_get_instr (cpu), 18, 18))
5203 index = uimm (aarch64_get_instr (cpu), 20, 19);
5204 aarch64_set_reg_u64 (cpu, rd, NO_SP,
5205 aarch64_get_vec_u32 (cpu, vs, index));
5209 if (uimm (aarch64_get_instr (cpu), 30, 30) != 1)
5212 index = uimm (aarch64_get_instr (cpu), 20, 20);
5213 aarch64_set_reg_u64 (cpu, rd, NO_SP,
5214 aarch64_get_vec_u64 (cpu, vs, index));
5219 do_vec_FABS (sim_cpu *cpu)
5222 instr[30] = half(0)/full(1)
5223 instr[29,23] = 00 1110 1
5224 instr[22] = float(0)/double(1)
5225 instr[21,16] = 10 0000
5226 instr[15,10] = 1111 10
5230 unsigned vn = uimm (aarch64_get_instr (cpu), 9, 5);
5231 unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
5232 unsigned full = uimm (aarch64_get_instr (cpu), 30, 30);
5235 NYI_assert (29, 23, 0x1D);
5236 NYI_assert (21, 10, 0x83E);
5238 if (uimm (aarch64_get_instr (cpu), 22, 22))
5243 for (i = 0; i < 2; i++)
5244 aarch64_set_vec_double (cpu, vd, i,
5245 fabs (aarch64_get_vec_double (cpu, vn, i)));
5249 for (i = 0; i < (full ? 4 : 2); i++)
5250 aarch64_set_vec_float (cpu, vd, i,
5251 fabsf (aarch64_get_vec_float (cpu, vn, i)));
5256 do_vec_FCVTZS (sim_cpu *cpu)
5259 instr[30] = half (0) / all (1)
5260 instr[29,23] = 00 1110 1
5261 instr[22] = single (0) / double (1)
5262 instr[21,10] = 10 0001 1011 10
5266 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
5267 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
5268 unsigned full = uimm (aarch64_get_instr (cpu), 30, 30);
5271 NYI_assert (31, 31, 0);
5272 NYI_assert (29, 23, 0x1D);
5273 NYI_assert (21, 10, 0x86E);
5275 if (uimm (aarch64_get_instr (cpu), 22, 22))
5280 for (i = 0; i < 2; i++)
5281 aarch64_set_vec_s64 (cpu, rd, i,
5282 (int64_t) aarch64_get_vec_double (cpu, rn, i));
5285 for (i = 0; i < (full ? 4 : 2); i++)
5286 aarch64_set_vec_s32 (cpu, rd, i,
5287 (int32_t) aarch64_get_vec_float (cpu, rn, i));
5291 do_vec_op1 (sim_cpu *cpu)
5294 instr[30] = half/full
5295 instr[29,24] = 00 1110
5298 instr[15,10] = sub-opcode
5301 NYI_assert (29, 24, 0x0E);
5303 if (uimm (aarch64_get_instr (cpu), 21, 21) == 0)
5305 if (uimm (aarch64_get_instr (cpu), 23, 22) == 0)
5307 if (uimm (aarch64_get_instr (cpu), 30, 30) == 1
5308 && uimm (aarch64_get_instr (cpu), 17, 14) == 0
5309 && uimm (aarch64_get_instr (cpu), 12, 10) == 7)
5310 return do_vec_ins_2 (cpu);
5312 switch (uimm (aarch64_get_instr (cpu), 15, 10))
5314 case 0x01: do_vec_DUP_vector_into_vector (cpu); return;
5315 case 0x03: do_vec_DUP_scalar_into_vector (cpu); return;
5316 case 0x07: do_vec_INS (cpu); return;
5317 case 0x0A: do_vec_TRN (cpu); return;
5320 if (uimm (aarch64_get_instr (cpu), 17, 16) == 0)
5322 do_vec_MOV_into_scalar (cpu);
5331 do_vec_TBL (cpu); return;
5335 do_vec_UZP (cpu); return;
5339 do_vec_ZIP (cpu); return;
5346 switch (uimm (aarch64_get_instr (cpu), 13, 10))
5348 case 0x6: do_vec_UZP (cpu); return;
5349 case 0xE: do_vec_ZIP (cpu); return;
5350 case 0xA: do_vec_TRN (cpu); return;
5351 case 0xF: do_vec_UMOV (cpu); return;
5356 switch (uimm (aarch64_get_instr (cpu), 15, 10))
5359 switch (uimm (aarch64_get_instr (cpu), 23, 21))
5361 case 1: do_vec_AND (cpu); return;
5362 case 3: do_vec_BIC (cpu); return;
5363 case 5: do_vec_ORR (cpu); return;
5364 case 7: do_vec_ORN (cpu); return;
5368 case 0x08: do_vec_sub_long (cpu); return;
5369 case 0x0a: do_vec_XTN (cpu); return;
5370 case 0x11: do_vec_SSHL (cpu); return;
5371 case 0x19: do_vec_max (cpu); return;
5372 case 0x1B: do_vec_min (cpu); return;
5373 case 0x21: do_vec_add (cpu); return;
5374 case 0x25: do_vec_MLA (cpu); return;
5375 case 0x27: do_vec_mul (cpu); return;
5376 case 0x2F: do_vec_ADDP (cpu); return;
5377 case 0x30: do_vec_mull (cpu); return;
5378 case 0x33: do_vec_FMLA (cpu); return;
5379 case 0x35: do_vec_fadd (cpu); return;
5382 switch (uimm (aarch64_get_instr (cpu), 20, 16))
5384 case 0x00: do_vec_ABS (cpu); return;
5385 case 0x01: do_vec_FCVTZS (cpu); return;
5386 case 0x11: do_vec_ADDV (cpu); return;
5392 do_vec_Fminmax (cpu); return;
5404 do_vec_compare (cpu); return;
5407 do_vec_FABS (cpu); return;
5415 do_vec_xtl (sim_cpu *cpu)
5418 instr[30,29] = SXTL (00), UXTL (01), SXTL2 (10), UXTL2 (11)
5419 instr[28,22] = 0 1111 00
5420 instr[21,16] = size & shift (USHLL, SSHLL, USHLL2, SSHLL2)
5421 instr[15,10] = 1010 01
5422 instr[9,5] = V source
5423 instr[4,0] = V dest. */
5425 unsigned vs = uimm (aarch64_get_instr (cpu), 9, 5);
5426 unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
5427 unsigned i, shift, bias = 0;
5429 NYI_assert (28, 22, 0x3C);
5430 NYI_assert (15, 10, 0x29);
5432 switch (uimm (aarch64_get_instr (cpu), 30, 29))
5434 case 2: /* SXTL2, SSHLL2. */
5436 case 0: /* SXTL, SSHLL. */
5437 if (uimm (aarch64_get_instr (cpu), 21, 21))
5439 shift = uimm (aarch64_get_instr (cpu), 20, 16);
5441 (cpu, vd, 0, aarch64_get_vec_s32 (cpu, vs, bias) << shift);
5443 (cpu, vd, 1, aarch64_get_vec_s32 (cpu, vs, bias + 1) << shift);
5445 else if (uimm (aarch64_get_instr (cpu), 20, 20))
5447 shift = uimm (aarch64_get_instr (cpu), 19, 16);
5449 for (i = 0; i < 4; i++)
5451 (cpu, vd, i, aarch64_get_vec_s16 (cpu, vs, i + bias) << shift);
5455 NYI_assert (19, 19, 1);
5457 shift = uimm (aarch64_get_instr (cpu), 18, 16);
5459 for (i = 0; i < 8; i++)
5461 (cpu, vd, i, aarch64_get_vec_s8 (cpu, vs, i + bias) << shift);
5465 case 3: /* UXTL2, USHLL2. */
5467 case 1: /* UXTL, USHLL. */
5468 if (uimm (aarch64_get_instr (cpu), 21, 21))
5470 shift = uimm (aarch64_get_instr (cpu), 20, 16);
5472 (cpu, vd, 0, aarch64_get_vec_u32 (cpu, vs, bias) << shift);
5474 (cpu, vd, 1, aarch64_get_vec_u32 (cpu, vs, bias + 1) << shift);
5476 else if (uimm (aarch64_get_instr (cpu), 20, 20))
5478 shift = uimm (aarch64_get_instr (cpu), 19, 16);
5480 for (i = 0; i < 4; i++)
5482 (cpu, vd, i, aarch64_get_vec_u16 (cpu, vs, i + bias) << shift);
5486 NYI_assert (19, 19, 1);
5488 shift = uimm (aarch64_get_instr (cpu), 18, 16);
5490 for (i = 0; i < 8; i++)
5492 (cpu, vd, i, aarch64_get_vec_u8 (cpu, vs, i + bias) << shift);
5502 do_vec_SHL (sim_cpu *cpu)
5505 instr [30] = half(0)/full(1)
5506 instr [29,23] = 001 1110
5507 instr [22,16] = size and shift amount
5508 instr [15,10] = 01 0101
5510 instr [4, 0] = Vd. */
5513 int full = uimm (aarch64_get_instr (cpu), 30, 30);
5514 unsigned vs = uimm (aarch64_get_instr (cpu), 9, 5);
5515 unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
5518 NYI_assert (29, 23, 0x1E);
5519 NYI_assert (15, 10, 0x15);
5521 if (uimm (aarch64_get_instr (cpu), 22, 22))
5523 shift = uimm (aarch64_get_instr (cpu), 21, 16) - 1;
5528 for (i = 0; i < 2; i++)
5530 uint64_t val = aarch64_get_vec_u64 (cpu, vs, i);
5531 aarch64_set_vec_u64 (cpu, vd, i, val << shift);
5537 if (uimm (aarch64_get_instr (cpu), 21, 21))
5539 shift = uimm (aarch64_get_instr (cpu), 20, 16) - 1;
5541 for (i = 0; i < (full ? 4 : 2); i++)
5543 uint32_t val = aarch64_get_vec_u32 (cpu, vs, i);
5544 aarch64_set_vec_u32 (cpu, vd, i, val << shift);
5550 if (uimm (aarch64_get_instr (cpu), 20, 20))
5552 shift = uimm (aarch64_get_instr (cpu), 19, 16) - 1;
5554 for (i = 0; i < (full ? 8 : 4); i++)
5556 uint16_t val = aarch64_get_vec_u16 (cpu, vs, i);
5557 aarch64_set_vec_u16 (cpu, vd, i, val << shift);
5563 if (uimm (aarch64_get_instr (cpu), 19, 19) == 0)
5566 shift = uimm (aarch64_get_instr (cpu), 18, 16) - 1;
5568 for (i = 0; i < (full ? 16 : 8); i++)
5570 uint8_t val = aarch64_get_vec_u8 (cpu, vs, i);
5571 aarch64_set_vec_u8 (cpu, vd, i, val << shift);
5576 do_vec_SSHR_USHR (sim_cpu *cpu)
5579 instr [30] = half(0)/full(1)
5580 instr [29] = signed(0)/unsigned(1)
5581 instr [28,23] = 01 1110
5582 instr [22,16] = size and shift amount
5583 instr [15,10] = 0000 01
5585 instr [4, 0] = Vd. */
5588 int full = uimm (aarch64_get_instr (cpu), 30, 30);
5589 int sign = uimm (aarch64_get_instr (cpu), 29, 29);
5590 unsigned vs = uimm (aarch64_get_instr (cpu), 9, 5);
5591 unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
5594 NYI_assert (28, 23, 0x1E);
5595 NYI_assert (15, 10, 0x01);
5597 if (uimm (aarch64_get_instr (cpu), 22, 22))
5599 shift = uimm (aarch64_get_instr (cpu), 21, 16);
5605 for (i = 0; i < 2; i++)
5607 int64_t val = aarch64_get_vec_s64 (cpu, vs, i);
5608 aarch64_set_vec_s64 (cpu, vd, i, val >> shift);
5611 for (i = 0; i < 2; i++)
5613 uint64_t val = aarch64_get_vec_u64 (cpu, vs, i);
5614 aarch64_set_vec_u64 (cpu, vd, i, val >> shift);
5620 if (uimm (aarch64_get_instr (cpu), 21, 21))
5622 shift = uimm (aarch64_get_instr (cpu), 20, 16);
5625 for (i = 0; i < (full ? 4 : 2); i++)
5627 int32_t val = aarch64_get_vec_s32 (cpu, vs, i);
5628 aarch64_set_vec_s32 (cpu, vd, i, val >> shift);
5631 for (i = 0; i < (full ? 4 : 2); i++)
5633 uint32_t val = aarch64_get_vec_u32 (cpu, vs, i);
5634 aarch64_set_vec_u32 (cpu, vd, i, val >> shift);
5640 if (uimm (aarch64_get_instr (cpu), 20, 20))
5642 shift = uimm (aarch64_get_instr (cpu), 19, 16);
5645 for (i = 0; i < (full ? 8 : 4); i++)
5647 int16_t val = aarch64_get_vec_s16 (cpu, vs, i);
5648 aarch64_set_vec_s16 (cpu, vd, i, val >> shift);
5651 for (i = 0; i < (full ? 8 : 4); i++)
5653 uint16_t val = aarch64_get_vec_u16 (cpu, vs, i);
5654 aarch64_set_vec_u16 (cpu, vd, i, val >> shift);
5660 if (uimm (aarch64_get_instr (cpu), 19, 19) == 0)
5663 shift = uimm (aarch64_get_instr (cpu), 18, 16);
5666 for (i = 0; i < (full ? 16 : 8); i++)
5668 int8_t val = aarch64_get_vec_s8 (cpu, vs, i);
5669 aarch64_set_vec_s8 (cpu, vd, i, val >> shift);
5672 for (i = 0; i < (full ? 16 : 8); i++)
5674 uint8_t val = aarch64_get_vec_u8 (cpu, vs, i);
5675 aarch64_set_vec_u8 (cpu, vd, i, val >> shift);
5680 do_vec_op2 (sim_cpu *cpu)
5683 instr[30] = half/full
5684 instr[29,24] = 00 1111
5686 instr[22,16] = element size & index
5687 instr[15,10] = sub-opcode
5691 NYI_assert (29, 24, 0x0F);
5693 if (uimm (aarch64_get_instr (cpu), 23, 23) != 0)
5696 switch (uimm (aarch64_get_instr (cpu), 15, 10))
5698 case 0x01: do_vec_SSHR_USHR (cpu); return;
5699 case 0x15: do_vec_SHL (cpu); return;
5700 case 0x29: do_vec_xtl (cpu); return;
5706 do_vec_neg (sim_cpu *cpu)
5709 instr[30] = full(1)/half(0)
5710 instr[29,24] = 10 1110
5711 instr[23,22] = size: byte(00), half (01), word (10), long (11)
5712 instr[21,10] = 1000 0010 1110
5716 int full = uimm (aarch64_get_instr (cpu), 30, 30);
5717 unsigned vs = uimm (aarch64_get_instr (cpu), 9, 5);
5718 unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
5721 NYI_assert (29, 24, 0x2E);
5722 NYI_assert (21, 10, 0x82E);
5724 switch (uimm (aarch64_get_instr (cpu), 23, 22))
5727 for (i = 0; i < (full ? 16 : 8); i++)
5728 aarch64_set_vec_s8 (cpu, vd, i, - aarch64_get_vec_s8 (cpu, vs, i));
5732 for (i = 0; i < (full ? 8 : 4); i++)
5733 aarch64_set_vec_s16 (cpu, vd, i, - aarch64_get_vec_s16 (cpu, vs, i));
5737 for (i = 0; i < (full ? 4 : 2); i++)
5738 aarch64_set_vec_s32 (cpu, vd, i, - aarch64_get_vec_s32 (cpu, vs, i));
5744 for (i = 0; i < 2; i++)
5745 aarch64_set_vec_s64 (cpu, vd, i, - aarch64_get_vec_s64 (cpu, vs, i));
5754 do_vec_sqrt (sim_cpu *cpu)
5757 instr[30] = full(1)/half(0)
5758 instr[29,23] = 101 1101
5759 instr[22] = single(0)/double(1)
5760 instr[21,10] = 1000 0111 1110
5764 int full = uimm (aarch64_get_instr (cpu), 30, 30);
5765 unsigned vs = uimm (aarch64_get_instr (cpu), 9, 5);
5766 unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
5769 NYI_assert (29, 23, 0x5B);
5770 NYI_assert (21, 10, 0x87E);
5772 if (uimm (aarch64_get_instr (cpu), 22, 22) == 0)
5773 for (i = 0; i < (full ? 4 : 2); i++)
5774 aarch64_set_vec_float (cpu, vd, i,
5775 sqrtf (aarch64_get_vec_float (cpu, vs, i)));
5777 for (i = 0; i < 2; i++)
5778 aarch64_set_vec_double (cpu, vd, i,
5779 sqrt (aarch64_get_vec_double (cpu, vs, i)));
5783 do_vec_mls_indexed (sim_cpu *cpu)
5786 instr[30] = half(0)/full(1)
5787 instr[29,24] = 10 1111
5788 instr[23,22] = 16-bit(01)/32-bit(10)
5789 instr[21,20+11] = index (if 16-bit)
5790 instr[21+11] = index (if 32-bit)
5793 instr[11] = part of index
5798 int full = uimm (aarch64_get_instr (cpu), 30, 30);
5799 unsigned vs = uimm (aarch64_get_instr (cpu), 9, 5);
5800 unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
5801 unsigned vm = uimm (aarch64_get_instr (cpu), 20, 16);
5804 NYI_assert (15, 12, 4);
5805 NYI_assert (10, 10, 0);
5807 switch (uimm (aarch64_get_instr (cpu), 23, 22))
5817 elem = (uimm (aarch64_get_instr (cpu), 21, 20) << 1)
5818 | uimm (aarch64_get_instr (cpu), 11, 11);
5819 val = aarch64_get_vec_u16 (cpu, vm, elem);
5821 for (i = 0; i < (full ? 8 : 4); i++)
5822 aarch64_set_vec_u32 (cpu, vd, i,
5823 aarch64_get_vec_u32 (cpu, vd, i) -
5824 (aarch64_get_vec_u32 (cpu, vs, i) * val));
5830 unsigned elem = (uimm (aarch64_get_instr (cpu), 21, 21) << 1)
5831 | uimm (aarch64_get_instr (cpu), 11, 11);
5832 uint64_t val = aarch64_get_vec_u32 (cpu, vm, elem);
5834 for (i = 0; i < (full ? 4 : 2); i++)
5835 aarch64_set_vec_u64 (cpu, vd, i,
5836 aarch64_get_vec_u64 (cpu, vd, i) -
5837 (aarch64_get_vec_u64 (cpu, vs, i) * val));
5849 do_vec_SUB (sim_cpu *cpu)
5852 instr [30] = half(0)/full(1)
5853 instr [29,24] = 10 1110
5854 instr [23,22] = size: byte(00, half(01), word (10), long (11)
5857 instr [15,10] = 10 0001
5859 instr [4, 0] = Vd. */
5861 unsigned full = uimm (aarch64_get_instr (cpu), 30, 30);
5862 unsigned vm = uimm (aarch64_get_instr (cpu), 20, 16);
5863 unsigned vn = uimm (aarch64_get_instr (cpu), 9, 5);
5864 unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
5867 NYI_assert (29, 24, 0x2E);
5868 NYI_assert (21, 21, 1);
5869 NYI_assert (15, 10, 0x21);
5871 switch (uimm (aarch64_get_instr (cpu), 23, 22))
5874 for (i = 0; i < (full ? 16 : 8); i++)
5875 aarch64_set_vec_s8 (cpu, vd, i,
5876 aarch64_get_vec_s8 (cpu, vn, i)
5877 - aarch64_get_vec_s8 (cpu, vm, i));
5881 for (i = 0; i < (full ? 8 : 4); i++)
5882 aarch64_set_vec_s16 (cpu, vd, i,
5883 aarch64_get_vec_s16 (cpu, vn, i)
5884 - aarch64_get_vec_s16 (cpu, vm, i));
5888 for (i = 0; i < (full ? 4 : 2); i++)
5889 aarch64_set_vec_s32 (cpu, vd, i,
5890 aarch64_get_vec_s32 (cpu, vn, i)
5891 - aarch64_get_vec_s32 (cpu, vm, i));
5898 for (i = 0; i < 2; i++)
5899 aarch64_set_vec_s64 (cpu, vd, i,
5900 aarch64_get_vec_s64 (cpu, vn, i)
5901 - aarch64_get_vec_s64 (cpu, vm, i));
5910 do_vec_MLS (sim_cpu *cpu)
5913 instr [30] = half(0)/full(1)
5914 instr [29,24] = 10 1110
5915 instr [23,22] = size: byte(00, half(01), word (10)
5918 instr [15,10] = 10 0101
5920 instr [4, 0] = Vd. */
5922 unsigned full = uimm (aarch64_get_instr (cpu), 30, 30);
5923 unsigned vm = uimm (aarch64_get_instr (cpu), 20, 16);
5924 unsigned vn = uimm (aarch64_get_instr (cpu), 9, 5);
5925 unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
5928 NYI_assert (29, 24, 0x2E);
5929 NYI_assert (21, 21, 1);
5930 NYI_assert (15, 10, 0x25);
5932 switch (uimm (aarch64_get_instr (cpu), 23, 22))
5935 for (i = 0; i < (full ? 16 : 8); i++)
5936 aarch64_set_vec_u8 (cpu, vd, i,
5937 (aarch64_get_vec_u8 (cpu, vn, i)
5938 * aarch64_get_vec_u8 (cpu, vm, i))
5939 - aarch64_get_vec_u8 (cpu, vd, i));
5943 for (i = 0; i < (full ? 8 : 4); i++)
5944 aarch64_set_vec_u16 (cpu, vd, i,
5945 (aarch64_get_vec_u16 (cpu, vn, i)
5946 * aarch64_get_vec_u16 (cpu, vm, i))
5947 - aarch64_get_vec_u16 (cpu, vd, i));
5951 for (i = 0; i < (full ? 4 : 2); i++)
5952 aarch64_set_vec_u32 (cpu, vd, i,
5953 (aarch64_get_vec_u32 (cpu, vn, i)
5954 * aarch64_get_vec_u32 (cpu, vm, i))
5955 - aarch64_get_vec_u32 (cpu, vd, i));
5964 do_vec_FDIV (sim_cpu *cpu)
5967 instr [30] = half(0)/full(1)
5968 instr [29,23] = 10 1110 0
5969 instr [22] = float()/double(1)
5972 instr [15,10] = 1111 11
5974 instr [4, 0] = Vd. */
5976 unsigned full = uimm (aarch64_get_instr (cpu), 30, 30);
5977 unsigned vm = uimm (aarch64_get_instr (cpu), 20, 16);
5978 unsigned vn = uimm (aarch64_get_instr (cpu), 9, 5);
5979 unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
5982 NYI_assert (29, 23, 0x5C);
5983 NYI_assert (21, 21, 1);
5984 NYI_assert (15, 10, 0x3F);
5986 if (uimm (aarch64_get_instr (cpu), 22, 22))
5991 for (i = 0; i < 2; i++)
5992 aarch64_set_vec_double (cpu, vd, i,
5993 aarch64_get_vec_double (cpu, vn, i)
5994 / aarch64_get_vec_double (cpu, vm, i));
5997 for (i = 0; i < (full ? 4 : 2); i++)
5998 aarch64_set_vec_float (cpu, vd, i,
5999 aarch64_get_vec_float (cpu, vn, i)
6000 / aarch64_get_vec_float (cpu, vm, i));
6004 do_vec_FMUL (sim_cpu *cpu)
6007 instr [30] = half(0)/full(1)
6008 instr [29,23] = 10 1110 0
6009 instr [22] = float(0)/double(1)
6012 instr [15,10] = 1101 11
6014 instr [4, 0] = Vd. */
6016 unsigned full = uimm (aarch64_get_instr (cpu), 30, 30);
6017 unsigned vm = uimm (aarch64_get_instr (cpu), 20, 16);
6018 unsigned vn = uimm (aarch64_get_instr (cpu), 9, 5);
6019 unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
6022 NYI_assert (29, 23, 0x5C);
6023 NYI_assert (21, 21, 1);
6024 NYI_assert (15, 10, 0x37);
6026 if (uimm (aarch64_get_instr (cpu), 22, 22))
6031 for (i = 0; i < 2; i++)
6032 aarch64_set_vec_double (cpu, vd, i,
6033 aarch64_get_vec_double (cpu, vn, i)
6034 * aarch64_get_vec_double (cpu, vm, i));
6037 for (i = 0; i < (full ? 4 : 2); i++)
6038 aarch64_set_vec_float (cpu, vd, i,
6039 aarch64_get_vec_float (cpu, vn, i)
6040 * aarch64_get_vec_float (cpu, vm, i));
6044 do_vec_FADDP (sim_cpu *cpu)
6047 instr [30] = half(0)/full(1)
6048 instr [29,23] = 10 1110 0
6049 instr [22] = float(0)/double(1)
6052 instr [15,10] = 1101 01
6054 instr [4, 0] = Vd. */
6056 unsigned full = uimm (aarch64_get_instr (cpu), 30, 30);
6057 unsigned vm = uimm (aarch64_get_instr (cpu), 20, 16);
6058 unsigned vn = uimm (aarch64_get_instr (cpu), 9, 5);
6059 unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
6061 NYI_assert (29, 23, 0x5C);
6062 NYI_assert (21, 21, 1);
6063 NYI_assert (15, 10, 0x35);
6065 if (uimm (aarch64_get_instr (cpu), 22, 22))
6070 aarch64_set_vec_double (cpu, vd, 0, aarch64_get_vec_double (cpu, vn, 0)
6071 + aarch64_get_vec_double (cpu, vn, 1));
6072 aarch64_set_vec_double (cpu, vd, 1, aarch64_get_vec_double (cpu, vm, 0)
6073 + aarch64_get_vec_double (cpu, vm, 1));
6077 aarch64_set_vec_float (cpu, vd, 0, aarch64_get_vec_float (cpu, vn, 0)
6078 + aarch64_get_vec_float (cpu, vn, 1));
6080 aarch64_set_vec_float (cpu, vd, 1, aarch64_get_vec_float (cpu, vn, 2)
6081 + aarch64_get_vec_float (cpu, vn, 3));
6082 aarch64_set_vec_float (cpu, vd, full ? 2 : 1,
6083 aarch64_get_vec_float (cpu, vm, 0)
6084 + aarch64_get_vec_float (cpu, vm, 1));
6086 aarch64_set_vec_float (cpu, vd, 3,
6087 aarch64_get_vec_float (cpu, vm, 2)
6088 + aarch64_get_vec_float (cpu, vm, 3));
6093 do_vec_FSQRT (sim_cpu *cpu)
6096 instr[30] = half(0)/full(1)
6097 instr[29,23] = 10 1110 1
6098 instr[22] = single(0)/double(1)
6099 instr[21,10] = 10 0001 1111 10
6101 instr[4,0] = Vdest. */
6103 unsigned vn = uimm (aarch64_get_instr (cpu), 9, 5);
6104 unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
6105 unsigned full = uimm (aarch64_get_instr (cpu), 30, 30);
6108 NYI_assert (29, 23, 0x5D);
6109 NYI_assert (21, 10, 0x87E);
6111 if (uimm (aarch64_get_instr (cpu), 22, 22))
6116 for (i = 0; i < 2; i++)
6117 aarch64_set_vec_double (cpu, vd, i,
6118 sqrt (aarch64_get_vec_double (cpu, vn, i)));
6122 for (i = 0; i < (full ? 4 : 2); i++)
6123 aarch64_set_vec_float (cpu, vd, i,
6124 sqrtf (aarch64_get_vec_float (cpu, vn, i)));
6129 do_vec_FNEG (sim_cpu *cpu)
6132 instr[30] = half (0)/full (1)
6133 instr[29,23] = 10 1110 1
6134 instr[22] = single (0)/double (1)
6135 instr[21,10] = 10 0000 1111 10
6137 instr[4,0] = Vdest. */
6139 unsigned vn = uimm (aarch64_get_instr (cpu), 9, 5);
6140 unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
6141 unsigned full = uimm (aarch64_get_instr (cpu), 30, 30);
6144 NYI_assert (29, 23, 0x5D);
6145 NYI_assert (21, 10, 0x83E);
6147 if (uimm (aarch64_get_instr (cpu), 22, 22))
6152 for (i = 0; i < 2; i++)
6153 aarch64_set_vec_double (cpu, vd, i,
6154 - aarch64_get_vec_double (cpu, vn, i));
6158 for (i = 0; i < (full ? 4 : 2); i++)
6159 aarch64_set_vec_float (cpu, vd, i,
6160 - aarch64_get_vec_float (cpu, vn, i));
6165 do_vec_NOT (sim_cpu *cpu)
6168 instr[30] = half (0)/full (1)
6169 instr[29,21] = 10 1110 001
6170 instr[20,16] = 0 0000
6171 instr[15,10] = 0101 10
6175 unsigned vn = uimm (aarch64_get_instr (cpu), 9, 5);
6176 unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
6178 int full = uimm (aarch64_get_instr (cpu), 30, 30);
6180 NYI_assert (29, 10, 0xB8816);
6182 for (i = 0; i < (full ? 16 : 8); i++)
6183 aarch64_set_vec_u8 (cpu, vd, i, ~ aarch64_get_vec_u8 (cpu, vn, i));
6187 do_vec_MOV_element (sim_cpu *cpu)
6189 /* instr[31,21] = 0110 1110 000
6190 instr[20,16] = size & dest index
6192 instr[14,11] = source index
6197 unsigned vs = uimm (aarch64_get_instr (cpu), 9, 5);
6198 unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
6202 NYI_assert (31, 21, 0x370);
6203 NYI_assert (15, 15, 0);
6204 NYI_assert (10, 10, 1);
6206 if (uimm (aarch64_get_instr (cpu), 16, 16))
6209 src_index = uimm (aarch64_get_instr (cpu), 14, 11);
6210 dst_index = uimm (aarch64_get_instr (cpu), 20, 17);
6211 aarch64_set_vec_u8 (cpu, vd, dst_index,
6212 aarch64_get_vec_u8 (cpu, vs, src_index));
6214 else if (uimm (aarch64_get_instr (cpu), 17, 17))
6217 NYI_assert (11, 11, 0);
6218 src_index = uimm (aarch64_get_instr (cpu), 14, 12);
6219 dst_index = uimm (aarch64_get_instr (cpu), 20, 18);
6220 aarch64_set_vec_u16 (cpu, vd, dst_index,
6221 aarch64_get_vec_u16 (cpu, vs, src_index));
6223 else if (uimm (aarch64_get_instr (cpu), 18, 18))
6226 NYI_assert (12, 11, 0);
6227 src_index = uimm (aarch64_get_instr (cpu), 14, 13);
6228 dst_index = uimm (aarch64_get_instr (cpu), 20, 19);
6229 aarch64_set_vec_u32 (cpu, vd, dst_index,
6230 aarch64_get_vec_u32 (cpu, vs, src_index));
6234 NYI_assert (19, 19, 1);
6235 NYI_assert (13, 11, 0);
6236 src_index = uimm (aarch64_get_instr (cpu), 14, 14);
6237 dst_index = uimm (aarch64_get_instr (cpu), 20, 20);
6238 aarch64_set_vec_u64 (cpu, vd, dst_index,
6239 aarch64_get_vec_u64 (cpu, vs, src_index));
6244 dexAdvSIMD0 (sim_cpu *cpu)
6246 /* instr [28,25] = 0 111. */
6247 if ( uimm (aarch64_get_instr (cpu), 15, 10) == 0x07
6248 && (uimm (aarch64_get_instr (cpu), 9, 5) ==
6249 uimm (aarch64_get_instr (cpu), 20, 16)))
6251 if (uimm (aarch64_get_instr (cpu), 31, 21) == 0x075
6252 || uimm (aarch64_get_instr (cpu), 31, 21) == 0x275)
6254 do_vec_MOV_whole_vector (cpu);
6259 if (uimm (aarch64_get_instr (cpu), 29, 19) == 0x1E0)
6261 do_vec_MOV_immediate (cpu);
6265 if (uimm (aarch64_get_instr (cpu), 29, 19) == 0x5E0)
6271 if (uimm (aarch64_get_instr (cpu), 29, 19) == 0x1C0
6272 || uimm (aarch64_get_instr (cpu), 29, 19) == 0x1C1)
6274 if (uimm (aarch64_get_instr (cpu), 15, 10) == 0x03)
6276 do_vec_DUP_scalar_into_vector (cpu);
6281 switch (uimm (aarch64_get_instr (cpu), 29, 24))
6283 case 0x0E: do_vec_op1 (cpu); return;
6284 case 0x0F: do_vec_op2 (cpu); return;
6287 switch (uimm (aarch64_get_instr (cpu), 15, 10))
6289 case 0x01: do_vec_SSHR_USHR (cpu); return;
6291 case 0x12: do_vec_mls_indexed (cpu); return;
6292 case 0x29: do_vec_xtl (cpu); return;
6298 if (uimm (aarch64_get_instr (cpu), 21, 21) == 1)
6300 switch (uimm (aarch64_get_instr (cpu), 15, 10))
6303 switch (uimm (aarch64_get_instr (cpu), 23, 22))
6305 case 0: do_vec_EOR (cpu); return;
6306 case 1: do_vec_BSL (cpu); return;
6308 case 3: do_vec_bit (cpu); return;
6312 case 0x08: do_vec_sub_long (cpu); return;
6313 case 0x11: do_vec_USHL (cpu); return;
6314 case 0x16: do_vec_NOT (cpu); return;
6315 case 0x19: do_vec_max (cpu); return;
6316 case 0x1B: do_vec_min (cpu); return;
6317 case 0x21: do_vec_SUB (cpu); return;
6318 case 0x25: do_vec_MLS (cpu); return;
6319 case 0x31: do_vec_FminmaxNMP (cpu); return;
6320 case 0x35: do_vec_FADDP (cpu); return;
6321 case 0x37: do_vec_FMUL (cpu); return;
6322 case 0x3F: do_vec_FDIV (cpu); return;
6325 switch (uimm (aarch64_get_instr (cpu), 20, 16))
6327 case 0x00: do_vec_FNEG (cpu); return;
6328 case 0x01: do_vec_FSQRT (cpu); return;
6342 do_vec_compare (cpu); return;
6348 if (uimm (aarch64_get_instr (cpu), 31, 21) == 0x370)
6350 do_vec_MOV_element (cpu);
6354 switch (uimm (aarch64_get_instr (cpu), 21, 10))
6356 case 0x82E: do_vec_neg (cpu); return;
6357 case 0x87E: do_vec_sqrt (cpu); return;
6359 if (uimm (aarch64_get_instr (cpu), 15, 10) == 0x30)
6377 /* Float multiply add. */
6379 fmadds (sim_cpu *cpu)
6381 unsigned sa = uimm (aarch64_get_instr (cpu), 14, 10);
6382 unsigned sm = uimm (aarch64_get_instr (cpu), 20, 16);
6383 unsigned sn = uimm (aarch64_get_instr (cpu), 9, 5);
6384 unsigned sd = uimm (aarch64_get_instr (cpu), 4, 0);
6386 aarch64_set_FP_float (cpu, sd, aarch64_get_FP_float (cpu, sa)
6387 + aarch64_get_FP_float (cpu, sn)
6388 * aarch64_get_FP_float (cpu, sm));
6391 /* Double multiply add. */
6393 fmaddd (sim_cpu *cpu)
6395 unsigned sa = uimm (aarch64_get_instr (cpu), 14, 10);
6396 unsigned sm = uimm (aarch64_get_instr (cpu), 20, 16);
6397 unsigned sn = uimm (aarch64_get_instr (cpu), 9, 5);
6398 unsigned sd = uimm (aarch64_get_instr (cpu), 4, 0);
6400 aarch64_set_FP_double (cpu, sd, aarch64_get_FP_double (cpu, sa)
6401 + aarch64_get_FP_double (cpu, sn)
6402 * aarch64_get_FP_double (cpu, sm));
6405 /* Float multiply subtract. */
6407 fmsubs (sim_cpu *cpu)
6409 unsigned sa = uimm (aarch64_get_instr (cpu), 14, 10);
6410 unsigned sm = uimm (aarch64_get_instr (cpu), 20, 16);
6411 unsigned sn = uimm (aarch64_get_instr (cpu), 9, 5);
6412 unsigned sd = uimm (aarch64_get_instr (cpu), 4, 0);
6414 aarch64_set_FP_float (cpu, sd, aarch64_get_FP_float (cpu, sa)
6415 - aarch64_get_FP_float (cpu, sn)
6416 * aarch64_get_FP_float (cpu, sm));
6419 /* Double multiply subtract. */
6421 fmsubd (sim_cpu *cpu)
6423 unsigned sa = uimm (aarch64_get_instr (cpu), 14, 10);
6424 unsigned sm = uimm (aarch64_get_instr (cpu), 20, 16);
6425 unsigned sn = uimm (aarch64_get_instr (cpu), 9, 5);
6426 unsigned sd = uimm (aarch64_get_instr (cpu), 4, 0);
6428 aarch64_set_FP_double (cpu, sd, aarch64_get_FP_double (cpu, sa)
6429 - aarch64_get_FP_double (cpu, sn)
6430 * aarch64_get_FP_double (cpu, sm));
6433 /* Float negative multiply add. */
6435 fnmadds (sim_cpu *cpu)
6437 unsigned sa = uimm (aarch64_get_instr (cpu), 14, 10);
6438 unsigned sm = uimm (aarch64_get_instr (cpu), 20, 16);
6439 unsigned sn = uimm (aarch64_get_instr (cpu), 9, 5);
6440 unsigned sd = uimm (aarch64_get_instr (cpu), 4, 0);
6442 aarch64_set_FP_float (cpu, sd, - aarch64_get_FP_float (cpu, sa)
6443 + (- aarch64_get_FP_float (cpu, sn))
6444 * aarch64_get_FP_float (cpu, sm));
6447 /* Double negative multiply add. */
6449 fnmaddd (sim_cpu *cpu)
6451 unsigned sa = uimm (aarch64_get_instr (cpu), 14, 10);
6452 unsigned sm = uimm (aarch64_get_instr (cpu), 20, 16);
6453 unsigned sn = uimm (aarch64_get_instr (cpu), 9, 5);
6454 unsigned sd = uimm (aarch64_get_instr (cpu), 4, 0);
6456 aarch64_set_FP_double (cpu, sd, - aarch64_get_FP_double (cpu, sa)
6457 + (- aarch64_get_FP_double (cpu, sn))
6458 * aarch64_get_FP_double (cpu, sm));
6461 /* Float negative multiply subtract. */
6463 fnmsubs (sim_cpu *cpu)
6465 unsigned sa = uimm (aarch64_get_instr (cpu), 14, 10);
6466 unsigned sm = uimm (aarch64_get_instr (cpu), 20, 16);
6467 unsigned sn = uimm (aarch64_get_instr (cpu), 9, 5);
6468 unsigned sd = uimm (aarch64_get_instr (cpu), 4, 0);
6470 aarch64_set_FP_float (cpu, sd, - aarch64_get_FP_float (cpu, sa)
6471 + aarch64_get_FP_float (cpu, sn)
6472 * aarch64_get_FP_float (cpu, sm));
6475 /* Double negative multiply subtract. */
6477 fnmsubd (sim_cpu *cpu)
6479 unsigned sa = uimm (aarch64_get_instr (cpu), 14, 10);
6480 unsigned sm = uimm (aarch64_get_instr (cpu), 20, 16);
6481 unsigned sn = uimm (aarch64_get_instr (cpu), 9, 5);
6482 unsigned sd = uimm (aarch64_get_instr (cpu), 4, 0);
6484 aarch64_set_FP_double (cpu, sd, - aarch64_get_FP_double (cpu, sa)
6485 + aarch64_get_FP_double (cpu, sn)
6486 * aarch64_get_FP_double (cpu, sm));
6490 dexSimpleFPDataProc3Source (sim_cpu *cpu)
6492 /* instr[31] ==> M : 0 ==> OK, 1 ==> UNALLOC
6494 instr[29] ==> S : 0 ==> OK, 1 ==> UNALLOC
6497 instr[23,22] ==> type : 0 ==> single, 01 ==> double, 1x ==> UNALLOC
6498 instr[21] ==> o1 : 0 ==> unnegated, 1 ==> negated
6499 instr[15] ==> o2 : 0 ==> ADD, 1 ==> SUB */
6501 uint32_t M_S = (uimm (aarch64_get_instr (cpu), 31, 31) << 1)
6502 | uimm (aarch64_get_instr (cpu), 29, 29);
6503 /* dispatch on combined type:o1:o2. */
6504 uint32_t dispatch = (uimm (aarch64_get_instr (cpu), 23, 21) << 1)
6505 | uimm (aarch64_get_instr (cpu), 15, 15);
6512 case 0: fmadds (cpu); return;
6513 case 1: fmsubs (cpu); return;
6514 case 2: fnmadds (cpu); return;
6515 case 3: fnmsubs (cpu); return;
6516 case 4: fmaddd (cpu); return;
6517 case 5: fmsubd (cpu); return;
6518 case 6: fnmaddd (cpu); return;
6519 case 7: fnmsubd (cpu); return;
6521 /* type > 1 is currently unallocated. */
6527 dexSimpleFPFixedConvert (sim_cpu *cpu)
6533 dexSimpleFPCondCompare (sim_cpu *cpu)
6542 fadds (sim_cpu *cpu)
6544 unsigned sm = uimm (aarch64_get_instr (cpu), 20, 16);
6545 unsigned sn = uimm (aarch64_get_instr (cpu), 9, 5);
6546 unsigned sd = uimm (aarch64_get_instr (cpu), 4, 0);
6548 aarch64_set_FP_float (cpu, sd, aarch64_get_FP_float (cpu, sn)
6549 + aarch64_get_FP_float (cpu, sm));
6554 faddd (sim_cpu *cpu)
6556 unsigned sm = uimm (aarch64_get_instr (cpu), 20, 16);
6557 unsigned sn = uimm (aarch64_get_instr (cpu), 9, 5);
6558 unsigned sd = uimm (aarch64_get_instr (cpu), 4, 0);
6560 aarch64_set_FP_double (cpu, sd, aarch64_get_FP_double (cpu, sn)
6561 + aarch64_get_FP_double (cpu, sm));
6566 fdivs (sim_cpu *cpu)
6568 unsigned sm = uimm (aarch64_get_instr (cpu), 20, 16);
6569 unsigned sn = uimm (aarch64_get_instr (cpu), 9, 5);
6570 unsigned sd = uimm (aarch64_get_instr (cpu), 4, 0);
6572 aarch64_set_FP_float (cpu, sd, aarch64_get_FP_float (cpu, sn)
6573 / aarch64_get_FP_float (cpu, sm));
6576 /* Double divide. */
6578 fdivd (sim_cpu *cpu)
6580 unsigned sm = uimm (aarch64_get_instr (cpu), 20, 16);
6581 unsigned sn = uimm (aarch64_get_instr (cpu), 9, 5);
6582 unsigned sd = uimm (aarch64_get_instr (cpu), 4, 0);
6584 aarch64_set_FP_double (cpu, sd, aarch64_get_FP_double (cpu, sn)
6585 / aarch64_get_FP_double (cpu, sm));
6588 /* Float multiply. */
6590 fmuls (sim_cpu *cpu)
6592 unsigned sm = uimm (aarch64_get_instr (cpu), 20, 16);
6593 unsigned sn = uimm (aarch64_get_instr (cpu), 9, 5);
6594 unsigned sd = uimm (aarch64_get_instr (cpu), 4, 0);
6596 aarch64_set_FP_float (cpu, sd, aarch64_get_FP_float (cpu, sn)
6597 * aarch64_get_FP_float (cpu, sm));
6600 /* Double multiply. */
6602 fmuld (sim_cpu *cpu)
6604 unsigned sm = uimm (aarch64_get_instr (cpu), 20, 16);
6605 unsigned sn = uimm (aarch64_get_instr (cpu), 9, 5);
6606 unsigned sd = uimm (aarch64_get_instr (cpu), 4, 0);
6608 aarch64_set_FP_double (cpu, sd, aarch64_get_FP_double (cpu, sn)
6609 * aarch64_get_FP_double (cpu, sm));
6612 /* Float negate and multiply. */
6614 fnmuls (sim_cpu *cpu)
6616 unsigned sm = uimm (aarch64_get_instr (cpu), 20, 16);
6617 unsigned sn = uimm (aarch64_get_instr (cpu), 9, 5);
6618 unsigned sd = uimm (aarch64_get_instr (cpu), 4, 0);
6620 aarch64_set_FP_float (cpu, sd, - (aarch64_get_FP_float (cpu, sn)
6621 * aarch64_get_FP_float (cpu, sm)));
6624 /* Double negate and multiply. */
6626 fnmuld (sim_cpu *cpu)
6628 unsigned sm = uimm (aarch64_get_instr (cpu), 20, 16);
6629 unsigned sn = uimm (aarch64_get_instr (cpu), 9, 5);
6630 unsigned sd = uimm (aarch64_get_instr (cpu), 4, 0);
6632 aarch64_set_FP_double (cpu, sd, - (aarch64_get_FP_double (cpu, sn)
6633 * aarch64_get_FP_double (cpu, sm)));
6636 /* Float subtract. */
6638 fsubs (sim_cpu *cpu)
6640 unsigned sm = uimm (aarch64_get_instr (cpu), 20, 16);
6641 unsigned sn = uimm (aarch64_get_instr (cpu), 9, 5);
6642 unsigned sd = uimm (aarch64_get_instr (cpu), 4, 0);
6644 aarch64_set_FP_float (cpu, sd, aarch64_get_FP_float (cpu, sn)
6645 - aarch64_get_FP_float (cpu, sm));
6648 /* Double subtract. */
6650 fsubd (sim_cpu *cpu)
6652 unsigned sm = uimm (aarch64_get_instr (cpu), 20, 16);
6653 unsigned sn = uimm (aarch64_get_instr (cpu), 9, 5);
6654 unsigned sd = uimm (aarch64_get_instr (cpu), 4, 0);
6656 aarch64_set_FP_double (cpu, sd, aarch64_get_FP_double (cpu, sn)
6657 - aarch64_get_FP_double (cpu, sm));
6661 do_FMINNM (sim_cpu *cpu)
6663 /* instr[31,23] = 0 0011 1100
6664 instr[22] = float(0)/double(1)
6667 instr[15,10] = 01 1110
6671 unsigned sm = uimm (aarch64_get_instr (cpu), 20, 16);
6672 unsigned sn = uimm (aarch64_get_instr (cpu), 9, 5);
6673 unsigned sd = uimm (aarch64_get_instr (cpu), 4, 0);
6675 NYI_assert (31, 23, 0x03C);
6676 NYI_assert (15, 10, 0x1E);
6678 if (uimm (aarch64_get_instr (cpu), 22, 22))
6679 aarch64_set_FP_double (cpu, sd,
6680 dminnm (aarch64_get_FP_double (cpu, sn),
6681 aarch64_get_FP_double (cpu, sm)));
6683 aarch64_set_FP_float (cpu, sd,
6684 fminnm (aarch64_get_FP_float (cpu, sn),
6685 aarch64_get_FP_float (cpu, sm)));
6689 do_FMAXNM (sim_cpu *cpu)
6691 /* instr[31,23] = 0 0011 1100
6692 instr[22] = float(0)/double(1)
6695 instr[15,10] = 01 1010
6699 unsigned sm = uimm (aarch64_get_instr (cpu), 20, 16);
6700 unsigned sn = uimm (aarch64_get_instr (cpu), 9, 5);
6701 unsigned sd = uimm (aarch64_get_instr (cpu), 4, 0);
6703 NYI_assert (31, 23, 0x03C);
6704 NYI_assert (15, 10, 0x1A);
6706 if (uimm (aarch64_get_instr (cpu), 22, 22))
6707 aarch64_set_FP_double (cpu, sd,
6708 dmaxnm (aarch64_get_FP_double (cpu, sn),
6709 aarch64_get_FP_double (cpu, sm)));
6711 aarch64_set_FP_float (cpu, sd,
6712 fmaxnm (aarch64_get_FP_float (cpu, sn),
6713 aarch64_get_FP_float (cpu, sm)));
6717 dexSimpleFPDataProc2Source (sim_cpu *cpu)
6719 /* instr[31] ==> M : 0 ==> OK, 1 ==> UNALLOC
6721 instr[29] ==> S : 0 ==> OK, 1 ==> UNALLOC
6724 instr[23,22] ==> type : 0 ==> single, 01 ==> double, 1x ==> UNALLOC
6727 instr[15,12] ==> opcode : 0000 ==> FMUL, 0001 ==> FDIV
6728 0010 ==> FADD, 0011 ==> FSUB,
6729 0100 ==> FMAX, 0101 ==> FMIN
6730 0110 ==> FMAXNM, 0111 ==> FMINNM
6731 1000 ==> FNMUL, ow ==> UNALLOC
6736 uint32_t M_S = (uimm (aarch64_get_instr (cpu), 31, 31) << 1)
6737 | uimm (aarch64_get_instr (cpu), 29, 29);
6738 uint32_t type = uimm (aarch64_get_instr (cpu), 23, 22);
6739 /* Dispatch on opcode. */
6740 uint32_t dispatch = uimm (aarch64_get_instr (cpu), 15, 12);
6751 case 0: fmuld (cpu); return;
6752 case 1: fdivd (cpu); return;
6753 case 2: faddd (cpu); return;
6754 case 3: fsubd (cpu); return;
6755 case 6: do_FMAXNM (cpu); return;
6756 case 7: do_FMINNM (cpu); return;
6757 case 8: fnmuld (cpu); return;
6759 /* Have not yet implemented fmax and fmin. */
6767 else /* type == 0 => floats. */
6770 case 0: fmuls (cpu); return;
6771 case 1: fdivs (cpu); return;
6772 case 2: fadds (cpu); return;
6773 case 3: fsubs (cpu); return;
6774 case 6: do_FMAXNM (cpu); return;
6775 case 7: do_FMINNM (cpu); return;
6776 case 8: fnmuls (cpu); return;
6788 dexSimpleFPCondSelect (sim_cpu *cpu)
6791 instr[31,23] = 0 0011 1100
6792 instr[22] = 0=>single 1=>double
6799 unsigned sm = uimm (aarch64_get_instr (cpu), 20, 16);
6800 unsigned sn = uimm (aarch64_get_instr (cpu), 9, 5);
6801 unsigned sd = uimm (aarch64_get_instr (cpu), 4, 0);
6802 uint32_t set = testConditionCode (cpu, uimm (aarch64_get_instr (cpu), 15, 12));
6804 NYI_assert (31, 23, 0x03C);
6805 NYI_assert (11, 10, 0x3);
6807 if (uimm (aarch64_get_instr (cpu), 22, 22))
6808 aarch64_set_FP_double (cpu, sd, set ? sn : sm);
6810 aarch64_set_FP_float (cpu, sd, set ? sn : sm);
6813 /* Store 32 bit unscaled signed 9 bit. */
6815 fsturs (sim_cpu *cpu, int32_t offset)
6817 unsigned int rn = uimm (aarch64_get_instr (cpu), 9, 5);
6818 unsigned int st = uimm (aarch64_get_instr (cpu), 4, 0);
6820 aarch64_set_mem_float (cpu, aarch64_get_reg_u64 (cpu, st, 1) + offset,
6821 aarch64_get_FP_float (cpu, rn));
6824 /* Store 64 bit unscaled signed 9 bit. */
6826 fsturd (sim_cpu *cpu, int32_t offset)
6828 unsigned int rn = uimm (aarch64_get_instr (cpu), 9, 5);
6829 unsigned int st = uimm (aarch64_get_instr (cpu), 4, 0);
6831 aarch64_set_mem_double (cpu, aarch64_get_reg_u64 (cpu, st, 1) + offset,
6832 aarch64_get_FP_double (cpu, rn));
6835 /* Store 128 bit unscaled signed 9 bit. */
6837 fsturq (sim_cpu *cpu, int32_t offset)
6839 unsigned int rn = uimm (aarch64_get_instr (cpu), 9, 5);
6840 unsigned int st = uimm (aarch64_get_instr (cpu), 4, 0);
6843 aarch64_get_FP_long_double (cpu, rn, & a);
6844 aarch64_set_mem_long_double (cpu,
6845 aarch64_get_reg_u64 (cpu, st, 1)
6849 /* TODO FP move register. */
6851 /* 32 bit fp to fp move register. */
6853 ffmovs (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_float (cpu, st, aarch64_get_FP_float (cpu, rn));
6861 /* 64 bit fp to fp move register. */
6863 ffmovd (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_FP_double (cpu, st, aarch64_get_FP_double (cpu, rn));
6871 /* 32 bit GReg to Vec move register. */
6873 fgmovs (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_u32 (cpu, st, 0, aarch64_get_reg_u32 (cpu, rn, NO_SP));
6881 /* 64 bit g to fp move register. */
6883 fgmovd (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_vec_u64 (cpu, st, 0, aarch64_get_reg_u64 (cpu, rn, NO_SP));
6891 /* 32 bit fp to g move register. */
6893 gfmovs (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_u32 (cpu, rn, 0));
6901 /* 64 bit fp to g move register. */
6903 gfmovd (sim_cpu *cpu)
6905 unsigned int rn = uimm (aarch64_get_instr (cpu), 9, 5);
6906 unsigned int st = uimm (aarch64_get_instr (cpu), 4, 0);
6908 aarch64_set_reg_u64 (cpu, st, NO_SP, aarch64_get_vec_u64 (cpu, rn, 0));
6911 /* FP move immediate
6913 These install an immediate 8 bit value in the target register
6914 where the 8 bits comprise 1 sign bit, 4 bits of fraction and a 3
6918 fmovs (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 float f = fp_immediate_for_encoding_32 (imm);
6924 aarch64_set_FP_float (cpu, sd, f);
6928 fmovd (sim_cpu *cpu)
6930 unsigned int sd = uimm (aarch64_get_instr (cpu), 4, 0);
6931 uint32_t imm = uimm (aarch64_get_instr (cpu), 20, 13);
6932 double d = fp_immediate_for_encoding_64 (imm);
6934 aarch64_set_FP_double (cpu, sd, d);
6938 dexSimpleFPImmediate (sim_cpu *cpu)
6940 /* instr[31,23] == 00111100
6941 instr[22] == type : single(0)/double(1)
6943 instr[20,13] == imm8
6945 instr[9,5] == imm5 : 00000 ==> PK, ow ==> UNALLOC
6947 uint32_t imm5 = uimm (aarch64_get_instr (cpu), 9, 5);
6949 NYI_assert (31, 23, 0x3C);
6954 if (uimm (aarch64_get_instr (cpu), 22, 22))
6960 /* TODO specific decode and execute for group Load Store. */
6962 /* TODO FP load/store single register (unscaled offset). */
6964 /* TODO load 8 bit unscaled signed 9 bit. */
6965 /* TODO load 16 bit unscaled signed 9 bit. */
6967 /* Load 32 bit unscaled signed 9 bit. */
6969 fldurs (sim_cpu *cpu, int32_t offset)
6971 unsigned int rn = uimm (aarch64_get_instr (cpu), 9, 5);
6972 unsigned int st = uimm (aarch64_get_instr (cpu), 4, 0);
6974 aarch64_set_FP_float (cpu, st, aarch64_get_mem_float
6975 (cpu, aarch64_get_reg_u64 (cpu, rn, SP_OK) + offset));
6978 /* Load 64 bit unscaled signed 9 bit. */
6980 fldurd (sim_cpu *cpu, int32_t offset)
6982 unsigned int rn = uimm (aarch64_get_instr (cpu), 9, 5);
6983 unsigned int st = uimm (aarch64_get_instr (cpu), 4, 0);
6985 aarch64_set_FP_double (cpu, st, aarch64_get_mem_double
6986 (cpu, aarch64_get_reg_u64 (cpu, rn, SP_OK) + offset));
6989 /* Load 128 bit unscaled signed 9 bit. */
6991 fldurq (sim_cpu *cpu, int32_t offset)
6993 unsigned int rn = uimm (aarch64_get_instr (cpu), 9, 5);
6994 unsigned int st = uimm (aarch64_get_instr (cpu), 4, 0);
6996 uint64_t addr = aarch64_get_reg_u64 (cpu, rn, SP_OK) + offset;
6998 aarch64_get_mem_long_double (cpu, addr, & a);
6999 aarch64_set_FP_long_double (cpu, st, a);
7002 /* TODO store 8 bit unscaled signed 9 bit. */
7003 /* TODO store 16 bit unscaled signed 9 bit. */
7008 /* Float absolute value. */
7010 fabss (sim_cpu *cpu)
7012 unsigned sn = uimm (aarch64_get_instr (cpu), 9, 5);
7013 unsigned sd = uimm (aarch64_get_instr (cpu), 4, 0);
7014 float value = aarch64_get_FP_float (cpu, sn);
7016 aarch64_set_FP_float (cpu, sd, fabsf (value));
7019 /* Double absolute value. */
7021 fabcpu (sim_cpu *cpu)
7023 unsigned sn = uimm (aarch64_get_instr (cpu), 9, 5);
7024 unsigned sd = uimm (aarch64_get_instr (cpu), 4, 0);
7025 double value = aarch64_get_FP_double (cpu, sn);
7027 aarch64_set_FP_double (cpu, sd, fabs (value));
7030 /* Float negative value. */
7032 fnegs (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_float (cpu, sd, - aarch64_get_FP_float (cpu, sn));
7040 /* Double negative value. */
7042 fnegd (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_double (cpu, sd, - aarch64_get_FP_double (cpu, sn));
7050 /* Float square root. */
7052 fsqrts (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_float (cpu, sd, sqrt (aarch64_get_FP_float (cpu, sn)));
7060 /* Double square root. */
7062 fsqrtd (sim_cpu *cpu)
7064 unsigned sn = uimm (aarch64_get_instr (cpu), 9, 5);
7065 unsigned sd = uimm (aarch64_get_instr (cpu), 4, 0);
7067 aarch64_set_FP_double (cpu, sd,
7068 sqrt (aarch64_get_FP_double (cpu, sn)));
7071 /* Convert double to float. */
7073 fcvtds (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_float (cpu, sd, (float) aarch64_get_FP_double (cpu, sn));
7081 /* Convert float to double. */
7083 fcvtcpu (sim_cpu *cpu)
7085 unsigned sn = uimm (aarch64_get_instr (cpu), 9, 5);
7086 unsigned sd = uimm (aarch64_get_instr (cpu), 4, 0);
7088 aarch64_set_FP_double (cpu, sd, (double) aarch64_get_FP_float (cpu, sn));
7092 do_FRINT (sim_cpu *cpu)
7094 /* instr[31,23] = 0001 1110 0
7095 instr[22] = single(0)/double(1)
7097 instr[17,15] = rounding mode
7098 instr[14,10] = 10000
7100 instr[4,0] = dest */
7103 unsigned rs = uimm (aarch64_get_instr (cpu), 9, 5);
7104 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
7105 unsigned int rmode = uimm (aarch64_get_instr (cpu), 17, 15);
7107 NYI_assert (31, 23, 0x03C);
7108 NYI_assert (21, 18, 0x9);
7109 NYI_assert (14, 10, 0x10);
7111 if (rmode == 6 || rmode == 7)
7112 /* FIXME: Add support for rmode == 6 exactness check. */
7113 rmode = uimm (aarch64_get_FPSR (cpu), 23, 22);
7115 if (uimm (aarch64_get_instr (cpu), 22, 22))
7117 double val = aarch64_get_FP_double (cpu, rs);
7121 case 0: /* mode N: nearest or even. */
7123 double rval = round (val);
7125 if (val - rval == 0.5)
7127 if (((rval / 2.0) * 2.0) != rval)
7131 aarch64_set_FP_double (cpu, rd, round (val));
7135 case 1: /* mode P: towards +inf. */
7137 aarch64_set_FP_double (cpu, rd, trunc (val));
7139 aarch64_set_FP_double (cpu, rd, round (val));
7142 case 2: /* mode M: towards -inf. */
7144 aarch64_set_FP_double (cpu, rd, round (val));
7146 aarch64_set_FP_double (cpu, rd, trunc (val));
7149 case 3: /* mode Z: towards 0. */
7150 aarch64_set_FP_double (cpu, rd, trunc (val));
7153 case 4: /* mode A: away from 0. */
7154 aarch64_set_FP_double (cpu, rd, round (val));
7157 case 6: /* mode X: use FPCR with exactness check. */
7158 case 7: /* mode I: use FPCR mode. */
7166 val = aarch64_get_FP_float (cpu, rs);
7170 case 0: /* mode N: nearest or even. */
7172 float rval = roundf (val);
7174 if (val - rval == 0.5)
7176 if (((rval / 2.0) * 2.0) != rval)
7180 aarch64_set_FP_float (cpu, rd, rval);
7184 case 1: /* mode P: towards +inf. */
7186 aarch64_set_FP_float (cpu, rd, truncf (val));
7188 aarch64_set_FP_float (cpu, rd, roundf (val));
7191 case 2: /* mode M: towards -inf. */
7193 aarch64_set_FP_float (cpu, rd, truncf (val));
7195 aarch64_set_FP_float (cpu, rd, roundf (val));
7198 case 3: /* mode Z: towards 0. */
7199 aarch64_set_FP_float (cpu, rd, truncf (val));
7202 case 4: /* mode A: away from 0. */
7203 aarch64_set_FP_float (cpu, rd, roundf (val));
7206 case 6: /* mode X: use FPCR with exactness check. */
7207 case 7: /* mode I: use FPCR mode. */
7216 dexSimpleFPDataProc1Source (sim_cpu *cpu)
7218 /* instr[31] ==> M : 0 ==> OK, 1 ==> UNALLOC
7220 instr[29] ==> S : 0 ==> OK, 1 ==> UNALLOC
7223 instr[23,22] ==> type : 00 ==> source is single,
7224 01 ==> source is double
7226 11 ==> UNALLOC or source is half
7228 instr[20,15] ==> opcode : with type 00 or 01
7229 000000 ==> FMOV, 000001 ==> FABS,
7230 000010 ==> FNEG, 000011 ==> FSQRT,
7231 000100 ==> UNALLOC, 000101 ==> FCVT,(to single/double)
7232 000110 ==> UNALLOC, 000111 ==> FCVT (to half)
7233 001000 ==> FRINTN, 001001 ==> FRINTP,
7234 001010 ==> FRINTM, 001011 ==> FRINTZ,
7235 001100 ==> FRINTA, 001101 ==> UNALLOC
7236 001110 ==> FRINTX, 001111 ==> FRINTI
7238 000100 ==> FCVT (half-to-single)
7239 000101 ==> FCVT (half-to-double)
7240 instr[14,10] = 10000. */
7242 uint32_t M_S = (uimm (aarch64_get_instr (cpu), 31, 31) << 1)
7243 | uimm (aarch64_get_instr (cpu), 29, 29);
7244 uint32_t type = uimm (aarch64_get_instr (cpu), 23, 22);
7245 uint32_t opcode = uimm (aarch64_get_instr (cpu), 20, 15);
7252 if (opcode == 4 || opcode == 5)
7304 case 8: /* FRINTN etc. */
7314 case 7: /* FCVT double/single to half precision. */
7323 /* 32 bit signed int to float. */
7325 scvtf32 (sim_cpu *cpu)
7327 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
7328 unsigned sd = uimm (aarch64_get_instr (cpu), 4, 0);
7330 aarch64_set_FP_float
7331 (cpu, sd, (float) aarch64_get_reg_s32 (cpu, rn, NO_SP));
7334 /* signed int to float. */
7336 scvtf (sim_cpu *cpu)
7338 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
7339 unsigned sd = uimm (aarch64_get_instr (cpu), 4, 0);
7341 aarch64_set_FP_float
7342 (cpu, sd, (float) aarch64_get_reg_s64 (cpu, rn, NO_SP));
7345 /* 32 bit signed int to double. */
7347 scvtd32 (sim_cpu *cpu)
7349 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
7350 unsigned sd = uimm (aarch64_get_instr (cpu), 4, 0);
7352 aarch64_set_FP_double
7353 (cpu, sd, (double) aarch64_get_reg_s32 (cpu, rn, NO_SP));
7356 /* signed int to double. */
7358 scvtd (sim_cpu *cpu)
7360 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
7361 unsigned sd = uimm (aarch64_get_instr (cpu), 4, 0);
7363 aarch64_set_FP_double
7364 (cpu, sd, (double) aarch64_get_reg_s64 (cpu, rn, NO_SP));
7367 static const float FLOAT_INT_MAX = (float) INT_MAX;
7368 static const float FLOAT_INT_MIN = (float) INT_MIN;
7369 static const double DOUBLE_INT_MAX = (double) INT_MAX;
7370 static const double DOUBLE_INT_MIN = (double) INT_MIN;
7371 static const float FLOAT_LONG_MAX = (float) LONG_MAX;
7372 static const float FLOAT_LONG_MIN = (float) LONG_MIN;
7373 static const double DOUBLE_LONG_MAX = (double) LONG_MAX;
7374 static const double DOUBLE_LONG_MIN = (double) LONG_MIN;
7376 /* Check for FP exception conditions:
7379 Out of Range raises IO and IX and saturates value
7380 Denormal raises ID and IX and sets to zero. */
7381 #define RAISE_EXCEPTIONS(F, VALUE, FTYPE, ITYPE) \
7384 switch (fpclassify (F)) \
7388 aarch64_set_FPSR (cpu, IO); \
7390 VALUE = ITYPE##_MAX; \
7392 VALUE = ITYPE##_MIN; \
7396 if (F >= FTYPE##_##ITYPE##_MAX) \
7398 aarch64_set_FPSR_bits (cpu, IO | IX, IO | IX); \
7399 VALUE = ITYPE##_MAX; \
7401 else if (F <= FTYPE##_##ITYPE##_MIN) \
7403 aarch64_set_FPSR_bits (cpu, IO | IX, IO | IX); \
7404 VALUE = ITYPE##_MIN; \
7408 case FP_SUBNORMAL: \
7409 aarch64_set_FPSR_bits (cpu, IO | IX | ID, IX | ID); \
7421 /* 32 bit convert float to signed int truncate towards zero. */
7423 fcvtszs32 (sim_cpu *cpu)
7425 unsigned sn = uimm (aarch64_get_instr (cpu), 9, 5);
7426 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
7427 /* TODO : check that this rounds toward zero. */
7428 float f = aarch64_get_FP_float (cpu, sn);
7429 int32_t value = (int32_t) f;
7431 RAISE_EXCEPTIONS (f, value, FLOAT, INT);
7433 /* Avoid sign extension to 64 bit. */
7434 aarch64_set_reg_u64 (cpu, rd, NO_SP, (uint32_t) value);
7437 /* 64 bit convert float to signed int truncate towards zero. */
7439 fcvtszs (sim_cpu *cpu)
7441 unsigned sn = uimm (aarch64_get_instr (cpu), 9, 5);
7442 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
7443 float f = aarch64_get_FP_float (cpu, sn);
7444 int64_t value = (int64_t) f;
7446 RAISE_EXCEPTIONS (f, value, FLOAT, LONG);
7448 aarch64_set_reg_s64 (cpu, rd, NO_SP, value);
7451 /* 32 bit convert double to signed int truncate towards zero. */
7453 fcvtszd32 (sim_cpu *cpu)
7455 unsigned sn = uimm (aarch64_get_instr (cpu), 9, 5);
7456 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
7457 /* TODO : check that this rounds toward zero. */
7458 double d = aarch64_get_FP_double (cpu, sn);
7459 int32_t value = (int32_t) d;
7461 RAISE_EXCEPTIONS (d, value, DOUBLE, INT);
7463 /* Avoid sign extension to 64 bit. */
7464 aarch64_set_reg_u64 (cpu, rd, NO_SP, (uint32_t) value);
7467 /* 64 bit convert double to signed int truncate towards zero. */
7469 fcvtszd (sim_cpu *cpu)
7471 unsigned sn = uimm (aarch64_get_instr (cpu), 9, 5);
7472 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
7473 /* TODO : check that this rounds toward zero. */
7474 double d = aarch64_get_FP_double (cpu, sn);
7477 value = (int64_t) d;
7479 RAISE_EXCEPTIONS (d, value, DOUBLE, LONG);
7481 aarch64_set_reg_s64 (cpu, rd, NO_SP, value);
7485 do_fcvtzu (sim_cpu *cpu)
7487 /* instr[31] = size: 32-bit (0), 64-bit (1)
7488 instr[30,23] = 00111100
7489 instr[22] = type: single (0)/ double (1)
7490 instr[21] = enable (0)/disable(1) precision
7491 instr[20,16] = 11001
7492 instr[15,10] = precision
7496 unsigned rs = uimm (aarch64_get_instr (cpu), 9, 5);
7497 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
7499 NYI_assert (30, 23, 0x3C);
7500 NYI_assert (20, 16, 0x19);
7502 if (uimm (aarch64_get_instr (cpu), 21, 21) != 1)
7503 /* Convert to fixed point. */
7506 if (uimm (aarch64_get_instr (cpu), 31, 31))
7508 /* Convert to unsigned 64-bit integer. */
7509 if (uimm (aarch64_get_instr (cpu), 22, 22))
7511 double d = aarch64_get_FP_double (cpu, rs);
7512 uint64_t value = (uint64_t) d;
7514 /* Do not raise an exception if we have reached ULONG_MAX. */
7515 if (value != (1UL << 63))
7516 RAISE_EXCEPTIONS (d, value, DOUBLE, LONG);
7518 aarch64_set_reg_u64 (cpu, rd, NO_SP, value);
7522 float f = aarch64_get_FP_float (cpu, rs);
7523 uint64_t value = (uint64_t) f;
7525 /* Do not raise an exception if we have reached ULONG_MAX. */
7526 if (value != (1UL << 63))
7527 RAISE_EXCEPTIONS (f, value, FLOAT, LONG);
7529 aarch64_set_reg_u64 (cpu, rd, NO_SP, value);
7536 /* Convert to unsigned 32-bit integer. */
7537 if (uimm (aarch64_get_instr (cpu), 22, 22))
7539 double d = aarch64_get_FP_double (cpu, rs);
7541 value = (uint32_t) d;
7542 /* Do not raise an exception if we have reached UINT_MAX. */
7543 if (value != (1UL << 31))
7544 RAISE_EXCEPTIONS (d, value, DOUBLE, INT);
7548 float f = aarch64_get_FP_float (cpu, rs);
7550 value = (uint32_t) f;
7551 /* Do not raise an exception if we have reached UINT_MAX. */
7552 if (value != (1UL << 31))
7553 RAISE_EXCEPTIONS (f, value, FLOAT, INT);
7556 aarch64_set_reg_u64 (cpu, rd, NO_SP, value);
7561 do_UCVTF (sim_cpu *cpu)
7563 /* instr[31] = size: 32-bit (0), 64-bit (1)
7564 instr[30,23] = 001 1110 0
7565 instr[22] = type: single (0)/ double (1)
7566 instr[21] = enable (0)/disable(1) precision
7567 instr[20,16] = 0 0011
7568 instr[15,10] = precision
7572 unsigned rs = uimm (aarch64_get_instr (cpu), 9, 5);
7573 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
7575 NYI_assert (30, 23, 0x3C);
7576 NYI_assert (20, 16, 0x03);
7578 if (uimm (aarch64_get_instr (cpu), 21, 21) != 1)
7581 /* FIXME: Add exception raising. */
7582 if (uimm (aarch64_get_instr (cpu), 31, 31))
7584 uint64_t value = aarch64_get_reg_u64 (cpu, rs, NO_SP);
7586 if (uimm (aarch64_get_instr (cpu), 22, 22))
7587 aarch64_set_FP_double (cpu, rd, (double) value);
7589 aarch64_set_FP_float (cpu, rd, (float) value);
7593 uint32_t value = aarch64_get_reg_u32 (cpu, rs, NO_SP);
7595 if (uimm (aarch64_get_instr (cpu), 22, 22))
7596 aarch64_set_FP_double (cpu, rd, (double) value);
7598 aarch64_set_FP_float (cpu, rd, (float) value);
7603 float_vector_move (sim_cpu *cpu)
7605 /* instr[31,17] == 100 1111 0101 0111
7606 instr[16] ==> direction 0=> to GR, 1=> from GR
7608 instr[9,5] ==> source
7609 instr[4,0] ==> dest. */
7611 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
7612 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
7614 NYI_assert (31, 17, 0x4F57);
7616 if (uimm (aarch64_get_instr (cpu), 15, 10) != 0)
7619 if (uimm (aarch64_get_instr (cpu), 16, 16))
7620 aarch64_set_vec_u64 (cpu, rd, 1, aarch64_get_reg_u64 (cpu, rn, NO_SP));
7622 aarch64_set_reg_u64 (cpu, rd, NO_SP, aarch64_get_vec_u64 (cpu, rn, 1));
7626 dexSimpleFPIntegerConvert (sim_cpu *cpu)
7628 /* instr[31] = size : 0 ==> 32 bit, 1 ==> 64 bit
7630 instr[29] = S : 0 ==> OK, 1 ==> UNALLOC
7633 instr[23,22] = type : 00 ==> single, 01 ==> double, 1x ==> UNALLOC
7635 instr[20,19] = rmode
7636 instr[18,16] = opcode
7637 instr[15,10] = 10 0000 */
7639 uint32_t rmode_opcode;
7645 if (uimm (aarch64_get_instr (cpu), 31, 17) == 0x4F57)
7647 float_vector_move (cpu);
7651 size = uimm (aarch64_get_instr (cpu), 31, 31);
7652 S = uimm (aarch64_get_instr (cpu), 29, 29);
7656 type = uimm (aarch64_get_instr (cpu), 23, 22);
7660 rmode_opcode = uimm (aarch64_get_instr (cpu), 20, 16);
7661 size_type = (size << 1) | type; /* 0==32f, 1==32d, 2==64f, 3==64d. */
7663 switch (rmode_opcode)
7665 case 2: /* SCVTF. */
7668 case 0: scvtf32 (cpu); return;
7669 case 1: scvtd32 (cpu); return;
7670 case 2: scvtf (cpu); return;
7671 case 3: scvtd (cpu); return;
7676 case 6: /* FMOV GR, Vec. */
7679 case 0: gfmovs (cpu); return;
7680 case 3: gfmovd (cpu); return;
7681 default: HALT_UNALLOC;
7684 case 7: /* FMOV vec, GR. */
7687 case 0: fgmovs (cpu); return;
7688 case 3: fgmovd (cpu); return;
7689 default: HALT_UNALLOC;
7692 case 24: /* FCVTZS. */
7695 case 0: fcvtszs32 (cpu); return;
7696 case 1: fcvtszd32 (cpu); return;
7697 case 2: fcvtszs (cpu); return;
7698 case 3: fcvtszd (cpu); return;
7699 default: HALT_UNREACHABLE;
7702 case 25: do_fcvtzu (cpu); return;
7703 case 3: do_UCVTF (cpu); return;
7705 case 0: /* FCVTNS. */
7706 case 1: /* FCVTNU. */
7707 case 4: /* FCVTAS. */
7708 case 5: /* FCVTAU. */
7709 case 8: /* FCVPTS. */
7710 case 9: /* FCVTPU. */
7711 case 16: /* FCVTMS. */
7712 case 17: /* FCVTMU. */
7719 set_flags_for_float_compare (sim_cpu *cpu, float fvalue1, float fvalue2)
7723 if (isnan (fvalue1) || isnan (fvalue2))
7727 float result = fvalue1 - fvalue2;
7731 else if (result < 0)
7733 else /* (result > 0). */
7737 aarch64_set_CPSR (cpu, flags);
7741 fcmps (sim_cpu *cpu)
7743 unsigned sm = uimm (aarch64_get_instr (cpu), 20, 16);
7744 unsigned sn = uimm (aarch64_get_instr (cpu), 9, 5);
7746 float fvalue1 = aarch64_get_FP_float (cpu, sn);
7747 float fvalue2 = aarch64_get_FP_float (cpu, sm);
7749 set_flags_for_float_compare (cpu, fvalue1, fvalue2);
7752 /* Float compare to zero -- Invalid Operation exception
7753 only on signaling NaNs. */
7755 fcmpzs (sim_cpu *cpu)
7757 unsigned sn = uimm (aarch64_get_instr (cpu), 9, 5);
7758 float fvalue1 = aarch64_get_FP_float (cpu, sn);
7760 set_flags_for_float_compare (cpu, fvalue1, 0.0f);
7763 /* Float compare -- Invalid Operation exception on all NaNs. */
7765 fcmpes (sim_cpu *cpu)
7767 unsigned sm = uimm (aarch64_get_instr (cpu), 20, 16);
7768 unsigned sn = uimm (aarch64_get_instr (cpu), 9, 5);
7770 float fvalue1 = aarch64_get_FP_float (cpu, sn);
7771 float fvalue2 = aarch64_get_FP_float (cpu, sm);
7773 set_flags_for_float_compare (cpu, fvalue1, fvalue2);
7776 /* Float compare to zero -- Invalid Operation exception on all NaNs. */
7778 fcmpzes (sim_cpu *cpu)
7780 unsigned sn = uimm (aarch64_get_instr (cpu), 9, 5);
7781 float fvalue1 = aarch64_get_FP_float (cpu, sn);
7783 set_flags_for_float_compare (cpu, fvalue1, 0.0f);
7787 set_flags_for_double_compare (sim_cpu *cpu, double dval1, double dval2)
7791 if (isnan (dval1) || isnan (dval2))
7795 double result = dval1 - dval2;
7799 else if (result < 0)
7801 else /* (result > 0). */
7805 aarch64_set_CPSR (cpu, flags);
7808 /* Double compare -- Invalid Operation exception only on signaling NaNs. */
7810 fcmpd (sim_cpu *cpu)
7812 unsigned sm = uimm (aarch64_get_instr (cpu), 20, 16);
7813 unsigned sn = uimm (aarch64_get_instr (cpu), 9, 5);
7815 double dvalue1 = aarch64_get_FP_double (cpu, sn);
7816 double dvalue2 = aarch64_get_FP_double (cpu, sm);
7818 set_flags_for_double_compare (cpu, dvalue1, dvalue2);
7821 /* Double compare to zero -- Invalid Operation exception
7822 only on signaling NaNs. */
7824 fcmpzd (sim_cpu *cpu)
7826 unsigned sn = uimm (aarch64_get_instr (cpu), 9, 5);
7827 double dvalue1 = aarch64_get_FP_double (cpu, sn);
7829 set_flags_for_double_compare (cpu, dvalue1, 0.0);
7832 /* Double compare -- Invalid Operation exception on all NaNs. */
7834 fcmped (sim_cpu *cpu)
7836 unsigned sm = uimm (aarch64_get_instr (cpu), 20, 16);
7837 unsigned sn = uimm (aarch64_get_instr (cpu), 9, 5);
7839 double dvalue1 = aarch64_get_FP_double (cpu, sn);
7840 double dvalue2 = aarch64_get_FP_double (cpu, sm);
7842 set_flags_for_double_compare (cpu, dvalue1, dvalue2);
7845 /* Double compare to zero -- Invalid Operation exception on all NaNs. */
7847 fcmpzed (sim_cpu *cpu)
7849 unsigned sn = uimm (aarch64_get_instr (cpu), 9, 5);
7850 double dvalue1 = aarch64_get_FP_double (cpu, sn);
7852 set_flags_for_double_compare (cpu, dvalue1, 0.0);
7856 dexSimpleFPCompare (sim_cpu *cpu)
7858 /* assert instr[28,25] == 1111
7859 instr[30:24:21:13,10] = 0011000
7860 instr[31] = M : 0 ==> OK, 1 ==> UNALLOC
7861 instr[29] ==> S : 0 ==> OK, 1 ==> UNALLOC
7862 instr[23,22] ==> type : 0 ==> single, 01 ==> double, 1x ==> UNALLOC
7863 instr[15,14] ==> op : 00 ==> OK, ow ==> UNALLOC
7864 instr[4,0] ==> opcode2 : 00000 ==> FCMP, 10000 ==> FCMPE,
7865 01000 ==> FCMPZ, 11000 ==> FCMPEZ,
7868 uint32_t M_S = (uimm (aarch64_get_instr (cpu), 31, 31) << 1)
7869 | uimm (aarch64_get_instr (cpu), 29, 29);
7870 uint32_t type = uimm (aarch64_get_instr (cpu), 23, 22);
7871 uint32_t op = uimm (aarch64_get_instr (cpu), 15, 14);
7872 uint32_t op2_2_0 = uimm (aarch64_get_instr (cpu), 2, 0);
7886 /* dispatch on type and top 2 bits of opcode. */
7887 dispatch = (type << 2) | uimm (aarch64_get_instr (cpu), 4, 3);
7891 case 0: fcmps (cpu); return;
7892 case 1: fcmpzs (cpu); return;
7893 case 2: fcmpes (cpu); return;
7894 case 3: fcmpzes (cpu); return;
7895 case 4: fcmpd (cpu); return;
7896 case 5: fcmpzd (cpu); return;
7897 case 6: fcmped (cpu); return;
7898 case 7: fcmpzed (cpu); return;
7899 default: HALT_UNREACHABLE;
7904 do_scalar_FADDP (sim_cpu *cpu)
7906 /* instr [31,23] = 011111100
7907 instr [22] = single(0)/double(1)
7908 instr [21,10] = 1100 0011 0110
7910 instr [4,0] = Fd. */
7912 unsigned Fn = uimm (aarch64_get_instr (cpu), 9, 5);
7913 unsigned Fd = uimm (aarch64_get_instr (cpu), 4, 0);
7915 NYI_assert (31, 23, 0x0FC);
7916 NYI_assert (21, 10, 0xC36);
7918 if (uimm (aarch64_get_instr (cpu), 22, 22))
7920 double val1 = aarch64_get_vec_double (cpu, Fn, 0);
7921 double val2 = aarch64_get_vec_double (cpu, Fn, 1);
7923 aarch64_set_FP_double (cpu, Fd, val1 + val2);
7927 float val1 = aarch64_get_vec_float (cpu, Fn, 0);
7928 float val2 = aarch64_get_vec_float (cpu, Fn, 1);
7930 aarch64_set_FP_float (cpu, Fd, val1 + val2);
7934 /* Floating point absolute difference. */
7937 do_scalar_FABD (sim_cpu *cpu)
7939 /* instr [31,23] = 0111 1110 1
7940 instr [22] = float(0)/double(1)
7943 instr [15,10] = 1101 01
7945 instr [4, 0] = Rd. */
7947 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
7948 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
7949 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
7951 NYI_assert (31, 23, 0x0FD);
7952 NYI_assert (21, 21, 1);
7953 NYI_assert (15, 10, 0x35);
7955 if (uimm (aarch64_get_instr (cpu), 22, 22))
7956 aarch64_set_FP_double (cpu, rd,
7957 fabs (aarch64_get_FP_double (cpu, rn)
7958 - aarch64_get_FP_double (cpu, rm)));
7960 aarch64_set_FP_float (cpu, rd,
7961 fabsf (aarch64_get_FP_float (cpu, rn)
7962 - aarch64_get_FP_float (cpu, rm)));
7966 do_scalar_CMGT (sim_cpu *cpu)
7968 /* instr [31,21] = 0101 1110 111
7970 instr [15,10] = 00 1101
7972 instr [4, 0] = Rd. */
7974 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
7975 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
7976 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
7978 NYI_assert (31, 21, 0x2F7);
7979 NYI_assert (15, 10, 0x0D);
7981 aarch64_set_vec_u64 (cpu, rd, 0,
7982 aarch64_get_vec_u64 (cpu, rn, 0) >
7983 aarch64_get_vec_u64 (cpu, rm, 0) ? -1L : 0L);
7987 do_scalar_USHR (sim_cpu *cpu)
7989 /* instr [31,23] = 0111 1111 0
7990 instr [22,16] = shift amount
7991 instr [15,10] = 0000 01
7993 instr [4, 0] = Rd. */
7995 unsigned amount = 128 - uimm (aarch64_get_instr (cpu), 22, 16);
7996 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
7997 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
7999 NYI_assert (31, 23, 0x0FE);
8000 NYI_assert (15, 10, 0x01);
8002 aarch64_set_vec_u64 (cpu, rd, 0,
8003 aarch64_get_vec_u64 (cpu, rn, 0) >> amount);
8007 do_scalar_SHL (sim_cpu *cpu)
8009 /* instr [31,23] = 0111 1101 0
8010 instr [22,16] = shift amount
8011 instr [15,10] = 0101 01
8013 instr [4, 0] = Rd. */
8015 unsigned amount = uimm (aarch64_get_instr (cpu), 22, 16) - 64;
8016 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
8017 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
8019 NYI_assert (31, 23, 0x0BE);
8020 NYI_assert (15, 10, 0x15);
8022 if (uimm (aarch64_get_instr (cpu), 22, 22) == 0)
8025 aarch64_set_vec_u64 (cpu, rd, 0,
8026 aarch64_get_vec_u64 (cpu, rn, 0) << amount);
8029 /* FCMEQ FCMGT FCMGE. */
8031 do_scalar_FCM (sim_cpu *cpu)
8033 /* instr [31,30] = 01
8035 instr [28,24] = 1 1110
8040 instr [15,12] = 1110
8044 instr [4, 0] = Rd. */
8046 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
8047 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
8048 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
8049 unsigned EUac = (uimm (aarch64_get_instr (cpu), 23, 23) << 2)
8050 | (uimm (aarch64_get_instr (cpu), 29, 29) << 1)
8051 | uimm (aarch64_get_instr (cpu), 11, 11);
8056 NYI_assert (31, 30, 1);
8057 NYI_assert (28, 24, 0x1E);
8058 NYI_assert (21, 21, 1);
8059 NYI_assert (15, 12, 0xE);
8060 NYI_assert (10, 10, 1);
8062 if (uimm (aarch64_get_instr (cpu), 22, 22))
8064 double val1 = aarch64_get_FP_double (cpu, rn);
8065 double val2 = aarch64_get_FP_double (cpu, rm);
8070 result = val1 == val2;
8078 result = val1 >= val2;
8086 result = val1 > val2;
8093 aarch64_set_vec_u32 (cpu, rd, 0, result ? -1 : 0);
8097 val1 = aarch64_get_FP_float (cpu, rn);
8098 val2 = aarch64_get_FP_float (cpu, rm);
8103 result = val1 == val2;
8107 val1 = fabsf (val1);
8108 val2 = fabsf (val2);
8111 result = val1 >= val2;
8115 val1 = fabsf (val1);
8116 val2 = fabsf (val2);
8119 result = val1 > val2;
8126 aarch64_set_vec_u32 (cpu, rd, 0, result ? -1 : 0);
8129 /* An alias of DUP. */
8131 do_scalar_MOV (sim_cpu *cpu)
8133 /* instr [31,21] = 0101 1110 000
8134 instr [20,16] = imm5
8135 instr [15,10] = 0000 01
8137 instr [4, 0] = Rd. */
8139 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
8140 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
8143 NYI_assert (31, 21, 0x2F0);
8144 NYI_assert (15, 10, 0x01);
8146 if (uimm (aarch64_get_instr (cpu), 16, 16))
8149 index = uimm (aarch64_get_instr (cpu), 20, 17);
8151 (cpu, rd, 0, aarch64_get_vec_u8 (cpu, rn, index));
8153 else if (uimm (aarch64_get_instr (cpu), 17, 17))
8156 index = uimm (aarch64_get_instr (cpu), 20, 18);
8158 (cpu, rd, 0, aarch64_get_vec_u16 (cpu, rn, index));
8160 else if (uimm (aarch64_get_instr (cpu), 18, 18))
8163 index = uimm (aarch64_get_instr (cpu), 20, 19);
8165 (cpu, rd, 0, aarch64_get_vec_u32 (cpu, rn, index));
8167 else if (uimm (aarch64_get_instr (cpu), 19, 19))
8170 index = uimm (aarch64_get_instr (cpu), 20, 20);
8172 (cpu, rd, 0, aarch64_get_vec_u64 (cpu, rn, index));
8179 do_double_add (sim_cpu *cpu)
8181 /* instr [28,25] = 1111. */
8188 switch (uimm (aarch64_get_instr (cpu), 31, 23))
8191 switch (uimm (aarch64_get_instr (cpu), 15, 10))
8193 case 0x01: do_scalar_MOV (cpu); return;
8194 case 0x39: do_scalar_FCM (cpu); return;
8195 case 0x3B: do_scalar_FCM (cpu); return;
8199 case 0xBE: do_scalar_SHL (cpu); return;
8202 switch (uimm (aarch64_get_instr (cpu), 15, 10))
8204 case 0x36: do_scalar_FADDP (cpu); return;
8205 case 0x39: do_scalar_FCM (cpu); return;
8206 case 0x3B: do_scalar_FCM (cpu); return;
8211 switch (uimm (aarch64_get_instr (cpu), 15, 10))
8213 case 0x0D: do_scalar_CMGT (cpu); return;
8214 case 0x35: do_scalar_FABD (cpu); return;
8215 case 0x39: do_scalar_FCM (cpu); return;
8216 case 0x3B: do_scalar_FCM (cpu); return;
8221 case 0xFE: do_scalar_USHR (cpu); return;
8226 /* instr [31,21] = 0101 1110 111
8228 instr [15,10] = 1000 01
8230 instr [4,0] = Fd. */
8231 if (uimm (aarch64_get_instr (cpu), 31, 21) != 0x2F7
8232 || uimm (aarch64_get_instr (cpu), 15, 10) != 0x21)
8235 Fd = uimm (aarch64_get_instr (cpu), 4, 0);
8236 Fm = uimm (aarch64_get_instr (cpu), 9, 5);
8237 Fn = uimm (aarch64_get_instr (cpu), 20, 16);
8239 val1 = aarch64_get_FP_double (cpu, Fm);
8240 val2 = aarch64_get_FP_double (cpu, Fn);
8242 aarch64_set_FP_double (cpu, Fd, val1 + val2);
8246 dexAdvSIMD1 (sim_cpu *cpu)
8248 /* instr [28,25] = 1 111. */
8250 /* we are currently only interested in the basic
8251 scalar fp routines which all have bit 30 = 0. */
8252 if (uimm (aarch64_get_instr (cpu), 30, 30))
8253 do_double_add (cpu);
8255 /* instr[24] is set for FP data processing 3-source and clear for
8256 all other basic scalar fp instruction groups. */
8257 else if (uimm (aarch64_get_instr (cpu), 24, 24))
8258 dexSimpleFPDataProc3Source (cpu);
8260 /* instr[21] is clear for floating <-> fixed conversions and set for
8261 all other basic scalar fp instruction groups. */
8262 else if (!uimm (aarch64_get_instr (cpu), 21, 21))
8263 dexSimpleFPFixedConvert (cpu);
8265 /* instr[11,10] : 01 ==> cond compare, 10 ==> Data Proc 2 Source
8266 11 ==> cond select, 00 ==> other. */
8268 switch (uimm (aarch64_get_instr (cpu), 11, 10))
8270 case 1: dexSimpleFPCondCompare (cpu); return;
8271 case 2: dexSimpleFPDataProc2Source (cpu); return;
8272 case 3: dexSimpleFPCondSelect (cpu); return;
8275 /* Now an ordered cascade of tests.
8276 FP immediate has aarch64_get_instr (cpu)[12] == 1.
8277 FP compare has aarch64_get_instr (cpu)[13] == 1.
8278 FP Data Proc 1 Source has aarch64_get_instr (cpu)[14] == 1.
8279 FP floating <--> integer conversions has aarch64_get_instr (cpu)[15] == 0. */
8280 if (uimm (aarch64_get_instr (cpu), 12, 12))
8281 dexSimpleFPImmediate (cpu);
8283 else if (uimm (aarch64_get_instr (cpu), 13, 13))
8284 dexSimpleFPCompare (cpu);
8286 else if (uimm (aarch64_get_instr (cpu), 14, 14))
8287 dexSimpleFPDataProc1Source (cpu);
8289 else if (!uimm (aarch64_get_instr (cpu), 15, 15))
8290 dexSimpleFPIntegerConvert (cpu);
8293 /* If we get here then instr[15] == 1 which means UNALLOC. */
8298 /* PC relative addressing. */
8301 pcadr (sim_cpu *cpu)
8303 /* instr[31] = op : 0 ==> ADR, 1 ==> ADRP
8304 instr[30,29] = immlo
8305 instr[23,5] = immhi. */
8307 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
8308 uint32_t isPage = uimm (aarch64_get_instr (cpu), 31, 31);
8309 union { int64_t u64; uint64_t s64; } imm;
8312 imm.s64 = simm64 (aarch64_get_instr (cpu), 23, 5);
8314 offset = (offset << 2) | uimm (aarch64_get_instr (cpu), 30, 29);
8316 address = aarch64_get_PC (cpu);
8324 aarch64_set_reg_u64 (cpu, rd, NO_SP, address + offset);
8327 /* Specific decode and execute for group Data Processing Immediate. */
8330 dexPCRelAddressing (sim_cpu *cpu)
8332 /* assert instr[28,24] = 10000. */
8336 /* Immediate logical.
8337 The bimm32/64 argument is constructed by replicating a 2, 4, 8,
8338 16, 32 or 64 bit sequence pulled out at decode and possibly
8341 N.B. the output register (dest) can normally be Xn or SP
8342 the exception occurs for flag setting instructions which may
8343 only use Xn for the output (dest). The input register can
8346 /* 32 bit and immediate. */
8348 and32 (sim_cpu *cpu, uint32_t bimm)
8350 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
8351 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
8353 aarch64_set_reg_u64 (cpu, rd, SP_OK,
8354 aarch64_get_reg_u32 (cpu, rn, NO_SP) & bimm);
8357 /* 64 bit and immediate. */
8359 and64 (sim_cpu *cpu, uint64_t bimm)
8361 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
8362 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
8364 aarch64_set_reg_u64 (cpu, rd, SP_OK,
8365 aarch64_get_reg_u64 (cpu, rn, NO_SP) & bimm);
8368 /* 32 bit and immediate set flags. */
8370 ands32 (sim_cpu *cpu, uint32_t bimm)
8372 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
8373 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
8375 uint32_t value1 = aarch64_get_reg_u32 (cpu, rn, NO_SP);
8376 uint32_t value2 = bimm;
8378 aarch64_set_reg_u64 (cpu, rd, NO_SP, value1 & value2);
8379 set_flags_for_binop32 (cpu, value1 & value2);
8382 /* 64 bit and immediate set flags. */
8384 ands64 (sim_cpu *cpu, uint64_t bimm)
8386 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
8387 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
8389 uint64_t value1 = aarch64_get_reg_u64 (cpu, rn, NO_SP);
8390 uint64_t value2 = bimm;
8392 aarch64_set_reg_u64 (cpu, rd, NO_SP, value1 & value2);
8393 set_flags_for_binop64 (cpu, value1 & value2);
8396 /* 32 bit exclusive or immediate. */
8398 eor32 (sim_cpu *cpu, uint32_t bimm)
8400 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
8401 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
8403 aarch64_set_reg_u64 (cpu, rd, SP_OK,
8404 aarch64_get_reg_u32 (cpu, rn, NO_SP) ^ bimm);
8407 /* 64 bit exclusive or immediate. */
8409 eor64 (sim_cpu *cpu, uint64_t bimm)
8411 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
8412 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
8414 aarch64_set_reg_u64 (cpu, rd, SP_OK,
8415 aarch64_get_reg_u64 (cpu, rn, NO_SP) ^ bimm);
8418 /* 32 bit or immediate. */
8420 orr32 (sim_cpu *cpu, uint32_t bimm)
8422 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
8423 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
8425 aarch64_set_reg_u64 (cpu, rd, SP_OK,
8426 aarch64_get_reg_u32 (cpu, rn, NO_SP) | bimm);
8429 /* 64 bit or immediate. */
8431 orr64 (sim_cpu *cpu, uint64_t bimm)
8433 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
8434 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
8436 aarch64_set_reg_u64 (cpu, rd, SP_OK,
8437 aarch64_get_reg_u64 (cpu, rn, NO_SP) | bimm);
8440 /* Logical shifted register.
8441 These allow an optional LSL, ASR, LSR or ROR to the second source
8442 register with a count up to the register bit count.
8443 N.B register args may not be SP. */
8445 /* 32 bit AND shifted register. */
8447 and32_shift (sim_cpu *cpu, Shift shift, uint32_t count)
8449 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
8450 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
8451 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
8454 (cpu, rd, NO_SP, aarch64_get_reg_u32 (cpu, rn, NO_SP)
8455 & shifted32 (aarch64_get_reg_u32 (cpu, rm, NO_SP), shift, count));
8458 /* 64 bit AND shifted register. */
8460 and64_shift (sim_cpu *cpu, Shift shift, uint32_t count)
8462 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
8463 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
8464 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
8467 (cpu, rd, NO_SP, aarch64_get_reg_u64 (cpu, rn, NO_SP)
8468 & shifted64 (aarch64_get_reg_u64 (cpu, rm, NO_SP), shift, count));
8471 /* 32 bit AND shifted register setting flags. */
8473 ands32_shift (sim_cpu *cpu, Shift shift, uint32_t count)
8475 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
8476 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
8477 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
8479 uint32_t value1 = aarch64_get_reg_u32 (cpu, rn, NO_SP);
8480 uint32_t value2 = shifted32 (aarch64_get_reg_u32 (cpu, rm, NO_SP),
8483 aarch64_set_reg_u64 (cpu, rd, NO_SP, value1 & value2);
8484 set_flags_for_binop32 (cpu, value1 & value2);
8487 /* 64 bit AND shifted register setting flags. */
8489 ands64_shift (sim_cpu *cpu, Shift shift, uint32_t count)
8491 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
8492 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
8493 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
8495 uint64_t value1 = aarch64_get_reg_u64 (cpu, rn, NO_SP);
8496 uint64_t value2 = shifted64 (aarch64_get_reg_u64 (cpu, rm, NO_SP),
8499 aarch64_set_reg_u64 (cpu, rd, NO_SP, value1 & value2);
8500 set_flags_for_binop64 (cpu, value1 & value2);
8503 /* 32 bit BIC shifted register. */
8505 bic32_shift (sim_cpu *cpu, Shift shift, uint32_t count)
8507 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
8508 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
8509 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
8512 (cpu, rd, NO_SP, aarch64_get_reg_u32 (cpu, rn, NO_SP)
8513 & ~ shifted32 (aarch64_get_reg_u32 (cpu, rm, NO_SP), shift, count));
8516 /* 64 bit BIC shifted register. */
8518 bic64_shift (sim_cpu *cpu, Shift shift, uint32_t count)
8520 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
8521 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
8522 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
8525 (cpu, rd, NO_SP, aarch64_get_reg_u64 (cpu, rn, NO_SP)
8526 & ~ shifted64 (aarch64_get_reg_u64 (cpu, rm, NO_SP), shift, count));
8529 /* 32 bit BIC shifted register setting flags. */
8531 bics32_shift (sim_cpu *cpu, Shift shift, uint32_t count)
8533 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
8534 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
8535 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
8537 uint32_t value1 = aarch64_get_reg_u32 (cpu, rn, NO_SP);
8538 uint32_t value2 = ~ shifted32 (aarch64_get_reg_u32 (cpu, rm, NO_SP),
8541 aarch64_set_reg_u64 (cpu, rd, NO_SP, value1 & value2);
8542 set_flags_for_binop32 (cpu, value1 & value2);
8545 /* 64 bit BIC shifted register setting flags. */
8547 bics64_shift (sim_cpu *cpu, Shift shift, uint32_t count)
8549 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
8550 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
8551 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
8553 uint64_t value1 = aarch64_get_reg_u64 (cpu, rn, NO_SP);
8554 uint64_t value2 = ~ shifted64 (aarch64_get_reg_u64 (cpu, rm, NO_SP),
8557 aarch64_set_reg_u64 (cpu, rd, NO_SP, value1 & value2);
8558 set_flags_for_binop64 (cpu, value1 & value2);
8561 /* 32 bit EON shifted register. */
8563 eon32_shift (sim_cpu *cpu, Shift shift, uint32_t count)
8565 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
8566 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
8567 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
8570 (cpu, rd, NO_SP, aarch64_get_reg_u32 (cpu, rn, NO_SP)
8571 ^ ~ shifted32 (aarch64_get_reg_u32 (cpu, rm, NO_SP), shift, count));
8574 /* 64 bit EON shifted register. */
8576 eon64_shift (sim_cpu *cpu, Shift shift, uint32_t count)
8578 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
8579 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
8580 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
8583 (cpu, rd, NO_SP, aarch64_get_reg_u64 (cpu, rn, NO_SP)
8584 ^ ~ shifted64 (aarch64_get_reg_u64 (cpu, rm, NO_SP), shift, count));
8587 /* 32 bit EOR shifted register. */
8589 eor32_shift (sim_cpu *cpu, Shift shift, uint32_t count)
8591 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
8592 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
8593 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
8596 (cpu, rd, NO_SP, aarch64_get_reg_u32 (cpu, rn, NO_SP)
8597 ^ shifted32 (aarch64_get_reg_u32 (cpu, rm, NO_SP), shift, count));
8600 /* 64 bit EOR shifted register. */
8602 eor64_shift (sim_cpu *cpu, Shift shift, uint32_t count)
8604 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
8605 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
8606 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
8609 (cpu, rd, NO_SP, aarch64_get_reg_u64 (cpu, rn, NO_SP)
8610 ^ shifted64 (aarch64_get_reg_u64 (cpu, rm, NO_SP), shift, count));
8613 /* 32 bit ORR shifted register. */
8615 orr32_shift (sim_cpu *cpu, Shift shift, uint32_t count)
8617 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
8618 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
8619 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
8622 (cpu, rd, NO_SP, aarch64_get_reg_u32 (cpu, rn, NO_SP)
8623 | shifted32 (aarch64_get_reg_u32 (cpu, rm, NO_SP), shift, count));
8626 /* 64 bit ORR shifted register. */
8628 orr64_shift (sim_cpu *cpu, Shift shift, uint32_t count)
8630 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
8631 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
8632 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
8635 (cpu, rd, NO_SP, aarch64_get_reg_u64 (cpu, rn, NO_SP)
8636 | shifted64 (aarch64_get_reg_u64 (cpu, rm, NO_SP), shift, count));
8639 /* 32 bit ORN shifted register. */
8641 orn32_shift (sim_cpu *cpu, Shift shift, uint32_t count)
8643 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
8644 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
8645 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
8648 (cpu, rd, NO_SP, aarch64_get_reg_u32 (cpu, rn, NO_SP)
8649 | ~ shifted32 (aarch64_get_reg_u32 (cpu, rm, NO_SP), shift, count));
8652 /* 64 bit ORN shifted register. */
8654 orn64_shift (sim_cpu *cpu, Shift shift, uint32_t count)
8656 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
8657 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
8658 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
8661 (cpu, rd, NO_SP, aarch64_get_reg_u64 (cpu, rn, NO_SP)
8662 | ~ shifted64 (aarch64_get_reg_u64 (cpu, rm, NO_SP), shift, count));
8666 dexLogicalImmediate (sim_cpu *cpu)
8668 /* assert instr[28,23] = 1001000
8669 instr[31] = size : 0 ==> 32 bit, 1 ==> 64 bit
8670 instr[30,29] = op : 0 ==> AND, 1 ==> ORR, 2 ==> EOR, 3 ==> ANDS
8671 instr[22] = N : used to construct immediate mask
8677 /* 32 bit operations must have N = 0 or else we have an UNALLOC. */
8678 uint32_t size = uimm (aarch64_get_instr (cpu), 31, 31);
8679 uint32_t N = uimm (aarch64_get_instr (cpu), 22, 22);
8680 /* uint32_t immr = uimm (aarch64_get_instr (cpu), 21, 16);. */
8681 /* uint32_t imms = uimm (aarch64_get_instr (cpu), 15, 10);. */
8682 uint32_t index = uimm (aarch64_get_instr (cpu), 22, 10);
8683 uint64_t bimm64 = LITable [index];
8684 uint32_t dispatch = uimm (aarch64_get_instr (cpu), 30, 29);
8694 uint32_t bimm = (uint32_t) bimm64;
8698 case 0: and32 (cpu, bimm); return;
8699 case 1: orr32 (cpu, bimm); return;
8700 case 2: eor32 (cpu, bimm); return;
8701 case 3: ands32 (cpu, bimm); return;
8708 case 0: and64 (cpu, bimm64); return;
8709 case 1: orr64 (cpu, bimm64); return;
8710 case 2: eor64 (cpu, bimm64); return;
8711 case 3: ands64 (cpu, bimm64); return;
8718 The uimm argument is a 16 bit value to be inserted into the
8719 target register the pos argument locates the 16 bit word in the
8720 dest register i.e. it is in {0, 1} for 32 bit and {0, 1, 2,
8722 N.B register arg may not be SP so it should be.
8723 accessed using the setGZRegisterXXX accessors. */
8725 /* 32 bit move 16 bit immediate zero remaining shorts. */
8727 movz32 (sim_cpu *cpu, uint32_t val, uint32_t pos)
8729 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
8731 aarch64_set_reg_u64 (cpu, rd, NO_SP, val << (pos * 16));
8734 /* 64 bit move 16 bit immediate zero remaining shorts. */
8736 movz64 (sim_cpu *cpu, uint32_t val, uint32_t pos)
8738 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
8740 aarch64_set_reg_u64 (cpu, rd, NO_SP, ((uint64_t) val) << (pos * 16));
8743 /* 32 bit move 16 bit immediate negated. */
8745 movn32 (sim_cpu *cpu, uint32_t val, uint32_t pos)
8747 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
8749 aarch64_set_reg_u64 (cpu, rd, NO_SP, ((val << (pos * 16)) ^ 0xffffffffU));
8752 /* 64 bit move 16 bit immediate negated. */
8754 movn64 (sim_cpu *cpu, uint32_t val, uint32_t pos)
8756 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
8759 (cpu, rd, NO_SP, ((((uint64_t) val) << (pos * 16))
8760 ^ 0xffffffffffffffffULL));
8763 /* 32 bit move 16 bit immediate keep remaining shorts. */
8765 movk32 (sim_cpu *cpu, uint32_t val, uint32_t pos)
8767 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
8768 uint32_t current = aarch64_get_reg_u32 (cpu, rd, NO_SP);
8769 uint32_t value = val << (pos * 16);
8770 uint32_t mask = ~(0xffffU << (pos * 16));
8772 aarch64_set_reg_u64 (cpu, rd, NO_SP, (value | (current & mask)));
8775 /* 64 bit move 16 it immediate keep remaining shorts. */
8777 movk64 (sim_cpu *cpu, uint32_t val, uint32_t pos)
8779 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
8780 uint64_t current = aarch64_get_reg_u64 (cpu, rd, NO_SP);
8781 uint64_t value = (uint64_t) val << (pos * 16);
8782 uint64_t mask = ~(0xffffULL << (pos * 16));
8784 aarch64_set_reg_u64 (cpu, rd, NO_SP, (value | (current & mask)));
8788 dexMoveWideImmediate (sim_cpu *cpu)
8790 /* assert instr[28:23] = 100101
8791 instr[31] = size : 0 ==> 32 bit, 1 ==> 64 bit
8792 instr[30,29] = op : 0 ==> MOVN, 1 ==> UNALLOC, 2 ==> MOVZ, 3 ==> MOVK
8793 instr[22,21] = shift : 00 == LSL#0, 01 = LSL#16, 10 = LSL#32, 11 = LSL#48
8794 instr[20,5] = uimm16
8797 /* N.B. the (multiple of 16) shift is applied by the called routine,
8798 we just pass the multiplier. */
8801 uint32_t size = uimm (aarch64_get_instr (cpu), 31, 31);
8802 uint32_t op = uimm (aarch64_get_instr (cpu), 30, 29);
8803 uint32_t shift = uimm (aarch64_get_instr (cpu), 22, 21);
8805 /* 32 bit can only shift 0 or 1 lot of 16.
8806 anything else is an unallocated instruction. */
8807 if (size == 0 && (shift > 1))
8813 imm = uimm (aarch64_get_instr (cpu), 20, 5);
8818 movn32 (cpu, imm, shift);
8820 movz32 (cpu, imm, shift);
8822 movk32 (cpu, imm, shift);
8827 movn64 (cpu, imm, shift);
8829 movz64 (cpu, imm, shift);
8831 movk64 (cpu, imm, shift);
8835 /* Bitfield operations.
8836 These take a pair of bit positions r and s which are in {0..31}
8837 or {0..63} depending on the instruction word size.
8838 N.B register args may not be SP. */
8840 /* OK, we start with ubfm which just needs to pick
8841 some bits out of source zero the rest and write
8842 the result to dest. Just need two logical shifts. */
8844 /* 32 bit bitfield move, left and right of affected zeroed
8845 if r <= s Wd<s-r:0> = Wn<s:r> else Wd<32+s-r,32-r> = Wn<s:0>. */
8847 ubfm32 (sim_cpu *cpu, uint32_t r, uint32_t s)
8850 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
8851 uint32_t value = aarch64_get_reg_u32 (cpu, rn, NO_SP);
8853 /* Pick either s+1-r or s+1 consecutive bits out of the original word. */
8856 /* 31:...:s:xxx:r:...:0 ==> 31:...:s-r:xxx:0.
8857 We want only bits s:xxx:r at the bottom of the word
8858 so we LSL bit s up to bit 31 i.e. by 31 - s
8859 and then we LSR to bring bit 31 down to bit s - r
8860 i.e. by 31 + r - s. */
8862 value >>= 31 + r - s;
8866 /* 31:...:s:xxx:0 ==> 31:...:31-(r-1)+s:xxx:31-(r-1):...:0
8867 We want only bits s:xxx:0 starting at it 31-(r-1)
8868 so we LSL bit s up to bit 31 i.e. by 31 - s
8869 and then we LSL to bring bit 31 down to 31-(r-1)+s
8870 i.e. by r - (s + 1). */
8872 value >>= r - (s + 1);
8875 rd = uimm (aarch64_get_instr (cpu), 4, 0);
8876 aarch64_set_reg_u64 (cpu, rd, NO_SP, value);
8879 /* 64 bit bitfield move, left and right of affected zeroed
8880 if r <= s Wd<s-r:0> = Wn<s:r> else Wd<64+s-r,64-r> = Wn<s:0>. */
8882 ubfm (sim_cpu *cpu, uint32_t r, uint32_t s)
8885 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
8886 uint64_t value = aarch64_get_reg_u64 (cpu, rn, NO_SP);
8890 /* 63:...:s:xxx:r:...:0 ==> 63:...:s-r:xxx:0.
8891 We want only bits s:xxx:r at the bottom of the word.
8892 So we LSL bit s up to bit 63 i.e. by 63 - s
8893 and then we LSR to bring bit 63 down to bit s - r
8894 i.e. by 63 + r - s. */
8896 value >>= 63 + r - s;
8900 /* 63:...:s:xxx:0 ==> 63:...:63-(r-1)+s:xxx:63-(r-1):...:0.
8901 We want only bits s:xxx:0 starting at it 63-(r-1).
8902 So we LSL bit s up to bit 63 i.e. by 63 - s
8903 and then we LSL to bring bit 63 down to 63-(r-1)+s
8904 i.e. by r - (s + 1). */
8906 value >>= r - (s + 1);
8909 rd = uimm (aarch64_get_instr (cpu), 4, 0);
8910 aarch64_set_reg_u64 (cpu, rd, NO_SP, value);
8913 /* The signed versions need to insert sign bits
8914 on the left of the inserted bit field. so we do
8915 much the same as the unsigned version except we
8916 use an arithmetic shift right -- this just means
8917 we need to operate on signed values. */
8919 /* 32 bit bitfield move, left of affected sign-extended, right zeroed. */
8920 /* If r <= s Wd<s-r:0> = Wn<s:r> else Wd<32+s-r,32-r> = Wn<s:0>. */
8922 sbfm32 (sim_cpu *cpu, uint32_t r, uint32_t s)
8925 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
8926 /* as per ubfm32 but use an ASR instead of an LSR. */
8927 int32_t value = aarch64_get_reg_s32 (cpu, rn, NO_SP);
8932 value >>= 31 + r - s;
8937 value >>= r - (s + 1);
8940 rd = uimm (aarch64_get_instr (cpu), 4, 0);
8941 aarch64_set_reg_u64 (cpu, rd, NO_SP, (uint32_t) value);
8944 /* 64 bit bitfield move, left of affected sign-extended, right zeroed. */
8945 /* If r <= s Wd<s-r:0> = Wn<s:r> else Wd<64+s-r,64-r> = Wn<s:0>. */
8947 sbfm (sim_cpu *cpu, uint32_t r, uint32_t s)
8950 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
8951 /* acpu per ubfm but use an ASR instead of an LSR. */
8952 int64_t value = aarch64_get_reg_s64 (cpu, rn, NO_SP);
8957 value >>= 63 + r - s;
8962 value >>= r - (s + 1);
8965 rd = uimm (aarch64_get_instr (cpu), 4, 0);
8966 aarch64_set_reg_s64 (cpu, rd, NO_SP, value);
8969 /* Finally, these versions leave non-affected bits
8970 as is. so we need to generate the bits as per
8971 ubfm and also generate a mask to pick the
8972 bits from the original and computed values. */
8974 /* 32 bit bitfield move, non-affected bits left as is.
8975 If r <= s Wd<s-r:0> = Wn<s:r> else Wd<32+s-r,32-r> = Wn<s:0>. */
8977 bfm32 (sim_cpu *cpu, uint32_t r, uint32_t s)
8979 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
8980 uint32_t value = aarch64_get_reg_u32 (cpu, rn, NO_SP);
8985 /* Pick either s+1-r or s+1 consecutive bits out of the original word. */
8988 /* 31:...:s:xxx:r:...:0 ==> 31:...:s-r:xxx:0.
8989 We want only bits s:xxx:r at the bottom of the word
8990 so we LSL bit s up to bit 31 i.e. by 31 - s
8991 and then we LSR to bring bit 31 down to bit s - r
8992 i.e. by 31 + r - s. */
8994 value >>= 31 + r - s;
8995 /* the mask must include the same bits. */
8997 mask >>= 31 + r - s;
9001 /* 31:...:s:xxx:0 ==> 31:...:31-(r-1)+s:xxx:31-(r-1):...:0.
9002 We want only bits s:xxx:0 starting at it 31-(r-1)
9003 so we LSL bit s up to bit 31 i.e. by 31 - s
9004 and then we LSL to bring bit 31 down to 31-(r-1)+s
9005 i.e. by r - (s + 1). */
9007 value >>= r - (s + 1);
9008 /* The mask must include the same bits. */
9010 mask >>= r - (s + 1);
9013 rd = uimm (aarch64_get_instr (cpu), 4, 0);
9014 value2 = aarch64_get_reg_u32 (cpu, rd, NO_SP);
9020 (cpu, rd, NO_SP, (aarch64_get_reg_u32 (cpu, rd, NO_SP) & ~mask) | value);
9023 /* 64 bit bitfield move, non-affected bits left as is.
9024 If r <= s Wd<s-r:0> = Wn<s:r> else Wd<64+s-r,64-r> = Wn<s:0>. */
9026 bfm (sim_cpu *cpu, uint32_t r, uint32_t s)
9029 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
9030 uint64_t value = aarch64_get_reg_u64 (cpu, rn, NO_SP);
9031 uint64_t mask = 0xffffffffffffffffULL;
9035 /* 63:...:s:xxx:r:...:0 ==> 63:...:s-r:xxx:0.
9036 We want only bits s:xxx:r at the bottom of the word
9037 so we LSL bit s up to bit 63 i.e. by 63 - s
9038 and then we LSR to bring bit 63 down to bit s - r
9039 i.e. by 63 + r - s. */
9041 value >>= 63 + r - s;
9042 /* The mask must include the same bits. */
9044 mask >>= 63 + r - s;
9048 /* 63:...:s:xxx:0 ==> 63:...:63-(r-1)+s:xxx:63-(r-1):...:0
9049 We want only bits s:xxx:0 starting at it 63-(r-1)
9050 so we LSL bit s up to bit 63 i.e. by 63 - s
9051 and then we LSL to bring bit 63 down to 63-(r-1)+s
9052 i.e. by r - (s + 1). */
9054 value >>= r - (s + 1);
9055 /* The mask must include the same bits. */
9057 mask >>= r - (s + 1);
9060 rd = uimm (aarch64_get_instr (cpu), 4, 0);
9062 (cpu, rd, NO_SP, (aarch64_get_reg_u64 (cpu, rd, NO_SP) & ~mask) | value);
9066 dexBitfieldImmediate (sim_cpu *cpu)
9068 /* assert instr[28:23] = 100110
9069 instr[31] = size : 0 ==> 32 bit, 1 ==> 64 bit
9070 instr[30,29] = op : 0 ==> SBFM, 1 ==> BFM, 2 ==> UBFM, 3 ==> UNALLOC
9071 instr[22] = N : must be 0 for 32 bit, 1 for 64 bit ow UNALLOC
9072 instr[21,16] = immr : 0xxxxx for 32 bit, xxxxxx for 64 bit
9073 instr[15,10] = imms : 0xxxxx for 32 bit, xxxxxx for 64 bit
9077 /* 32 bit operations must have N = 0 or else we have an UNALLOC. */
9080 uint32_t size = uimm (aarch64_get_instr (cpu), 31, 31);
9081 uint32_t N = uimm (aarch64_get_instr (cpu), 22, 22);
9082 /* 32 bit operations must have immr[5] = 0 and imms[5] = 0. */
9083 /* or else we have an UNALLOC. */
9084 uint32_t immr = uimm (aarch64_get_instr (cpu), 21, 16);
9089 if (!size && uimm (immr, 5, 5))
9092 imms = uimm (aarch64_get_instr (cpu), 15, 10);
9093 if (!size && uimm (imms, 5, 5))
9096 /* Switch on combined size and op. */
9097 dispatch = uimm (aarch64_get_instr (cpu), 31, 29);
9100 case 0: sbfm32 (cpu, immr, imms); return;
9101 case 1: bfm32 (cpu, immr, imms); return;
9102 case 2: ubfm32 (cpu, immr, imms); return;
9103 case 4: sbfm (cpu, immr, imms); return;
9104 case 5: bfm (cpu, immr, imms); return;
9105 case 6: ubfm (cpu, immr, imms); return;
9106 default: HALT_UNALLOC;
9111 do_EXTR_32 (sim_cpu *cpu)
9113 /* instr[31:21] = 00010011100
9115 instr[15,10] = imms : 0xxxxx for 32 bit
9118 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
9119 unsigned imms = uimm (aarch64_get_instr (cpu), 15, 10) & 31;
9120 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
9121 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
9125 val1 = aarch64_get_reg_u32 (cpu, rm, NO_SP);
9127 val2 = aarch64_get_reg_u32 (cpu, rn, NO_SP);
9128 val2 <<= (32 - imms);
9130 aarch64_set_reg_u64 (cpu, rd, NO_SP, val1 | val2);
9134 do_EXTR_64 (sim_cpu *cpu)
9136 /* instr[31:21] = 10010011100
9141 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
9142 unsigned imms = uimm (aarch64_get_instr (cpu), 15, 10) & 63;
9143 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
9144 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
9147 val = aarch64_get_reg_u64 (cpu, rm, NO_SP);
9149 val |= (aarch64_get_reg_u64 (cpu, rn, NO_SP) << (64 - imms));
9151 aarch64_set_reg_u64 (cpu, rd, NO_SP, val);
9155 dexExtractImmediate (sim_cpu *cpu)
9157 /* assert instr[28:23] = 100111
9158 instr[31] = size : 0 ==> 32 bit, 1 ==> 64 bit
9159 instr[30,29] = op21 : 0 ==> EXTR, 1,2,3 ==> UNALLOC
9160 instr[22] = N : must be 0 for 32 bit, 1 for 64 bit or UNALLOC
9161 instr[21] = op0 : must be 0 or UNALLOC
9163 instr[15,10] = imms : 0xxxxx for 32 bit, xxxxxx for 64 bit
9167 /* 32 bit operations must have N = 0 or else we have an UNALLOC. */
9168 /* 64 bit operations must have N = 1 or else we have an UNALLOC. */
9170 uint32_t size = uimm (aarch64_get_instr (cpu), 31, 31);
9171 uint32_t N = uimm (aarch64_get_instr (cpu), 22, 22);
9172 /* 32 bit operations must have imms[5] = 0
9173 or else we have an UNALLOC. */
9174 uint32_t imms = uimm (aarch64_get_instr (cpu), 15, 10);
9179 if (!size && uimm (imms, 5, 5))
9182 /* Switch on combined size and op. */
9183 dispatch = uimm (aarch64_get_instr (cpu), 31, 29);
9188 else if (dispatch == 4)
9191 else if (dispatch == 1)
9198 dexDPImm (sim_cpu *cpu)
9200 /* uint32_t group = dispatchGroup (aarch64_get_instr (cpu));
9201 assert group == GROUP_DPIMM_1000 || grpoup == GROUP_DPIMM_1001
9202 bits [25,23] of a DPImm are the secondary dispatch vector. */
9203 uint32_t group2 = dispatchDPImm (aarch64_get_instr (cpu));
9207 case DPIMM_PCADR_000:
9208 case DPIMM_PCADR_001:
9209 dexPCRelAddressing (cpu);
9212 case DPIMM_ADDSUB_010:
9213 case DPIMM_ADDSUB_011:
9214 dexAddSubtractImmediate (cpu);
9218 dexLogicalImmediate (cpu);
9222 dexMoveWideImmediate (cpu);
9225 case DPIMM_BITF_110:
9226 dexBitfieldImmediate (cpu);
9229 case DPIMM_EXTR_111:
9230 dexExtractImmediate (cpu);
9234 /* Should never reach here. */
9240 dexLoadUnscaledImmediate (sim_cpu *cpu)
9242 /* instr[29,24] == 111_00
9248 instr[20,12] = simm9
9249 instr[9,5] = rn may be SP. */
9250 /* unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0); */
9251 uint32_t V = uimm (aarch64_get_instr (cpu), 26, 26);
9252 uint32_t dispatch = ( (uimm (aarch64_get_instr (cpu), 31, 30) << 2)
9253 | uimm (aarch64_get_instr (cpu), 23, 22));
9254 int32_t imm = simm32 (aarch64_get_instr (cpu), 20, 12);
9258 /* GReg operations. */
9261 case 0: sturb (cpu, imm); return;
9262 case 1: ldurb32 (cpu, imm); return;
9263 case 2: ldursb64 (cpu, imm); return;
9264 case 3: ldursb32 (cpu, imm); return;
9265 case 4: sturh (cpu, imm); return;
9266 case 5: ldurh32 (cpu, imm); return;
9267 case 6: ldursh64 (cpu, imm); return;
9268 case 7: ldursh32 (cpu, imm); return;
9269 case 8: stur32 (cpu, imm); return;
9270 case 9: ldur32 (cpu, imm); return;
9271 case 10: ldursw (cpu, imm); return;
9272 case 12: stur64 (cpu, imm); return;
9273 case 13: ldur64 (cpu, imm); return;
9286 /* FReg operations. */
9289 case 2: fsturq (cpu, imm); return;
9290 case 3: fldurq (cpu, imm); return;
9291 case 8: fsturs (cpu, imm); return;
9292 case 9: fldurs (cpu, imm); return;
9293 case 12: fsturd (cpu, imm); return;
9294 case 13: fldurd (cpu, imm); return;
9296 case 0: /* STUR 8 bit FP. */
9297 case 1: /* LDUR 8 bit FP. */
9298 case 4: /* STUR 16 bit FP. */
9299 case 5: /* LDUR 8 bit FP. */
9313 /* N.B. A preliminary note regarding all the ldrs<x>32
9316 The signed value loaded by these instructions is cast to unsigned
9317 before being assigned to aarch64_get_reg_u64 (cpu, N) i.e. to the
9318 64 bit element of the GReg union. this performs a 32 bit sign extension
9319 (as required) but avoids 64 bit sign extension, thus ensuring that the
9320 top half of the register word is zero. this is what the spec demands
9321 when a 32 bit load occurs. */
9323 /* 32 bit load sign-extended byte scaled unsigned 12 bit. */
9325 ldrsb32_abs (sim_cpu *cpu, uint32_t offset)
9327 unsigned int rn = uimm (aarch64_get_instr (cpu), 9, 5);
9328 unsigned int rt = uimm (aarch64_get_instr (cpu), 4, 0);
9330 /* The target register may not be SP but the source may be
9331 there is no scaling required for a byte load. */
9332 uint64_t address = aarch64_get_reg_u64 (cpu, rn, SP_OK) + offset;
9333 aarch64_set_reg_u64 (cpu, rt, NO_SP,
9334 (int64_t) aarch64_get_mem_s8 (cpu, address));
9337 /* 32 bit load sign-extended byte scaled or unscaled zero-
9338 or sign-extended 32-bit register offset. */
9340 ldrsb32_scale_ext (sim_cpu *cpu, Scaling scaling, Extension extension)
9342 unsigned int rm = uimm (aarch64_get_instr (cpu), 20, 16);
9343 unsigned int rn = uimm (aarch64_get_instr (cpu), 9, 5);
9344 unsigned int rt = uimm (aarch64_get_instr (cpu), 4, 0);
9346 /* rn may reference SP, rm and rt must reference ZR. */
9348 uint64_t address = aarch64_get_reg_u64 (cpu, rn, SP_OK);
9349 int64_t displacement = extend (aarch64_get_reg_u32 (cpu, rm, NO_SP),
9352 /* There is no scaling required for a byte load. */
9354 (cpu, rt, NO_SP, (int64_t) aarch64_get_mem_s8 (cpu, address
9358 /* 32 bit load sign-extended byte unscaled signed 9 bit with
9359 pre- or post-writeback. */
9361 ldrsb32_wb (sim_cpu *cpu, int32_t offset, WriteBack wb)
9364 unsigned int rn = uimm (aarch64_get_instr (cpu), 9, 5);
9365 unsigned int rt = uimm (aarch64_get_instr (cpu), 4, 0);
9367 if (rn == rt && wb != NoWriteBack)
9370 address = aarch64_get_reg_u64 (cpu, rn, SP_OK);
9375 aarch64_set_reg_u64 (cpu, rt, NO_SP,
9376 (int64_t) aarch64_get_mem_s8 (cpu, address));
9381 if (wb != NoWriteBack)
9382 aarch64_set_reg_u64 (cpu, rn, NO_SP, address);
9385 /* 8 bit store scaled. */
9387 fstrb_abs (sim_cpu *cpu, uint32_t offset)
9389 unsigned st = uimm (aarch64_get_instr (cpu), 4, 0);
9390 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
9392 aarch64_set_mem_u8 (cpu,
9393 aarch64_get_reg_u64 (cpu, rn, SP_OK) + offset,
9394 aarch64_get_vec_u8 (cpu, st, 0));
9397 /* 8 bit store scaled or unscaled zero- or
9398 sign-extended 8-bit register offset. */
9400 fstrb_scale_ext (sim_cpu *cpu, Scaling scaling, Extension extension)
9402 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
9403 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
9404 unsigned st = uimm (aarch64_get_instr (cpu), 4, 0);
9406 uint64_t address = aarch64_get_reg_u64 (cpu, rn, SP_OK);
9407 int64_t extended = extend (aarch64_get_reg_u32 (cpu, rm, NO_SP),
9409 uint64_t displacement = OPT_SCALE (extended, 32, scaling);
9412 (cpu, address + displacement, aarch64_get_vec_u8 (cpu, st, 0));
9415 /* 16 bit store scaled. */
9417 fstrh_abs (sim_cpu *cpu, uint32_t offset)
9419 unsigned st = uimm (aarch64_get_instr (cpu), 4, 0);
9420 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
9424 aarch64_get_reg_u64 (cpu, rn, SP_OK) + SCALE (offset, 16),
9425 aarch64_get_vec_u16 (cpu, st, 0));
9428 /* 16 bit store scaled or unscaled zero-
9429 or sign-extended 16-bit register offset. */
9431 fstrh_scale_ext (sim_cpu *cpu, Scaling scaling, Extension extension)
9433 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
9434 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
9435 unsigned st = uimm (aarch64_get_instr (cpu), 4, 0);
9437 uint64_t address = aarch64_get_reg_u64 (cpu, rn, SP_OK);
9438 int64_t extended = extend (aarch64_get_reg_u32 (cpu, rm, NO_SP),
9440 uint64_t displacement = OPT_SCALE (extended, 32, scaling);
9443 (cpu, address + displacement, aarch64_get_vec_u16 (cpu, st, 0));
9446 /* 32 bit store scaled unsigned 12 bit. */
9448 fstrs_abs (sim_cpu *cpu, uint32_t offset)
9450 unsigned st = uimm (aarch64_get_instr (cpu), 4, 0);
9451 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
9453 aarch64_set_mem_float
9455 aarch64_get_reg_u64 (cpu, rn, SP_OK) + SCALE (offset, 32),
9456 aarch64_get_FP_float (cpu, st));
9459 /* 32 bit store unscaled signed 9 bit with pre- or post-writeback. */
9461 fstrs_wb (sim_cpu *cpu, int32_t offset, WriteBack wb)
9463 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
9464 unsigned st = uimm (aarch64_get_instr (cpu), 4, 0);
9466 uint64_t address = aarch64_get_reg_u64 (cpu, rn, SP_OK);
9471 aarch64_set_mem_float (cpu, address, aarch64_get_FP_float (cpu, st));
9476 if (wb != NoWriteBack)
9477 aarch64_set_reg_u64 (cpu, rn, SP_OK, address);
9480 /* 32 bit store scaled or unscaled zero-
9481 or sign-extended 32-bit register offset. */
9483 fstrs_scale_ext (sim_cpu *cpu, Scaling scaling, Extension extension)
9485 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
9486 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
9487 unsigned st = uimm (aarch64_get_instr (cpu), 4, 0);
9489 uint64_t address = aarch64_get_reg_u64 (cpu, rn, SP_OK);
9490 int64_t extended = extend (aarch64_get_reg_u32 (cpu, rm, NO_SP),
9492 uint64_t displacement = OPT_SCALE (extended, 32, scaling);
9494 aarch64_set_mem_float
9495 (cpu, address + displacement, aarch64_get_FP_float (cpu, st));
9498 /* 64 bit store scaled unsigned 12 bit. */
9500 fstrd_abs (sim_cpu *cpu, uint32_t offset)
9502 unsigned st = uimm (aarch64_get_instr (cpu), 4, 0);
9503 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
9505 aarch64_set_mem_double
9507 aarch64_get_reg_u64 (cpu, rn, SP_OK) + SCALE (offset, 64),
9508 aarch64_get_FP_double (cpu, st));
9511 /* 64 bit store unscaled signed 9 bit with pre- or post-writeback. */
9513 fstrd_wb (sim_cpu *cpu, int32_t offset, WriteBack wb)
9515 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
9516 unsigned st = uimm (aarch64_get_instr (cpu), 4, 0);
9518 uint64_t address = aarch64_get_reg_u64 (cpu, rn, SP_OK);
9523 aarch64_set_mem_double (cpu, address, aarch64_get_FP_double (cpu, st));
9528 if (wb != NoWriteBack)
9529 aarch64_set_reg_u64 (cpu, rn, SP_OK, address);
9532 /* 64 bit store scaled or unscaled zero-
9533 or sign-extended 32-bit register offset. */
9535 fstrd_scale_ext (sim_cpu *cpu, Scaling scaling, Extension extension)
9537 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
9538 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
9539 unsigned st = uimm (aarch64_get_instr (cpu), 4, 0);
9541 uint64_t address = aarch64_get_reg_u64 (cpu, rn, SP_OK);
9542 int64_t extended = extend (aarch64_get_reg_u32 (cpu, rm, NO_SP),
9544 uint64_t displacement = OPT_SCALE (extended, 64, scaling);
9546 aarch64_set_mem_double
9547 (cpu, address + displacement, aarch64_get_FP_double (cpu, st));
9550 /* 128 bit store scaled unsigned 12 bit. */
9552 fstrq_abs (sim_cpu *cpu, uint32_t offset)
9555 unsigned st = uimm (aarch64_get_instr (cpu), 4, 0);
9556 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
9559 aarch64_get_FP_long_double (cpu, st, & a);
9561 addr = aarch64_get_reg_u64 (cpu, rn, SP_OK) + SCALE (offset, 128);
9562 aarch64_set_mem_long_double (cpu, addr, a);
9565 /* 128 bit store unscaled signed 9 bit with pre- or post-writeback. */
9567 fstrq_wb (sim_cpu *cpu, int32_t offset, WriteBack wb)
9570 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
9571 unsigned st = uimm (aarch64_get_instr (cpu), 4, 0);
9572 uint64_t address = aarch64_get_reg_u64 (cpu, rn, SP_OK);
9577 aarch64_get_FP_long_double (cpu, st, & a);
9578 aarch64_set_mem_long_double (cpu, address, a);
9583 if (wb != NoWriteBack)
9584 aarch64_set_reg_u64 (cpu, rn, SP_OK, address);
9587 /* 128 bit store scaled or unscaled zero-
9588 or sign-extended 32-bit register offset. */
9590 fstrq_scale_ext (sim_cpu *cpu, Scaling scaling, Extension extension)
9592 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
9593 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
9594 unsigned st = uimm (aarch64_get_instr (cpu), 4, 0);
9596 uint64_t address = aarch64_get_reg_u64 (cpu, rn, SP_OK);
9597 int64_t extended = extend (aarch64_get_reg_u32 (cpu, rm, NO_SP),
9599 uint64_t displacement = OPT_SCALE (extended, 128, scaling);
9603 aarch64_get_FP_long_double (cpu, st, & a);
9604 aarch64_set_mem_long_double (cpu, address + displacement, a);
9608 dexLoadImmediatePrePost (sim_cpu *cpu)
9610 /* instr[29,24] == 111_00
9616 instr[20,12] = simm9
9617 instr[11] = wb : 0 ==> Post, 1 ==> Pre
9618 instr[9,5] = rn may be SP. */
9619 /* unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0); */
9620 uint32_t V = uimm (aarch64_get_instr (cpu), 26, 26);
9621 uint32_t dispatch = ( (uimm (aarch64_get_instr (cpu), 31, 30) << 2)
9622 | uimm (aarch64_get_instr (cpu), 23, 22));
9623 int32_t imm = simm32 (aarch64_get_instr (cpu), 20, 12);
9624 WriteBack wb = writeback (aarch64_get_instr (cpu), 11);
9628 /* GReg operations. */
9631 case 0: strb_wb (cpu, imm, wb); return;
9632 case 1: ldrb32_wb (cpu, imm, wb); return;
9633 case 2: ldrsb_wb (cpu, imm, wb); return;
9634 case 3: ldrsb32_wb (cpu, imm, wb); return;
9635 case 4: strh_wb (cpu, imm, wb); return;
9636 case 5: ldrh32_wb (cpu, imm, wb); return;
9637 case 6: ldrsh64_wb (cpu, imm, wb); return;
9638 case 7: ldrsh32_wb (cpu, imm, wb); return;
9639 case 8: str32_wb (cpu, imm, wb); return;
9640 case 9: ldr32_wb (cpu, imm, wb); return;
9641 case 10: ldrsw_wb (cpu, imm, wb); return;
9642 case 12: str_wb (cpu, imm, wb); return;
9643 case 13: ldr_wb (cpu, imm, wb); return;
9653 /* FReg operations. */
9656 case 2: fstrq_wb (cpu, imm, wb); return;
9657 case 3: fldrq_wb (cpu, imm, wb); return;
9658 case 8: fstrs_wb (cpu, imm, wb); return;
9659 case 9: fldrs_wb (cpu, imm, wb); return;
9660 case 12: fstrd_wb (cpu, imm, wb); return;
9661 case 13: fldrd_wb (cpu, imm, wb); return;
9663 case 0: /* STUR 8 bit FP. */
9664 case 1: /* LDUR 8 bit FP. */
9665 case 4: /* STUR 16 bit FP. */
9666 case 5: /* LDUR 8 bit FP. */
9681 dexLoadRegisterOffset (sim_cpu *cpu)
9683 /* instr[31,30] = size
9690 instr[15,13] = option : 010 ==> UXTW, 011 ==> UXTX/LSL,
9691 110 ==> SXTW, 111 ==> SXTX,
9698 uint32_t V = uimm (aarch64_get_instr (cpu), 26,26);
9699 uint32_t dispatch = ( (uimm (aarch64_get_instr (cpu), 31, 30) << 2)
9700 | uimm (aarch64_get_instr (cpu), 23, 22));
9701 Scaling scale = scaling (aarch64_get_instr (cpu), 12);
9702 Extension extensionType = extension (aarch64_get_instr (cpu), 13);
9704 /* Check for illegal extension types. */
9705 if (uimm (extensionType, 1, 1) == 0)
9708 if (extensionType == UXTX || extensionType == SXTX)
9709 extensionType = NoExtension;
9713 /* GReg operations. */
9716 case 0: strb_scale_ext (cpu, scale, extensionType); return;
9717 case 1: ldrb32_scale_ext (cpu, scale, extensionType); return;
9718 case 2: ldrsb_scale_ext (cpu, scale, extensionType); return;
9719 case 3: ldrsb32_scale_ext (cpu, scale, extensionType); return;
9720 case 4: strh_scale_ext (cpu, scale, extensionType); return;
9721 case 5: ldrh32_scale_ext (cpu, scale, extensionType); return;
9722 case 6: ldrsh_scale_ext (cpu, scale, extensionType); return;
9723 case 7: ldrsh32_scale_ext (cpu, scale, extensionType); return;
9724 case 8: str32_scale_ext (cpu, scale, extensionType); return;
9725 case 9: ldr32_scale_ext (cpu, scale, extensionType); return;
9726 case 10: ldrsw_scale_ext (cpu, scale, extensionType); return;
9727 case 12: str_scale_ext (cpu, scale, extensionType); return;
9728 case 13: ldr_scale_ext (cpu, scale, extensionType); return;
9729 case 14: prfm_scale_ext (cpu, scale, extensionType); return;
9738 /* FReg operations. */
9741 case 1: /* LDUR 8 bit FP. */
9743 case 3: fldrq_scale_ext (cpu, scale, extensionType); return;
9744 case 5: /* LDUR 8 bit FP. */
9746 case 9: fldrs_scale_ext (cpu, scale, extensionType); return;
9747 case 13: fldrd_scale_ext (cpu, scale, extensionType); return;
9749 case 0: fstrb_scale_ext (cpu, scale, extensionType); return;
9750 case 2: fstrq_scale_ext (cpu, scale, extensionType); return;
9751 case 4: fstrh_scale_ext (cpu, scale, extensionType); return;
9752 case 8: fstrs_scale_ext (cpu, scale, extensionType); return;
9753 case 12: fstrd_scale_ext (cpu, scale, extensionType); return;
9767 dexLoadUnsignedImmediate (sim_cpu *cpu)
9769 /* assert instr[29,24] == 111_01
9773 instr[21,10] = uimm12 : unsigned immediate offset
9774 instr[9,5] = rn may be SP. */
9775 /* unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0); */
9776 uint32_t V = uimm (aarch64_get_instr (cpu), 26,26);
9777 uint32_t dispatch = ( (uimm (aarch64_get_instr (cpu), 31, 30) << 2)
9778 | uimm (aarch64_get_instr (cpu), 23, 22));
9779 uint32_t imm = uimm (aarch64_get_instr (cpu), 21, 10);
9783 /* GReg operations. */
9786 case 0: strb_abs (cpu, imm); return;
9787 case 1: ldrb32_abs (cpu, imm); return;
9788 case 2: ldrsb_abs (cpu, imm); return;
9789 case 3: ldrsb32_abs (cpu, imm); return;
9790 case 4: strh_abs (cpu, imm); return;
9791 case 5: ldrh32_abs (cpu, imm); return;
9792 case 6: ldrsh_abs (cpu, imm); return;
9793 case 7: ldrsh32_abs (cpu, imm); return;
9794 case 8: str32_abs (cpu, imm); return;
9795 case 9: ldr32_abs (cpu, imm); return;
9796 case 10: ldrsw_abs (cpu, imm); return;
9797 case 12: str_abs (cpu, imm); return;
9798 case 13: ldr_abs (cpu, imm); return;
9799 case 14: prfm_abs (cpu, imm); return;
9808 /* FReg operations. */
9811 case 3: fldrq_abs (cpu, imm); return;
9812 case 9: fldrs_abs (cpu, imm); return;
9813 case 13: fldrd_abs (cpu, imm); return;
9815 case 0: fstrb_abs (cpu, imm); return;
9816 case 2: fstrq_abs (cpu, imm); return;
9817 case 4: fstrh_abs (cpu, imm); return;
9818 case 8: fstrs_abs (cpu, imm); return;
9819 case 12: fstrd_abs (cpu, imm); return;
9821 case 1: /* LDR 8 bit FP. */
9822 case 5: /* LDR 8 bit FP. */
9837 dexLoadExclusive (sim_cpu *cpu)
9839 /* assert instr[29:24] = 001000;
9841 instr[23] = 0 if exclusive
9842 instr[22] = L : 1 if load, 0 if store
9843 instr[21] = 1 if pair
9845 instr[15] = o0 : 1 if ordered
9850 switch (uimm (aarch64_get_instr (cpu), 22, 21))
9852 case 2: ldxr (cpu); return;
9853 case 0: stxr (cpu); return;
9859 dexLoadOther (sim_cpu *cpu)
9863 /* instr[29,25] = 111_0
9864 instr[24] == 0 ==> dispatch, 1 ==> ldst reg unsigned immediate
9865 instr[21:11,10] is the secondary dispatch. */
9866 if (uimm (aarch64_get_instr (cpu), 24, 24))
9868 dexLoadUnsignedImmediate (cpu);
9872 dispatch = ( (uimm (aarch64_get_instr (cpu), 21, 21) << 2)
9873 | uimm (aarch64_get_instr (cpu), 11, 10));
9876 case 0: dexLoadUnscaledImmediate (cpu); return;
9877 case 1: dexLoadImmediatePrePost (cpu); return;
9878 case 3: dexLoadImmediatePrePost (cpu); return;
9879 case 6: dexLoadRegisterOffset (cpu); return;
9891 store_pair_u32 (sim_cpu *cpu, int32_t offset, WriteBack wb)
9893 unsigned rn = uimm (aarch64_get_instr (cpu), 14, 10);
9894 unsigned rd = uimm (aarch64_get_instr (cpu), 9, 5);
9895 unsigned rm = uimm (aarch64_get_instr (cpu), 4, 0);
9896 uint64_t address = aarch64_get_reg_u64 (cpu, rd, SP_OK);
9898 if ((rn == rd || rm == rd) && wb != NoWriteBack)
9899 HALT_UNALLOC; /* ??? */
9906 aarch64_set_mem_u32 (cpu, address,
9907 aarch64_get_reg_u32 (cpu, rm, NO_SP));
9908 aarch64_set_mem_u32 (cpu, address + 4,
9909 aarch64_get_reg_u32 (cpu, rn, NO_SP));
9914 if (wb != NoWriteBack)
9915 aarch64_set_reg_u64 (cpu, rd, SP_OK, address);
9919 store_pair_u64 (sim_cpu *cpu, int32_t offset, WriteBack wb)
9921 unsigned rn = uimm (aarch64_get_instr (cpu), 14, 10);
9922 unsigned rd = uimm (aarch64_get_instr (cpu), 9, 5);
9923 unsigned rm = uimm (aarch64_get_instr (cpu), 4, 0);
9924 uint64_t address = aarch64_get_reg_u64 (cpu, rd, SP_OK);
9926 if ((rn == rd || rm == rd) && wb != NoWriteBack)
9927 HALT_UNALLOC; /* ??? */
9934 aarch64_set_mem_u64 (cpu, address,
9935 aarch64_get_reg_u64 (cpu, rm, SP_OK));
9936 aarch64_set_mem_u64 (cpu, address + 8,
9937 aarch64_get_reg_u64 (cpu, rn, SP_OK));
9942 if (wb != NoWriteBack)
9943 aarch64_set_reg_u64 (cpu, rd, SP_OK, address);
9947 load_pair_u32 (sim_cpu *cpu, int32_t offset, WriteBack wb)
9949 unsigned rn = uimm (aarch64_get_instr (cpu), 14, 10);
9950 unsigned rd = uimm (aarch64_get_instr (cpu), 9, 5);
9951 unsigned rm = uimm (aarch64_get_instr (cpu), 4, 0);
9952 uint64_t address = aarch64_get_reg_u64 (cpu, rd, SP_OK);
9954 /* treat this as unalloc to make sure we don't do it. */
9963 aarch64_set_reg_u64 (cpu, rm, SP_OK, aarch64_get_mem_u32 (cpu, address));
9964 aarch64_set_reg_u64 (cpu, rn, SP_OK, aarch64_get_mem_u32 (cpu, address + 4));
9969 if (wb != NoWriteBack)
9970 aarch64_set_reg_u64 (cpu, rd, SP_OK, address);
9974 load_pair_s32 (sim_cpu *cpu, int32_t offset, WriteBack wb)
9976 unsigned rn = uimm (aarch64_get_instr (cpu), 14, 10);
9977 unsigned rd = uimm (aarch64_get_instr (cpu), 9, 5);
9978 unsigned rm = uimm (aarch64_get_instr (cpu), 4, 0);
9979 uint64_t address = aarch64_get_reg_u64 (cpu, rd, SP_OK);
9981 /* Treat this as unalloc to make sure we don't do it. */
9990 aarch64_set_reg_s64 (cpu, rm, SP_OK, aarch64_get_mem_s32 (cpu, address));
9991 aarch64_set_reg_s64 (cpu, rn, SP_OK, aarch64_get_mem_s32 (cpu, address + 4));
9996 if (wb != NoWriteBack)
9997 aarch64_set_reg_u64 (cpu, rd, SP_OK, address);
10001 load_pair_u64 (sim_cpu *cpu, int32_t offset, WriteBack wb)
10003 unsigned rn = uimm (aarch64_get_instr (cpu), 14, 10);
10004 unsigned rd = uimm (aarch64_get_instr (cpu), 9, 5);
10005 unsigned rm = uimm (aarch64_get_instr (cpu), 4, 0);
10006 uint64_t address = aarch64_get_reg_u64 (cpu, rd, SP_OK);
10008 /* Treat this as unalloc to make sure we don't do it. */
10017 aarch64_set_reg_u64 (cpu, rm, SP_OK, aarch64_get_mem_u64 (cpu, address));
10018 aarch64_set_reg_u64 (cpu, rn, SP_OK, aarch64_get_mem_u64 (cpu, address + 8));
10023 if (wb != NoWriteBack)
10024 aarch64_set_reg_u64 (cpu, rd, SP_OK, address);
10028 dex_load_store_pair_gr (sim_cpu *cpu)
10030 /* instr[31,30] = size (10=> 64-bit, 01=> signed 32-bit, 00=> 32-bit)
10031 instr[29,25] = instruction encoding: 101_0
10032 instr[26] = V : 1 if fp 0 if gp
10033 instr[24,23] = addressing mode (10=> offset, 01=> post, 11=> pre)
10034 instr[22] = load/store (1=> load)
10035 instr[21,15] = signed, scaled, offset
10038 instr[ 4, 0] = Rm. */
10040 uint32_t dispatch = ((uimm (aarch64_get_instr (cpu), 31, 30) << 3)
10041 | uimm (aarch64_get_instr (cpu), 24, 22));
10042 int32_t offset = simm32 (aarch64_get_instr (cpu), 21, 15);
10046 case 2: store_pair_u32 (cpu, offset, Post); return;
10047 case 3: load_pair_u32 (cpu, offset, Post); return;
10048 case 4: store_pair_u32 (cpu, offset, NoWriteBack); return;
10049 case 5: load_pair_u32 (cpu, offset, NoWriteBack); return;
10050 case 6: store_pair_u32 (cpu, offset, Pre); return;
10051 case 7: load_pair_u32 (cpu, offset, Pre); return;
10053 case 11: load_pair_s32 (cpu, offset, Post); return;
10054 case 13: load_pair_s32 (cpu, offset, NoWriteBack); return;
10055 case 15: load_pair_s32 (cpu, offset, Pre); return;
10057 case 18: store_pair_u64 (cpu, offset, Post); return;
10058 case 19: load_pair_u64 (cpu, offset, Post); return;
10059 case 20: store_pair_u64 (cpu, offset, NoWriteBack); return;
10060 case 21: load_pair_u64 (cpu, offset, NoWriteBack); return;
10061 case 22: store_pair_u64 (cpu, offset, Pre); return;
10062 case 23: load_pair_u64 (cpu, offset, Pre); return;
10070 store_pair_float (sim_cpu *cpu, int32_t offset, WriteBack wb)
10072 unsigned rn = uimm (aarch64_get_instr (cpu), 14, 10);
10073 unsigned rd = uimm (aarch64_get_instr (cpu), 9, 5);
10074 unsigned rm = uimm (aarch64_get_instr (cpu), 4, 0);
10075 uint64_t address = aarch64_get_reg_u64 (cpu, rd, SP_OK);
10082 aarch64_set_mem_float (cpu, address, aarch64_get_FP_float (cpu, rm));
10083 aarch64_set_mem_float (cpu, address + 4, aarch64_get_FP_float (cpu, rn));
10088 if (wb != NoWriteBack)
10089 aarch64_set_reg_u64 (cpu, rd, SP_OK, address);
10093 store_pair_double (sim_cpu *cpu, int32_t offset, WriteBack wb)
10095 unsigned rn = uimm (aarch64_get_instr (cpu), 14, 10);
10096 unsigned rd = uimm (aarch64_get_instr (cpu), 9, 5);
10097 unsigned rm = uimm (aarch64_get_instr (cpu), 4, 0);
10098 uint64_t address = aarch64_get_reg_u64 (cpu, rd, SP_OK);
10105 aarch64_set_mem_double (cpu, address, aarch64_get_FP_double (cpu, rm));
10106 aarch64_set_mem_double (cpu, address + 8, aarch64_get_FP_double (cpu, rn));
10111 if (wb != NoWriteBack)
10112 aarch64_set_reg_u64 (cpu, rd, SP_OK, address);
10116 store_pair_long_double (sim_cpu *cpu, int32_t offset, WriteBack wb)
10119 unsigned rn = uimm (aarch64_get_instr (cpu), 14, 10);
10120 unsigned rd = uimm (aarch64_get_instr (cpu), 9, 5);
10121 unsigned rm = uimm (aarch64_get_instr (cpu), 4, 0);
10122 uint64_t address = aarch64_get_reg_u64 (cpu, rd, SP_OK);
10129 aarch64_get_FP_long_double (cpu, rm, & a);
10130 aarch64_set_mem_long_double (cpu, address, a);
10131 aarch64_get_FP_long_double (cpu, rn, & a);
10132 aarch64_set_mem_long_double (cpu, address + 16, a);
10137 if (wb != NoWriteBack)
10138 aarch64_set_reg_u64 (cpu, rd, SP_OK, address);
10142 load_pair_float (sim_cpu *cpu, int32_t offset, WriteBack wb)
10144 unsigned rn = uimm (aarch64_get_instr (cpu), 14, 10);
10145 unsigned rd = uimm (aarch64_get_instr (cpu), 9, 5);
10146 unsigned rm = uimm (aarch64_get_instr (cpu), 4, 0);
10147 uint64_t address = aarch64_get_reg_u64 (cpu, rd, SP_OK);
10157 aarch64_set_FP_float (cpu, rm, aarch64_get_mem_float (cpu, address));
10158 aarch64_set_FP_float (cpu, rn, aarch64_get_mem_float (cpu, address + 4));
10163 if (wb != NoWriteBack)
10164 aarch64_set_reg_u64 (cpu, rd, SP_OK, address);
10168 load_pair_double (sim_cpu *cpu, int32_t offset, WriteBack wb)
10170 unsigned rn = uimm (aarch64_get_instr (cpu), 14, 10);
10171 unsigned rd = uimm (aarch64_get_instr (cpu), 9, 5);
10172 unsigned rm = uimm (aarch64_get_instr (cpu), 4, 0);
10173 uint64_t address = aarch64_get_reg_u64 (cpu, rd, SP_OK);
10183 aarch64_set_FP_double (cpu, rm, aarch64_get_mem_double (cpu, address));
10184 aarch64_set_FP_double (cpu, rn, aarch64_get_mem_double (cpu, address + 8));
10189 if (wb != NoWriteBack)
10190 aarch64_set_reg_u64 (cpu, rd, SP_OK, address);
10194 load_pair_long_double (sim_cpu *cpu, int32_t offset, WriteBack wb)
10197 unsigned rn = uimm (aarch64_get_instr (cpu), 14, 10);
10198 unsigned rd = uimm (aarch64_get_instr (cpu), 9, 5);
10199 unsigned rm = uimm (aarch64_get_instr (cpu), 4, 0);
10200 uint64_t address = aarch64_get_reg_u64 (cpu, rd, SP_OK);
10210 aarch64_get_mem_long_double (cpu, address, & a);
10211 aarch64_set_FP_long_double (cpu, rm, a);
10212 aarch64_get_mem_long_double (cpu, address + 16, & a);
10213 aarch64_set_FP_long_double (cpu, rn, a);
10218 if (wb != NoWriteBack)
10219 aarch64_set_reg_u64 (cpu, rd, SP_OK, address);
10223 dex_load_store_pair_fp (sim_cpu *cpu)
10225 /* instr[31,30] = size (10=> 128-bit, 01=> 64-bit, 00=> 32-bit)
10226 instr[29,25] = instruction encoding
10227 instr[24,23] = addressing mode (10=> offset, 01=> post, 11=> pre)
10228 instr[22] = load/store (1=> load)
10229 instr[21,15] = signed, scaled, offset
10232 instr[ 4, 0] = Rm */
10234 uint32_t dispatch = ((uimm (aarch64_get_instr (cpu), 31, 30) << 3)
10235 | uimm (aarch64_get_instr (cpu), 24, 22));
10236 int32_t offset = simm32 (aarch64_get_instr (cpu), 21, 15);
10240 case 2: store_pair_float (cpu, offset, Post); return;
10241 case 3: load_pair_float (cpu, offset, Post); return;
10242 case 4: store_pair_float (cpu, offset, NoWriteBack); return;
10243 case 5: load_pair_float (cpu, offset, NoWriteBack); return;
10244 case 6: store_pair_float (cpu, offset, Pre); return;
10245 case 7: load_pair_float (cpu, offset, Pre); return;
10247 case 10: store_pair_double (cpu, offset, Post); return;
10248 case 11: load_pair_double (cpu, offset, Post); return;
10249 case 12: store_pair_double (cpu, offset, NoWriteBack); return;
10250 case 13: load_pair_double (cpu, offset, NoWriteBack); return;
10251 case 14: store_pair_double (cpu, offset, Pre); return;
10252 case 15: load_pair_double (cpu, offset, Pre); return;
10254 case 18: store_pair_long_double (cpu, offset, Post); return;
10255 case 19: load_pair_long_double (cpu, offset, Post); return;
10256 case 20: store_pair_long_double (cpu, offset, NoWriteBack); return;
10257 case 21: load_pair_long_double (cpu, offset, NoWriteBack); return;
10258 case 22: store_pair_long_double (cpu, offset, Pre); return;
10259 case 23: load_pair_long_double (cpu, offset, Pre); return;
10266 static inline unsigned
10267 vec_reg (unsigned v, unsigned o)
10269 return (v + o) & 0x3F;
10272 /* Load multiple N-element structures to N consecutive registers. */
10274 vec_load (sim_cpu *cpu, uint64_t address, unsigned N)
10276 int all = uimm (aarch64_get_instr (cpu), 30, 30);
10277 unsigned size = uimm (aarch64_get_instr (cpu), 11, 10);
10278 unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
10283 case 0: /* 8-bit operations. */
10285 for (i = 0; i < (16 * N); i++)
10286 aarch64_set_vec_u8 (cpu, vec_reg (vd, i >> 4), i & 15,
10287 aarch64_get_mem_u8 (cpu, address + i));
10289 for (i = 0; i < (8 * N); i++)
10290 aarch64_set_vec_u8 (cpu, vec_reg (vd, i >> 3), i & 7,
10291 aarch64_get_mem_u8 (cpu, address + i));
10294 case 1: /* 16-bit operations. */
10296 for (i = 0; i < (8 * N); i++)
10297 aarch64_set_vec_u16 (cpu, vec_reg (vd, i >> 3), i & 7,
10298 aarch64_get_mem_u16 (cpu, address + i * 2));
10300 for (i = 0; i < (4 * N); i++)
10301 aarch64_set_vec_u16 (cpu, vec_reg (vd, i >> 2), i & 3,
10302 aarch64_get_mem_u16 (cpu, address + i * 2));
10305 case 2: /* 32-bit operations. */
10307 for (i = 0; i < (4 * N); i++)
10308 aarch64_set_vec_u32 (cpu, vec_reg (vd, i >> 2), i & 3,
10309 aarch64_get_mem_u32 (cpu, address + i * 4));
10311 for (i = 0; i < (2 * N); i++)
10312 aarch64_set_vec_u32 (cpu, vec_reg (vd, i >> 1), i & 1,
10313 aarch64_get_mem_u32 (cpu, address + i * 4));
10316 case 3: /* 64-bit operations. */
10318 for (i = 0; i < (2 * N); i++)
10319 aarch64_set_vec_u64 (cpu, vec_reg (vd, i >> 1), i & 1,
10320 aarch64_get_mem_u64 (cpu, address + i * 8));
10322 for (i = 0; i < N; i++)
10323 aarch64_set_vec_u64 (cpu, vec_reg (vd, i), 0,
10324 aarch64_get_mem_u64 (cpu, address + i * 8));
10332 /* LD4: load multiple 4-element to four consecutive registers. */
10334 LD4 (sim_cpu *cpu, uint64_t address)
10336 vec_load (cpu, address, 4);
10339 /* LD3: load multiple 3-element structures to three consecutive registers. */
10341 LD3 (sim_cpu *cpu, uint64_t address)
10343 vec_load (cpu, address, 3);
10346 /* LD2: load multiple 2-element structures to two consecutive registers. */
10348 LD2 (sim_cpu *cpu, uint64_t address)
10350 vec_load (cpu, address, 2);
10353 /* Load multiple 1-element structures into one register. */
10355 LD1_1 (sim_cpu *cpu, uint64_t address)
10357 int all = uimm (aarch64_get_instr (cpu), 30, 30);
10358 unsigned size = uimm (aarch64_get_instr (cpu), 11, 10);
10359 unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
10365 /* LD1 {Vd.16b}, addr, #16 */
10366 /* LD1 {Vd.8b}, addr, #8 */
10367 for (i = 0; i < (all ? 16 : 8); i++)
10368 aarch64_set_vec_u8 (cpu, vd, i,
10369 aarch64_get_mem_u8 (cpu, address + i));
10373 /* LD1 {Vd.8h}, addr, #16 */
10374 /* LD1 {Vd.4h}, addr, #8 */
10375 for (i = 0; i < (all ? 8 : 4); i++)
10376 aarch64_set_vec_u16 (cpu, vd, i,
10377 aarch64_get_mem_u16 (cpu, address + i * 2));
10381 /* LD1 {Vd.4s}, addr, #16 */
10382 /* LD1 {Vd.2s}, addr, #8 */
10383 for (i = 0; i < (all ? 4 : 2); i++)
10384 aarch64_set_vec_u32 (cpu, vd, i,
10385 aarch64_get_mem_u32 (cpu, address + i * 4));
10389 /* LD1 {Vd.2d}, addr, #16 */
10390 /* LD1 {Vd.1d}, addr, #8 */
10391 for (i = 0; i < (all ? 2 : 1); i++)
10392 aarch64_set_vec_u64 (cpu, vd, i,
10393 aarch64_get_mem_u64 (cpu, address + i * 8));
10401 /* Load multiple 1-element structures into two registers. */
10403 LD1_2 (sim_cpu *cpu, uint64_t address)
10405 /* FIXME: This algorithm is *exactly* the same as the LD2 version.
10406 So why have two different instructions ? There must be something
10407 wrong somewhere. */
10408 vec_load (cpu, address, 2);
10411 /* Load multiple 1-element structures into three registers. */
10413 LD1_3 (sim_cpu *cpu, uint64_t address)
10415 /* FIXME: This algorithm is *exactly* the same as the LD3 version.
10416 So why have two different instructions ? There must be something
10417 wrong somewhere. */
10418 vec_load (cpu, address, 3);
10421 /* Load multiple 1-element structures into four registers. */
10423 LD1_4 (sim_cpu *cpu, uint64_t address)
10425 /* FIXME: This algorithm is *exactly* the same as the LD4 version.
10426 So why have two different instructions ? There must be something
10427 wrong somewhere. */
10428 vec_load (cpu, address, 4);
10431 /* Store multiple N-element structures to N consecutive registers. */
10433 vec_store (sim_cpu *cpu, uint64_t address, unsigned N)
10435 int all = uimm (aarch64_get_instr (cpu), 30, 30);
10436 unsigned size = uimm (aarch64_get_instr (cpu), 11, 10);
10437 unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
10442 case 0: /* 8-bit operations. */
10444 for (i = 0; i < (16 * N); i++)
10447 aarch64_get_vec_u8 (cpu, vec_reg (vd, i >> 4), i & 15));
10449 for (i = 0; i < (8 * N); i++)
10452 aarch64_get_vec_u8 (cpu, vec_reg (vd, i >> 3), i & 7));
10455 case 1: /* 16-bit operations. */
10457 for (i = 0; i < (8 * N); i++)
10458 aarch64_set_mem_u16
10459 (cpu, address + i * 2,
10460 aarch64_get_vec_u16 (cpu, vec_reg (vd, i >> 3), i & 7));
10462 for (i = 0; i < (4 * N); i++)
10463 aarch64_set_mem_u16
10464 (cpu, address + i * 2,
10465 aarch64_get_vec_u16 (cpu, vec_reg (vd, i >> 2), i & 3));
10468 case 2: /* 32-bit operations. */
10470 for (i = 0; i < (4 * N); i++)
10471 aarch64_set_mem_u32
10472 (cpu, address + i * 4,
10473 aarch64_get_vec_u32 (cpu, vec_reg (vd, i >> 2), i & 3));
10475 for (i = 0; i < (2 * N); i++)
10476 aarch64_set_mem_u32
10477 (cpu, address + i * 4,
10478 aarch64_get_vec_u32 (cpu, vec_reg (vd, i >> 1), i & 1));
10481 case 3: /* 64-bit operations. */
10483 for (i = 0; i < (2 * N); i++)
10484 aarch64_set_mem_u64
10485 (cpu, address + i * 8,
10486 aarch64_get_vec_u64 (cpu, vec_reg (vd, i >> 1), i & 1));
10488 for (i = 0; i < N; i++)
10489 aarch64_set_mem_u64
10490 (cpu, address + i * 8,
10491 aarch64_get_vec_u64 (cpu, vec_reg (vd, i), 0));
10499 /* Store multiple 4-element structure to four consecutive registers. */
10501 ST4 (sim_cpu *cpu, uint64_t address)
10503 vec_store (cpu, address, 4);
10506 /* Store multiple 3-element structures to three consecutive registers. */
10508 ST3 (sim_cpu *cpu, uint64_t address)
10510 vec_store (cpu, address, 3);
10513 /* Store multiple 2-element structures to two consecutive registers. */
10515 ST2 (sim_cpu *cpu, uint64_t address)
10517 vec_store (cpu, address, 2);
10520 /* Store multiple 1-element structures into one register. */
10522 ST1_1 (sim_cpu *cpu, uint64_t address)
10524 int all = uimm (aarch64_get_instr (cpu), 30, 30);
10525 unsigned size = uimm (aarch64_get_instr (cpu), 11, 10);
10526 unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
10532 for (i = 0; i < (all ? 16 : 8); i++)
10533 aarch64_set_mem_u8 (cpu, address + i,
10534 aarch64_get_vec_u8 (cpu, vd, i));
10538 for (i = 0; i < (all ? 8 : 4); i++)
10539 aarch64_set_mem_u16 (cpu, address + i * 2,
10540 aarch64_get_vec_u16 (cpu, vd, i));
10544 for (i = 0; i < (all ? 4 : 2); i++)
10545 aarch64_set_mem_u32 (cpu, address + i * 4,
10546 aarch64_get_vec_u32 (cpu, vd, i));
10550 for (i = 0; i < (all ? 2 : 1); i++)
10551 aarch64_set_mem_u64 (cpu, address + i * 8,
10552 aarch64_get_vec_u64 (cpu, vd, i));
10560 /* Store multiple 1-element structures into two registers. */
10562 ST1_2 (sim_cpu *cpu, uint64_t address)
10564 /* FIXME: This algorithm is *exactly* the same as the ST2 version.
10565 So why have two different instructions ? There must be
10566 something wrong somewhere. */
10567 vec_store (cpu, address, 2);
10570 /* Store multiple 1-element structures into three registers. */
10572 ST1_3 (sim_cpu *cpu, uint64_t address)
10574 /* FIXME: This algorithm is *exactly* the same as the ST3 version.
10575 So why have two different instructions ? There must be
10576 something wrong somewhere. */
10577 vec_store (cpu, address, 3);
10580 /* Store multiple 1-element structures into four registers. */
10582 ST1_4 (sim_cpu *cpu, uint64_t address)
10584 /* FIXME: This algorithm is *exactly* the same as the ST4 version.
10585 So why have two different instructions ? There must be
10586 something wrong somewhere. */
10587 vec_store (cpu, address, 4);
10591 do_vec_LDnR (sim_cpu *cpu, uint64_t address)
10594 instr[30] = element selector 0=>half, 1=>all elements
10595 instr[29,24] = 00 1101
10596 instr[23] = 0=>simple, 1=>post
10598 instr[21] = width: LD1R-or-LD3R (0) / LD2R-or-LD4R (1)
10599 instr[20,16] = 0 0000 (simple), Vinc (reg-post-inc, no SP),
10600 11111 (immediate post inc)
10602 instr[13] = width: LD1R-or-LD2R (0) / LD3R-or-LD4R (1)
10604 instr[11,10] = element size 00=> byte(b), 01=> half(h),
10605 10=> word(s), 11=> double(d)
10606 instr[9,5] = address
10609 unsigned full = uimm (aarch64_get_instr (cpu), 30, 30);
10610 unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
10611 unsigned size = uimm (aarch64_get_instr (cpu), 11, 10);
10614 NYI_assert (29, 24, 0x0D);
10615 NYI_assert (22, 22, 1);
10616 NYI_assert (15, 14, 3);
10617 NYI_assert (12, 12, 0);
10619 switch ((uimm (aarch64_get_instr (cpu), 13, 13) << 1)
10620 | uimm (aarch64_get_instr (cpu), 21, 21))
10622 case 0: /* LD1R. */
10627 uint8_t val = aarch64_get_mem_u8 (cpu, address);
10628 for (i = 0; i < (full ? 16 : 8); i++)
10629 aarch64_set_vec_u8 (cpu, vd, i, val);
10635 uint16_t val = aarch64_get_mem_u16 (cpu, address);
10636 for (i = 0; i < (full ? 8 : 4); i++)
10637 aarch64_set_vec_u16 (cpu, vd, i, val);
10643 uint32_t val = aarch64_get_mem_u32 (cpu, address);
10644 for (i = 0; i < (full ? 4 : 2); i++)
10645 aarch64_set_vec_u32 (cpu, vd, i, val);
10651 uint64_t val = aarch64_get_mem_u64 (cpu, address);
10652 for (i = 0; i < (full ? 2 : 1); i++)
10653 aarch64_set_vec_u64 (cpu, vd, i, val);
10662 case 1: /* LD2R. */
10667 uint8_t val1 = aarch64_get_mem_u8 (cpu, address);
10668 uint8_t val2 = aarch64_get_mem_u8 (cpu, address + 1);
10670 for (i = 0; i < (full ? 16 : 8); i++)
10672 aarch64_set_vec_u8 (cpu, vd, 0, val1);
10673 aarch64_set_vec_u8 (cpu, vd + 1, 0, val2);
10680 uint16_t val1 = aarch64_get_mem_u16 (cpu, address);
10681 uint16_t val2 = aarch64_get_mem_u16 (cpu, address + 2);
10683 for (i = 0; i < (full ? 8 : 4); i++)
10685 aarch64_set_vec_u16 (cpu, vd, 0, val1);
10686 aarch64_set_vec_u16 (cpu, vd + 1, 0, val2);
10693 uint32_t val1 = aarch64_get_mem_u32 (cpu, address);
10694 uint32_t val2 = aarch64_get_mem_u32 (cpu, address + 4);
10696 for (i = 0; i < (full ? 4 : 2); i++)
10698 aarch64_set_vec_u32 (cpu, vd, 0, val1);
10699 aarch64_set_vec_u32 (cpu, vd + 1, 0, val2);
10706 uint64_t val1 = aarch64_get_mem_u64 (cpu, address);
10707 uint64_t val2 = aarch64_get_mem_u64 (cpu, address + 8);
10709 for (i = 0; i < (full ? 2 : 1); i++)
10711 aarch64_set_vec_u64 (cpu, vd, 0, val1);
10712 aarch64_set_vec_u64 (cpu, vd + 1, 0, val2);
10722 case 2: /* LD3R. */
10727 uint8_t val1 = aarch64_get_mem_u8 (cpu, address);
10728 uint8_t val2 = aarch64_get_mem_u8 (cpu, address + 1);
10729 uint8_t val3 = aarch64_get_mem_u8 (cpu, address + 2);
10731 for (i = 0; i < (full ? 16 : 8); i++)
10733 aarch64_set_vec_u8 (cpu, vd, 0, val1);
10734 aarch64_set_vec_u8 (cpu, vd + 1, 0, val2);
10735 aarch64_set_vec_u8 (cpu, vd + 2, 0, val3);
10742 uint32_t val1 = aarch64_get_mem_u16 (cpu, address);
10743 uint32_t val2 = aarch64_get_mem_u16 (cpu, address + 2);
10744 uint32_t val3 = aarch64_get_mem_u16 (cpu, address + 4);
10746 for (i = 0; i < (full ? 8 : 4); i++)
10748 aarch64_set_vec_u16 (cpu, vd, 0, val1);
10749 aarch64_set_vec_u16 (cpu, vd + 1, 0, val2);
10750 aarch64_set_vec_u16 (cpu, vd + 2, 0, val3);
10757 uint32_t val1 = aarch64_get_mem_u32 (cpu, address);
10758 uint32_t val2 = aarch64_get_mem_u32 (cpu, address + 4);
10759 uint32_t val3 = aarch64_get_mem_u32 (cpu, address + 8);
10761 for (i = 0; i < (full ? 4 : 2); i++)
10763 aarch64_set_vec_u32 (cpu, vd, 0, val1);
10764 aarch64_set_vec_u32 (cpu, vd + 1, 0, val2);
10765 aarch64_set_vec_u32 (cpu, vd + 2, 0, val3);
10772 uint64_t val1 = aarch64_get_mem_u64 (cpu, address);
10773 uint64_t val2 = aarch64_get_mem_u64 (cpu, address + 8);
10774 uint64_t val3 = aarch64_get_mem_u64 (cpu, address + 16);
10776 for (i = 0; i < (full ? 2 : 1); i++)
10778 aarch64_set_vec_u64 (cpu, vd, 0, val1);
10779 aarch64_set_vec_u64 (cpu, vd + 1, 0, val2);
10780 aarch64_set_vec_u64 (cpu, vd + 2, 0, val3);
10790 case 3: /* LD4R. */
10795 uint8_t val1 = aarch64_get_mem_u8 (cpu, address);
10796 uint8_t val2 = aarch64_get_mem_u8 (cpu, address + 1);
10797 uint8_t val3 = aarch64_get_mem_u8 (cpu, address + 2);
10798 uint8_t val4 = aarch64_get_mem_u8 (cpu, address + 3);
10800 for (i = 0; i < (full ? 16 : 8); i++)
10802 aarch64_set_vec_u8 (cpu, vd, 0, val1);
10803 aarch64_set_vec_u8 (cpu, vd + 1, 0, val2);
10804 aarch64_set_vec_u8 (cpu, vd + 2, 0, val3);
10805 aarch64_set_vec_u8 (cpu, vd + 3, 0, val4);
10812 uint32_t val1 = aarch64_get_mem_u16 (cpu, address);
10813 uint32_t val2 = aarch64_get_mem_u16 (cpu, address + 2);
10814 uint32_t val3 = aarch64_get_mem_u16 (cpu, address + 4);
10815 uint32_t val4 = aarch64_get_mem_u16 (cpu, address + 6);
10817 for (i = 0; i < (full ? 8 : 4); i++)
10819 aarch64_set_vec_u16 (cpu, vd, 0, val1);
10820 aarch64_set_vec_u16 (cpu, vd + 1, 0, val2);
10821 aarch64_set_vec_u16 (cpu, vd + 2, 0, val3);
10822 aarch64_set_vec_u16 (cpu, vd + 3, 0, val4);
10829 uint32_t val1 = aarch64_get_mem_u32 (cpu, address);
10830 uint32_t val2 = aarch64_get_mem_u32 (cpu, address + 4);
10831 uint32_t val3 = aarch64_get_mem_u32 (cpu, address + 8);
10832 uint32_t val4 = aarch64_get_mem_u32 (cpu, address + 12);
10834 for (i = 0; i < (full ? 4 : 2); i++)
10836 aarch64_set_vec_u32 (cpu, vd, 0, val1);
10837 aarch64_set_vec_u32 (cpu, vd + 1, 0, val2);
10838 aarch64_set_vec_u32 (cpu, vd + 2, 0, val3);
10839 aarch64_set_vec_u32 (cpu, vd + 3, 0, val4);
10846 uint64_t val1 = aarch64_get_mem_u64 (cpu, address);
10847 uint64_t val2 = aarch64_get_mem_u64 (cpu, address + 8);
10848 uint64_t val3 = aarch64_get_mem_u64 (cpu, address + 16);
10849 uint64_t val4 = aarch64_get_mem_u64 (cpu, address + 24);
10851 for (i = 0; i < (full ? 2 : 1); i++)
10853 aarch64_set_vec_u64 (cpu, vd, 0, val1);
10854 aarch64_set_vec_u64 (cpu, vd + 1, 0, val2);
10855 aarch64_set_vec_u64 (cpu, vd + 2, 0, val3);
10856 aarch64_set_vec_u64 (cpu, vd + 3, 0, val4);
10872 do_vec_load_store (sim_cpu *cpu)
10874 /* {LD|ST}<N> {Vd..Vd+N}, vaddr
10877 instr[30] = element selector 0=>half, 1=>all elements
10878 instr[29,25] = 00110
10880 instr[23] = 0=>simple, 1=>post
10881 instr[22] = 0=>store, 1=>load
10882 instr[21] = 0 (LDn) / small(0)-large(1) selector (LDnR)
10883 instr[20,16] = 00000 (simple), Vinc (reg-post-inc, no SP),
10884 11111 (immediate post inc)
10885 instr[15,12] = elements and destinations. eg for load:
10886 0000=>LD4 => load multiple 4-element to
10887 four consecutive registers
10888 0100=>LD3 => load multiple 3-element to
10889 three consecutive registers
10890 1000=>LD2 => load multiple 2-element to
10891 two consecutive registers
10892 0010=>LD1 => load multiple 1-element to
10893 four consecutive registers
10894 0110=>LD1 => load multiple 1-element to
10895 three consecutive registers
10896 1010=>LD1 => load multiple 1-element to
10897 two consecutive registers
10898 0111=>LD1 => load multiple 1-element to
10902 instr[11,10] = element size 00=> byte(b), 01=> half(h),
10903 10=> word(s), 11=> double(d)
10904 instr[9,5] = Vn, can be SP
10913 if (uimm (aarch64_get_instr (cpu), 31, 31) != 0
10914 || uimm (aarch64_get_instr (cpu), 29, 25) != 0x06)
10917 type = uimm (aarch64_get_instr (cpu), 15, 12);
10918 if (type != 0xE && type != 0xE && uimm (aarch64_get_instr (cpu), 21, 21) != 0)
10921 post = uimm (aarch64_get_instr (cpu), 23, 23);
10922 load = uimm (aarch64_get_instr (cpu), 22, 22);
10923 vn = uimm (aarch64_get_instr (cpu), 9, 5);
10924 address = aarch64_get_reg_u64 (cpu, vn, SP_OK);
10928 unsigned vm = uimm (aarch64_get_instr (cpu), 20, 16);
10932 unsigned sizeof_operation;
10936 case 0: sizeof_operation = 32; break;
10937 case 4: sizeof_operation = 24; break;
10938 case 8: sizeof_operation = 16; break;
10941 sizeof_operation = uimm (aarch64_get_instr (cpu), 21, 21) ? 2 : 1;
10942 sizeof_operation <<= uimm (aarch64_get_instr (cpu), 11, 10);
10946 sizeof_operation = uimm (aarch64_get_instr (cpu), 21, 21) ? 8 : 4;
10947 sizeof_operation <<= uimm (aarch64_get_instr (cpu), 11, 10);
10954 sizeof_operation = 2 << uimm (aarch64_get_instr (cpu), 11, 10);
10961 if (uimm (aarch64_get_instr (cpu), 30, 30))
10962 sizeof_operation *= 2;
10964 aarch64_set_reg_u64 (cpu, vn, SP_OK, address + sizeof_operation);
10967 aarch64_set_reg_u64 (cpu, vn, SP_OK,
10968 address + aarch64_get_reg_u64 (cpu, vm, NO_SP));
10972 NYI_assert (20, 16, 0);
10979 case 0: LD4 (cpu, address); return;
10980 case 4: LD3 (cpu, address); return;
10981 case 8: LD2 (cpu, address); return;
10982 case 2: LD1_4 (cpu, address); return;
10983 case 6: LD1_3 (cpu, address); return;
10984 case 10: LD1_2 (cpu, address); return;
10985 case 7: LD1_1 (cpu, address); return;
10988 case 0xC: do_vec_LDnR (cpu, address); return;
10998 case 0: ST4 (cpu, address); return;
10999 case 4: ST3 (cpu, address); return;
11000 case 8: ST2 (cpu, address); return;
11001 case 2: ST1_4 (cpu, address); return;
11002 case 6: ST1_3 (cpu, address); return;
11003 case 10: ST1_2 (cpu, address); return;
11004 case 7: ST1_1 (cpu, address); return;
11011 dexLdSt (sim_cpu *cpu)
11013 /* uint32_t group = dispatchGroup (aarch64_get_instr (cpu));
11014 assert group == GROUP_LDST_0100 || group == GROUP_LDST_0110 ||
11015 group == GROUP_LDST_1100 || group == GROUP_LDST_1110
11016 bits [29,28:26] of a LS are the secondary dispatch vector. */
11017 uint32_t group2 = dispatchLS (aarch64_get_instr (cpu));
11022 dexLoadExclusive (cpu); return;
11026 dexLoadLiteral (cpu); return;
11030 dexLoadOther (cpu); return;
11032 case LS_ADVSIMD_001:
11033 do_vec_load_store (cpu); return;
11036 dex_load_store_pair_gr (cpu); return;
11039 dex_load_store_pair_fp (cpu); return;
11042 /* Should never reach here. */
11047 /* Specific decode and execute for group Data Processing Register. */
11050 dexLogicalShiftedRegister (sim_cpu *cpu)
11052 /* assert instr[28:24] = 01010
11053 instr[31] = size : 0 ==> 32 bit, 1 ==> 64 bit
11054 instr[30,29:21] = op,N : 000 ==> AND, 001 ==> BIC,
11055 010 ==> ORR, 011 ==> ORN
11056 100 ==> EOR, 101 ==> EON,
11057 110 ==> ANDS, 111 ==> BICS
11058 instr[23,22] = shift : 0 ==> LSL, 1 ==> LSR, 2 ==> ASR, 3 ==> ROR
11059 instr[15,10] = count : must be 0xxxxx for 32 bit
11063 /* unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16); */
11066 uint32_t size = uimm (aarch64_get_instr (cpu), 31, 31);
11068 /* 32 bit operations must have count[5] = 0. */
11069 /* or else we have an UNALLOC. */
11070 uint32_t count = uimm (aarch64_get_instr (cpu), 15, 10);
11072 if (!size && uimm (count, 5, 5))
11075 shiftType = shift (aarch64_get_instr (cpu), 22);
11077 /* dispatch on size:op:N i.e aarch64_get_instr (cpu)[31,29:21]. */
11078 dispatch = ( (uimm (aarch64_get_instr (cpu), 31, 29) << 1)
11079 | uimm (aarch64_get_instr (cpu), 21, 21));
11083 case 0: and32_shift (cpu, shiftType, count); return;
11084 case 1: bic32_shift (cpu, shiftType, count); return;
11085 case 2: orr32_shift (cpu, shiftType, count); return;
11086 case 3: orn32_shift (cpu, shiftType, count); return;
11087 case 4: eor32_shift (cpu, shiftType, count); return;
11088 case 5: eon32_shift (cpu, shiftType, count); return;
11089 case 6: ands32_shift (cpu, shiftType, count); return;
11090 case 7: bics32_shift (cpu, shiftType, count); return;
11091 case 8: and64_shift (cpu, shiftType, count); return;
11092 case 9: bic64_shift (cpu, shiftType, count); return;
11093 case 10:orr64_shift (cpu, shiftType, count); return;
11094 case 11:orn64_shift (cpu, shiftType, count); return;
11095 case 12:eor64_shift (cpu, shiftType, count); return;
11096 case 13:eon64_shift (cpu, shiftType, count); return;
11097 case 14:ands64_shift (cpu, shiftType, count); return;
11098 case 15:bics64_shift (cpu, shiftType, count); return;
11099 default: HALT_UNALLOC;
11103 /* 32 bit conditional select. */
11105 csel32 (sim_cpu *cpu, CondCode cc)
11107 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
11108 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
11109 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
11111 aarch64_set_reg_u64 (cpu, rd, NO_SP,
11112 testConditionCode (cpu, cc)
11113 ? aarch64_get_reg_u32 (cpu, rn, NO_SP)
11114 : aarch64_get_reg_u32 (cpu, rm, NO_SP));
11117 /* 64 bit conditional select. */
11119 csel64 (sim_cpu *cpu, CondCode cc)
11121 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
11122 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
11123 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
11125 aarch64_set_reg_u64 (cpu, rd, NO_SP,
11126 testConditionCode (cpu, cc)
11127 ? aarch64_get_reg_u64 (cpu, rn, NO_SP)
11128 : aarch64_get_reg_u64 (cpu, rm, NO_SP));
11131 /* 32 bit conditional increment. */
11133 csinc32 (sim_cpu *cpu, CondCode cc)
11135 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
11136 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
11137 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
11139 aarch64_set_reg_u64 (cpu, rd, NO_SP,
11140 testConditionCode (cpu, cc)
11141 ? aarch64_get_reg_u32 (cpu, rn, NO_SP)
11142 : aarch64_get_reg_u32 (cpu, rm, NO_SP) + 1);
11145 /* 64 bit conditional increment. */
11147 csinc64 (sim_cpu *cpu, CondCode cc)
11149 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
11150 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
11151 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
11153 aarch64_set_reg_u64 (cpu, rd, NO_SP,
11154 testConditionCode (cpu, cc)
11155 ? aarch64_get_reg_u64 (cpu, rn, NO_SP)
11156 : aarch64_get_reg_u64 (cpu, rm, NO_SP) + 1);
11159 /* 32 bit conditional invert. */
11161 csinv32 (sim_cpu *cpu, CondCode cc)
11163 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
11164 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
11165 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
11167 aarch64_set_reg_u64 (cpu, rd, NO_SP,
11168 testConditionCode (cpu, cc)
11169 ? aarch64_get_reg_u32 (cpu, rn, NO_SP)
11170 : ~ aarch64_get_reg_u32 (cpu, rm, NO_SP));
11173 /* 64 bit conditional invert. */
11175 csinv64 (sim_cpu *cpu, CondCode cc)
11177 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
11178 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
11179 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
11181 aarch64_set_reg_u64 (cpu, rd, NO_SP,
11182 testConditionCode (cpu, cc)
11183 ? aarch64_get_reg_u64 (cpu, rn, NO_SP)
11184 : ~ aarch64_get_reg_u64 (cpu, rm, NO_SP));
11187 /* 32 bit conditional negate. */
11189 csneg32 (sim_cpu *cpu, CondCode cc)
11191 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
11192 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
11193 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
11195 aarch64_set_reg_u64 (cpu, rd, NO_SP,
11196 testConditionCode (cpu, cc)
11197 ? aarch64_get_reg_u32 (cpu, rn, NO_SP)
11198 : - aarch64_get_reg_u32 (cpu, rm, NO_SP));
11201 /* 64 bit conditional negate. */
11203 csneg64 (sim_cpu *cpu, CondCode cc)
11205 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
11206 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
11207 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
11209 aarch64_set_reg_u64 (cpu, rd, NO_SP,
11210 testConditionCode (cpu, cc)
11211 ? aarch64_get_reg_u64 (cpu, rn, NO_SP)
11212 : - aarch64_get_reg_u64 (cpu, rm, NO_SP));
11216 dexCondSelect (sim_cpu *cpu)
11218 /* assert instr[28,21] = 11011011
11219 instr[31] = size : 0 ==> 32 bit, 1 ==> 64 bit
11220 instr[30:11,10] = op : 000 ==> CSEL, 001 ==> CSINC,
11221 100 ==> CSINV, 101 ==> CSNEG,
11223 instr[29] = S : 0 ==> ok, 1 ==> UNALLOC
11224 instr[15,12] = cond
11225 instr[29] = S : 0 ==> ok, 1 ==> UNALLOC */
11229 uint32_t S = uimm (aarch64_get_instr (cpu), 29, 29);
11230 uint32_t op2 = uimm (aarch64_get_instr (cpu), 11, 10);
11238 cc = condcode (aarch64_get_instr (cpu), 12);
11239 dispatch = ((uimm (aarch64_get_instr (cpu), 31, 30) << 1) | op2);
11243 case 0: csel32 (cpu, cc); return;
11244 case 1: csinc32 (cpu, cc); return;
11245 case 2: csinv32 (cpu, cc); return;
11246 case 3: csneg32 (cpu, cc); return;
11247 case 4: csel64 (cpu, cc); return;
11248 case 5: csinc64 (cpu, cc); return;
11249 case 6: csinv64 (cpu, cc); return;
11250 case 7: csneg64 (cpu, cc); return;
11251 default: HALT_UNALLOC;
11255 /* Some helpers for counting leading 1 or 0 bits. */
11257 /* Counts the number of leading bits which are the same
11258 in a 32 bit value in the range 1 to 32. */
11260 leading32 (uint32_t value)
11262 int32_t mask= 0xffff0000;
11263 uint32_t count= 16; /* Counts number of bits set in mask. */
11264 uint32_t lo = 1; /* Lower bound for number of sign bits. */
11265 uint32_t hi = 32; /* Upper bound for number of sign bits. */
11267 while (lo + 1 < hi)
11269 int32_t test = (value & mask);
11271 if (test == 0 || test == mask)
11274 count = (lo + hi) / 2;
11275 mask >>= (count - lo);
11280 count = (lo + hi) / 2;
11281 mask <<= hi - count;
11290 test = (value & mask);
11292 if (test == 0 || test == mask)
11301 /* Counts the number of leading bits which are the same
11302 in a 64 bit value in the range 1 to 64. */
11304 leading64 (uint64_t value)
11306 int64_t mask= 0xffffffff00000000LL;
11307 uint64_t count = 32; /* Counts number of bits set in mask. */
11308 uint64_t lo = 1; /* Lower bound for number of sign bits. */
11309 uint64_t hi = 64; /* Upper bound for number of sign bits. */
11311 while (lo + 1 < hi)
11313 int64_t test = (value & mask);
11315 if (test == 0 || test == mask)
11318 count = (lo + hi) / 2;
11319 mask >>= (count - lo);
11324 count = (lo + hi) / 2;
11325 mask <<= hi - count;
11334 test = (value & mask);
11336 if (test == 0 || test == mask)
11345 /* Bit operations. */
11346 /* N.B register args may not be SP. */
11348 /* 32 bit count leading sign bits. */
11350 cls32 (sim_cpu *cpu)
11352 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
11353 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
11355 /* N.B. the result needs to exclude the leading bit. */
11356 aarch64_set_reg_u64
11357 (cpu, rd, NO_SP, leading32 (aarch64_get_reg_u32 (cpu, rn, NO_SP)) - 1);
11360 /* 64 bit count leading sign bits. */
11362 cls64 (sim_cpu *cpu)
11364 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
11365 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
11367 /* N.B. the result needs to exclude the leading bit. */
11368 aarch64_set_reg_u64
11369 (cpu, rd, NO_SP, leading64 (aarch64_get_reg_u64 (cpu, rn, NO_SP)) - 1);
11372 /* 32 bit count leading zero bits. */
11374 clz32 (sim_cpu *cpu)
11376 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
11377 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
11378 uint32_t value = aarch64_get_reg_u32 (cpu, rn, NO_SP);
11380 /* if the sign (top) bit is set then the count is 0. */
11381 if (pick32 (value, 31, 31))
11382 aarch64_set_reg_u64 (cpu, rd, NO_SP, 0L);
11384 aarch64_set_reg_u64 (cpu, rd, NO_SP, leading32 (value));
11387 /* 64 bit count leading zero bits. */
11389 clz64 (sim_cpu *cpu)
11391 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
11392 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
11393 uint64_t value = aarch64_get_reg_u64 (cpu, rn, NO_SP);
11395 /* if the sign (top) bit is set then the count is 0. */
11396 if (pick64 (value, 63, 63))
11397 aarch64_set_reg_u64 (cpu, rd, NO_SP, 0L);
11399 aarch64_set_reg_u64 (cpu, rd, NO_SP, leading64 (value));
11402 /* 32 bit reverse bits. */
11404 rbit32 (sim_cpu *cpu)
11406 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
11407 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
11408 uint32_t value = aarch64_get_reg_u32 (cpu, rn, NO_SP);
11409 uint32_t result = 0;
11412 for (i = 0; i < 32; i++)
11415 result |= (value & 1);
11418 aarch64_set_reg_u64 (cpu, rd, NO_SP, result);
11421 /* 64 bit reverse bits. */
11423 rbit64 (sim_cpu *cpu)
11425 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
11426 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
11427 uint64_t value = aarch64_get_reg_u64 (cpu, rn, NO_SP);
11428 uint64_t result = 0;
11431 for (i = 0; i < 64; i++)
11434 result |= (value & 1L);
11437 aarch64_set_reg_u64 (cpu, rd, NO_SP, result);
11440 /* 32 bit reverse bytes. */
11442 rev32 (sim_cpu *cpu)
11444 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
11445 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
11446 uint32_t value = aarch64_get_reg_u32 (cpu, rn, NO_SP);
11447 uint32_t result = 0;
11450 for (i = 0; i < 4; i++)
11453 result |= (value & 0xff);
11456 aarch64_set_reg_u64 (cpu, rd, NO_SP, result);
11459 /* 64 bit reverse bytes. */
11461 rev64 (sim_cpu *cpu)
11463 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
11464 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
11465 uint64_t value = aarch64_get_reg_u64 (cpu, rn, NO_SP);
11466 uint64_t result = 0;
11469 for (i = 0; i < 8; i++)
11472 result |= (value & 0xffULL);
11475 aarch64_set_reg_u64 (cpu, rd, NO_SP, result);
11478 /* 32 bit reverse shorts. */
11479 /* N.B.this reverses the order of the bytes in each half word. */
11481 revh32 (sim_cpu *cpu)
11483 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
11484 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
11485 uint32_t value = aarch64_get_reg_u32 (cpu, rn, NO_SP);
11486 uint32_t result = 0;
11489 for (i = 0; i < 2; i++)
11492 result |= (value & 0x00ff00ff);
11495 aarch64_set_reg_u64 (cpu, rd, NO_SP, result);
11498 /* 64 bit reverse shorts. */
11499 /* N.B.this reverses the order of the bytes in each half word. */
11501 revh64 (sim_cpu *cpu)
11503 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
11504 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
11505 uint64_t value = aarch64_get_reg_u64 (cpu, rn, NO_SP);
11506 uint64_t result = 0;
11509 for (i = 0; i < 2; i++)
11512 result |= (value & 0x00ff00ff00ff00ffULL);
11515 aarch64_set_reg_u64 (cpu, rd, NO_SP, result);
11519 dexDataProc1Source (sim_cpu *cpu)
11521 /* assert instr[30] == 1
11522 aarch64_get_instr (cpu)[28,21] == 111010110
11523 instr[31] = size : 0 ==> 32 bit, 1 ==> 64 bit
11524 instr[29] = S : 0 ==> ok, 1 ==> UNALLOC
11525 instr[20,16] = opcode2 : 00000 ==> ok, ow ==> UNALLOC
11526 instr[15,10] = opcode : 000000 ==> RBIT, 000001 ==> REV16,
11527 000010 ==> REV, 000011 ==> UNALLOC
11528 000100 ==> CLZ, 000101 ==> CLS
11530 instr[9,5] = rn : may not be SP
11531 instr[4,0] = rd : may not be SP. */
11533 uint32_t S = uimm (aarch64_get_instr (cpu), 29, 29);
11534 uint32_t opcode2 = uimm (aarch64_get_instr (cpu), 20, 16);
11535 uint32_t opcode = uimm (aarch64_get_instr (cpu), 15, 10);
11536 uint32_t dispatch = ((uimm (aarch64_get_instr (cpu), 31, 31) << 3) | opcode);
11549 case 0: rbit32 (cpu); return;
11550 case 1: revh32 (cpu); return;
11551 case 2: rev32 (cpu); return;
11552 case 4: clz32 (cpu); return;
11553 case 5: cls32 (cpu); return;
11554 case 8: rbit64 (cpu); return;
11555 case 9: revh64 (cpu); return;
11556 case 10:rev32 (cpu); return;
11557 case 11:rev64 (cpu); return;
11558 case 12:clz64 (cpu); return;
11559 case 13:cls64 (cpu); return;
11560 default: HALT_UNALLOC;
11565 Shifts by count supplied in register.
11566 N.B register args may not be SP.
11567 These all use the shifted auxiliary function for
11568 simplicity and clarity. Writing the actual shift
11569 inline would avoid a branch and so be faster but
11570 would also necessitate getting signs right. */
11572 /* 32 bit arithmetic shift right. */
11574 asrv32 (sim_cpu *cpu)
11576 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
11577 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
11578 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
11580 aarch64_set_reg_u64
11582 shifted32 (aarch64_get_reg_u32 (cpu, rn, NO_SP), ASR,
11583 (aarch64_get_reg_u32 (cpu, rm, NO_SP) & 0x1f)));
11586 /* 64 bit arithmetic shift right. */
11588 asrv64 (sim_cpu *cpu)
11590 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
11591 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
11592 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
11594 aarch64_set_reg_u64
11596 shifted64 (aarch64_get_reg_u64 (cpu, rn, NO_SP), ASR,
11597 (aarch64_get_reg_u64 (cpu, rm, NO_SP) & 0x3f)));
11600 /* 32 bit logical shift left. */
11602 lslv32 (sim_cpu *cpu)
11604 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
11605 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
11606 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
11608 aarch64_set_reg_u64
11610 shifted32 (aarch64_get_reg_u32 (cpu, rn, NO_SP), LSL,
11611 (aarch64_get_reg_u32 (cpu, rm, NO_SP) & 0x1f)));
11614 /* 64 bit arithmetic shift left. */
11616 lslv64 (sim_cpu *cpu)
11618 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
11619 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
11620 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
11622 aarch64_set_reg_u64
11624 shifted64 (aarch64_get_reg_u64 (cpu, rn, NO_SP), LSL,
11625 (aarch64_get_reg_u64 (cpu, rm, NO_SP) & 0x3f)));
11628 /* 32 bit logical shift right. */
11630 lsrv32 (sim_cpu *cpu)
11632 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
11633 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
11634 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
11636 aarch64_set_reg_u64
11638 shifted32 (aarch64_get_reg_u32 (cpu, rn, NO_SP), LSR,
11639 (aarch64_get_reg_u32 (cpu, rm, NO_SP) & 0x1f)));
11642 /* 64 bit logical shift right. */
11644 lsrv64 (sim_cpu *cpu)
11646 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
11647 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
11648 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
11650 aarch64_set_reg_u64
11652 shifted64 (aarch64_get_reg_u64 (cpu, rn, NO_SP), LSR,
11653 (aarch64_get_reg_u64 (cpu, rm, NO_SP) & 0x3f)));
11656 /* 32 bit rotate right. */
11658 rorv32 (sim_cpu *cpu)
11660 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
11661 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
11662 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
11664 aarch64_set_reg_u64
11666 shifted32 (aarch64_get_reg_u32 (cpu, rn, NO_SP), ROR,
11667 (aarch64_get_reg_u32 (cpu, rm, NO_SP) & 0x1f)));
11670 /* 64 bit rotate right. */
11672 rorv64 (sim_cpu *cpu)
11674 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
11675 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
11676 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
11678 aarch64_set_reg_u64
11680 shifted64 (aarch64_get_reg_u64 (cpu, rn, NO_SP), ROR,
11681 (aarch64_get_reg_u64 (cpu, rm, NO_SP) & 0x3f)));
11687 /* 32 bit signed divide. */
11689 cpuiv32 (sim_cpu *cpu)
11691 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
11692 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
11693 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
11694 /* N.B. the pseudo-code does the divide using 64 bit data. */
11695 /* TODO : check that this rounds towards zero as required. */
11696 int64_t dividend = aarch64_get_reg_s32 (cpu, rn, NO_SP);
11697 int64_t divisor = aarch64_get_reg_s32 (cpu, rm, NO_SP);
11699 aarch64_set_reg_s64 (cpu, rd, NO_SP,
11700 divisor ? ((int32_t) (dividend / divisor)) : 0);
11703 /* 64 bit signed divide. */
11705 cpuiv64 (sim_cpu *cpu)
11707 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
11708 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
11709 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
11711 /* TODO : check that this rounds towards zero as required. */
11712 int64_t divisor = aarch64_get_reg_s64 (cpu, rm, NO_SP);
11714 aarch64_set_reg_s64
11716 divisor ? (aarch64_get_reg_s64 (cpu, rn, NO_SP) / divisor) : 0);
11719 /* 32 bit unsigned divide. */
11721 udiv32 (sim_cpu *cpu)
11723 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
11724 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
11725 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
11727 /* N.B. the pseudo-code does the divide using 64 bit data. */
11728 uint64_t dividend = aarch64_get_reg_u32 (cpu, rn, NO_SP);
11729 uint64_t divisor = aarch64_get_reg_u32 (cpu, rm, NO_SP);
11731 aarch64_set_reg_u64 (cpu, rd, NO_SP,
11732 divisor ? (uint32_t) (dividend / divisor) : 0);
11735 /* 64 bit unsigned divide. */
11737 udiv64 (sim_cpu *cpu)
11739 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
11740 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
11741 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
11743 /* TODO : check that this rounds towards zero as required. */
11744 uint64_t divisor = aarch64_get_reg_u64 (cpu, rm, NO_SP);
11746 aarch64_set_reg_u64
11748 divisor ? (aarch64_get_reg_u64 (cpu, rn, NO_SP) / divisor) : 0);
11752 dexDataProc2Source (sim_cpu *cpu)
11754 /* assert instr[30] == 0
11755 instr[28,21] == 11010110
11756 instr[31] = size : 0 ==> 32 bit, 1 ==> 64 bit
11757 instr[29] = S : 0 ==> ok, 1 ==> UNALLOC
11758 instr[15,10] = opcode : 000010 ==> UDIV, 000011 ==> CPUIV,
11759 001000 ==> LSLV, 001001 ==> LSRV
11760 001010 ==> ASRV, 001011 ==> RORV
11764 uint32_t S = uimm (aarch64_get_instr (cpu), 29, 29);
11765 uint32_t opcode = uimm (aarch64_get_instr (cpu), 15, 10);
11773 dispatch = ( (uimm (aarch64_get_instr (cpu), 31, 31) << 3)
11774 | (uimm (opcode, 3, 3) << 2)
11775 | uimm (opcode, 1, 0));
11778 case 2: udiv32 (cpu); return;
11779 case 3: cpuiv32 (cpu); return;
11780 case 4: lslv32 (cpu); return;
11781 case 5: lsrv32 (cpu); return;
11782 case 6: asrv32 (cpu); return;
11783 case 7: rorv32 (cpu); return;
11784 case 10: udiv64 (cpu); return;
11785 case 11: cpuiv64 (cpu); return;
11786 case 12: lslv64 (cpu); return;
11787 case 13: lsrv64 (cpu); return;
11788 case 14: asrv64 (cpu); return;
11789 case 15: rorv64 (cpu); return;
11790 default: HALT_UNALLOC;
11797 /* 32 bit multiply and add. */
11799 madd32 (sim_cpu *cpu)
11801 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
11802 unsigned ra = uimm (aarch64_get_instr (cpu), 14, 10);
11803 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
11804 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
11806 aarch64_set_reg_u64 (cpu, rd, NO_SP,
11807 aarch64_get_reg_u32 (cpu, ra, NO_SP)
11808 + aarch64_get_reg_u32 (cpu, rn, NO_SP)
11809 * aarch64_get_reg_u32 (cpu, rm, NO_SP));
11812 /* 64 bit multiply and add. */
11814 madd64 (sim_cpu *cpu)
11816 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
11817 unsigned ra = uimm (aarch64_get_instr (cpu), 14, 10);
11818 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
11819 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
11821 aarch64_set_reg_u64 (cpu, rd, NO_SP,
11822 aarch64_get_reg_u64 (cpu, ra, NO_SP)
11823 + aarch64_get_reg_u64 (cpu, rn, NO_SP)
11824 * aarch64_get_reg_u64 (cpu, rm, NO_SP));
11827 /* 32 bit multiply and sub. */
11829 msub32 (sim_cpu *cpu)
11831 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
11832 unsigned ra = uimm (aarch64_get_instr (cpu), 14, 10);
11833 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
11834 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
11836 aarch64_set_reg_u64 (cpu, rd, NO_SP,
11837 aarch64_get_reg_u32 (cpu, ra, NO_SP)
11838 - aarch64_get_reg_u32 (cpu, rn, NO_SP)
11839 * aarch64_get_reg_u32 (cpu, rm, NO_SP));
11842 /* 64 bit multiply and sub. */
11844 msub64 (sim_cpu *cpu)
11846 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
11847 unsigned ra = uimm (aarch64_get_instr (cpu), 14, 10);
11848 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
11849 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
11851 aarch64_set_reg_u64 (cpu, rd, NO_SP,
11852 aarch64_get_reg_u64 (cpu, ra, NO_SP)
11853 - aarch64_get_reg_u64 (cpu, rn, NO_SP)
11854 * aarch64_get_reg_u64 (cpu, rm, NO_SP));
11857 /* Signed multiply add long -- source, source2 : 32 bit, source3 : 64 bit. */
11859 smaddl (sim_cpu *cpu)
11861 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
11862 unsigned ra = uimm (aarch64_get_instr (cpu), 14, 10);
11863 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
11864 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
11866 /* N.B. we need to multiply the signed 32 bit values in rn, rm to
11867 obtain a 64 bit product. */
11868 aarch64_set_reg_s64
11870 aarch64_get_reg_s64 (cpu, ra, NO_SP)
11871 + ((int64_t) aarch64_get_reg_s32 (cpu, rn, NO_SP))
11872 * ((int64_t) aarch64_get_reg_s32 (cpu, rm, NO_SP)));
11875 /* Signed multiply sub long -- source, source2 : 32 bit, source3 : 64 bit. */
11877 smsubl (sim_cpu *cpu)
11879 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
11880 unsigned ra = uimm (aarch64_get_instr (cpu), 14, 10);
11881 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
11882 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
11884 /* N.B. we need to multiply the signed 32 bit values in rn, rm to
11885 obtain a 64 bit product. */
11886 aarch64_set_reg_s64
11888 aarch64_get_reg_s64 (cpu, ra, NO_SP)
11889 - ((int64_t) aarch64_get_reg_s32 (cpu, rn, NO_SP))
11890 * ((int64_t) aarch64_get_reg_s32 (cpu, rm, NO_SP)));
11893 /* Integer Multiply/Divide. */
11895 /* First some macros and a helper function. */
11896 /* Macros to test or access elements of 64 bit words. */
11898 /* Mask used to access lo 32 bits of 64 bit unsigned int. */
11899 #define LOW_WORD_MASK ((1ULL << 32) - 1)
11900 /* Return the lo 32 bit word of a 64 bit unsigned int as a 64 bit unsigned int. */
11901 #define lowWordToU64(_value_u64) ((_value_u64) & LOW_WORD_MASK)
11902 /* Return the hi 32 bit word of a 64 bit unsigned int as a 64 bit unsigned int. */
11903 #define highWordToU64(_value_u64) ((_value_u64) >> 32)
11905 /* Offset of sign bit in 64 bit signed integger. */
11906 #define SIGN_SHIFT_U64 63
11907 /* The sign bit itself -- also identifies the minimum negative int value. */
11908 #define SIGN_BIT_U64 (1UL << SIGN_SHIFT_U64)
11909 /* Return true if a 64 bit signed int presented as an unsigned int is the
11910 most negative value. */
11911 #define isMinimumU64(_value_u64) ((_value_u64) == SIGN_BIT_U64)
11912 /* Return true (non-zero) if a 64 bit signed int presented as an unsigned
11913 int has its sign bit set to false. */
11914 #define isSignSetU64(_value_u64) ((_value_u64) & SIGN_BIT_U64)
11915 /* Return 1L or -1L according to whether a 64 bit signed int presented as
11916 an unsigned int has its sign bit set or not. */
11917 #define signOfU64(_value_u64) (1L + (((value_u64) >> SIGN_SHIFT_U64) * -2L)
11918 /* Clear the sign bit of a 64 bit signed int presented as an unsigned int. */
11919 #define clearSignU64(_value_u64) ((_value_u64) &= ~SIGN_BIT_U64)
11921 /* Multiply two 64 bit ints and return.
11922 the hi 64 bits of the 128 bit product. */
11925 mul64hi (uint64_t value1, uint64_t value2)
11927 uint64_t resultmid1;
11929 uint64_t value1_lo = lowWordToU64 (value1);
11930 uint64_t value1_hi = highWordToU64 (value1) ;
11931 uint64_t value2_lo = lowWordToU64 (value2);
11932 uint64_t value2_hi = highWordToU64 (value2);
11934 /* Cross-multiply and collect results. */
11936 uint64_t xproductlo = value1_lo * value2_lo;
11937 uint64_t xproductmid1 = value1_lo * value2_hi;
11938 uint64_t xproductmid2 = value1_hi * value2_lo;
11939 uint64_t xproducthi = value1_hi * value2_hi;
11940 uint64_t carry = 0;
11941 /* Start accumulating 64 bit results. */
11942 /* Drop bottom half of lowest cross-product. */
11943 uint64_t resultmid = xproductlo >> 32;
11944 /* Add in middle products. */
11945 resultmid = resultmid + xproductmid1;
11947 /* Check for overflow. */
11948 if (resultmid < xproductmid1)
11949 /* Carry over 1 into top cross-product. */
11952 resultmid1 = resultmid + xproductmid2;
11954 /* Check for overflow. */
11955 if (resultmid1 < xproductmid2)
11956 /* Carry over 1 into top cross-product. */
11959 /* Drop lowest 32 bits of middle cross-product. */
11960 result = resultmid1 >> 32;
11962 /* Add top cross-product plus and any carry. */
11963 result += xproducthi + carry;
11968 /* Signed multiply high, source, source2 :
11969 64 bit, dest <-- high 64-bit of result. */
11971 smulh (sim_cpu *cpu)
11975 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
11976 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
11977 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
11978 GReg ra = greg (aarch64_get_instr (cpu), 10);
11979 int64_t value1 = aarch64_get_reg_u64 (cpu, rn, NO_SP);
11980 int64_t value2 = aarch64_get_reg_u64 (cpu, rm, NO_SP);
11983 int64_t signum = 1;
11988 /* Convert to unsigned and use the unsigned mul64hi routine
11989 the fix the sign up afterwards. */
12010 uresult = mul64hi (uvalue1, uvalue2);
12014 aarch64_set_reg_s64 (cpu, rd, NO_SP, result);
12017 /* Unsigned multiply add long -- source, source2 :
12018 32 bit, source3 : 64 bit. */
12020 umaddl (sim_cpu *cpu)
12022 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
12023 unsigned ra = uimm (aarch64_get_instr (cpu), 14, 10);
12024 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
12025 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
12027 /* N.B. we need to multiply the signed 32 bit values in rn, rm to
12028 obtain a 64 bit product. */
12029 aarch64_set_reg_u64
12031 aarch64_get_reg_u64 (cpu, ra, NO_SP)
12032 + ((uint64_t) aarch64_get_reg_u32 (cpu, rn, NO_SP))
12033 * ((uint64_t) aarch64_get_reg_u32 (cpu, rm, NO_SP)));
12036 /* Unsigned multiply sub long -- source, source2 : 32 bit, source3 : 64 bit. */
12038 umsubl (sim_cpu *cpu)
12040 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
12041 unsigned ra = uimm (aarch64_get_instr (cpu), 14, 10);
12042 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
12043 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
12045 /* N.B. we need to multiply the signed 32 bit values in rn, rm to
12046 obtain a 64 bit product. */
12047 aarch64_set_reg_u64
12049 aarch64_get_reg_u64 (cpu, ra, NO_SP)
12050 - ((uint64_t) aarch64_get_reg_u32 (cpu, rn, NO_SP))
12051 * ((uint64_t) aarch64_get_reg_u32 (cpu, rm, NO_SP)));
12054 /* Unsigned multiply high, source, source2 :
12055 64 bit, dest <-- high 64-bit of result. */
12057 umulh (sim_cpu *cpu)
12059 unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
12060 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
12061 unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
12062 GReg ra = greg (aarch64_get_instr (cpu), 10);
12067 aarch64_set_reg_u64 (cpu, rd, NO_SP,
12068 mul64hi (aarch64_get_reg_u64 (cpu, rn, NO_SP),
12069 aarch64_get_reg_u64 (cpu, rm, NO_SP)));
12073 dexDataProc3Source (sim_cpu *cpu)
12075 /* assert instr[28,24] == 11011. */
12076 /* instr[31] = size : 0 ==> 32 bit, 1 ==> 64 bit (for rd at least)
12077 instr[30,29] = op54 : 00 ==> ok, ow ==> UNALLOC
12078 instr[23,21] = op31 : 111 ==> UNALLOC, o2 ==> ok
12079 instr[15] = o0 : 0/1 ==> ok
12080 instr[23,21:15] ==> op : 0000 ==> MADD, 0001 ==> MSUB, (32/64 bit)
12081 0010 ==> SMADDL, 0011 ==> SMSUBL, (64 bit only)
12082 0100 ==> SMULH, (64 bit only)
12083 1010 ==> UMADDL, 1011 ==> UNSUBL, (64 bit only)
12084 1100 ==> UMULH (64 bit only)
12088 uint32_t size = uimm (aarch64_get_instr (cpu), 31, 31);
12089 uint32_t op54 = uimm (aarch64_get_instr (cpu), 30, 29);
12090 uint32_t op31 = uimm (aarch64_get_instr (cpu), 23, 21);
12091 uint32_t o0 = uimm (aarch64_get_instr (cpu), 15, 15);
12108 dispatch = (op31 << 1) | o0;
12112 case 0: madd64 (cpu); return;
12113 case 1: msub64 (cpu); return;
12114 case 2: smaddl (cpu); return;
12115 case 3: smsubl (cpu); return;
12116 case 4: smulh (cpu); return;
12117 case 10: umaddl (cpu); return;
12118 case 11: umsubl (cpu); return;
12119 case 12: umulh (cpu); return;
12120 default: HALT_UNALLOC;
12125 dexDPReg (sim_cpu *cpu)
12127 /* uint32_t group = dispatchGroup (aarch64_get_instr (cpu));
12128 assert group == GROUP_DPREG_0101 || group == GROUP_DPREG_1101
12129 bits [28:24:21] of a DPReg are the secondary dispatch vector. */
12130 uint32_t group2 = dispatchDPReg (aarch64_get_instr (cpu));
12134 case DPREG_LOG_000:
12135 case DPREG_LOG_001:
12136 dexLogicalShiftedRegister (cpu); return;
12138 case DPREG_ADDSHF_010:
12139 dexAddSubtractShiftedRegister (cpu); return;
12141 case DPREG_ADDEXT_011:
12142 dexAddSubtractExtendedRegister (cpu); return;
12144 case DPREG_ADDCOND_100:
12146 /* This set bundles a variety of different operations. */
12148 /* 1) add/sub w carry. */
12149 uint32_t mask1 = 0x1FE00000U;
12150 uint32_t val1 = 0x1A000000U;
12151 /* 2) cond compare register/immediate. */
12152 uint32_t mask2 = 0x1FE00000U;
12153 uint32_t val2 = 0x1A400000U;
12154 /* 3) cond select. */
12155 uint32_t mask3 = 0x1FE00000U;
12156 uint32_t val3 = 0x1A800000U;
12157 /* 4) data proc 1/2 source. */
12158 uint32_t mask4 = 0x1FE00000U;
12159 uint32_t val4 = 0x1AC00000U;
12161 if ((aarch64_get_instr (cpu) & mask1) == val1)
12162 dexAddSubtractWithCarry (cpu);
12164 else if ((aarch64_get_instr (cpu) & mask2) == val2)
12167 else if ((aarch64_get_instr (cpu) & mask3) == val3)
12168 dexCondSelect (cpu);
12170 else if ((aarch64_get_instr (cpu) & mask4) == val4)
12172 /* Bit 30 is clear for data proc 2 source
12173 and set for data proc 1 source. */
12174 if (aarch64_get_instr (cpu) & (1U << 30))
12175 dexDataProc1Source (cpu);
12177 dexDataProc2Source (cpu);
12181 /* Should not reach here. */
12187 case DPREG_3SRC_110:
12188 dexDataProc3Source (cpu); return;
12190 case DPREG_UNALLOC_101:
12193 case DPREG_3SRC_111:
12194 dexDataProc3Source (cpu); return;
12197 /* Should never reach here. */
12202 /* Unconditional Branch immediate.
12203 Offset is a PC-relative byte offset in the range +/- 128MiB.
12204 The offset is assumed to be raw from the decode i.e. the
12205 simulator is expected to scale them from word offsets to byte. */
12207 /* Unconditional branch. */
12209 buc (sim_cpu *cpu, int32_t offset)
12211 aarch64_set_next_PC_by_offset (cpu, offset);
12214 static unsigned stack_depth = 0;
12216 /* Unconditional branch and link -- writes return PC to LR. */
12218 bl (sim_cpu *cpu, int32_t offset)
12220 aarch64_save_LR (cpu);
12221 aarch64_set_next_PC_by_offset (cpu, offset);
12223 if (TRACE_BRANCH_P (cpu))
12227 " %*scall %" PRIx64 " [%s]"
12228 " [args: %" PRIx64 " %" PRIx64 " %" PRIx64 "]",
12229 stack_depth, " ", aarch64_get_next_PC (cpu),
12230 aarch64_get_func (aarch64_get_next_PC (cpu)),
12231 aarch64_get_reg_u64 (cpu, 0, NO_SP),
12232 aarch64_get_reg_u64 (cpu, 1, NO_SP),
12233 aarch64_get_reg_u64 (cpu, 2, NO_SP)
12238 /* Unconditional Branch register.
12239 Branch/return address is in source register. */
12241 /* Unconditional branch. */
12245 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
12246 aarch64_set_next_PC (cpu, aarch64_get_reg_u64 (cpu, rn, NO_SP));
12249 /* Unconditional branch and link -- writes return PC to LR. */
12253 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
12255 /* The pseudo code in the spec says we update LR before fetching.
12256 the value from the rn. */
12257 aarch64_save_LR (cpu);
12258 aarch64_set_next_PC (cpu, aarch64_get_reg_u64 (cpu, rn, NO_SP));
12260 if (TRACE_BRANCH_P (cpu))
12264 " %*scall %" PRIx64 " [%s]"
12265 " [args: %" PRIx64 " %" PRIx64 " %" PRIx64 "]",
12266 stack_depth, " ", aarch64_get_next_PC (cpu),
12267 aarch64_get_func (aarch64_get_next_PC (cpu)),
12268 aarch64_get_reg_u64 (cpu, 0, NO_SP),
12269 aarch64_get_reg_u64 (cpu, 1, NO_SP),
12270 aarch64_get_reg_u64 (cpu, 2, NO_SP)
12275 /* Return -- assembler will default source to LR this is functionally
12276 equivalent to br but, presumably, unlike br it side effects the
12277 branch predictor. */
12281 unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
12282 aarch64_set_next_PC (cpu, aarch64_get_reg_u64 (cpu, rn, NO_SP));
12284 if (TRACE_BRANCH_P (cpu))
12287 " %*sreturn [result: %" PRIx64 "]",
12288 stack_depth, " ", aarch64_get_reg_u64 (cpu, 0, NO_SP));
12293 /* NOP -- we implement this and call it from the decode in case we
12294 want to intercept it later. */
12301 /* Data synchronization barrier. */
12308 /* Data memory barrier. */
12315 /* Instruction synchronization barrier. */
12323 dexBranchImmediate (sim_cpu *cpu)
12325 /* assert instr[30,26] == 00101
12326 instr[31] ==> 0 == B, 1 == BL
12327 instr[25,0] == imm26 branch offset counted in words. */
12329 uint32_t top = uimm (aarch64_get_instr (cpu), 31, 31);
12330 /* We have a 26 byte signed word offset which we need to pass to the
12331 execute routine as a signed byte offset. */
12332 int32_t offset = simm32 (aarch64_get_instr (cpu), 25, 0) << 2;
12340 /* Control Flow. */
12342 /* Conditional branch
12344 Offset is a PC-relative byte offset in the range +/- 1MiB pos is
12345 a bit position in the range 0 .. 63
12347 cc is a CondCode enum value as pulled out of the decode
12349 N.B. any offset register (source) can only be Xn or Wn. */
12352 bcc (sim_cpu *cpu, int32_t offset, CondCode cc)
12354 /* the test returns TRUE if CC is met. */
12355 if (testConditionCode (cpu, cc))
12356 aarch64_set_next_PC_by_offset (cpu, offset);
12359 /* 32 bit branch on register non-zero. */
12361 cbnz32 (sim_cpu *cpu, int32_t offset)
12363 unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
12365 if (aarch64_get_reg_u32 (cpu, rt, NO_SP) != 0)
12366 aarch64_set_next_PC_by_offset (cpu, offset);
12369 /* 64 bit branch on register zero. */
12371 cbnz (sim_cpu *cpu, int32_t offset)
12373 unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
12375 if (aarch64_get_reg_u64 (cpu, rt, NO_SP) != 0)
12376 aarch64_set_next_PC_by_offset (cpu, offset);
12379 /* 32 bit branch on register non-zero. */
12381 cbz32 (sim_cpu *cpu, int32_t offset)
12383 unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
12385 if (aarch64_get_reg_u32 (cpu, rt, NO_SP) == 0)
12386 aarch64_set_next_PC_by_offset (cpu, offset);
12389 /* 64 bit branch on register zero. */
12391 cbz (sim_cpu *cpu, int32_t offset)
12393 unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
12395 if (aarch64_get_reg_u64 (cpu, rt, NO_SP) == 0)
12396 aarch64_set_next_PC_by_offset (cpu, offset);
12399 /* Branch on register bit test non-zero -- one size fits all. */
12401 tbnz (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);
12409 /* branch on register bit test zero -- one size fits all. */
12411 tbz (sim_cpu *cpu, uint32_t pos, int32_t offset)
12413 unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
12415 if (!(aarch64_get_reg_u64 (cpu, rt, NO_SP) & (1 << pos)))
12416 aarch64_set_next_PC_by_offset (cpu, offset);
12420 dexCompareBranchImmediate (sim_cpu *cpu)
12422 /* instr[30,25] = 01 1010
12423 instr[31] = size : 0 ==> 32, 1 ==> 64
12424 instr[24] = op : 0 ==> CBZ, 1 ==> CBNZ
12425 instr[23,5] = simm19 branch offset counted in words
12428 uint32_t size = uimm (aarch64_get_instr (cpu), 31, 31);
12429 uint32_t op = uimm (aarch64_get_instr (cpu), 24, 24);
12430 int32_t offset = simm32 (aarch64_get_instr (cpu), 23, 5) << 2;
12435 cbz32 (cpu, offset);
12437 cbnz32 (cpu, offset);
12444 cbnz (cpu, offset);
12449 dexTestBranchImmediate (sim_cpu *cpu)
12451 /* instr[31] = b5 : bit 5 of test bit idx
12452 instr[30,25] = 01 1011
12453 instr[24] = op : 0 ==> TBZ, 1 == TBNZ
12454 instr[23,19] = b40 : bits 4 to 0 of test bit idx
12455 instr[18,5] = simm14 : signed offset counted in words
12456 instr[4,0] = uimm5 */
12458 uint32_t pos = ((uimm (aarch64_get_instr (cpu), 31, 31) << 4)
12459 | uimm (aarch64_get_instr (cpu), 23,19));
12460 int32_t offset = simm32 (aarch64_get_instr (cpu), 18, 5) << 2;
12462 NYI_assert (30, 25, 0x1b);
12464 if (uimm (aarch64_get_instr (cpu), 24, 24) == 0)
12465 tbz (cpu, pos, offset);
12467 tbnz (cpu, pos, offset);
12471 dexCondBranchImmediate (sim_cpu *cpu)
12473 /* instr[31,25] = 010 1010
12474 instr[24] = op1; op => 00 ==> B.cond
12475 instr[23,5] = simm19 : signed offset counted in words
12477 instr[3,0] = cond */
12481 uint32_t op = ((uimm (aarch64_get_instr (cpu), 24, 24) << 1)
12482 | uimm (aarch64_get_instr (cpu), 4, 4));
12484 NYI_assert (31, 25, 0x2a);
12489 offset = simm32 (aarch64_get_instr (cpu), 23, 5) << 2;
12490 cc = condcode (aarch64_get_instr (cpu), 0);
12492 bcc (cpu, offset, cc);
12496 dexBranchRegister (sim_cpu *cpu)
12498 /* instr[31,25] = 110 1011
12499 instr[24,21] = op : 0 ==> BR, 1 => BLR, 2 => RET, 3 => ERET, 4 => DRPS
12500 instr[20,16] = op2 : must be 11111
12501 instr[15,10] = op3 : must be 000000
12502 instr[4,0] = op2 : must be 11111. */
12504 uint32_t op = uimm (aarch64_get_instr (cpu), 24, 21);
12505 uint32_t op2 = uimm (aarch64_get_instr (cpu), 20, 16);
12506 uint32_t op3 = uimm (aarch64_get_instr (cpu), 15, 10);
12507 uint32_t op4 = uimm (aarch64_get_instr (cpu), 4, 0);
12509 NYI_assert (31, 25, 0x6b);
12511 if (op2 != 0x1F || op3 != 0 || op4 != 0)
12525 /* ERET and DRPS accept 0b11111 for rn = aarch64_get_instr (cpu)[4,0]. */
12526 /* anything else is unallocated. */
12527 uint32_t rn = greg (aarch64_get_instr (cpu), 0);
12532 if (op == 4 || op == 5)
12539 /* FIXME: We should get the Angel SWI values from ../../libgloss/aarch64/svc.h
12540 but this may not be available. So instead we define the values we need
12542 #define AngelSVC_Reason_Open 0x01
12543 #define AngelSVC_Reason_Close 0x02
12544 #define AngelSVC_Reason_Write 0x05
12545 #define AngelSVC_Reason_Read 0x06
12546 #define AngelSVC_Reason_IsTTY 0x09
12547 #define AngelSVC_Reason_Seek 0x0A
12548 #define AngelSVC_Reason_FLen 0x0C
12549 #define AngelSVC_Reason_Remove 0x0E
12550 #define AngelSVC_Reason_Rename 0x0F
12551 #define AngelSVC_Reason_Clock 0x10
12552 #define AngelSVC_Reason_Time 0x11
12553 #define AngelSVC_Reason_System 0x12
12554 #define AngelSVC_Reason_Errno 0x13
12555 #define AngelSVC_Reason_GetCmdLine 0x15
12556 #define AngelSVC_Reason_HeapInfo 0x16
12557 #define AngelSVC_Reason_ReportException 0x18
12558 #define AngelSVC_Reason_Elapsed 0x30
12562 handle_halt (sim_cpu *cpu, uint32_t val)
12564 uint64_t result = 0;
12568 TRACE_SYSCALL (cpu, " HLT [0x%x]", val);
12569 sim_engine_halt (CPU_STATE (cpu), cpu, NULL, aarch64_get_PC (cpu),
12570 sim_stopped, SIM_SIGTRAP);
12573 /* We have encountered an Angel SVC call. See if we can process it. */
12574 switch (aarch64_get_reg_u32 (cpu, 0, NO_SP))
12576 case AngelSVC_Reason_HeapInfo:
12578 /* Get the values. */
12579 uint64_t stack_top = aarch64_get_stack_start (cpu);
12580 uint64_t heap_base = aarch64_get_heap_start (cpu);
12582 /* Get the pointer */
12583 uint64_t ptr = aarch64_get_reg_u64 (cpu, 1, SP_OK);
12584 ptr = aarch64_get_mem_u64 (cpu, ptr);
12586 /* Fill in the memory block. */
12587 /* Start addr of heap. */
12588 aarch64_set_mem_u64 (cpu, ptr + 0, heap_base);
12589 /* End addr of heap. */
12590 aarch64_set_mem_u64 (cpu, ptr + 8, stack_top);
12591 /* Lowest stack addr. */
12592 aarch64_set_mem_u64 (cpu, ptr + 16, heap_base);
12593 /* Initial stack addr. */
12594 aarch64_set_mem_u64 (cpu, ptr + 24, stack_top);
12596 TRACE_SYSCALL (cpu, " AngelSVC: Get Heap Info");
12600 case AngelSVC_Reason_Open:
12602 /* Get the pointer */
12603 /* uint64_t ptr = aarch64_get_reg_u64 (cpu, 1, SP_OK);. */
12604 /* FIXME: For now we just assume that we will only be asked
12605 to open the standard file descriptors. */
12609 TRACE_SYSCALL (cpu, " AngelSVC: Open file %d", fd - 1);
12613 case AngelSVC_Reason_Close:
12615 uint64_t fh = aarch64_get_reg_u64 (cpu, 1, SP_OK);
12616 TRACE_SYSCALL (cpu, " AngelSVC: Close file %d", (int) fh);
12621 case AngelSVC_Reason_Errno:
12623 TRACE_SYSCALL (cpu, " AngelSVC: Get Errno");
12626 case AngelSVC_Reason_Clock:
12628 #ifdef CLOCKS_PER_SEC
12629 (CLOCKS_PER_SEC >= 100)
12630 ? (clock () / (CLOCKS_PER_SEC / 100))
12631 : ((clock () * 100) / CLOCKS_PER_SEC)
12633 /* Presume unix... clock() returns microseconds. */
12637 TRACE_SYSCALL (cpu, " AngelSVC: Get Clock");
12640 case AngelSVC_Reason_GetCmdLine:
12642 /* Get the pointer */
12643 uint64_t ptr = aarch64_get_reg_u64 (cpu, 1, SP_OK);
12644 ptr = aarch64_get_mem_u64 (cpu, ptr);
12646 /* FIXME: No command line for now. */
12647 aarch64_set_mem_u64 (cpu, ptr, 0);
12648 TRACE_SYSCALL (cpu, " AngelSVC: Get Command Line");
12652 case AngelSVC_Reason_IsTTY:
12654 TRACE_SYSCALL (cpu, " AngelSVC: IsTTY ?");
12657 case AngelSVC_Reason_Write:
12659 /* Get the pointer */
12660 uint64_t ptr = aarch64_get_reg_u64 (cpu, 1, SP_OK);
12661 /* Get the write control block. */
12662 uint64_t fd = aarch64_get_mem_u64 (cpu, ptr);
12663 uint64_t buf = aarch64_get_mem_u64 (cpu, ptr + 8);
12664 uint64_t len = aarch64_get_mem_u64 (cpu, ptr + 16);
12666 TRACE_SYSCALL (cpu, "write of %" PRIx64 " bytes from %"
12667 PRIx64 " on descriptor %" PRIx64,
12672 TRACE_SYSCALL (cpu,
12673 " AngelSVC: Write: Suspiciously long write: %ld",
12675 sim_engine_halt (CPU_STATE (cpu), cpu, NULL, aarch64_get_PC (cpu),
12676 sim_stopped, SIM_SIGBUS);
12680 printf ("%.*s", (int) len, aarch64_get_mem_ptr (cpu, buf));
12682 /* So that the output stays in sync with trace output. */
12687 TRACE (cpu, 0, "\n");
12688 sim_io_eprintf (CPU_STATE (cpu), "%.*s",
12689 (int) len, aarch64_get_mem_ptr (cpu, buf));
12690 TRACE (cpu, 0, "\n");
12694 TRACE_SYSCALL (cpu,
12695 " AngelSVC: Write: Unexpected file handle: %d",
12697 sim_engine_halt (CPU_STATE (cpu), cpu, NULL, aarch64_get_PC (cpu),
12698 sim_stopped, SIM_SIGABRT);
12703 case AngelSVC_Reason_ReportException:
12705 /* Get the pointer */
12706 uint64_t ptr = aarch64_get_reg_u64 (cpu, 1, SP_OK);
12707 /*ptr = aarch64_get_mem_u64 (cpu, ptr);. */
12708 uint64_t type = aarch64_get_mem_u64 (cpu, ptr);
12709 uint64_t state = aarch64_get_mem_u64 (cpu, ptr + 8);
12711 TRACE_SYSCALL (cpu,
12712 "Angel Exception: type 0x%" PRIx64 " state %" PRIx64,
12715 if (type == 0x20026)
12716 sim_engine_halt (CPU_STATE (cpu), cpu, NULL, aarch64_get_PC (cpu),
12717 sim_exited, state);
12719 sim_engine_halt (CPU_STATE (cpu), cpu, NULL, aarch64_get_PC (cpu),
12720 sim_stopped, SIM_SIGINT);
12724 case AngelSVC_Reason_Read:
12725 case AngelSVC_Reason_FLen:
12726 case AngelSVC_Reason_Seek:
12727 case AngelSVC_Reason_Remove:
12728 case AngelSVC_Reason_Time:
12729 case AngelSVC_Reason_System:
12730 case AngelSVC_Reason_Rename:
12731 case AngelSVC_Reason_Elapsed:
12733 TRACE_SYSCALL (cpu, " HLT [Unknown angel %x]",
12734 aarch64_get_reg_u32 (cpu, 0, NO_SP));
12735 sim_engine_halt (CPU_STATE (cpu), cpu, NULL, aarch64_get_PC (cpu),
12736 sim_stopped, SIM_SIGTRAP);
12739 aarch64_set_reg_u64 (cpu, 0, NO_SP, result);
12743 dexExcpnGen (sim_cpu *cpu)
12745 /* instr[31:24] = 11010100
12746 instr[23,21] = opc : 000 ==> GEN EXCPN, 001 ==> BRK
12747 010 ==> HLT, 101 ==> DBG GEN EXCPN
12748 instr[20,5] = imm16
12749 instr[4,2] = opc2 000 ==> OK, ow ==> UNALLOC
12750 instr[1,0] = LL : discriminates opc */
12752 uint32_t opc = uimm (aarch64_get_instr (cpu), 23, 21);
12753 uint32_t imm16 = uimm (aarch64_get_instr (cpu), 20, 5);
12754 uint32_t opc2 = uimm (aarch64_get_instr (cpu), 4, 2);
12757 NYI_assert (31, 24, 0xd4);
12762 LL = uimm (aarch64_get_instr (cpu), 1, 0);
12764 /* We only implement HLT and BRK for now. */
12765 if (opc == 1 && LL == 0)
12767 TRACE_EVENTS (cpu, " BRK [0x%x]", imm16);
12768 sim_engine_halt (CPU_STATE (cpu), cpu, NULL, aarch64_get_PC (cpu),
12769 sim_exited, aarch64_get_reg_s32 (cpu, R0, SP_OK));
12772 if (opc == 2 && LL == 0)
12773 handle_halt (cpu, imm16);
12775 else if (opc == 0 || opc == 5)
12782 /* Stub for accessing system registers.
12783 We implement support for the DCZID register since this is used
12784 by the C library's memset function. */
12787 system_get (sim_cpu *cpu, unsigned op0, unsigned op1, unsigned crn,
12788 unsigned crm, unsigned op2)
12790 if (crn == 0 && op1 == 3 && crm == 0 && op2 == 7)
12791 /* DCZID_EL0 - the Data Cache Zero ID register.
12792 We do not support DC ZVA at the moment, so
12793 we return a value with the disable bit set. */
12794 return ((uint64_t) 1) << 4;
12800 do_mrs (sim_cpu *cpu)
12802 /* instr[31:20] = 1101 01010 0011
12809 unsigned sys_op0 = uimm (aarch64_get_instr (cpu), 19, 19) + 2;
12810 unsigned sys_op1 = uimm (aarch64_get_instr (cpu), 18, 16);
12811 unsigned sys_crn = uimm (aarch64_get_instr (cpu), 15, 12);
12812 unsigned sys_crm = uimm (aarch64_get_instr (cpu), 11, 8);
12813 unsigned sys_op2 = uimm (aarch64_get_instr (cpu), 7, 5);
12814 unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
12816 aarch64_set_reg_u64 (cpu, rt, NO_SP,
12817 system_get (cpu, sys_op0, sys_op1, sys_crn, sys_crm, sys_op2));
12821 dexSystem (sim_cpu *cpu)
12823 /* instr[31:22] = 1101 01010 0
12830 instr[4,0] = uimm5 */
12832 /* We are interested in HINT, DSB, DMB and ISB
12834 Hint #0 encodes NOOP (this is the only hint we care about)
12835 L == 0, op0 == 0, op1 = 011, CRn = 0010, Rt = 11111,
12836 CRm op2 != 0000 000 OR CRm op2 == 0000 000 || CRm op > 0000 101
12838 DSB, DMB, ISB are data store barrier, data memory barrier and
12839 instruction store barrier, respectively, where
12841 L == 0, op0 == 0, op1 = 011, CRn = 0011, Rt = 11111,
12842 op2 : DSB ==> 100, DMB ==> 101, ISB ==> 110
12843 CRm<3:2> ==> domain, CRm<1:0> ==> types,
12844 domain : 00 ==> OuterShareable, 01 ==> Nonshareable,
12845 10 ==> InerShareable, 11 ==> FullSystem
12846 types : 01 ==> Reads, 10 ==> Writes,
12847 11 ==> All, 00 ==> All (domain == FullSystem). */
12849 unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
12850 uint32_t l_op0_op1_crn = uimm (aarch64_get_instr (cpu), 21, 12);
12852 NYI_assert (31, 22, 0x354);
12854 switch (l_op0_op1_crn)
12859 /* NOP has CRm != 0000 OR. */
12860 /* (CRm == 0000 AND (op2 == 000 OR op2 > 101)). */
12861 uint32_t crm = uimm (aarch64_get_instr (cpu), 11, 8);
12862 uint32_t op2 = uimm (aarch64_get_instr (cpu), 7, 5);
12864 if (crm != 0 || (op2 == 0 || op2 > 5))
12866 /* Actually call nop method so we can reimplement it later. */
12875 uint32_t op2 = uimm (aarch64_get_instr (cpu), 7, 5);
12880 case 4: dsb (cpu); return;
12881 case 5: dmb (cpu); return;
12882 case 6: isb (cpu); return;
12884 default: HALT_UNALLOC;
12889 /* MRS Wt, sys-reg. */
12895 /* MRS Xt, sys-reg. */
12900 /* DC <type>, x<n>. */
12905 /* if (uimm (aarch64_get_instr (cpu), 21, 20) == 0x1)
12906 MRS Xt, sys-reg. */
12913 dexBr (sim_cpu *cpu)
12915 /* uint32_t group = dispatchGroup (aarch64_get_instr (cpu));
12916 assert group == GROUP_BREXSYS_1010 || group == GROUP_BREXSYS_1011
12917 bits [31,29] of a BrExSys are the secondary dispatch vector. */
12918 uint32_t group2 = dispatchBrExSys (aarch64_get_instr (cpu));
12923 return dexBranchImmediate (cpu);
12925 case BR_IMMCMP_001:
12926 /* Compare has bit 25 clear while test has it set. */
12927 if (!uimm (aarch64_get_instr (cpu), 25, 25))
12928 dexCompareBranchImmediate (cpu);
12930 dexTestBranchImmediate (cpu);
12933 case BR_IMMCOND_010:
12934 /* This is a conditional branch if bit 25 is clear otherwise
12936 if (!uimm (aarch64_get_instr (cpu), 25, 25))
12937 dexCondBranchImmediate (cpu);
12942 case BR_UNALLOC_011:
12946 dexBranchImmediate (cpu);
12949 case BR_IMMCMP_101:
12950 /* Compare has bit 25 clear while test has it set. */
12951 if (!uimm (aarch64_get_instr (cpu), 25, 25))
12952 dexCompareBranchImmediate (cpu);
12954 dexTestBranchImmediate (cpu);
12958 /* Unconditional branch reg has bit 25 set. */
12959 if (uimm (aarch64_get_instr (cpu), 25, 25))
12960 dexBranchRegister (cpu);
12962 /* This includes both Excpn Gen, System and unalloc operations.
12963 We need to decode the Excpn Gen operation BRK so we can plant
12964 debugger entry points.
12965 Excpn Gen operations have aarch64_get_instr (cpu)[24] = 0.
12966 we need to decode at least one of the System operations NOP
12967 which is an alias for HINT #0.
12968 System operations have aarch64_get_instr (cpu)[24,22] = 100. */
12969 else if (uimm (aarch64_get_instr (cpu), 24, 24) == 0)
12972 else if (uimm (aarch64_get_instr (cpu), 24, 22) == 4)
12980 case BR_UNALLOC_111:
12984 /* Should never reach here. */
12990 aarch64_decode_and_execute (sim_cpu *cpu, uint64_t pc)
12992 /* We need to check if gdb wants an in here. */
12993 /* checkBreak (cpu);. */
12995 uint64_t group = dispatchGroup (aarch64_get_instr (cpu));
12999 case GROUP_PSEUDO_0000: dexPseudo (cpu); break;
13000 case GROUP_LDST_0100: dexLdSt (cpu); break;
13001 case GROUP_DPREG_0101: dexDPReg (cpu); break;
13002 case GROUP_LDST_0110: dexLdSt (cpu); break;
13003 case GROUP_ADVSIMD_0111: dexAdvSIMD0 (cpu); break;
13004 case GROUP_DPIMM_1000: dexDPImm (cpu); break;
13005 case GROUP_DPIMM_1001: dexDPImm (cpu); break;
13006 case GROUP_BREXSYS_1010: dexBr (cpu); break;
13007 case GROUP_BREXSYS_1011: dexBr (cpu); break;
13008 case GROUP_LDST_1100: dexLdSt (cpu); break;
13009 case GROUP_DPREG_1101: dexDPReg (cpu); break;
13010 case GROUP_LDST_1110: dexLdSt (cpu); break;
13011 case GROUP_ADVSIMD_1111: dexAdvSIMD1 (cpu); break;
13013 case GROUP_UNALLOC_0001:
13014 case GROUP_UNALLOC_0010:
13015 case GROUP_UNALLOC_0011:
13019 /* Should never reach here. */
13025 aarch64_step (sim_cpu *cpu)
13027 uint64_t pc = aarch64_get_PC (cpu);
13029 if (pc == TOP_LEVEL_RETURN_PC)
13032 aarch64_set_next_PC (cpu, pc + 4);
13033 aarch64_get_instr (cpu) = aarch64_get_mem_u32 (cpu, pc);
13035 if (TRACE_INSN_P (cpu))
13038 TRACE_INSN (cpu, " pc = %" PRIx64 " ", pc);
13040 TRACE_INSN (cpu, " pc = %" PRIx64 " instr = %x", pc,
13041 aarch64_get_instr (cpu));
13044 sim_io_eprintf (CPU_STATE (cpu), " %" PRIx64 " ", pc);
13047 aarch64_print_insn (CPU_STATE (cpu), pc);
13049 aarch64_decode_and_execute (cpu, pc);
13055 aarch64_run (SIM_DESC sd)
13057 sim_cpu *cpu = STATE_CPU (sd, 0);
13059 while (aarch64_step (cpu))
13060 aarch64_update_PC (cpu);
13062 sim_engine_halt (sd, NULL, NULL, aarch64_get_PC (cpu),
13063 sim_exited, aarch64_get_reg_s32 (cpu, R0, SP_OK));
13067 aarch64_init (sim_cpu *cpu, uint64_t pc)
13069 uint64_t sp = aarch64_get_stack_start (cpu);
13071 /* Install SP, FP and PC and set LR to -20
13072 so we can detect a top-level return. */
13073 aarch64_set_reg_u64 (cpu, SP, SP_OK, sp);
13074 aarch64_set_reg_u64 (cpu, FP, SP_OK, sp);
13075 aarch64_set_reg_u64 (cpu, LR, SP_OK, TOP_LEVEL_RETURN_PC);
13076 aarch64_set_next_PC (cpu, pc);
13077 aarch64_update_PC (cpu);
13078 aarch64_init_LIT_table ();