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
));
4111 #define MAX(A,B) ((A) > (B) ? (A) : (B))
4112 #define MIN(A,B) ((A) < (B) ? (A) : (B))
4115 do_vec_maxv (sim_cpu
*cpu
)
4118 instr[30] = half(0)/full(1)
4119 instr[29] = signed (0)/unsigned(1)
4120 instr[28,24] = 0 1110
4121 instr[23,22] = size: byte(00), half(01), word (10)
4123 instr[20,17] = 1 000
4124 instr[16] = max(0)/min(1)
4125 instr[15,10] = 1010 10
4126 instr[9,5] = V source
4127 instr[4.0] = R dest. */
4129 unsigned vs
= uimm (aarch64_get_instr (cpu
), 9, 5);
4130 unsigned rd
= uimm (aarch64_get_instr (cpu
), 4, 0);
4131 unsigned full
= uimm (aarch64_get_instr (cpu
), 30, 30);
4134 NYI_assert (28, 24, 0x0E);
4135 NYI_assert (21, 21, 1);
4136 NYI_assert (20, 17, 8);
4137 NYI_assert (15, 10, 0x2A);
4139 switch ((uimm (aarch64_get_instr (cpu
), 29, 29) << 1)
4140 | uimm (aarch64_get_instr (cpu
), 16, 16))
4142 case 0: /* SMAXV. */
4145 switch (uimm (aarch64_get_instr (cpu
), 23, 22))
4148 smax
= aarch64_get_vec_s8 (cpu
, vs
, 0);
4149 for (i
= 1; i
< (full
? 16 : 8); i
++)
4150 smax
= MAX (smax
, aarch64_get_vec_s8 (cpu
, vs
, i
));
4153 smax
= aarch64_get_vec_s16 (cpu
, vs
, 0);
4154 for (i
= 1; i
< (full
? 8 : 4); i
++)
4155 smax
= MAX (smax
, aarch64_get_vec_s16 (cpu
, vs
, i
));
4158 smax
= aarch64_get_vec_s32 (cpu
, vs
, 0);
4159 for (i
= 1; i
< (full
? 4 : 2); i
++)
4160 smax
= MAX (smax
, aarch64_get_vec_s32 (cpu
, vs
, i
));
4166 aarch64_set_reg_s64 (cpu
, rd
, NO_SP
, smax
);
4170 case 1: /* SMINV. */
4173 switch (uimm (aarch64_get_instr (cpu
), 23, 22))
4176 smin
= aarch64_get_vec_s8 (cpu
, vs
, 0);
4177 for (i
= 1; i
< (full
? 16 : 8); i
++)
4178 smin
= MIN (smin
, aarch64_get_vec_s8 (cpu
, vs
, i
));
4181 smin
= aarch64_get_vec_s16 (cpu
, vs
, 0);
4182 for (i
= 1; i
< (full
? 8 : 4); i
++)
4183 smin
= MIN (smin
, aarch64_get_vec_s16 (cpu
, vs
, i
));
4186 smin
= aarch64_get_vec_s32 (cpu
, vs
, 0);
4187 for (i
= 1; i
< (full
? 4 : 2); i
++)
4188 smin
= MIN (smin
, aarch64_get_vec_s32 (cpu
, vs
, i
));
4194 aarch64_set_reg_s64 (cpu
, rd
, NO_SP
, smin
);
4198 case 2: /* UMAXV. */
4201 switch (uimm (aarch64_get_instr (cpu
), 23, 22))
4204 umax
= aarch64_get_vec_u8 (cpu
, vs
, 0);
4205 for (i
= 1; i
< (full
? 16 : 8); i
++)
4206 umax
= MAX (umax
, aarch64_get_vec_u8 (cpu
, vs
, i
));
4209 umax
= aarch64_get_vec_u16 (cpu
, vs
, 0);
4210 for (i
= 1; i
< (full
? 8 : 4); i
++)
4211 umax
= MAX (umax
, aarch64_get_vec_u16 (cpu
, vs
, i
));
4214 umax
= aarch64_get_vec_u32 (cpu
, vs
, 0);
4215 for (i
= 1; i
< (full
? 4 : 2); i
++)
4216 umax
= MAX (umax
, aarch64_get_vec_u32 (cpu
, vs
, i
));
4222 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, umax
);
4226 case 3: /* UMINV. */
4229 switch (uimm (aarch64_get_instr (cpu
), 23, 22))
4232 umin
= aarch64_get_vec_u8 (cpu
, vs
, 0);
4233 for (i
= 1; i
< (full
? 16 : 8); i
++)
4234 umin
= MIN (umin
, aarch64_get_vec_u8 (cpu
, vs
, i
));
4237 umin
= aarch64_get_vec_u16 (cpu
, vs
, 0);
4238 for (i
= 1; i
< (full
? 8 : 4); i
++)
4239 umin
= MIN (umin
, aarch64_get_vec_u16 (cpu
, vs
, i
));
4242 umin
= aarch64_get_vec_u32 (cpu
, vs
, 0);
4243 for (i
= 1; i
< (full
? 4 : 2); i
++)
4244 umin
= MIN (umin
, aarch64_get_vec_u32 (cpu
, vs
, i
));
4250 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, umin
);
4260 do_vec_fminmaxV (sim_cpu
*cpu
)
4262 /* instr[31,24] = 0110 1110
4263 instr[23] = max(0)/min(1)
4264 instr[22,14] = 011 0000 11
4265 instr[13,12] = nm(00)/normal(11)
4267 instr[9,5] = V source
4268 instr[4.0] = R dest. */
4270 unsigned vs
= uimm (aarch64_get_instr (cpu
), 9, 5);
4271 unsigned rd
= uimm (aarch64_get_instr (cpu
), 4, 0);
4273 float res
= aarch64_get_vec_float (cpu
, vs
, 0);
4275 NYI_assert (31, 24, 0x6E);
4276 NYI_assert (22, 14, 0x0C3);
4277 NYI_assert (11, 10, 2);
4279 if (uimm (aarch64_get_instr (cpu
), 23, 23))
4281 switch (uimm (aarch64_get_instr (cpu
), 13, 12))
4283 case 0: /* FMNINNMV. */
4284 for (i
= 1; i
< 4; i
++)
4285 res
= fminnm (res
, aarch64_get_vec_float (cpu
, vs
, i
));
4288 case 3: /* FMINV. */
4289 for (i
= 1; i
< 4; i
++)
4290 res
= MIN (res
, aarch64_get_vec_float (cpu
, vs
, i
));
4299 switch (uimm (aarch64_get_instr (cpu
), 13, 12))
4301 case 0: /* FMNAXNMV. */
4302 for (i
= 1; i
< 4; i
++)
4303 res
= fmaxnm (res
, aarch64_get_vec_float (cpu
, vs
, i
));
4306 case 3: /* FMAXV. */
4307 for (i
= 1; i
< 4; i
++)
4308 res
= MAX (res
, aarch64_get_vec_float (cpu
, vs
, i
));
4316 aarch64_set_FP_float (cpu
, rd
, res
);
4320 do_vec_Fminmax (sim_cpu
*cpu
)
4323 instr[30] = half(0)/full(1)
4324 instr[29,24] = 00 1110
4325 instr[23] = max(0)/min(1)
4326 instr[22] = float(0)/double(1)
4330 instr[13,12] = nm(00)/normal(11)
4335 unsigned vm
= uimm (aarch64_get_instr (cpu
), 20, 16);
4336 unsigned vn
= uimm (aarch64_get_instr (cpu
), 9, 5);
4337 unsigned vd
= uimm (aarch64_get_instr (cpu
), 4, 0);
4338 unsigned full
= uimm (aarch64_get_instr (cpu
), 30, 30);
4339 unsigned min
= uimm (aarch64_get_instr (cpu
), 23, 23);
4342 NYI_assert (29, 24, 0x0E);
4343 NYI_assert (21, 21, 1);
4344 NYI_assert (15, 14, 3);
4345 NYI_assert (11, 10, 1);
4347 if (uimm (aarch64_get_instr (cpu
), 22, 22))
4349 double (* func
)(double, double);
4354 if (uimm (aarch64_get_instr (cpu
), 13, 12) == 0)
4355 func
= min
? dminnm
: dmaxnm
;
4356 else if (uimm (aarch64_get_instr (cpu
), 13, 12) == 3)
4357 func
= min
? fmin
: fmax
;
4361 for (i
= 0; i
< 2; i
++)
4362 aarch64_set_vec_double (cpu
, vd
, i
,
4363 func (aarch64_get_vec_double (cpu
, vn
, i
),
4364 aarch64_get_vec_double (cpu
, vm
, i
)));
4368 float (* func
)(float, float);
4370 if (uimm (aarch64_get_instr (cpu
), 13, 12) == 0)
4371 func
= min
? fminnm
: fmaxnm
;
4372 else if (uimm (aarch64_get_instr (cpu
), 13, 12) == 3)
4373 func
= min
? fminf
: fmaxf
;
4377 for (i
= 0; i
< (full
? 4 : 2); i
++)
4378 aarch64_set_vec_float (cpu
, vd
, i
,
4379 func (aarch64_get_vec_float (cpu
, vn
, i
),
4380 aarch64_get_vec_float (cpu
, vm
, i
)));
4385 do_vec_SCVTF (sim_cpu
*cpu
)
4389 instr[29,23] = 00 1110 0
4390 instr[22] = float(0)/double(1)
4391 instr[21,10] = 10 0001 1101 10
4395 unsigned vn
= uimm (aarch64_get_instr (cpu
), 9, 5);
4396 unsigned vd
= uimm (aarch64_get_instr (cpu
), 4, 0);
4397 unsigned full
= uimm (aarch64_get_instr (cpu
), 30, 30);
4398 unsigned size
= uimm (aarch64_get_instr (cpu
), 22, 22);
4401 NYI_assert (29, 23, 0x1C);
4402 NYI_assert (21, 10, 0x876);
4409 for (i
= 0; i
< 2; i
++)
4411 double val
= (double) aarch64_get_vec_u64 (cpu
, vn
, i
);
4412 aarch64_set_vec_double (cpu
, vd
, i
, val
);
4417 for (i
= 0; i
< (full
? 4 : 2); i
++)
4419 float val
= (float) aarch64_get_vec_u32 (cpu
, vn
, i
);
4420 aarch64_set_vec_float (cpu
, vd
, i
, val
);
4425 #define VEC_CMP(SOURCE, CMP) \
4431 for (i = 0; i < (full ? 16 : 8); i++) \
4432 aarch64_set_vec_u8 (cpu, vd, i, \
4433 aarch64_get_vec_##SOURCE##8 (cpu, vn, i) \
4435 aarch64_get_vec_##SOURCE##8 (cpu, vm, i) \
4439 for (i = 0; i < (full ? 8 : 4); i++) \
4440 aarch64_set_vec_u16 (cpu, vd, i, \
4441 aarch64_get_vec_##SOURCE##16 (cpu, vn, i) \
4443 aarch64_get_vec_##SOURCE##16 (cpu, vm, i) \
4447 for (i = 0; i < (full ? 4 : 2); i++) \
4448 aarch64_set_vec_u32 (cpu, vd, i, \
4449 aarch64_get_vec_##SOURCE##32 (cpu, vn, i) \
4451 aarch64_get_vec_##SOURCE##32 (cpu, vm, i) \
4457 for (i = 0; i < 2; i++) \
4458 aarch64_set_vec_u64 (cpu, vd, i, \
4459 aarch64_get_vec_##SOURCE##64 (cpu, vn, i) \
4461 aarch64_get_vec_##SOURCE##64 (cpu, vm, i) \
4470 #define VEC_CMP0(SOURCE, CMP) \
4476 for (i = 0; i < (full ? 16 : 8); i++) \
4477 aarch64_set_vec_u8 (cpu, vd, i, \
4478 aarch64_get_vec_##SOURCE##8 (cpu, vn, i) \
4482 for (i = 0; i < (full ? 8 : 4); i++) \
4483 aarch64_set_vec_u16 (cpu, vd, i, \
4484 aarch64_get_vec_##SOURCE##16 (cpu, vn, i) \
4488 for (i = 0; i < (full ? 4 : 2); i++) \
4489 aarch64_set_vec_u32 (cpu, vd, i, \
4490 aarch64_get_vec_##SOURCE##32 (cpu, vn, i) \
4496 for (i = 0; i < 2; i++) \
4497 aarch64_set_vec_u64 (cpu, vd, i, \
4498 aarch64_get_vec_##SOURCE##64 (cpu, vn, i) \
4499 CMP 0 ? -1ULL : 0); \
4507 #define VEC_FCMP0(CMP) \
4512 if (uimm (aarch64_get_instr (cpu), 22, 22)) \
4516 for (i = 0; i < 2; i++) \
4517 aarch64_set_vec_u64 (cpu, vd, i, \
4518 aarch64_get_vec_double (cpu, vn, i) \
4519 CMP 0.0 ? -1 : 0); \
4523 for (i = 0; i < (full ? 4 : 2); i++) \
4524 aarch64_set_vec_u32 (cpu, vd, i, \
4525 aarch64_get_vec_float (cpu, vn, i) \
4526 CMP 0.0 ? -1 : 0); \
4532 #define VEC_FCMP(CMP) \
4535 if (uimm (aarch64_get_instr (cpu), 22, 22)) \
4539 for (i = 0; i < 2; i++) \
4540 aarch64_set_vec_u64 (cpu, vd, i, \
4541 aarch64_get_vec_double (cpu, vn, i) \
4543 aarch64_get_vec_double (cpu, vm, i) \
4548 for (i = 0; i < (full ? 4 : 2); i++) \
4549 aarch64_set_vec_u32 (cpu, vd, i, \
4550 aarch64_get_vec_float (cpu, vn, i) \
4552 aarch64_get_vec_float (cpu, vm, i) \
4560 do_vec_compare (sim_cpu
*cpu
)
4563 instr[30] = half(0)/full(1)
4564 instr[29] = part-of-comparison-type
4565 instr[28,24] = 0 1110
4566 instr[23,22] = size of integer compares: byte(00), half(01), word (10), long (11)
4567 type of float compares: single (-0) / double (-1)
4569 instr[20,16] = Vm or 00000 (compare vs 0)
4570 instr[15,10] = part-of-comparison-type
4574 int full
= uimm (aarch64_get_instr (cpu
), 30, 30);
4575 int size
= uimm (aarch64_get_instr (cpu
), 23, 22);
4576 unsigned vm
= uimm (aarch64_get_instr (cpu
), 20, 16);
4577 unsigned vn
= uimm (aarch64_get_instr (cpu
), 9, 5);
4578 unsigned vd
= uimm (aarch64_get_instr (cpu
), 4, 0);
4581 NYI_assert (28, 24, 0x0E);
4582 NYI_assert (21, 21, 1);
4584 if ((uimm (aarch64_get_instr (cpu
), 11, 11)
4585 && uimm (aarch64_get_instr (cpu
), 14, 14))
4586 || ((uimm (aarch64_get_instr (cpu
), 11, 11) == 0
4587 && uimm (aarch64_get_instr (cpu
), 10, 10) == 0)))
4589 /* A compare vs 0. */
4592 if (uimm (aarch64_get_instr (cpu
), 15, 10) == 0x2A)
4594 else if (uimm (aarch64_get_instr (cpu
), 15, 10) == 0x32
4595 || uimm (aarch64_get_instr (cpu
), 15, 10) == 0x3E)
4596 do_vec_fminmaxV (cpu
);
4597 else if (uimm (aarch64_get_instr (cpu
), 29, 23) == 0x1C
4598 && uimm (aarch64_get_instr (cpu
), 21, 10) == 0x876)
4606 if (uimm (aarch64_get_instr (cpu
), 14, 14))
4608 /* A floating point compare. */
4609 unsigned decode
= (uimm (aarch64_get_instr (cpu
), 29, 29) << 5)
4610 | (uimm (aarch64_get_instr (cpu
), 23, 23) << 4)
4611 | uimm (aarch64_get_instr (cpu
), 13, 10);
4613 NYI_assert (15, 15, 1);
4617 case /* 0b010010: GT#0 */ 0x12: VEC_FCMP0 (>);
4618 case /* 0b110010: GE#0 */ 0x32: VEC_FCMP0 (>=);
4619 case /* 0b010110: EQ#0 */ 0x16: VEC_FCMP0 (==);
4620 case /* 0b110110: LE#0 */ 0x36: VEC_FCMP0 (<=);
4621 case /* 0b011010: LT#0 */ 0x1A: VEC_FCMP0 (<);
4622 case /* 0b111001: GT */ 0x39: VEC_FCMP (>);
4623 case /* 0b101001: GE */ 0x29: VEC_FCMP (>=);
4624 case /* 0b001001: EQ */ 0x09: VEC_FCMP (==);
4632 unsigned decode
= (uimm (aarch64_get_instr (cpu
), 29, 29) << 6)
4633 | uimm (aarch64_get_instr (cpu
), 15, 10);
4637 case 0x0D: /* 0001101 GT */ VEC_CMP (s
, > );
4638 case 0x0F: /* 0001111 GE */ VEC_CMP (s
, >= );
4639 case 0x22: /* 0100010 GT #0 */ VEC_CMP0 (s
, > );
4640 case 0x26: /* 0100110 EQ #0 */ VEC_CMP0 (s
, == );
4641 case 0x2A: /* 0101010 LT #0 */ VEC_CMP0 (s
, < );
4642 case 0x4D: /* 1001101 HI */ VEC_CMP (u
, > );
4643 case 0x4F: /* 1001111 HS */ VEC_CMP (u
, >= );
4644 case 0x62: /* 1100010 GE #0 */ VEC_CMP0 (s
, >= );
4645 case 0x63: /* 1100011 EQ */ VEC_CMP (u
, == );
4646 case 0x66: /* 1100110 LE #0 */ VEC_CMP0 (s
, <= );
4656 do_vec_SSHL (sim_cpu
*cpu
)
4659 instr[30] = first part (0)/ second part (1)
4660 instr[29,24] = 00 1110
4661 instr[23,22] = size: byte(00), half(01), word (10), long (11)
4664 instr[15,10] = 0100 01
4668 unsigned full
= uimm (aarch64_get_instr (cpu
), 30, 30);
4669 unsigned vm
= uimm (aarch64_get_instr (cpu
), 20, 16);
4670 unsigned vn
= uimm (aarch64_get_instr (cpu
), 9, 5);
4671 unsigned vd
= uimm (aarch64_get_instr (cpu
), 4, 0);
4674 NYI_assert (29, 24, 0x0E);
4675 NYI_assert (21, 21, 1);
4676 NYI_assert (15, 10, 0x11);
4678 /* FIXME: What is a signed shift left in this context ?. */
4680 switch (uimm (aarch64_get_instr (cpu
), 23, 22))
4683 for (i
= 0; i
< (full
? 16 : 8); i
++)
4684 aarch64_set_vec_s8 (cpu
, vd
, i
, aarch64_get_vec_s8 (cpu
, vn
, i
)
4685 << aarch64_get_vec_s8 (cpu
, vm
, i
));
4689 for (i
= 0; i
< (full
? 8 : 4); i
++)
4690 aarch64_set_vec_s16 (cpu
, vd
, i
, aarch64_get_vec_s16 (cpu
, vn
, i
)
4691 << aarch64_get_vec_s16 (cpu
, vm
, i
));
4695 for (i
= 0; i
< (full
? 4 : 2); i
++)
4696 aarch64_set_vec_s32 (cpu
, vd
, i
, aarch64_get_vec_s32 (cpu
, vn
, i
)
4697 << aarch64_get_vec_s32 (cpu
, vm
, i
));
4703 for (i
= 0; i
< 2; i
++)
4704 aarch64_set_vec_s64 (cpu
, vd
, i
, aarch64_get_vec_s64 (cpu
, vn
, i
)
4705 << aarch64_get_vec_s64 (cpu
, vm
, i
));
4714 do_vec_USHL (sim_cpu
*cpu
)
4717 instr[30] = first part (0)/ second part (1)
4718 instr[29,24] = 10 1110
4719 instr[23,22] = size: byte(00), half(01), word (10), long (11)
4722 instr[15,10] = 0100 01
4726 unsigned full
= uimm (aarch64_get_instr (cpu
), 30, 30);
4727 unsigned vm
= uimm (aarch64_get_instr (cpu
), 20, 16);
4728 unsigned vn
= uimm (aarch64_get_instr (cpu
), 9, 5);
4729 unsigned vd
= uimm (aarch64_get_instr (cpu
), 4, 0);
4732 NYI_assert (29, 24, 0x2E);
4733 NYI_assert (15, 10, 0x11);
4735 switch (uimm (aarch64_get_instr (cpu
), 23, 22))
4738 for (i
= 0; i
< (full
? 16 : 8); i
++)
4739 aarch64_set_vec_u8 (cpu
, vd
, i
, aarch64_get_vec_u8 (cpu
, vn
, i
)
4740 << aarch64_get_vec_u8 (cpu
, vm
, i
));
4744 for (i
= 0; i
< (full
? 8 : 4); i
++)
4745 aarch64_set_vec_u16 (cpu
, vd
, i
, aarch64_get_vec_u16 (cpu
, vn
, i
)
4746 << aarch64_get_vec_u16 (cpu
, vm
, i
));
4750 for (i
= 0; i
< (full
? 4 : 2); i
++)
4751 aarch64_set_vec_u32 (cpu
, vd
, i
, aarch64_get_vec_u32 (cpu
, vn
, i
)
4752 << aarch64_get_vec_u32 (cpu
, vm
, i
));
4758 for (i
= 0; i
< 2; i
++)
4759 aarch64_set_vec_u64 (cpu
, vd
, i
, aarch64_get_vec_u64 (cpu
, vn
, i
)
4760 << aarch64_get_vec_u64 (cpu
, vm
, i
));
4769 do_vec_FMLA (sim_cpu
*cpu
)
4772 instr[30] = full/half selector
4773 instr[29,23] = 0011100
4774 instr[22] = size: 0=>float, 1=>double
4777 instr[15,10] = 1100 11
4781 unsigned vm
= uimm (aarch64_get_instr (cpu
), 20, 16);
4782 unsigned vn
= uimm (aarch64_get_instr (cpu
), 9, 5);
4783 unsigned vd
= uimm (aarch64_get_instr (cpu
), 4, 0);
4785 int full
= uimm (aarch64_get_instr (cpu
), 30, 30);
4787 NYI_assert (29, 23, 0x1C);
4788 NYI_assert (21, 21, 1);
4789 NYI_assert (15, 10, 0x33);
4791 if (uimm (aarch64_get_instr (cpu
), 22, 22))
4795 for (i
= 0; i
< 2; i
++)
4796 aarch64_set_vec_double (cpu
, vd
, i
,
4797 aarch64_get_vec_double (cpu
, vn
, i
) *
4798 aarch64_get_vec_double (cpu
, vm
, i
) +
4799 aarch64_get_vec_double (cpu
, vd
, i
));
4803 for (i
= 0; i
< (full
? 4 : 2); i
++)
4804 aarch64_set_vec_float (cpu
, vd
, i
,
4805 aarch64_get_vec_float (cpu
, vn
, i
) *
4806 aarch64_get_vec_float (cpu
, vm
, i
) +
4807 aarch64_get_vec_float (cpu
, vd
, i
));
4812 do_vec_max (sim_cpu
*cpu
)
4815 instr[30] = full/half selector
4816 instr[29] = SMAX (0) / UMAX (1)
4817 instr[28,24] = 0 1110
4818 instr[23,22] = size: 00=> 8-bit, 01=> 16-bit, 10=> 32-bit
4821 instr[15,10] = 0110 01
4825 unsigned vm
= uimm (aarch64_get_instr (cpu
), 20, 16);
4826 unsigned vn
= uimm (aarch64_get_instr (cpu
), 9, 5);
4827 unsigned vd
= uimm (aarch64_get_instr (cpu
), 4, 0);
4829 int full
= uimm (aarch64_get_instr (cpu
), 30, 30);
4831 NYI_assert (28, 24, 0x0E);
4832 NYI_assert (21, 21, 1);
4833 NYI_assert (15, 10, 0x19);
4835 if (uimm (aarch64_get_instr (cpu
), 29, 29))
4837 switch (uimm (aarch64_get_instr (cpu
), 23, 22))
4840 for (i
= 0; i
< (full
? 16 : 8); i
++)
4841 aarch64_set_vec_u8 (cpu
, vd
, i
,
4842 aarch64_get_vec_u8 (cpu
, vn
, i
)
4843 > aarch64_get_vec_u8 (cpu
, vm
, i
)
4844 ? aarch64_get_vec_u8 (cpu
, vn
, i
)
4845 : aarch64_get_vec_u8 (cpu
, vm
, i
));
4849 for (i
= 0; i
< (full
? 8 : 4); i
++)
4850 aarch64_set_vec_u16 (cpu
, vd
, i
,
4851 aarch64_get_vec_u16 (cpu
, vn
, i
)
4852 > aarch64_get_vec_u16 (cpu
, vm
, i
)
4853 ? aarch64_get_vec_u16 (cpu
, vn
, i
)
4854 : aarch64_get_vec_u16 (cpu
, vm
, i
));
4858 for (i
= 0; i
< (full
? 4 : 2); i
++)
4859 aarch64_set_vec_u32 (cpu
, vd
, i
,
4860 aarch64_get_vec_u32 (cpu
, vn
, i
)
4861 > aarch64_get_vec_u32 (cpu
, vm
, i
)
4862 ? aarch64_get_vec_u32 (cpu
, vn
, i
)
4863 : aarch64_get_vec_u32 (cpu
, vm
, i
));
4873 switch (uimm (aarch64_get_instr (cpu
), 23, 22))
4876 for (i
= 0; i
< (full
? 16 : 8); i
++)
4877 aarch64_set_vec_s8 (cpu
, vd
, i
,
4878 aarch64_get_vec_s8 (cpu
, vn
, i
)
4879 > aarch64_get_vec_s8 (cpu
, vm
, i
)
4880 ? aarch64_get_vec_s8 (cpu
, vn
, i
)
4881 : aarch64_get_vec_s8 (cpu
, vm
, i
));
4885 for (i
= 0; i
< (full
? 8 : 4); i
++)
4886 aarch64_set_vec_s16 (cpu
, vd
, i
,
4887 aarch64_get_vec_s16 (cpu
, vn
, i
)
4888 > aarch64_get_vec_s16 (cpu
, vm
, i
)
4889 ? aarch64_get_vec_s16 (cpu
, vn
, i
)
4890 : aarch64_get_vec_s16 (cpu
, vm
, i
));
4894 for (i
= 0; i
< (full
? 4 : 2); i
++)
4895 aarch64_set_vec_s32 (cpu
, vd
, i
,
4896 aarch64_get_vec_s32 (cpu
, vn
, i
)
4897 > aarch64_get_vec_s32 (cpu
, vm
, i
)
4898 ? aarch64_get_vec_s32 (cpu
, vn
, i
)
4899 : aarch64_get_vec_s32 (cpu
, vm
, i
));
4910 do_vec_min (sim_cpu
*cpu
)
4913 instr[30] = full/half selector
4914 instr[29] = SMIN (0) / UMIN (1)
4915 instr[28,24] = 0 1110
4916 instr[23,22] = size: 00=> 8-bit, 01=> 16-bit, 10=> 32-bit
4919 instr[15,10] = 0110 11
4923 unsigned vm
= uimm (aarch64_get_instr (cpu
), 20, 16);
4924 unsigned vn
= uimm (aarch64_get_instr (cpu
), 9, 5);
4925 unsigned vd
= uimm (aarch64_get_instr (cpu
), 4, 0);
4927 int full
= uimm (aarch64_get_instr (cpu
), 30, 30);
4929 NYI_assert (28, 24, 0x0E);
4930 NYI_assert (21, 21, 1);
4931 NYI_assert (15, 10, 0x1B);
4933 if (uimm (aarch64_get_instr (cpu
), 29, 29))
4935 switch (uimm (aarch64_get_instr (cpu
), 23, 22))
4938 for (i
= 0; i
< (full
? 16 : 8); i
++)
4939 aarch64_set_vec_u8 (cpu
, vd
, i
,
4940 aarch64_get_vec_u8 (cpu
, vn
, i
)
4941 < aarch64_get_vec_u8 (cpu
, vm
, i
)
4942 ? aarch64_get_vec_u8 (cpu
, vn
, i
)
4943 : aarch64_get_vec_u8 (cpu
, vm
, i
));
4947 for (i
= 0; i
< (full
? 8 : 4); i
++)
4948 aarch64_set_vec_u16 (cpu
, vd
, i
,
4949 aarch64_get_vec_u16 (cpu
, vn
, i
)
4950 < aarch64_get_vec_u16 (cpu
, vm
, i
)
4951 ? aarch64_get_vec_u16 (cpu
, vn
, i
)
4952 : aarch64_get_vec_u16 (cpu
, vm
, i
));
4956 for (i
= 0; i
< (full
? 4 : 2); i
++)
4957 aarch64_set_vec_u32 (cpu
, vd
, i
,
4958 aarch64_get_vec_u32 (cpu
, vn
, i
)
4959 < aarch64_get_vec_u32 (cpu
, vm
, i
)
4960 ? aarch64_get_vec_u32 (cpu
, vn
, i
)
4961 : aarch64_get_vec_u32 (cpu
, vm
, i
));
4971 switch (uimm (aarch64_get_instr (cpu
), 23, 22))
4974 for (i
= 0; i
< (full
? 16 : 8); i
++)
4975 aarch64_set_vec_s8 (cpu
, vd
, i
,
4976 aarch64_get_vec_s8 (cpu
, vn
, i
)
4977 < aarch64_get_vec_s8 (cpu
, vm
, i
)
4978 ? aarch64_get_vec_s8 (cpu
, vn
, i
)
4979 : aarch64_get_vec_s8 (cpu
, vm
, i
));
4983 for (i
= 0; i
< (full
? 8 : 4); i
++)
4984 aarch64_set_vec_s16 (cpu
, vd
, i
,
4985 aarch64_get_vec_s16 (cpu
, vn
, i
)
4986 < aarch64_get_vec_s16 (cpu
, vm
, i
)
4987 ? aarch64_get_vec_s16 (cpu
, vn
, i
)
4988 : aarch64_get_vec_s16 (cpu
, vm
, i
));
4992 for (i
= 0; i
< (full
? 4 : 2); i
++)
4993 aarch64_set_vec_s32 (cpu
, vd
, i
,
4994 aarch64_get_vec_s32 (cpu
, vn
, i
)
4995 < aarch64_get_vec_s32 (cpu
, vm
, i
)
4996 ? aarch64_get_vec_s32 (cpu
, vn
, i
)
4997 : aarch64_get_vec_s32 (cpu
, vm
, i
));
5008 do_vec_sub_long (sim_cpu
*cpu
)
5011 instr[30] = lower (0) / upper (1)
5012 instr[29] = signed (0) / unsigned (1)
5013 instr[28,24] = 0 1110
5014 instr[23,22] = size: bytes (00), half (01), word (10)
5017 instr[15,10] = 0010 00
5019 instr[4,0] = V dest. */
5021 unsigned size
= uimm (aarch64_get_instr (cpu
), 23, 22);
5022 unsigned vm
= uimm (aarch64_get_instr (cpu
), 20, 16);
5023 unsigned vn
= uimm (aarch64_get_instr (cpu
), 9, 5);
5024 unsigned vd
= uimm (aarch64_get_instr (cpu
), 4, 0);
5028 NYI_assert (28, 24, 0x0E);
5029 NYI_assert (21, 21, 1);
5030 NYI_assert (15, 10, 0x08);
5035 switch (uimm (aarch64_get_instr (cpu
), 30, 29))
5037 case 2: /* SSUBL2. */
5039 case 0: /* SSUBL. */
5044 for (i
= 0; i
< 8; i
++)
5045 aarch64_set_vec_s16 (cpu
, vd
, i
,
5046 aarch64_get_vec_s8 (cpu
, vn
, i
+ bias
)
5047 - aarch64_get_vec_s8 (cpu
, vm
, i
+ bias
));
5052 for (i
= 0; i
< 4; i
++)
5053 aarch64_set_vec_s32 (cpu
, vd
, i
,
5054 aarch64_get_vec_s16 (cpu
, vn
, i
+ bias
)
5055 - aarch64_get_vec_s16 (cpu
, vm
, i
+ bias
));
5059 for (i
= 0; i
< 2; i
++)
5060 aarch64_set_vec_s64 (cpu
, vd
, i
,
5061 aarch64_get_vec_s32 (cpu
, vn
, i
+ bias
)
5062 - aarch64_get_vec_s32 (cpu
, vm
, i
+ bias
));
5070 case 3: /* USUBL2. */
5072 case 1: /* USUBL. */
5077 for (i
= 0; i
< 8; i
++)
5078 aarch64_set_vec_u16 (cpu
, vd
, i
,
5079 aarch64_get_vec_u8 (cpu
, vn
, i
+ bias
)
5080 - aarch64_get_vec_u8 (cpu
, vm
, i
+ bias
));
5085 for (i
= 0; i
< 4; i
++)
5086 aarch64_set_vec_u32 (cpu
, vd
, i
,
5087 aarch64_get_vec_u16 (cpu
, vn
, i
+ bias
)
5088 - aarch64_get_vec_u16 (cpu
, vm
, i
+ bias
));
5092 for (i
= 0; i
< 2; i
++)
5093 aarch64_set_vec_u64 (cpu
, vd
, i
,
5094 aarch64_get_vec_u32 (cpu
, vn
, i
+ bias
)
5095 - aarch64_get_vec_u32 (cpu
, vm
, i
+ bias
));
5105 #define DO_ADDP(FN) \
5108 for (i = 0; i < range; i++) \
5110 aarch64_set_vec_##FN (cpu, vd, i, \
5111 aarch64_get_vec_##FN (cpu, vn, i * 2) \
5112 + aarch64_get_vec_##FN (cpu, vn, i * 2 + 1)); \
5113 aarch64_set_vec_##FN (cpu, vd, i + range, \
5114 aarch64_get_vec_##FN (cpu, vm, i * 2) \
5115 + aarch64_get_vec_##FN (cpu, vm, i * 2 + 1)); \
5121 do_vec_ADDP (sim_cpu
*cpu
)
5124 instr[30] = half(0)/full(1)
5125 instr[29,24] = 00 1110
5126 instr[23,22] = size: bytes (00), half (01), word (10), long (11)
5129 instr[15,10] = 1011 11
5131 instr[4,0] = V dest. */
5133 unsigned full
= uimm (aarch64_get_instr (cpu
), 30, 30);
5134 unsigned size
= uimm (aarch64_get_instr (cpu
), 23, 22);
5135 unsigned vm
= uimm (aarch64_get_instr (cpu
), 20, 16);
5136 unsigned vn
= uimm (aarch64_get_instr (cpu
), 9, 5);
5137 unsigned vd
= uimm (aarch64_get_instr (cpu
), 4, 0);
5140 NYI_assert (29, 24, 0x0E);
5141 NYI_assert (21, 21, 1);
5142 NYI_assert (15, 10, 0x2F);
5147 range
= full
? 8 : 4;
5152 range
= full
? 4 : 2;
5157 range
= full
? 2 : 1;
5174 do_vec_UMOV (sim_cpu
*cpu
)
5177 instr[30] = 32-bit(0)/64-bit(1)
5178 instr[29,21] = 00 1110 000
5179 insrt[20,16] = size & index
5180 instr[15,10] = 0011 11
5181 instr[9,5] = V source
5182 instr[4,0] = R dest. */
5184 unsigned vs
= uimm (aarch64_get_instr (cpu
), 9, 5);
5185 unsigned rd
= uimm (aarch64_get_instr (cpu
), 4, 0);
5188 NYI_assert (29, 21, 0x070);
5189 NYI_assert (15, 10, 0x0F);
5191 if (uimm (aarch64_get_instr (cpu
), 16, 16))
5193 /* Byte transfer. */
5194 index
= uimm (aarch64_get_instr (cpu
), 20, 17);
5195 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
,
5196 aarch64_get_vec_u8 (cpu
, vs
, index
));
5198 else if (uimm (aarch64_get_instr (cpu
), 17, 17))
5200 index
= uimm (aarch64_get_instr (cpu
), 20, 18);
5201 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
,
5202 aarch64_get_vec_u16 (cpu
, vs
, index
));
5204 else if (uimm (aarch64_get_instr (cpu
), 18, 18))
5206 index
= uimm (aarch64_get_instr (cpu
), 20, 19);
5207 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
,
5208 aarch64_get_vec_u32 (cpu
, vs
, index
));
5212 if (uimm (aarch64_get_instr (cpu
), 30, 30) != 1)
5215 index
= uimm (aarch64_get_instr (cpu
), 20, 20);
5216 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
,
5217 aarch64_get_vec_u64 (cpu
, vs
, index
));
5222 do_vec_FABS (sim_cpu
*cpu
)
5225 instr[30] = half(0)/full(1)
5226 instr[29,23] = 00 1110 1
5227 instr[22] = float(0)/double(1)
5228 instr[21,16] = 10 0000
5229 instr[15,10] = 1111 10
5233 unsigned vn
= uimm (aarch64_get_instr (cpu
), 9, 5);
5234 unsigned vd
= uimm (aarch64_get_instr (cpu
), 4, 0);
5235 unsigned full
= uimm (aarch64_get_instr (cpu
), 30, 30);
5238 NYI_assert (29, 23, 0x1D);
5239 NYI_assert (21, 10, 0x83E);
5241 if (uimm (aarch64_get_instr (cpu
), 22, 22))
5246 for (i
= 0; i
< 2; i
++)
5247 aarch64_set_vec_double (cpu
, vd
, i
,
5248 fabs (aarch64_get_vec_double (cpu
, vn
, i
)));
5252 for (i
= 0; i
< (full
? 4 : 2); i
++)
5253 aarch64_set_vec_float (cpu
, vd
, i
,
5254 fabsf (aarch64_get_vec_float (cpu
, vn
, i
)));
5259 do_vec_FCVTZS (sim_cpu
*cpu
)
5262 instr[30] = half (0) / all (1)
5263 instr[29,23] = 00 1110 1
5264 instr[22] = single (0) / double (1)
5265 instr[21,10] = 10 0001 1011 10
5269 unsigned rn
= uimm (aarch64_get_instr (cpu
), 9, 5);
5270 unsigned rd
= uimm (aarch64_get_instr (cpu
), 4, 0);
5271 unsigned full
= uimm (aarch64_get_instr (cpu
), 30, 30);
5274 NYI_assert (31, 31, 0);
5275 NYI_assert (29, 23, 0x1D);
5276 NYI_assert (21, 10, 0x86E);
5278 if (uimm (aarch64_get_instr (cpu
), 22, 22))
5283 for (i
= 0; i
< 2; i
++)
5284 aarch64_set_vec_s64 (cpu
, rd
, i
,
5285 (int64_t) aarch64_get_vec_double (cpu
, rn
, i
));
5288 for (i
= 0; i
< (full
? 4 : 2); i
++)
5289 aarch64_set_vec_s32 (cpu
, rd
, i
,
5290 (int32_t) aarch64_get_vec_float (cpu
, rn
, i
));
5294 do_vec_op1 (sim_cpu
*cpu
)
5297 instr[30] = half/full
5298 instr[29,24] = 00 1110
5301 instr[15,10] = sub-opcode
5304 NYI_assert (29, 24, 0x0E);
5306 if (uimm (aarch64_get_instr (cpu
), 21, 21) == 0)
5308 if (uimm (aarch64_get_instr (cpu
), 23, 22) == 0)
5310 if (uimm (aarch64_get_instr (cpu
), 30, 30) == 1
5311 && uimm (aarch64_get_instr (cpu
), 17, 14) == 0
5312 && uimm (aarch64_get_instr (cpu
), 12, 10) == 7)
5313 return do_vec_ins_2 (cpu
);
5315 switch (uimm (aarch64_get_instr (cpu
), 15, 10))
5317 case 0x01: do_vec_DUP_vector_into_vector (cpu
); return;
5318 case 0x03: do_vec_DUP_scalar_into_vector (cpu
); return;
5319 case 0x07: do_vec_INS (cpu
); return;
5320 case 0x0A: do_vec_TRN (cpu
); return;
5323 if (uimm (aarch64_get_instr (cpu
), 17, 16) == 0)
5325 do_vec_MOV_into_scalar (cpu
);
5334 do_vec_TBL (cpu
); return;
5338 do_vec_UZP (cpu
); return;
5342 do_vec_ZIP (cpu
); return;
5349 switch (uimm (aarch64_get_instr (cpu
), 13, 10))
5351 case 0x6: do_vec_UZP (cpu
); return;
5352 case 0xE: do_vec_ZIP (cpu
); return;
5353 case 0xA: do_vec_TRN (cpu
); return;
5354 case 0xF: do_vec_UMOV (cpu
); return;
5359 switch (uimm (aarch64_get_instr (cpu
), 15, 10))
5362 switch (uimm (aarch64_get_instr (cpu
), 23, 21))
5364 case 1: do_vec_AND (cpu
); return;
5365 case 3: do_vec_BIC (cpu
); return;
5366 case 5: do_vec_ORR (cpu
); return;
5367 case 7: do_vec_ORN (cpu
); return;
5371 case 0x08: do_vec_sub_long (cpu
); return;
5372 case 0x0a: do_vec_XTN (cpu
); return;
5373 case 0x11: do_vec_SSHL (cpu
); return;
5374 case 0x19: do_vec_max (cpu
); return;
5375 case 0x1B: do_vec_min (cpu
); return;
5376 case 0x21: do_vec_add (cpu
); return;
5377 case 0x25: do_vec_MLA (cpu
); return;
5378 case 0x27: do_vec_mul (cpu
); return;
5379 case 0x2F: do_vec_ADDP (cpu
); return;
5380 case 0x30: do_vec_mull (cpu
); return;
5381 case 0x33: do_vec_FMLA (cpu
); return;
5382 case 0x35: do_vec_fadd (cpu
); return;
5385 switch (uimm (aarch64_get_instr (cpu
), 20, 16))
5387 case 0x00: do_vec_ABS (cpu
); return;
5388 case 0x01: do_vec_FCVTZS (cpu
); return;
5389 case 0x11: do_vec_ADDV (cpu
); return;
5395 do_vec_Fminmax (cpu
); return;
5407 do_vec_compare (cpu
); return;
5410 do_vec_FABS (cpu
); return;
5418 do_vec_xtl (sim_cpu
*cpu
)
5421 instr[30,29] = SXTL (00), UXTL (01), SXTL2 (10), UXTL2 (11)
5422 instr[28,22] = 0 1111 00
5423 instr[21,16] = size & shift (USHLL, SSHLL, USHLL2, SSHLL2)
5424 instr[15,10] = 1010 01
5425 instr[9,5] = V source
5426 instr[4,0] = V dest. */
5428 unsigned vs
= uimm (aarch64_get_instr (cpu
), 9, 5);
5429 unsigned vd
= uimm (aarch64_get_instr (cpu
), 4, 0);
5430 unsigned i
, shift
, bias
= 0;
5432 NYI_assert (28, 22, 0x3C);
5433 NYI_assert (15, 10, 0x29);
5435 switch (uimm (aarch64_get_instr (cpu
), 30, 29))
5437 case 2: /* SXTL2, SSHLL2. */
5439 case 0: /* SXTL, SSHLL. */
5440 if (uimm (aarch64_get_instr (cpu
), 21, 21))
5442 shift
= uimm (aarch64_get_instr (cpu
), 20, 16);
5444 (cpu
, vd
, 0, aarch64_get_vec_s32 (cpu
, vs
, bias
) << shift
);
5446 (cpu
, vd
, 1, aarch64_get_vec_s32 (cpu
, vs
, bias
+ 1) << shift
);
5448 else if (uimm (aarch64_get_instr (cpu
), 20, 20))
5450 shift
= uimm (aarch64_get_instr (cpu
), 19, 16);
5452 for (i
= 0; i
< 4; i
++)
5454 (cpu
, vd
, i
, aarch64_get_vec_s16 (cpu
, vs
, i
+ bias
) << shift
);
5458 NYI_assert (19, 19, 1);
5460 shift
= uimm (aarch64_get_instr (cpu
), 18, 16);
5462 for (i
= 0; i
< 8; i
++)
5464 (cpu
, vd
, i
, aarch64_get_vec_s8 (cpu
, vs
, i
+ bias
) << shift
);
5468 case 3: /* UXTL2, USHLL2. */
5470 case 1: /* UXTL, USHLL. */
5471 if (uimm (aarch64_get_instr (cpu
), 21, 21))
5473 shift
= uimm (aarch64_get_instr (cpu
), 20, 16);
5475 (cpu
, vd
, 0, aarch64_get_vec_u32 (cpu
, vs
, bias
) << shift
);
5477 (cpu
, vd
, 1, aarch64_get_vec_u32 (cpu
, vs
, bias
+ 1) << shift
);
5479 else if (uimm (aarch64_get_instr (cpu
), 20, 20))
5481 shift
= uimm (aarch64_get_instr (cpu
), 19, 16);
5483 for (i
= 0; i
< 4; i
++)
5485 (cpu
, vd
, i
, aarch64_get_vec_u16 (cpu
, vs
, i
+ bias
) << shift
);
5489 NYI_assert (19, 19, 1);
5491 shift
= uimm (aarch64_get_instr (cpu
), 18, 16);
5493 for (i
= 0; i
< 8; i
++)
5495 (cpu
, vd
, i
, aarch64_get_vec_u8 (cpu
, vs
, i
+ bias
) << shift
);
5505 do_vec_SHL (sim_cpu
*cpu
)
5508 instr [30] = half(0)/full(1)
5509 instr [29,23] = 001 1110
5510 instr [22,16] = size and shift amount
5511 instr [15,10] = 01 0101
5513 instr [4, 0] = Vd. */
5516 int full
= uimm (aarch64_get_instr (cpu
), 30, 30);
5517 unsigned vs
= uimm (aarch64_get_instr (cpu
), 9, 5);
5518 unsigned vd
= uimm (aarch64_get_instr (cpu
), 4, 0);
5521 NYI_assert (29, 23, 0x1E);
5522 NYI_assert (15, 10, 0x15);
5524 if (uimm (aarch64_get_instr (cpu
), 22, 22))
5526 shift
= uimm (aarch64_get_instr (cpu
), 21, 16) - 1;
5531 for (i
= 0; i
< 2; i
++)
5533 uint64_t val
= aarch64_get_vec_u64 (cpu
, vs
, i
);
5534 aarch64_set_vec_u64 (cpu
, vd
, i
, val
<< shift
);
5540 if (uimm (aarch64_get_instr (cpu
), 21, 21))
5542 shift
= uimm (aarch64_get_instr (cpu
), 20, 16) - 1;
5544 for (i
= 0; i
< (full
? 4 : 2); i
++)
5546 uint32_t val
= aarch64_get_vec_u32 (cpu
, vs
, i
);
5547 aarch64_set_vec_u32 (cpu
, vd
, i
, val
<< shift
);
5553 if (uimm (aarch64_get_instr (cpu
), 20, 20))
5555 shift
= uimm (aarch64_get_instr (cpu
), 19, 16) - 1;
5557 for (i
= 0; i
< (full
? 8 : 4); i
++)
5559 uint16_t val
= aarch64_get_vec_u16 (cpu
, vs
, i
);
5560 aarch64_set_vec_u16 (cpu
, vd
, i
, val
<< shift
);
5566 if (uimm (aarch64_get_instr (cpu
), 19, 19) == 0)
5569 shift
= uimm (aarch64_get_instr (cpu
), 18, 16) - 1;
5571 for (i
= 0; i
< (full
? 16 : 8); i
++)
5573 uint8_t val
= aarch64_get_vec_u8 (cpu
, vs
, i
);
5574 aarch64_set_vec_u8 (cpu
, vd
, i
, val
<< shift
);
5579 do_vec_SSHR_USHR (sim_cpu
*cpu
)
5582 instr [30] = half(0)/full(1)
5583 instr [29] = signed(0)/unsigned(1)
5584 instr [28,23] = 01 1110
5585 instr [22,16] = size and shift amount
5586 instr [15,10] = 0000 01
5588 instr [4, 0] = Vd. */
5591 int full
= uimm (aarch64_get_instr (cpu
), 30, 30);
5592 int sign
= uimm (aarch64_get_instr (cpu
), 29, 29);
5593 unsigned vs
= uimm (aarch64_get_instr (cpu
), 9, 5);
5594 unsigned vd
= uimm (aarch64_get_instr (cpu
), 4, 0);
5597 NYI_assert (28, 23, 0x1E);
5598 NYI_assert (15, 10, 0x01);
5600 if (uimm (aarch64_get_instr (cpu
), 22, 22))
5602 shift
= uimm (aarch64_get_instr (cpu
), 21, 16);
5608 for (i
= 0; i
< 2; i
++)
5610 int64_t val
= aarch64_get_vec_s64 (cpu
, vs
, i
);
5611 aarch64_set_vec_s64 (cpu
, vd
, i
, val
>> shift
);
5614 for (i
= 0; i
< 2; i
++)
5616 uint64_t val
= aarch64_get_vec_u64 (cpu
, vs
, i
);
5617 aarch64_set_vec_u64 (cpu
, vd
, i
, val
>> shift
);
5623 if (uimm (aarch64_get_instr (cpu
), 21, 21))
5625 shift
= uimm (aarch64_get_instr (cpu
), 20, 16);
5628 for (i
= 0; i
< (full
? 4 : 2); i
++)
5630 int32_t val
= aarch64_get_vec_s32 (cpu
, vs
, i
);
5631 aarch64_set_vec_s32 (cpu
, vd
, i
, val
>> shift
);
5634 for (i
= 0; i
< (full
? 4 : 2); i
++)
5636 uint32_t val
= aarch64_get_vec_u32 (cpu
, vs
, i
);
5637 aarch64_set_vec_u32 (cpu
, vd
, i
, val
>> shift
);
5643 if (uimm (aarch64_get_instr (cpu
), 20, 20))
5645 shift
= uimm (aarch64_get_instr (cpu
), 19, 16);
5648 for (i
= 0; i
< (full
? 8 : 4); i
++)
5650 int16_t val
= aarch64_get_vec_s16 (cpu
, vs
, i
);
5651 aarch64_set_vec_s16 (cpu
, vd
, i
, val
>> shift
);
5654 for (i
= 0; i
< (full
? 8 : 4); i
++)
5656 uint16_t val
= aarch64_get_vec_u16 (cpu
, vs
, i
);
5657 aarch64_set_vec_u16 (cpu
, vd
, i
, val
>> shift
);
5663 if (uimm (aarch64_get_instr (cpu
), 19, 19) == 0)
5666 shift
= uimm (aarch64_get_instr (cpu
), 18, 16);
5669 for (i
= 0; i
< (full
? 16 : 8); i
++)
5671 int8_t val
= aarch64_get_vec_s8 (cpu
, vs
, i
);
5672 aarch64_set_vec_s8 (cpu
, vd
, i
, val
>> shift
);
5675 for (i
= 0; i
< (full
? 16 : 8); i
++)
5677 uint8_t val
= aarch64_get_vec_u8 (cpu
, vs
, i
);
5678 aarch64_set_vec_u8 (cpu
, vd
, i
, val
>> shift
);
5683 do_vec_op2 (sim_cpu
*cpu
)
5686 instr[30] = half/full
5687 instr[29,24] = 00 1111
5689 instr[22,16] = element size & index
5690 instr[15,10] = sub-opcode
5694 NYI_assert (29, 24, 0x0F);
5696 if (uimm (aarch64_get_instr (cpu
), 23, 23) != 0)
5699 switch (uimm (aarch64_get_instr (cpu
), 15, 10))
5701 case 0x01: do_vec_SSHR_USHR (cpu
); return;
5702 case 0x15: do_vec_SHL (cpu
); return;
5703 case 0x29: do_vec_xtl (cpu
); return;
5709 do_vec_neg (sim_cpu
*cpu
)
5712 instr[30] = full(1)/half(0)
5713 instr[29,24] = 10 1110
5714 instr[23,22] = size: byte(00), half (01), word (10), long (11)
5715 instr[21,10] = 1000 0010 1110
5719 int full
= uimm (aarch64_get_instr (cpu
), 30, 30);
5720 unsigned vs
= uimm (aarch64_get_instr (cpu
), 9, 5);
5721 unsigned vd
= uimm (aarch64_get_instr (cpu
), 4, 0);
5724 NYI_assert (29, 24, 0x2E);
5725 NYI_assert (21, 10, 0x82E);
5727 switch (uimm (aarch64_get_instr (cpu
), 23, 22))
5730 for (i
= 0; i
< (full
? 16 : 8); i
++)
5731 aarch64_set_vec_s8 (cpu
, vd
, i
, - aarch64_get_vec_s8 (cpu
, vs
, i
));
5735 for (i
= 0; i
< (full
? 8 : 4); i
++)
5736 aarch64_set_vec_s16 (cpu
, vd
, i
, - aarch64_get_vec_s16 (cpu
, vs
, i
));
5740 for (i
= 0; i
< (full
? 4 : 2); i
++)
5741 aarch64_set_vec_s32 (cpu
, vd
, i
, - aarch64_get_vec_s32 (cpu
, vs
, i
));
5747 for (i
= 0; i
< 2; i
++)
5748 aarch64_set_vec_s64 (cpu
, vd
, i
, - aarch64_get_vec_s64 (cpu
, vs
, i
));
5757 do_vec_sqrt (sim_cpu
*cpu
)
5760 instr[30] = full(1)/half(0)
5761 instr[29,23] = 101 1101
5762 instr[22] = single(0)/double(1)
5763 instr[21,10] = 1000 0111 1110
5767 int full
= uimm (aarch64_get_instr (cpu
), 30, 30);
5768 unsigned vs
= uimm (aarch64_get_instr (cpu
), 9, 5);
5769 unsigned vd
= uimm (aarch64_get_instr (cpu
), 4, 0);
5772 NYI_assert (29, 23, 0x5B);
5773 NYI_assert (21, 10, 0x87E);
5775 if (uimm (aarch64_get_instr (cpu
), 22, 22) == 0)
5776 for (i
= 0; i
< (full
? 4 : 2); i
++)
5777 aarch64_set_vec_float (cpu
, vd
, i
,
5778 sqrtf (aarch64_get_vec_float (cpu
, vs
, i
)));
5780 for (i
= 0; i
< 2; i
++)
5781 aarch64_set_vec_double (cpu
, vd
, i
,
5782 sqrt (aarch64_get_vec_double (cpu
, vs
, i
)));
5786 do_vec_mls_indexed (sim_cpu
*cpu
)
5789 instr[30] = half(0)/full(1)
5790 instr[29,24] = 10 1111
5791 instr[23,22] = 16-bit(01)/32-bit(10)
5792 instr[21,20+11] = index (if 16-bit)
5793 instr[21+11] = index (if 32-bit)
5796 instr[11] = part of index
5801 int full
= uimm (aarch64_get_instr (cpu
), 30, 30);
5802 unsigned vs
= uimm (aarch64_get_instr (cpu
), 9, 5);
5803 unsigned vd
= uimm (aarch64_get_instr (cpu
), 4, 0);
5804 unsigned vm
= uimm (aarch64_get_instr (cpu
), 20, 16);
5807 NYI_assert (15, 12, 4);
5808 NYI_assert (10, 10, 0);
5810 switch (uimm (aarch64_get_instr (cpu
), 23, 22))
5820 elem
= (uimm (aarch64_get_instr (cpu
), 21, 20) << 1)
5821 | uimm (aarch64_get_instr (cpu
), 11, 11);
5822 val
= aarch64_get_vec_u16 (cpu
, vm
, elem
);
5824 for (i
= 0; i
< (full
? 8 : 4); i
++)
5825 aarch64_set_vec_u32 (cpu
, vd
, i
,
5826 aarch64_get_vec_u32 (cpu
, vd
, i
) -
5827 (aarch64_get_vec_u32 (cpu
, vs
, i
) * val
));
5833 unsigned elem
= (uimm (aarch64_get_instr (cpu
), 21, 21) << 1)
5834 | uimm (aarch64_get_instr (cpu
), 11, 11);
5835 uint64_t val
= aarch64_get_vec_u32 (cpu
, vm
, elem
);
5837 for (i
= 0; i
< (full
? 4 : 2); i
++)
5838 aarch64_set_vec_u64 (cpu
, vd
, i
,
5839 aarch64_get_vec_u64 (cpu
, vd
, i
) -
5840 (aarch64_get_vec_u64 (cpu
, vs
, i
) * val
));
5852 do_vec_SUB (sim_cpu
*cpu
)
5855 instr [30] = half(0)/full(1)
5856 instr [29,24] = 10 1110
5857 instr [23,22] = size: byte(00, half(01), word (10), long (11)
5860 instr [15,10] = 10 0001
5862 instr [4, 0] = Vd. */
5864 unsigned full
= uimm (aarch64_get_instr (cpu
), 30, 30);
5865 unsigned vm
= uimm (aarch64_get_instr (cpu
), 20, 16);
5866 unsigned vn
= uimm (aarch64_get_instr (cpu
), 9, 5);
5867 unsigned vd
= uimm (aarch64_get_instr (cpu
), 4, 0);
5870 NYI_assert (29, 24, 0x2E);
5871 NYI_assert (21, 21, 1);
5872 NYI_assert (15, 10, 0x21);
5874 switch (uimm (aarch64_get_instr (cpu
), 23, 22))
5877 for (i
= 0; i
< (full
? 16 : 8); i
++)
5878 aarch64_set_vec_s8 (cpu
, vd
, i
,
5879 aarch64_get_vec_s8 (cpu
, vn
, i
)
5880 - aarch64_get_vec_s8 (cpu
, vm
, i
));
5884 for (i
= 0; i
< (full
? 8 : 4); i
++)
5885 aarch64_set_vec_s16 (cpu
, vd
, i
,
5886 aarch64_get_vec_s16 (cpu
, vn
, i
)
5887 - aarch64_get_vec_s16 (cpu
, vm
, i
));
5891 for (i
= 0; i
< (full
? 4 : 2); i
++)
5892 aarch64_set_vec_s32 (cpu
, vd
, i
,
5893 aarch64_get_vec_s32 (cpu
, vn
, i
)
5894 - aarch64_get_vec_s32 (cpu
, vm
, i
));
5901 for (i
= 0; i
< 2; i
++)
5902 aarch64_set_vec_s64 (cpu
, vd
, i
,
5903 aarch64_get_vec_s64 (cpu
, vn
, i
)
5904 - aarch64_get_vec_s64 (cpu
, vm
, i
));
5913 do_vec_MLS (sim_cpu
*cpu
)
5916 instr [30] = half(0)/full(1)
5917 instr [29,24] = 10 1110
5918 instr [23,22] = size: byte(00, half(01), word (10)
5921 instr [15,10] = 10 0101
5923 instr [4, 0] = Vd. */
5925 unsigned full
= uimm (aarch64_get_instr (cpu
), 30, 30);
5926 unsigned vm
= uimm (aarch64_get_instr (cpu
), 20, 16);
5927 unsigned vn
= uimm (aarch64_get_instr (cpu
), 9, 5);
5928 unsigned vd
= uimm (aarch64_get_instr (cpu
), 4, 0);
5931 NYI_assert (29, 24, 0x2E);
5932 NYI_assert (21, 21, 1);
5933 NYI_assert (15, 10, 0x25);
5935 switch (uimm (aarch64_get_instr (cpu
), 23, 22))
5938 for (i
= 0; i
< (full
? 16 : 8); i
++)
5939 aarch64_set_vec_u8 (cpu
, vd
, i
,
5940 (aarch64_get_vec_u8 (cpu
, vn
, i
)
5941 * aarch64_get_vec_u8 (cpu
, vm
, i
))
5942 - aarch64_get_vec_u8 (cpu
, vd
, i
));
5946 for (i
= 0; i
< (full
? 8 : 4); i
++)
5947 aarch64_set_vec_u16 (cpu
, vd
, i
,
5948 (aarch64_get_vec_u16 (cpu
, vn
, i
)
5949 * aarch64_get_vec_u16 (cpu
, vm
, i
))
5950 - aarch64_get_vec_u16 (cpu
, vd
, i
));
5954 for (i
= 0; i
< (full
? 4 : 2); i
++)
5955 aarch64_set_vec_u32 (cpu
, vd
, i
,
5956 (aarch64_get_vec_u32 (cpu
, vn
, i
)
5957 * aarch64_get_vec_u32 (cpu
, vm
, i
))
5958 - aarch64_get_vec_u32 (cpu
, vd
, i
));
5967 do_vec_FDIV (sim_cpu
*cpu
)
5970 instr [30] = half(0)/full(1)
5971 instr [29,23] = 10 1110 0
5972 instr [22] = float()/double(1)
5975 instr [15,10] = 1111 11
5977 instr [4, 0] = Vd. */
5979 unsigned full
= uimm (aarch64_get_instr (cpu
), 30, 30);
5980 unsigned vm
= uimm (aarch64_get_instr (cpu
), 20, 16);
5981 unsigned vn
= uimm (aarch64_get_instr (cpu
), 9, 5);
5982 unsigned vd
= uimm (aarch64_get_instr (cpu
), 4, 0);
5985 NYI_assert (29, 23, 0x5C);
5986 NYI_assert (21, 21, 1);
5987 NYI_assert (15, 10, 0x3F);
5989 if (uimm (aarch64_get_instr (cpu
), 22, 22))
5994 for (i
= 0; i
< 2; i
++)
5995 aarch64_set_vec_double (cpu
, vd
, i
,
5996 aarch64_get_vec_double (cpu
, vn
, i
)
5997 / aarch64_get_vec_double (cpu
, vm
, i
));
6000 for (i
= 0; i
< (full
? 4 : 2); i
++)
6001 aarch64_set_vec_float (cpu
, vd
, i
,
6002 aarch64_get_vec_float (cpu
, vn
, i
)
6003 / aarch64_get_vec_float (cpu
, vm
, i
));
6007 do_vec_FMUL (sim_cpu
*cpu
)
6010 instr [30] = half(0)/full(1)
6011 instr [29,23] = 10 1110 0
6012 instr [22] = float(0)/double(1)
6015 instr [15,10] = 1101 11
6017 instr [4, 0] = Vd. */
6019 unsigned full
= uimm (aarch64_get_instr (cpu
), 30, 30);
6020 unsigned vm
= uimm (aarch64_get_instr (cpu
), 20, 16);
6021 unsigned vn
= uimm (aarch64_get_instr (cpu
), 9, 5);
6022 unsigned vd
= uimm (aarch64_get_instr (cpu
), 4, 0);
6025 NYI_assert (29, 23, 0x5C);
6026 NYI_assert (21, 21, 1);
6027 NYI_assert (15, 10, 0x37);
6029 if (uimm (aarch64_get_instr (cpu
), 22, 22))
6034 for (i
= 0; i
< 2; i
++)
6035 aarch64_set_vec_double (cpu
, vd
, i
,
6036 aarch64_get_vec_double (cpu
, vn
, i
)
6037 * aarch64_get_vec_double (cpu
, vm
, i
));
6040 for (i
= 0; i
< (full
? 4 : 2); i
++)
6041 aarch64_set_vec_float (cpu
, vd
, i
,
6042 aarch64_get_vec_float (cpu
, vn
, i
)
6043 * aarch64_get_vec_float (cpu
, vm
, i
));
6047 do_vec_FADDP (sim_cpu
*cpu
)
6050 instr [30] = half(0)/full(1)
6051 instr [29,23] = 10 1110 0
6052 instr [22] = float(0)/double(1)
6055 instr [15,10] = 1101 01
6057 instr [4, 0] = Vd. */
6059 unsigned full
= uimm (aarch64_get_instr (cpu
), 30, 30);
6060 unsigned vm
= uimm (aarch64_get_instr (cpu
), 20, 16);
6061 unsigned vn
= uimm (aarch64_get_instr (cpu
), 9, 5);
6062 unsigned vd
= uimm (aarch64_get_instr (cpu
), 4, 0);
6064 NYI_assert (29, 23, 0x5C);
6065 NYI_assert (21, 21, 1);
6066 NYI_assert (15, 10, 0x35);
6068 if (uimm (aarch64_get_instr (cpu
), 22, 22))
6073 aarch64_set_vec_double (cpu
, vd
, 0, aarch64_get_vec_double (cpu
, vn
, 0)
6074 + aarch64_get_vec_double (cpu
, vn
, 1));
6075 aarch64_set_vec_double (cpu
, vd
, 1, aarch64_get_vec_double (cpu
, vm
, 0)
6076 + aarch64_get_vec_double (cpu
, vm
, 1));
6080 aarch64_set_vec_float (cpu
, vd
, 0, aarch64_get_vec_float (cpu
, vn
, 0)
6081 + aarch64_get_vec_float (cpu
, vn
, 1));
6083 aarch64_set_vec_float (cpu
, vd
, 1, aarch64_get_vec_float (cpu
, vn
, 2)
6084 + aarch64_get_vec_float (cpu
, vn
, 3));
6085 aarch64_set_vec_float (cpu
, vd
, full
? 2 : 1,
6086 aarch64_get_vec_float (cpu
, vm
, 0)
6087 + aarch64_get_vec_float (cpu
, vm
, 1));
6089 aarch64_set_vec_float (cpu
, vd
, 3,
6090 aarch64_get_vec_float (cpu
, vm
, 2)
6091 + aarch64_get_vec_float (cpu
, vm
, 3));
6096 do_vec_FSQRT (sim_cpu
*cpu
)
6099 instr[30] = half(0)/full(1)
6100 instr[29,23] = 10 1110 1
6101 instr[22] = single(0)/double(1)
6102 instr[21,10] = 10 0001 1111 10
6104 instr[4,0] = Vdest. */
6106 unsigned vn
= uimm (aarch64_get_instr (cpu
), 9, 5);
6107 unsigned vd
= uimm (aarch64_get_instr (cpu
), 4, 0);
6108 unsigned full
= uimm (aarch64_get_instr (cpu
), 30, 30);
6111 NYI_assert (29, 23, 0x5D);
6112 NYI_assert (21, 10, 0x87E);
6114 if (uimm (aarch64_get_instr (cpu
), 22, 22))
6119 for (i
= 0; i
< 2; i
++)
6120 aarch64_set_vec_double (cpu
, vd
, i
,
6121 sqrt (aarch64_get_vec_double (cpu
, vn
, i
)));
6125 for (i
= 0; i
< (full
? 4 : 2); i
++)
6126 aarch64_set_vec_float (cpu
, vd
, i
,
6127 sqrtf (aarch64_get_vec_float (cpu
, vn
, i
)));
6132 do_vec_FNEG (sim_cpu
*cpu
)
6135 instr[30] = half (0)/full (1)
6136 instr[29,23] = 10 1110 1
6137 instr[22] = single (0)/double (1)
6138 instr[21,10] = 10 0000 1111 10
6140 instr[4,0] = Vdest. */
6142 unsigned vn
= uimm (aarch64_get_instr (cpu
), 9, 5);
6143 unsigned vd
= uimm (aarch64_get_instr (cpu
), 4, 0);
6144 unsigned full
= uimm (aarch64_get_instr (cpu
), 30, 30);
6147 NYI_assert (29, 23, 0x5D);
6148 NYI_assert (21, 10, 0x83E);
6150 if (uimm (aarch64_get_instr (cpu
), 22, 22))
6155 for (i
= 0; i
< 2; i
++)
6156 aarch64_set_vec_double (cpu
, vd
, i
,
6157 - aarch64_get_vec_double (cpu
, vn
, i
));
6161 for (i
= 0; i
< (full
? 4 : 2); i
++)
6162 aarch64_set_vec_float (cpu
, vd
, i
,
6163 - aarch64_get_vec_float (cpu
, vn
, i
));
6168 do_vec_NOT (sim_cpu
*cpu
)
6171 instr[30] = half (0)/full (1)
6172 instr[29,21] = 10 1110 001
6173 instr[20,16] = 0 0000
6174 instr[15,10] = 0101 10
6178 unsigned vn
= uimm (aarch64_get_instr (cpu
), 9, 5);
6179 unsigned vd
= uimm (aarch64_get_instr (cpu
), 4, 0);
6181 int full
= uimm (aarch64_get_instr (cpu
), 30, 30);
6183 NYI_assert (29, 10, 0xB8816);
6185 for (i
= 0; i
< (full
? 16 : 8); i
++)
6186 aarch64_set_vec_u8 (cpu
, vd
, i
, ~ aarch64_get_vec_u8 (cpu
, vn
, i
));
6190 do_vec_MOV_element (sim_cpu
*cpu
)
6192 /* instr[31,21] = 0110 1110 000
6193 instr[20,16] = size & dest index
6195 instr[14,11] = source index
6200 unsigned vs
= uimm (aarch64_get_instr (cpu
), 9, 5);
6201 unsigned vd
= uimm (aarch64_get_instr (cpu
), 4, 0);
6205 NYI_assert (31, 21, 0x370);
6206 NYI_assert (15, 15, 0);
6207 NYI_assert (10, 10, 1);
6209 if (uimm (aarch64_get_instr (cpu
), 16, 16))
6212 src_index
= uimm (aarch64_get_instr (cpu
), 14, 11);
6213 dst_index
= uimm (aarch64_get_instr (cpu
), 20, 17);
6214 aarch64_set_vec_u8 (cpu
, vd
, dst_index
,
6215 aarch64_get_vec_u8 (cpu
, vs
, src_index
));
6217 else if (uimm (aarch64_get_instr (cpu
), 17, 17))
6220 NYI_assert (11, 11, 0);
6221 src_index
= uimm (aarch64_get_instr (cpu
), 14, 12);
6222 dst_index
= uimm (aarch64_get_instr (cpu
), 20, 18);
6223 aarch64_set_vec_u16 (cpu
, vd
, dst_index
,
6224 aarch64_get_vec_u16 (cpu
, vs
, src_index
));
6226 else if (uimm (aarch64_get_instr (cpu
), 18, 18))
6229 NYI_assert (12, 11, 0);
6230 src_index
= uimm (aarch64_get_instr (cpu
), 14, 13);
6231 dst_index
= uimm (aarch64_get_instr (cpu
), 20, 19);
6232 aarch64_set_vec_u32 (cpu
, vd
, dst_index
,
6233 aarch64_get_vec_u32 (cpu
, vs
, src_index
));
6237 NYI_assert (19, 19, 1);
6238 NYI_assert (13, 11, 0);
6239 src_index
= uimm (aarch64_get_instr (cpu
), 14, 14);
6240 dst_index
= uimm (aarch64_get_instr (cpu
), 20, 20);
6241 aarch64_set_vec_u64 (cpu
, vd
, dst_index
,
6242 aarch64_get_vec_u64 (cpu
, vs
, src_index
));
6247 dexAdvSIMD0 (sim_cpu
*cpu
)
6249 /* instr [28,25] = 0 111. */
6250 if ( uimm (aarch64_get_instr (cpu
), 15, 10) == 0x07
6251 && (uimm (aarch64_get_instr (cpu
), 9, 5) ==
6252 uimm (aarch64_get_instr (cpu
), 20, 16)))
6254 if (uimm (aarch64_get_instr (cpu
), 31, 21) == 0x075
6255 || uimm (aarch64_get_instr (cpu
), 31, 21) == 0x275)
6257 do_vec_MOV_whole_vector (cpu
);
6262 if (uimm (aarch64_get_instr (cpu
), 29, 19) == 0x1E0)
6264 do_vec_MOV_immediate (cpu
);
6268 if (uimm (aarch64_get_instr (cpu
), 29, 19) == 0x5E0)
6274 if (uimm (aarch64_get_instr (cpu
), 29, 19) == 0x1C0
6275 || uimm (aarch64_get_instr (cpu
), 29, 19) == 0x1C1)
6277 if (uimm (aarch64_get_instr (cpu
), 15, 10) == 0x03)
6279 do_vec_DUP_scalar_into_vector (cpu
);
6284 switch (uimm (aarch64_get_instr (cpu
), 29, 24))
6286 case 0x0E: do_vec_op1 (cpu
); return;
6287 case 0x0F: do_vec_op2 (cpu
); return;
6290 switch (uimm (aarch64_get_instr (cpu
), 15, 10))
6292 case 0x01: do_vec_SSHR_USHR (cpu
); return;
6294 case 0x12: do_vec_mls_indexed (cpu
); return;
6295 case 0x29: do_vec_xtl (cpu
); return;
6301 if (uimm (aarch64_get_instr (cpu
), 21, 21) == 1)
6303 switch (uimm (aarch64_get_instr (cpu
), 15, 10))
6306 switch (uimm (aarch64_get_instr (cpu
), 23, 22))
6308 case 0: do_vec_EOR (cpu
); return;
6309 case 1: do_vec_BSL (cpu
); return;
6311 case 3: do_vec_bit (cpu
); return;
6315 case 0x08: do_vec_sub_long (cpu
); return;
6316 case 0x11: do_vec_USHL (cpu
); return;
6317 case 0x16: do_vec_NOT (cpu
); return;
6318 case 0x19: do_vec_max (cpu
); return;
6319 case 0x1B: do_vec_min (cpu
); return;
6320 case 0x21: do_vec_SUB (cpu
); return;
6321 case 0x25: do_vec_MLS (cpu
); return;
6322 case 0x31: do_vec_FminmaxNMP (cpu
); return;
6323 case 0x35: do_vec_FADDP (cpu
); return;
6324 case 0x37: do_vec_FMUL (cpu
); return;
6325 case 0x3F: do_vec_FDIV (cpu
); return;
6328 switch (uimm (aarch64_get_instr (cpu
), 20, 16))
6330 case 0x00: do_vec_FNEG (cpu
); return;
6331 case 0x01: do_vec_FSQRT (cpu
); return;
6345 do_vec_compare (cpu
); return;
6351 if (uimm (aarch64_get_instr (cpu
), 31, 21) == 0x370)
6353 do_vec_MOV_element (cpu
);
6357 switch (uimm (aarch64_get_instr (cpu
), 21, 10))
6359 case 0x82E: do_vec_neg (cpu
); return;
6360 case 0x87E: do_vec_sqrt (cpu
); return;
6362 if (uimm (aarch64_get_instr (cpu
), 15, 10) == 0x30)
6380 /* Float multiply add. */
6382 fmadds (sim_cpu
*cpu
)
6384 unsigned sa
= uimm (aarch64_get_instr (cpu
), 14, 10);
6385 unsigned sm
= uimm (aarch64_get_instr (cpu
), 20, 16);
6386 unsigned sn
= uimm (aarch64_get_instr (cpu
), 9, 5);
6387 unsigned sd
= uimm (aarch64_get_instr (cpu
), 4, 0);
6389 aarch64_set_FP_float (cpu
, sd
, aarch64_get_FP_float (cpu
, sa
)
6390 + aarch64_get_FP_float (cpu
, sn
)
6391 * aarch64_get_FP_float (cpu
, sm
));
6394 /* Double multiply add. */
6396 fmaddd (sim_cpu
*cpu
)
6398 unsigned sa
= uimm (aarch64_get_instr (cpu
), 14, 10);
6399 unsigned sm
= uimm (aarch64_get_instr (cpu
), 20, 16);
6400 unsigned sn
= uimm (aarch64_get_instr (cpu
), 9, 5);
6401 unsigned sd
= uimm (aarch64_get_instr (cpu
), 4, 0);
6403 aarch64_set_FP_double (cpu
, sd
, aarch64_get_FP_double (cpu
, sa
)
6404 + aarch64_get_FP_double (cpu
, sn
)
6405 * aarch64_get_FP_double (cpu
, sm
));
6408 /* Float multiply subtract. */
6410 fmsubs (sim_cpu
*cpu
)
6412 unsigned sa
= uimm (aarch64_get_instr (cpu
), 14, 10);
6413 unsigned sm
= uimm (aarch64_get_instr (cpu
), 20, 16);
6414 unsigned sn
= uimm (aarch64_get_instr (cpu
), 9, 5);
6415 unsigned sd
= uimm (aarch64_get_instr (cpu
), 4, 0);
6417 aarch64_set_FP_float (cpu
, sd
, aarch64_get_FP_float (cpu
, sa
)
6418 - aarch64_get_FP_float (cpu
, sn
)
6419 * aarch64_get_FP_float (cpu
, sm
));
6422 /* Double multiply subtract. */
6424 fmsubd (sim_cpu
*cpu
)
6426 unsigned sa
= uimm (aarch64_get_instr (cpu
), 14, 10);
6427 unsigned sm
= uimm (aarch64_get_instr (cpu
), 20, 16);
6428 unsigned sn
= uimm (aarch64_get_instr (cpu
), 9, 5);
6429 unsigned sd
= uimm (aarch64_get_instr (cpu
), 4, 0);
6431 aarch64_set_FP_double (cpu
, sd
, aarch64_get_FP_double (cpu
, sa
)
6432 - aarch64_get_FP_double (cpu
, sn
)
6433 * aarch64_get_FP_double (cpu
, sm
));
6436 /* Float negative multiply add. */
6438 fnmadds (sim_cpu
*cpu
)
6440 unsigned sa
= uimm (aarch64_get_instr (cpu
), 14, 10);
6441 unsigned sm
= uimm (aarch64_get_instr (cpu
), 20, 16);
6442 unsigned sn
= uimm (aarch64_get_instr (cpu
), 9, 5);
6443 unsigned sd
= uimm (aarch64_get_instr (cpu
), 4, 0);
6445 aarch64_set_FP_float (cpu
, sd
, - aarch64_get_FP_float (cpu
, sa
)
6446 + (- aarch64_get_FP_float (cpu
, sn
))
6447 * aarch64_get_FP_float (cpu
, sm
));
6450 /* Double negative multiply add. */
6452 fnmaddd (sim_cpu
*cpu
)
6454 unsigned sa
= uimm (aarch64_get_instr (cpu
), 14, 10);
6455 unsigned sm
= uimm (aarch64_get_instr (cpu
), 20, 16);
6456 unsigned sn
= uimm (aarch64_get_instr (cpu
), 9, 5);
6457 unsigned sd
= uimm (aarch64_get_instr (cpu
), 4, 0);
6459 aarch64_set_FP_double (cpu
, sd
, - aarch64_get_FP_double (cpu
, sa
)
6460 + (- aarch64_get_FP_double (cpu
, sn
))
6461 * aarch64_get_FP_double (cpu
, sm
));
6464 /* Float negative multiply subtract. */
6466 fnmsubs (sim_cpu
*cpu
)
6468 unsigned sa
= uimm (aarch64_get_instr (cpu
), 14, 10);
6469 unsigned sm
= uimm (aarch64_get_instr (cpu
), 20, 16);
6470 unsigned sn
= uimm (aarch64_get_instr (cpu
), 9, 5);
6471 unsigned sd
= uimm (aarch64_get_instr (cpu
), 4, 0);
6473 aarch64_set_FP_float (cpu
, sd
, - aarch64_get_FP_float (cpu
, sa
)
6474 + aarch64_get_FP_float (cpu
, sn
)
6475 * aarch64_get_FP_float (cpu
, sm
));
6478 /* Double negative multiply subtract. */
6480 fnmsubd (sim_cpu
*cpu
)
6482 unsigned sa
= uimm (aarch64_get_instr (cpu
), 14, 10);
6483 unsigned sm
= uimm (aarch64_get_instr (cpu
), 20, 16);
6484 unsigned sn
= uimm (aarch64_get_instr (cpu
), 9, 5);
6485 unsigned sd
= uimm (aarch64_get_instr (cpu
), 4, 0);
6487 aarch64_set_FP_double (cpu
, sd
, - aarch64_get_FP_double (cpu
, sa
)
6488 + aarch64_get_FP_double (cpu
, sn
)
6489 * aarch64_get_FP_double (cpu
, sm
));
6493 dexSimpleFPDataProc3Source (sim_cpu
*cpu
)
6495 /* instr[31] ==> M : 0 ==> OK, 1 ==> UNALLOC
6497 instr[29] ==> S : 0 ==> OK, 1 ==> UNALLOC
6500 instr[23,22] ==> type : 0 ==> single, 01 ==> double, 1x ==> UNALLOC
6501 instr[21] ==> o1 : 0 ==> unnegated, 1 ==> negated
6502 instr[15] ==> o2 : 0 ==> ADD, 1 ==> SUB */
6504 uint32_t M_S
= (uimm (aarch64_get_instr (cpu
), 31, 31) << 1)
6505 | uimm (aarch64_get_instr (cpu
), 29, 29);
6506 /* dispatch on combined type:o1:o2. */
6507 uint32_t dispatch
= (uimm (aarch64_get_instr (cpu
), 23, 21) << 1)
6508 | uimm (aarch64_get_instr (cpu
), 15, 15);
6515 case 0: fmadds (cpu
); return;
6516 case 1: fmsubs (cpu
); return;
6517 case 2: fnmadds (cpu
); return;
6518 case 3: fnmsubs (cpu
); return;
6519 case 4: fmaddd (cpu
); return;
6520 case 5: fmsubd (cpu
); return;
6521 case 6: fnmaddd (cpu
); return;
6522 case 7: fnmsubd (cpu
); return;
6524 /* type > 1 is currently unallocated. */
6530 dexSimpleFPFixedConvert (sim_cpu
*cpu
)
6536 dexSimpleFPCondCompare (sim_cpu
*cpu
)
6545 fadds (sim_cpu
*cpu
)
6547 unsigned sm
= uimm (aarch64_get_instr (cpu
), 20, 16);
6548 unsigned sn
= uimm (aarch64_get_instr (cpu
), 9, 5);
6549 unsigned sd
= uimm (aarch64_get_instr (cpu
), 4, 0);
6551 aarch64_set_FP_float (cpu
, sd
, aarch64_get_FP_float (cpu
, sn
)
6552 + aarch64_get_FP_float (cpu
, sm
));
6557 faddd (sim_cpu
*cpu
)
6559 unsigned sm
= uimm (aarch64_get_instr (cpu
), 20, 16);
6560 unsigned sn
= uimm (aarch64_get_instr (cpu
), 9, 5);
6561 unsigned sd
= uimm (aarch64_get_instr (cpu
), 4, 0);
6563 aarch64_set_FP_double (cpu
, sd
, aarch64_get_FP_double (cpu
, sn
)
6564 + aarch64_get_FP_double (cpu
, sm
));
6569 fdivs (sim_cpu
*cpu
)
6571 unsigned sm
= uimm (aarch64_get_instr (cpu
), 20, 16);
6572 unsigned sn
= uimm (aarch64_get_instr (cpu
), 9, 5);
6573 unsigned sd
= uimm (aarch64_get_instr (cpu
), 4, 0);
6575 aarch64_set_FP_float (cpu
, sd
, aarch64_get_FP_float (cpu
, sn
)
6576 / aarch64_get_FP_float (cpu
, sm
));
6579 /* Double divide. */
6581 fdivd (sim_cpu
*cpu
)
6583 unsigned sm
= uimm (aarch64_get_instr (cpu
), 20, 16);
6584 unsigned sn
= uimm (aarch64_get_instr (cpu
), 9, 5);
6585 unsigned sd
= uimm (aarch64_get_instr (cpu
), 4, 0);
6587 aarch64_set_FP_double (cpu
, sd
, aarch64_get_FP_double (cpu
, sn
)
6588 / aarch64_get_FP_double (cpu
, sm
));
6591 /* Float multiply. */
6593 fmuls (sim_cpu
*cpu
)
6595 unsigned sm
= uimm (aarch64_get_instr (cpu
), 20, 16);
6596 unsigned sn
= uimm (aarch64_get_instr (cpu
), 9, 5);
6597 unsigned sd
= uimm (aarch64_get_instr (cpu
), 4, 0);
6599 aarch64_set_FP_float (cpu
, sd
, aarch64_get_FP_float (cpu
, sn
)
6600 * aarch64_get_FP_float (cpu
, sm
));
6603 /* Double multiply. */
6605 fmuld (sim_cpu
*cpu
)
6607 unsigned sm
= uimm (aarch64_get_instr (cpu
), 20, 16);
6608 unsigned sn
= uimm (aarch64_get_instr (cpu
), 9, 5);
6609 unsigned sd
= uimm (aarch64_get_instr (cpu
), 4, 0);
6611 aarch64_set_FP_double (cpu
, sd
, aarch64_get_FP_double (cpu
, sn
)
6612 * aarch64_get_FP_double (cpu
, sm
));
6615 /* Float negate and multiply. */
6617 fnmuls (sim_cpu
*cpu
)
6619 unsigned sm
= uimm (aarch64_get_instr (cpu
), 20, 16);
6620 unsigned sn
= uimm (aarch64_get_instr (cpu
), 9, 5);
6621 unsigned sd
= uimm (aarch64_get_instr (cpu
), 4, 0);
6623 aarch64_set_FP_float (cpu
, sd
, - (aarch64_get_FP_float (cpu
, sn
)
6624 * aarch64_get_FP_float (cpu
, sm
)));
6627 /* Double negate and multiply. */
6629 fnmuld (sim_cpu
*cpu
)
6631 unsigned sm
= uimm (aarch64_get_instr (cpu
), 20, 16);
6632 unsigned sn
= uimm (aarch64_get_instr (cpu
), 9, 5);
6633 unsigned sd
= uimm (aarch64_get_instr (cpu
), 4, 0);
6635 aarch64_set_FP_double (cpu
, sd
, - (aarch64_get_FP_double (cpu
, sn
)
6636 * aarch64_get_FP_double (cpu
, sm
)));
6639 /* Float subtract. */
6641 fsubs (sim_cpu
*cpu
)
6643 unsigned sm
= uimm (aarch64_get_instr (cpu
), 20, 16);
6644 unsigned sn
= uimm (aarch64_get_instr (cpu
), 9, 5);
6645 unsigned sd
= uimm (aarch64_get_instr (cpu
), 4, 0);
6647 aarch64_set_FP_float (cpu
, sd
, aarch64_get_FP_float (cpu
, sn
)
6648 - aarch64_get_FP_float (cpu
, sm
));
6651 /* Double subtract. */
6653 fsubd (sim_cpu
*cpu
)
6655 unsigned sm
= uimm (aarch64_get_instr (cpu
), 20, 16);
6656 unsigned sn
= uimm (aarch64_get_instr (cpu
), 9, 5);
6657 unsigned sd
= uimm (aarch64_get_instr (cpu
), 4, 0);
6659 aarch64_set_FP_double (cpu
, sd
, aarch64_get_FP_double (cpu
, sn
)
6660 - aarch64_get_FP_double (cpu
, sm
));
6664 do_FMINNM (sim_cpu
*cpu
)
6666 /* instr[31,23] = 0 0011 1100
6667 instr[22] = float(0)/double(1)
6670 instr[15,10] = 01 1110
6674 unsigned sm
= uimm (aarch64_get_instr (cpu
), 20, 16);
6675 unsigned sn
= uimm (aarch64_get_instr (cpu
), 9, 5);
6676 unsigned sd
= uimm (aarch64_get_instr (cpu
), 4, 0);
6678 NYI_assert (31, 23, 0x03C);
6679 NYI_assert (15, 10, 0x1E);
6681 if (uimm (aarch64_get_instr (cpu
), 22, 22))
6682 aarch64_set_FP_double (cpu
, sd
,
6683 dminnm (aarch64_get_FP_double (cpu
, sn
),
6684 aarch64_get_FP_double (cpu
, sm
)));
6686 aarch64_set_FP_float (cpu
, sd
,
6687 fminnm (aarch64_get_FP_float (cpu
, sn
),
6688 aarch64_get_FP_float (cpu
, sm
)));
6692 do_FMAXNM (sim_cpu
*cpu
)
6694 /* instr[31,23] = 0 0011 1100
6695 instr[22] = float(0)/double(1)
6698 instr[15,10] = 01 1010
6702 unsigned sm
= uimm (aarch64_get_instr (cpu
), 20, 16);
6703 unsigned sn
= uimm (aarch64_get_instr (cpu
), 9, 5);
6704 unsigned sd
= uimm (aarch64_get_instr (cpu
), 4, 0);
6706 NYI_assert (31, 23, 0x03C);
6707 NYI_assert (15, 10, 0x1A);
6709 if (uimm (aarch64_get_instr (cpu
), 22, 22))
6710 aarch64_set_FP_double (cpu
, sd
,
6711 dmaxnm (aarch64_get_FP_double (cpu
, sn
),
6712 aarch64_get_FP_double (cpu
, sm
)));
6714 aarch64_set_FP_float (cpu
, sd
,
6715 fmaxnm (aarch64_get_FP_float (cpu
, sn
),
6716 aarch64_get_FP_float (cpu
, sm
)));
6720 dexSimpleFPDataProc2Source (sim_cpu
*cpu
)
6722 /* instr[31] ==> M : 0 ==> OK, 1 ==> UNALLOC
6724 instr[29] ==> S : 0 ==> OK, 1 ==> UNALLOC
6727 instr[23,22] ==> type : 0 ==> single, 01 ==> double, 1x ==> UNALLOC
6730 instr[15,12] ==> opcode : 0000 ==> FMUL, 0001 ==> FDIV
6731 0010 ==> FADD, 0011 ==> FSUB,
6732 0100 ==> FMAX, 0101 ==> FMIN
6733 0110 ==> FMAXNM, 0111 ==> FMINNM
6734 1000 ==> FNMUL, ow ==> UNALLOC
6739 uint32_t M_S
= (uimm (aarch64_get_instr (cpu
), 31, 31) << 1)
6740 | uimm (aarch64_get_instr (cpu
), 29, 29);
6741 uint32_t type
= uimm (aarch64_get_instr (cpu
), 23, 22);
6742 /* Dispatch on opcode. */
6743 uint32_t dispatch
= uimm (aarch64_get_instr (cpu
), 15, 12);
6754 case 0: fmuld (cpu
); return;
6755 case 1: fdivd (cpu
); return;
6756 case 2: faddd (cpu
); return;
6757 case 3: fsubd (cpu
); return;
6758 case 6: do_FMAXNM (cpu
); return;
6759 case 7: do_FMINNM (cpu
); return;
6760 case 8: fnmuld (cpu
); return;
6762 /* Have not yet implemented fmax and fmin. */
6770 else /* type == 0 => floats. */
6773 case 0: fmuls (cpu
); return;
6774 case 1: fdivs (cpu
); return;
6775 case 2: fadds (cpu
); return;
6776 case 3: fsubs (cpu
); return;
6777 case 6: do_FMAXNM (cpu
); return;
6778 case 7: do_FMINNM (cpu
); return;
6779 case 8: fnmuls (cpu
); return;
6791 dexSimpleFPCondSelect (sim_cpu
*cpu
)
6794 instr[31,23] = 0 0011 1100
6795 instr[22] = 0=>single 1=>double
6802 unsigned sm
= uimm (aarch64_get_instr (cpu
), 20, 16);
6803 unsigned sn
= uimm (aarch64_get_instr (cpu
), 9, 5);
6804 unsigned sd
= uimm (aarch64_get_instr (cpu
), 4, 0);
6805 uint32_t set
= testConditionCode (cpu
, uimm (aarch64_get_instr (cpu
), 15, 12));
6807 NYI_assert (31, 23, 0x03C);
6808 NYI_assert (11, 10, 0x3);
6810 if (uimm (aarch64_get_instr (cpu
), 22, 22))
6811 aarch64_set_FP_double (cpu
, sd
, set
? sn
: sm
);
6813 aarch64_set_FP_float (cpu
, sd
, set
? sn
: sm
);
6816 /* Store 32 bit unscaled signed 9 bit. */
6818 fsturs (sim_cpu
*cpu
, int32_t offset
)
6820 unsigned int rn
= uimm (aarch64_get_instr (cpu
), 9, 5);
6821 unsigned int st
= uimm (aarch64_get_instr (cpu
), 4, 0);
6823 aarch64_set_mem_float (cpu
, aarch64_get_reg_u64 (cpu
, st
, 1) + offset
,
6824 aarch64_get_FP_float (cpu
, rn
));
6827 /* Store 64 bit unscaled signed 9 bit. */
6829 fsturd (sim_cpu
*cpu
, int32_t offset
)
6831 unsigned int rn
= uimm (aarch64_get_instr (cpu
), 9, 5);
6832 unsigned int st
= uimm (aarch64_get_instr (cpu
), 4, 0);
6834 aarch64_set_mem_double (cpu
, aarch64_get_reg_u64 (cpu
, st
, 1) + offset
,
6835 aarch64_get_FP_double (cpu
, rn
));
6838 /* Store 128 bit unscaled signed 9 bit. */
6840 fsturq (sim_cpu
*cpu
, int32_t offset
)
6842 unsigned int rn
= uimm (aarch64_get_instr (cpu
), 9, 5);
6843 unsigned int st
= uimm (aarch64_get_instr (cpu
), 4, 0);
6846 aarch64_get_FP_long_double (cpu
, rn
, & a
);
6847 aarch64_set_mem_long_double (cpu
,
6848 aarch64_get_reg_u64 (cpu
, st
, 1)
6852 /* TODO FP move register. */
6854 /* 32 bit fp to fp move register. */
6856 ffmovs (sim_cpu
*cpu
)
6858 unsigned int rn
= uimm (aarch64_get_instr (cpu
), 9, 5);
6859 unsigned int st
= uimm (aarch64_get_instr (cpu
), 4, 0);
6861 aarch64_set_FP_float (cpu
, st
, aarch64_get_FP_float (cpu
, rn
));
6864 /* 64 bit fp to fp move register. */
6866 ffmovd (sim_cpu
*cpu
)
6868 unsigned int rn
= uimm (aarch64_get_instr (cpu
), 9, 5);
6869 unsigned int st
= uimm (aarch64_get_instr (cpu
), 4, 0);
6871 aarch64_set_FP_double (cpu
, st
, aarch64_get_FP_double (cpu
, rn
));
6874 /* 32 bit GReg to Vec move register. */
6876 fgmovs (sim_cpu
*cpu
)
6878 unsigned int rn
= uimm (aarch64_get_instr (cpu
), 9, 5);
6879 unsigned int st
= uimm (aarch64_get_instr (cpu
), 4, 0);
6881 aarch64_set_vec_u32 (cpu
, st
, 0, aarch64_get_reg_u32 (cpu
, rn
, NO_SP
));
6884 /* 64 bit g to fp move register. */
6886 fgmovd (sim_cpu
*cpu
)
6888 unsigned int rn
= uimm (aarch64_get_instr (cpu
), 9, 5);
6889 unsigned int st
= uimm (aarch64_get_instr (cpu
), 4, 0);
6891 aarch64_set_vec_u64 (cpu
, st
, 0, aarch64_get_reg_u64 (cpu
, rn
, NO_SP
));
6894 /* 32 bit fp to g move register. */
6896 gfmovs (sim_cpu
*cpu
)
6898 unsigned int rn
= uimm (aarch64_get_instr (cpu
), 9, 5);
6899 unsigned int st
= uimm (aarch64_get_instr (cpu
), 4, 0);
6901 aarch64_set_reg_u64 (cpu
, st
, NO_SP
, aarch64_get_vec_u32 (cpu
, rn
, 0));
6904 /* 64 bit fp to g move register. */
6906 gfmovd (sim_cpu
*cpu
)
6908 unsigned int rn
= uimm (aarch64_get_instr (cpu
), 9, 5);
6909 unsigned int st
= uimm (aarch64_get_instr (cpu
), 4, 0);
6911 aarch64_set_reg_u64 (cpu
, st
, NO_SP
, aarch64_get_vec_u64 (cpu
, rn
, 0));
6914 /* FP move immediate
6916 These install an immediate 8 bit value in the target register
6917 where the 8 bits comprise 1 sign bit, 4 bits of fraction and a 3
6921 fmovs (sim_cpu
*cpu
)
6923 unsigned int sd
= uimm (aarch64_get_instr (cpu
), 4, 0);
6924 uint32_t imm
= uimm (aarch64_get_instr (cpu
), 20, 13);
6925 float f
= fp_immediate_for_encoding_32 (imm
);
6927 aarch64_set_FP_float (cpu
, sd
, f
);
6931 fmovd (sim_cpu
*cpu
)
6933 unsigned int sd
= uimm (aarch64_get_instr (cpu
), 4, 0);
6934 uint32_t imm
= uimm (aarch64_get_instr (cpu
), 20, 13);
6935 double d
= fp_immediate_for_encoding_64 (imm
);
6937 aarch64_set_FP_double (cpu
, sd
, d
);
6941 dexSimpleFPImmediate (sim_cpu
*cpu
)
6943 /* instr[31,23] == 00111100
6944 instr[22] == type : single(0)/double(1)
6946 instr[20,13] == imm8
6948 instr[9,5] == imm5 : 00000 ==> PK, ow ==> UNALLOC
6950 uint32_t imm5
= uimm (aarch64_get_instr (cpu
), 9, 5);
6952 NYI_assert (31, 23, 0x3C);
6957 if (uimm (aarch64_get_instr (cpu
), 22, 22))
6963 /* TODO specific decode and execute for group Load Store. */
6965 /* TODO FP load/store single register (unscaled offset). */
6967 /* TODO load 8 bit unscaled signed 9 bit. */
6968 /* TODO load 16 bit unscaled signed 9 bit. */
6970 /* Load 32 bit unscaled signed 9 bit. */
6972 fldurs (sim_cpu
*cpu
, int32_t offset
)
6974 unsigned int rn
= uimm (aarch64_get_instr (cpu
), 9, 5);
6975 unsigned int st
= uimm (aarch64_get_instr (cpu
), 4, 0);
6977 aarch64_set_FP_float (cpu
, st
, aarch64_get_mem_float
6978 (cpu
, aarch64_get_reg_u64 (cpu
, rn
, SP_OK
) + offset
));
6981 /* Load 64 bit unscaled signed 9 bit. */
6983 fldurd (sim_cpu
*cpu
, int32_t offset
)
6985 unsigned int rn
= uimm (aarch64_get_instr (cpu
), 9, 5);
6986 unsigned int st
= uimm (aarch64_get_instr (cpu
), 4, 0);
6988 aarch64_set_FP_double (cpu
, st
, aarch64_get_mem_double
6989 (cpu
, aarch64_get_reg_u64 (cpu
, rn
, SP_OK
) + offset
));
6992 /* Load 128 bit unscaled signed 9 bit. */
6994 fldurq (sim_cpu
*cpu
, int32_t offset
)
6996 unsigned int rn
= uimm (aarch64_get_instr (cpu
), 9, 5);
6997 unsigned int st
= uimm (aarch64_get_instr (cpu
), 4, 0);
6999 uint64_t addr
= aarch64_get_reg_u64 (cpu
, rn
, SP_OK
) + offset
;
7001 aarch64_get_mem_long_double (cpu
, addr
, & a
);
7002 aarch64_set_FP_long_double (cpu
, st
, a
);
7005 /* TODO store 8 bit unscaled signed 9 bit. */
7006 /* TODO store 16 bit unscaled signed 9 bit. */
7011 /* Float absolute value. */
7013 fabss (sim_cpu
*cpu
)
7015 unsigned sn
= uimm (aarch64_get_instr (cpu
), 9, 5);
7016 unsigned sd
= uimm (aarch64_get_instr (cpu
), 4, 0);
7017 float value
= aarch64_get_FP_float (cpu
, sn
);
7019 aarch64_set_FP_float (cpu
, sd
, fabsf (value
));
7022 /* Double absolute value. */
7024 fabcpu (sim_cpu
*cpu
)
7026 unsigned sn
= uimm (aarch64_get_instr (cpu
), 9, 5);
7027 unsigned sd
= uimm (aarch64_get_instr (cpu
), 4, 0);
7028 double value
= aarch64_get_FP_double (cpu
, sn
);
7030 aarch64_set_FP_double (cpu
, sd
, fabs (value
));
7033 /* Float negative value. */
7035 fnegs (sim_cpu
*cpu
)
7037 unsigned sn
= uimm (aarch64_get_instr (cpu
), 9, 5);
7038 unsigned sd
= uimm (aarch64_get_instr (cpu
), 4, 0);
7040 aarch64_set_FP_float (cpu
, sd
, - aarch64_get_FP_float (cpu
, sn
));
7043 /* Double negative value. */
7045 fnegd (sim_cpu
*cpu
)
7047 unsigned sn
= uimm (aarch64_get_instr (cpu
), 9, 5);
7048 unsigned sd
= uimm (aarch64_get_instr (cpu
), 4, 0);
7050 aarch64_set_FP_double (cpu
, sd
, - aarch64_get_FP_double (cpu
, sn
));
7053 /* Float square root. */
7055 fsqrts (sim_cpu
*cpu
)
7057 unsigned sn
= uimm (aarch64_get_instr (cpu
), 9, 5);
7058 unsigned sd
= uimm (aarch64_get_instr (cpu
), 4, 0);
7060 aarch64_set_FP_float (cpu
, sd
, sqrt (aarch64_get_FP_float (cpu
, sn
)));
7063 /* Double square root. */
7065 fsqrtd (sim_cpu
*cpu
)
7067 unsigned sn
= uimm (aarch64_get_instr (cpu
), 9, 5);
7068 unsigned sd
= uimm (aarch64_get_instr (cpu
), 4, 0);
7070 aarch64_set_FP_double (cpu
, sd
,
7071 sqrt (aarch64_get_FP_double (cpu
, sn
)));
7074 /* Convert double to float. */
7076 fcvtds (sim_cpu
*cpu
)
7078 unsigned sn
= uimm (aarch64_get_instr (cpu
), 9, 5);
7079 unsigned sd
= uimm (aarch64_get_instr (cpu
), 4, 0);
7081 aarch64_set_FP_float (cpu
, sd
, (float) aarch64_get_FP_double (cpu
, sn
));
7084 /* Convert float to double. */
7086 fcvtcpu (sim_cpu
*cpu
)
7088 unsigned sn
= uimm (aarch64_get_instr (cpu
), 9, 5);
7089 unsigned sd
= uimm (aarch64_get_instr (cpu
), 4, 0);
7091 aarch64_set_FP_double (cpu
, sd
, (double) aarch64_get_FP_float (cpu
, sn
));
7095 do_FRINT (sim_cpu
*cpu
)
7097 /* instr[31,23] = 0001 1110 0
7098 instr[22] = single(0)/double(1)
7100 instr[17,15] = rounding mode
7101 instr[14,10] = 10000
7103 instr[4,0] = dest */
7106 unsigned rs
= uimm (aarch64_get_instr (cpu
), 9, 5);
7107 unsigned rd
= uimm (aarch64_get_instr (cpu
), 4, 0);
7108 unsigned int rmode
= uimm (aarch64_get_instr (cpu
), 17, 15);
7110 NYI_assert (31, 23, 0x03C);
7111 NYI_assert (21, 18, 0x9);
7112 NYI_assert (14, 10, 0x10);
7114 if (rmode
== 6 || rmode
== 7)
7115 /* FIXME: Add support for rmode == 6 exactness check. */
7116 rmode
= uimm (aarch64_get_FPSR (cpu
), 23, 22);
7118 if (uimm (aarch64_get_instr (cpu
), 22, 22))
7120 double val
= aarch64_get_FP_double (cpu
, rs
);
7124 case 0: /* mode N: nearest or even. */
7126 double rval
= round (val
);
7128 if (val
- rval
== 0.5)
7130 if (((rval
/ 2.0) * 2.0) != rval
)
7134 aarch64_set_FP_double (cpu
, rd
, round (val
));
7138 case 1: /* mode P: towards +inf. */
7140 aarch64_set_FP_double (cpu
, rd
, trunc (val
));
7142 aarch64_set_FP_double (cpu
, rd
, round (val
));
7145 case 2: /* mode M: towards -inf. */
7147 aarch64_set_FP_double (cpu
, rd
, round (val
));
7149 aarch64_set_FP_double (cpu
, rd
, trunc (val
));
7152 case 3: /* mode Z: towards 0. */
7153 aarch64_set_FP_double (cpu
, rd
, trunc (val
));
7156 case 4: /* mode A: away from 0. */
7157 aarch64_set_FP_double (cpu
, rd
, round (val
));
7160 case 6: /* mode X: use FPCR with exactness check. */
7161 case 7: /* mode I: use FPCR mode. */
7169 val
= aarch64_get_FP_float (cpu
, rs
);
7173 case 0: /* mode N: nearest or even. */
7175 float rval
= roundf (val
);
7177 if (val
- rval
== 0.5)
7179 if (((rval
/ 2.0) * 2.0) != rval
)
7183 aarch64_set_FP_float (cpu
, rd
, rval
);
7187 case 1: /* mode P: towards +inf. */
7189 aarch64_set_FP_float (cpu
, rd
, truncf (val
));
7191 aarch64_set_FP_float (cpu
, rd
, roundf (val
));
7194 case 2: /* mode M: towards -inf. */
7196 aarch64_set_FP_float (cpu
, rd
, truncf (val
));
7198 aarch64_set_FP_float (cpu
, rd
, roundf (val
));
7201 case 3: /* mode Z: towards 0. */
7202 aarch64_set_FP_float (cpu
, rd
, truncf (val
));
7205 case 4: /* mode A: away from 0. */
7206 aarch64_set_FP_float (cpu
, rd
, roundf (val
));
7209 case 6: /* mode X: use FPCR with exactness check. */
7210 case 7: /* mode I: use FPCR mode. */
7219 dexSimpleFPDataProc1Source (sim_cpu
*cpu
)
7221 /* instr[31] ==> M : 0 ==> OK, 1 ==> UNALLOC
7223 instr[29] ==> S : 0 ==> OK, 1 ==> UNALLOC
7226 instr[23,22] ==> type : 00 ==> source is single,
7227 01 ==> source is double
7229 11 ==> UNALLOC or source is half
7231 instr[20,15] ==> opcode : with type 00 or 01
7232 000000 ==> FMOV, 000001 ==> FABS,
7233 000010 ==> FNEG, 000011 ==> FSQRT,
7234 000100 ==> UNALLOC, 000101 ==> FCVT,(to single/double)
7235 000110 ==> UNALLOC, 000111 ==> FCVT (to half)
7236 001000 ==> FRINTN, 001001 ==> FRINTP,
7237 001010 ==> FRINTM, 001011 ==> FRINTZ,
7238 001100 ==> FRINTA, 001101 ==> UNALLOC
7239 001110 ==> FRINTX, 001111 ==> FRINTI
7241 000100 ==> FCVT (half-to-single)
7242 000101 ==> FCVT (half-to-double)
7243 instr[14,10] = 10000. */
7245 uint32_t M_S
= (uimm (aarch64_get_instr (cpu
), 31, 31) << 1)
7246 | uimm (aarch64_get_instr (cpu
), 29, 29);
7247 uint32_t type
= uimm (aarch64_get_instr (cpu
), 23, 22);
7248 uint32_t opcode
= uimm (aarch64_get_instr (cpu
), 20, 15);
7255 if (opcode
== 4 || opcode
== 5)
7307 case 8: /* FRINTN etc. */
7317 case 7: /* FCVT double/single to half precision. */
7326 /* 32 bit signed int to float. */
7328 scvtf32 (sim_cpu
*cpu
)
7330 unsigned rn
= uimm (aarch64_get_instr (cpu
), 9, 5);
7331 unsigned sd
= uimm (aarch64_get_instr (cpu
), 4, 0);
7333 aarch64_set_FP_float
7334 (cpu
, sd
, (float) aarch64_get_reg_s32 (cpu
, rn
, NO_SP
));
7337 /* signed int to float. */
7339 scvtf (sim_cpu
*cpu
)
7341 unsigned rn
= uimm (aarch64_get_instr (cpu
), 9, 5);
7342 unsigned sd
= uimm (aarch64_get_instr (cpu
), 4, 0);
7344 aarch64_set_FP_float
7345 (cpu
, sd
, (float) aarch64_get_reg_s64 (cpu
, rn
, NO_SP
));
7348 /* 32 bit signed int to double. */
7350 scvtd32 (sim_cpu
*cpu
)
7352 unsigned rn
= uimm (aarch64_get_instr (cpu
), 9, 5);
7353 unsigned sd
= uimm (aarch64_get_instr (cpu
), 4, 0);
7355 aarch64_set_FP_double
7356 (cpu
, sd
, (double) aarch64_get_reg_s32 (cpu
, rn
, NO_SP
));
7359 /* signed int to double. */
7361 scvtd (sim_cpu
*cpu
)
7363 unsigned rn
= uimm (aarch64_get_instr (cpu
), 9, 5);
7364 unsigned sd
= uimm (aarch64_get_instr (cpu
), 4, 0);
7366 aarch64_set_FP_double
7367 (cpu
, sd
, (double) aarch64_get_reg_s64 (cpu
, rn
, NO_SP
));
7370 static const float FLOAT_INT_MAX
= (float) INT_MAX
;
7371 static const float FLOAT_INT_MIN
= (float) INT_MIN
;
7372 static const double DOUBLE_INT_MAX
= (double) INT_MAX
;
7373 static const double DOUBLE_INT_MIN
= (double) INT_MIN
;
7374 static const float FLOAT_LONG_MAX
= (float) LONG_MAX
;
7375 static const float FLOAT_LONG_MIN
= (float) LONG_MIN
;
7376 static const double DOUBLE_LONG_MAX
= (double) LONG_MAX
;
7377 static const double DOUBLE_LONG_MIN
= (double) LONG_MIN
;
7379 /* Check for FP exception conditions:
7382 Out of Range raises IO and IX and saturates value
7383 Denormal raises ID and IX and sets to zero. */
7384 #define RAISE_EXCEPTIONS(F, VALUE, FTYPE, ITYPE) \
7387 switch (fpclassify (F)) \
7391 aarch64_set_FPSR (cpu, IO); \
7393 VALUE = ITYPE##_MAX; \
7395 VALUE = ITYPE##_MIN; \
7399 if (F >= FTYPE##_##ITYPE##_MAX) \
7401 aarch64_set_FPSR_bits (cpu, IO | IX, IO | IX); \
7402 VALUE = ITYPE##_MAX; \
7404 else if (F <= FTYPE##_##ITYPE##_MIN) \
7406 aarch64_set_FPSR_bits (cpu, IO | IX, IO | IX); \
7407 VALUE = ITYPE##_MIN; \
7411 case FP_SUBNORMAL: \
7412 aarch64_set_FPSR_bits (cpu, IO | IX | ID, IX | ID); \
7424 /* 32 bit convert float to signed int truncate towards zero. */
7426 fcvtszs32 (sim_cpu
*cpu
)
7428 unsigned sn
= uimm (aarch64_get_instr (cpu
), 9, 5);
7429 unsigned rd
= uimm (aarch64_get_instr (cpu
), 4, 0);
7430 /* TODO : check that this rounds toward zero. */
7431 float f
= aarch64_get_FP_float (cpu
, sn
);
7432 int32_t value
= (int32_t) f
;
7434 RAISE_EXCEPTIONS (f
, value
, FLOAT
, INT
);
7436 /* Avoid sign extension to 64 bit. */
7437 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, (uint32_t) value
);
7440 /* 64 bit convert float to signed int truncate towards zero. */
7442 fcvtszs (sim_cpu
*cpu
)
7444 unsigned sn
= uimm (aarch64_get_instr (cpu
), 9, 5);
7445 unsigned rd
= uimm (aarch64_get_instr (cpu
), 4, 0);
7446 float f
= aarch64_get_FP_float (cpu
, sn
);
7447 int64_t value
= (int64_t) f
;
7449 RAISE_EXCEPTIONS (f
, value
, FLOAT
, LONG
);
7451 aarch64_set_reg_s64 (cpu
, rd
, NO_SP
, value
);
7454 /* 32 bit convert double to signed int truncate towards zero. */
7456 fcvtszd32 (sim_cpu
*cpu
)
7458 unsigned sn
= uimm (aarch64_get_instr (cpu
), 9, 5);
7459 unsigned rd
= uimm (aarch64_get_instr (cpu
), 4, 0);
7460 /* TODO : check that this rounds toward zero. */
7461 double d
= aarch64_get_FP_double (cpu
, sn
);
7462 int32_t value
= (int32_t) d
;
7464 RAISE_EXCEPTIONS (d
, value
, DOUBLE
, INT
);
7466 /* Avoid sign extension to 64 bit. */
7467 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, (uint32_t) value
);
7470 /* 64 bit convert double to signed int truncate towards zero. */
7472 fcvtszd (sim_cpu
*cpu
)
7474 unsigned sn
= uimm (aarch64_get_instr (cpu
), 9, 5);
7475 unsigned rd
= uimm (aarch64_get_instr (cpu
), 4, 0);
7476 /* TODO : check that this rounds toward zero. */
7477 double d
= aarch64_get_FP_double (cpu
, sn
);
7480 value
= (int64_t) d
;
7482 RAISE_EXCEPTIONS (d
, value
, DOUBLE
, LONG
);
7484 aarch64_set_reg_s64 (cpu
, rd
, NO_SP
, value
);
7488 do_fcvtzu (sim_cpu
*cpu
)
7490 /* instr[31] = size: 32-bit (0), 64-bit (1)
7491 instr[30,23] = 00111100
7492 instr[22] = type: single (0)/ double (1)
7493 instr[21] = enable (0)/disable(1) precision
7494 instr[20,16] = 11001
7495 instr[15,10] = precision
7499 unsigned rs
= uimm (aarch64_get_instr (cpu
), 9, 5);
7500 unsigned rd
= uimm (aarch64_get_instr (cpu
), 4, 0);
7502 NYI_assert (30, 23, 0x3C);
7503 NYI_assert (20, 16, 0x19);
7505 if (uimm (aarch64_get_instr (cpu
), 21, 21) != 1)
7506 /* Convert to fixed point. */
7509 if (uimm (aarch64_get_instr (cpu
), 31, 31))
7511 /* Convert to unsigned 64-bit integer. */
7512 if (uimm (aarch64_get_instr (cpu
), 22, 22))
7514 double d
= aarch64_get_FP_double (cpu
, rs
);
7515 uint64_t value
= (uint64_t) d
;
7517 /* Do not raise an exception if we have reached ULONG_MAX. */
7518 if (value
!= (1UL << 63))
7519 RAISE_EXCEPTIONS (d
, value
, DOUBLE
, LONG
);
7521 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, value
);
7525 float f
= aarch64_get_FP_float (cpu
, rs
);
7526 uint64_t value
= (uint64_t) f
;
7528 /* Do not raise an exception if we have reached ULONG_MAX. */
7529 if (value
!= (1UL << 63))
7530 RAISE_EXCEPTIONS (f
, value
, FLOAT
, LONG
);
7532 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, value
);
7539 /* Convert to unsigned 32-bit integer. */
7540 if (uimm (aarch64_get_instr (cpu
), 22, 22))
7542 double d
= aarch64_get_FP_double (cpu
, rs
);
7544 value
= (uint32_t) d
;
7545 /* Do not raise an exception if we have reached UINT_MAX. */
7546 if (value
!= (1UL << 31))
7547 RAISE_EXCEPTIONS (d
, value
, DOUBLE
, INT
);
7551 float f
= aarch64_get_FP_float (cpu
, rs
);
7553 value
= (uint32_t) f
;
7554 /* Do not raise an exception if we have reached UINT_MAX. */
7555 if (value
!= (1UL << 31))
7556 RAISE_EXCEPTIONS (f
, value
, FLOAT
, INT
);
7559 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, value
);
7564 do_UCVTF (sim_cpu
*cpu
)
7566 /* instr[31] = size: 32-bit (0), 64-bit (1)
7567 instr[30,23] = 001 1110 0
7568 instr[22] = type: single (0)/ double (1)
7569 instr[21] = enable (0)/disable(1) precision
7570 instr[20,16] = 0 0011
7571 instr[15,10] = precision
7575 unsigned rs
= uimm (aarch64_get_instr (cpu
), 9, 5);
7576 unsigned rd
= uimm (aarch64_get_instr (cpu
), 4, 0);
7578 NYI_assert (30, 23, 0x3C);
7579 NYI_assert (20, 16, 0x03);
7581 if (uimm (aarch64_get_instr (cpu
), 21, 21) != 1)
7584 /* FIXME: Add exception raising. */
7585 if (uimm (aarch64_get_instr (cpu
), 31, 31))
7587 uint64_t value
= aarch64_get_reg_u64 (cpu
, rs
, NO_SP
);
7589 if (uimm (aarch64_get_instr (cpu
), 22, 22))
7590 aarch64_set_FP_double (cpu
, rd
, (double) value
);
7592 aarch64_set_FP_float (cpu
, rd
, (float) value
);
7596 uint32_t value
= aarch64_get_reg_u32 (cpu
, rs
, NO_SP
);
7598 if (uimm (aarch64_get_instr (cpu
), 22, 22))
7599 aarch64_set_FP_double (cpu
, rd
, (double) value
);
7601 aarch64_set_FP_float (cpu
, rd
, (float) value
);
7606 float_vector_move (sim_cpu
*cpu
)
7608 /* instr[31,17] == 100 1111 0101 0111
7609 instr[16] ==> direction 0=> to GR, 1=> from GR
7611 instr[9,5] ==> source
7612 instr[4,0] ==> dest. */
7614 unsigned rn
= uimm (aarch64_get_instr (cpu
), 9, 5);
7615 unsigned rd
= uimm (aarch64_get_instr (cpu
), 4, 0);
7617 NYI_assert (31, 17, 0x4F57);
7619 if (uimm (aarch64_get_instr (cpu
), 15, 10) != 0)
7622 if (uimm (aarch64_get_instr (cpu
), 16, 16))
7623 aarch64_set_vec_u64 (cpu
, rd
, 1, aarch64_get_reg_u64 (cpu
, rn
, NO_SP
));
7625 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, aarch64_get_vec_u64 (cpu
, rn
, 1));
7629 dexSimpleFPIntegerConvert (sim_cpu
*cpu
)
7631 /* instr[31] = size : 0 ==> 32 bit, 1 ==> 64 bit
7633 instr[29] = S : 0 ==> OK, 1 ==> UNALLOC
7636 instr[23,22] = type : 00 ==> single, 01 ==> double, 1x ==> UNALLOC
7638 instr[20,19] = rmode
7639 instr[18,16] = opcode
7640 instr[15,10] = 10 0000 */
7642 uint32_t rmode_opcode
;
7648 if (uimm (aarch64_get_instr (cpu
), 31, 17) == 0x4F57)
7650 float_vector_move (cpu
);
7654 size
= uimm (aarch64_get_instr (cpu
), 31, 31);
7655 S
= uimm (aarch64_get_instr (cpu
), 29, 29);
7659 type
= uimm (aarch64_get_instr (cpu
), 23, 22);
7663 rmode_opcode
= uimm (aarch64_get_instr (cpu
), 20, 16);
7664 size_type
= (size
<< 1) | type
; /* 0==32f, 1==32d, 2==64f, 3==64d. */
7666 switch (rmode_opcode
)
7668 case 2: /* SCVTF. */
7671 case 0: scvtf32 (cpu
); return;
7672 case 1: scvtd32 (cpu
); return;
7673 case 2: scvtf (cpu
); return;
7674 case 3: scvtd (cpu
); return;
7679 case 6: /* FMOV GR, Vec. */
7682 case 0: gfmovs (cpu
); return;
7683 case 3: gfmovd (cpu
); return;
7684 default: HALT_UNALLOC
;
7687 case 7: /* FMOV vec, GR. */
7690 case 0: fgmovs (cpu
); return;
7691 case 3: fgmovd (cpu
); return;
7692 default: HALT_UNALLOC
;
7695 case 24: /* FCVTZS. */
7698 case 0: fcvtszs32 (cpu
); return;
7699 case 1: fcvtszd32 (cpu
); return;
7700 case 2: fcvtszs (cpu
); return;
7701 case 3: fcvtszd (cpu
); return;
7702 default: HALT_UNREACHABLE
;
7705 case 25: do_fcvtzu (cpu
); return;
7706 case 3: do_UCVTF (cpu
); return;
7708 case 0: /* FCVTNS. */
7709 case 1: /* FCVTNU. */
7710 case 4: /* FCVTAS. */
7711 case 5: /* FCVTAU. */
7712 case 8: /* FCVPTS. */
7713 case 9: /* FCVTPU. */
7714 case 16: /* FCVTMS. */
7715 case 17: /* FCVTMU. */
7722 set_flags_for_float_compare (sim_cpu
*cpu
, float fvalue1
, float fvalue2
)
7726 if (isnan (fvalue1
) || isnan (fvalue2
))
7730 float result
= fvalue1
- fvalue2
;
7734 else if (result
< 0)
7736 else /* (result > 0). */
7740 aarch64_set_CPSR (cpu
, flags
);
7744 fcmps (sim_cpu
*cpu
)
7746 unsigned sm
= uimm (aarch64_get_instr (cpu
), 20, 16);
7747 unsigned sn
= uimm (aarch64_get_instr (cpu
), 9, 5);
7749 float fvalue1
= aarch64_get_FP_float (cpu
, sn
);
7750 float fvalue2
= aarch64_get_FP_float (cpu
, sm
);
7752 set_flags_for_float_compare (cpu
, fvalue1
, fvalue2
);
7755 /* Float compare to zero -- Invalid Operation exception
7756 only on signaling NaNs. */
7758 fcmpzs (sim_cpu
*cpu
)
7760 unsigned sn
= uimm (aarch64_get_instr (cpu
), 9, 5);
7761 float fvalue1
= aarch64_get_FP_float (cpu
, sn
);
7763 set_flags_for_float_compare (cpu
, fvalue1
, 0.0f
);
7766 /* Float compare -- Invalid Operation exception on all NaNs. */
7768 fcmpes (sim_cpu
*cpu
)
7770 unsigned sm
= uimm (aarch64_get_instr (cpu
), 20, 16);
7771 unsigned sn
= uimm (aarch64_get_instr (cpu
), 9, 5);
7773 float fvalue1
= aarch64_get_FP_float (cpu
, sn
);
7774 float fvalue2
= aarch64_get_FP_float (cpu
, sm
);
7776 set_flags_for_float_compare (cpu
, fvalue1
, fvalue2
);
7779 /* Float compare to zero -- Invalid Operation exception on all NaNs. */
7781 fcmpzes (sim_cpu
*cpu
)
7783 unsigned sn
= uimm (aarch64_get_instr (cpu
), 9, 5);
7784 float fvalue1
= aarch64_get_FP_float (cpu
, sn
);
7786 set_flags_for_float_compare (cpu
, fvalue1
, 0.0f
);
7790 set_flags_for_double_compare (sim_cpu
*cpu
, double dval1
, double dval2
)
7794 if (isnan (dval1
) || isnan (dval2
))
7798 double result
= dval1
- dval2
;
7802 else if (result
< 0)
7804 else /* (result > 0). */
7808 aarch64_set_CPSR (cpu
, flags
);
7811 /* Double compare -- Invalid Operation exception only on signaling NaNs. */
7813 fcmpd (sim_cpu
*cpu
)
7815 unsigned sm
= uimm (aarch64_get_instr (cpu
), 20, 16);
7816 unsigned sn
= uimm (aarch64_get_instr (cpu
), 9, 5);
7818 double dvalue1
= aarch64_get_FP_double (cpu
, sn
);
7819 double dvalue2
= aarch64_get_FP_double (cpu
, sm
);
7821 set_flags_for_double_compare (cpu
, dvalue1
, dvalue2
);
7824 /* Double compare to zero -- Invalid Operation exception
7825 only on signaling NaNs. */
7827 fcmpzd (sim_cpu
*cpu
)
7829 unsigned sn
= uimm (aarch64_get_instr (cpu
), 9, 5);
7830 double dvalue1
= aarch64_get_FP_double (cpu
, sn
);
7832 set_flags_for_double_compare (cpu
, dvalue1
, 0.0);
7835 /* Double compare -- Invalid Operation exception on all NaNs. */
7837 fcmped (sim_cpu
*cpu
)
7839 unsigned sm
= uimm (aarch64_get_instr (cpu
), 20, 16);
7840 unsigned sn
= uimm (aarch64_get_instr (cpu
), 9, 5);
7842 double dvalue1
= aarch64_get_FP_double (cpu
, sn
);
7843 double dvalue2
= aarch64_get_FP_double (cpu
, sm
);
7845 set_flags_for_double_compare (cpu
, dvalue1
, dvalue2
);
7848 /* Double compare to zero -- Invalid Operation exception on all NaNs. */
7850 fcmpzed (sim_cpu
*cpu
)
7852 unsigned sn
= uimm (aarch64_get_instr (cpu
), 9, 5);
7853 double dvalue1
= aarch64_get_FP_double (cpu
, sn
);
7855 set_flags_for_double_compare (cpu
, dvalue1
, 0.0);
7859 dexSimpleFPCompare (sim_cpu
*cpu
)
7861 /* assert instr[28,25] == 1111
7862 instr[30:24:21:13,10] = 0011000
7863 instr[31] = M : 0 ==> OK, 1 ==> UNALLOC
7864 instr[29] ==> S : 0 ==> OK, 1 ==> UNALLOC
7865 instr[23,22] ==> type : 0 ==> single, 01 ==> double, 1x ==> UNALLOC
7866 instr[15,14] ==> op : 00 ==> OK, ow ==> UNALLOC
7867 instr[4,0] ==> opcode2 : 00000 ==> FCMP, 10000 ==> FCMPE,
7868 01000 ==> FCMPZ, 11000 ==> FCMPEZ,
7871 uint32_t M_S
= (uimm (aarch64_get_instr (cpu
), 31, 31) << 1)
7872 | uimm (aarch64_get_instr (cpu
), 29, 29);
7873 uint32_t type
= uimm (aarch64_get_instr (cpu
), 23, 22);
7874 uint32_t op
= uimm (aarch64_get_instr (cpu
), 15, 14);
7875 uint32_t op2_2_0
= uimm (aarch64_get_instr (cpu
), 2, 0);
7889 /* dispatch on type and top 2 bits of opcode. */
7890 dispatch
= (type
<< 2) | uimm (aarch64_get_instr (cpu
), 4, 3);
7894 case 0: fcmps (cpu
); return;
7895 case 1: fcmpzs (cpu
); return;
7896 case 2: fcmpes (cpu
); return;
7897 case 3: fcmpzes (cpu
); return;
7898 case 4: fcmpd (cpu
); return;
7899 case 5: fcmpzd (cpu
); return;
7900 case 6: fcmped (cpu
); return;
7901 case 7: fcmpzed (cpu
); return;
7902 default: HALT_UNREACHABLE
;
7907 do_scalar_FADDP (sim_cpu
*cpu
)
7909 /* instr [31,23] = 011111100
7910 instr [22] = single(0)/double(1)
7911 instr [21,10] = 1100 0011 0110
7913 instr [4,0] = Fd. */
7915 unsigned Fn
= uimm (aarch64_get_instr (cpu
), 9, 5);
7916 unsigned Fd
= uimm (aarch64_get_instr (cpu
), 4, 0);
7918 NYI_assert (31, 23, 0x0FC);
7919 NYI_assert (21, 10, 0xC36);
7921 if (uimm (aarch64_get_instr (cpu
), 22, 22))
7923 double val1
= aarch64_get_vec_double (cpu
, Fn
, 0);
7924 double val2
= aarch64_get_vec_double (cpu
, Fn
, 1);
7926 aarch64_set_FP_double (cpu
, Fd
, val1
+ val2
);
7930 float val1
= aarch64_get_vec_float (cpu
, Fn
, 0);
7931 float val2
= aarch64_get_vec_float (cpu
, Fn
, 1);
7933 aarch64_set_FP_float (cpu
, Fd
, val1
+ val2
);
7937 /* Floating point absolute difference. */
7940 do_scalar_FABD (sim_cpu
*cpu
)
7942 /* instr [31,23] = 0111 1110 1
7943 instr [22] = float(0)/double(1)
7946 instr [15,10] = 1101 01
7948 instr [4, 0] = Rd. */
7950 unsigned rm
= uimm (aarch64_get_instr (cpu
), 20, 16);
7951 unsigned rn
= uimm (aarch64_get_instr (cpu
), 9, 5);
7952 unsigned rd
= uimm (aarch64_get_instr (cpu
), 4, 0);
7954 NYI_assert (31, 23, 0x0FD);
7955 NYI_assert (21, 21, 1);
7956 NYI_assert (15, 10, 0x35);
7958 if (uimm (aarch64_get_instr (cpu
), 22, 22))
7959 aarch64_set_FP_double (cpu
, rd
,
7960 fabs (aarch64_get_FP_double (cpu
, rn
)
7961 - aarch64_get_FP_double (cpu
, rm
)));
7963 aarch64_set_FP_float (cpu
, rd
,
7964 fabsf (aarch64_get_FP_float (cpu
, rn
)
7965 - aarch64_get_FP_float (cpu
, rm
)));
7969 do_scalar_CMGT (sim_cpu
*cpu
)
7971 /* instr [31,21] = 0101 1110 111
7973 instr [15,10] = 00 1101
7975 instr [4, 0] = Rd. */
7977 unsigned rm
= uimm (aarch64_get_instr (cpu
), 20, 16);
7978 unsigned rn
= uimm (aarch64_get_instr (cpu
), 9, 5);
7979 unsigned rd
= uimm (aarch64_get_instr (cpu
), 4, 0);
7981 NYI_assert (31, 21, 0x2F7);
7982 NYI_assert (15, 10, 0x0D);
7984 aarch64_set_vec_u64 (cpu
, rd
, 0,
7985 aarch64_get_vec_u64 (cpu
, rn
, 0) >
7986 aarch64_get_vec_u64 (cpu
, rm
, 0) ? -1L : 0L);
7990 do_scalar_USHR (sim_cpu
*cpu
)
7992 /* instr [31,23] = 0111 1111 0
7993 instr [22,16] = shift amount
7994 instr [15,10] = 0000 01
7996 instr [4, 0] = Rd. */
7998 unsigned amount
= 128 - uimm (aarch64_get_instr (cpu
), 22, 16);
7999 unsigned rn
= uimm (aarch64_get_instr (cpu
), 9, 5);
8000 unsigned rd
= uimm (aarch64_get_instr (cpu
), 4, 0);
8002 NYI_assert (31, 23, 0x0FE);
8003 NYI_assert (15, 10, 0x01);
8005 aarch64_set_vec_u64 (cpu
, rd
, 0,
8006 aarch64_get_vec_u64 (cpu
, rn
, 0) >> amount
);
8010 do_scalar_SHL (sim_cpu
*cpu
)
8012 /* instr [31,23] = 0111 1101 0
8013 instr [22,16] = shift amount
8014 instr [15,10] = 0101 01
8016 instr [4, 0] = Rd. */
8018 unsigned amount
= uimm (aarch64_get_instr (cpu
), 22, 16) - 64;
8019 unsigned rn
= uimm (aarch64_get_instr (cpu
), 9, 5);
8020 unsigned rd
= uimm (aarch64_get_instr (cpu
), 4, 0);
8022 NYI_assert (31, 23, 0x0BE);
8023 NYI_assert (15, 10, 0x15);
8025 if (uimm (aarch64_get_instr (cpu
), 22, 22) == 0)
8028 aarch64_set_vec_u64 (cpu
, rd
, 0,
8029 aarch64_get_vec_u64 (cpu
, rn
, 0) << amount
);
8032 /* FCMEQ FCMGT FCMGE. */
8034 do_scalar_FCM (sim_cpu
*cpu
)
8036 /* instr [31,30] = 01
8038 instr [28,24] = 1 1110
8043 instr [15,12] = 1110
8047 instr [4, 0] = Rd. */
8049 unsigned rm
= uimm (aarch64_get_instr (cpu
), 20, 16);
8050 unsigned rn
= uimm (aarch64_get_instr (cpu
), 9, 5);
8051 unsigned rd
= uimm (aarch64_get_instr (cpu
), 4, 0);
8052 unsigned EUac
= (uimm (aarch64_get_instr (cpu
), 23, 23) << 2)
8053 | (uimm (aarch64_get_instr (cpu
), 29, 29) << 1)
8054 | uimm (aarch64_get_instr (cpu
), 11, 11);
8059 NYI_assert (31, 30, 1);
8060 NYI_assert (28, 24, 0x1E);
8061 NYI_assert (21, 21, 1);
8062 NYI_assert (15, 12, 0xE);
8063 NYI_assert (10, 10, 1);
8065 if (uimm (aarch64_get_instr (cpu
), 22, 22))
8067 double val1
= aarch64_get_FP_double (cpu
, rn
);
8068 double val2
= aarch64_get_FP_double (cpu
, rm
);
8073 result
= val1
== val2
;
8081 result
= val1
>= val2
;
8089 result
= val1
> val2
;
8096 aarch64_set_vec_u32 (cpu
, rd
, 0, result
? -1 : 0);
8100 val1
= aarch64_get_FP_float (cpu
, rn
);
8101 val2
= aarch64_get_FP_float (cpu
, rm
);
8106 result
= val1
== val2
;
8110 val1
= fabsf (val1
);
8111 val2
= fabsf (val2
);
8114 result
= val1
>= val2
;
8118 val1
= fabsf (val1
);
8119 val2
= fabsf (val2
);
8122 result
= val1
> val2
;
8129 aarch64_set_vec_u32 (cpu
, rd
, 0, result
? -1 : 0);
8132 /* An alias of DUP. */
8134 do_scalar_MOV (sim_cpu
*cpu
)
8136 /* instr [31,21] = 0101 1110 000
8137 instr [20,16] = imm5
8138 instr [15,10] = 0000 01
8140 instr [4, 0] = Rd. */
8142 unsigned rn
= uimm (aarch64_get_instr (cpu
), 9, 5);
8143 unsigned rd
= uimm (aarch64_get_instr (cpu
), 4, 0);
8146 NYI_assert (31, 21, 0x2F0);
8147 NYI_assert (15, 10, 0x01);
8149 if (uimm (aarch64_get_instr (cpu
), 16, 16))
8152 index
= uimm (aarch64_get_instr (cpu
), 20, 17);
8154 (cpu
, rd
, 0, aarch64_get_vec_u8 (cpu
, rn
, index
));
8156 else if (uimm (aarch64_get_instr (cpu
), 17, 17))
8159 index
= uimm (aarch64_get_instr (cpu
), 20, 18);
8161 (cpu
, rd
, 0, aarch64_get_vec_u16 (cpu
, rn
, index
));
8163 else if (uimm (aarch64_get_instr (cpu
), 18, 18))
8166 index
= uimm (aarch64_get_instr (cpu
), 20, 19);
8168 (cpu
, rd
, 0, aarch64_get_vec_u32 (cpu
, rn
, index
));
8170 else if (uimm (aarch64_get_instr (cpu
), 19, 19))
8173 index
= uimm (aarch64_get_instr (cpu
), 20, 20);
8175 (cpu
, rd
, 0, aarch64_get_vec_u64 (cpu
, rn
, index
));
8182 do_double_add (sim_cpu
*cpu
)
8184 /* instr [28,25] = 1111. */
8191 switch (uimm (aarch64_get_instr (cpu
), 31, 23))
8194 switch (uimm (aarch64_get_instr (cpu
), 15, 10))
8196 case 0x01: do_scalar_MOV (cpu
); return;
8197 case 0x39: do_scalar_FCM (cpu
); return;
8198 case 0x3B: do_scalar_FCM (cpu
); return;
8202 case 0xBE: do_scalar_SHL (cpu
); return;
8205 switch (uimm (aarch64_get_instr (cpu
), 15, 10))
8207 case 0x36: do_scalar_FADDP (cpu
); return;
8208 case 0x39: do_scalar_FCM (cpu
); return;
8209 case 0x3B: do_scalar_FCM (cpu
); return;
8214 switch (uimm (aarch64_get_instr (cpu
), 15, 10))
8216 case 0x0D: do_scalar_CMGT (cpu
); return;
8217 case 0x35: do_scalar_FABD (cpu
); return;
8218 case 0x39: do_scalar_FCM (cpu
); return;
8219 case 0x3B: do_scalar_FCM (cpu
); return;
8224 case 0xFE: do_scalar_USHR (cpu
); return;
8229 /* instr [31,21] = 0101 1110 111
8231 instr [15,10] = 1000 01
8233 instr [4,0] = Fd. */
8234 if (uimm (aarch64_get_instr (cpu
), 31, 21) != 0x2F7
8235 || uimm (aarch64_get_instr (cpu
), 15, 10) != 0x21)
8238 Fd
= uimm (aarch64_get_instr (cpu
), 4, 0);
8239 Fm
= uimm (aarch64_get_instr (cpu
), 9, 5);
8240 Fn
= uimm (aarch64_get_instr (cpu
), 20, 16);
8242 val1
= aarch64_get_FP_double (cpu
, Fm
);
8243 val2
= aarch64_get_FP_double (cpu
, Fn
);
8245 aarch64_set_FP_double (cpu
, Fd
, val1
+ val2
);
8249 dexAdvSIMD1 (sim_cpu
*cpu
)
8251 /* instr [28,25] = 1 111. */
8253 /* we are currently only interested in the basic
8254 scalar fp routines which all have bit 30 = 0. */
8255 if (uimm (aarch64_get_instr (cpu
), 30, 30))
8256 do_double_add (cpu
);
8258 /* instr[24] is set for FP data processing 3-source and clear for
8259 all other basic scalar fp instruction groups. */
8260 else if (uimm (aarch64_get_instr (cpu
), 24, 24))
8261 dexSimpleFPDataProc3Source (cpu
);
8263 /* instr[21] is clear for floating <-> fixed conversions and set for
8264 all other basic scalar fp instruction groups. */
8265 else if (!uimm (aarch64_get_instr (cpu
), 21, 21))
8266 dexSimpleFPFixedConvert (cpu
);
8268 /* instr[11,10] : 01 ==> cond compare, 10 ==> Data Proc 2 Source
8269 11 ==> cond select, 00 ==> other. */
8271 switch (uimm (aarch64_get_instr (cpu
), 11, 10))
8273 case 1: dexSimpleFPCondCompare (cpu
); return;
8274 case 2: dexSimpleFPDataProc2Source (cpu
); return;
8275 case 3: dexSimpleFPCondSelect (cpu
); return;
8278 /* Now an ordered cascade of tests.
8279 FP immediate has aarch64_get_instr (cpu)[12] == 1.
8280 FP compare has aarch64_get_instr (cpu)[13] == 1.
8281 FP Data Proc 1 Source has aarch64_get_instr (cpu)[14] == 1.
8282 FP floating <--> integer conversions has aarch64_get_instr (cpu)[15] == 0. */
8283 if (uimm (aarch64_get_instr (cpu
), 12, 12))
8284 dexSimpleFPImmediate (cpu
);
8286 else if (uimm (aarch64_get_instr (cpu
), 13, 13))
8287 dexSimpleFPCompare (cpu
);
8289 else if (uimm (aarch64_get_instr (cpu
), 14, 14))
8290 dexSimpleFPDataProc1Source (cpu
);
8292 else if (!uimm (aarch64_get_instr (cpu
), 15, 15))
8293 dexSimpleFPIntegerConvert (cpu
);
8296 /* If we get here then instr[15] == 1 which means UNALLOC. */
8301 /* PC relative addressing. */
8304 pcadr (sim_cpu
*cpu
)
8306 /* instr[31] = op : 0 ==> ADR, 1 ==> ADRP
8307 instr[30,29] = immlo
8308 instr[23,5] = immhi. */
8310 unsigned rd
= uimm (aarch64_get_instr (cpu
), 4, 0);
8311 uint32_t isPage
= uimm (aarch64_get_instr (cpu
), 31, 31);
8312 union { int64_t u64
; uint64_t s64
; } imm
;
8315 imm
.s64
= simm64 (aarch64_get_instr (cpu
), 23, 5);
8317 offset
= (offset
<< 2) | uimm (aarch64_get_instr (cpu
), 30, 29);
8319 address
= aarch64_get_PC (cpu
);
8327 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, address
+ offset
);
8330 /* Specific decode and execute for group Data Processing Immediate. */
8333 dexPCRelAddressing (sim_cpu
*cpu
)
8335 /* assert instr[28,24] = 10000. */
8339 /* Immediate logical.
8340 The bimm32/64 argument is constructed by replicating a 2, 4, 8,
8341 16, 32 or 64 bit sequence pulled out at decode and possibly
8344 N.B. the output register (dest) can normally be Xn or SP
8345 the exception occurs for flag setting instructions which may
8346 only use Xn for the output (dest). The input register can
8349 /* 32 bit and immediate. */
8351 and32 (sim_cpu
*cpu
, uint32_t bimm
)
8353 unsigned rn
= uimm (aarch64_get_instr (cpu
), 9, 5);
8354 unsigned rd
= uimm (aarch64_get_instr (cpu
), 4, 0);
8356 aarch64_set_reg_u64 (cpu
, rd
, SP_OK
,
8357 aarch64_get_reg_u32 (cpu
, rn
, NO_SP
) & bimm
);
8360 /* 64 bit and immediate. */
8362 and64 (sim_cpu
*cpu
, uint64_t bimm
)
8364 unsigned rn
= uimm (aarch64_get_instr (cpu
), 9, 5);
8365 unsigned rd
= uimm (aarch64_get_instr (cpu
), 4, 0);
8367 aarch64_set_reg_u64 (cpu
, rd
, SP_OK
,
8368 aarch64_get_reg_u64 (cpu
, rn
, NO_SP
) & bimm
);
8371 /* 32 bit and immediate set flags. */
8373 ands32 (sim_cpu
*cpu
, uint32_t bimm
)
8375 unsigned rn
= uimm (aarch64_get_instr (cpu
), 9, 5);
8376 unsigned rd
= uimm (aarch64_get_instr (cpu
), 4, 0);
8378 uint32_t value1
= aarch64_get_reg_u32 (cpu
, rn
, NO_SP
);
8379 uint32_t value2
= bimm
;
8381 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, value1
& value2
);
8382 set_flags_for_binop32 (cpu
, value1
& value2
);
8385 /* 64 bit and immediate set flags. */
8387 ands64 (sim_cpu
*cpu
, uint64_t bimm
)
8389 unsigned rn
= uimm (aarch64_get_instr (cpu
), 9, 5);
8390 unsigned rd
= uimm (aarch64_get_instr (cpu
), 4, 0);
8392 uint64_t value1
= aarch64_get_reg_u64 (cpu
, rn
, NO_SP
);
8393 uint64_t value2
= bimm
;
8395 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, value1
& value2
);
8396 set_flags_for_binop64 (cpu
, value1
& value2
);
8399 /* 32 bit exclusive or immediate. */
8401 eor32 (sim_cpu
*cpu
, uint32_t bimm
)
8403 unsigned rn
= uimm (aarch64_get_instr (cpu
), 9, 5);
8404 unsigned rd
= uimm (aarch64_get_instr (cpu
), 4, 0);
8406 aarch64_set_reg_u64 (cpu
, rd
, SP_OK
,
8407 aarch64_get_reg_u32 (cpu
, rn
, NO_SP
) ^ bimm
);
8410 /* 64 bit exclusive or immediate. */
8412 eor64 (sim_cpu
*cpu
, uint64_t bimm
)
8414 unsigned rn
= uimm (aarch64_get_instr (cpu
), 9, 5);
8415 unsigned rd
= uimm (aarch64_get_instr (cpu
), 4, 0);
8417 aarch64_set_reg_u64 (cpu
, rd
, SP_OK
,
8418 aarch64_get_reg_u64 (cpu
, rn
, NO_SP
) ^ bimm
);
8421 /* 32 bit or immediate. */
8423 orr32 (sim_cpu
*cpu
, uint32_t bimm
)
8425 unsigned rn
= uimm (aarch64_get_instr (cpu
), 9, 5);
8426 unsigned rd
= uimm (aarch64_get_instr (cpu
), 4, 0);
8428 aarch64_set_reg_u64 (cpu
, rd
, SP_OK
,
8429 aarch64_get_reg_u32 (cpu
, rn
, NO_SP
) | bimm
);
8432 /* 64 bit or immediate. */
8434 orr64 (sim_cpu
*cpu
, uint64_t bimm
)
8436 unsigned rn
= uimm (aarch64_get_instr (cpu
), 9, 5);
8437 unsigned rd
= uimm (aarch64_get_instr (cpu
), 4, 0);
8439 aarch64_set_reg_u64 (cpu
, rd
, SP_OK
,
8440 aarch64_get_reg_u64 (cpu
, rn
, NO_SP
) | bimm
);
8443 /* Logical shifted register.
8444 These allow an optional LSL, ASR, LSR or ROR to the second source
8445 register with a count up to the register bit count.
8446 N.B register args may not be SP. */
8448 /* 32 bit AND shifted register. */
8450 and32_shift (sim_cpu
*cpu
, Shift shift
, uint32_t count
)
8452 unsigned rm
= uimm (aarch64_get_instr (cpu
), 20, 16);
8453 unsigned rn
= uimm (aarch64_get_instr (cpu
), 9, 5);
8454 unsigned rd
= uimm (aarch64_get_instr (cpu
), 4, 0);
8457 (cpu
, rd
, NO_SP
, aarch64_get_reg_u32 (cpu
, rn
, NO_SP
)
8458 & shifted32 (aarch64_get_reg_u32 (cpu
, rm
, NO_SP
), shift
, count
));
8461 /* 64 bit AND shifted register. */
8463 and64_shift (sim_cpu
*cpu
, Shift shift
, uint32_t count
)
8465 unsigned rm
= uimm (aarch64_get_instr (cpu
), 20, 16);
8466 unsigned rn
= uimm (aarch64_get_instr (cpu
), 9, 5);
8467 unsigned rd
= uimm (aarch64_get_instr (cpu
), 4, 0);
8470 (cpu
, rd
, NO_SP
, aarch64_get_reg_u64 (cpu
, rn
, NO_SP
)
8471 & shifted64 (aarch64_get_reg_u64 (cpu
, rm
, NO_SP
), shift
, count
));
8474 /* 32 bit AND shifted register setting flags. */
8476 ands32_shift (sim_cpu
*cpu
, Shift shift
, uint32_t count
)
8478 unsigned rm
= uimm (aarch64_get_instr (cpu
), 20, 16);
8479 unsigned rn
= uimm (aarch64_get_instr (cpu
), 9, 5);
8480 unsigned rd
= uimm (aarch64_get_instr (cpu
), 4, 0);
8482 uint32_t value1
= aarch64_get_reg_u32 (cpu
, rn
, NO_SP
);
8483 uint32_t value2
= shifted32 (aarch64_get_reg_u32 (cpu
, rm
, NO_SP
),
8486 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, value1
& value2
);
8487 set_flags_for_binop32 (cpu
, value1
& value2
);
8490 /* 64 bit AND shifted register setting flags. */
8492 ands64_shift (sim_cpu
*cpu
, Shift shift
, uint32_t count
)
8494 unsigned rm
= uimm (aarch64_get_instr (cpu
), 20, 16);
8495 unsigned rn
= uimm (aarch64_get_instr (cpu
), 9, 5);
8496 unsigned rd
= uimm (aarch64_get_instr (cpu
), 4, 0);
8498 uint64_t value1
= aarch64_get_reg_u64 (cpu
, rn
, NO_SP
);
8499 uint64_t value2
= shifted64 (aarch64_get_reg_u64 (cpu
, rm
, NO_SP
),
8502 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, value1
& value2
);
8503 set_flags_for_binop64 (cpu
, value1
& value2
);
8506 /* 32 bit BIC shifted register. */
8508 bic32_shift (sim_cpu
*cpu
, Shift shift
, uint32_t count
)
8510 unsigned rm
= uimm (aarch64_get_instr (cpu
), 20, 16);
8511 unsigned rn
= uimm (aarch64_get_instr (cpu
), 9, 5);
8512 unsigned rd
= uimm (aarch64_get_instr (cpu
), 4, 0);
8515 (cpu
, rd
, NO_SP
, aarch64_get_reg_u32 (cpu
, rn
, NO_SP
)
8516 & ~ shifted32 (aarch64_get_reg_u32 (cpu
, rm
, NO_SP
), shift
, count
));
8519 /* 64 bit BIC shifted register. */
8521 bic64_shift (sim_cpu
*cpu
, Shift shift
, uint32_t count
)
8523 unsigned rm
= uimm (aarch64_get_instr (cpu
), 20, 16);
8524 unsigned rn
= uimm (aarch64_get_instr (cpu
), 9, 5);
8525 unsigned rd
= uimm (aarch64_get_instr (cpu
), 4, 0);
8528 (cpu
, rd
, NO_SP
, aarch64_get_reg_u64 (cpu
, rn
, NO_SP
)
8529 & ~ shifted64 (aarch64_get_reg_u64 (cpu
, rm
, NO_SP
), shift
, count
));
8532 /* 32 bit BIC shifted register setting flags. */
8534 bics32_shift (sim_cpu
*cpu
, Shift shift
, uint32_t count
)
8536 unsigned rm
= uimm (aarch64_get_instr (cpu
), 20, 16);
8537 unsigned rn
= uimm (aarch64_get_instr (cpu
), 9, 5);
8538 unsigned rd
= uimm (aarch64_get_instr (cpu
), 4, 0);
8540 uint32_t value1
= aarch64_get_reg_u32 (cpu
, rn
, NO_SP
);
8541 uint32_t value2
= ~ shifted32 (aarch64_get_reg_u32 (cpu
, rm
, NO_SP
),
8544 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, value1
& value2
);
8545 set_flags_for_binop32 (cpu
, value1
& value2
);
8548 /* 64 bit BIC shifted register setting flags. */
8550 bics64_shift (sim_cpu
*cpu
, Shift shift
, uint32_t count
)
8552 unsigned rm
= uimm (aarch64_get_instr (cpu
), 20, 16);
8553 unsigned rn
= uimm (aarch64_get_instr (cpu
), 9, 5);
8554 unsigned rd
= uimm (aarch64_get_instr (cpu
), 4, 0);
8556 uint64_t value1
= aarch64_get_reg_u64 (cpu
, rn
, NO_SP
);
8557 uint64_t value2
= ~ shifted64 (aarch64_get_reg_u64 (cpu
, rm
, NO_SP
),
8560 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, value1
& value2
);
8561 set_flags_for_binop64 (cpu
, value1
& value2
);
8564 /* 32 bit EON shifted register. */
8566 eon32_shift (sim_cpu
*cpu
, Shift shift
, uint32_t count
)
8568 unsigned rm
= uimm (aarch64_get_instr (cpu
), 20, 16);
8569 unsigned rn
= uimm (aarch64_get_instr (cpu
), 9, 5);
8570 unsigned rd
= uimm (aarch64_get_instr (cpu
), 4, 0);
8573 (cpu
, rd
, NO_SP
, aarch64_get_reg_u32 (cpu
, rn
, NO_SP
)
8574 ^ ~ shifted32 (aarch64_get_reg_u32 (cpu
, rm
, NO_SP
), shift
, count
));
8577 /* 64 bit EON shifted register. */
8579 eon64_shift (sim_cpu
*cpu
, Shift shift
, uint32_t count
)
8581 unsigned rm
= uimm (aarch64_get_instr (cpu
), 20, 16);
8582 unsigned rn
= uimm (aarch64_get_instr (cpu
), 9, 5);
8583 unsigned rd
= uimm (aarch64_get_instr (cpu
), 4, 0);
8586 (cpu
, rd
, NO_SP
, aarch64_get_reg_u64 (cpu
, rn
, NO_SP
)
8587 ^ ~ shifted64 (aarch64_get_reg_u64 (cpu
, rm
, NO_SP
), shift
, count
));
8590 /* 32 bit EOR shifted register. */
8592 eor32_shift (sim_cpu
*cpu
, Shift shift
, uint32_t count
)
8594 unsigned rm
= uimm (aarch64_get_instr (cpu
), 20, 16);
8595 unsigned rn
= uimm (aarch64_get_instr (cpu
), 9, 5);
8596 unsigned rd
= uimm (aarch64_get_instr (cpu
), 4, 0);
8599 (cpu
, rd
, NO_SP
, aarch64_get_reg_u32 (cpu
, rn
, NO_SP
)
8600 ^ shifted32 (aarch64_get_reg_u32 (cpu
, rm
, NO_SP
), shift
, count
));
8603 /* 64 bit EOR shifted register. */
8605 eor64_shift (sim_cpu
*cpu
, Shift shift
, uint32_t count
)
8607 unsigned rm
= uimm (aarch64_get_instr (cpu
), 20, 16);
8608 unsigned rn
= uimm (aarch64_get_instr (cpu
), 9, 5);
8609 unsigned rd
= uimm (aarch64_get_instr (cpu
), 4, 0);
8612 (cpu
, rd
, NO_SP
, aarch64_get_reg_u64 (cpu
, rn
, NO_SP
)
8613 ^ shifted64 (aarch64_get_reg_u64 (cpu
, rm
, NO_SP
), shift
, count
));
8616 /* 32 bit ORR shifted register. */
8618 orr32_shift (sim_cpu
*cpu
, Shift shift
, uint32_t count
)
8620 unsigned rm
= uimm (aarch64_get_instr (cpu
), 20, 16);
8621 unsigned rn
= uimm (aarch64_get_instr (cpu
), 9, 5);
8622 unsigned rd
= uimm (aarch64_get_instr (cpu
), 4, 0);
8625 (cpu
, rd
, NO_SP
, aarch64_get_reg_u32 (cpu
, rn
, NO_SP
)
8626 | shifted32 (aarch64_get_reg_u32 (cpu
, rm
, NO_SP
), shift
, count
));
8629 /* 64 bit ORR shifted register. */
8631 orr64_shift (sim_cpu
*cpu
, Shift shift
, uint32_t count
)
8633 unsigned rm
= uimm (aarch64_get_instr (cpu
), 20, 16);
8634 unsigned rn
= uimm (aarch64_get_instr (cpu
), 9, 5);
8635 unsigned rd
= uimm (aarch64_get_instr (cpu
), 4, 0);
8638 (cpu
, rd
, NO_SP
, aarch64_get_reg_u64 (cpu
, rn
, NO_SP
)
8639 | shifted64 (aarch64_get_reg_u64 (cpu
, rm
, NO_SP
), shift
, count
));
8642 /* 32 bit ORN shifted register. */
8644 orn32_shift (sim_cpu
*cpu
, Shift shift
, uint32_t count
)
8646 unsigned rm
= uimm (aarch64_get_instr (cpu
), 20, 16);
8647 unsigned rn
= uimm (aarch64_get_instr (cpu
), 9, 5);
8648 unsigned rd
= uimm (aarch64_get_instr (cpu
), 4, 0);
8651 (cpu
, rd
, NO_SP
, aarch64_get_reg_u32 (cpu
, rn
, NO_SP
)
8652 | ~ shifted32 (aarch64_get_reg_u32 (cpu
, rm
, NO_SP
), shift
, count
));
8655 /* 64 bit ORN shifted register. */
8657 orn64_shift (sim_cpu
*cpu
, Shift shift
, uint32_t count
)
8659 unsigned rm
= uimm (aarch64_get_instr (cpu
), 20, 16);
8660 unsigned rn
= uimm (aarch64_get_instr (cpu
), 9, 5);
8661 unsigned rd
= uimm (aarch64_get_instr (cpu
), 4, 0);
8664 (cpu
, rd
, NO_SP
, aarch64_get_reg_u64 (cpu
, rn
, NO_SP
)
8665 | ~ shifted64 (aarch64_get_reg_u64 (cpu
, rm
, NO_SP
), shift
, count
));
8669 dexLogicalImmediate (sim_cpu
*cpu
)
8671 /* assert instr[28,23] = 1001000
8672 instr[31] = size : 0 ==> 32 bit, 1 ==> 64 bit
8673 instr[30,29] = op : 0 ==> AND, 1 ==> ORR, 2 ==> EOR, 3 ==> ANDS
8674 instr[22] = N : used to construct immediate mask
8680 /* 32 bit operations must have N = 0 or else we have an UNALLOC. */
8681 uint32_t size
= uimm (aarch64_get_instr (cpu
), 31, 31);
8682 uint32_t N
= uimm (aarch64_get_instr (cpu
), 22, 22);
8683 /* uint32_t immr = uimm (aarch64_get_instr (cpu), 21, 16);. */
8684 /* uint32_t imms = uimm (aarch64_get_instr (cpu), 15, 10);. */
8685 uint32_t index
= uimm (aarch64_get_instr (cpu
), 22, 10);
8686 uint64_t bimm64
= LITable
[index
];
8687 uint32_t dispatch
= uimm (aarch64_get_instr (cpu
), 30, 29);
8697 uint32_t bimm
= (uint32_t) bimm64
;
8701 case 0: and32 (cpu
, bimm
); return;
8702 case 1: orr32 (cpu
, bimm
); return;
8703 case 2: eor32 (cpu
, bimm
); return;
8704 case 3: ands32 (cpu
, bimm
); return;
8711 case 0: and64 (cpu
, bimm64
); return;
8712 case 1: orr64 (cpu
, bimm64
); return;
8713 case 2: eor64 (cpu
, bimm64
); return;
8714 case 3: ands64 (cpu
, bimm64
); return;
8721 The uimm argument is a 16 bit value to be inserted into the
8722 target register the pos argument locates the 16 bit word in the
8723 dest register i.e. it is in {0, 1} for 32 bit and {0, 1, 2,
8725 N.B register arg may not be SP so it should be.
8726 accessed using the setGZRegisterXXX accessors. */
8728 /* 32 bit move 16 bit immediate zero remaining shorts. */
8730 movz32 (sim_cpu
*cpu
, uint32_t val
, uint32_t pos
)
8732 unsigned rd
= uimm (aarch64_get_instr (cpu
), 4, 0);
8734 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, val
<< (pos
* 16));
8737 /* 64 bit move 16 bit immediate zero remaining shorts. */
8739 movz64 (sim_cpu
*cpu
, uint32_t val
, uint32_t pos
)
8741 unsigned rd
= uimm (aarch64_get_instr (cpu
), 4, 0);
8743 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, ((uint64_t) val
) << (pos
* 16));
8746 /* 32 bit move 16 bit immediate negated. */
8748 movn32 (sim_cpu
*cpu
, uint32_t val
, uint32_t pos
)
8750 unsigned rd
= uimm (aarch64_get_instr (cpu
), 4, 0);
8752 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, ((val
<< (pos
* 16)) ^ 0xffffffffU
));
8755 /* 64 bit move 16 bit immediate negated. */
8757 movn64 (sim_cpu
*cpu
, uint32_t val
, uint32_t pos
)
8759 unsigned rd
= uimm (aarch64_get_instr (cpu
), 4, 0);
8762 (cpu
, rd
, NO_SP
, ((((uint64_t) val
) << (pos
* 16))
8763 ^ 0xffffffffffffffffULL
));
8766 /* 32 bit move 16 bit immediate keep remaining shorts. */
8768 movk32 (sim_cpu
*cpu
, uint32_t val
, uint32_t pos
)
8770 unsigned rd
= uimm (aarch64_get_instr (cpu
), 4, 0);
8771 uint32_t current
= aarch64_get_reg_u32 (cpu
, rd
, NO_SP
);
8772 uint32_t value
= val
<< (pos
* 16);
8773 uint32_t mask
= ~(0xffffU
<< (pos
* 16));
8775 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, (value
| (current
& mask
)));
8778 /* 64 bit move 16 it immediate keep remaining shorts. */
8780 movk64 (sim_cpu
*cpu
, uint32_t val
, uint32_t pos
)
8782 unsigned rd
= uimm (aarch64_get_instr (cpu
), 4, 0);
8783 uint64_t current
= aarch64_get_reg_u64 (cpu
, rd
, NO_SP
);
8784 uint64_t value
= (uint64_t) val
<< (pos
* 16);
8785 uint64_t mask
= ~(0xffffULL
<< (pos
* 16));
8787 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, (value
| (current
& mask
)));
8791 dexMoveWideImmediate (sim_cpu
*cpu
)
8793 /* assert instr[28:23] = 100101
8794 instr[31] = size : 0 ==> 32 bit, 1 ==> 64 bit
8795 instr[30,29] = op : 0 ==> MOVN, 1 ==> UNALLOC, 2 ==> MOVZ, 3 ==> MOVK
8796 instr[22,21] = shift : 00 == LSL#0, 01 = LSL#16, 10 = LSL#32, 11 = LSL#48
8797 instr[20,5] = uimm16
8800 /* N.B. the (multiple of 16) shift is applied by the called routine,
8801 we just pass the multiplier. */
8804 uint32_t size
= uimm (aarch64_get_instr (cpu
), 31, 31);
8805 uint32_t op
= uimm (aarch64_get_instr (cpu
), 30, 29);
8806 uint32_t shift
= uimm (aarch64_get_instr (cpu
), 22, 21);
8808 /* 32 bit can only shift 0 or 1 lot of 16.
8809 anything else is an unallocated instruction. */
8810 if (size
== 0 && (shift
> 1))
8816 imm
= uimm (aarch64_get_instr (cpu
), 20, 5);
8821 movn32 (cpu
, imm
, shift
);
8823 movz32 (cpu
, imm
, shift
);
8825 movk32 (cpu
, imm
, shift
);
8830 movn64 (cpu
, imm
, shift
);
8832 movz64 (cpu
, imm
, shift
);
8834 movk64 (cpu
, imm
, shift
);
8838 /* Bitfield operations.
8839 These take a pair of bit positions r and s which are in {0..31}
8840 or {0..63} depending on the instruction word size.
8841 N.B register args may not be SP. */
8843 /* OK, we start with ubfm which just needs to pick
8844 some bits out of source zero the rest and write
8845 the result to dest. Just need two logical shifts. */
8847 /* 32 bit bitfield move, left and right of affected zeroed
8848 if r <= s Wd<s-r:0> = Wn<s:r> else Wd<32+s-r,32-r> = Wn<s:0>. */
8850 ubfm32 (sim_cpu
*cpu
, uint32_t r
, uint32_t s
)
8853 unsigned rn
= uimm (aarch64_get_instr (cpu
), 9, 5);
8854 uint32_t value
= aarch64_get_reg_u32 (cpu
, rn
, NO_SP
);
8856 /* Pick either s+1-r or s+1 consecutive bits out of the original word. */
8859 /* 31:...:s:xxx:r:...:0 ==> 31:...:s-r:xxx:0.
8860 We want only bits s:xxx:r at the bottom of the word
8861 so we LSL bit s up to bit 31 i.e. by 31 - s
8862 and then we LSR to bring bit 31 down to bit s - r
8863 i.e. by 31 + r - s. */
8865 value
>>= 31 + r
- s
;
8869 /* 31:...:s:xxx:0 ==> 31:...:31-(r-1)+s:xxx:31-(r-1):...:0
8870 We want only bits s:xxx:0 starting at it 31-(r-1)
8871 so we LSL bit s up to bit 31 i.e. by 31 - s
8872 and then we LSL to bring bit 31 down to 31-(r-1)+s
8873 i.e. by r - (s + 1). */
8875 value
>>= r
- (s
+ 1);
8878 rd
= uimm (aarch64_get_instr (cpu
), 4, 0);
8879 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, value
);
8882 /* 64 bit bitfield move, left and right of affected zeroed
8883 if r <= s Wd<s-r:0> = Wn<s:r> else Wd<64+s-r,64-r> = Wn<s:0>. */
8885 ubfm (sim_cpu
*cpu
, uint32_t r
, uint32_t s
)
8888 unsigned rn
= uimm (aarch64_get_instr (cpu
), 9, 5);
8889 uint64_t value
= aarch64_get_reg_u64 (cpu
, rn
, NO_SP
);
8893 /* 63:...:s:xxx:r:...:0 ==> 63:...:s-r:xxx:0.
8894 We want only bits s:xxx:r at the bottom of the word.
8895 So we LSL bit s up to bit 63 i.e. by 63 - s
8896 and then we LSR to bring bit 63 down to bit s - r
8897 i.e. by 63 + r - s. */
8899 value
>>= 63 + r
- s
;
8903 /* 63:...:s:xxx:0 ==> 63:...:63-(r-1)+s:xxx:63-(r-1):...:0.
8904 We want only bits s:xxx:0 starting at it 63-(r-1).
8905 So we LSL bit s up to bit 63 i.e. by 63 - s
8906 and then we LSL to bring bit 63 down to 63-(r-1)+s
8907 i.e. by r - (s + 1). */
8909 value
>>= r
- (s
+ 1);
8912 rd
= uimm (aarch64_get_instr (cpu
), 4, 0);
8913 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, value
);
8916 /* The signed versions need to insert sign bits
8917 on the left of the inserted bit field. so we do
8918 much the same as the unsigned version except we
8919 use an arithmetic shift right -- this just means
8920 we need to operate on signed values. */
8922 /* 32 bit bitfield move, left of affected sign-extended, right zeroed. */
8923 /* If r <= s Wd<s-r:0> = Wn<s:r> else Wd<32+s-r,32-r> = Wn<s:0>. */
8925 sbfm32 (sim_cpu
*cpu
, uint32_t r
, uint32_t s
)
8928 unsigned rn
= uimm (aarch64_get_instr (cpu
), 9, 5);
8929 /* as per ubfm32 but use an ASR instead of an LSR. */
8930 int32_t value
= aarch64_get_reg_s32 (cpu
, rn
, NO_SP
);
8935 value
>>= 31 + r
- s
;
8940 value
>>= r
- (s
+ 1);
8943 rd
= uimm (aarch64_get_instr (cpu
), 4, 0);
8944 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, (uint32_t) value
);
8947 /* 64 bit bitfield move, left of affected sign-extended, right zeroed. */
8948 /* If r <= s Wd<s-r:0> = Wn<s:r> else Wd<64+s-r,64-r> = Wn<s:0>. */
8950 sbfm (sim_cpu
*cpu
, uint32_t r
, uint32_t s
)
8953 unsigned rn
= uimm (aarch64_get_instr (cpu
), 9, 5);
8954 /* acpu per ubfm but use an ASR instead of an LSR. */
8955 int64_t value
= aarch64_get_reg_s64 (cpu
, rn
, NO_SP
);
8960 value
>>= 63 + r
- s
;
8965 value
>>= r
- (s
+ 1);
8968 rd
= uimm (aarch64_get_instr (cpu
), 4, 0);
8969 aarch64_set_reg_s64 (cpu
, rd
, NO_SP
, value
);
8972 /* Finally, these versions leave non-affected bits
8973 as is. so we need to generate the bits as per
8974 ubfm and also generate a mask to pick the
8975 bits from the original and computed values. */
8977 /* 32 bit bitfield move, non-affected bits left as is.
8978 If r <= s Wd<s-r:0> = Wn<s:r> else Wd<32+s-r,32-r> = Wn<s:0>. */
8980 bfm32 (sim_cpu
*cpu
, uint32_t r
, uint32_t s
)
8982 unsigned rn
= uimm (aarch64_get_instr (cpu
), 9, 5);
8983 uint32_t value
= aarch64_get_reg_u32 (cpu
, rn
, NO_SP
);
8988 /* Pick either s+1-r or s+1 consecutive bits out of the original word. */
8991 /* 31:...:s:xxx:r:...:0 ==> 31:...:s-r:xxx:0.
8992 We want only bits s:xxx:r at the bottom of the word
8993 so we LSL bit s up to bit 31 i.e. by 31 - s
8994 and then we LSR to bring bit 31 down to bit s - r
8995 i.e. by 31 + r - s. */
8997 value
>>= 31 + r
- s
;
8998 /* the mask must include the same bits. */
9000 mask
>>= 31 + r
- s
;
9004 /* 31:...:s:xxx:0 ==> 31:...:31-(r-1)+s:xxx:31-(r-1):...:0.
9005 We want only bits s:xxx:0 starting at it 31-(r-1)
9006 so we LSL bit s up to bit 31 i.e. by 31 - s
9007 and then we LSL to bring bit 31 down to 31-(r-1)+s
9008 i.e. by r - (s + 1). */
9010 value
>>= r
- (s
+ 1);
9011 /* The mask must include the same bits. */
9013 mask
>>= r
- (s
+ 1);
9016 rd
= uimm (aarch64_get_instr (cpu
), 4, 0);
9017 value2
= aarch64_get_reg_u32 (cpu
, rd
, NO_SP
);
9023 (cpu
, rd
, NO_SP
, (aarch64_get_reg_u32 (cpu
, rd
, NO_SP
) & ~mask
) | value
);
9026 /* 64 bit bitfield move, non-affected bits left as is.
9027 If r <= s Wd<s-r:0> = Wn<s:r> else Wd<64+s-r,64-r> = Wn<s:0>. */
9029 bfm (sim_cpu
*cpu
, uint32_t r
, uint32_t s
)
9032 unsigned rn
= uimm (aarch64_get_instr (cpu
), 9, 5);
9033 uint64_t value
= aarch64_get_reg_u64 (cpu
, rn
, NO_SP
);
9034 uint64_t mask
= 0xffffffffffffffffULL
;
9038 /* 63:...:s:xxx:r:...:0 ==> 63:...:s-r:xxx:0.
9039 We want only bits s:xxx:r at the bottom of the word
9040 so we LSL bit s up to bit 63 i.e. by 63 - s
9041 and then we LSR to bring bit 63 down to bit s - r
9042 i.e. by 63 + r - s. */
9044 value
>>= 63 + r
- s
;
9045 /* The mask must include the same bits. */
9047 mask
>>= 63 + r
- s
;
9051 /* 63:...:s:xxx:0 ==> 63:...:63-(r-1)+s:xxx:63-(r-1):...:0
9052 We want only bits s:xxx:0 starting at it 63-(r-1)
9053 so we LSL bit s up to bit 63 i.e. by 63 - s
9054 and then we LSL to bring bit 63 down to 63-(r-1)+s
9055 i.e. by r - (s + 1). */
9057 value
>>= r
- (s
+ 1);
9058 /* The mask must include the same bits. */
9060 mask
>>= r
- (s
+ 1);
9063 rd
= uimm (aarch64_get_instr (cpu
), 4, 0);
9065 (cpu
, rd
, NO_SP
, (aarch64_get_reg_u64 (cpu
, rd
, NO_SP
) & ~mask
) | value
);
9069 dexBitfieldImmediate (sim_cpu
*cpu
)
9071 /* assert instr[28:23] = 100110
9072 instr[31] = size : 0 ==> 32 bit, 1 ==> 64 bit
9073 instr[30,29] = op : 0 ==> SBFM, 1 ==> BFM, 2 ==> UBFM, 3 ==> UNALLOC
9074 instr[22] = N : must be 0 for 32 bit, 1 for 64 bit ow UNALLOC
9075 instr[21,16] = immr : 0xxxxx for 32 bit, xxxxxx for 64 bit
9076 instr[15,10] = imms : 0xxxxx for 32 bit, xxxxxx for 64 bit
9080 /* 32 bit operations must have N = 0 or else we have an UNALLOC. */
9083 uint32_t size
= uimm (aarch64_get_instr (cpu
), 31, 31);
9084 uint32_t N
= uimm (aarch64_get_instr (cpu
), 22, 22);
9085 /* 32 bit operations must have immr[5] = 0 and imms[5] = 0. */
9086 /* or else we have an UNALLOC. */
9087 uint32_t immr
= uimm (aarch64_get_instr (cpu
), 21, 16);
9092 if (!size
&& uimm (immr
, 5, 5))
9095 imms
= uimm (aarch64_get_instr (cpu
), 15, 10);
9096 if (!size
&& uimm (imms
, 5, 5))
9099 /* Switch on combined size and op. */
9100 dispatch
= uimm (aarch64_get_instr (cpu
), 31, 29);
9103 case 0: sbfm32 (cpu
, immr
, imms
); return;
9104 case 1: bfm32 (cpu
, immr
, imms
); return;
9105 case 2: ubfm32 (cpu
, immr
, imms
); return;
9106 case 4: sbfm (cpu
, immr
, imms
); return;
9107 case 5: bfm (cpu
, immr
, imms
); return;
9108 case 6: ubfm (cpu
, immr
, imms
); return;
9109 default: HALT_UNALLOC
;
9114 do_EXTR_32 (sim_cpu
*cpu
)
9116 /* instr[31:21] = 00010011100
9118 instr[15,10] = imms : 0xxxxx for 32 bit
9121 unsigned rm
= uimm (aarch64_get_instr (cpu
), 20, 16);
9122 unsigned imms
= uimm (aarch64_get_instr (cpu
), 15, 10) & 31;
9123 unsigned rn
= uimm (aarch64_get_instr (cpu
), 9, 5);
9124 unsigned rd
= uimm (aarch64_get_instr (cpu
), 4, 0);
9128 val1
= aarch64_get_reg_u32 (cpu
, rm
, NO_SP
);
9130 val2
= aarch64_get_reg_u32 (cpu
, rn
, NO_SP
);
9131 val2
<<= (32 - imms
);
9133 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, val1
| val2
);
9137 do_EXTR_64 (sim_cpu
*cpu
)
9139 /* instr[31:21] = 10010011100
9144 unsigned rm
= uimm (aarch64_get_instr (cpu
), 20, 16);
9145 unsigned imms
= uimm (aarch64_get_instr (cpu
), 15, 10) & 63;
9146 unsigned rn
= uimm (aarch64_get_instr (cpu
), 9, 5);
9147 unsigned rd
= uimm (aarch64_get_instr (cpu
), 4, 0);
9150 val
= aarch64_get_reg_u64 (cpu
, rm
, NO_SP
);
9152 val
|= (aarch64_get_reg_u64 (cpu
, rn
, NO_SP
) << (64 - imms
));
9154 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, val
);
9158 dexExtractImmediate (sim_cpu
*cpu
)
9160 /* assert instr[28:23] = 100111
9161 instr[31] = size : 0 ==> 32 bit, 1 ==> 64 bit
9162 instr[30,29] = op21 : 0 ==> EXTR, 1,2,3 ==> UNALLOC
9163 instr[22] = N : must be 0 for 32 bit, 1 for 64 bit or UNALLOC
9164 instr[21] = op0 : must be 0 or UNALLOC
9166 instr[15,10] = imms : 0xxxxx for 32 bit, xxxxxx for 64 bit
9170 /* 32 bit operations must have N = 0 or else we have an UNALLOC. */
9171 /* 64 bit operations must have N = 1 or else we have an UNALLOC. */
9173 uint32_t size
= uimm (aarch64_get_instr (cpu
), 31, 31);
9174 uint32_t N
= uimm (aarch64_get_instr (cpu
), 22, 22);
9175 /* 32 bit operations must have imms[5] = 0
9176 or else we have an UNALLOC. */
9177 uint32_t imms
= uimm (aarch64_get_instr (cpu
), 15, 10);
9182 if (!size
&& uimm (imms
, 5, 5))
9185 /* Switch on combined size and op. */
9186 dispatch
= uimm (aarch64_get_instr (cpu
), 31, 29);
9191 else if (dispatch
== 4)
9194 else if (dispatch
== 1)
9201 dexDPImm (sim_cpu
*cpu
)
9203 /* uint32_t group = dispatchGroup (aarch64_get_instr (cpu));
9204 assert group == GROUP_DPIMM_1000 || grpoup == GROUP_DPIMM_1001
9205 bits [25,23] of a DPImm are the secondary dispatch vector. */
9206 uint32_t group2
= dispatchDPImm (aarch64_get_instr (cpu
));
9210 case DPIMM_PCADR_000
:
9211 case DPIMM_PCADR_001
:
9212 dexPCRelAddressing (cpu
);
9215 case DPIMM_ADDSUB_010
:
9216 case DPIMM_ADDSUB_011
:
9217 dexAddSubtractImmediate (cpu
);
9221 dexLogicalImmediate (cpu
);
9225 dexMoveWideImmediate (cpu
);
9228 case DPIMM_BITF_110
:
9229 dexBitfieldImmediate (cpu
);
9232 case DPIMM_EXTR_111
:
9233 dexExtractImmediate (cpu
);
9237 /* Should never reach here. */
9243 dexLoadUnscaledImmediate (sim_cpu
*cpu
)
9245 /* instr[29,24] == 111_00
9251 instr[20,12] = simm9
9252 instr[9,5] = rn may be SP. */
9253 /* unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0); */
9254 uint32_t V
= uimm (aarch64_get_instr (cpu
), 26, 26);
9255 uint32_t dispatch
= ( (uimm (aarch64_get_instr (cpu
), 31, 30) << 2)
9256 | uimm (aarch64_get_instr (cpu
), 23, 22));
9257 int32_t imm
= simm32 (aarch64_get_instr (cpu
), 20, 12);
9261 /* GReg operations. */
9264 case 0: sturb (cpu
, imm
); return;
9265 case 1: ldurb32 (cpu
, imm
); return;
9266 case 2: ldursb64 (cpu
, imm
); return;
9267 case 3: ldursb32 (cpu
, imm
); return;
9268 case 4: sturh (cpu
, imm
); return;
9269 case 5: ldurh32 (cpu
, imm
); return;
9270 case 6: ldursh64 (cpu
, imm
); return;
9271 case 7: ldursh32 (cpu
, imm
); return;
9272 case 8: stur32 (cpu
, imm
); return;
9273 case 9: ldur32 (cpu
, imm
); return;
9274 case 10: ldursw (cpu
, imm
); return;
9275 case 12: stur64 (cpu
, imm
); return;
9276 case 13: ldur64 (cpu
, imm
); return;
9289 /* FReg operations. */
9292 case 2: fsturq (cpu
, imm
); return;
9293 case 3: fldurq (cpu
, imm
); return;
9294 case 8: fsturs (cpu
, imm
); return;
9295 case 9: fldurs (cpu
, imm
); return;
9296 case 12: fsturd (cpu
, imm
); return;
9297 case 13: fldurd (cpu
, imm
); return;
9299 case 0: /* STUR 8 bit FP. */
9300 case 1: /* LDUR 8 bit FP. */
9301 case 4: /* STUR 16 bit FP. */
9302 case 5: /* LDUR 8 bit FP. */
9316 /* N.B. A preliminary note regarding all the ldrs<x>32
9319 The signed value loaded by these instructions is cast to unsigned
9320 before being assigned to aarch64_get_reg_u64 (cpu, N) i.e. to the
9321 64 bit element of the GReg union. this performs a 32 bit sign extension
9322 (as required) but avoids 64 bit sign extension, thus ensuring that the
9323 top half of the register word is zero. this is what the spec demands
9324 when a 32 bit load occurs. */
9326 /* 32 bit load sign-extended byte scaled unsigned 12 bit. */
9328 ldrsb32_abs (sim_cpu
*cpu
, uint32_t offset
)
9330 unsigned int rn
= uimm (aarch64_get_instr (cpu
), 9, 5);
9331 unsigned int rt
= uimm (aarch64_get_instr (cpu
), 4, 0);
9333 /* The target register may not be SP but the source may be
9334 there is no scaling required for a byte load. */
9335 uint64_t address
= aarch64_get_reg_u64 (cpu
, rn
, SP_OK
) + offset
;
9336 aarch64_set_reg_u64 (cpu
, rt
, NO_SP
,
9337 (int64_t) aarch64_get_mem_s8 (cpu
, address
));
9340 /* 32 bit load sign-extended byte scaled or unscaled zero-
9341 or sign-extended 32-bit register offset. */
9343 ldrsb32_scale_ext (sim_cpu
*cpu
, Scaling scaling
, Extension extension
)
9345 unsigned int rm
= uimm (aarch64_get_instr (cpu
), 20, 16);
9346 unsigned int rn
= uimm (aarch64_get_instr (cpu
), 9, 5);
9347 unsigned int rt
= uimm (aarch64_get_instr (cpu
), 4, 0);
9349 /* rn may reference SP, rm and rt must reference ZR. */
9351 uint64_t address
= aarch64_get_reg_u64 (cpu
, rn
, SP_OK
);
9352 int64_t displacement
= extend (aarch64_get_reg_u32 (cpu
, rm
, NO_SP
),
9355 /* There is no scaling required for a byte load. */
9357 (cpu
, rt
, NO_SP
, (int64_t) aarch64_get_mem_s8 (cpu
, address
9361 /* 32 bit load sign-extended byte unscaled signed 9 bit with
9362 pre- or post-writeback. */
9364 ldrsb32_wb (sim_cpu
*cpu
, int32_t offset
, WriteBack wb
)
9367 unsigned int rn
= uimm (aarch64_get_instr (cpu
), 9, 5);
9368 unsigned int rt
= uimm (aarch64_get_instr (cpu
), 4, 0);
9370 if (rn
== rt
&& wb
!= NoWriteBack
)
9373 address
= aarch64_get_reg_u64 (cpu
, rn
, SP_OK
);
9378 aarch64_set_reg_u64 (cpu
, rt
, NO_SP
,
9379 (int64_t) aarch64_get_mem_s8 (cpu
, address
));
9384 if (wb
!= NoWriteBack
)
9385 aarch64_set_reg_u64 (cpu
, rn
, NO_SP
, address
);
9388 /* 8 bit store scaled. */
9390 fstrb_abs (sim_cpu
*cpu
, uint32_t offset
)
9392 unsigned st
= uimm (aarch64_get_instr (cpu
), 4, 0);
9393 unsigned rn
= uimm (aarch64_get_instr (cpu
), 9, 5);
9395 aarch64_set_mem_u8 (cpu
,
9396 aarch64_get_reg_u64 (cpu
, rn
, SP_OK
) + offset
,
9397 aarch64_get_vec_u8 (cpu
, st
, 0));
9400 /* 8 bit store scaled or unscaled zero- or
9401 sign-extended 8-bit register offset. */
9403 fstrb_scale_ext (sim_cpu
*cpu
, Scaling scaling
, Extension extension
)
9405 unsigned rm
= uimm (aarch64_get_instr (cpu
), 20, 16);
9406 unsigned rn
= uimm (aarch64_get_instr (cpu
), 9, 5);
9407 unsigned st
= uimm (aarch64_get_instr (cpu
), 4, 0);
9409 uint64_t address
= aarch64_get_reg_u64 (cpu
, rn
, SP_OK
);
9410 int64_t extended
= extend (aarch64_get_reg_u32 (cpu
, rm
, NO_SP
),
9412 uint64_t displacement
= OPT_SCALE (extended
, 32, scaling
);
9415 (cpu
, address
+ displacement
, aarch64_get_vec_u8 (cpu
, st
, 0));
9418 /* 16 bit store scaled. */
9420 fstrh_abs (sim_cpu
*cpu
, uint32_t offset
)
9422 unsigned st
= uimm (aarch64_get_instr (cpu
), 4, 0);
9423 unsigned rn
= uimm (aarch64_get_instr (cpu
), 9, 5);
9427 aarch64_get_reg_u64 (cpu
, rn
, SP_OK
) + SCALE (offset
, 16),
9428 aarch64_get_vec_u16 (cpu
, st
, 0));
9431 /* 16 bit store scaled or unscaled zero-
9432 or sign-extended 16-bit register offset. */
9434 fstrh_scale_ext (sim_cpu
*cpu
, Scaling scaling
, Extension extension
)
9436 unsigned rm
= uimm (aarch64_get_instr (cpu
), 20, 16);
9437 unsigned rn
= uimm (aarch64_get_instr (cpu
), 9, 5);
9438 unsigned st
= uimm (aarch64_get_instr (cpu
), 4, 0);
9440 uint64_t address
= aarch64_get_reg_u64 (cpu
, rn
, SP_OK
);
9441 int64_t extended
= extend (aarch64_get_reg_u32 (cpu
, rm
, NO_SP
),
9443 uint64_t displacement
= OPT_SCALE (extended
, 32, scaling
);
9446 (cpu
, address
+ displacement
, aarch64_get_vec_u16 (cpu
, st
, 0));
9449 /* 32 bit store scaled unsigned 12 bit. */
9451 fstrs_abs (sim_cpu
*cpu
, uint32_t offset
)
9453 unsigned st
= uimm (aarch64_get_instr (cpu
), 4, 0);
9454 unsigned rn
= uimm (aarch64_get_instr (cpu
), 9, 5);
9456 aarch64_set_mem_float
9458 aarch64_get_reg_u64 (cpu
, rn
, SP_OK
) + SCALE (offset
, 32),
9459 aarch64_get_FP_float (cpu
, st
));
9462 /* 32 bit store unscaled signed 9 bit with pre- or post-writeback. */
9464 fstrs_wb (sim_cpu
*cpu
, int32_t offset
, WriteBack wb
)
9466 unsigned rn
= uimm (aarch64_get_instr (cpu
), 9, 5);
9467 unsigned st
= uimm (aarch64_get_instr (cpu
), 4, 0);
9469 uint64_t address
= aarch64_get_reg_u64 (cpu
, rn
, SP_OK
);
9474 aarch64_set_mem_float (cpu
, address
, aarch64_get_FP_float (cpu
, st
));
9479 if (wb
!= NoWriteBack
)
9480 aarch64_set_reg_u64 (cpu
, rn
, SP_OK
, address
);
9483 /* 32 bit store scaled or unscaled zero-
9484 or sign-extended 32-bit register offset. */
9486 fstrs_scale_ext (sim_cpu
*cpu
, Scaling scaling
, Extension extension
)
9488 unsigned rm
= uimm (aarch64_get_instr (cpu
), 20, 16);
9489 unsigned rn
= uimm (aarch64_get_instr (cpu
), 9, 5);
9490 unsigned st
= uimm (aarch64_get_instr (cpu
), 4, 0);
9492 uint64_t address
= aarch64_get_reg_u64 (cpu
, rn
, SP_OK
);
9493 int64_t extended
= extend (aarch64_get_reg_u32 (cpu
, rm
, NO_SP
),
9495 uint64_t displacement
= OPT_SCALE (extended
, 32, scaling
);
9497 aarch64_set_mem_float
9498 (cpu
, address
+ displacement
, aarch64_get_FP_float (cpu
, st
));
9501 /* 64 bit store scaled unsigned 12 bit. */
9503 fstrd_abs (sim_cpu
*cpu
, uint32_t offset
)
9505 unsigned st
= uimm (aarch64_get_instr (cpu
), 4, 0);
9506 unsigned rn
= uimm (aarch64_get_instr (cpu
), 9, 5);
9508 aarch64_set_mem_double
9510 aarch64_get_reg_u64 (cpu
, rn
, SP_OK
) + SCALE (offset
, 64),
9511 aarch64_get_FP_double (cpu
, st
));
9514 /* 64 bit store unscaled signed 9 bit with pre- or post-writeback. */
9516 fstrd_wb (sim_cpu
*cpu
, int32_t offset
, WriteBack wb
)
9518 unsigned rn
= uimm (aarch64_get_instr (cpu
), 9, 5);
9519 unsigned st
= uimm (aarch64_get_instr (cpu
), 4, 0);
9521 uint64_t address
= aarch64_get_reg_u64 (cpu
, rn
, SP_OK
);
9526 aarch64_set_mem_double (cpu
, address
, aarch64_get_FP_double (cpu
, st
));
9531 if (wb
!= NoWriteBack
)
9532 aarch64_set_reg_u64 (cpu
, rn
, SP_OK
, address
);
9535 /* 64 bit store scaled or unscaled zero-
9536 or sign-extended 32-bit register offset. */
9538 fstrd_scale_ext (sim_cpu
*cpu
, Scaling scaling
, Extension extension
)
9540 unsigned rm
= uimm (aarch64_get_instr (cpu
), 20, 16);
9541 unsigned rn
= uimm (aarch64_get_instr (cpu
), 9, 5);
9542 unsigned st
= uimm (aarch64_get_instr (cpu
), 4, 0);
9544 uint64_t address
= aarch64_get_reg_u64 (cpu
, rn
, SP_OK
);
9545 int64_t extended
= extend (aarch64_get_reg_u32 (cpu
, rm
, NO_SP
),
9547 uint64_t displacement
= OPT_SCALE (extended
, 64, scaling
);
9549 aarch64_set_mem_double
9550 (cpu
, address
+ displacement
, aarch64_get_FP_double (cpu
, st
));
9553 /* 128 bit store scaled unsigned 12 bit. */
9555 fstrq_abs (sim_cpu
*cpu
, uint32_t offset
)
9558 unsigned st
= uimm (aarch64_get_instr (cpu
), 4, 0);
9559 unsigned rn
= uimm (aarch64_get_instr (cpu
), 9, 5);
9562 aarch64_get_FP_long_double (cpu
, st
, & a
);
9564 addr
= aarch64_get_reg_u64 (cpu
, rn
, SP_OK
) + SCALE (offset
, 128);
9565 aarch64_set_mem_long_double (cpu
, addr
, a
);
9568 /* 128 bit store unscaled signed 9 bit with pre- or post-writeback. */
9570 fstrq_wb (sim_cpu
*cpu
, int32_t offset
, WriteBack wb
)
9573 unsigned rn
= uimm (aarch64_get_instr (cpu
), 9, 5);
9574 unsigned st
= uimm (aarch64_get_instr (cpu
), 4, 0);
9575 uint64_t address
= aarch64_get_reg_u64 (cpu
, rn
, SP_OK
);
9580 aarch64_get_FP_long_double (cpu
, st
, & a
);
9581 aarch64_set_mem_long_double (cpu
, address
, a
);
9586 if (wb
!= NoWriteBack
)
9587 aarch64_set_reg_u64 (cpu
, rn
, SP_OK
, address
);
9590 /* 128 bit store scaled or unscaled zero-
9591 or sign-extended 32-bit register offset. */
9593 fstrq_scale_ext (sim_cpu
*cpu
, Scaling scaling
, Extension extension
)
9595 unsigned rm
= uimm (aarch64_get_instr (cpu
), 20, 16);
9596 unsigned rn
= uimm (aarch64_get_instr (cpu
), 9, 5);
9597 unsigned st
= uimm (aarch64_get_instr (cpu
), 4, 0);
9599 uint64_t address
= aarch64_get_reg_u64 (cpu
, rn
, SP_OK
);
9600 int64_t extended
= extend (aarch64_get_reg_u32 (cpu
, rm
, NO_SP
),
9602 uint64_t displacement
= OPT_SCALE (extended
, 128, scaling
);
9606 aarch64_get_FP_long_double (cpu
, st
, & a
);
9607 aarch64_set_mem_long_double (cpu
, address
+ displacement
, a
);
9611 dexLoadImmediatePrePost (sim_cpu
*cpu
)
9613 /* instr[29,24] == 111_00
9619 instr[20,12] = simm9
9620 instr[11] = wb : 0 ==> Post, 1 ==> Pre
9621 instr[9,5] = rn may be SP. */
9622 /* unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0); */
9623 uint32_t V
= uimm (aarch64_get_instr (cpu
), 26, 26);
9624 uint32_t dispatch
= ( (uimm (aarch64_get_instr (cpu
), 31, 30) << 2)
9625 | uimm (aarch64_get_instr (cpu
), 23, 22));
9626 int32_t imm
= simm32 (aarch64_get_instr (cpu
), 20, 12);
9627 WriteBack wb
= writeback (aarch64_get_instr (cpu
), 11);
9631 /* GReg operations. */
9634 case 0: strb_wb (cpu
, imm
, wb
); return;
9635 case 1: ldrb32_wb (cpu
, imm
, wb
); return;
9636 case 2: ldrsb_wb (cpu
, imm
, wb
); return;
9637 case 3: ldrsb32_wb (cpu
, imm
, wb
); return;
9638 case 4: strh_wb (cpu
, imm
, wb
); return;
9639 case 5: ldrh32_wb (cpu
, imm
, wb
); return;
9640 case 6: ldrsh64_wb (cpu
, imm
, wb
); return;
9641 case 7: ldrsh32_wb (cpu
, imm
, wb
); return;
9642 case 8: str32_wb (cpu
, imm
, wb
); return;
9643 case 9: ldr32_wb (cpu
, imm
, wb
); return;
9644 case 10: ldrsw_wb (cpu
, imm
, wb
); return;
9645 case 12: str_wb (cpu
, imm
, wb
); return;
9646 case 13: ldr_wb (cpu
, imm
, wb
); return;
9656 /* FReg operations. */
9659 case 2: fstrq_wb (cpu
, imm
, wb
); return;
9660 case 3: fldrq_wb (cpu
, imm
, wb
); return;
9661 case 8: fstrs_wb (cpu
, imm
, wb
); return;
9662 case 9: fldrs_wb (cpu
, imm
, wb
); return;
9663 case 12: fstrd_wb (cpu
, imm
, wb
); return;
9664 case 13: fldrd_wb (cpu
, imm
, wb
); return;
9666 case 0: /* STUR 8 bit FP. */
9667 case 1: /* LDUR 8 bit FP. */
9668 case 4: /* STUR 16 bit FP. */
9669 case 5: /* LDUR 8 bit FP. */
9684 dexLoadRegisterOffset (sim_cpu
*cpu
)
9686 /* instr[31,30] = size
9693 instr[15,13] = option : 010 ==> UXTW, 011 ==> UXTX/LSL,
9694 110 ==> SXTW, 111 ==> SXTX,
9701 uint32_t V
= uimm (aarch64_get_instr (cpu
), 26,26);
9702 uint32_t dispatch
= ( (uimm (aarch64_get_instr (cpu
), 31, 30) << 2)
9703 | uimm (aarch64_get_instr (cpu
), 23, 22));
9704 Scaling scale
= scaling (aarch64_get_instr (cpu
), 12);
9705 Extension extensionType
= extension (aarch64_get_instr (cpu
), 13);
9707 /* Check for illegal extension types. */
9708 if (uimm (extensionType
, 1, 1) == 0)
9711 if (extensionType
== UXTX
|| extensionType
== SXTX
)
9712 extensionType
= NoExtension
;
9716 /* GReg operations. */
9719 case 0: strb_scale_ext (cpu
, scale
, extensionType
); return;
9720 case 1: ldrb32_scale_ext (cpu
, scale
, extensionType
); return;
9721 case 2: ldrsb_scale_ext (cpu
, scale
, extensionType
); return;
9722 case 3: ldrsb32_scale_ext (cpu
, scale
, extensionType
); return;
9723 case 4: strh_scale_ext (cpu
, scale
, extensionType
); return;
9724 case 5: ldrh32_scale_ext (cpu
, scale
, extensionType
); return;
9725 case 6: ldrsh_scale_ext (cpu
, scale
, extensionType
); return;
9726 case 7: ldrsh32_scale_ext (cpu
, scale
, extensionType
); return;
9727 case 8: str32_scale_ext (cpu
, scale
, extensionType
); return;
9728 case 9: ldr32_scale_ext (cpu
, scale
, extensionType
); return;
9729 case 10: ldrsw_scale_ext (cpu
, scale
, extensionType
); return;
9730 case 12: str_scale_ext (cpu
, scale
, extensionType
); return;
9731 case 13: ldr_scale_ext (cpu
, scale
, extensionType
); return;
9732 case 14: prfm_scale_ext (cpu
, scale
, extensionType
); return;
9741 /* FReg operations. */
9744 case 1: /* LDUR 8 bit FP. */
9746 case 3: fldrq_scale_ext (cpu
, scale
, extensionType
); return;
9747 case 5: /* LDUR 8 bit FP. */
9749 case 9: fldrs_scale_ext (cpu
, scale
, extensionType
); return;
9750 case 13: fldrd_scale_ext (cpu
, scale
, extensionType
); return;
9752 case 0: fstrb_scale_ext (cpu
, scale
, extensionType
); return;
9753 case 2: fstrq_scale_ext (cpu
, scale
, extensionType
); return;
9754 case 4: fstrh_scale_ext (cpu
, scale
, extensionType
); return;
9755 case 8: fstrs_scale_ext (cpu
, scale
, extensionType
); return;
9756 case 12: fstrd_scale_ext (cpu
, scale
, extensionType
); return;
9770 dexLoadUnsignedImmediate (sim_cpu
*cpu
)
9772 /* assert instr[29,24] == 111_01
9776 instr[21,10] = uimm12 : unsigned immediate offset
9777 instr[9,5] = rn may be SP. */
9778 /* unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0); */
9779 uint32_t V
= uimm (aarch64_get_instr (cpu
), 26,26);
9780 uint32_t dispatch
= ( (uimm (aarch64_get_instr (cpu
), 31, 30) << 2)
9781 | uimm (aarch64_get_instr (cpu
), 23, 22));
9782 uint32_t imm
= uimm (aarch64_get_instr (cpu
), 21, 10);
9786 /* GReg operations. */
9789 case 0: strb_abs (cpu
, imm
); return;
9790 case 1: ldrb32_abs (cpu
, imm
); return;
9791 case 2: ldrsb_abs (cpu
, imm
); return;
9792 case 3: ldrsb32_abs (cpu
, imm
); return;
9793 case 4: strh_abs (cpu
, imm
); return;
9794 case 5: ldrh32_abs (cpu
, imm
); return;
9795 case 6: ldrsh_abs (cpu
, imm
); return;
9796 case 7: ldrsh32_abs (cpu
, imm
); return;
9797 case 8: str32_abs (cpu
, imm
); return;
9798 case 9: ldr32_abs (cpu
, imm
); return;
9799 case 10: ldrsw_abs (cpu
, imm
); return;
9800 case 12: str_abs (cpu
, imm
); return;
9801 case 13: ldr_abs (cpu
, imm
); return;
9802 case 14: prfm_abs (cpu
, imm
); return;
9811 /* FReg operations. */
9814 case 3: fldrq_abs (cpu
, imm
); return;
9815 case 9: fldrs_abs (cpu
, imm
); return;
9816 case 13: fldrd_abs (cpu
, imm
); return;
9818 case 0: fstrb_abs (cpu
, imm
); return;
9819 case 2: fstrq_abs (cpu
, imm
); return;
9820 case 4: fstrh_abs (cpu
, imm
); return;
9821 case 8: fstrs_abs (cpu
, imm
); return;
9822 case 12: fstrd_abs (cpu
, imm
); return;
9824 case 1: /* LDR 8 bit FP. */
9825 case 5: /* LDR 8 bit FP. */
9840 dexLoadExclusive (sim_cpu
*cpu
)
9842 /* assert instr[29:24] = 001000;
9844 instr[23] = 0 if exclusive
9845 instr[22] = L : 1 if load, 0 if store
9846 instr[21] = 1 if pair
9848 instr[15] = o0 : 1 if ordered
9853 switch (uimm (aarch64_get_instr (cpu
), 22, 21))
9855 case 2: ldxr (cpu
); return;
9856 case 0: stxr (cpu
); return;
9862 dexLoadOther (sim_cpu
*cpu
)
9866 /* instr[29,25] = 111_0
9867 instr[24] == 0 ==> dispatch, 1 ==> ldst reg unsigned immediate
9868 instr[21:11,10] is the secondary dispatch. */
9869 if (uimm (aarch64_get_instr (cpu
), 24, 24))
9871 dexLoadUnsignedImmediate (cpu
);
9875 dispatch
= ( (uimm (aarch64_get_instr (cpu
), 21, 21) << 2)
9876 | uimm (aarch64_get_instr (cpu
), 11, 10));
9879 case 0: dexLoadUnscaledImmediate (cpu
); return;
9880 case 1: dexLoadImmediatePrePost (cpu
); return;
9881 case 3: dexLoadImmediatePrePost (cpu
); return;
9882 case 6: dexLoadRegisterOffset (cpu
); return;
9894 store_pair_u32 (sim_cpu
*cpu
, int32_t offset
, WriteBack wb
)
9896 unsigned rn
= uimm (aarch64_get_instr (cpu
), 14, 10);
9897 unsigned rd
= uimm (aarch64_get_instr (cpu
), 9, 5);
9898 unsigned rm
= uimm (aarch64_get_instr (cpu
), 4, 0);
9899 uint64_t address
= aarch64_get_reg_u64 (cpu
, rd
, SP_OK
);
9901 if ((rn
== rd
|| rm
== rd
) && wb
!= NoWriteBack
)
9902 HALT_UNALLOC
; /* ??? */
9909 aarch64_set_mem_u32 (cpu
, address
,
9910 aarch64_get_reg_u32 (cpu
, rm
, NO_SP
));
9911 aarch64_set_mem_u32 (cpu
, address
+ 4,
9912 aarch64_get_reg_u32 (cpu
, rn
, NO_SP
));
9917 if (wb
!= NoWriteBack
)
9918 aarch64_set_reg_u64 (cpu
, rd
, SP_OK
, address
);
9922 store_pair_u64 (sim_cpu
*cpu
, int32_t offset
, WriteBack wb
)
9924 unsigned rn
= uimm (aarch64_get_instr (cpu
), 14, 10);
9925 unsigned rd
= uimm (aarch64_get_instr (cpu
), 9, 5);
9926 unsigned rm
= uimm (aarch64_get_instr (cpu
), 4, 0);
9927 uint64_t address
= aarch64_get_reg_u64 (cpu
, rd
, SP_OK
);
9929 if ((rn
== rd
|| rm
== rd
) && wb
!= NoWriteBack
)
9930 HALT_UNALLOC
; /* ??? */
9937 aarch64_set_mem_u64 (cpu
, address
,
9938 aarch64_get_reg_u64 (cpu
, rm
, SP_OK
));
9939 aarch64_set_mem_u64 (cpu
, address
+ 8,
9940 aarch64_get_reg_u64 (cpu
, rn
, SP_OK
));
9945 if (wb
!= NoWriteBack
)
9946 aarch64_set_reg_u64 (cpu
, rd
, SP_OK
, address
);
9950 load_pair_u32 (sim_cpu
*cpu
, int32_t offset
, WriteBack wb
)
9952 unsigned rn
= uimm (aarch64_get_instr (cpu
), 14, 10);
9953 unsigned rd
= uimm (aarch64_get_instr (cpu
), 9, 5);
9954 unsigned rm
= uimm (aarch64_get_instr (cpu
), 4, 0);
9955 uint64_t address
= aarch64_get_reg_u64 (cpu
, rd
, SP_OK
);
9957 /* treat this as unalloc to make sure we don't do it. */
9966 aarch64_set_reg_u64 (cpu
, rm
, SP_OK
, aarch64_get_mem_u32 (cpu
, address
));
9967 aarch64_set_reg_u64 (cpu
, rn
, SP_OK
, aarch64_get_mem_u32 (cpu
, address
+ 4));
9972 if (wb
!= NoWriteBack
)
9973 aarch64_set_reg_u64 (cpu
, rd
, SP_OK
, address
);
9977 load_pair_s32 (sim_cpu
*cpu
, int32_t offset
, WriteBack wb
)
9979 unsigned rn
= uimm (aarch64_get_instr (cpu
), 14, 10);
9980 unsigned rd
= uimm (aarch64_get_instr (cpu
), 9, 5);
9981 unsigned rm
= uimm (aarch64_get_instr (cpu
), 4, 0);
9982 uint64_t address
= aarch64_get_reg_u64 (cpu
, rd
, SP_OK
);
9984 /* Treat this as unalloc to make sure we don't do it. */
9993 aarch64_set_reg_s64 (cpu
, rm
, SP_OK
, aarch64_get_mem_s32 (cpu
, address
));
9994 aarch64_set_reg_s64 (cpu
, rn
, SP_OK
, aarch64_get_mem_s32 (cpu
, address
+ 4));
9999 if (wb
!= NoWriteBack
)
10000 aarch64_set_reg_u64 (cpu
, rd
, SP_OK
, address
);
10004 load_pair_u64 (sim_cpu
*cpu
, int32_t offset
, WriteBack wb
)
10006 unsigned rn
= uimm (aarch64_get_instr (cpu
), 14, 10);
10007 unsigned rd
= uimm (aarch64_get_instr (cpu
), 9, 5);
10008 unsigned rm
= uimm (aarch64_get_instr (cpu
), 4, 0);
10009 uint64_t address
= aarch64_get_reg_u64 (cpu
, rd
, SP_OK
);
10011 /* Treat this as unalloc to make sure we don't do it. */
10020 aarch64_set_reg_u64 (cpu
, rm
, SP_OK
, aarch64_get_mem_u64 (cpu
, address
));
10021 aarch64_set_reg_u64 (cpu
, rn
, SP_OK
, aarch64_get_mem_u64 (cpu
, address
+ 8));
10026 if (wb
!= NoWriteBack
)
10027 aarch64_set_reg_u64 (cpu
, rd
, SP_OK
, address
);
10031 dex_load_store_pair_gr (sim_cpu
*cpu
)
10033 /* instr[31,30] = size (10=> 64-bit, 01=> signed 32-bit, 00=> 32-bit)
10034 instr[29,25] = instruction encoding: 101_0
10035 instr[26] = V : 1 if fp 0 if gp
10036 instr[24,23] = addressing mode (10=> offset, 01=> post, 11=> pre)
10037 instr[22] = load/store (1=> load)
10038 instr[21,15] = signed, scaled, offset
10041 instr[ 4, 0] = Rm. */
10043 uint32_t dispatch
= ((uimm (aarch64_get_instr (cpu
), 31, 30) << 3)
10044 | uimm (aarch64_get_instr (cpu
), 24, 22));
10045 int32_t offset
= simm32 (aarch64_get_instr (cpu
), 21, 15);
10049 case 2: store_pair_u32 (cpu
, offset
, Post
); return;
10050 case 3: load_pair_u32 (cpu
, offset
, Post
); return;
10051 case 4: store_pair_u32 (cpu
, offset
, NoWriteBack
); return;
10052 case 5: load_pair_u32 (cpu
, offset
, NoWriteBack
); return;
10053 case 6: store_pair_u32 (cpu
, offset
, Pre
); return;
10054 case 7: load_pair_u32 (cpu
, offset
, Pre
); return;
10056 case 11: load_pair_s32 (cpu
, offset
, Post
); return;
10057 case 13: load_pair_s32 (cpu
, offset
, NoWriteBack
); return;
10058 case 15: load_pair_s32 (cpu
, offset
, Pre
); return;
10060 case 18: store_pair_u64 (cpu
, offset
, Post
); return;
10061 case 19: load_pair_u64 (cpu
, offset
, Post
); return;
10062 case 20: store_pair_u64 (cpu
, offset
, NoWriteBack
); return;
10063 case 21: load_pair_u64 (cpu
, offset
, NoWriteBack
); return;
10064 case 22: store_pair_u64 (cpu
, offset
, Pre
); return;
10065 case 23: load_pair_u64 (cpu
, offset
, Pre
); return;
10073 store_pair_float (sim_cpu
*cpu
, int32_t offset
, WriteBack wb
)
10075 unsigned rn
= uimm (aarch64_get_instr (cpu
), 14, 10);
10076 unsigned rd
= uimm (aarch64_get_instr (cpu
), 9, 5);
10077 unsigned rm
= uimm (aarch64_get_instr (cpu
), 4, 0);
10078 uint64_t address
= aarch64_get_reg_u64 (cpu
, rd
, SP_OK
);
10085 aarch64_set_mem_float (cpu
, address
, aarch64_get_FP_float (cpu
, rm
));
10086 aarch64_set_mem_float (cpu
, address
+ 4, aarch64_get_FP_float (cpu
, rn
));
10091 if (wb
!= NoWriteBack
)
10092 aarch64_set_reg_u64 (cpu
, rd
, SP_OK
, address
);
10096 store_pair_double (sim_cpu
*cpu
, int32_t offset
, WriteBack wb
)
10098 unsigned rn
= uimm (aarch64_get_instr (cpu
), 14, 10);
10099 unsigned rd
= uimm (aarch64_get_instr (cpu
), 9, 5);
10100 unsigned rm
= uimm (aarch64_get_instr (cpu
), 4, 0);
10101 uint64_t address
= aarch64_get_reg_u64 (cpu
, rd
, SP_OK
);
10108 aarch64_set_mem_double (cpu
, address
, aarch64_get_FP_double (cpu
, rm
));
10109 aarch64_set_mem_double (cpu
, address
+ 8, aarch64_get_FP_double (cpu
, rn
));
10114 if (wb
!= NoWriteBack
)
10115 aarch64_set_reg_u64 (cpu
, rd
, SP_OK
, address
);
10119 store_pair_long_double (sim_cpu
*cpu
, int32_t offset
, WriteBack wb
)
10122 unsigned rn
= uimm (aarch64_get_instr (cpu
), 14, 10);
10123 unsigned rd
= uimm (aarch64_get_instr (cpu
), 9, 5);
10124 unsigned rm
= uimm (aarch64_get_instr (cpu
), 4, 0);
10125 uint64_t address
= aarch64_get_reg_u64 (cpu
, rd
, SP_OK
);
10132 aarch64_get_FP_long_double (cpu
, rm
, & a
);
10133 aarch64_set_mem_long_double (cpu
, address
, a
);
10134 aarch64_get_FP_long_double (cpu
, rn
, & a
);
10135 aarch64_set_mem_long_double (cpu
, address
+ 16, a
);
10140 if (wb
!= NoWriteBack
)
10141 aarch64_set_reg_u64 (cpu
, rd
, SP_OK
, address
);
10145 load_pair_float (sim_cpu
*cpu
, int32_t offset
, WriteBack wb
)
10147 unsigned rn
= uimm (aarch64_get_instr (cpu
), 14, 10);
10148 unsigned rd
= uimm (aarch64_get_instr (cpu
), 9, 5);
10149 unsigned rm
= uimm (aarch64_get_instr (cpu
), 4, 0);
10150 uint64_t address
= aarch64_get_reg_u64 (cpu
, rd
, SP_OK
);
10160 aarch64_set_FP_float (cpu
, rm
, aarch64_get_mem_float (cpu
, address
));
10161 aarch64_set_FP_float (cpu
, rn
, aarch64_get_mem_float (cpu
, address
+ 4));
10166 if (wb
!= NoWriteBack
)
10167 aarch64_set_reg_u64 (cpu
, rd
, SP_OK
, address
);
10171 load_pair_double (sim_cpu
*cpu
, int32_t offset
, WriteBack wb
)
10173 unsigned rn
= uimm (aarch64_get_instr (cpu
), 14, 10);
10174 unsigned rd
= uimm (aarch64_get_instr (cpu
), 9, 5);
10175 unsigned rm
= uimm (aarch64_get_instr (cpu
), 4, 0);
10176 uint64_t address
= aarch64_get_reg_u64 (cpu
, rd
, SP_OK
);
10186 aarch64_set_FP_double (cpu
, rm
, aarch64_get_mem_double (cpu
, address
));
10187 aarch64_set_FP_double (cpu
, rn
, aarch64_get_mem_double (cpu
, address
+ 8));
10192 if (wb
!= NoWriteBack
)
10193 aarch64_set_reg_u64 (cpu
, rd
, SP_OK
, address
);
10197 load_pair_long_double (sim_cpu
*cpu
, int32_t offset
, WriteBack wb
)
10200 unsigned rn
= uimm (aarch64_get_instr (cpu
), 14, 10);
10201 unsigned rd
= uimm (aarch64_get_instr (cpu
), 9, 5);
10202 unsigned rm
= uimm (aarch64_get_instr (cpu
), 4, 0);
10203 uint64_t address
= aarch64_get_reg_u64 (cpu
, rd
, SP_OK
);
10213 aarch64_get_mem_long_double (cpu
, address
, & a
);
10214 aarch64_set_FP_long_double (cpu
, rm
, a
);
10215 aarch64_get_mem_long_double (cpu
, address
+ 16, & a
);
10216 aarch64_set_FP_long_double (cpu
, rn
, a
);
10221 if (wb
!= NoWriteBack
)
10222 aarch64_set_reg_u64 (cpu
, rd
, SP_OK
, address
);
10226 dex_load_store_pair_fp (sim_cpu
*cpu
)
10228 /* instr[31,30] = size (10=> 128-bit, 01=> 64-bit, 00=> 32-bit)
10229 instr[29,25] = instruction encoding
10230 instr[24,23] = addressing mode (10=> offset, 01=> post, 11=> pre)
10231 instr[22] = load/store (1=> load)
10232 instr[21,15] = signed, scaled, offset
10235 instr[ 4, 0] = Rm */
10237 uint32_t dispatch
= ((uimm (aarch64_get_instr (cpu
), 31, 30) << 3)
10238 | uimm (aarch64_get_instr (cpu
), 24, 22));
10239 int32_t offset
= simm32 (aarch64_get_instr (cpu
), 21, 15);
10243 case 2: store_pair_float (cpu
, offset
, Post
); return;
10244 case 3: load_pair_float (cpu
, offset
, Post
); return;
10245 case 4: store_pair_float (cpu
, offset
, NoWriteBack
); return;
10246 case 5: load_pair_float (cpu
, offset
, NoWriteBack
); return;
10247 case 6: store_pair_float (cpu
, offset
, Pre
); return;
10248 case 7: load_pair_float (cpu
, offset
, Pre
); return;
10250 case 10: store_pair_double (cpu
, offset
, Post
); return;
10251 case 11: load_pair_double (cpu
, offset
, Post
); return;
10252 case 12: store_pair_double (cpu
, offset
, NoWriteBack
); return;
10253 case 13: load_pair_double (cpu
, offset
, NoWriteBack
); return;
10254 case 14: store_pair_double (cpu
, offset
, Pre
); return;
10255 case 15: load_pair_double (cpu
, offset
, Pre
); return;
10257 case 18: store_pair_long_double (cpu
, offset
, Post
); return;
10258 case 19: load_pair_long_double (cpu
, offset
, Post
); return;
10259 case 20: store_pair_long_double (cpu
, offset
, NoWriteBack
); return;
10260 case 21: load_pair_long_double (cpu
, offset
, NoWriteBack
); return;
10261 case 22: store_pair_long_double (cpu
, offset
, Pre
); return;
10262 case 23: load_pair_long_double (cpu
, offset
, Pre
); return;
10269 static inline unsigned
10270 vec_reg (unsigned v
, unsigned o
)
10272 return (v
+ o
) & 0x3F;
10275 /* Load multiple N-element structures to N consecutive registers. */
10277 vec_load (sim_cpu
*cpu
, uint64_t address
, unsigned N
)
10279 int all
= uimm (aarch64_get_instr (cpu
), 30, 30);
10280 unsigned size
= uimm (aarch64_get_instr (cpu
), 11, 10);
10281 unsigned vd
= uimm (aarch64_get_instr (cpu
), 4, 0);
10286 case 0: /* 8-bit operations. */
10288 for (i
= 0; i
< (16 * N
); i
++)
10289 aarch64_set_vec_u8 (cpu
, vec_reg (vd
, i
>> 4), i
& 15,
10290 aarch64_get_mem_u8 (cpu
, address
+ i
));
10292 for (i
= 0; i
< (8 * N
); i
++)
10293 aarch64_set_vec_u8 (cpu
, vec_reg (vd
, i
>> 3), i
& 7,
10294 aarch64_get_mem_u8 (cpu
, address
+ i
));
10297 case 1: /* 16-bit operations. */
10299 for (i
= 0; i
< (8 * N
); i
++)
10300 aarch64_set_vec_u16 (cpu
, vec_reg (vd
, i
>> 3), i
& 7,
10301 aarch64_get_mem_u16 (cpu
, address
+ i
* 2));
10303 for (i
= 0; i
< (4 * N
); i
++)
10304 aarch64_set_vec_u16 (cpu
, vec_reg (vd
, i
>> 2), i
& 3,
10305 aarch64_get_mem_u16 (cpu
, address
+ i
* 2));
10308 case 2: /* 32-bit operations. */
10310 for (i
= 0; i
< (4 * N
); i
++)
10311 aarch64_set_vec_u32 (cpu
, vec_reg (vd
, i
>> 2), i
& 3,
10312 aarch64_get_mem_u32 (cpu
, address
+ i
* 4));
10314 for (i
= 0; i
< (2 * N
); i
++)
10315 aarch64_set_vec_u32 (cpu
, vec_reg (vd
, i
>> 1), i
& 1,
10316 aarch64_get_mem_u32 (cpu
, address
+ i
* 4));
10319 case 3: /* 64-bit operations. */
10321 for (i
= 0; i
< (2 * N
); i
++)
10322 aarch64_set_vec_u64 (cpu
, vec_reg (vd
, i
>> 1), i
& 1,
10323 aarch64_get_mem_u64 (cpu
, address
+ i
* 8));
10325 for (i
= 0; i
< N
; i
++)
10326 aarch64_set_vec_u64 (cpu
, vec_reg (vd
, i
), 0,
10327 aarch64_get_mem_u64 (cpu
, address
+ i
* 8));
10335 /* LD4: load multiple 4-element to four consecutive registers. */
10337 LD4 (sim_cpu
*cpu
, uint64_t address
)
10339 vec_load (cpu
, address
, 4);
10342 /* LD3: load multiple 3-element structures to three consecutive registers. */
10344 LD3 (sim_cpu
*cpu
, uint64_t address
)
10346 vec_load (cpu
, address
, 3);
10349 /* LD2: load multiple 2-element structures to two consecutive registers. */
10351 LD2 (sim_cpu
*cpu
, uint64_t address
)
10353 vec_load (cpu
, address
, 2);
10356 /* Load multiple 1-element structures into one register. */
10358 LD1_1 (sim_cpu
*cpu
, uint64_t address
)
10360 int all
= uimm (aarch64_get_instr (cpu
), 30, 30);
10361 unsigned size
= uimm (aarch64_get_instr (cpu
), 11, 10);
10362 unsigned vd
= uimm (aarch64_get_instr (cpu
), 4, 0);
10368 /* LD1 {Vd.16b}, addr, #16 */
10369 /* LD1 {Vd.8b}, addr, #8 */
10370 for (i
= 0; i
< (all
? 16 : 8); i
++)
10371 aarch64_set_vec_u8 (cpu
, vd
, i
,
10372 aarch64_get_mem_u8 (cpu
, address
+ i
));
10376 /* LD1 {Vd.8h}, addr, #16 */
10377 /* LD1 {Vd.4h}, addr, #8 */
10378 for (i
= 0; i
< (all
? 8 : 4); i
++)
10379 aarch64_set_vec_u16 (cpu
, vd
, i
,
10380 aarch64_get_mem_u16 (cpu
, address
+ i
* 2));
10384 /* LD1 {Vd.4s}, addr, #16 */
10385 /* LD1 {Vd.2s}, addr, #8 */
10386 for (i
= 0; i
< (all
? 4 : 2); i
++)
10387 aarch64_set_vec_u32 (cpu
, vd
, i
,
10388 aarch64_get_mem_u32 (cpu
, address
+ i
* 4));
10392 /* LD1 {Vd.2d}, addr, #16 */
10393 /* LD1 {Vd.1d}, addr, #8 */
10394 for (i
= 0; i
< (all
? 2 : 1); i
++)
10395 aarch64_set_vec_u64 (cpu
, vd
, i
,
10396 aarch64_get_mem_u64 (cpu
, address
+ i
* 8));
10404 /* Load multiple 1-element structures into two registers. */
10406 LD1_2 (sim_cpu
*cpu
, uint64_t address
)
10408 /* FIXME: This algorithm is *exactly* the same as the LD2 version.
10409 So why have two different instructions ? There must be something
10410 wrong somewhere. */
10411 vec_load (cpu
, address
, 2);
10414 /* Load multiple 1-element structures into three registers. */
10416 LD1_3 (sim_cpu
*cpu
, uint64_t address
)
10418 /* FIXME: This algorithm is *exactly* the same as the LD3 version.
10419 So why have two different instructions ? There must be something
10420 wrong somewhere. */
10421 vec_load (cpu
, address
, 3);
10424 /* Load multiple 1-element structures into four registers. */
10426 LD1_4 (sim_cpu
*cpu
, uint64_t address
)
10428 /* FIXME: This algorithm is *exactly* the same as the LD4 version.
10429 So why have two different instructions ? There must be something
10430 wrong somewhere. */
10431 vec_load (cpu
, address
, 4);
10434 /* Store multiple N-element structures to N consecutive registers. */
10436 vec_store (sim_cpu
*cpu
, uint64_t address
, unsigned N
)
10438 int all
= uimm (aarch64_get_instr (cpu
), 30, 30);
10439 unsigned size
= uimm (aarch64_get_instr (cpu
), 11, 10);
10440 unsigned vd
= uimm (aarch64_get_instr (cpu
), 4, 0);
10445 case 0: /* 8-bit operations. */
10447 for (i
= 0; i
< (16 * N
); i
++)
10450 aarch64_get_vec_u8 (cpu
, vec_reg (vd
, i
>> 4), i
& 15));
10452 for (i
= 0; i
< (8 * N
); i
++)
10455 aarch64_get_vec_u8 (cpu
, vec_reg (vd
, i
>> 3), i
& 7));
10458 case 1: /* 16-bit operations. */
10460 for (i
= 0; i
< (8 * N
); i
++)
10461 aarch64_set_mem_u16
10462 (cpu
, address
+ i
* 2,
10463 aarch64_get_vec_u16 (cpu
, vec_reg (vd
, i
>> 3), i
& 7));
10465 for (i
= 0; i
< (4 * N
); i
++)
10466 aarch64_set_mem_u16
10467 (cpu
, address
+ i
* 2,
10468 aarch64_get_vec_u16 (cpu
, vec_reg (vd
, i
>> 2), i
& 3));
10471 case 2: /* 32-bit operations. */
10473 for (i
= 0; i
< (4 * N
); i
++)
10474 aarch64_set_mem_u32
10475 (cpu
, address
+ i
* 4,
10476 aarch64_get_vec_u32 (cpu
, vec_reg (vd
, i
>> 2), i
& 3));
10478 for (i
= 0; i
< (2 * N
); i
++)
10479 aarch64_set_mem_u32
10480 (cpu
, address
+ i
* 4,
10481 aarch64_get_vec_u32 (cpu
, vec_reg (vd
, i
>> 1), i
& 1));
10484 case 3: /* 64-bit operations. */
10486 for (i
= 0; i
< (2 * N
); i
++)
10487 aarch64_set_mem_u64
10488 (cpu
, address
+ i
* 8,
10489 aarch64_get_vec_u64 (cpu
, vec_reg (vd
, i
>> 1), i
& 1));
10491 for (i
= 0; i
< N
; i
++)
10492 aarch64_set_mem_u64
10493 (cpu
, address
+ i
* 8,
10494 aarch64_get_vec_u64 (cpu
, vec_reg (vd
, i
), 0));
10502 /* Store multiple 4-element structure to four consecutive registers. */
10504 ST4 (sim_cpu
*cpu
, uint64_t address
)
10506 vec_store (cpu
, address
, 4);
10509 /* Store multiple 3-element structures to three consecutive registers. */
10511 ST3 (sim_cpu
*cpu
, uint64_t address
)
10513 vec_store (cpu
, address
, 3);
10516 /* Store multiple 2-element structures to two consecutive registers. */
10518 ST2 (sim_cpu
*cpu
, uint64_t address
)
10520 vec_store (cpu
, address
, 2);
10523 /* Store multiple 1-element structures into one register. */
10525 ST1_1 (sim_cpu
*cpu
, uint64_t address
)
10527 int all
= uimm (aarch64_get_instr (cpu
), 30, 30);
10528 unsigned size
= uimm (aarch64_get_instr (cpu
), 11, 10);
10529 unsigned vd
= uimm (aarch64_get_instr (cpu
), 4, 0);
10535 for (i
= 0; i
< (all
? 16 : 8); i
++)
10536 aarch64_set_mem_u8 (cpu
, address
+ i
,
10537 aarch64_get_vec_u8 (cpu
, vd
, i
));
10541 for (i
= 0; i
< (all
? 8 : 4); i
++)
10542 aarch64_set_mem_u16 (cpu
, address
+ i
* 2,
10543 aarch64_get_vec_u16 (cpu
, vd
, i
));
10547 for (i
= 0; i
< (all
? 4 : 2); i
++)
10548 aarch64_set_mem_u32 (cpu
, address
+ i
* 4,
10549 aarch64_get_vec_u32 (cpu
, vd
, i
));
10553 for (i
= 0; i
< (all
? 2 : 1); i
++)
10554 aarch64_set_mem_u64 (cpu
, address
+ i
* 8,
10555 aarch64_get_vec_u64 (cpu
, vd
, i
));
10563 /* Store multiple 1-element structures into two registers. */
10565 ST1_2 (sim_cpu
*cpu
, uint64_t address
)
10567 /* FIXME: This algorithm is *exactly* the same as the ST2 version.
10568 So why have two different instructions ? There must be
10569 something wrong somewhere. */
10570 vec_store (cpu
, address
, 2);
10573 /* Store multiple 1-element structures into three registers. */
10575 ST1_3 (sim_cpu
*cpu
, uint64_t address
)
10577 /* FIXME: This algorithm is *exactly* the same as the ST3 version.
10578 So why have two different instructions ? There must be
10579 something wrong somewhere. */
10580 vec_store (cpu
, address
, 3);
10583 /* Store multiple 1-element structures into four registers. */
10585 ST1_4 (sim_cpu
*cpu
, uint64_t address
)
10587 /* FIXME: This algorithm is *exactly* the same as the ST4 version.
10588 So why have two different instructions ? There must be
10589 something wrong somewhere. */
10590 vec_store (cpu
, address
, 4);
10594 do_vec_LDnR (sim_cpu
*cpu
, uint64_t address
)
10597 instr[30] = element selector 0=>half, 1=>all elements
10598 instr[29,24] = 00 1101
10599 instr[23] = 0=>simple, 1=>post
10601 instr[21] = width: LD1R-or-LD3R (0) / LD2R-or-LD4R (1)
10602 instr[20,16] = 0 0000 (simple), Vinc (reg-post-inc, no SP),
10603 11111 (immediate post inc)
10605 instr[13] = width: LD1R-or-LD2R (0) / LD3R-or-LD4R (1)
10607 instr[11,10] = element size 00=> byte(b), 01=> half(h),
10608 10=> word(s), 11=> double(d)
10609 instr[9,5] = address
10612 unsigned full
= uimm (aarch64_get_instr (cpu
), 30, 30);
10613 unsigned vd
= uimm (aarch64_get_instr (cpu
), 4, 0);
10614 unsigned size
= uimm (aarch64_get_instr (cpu
), 11, 10);
10617 NYI_assert (29, 24, 0x0D);
10618 NYI_assert (22, 22, 1);
10619 NYI_assert (15, 14, 3);
10620 NYI_assert (12, 12, 0);
10622 switch ((uimm (aarch64_get_instr (cpu
), 13, 13) << 1)
10623 | uimm (aarch64_get_instr (cpu
), 21, 21))
10625 case 0: /* LD1R. */
10630 uint8_t val
= aarch64_get_mem_u8 (cpu
, address
);
10631 for (i
= 0; i
< (full
? 16 : 8); i
++)
10632 aarch64_set_vec_u8 (cpu
, vd
, i
, val
);
10638 uint16_t val
= aarch64_get_mem_u16 (cpu
, address
);
10639 for (i
= 0; i
< (full
? 8 : 4); i
++)
10640 aarch64_set_vec_u16 (cpu
, vd
, i
, val
);
10646 uint32_t val
= aarch64_get_mem_u32 (cpu
, address
);
10647 for (i
= 0; i
< (full
? 4 : 2); i
++)
10648 aarch64_set_vec_u32 (cpu
, vd
, i
, val
);
10654 uint64_t val
= aarch64_get_mem_u64 (cpu
, address
);
10655 for (i
= 0; i
< (full
? 2 : 1); i
++)
10656 aarch64_set_vec_u64 (cpu
, vd
, i
, val
);
10665 case 1: /* LD2R. */
10670 uint8_t val1
= aarch64_get_mem_u8 (cpu
, address
);
10671 uint8_t val2
= aarch64_get_mem_u8 (cpu
, address
+ 1);
10673 for (i
= 0; i
< (full
? 16 : 8); i
++)
10675 aarch64_set_vec_u8 (cpu
, vd
, 0, val1
);
10676 aarch64_set_vec_u8 (cpu
, vd
+ 1, 0, val2
);
10683 uint16_t val1
= aarch64_get_mem_u16 (cpu
, address
);
10684 uint16_t val2
= aarch64_get_mem_u16 (cpu
, address
+ 2);
10686 for (i
= 0; i
< (full
? 8 : 4); i
++)
10688 aarch64_set_vec_u16 (cpu
, vd
, 0, val1
);
10689 aarch64_set_vec_u16 (cpu
, vd
+ 1, 0, val2
);
10696 uint32_t val1
= aarch64_get_mem_u32 (cpu
, address
);
10697 uint32_t val2
= aarch64_get_mem_u32 (cpu
, address
+ 4);
10699 for (i
= 0; i
< (full
? 4 : 2); i
++)
10701 aarch64_set_vec_u32 (cpu
, vd
, 0, val1
);
10702 aarch64_set_vec_u32 (cpu
, vd
+ 1, 0, val2
);
10709 uint64_t val1
= aarch64_get_mem_u64 (cpu
, address
);
10710 uint64_t val2
= aarch64_get_mem_u64 (cpu
, address
+ 8);
10712 for (i
= 0; i
< (full
? 2 : 1); i
++)
10714 aarch64_set_vec_u64 (cpu
, vd
, 0, val1
);
10715 aarch64_set_vec_u64 (cpu
, vd
+ 1, 0, val2
);
10725 case 2: /* LD3R. */
10730 uint8_t val1
= aarch64_get_mem_u8 (cpu
, address
);
10731 uint8_t val2
= aarch64_get_mem_u8 (cpu
, address
+ 1);
10732 uint8_t val3
= aarch64_get_mem_u8 (cpu
, address
+ 2);
10734 for (i
= 0; i
< (full
? 16 : 8); i
++)
10736 aarch64_set_vec_u8 (cpu
, vd
, 0, val1
);
10737 aarch64_set_vec_u8 (cpu
, vd
+ 1, 0, val2
);
10738 aarch64_set_vec_u8 (cpu
, vd
+ 2, 0, val3
);
10745 uint32_t val1
= aarch64_get_mem_u16 (cpu
, address
);
10746 uint32_t val2
= aarch64_get_mem_u16 (cpu
, address
+ 2);
10747 uint32_t val3
= aarch64_get_mem_u16 (cpu
, address
+ 4);
10749 for (i
= 0; i
< (full
? 8 : 4); i
++)
10751 aarch64_set_vec_u16 (cpu
, vd
, 0, val1
);
10752 aarch64_set_vec_u16 (cpu
, vd
+ 1, 0, val2
);
10753 aarch64_set_vec_u16 (cpu
, vd
+ 2, 0, val3
);
10760 uint32_t val1
= aarch64_get_mem_u32 (cpu
, address
);
10761 uint32_t val2
= aarch64_get_mem_u32 (cpu
, address
+ 4);
10762 uint32_t val3
= aarch64_get_mem_u32 (cpu
, address
+ 8);
10764 for (i
= 0; i
< (full
? 4 : 2); i
++)
10766 aarch64_set_vec_u32 (cpu
, vd
, 0, val1
);
10767 aarch64_set_vec_u32 (cpu
, vd
+ 1, 0, val2
);
10768 aarch64_set_vec_u32 (cpu
, vd
+ 2, 0, val3
);
10775 uint64_t val1
= aarch64_get_mem_u64 (cpu
, address
);
10776 uint64_t val2
= aarch64_get_mem_u64 (cpu
, address
+ 8);
10777 uint64_t val3
= aarch64_get_mem_u64 (cpu
, address
+ 16);
10779 for (i
= 0; i
< (full
? 2 : 1); i
++)
10781 aarch64_set_vec_u64 (cpu
, vd
, 0, val1
);
10782 aarch64_set_vec_u64 (cpu
, vd
+ 1, 0, val2
);
10783 aarch64_set_vec_u64 (cpu
, vd
+ 2, 0, val3
);
10793 case 3: /* LD4R. */
10798 uint8_t val1
= aarch64_get_mem_u8 (cpu
, address
);
10799 uint8_t val2
= aarch64_get_mem_u8 (cpu
, address
+ 1);
10800 uint8_t val3
= aarch64_get_mem_u8 (cpu
, address
+ 2);
10801 uint8_t val4
= aarch64_get_mem_u8 (cpu
, address
+ 3);
10803 for (i
= 0; i
< (full
? 16 : 8); i
++)
10805 aarch64_set_vec_u8 (cpu
, vd
, 0, val1
);
10806 aarch64_set_vec_u8 (cpu
, vd
+ 1, 0, val2
);
10807 aarch64_set_vec_u8 (cpu
, vd
+ 2, 0, val3
);
10808 aarch64_set_vec_u8 (cpu
, vd
+ 3, 0, val4
);
10815 uint32_t val1
= aarch64_get_mem_u16 (cpu
, address
);
10816 uint32_t val2
= aarch64_get_mem_u16 (cpu
, address
+ 2);
10817 uint32_t val3
= aarch64_get_mem_u16 (cpu
, address
+ 4);
10818 uint32_t val4
= aarch64_get_mem_u16 (cpu
, address
+ 6);
10820 for (i
= 0; i
< (full
? 8 : 4); i
++)
10822 aarch64_set_vec_u16 (cpu
, vd
, 0, val1
);
10823 aarch64_set_vec_u16 (cpu
, vd
+ 1, 0, val2
);
10824 aarch64_set_vec_u16 (cpu
, vd
+ 2, 0, val3
);
10825 aarch64_set_vec_u16 (cpu
, vd
+ 3, 0, val4
);
10832 uint32_t val1
= aarch64_get_mem_u32 (cpu
, address
);
10833 uint32_t val2
= aarch64_get_mem_u32 (cpu
, address
+ 4);
10834 uint32_t val3
= aarch64_get_mem_u32 (cpu
, address
+ 8);
10835 uint32_t val4
= aarch64_get_mem_u32 (cpu
, address
+ 12);
10837 for (i
= 0; i
< (full
? 4 : 2); i
++)
10839 aarch64_set_vec_u32 (cpu
, vd
, 0, val1
);
10840 aarch64_set_vec_u32 (cpu
, vd
+ 1, 0, val2
);
10841 aarch64_set_vec_u32 (cpu
, vd
+ 2, 0, val3
);
10842 aarch64_set_vec_u32 (cpu
, vd
+ 3, 0, val4
);
10849 uint64_t val1
= aarch64_get_mem_u64 (cpu
, address
);
10850 uint64_t val2
= aarch64_get_mem_u64 (cpu
, address
+ 8);
10851 uint64_t val3
= aarch64_get_mem_u64 (cpu
, address
+ 16);
10852 uint64_t val4
= aarch64_get_mem_u64 (cpu
, address
+ 24);
10854 for (i
= 0; i
< (full
? 2 : 1); i
++)
10856 aarch64_set_vec_u64 (cpu
, vd
, 0, val1
);
10857 aarch64_set_vec_u64 (cpu
, vd
+ 1, 0, val2
);
10858 aarch64_set_vec_u64 (cpu
, vd
+ 2, 0, val3
);
10859 aarch64_set_vec_u64 (cpu
, vd
+ 3, 0, val4
);
10875 do_vec_load_store (sim_cpu
*cpu
)
10877 /* {LD|ST}<N> {Vd..Vd+N}, vaddr
10880 instr[30] = element selector 0=>half, 1=>all elements
10881 instr[29,25] = 00110
10883 instr[23] = 0=>simple, 1=>post
10884 instr[22] = 0=>store, 1=>load
10885 instr[21] = 0 (LDn) / small(0)-large(1) selector (LDnR)
10886 instr[20,16] = 00000 (simple), Vinc (reg-post-inc, no SP),
10887 11111 (immediate post inc)
10888 instr[15,12] = elements and destinations. eg for load:
10889 0000=>LD4 => load multiple 4-element to
10890 four consecutive registers
10891 0100=>LD3 => load multiple 3-element to
10892 three consecutive registers
10893 1000=>LD2 => load multiple 2-element to
10894 two consecutive registers
10895 0010=>LD1 => load multiple 1-element to
10896 four consecutive registers
10897 0110=>LD1 => load multiple 1-element to
10898 three consecutive registers
10899 1010=>LD1 => load multiple 1-element to
10900 two consecutive registers
10901 0111=>LD1 => load multiple 1-element to
10905 instr[11,10] = element size 00=> byte(b), 01=> half(h),
10906 10=> word(s), 11=> double(d)
10907 instr[9,5] = Vn, can be SP
10916 if (uimm (aarch64_get_instr (cpu
), 31, 31) != 0
10917 || uimm (aarch64_get_instr (cpu
), 29, 25) != 0x06)
10920 type
= uimm (aarch64_get_instr (cpu
), 15, 12);
10921 if (type
!= 0xE && type
!= 0xE && uimm (aarch64_get_instr (cpu
), 21, 21) != 0)
10924 post
= uimm (aarch64_get_instr (cpu
), 23, 23);
10925 load
= uimm (aarch64_get_instr (cpu
), 22, 22);
10926 vn
= uimm (aarch64_get_instr (cpu
), 9, 5);
10927 address
= aarch64_get_reg_u64 (cpu
, vn
, SP_OK
);
10931 unsigned vm
= uimm (aarch64_get_instr (cpu
), 20, 16);
10935 unsigned sizeof_operation
;
10939 case 0: sizeof_operation
= 32; break;
10940 case 4: sizeof_operation
= 24; break;
10941 case 8: sizeof_operation
= 16; break;
10944 sizeof_operation
= uimm (aarch64_get_instr (cpu
), 21, 21) ? 2 : 1;
10945 sizeof_operation
<<= uimm (aarch64_get_instr (cpu
), 11, 10);
10949 sizeof_operation
= uimm (aarch64_get_instr (cpu
), 21, 21) ? 8 : 4;
10950 sizeof_operation
<<= uimm (aarch64_get_instr (cpu
), 11, 10);
10957 sizeof_operation
= 2 << uimm (aarch64_get_instr (cpu
), 11, 10);
10964 if (uimm (aarch64_get_instr (cpu
), 30, 30))
10965 sizeof_operation
*= 2;
10967 aarch64_set_reg_u64 (cpu
, vn
, SP_OK
, address
+ sizeof_operation
);
10970 aarch64_set_reg_u64 (cpu
, vn
, SP_OK
,
10971 address
+ aarch64_get_reg_u64 (cpu
, vm
, NO_SP
));
10975 NYI_assert (20, 16, 0);
10982 case 0: LD4 (cpu
, address
); return;
10983 case 4: LD3 (cpu
, address
); return;
10984 case 8: LD2 (cpu
, address
); return;
10985 case 2: LD1_4 (cpu
, address
); return;
10986 case 6: LD1_3 (cpu
, address
); return;
10987 case 10: LD1_2 (cpu
, address
); return;
10988 case 7: LD1_1 (cpu
, address
); return;
10991 case 0xC: do_vec_LDnR (cpu
, address
); return;
11001 case 0: ST4 (cpu
, address
); return;
11002 case 4: ST3 (cpu
, address
); return;
11003 case 8: ST2 (cpu
, address
); return;
11004 case 2: ST1_4 (cpu
, address
); return;
11005 case 6: ST1_3 (cpu
, address
); return;
11006 case 10: ST1_2 (cpu
, address
); return;
11007 case 7: ST1_1 (cpu
, address
); return;
11014 dexLdSt (sim_cpu
*cpu
)
11016 /* uint32_t group = dispatchGroup (aarch64_get_instr (cpu));
11017 assert group == GROUP_LDST_0100 || group == GROUP_LDST_0110 ||
11018 group == GROUP_LDST_1100 || group == GROUP_LDST_1110
11019 bits [29,28:26] of a LS are the secondary dispatch vector. */
11020 uint32_t group2
= dispatchLS (aarch64_get_instr (cpu
));
11025 dexLoadExclusive (cpu
); return;
11029 dexLoadLiteral (cpu
); return;
11033 dexLoadOther (cpu
); return;
11035 case LS_ADVSIMD_001
:
11036 do_vec_load_store (cpu
); return;
11039 dex_load_store_pair_gr (cpu
); return;
11042 dex_load_store_pair_fp (cpu
); return;
11045 /* Should never reach here. */
11050 /* Specific decode and execute for group Data Processing Register. */
11053 dexLogicalShiftedRegister (sim_cpu
*cpu
)
11055 /* assert instr[28:24] = 01010
11056 instr[31] = size : 0 ==> 32 bit, 1 ==> 64 bit
11057 instr[30,29:21] = op,N : 000 ==> AND, 001 ==> BIC,
11058 010 ==> ORR, 011 ==> ORN
11059 100 ==> EOR, 101 ==> EON,
11060 110 ==> ANDS, 111 ==> BICS
11061 instr[23,22] = shift : 0 ==> LSL, 1 ==> LSR, 2 ==> ASR, 3 ==> ROR
11062 instr[15,10] = count : must be 0xxxxx for 32 bit
11066 /* unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16); */
11069 uint32_t size
= uimm (aarch64_get_instr (cpu
), 31, 31);
11071 /* 32 bit operations must have count[5] = 0. */
11072 /* or else we have an UNALLOC. */
11073 uint32_t count
= uimm (aarch64_get_instr (cpu
), 15, 10);
11075 if (!size
&& uimm (count
, 5, 5))
11078 shiftType
= shift (aarch64_get_instr (cpu
), 22);
11080 /* dispatch on size:op:N i.e aarch64_get_instr (cpu)[31,29:21]. */
11081 dispatch
= ( (uimm (aarch64_get_instr (cpu
), 31, 29) << 1)
11082 | uimm (aarch64_get_instr (cpu
), 21, 21));
11086 case 0: and32_shift (cpu
, shiftType
, count
); return;
11087 case 1: bic32_shift (cpu
, shiftType
, count
); return;
11088 case 2: orr32_shift (cpu
, shiftType
, count
); return;
11089 case 3: orn32_shift (cpu
, shiftType
, count
); return;
11090 case 4: eor32_shift (cpu
, shiftType
, count
); return;
11091 case 5: eon32_shift (cpu
, shiftType
, count
); return;
11092 case 6: ands32_shift (cpu
, shiftType
, count
); return;
11093 case 7: bics32_shift (cpu
, shiftType
, count
); return;
11094 case 8: and64_shift (cpu
, shiftType
, count
); return;
11095 case 9: bic64_shift (cpu
, shiftType
, count
); return;
11096 case 10:orr64_shift (cpu
, shiftType
, count
); return;
11097 case 11:orn64_shift (cpu
, shiftType
, count
); return;
11098 case 12:eor64_shift (cpu
, shiftType
, count
); return;
11099 case 13:eon64_shift (cpu
, shiftType
, count
); return;
11100 case 14:ands64_shift (cpu
, shiftType
, count
); return;
11101 case 15:bics64_shift (cpu
, shiftType
, count
); return;
11102 default: HALT_UNALLOC
;
11106 /* 32 bit conditional select. */
11108 csel32 (sim_cpu
*cpu
, CondCode cc
)
11110 unsigned rm
= uimm (aarch64_get_instr (cpu
), 20, 16);
11111 unsigned rn
= uimm (aarch64_get_instr (cpu
), 9, 5);
11112 unsigned rd
= uimm (aarch64_get_instr (cpu
), 4, 0);
11114 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
,
11115 testConditionCode (cpu
, cc
)
11116 ? aarch64_get_reg_u32 (cpu
, rn
, NO_SP
)
11117 : aarch64_get_reg_u32 (cpu
, rm
, NO_SP
));
11120 /* 64 bit conditional select. */
11122 csel64 (sim_cpu
*cpu
, CondCode cc
)
11124 unsigned rm
= uimm (aarch64_get_instr (cpu
), 20, 16);
11125 unsigned rn
= uimm (aarch64_get_instr (cpu
), 9, 5);
11126 unsigned rd
= uimm (aarch64_get_instr (cpu
), 4, 0);
11128 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
,
11129 testConditionCode (cpu
, cc
)
11130 ? aarch64_get_reg_u64 (cpu
, rn
, NO_SP
)
11131 : aarch64_get_reg_u64 (cpu
, rm
, NO_SP
));
11134 /* 32 bit conditional increment. */
11136 csinc32 (sim_cpu
*cpu
, CondCode cc
)
11138 unsigned rm
= uimm (aarch64_get_instr (cpu
), 20, 16);
11139 unsigned rn
= uimm (aarch64_get_instr (cpu
), 9, 5);
11140 unsigned rd
= uimm (aarch64_get_instr (cpu
), 4, 0);
11142 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
,
11143 testConditionCode (cpu
, cc
)
11144 ? aarch64_get_reg_u32 (cpu
, rn
, NO_SP
)
11145 : aarch64_get_reg_u32 (cpu
, rm
, NO_SP
) + 1);
11148 /* 64 bit conditional increment. */
11150 csinc64 (sim_cpu
*cpu
, CondCode cc
)
11152 unsigned rm
= uimm (aarch64_get_instr (cpu
), 20, 16);
11153 unsigned rn
= uimm (aarch64_get_instr (cpu
), 9, 5);
11154 unsigned rd
= uimm (aarch64_get_instr (cpu
), 4, 0);
11156 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
,
11157 testConditionCode (cpu
, cc
)
11158 ? aarch64_get_reg_u64 (cpu
, rn
, NO_SP
)
11159 : aarch64_get_reg_u64 (cpu
, rm
, NO_SP
) + 1);
11162 /* 32 bit conditional invert. */
11164 csinv32 (sim_cpu
*cpu
, CondCode cc
)
11166 unsigned rm
= uimm (aarch64_get_instr (cpu
), 20, 16);
11167 unsigned rn
= uimm (aarch64_get_instr (cpu
), 9, 5);
11168 unsigned rd
= uimm (aarch64_get_instr (cpu
), 4, 0);
11170 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
,
11171 testConditionCode (cpu
, cc
)
11172 ? aarch64_get_reg_u32 (cpu
, rn
, NO_SP
)
11173 : ~ aarch64_get_reg_u32 (cpu
, rm
, NO_SP
));
11176 /* 64 bit conditional invert. */
11178 csinv64 (sim_cpu
*cpu
, CondCode cc
)
11180 unsigned rm
= uimm (aarch64_get_instr (cpu
), 20, 16);
11181 unsigned rn
= uimm (aarch64_get_instr (cpu
), 9, 5);
11182 unsigned rd
= uimm (aarch64_get_instr (cpu
), 4, 0);
11184 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
,
11185 testConditionCode (cpu
, cc
)
11186 ? aarch64_get_reg_u64 (cpu
, rn
, NO_SP
)
11187 : ~ aarch64_get_reg_u64 (cpu
, rm
, NO_SP
));
11190 /* 32 bit conditional negate. */
11192 csneg32 (sim_cpu
*cpu
, CondCode cc
)
11194 unsigned rm
= uimm (aarch64_get_instr (cpu
), 20, 16);
11195 unsigned rn
= uimm (aarch64_get_instr (cpu
), 9, 5);
11196 unsigned rd
= uimm (aarch64_get_instr (cpu
), 4, 0);
11198 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
,
11199 testConditionCode (cpu
, cc
)
11200 ? aarch64_get_reg_u32 (cpu
, rn
, NO_SP
)
11201 : - aarch64_get_reg_u32 (cpu
, rm
, NO_SP
));
11204 /* 64 bit conditional negate. */
11206 csneg64 (sim_cpu
*cpu
, CondCode cc
)
11208 unsigned rm
= uimm (aarch64_get_instr (cpu
), 20, 16);
11209 unsigned rn
= uimm (aarch64_get_instr (cpu
), 9, 5);
11210 unsigned rd
= uimm (aarch64_get_instr (cpu
), 4, 0);
11212 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
,
11213 testConditionCode (cpu
, cc
)
11214 ? aarch64_get_reg_u64 (cpu
, rn
, NO_SP
)
11215 : - aarch64_get_reg_u64 (cpu
, rm
, NO_SP
));
11219 dexCondSelect (sim_cpu
*cpu
)
11221 /* assert instr[28,21] = 11011011
11222 instr[31] = size : 0 ==> 32 bit, 1 ==> 64 bit
11223 instr[30:11,10] = op : 000 ==> CSEL, 001 ==> CSINC,
11224 100 ==> CSINV, 101 ==> CSNEG,
11226 instr[29] = S : 0 ==> ok, 1 ==> UNALLOC
11227 instr[15,12] = cond
11228 instr[29] = S : 0 ==> ok, 1 ==> UNALLOC */
11232 uint32_t S
= uimm (aarch64_get_instr (cpu
), 29, 29);
11233 uint32_t op2
= uimm (aarch64_get_instr (cpu
), 11, 10);
11241 cc
= condcode (aarch64_get_instr (cpu
), 12);
11242 dispatch
= ((uimm (aarch64_get_instr (cpu
), 31, 30) << 1) | op2
);
11246 case 0: csel32 (cpu
, cc
); return;
11247 case 1: csinc32 (cpu
, cc
); return;
11248 case 2: csinv32 (cpu
, cc
); return;
11249 case 3: csneg32 (cpu
, cc
); return;
11250 case 4: csel64 (cpu
, cc
); return;
11251 case 5: csinc64 (cpu
, cc
); return;
11252 case 6: csinv64 (cpu
, cc
); return;
11253 case 7: csneg64 (cpu
, cc
); return;
11254 default: HALT_UNALLOC
;
11258 /* Some helpers for counting leading 1 or 0 bits. */
11260 /* Counts the number of leading bits which are the same
11261 in a 32 bit value in the range 1 to 32. */
11263 leading32 (uint32_t value
)
11265 int32_t mask
= 0xffff0000;
11266 uint32_t count
= 16; /* Counts number of bits set in mask. */
11267 uint32_t lo
= 1; /* Lower bound for number of sign bits. */
11268 uint32_t hi
= 32; /* Upper bound for number of sign bits. */
11270 while (lo
+ 1 < hi
)
11272 int32_t test
= (value
& mask
);
11274 if (test
== 0 || test
== mask
)
11277 count
= (lo
+ hi
) / 2;
11278 mask
>>= (count
- lo
);
11283 count
= (lo
+ hi
) / 2;
11284 mask
<<= hi
- count
;
11293 test
= (value
& mask
);
11295 if (test
== 0 || test
== mask
)
11304 /* Counts the number of leading bits which are the same
11305 in a 64 bit value in the range 1 to 64. */
11307 leading64 (uint64_t value
)
11309 int64_t mask
= 0xffffffff00000000LL
;
11310 uint64_t count
= 32; /* Counts number of bits set in mask. */
11311 uint64_t lo
= 1; /* Lower bound for number of sign bits. */
11312 uint64_t hi
= 64; /* Upper bound for number of sign bits. */
11314 while (lo
+ 1 < hi
)
11316 int64_t test
= (value
& mask
);
11318 if (test
== 0 || test
== mask
)
11321 count
= (lo
+ hi
) / 2;
11322 mask
>>= (count
- lo
);
11327 count
= (lo
+ hi
) / 2;
11328 mask
<<= hi
- count
;
11337 test
= (value
& mask
);
11339 if (test
== 0 || test
== mask
)
11348 /* Bit operations. */
11349 /* N.B register args may not be SP. */
11351 /* 32 bit count leading sign bits. */
11353 cls32 (sim_cpu
*cpu
)
11355 unsigned rn
= uimm (aarch64_get_instr (cpu
), 9, 5);
11356 unsigned rd
= uimm (aarch64_get_instr (cpu
), 4, 0);
11358 /* N.B. the result needs to exclude the leading bit. */
11359 aarch64_set_reg_u64
11360 (cpu
, rd
, NO_SP
, leading32 (aarch64_get_reg_u32 (cpu
, rn
, NO_SP
)) - 1);
11363 /* 64 bit count leading sign bits. */
11365 cls64 (sim_cpu
*cpu
)
11367 unsigned rn
= uimm (aarch64_get_instr (cpu
), 9, 5);
11368 unsigned rd
= uimm (aarch64_get_instr (cpu
), 4, 0);
11370 /* N.B. the result needs to exclude the leading bit. */
11371 aarch64_set_reg_u64
11372 (cpu
, rd
, NO_SP
, leading64 (aarch64_get_reg_u64 (cpu
, rn
, NO_SP
)) - 1);
11375 /* 32 bit count leading zero bits. */
11377 clz32 (sim_cpu
*cpu
)
11379 unsigned rn
= uimm (aarch64_get_instr (cpu
), 9, 5);
11380 unsigned rd
= uimm (aarch64_get_instr (cpu
), 4, 0);
11381 uint32_t value
= aarch64_get_reg_u32 (cpu
, rn
, NO_SP
);
11383 /* if the sign (top) bit is set then the count is 0. */
11384 if (pick32 (value
, 31, 31))
11385 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, 0L);
11387 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, leading32 (value
));
11390 /* 64 bit count leading zero bits. */
11392 clz64 (sim_cpu
*cpu
)
11394 unsigned rn
= uimm (aarch64_get_instr (cpu
), 9, 5);
11395 unsigned rd
= uimm (aarch64_get_instr (cpu
), 4, 0);
11396 uint64_t value
= aarch64_get_reg_u64 (cpu
, rn
, NO_SP
);
11398 /* if the sign (top) bit is set then the count is 0. */
11399 if (pick64 (value
, 63, 63))
11400 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, 0L);
11402 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, leading64 (value
));
11405 /* 32 bit reverse bits. */
11407 rbit32 (sim_cpu
*cpu
)
11409 unsigned rn
= uimm (aarch64_get_instr (cpu
), 9, 5);
11410 unsigned rd
= uimm (aarch64_get_instr (cpu
), 4, 0);
11411 uint32_t value
= aarch64_get_reg_u32 (cpu
, rn
, NO_SP
);
11412 uint32_t result
= 0;
11415 for (i
= 0; i
< 32; i
++)
11418 result
|= (value
& 1);
11421 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, result
);
11424 /* 64 bit reverse bits. */
11426 rbit64 (sim_cpu
*cpu
)
11428 unsigned rn
= uimm (aarch64_get_instr (cpu
), 9, 5);
11429 unsigned rd
= uimm (aarch64_get_instr (cpu
), 4, 0);
11430 uint64_t value
= aarch64_get_reg_u64 (cpu
, rn
, NO_SP
);
11431 uint64_t result
= 0;
11434 for (i
= 0; i
< 64; i
++)
11437 result
|= (value
& 1L);
11440 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, result
);
11443 /* 32 bit reverse bytes. */
11445 rev32 (sim_cpu
*cpu
)
11447 unsigned rn
= uimm (aarch64_get_instr (cpu
), 9, 5);
11448 unsigned rd
= uimm (aarch64_get_instr (cpu
), 4, 0);
11449 uint32_t value
= aarch64_get_reg_u32 (cpu
, rn
, NO_SP
);
11450 uint32_t result
= 0;
11453 for (i
= 0; i
< 4; i
++)
11456 result
|= (value
& 0xff);
11459 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, result
);
11462 /* 64 bit reverse bytes. */
11464 rev64 (sim_cpu
*cpu
)
11466 unsigned rn
= uimm (aarch64_get_instr (cpu
), 9, 5);
11467 unsigned rd
= uimm (aarch64_get_instr (cpu
), 4, 0);
11468 uint64_t value
= aarch64_get_reg_u64 (cpu
, rn
, NO_SP
);
11469 uint64_t result
= 0;
11472 for (i
= 0; i
< 8; i
++)
11475 result
|= (value
& 0xffULL
);
11478 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, result
);
11481 /* 32 bit reverse shorts. */
11482 /* N.B.this reverses the order of the bytes in each half word. */
11484 revh32 (sim_cpu
*cpu
)
11486 unsigned rn
= uimm (aarch64_get_instr (cpu
), 9, 5);
11487 unsigned rd
= uimm (aarch64_get_instr (cpu
), 4, 0);
11488 uint32_t value
= aarch64_get_reg_u32 (cpu
, rn
, NO_SP
);
11489 uint32_t result
= 0;
11492 for (i
= 0; i
< 2; i
++)
11495 result
|= (value
& 0x00ff00ff);
11498 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, result
);
11501 /* 64 bit reverse shorts. */
11502 /* N.B.this reverses the order of the bytes in each half word. */
11504 revh64 (sim_cpu
*cpu
)
11506 unsigned rn
= uimm (aarch64_get_instr (cpu
), 9, 5);
11507 unsigned rd
= uimm (aarch64_get_instr (cpu
), 4, 0);
11508 uint64_t value
= aarch64_get_reg_u64 (cpu
, rn
, NO_SP
);
11509 uint64_t result
= 0;
11512 for (i
= 0; i
< 2; i
++)
11515 result
|= (value
& 0x00ff00ff00ff00ffULL
);
11518 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, result
);
11522 dexDataProc1Source (sim_cpu
*cpu
)
11524 /* assert instr[30] == 1
11525 aarch64_get_instr (cpu)[28,21] == 111010110
11526 instr[31] = size : 0 ==> 32 bit, 1 ==> 64 bit
11527 instr[29] = S : 0 ==> ok, 1 ==> UNALLOC
11528 instr[20,16] = opcode2 : 00000 ==> ok, ow ==> UNALLOC
11529 instr[15,10] = opcode : 000000 ==> RBIT, 000001 ==> REV16,
11530 000010 ==> REV, 000011 ==> UNALLOC
11531 000100 ==> CLZ, 000101 ==> CLS
11533 instr[9,5] = rn : may not be SP
11534 instr[4,0] = rd : may not be SP. */
11536 uint32_t S
= uimm (aarch64_get_instr (cpu
), 29, 29);
11537 uint32_t opcode2
= uimm (aarch64_get_instr (cpu
), 20, 16);
11538 uint32_t opcode
= uimm (aarch64_get_instr (cpu
), 15, 10);
11539 uint32_t dispatch
= ((uimm (aarch64_get_instr (cpu
), 31, 31) << 3) | opcode
);
11552 case 0: rbit32 (cpu
); return;
11553 case 1: revh32 (cpu
); return;
11554 case 2: rev32 (cpu
); return;
11555 case 4: clz32 (cpu
); return;
11556 case 5: cls32 (cpu
); return;
11557 case 8: rbit64 (cpu
); return;
11558 case 9: revh64 (cpu
); return;
11559 case 10:rev32 (cpu
); return;
11560 case 11:rev64 (cpu
); return;
11561 case 12:clz64 (cpu
); return;
11562 case 13:cls64 (cpu
); return;
11563 default: HALT_UNALLOC
;
11568 Shifts by count supplied in register.
11569 N.B register args may not be SP.
11570 These all use the shifted auxiliary function for
11571 simplicity and clarity. Writing the actual shift
11572 inline would avoid a branch and so be faster but
11573 would also necessitate getting signs right. */
11575 /* 32 bit arithmetic shift right. */
11577 asrv32 (sim_cpu
*cpu
)
11579 unsigned rm
= uimm (aarch64_get_instr (cpu
), 20, 16);
11580 unsigned rn
= uimm (aarch64_get_instr (cpu
), 9, 5);
11581 unsigned rd
= uimm (aarch64_get_instr (cpu
), 4, 0);
11583 aarch64_set_reg_u64
11585 shifted32 (aarch64_get_reg_u32 (cpu
, rn
, NO_SP
), ASR
,
11586 (aarch64_get_reg_u32 (cpu
, rm
, NO_SP
) & 0x1f)));
11589 /* 64 bit arithmetic shift right. */
11591 asrv64 (sim_cpu
*cpu
)
11593 unsigned rm
= uimm (aarch64_get_instr (cpu
), 20, 16);
11594 unsigned rn
= uimm (aarch64_get_instr (cpu
), 9, 5);
11595 unsigned rd
= uimm (aarch64_get_instr (cpu
), 4, 0);
11597 aarch64_set_reg_u64
11599 shifted64 (aarch64_get_reg_u64 (cpu
, rn
, NO_SP
), ASR
,
11600 (aarch64_get_reg_u64 (cpu
, rm
, NO_SP
) & 0x3f)));
11603 /* 32 bit logical shift left. */
11605 lslv32 (sim_cpu
*cpu
)
11607 unsigned rm
= uimm (aarch64_get_instr (cpu
), 20, 16);
11608 unsigned rn
= uimm (aarch64_get_instr (cpu
), 9, 5);
11609 unsigned rd
= uimm (aarch64_get_instr (cpu
), 4, 0);
11611 aarch64_set_reg_u64
11613 shifted32 (aarch64_get_reg_u32 (cpu
, rn
, NO_SP
), LSL
,
11614 (aarch64_get_reg_u32 (cpu
, rm
, NO_SP
) & 0x1f)));
11617 /* 64 bit arithmetic shift left. */
11619 lslv64 (sim_cpu
*cpu
)
11621 unsigned rm
= uimm (aarch64_get_instr (cpu
), 20, 16);
11622 unsigned rn
= uimm (aarch64_get_instr (cpu
), 9, 5);
11623 unsigned rd
= uimm (aarch64_get_instr (cpu
), 4, 0);
11625 aarch64_set_reg_u64
11627 shifted64 (aarch64_get_reg_u64 (cpu
, rn
, NO_SP
), LSL
,
11628 (aarch64_get_reg_u64 (cpu
, rm
, NO_SP
) & 0x3f)));
11631 /* 32 bit logical shift right. */
11633 lsrv32 (sim_cpu
*cpu
)
11635 unsigned rm
= uimm (aarch64_get_instr (cpu
), 20, 16);
11636 unsigned rn
= uimm (aarch64_get_instr (cpu
), 9, 5);
11637 unsigned rd
= uimm (aarch64_get_instr (cpu
), 4, 0);
11639 aarch64_set_reg_u64
11641 shifted32 (aarch64_get_reg_u32 (cpu
, rn
, NO_SP
), LSR
,
11642 (aarch64_get_reg_u32 (cpu
, rm
, NO_SP
) & 0x1f)));
11645 /* 64 bit logical shift right. */
11647 lsrv64 (sim_cpu
*cpu
)
11649 unsigned rm
= uimm (aarch64_get_instr (cpu
), 20, 16);
11650 unsigned rn
= uimm (aarch64_get_instr (cpu
), 9, 5);
11651 unsigned rd
= uimm (aarch64_get_instr (cpu
), 4, 0);
11653 aarch64_set_reg_u64
11655 shifted64 (aarch64_get_reg_u64 (cpu
, rn
, NO_SP
), LSR
,
11656 (aarch64_get_reg_u64 (cpu
, rm
, NO_SP
) & 0x3f)));
11659 /* 32 bit rotate right. */
11661 rorv32 (sim_cpu
*cpu
)
11663 unsigned rm
= uimm (aarch64_get_instr (cpu
), 20, 16);
11664 unsigned rn
= uimm (aarch64_get_instr (cpu
), 9, 5);
11665 unsigned rd
= uimm (aarch64_get_instr (cpu
), 4, 0);
11667 aarch64_set_reg_u64
11669 shifted32 (aarch64_get_reg_u32 (cpu
, rn
, NO_SP
), ROR
,
11670 (aarch64_get_reg_u32 (cpu
, rm
, NO_SP
) & 0x1f)));
11673 /* 64 bit rotate right. */
11675 rorv64 (sim_cpu
*cpu
)
11677 unsigned rm
= uimm (aarch64_get_instr (cpu
), 20, 16);
11678 unsigned rn
= uimm (aarch64_get_instr (cpu
), 9, 5);
11679 unsigned rd
= uimm (aarch64_get_instr (cpu
), 4, 0);
11681 aarch64_set_reg_u64
11683 shifted64 (aarch64_get_reg_u64 (cpu
, rn
, NO_SP
), ROR
,
11684 (aarch64_get_reg_u64 (cpu
, rm
, NO_SP
) & 0x3f)));
11690 /* 32 bit signed divide. */
11692 cpuiv32 (sim_cpu
*cpu
)
11694 unsigned rm
= uimm (aarch64_get_instr (cpu
), 20, 16);
11695 unsigned rn
= uimm (aarch64_get_instr (cpu
), 9, 5);
11696 unsigned rd
= uimm (aarch64_get_instr (cpu
), 4, 0);
11697 /* N.B. the pseudo-code does the divide using 64 bit data. */
11698 /* TODO : check that this rounds towards zero as required. */
11699 int64_t dividend
= aarch64_get_reg_s32 (cpu
, rn
, NO_SP
);
11700 int64_t divisor
= aarch64_get_reg_s32 (cpu
, rm
, NO_SP
);
11702 aarch64_set_reg_s64 (cpu
, rd
, NO_SP
,
11703 divisor
? ((int32_t) (dividend
/ divisor
)) : 0);
11706 /* 64 bit signed divide. */
11708 cpuiv64 (sim_cpu
*cpu
)
11710 unsigned rm
= uimm (aarch64_get_instr (cpu
), 20, 16);
11711 unsigned rn
= uimm (aarch64_get_instr (cpu
), 9, 5);
11712 unsigned rd
= uimm (aarch64_get_instr (cpu
), 4, 0);
11714 /* TODO : check that this rounds towards zero as required. */
11715 int64_t divisor
= aarch64_get_reg_s64 (cpu
, rm
, NO_SP
);
11717 aarch64_set_reg_s64
11719 divisor
? (aarch64_get_reg_s64 (cpu
, rn
, NO_SP
) / divisor
) : 0);
11722 /* 32 bit unsigned divide. */
11724 udiv32 (sim_cpu
*cpu
)
11726 unsigned rm
= uimm (aarch64_get_instr (cpu
), 20, 16);
11727 unsigned rn
= uimm (aarch64_get_instr (cpu
), 9, 5);
11728 unsigned rd
= uimm (aarch64_get_instr (cpu
), 4, 0);
11730 /* N.B. the pseudo-code does the divide using 64 bit data. */
11731 uint64_t dividend
= aarch64_get_reg_u32 (cpu
, rn
, NO_SP
);
11732 uint64_t divisor
= aarch64_get_reg_u32 (cpu
, rm
, NO_SP
);
11734 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
,
11735 divisor
? (uint32_t) (dividend
/ divisor
) : 0);
11738 /* 64 bit unsigned divide. */
11740 udiv64 (sim_cpu
*cpu
)
11742 unsigned rm
= uimm (aarch64_get_instr (cpu
), 20, 16);
11743 unsigned rn
= uimm (aarch64_get_instr (cpu
), 9, 5);
11744 unsigned rd
= uimm (aarch64_get_instr (cpu
), 4, 0);
11746 /* TODO : check that this rounds towards zero as required. */
11747 uint64_t divisor
= aarch64_get_reg_u64 (cpu
, rm
, NO_SP
);
11749 aarch64_set_reg_u64
11751 divisor
? (aarch64_get_reg_u64 (cpu
, rn
, NO_SP
) / divisor
) : 0);
11755 dexDataProc2Source (sim_cpu
*cpu
)
11757 /* assert instr[30] == 0
11758 instr[28,21] == 11010110
11759 instr[31] = size : 0 ==> 32 bit, 1 ==> 64 bit
11760 instr[29] = S : 0 ==> ok, 1 ==> UNALLOC
11761 instr[15,10] = opcode : 000010 ==> UDIV, 000011 ==> CPUIV,
11762 001000 ==> LSLV, 001001 ==> LSRV
11763 001010 ==> ASRV, 001011 ==> RORV
11767 uint32_t S
= uimm (aarch64_get_instr (cpu
), 29, 29);
11768 uint32_t opcode
= uimm (aarch64_get_instr (cpu
), 15, 10);
11776 dispatch
= ( (uimm (aarch64_get_instr (cpu
), 31, 31) << 3)
11777 | (uimm (opcode
, 3, 3) << 2)
11778 | uimm (opcode
, 1, 0));
11781 case 2: udiv32 (cpu
); return;
11782 case 3: cpuiv32 (cpu
); return;
11783 case 4: lslv32 (cpu
); return;
11784 case 5: lsrv32 (cpu
); return;
11785 case 6: asrv32 (cpu
); return;
11786 case 7: rorv32 (cpu
); return;
11787 case 10: udiv64 (cpu
); return;
11788 case 11: cpuiv64 (cpu
); return;
11789 case 12: lslv64 (cpu
); return;
11790 case 13: lsrv64 (cpu
); return;
11791 case 14: asrv64 (cpu
); return;
11792 case 15: rorv64 (cpu
); return;
11793 default: HALT_UNALLOC
;
11800 /* 32 bit multiply and add. */
11802 madd32 (sim_cpu
*cpu
)
11804 unsigned rm
= uimm (aarch64_get_instr (cpu
), 20, 16);
11805 unsigned ra
= uimm (aarch64_get_instr (cpu
), 14, 10);
11806 unsigned rn
= uimm (aarch64_get_instr (cpu
), 9, 5);
11807 unsigned rd
= uimm (aarch64_get_instr (cpu
), 4, 0);
11809 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
,
11810 aarch64_get_reg_u32 (cpu
, ra
, NO_SP
)
11811 + aarch64_get_reg_u32 (cpu
, rn
, NO_SP
)
11812 * aarch64_get_reg_u32 (cpu
, rm
, NO_SP
));
11815 /* 64 bit multiply and add. */
11817 madd64 (sim_cpu
*cpu
)
11819 unsigned rm
= uimm (aarch64_get_instr (cpu
), 20, 16);
11820 unsigned ra
= uimm (aarch64_get_instr (cpu
), 14, 10);
11821 unsigned rn
= uimm (aarch64_get_instr (cpu
), 9, 5);
11822 unsigned rd
= uimm (aarch64_get_instr (cpu
), 4, 0);
11824 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
,
11825 aarch64_get_reg_u64 (cpu
, ra
, NO_SP
)
11826 + aarch64_get_reg_u64 (cpu
, rn
, NO_SP
)
11827 * aarch64_get_reg_u64 (cpu
, rm
, NO_SP
));
11830 /* 32 bit multiply and sub. */
11832 msub32 (sim_cpu
*cpu
)
11834 unsigned rm
= uimm (aarch64_get_instr (cpu
), 20, 16);
11835 unsigned ra
= uimm (aarch64_get_instr (cpu
), 14, 10);
11836 unsigned rn
= uimm (aarch64_get_instr (cpu
), 9, 5);
11837 unsigned rd
= uimm (aarch64_get_instr (cpu
), 4, 0);
11839 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
,
11840 aarch64_get_reg_u32 (cpu
, ra
, NO_SP
)
11841 - aarch64_get_reg_u32 (cpu
, rn
, NO_SP
)
11842 * aarch64_get_reg_u32 (cpu
, rm
, NO_SP
));
11845 /* 64 bit multiply and sub. */
11847 msub64 (sim_cpu
*cpu
)
11849 unsigned rm
= uimm (aarch64_get_instr (cpu
), 20, 16);
11850 unsigned ra
= uimm (aarch64_get_instr (cpu
), 14, 10);
11851 unsigned rn
= uimm (aarch64_get_instr (cpu
), 9, 5);
11852 unsigned rd
= uimm (aarch64_get_instr (cpu
), 4, 0);
11854 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
,
11855 aarch64_get_reg_u64 (cpu
, ra
, NO_SP
)
11856 - aarch64_get_reg_u64 (cpu
, rn
, NO_SP
)
11857 * aarch64_get_reg_u64 (cpu
, rm
, NO_SP
));
11860 /* Signed multiply add long -- source, source2 : 32 bit, source3 : 64 bit. */
11862 smaddl (sim_cpu
*cpu
)
11864 unsigned rm
= uimm (aarch64_get_instr (cpu
), 20, 16);
11865 unsigned ra
= uimm (aarch64_get_instr (cpu
), 14, 10);
11866 unsigned rn
= uimm (aarch64_get_instr (cpu
), 9, 5);
11867 unsigned rd
= uimm (aarch64_get_instr (cpu
), 4, 0);
11869 /* N.B. we need to multiply the signed 32 bit values in rn, rm to
11870 obtain a 64 bit product. */
11871 aarch64_set_reg_s64
11873 aarch64_get_reg_s64 (cpu
, ra
, NO_SP
)
11874 + ((int64_t) aarch64_get_reg_s32 (cpu
, rn
, NO_SP
))
11875 * ((int64_t) aarch64_get_reg_s32 (cpu
, rm
, NO_SP
)));
11878 /* Signed multiply sub long -- source, source2 : 32 bit, source3 : 64 bit. */
11880 smsubl (sim_cpu
*cpu
)
11882 unsigned rm
= uimm (aarch64_get_instr (cpu
), 20, 16);
11883 unsigned ra
= uimm (aarch64_get_instr (cpu
), 14, 10);
11884 unsigned rn
= uimm (aarch64_get_instr (cpu
), 9, 5);
11885 unsigned rd
= uimm (aarch64_get_instr (cpu
), 4, 0);
11887 /* N.B. we need to multiply the signed 32 bit values in rn, rm to
11888 obtain a 64 bit product. */
11889 aarch64_set_reg_s64
11891 aarch64_get_reg_s64 (cpu
, ra
, NO_SP
)
11892 - ((int64_t) aarch64_get_reg_s32 (cpu
, rn
, NO_SP
))
11893 * ((int64_t) aarch64_get_reg_s32 (cpu
, rm
, NO_SP
)));
11896 /* Integer Multiply/Divide. */
11898 /* First some macros and a helper function. */
11899 /* Macros to test or access elements of 64 bit words. */
11901 /* Mask used to access lo 32 bits of 64 bit unsigned int. */
11902 #define LOW_WORD_MASK ((1ULL << 32) - 1)
11903 /* Return the lo 32 bit word of a 64 bit unsigned int as a 64 bit unsigned int. */
11904 #define lowWordToU64(_value_u64) ((_value_u64) & LOW_WORD_MASK)
11905 /* Return the hi 32 bit word of a 64 bit unsigned int as a 64 bit unsigned int. */
11906 #define highWordToU64(_value_u64) ((_value_u64) >> 32)
11908 /* Offset of sign bit in 64 bit signed integger. */
11909 #define SIGN_SHIFT_U64 63
11910 /* The sign bit itself -- also identifies the minimum negative int value. */
11911 #define SIGN_BIT_U64 (1UL << SIGN_SHIFT_U64)
11912 /* Return true if a 64 bit signed int presented as an unsigned int is the
11913 most negative value. */
11914 #define isMinimumU64(_value_u64) ((_value_u64) == SIGN_BIT_U64)
11915 /* Return true (non-zero) if a 64 bit signed int presented as an unsigned
11916 int has its sign bit set to false. */
11917 #define isSignSetU64(_value_u64) ((_value_u64) & SIGN_BIT_U64)
11918 /* Return 1L or -1L according to whether a 64 bit signed int presented as
11919 an unsigned int has its sign bit set or not. */
11920 #define signOfU64(_value_u64) (1L + (((value_u64) >> SIGN_SHIFT_U64) * -2L)
11921 /* Clear the sign bit of a 64 bit signed int presented as an unsigned int. */
11922 #define clearSignU64(_value_u64) ((_value_u64) &= ~SIGN_BIT_U64)
11924 /* Multiply two 64 bit ints and return.
11925 the hi 64 bits of the 128 bit product. */
11928 mul64hi (uint64_t value1
, uint64_t value2
)
11930 uint64_t resultmid1
;
11932 uint64_t value1_lo
= lowWordToU64 (value1
);
11933 uint64_t value1_hi
= highWordToU64 (value1
) ;
11934 uint64_t value2_lo
= lowWordToU64 (value2
);
11935 uint64_t value2_hi
= highWordToU64 (value2
);
11937 /* Cross-multiply and collect results. */
11939 uint64_t xproductlo
= value1_lo
* value2_lo
;
11940 uint64_t xproductmid1
= value1_lo
* value2_hi
;
11941 uint64_t xproductmid2
= value1_hi
* value2_lo
;
11942 uint64_t xproducthi
= value1_hi
* value2_hi
;
11943 uint64_t carry
= 0;
11944 /* Start accumulating 64 bit results. */
11945 /* Drop bottom half of lowest cross-product. */
11946 uint64_t resultmid
= xproductlo
>> 32;
11947 /* Add in middle products. */
11948 resultmid
= resultmid
+ xproductmid1
;
11950 /* Check for overflow. */
11951 if (resultmid
< xproductmid1
)
11952 /* Carry over 1 into top cross-product. */
11955 resultmid1
= resultmid
+ xproductmid2
;
11957 /* Check for overflow. */
11958 if (resultmid1
< xproductmid2
)
11959 /* Carry over 1 into top cross-product. */
11962 /* Drop lowest 32 bits of middle cross-product. */
11963 result
= resultmid1
>> 32;
11965 /* Add top cross-product plus and any carry. */
11966 result
+= xproducthi
+ carry
;
11971 /* Signed multiply high, source, source2 :
11972 64 bit, dest <-- high 64-bit of result. */
11974 smulh (sim_cpu
*cpu
)
11978 unsigned rm
= uimm (aarch64_get_instr (cpu
), 20, 16);
11979 unsigned rn
= uimm (aarch64_get_instr (cpu
), 9, 5);
11980 unsigned rd
= uimm (aarch64_get_instr (cpu
), 4, 0);
11981 GReg ra
= greg (aarch64_get_instr (cpu
), 10);
11982 int64_t value1
= aarch64_get_reg_u64 (cpu
, rn
, NO_SP
);
11983 int64_t value2
= aarch64_get_reg_u64 (cpu
, rm
, NO_SP
);
11986 int64_t signum
= 1;
11991 /* Convert to unsigned and use the unsigned mul64hi routine
11992 the fix the sign up afterwards. */
12013 uresult
= mul64hi (uvalue1
, uvalue2
);
12017 aarch64_set_reg_s64 (cpu
, rd
, NO_SP
, result
);
12020 /* Unsigned multiply add long -- source, source2 :
12021 32 bit, source3 : 64 bit. */
12023 umaddl (sim_cpu
*cpu
)
12025 unsigned rm
= uimm (aarch64_get_instr (cpu
), 20, 16);
12026 unsigned ra
= uimm (aarch64_get_instr (cpu
), 14, 10);
12027 unsigned rn
= uimm (aarch64_get_instr (cpu
), 9, 5);
12028 unsigned rd
= uimm (aarch64_get_instr (cpu
), 4, 0);
12030 /* N.B. we need to multiply the signed 32 bit values in rn, rm to
12031 obtain a 64 bit product. */
12032 aarch64_set_reg_u64
12034 aarch64_get_reg_u64 (cpu
, ra
, NO_SP
)
12035 + ((uint64_t) aarch64_get_reg_u32 (cpu
, rn
, NO_SP
))
12036 * ((uint64_t) aarch64_get_reg_u32 (cpu
, rm
, NO_SP
)));
12039 /* Unsigned multiply sub long -- source, source2 : 32 bit, source3 : 64 bit. */
12041 umsubl (sim_cpu
*cpu
)
12043 unsigned rm
= uimm (aarch64_get_instr (cpu
), 20, 16);
12044 unsigned ra
= uimm (aarch64_get_instr (cpu
), 14, 10);
12045 unsigned rn
= uimm (aarch64_get_instr (cpu
), 9, 5);
12046 unsigned rd
= uimm (aarch64_get_instr (cpu
), 4, 0);
12048 /* N.B. we need to multiply the signed 32 bit values in rn, rm to
12049 obtain a 64 bit product. */
12050 aarch64_set_reg_u64
12052 aarch64_get_reg_u64 (cpu
, ra
, NO_SP
)
12053 - ((uint64_t) aarch64_get_reg_u32 (cpu
, rn
, NO_SP
))
12054 * ((uint64_t) aarch64_get_reg_u32 (cpu
, rm
, NO_SP
)));
12057 /* Unsigned multiply high, source, source2 :
12058 64 bit, dest <-- high 64-bit of result. */
12060 umulh (sim_cpu
*cpu
)
12062 unsigned rm
= uimm (aarch64_get_instr (cpu
), 20, 16);
12063 unsigned rn
= uimm (aarch64_get_instr (cpu
), 9, 5);
12064 unsigned rd
= uimm (aarch64_get_instr (cpu
), 4, 0);
12065 GReg ra
= greg (aarch64_get_instr (cpu
), 10);
12070 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
,
12071 mul64hi (aarch64_get_reg_u64 (cpu
, rn
, NO_SP
),
12072 aarch64_get_reg_u64 (cpu
, rm
, NO_SP
)));
12076 dexDataProc3Source (sim_cpu
*cpu
)
12078 /* assert instr[28,24] == 11011. */
12079 /* instr[31] = size : 0 ==> 32 bit, 1 ==> 64 bit (for rd at least)
12080 instr[30,29] = op54 : 00 ==> ok, ow ==> UNALLOC
12081 instr[23,21] = op31 : 111 ==> UNALLOC, o2 ==> ok
12082 instr[15] = o0 : 0/1 ==> ok
12083 instr[23,21:15] ==> op : 0000 ==> MADD, 0001 ==> MSUB, (32/64 bit)
12084 0010 ==> SMADDL, 0011 ==> SMSUBL, (64 bit only)
12085 0100 ==> SMULH, (64 bit only)
12086 1010 ==> UMADDL, 1011 ==> UNSUBL, (64 bit only)
12087 1100 ==> UMULH (64 bit only)
12091 uint32_t size
= uimm (aarch64_get_instr (cpu
), 31, 31);
12092 uint32_t op54
= uimm (aarch64_get_instr (cpu
), 30, 29);
12093 uint32_t op31
= uimm (aarch64_get_instr (cpu
), 23, 21);
12094 uint32_t o0
= uimm (aarch64_get_instr (cpu
), 15, 15);
12111 dispatch
= (op31
<< 1) | o0
;
12115 case 0: madd64 (cpu
); return;
12116 case 1: msub64 (cpu
); return;
12117 case 2: smaddl (cpu
); return;
12118 case 3: smsubl (cpu
); return;
12119 case 4: smulh (cpu
); return;
12120 case 10: umaddl (cpu
); return;
12121 case 11: umsubl (cpu
); return;
12122 case 12: umulh (cpu
); return;
12123 default: HALT_UNALLOC
;
12128 dexDPReg (sim_cpu
*cpu
)
12130 /* uint32_t group = dispatchGroup (aarch64_get_instr (cpu));
12131 assert group == GROUP_DPREG_0101 || group == GROUP_DPREG_1101
12132 bits [28:24:21] of a DPReg are the secondary dispatch vector. */
12133 uint32_t group2
= dispatchDPReg (aarch64_get_instr (cpu
));
12137 case DPREG_LOG_000
:
12138 case DPREG_LOG_001
:
12139 dexLogicalShiftedRegister (cpu
); return;
12141 case DPREG_ADDSHF_010
:
12142 dexAddSubtractShiftedRegister (cpu
); return;
12144 case DPREG_ADDEXT_011
:
12145 dexAddSubtractExtendedRegister (cpu
); return;
12147 case DPREG_ADDCOND_100
:
12149 /* This set bundles a variety of different operations. */
12151 /* 1) add/sub w carry. */
12152 uint32_t mask1
= 0x1FE00000U
;
12153 uint32_t val1
= 0x1A000000U
;
12154 /* 2) cond compare register/immediate. */
12155 uint32_t mask2
= 0x1FE00000U
;
12156 uint32_t val2
= 0x1A400000U
;
12157 /* 3) cond select. */
12158 uint32_t mask3
= 0x1FE00000U
;
12159 uint32_t val3
= 0x1A800000U
;
12160 /* 4) data proc 1/2 source. */
12161 uint32_t mask4
= 0x1FE00000U
;
12162 uint32_t val4
= 0x1AC00000U
;
12164 if ((aarch64_get_instr (cpu
) & mask1
) == val1
)
12165 dexAddSubtractWithCarry (cpu
);
12167 else if ((aarch64_get_instr (cpu
) & mask2
) == val2
)
12170 else if ((aarch64_get_instr (cpu
) & mask3
) == val3
)
12171 dexCondSelect (cpu
);
12173 else if ((aarch64_get_instr (cpu
) & mask4
) == val4
)
12175 /* Bit 30 is clear for data proc 2 source
12176 and set for data proc 1 source. */
12177 if (aarch64_get_instr (cpu
) & (1U << 30))
12178 dexDataProc1Source (cpu
);
12180 dexDataProc2Source (cpu
);
12184 /* Should not reach here. */
12190 case DPREG_3SRC_110
:
12191 dexDataProc3Source (cpu
); return;
12193 case DPREG_UNALLOC_101
:
12196 case DPREG_3SRC_111
:
12197 dexDataProc3Source (cpu
); return;
12200 /* Should never reach here. */
12205 /* Unconditional Branch immediate.
12206 Offset is a PC-relative byte offset in the range +/- 128MiB.
12207 The offset is assumed to be raw from the decode i.e. the
12208 simulator is expected to scale them from word offsets to byte. */
12210 /* Unconditional branch. */
12212 buc (sim_cpu
*cpu
, int32_t offset
)
12214 aarch64_set_next_PC_by_offset (cpu
, offset
);
12217 static unsigned stack_depth
= 0;
12219 /* Unconditional branch and link -- writes return PC to LR. */
12221 bl (sim_cpu
*cpu
, int32_t offset
)
12223 aarch64_save_LR (cpu
);
12224 aarch64_set_next_PC_by_offset (cpu
, offset
);
12226 if (TRACE_BRANCH_P (cpu
))
12230 " %*scall %" PRIx64
" [%s]"
12231 " [args: %" PRIx64
" %" PRIx64
" %" PRIx64
"]",
12232 stack_depth
, " ", aarch64_get_next_PC (cpu
),
12233 aarch64_get_func (aarch64_get_next_PC (cpu
)),
12234 aarch64_get_reg_u64 (cpu
, 0, NO_SP
),
12235 aarch64_get_reg_u64 (cpu
, 1, NO_SP
),
12236 aarch64_get_reg_u64 (cpu
, 2, NO_SP
)
12241 /* Unconditional Branch register.
12242 Branch/return address is in source register. */
12244 /* Unconditional branch. */
12248 unsigned rn
= uimm (aarch64_get_instr (cpu
), 9, 5);
12249 aarch64_set_next_PC (cpu
, aarch64_get_reg_u64 (cpu
, rn
, NO_SP
));
12252 /* Unconditional branch and link -- writes return PC to LR. */
12256 unsigned rn
= uimm (aarch64_get_instr (cpu
), 9, 5);
12258 /* The pseudo code in the spec says we update LR before fetching.
12259 the value from the rn. */
12260 aarch64_save_LR (cpu
);
12261 aarch64_set_next_PC (cpu
, aarch64_get_reg_u64 (cpu
, rn
, NO_SP
));
12263 if (TRACE_BRANCH_P (cpu
))
12267 " %*scall %" PRIx64
" [%s]"
12268 " [args: %" PRIx64
" %" PRIx64
" %" PRIx64
"]",
12269 stack_depth
, " ", aarch64_get_next_PC (cpu
),
12270 aarch64_get_func (aarch64_get_next_PC (cpu
)),
12271 aarch64_get_reg_u64 (cpu
, 0, NO_SP
),
12272 aarch64_get_reg_u64 (cpu
, 1, NO_SP
),
12273 aarch64_get_reg_u64 (cpu
, 2, NO_SP
)
12278 /* Return -- assembler will default source to LR this is functionally
12279 equivalent to br but, presumably, unlike br it side effects the
12280 branch predictor. */
12284 unsigned rn
= uimm (aarch64_get_instr (cpu
), 9, 5);
12285 aarch64_set_next_PC (cpu
, aarch64_get_reg_u64 (cpu
, rn
, NO_SP
));
12287 if (TRACE_BRANCH_P (cpu
))
12290 " %*sreturn [result: %" PRIx64
"]",
12291 stack_depth
, " ", aarch64_get_reg_u64 (cpu
, 0, NO_SP
));
12296 /* NOP -- we implement this and call it from the decode in case we
12297 want to intercept it later. */
12304 /* Data synchronization barrier. */
12311 /* Data memory barrier. */
12318 /* Instruction synchronization barrier. */
12326 dexBranchImmediate (sim_cpu
*cpu
)
12328 /* assert instr[30,26] == 00101
12329 instr[31] ==> 0 == B, 1 == BL
12330 instr[25,0] == imm26 branch offset counted in words. */
12332 uint32_t top
= uimm (aarch64_get_instr (cpu
), 31, 31);
12333 /* We have a 26 byte signed word offset which we need to pass to the
12334 execute routine as a signed byte offset. */
12335 int32_t offset
= simm32 (aarch64_get_instr (cpu
), 25, 0) << 2;
12343 /* Control Flow. */
12345 /* Conditional branch
12347 Offset is a PC-relative byte offset in the range +/- 1MiB pos is
12348 a bit position in the range 0 .. 63
12350 cc is a CondCode enum value as pulled out of the decode
12352 N.B. any offset register (source) can only be Xn or Wn. */
12355 bcc (sim_cpu
*cpu
, int32_t offset
, CondCode cc
)
12357 /* the test returns TRUE if CC is met. */
12358 if (testConditionCode (cpu
, cc
))
12359 aarch64_set_next_PC_by_offset (cpu
, offset
);
12362 /* 32 bit branch on register non-zero. */
12364 cbnz32 (sim_cpu
*cpu
, int32_t offset
)
12366 unsigned rt
= uimm (aarch64_get_instr (cpu
), 4, 0);
12368 if (aarch64_get_reg_u32 (cpu
, rt
, NO_SP
) != 0)
12369 aarch64_set_next_PC_by_offset (cpu
, offset
);
12372 /* 64 bit branch on register zero. */
12374 cbnz (sim_cpu
*cpu
, int32_t offset
)
12376 unsigned rt
= uimm (aarch64_get_instr (cpu
), 4, 0);
12378 if (aarch64_get_reg_u64 (cpu
, rt
, NO_SP
) != 0)
12379 aarch64_set_next_PC_by_offset (cpu
, offset
);
12382 /* 32 bit branch on register non-zero. */
12384 cbz32 (sim_cpu
*cpu
, int32_t offset
)
12386 unsigned rt
= uimm (aarch64_get_instr (cpu
), 4, 0);
12388 if (aarch64_get_reg_u32 (cpu
, rt
, NO_SP
) == 0)
12389 aarch64_set_next_PC_by_offset (cpu
, offset
);
12392 /* 64 bit branch on register zero. */
12394 cbz (sim_cpu
*cpu
, int32_t offset
)
12396 unsigned rt
= uimm (aarch64_get_instr (cpu
), 4, 0);
12398 if (aarch64_get_reg_u64 (cpu
, rt
, NO_SP
) == 0)
12399 aarch64_set_next_PC_by_offset (cpu
, offset
);
12402 /* Branch on register bit test non-zero -- one size fits all. */
12404 tbnz (sim_cpu
*cpu
, uint32_t pos
, int32_t offset
)
12406 unsigned rt
= uimm (aarch64_get_instr (cpu
), 4, 0);
12408 if (aarch64_get_reg_u64 (cpu
, rt
, NO_SP
) & (1 << pos
))
12409 aarch64_set_next_PC_by_offset (cpu
, offset
);
12412 /* branch on register bit test zero -- one size fits all. */
12414 tbz (sim_cpu
*cpu
, uint32_t pos
, int32_t offset
)
12416 unsigned rt
= uimm (aarch64_get_instr (cpu
), 4, 0);
12418 if (!(aarch64_get_reg_u64 (cpu
, rt
, NO_SP
) & (1 << pos
)))
12419 aarch64_set_next_PC_by_offset (cpu
, offset
);
12423 dexCompareBranchImmediate (sim_cpu
*cpu
)
12425 /* instr[30,25] = 01 1010
12426 instr[31] = size : 0 ==> 32, 1 ==> 64
12427 instr[24] = op : 0 ==> CBZ, 1 ==> CBNZ
12428 instr[23,5] = simm19 branch offset counted in words
12431 uint32_t size
= uimm (aarch64_get_instr (cpu
), 31, 31);
12432 uint32_t op
= uimm (aarch64_get_instr (cpu
), 24, 24);
12433 int32_t offset
= simm32 (aarch64_get_instr (cpu
), 23, 5) << 2;
12438 cbz32 (cpu
, offset
);
12440 cbnz32 (cpu
, offset
);
12447 cbnz (cpu
, offset
);
12452 dexTestBranchImmediate (sim_cpu
*cpu
)
12454 /* instr[31] = b5 : bit 5 of test bit idx
12455 instr[30,25] = 01 1011
12456 instr[24] = op : 0 ==> TBZ, 1 == TBNZ
12457 instr[23,19] = b40 : bits 4 to 0 of test bit idx
12458 instr[18,5] = simm14 : signed offset counted in words
12459 instr[4,0] = uimm5 */
12461 uint32_t pos
= ((uimm (aarch64_get_instr (cpu
), 31, 31) << 4)
12462 | uimm (aarch64_get_instr (cpu
), 23,19));
12463 int32_t offset
= simm32 (aarch64_get_instr (cpu
), 18, 5) << 2;
12465 NYI_assert (30, 25, 0x1b);
12467 if (uimm (aarch64_get_instr (cpu
), 24, 24) == 0)
12468 tbz (cpu
, pos
, offset
);
12470 tbnz (cpu
, pos
, offset
);
12474 dexCondBranchImmediate (sim_cpu
*cpu
)
12476 /* instr[31,25] = 010 1010
12477 instr[24] = op1; op => 00 ==> B.cond
12478 instr[23,5] = simm19 : signed offset counted in words
12480 instr[3,0] = cond */
12484 uint32_t op
= ((uimm (aarch64_get_instr (cpu
), 24, 24) << 1)
12485 | uimm (aarch64_get_instr (cpu
), 4, 4));
12487 NYI_assert (31, 25, 0x2a);
12492 offset
= simm32 (aarch64_get_instr (cpu
), 23, 5) << 2;
12493 cc
= condcode (aarch64_get_instr (cpu
), 0);
12495 bcc (cpu
, offset
, cc
);
12499 dexBranchRegister (sim_cpu
*cpu
)
12501 /* instr[31,25] = 110 1011
12502 instr[24,21] = op : 0 ==> BR, 1 => BLR, 2 => RET, 3 => ERET, 4 => DRPS
12503 instr[20,16] = op2 : must be 11111
12504 instr[15,10] = op3 : must be 000000
12505 instr[4,0] = op2 : must be 11111. */
12507 uint32_t op
= uimm (aarch64_get_instr (cpu
), 24, 21);
12508 uint32_t op2
= uimm (aarch64_get_instr (cpu
), 20, 16);
12509 uint32_t op3
= uimm (aarch64_get_instr (cpu
), 15, 10);
12510 uint32_t op4
= uimm (aarch64_get_instr (cpu
), 4, 0);
12512 NYI_assert (31, 25, 0x6b);
12514 if (op2
!= 0x1F || op3
!= 0 || op4
!= 0)
12528 /* ERET and DRPS accept 0b11111 for rn = aarch64_get_instr (cpu)[4,0]. */
12529 /* anything else is unallocated. */
12530 uint32_t rn
= greg (aarch64_get_instr (cpu
), 0);
12535 if (op
== 4 || op
== 5)
12542 /* FIXME: We should get the Angel SWI values from ../../libgloss/aarch64/svc.h
12543 but this may not be available. So instead we define the values we need
12545 #define AngelSVC_Reason_Open 0x01
12546 #define AngelSVC_Reason_Close 0x02
12547 #define AngelSVC_Reason_Write 0x05
12548 #define AngelSVC_Reason_Read 0x06
12549 #define AngelSVC_Reason_IsTTY 0x09
12550 #define AngelSVC_Reason_Seek 0x0A
12551 #define AngelSVC_Reason_FLen 0x0C
12552 #define AngelSVC_Reason_Remove 0x0E
12553 #define AngelSVC_Reason_Rename 0x0F
12554 #define AngelSVC_Reason_Clock 0x10
12555 #define AngelSVC_Reason_Time 0x11
12556 #define AngelSVC_Reason_System 0x12
12557 #define AngelSVC_Reason_Errno 0x13
12558 #define AngelSVC_Reason_GetCmdLine 0x15
12559 #define AngelSVC_Reason_HeapInfo 0x16
12560 #define AngelSVC_Reason_ReportException 0x18
12561 #define AngelSVC_Reason_Elapsed 0x30
12565 handle_halt (sim_cpu
*cpu
, uint32_t val
)
12567 uint64_t result
= 0;
12571 TRACE_SYSCALL (cpu
, " HLT [0x%x]", val
);
12572 sim_engine_halt (CPU_STATE (cpu
), cpu
, NULL
, aarch64_get_PC (cpu
),
12573 sim_stopped
, SIM_SIGTRAP
);
12576 /* We have encountered an Angel SVC call. See if we can process it. */
12577 switch (aarch64_get_reg_u32 (cpu
, 0, NO_SP
))
12579 case AngelSVC_Reason_HeapInfo
:
12581 /* Get the values. */
12582 uint64_t stack_top
= aarch64_get_stack_start (cpu
);
12583 uint64_t heap_base
= aarch64_get_heap_start (cpu
);
12585 /* Get the pointer */
12586 uint64_t ptr
= aarch64_get_reg_u64 (cpu
, 1, SP_OK
);
12587 ptr
= aarch64_get_mem_u64 (cpu
, ptr
);
12589 /* Fill in the memory block. */
12590 /* Start addr of heap. */
12591 aarch64_set_mem_u64 (cpu
, ptr
+ 0, heap_base
);
12592 /* End addr of heap. */
12593 aarch64_set_mem_u64 (cpu
, ptr
+ 8, stack_top
);
12594 /* Lowest stack addr. */
12595 aarch64_set_mem_u64 (cpu
, ptr
+ 16, heap_base
);
12596 /* Initial stack addr. */
12597 aarch64_set_mem_u64 (cpu
, ptr
+ 24, stack_top
);
12599 TRACE_SYSCALL (cpu
, " AngelSVC: Get Heap Info");
12603 case AngelSVC_Reason_Open
:
12605 /* Get the pointer */
12606 /* uint64_t ptr = aarch64_get_reg_u64 (cpu, 1, SP_OK);. */
12607 /* FIXME: For now we just assume that we will only be asked
12608 to open the standard file descriptors. */
12612 TRACE_SYSCALL (cpu
, " AngelSVC: Open file %d", fd
- 1);
12616 case AngelSVC_Reason_Close
:
12618 uint64_t fh
= aarch64_get_reg_u64 (cpu
, 1, SP_OK
);
12619 TRACE_SYSCALL (cpu
, " AngelSVC: Close file %d", (int) fh
);
12624 case AngelSVC_Reason_Errno
:
12626 TRACE_SYSCALL (cpu
, " AngelSVC: Get Errno");
12629 case AngelSVC_Reason_Clock
:
12631 #ifdef CLOCKS_PER_SEC
12632 (CLOCKS_PER_SEC
>= 100)
12633 ? (clock () / (CLOCKS_PER_SEC
/ 100))
12634 : ((clock () * 100) / CLOCKS_PER_SEC
)
12636 /* Presume unix... clock() returns microseconds. */
12640 TRACE_SYSCALL (cpu
, " AngelSVC: Get Clock");
12643 case AngelSVC_Reason_GetCmdLine
:
12645 /* Get the pointer */
12646 uint64_t ptr
= aarch64_get_reg_u64 (cpu
, 1, SP_OK
);
12647 ptr
= aarch64_get_mem_u64 (cpu
, ptr
);
12649 /* FIXME: No command line for now. */
12650 aarch64_set_mem_u64 (cpu
, ptr
, 0);
12651 TRACE_SYSCALL (cpu
, " AngelSVC: Get Command Line");
12655 case AngelSVC_Reason_IsTTY
:
12657 TRACE_SYSCALL (cpu
, " AngelSVC: IsTTY ?");
12660 case AngelSVC_Reason_Write
:
12662 /* Get the pointer */
12663 uint64_t ptr
= aarch64_get_reg_u64 (cpu
, 1, SP_OK
);
12664 /* Get the write control block. */
12665 uint64_t fd
= aarch64_get_mem_u64 (cpu
, ptr
);
12666 uint64_t buf
= aarch64_get_mem_u64 (cpu
, ptr
+ 8);
12667 uint64_t len
= aarch64_get_mem_u64 (cpu
, ptr
+ 16);
12669 TRACE_SYSCALL (cpu
, "write of %" PRIx64
" bytes from %"
12670 PRIx64
" on descriptor %" PRIx64
,
12675 TRACE_SYSCALL (cpu
,
12676 " AngelSVC: Write: Suspiciously long write: %ld",
12678 sim_engine_halt (CPU_STATE (cpu
), cpu
, NULL
, aarch64_get_PC (cpu
),
12679 sim_stopped
, SIM_SIGBUS
);
12683 printf ("%.*s", (int) len
, aarch64_get_mem_ptr (cpu
, buf
));
12685 /* So that the output stays in sync with trace output. */
12690 TRACE (cpu
, 0, "\n");
12691 sim_io_eprintf (CPU_STATE (cpu
), "%.*s",
12692 (int) len
, aarch64_get_mem_ptr (cpu
, buf
));
12693 TRACE (cpu
, 0, "\n");
12697 TRACE_SYSCALL (cpu
,
12698 " AngelSVC: Write: Unexpected file handle: %d",
12700 sim_engine_halt (CPU_STATE (cpu
), cpu
, NULL
, aarch64_get_PC (cpu
),
12701 sim_stopped
, SIM_SIGABRT
);
12706 case AngelSVC_Reason_ReportException
:
12708 /* Get the pointer */
12709 uint64_t ptr
= aarch64_get_reg_u64 (cpu
, 1, SP_OK
);
12710 /*ptr = aarch64_get_mem_u64 (cpu, ptr);. */
12711 uint64_t type
= aarch64_get_mem_u64 (cpu
, ptr
);
12712 uint64_t state
= aarch64_get_mem_u64 (cpu
, ptr
+ 8);
12714 TRACE_SYSCALL (cpu
,
12715 "Angel Exception: type 0x%" PRIx64
" state %" PRIx64
,
12718 if (type
== 0x20026)
12719 sim_engine_halt (CPU_STATE (cpu
), cpu
, NULL
, aarch64_get_PC (cpu
),
12720 sim_exited
, state
);
12722 sim_engine_halt (CPU_STATE (cpu
), cpu
, NULL
, aarch64_get_PC (cpu
),
12723 sim_stopped
, SIM_SIGINT
);
12727 case AngelSVC_Reason_Read
:
12728 case AngelSVC_Reason_FLen
:
12729 case AngelSVC_Reason_Seek
:
12730 case AngelSVC_Reason_Remove
:
12731 case AngelSVC_Reason_Time
:
12732 case AngelSVC_Reason_System
:
12733 case AngelSVC_Reason_Rename
:
12734 case AngelSVC_Reason_Elapsed
:
12736 TRACE_SYSCALL (cpu
, " HLT [Unknown angel %x]",
12737 aarch64_get_reg_u32 (cpu
, 0, NO_SP
));
12738 sim_engine_halt (CPU_STATE (cpu
), cpu
, NULL
, aarch64_get_PC (cpu
),
12739 sim_stopped
, SIM_SIGTRAP
);
12742 aarch64_set_reg_u64 (cpu
, 0, NO_SP
, result
);
12746 dexExcpnGen (sim_cpu
*cpu
)
12748 /* instr[31:24] = 11010100
12749 instr[23,21] = opc : 000 ==> GEN EXCPN, 001 ==> BRK
12750 010 ==> HLT, 101 ==> DBG GEN EXCPN
12751 instr[20,5] = imm16
12752 instr[4,2] = opc2 000 ==> OK, ow ==> UNALLOC
12753 instr[1,0] = LL : discriminates opc */
12755 uint32_t opc
= uimm (aarch64_get_instr (cpu
), 23, 21);
12756 uint32_t imm16
= uimm (aarch64_get_instr (cpu
), 20, 5);
12757 uint32_t opc2
= uimm (aarch64_get_instr (cpu
), 4, 2);
12760 NYI_assert (31, 24, 0xd4);
12765 LL
= uimm (aarch64_get_instr (cpu
), 1, 0);
12767 /* We only implement HLT and BRK for now. */
12768 if (opc
== 1 && LL
== 0)
12770 TRACE_EVENTS (cpu
, " BRK [0x%x]", imm16
);
12771 sim_engine_halt (CPU_STATE (cpu
), cpu
, NULL
, aarch64_get_PC (cpu
),
12772 sim_exited
, aarch64_get_reg_s32 (cpu
, R0
, SP_OK
));
12775 if (opc
== 2 && LL
== 0)
12776 handle_halt (cpu
, imm16
);
12778 else if (opc
== 0 || opc
== 5)
12785 /* Stub for accessing system registers.
12786 We implement support for the DCZID register since this is used
12787 by the C library's memset function. */
12790 system_get (sim_cpu
*cpu
, unsigned op0
, unsigned op1
, unsigned crn
,
12791 unsigned crm
, unsigned op2
)
12793 if (crn
== 0 && op1
== 3 && crm
== 0 && op2
== 7)
12794 /* DCZID_EL0 - the Data Cache Zero ID register.
12795 We do not support DC ZVA at the moment, so
12796 we return a value with the disable bit set. */
12797 return ((uint64_t) 1) << 4;
12803 do_mrs (sim_cpu
*cpu
)
12805 /* instr[31:20] = 1101 01010 0011
12812 unsigned sys_op0
= uimm (aarch64_get_instr (cpu
), 19, 19) + 2;
12813 unsigned sys_op1
= uimm (aarch64_get_instr (cpu
), 18, 16);
12814 unsigned sys_crn
= uimm (aarch64_get_instr (cpu
), 15, 12);
12815 unsigned sys_crm
= uimm (aarch64_get_instr (cpu
), 11, 8);
12816 unsigned sys_op2
= uimm (aarch64_get_instr (cpu
), 7, 5);
12817 unsigned rt
= uimm (aarch64_get_instr (cpu
), 4, 0);
12819 aarch64_set_reg_u64 (cpu
, rt
, NO_SP
,
12820 system_get (cpu
, sys_op0
, sys_op1
, sys_crn
, sys_crm
, sys_op2
));
12824 dexSystem (sim_cpu
*cpu
)
12826 /* instr[31:22] = 1101 01010 0
12833 instr[4,0] = uimm5 */
12835 /* We are interested in HINT, DSB, DMB and ISB
12837 Hint #0 encodes NOOP (this is the only hint we care about)
12838 L == 0, op0 == 0, op1 = 011, CRn = 0010, Rt = 11111,
12839 CRm op2 != 0000 000 OR CRm op2 == 0000 000 || CRm op > 0000 101
12841 DSB, DMB, ISB are data store barrier, data memory barrier and
12842 instruction store barrier, respectively, where
12844 L == 0, op0 == 0, op1 = 011, CRn = 0011, Rt = 11111,
12845 op2 : DSB ==> 100, DMB ==> 101, ISB ==> 110
12846 CRm<3:2> ==> domain, CRm<1:0> ==> types,
12847 domain : 00 ==> OuterShareable, 01 ==> Nonshareable,
12848 10 ==> InerShareable, 11 ==> FullSystem
12849 types : 01 ==> Reads, 10 ==> Writes,
12850 11 ==> All, 00 ==> All (domain == FullSystem). */
12852 unsigned rt
= uimm (aarch64_get_instr (cpu
), 4, 0);
12853 uint32_t l_op0_op1_crn
= uimm (aarch64_get_instr (cpu
), 21, 12);
12855 NYI_assert (31, 22, 0x354);
12857 switch (l_op0_op1_crn
)
12862 /* NOP has CRm != 0000 OR. */
12863 /* (CRm == 0000 AND (op2 == 000 OR op2 > 101)). */
12864 uint32_t crm
= uimm (aarch64_get_instr (cpu
), 11, 8);
12865 uint32_t op2
= uimm (aarch64_get_instr (cpu
), 7, 5);
12867 if (crm
!= 0 || (op2
== 0 || op2
> 5))
12869 /* Actually call nop method so we can reimplement it later. */
12878 uint32_t op2
= uimm (aarch64_get_instr (cpu
), 7, 5);
12883 case 4: dsb (cpu
); return;
12884 case 5: dmb (cpu
); return;
12885 case 6: isb (cpu
); return;
12887 default: HALT_UNALLOC
;
12892 /* MRS Wt, sys-reg. */
12898 /* MRS Xt, sys-reg. */
12903 /* DC <type>, x<n>. */
12908 /* if (uimm (aarch64_get_instr (cpu), 21, 20) == 0x1)
12909 MRS Xt, sys-reg. */
12916 dexBr (sim_cpu
*cpu
)
12918 /* uint32_t group = dispatchGroup (aarch64_get_instr (cpu));
12919 assert group == GROUP_BREXSYS_1010 || group == GROUP_BREXSYS_1011
12920 bits [31,29] of a BrExSys are the secondary dispatch vector. */
12921 uint32_t group2
= dispatchBrExSys (aarch64_get_instr (cpu
));
12926 return dexBranchImmediate (cpu
);
12928 case BR_IMMCMP_001
:
12929 /* Compare has bit 25 clear while test has it set. */
12930 if (!uimm (aarch64_get_instr (cpu
), 25, 25))
12931 dexCompareBranchImmediate (cpu
);
12933 dexTestBranchImmediate (cpu
);
12936 case BR_IMMCOND_010
:
12937 /* This is a conditional branch if bit 25 is clear otherwise
12939 if (!uimm (aarch64_get_instr (cpu
), 25, 25))
12940 dexCondBranchImmediate (cpu
);
12945 case BR_UNALLOC_011
:
12949 dexBranchImmediate (cpu
);
12952 case BR_IMMCMP_101
:
12953 /* Compare has bit 25 clear while test has it set. */
12954 if (!uimm (aarch64_get_instr (cpu
), 25, 25))
12955 dexCompareBranchImmediate (cpu
);
12957 dexTestBranchImmediate (cpu
);
12961 /* Unconditional branch reg has bit 25 set. */
12962 if (uimm (aarch64_get_instr (cpu
), 25, 25))
12963 dexBranchRegister (cpu
);
12965 /* This includes both Excpn Gen, System and unalloc operations.
12966 We need to decode the Excpn Gen operation BRK so we can plant
12967 debugger entry points.
12968 Excpn Gen operations have aarch64_get_instr (cpu)[24] = 0.
12969 we need to decode at least one of the System operations NOP
12970 which is an alias for HINT #0.
12971 System operations have aarch64_get_instr (cpu)[24,22] = 100. */
12972 else if (uimm (aarch64_get_instr (cpu
), 24, 24) == 0)
12975 else if (uimm (aarch64_get_instr (cpu
), 24, 22) == 4)
12983 case BR_UNALLOC_111
:
12987 /* Should never reach here. */
12993 aarch64_decode_and_execute (sim_cpu
*cpu
, uint64_t pc
)
12995 /* We need to check if gdb wants an in here. */
12996 /* checkBreak (cpu);. */
12998 uint64_t group
= dispatchGroup (aarch64_get_instr (cpu
));
13002 case GROUP_PSEUDO_0000
: dexPseudo (cpu
); break;
13003 case GROUP_LDST_0100
: dexLdSt (cpu
); break;
13004 case GROUP_DPREG_0101
: dexDPReg (cpu
); break;
13005 case GROUP_LDST_0110
: dexLdSt (cpu
); break;
13006 case GROUP_ADVSIMD_0111
: dexAdvSIMD0 (cpu
); break;
13007 case GROUP_DPIMM_1000
: dexDPImm (cpu
); break;
13008 case GROUP_DPIMM_1001
: dexDPImm (cpu
); break;
13009 case GROUP_BREXSYS_1010
: dexBr (cpu
); break;
13010 case GROUP_BREXSYS_1011
: dexBr (cpu
); break;
13011 case GROUP_LDST_1100
: dexLdSt (cpu
); break;
13012 case GROUP_DPREG_1101
: dexDPReg (cpu
); break;
13013 case GROUP_LDST_1110
: dexLdSt (cpu
); break;
13014 case GROUP_ADVSIMD_1111
: dexAdvSIMD1 (cpu
); break;
13016 case GROUP_UNALLOC_0001
:
13017 case GROUP_UNALLOC_0010
:
13018 case GROUP_UNALLOC_0011
:
13022 /* Should never reach here. */
13028 aarch64_step (sim_cpu
*cpu
)
13030 uint64_t pc
= aarch64_get_PC (cpu
);
13032 if (pc
== TOP_LEVEL_RETURN_PC
)
13035 aarch64_set_next_PC (cpu
, pc
+ 4);
13036 aarch64_get_instr (cpu
) = aarch64_get_mem_u32 (cpu
, pc
);
13038 if (TRACE_INSN_P (cpu
))
13041 TRACE_INSN (cpu
, " pc = %" PRIx64
" ", pc
);
13043 TRACE_INSN (cpu
, " pc = %" PRIx64
" instr = %x", pc
,
13044 aarch64_get_instr (cpu
));
13047 sim_io_eprintf (CPU_STATE (cpu
), " %" PRIx64
" ", pc
);
13050 aarch64_print_insn (CPU_STATE (cpu
), pc
);
13052 aarch64_decode_and_execute (cpu
, pc
);
13058 aarch64_run (SIM_DESC sd
)
13060 sim_cpu
*cpu
= STATE_CPU (sd
, 0);
13062 while (aarch64_step (cpu
))
13063 aarch64_update_PC (cpu
);
13065 sim_engine_halt (sd
, NULL
, NULL
, aarch64_get_PC (cpu
),
13066 sim_exited
, aarch64_get_reg_s32 (cpu
, R0
, SP_OK
));
13070 aarch64_init (sim_cpu
*cpu
, uint64_t pc
)
13072 uint64_t sp
= aarch64_get_stack_start (cpu
);
13074 /* Install SP, FP and PC and set LR to -20
13075 so we can detect a top-level return. */
13076 aarch64_set_reg_u64 (cpu
, SP
, SP_OK
, sp
);
13077 aarch64_set_reg_u64 (cpu
, FP
, SP_OK
, sp
);
13078 aarch64_set_reg_u64 (cpu
, LR
, SP_OK
, TOP_LEVEL_RETURN_PC
);
13079 aarch64_set_next_PC (cpu
, pc
);
13080 aarch64_update_PC (cpu
);
13081 aarch64_init_LIT_table ();