1 /* simulator.c -- Interface for the AArch64 simulator.
3 Copyright (C) 2015-2016 Free Software Foundation, Inc.
5 Contributed by Red Hat.
7 This file is part of GDB.
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 3 of the License, or
12 (at your option) any later version.
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with this program. If not, see <http://www.gnu.org/licenses/>. */
26 #include <sys/types.h>
31 #include "simulator.h"
38 #define TST(_flag) (aarch64_test_CPSR_bit (cpu, _flag))
39 #define IS_SET(_X) (TST (( _X )) ? 1 : 0)
40 #define IS_CLEAR(_X) (TST (( _X )) ? 0 : 1)
42 /* Space saver macro. */
43 #define INSTR(HIGH, LOW) uimm (aarch64_get_instr (cpu), (HIGH), (LOW))
45 #define HALT_UNALLOC \
48 TRACE_DISASM (cpu, aarch64_get_PC (cpu)); \
50 "Unallocated instruction detected at sim line %d," \
51 " exe addr %" PRIx64, \
52 __LINE__, aarch64_get_PC (cpu)); \
53 sim_engine_halt (CPU_STATE (cpu), cpu, NULL, aarch64_get_PC (cpu),\
54 sim_stopped, SIM_SIGILL); \
61 TRACE_DISASM (cpu, aarch64_get_PC (cpu)); \
63 "Unimplemented instruction detected at sim line %d," \
64 " exe addr %" PRIx64, \
65 __LINE__, aarch64_get_PC (cpu)); \
66 if (! TRACE_ANY_P (cpu)) \
68 sim_io_eprintf (CPU_STATE (cpu), "SIM Error: Unimplemented instruction: "); \
69 trace_disasm (CPU_STATE (cpu), cpu, aarch64_get_PC (cpu)); \
71 sim_engine_halt (CPU_STATE (cpu), cpu, NULL, aarch64_get_PC (cpu),\
72 sim_stopped, SIM_SIGABRT); \
76 #define NYI_assert(HI, LO, EXPECTED) \
79 if (INSTR ((HI), (LO)) != (EXPECTED)) \
84 /* Helper functions used by expandLogicalImmediate. */
86 /* for i = 1, ... N result<i-1> = 1 other bits are zero */
87 static inline uint64_t
90 return (N
== 64 ? (uint64_t)-1UL : ((1UL << N
) - 1));
93 /* result<0> to val<N> */
94 static inline uint64_t
95 pickbit (uint64_t val
, int N
)
97 return pickbits64 (val
, N
, N
);
101 expand_logical_immediate (uint32_t S
, uint32_t R
, uint32_t N
)
107 /* The immediate value is S+1 bits to 1, left rotated by SIMDsize - R
108 (in other words, right rotated by R), then replicated. */
112 mask
= 0xffffffffffffffffull
;
118 case 0x00 ... 0x1f: /* 0xxxxx */ simd_size
= 32; break;
119 case 0x20 ... 0x2f: /* 10xxxx */ simd_size
= 16; S
&= 0xf; break;
120 case 0x30 ... 0x37: /* 110xxx */ simd_size
= 8; S
&= 0x7; break;
121 case 0x38 ... 0x3b: /* 1110xx */ simd_size
= 4; S
&= 0x3; break;
122 case 0x3c ... 0x3d: /* 11110x */ simd_size
= 2; S
&= 0x1; break;
125 mask
= (1ull << simd_size
) - 1;
126 /* Top bits are IGNORED. */
130 /* NOTE: if S = simd_size - 1 we get 0xf..f which is rejected. */
131 if (S
== simd_size
- 1)
134 /* S+1 consecutive bits to 1. */
135 /* NOTE: S can't be 63 due to detection above. */
136 imm
= (1ull << (S
+ 1)) - 1;
138 /* Rotate to the left by simd_size - R. */
140 imm
= ((imm
<< (simd_size
- R
)) & mask
) | (imm
>> R
);
142 /* Replicate the value according to SIMD size. */
145 case 2: imm
= (imm
<< 2) | imm
;
146 case 4: imm
= (imm
<< 4) | imm
;
147 case 8: imm
= (imm
<< 8) | imm
;
148 case 16: imm
= (imm
<< 16) | imm
;
149 case 32: imm
= (imm
<< 32) | imm
;
157 /* Instr[22,10] encodes N immr and imms. we want a lookup table
158 for each possible combination i.e. 13 bits worth of int entries. */
159 #define LI_TABLE_SIZE (1 << 13)
160 static uint64_t LITable
[LI_TABLE_SIZE
];
163 aarch64_init_LIT_table (void)
167 for (index
= 0; index
< LI_TABLE_SIZE
; index
++)
169 uint32_t N
= uimm (index
, 12, 12);
170 uint32_t immr
= uimm (index
, 11, 6);
171 uint32_t imms
= uimm (index
, 5, 0);
173 LITable
[index
] = expand_logical_immediate (imms
, immr
, N
);
178 dexNotify (sim_cpu
*cpu
)
180 /* instr[14,0] == type : 0 ==> method entry, 1 ==> method reentry
181 2 ==> exit Java, 3 ==> start next bytecode. */
182 uint32_t type
= INSTR (14, 0);
184 TRACE_EVENTS (cpu
, "Notify Insn encountered, type = 0x%x", type
);
189 /* aarch64_notifyMethodEntry (aarch64_get_reg_u64 (cpu, R23, 0),
190 aarch64_get_reg_u64 (cpu, R22, 0)); */
193 /* aarch64_notifyMethodReentry (aarch64_get_reg_u64 (cpu, R23, 0),
194 aarch64_get_reg_u64 (cpu, R22, 0)); */
197 /* aarch64_notifyMethodExit (); */
200 /* aarch64_notifyBCStart (aarch64_get_reg_u64 (cpu, R23, 0),
201 aarch64_get_reg_u64 (cpu, R22, 0)); */
206 /* secondary decode within top level groups */
209 dexPseudo (sim_cpu
*cpu
)
211 /* assert instr[28,27] = 00
213 We provide 2 pseudo instructions:
215 HALT stops execution of the simulator causing an immediate
216 return to the x86 code which entered it.
218 CALLOUT initiates recursive entry into x86 code. A register
219 argument holds the address of the x86 routine. Immediate
220 values in the instruction identify the number of general
221 purpose and floating point register arguments to be passed
222 and the type of any value to be returned. */
224 uint32_t PSEUDO_HALT
= 0xE0000000U
;
225 uint32_t PSEUDO_CALLOUT
= 0x00018000U
;
226 uint32_t PSEUDO_CALLOUTR
= 0x00018001U
;
227 uint32_t PSEUDO_NOTIFY
= 0x00014000U
;
230 if (aarch64_get_instr (cpu
) == PSEUDO_HALT
)
232 TRACE_EVENTS (cpu
, " Pseudo Halt Instruction");
233 sim_engine_halt (CPU_STATE (cpu
), cpu
, NULL
, aarch64_get_PC (cpu
),
234 sim_stopped
, SIM_SIGTRAP
);
237 dispatch
= INSTR (31, 15);
239 /* We do not handle callouts at the moment. */
240 if (dispatch
== PSEUDO_CALLOUT
|| dispatch
== PSEUDO_CALLOUTR
)
242 TRACE_EVENTS (cpu
, " Callout");
243 sim_engine_halt (CPU_STATE (cpu
), cpu
, NULL
, aarch64_get_PC (cpu
),
244 sim_stopped
, SIM_SIGABRT
);
247 else if (dispatch
== PSEUDO_NOTIFY
)
254 /* Load-store single register (unscaled offset)
255 These instructions employ a base register plus an unscaled signed
258 N.B. the base register (source) can be Xn or SP. all other
259 registers may not be SP. */
261 /* 32 bit load 32 bit unscaled signed 9 bit. */
263 ldur32 (sim_cpu
*cpu
, int32_t offset
)
265 unsigned rn
= INSTR (9, 5);
266 unsigned rt
= INSTR (4, 0);
268 aarch64_set_reg_u64 (cpu
, rt
, NO_SP
, aarch64_get_mem_u32
269 (cpu
, aarch64_get_reg_u64 (cpu
, rn
, SP_OK
)
273 /* 64 bit load 64 bit unscaled signed 9 bit. */
275 ldur64 (sim_cpu
*cpu
, int32_t offset
)
277 unsigned rn
= INSTR (9, 5);
278 unsigned rt
= INSTR (4, 0);
280 aarch64_set_reg_u64 (cpu
, rt
, NO_SP
, aarch64_get_mem_u64
281 (cpu
, aarch64_get_reg_u64 (cpu
, rn
, SP_OK
)
285 /* 32 bit load zero-extended byte unscaled signed 9 bit. */
287 ldurb32 (sim_cpu
*cpu
, int32_t offset
)
289 unsigned rn
= INSTR (9, 5);
290 unsigned rt
= INSTR (4, 0);
292 aarch64_set_reg_u64 (cpu
, rt
, NO_SP
, aarch64_get_mem_u8
293 (cpu
, aarch64_get_reg_u64 (cpu
, rn
, SP_OK
)
297 /* 32 bit load sign-extended byte unscaled signed 9 bit. */
299 ldursb32 (sim_cpu
*cpu
, int32_t offset
)
301 unsigned rn
= INSTR (9, 5);
302 unsigned rt
= INSTR (4, 0);
304 aarch64_set_reg_u64 (cpu
, rt
, NO_SP
, (uint32_t) aarch64_get_mem_s8
305 (cpu
, aarch64_get_reg_u64 (cpu
, rn
, SP_OK
)
309 /* 64 bit load sign-extended byte unscaled signed 9 bit. */
311 ldursb64 (sim_cpu
*cpu
, int32_t offset
)
313 unsigned rn
= INSTR (9, 5);
314 unsigned rt
= INSTR (4, 0);
316 aarch64_set_reg_s64 (cpu
, rt
, NO_SP
, aarch64_get_mem_s8
317 (cpu
, aarch64_get_reg_u64 (cpu
, rn
, SP_OK
)
321 /* 32 bit load zero-extended short unscaled signed 9 bit */
323 ldurh32 (sim_cpu
*cpu
, int32_t offset
)
325 unsigned rn
= INSTR (9, 5);
326 unsigned rd
= INSTR (4, 0);
328 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, aarch64_get_mem_u16
329 (cpu
, aarch64_get_reg_u64 (cpu
, rn
, SP_OK
)
333 /* 32 bit load sign-extended short unscaled signed 9 bit */
335 ldursh32 (sim_cpu
*cpu
, int32_t offset
)
337 unsigned rn
= INSTR (9, 5);
338 unsigned rd
= INSTR (4, 0);
340 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, (uint32_t) aarch64_get_mem_s16
341 (cpu
, aarch64_get_reg_u64 (cpu
, rn
, SP_OK
)
345 /* 64 bit load sign-extended short unscaled signed 9 bit */
347 ldursh64 (sim_cpu
*cpu
, int32_t offset
)
349 unsigned rn
= INSTR (9, 5);
350 unsigned rt
= INSTR (4, 0);
352 aarch64_set_reg_s64 (cpu
, rt
, NO_SP
, aarch64_get_mem_s16
353 (cpu
, aarch64_get_reg_u64 (cpu
, rn
, SP_OK
)
357 /* 64 bit load sign-extended word unscaled signed 9 bit */
359 ldursw (sim_cpu
*cpu
, int32_t offset
)
361 unsigned rn
= INSTR (9, 5);
362 unsigned rd
= INSTR (4, 0);
364 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, (uint32_t) aarch64_get_mem_s32
365 (cpu
, aarch64_get_reg_u64 (cpu
, rn
, SP_OK
)
369 /* N.B. with stores the value in source is written to the address
370 identified by source2 modified by offset. */
372 /* 32 bit store 32 bit unscaled signed 9 bit. */
374 stur32 (sim_cpu
*cpu
, int32_t offset
)
376 unsigned rn
= INSTR (9, 5);
377 unsigned rd
= INSTR (4, 0);
379 aarch64_set_mem_u32 (cpu
,
380 aarch64_get_reg_u64 (cpu
, rn
, SP_OK
) + offset
,
381 aarch64_get_reg_u32 (cpu
, rd
, NO_SP
));
384 /* 64 bit store 64 bit unscaled signed 9 bit */
386 stur64 (sim_cpu
*cpu
, int32_t offset
)
388 unsigned rn
= INSTR (9, 5);
389 unsigned rd
= INSTR (4, 0);
391 aarch64_set_mem_u64 (cpu
,
392 aarch64_get_reg_u64 (cpu
, rn
, SP_OK
) + offset
,
393 aarch64_get_reg_u64 (cpu
, rd
, NO_SP
));
396 /* 32 bit store byte unscaled signed 9 bit */
398 sturb (sim_cpu
*cpu
, int32_t offset
)
400 unsigned rn
= INSTR (9, 5);
401 unsigned rd
= INSTR (4, 0);
403 aarch64_set_mem_u8 (cpu
,
404 aarch64_get_reg_u64 (cpu
, rn
, SP_OK
) + offset
,
405 aarch64_get_reg_u8 (cpu
, rd
, NO_SP
));
408 /* 32 bit store short unscaled signed 9 bit */
410 sturh (sim_cpu
*cpu
, int32_t offset
)
412 unsigned rn
= INSTR (9, 5);
413 unsigned rd
= INSTR (4, 0);
415 aarch64_set_mem_u16 (cpu
,
416 aarch64_get_reg_u64 (cpu
, rn
, SP_OK
) + offset
,
417 aarch64_get_reg_u16 (cpu
, rd
, NO_SP
));
420 /* Load single register pc-relative label
421 Offset is a signed 19 bit immediate count in words
424 /* 32 bit pc-relative load */
426 ldr32_pcrel (sim_cpu
*cpu
, int32_t offset
)
428 unsigned rd
= INSTR (4, 0);
430 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
,
432 (cpu
, aarch64_get_PC (cpu
) + offset
* 4));
435 /* 64 bit pc-relative load */
437 ldr_pcrel (sim_cpu
*cpu
, int32_t offset
)
439 unsigned rd
= INSTR (4, 0);
441 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
,
443 (cpu
, aarch64_get_PC (cpu
) + offset
* 4));
446 /* sign extended 32 bit pc-relative load */
448 ldrsw_pcrel (sim_cpu
*cpu
, int32_t offset
)
450 unsigned rd
= INSTR (4, 0);
452 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
,
454 (cpu
, aarch64_get_PC (cpu
) + offset
* 4));
457 /* float pc-relative load */
459 fldrs_pcrel (sim_cpu
*cpu
, int32_t offset
)
461 unsigned int rd
= INSTR (4, 0);
463 aarch64_set_vec_u32 (cpu
, rd
, 0,
465 (cpu
, aarch64_get_PC (cpu
) + offset
* 4));
468 /* double pc-relative load */
470 fldrd_pcrel (sim_cpu
*cpu
, int32_t offset
)
472 unsigned int st
= INSTR (4, 0);
474 aarch64_set_vec_u64 (cpu
, st
, 0,
476 (cpu
, aarch64_get_PC (cpu
) + offset
* 4));
479 /* long double pc-relative load. */
481 fldrq_pcrel (sim_cpu
*cpu
, int32_t offset
)
483 unsigned int st
= INSTR (4, 0);
484 uint64_t addr
= aarch64_get_PC (cpu
) + offset
* 4;
487 aarch64_get_mem_long_double (cpu
, addr
, & a
);
488 aarch64_set_FP_long_double (cpu
, st
, a
);
491 /* This can be used to scale an offset by applying
492 the requisite shift. the second argument is either
495 #define SCALE(_offset, _elementSize) \
496 ((_offset) << ScaleShift ## _elementSize)
498 /* This can be used to optionally scale a register derived offset
499 by applying the requisite shift as indicated by the Scaling
500 argument. The second argument is either Byte, Short, Word
501 or Long. The third argument is either Scaled or Unscaled.
502 N.B. when _Scaling is Scaled the shift gets ANDed with
503 all 1s while when it is Unscaled it gets ANDed with 0. */
505 #define OPT_SCALE(_offset, _elementType, _Scaling) \
506 ((_offset) << (_Scaling ? ScaleShift ## _elementType : 0))
508 /* This can be used to zero or sign extend a 32 bit register derived
509 value to a 64 bit value. the first argument must be the value as
510 a uint32_t and the second must be either UXTW or SXTW. The result
511 is returned as an int64_t. */
513 static inline int64_t
514 extend (uint32_t value
, Extension extension
)
522 /* A branchless variant of this ought to be possible. */
523 if (extension
== UXTW
|| extension
== NoExtension
)
530 /* Scalar Floating Point
532 FP load/store single register (4 addressing modes)
534 N.B. the base register (source) can be the stack pointer.
535 The secondary source register (source2) can only be an Xn register. */
537 /* Load 32 bit unscaled signed 9 bit with pre- or post-writeback. */
539 fldrs_wb (sim_cpu
*cpu
, int32_t offset
, WriteBack wb
)
541 unsigned rn
= INSTR (9, 5);
542 unsigned st
= INSTR (4, 0);
543 uint64_t address
= aarch64_get_reg_u64 (cpu
, rn
, SP_OK
);
548 aarch64_set_vec_u32 (cpu
, st
, 0, aarch64_get_mem_u32 (cpu
, address
));
552 if (wb
!= NoWriteBack
)
553 aarch64_set_reg_u64 (cpu
, rn
, SP_OK
, address
);
556 /* Load 8 bit with unsigned 12 bit offset. */
558 fldrb_abs (sim_cpu
*cpu
, uint32_t offset
)
560 unsigned rd
= INSTR (4, 0);
561 unsigned rn
= INSTR (9, 5);
562 uint64_t addr
= aarch64_get_reg_u64 (cpu
, rn
, SP_OK
) + offset
;
564 aarch64_set_vec_u8 (cpu
, rd
, 0, aarch64_get_mem_u32 (cpu
, addr
));
567 /* Load 16 bit scaled unsigned 12 bit. */
569 fldrh_abs (sim_cpu
*cpu
, uint32_t offset
)
571 unsigned rd
= INSTR (4, 0);
572 unsigned rn
= INSTR (9, 5);
573 uint64_t addr
= aarch64_get_reg_u64 (cpu
, rn
, SP_OK
) + SCALE (offset
, 16);
575 aarch64_set_vec_u16 (cpu
, rd
, 0, aarch64_get_mem_u16 (cpu
, addr
));
578 /* Load 32 bit scaled unsigned 12 bit. */
580 fldrs_abs (sim_cpu
*cpu
, uint32_t offset
)
582 unsigned rd
= INSTR (4, 0);
583 unsigned rn
= INSTR (9, 5);
584 uint64_t addr
= aarch64_get_reg_u64 (cpu
, rn
, SP_OK
) + SCALE (offset
, 32);
586 aarch64_set_vec_u32 (cpu
, rd
, 0, aarch64_get_mem_u32 (cpu
, addr
));
589 /* Load 64 bit scaled unsigned 12 bit. */
591 fldrd_abs (sim_cpu
*cpu
, uint32_t offset
)
593 unsigned rd
= INSTR (4, 0);
594 unsigned rn
= INSTR (9, 5);
595 uint64_t addr
= aarch64_get_reg_u64 (cpu
, rn
, SP_OK
) + SCALE (offset
, 64);
597 aarch64_set_vec_u64 (cpu
, rd
, 0, aarch64_get_mem_u64 (cpu
, addr
));
600 /* Load 128 bit scaled unsigned 12 bit. */
602 fldrq_abs (sim_cpu
*cpu
, uint32_t offset
)
604 unsigned rd
= INSTR (4, 0);
605 unsigned rn
= INSTR (9, 5);
606 uint64_t addr
= aarch64_get_reg_u64 (cpu
, rn
, SP_OK
) + SCALE (offset
, 128);
608 aarch64_set_vec_u64 (cpu
, rd
, 0, aarch64_get_mem_u64 (cpu
, addr
));
609 aarch64_set_vec_u64 (cpu
, rd
, 1, aarch64_get_mem_u64 (cpu
, addr
+ 8));
612 /* Load 32 bit scaled or unscaled zero- or sign-extended
613 32-bit register offset. */
615 fldrs_scale_ext (sim_cpu
*cpu
, Scaling scaling
, Extension extension
)
617 unsigned rm
= INSTR (20, 16);
618 unsigned rn
= INSTR (9, 5);
619 unsigned st
= INSTR (4, 0);
620 uint64_t address
= aarch64_get_reg_u64 (cpu
, rn
, SP_OK
);
621 int64_t extended
= extend (aarch64_get_reg_u32 (cpu
, rm
, NO_SP
), extension
);
622 uint64_t displacement
= OPT_SCALE (extended
, 32, scaling
);
624 aarch64_set_vec_u32 (cpu
, st
, 0, aarch64_get_mem_u32
625 (cpu
, address
+ displacement
));
628 /* Load 64 bit unscaled signed 9 bit with pre- or post-writeback. */
630 fldrd_wb (sim_cpu
*cpu
, int32_t offset
, WriteBack wb
)
632 unsigned rn
= INSTR (9, 5);
633 unsigned st
= INSTR (4, 0);
634 uint64_t address
= aarch64_get_reg_u64 (cpu
, rn
, SP_OK
);
639 aarch64_set_vec_u64 (cpu
, st
, 0, aarch64_get_mem_u64 (cpu
, address
));
644 if (wb
!= NoWriteBack
)
645 aarch64_set_reg_u64 (cpu
, rn
, SP_OK
, address
);
648 /* Load 64 bit scaled or unscaled zero- or sign-extended 32-bit register offset. */
650 fldrd_scale_ext (sim_cpu
*cpu
, Scaling scaling
, Extension extension
)
652 unsigned rm
= INSTR (20, 16);
653 int64_t extended
= extend (aarch64_get_reg_u32 (cpu
, rm
, NO_SP
), extension
);
654 uint64_t displacement
= OPT_SCALE (extended
, 64, scaling
);
656 fldrd_wb (cpu
, displacement
, NoWriteBack
);
659 /* Load 128 bit unscaled signed 9 bit with pre- or post-writeback. */
661 fldrq_wb (sim_cpu
*cpu
, int32_t offset
, WriteBack wb
)
664 unsigned rn
= INSTR (9, 5);
665 unsigned st
= INSTR (4, 0);
666 uint64_t address
= aarch64_get_reg_u64 (cpu
, rn
, SP_OK
);
671 aarch64_get_mem_long_double (cpu
, address
, & a
);
672 aarch64_set_FP_long_double (cpu
, st
, a
);
677 if (wb
!= NoWriteBack
)
678 aarch64_set_reg_u64 (cpu
, rn
, SP_OK
, address
);
681 /* Load 128 bit scaled or unscaled zero- or sign-extended 32-bit register offset */
683 fldrq_scale_ext (sim_cpu
*cpu
, Scaling scaling
, Extension extension
)
685 unsigned rm
= INSTR (20, 16);
686 int64_t extended
= extend (aarch64_get_reg_u32 (cpu
, rm
, NO_SP
), extension
);
687 uint64_t displacement
= OPT_SCALE (extended
, 128, scaling
);
689 fldrq_wb (cpu
, displacement
, NoWriteBack
);
694 load-store single register
695 There are four addressing modes available here which all employ a
696 64 bit source (base) register.
698 N.B. the base register (source) can be the stack pointer.
699 The secondary source register (source2)can only be an Xn register.
701 Scaled, 12-bit, unsigned immediate offset, without pre- and
703 Unscaled, 9-bit, signed immediate offset with pre- or post-index
705 scaled or unscaled 64-bit register offset.
706 scaled or unscaled 32-bit extended register offset.
708 All offsets are assumed to be raw from the decode i.e. the
709 simulator is expected to adjust scaled offsets based on the
710 accessed data size with register or extended register offset
711 versions the same applies except that in the latter case the
712 operation may also require a sign extend.
714 A separate method is provided for each possible addressing mode. */
716 /* 32 bit load 32 bit scaled unsigned 12 bit */
718 ldr32_abs (sim_cpu
*cpu
, uint32_t offset
)
720 unsigned rn
= INSTR (9, 5);
721 unsigned rt
= INSTR (4, 0);
723 /* The target register may not be SP but the source may be. */
724 aarch64_set_reg_u64 (cpu
, rt
, NO_SP
, aarch64_get_mem_u32
725 (cpu
, aarch64_get_reg_u64 (cpu
, rn
, SP_OK
)
726 + SCALE (offset
, 32)));
729 /* 32 bit load 32 bit unscaled signed 9 bit with pre- or post-writeback. */
731 ldr32_wb (sim_cpu
*cpu
, int32_t offset
, WriteBack wb
)
733 unsigned rn
= INSTR (9, 5);
734 unsigned rt
= INSTR (4, 0);
737 if (rn
== rt
&& wb
!= NoWriteBack
)
740 address
= aarch64_get_reg_u64 (cpu
, rn
, SP_OK
);
745 aarch64_set_reg_u64 (cpu
, rt
, NO_SP
, aarch64_get_mem_u32 (cpu
, address
));
750 if (wb
!= NoWriteBack
)
751 aarch64_set_reg_u64 (cpu
, rn
, SP_OK
, address
);
754 /* 32 bit load 32 bit scaled or unscaled
755 zero- or sign-extended 32-bit register offset */
757 ldr32_scale_ext (sim_cpu
*cpu
, Scaling scaling
, Extension extension
)
759 unsigned rm
= INSTR (20, 16);
760 unsigned rn
= INSTR (9, 5);
761 unsigned rt
= INSTR (4, 0);
762 /* rn may reference SP, rm and rt must reference ZR */
764 uint64_t address
= aarch64_get_reg_u64 (cpu
, rn
, SP_OK
);
765 int64_t extended
= extend (aarch64_get_reg_u32 (cpu
, rm
, NO_SP
), extension
);
766 uint64_t displacement
= OPT_SCALE (extended
, 32, scaling
);
768 aarch64_set_reg_u64 (cpu
, rt
, NO_SP
,
769 aarch64_get_mem_u32 (cpu
, address
+ displacement
));
772 /* 64 bit load 64 bit scaled unsigned 12 bit */
774 ldr_abs (sim_cpu
*cpu
, uint32_t offset
)
776 unsigned rn
= INSTR (9, 5);
777 unsigned rt
= INSTR (4, 0);
779 /* The target register may not be SP but the source may be. */
780 aarch64_set_reg_u64 (cpu
, rt
, NO_SP
, aarch64_get_mem_u64
781 (cpu
, aarch64_get_reg_u64 (cpu
, rn
, SP_OK
)
782 + SCALE (offset
, 64)));
785 /* 64 bit load 64 bit unscaled signed 9 bit with pre- or post-writeback. */
787 ldr_wb (sim_cpu
*cpu
, int32_t offset
, WriteBack wb
)
789 unsigned rn
= INSTR (9, 5);
790 unsigned rt
= INSTR (4, 0);
793 if (rn
== rt
&& wb
!= NoWriteBack
)
796 address
= aarch64_get_reg_u64 (cpu
, rn
, SP_OK
);
801 aarch64_set_reg_u64 (cpu
, rt
, NO_SP
, aarch64_get_mem_u64 (cpu
, address
));
806 if (wb
!= NoWriteBack
)
807 aarch64_set_reg_u64 (cpu
, rn
, SP_OK
, address
);
810 /* 64 bit load 64 bit scaled or unscaled zero-
811 or sign-extended 32-bit register offset. */
813 ldr_scale_ext (sim_cpu
*cpu
, Scaling scaling
, Extension extension
)
815 unsigned rm
= INSTR (20, 16);
816 unsigned rn
= INSTR (9, 5);
817 unsigned rt
= INSTR (4, 0);
818 /* rn may reference SP, rm and rt must reference ZR */
820 uint64_t address
= aarch64_get_reg_u64 (cpu
, rn
, SP_OK
);
821 int64_t extended
= extend (aarch64_get_reg_u32 (cpu
, rm
, NO_SP
), extension
);
822 uint64_t displacement
= OPT_SCALE (extended
, 64, scaling
);
824 aarch64_set_reg_u64 (cpu
, rt
, NO_SP
,
825 aarch64_get_mem_u64 (cpu
, address
+ displacement
));
828 /* 32 bit load zero-extended byte scaled unsigned 12 bit. */
830 ldrb32_abs (sim_cpu
*cpu
, uint32_t offset
)
832 unsigned rn
= INSTR (9, 5);
833 unsigned rt
= INSTR (4, 0);
835 /* The target register may not be SP but the source may be
836 there is no scaling required for a byte load. */
837 aarch64_set_reg_u64 (cpu
, rt
, NO_SP
,
839 (cpu
, aarch64_get_reg_u64 (cpu
, rn
, SP_OK
) + offset
));
842 /* 32 bit load zero-extended byte unscaled signed 9 bit with pre- or post-writeback. */
844 ldrb32_wb (sim_cpu
*cpu
, int32_t offset
, WriteBack wb
)
846 unsigned rn
= INSTR (9, 5);
847 unsigned rt
= INSTR (4, 0);
850 if (rn
== rt
&& wb
!= NoWriteBack
)
853 address
= aarch64_get_reg_u64 (cpu
, rn
, SP_OK
);
858 aarch64_set_reg_u64 (cpu
, rt
, NO_SP
, aarch64_get_mem_u8 (cpu
, address
));
863 if (wb
!= NoWriteBack
)
864 aarch64_set_reg_u64 (cpu
, rn
, SP_OK
, address
);
867 /* 32 bit load zero-extended byte scaled or unscaled zero-
868 or sign-extended 32-bit register offset. */
870 ldrb32_scale_ext (sim_cpu
*cpu
, Scaling scaling
, Extension extension
)
872 unsigned rm
= INSTR (20, 16);
873 unsigned rn
= INSTR (9, 5);
874 unsigned rt
= INSTR (4, 0);
875 /* rn may reference SP, rm and rt must reference ZR */
877 uint64_t address
= aarch64_get_reg_u64 (cpu
, rn
, SP_OK
);
878 int64_t displacement
= extend (aarch64_get_reg_u32 (cpu
, rm
, NO_SP
),
881 /* There is no scaling required for a byte load. */
882 aarch64_set_reg_u64 (cpu
, rt
, NO_SP
,
883 aarch64_get_mem_u8 (cpu
, address
+ displacement
));
886 /* 64 bit load sign-extended byte unscaled signed 9 bit
887 with pre- or post-writeback. */
889 ldrsb_wb (sim_cpu
*cpu
, int32_t offset
, WriteBack wb
)
891 unsigned rn
= INSTR (9, 5);
892 unsigned rt
= INSTR (4, 0);
896 if (rn
== rt
&& wb
!= NoWriteBack
)
899 address
= aarch64_get_reg_u64 (cpu
, rn
, SP_OK
);
904 val
= aarch64_get_mem_s8 (cpu
, address
);
905 aarch64_set_reg_s64 (cpu
, rt
, NO_SP
, val
);
910 if (wb
!= NoWriteBack
)
911 aarch64_set_reg_u64 (cpu
, rn
, SP_OK
, address
);
914 /* 64 bit load sign-extended byte scaled unsigned 12 bit. */
916 ldrsb_abs (sim_cpu
*cpu
, uint32_t offset
)
918 ldrsb_wb (cpu
, offset
, NoWriteBack
);
921 /* 64 bit load sign-extended byte scaled or unscaled zero-
922 or sign-extended 32-bit register offset. */
924 ldrsb_scale_ext (sim_cpu
*cpu
, Scaling scaling
, Extension extension
)
926 unsigned rm
= INSTR (20, 16);
927 unsigned rn
= INSTR (9, 5);
928 unsigned rt
= INSTR (4, 0);
929 /* rn may reference SP, rm and rt must reference ZR */
931 uint64_t address
= aarch64_get_reg_u64 (cpu
, rn
, SP_OK
);
932 int64_t displacement
= extend (aarch64_get_reg_u32 (cpu
, rm
, NO_SP
),
934 /* There is no scaling required for a byte load. */
935 aarch64_set_reg_s64 (cpu
, rt
, NO_SP
,
936 aarch64_get_mem_s8 (cpu
, address
+ displacement
));
939 /* 32 bit load zero-extended short scaled unsigned 12 bit. */
941 ldrh32_abs (sim_cpu
*cpu
, uint32_t offset
)
943 unsigned rn
= INSTR (9, 5);
944 unsigned rt
= INSTR (4, 0);
947 /* The target register may not be SP but the source may be. */
948 val
= aarch64_get_mem_u16 (cpu
, aarch64_get_reg_u64 (cpu
, rn
, SP_OK
)
949 + SCALE (offset
, 16));
950 aarch64_set_reg_u32 (cpu
, rt
, NO_SP
, val
);
953 /* 32 bit load zero-extended short unscaled signed 9 bit
954 with pre- or post-writeback. */
956 ldrh32_wb (sim_cpu
*cpu
, int32_t offset
, WriteBack wb
)
958 unsigned rn
= INSTR (9, 5);
959 unsigned rt
= INSTR (4, 0);
962 if (rn
== rt
&& wb
!= NoWriteBack
)
965 address
= aarch64_get_reg_u64 (cpu
, rn
, SP_OK
);
970 aarch64_set_reg_u32 (cpu
, rt
, NO_SP
, aarch64_get_mem_u16 (cpu
, address
));
975 if (wb
!= NoWriteBack
)
976 aarch64_set_reg_u64 (cpu
, rn
, SP_OK
, address
);
979 /* 32 bit load zero-extended short scaled or unscaled zero-
980 or sign-extended 32-bit register offset. */
982 ldrh32_scale_ext (sim_cpu
*cpu
, Scaling scaling
, Extension extension
)
984 unsigned rm
= INSTR (20, 16);
985 unsigned rn
= INSTR (9, 5);
986 unsigned rt
= INSTR (4, 0);
987 /* rn may reference SP, rm and rt must reference ZR */
989 uint64_t address
= aarch64_get_reg_u64 (cpu
, rn
, SP_OK
);
990 int64_t extended
= extend (aarch64_get_reg_u32 (cpu
, rm
, NO_SP
), extension
);
991 uint64_t displacement
= OPT_SCALE (extended
, 16, scaling
);
993 aarch64_set_reg_u32 (cpu
, rt
, NO_SP
,
994 aarch64_get_mem_u16 (cpu
, address
+ displacement
));
997 /* 32 bit load sign-extended short scaled unsigned 12 bit. */
999 ldrsh32_abs (sim_cpu
*cpu
, uint32_t offset
)
1001 unsigned rn
= INSTR (9, 5);
1002 unsigned rt
= INSTR (4, 0);
1005 /* The target register may not be SP but the source may be. */
1006 val
= aarch64_get_mem_s16 (cpu
, aarch64_get_reg_u64 (cpu
, rn
, SP_OK
)
1007 + SCALE (offset
, 16));
1008 aarch64_set_reg_s32 (cpu
, rt
, NO_SP
, val
);
1011 /* 32 bit load sign-extended short unscaled signed 9 bit
1012 with pre- or post-writeback. */
1014 ldrsh32_wb (sim_cpu
*cpu
, int32_t offset
, WriteBack wb
)
1016 unsigned rn
= INSTR (9, 5);
1017 unsigned rt
= INSTR (4, 0);
1020 if (rn
== rt
&& wb
!= NoWriteBack
)
1023 address
= aarch64_get_reg_u64 (cpu
, rn
, SP_OK
);
1028 aarch64_set_reg_s32 (cpu
, rt
, NO_SP
,
1029 (int32_t) aarch64_get_mem_s16 (cpu
, address
));
1034 if (wb
!= NoWriteBack
)
1035 aarch64_set_reg_u64 (cpu
, rn
, SP_OK
, address
);
1038 /* 32 bit load sign-extended short scaled or unscaled zero-
1039 or sign-extended 32-bit register offset. */
1041 ldrsh32_scale_ext (sim_cpu
*cpu
, Scaling scaling
, Extension extension
)
1043 unsigned rm
= INSTR (20, 16);
1044 unsigned rn
= INSTR (9, 5);
1045 unsigned rt
= INSTR (4, 0);
1046 /* rn may reference SP, rm and rt must reference ZR */
1048 uint64_t address
= aarch64_get_reg_u64 (cpu
, rn
, SP_OK
);
1049 int64_t extended
= extend (aarch64_get_reg_u32 (cpu
, rm
, NO_SP
), extension
);
1050 uint64_t displacement
= OPT_SCALE (extended
, 16, scaling
);
1052 aarch64_set_reg_s32 (cpu
, rt
, NO_SP
,
1053 (int32_t) aarch64_get_mem_s16
1054 (cpu
, address
+ displacement
));
1057 /* 64 bit load sign-extended short scaled unsigned 12 bit. */
1059 ldrsh_abs (sim_cpu
*cpu
, uint32_t offset
)
1061 unsigned rn
= INSTR (9, 5);
1062 unsigned rt
= INSTR (4, 0);
1065 /* The target register may not be SP but the source may be. */
1066 val
= aarch64_get_mem_s16 (cpu
, aarch64_get_reg_u64 (cpu
, rn
, SP_OK
)
1067 + SCALE (offset
, 16));
1068 aarch64_set_reg_s64 (cpu
, rt
, NO_SP
, val
);
1071 /* 64 bit load sign-extended short unscaled signed 9 bit
1072 with pre- or post-writeback. */
1074 ldrsh64_wb (sim_cpu
*cpu
, int32_t offset
, WriteBack wb
)
1076 unsigned rn
= INSTR (9, 5);
1077 unsigned rt
= INSTR (4, 0);
1081 if (rn
== rt
&& wb
!= NoWriteBack
)
1084 address
= aarch64_get_reg_u64 (cpu
, rn
, SP_OK
);
1089 val
= aarch64_get_mem_s16 (cpu
, address
);
1090 aarch64_set_reg_s64 (cpu
, rt
, NO_SP
, val
);
1095 if (wb
!= NoWriteBack
)
1096 aarch64_set_reg_u64 (cpu
, rn
, SP_OK
, address
);
1099 /* 64 bit load sign-extended short scaled or unscaled zero-
1100 or sign-extended 32-bit register offset. */
1102 ldrsh_scale_ext (sim_cpu
*cpu
, Scaling scaling
, Extension extension
)
1104 unsigned rm
= INSTR (20, 16);
1105 unsigned rn
= INSTR (9, 5);
1106 unsigned rt
= INSTR (4, 0);
1108 /* rn may reference SP, rm and rt must reference ZR */
1110 uint64_t address
= aarch64_get_reg_u64 (cpu
, rn
, SP_OK
);
1111 int64_t extended
= extend (aarch64_get_reg_u32 (cpu
, rm
, NO_SP
), extension
);
1112 uint64_t displacement
= OPT_SCALE (extended
, 16, scaling
);
1115 val
= aarch64_get_mem_s16 (cpu
, address
+ displacement
);
1116 aarch64_set_reg_s64 (cpu
, rt
, NO_SP
, val
);
1119 /* 64 bit load sign-extended 32 bit scaled unsigned 12 bit. */
1121 ldrsw_abs (sim_cpu
*cpu
, uint32_t offset
)
1123 unsigned rn
= INSTR (9, 5);
1124 unsigned rt
= INSTR (4, 0);
1127 val
= aarch64_get_mem_s32 (cpu
, aarch64_get_reg_u64 (cpu
, rn
, SP_OK
)
1128 + SCALE (offset
, 32));
1129 /* The target register may not be SP but the source may be. */
1130 return aarch64_set_reg_s64 (cpu
, rt
, NO_SP
, val
);
1133 /* 64 bit load sign-extended 32 bit unscaled signed 9 bit
1134 with pre- or post-writeback. */
1136 ldrsw_wb (sim_cpu
*cpu
, int32_t offset
, WriteBack wb
)
1138 unsigned rn
= INSTR (9, 5);
1139 unsigned rt
= INSTR (4, 0);
1142 if (rn
== rt
&& wb
!= NoWriteBack
)
1145 address
= aarch64_get_reg_u64 (cpu
, rn
, SP_OK
);
1150 aarch64_set_reg_s64 (cpu
, rt
, NO_SP
, aarch64_get_mem_s32 (cpu
, address
));
1155 if (wb
!= NoWriteBack
)
1156 aarch64_set_reg_u64 (cpu
, rn
, SP_OK
, address
);
1159 /* 64 bit load sign-extended 32 bit scaled or unscaled zero-
1160 or sign-extended 32-bit register offset. */
1162 ldrsw_scale_ext (sim_cpu
*cpu
, Scaling scaling
, Extension extension
)
1164 unsigned rm
= INSTR (20, 16);
1165 unsigned rn
= INSTR (9, 5);
1166 unsigned rt
= INSTR (4, 0);
1167 /* rn may reference SP, rm and rt must reference ZR */
1169 uint64_t address
= aarch64_get_reg_u64 (cpu
, rn
, SP_OK
);
1170 int64_t extended
= extend (aarch64_get_reg_u32 (cpu
, rm
, NO_SP
), extension
);
1171 uint64_t displacement
= OPT_SCALE (extended
, 32, scaling
);
1173 aarch64_set_reg_s64 (cpu
, rt
, NO_SP
,
1174 aarch64_get_mem_s32 (cpu
, address
+ displacement
));
1177 /* N.B. with stores the value in source is written to the
1178 address identified by source2 modified by source3/offset. */
1180 /* 32 bit store scaled unsigned 12 bit. */
1182 str32_abs (sim_cpu
*cpu
, uint32_t offset
)
1184 unsigned rn
= INSTR (9, 5);
1185 unsigned rt
= INSTR (4, 0);
1187 /* The target register may not be SP but the source may be. */
1188 aarch64_set_mem_u32 (cpu
, (aarch64_get_reg_u64 (cpu
, rn
, SP_OK
)
1189 + SCALE (offset
, 32)),
1190 aarch64_get_reg_u32 (cpu
, rt
, NO_SP
));
1193 /* 32 bit store unscaled signed 9 bit with pre- or post-writeback. */
1195 str32_wb (sim_cpu
*cpu
, int32_t offset
, WriteBack wb
)
1197 unsigned rn
= INSTR (9, 5);
1198 unsigned rt
= INSTR (4, 0);
1201 if (rn
== rt
&& wb
!= NoWriteBack
)
1204 address
= aarch64_get_reg_u64 (cpu
, rn
, SP_OK
);
1208 aarch64_set_mem_u32 (cpu
, address
, aarch64_get_reg_u32 (cpu
, rt
, NO_SP
));
1213 if (wb
!= NoWriteBack
)
1214 aarch64_set_reg_u64 (cpu
, rn
, SP_OK
, address
);
1217 /* 32 bit store scaled or unscaled zero- or
1218 sign-extended 32-bit register offset. */
1220 str32_scale_ext (sim_cpu
*cpu
, Scaling scaling
, Extension extension
)
1222 unsigned rm
= INSTR (20, 16);
1223 unsigned rn
= INSTR (9, 5);
1224 unsigned rt
= INSTR (4, 0);
1226 uint64_t address
= aarch64_get_reg_u64 (cpu
, rn
, SP_OK
);
1227 int64_t extended
= extend (aarch64_get_reg_u32 (cpu
, rm
, NO_SP
), extension
);
1228 uint64_t displacement
= OPT_SCALE (extended
, 32, scaling
);
1230 aarch64_set_mem_u32 (cpu
, address
+ displacement
,
1231 aarch64_get_reg_u64 (cpu
, rt
, NO_SP
));
1234 /* 64 bit store scaled unsigned 12 bit. */
1236 str_abs (sim_cpu
*cpu
, uint32_t offset
)
1238 unsigned rn
= INSTR (9, 5);
1239 unsigned rt
= INSTR (4, 0);
1241 aarch64_set_mem_u64 (cpu
,
1242 aarch64_get_reg_u64 (cpu
, rn
, SP_OK
)
1243 + SCALE (offset
, 64),
1244 aarch64_get_reg_u64 (cpu
, rt
, NO_SP
));
1247 /* 64 bit store unscaled signed 9 bit with pre- or post-writeback. */
1249 str_wb (sim_cpu
*cpu
, int32_t offset
, WriteBack wb
)
1251 unsigned rn
= INSTR (9, 5);
1252 unsigned rt
= INSTR (4, 0);
1255 if (rn
== rt
&& wb
!= NoWriteBack
)
1258 address
= aarch64_get_reg_u64 (cpu
, rn
, SP_OK
);
1263 aarch64_set_mem_u64 (cpu
, address
, aarch64_get_reg_u64 (cpu
, rt
, NO_SP
));
1268 if (wb
!= NoWriteBack
)
1269 aarch64_set_reg_u64 (cpu
, rn
, SP_OK
, address
);
1272 /* 64 bit store scaled or unscaled zero-
1273 or sign-extended 32-bit register offset. */
1275 str_scale_ext (sim_cpu
*cpu
, Scaling scaling
, Extension extension
)
1277 unsigned rm
= INSTR (20, 16);
1278 unsigned rn
= INSTR (9, 5);
1279 unsigned rt
= INSTR (4, 0);
1280 /* rn may reference SP, rm and rt must reference ZR */
1282 uint64_t address
= aarch64_get_reg_u64 (cpu
, rn
, SP_OK
);
1283 int64_t extended
= extend (aarch64_get_reg_u32 (cpu
, rm
, NO_SP
),
1285 uint64_t displacement
= OPT_SCALE (extended
, 64, scaling
);
1287 aarch64_set_mem_u64 (cpu
, address
+ displacement
,
1288 aarch64_get_reg_u64 (cpu
, rt
, NO_SP
));
1291 /* 32 bit store byte scaled unsigned 12 bit. */
1293 strb_abs (sim_cpu
*cpu
, uint32_t offset
)
1295 unsigned rn
= INSTR (9, 5);
1296 unsigned rt
= INSTR (4, 0);
1298 /* The target register may not be SP but the source may be.
1299 There is no scaling required for a byte load. */
1300 aarch64_set_mem_u8 (cpu
,
1301 aarch64_get_reg_u64 (cpu
, rn
, SP_OK
) + offset
,
1302 aarch64_get_reg_u8 (cpu
, rt
, NO_SP
));
1305 /* 32 bit store byte unscaled signed 9 bit with pre- or post-writeback. */
1307 strb_wb (sim_cpu
*cpu
, int32_t offset
, WriteBack wb
)
1309 unsigned rn
= INSTR (9, 5);
1310 unsigned rt
= INSTR (4, 0);
1313 if (rn
== rt
&& wb
!= NoWriteBack
)
1316 address
= aarch64_get_reg_u64 (cpu
, rn
, SP_OK
);
1321 aarch64_set_mem_u8 (cpu
, address
, aarch64_get_reg_u8 (cpu
, rt
, NO_SP
));
1326 if (wb
!= NoWriteBack
)
1327 aarch64_set_reg_u64 (cpu
, rn
, SP_OK
, address
);
1330 /* 32 bit store byte scaled or unscaled zero-
1331 or sign-extended 32-bit register offset. */
1333 strb_scale_ext (sim_cpu
*cpu
, Scaling scaling
, Extension extension
)
1335 unsigned rm
= INSTR (20, 16);
1336 unsigned rn
= INSTR (9, 5);
1337 unsigned rt
= INSTR (4, 0);
1338 /* rn may reference SP, rm and rt must reference ZR */
1340 uint64_t address
= aarch64_get_reg_u64 (cpu
, rn
, SP_OK
);
1341 int64_t displacement
= extend (aarch64_get_reg_u32 (cpu
, rm
, NO_SP
),
1344 /* There is no scaling required for a byte load. */
1345 aarch64_set_mem_u8 (cpu
, address
+ displacement
,
1346 aarch64_get_reg_u8 (cpu
, rt
, NO_SP
));
1349 /* 32 bit store short scaled unsigned 12 bit. */
1351 strh_abs (sim_cpu
*cpu
, uint32_t offset
)
1353 unsigned rn
= INSTR (9, 5);
1354 unsigned rt
= INSTR (4, 0);
1356 /* The target register may not be SP but the source may be. */
1357 aarch64_set_mem_u16 (cpu
, aarch64_get_reg_u64 (cpu
, rn
, SP_OK
)
1358 + SCALE (offset
, 16),
1359 aarch64_get_reg_u16 (cpu
, rt
, NO_SP
));
1362 /* 32 bit store short unscaled signed 9 bit with pre- or post-writeback. */
1364 strh_wb (sim_cpu
*cpu
, int32_t offset
, WriteBack wb
)
1366 unsigned rn
= INSTR (9, 5);
1367 unsigned rt
= INSTR (4, 0);
1370 if (rn
== rt
&& wb
!= NoWriteBack
)
1373 address
= aarch64_get_reg_u64 (cpu
, rn
, SP_OK
);
1378 aarch64_set_mem_u16 (cpu
, address
, aarch64_get_reg_u16 (cpu
, rt
, NO_SP
));
1383 if (wb
!= NoWriteBack
)
1384 aarch64_set_reg_u64 (cpu
, rn
, SP_OK
, address
);
1387 /* 32 bit store short scaled or unscaled zero-
1388 or sign-extended 32-bit register offset. */
1390 strh_scale_ext (sim_cpu
*cpu
, Scaling scaling
, Extension extension
)
1392 unsigned rm
= INSTR (20, 16);
1393 unsigned rn
= INSTR (9, 5);
1394 unsigned rt
= INSTR (4, 0);
1395 /* rn may reference SP, rm and rt must reference ZR */
1397 uint64_t address
= aarch64_get_reg_u64 (cpu
, rn
, SP_OK
);
1398 int64_t extended
= extend (aarch64_get_reg_u32 (cpu
, rm
, NO_SP
), extension
);
1399 uint64_t displacement
= OPT_SCALE (extended
, 16, scaling
);
1401 aarch64_set_mem_u16 (cpu
, address
+ displacement
,
1402 aarch64_get_reg_u16 (cpu
, rt
, NO_SP
));
1405 /* Prefetch unsigned 12 bit. */
1407 prfm_abs (sim_cpu
*cpu
, uint32_t offset
)
1409 /* instr[4,0] = prfop : 00000 ==> PLDL1KEEP, 00001 ==> PLDL1STRM,
1410 00010 ==> PLDL2KEEP, 00001 ==> PLDL2STRM,
1411 00100 ==> PLDL3KEEP, 00101 ==> PLDL3STRM,
1412 10000 ==> PSTL1KEEP, 10001 ==> PSTL1STRM,
1413 10010 ==> PSTL2KEEP, 10001 ==> PSTL2STRM,
1414 10100 ==> PSTL3KEEP, 10101 ==> PSTL3STRM,
1416 PrfOp prfop = prfop (instr, 4, 0);
1417 uint64_t address = aarch64_get_reg_u64 (cpu, rn, SP_OK)
1418 + SCALE (offset, 64). */
1420 /* TODO : implement prefetch of address. */
1423 /* Prefetch scaled or unscaled zero- or sign-extended 32-bit register offset. */
1425 prfm_scale_ext (sim_cpu
*cpu
, Scaling scaling
, Extension extension
)
1427 /* instr[4,0] = prfop : 00000 ==> PLDL1KEEP, 00001 ==> PLDL1STRM,
1428 00010 ==> PLDL2KEEP, 00001 ==> PLDL2STRM,
1429 00100 ==> PLDL3KEEP, 00101 ==> PLDL3STRM,
1430 10000 ==> PSTL1KEEP, 10001 ==> PSTL1STRM,
1431 10010 ==> PSTL2KEEP, 10001 ==> PSTL2STRM,
1432 10100 ==> PSTL3KEEP, 10101 ==> PSTL3STRM,
1434 rn may reference SP, rm may only reference ZR
1435 PrfOp prfop = prfop (instr, 4, 0);
1436 uint64_t base = aarch64_get_reg_u64 (cpu, rn, SP_OK);
1437 int64_t extended = extend (aarch64_get_reg_u32 (cpu, rm, NO_SP),
1439 uint64_t displacement = OPT_SCALE (extended, 64, scaling);
1440 uint64_t address = base + displacement. */
1442 /* TODO : implement prefetch of address */
1445 /* 64 bit pc-relative prefetch. */
1447 prfm_pcrel (sim_cpu
*cpu
, int32_t offset
)
1449 /* instr[4,0] = prfop : 00000 ==> PLDL1KEEP, 00001 ==> PLDL1STRM,
1450 00010 ==> PLDL2KEEP, 00001 ==> PLDL2STRM,
1451 00100 ==> PLDL3KEEP, 00101 ==> PLDL3STRM,
1452 10000 ==> PSTL1KEEP, 10001 ==> PSTL1STRM,
1453 10010 ==> PSTL2KEEP, 10001 ==> PSTL2STRM,
1454 10100 ==> PSTL3KEEP, 10101 ==> PSTL3STRM,
1456 PrfOp prfop = prfop (instr, 4, 0);
1457 uint64_t address = aarch64_get_PC (cpu) + offset. */
1459 /* TODO : implement this */
1462 /* Load-store exclusive. */
1467 unsigned rn
= INSTR (9, 5);
1468 unsigned rt
= INSTR (4, 0);
1469 uint64_t address
= aarch64_get_reg_u64 (cpu
, rn
, SP_OK
);
1470 int size
= INSTR (31, 30);
1471 /* int ordered = INSTR (15, 15); */
1472 /* int exclusive = ! INSTR (23, 23); */
1477 aarch64_set_reg_u64 (cpu
, rt
, NO_SP
, aarch64_get_mem_u8 (cpu
, address
));
1480 aarch64_set_reg_u64 (cpu
, rt
, NO_SP
, aarch64_get_mem_u16 (cpu
, address
));
1483 aarch64_set_reg_u64 (cpu
, rt
, NO_SP
, aarch64_get_mem_u32 (cpu
, address
));
1486 aarch64_set_reg_u64 (cpu
, rt
, NO_SP
, aarch64_get_mem_u64 (cpu
, address
));
1494 unsigned rn
= INSTR (9, 5);
1495 unsigned rt
= INSTR (4, 0);
1496 unsigned rs
= INSTR (20, 16);
1497 uint64_t address
= aarch64_get_reg_u64 (cpu
, rn
, SP_OK
);
1498 int size
= INSTR (31, 30);
1499 uint64_t data
= aarch64_get_reg_u64 (cpu
, rt
, NO_SP
);
1503 case 0: aarch64_set_mem_u8 (cpu
, address
, data
); break;
1504 case 1: aarch64_set_mem_u16 (cpu
, address
, data
); break;
1505 case 2: aarch64_set_mem_u32 (cpu
, address
, data
); break;
1506 case 3: aarch64_set_mem_u64 (cpu
, address
, data
); break;
1509 aarch64_set_reg_u64 (cpu
, rs
, NO_SP
, 0); /* Always exclusive... */
1513 dexLoadLiteral (sim_cpu
*cpu
)
1515 /* instr[29,27] == 011
1517 instr[31,30:26] = opc: 000 ==> LDRW, 001 ==> FLDRS
1518 010 ==> LDRX, 011 ==> FLDRD
1519 100 ==> LDRSW, 101 ==> FLDRQ
1520 110 ==> PRFM, 111 ==> UNALLOC
1521 instr[26] ==> V : 0 ==> GReg, 1 ==> FReg
1522 instr[23, 5] == simm19 */
1524 /* unsigned rt = INSTR (4, 0); */
1525 uint32_t dispatch
= (INSTR (31, 30) << 1) | INSTR (26, 26);
1526 int32_t imm
= simm32 (aarch64_get_instr (cpu
), 23, 5);
1530 case 0: ldr32_pcrel (cpu
, imm
); break;
1531 case 1: fldrs_pcrel (cpu
, imm
); break;
1532 case 2: ldr_pcrel (cpu
, imm
); break;
1533 case 3: fldrd_pcrel (cpu
, imm
); break;
1534 case 4: ldrsw_pcrel (cpu
, imm
); break;
1535 case 5: fldrq_pcrel (cpu
, imm
); break;
1536 case 6: prfm_pcrel (cpu
, imm
); break;
1543 /* Immediate arithmetic
1544 The aimm argument is a 12 bit unsigned value or a 12 bit unsigned
1545 value left shifted by 12 bits (done at decode).
1547 N.B. the register args (dest, source) can normally be Xn or SP.
1548 the exception occurs for flag setting instructions which may
1549 only use Xn for the output (dest). */
1551 /* 32 bit add immediate. */
1553 add32 (sim_cpu
*cpu
, uint32_t aimm
)
1555 unsigned rn
= INSTR (9, 5);
1556 unsigned rd
= INSTR (4, 0);
1558 aarch64_set_reg_u64 (cpu
, rd
, SP_OK
,
1559 aarch64_get_reg_u32 (cpu
, rn
, SP_OK
) + aimm
);
1562 /* 64 bit add immediate. */
1564 add64 (sim_cpu
*cpu
, uint32_t aimm
)
1566 unsigned rn
= INSTR (9, 5);
1567 unsigned rd
= INSTR (4, 0);
1569 aarch64_set_reg_u64 (cpu
, rd
, SP_OK
,
1570 aarch64_get_reg_u64 (cpu
, rn
, SP_OK
) + aimm
);
1574 set_flags_for_add32 (sim_cpu
*cpu
, int32_t value1
, int32_t value2
)
1576 int32_t result
= value1
+ value2
;
1577 int64_t sresult
= (int64_t) value1
+ (int64_t) value2
;
1578 uint64_t uresult
= (uint64_t)(uint32_t) value1
1579 + (uint64_t)(uint32_t) value2
;
1585 if (result
& (1 << 31))
1588 if (uresult
!= result
)
1591 if (sresult
!= result
)
1594 aarch64_set_CPSR (cpu
, flags
);
1598 set_flags_for_add64 (sim_cpu
*cpu
, uint64_t value1
, uint64_t value2
)
1600 int64_t sval1
= value1
;
1601 int64_t sval2
= value2
;
1602 uint64_t result
= value1
+ value2
;
1603 int64_t sresult
= sval1
+ sval2
;
1609 if (result
& (1ULL << 63))
1616 /* Negative plus a negative. Overflow happens if
1617 the result is greater than either of the operands. */
1618 if (sresult
> sval1
|| sresult
> sval2
)
1621 /* else Negative plus a positive. Overflow cannot happen. */
1623 else /* value1 is +ve. */
1627 /* Overflow can only occur if we computed "0 - MININT". */
1628 if (sval1
== 0 && sval2
== (1LL << 63))
1633 /* Postive plus positive - overflow has happened if the
1634 result is smaller than either of the operands. */
1635 if (result
< value1
|| result
< value2
)
1640 aarch64_set_CPSR (cpu
, flags
);
1643 #define NEG(a) (((a) & signbit) == signbit)
1644 #define POS(a) (((a) & signbit) == 0)
1647 set_flags_for_sub32 (sim_cpu
*cpu
, uint32_t value1
, uint32_t value2
)
1649 uint32_t result
= value1
- value2
;
1651 uint32_t signbit
= 1U << 31;
1659 if ( (NEG (value1
) && POS (value2
))
1660 || (NEG (value1
) && POS (result
))
1661 || (POS (value2
) && POS (result
)))
1664 if ( (NEG (value1
) && POS (value2
) && POS (result
))
1665 || (POS (value1
) && NEG (value2
) && NEG (result
)))
1668 aarch64_set_CPSR (cpu
, flags
);
1672 set_flags_for_sub64 (sim_cpu
*cpu
, uint64_t value1
, uint64_t value2
)
1674 uint64_t result
= value1
- value2
;
1676 uint64_t signbit
= 1ULL << 63;
1684 if ( (NEG (value1
) && POS (value2
))
1685 || (NEG (value1
) && POS (result
))
1686 || (POS (value2
) && POS (result
)))
1689 if ( (NEG (value1
) && POS (value2
) && POS (result
))
1690 || (POS (value1
) && NEG (value2
) && NEG (result
)))
1693 aarch64_set_CPSR (cpu
, flags
);
1697 set_flags_for_binop32 (sim_cpu
*cpu
, uint32_t result
)
1706 if (result
& (1 << 31))
1711 aarch64_set_CPSR (cpu
, flags
);
1715 set_flags_for_binop64 (sim_cpu
*cpu
, uint64_t result
)
1724 if (result
& (1ULL << 63))
1729 aarch64_set_CPSR (cpu
, flags
);
1732 /* 32 bit add immediate set flags. */
1734 adds32 (sim_cpu
*cpu
, uint32_t aimm
)
1736 unsigned rn
= INSTR (9, 5);
1737 unsigned rd
= INSTR (4, 0);
1738 /* TODO : do we need to worry about signs here? */
1739 int32_t value1
= aarch64_get_reg_s32 (cpu
, rn
, SP_OK
);
1741 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, value1
+ aimm
);
1742 set_flags_for_add32 (cpu
, value1
, aimm
);
1745 /* 64 bit add immediate set flags. */
1747 adds64 (sim_cpu
*cpu
, uint32_t aimm
)
1749 unsigned rn
= INSTR (9, 5);
1750 unsigned rd
= INSTR (4, 0);
1751 uint64_t value1
= aarch64_get_reg_u64 (cpu
, rn
, SP_OK
);
1752 uint64_t value2
= aimm
;
1754 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, value1
+ value2
);
1755 set_flags_for_add64 (cpu
, value1
, value2
);
1758 /* 32 bit sub immediate. */
1760 sub32 (sim_cpu
*cpu
, uint32_t aimm
)
1762 unsigned rn
= INSTR (9, 5);
1763 unsigned rd
= INSTR (4, 0);
1765 aarch64_set_reg_u64 (cpu
, rd
, SP_OK
,
1766 aarch64_get_reg_u32 (cpu
, rn
, SP_OK
) - aimm
);
1769 /* 64 bit sub immediate. */
1771 sub64 (sim_cpu
*cpu
, uint32_t aimm
)
1773 unsigned rn
= INSTR (9, 5);
1774 unsigned rd
= INSTR (4, 0);
1776 aarch64_set_reg_u64 (cpu
, rd
, SP_OK
,
1777 aarch64_get_reg_u64 (cpu
, rn
, SP_OK
) - aimm
);
1780 /* 32 bit sub immediate set flags. */
1782 subs32 (sim_cpu
*cpu
, uint32_t aimm
)
1784 unsigned rn
= INSTR (9, 5);
1785 unsigned rd
= INSTR (4, 0);
1786 uint32_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_sub32 (cpu
, value1
, value2
);
1793 /* 64 bit sub immediate set flags. */
1795 subs64 (sim_cpu
*cpu
, uint32_t aimm
)
1797 unsigned rn
= INSTR (9, 5);
1798 unsigned rd
= INSTR (4, 0);
1799 uint64_t value1
= aarch64_get_reg_u64 (cpu
, rn
, SP_OK
);
1800 uint32_t value2
= aimm
;
1802 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, value1
- value2
);
1803 set_flags_for_sub64 (cpu
, value1
, value2
);
1806 /* Data Processing Register. */
1808 /* First two helpers to perform the shift operations. */
1810 static inline uint32_t
1811 shifted32 (uint32_t value
, Shift shift
, uint32_t count
)
1817 return (value
<< count
);
1819 return (value
>> count
);
1822 int32_t svalue
= value
;
1823 return (svalue
>> count
);
1827 uint32_t top
= value
>> count
;
1828 uint32_t bottom
= value
<< (32 - count
);
1829 return (bottom
| top
);
1834 static inline uint64_t
1835 shifted64 (uint64_t value
, Shift shift
, uint32_t count
)
1841 return (value
<< count
);
1843 return (value
>> count
);
1846 int64_t svalue
= value
;
1847 return (svalue
>> count
);
1851 uint64_t top
= value
>> count
;
1852 uint64_t bottom
= value
<< (64 - count
);
1853 return (bottom
| top
);
1858 /* Arithmetic shifted register.
1859 These allow an optional LSL, ASR or LSR to the second source
1860 register with a count up to the register bit count.
1862 N.B register args may not be SP. */
1864 /* 32 bit ADD shifted register. */
1866 add32_shift (sim_cpu
*cpu
, Shift shift
, uint32_t count
)
1868 unsigned rm
= INSTR (20, 16);
1869 unsigned rn
= INSTR (9, 5);
1870 unsigned rd
= INSTR (4, 0);
1872 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
,
1873 aarch64_get_reg_u32 (cpu
, rn
, NO_SP
)
1874 + shifted32 (aarch64_get_reg_u32 (cpu
, rm
, NO_SP
),
1878 /* 64 bit ADD shifted register. */
1880 add64_shift (sim_cpu
*cpu
, Shift shift
, uint32_t count
)
1882 unsigned rm
= INSTR (20, 16);
1883 unsigned rn
= INSTR (9, 5);
1884 unsigned rd
= INSTR (4, 0);
1886 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
,
1887 aarch64_get_reg_u64 (cpu
, rn
, NO_SP
)
1888 + shifted64 (aarch64_get_reg_u64 (cpu
, rm
, NO_SP
),
1892 /* 32 bit ADD shifted register setting flags. */
1894 adds32_shift (sim_cpu
*cpu
, Shift shift
, uint32_t count
)
1896 unsigned rm
= INSTR (20, 16);
1897 unsigned rn
= INSTR (9, 5);
1898 unsigned rd
= INSTR (4, 0);
1900 uint32_t value1
= aarch64_get_reg_u32 (cpu
, rn
, NO_SP
);
1901 uint32_t value2
= shifted32 (aarch64_get_reg_u32 (cpu
, rm
, NO_SP
),
1904 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, value1
+ value2
);
1905 set_flags_for_add32 (cpu
, value1
, value2
);
1908 /* 64 bit ADD shifted register setting flags. */
1910 adds64_shift (sim_cpu
*cpu
, Shift shift
, uint32_t count
)
1912 unsigned rm
= INSTR (20, 16);
1913 unsigned rn
= INSTR (9, 5);
1914 unsigned rd
= INSTR (4, 0);
1916 uint64_t value1
= aarch64_get_reg_u64 (cpu
, rn
, NO_SP
);
1917 uint64_t value2
= shifted64 (aarch64_get_reg_u64 (cpu
, rm
, NO_SP
),
1920 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, value1
+ value2
);
1921 set_flags_for_add64 (cpu
, value1
, value2
);
1924 /* 32 bit SUB shifted register. */
1926 sub32_shift (sim_cpu
*cpu
, Shift shift
, uint32_t count
)
1928 unsigned rm
= INSTR (20, 16);
1929 unsigned rn
= INSTR (9, 5);
1930 unsigned rd
= INSTR (4, 0);
1932 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
,
1933 aarch64_get_reg_u32 (cpu
, rn
, NO_SP
)
1934 - shifted32 (aarch64_get_reg_u32 (cpu
, rm
, NO_SP
),
1938 /* 64 bit SUB shifted register. */
1940 sub64_shift (sim_cpu
*cpu
, Shift shift
, uint32_t count
)
1942 unsigned rm
= INSTR (20, 16);
1943 unsigned rn
= INSTR (9, 5);
1944 unsigned rd
= INSTR (4, 0);
1946 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
,
1947 aarch64_get_reg_u64 (cpu
, rn
, NO_SP
)
1948 - shifted64 (aarch64_get_reg_u64 (cpu
, rm
, NO_SP
),
1952 /* 32 bit SUB shifted register setting flags. */
1954 subs32_shift (sim_cpu
*cpu
, Shift shift
, uint32_t count
)
1956 unsigned rm
= INSTR (20, 16);
1957 unsigned rn
= INSTR (9, 5);
1958 unsigned rd
= INSTR (4, 0);
1960 uint32_t value1
= aarch64_get_reg_u32 (cpu
, rn
, NO_SP
);
1961 uint32_t value2
= shifted32 (aarch64_get_reg_u32 (cpu
, rm
, NO_SP
),
1964 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, value1
- value2
);
1965 set_flags_for_sub32 (cpu
, value1
, value2
);
1968 /* 64 bit SUB shifted register setting flags. */
1970 subs64_shift (sim_cpu
*cpu
, Shift shift
, uint32_t count
)
1972 unsigned rm
= INSTR (20, 16);
1973 unsigned rn
= INSTR (9, 5);
1974 unsigned rd
= INSTR (4, 0);
1976 uint64_t value1
= aarch64_get_reg_u64 (cpu
, rn
, NO_SP
);
1977 uint64_t value2
= shifted64 (aarch64_get_reg_u64 (cpu
, rm
, NO_SP
),
1980 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, value1
- value2
);
1981 set_flags_for_sub64 (cpu
, value1
, value2
);
1984 /* First a couple more helpers to fetch the
1985 relevant source register element either
1986 sign or zero extended as required by the
1990 extreg32 (sim_cpu
*cpu
, unsigned int lo
, Extension extension
)
1994 case UXTB
: return aarch64_get_reg_u8 (cpu
, lo
, NO_SP
);
1995 case UXTH
: return aarch64_get_reg_u16 (cpu
, lo
, NO_SP
);
1996 case UXTW
: /* Fall through. */
1997 case UXTX
: return aarch64_get_reg_u32 (cpu
, lo
, NO_SP
);
1998 case SXTB
: return aarch64_get_reg_s8 (cpu
, lo
, NO_SP
);
1999 case SXTH
: return aarch64_get_reg_s16 (cpu
, lo
, NO_SP
);
2000 case SXTW
: /* Fall through. */
2001 case SXTX
: /* Fall through. */
2002 default: return aarch64_get_reg_s32 (cpu
, lo
, NO_SP
);
2007 extreg64 (sim_cpu
*cpu
, unsigned int lo
, Extension extension
)
2011 case UXTB
: return aarch64_get_reg_u8 (cpu
, lo
, NO_SP
);
2012 case UXTH
: return aarch64_get_reg_u16 (cpu
, lo
, NO_SP
);
2013 case UXTW
: return aarch64_get_reg_u32 (cpu
, lo
, NO_SP
);
2014 case UXTX
: return aarch64_get_reg_u64 (cpu
, lo
, NO_SP
);
2015 case SXTB
: return aarch64_get_reg_s8 (cpu
, lo
, NO_SP
);
2016 case SXTH
: return aarch64_get_reg_s16 (cpu
, lo
, NO_SP
);
2017 case SXTW
: return aarch64_get_reg_s32 (cpu
, lo
, NO_SP
);
2019 default: return aarch64_get_reg_s64 (cpu
, lo
, NO_SP
);
2023 /* Arithmetic extending register
2024 These allow an optional sign extension of some portion of the
2025 second source register followed by an optional left shift of
2026 between 1 and 4 bits (i.e. a shift of 0-4 bits???)
2028 N.B output (dest) and first input arg (source) may normally be Xn
2029 or SP. However, for flag setting operations dest can only be
2030 Xn. Second input registers are always Xn. */
2032 /* 32 bit ADD extending register. */
2034 add32_ext (sim_cpu
*cpu
, Extension extension
, uint32_t shift
)
2036 unsigned rm
= INSTR (20, 16);
2037 unsigned rn
= INSTR (9, 5);
2038 unsigned rd
= INSTR (4, 0);
2040 aarch64_set_reg_u64 (cpu
, rd
, SP_OK
,
2041 aarch64_get_reg_u32 (cpu
, rn
, SP_OK
)
2042 + (extreg32 (cpu
, rm
, extension
) << shift
));
2045 /* 64 bit ADD extending register.
2046 N.B. This subsumes the case with 64 bit source2 and UXTX #n or LSL #0. */
2048 add64_ext (sim_cpu
*cpu
, Extension extension
, uint32_t shift
)
2050 unsigned rm
= INSTR (20, 16);
2051 unsigned rn
= INSTR (9, 5);
2052 unsigned rd
= INSTR (4, 0);
2054 aarch64_set_reg_u64 (cpu
, rd
, SP_OK
,
2055 aarch64_get_reg_u64 (cpu
, rn
, SP_OK
)
2056 + (extreg64 (cpu
, rm
, extension
) << shift
));
2059 /* 32 bit ADD extending register setting flags. */
2061 adds32_ext (sim_cpu
*cpu
, Extension extension
, uint32_t shift
)
2063 unsigned rm
= INSTR (20, 16);
2064 unsigned rn
= INSTR (9, 5);
2065 unsigned rd
= INSTR (4, 0);
2067 uint32_t value1
= aarch64_get_reg_u32 (cpu
, rn
, SP_OK
);
2068 uint32_t value2
= extreg32 (cpu
, rm
, extension
) << shift
;
2070 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, value1
+ value2
);
2071 set_flags_for_add32 (cpu
, value1
, value2
);
2074 /* 64 bit ADD extending register setting flags */
2075 /* N.B. this subsumes the case with 64 bit source2 and UXTX #n or LSL #0 */
2077 adds64_ext (sim_cpu
*cpu
, Extension extension
, uint32_t shift
)
2079 unsigned rm
= INSTR (20, 16);
2080 unsigned rn
= INSTR (9, 5);
2081 unsigned rd
= INSTR (4, 0);
2083 uint64_t value1
= aarch64_get_reg_u64 (cpu
, rn
, SP_OK
);
2084 uint64_t value2
= extreg64 (cpu
, rm
, extension
) << shift
;
2086 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, value1
+ value2
);
2087 set_flags_for_add64 (cpu
, value1
, value2
);
2090 /* 32 bit SUB extending register. */
2092 sub32_ext (sim_cpu
*cpu
, Extension extension
, uint32_t shift
)
2094 unsigned rm
= INSTR (20, 16);
2095 unsigned rn
= INSTR (9, 5);
2096 unsigned rd
= INSTR (4, 0);
2098 aarch64_set_reg_u64 (cpu
, rd
, SP_OK
,
2099 aarch64_get_reg_u32 (cpu
, rn
, SP_OK
)
2100 - (extreg32 (cpu
, rm
, extension
) << shift
));
2103 /* 64 bit SUB extending register. */
2104 /* N.B. this subsumes the case with 64 bit source2 and UXTX #n or LSL #0. */
2106 sub64_ext (sim_cpu
*cpu
, Extension extension
, uint32_t shift
)
2108 unsigned rm
= INSTR (20, 16);
2109 unsigned rn
= INSTR (9, 5);
2110 unsigned rd
= INSTR (4, 0);
2112 aarch64_set_reg_u64 (cpu
, rd
, SP_OK
,
2113 aarch64_get_reg_u64 (cpu
, rn
, SP_OK
)
2114 - (extreg64 (cpu
, rm
, extension
) << shift
));
2117 /* 32 bit SUB extending register setting flags. */
2119 subs32_ext (sim_cpu
*cpu
, Extension extension
, uint32_t shift
)
2121 unsigned rm
= INSTR (20, 16);
2122 unsigned rn
= INSTR (9, 5);
2123 unsigned rd
= INSTR (4, 0);
2125 uint32_t value1
= aarch64_get_reg_u32 (cpu
, rn
, SP_OK
);
2126 uint32_t value2
= extreg32 (cpu
, rm
, extension
) << shift
;
2128 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, value1
- value2
);
2129 set_flags_for_sub32 (cpu
, value1
, value2
);
2132 /* 64 bit SUB extending register setting flags */
2133 /* N.B. this subsumes the case with 64 bit source2 and UXTX #n or LSL #0 */
2135 subs64_ext (sim_cpu
*cpu
, Extension extension
, uint32_t shift
)
2137 unsigned rm
= INSTR (20, 16);
2138 unsigned rn
= INSTR (9, 5);
2139 unsigned rd
= INSTR (4, 0);
2141 uint64_t value1
= aarch64_get_reg_u64 (cpu
, rn
, SP_OK
);
2142 uint64_t value2
= extreg64 (cpu
, rm
, extension
) << shift
;
2144 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, value1
- value2
);
2145 set_flags_for_sub64 (cpu
, value1
, value2
);
2149 dexAddSubtractImmediate (sim_cpu
*cpu
)
2151 /* instr[31] = size : 0 ==> 32 bit, 1 ==> 64 bit
2152 instr[30] = op : 0 ==> ADD, 1 ==> SUB
2153 instr[29] = set : 0 ==> no flags, 1 ==> set flags
2154 instr[28,24] = 10001
2155 instr[23,22] = shift : 00 == LSL#0, 01 = LSL#12 1x = UNALLOC
2156 instr[21,10] = uimm12
2160 /* N.B. the shift is applied at decode before calling the add/sub routine. */
2161 uint32_t shift
= INSTR (23, 22);
2162 uint32_t imm
= INSTR (21, 10);
2163 uint32_t dispatch
= INSTR (31, 29);
2165 NYI_assert (28, 24, 0x11);
2175 case 0: add32 (cpu
, imm
); break;
2176 case 1: adds32 (cpu
, imm
); break;
2177 case 2: sub32 (cpu
, imm
); break;
2178 case 3: subs32 (cpu
, imm
); break;
2179 case 4: add64 (cpu
, imm
); break;
2180 case 5: adds64 (cpu
, imm
); break;
2181 case 6: sub64 (cpu
, imm
); break;
2182 case 7: subs64 (cpu
, imm
); break;
2187 dexAddSubtractShiftedRegister (sim_cpu
*cpu
)
2189 /* instr[31] = size : 0 ==> 32 bit, 1 ==> 64 bit
2190 instr[30,29] = op : 00 ==> ADD, 01 ==> ADDS, 10 ==> SUB, 11 ==> SUBS
2191 instr[28,24] = 01011
2192 instr[23,22] = shift : 0 ==> LSL, 1 ==> LSR, 2 ==> ASR, 3 ==> UNALLOC
2195 instr[15,10] = count : must be 0xxxxx for 32 bit
2199 uint32_t size
= INSTR (31, 31);
2200 uint32_t count
= INSTR (15, 10);
2201 Shift shiftType
= INSTR (23, 22);
2203 NYI_assert (28, 24, 0x0B);
2204 NYI_assert (21, 21, 0);
2206 /* Shift encoded as ROR is unallocated. */
2207 if (shiftType
== ROR
)
2210 /* 32 bit operations must have count[5] = 0
2211 or else we have an UNALLOC. */
2212 if (size
== 0 && uimm (count
, 5, 5))
2215 /* Dispatch on size:op i.e instr [31,29]. */
2216 switch (INSTR (31, 29))
2218 case 0: add32_shift (cpu
, shiftType
, count
); break;
2219 case 1: adds32_shift (cpu
, shiftType
, count
); break;
2220 case 2: sub32_shift (cpu
, shiftType
, count
); break;
2221 case 3: subs32_shift (cpu
, shiftType
, count
); break;
2222 case 4: add64_shift (cpu
, shiftType
, count
); break;
2223 case 5: adds64_shift (cpu
, shiftType
, count
); break;
2224 case 6: sub64_shift (cpu
, shiftType
, count
); break;
2225 case 7: subs64_shift (cpu
, shiftType
, count
); break;
2230 dexAddSubtractExtendedRegister (sim_cpu
*cpu
)
2232 /* instr[31] = size : 0 ==> 32 bit, 1 ==> 64 bit
2233 instr[30] = op : 0 ==> ADD, 1 ==> SUB
2234 instr[29] = set? : 0 ==> no flags, 1 ==> set flags
2235 instr[28,24] = 01011
2236 instr[23,22] = opt : 0 ==> ok, 1,2,3 ==> UNALLOC
2239 instr[15,13] = option : 000 ==> UXTB, 001 ==> UXTH,
2240 000 ==> LSL|UXTW, 001 ==> UXTZ,
2241 000 ==> SXTB, 001 ==> SXTH,
2242 000 ==> SXTW, 001 ==> SXTX,
2243 instr[12,10] = shift : 0,1,2,3,4 ==> ok, 5,6,7 ==> UNALLOC
2247 Extension extensionType
= INSTR (15, 13);
2248 uint32_t shift
= INSTR (12, 10);
2250 NYI_assert (28, 24, 0x0B);
2251 NYI_assert (21, 21, 1);
2253 /* Shift may not exceed 4. */
2257 /* Dispatch on size:op:set?. */
2258 switch (INSTR (31, 29))
2260 case 0: add32_ext (cpu
, extensionType
, shift
); break;
2261 case 1: adds32_ext (cpu
, extensionType
, shift
); break;
2262 case 2: sub32_ext (cpu
, extensionType
, shift
); break;
2263 case 3: subs32_ext (cpu
, extensionType
, shift
); break;
2264 case 4: add64_ext (cpu
, extensionType
, shift
); break;
2265 case 5: adds64_ext (cpu
, extensionType
, shift
); break;
2266 case 6: sub64_ext (cpu
, extensionType
, shift
); break;
2267 case 7: subs64_ext (cpu
, extensionType
, shift
); break;
2271 /* Conditional data processing
2272 Condition register is implicit 3rd source. */
2274 /* 32 bit add with carry. */
2275 /* N.B register args may not be SP. */
2278 adc32 (sim_cpu
*cpu
)
2280 unsigned rm
= INSTR (20, 16);
2281 unsigned rn
= INSTR (9, 5);
2282 unsigned rd
= INSTR (4, 0);
2284 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
,
2285 aarch64_get_reg_u32 (cpu
, rn
, NO_SP
)
2286 + aarch64_get_reg_u32 (cpu
, rm
, NO_SP
)
2290 /* 64 bit add with carry */
2292 adc64 (sim_cpu
*cpu
)
2294 unsigned rm
= INSTR (20, 16);
2295 unsigned rn
= INSTR (9, 5);
2296 unsigned rd
= INSTR (4, 0);
2298 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
,
2299 aarch64_get_reg_u64 (cpu
, rn
, NO_SP
)
2300 + aarch64_get_reg_u64 (cpu
, rm
, NO_SP
)
2304 /* 32 bit add with carry setting flags. */
2306 adcs32 (sim_cpu
*cpu
)
2308 unsigned rm
= INSTR (20, 16);
2309 unsigned rn
= INSTR (9, 5);
2310 unsigned rd
= INSTR (4, 0);
2312 uint32_t value1
= aarch64_get_reg_u32 (cpu
, rn
, NO_SP
);
2313 uint32_t value2
= aarch64_get_reg_u32 (cpu
, rm
, NO_SP
);
2314 uint32_t carry
= IS_SET (C
);
2316 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, value1
+ value2
+ carry
);
2317 set_flags_for_add32 (cpu
, value1
, value2
+ carry
);
2320 /* 64 bit add with carry setting flags. */
2322 adcs64 (sim_cpu
*cpu
)
2324 unsigned rm
= INSTR (20, 16);
2325 unsigned rn
= INSTR (9, 5);
2326 unsigned rd
= INSTR (4, 0);
2328 uint64_t value1
= aarch64_get_reg_u64 (cpu
, rn
, NO_SP
);
2329 uint64_t value2
= aarch64_get_reg_u64 (cpu
, rm
, NO_SP
);
2330 uint64_t carry
= IS_SET (C
);
2332 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, value1
+ value2
+ carry
);
2333 set_flags_for_add64 (cpu
, value1
, value2
+ carry
);
2336 /* 32 bit sub with carry. */
2338 sbc32 (sim_cpu
*cpu
)
2340 unsigned rm
= INSTR (20, 16);
2341 unsigned rn
= INSTR (9, 5); /* ngc iff rn == 31. */
2342 unsigned rd
= INSTR (4, 0);
2344 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
,
2345 aarch64_get_reg_u32 (cpu
, rn
, NO_SP
)
2346 - aarch64_get_reg_u32 (cpu
, rm
, NO_SP
)
2350 /* 64 bit sub with carry */
2352 sbc64 (sim_cpu
*cpu
)
2354 unsigned rm
= INSTR (20, 16);
2355 unsigned rn
= INSTR (9, 5);
2356 unsigned rd
= INSTR (4, 0);
2358 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
,
2359 aarch64_get_reg_u64 (cpu
, rn
, NO_SP
)
2360 - aarch64_get_reg_u64 (cpu
, rm
, NO_SP
)
2364 /* 32 bit sub with carry setting flags */
2366 sbcs32 (sim_cpu
*cpu
)
2368 unsigned rm
= INSTR (20, 16);
2369 unsigned rn
= INSTR (9, 5);
2370 unsigned rd
= INSTR (4, 0);
2372 uint32_t value1
= aarch64_get_reg_u32 (cpu
, rn
, NO_SP
);
2373 uint32_t value2
= aarch64_get_reg_u32 (cpu
, rm
, NO_SP
);
2374 uint32_t carry
= IS_SET (C
);
2375 uint32_t result
= value1
- value2
+ 1 - carry
;
2377 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, result
);
2378 set_flags_for_sub32 (cpu
, value1
, value2
+ 1 - carry
);
2381 /* 64 bit sub with carry setting flags */
2383 sbcs64 (sim_cpu
*cpu
)
2385 unsigned rm
= INSTR (20, 16);
2386 unsigned rn
= INSTR (9, 5);
2387 unsigned rd
= INSTR (4, 0);
2389 uint64_t value1
= aarch64_get_reg_u64 (cpu
, rn
, NO_SP
);
2390 uint64_t value2
= aarch64_get_reg_u64 (cpu
, rm
, NO_SP
);
2391 uint64_t carry
= IS_SET (C
);
2392 uint64_t result
= value1
- value2
+ 1 - carry
;
2394 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, result
);
2395 set_flags_for_sub64 (cpu
, value1
, value2
+ 1 - carry
);
2399 dexAddSubtractWithCarry (sim_cpu
*cpu
)
2401 /* instr[31] = size : 0 ==> 32 bit, 1 ==> 64 bit
2402 instr[30] = op : 0 ==> ADC, 1 ==> SBC
2403 instr[29] = set? : 0 ==> no flags, 1 ==> set flags
2404 instr[28,21] = 1 1010 000
2406 instr[15,10] = op2 : 00000 ==> ok, ow ==> UNALLOC
2410 uint32_t op2
= INSTR (15, 10);
2412 NYI_assert (28, 21, 0xD0);
2417 /* Dispatch on size:op:set?. */
2418 switch (INSTR (31, 29))
2420 case 0: adc32 (cpu
); break;
2421 case 1: adcs32 (cpu
); break;
2422 case 2: sbc32 (cpu
); break;
2423 case 3: sbcs32 (cpu
); break;
2424 case 4: adc64 (cpu
); break;
2425 case 5: adcs64 (cpu
); break;
2426 case 6: sbc64 (cpu
); break;
2427 case 7: sbcs64 (cpu
); break;
2432 testConditionCode (sim_cpu
*cpu
, CondCode cc
)
2434 /* This should be reduceable to branchless logic
2435 by some careful testing of bits in CC followed
2436 by the requisite masking and combining of bits
2437 from the flag register.
2439 For now we do it with a switch. */
2444 case EQ
: res
= IS_SET (Z
); break;
2445 case NE
: res
= IS_CLEAR (Z
); break;
2446 case CS
: res
= IS_SET (C
); break;
2447 case CC
: res
= IS_CLEAR (C
); break;
2448 case MI
: res
= IS_SET (N
); break;
2449 case PL
: res
= IS_CLEAR (N
); break;
2450 case VS
: res
= IS_SET (V
); break;
2451 case VC
: res
= IS_CLEAR (V
); break;
2452 case HI
: res
= IS_SET (C
) && IS_CLEAR (Z
); break;
2453 case LS
: res
= IS_CLEAR (C
) || IS_SET (Z
); break;
2454 case GE
: res
= IS_SET (N
) == IS_SET (V
); break;
2455 case LT
: res
= IS_SET (N
) != IS_SET (V
); break;
2456 case GT
: res
= IS_CLEAR (Z
) && (IS_SET (N
) == IS_SET (V
)); break;
2457 case LE
: res
= IS_SET (Z
) || (IS_SET (N
) != IS_SET (V
)); break;
2468 CondCompare (sim_cpu
*cpu
) /* aka: ccmp and ccmn */
2470 /* instr[31] = size : 0 ==> 32 bit, 1 ==> 64 bit
2471 instr[30] = compare with positive (1) or negative value (0)
2472 instr[29,21] = 1 1101 0010
2473 instr[20,16] = Rm or const
2475 instr[11] = compare reg (0) or const (1)
2479 instr[3,0] = value for CPSR bits if the comparison does not take place. */
2484 NYI_assert (29, 21, 0x1d2);
2485 NYI_assert (10, 10, 0);
2486 NYI_assert (4, 4, 0);
2488 if (! testConditionCode (cpu
, INSTR (15, 12)))
2490 aarch64_set_CPSR (cpu
, INSTR (3, 0));
2494 negate
= INSTR (30, 30) ? 1 : -1;
2495 rm
= INSTR (20, 16);
2501 set_flags_for_sub64 (cpu
, aarch64_get_reg_u64 (cpu
, rn
, SP_OK
),
2502 negate
* (uint64_t) rm
);
2504 set_flags_for_sub64 (cpu
, aarch64_get_reg_u64 (cpu
, rn
, SP_OK
),
2505 negate
* aarch64_get_reg_u64 (cpu
, rm
, SP_OK
));
2510 set_flags_for_sub32 (cpu
, aarch64_get_reg_u32 (cpu
, rn
, SP_OK
),
2513 set_flags_for_sub32 (cpu
, aarch64_get_reg_u32 (cpu
, rn
, SP_OK
),
2514 negate
* aarch64_get_reg_u32 (cpu
, rm
, SP_OK
));
2519 do_vec_MOV_whole_vector (sim_cpu
*cpu
)
2521 /* MOV Vd.T, Vs.T (alias for ORR Vd.T, Vn.T, Vm.T where Vn == Vm)
2524 instr[30] = half(0)/full(1)
2525 instr[29,21] = 001110101
2527 instr[15,10] = 000111
2531 unsigned vs
= INSTR (9, 5);
2532 unsigned vd
= INSTR (4, 0);
2534 NYI_assert (29, 21, 0x075);
2535 NYI_assert (15, 10, 0x07);
2537 if (INSTR (20, 16) != vs
)
2541 aarch64_set_vec_u64 (cpu
, vd
, 1, aarch64_get_vec_u64 (cpu
, vs
, 1));
2543 aarch64_set_vec_u64 (cpu
, vd
, 0, aarch64_get_vec_u64 (cpu
, vs
, 0));
2547 do_vec_MOV_into_scalar (sim_cpu
*cpu
)
2550 instr[30] = word(0)/long(1)
2551 instr[29,21] = 00 1110 000
2552 instr[20,18] = element size and index
2553 instr[17,10] = 00 0011 11
2554 instr[9,5] = V source
2555 instr[4,0] = R dest */
2557 unsigned vs
= INSTR (9, 5);
2558 unsigned rd
= INSTR (4, 0);
2560 NYI_assert (29, 21, 0x070);
2561 NYI_assert (17, 10, 0x0F);
2563 switch (INSTR (20, 18))
2566 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, aarch64_get_vec_u64 (cpu
, vs
, 0));
2570 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, aarch64_get_vec_u64 (cpu
, vs
, 1));
2577 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, aarch64_get_vec_u32
2578 (cpu
, vs
, INSTR (20, 19)));
2587 do_vec_INS (sim_cpu
*cpu
)
2589 /* instr[31,21] = 01001110000
2590 instr[20,16] = element size and index
2591 instr[15,10] = 000111
2592 instr[9,5] = W source
2593 instr[4,0] = V dest */
2596 unsigned rs
= INSTR (9, 5);
2597 unsigned vd
= INSTR (4, 0);
2599 NYI_assert (31, 21, 0x270);
2600 NYI_assert (15, 10, 0x07);
2604 index
= INSTR (20, 17);
2605 aarch64_set_vec_u8 (cpu
, vd
, index
,
2606 aarch64_get_reg_u8 (cpu
, rs
, NO_SP
));
2608 else if (INSTR (17, 17))
2610 index
= INSTR (20, 18);
2611 aarch64_set_vec_u16 (cpu
, vd
, index
,
2612 aarch64_get_reg_u16 (cpu
, rs
, NO_SP
));
2614 else if (INSTR (18, 18))
2616 index
= INSTR (20, 19);
2617 aarch64_set_vec_u32 (cpu
, vd
, index
,
2618 aarch64_get_reg_u32 (cpu
, rs
, NO_SP
));
2620 else if (INSTR (19, 19))
2622 index
= INSTR (20, 20);
2623 aarch64_set_vec_u64 (cpu
, vd
, index
,
2624 aarch64_get_reg_u64 (cpu
, rs
, NO_SP
));
2631 do_vec_DUP_vector_into_vector (sim_cpu
*cpu
)
2634 instr[30] = half(0)/full(1)
2635 instr[29,21] = 00 1110 000
2636 instr[20,16] = element size and index
2637 instr[15,10] = 0000 01
2638 instr[9,5] = V source
2639 instr[4,0] = V dest. */
2641 unsigned full
= INSTR (30, 30);
2642 unsigned vs
= INSTR (9, 5);
2643 unsigned vd
= INSTR (4, 0);
2646 NYI_assert (29, 21, 0x070);
2647 NYI_assert (15, 10, 0x01);
2651 index
= INSTR (20, 17);
2653 for (i
= 0; i
< (full
? 16 : 8); i
++)
2654 aarch64_set_vec_u8 (cpu
, vd
, i
, aarch64_get_vec_u8 (cpu
, vs
, index
));
2656 else if (INSTR (17, 17))
2658 index
= INSTR (20, 18);
2660 for (i
= 0; i
< (full
? 8 : 4); i
++)
2661 aarch64_set_vec_u16 (cpu
, vd
, i
, aarch64_get_vec_u16 (cpu
, vs
, index
));
2663 else if (INSTR (18, 18))
2665 index
= INSTR (20, 19);
2667 for (i
= 0; i
< (full
? 4 : 2); i
++)
2668 aarch64_set_vec_u32 (cpu
, vd
, i
, aarch64_get_vec_u32 (cpu
, vs
, index
));
2672 if (INSTR (19, 19) == 0)
2678 index
= INSTR (20, 20);
2680 for (i
= 0; i
< 2; i
++)
2681 aarch64_set_vec_u64 (cpu
, vd
, i
, aarch64_get_vec_u64 (cpu
, vs
, index
));
2686 do_vec_TBL (sim_cpu
*cpu
)
2689 instr[30] = half(0)/full(1)
2690 instr[29,21] = 00 1110 000
2693 instr[14,13] = vec length
2695 instr[9,5] = V start
2696 instr[4,0] = V dest */
2698 int full
= INSTR (30, 30);
2699 int len
= INSTR (14, 13) + 1;
2700 unsigned vm
= INSTR (20, 16);
2701 unsigned vn
= INSTR (9, 5);
2702 unsigned vd
= INSTR (4, 0);
2705 NYI_assert (29, 21, 0x070);
2706 NYI_assert (12, 10, 0);
2708 for (i
= 0; i
< (full
? 16 : 8); i
++)
2710 unsigned int selector
= aarch64_get_vec_u8 (cpu
, vm
, i
);
2714 val
= aarch64_get_vec_u8 (cpu
, vn
, selector
);
2715 else if (selector
< 32)
2716 val
= len
< 2 ? 0 : aarch64_get_vec_u8 (cpu
, vn
+ 1, selector
- 16);
2717 else if (selector
< 48)
2718 val
= len
< 3 ? 0 : aarch64_get_vec_u8 (cpu
, vn
+ 2, selector
- 32);
2719 else if (selector
< 64)
2720 val
= len
< 4 ? 0 : aarch64_get_vec_u8 (cpu
, vn
+ 3, selector
- 48);
2724 aarch64_set_vec_u8 (cpu
, vd
, i
, val
);
2729 do_vec_TRN (sim_cpu
*cpu
)
2732 instr[30] = half(0)/full(1)
2733 instr[29,24] = 00 1110
2738 instr[14] = TRN1 (0) / TRN2 (1)
2740 instr[9,5] = V source
2741 instr[4,0] = V dest. */
2743 int full
= INSTR (30, 30);
2744 int second
= INSTR (14, 14);
2745 unsigned vm
= INSTR (20, 16);
2746 unsigned vn
= INSTR (9, 5);
2747 unsigned vd
= INSTR (4, 0);
2750 NYI_assert (29, 24, 0x0E);
2751 NYI_assert (13, 10, 0xA);
2753 switch (INSTR (23, 22))
2756 for (i
= 0; i
< (full
? 8 : 4); i
++)
2760 aarch64_get_vec_u8 (cpu
, second
? vm
: vn
, i
* 2));
2762 (cpu
, vd
, 1 * 2 + 1,
2763 aarch64_get_vec_u8 (cpu
, second
? vn
: vm
, i
* 2 + 1));
2768 for (i
= 0; i
< (full
? 4 : 2); i
++)
2772 aarch64_get_vec_u16 (cpu
, second
? vm
: vn
, i
* 2));
2774 (cpu
, vd
, 1 * 2 + 1,
2775 aarch64_get_vec_u16 (cpu
, second
? vn
: vm
, i
* 2 + 1));
2781 (cpu
, vd
, 0, aarch64_get_vec_u32 (cpu
, second
? vm
: vn
, 0));
2783 (cpu
, vd
, 1, aarch64_get_vec_u32 (cpu
, second
? vn
: vm
, 1));
2785 (cpu
, vd
, 2, aarch64_get_vec_u32 (cpu
, second
? vm
: vn
, 2));
2787 (cpu
, vd
, 3, aarch64_get_vec_u32 (cpu
, second
? vn
: vm
, 3));
2794 aarch64_set_vec_u64 (cpu
, vd
, 0,
2795 aarch64_get_vec_u64 (cpu
, second
? vm
: vn
, 0));
2796 aarch64_set_vec_u64 (cpu
, vd
, 1,
2797 aarch64_get_vec_u64 (cpu
, second
? vn
: vm
, 1));
2803 do_vec_DUP_scalar_into_vector (sim_cpu
*cpu
)
2806 instr[30] = 0=> zero top 64-bits, 1=> duplicate into top 64-bits
2807 [must be 1 for 64-bit xfer]
2808 instr[29,20] = 00 1110 0000
2809 instr[19,16] = element size: 0001=> 8-bits, 0010=> 16-bits,
2810 0100=> 32-bits. 1000=>64-bits
2811 instr[15,10] = 0000 11
2812 instr[9,5] = W source
2813 instr[4,0] = V dest. */
2816 unsigned Vd
= INSTR (4, 0);
2817 unsigned Rs
= INSTR (9, 5);
2818 int both
= INSTR (30, 30);
2820 NYI_assert (29, 20, 0x0E0);
2821 NYI_assert (15, 10, 0x03);
2823 switch (INSTR (19, 16))
2826 for (i
= 0; i
< (both
? 16 : 8); i
++)
2827 aarch64_set_vec_u8 (cpu
, Vd
, i
, aarch64_get_reg_u8 (cpu
, Rs
, NO_SP
));
2831 for (i
= 0; i
< (both
? 8 : 4); i
++)
2832 aarch64_set_vec_u16 (cpu
, Vd
, i
, aarch64_get_reg_u16 (cpu
, Rs
, NO_SP
));
2836 for (i
= 0; i
< (both
? 4 : 2); i
++)
2837 aarch64_set_vec_u32 (cpu
, Vd
, i
, aarch64_get_reg_u32 (cpu
, Rs
, NO_SP
));
2843 aarch64_set_vec_u64 (cpu
, Vd
, 0, aarch64_get_reg_u64 (cpu
, Rs
, NO_SP
));
2844 aarch64_set_vec_u64 (cpu
, Vd
, 1, aarch64_get_reg_u64 (cpu
, Rs
, NO_SP
));
2853 do_vec_UZP (sim_cpu
*cpu
)
2856 instr[30] = half(0)/full(1)
2857 instr[29,24] = 00 1110
2858 instr[23,22] = size: byte(00), half(01), word (10), long (11)
2862 instr[14] = lower (0) / upper (1)
2867 int full
= INSTR (30, 30);
2868 int upper
= INSTR (14, 14);
2870 unsigned vm
= INSTR (20, 16);
2871 unsigned vn
= INSTR (9, 5);
2872 unsigned vd
= INSTR (4, 0);
2874 uint64_t val_m1
= aarch64_get_vec_u64 (cpu
, vm
, 0);
2875 uint64_t val_m2
= aarch64_get_vec_u64 (cpu
, vm
, 1);
2876 uint64_t val_n1
= aarch64_get_vec_u64 (cpu
, vn
, 0);
2877 uint64_t val_n2
= aarch64_get_vec_u64 (cpu
, vn
, 1);
2882 uint64_t input1
= upper
? val_n1
: val_m1
;
2883 uint64_t input2
= upper
? val_n2
: val_m2
;
2886 NYI_assert (29, 24, 0x0E);
2887 NYI_assert (21, 21, 0);
2888 NYI_assert (15, 15, 0);
2889 NYI_assert (13, 10, 6);
2891 switch (INSTR (23, 23))
2894 for (i
= 0; i
< 8; i
++)
2896 val1
|= (input1
>> (i
* 8)) & (0xFFULL
<< (i
* 8));
2897 val2
|= (input2
>> (i
* 8)) & (0xFFULL
<< (i
* 8));
2902 for (i
= 0; i
< 4; i
++)
2904 val1
|= (input1
>> (i
* 16)) & (0xFFFFULL
<< (i
* 16));
2905 val2
|= (input2
>> (i
* 16)) & (0xFFFFULL
<< (i
* 16));
2910 val1
= ((input1
& 0xFFFFFFFF) | ((input1
>> 32) & 0xFFFFFFFF00000000ULL
));
2911 val2
= ((input2
& 0xFFFFFFFF) | ((input2
>> 32) & 0xFFFFFFFF00000000ULL
));
2919 aarch64_set_vec_u64 (cpu
, vd
, 0, val1
);
2921 aarch64_set_vec_u64 (cpu
, vd
, 1, val2
);
2925 do_vec_ZIP (sim_cpu
*cpu
)
2928 instr[30] = half(0)/full(1)
2929 instr[29,24] = 00 1110
2930 instr[23,22] = size: byte(00), hald(01), word (10), long (11)
2934 instr[14] = lower (0) / upper (1)
2939 int full
= INSTR (30, 30);
2940 int upper
= INSTR (14, 14);
2942 unsigned vm
= INSTR (20, 16);
2943 unsigned vn
= INSTR (9, 5);
2944 unsigned vd
= INSTR (4, 0);
2946 uint64_t val_m1
= aarch64_get_vec_u64 (cpu
, vm
, 0);
2947 uint64_t val_m2
= aarch64_get_vec_u64 (cpu
, vm
, 1);
2948 uint64_t val_n1
= aarch64_get_vec_u64 (cpu
, vn
, 0);
2949 uint64_t val_n2
= aarch64_get_vec_u64 (cpu
, vn
, 1);
2954 uint64_t input1
= upper
? val_n1
: val_m1
;
2955 uint64_t input2
= upper
? val_n2
: val_m2
;
2957 NYI_assert (29, 24, 0x0E);
2958 NYI_assert (21, 21, 0);
2959 NYI_assert (15, 15, 0);
2960 NYI_assert (13, 10, 0xE);
2962 switch (INSTR (23, 23))
2966 ((input1
<< 0) & (0xFF << 0))
2967 | ((input2
<< 8) & (0xFF << 8))
2968 | ((input1
<< 8) & (0xFF << 16))
2969 | ((input2
<< 16) & (0xFF << 24))
2970 | ((input1
<< 16) & (0xFFULL
<< 32))
2971 | ((input2
<< 24) & (0xFFULL
<< 40))
2972 | ((input1
<< 24) & (0xFFULL
<< 48))
2973 | ((input2
<< 32) & (0xFFULL
<< 56));
2976 ((input1
>> 32) & (0xFF << 0))
2977 | ((input2
>> 24) & (0xFF << 8))
2978 | ((input1
>> 24) & (0xFF << 16))
2979 | ((input2
>> 16) & (0xFF << 24))
2980 | ((input1
>> 16) & (0xFFULL
<< 32))
2981 | ((input2
>> 8) & (0xFFULL
<< 40))
2982 | ((input1
>> 8) & (0xFFULL
<< 48))
2983 | ((input2
>> 0) & (0xFFULL
<< 56));
2988 ((input1
<< 0) & (0xFFFF << 0))
2989 | ((input2
<< 16) & (0xFFFF << 16))
2990 | ((input1
<< 16) & (0xFFFFULL
<< 32))
2991 | ((input2
<< 32) & (0xFFFFULL
<< 48));
2994 ((input1
>> 32) & (0xFFFF << 0))
2995 | ((input2
>> 16) & (0xFFFF << 16))
2996 | ((input1
>> 16) & (0xFFFFULL
<< 32))
2997 | ((input2
>> 0) & (0xFFFFULL
<< 48));
3001 val1
= (input1
& 0xFFFFFFFFULL
) | (input2
<< 32);
3002 val2
= (input2
& 0xFFFFFFFFULL
) | (input1
<< 32);
3011 aarch64_set_vec_u64 (cpu
, vd
, 0, val1
);
3013 aarch64_set_vec_u64 (cpu
, vd
, 1, val2
);
3016 /* Floating point immediates are encoded in 8 bits.
3017 fpimm[7] = sign bit.
3018 fpimm[6:4] = signed exponent.
3019 fpimm[3:0] = fraction (assuming leading 1).
3020 i.e. F = s * 1.f * 2^(e - b). */
3023 fp_immediate_for_encoding_32 (uint32_t imm8
)
3026 uint32_t s
, e
, f
, i
;
3028 s
= (imm8
>> 7) & 0x1;
3029 e
= (imm8
>> 4) & 0x7;
3032 /* The fp value is s * n/16 * 2r where n is 16+e. */
3033 u
= (16.0 + f
) / 16.0;
3035 /* N.B. exponent is signed. */
3040 for (i
= 0; i
<= epos
; i
++)
3047 for (i
= 0; i
< eneg
; i
++)
3058 fp_immediate_for_encoding_64 (uint32_t imm8
)
3061 uint32_t s
, e
, f
, i
;
3063 s
= (imm8
>> 7) & 0x1;
3064 e
= (imm8
>> 4) & 0x7;
3067 /* The fp value is s * n/16 * 2r where n is 16+e. */
3068 u
= (16.0 + f
) / 16.0;
3070 /* N.B. exponent is signed. */
3075 for (i
= 0; i
<= epos
; i
++)
3082 for (i
= 0; i
< eneg
; i
++)
3093 do_vec_MOV_immediate (sim_cpu
*cpu
)
3096 instr[30] = full/half selector
3097 instr[29,19] = 00111100000
3098 instr[18,16] = high 3 bits of uimm8
3099 instr[15,12] = size & shift:
3101 0010 => 32-bit + LSL#8
3102 0100 => 32-bit + LSL#16
3103 0110 => 32-bit + LSL#24
3104 1010 => 16-bit + LSL#8
3106 1101 => 32-bit + MSL#16
3107 1100 => 32-bit + MSL#8
3111 instr[9,5] = low 5-bits of uimm8
3114 int full
= INSTR (30, 30);
3115 unsigned vd
= INSTR (4, 0);
3116 unsigned val
= (INSTR (18, 16) << 5) | INSTR (9, 5);
3119 NYI_assert (29, 19, 0x1E0);
3120 NYI_assert (11, 10, 1);
3122 switch (INSTR (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 * INSTR (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
= INSTR (30, 30);
3182 unsigned vd
= INSTR (4, 0);
3183 unsigned val
= (INSTR (18, 16) << 5) | INSTR (9, 5);
3186 NYI_assert (29, 19, 0x5E0);
3187 NYI_assert (11, 10, 1);
3189 switch (INSTR (15, 12))
3191 case 0x0: /* 32-bit, no shift. */
3192 case 0x2: /* 32-bit, shift by 8. */
3193 case 0x4: /* 32-bit, shift by 16. */
3194 case 0x6: /* 32-bit, shift by 24. */
3195 val
<<= (8 * INSTR (14, 13));
3197 for (i
= 0; i
< (full
? 4 : 2); i
++)
3198 aarch64_set_vec_u32 (cpu
, vd
, i
, val
);
3201 case 0xa: /* 16-bit, 8 bit shift. */
3203 case 0x8: /* 16-bit, no shift. */
3205 for (i
= 0; i
< (full
? 8 : 4); i
++)
3206 aarch64_set_vec_u16 (cpu
, vd
, i
, val
);
3209 case 0xd: /* 32-bit, mask shift by 16. */
3212 case 0xc: /* 32-bit, mask shift by 8. */
3216 for (i
= 0; i
< (full
? 4 : 2); i
++)
3217 aarch64_set_vec_u32 (cpu
, vd
, i
, val
);
3220 case 0xE: /* MOVI Dn, #mask64 */
3224 for (i
= 0; i
< 8; i
++)
3226 mask
|= (0xFFUL
<< (i
* 8));
3227 aarch64_set_vec_u64 (cpu
, vd
, 0, mask
);
3228 aarch64_set_vec_u64 (cpu
, vd
, 1, mask
);
3232 case 0xf: /* FMOV Vd.2D, #fpimm. */
3234 double u
= fp_immediate_for_encoding_64 (val
);
3239 aarch64_set_vec_double (cpu
, vd
, 0, u
);
3240 aarch64_set_vec_double (cpu
, vd
, 1, u
);
3249 #define ABS(A) ((A) < 0 ? - (A) : (A))
3252 do_vec_ABS (sim_cpu
*cpu
)
3255 instr[30] = half(0)/full(1)
3256 instr[29,24] = 00 1110
3257 instr[23,22] = size: 00=> 8-bit, 01=> 16-bit, 10=> 32-bit, 11=> 64-bit
3258 instr[21,10] = 10 0000 1011 10
3262 unsigned vn
= INSTR (9, 5);
3263 unsigned vd
= INSTR (4, 0);
3264 unsigned full
= INSTR (30, 30);
3267 NYI_assert (29, 24, 0x0E);
3268 NYI_assert (21, 10, 0x82E);
3270 switch (INSTR (23, 22))
3273 for (i
= 0; i
< (full
? 16 : 8); i
++)
3274 aarch64_set_vec_s8 (cpu
, vd
, i
,
3275 ABS (aarch64_get_vec_s8 (cpu
, vn
, i
)));
3279 for (i
= 0; i
< (full
? 8 : 4); i
++)
3280 aarch64_set_vec_s16 (cpu
, vd
, i
,
3281 ABS (aarch64_get_vec_s16 (cpu
, vn
, i
)));
3285 for (i
= 0; i
< (full
? 4 : 2); i
++)
3286 aarch64_set_vec_s32 (cpu
, vd
, i
,
3287 ABS (aarch64_get_vec_s32 (cpu
, vn
, i
)));
3293 for (i
= 0; i
< 2; i
++)
3294 aarch64_set_vec_s64 (cpu
, vd
, i
,
3295 ABS (aarch64_get_vec_s64 (cpu
, vn
, i
)));
3301 do_vec_ADDV (sim_cpu
*cpu
)
3304 instr[30] = full/half selector
3305 instr[29,24] = 00 1110
3306 instr[23,22] = size: 00=> 8-bit, 01=> 16-bit, 10=> 32-bit, 11=> 64-bit
3307 instr[21,10] = 11 0001 1011 10
3311 unsigned vm
= INSTR (9, 5);
3312 unsigned rd
= INSTR (4, 0);
3315 int full
= INSTR (30, 30);
3317 NYI_assert (29, 24, 0x0E);
3318 NYI_assert (21, 10, 0xC6E);
3320 switch (INSTR (23, 22))
3323 for (i
= 0; i
< (full
? 16 : 8); i
++)
3324 val
+= aarch64_get_vec_u8 (cpu
, vm
, i
);
3325 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, val
);
3329 for (i
= 0; i
< (full
? 8 : 4); i
++)
3330 val
+= aarch64_get_vec_u16 (cpu
, vm
, i
);
3331 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, val
);
3335 for (i
= 0; i
< (full
? 4 : 2); i
++)
3336 val
+= aarch64_get_vec_u32 (cpu
, vm
, i
);
3337 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, val
);
3343 val
= aarch64_get_vec_u64 (cpu
, vm
, 0);
3344 val
+= aarch64_get_vec_u64 (cpu
, vm
, 1);
3345 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, val
);
3351 do_vec_ins_2 (sim_cpu
*cpu
)
3353 /* instr[31,21] = 01001110000
3354 instr[20,18] = size & element selector
3356 instr[13] = direction: to vec(0), from vec (1)
3362 unsigned vm
= INSTR (9, 5);
3363 unsigned vd
= INSTR (4, 0);
3365 NYI_assert (31, 21, 0x270);
3366 NYI_assert (17, 14, 0);
3367 NYI_assert (12, 10, 7);
3369 if (INSTR (13, 13) == 1)
3371 if (INSTR (18, 18) == 1)
3374 elem
= INSTR (20, 19);
3375 aarch64_set_reg_u64 (cpu
, vd
, NO_SP
,
3376 aarch64_get_vec_u32 (cpu
, vm
, elem
));
3381 if (INSTR (19, 19) != 1)
3384 elem
= INSTR (20, 20);
3385 aarch64_set_reg_u64 (cpu
, vd
, NO_SP
,
3386 aarch64_get_vec_u64 (cpu
, vm
, elem
));
3391 if (INSTR (18, 18) == 1)
3394 elem
= INSTR (20, 19);
3395 aarch64_set_vec_u32 (cpu
, vd
, elem
,
3396 aarch64_get_reg_u32 (cpu
, vm
, NO_SP
));
3401 if (INSTR (19, 19) != 1)
3404 elem
= INSTR (20, 20);
3405 aarch64_set_vec_u64 (cpu
, vd
, elem
,
3406 aarch64_get_reg_u64 (cpu
, vm
, NO_SP
));
3411 #define DO_VEC_WIDENING_MUL(N, DST_TYPE, READ_TYPE, WRITE_TYPE) \
3414 DST_TYPE a[N], b[N]; \
3416 for (i = 0; i < (N); i++) \
3418 a[i] = aarch64_get_vec_##READ_TYPE (cpu, vn, i + bias); \
3419 b[i] = aarch64_get_vec_##READ_TYPE (cpu, vm, i + bias); \
3421 for (i = 0; i < (N); i++) \
3422 aarch64_set_vec_##WRITE_TYPE (cpu, vd, i, a[i] * b[i]); \
3427 do_vec_mull (sim_cpu
*cpu
)
3430 instr[30] = lower(0)/upper(1) selector
3431 instr[29] = signed(0)/unsigned(1)
3432 instr[28,24] = 0 1110
3433 instr[23,22] = size: 8-bit (00), 16-bit (01), 32-bit (10)
3436 instr[15,10] = 11 0000
3440 int unsign
= INSTR (29, 29);
3441 int bias
= INSTR (30, 30);
3442 unsigned vm
= INSTR (20, 16);
3443 unsigned vn
= INSTR ( 9, 5);
3444 unsigned vd
= INSTR ( 4, 0);
3447 NYI_assert (28, 24, 0x0E);
3448 NYI_assert (15, 10, 0x30);
3450 /* NB: Read source values before writing results, in case
3451 the source and destination vectors are the same. */
3452 switch (INSTR (23, 22))
3458 DO_VEC_WIDENING_MUL (8, uint16_t, u8
, u16
);
3460 DO_VEC_WIDENING_MUL (8, int16_t, s8
, s16
);
3467 DO_VEC_WIDENING_MUL (4, uint32_t, u16
, u32
);
3469 DO_VEC_WIDENING_MUL (4, int32_t, s16
, s32
);
3476 DO_VEC_WIDENING_MUL (2, uint64_t, u32
, u64
);
3478 DO_VEC_WIDENING_MUL (2, int64_t, s32
, s64
);
3487 do_vec_fadd (sim_cpu
*cpu
)
3490 instr[30] = half(0)/full(1)
3491 instr[29,24] = 001110
3492 instr[23] = FADD(0)/FSUB(1)
3493 instr[22] = float (0)/double(1)
3496 instr[15,10] = 110101
3500 unsigned vm
= INSTR (20, 16);
3501 unsigned vn
= INSTR (9, 5);
3502 unsigned vd
= INSTR (4, 0);
3504 int full
= INSTR (30, 30);
3506 NYI_assert (29, 24, 0x0E);
3507 NYI_assert (21, 21, 1);
3508 NYI_assert (15, 10, 0x35);
3517 for (i
= 0; i
< 2; i
++)
3518 aarch64_set_vec_double (cpu
, vd
, i
,
3519 aarch64_get_vec_double (cpu
, vn
, i
)
3520 - aarch64_get_vec_double (cpu
, vm
, i
));
3524 for (i
= 0; i
< (full
? 4 : 2); i
++)
3525 aarch64_set_vec_float (cpu
, vd
, i
,
3526 aarch64_get_vec_float (cpu
, vn
, i
)
3527 - aarch64_get_vec_float (cpu
, vm
, i
));
3537 for (i
= 0; i
< 2; i
++)
3538 aarch64_set_vec_double (cpu
, vd
, i
,
3539 aarch64_get_vec_double (cpu
, vm
, i
)
3540 + aarch64_get_vec_double (cpu
, vn
, i
));
3544 for (i
= 0; i
< (full
? 4 : 2); i
++)
3545 aarch64_set_vec_float (cpu
, vd
, i
,
3546 aarch64_get_vec_float (cpu
, vm
, i
)
3547 + aarch64_get_vec_float (cpu
, vn
, i
));
3553 do_vec_add (sim_cpu
*cpu
)
3556 instr[30] = full/half selector
3557 instr[29,24] = 001110
3558 instr[23,22] = size: 00=> 8-bit, 01=> 16-bit, 10=> 32-bit, 11=> 64-bit
3561 instr[15,10] = 100001
3565 unsigned vm
= INSTR (20, 16);
3566 unsigned vn
= INSTR (9, 5);
3567 unsigned vd
= INSTR (4, 0);
3569 int full
= INSTR (30, 30);
3571 NYI_assert (29, 24, 0x0E);
3572 NYI_assert (21, 21, 1);
3573 NYI_assert (15, 10, 0x21);
3575 switch (INSTR (23, 22))
3578 for (i
= 0; i
< (full
? 16 : 8); i
++)
3579 aarch64_set_vec_u8 (cpu
, vd
, i
, aarch64_get_vec_u8 (cpu
, vn
, i
)
3580 + aarch64_get_vec_u8 (cpu
, vm
, i
));
3584 for (i
= 0; i
< (full
? 8 : 4); i
++)
3585 aarch64_set_vec_u16 (cpu
, vd
, i
, aarch64_get_vec_u16 (cpu
, vn
, i
)
3586 + aarch64_get_vec_u16 (cpu
, vm
, i
));
3590 for (i
= 0; i
< (full
? 4 : 2); i
++)
3591 aarch64_set_vec_u32 (cpu
, vd
, i
, aarch64_get_vec_u32 (cpu
, vn
, i
)
3592 + aarch64_get_vec_u32 (cpu
, vm
, i
));
3598 aarch64_set_vec_u64 (cpu
, vd
, 0, aarch64_get_vec_u64 (cpu
, vn
, 0)
3599 + aarch64_get_vec_u64 (cpu
, vm
, 0));
3600 aarch64_set_vec_u64 (cpu
, vd
, 1,
3601 aarch64_get_vec_u64 (cpu
, vn
, 1)
3602 + aarch64_get_vec_u64 (cpu
, vm
, 1));
3608 do_vec_mul (sim_cpu
*cpu
)
3611 instr[30] = full/half selector
3612 instr[29,24] = 00 1110
3613 instr[23,22] = size: 00=> 8-bit, 01=> 16-bit, 10=> 32-bit
3616 instr[15,10] = 10 0111
3620 unsigned vm
= INSTR (20, 16);
3621 unsigned vn
= INSTR (9, 5);
3622 unsigned vd
= INSTR (4, 0);
3624 int full
= INSTR (30, 30);
3627 NYI_assert (29, 24, 0x0E);
3628 NYI_assert (21, 21, 1);
3629 NYI_assert (15, 10, 0x27);
3631 switch (INSTR (23, 22))
3634 DO_VEC_WIDENING_MUL (full
? 16 : 8, uint16_t, u8
, u16
);
3638 DO_VEC_WIDENING_MUL (full
? 8 : 4, uint32_t, u16
, u32
);
3642 DO_VEC_WIDENING_MUL (full
? 4 : 2, uint64_t, u32
, u64
);
3651 do_vec_MLA (sim_cpu
*cpu
)
3654 instr[30] = full/half selector
3655 instr[29,24] = 00 1110
3656 instr[23,22] = size: 00=> 8-bit, 01=> 16-bit, 10=> 32-bit
3659 instr[15,10] = 1001 01
3663 unsigned vm
= INSTR (20, 16);
3664 unsigned vn
= INSTR (9, 5);
3665 unsigned vd
= INSTR (4, 0);
3667 int full
= INSTR (30, 30);
3669 NYI_assert (29, 24, 0x0E);
3670 NYI_assert (21, 21, 1);
3671 NYI_assert (15, 10, 0x25);
3673 switch (INSTR (23, 22))
3677 uint16_t a
[16], b
[16];
3679 for (i
= 0; i
< (full
? 16 : 8); i
++)
3681 a
[i
] = aarch64_get_vec_u8 (cpu
, vn
, i
);
3682 b
[i
] = aarch64_get_vec_u8 (cpu
, vm
, i
);
3685 for (i
= 0; i
< (full
? 16 : 8); i
++)
3687 uint16_t v
= aarch64_get_vec_u8 (cpu
, vd
, i
);
3689 aarch64_set_vec_u16 (cpu
, vd
, i
, v
+ (a
[i
] * b
[i
]));
3696 uint32_t a
[8], b
[8];
3698 for (i
= 0; i
< (full
? 8 : 4); i
++)
3700 a
[i
] = aarch64_get_vec_u16 (cpu
, vn
, i
);
3701 b
[i
] = aarch64_get_vec_u16 (cpu
, vm
, i
);
3704 for (i
= 0; i
< (full
? 8 : 4); i
++)
3706 uint32_t v
= aarch64_get_vec_u16 (cpu
, vd
, i
);
3708 aarch64_set_vec_u32 (cpu
, vd
, i
, v
+ (a
[i
] * b
[i
]));
3715 uint64_t a
[4], b
[4];
3717 for (i
= 0; i
< (full
? 4 : 2); i
++)
3719 a
[i
] = aarch64_get_vec_u32 (cpu
, vn
, i
);
3720 b
[i
] = aarch64_get_vec_u32 (cpu
, vm
, i
);
3723 for (i
= 0; i
< (full
? 4 : 2); i
++)
3725 uint64_t v
= aarch64_get_vec_u32 (cpu
, vd
, i
);
3727 aarch64_set_vec_u64 (cpu
, vd
, i
, v
+ (a
[i
] * b
[i
]));
3738 fmaxnm (float a
, float b
)
3740 if (fpclassify (a
) == FP_NORMAL
)
3742 if (fpclassify (b
) == FP_NORMAL
)
3743 return a
> b
? a
: b
;
3746 else if (fpclassify (b
) == FP_NORMAL
)
3752 fminnm (float a
, float b
)
3754 if (fpclassify (a
) == FP_NORMAL
)
3756 if (fpclassify (b
) == FP_NORMAL
)
3757 return a
< b
? a
: b
;
3760 else if (fpclassify (b
) == FP_NORMAL
)
3766 dmaxnm (double a
, double b
)
3768 if (fpclassify (a
) == FP_NORMAL
)
3770 if (fpclassify (b
) == FP_NORMAL
)
3771 return a
> b
? a
: b
;
3774 else if (fpclassify (b
) == FP_NORMAL
)
3780 dminnm (double a
, double b
)
3782 if (fpclassify (a
) == FP_NORMAL
)
3784 if (fpclassify (b
) == FP_NORMAL
)
3785 return a
< b
? a
: b
;
3788 else if (fpclassify (b
) == FP_NORMAL
)
3794 do_vec_FminmaxNMP (sim_cpu
*cpu
)
3797 instr [30] = half (0)/full (1)
3798 instr [29,24] = 10 1110
3799 instr [23] = max(0)/min(1)
3800 instr [22] = float (0)/double (1)
3803 instr [15,10] = 1100 01
3805 instr [4.0] = Vd. */
3807 unsigned vm
= INSTR (20, 16);
3808 unsigned vn
= INSTR (9, 5);
3809 unsigned vd
= INSTR (4, 0);
3810 int full
= INSTR (30, 30);
3812 NYI_assert (29, 24, 0x2E);
3813 NYI_assert (21, 21, 1);
3814 NYI_assert (15, 10, 0x31);
3818 double (* fn
)(double, double) = INSTR (23, 23)
3823 aarch64_set_vec_double (cpu
, vd
, 0,
3824 fn (aarch64_get_vec_double (cpu
, vn
, 0),
3825 aarch64_get_vec_double (cpu
, vn
, 1)));
3826 aarch64_set_vec_double (cpu
, vd
, 0,
3827 fn (aarch64_get_vec_double (cpu
, vm
, 0),
3828 aarch64_get_vec_double (cpu
, vm
, 1)));
3832 float (* fn
)(float, float) = INSTR (23, 23)
3835 aarch64_set_vec_float (cpu
, vd
, 0,
3836 fn (aarch64_get_vec_float (cpu
, vn
, 0),
3837 aarch64_get_vec_float (cpu
, vn
, 1)));
3839 aarch64_set_vec_float (cpu
, vd
, 1,
3840 fn (aarch64_get_vec_float (cpu
, vn
, 2),
3841 aarch64_get_vec_float (cpu
, vn
, 3)));
3843 aarch64_set_vec_float (cpu
, vd
, (full
? 2 : 1),
3844 fn (aarch64_get_vec_float (cpu
, vm
, 0),
3845 aarch64_get_vec_float (cpu
, vm
, 1)));
3847 aarch64_set_vec_float (cpu
, vd
, 3,
3848 fn (aarch64_get_vec_float (cpu
, vm
, 2),
3849 aarch64_get_vec_float (cpu
, vm
, 3)));
3854 do_vec_AND (sim_cpu
*cpu
)
3857 instr[30] = half (0)/full (1)
3858 instr[29,21] = 001110001
3860 instr[15,10] = 000111
3864 unsigned vm
= INSTR (20, 16);
3865 unsigned vn
= INSTR (9, 5);
3866 unsigned vd
= INSTR (4, 0);
3868 int full
= INSTR (30, 30);
3870 NYI_assert (29, 21, 0x071);
3871 NYI_assert (15, 10, 0x07);
3873 for (i
= 0; i
< (full
? 4 : 2); i
++)
3874 aarch64_set_vec_u32 (cpu
, vd
, i
,
3875 aarch64_get_vec_u32 (cpu
, vn
, i
)
3876 & aarch64_get_vec_u32 (cpu
, vm
, i
));
3880 do_vec_BSL (sim_cpu
*cpu
)
3883 instr[30] = half (0)/full (1)
3884 instr[29,21] = 101110011
3886 instr[15,10] = 000111
3890 unsigned vm
= INSTR (20, 16);
3891 unsigned vn
= INSTR (9, 5);
3892 unsigned vd
= INSTR (4, 0);
3894 int full
= INSTR (30, 30);
3896 NYI_assert (29, 21, 0x173);
3897 NYI_assert (15, 10, 0x07);
3899 for (i
= 0; i
< (full
? 16 : 8); i
++)
3900 aarch64_set_vec_u8 (cpu
, vd
, i
,
3901 ( aarch64_get_vec_u8 (cpu
, vd
, i
)
3902 & aarch64_get_vec_u8 (cpu
, vn
, i
))
3903 | ((~ aarch64_get_vec_u8 (cpu
, vd
, i
))
3904 & aarch64_get_vec_u8 (cpu
, vm
, i
)));
3908 do_vec_EOR (sim_cpu
*cpu
)
3911 instr[30] = half (0)/full (1)
3912 instr[29,21] = 10 1110 001
3914 instr[15,10] = 000111
3918 unsigned vm
= INSTR (20, 16);
3919 unsigned vn
= INSTR (9, 5);
3920 unsigned vd
= INSTR (4, 0);
3922 int full
= INSTR (30, 30);
3924 NYI_assert (29, 21, 0x171);
3925 NYI_assert (15, 10, 0x07);
3927 for (i
= 0; i
< (full
? 4 : 2); i
++)
3928 aarch64_set_vec_u32 (cpu
, vd
, i
,
3929 aarch64_get_vec_u32 (cpu
, vn
, i
)
3930 ^ aarch64_get_vec_u32 (cpu
, vm
, i
));
3934 do_vec_bit (sim_cpu
*cpu
)
3937 instr[30] = half (0)/full (1)
3938 instr[29,23] = 10 1110 1
3939 instr[22] = BIT (0) / BIF (1)
3942 instr[15,10] = 0001 11
3946 unsigned vm
= INSTR (20, 16);
3947 unsigned vn
= INSTR (9, 5);
3948 unsigned vd
= INSTR (4, 0);
3949 unsigned full
= INSTR (30, 30);
3950 unsigned test_false
= INSTR (22, 22);
3953 NYI_assert (29, 23, 0x5D);
3954 NYI_assert (21, 21, 1);
3955 NYI_assert (15, 10, 0x07);
3959 for (i
= 0; i
< (full
? 16 : 8); i
++)
3960 if (aarch64_get_vec_u32 (cpu
, vn
, i
) == 0)
3961 aarch64_set_vec_u32 (cpu
, vd
, i
, aarch64_get_vec_u32 (cpu
, vm
, i
));
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
));
3972 do_vec_ORN (sim_cpu
*cpu
)
3975 instr[30] = half (0)/full (1)
3976 instr[29,21] = 00 1110 111
3978 instr[15,10] = 00 0111
3982 unsigned vm
= INSTR (20, 16);
3983 unsigned vn
= INSTR (9, 5);
3984 unsigned vd
= INSTR (4, 0);
3986 int full
= INSTR (30, 30);
3988 NYI_assert (29, 21, 0x077);
3989 NYI_assert (15, 10, 0x07);
3991 for (i
= 0; i
< (full
? 16 : 8); i
++)
3992 aarch64_set_vec_u8 (cpu
, vd
, i
,
3993 aarch64_get_vec_u8 (cpu
, vn
, i
)
3994 | ~ aarch64_get_vec_u8 (cpu
, vm
, i
));
3998 do_vec_ORR (sim_cpu
*cpu
)
4001 instr[30] = half (0)/full (1)
4002 instr[29,21] = 00 1110 101
4004 instr[15,10] = 0001 11
4008 unsigned vm
= INSTR (20, 16);
4009 unsigned vn
= INSTR (9, 5);
4010 unsigned vd
= INSTR (4, 0);
4012 int full
= INSTR (30, 30);
4014 NYI_assert (29, 21, 0x075);
4015 NYI_assert (15, 10, 0x07);
4017 for (i
= 0; i
< (full
? 16 : 8); i
++)
4018 aarch64_set_vec_u8 (cpu
, vd
, i
,
4019 aarch64_get_vec_u8 (cpu
, vn
, i
)
4020 | aarch64_get_vec_u8 (cpu
, vm
, i
));
4024 do_vec_BIC (sim_cpu
*cpu
)
4027 instr[30] = half (0)/full (1)
4028 instr[29,21] = 00 1110 011
4030 instr[15,10] = 00 0111
4034 unsigned vm
= INSTR (20, 16);
4035 unsigned vn
= INSTR (9, 5);
4036 unsigned vd
= INSTR (4, 0);
4038 int full
= INSTR (30, 30);
4040 NYI_assert (29, 21, 0x073);
4041 NYI_assert (15, 10, 0x07);
4043 for (i
= 0; i
< (full
? 16 : 8); i
++)
4044 aarch64_set_vec_u8 (cpu
, vd
, i
,
4045 aarch64_get_vec_u8 (cpu
, vn
, i
)
4046 & ~ aarch64_get_vec_u8 (cpu
, vm
, i
));
4050 do_vec_XTN (sim_cpu
*cpu
)
4053 instr[30] = first part (0)/ second part (1)
4054 instr[29,24] = 00 1110
4055 instr[23,22] = size: byte(00), half(01), word (10)
4056 instr[21,10] = 1000 0100 1010
4060 unsigned vs
= INSTR (9, 5);
4061 unsigned vd
= INSTR (4, 0);
4062 unsigned bias
= INSTR (30, 30);
4065 NYI_assert (29, 24, 0x0E);
4066 NYI_assert (21, 10, 0x84A);
4068 switch (INSTR (23, 22))
4072 for (i
= 0; i
< 8; i
++)
4073 aarch64_set_vec_u8 (cpu
, vd
, i
+ 8,
4074 aarch64_get_vec_u16 (cpu
, vs
, i
) >> 8);
4076 for (i
= 0; i
< 8; i
++)
4077 aarch64_set_vec_u8 (cpu
, vd
, i
, aarch64_get_vec_u16 (cpu
, vs
, i
));
4082 for (i
= 0; i
< 4; i
++)
4083 aarch64_set_vec_u16 (cpu
, vd
, i
+ 4,
4084 aarch64_get_vec_u32 (cpu
, vs
, i
) >> 16);
4086 for (i
= 0; i
< 4; i
++)
4087 aarch64_set_vec_u16 (cpu
, vd
, i
, aarch64_get_vec_u32 (cpu
, vs
, i
));
4092 for (i
= 0; i
< 2; i
++)
4093 aarch64_set_vec_u32 (cpu
, vd
, i
+ 4,
4094 aarch64_get_vec_u64 (cpu
, vs
, i
) >> 32);
4096 for (i
= 0; i
< 2; i
++)
4097 aarch64_set_vec_u32 (cpu
, vd
, i
, aarch64_get_vec_u64 (cpu
, vs
, i
));
4103 do_vec_maxv (sim_cpu
*cpu
)
4106 instr[30] = half(0)/full(1)
4107 instr[29] = signed (0)/unsigned(1)
4108 instr[28,24] = 0 1110
4109 instr[23,22] = size: byte(00), half(01), word (10)
4111 instr[20,17] = 1 000
4112 instr[16] = max(0)/min(1)
4113 instr[15,10] = 1010 10
4114 instr[9,5] = V source
4115 instr[4.0] = R dest. */
4117 unsigned vs
= INSTR (9, 5);
4118 unsigned rd
= INSTR (4, 0);
4119 unsigned full
= INSTR (30, 30);
4122 NYI_assert (28, 24, 0x0E);
4123 NYI_assert (21, 21, 1);
4124 NYI_assert (20, 17, 8);
4125 NYI_assert (15, 10, 0x2A);
4127 switch ((INSTR (29, 29) << 1) | INSTR (16, 16))
4129 case 0: /* SMAXV. */
4132 switch (INSTR (23, 22))
4135 smax
= aarch64_get_vec_s8 (cpu
, vs
, 0);
4136 for (i
= 1; i
< (full
? 16 : 8); i
++)
4137 smax
= max (smax
, aarch64_get_vec_s8 (cpu
, vs
, i
));
4140 smax
= aarch64_get_vec_s16 (cpu
, vs
, 0);
4141 for (i
= 1; i
< (full
? 8 : 4); i
++)
4142 smax
= max (smax
, aarch64_get_vec_s16 (cpu
, vs
, i
));
4145 smax
= aarch64_get_vec_s32 (cpu
, vs
, 0);
4146 for (i
= 1; i
< (full
? 4 : 2); i
++)
4147 smax
= max (smax
, aarch64_get_vec_s32 (cpu
, vs
, i
));
4152 aarch64_set_reg_s64 (cpu
, rd
, NO_SP
, smax
);
4156 case 1: /* SMINV. */
4159 switch (INSTR (23, 22))
4162 smin
= aarch64_get_vec_s8 (cpu
, vs
, 0);
4163 for (i
= 1; i
< (full
? 16 : 8); i
++)
4164 smin
= min (smin
, aarch64_get_vec_s8 (cpu
, vs
, i
));
4167 smin
= aarch64_get_vec_s16 (cpu
, vs
, 0);
4168 for (i
= 1; i
< (full
? 8 : 4); i
++)
4169 smin
= min (smin
, aarch64_get_vec_s16 (cpu
, vs
, i
));
4172 smin
= aarch64_get_vec_s32 (cpu
, vs
, 0);
4173 for (i
= 1; i
< (full
? 4 : 2); i
++)
4174 smin
= min (smin
, aarch64_get_vec_s32 (cpu
, vs
, i
));
4180 aarch64_set_reg_s64 (cpu
, rd
, NO_SP
, smin
);
4184 case 2: /* UMAXV. */
4187 switch (INSTR (23, 22))
4190 umax
= aarch64_get_vec_u8 (cpu
, vs
, 0);
4191 for (i
= 1; i
< (full
? 16 : 8); i
++)
4192 umax
= max (umax
, aarch64_get_vec_u8 (cpu
, vs
, i
));
4195 umax
= aarch64_get_vec_u16 (cpu
, vs
, 0);
4196 for (i
= 1; i
< (full
? 8 : 4); i
++)
4197 umax
= max (umax
, aarch64_get_vec_u16 (cpu
, vs
, i
));
4200 umax
= aarch64_get_vec_u32 (cpu
, vs
, 0);
4201 for (i
= 1; i
< (full
? 4 : 2); i
++)
4202 umax
= max (umax
, aarch64_get_vec_u32 (cpu
, vs
, i
));
4208 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, umax
);
4212 case 3: /* UMINV. */
4215 switch (INSTR (23, 22))
4218 umin
= aarch64_get_vec_u8 (cpu
, vs
, 0);
4219 for (i
= 1; i
< (full
? 16 : 8); i
++)
4220 umin
= min (umin
, aarch64_get_vec_u8 (cpu
, vs
, i
));
4223 umin
= aarch64_get_vec_u16 (cpu
, vs
, 0);
4224 for (i
= 1; i
< (full
? 8 : 4); i
++)
4225 umin
= min (umin
, aarch64_get_vec_u16 (cpu
, vs
, i
));
4228 umin
= aarch64_get_vec_u32 (cpu
, vs
, 0);
4229 for (i
= 1; i
< (full
? 4 : 2); i
++)
4230 umin
= min (umin
, aarch64_get_vec_u32 (cpu
, vs
, i
));
4236 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, umin
);
4243 do_vec_fminmaxV (sim_cpu
*cpu
)
4245 /* instr[31,24] = 0110 1110
4246 instr[23] = max(0)/min(1)
4247 instr[22,14] = 011 0000 11
4248 instr[13,12] = nm(00)/normal(11)
4250 instr[9,5] = V source
4251 instr[4.0] = R dest. */
4253 unsigned vs
= INSTR (9, 5);
4254 unsigned rd
= INSTR (4, 0);
4256 float res
= aarch64_get_vec_float (cpu
, vs
, 0);
4258 NYI_assert (31, 24, 0x6E);
4259 NYI_assert (22, 14, 0x0C3);
4260 NYI_assert (11, 10, 2);
4264 switch (INSTR (13, 12))
4266 case 0: /* FMNINNMV. */
4267 for (i
= 1; i
< 4; i
++)
4268 res
= fminnm (res
, aarch64_get_vec_float (cpu
, vs
, i
));
4271 case 3: /* FMINV. */
4272 for (i
= 1; i
< 4; i
++)
4273 res
= min (res
, aarch64_get_vec_float (cpu
, vs
, i
));
4282 switch (INSTR (13, 12))
4284 case 0: /* FMNAXNMV. */
4285 for (i
= 1; i
< 4; i
++)
4286 res
= fmaxnm (res
, aarch64_get_vec_float (cpu
, vs
, i
));
4289 case 3: /* FMAXV. */
4290 for (i
= 1; i
< 4; i
++)
4291 res
= max (res
, aarch64_get_vec_float (cpu
, vs
, i
));
4299 aarch64_set_FP_float (cpu
, rd
, res
);
4303 do_vec_Fminmax (sim_cpu
*cpu
)
4306 instr[30] = half(0)/full(1)
4307 instr[29,24] = 00 1110
4308 instr[23] = max(0)/min(1)
4309 instr[22] = float(0)/double(1)
4313 instr[13,12] = nm(00)/normal(11)
4318 unsigned vm
= INSTR (20, 16);
4319 unsigned vn
= INSTR (9, 5);
4320 unsigned vd
= INSTR (4, 0);
4321 unsigned full
= INSTR (30, 30);
4322 unsigned min
= INSTR (23, 23);
4325 NYI_assert (29, 24, 0x0E);
4326 NYI_assert (21, 21, 1);
4327 NYI_assert (15, 14, 3);
4328 NYI_assert (11, 10, 1);
4332 double (* func
)(double, double);
4337 if (INSTR (13, 12) == 0)
4338 func
= min
? dminnm
: dmaxnm
;
4339 else if (INSTR (13, 12) == 3)
4340 func
= min
? fmin
: fmax
;
4344 for (i
= 0; i
< 2; i
++)
4345 aarch64_set_vec_double (cpu
, vd
, i
,
4346 func (aarch64_get_vec_double (cpu
, vn
, i
),
4347 aarch64_get_vec_double (cpu
, vm
, i
)));
4351 float (* func
)(float, float);
4353 if (INSTR (13, 12) == 0)
4354 func
= min
? fminnm
: fmaxnm
;
4355 else if (INSTR (13, 12) == 3)
4356 func
= min
? fminf
: fmaxf
;
4360 for (i
= 0; i
< (full
? 4 : 2); i
++)
4361 aarch64_set_vec_float (cpu
, vd
, i
,
4362 func (aarch64_get_vec_float (cpu
, vn
, i
),
4363 aarch64_get_vec_float (cpu
, vm
, i
)));
4368 do_vec_SCVTF (sim_cpu
*cpu
)
4372 instr[29,23] = 00 1110 0
4373 instr[22] = float(0)/double(1)
4374 instr[21,10] = 10 0001 1101 10
4378 unsigned vn
= INSTR (9, 5);
4379 unsigned vd
= INSTR (4, 0);
4380 unsigned full
= INSTR (30, 30);
4381 unsigned size
= INSTR (22, 22);
4384 NYI_assert (29, 23, 0x1C);
4385 NYI_assert (21, 10, 0x876);
4392 for (i
= 0; i
< 2; i
++)
4394 double val
= (double) aarch64_get_vec_u64 (cpu
, vn
, i
);
4395 aarch64_set_vec_double (cpu
, vd
, i
, val
);
4400 for (i
= 0; i
< (full
? 4 : 2); i
++)
4402 float val
= (float) aarch64_get_vec_u32 (cpu
, vn
, i
);
4403 aarch64_set_vec_float (cpu
, vd
, i
, val
);
4408 #define VEC_CMP(SOURCE, CMP) \
4414 for (i = 0; i < (full ? 16 : 8); i++) \
4415 aarch64_set_vec_u8 (cpu, vd, i, \
4416 aarch64_get_vec_##SOURCE##8 (cpu, vn, i) \
4418 aarch64_get_vec_##SOURCE##8 (cpu, vm, i) \
4422 for (i = 0; i < (full ? 8 : 4); i++) \
4423 aarch64_set_vec_u16 (cpu, vd, i, \
4424 aarch64_get_vec_##SOURCE##16 (cpu, vn, i) \
4426 aarch64_get_vec_##SOURCE##16 (cpu, vm, i) \
4430 for (i = 0; i < (full ? 4 : 2); i++) \
4431 aarch64_set_vec_u32 (cpu, vd, i, \
4432 aarch64_get_vec_##SOURCE##32 (cpu, vn, i) \
4434 aarch64_get_vec_##SOURCE##32 (cpu, vm, i) \
4440 for (i = 0; i < 2; i++) \
4441 aarch64_set_vec_u64 (cpu, vd, i, \
4442 aarch64_get_vec_##SOURCE##64 (cpu, vn, i) \
4444 aarch64_get_vec_##SOURCE##64 (cpu, vm, i) \
4451 #define VEC_CMP0(SOURCE, CMP) \
4457 for (i = 0; i < (full ? 16 : 8); i++) \
4458 aarch64_set_vec_u8 (cpu, vd, i, \
4459 aarch64_get_vec_##SOURCE##8 (cpu, vn, i) \
4463 for (i = 0; i < (full ? 8 : 4); i++) \
4464 aarch64_set_vec_u16 (cpu, vd, i, \
4465 aarch64_get_vec_##SOURCE##16 (cpu, vn, i) \
4469 for (i = 0; i < (full ? 4 : 2); i++) \
4470 aarch64_set_vec_u32 (cpu, vd, i, \
4471 aarch64_get_vec_##SOURCE##32 (cpu, vn, i) \
4477 for (i = 0; i < 2; i++) \
4478 aarch64_set_vec_u64 (cpu, vd, i, \
4479 aarch64_get_vec_##SOURCE##64 (cpu, vn, i) \
4480 CMP 0 ? -1ULL : 0); \
4486 #define VEC_FCMP0(CMP) \
4491 if (INSTR (22, 22)) \
4495 for (i = 0; i < 2; i++) \
4496 aarch64_set_vec_u64 (cpu, vd, i, \
4497 aarch64_get_vec_double (cpu, vn, i) \
4498 CMP 0.0 ? -1 : 0); \
4502 for (i = 0; i < (full ? 4 : 2); i++) \
4503 aarch64_set_vec_u32 (cpu, vd, i, \
4504 aarch64_get_vec_float (cpu, vn, i) \
4505 CMP 0.0 ? -1 : 0); \
4511 #define VEC_FCMP(CMP) \
4514 if (INSTR (22, 22)) \
4518 for (i = 0; i < 2; i++) \
4519 aarch64_set_vec_u64 (cpu, vd, i, \
4520 aarch64_get_vec_double (cpu, vn, i) \
4522 aarch64_get_vec_double (cpu, vm, i) \
4527 for (i = 0; i < (full ? 4 : 2); i++) \
4528 aarch64_set_vec_u32 (cpu, vd, i, \
4529 aarch64_get_vec_float (cpu, vn, i) \
4531 aarch64_get_vec_float (cpu, vm, i) \
4539 do_vec_compare (sim_cpu
*cpu
)
4542 instr[30] = half(0)/full(1)
4543 instr[29] = part-of-comparison-type
4544 instr[28,24] = 0 1110
4545 instr[23,22] = size of integer compares: byte(00), half(01), word (10), long (11)
4546 type of float compares: single (-0) / double (-1)
4548 instr[20,16] = Vm or 00000 (compare vs 0)
4549 instr[15,10] = part-of-comparison-type
4553 int full
= INSTR (30, 30);
4554 int size
= INSTR (23, 22);
4555 unsigned vm
= INSTR (20, 16);
4556 unsigned vn
= INSTR (9, 5);
4557 unsigned vd
= INSTR (4, 0);
4560 NYI_assert (28, 24, 0x0E);
4561 NYI_assert (21, 21, 1);
4565 || ((INSTR (11, 11) == 0
4566 && INSTR (10, 10) == 0)))
4568 /* A compare vs 0. */
4571 if (INSTR (15, 10) == 0x2A)
4573 else if (INSTR (15, 10) == 0x32
4574 || INSTR (15, 10) == 0x3E)
4575 do_vec_fminmaxV (cpu
);
4576 else if (INSTR (29, 23) == 0x1C
4577 && INSTR (21, 10) == 0x876)
4587 /* A floating point compare. */
4588 unsigned decode
= (INSTR (29, 29) << 5) | (INSTR (23, 23) << 4)
4591 NYI_assert (15, 15, 1);
4595 case /* 0b010010: GT#0 */ 0x12: VEC_FCMP0 (>);
4596 case /* 0b110010: GE#0 */ 0x32: VEC_FCMP0 (>=);
4597 case /* 0b010110: EQ#0 */ 0x16: VEC_FCMP0 (==);
4598 case /* 0b110110: LE#0 */ 0x36: VEC_FCMP0 (<=);
4599 case /* 0b011010: LT#0 */ 0x1A: VEC_FCMP0 (<);
4600 case /* 0b111001: GT */ 0x39: VEC_FCMP (>);
4601 case /* 0b101001: GE */ 0x29: VEC_FCMP (>=);
4602 case /* 0b001001: EQ */ 0x09: VEC_FCMP (==);
4610 unsigned decode
= (INSTR (29, 29) << 6) | INSTR (15, 10);
4614 case 0x0D: /* 0001101 GT */ VEC_CMP (s
, > );
4615 case 0x0F: /* 0001111 GE */ VEC_CMP (s
, >= );
4616 case 0x22: /* 0100010 GT #0 */ VEC_CMP0 (s
, > );
4617 case 0x26: /* 0100110 EQ #0 */ VEC_CMP0 (s
, == );
4618 case 0x2A: /* 0101010 LT #0 */ VEC_CMP0 (s
, < );
4619 case 0x4D: /* 1001101 HI */ VEC_CMP (u
, > );
4620 case 0x4F: /* 1001111 HS */ VEC_CMP (u
, >= );
4621 case 0x62: /* 1100010 GE #0 */ VEC_CMP0 (s
, >= );
4622 case 0x63: /* 1100011 EQ */ VEC_CMP (u
, == );
4623 case 0x66: /* 1100110 LE #0 */ VEC_CMP0 (s
, <= );
4633 do_vec_SSHL (sim_cpu
*cpu
)
4636 instr[30] = first part (0)/ second part (1)
4637 instr[29,24] = 00 1110
4638 instr[23,22] = size: byte(00), half(01), word (10), long (11)
4641 instr[15,10] = 0100 01
4645 unsigned full
= INSTR (30, 30);
4646 unsigned vm
= INSTR (20, 16);
4647 unsigned vn
= INSTR (9, 5);
4648 unsigned vd
= INSTR (4, 0);
4652 NYI_assert (29, 24, 0x0E);
4653 NYI_assert (21, 21, 1);
4654 NYI_assert (15, 10, 0x11);
4656 /* FIXME: What is a signed shift left in this context ?. */
4658 switch (INSTR (23, 22))
4661 for (i
= 0; i
< (full
? 16 : 8); i
++)
4663 shift
= aarch64_get_vec_s8 (cpu
, vm
, i
);
4665 aarch64_set_vec_s8 (cpu
, vd
, i
, aarch64_get_vec_s8 (cpu
, vn
, i
)
4668 aarch64_set_vec_s8 (cpu
, vd
, i
, aarch64_get_vec_s8 (cpu
, vn
, i
)
4674 for (i
= 0; i
< (full
? 8 : 4); i
++)
4676 shift
= aarch64_get_vec_s8 (cpu
, vm
, i
* 2);
4678 aarch64_set_vec_s16 (cpu
, vd
, i
, aarch64_get_vec_s16 (cpu
, vn
, i
)
4681 aarch64_set_vec_s16 (cpu
, vd
, i
, aarch64_get_vec_s16 (cpu
, vn
, i
)
4687 for (i
= 0; i
< (full
? 4 : 2); i
++)
4689 shift
= aarch64_get_vec_s8 (cpu
, vm
, i
* 4);
4691 aarch64_set_vec_s32 (cpu
, vd
, i
, aarch64_get_vec_s32 (cpu
, vn
, i
)
4694 aarch64_set_vec_s32 (cpu
, vd
, i
, aarch64_get_vec_s32 (cpu
, vn
, i
)
4702 for (i
= 0; i
< 2; i
++)
4704 shift
= aarch64_get_vec_s8 (cpu
, vm
, i
* 8);
4706 aarch64_set_vec_s64 (cpu
, vd
, i
, aarch64_get_vec_s64 (cpu
, vn
, i
)
4709 aarch64_set_vec_s64 (cpu
, vd
, i
, aarch64_get_vec_s64 (cpu
, vn
, i
)
4717 do_vec_USHL (sim_cpu
*cpu
)
4720 instr[30] = first part (0)/ second part (1)
4721 instr[29,24] = 10 1110
4722 instr[23,22] = size: byte(00), half(01), word (10), long (11)
4725 instr[15,10] = 0100 01
4729 unsigned full
= INSTR (30, 30);
4730 unsigned vm
= INSTR (20, 16);
4731 unsigned vn
= INSTR (9, 5);
4732 unsigned vd
= INSTR (4, 0);
4736 NYI_assert (29, 24, 0x2E);
4737 NYI_assert (15, 10, 0x11);
4739 switch (INSTR (23, 22))
4742 for (i
= 0; i
< (full
? 16 : 8); i
++)
4744 shift
= aarch64_get_vec_s8 (cpu
, vm
, i
);
4746 aarch64_set_vec_u8 (cpu
, vd
, i
, aarch64_get_vec_u8 (cpu
, vn
, i
)
4749 aarch64_set_vec_u8 (cpu
, vd
, i
, aarch64_get_vec_u8 (cpu
, vn
, i
)
4755 for (i
= 0; i
< (full
? 8 : 4); i
++)
4757 shift
= aarch64_get_vec_s8 (cpu
, vm
, i
* 2);
4759 aarch64_set_vec_u16 (cpu
, vd
, i
, aarch64_get_vec_u16 (cpu
, vn
, i
)
4762 aarch64_set_vec_u16 (cpu
, vd
, i
, aarch64_get_vec_u16 (cpu
, vn
, i
)
4768 for (i
= 0; i
< (full
? 4 : 2); i
++)
4770 shift
= aarch64_get_vec_s8 (cpu
, vm
, i
* 4);
4772 aarch64_set_vec_u32 (cpu
, vd
, i
, aarch64_get_vec_u32 (cpu
, vn
, i
)
4775 aarch64_set_vec_u32 (cpu
, vd
, i
, aarch64_get_vec_u32 (cpu
, vn
, i
)
4783 for (i
= 0; i
< 2; i
++)
4785 shift
= aarch64_get_vec_s8 (cpu
, vm
, i
* 8);
4787 aarch64_set_vec_u64 (cpu
, vd
, i
, aarch64_get_vec_u64 (cpu
, vn
, i
)
4790 aarch64_set_vec_u64 (cpu
, vd
, i
, aarch64_get_vec_u64 (cpu
, vn
, i
)
4798 do_vec_FMLA (sim_cpu
*cpu
)
4801 instr[30] = full/half selector
4802 instr[29,23] = 0011100
4803 instr[22] = size: 0=>float, 1=>double
4806 instr[15,10] = 1100 11
4810 unsigned vm
= INSTR (20, 16);
4811 unsigned vn
= INSTR (9, 5);
4812 unsigned vd
= INSTR (4, 0);
4814 int full
= INSTR (30, 30);
4816 NYI_assert (29, 23, 0x1C);
4817 NYI_assert (21, 21, 1);
4818 NYI_assert (15, 10, 0x33);
4824 for (i
= 0; i
< 2; i
++)
4825 aarch64_set_vec_double (cpu
, vd
, i
,
4826 aarch64_get_vec_double (cpu
, vn
, i
) *
4827 aarch64_get_vec_double (cpu
, vm
, i
) +
4828 aarch64_get_vec_double (cpu
, vd
, i
));
4832 for (i
= 0; i
< (full
? 4 : 2); i
++)
4833 aarch64_set_vec_float (cpu
, vd
, i
,
4834 aarch64_get_vec_float (cpu
, vn
, i
) *
4835 aarch64_get_vec_float (cpu
, vm
, i
) +
4836 aarch64_get_vec_float (cpu
, vd
, i
));
4841 do_vec_max (sim_cpu
*cpu
)
4844 instr[30] = full/half selector
4845 instr[29] = SMAX (0) / UMAX (1)
4846 instr[28,24] = 0 1110
4847 instr[23,22] = size: 00=> 8-bit, 01=> 16-bit, 10=> 32-bit
4850 instr[15,10] = 0110 01
4854 unsigned vm
= INSTR (20, 16);
4855 unsigned vn
= INSTR (9, 5);
4856 unsigned vd
= INSTR (4, 0);
4858 int full
= INSTR (30, 30);
4860 NYI_assert (28, 24, 0x0E);
4861 NYI_assert (21, 21, 1);
4862 NYI_assert (15, 10, 0x19);
4866 switch (INSTR (23, 22))
4869 for (i
= 0; i
< (full
? 16 : 8); i
++)
4870 aarch64_set_vec_u8 (cpu
, vd
, i
,
4871 aarch64_get_vec_u8 (cpu
, vn
, i
)
4872 > aarch64_get_vec_u8 (cpu
, vm
, i
)
4873 ? aarch64_get_vec_u8 (cpu
, vn
, i
)
4874 : aarch64_get_vec_u8 (cpu
, vm
, i
));
4878 for (i
= 0; i
< (full
? 8 : 4); i
++)
4879 aarch64_set_vec_u16 (cpu
, vd
, i
,
4880 aarch64_get_vec_u16 (cpu
, vn
, i
)
4881 > aarch64_get_vec_u16 (cpu
, vm
, i
)
4882 ? aarch64_get_vec_u16 (cpu
, vn
, i
)
4883 : aarch64_get_vec_u16 (cpu
, vm
, i
));
4887 for (i
= 0; i
< (full
? 4 : 2); i
++)
4888 aarch64_set_vec_u32 (cpu
, vd
, i
,
4889 aarch64_get_vec_u32 (cpu
, vn
, i
)
4890 > aarch64_get_vec_u32 (cpu
, vm
, i
)
4891 ? aarch64_get_vec_u32 (cpu
, vn
, i
)
4892 : aarch64_get_vec_u32 (cpu
, vm
, i
));
4901 switch (INSTR (23, 22))
4904 for (i
= 0; i
< (full
? 16 : 8); i
++)
4905 aarch64_set_vec_s8 (cpu
, vd
, i
,
4906 aarch64_get_vec_s8 (cpu
, vn
, i
)
4907 > aarch64_get_vec_s8 (cpu
, vm
, i
)
4908 ? aarch64_get_vec_s8 (cpu
, vn
, i
)
4909 : aarch64_get_vec_s8 (cpu
, vm
, i
));
4913 for (i
= 0; i
< (full
? 8 : 4); i
++)
4914 aarch64_set_vec_s16 (cpu
, vd
, i
,
4915 aarch64_get_vec_s16 (cpu
, vn
, i
)
4916 > aarch64_get_vec_s16 (cpu
, vm
, i
)
4917 ? aarch64_get_vec_s16 (cpu
, vn
, i
)
4918 : aarch64_get_vec_s16 (cpu
, vm
, i
));
4922 for (i
= 0; i
< (full
? 4 : 2); i
++)
4923 aarch64_set_vec_s32 (cpu
, vd
, i
,
4924 aarch64_get_vec_s32 (cpu
, vn
, i
)
4925 > aarch64_get_vec_s32 (cpu
, vm
, i
)
4926 ? aarch64_get_vec_s32 (cpu
, vn
, i
)
4927 : aarch64_get_vec_s32 (cpu
, vm
, i
));
4937 do_vec_min (sim_cpu
*cpu
)
4940 instr[30] = full/half selector
4941 instr[29] = SMIN (0) / UMIN (1)
4942 instr[28,24] = 0 1110
4943 instr[23,22] = size: 00=> 8-bit, 01=> 16-bit, 10=> 32-bit
4946 instr[15,10] = 0110 11
4950 unsigned vm
= INSTR (20, 16);
4951 unsigned vn
= INSTR (9, 5);
4952 unsigned vd
= INSTR (4, 0);
4954 int full
= INSTR (30, 30);
4956 NYI_assert (28, 24, 0x0E);
4957 NYI_assert (21, 21, 1);
4958 NYI_assert (15, 10, 0x1B);
4962 switch (INSTR (23, 22))
4965 for (i
= 0; i
< (full
? 16 : 8); i
++)
4966 aarch64_set_vec_u8 (cpu
, vd
, i
,
4967 aarch64_get_vec_u8 (cpu
, vn
, i
)
4968 < aarch64_get_vec_u8 (cpu
, vm
, i
)
4969 ? aarch64_get_vec_u8 (cpu
, vn
, i
)
4970 : aarch64_get_vec_u8 (cpu
, vm
, i
));
4974 for (i
= 0; i
< (full
? 8 : 4); i
++)
4975 aarch64_set_vec_u16 (cpu
, vd
, i
,
4976 aarch64_get_vec_u16 (cpu
, vn
, i
)
4977 < aarch64_get_vec_u16 (cpu
, vm
, i
)
4978 ? aarch64_get_vec_u16 (cpu
, vn
, i
)
4979 : aarch64_get_vec_u16 (cpu
, vm
, i
));
4983 for (i
= 0; i
< (full
? 4 : 2); i
++)
4984 aarch64_set_vec_u32 (cpu
, vd
, i
,
4985 aarch64_get_vec_u32 (cpu
, vn
, i
)
4986 < aarch64_get_vec_u32 (cpu
, vm
, i
)
4987 ? aarch64_get_vec_u32 (cpu
, vn
, i
)
4988 : aarch64_get_vec_u32 (cpu
, vm
, i
));
4997 switch (INSTR (23, 22))
5000 for (i
= 0; i
< (full
? 16 : 8); i
++)
5001 aarch64_set_vec_s8 (cpu
, vd
, i
,
5002 aarch64_get_vec_s8 (cpu
, vn
, i
)
5003 < aarch64_get_vec_s8 (cpu
, vm
, i
)
5004 ? aarch64_get_vec_s8 (cpu
, vn
, i
)
5005 : aarch64_get_vec_s8 (cpu
, vm
, i
));
5009 for (i
= 0; i
< (full
? 8 : 4); i
++)
5010 aarch64_set_vec_s16 (cpu
, vd
, i
,
5011 aarch64_get_vec_s16 (cpu
, vn
, i
)
5012 < aarch64_get_vec_s16 (cpu
, vm
, i
)
5013 ? aarch64_get_vec_s16 (cpu
, vn
, i
)
5014 : aarch64_get_vec_s16 (cpu
, vm
, i
));
5018 for (i
= 0; i
< (full
? 4 : 2); i
++)
5019 aarch64_set_vec_s32 (cpu
, vd
, i
,
5020 aarch64_get_vec_s32 (cpu
, vn
, i
)
5021 < aarch64_get_vec_s32 (cpu
, vm
, i
)
5022 ? aarch64_get_vec_s32 (cpu
, vn
, i
)
5023 : aarch64_get_vec_s32 (cpu
, vm
, i
));
5033 do_vec_sub_long (sim_cpu
*cpu
)
5036 instr[30] = lower (0) / upper (1)
5037 instr[29] = signed (0) / unsigned (1)
5038 instr[28,24] = 0 1110
5039 instr[23,22] = size: bytes (00), half (01), word (10)
5042 instr[15,10] = 0010 00
5044 instr[4,0] = V dest. */
5046 unsigned size
= INSTR (23, 22);
5047 unsigned vm
= INSTR (20, 16);
5048 unsigned vn
= INSTR (9, 5);
5049 unsigned vd
= INSTR (4, 0);
5053 NYI_assert (28, 24, 0x0E);
5054 NYI_assert (21, 21, 1);
5055 NYI_assert (15, 10, 0x08);
5060 switch (INSTR (30, 29))
5062 case 2: /* SSUBL2. */
5064 case 0: /* SSUBL. */
5069 for (i
= 0; i
< 8; i
++)
5070 aarch64_set_vec_s16 (cpu
, vd
, i
,
5071 aarch64_get_vec_s8 (cpu
, vn
, i
+ bias
)
5072 - aarch64_get_vec_s8 (cpu
, vm
, i
+ bias
));
5077 for (i
= 0; i
< 4; i
++)
5078 aarch64_set_vec_s32 (cpu
, vd
, i
,
5079 aarch64_get_vec_s16 (cpu
, vn
, i
+ bias
)
5080 - aarch64_get_vec_s16 (cpu
, vm
, i
+ bias
));
5084 for (i
= 0; i
< 2; i
++)
5085 aarch64_set_vec_s64 (cpu
, vd
, i
,
5086 aarch64_get_vec_s32 (cpu
, vn
, i
+ bias
)
5087 - aarch64_get_vec_s32 (cpu
, vm
, i
+ bias
));
5095 case 3: /* USUBL2. */
5097 case 1: /* USUBL. */
5102 for (i
= 0; i
< 8; i
++)
5103 aarch64_set_vec_u16 (cpu
, vd
, i
,
5104 aarch64_get_vec_u8 (cpu
, vn
, i
+ bias
)
5105 - aarch64_get_vec_u8 (cpu
, vm
, i
+ bias
));
5110 for (i
= 0; i
< 4; i
++)
5111 aarch64_set_vec_u32 (cpu
, vd
, i
,
5112 aarch64_get_vec_u16 (cpu
, vn
, i
+ bias
)
5113 - aarch64_get_vec_u16 (cpu
, vm
, i
+ bias
));
5117 for (i
= 0; i
< 2; i
++)
5118 aarch64_set_vec_u64 (cpu
, vd
, i
,
5119 aarch64_get_vec_u32 (cpu
, vn
, i
+ bias
)
5120 - aarch64_get_vec_u32 (cpu
, vm
, i
+ bias
));
5131 do_vec_ADDP (sim_cpu
*cpu
)
5134 instr[30] = half(0)/full(1)
5135 instr[29,24] = 00 1110
5136 instr[23,22] = size: bytes (00), half (01), word (10), long (11)
5139 instr[15,10] = 1011 11
5141 instr[4,0] = V dest. */
5145 unsigned full
= INSTR (30, 30);
5146 unsigned size
= INSTR (23, 22);
5147 unsigned vm
= INSTR (20, 16);
5148 unsigned vn
= INSTR (9, 5);
5149 unsigned vd
= INSTR (4, 0);
5152 NYI_assert (29, 24, 0x0E);
5153 NYI_assert (21, 21, 1);
5154 NYI_assert (15, 10, 0x2F);
5156 /* Make copies of the source registers in case vd == vn/vm. */
5157 copy_vn
= cpu
->fr
[vn
];
5158 copy_vm
= cpu
->fr
[vm
];
5163 range
= full
? 8 : 4;
5164 for (i
= 0; i
< range
; i
++)
5166 aarch64_set_vec_u8 (cpu
, vd
, i
,
5167 copy_vn
.b
[i
* 2] + copy_vn
.b
[i
* 2 + 1]);
5168 aarch64_set_vec_u8 (cpu
, vd
, i
+ range
,
5169 copy_vm
.b
[i
* 2] + copy_vm
.b
[i
* 2 + 1]);
5174 range
= full
? 4 : 2;
5175 for (i
= 0; i
< range
; i
++)
5177 aarch64_set_vec_u16 (cpu
, vd
, i
,
5178 copy_vn
.h
[i
* 2] + copy_vn
.h
[i
* 2 + 1]);
5179 aarch64_set_vec_u16 (cpu
, vd
, i
+ range
,
5180 copy_vm
.h
[i
* 2] + copy_vm
.h
[i
* 2 + 1]);
5185 range
= full
? 2 : 1;
5186 for (i
= 0; i
< range
; i
++)
5188 aarch64_set_vec_u32 (cpu
, vd
, i
,
5189 copy_vn
.w
[i
* 2] + copy_vn
.w
[i
* 2 + 1]);
5190 aarch64_set_vec_u32 (cpu
, vd
, i
+ range
,
5191 copy_vm
.w
[i
* 2] + copy_vm
.w
[i
* 2 + 1]);
5198 aarch64_set_vec_u64 (cpu
, vd
, 0, copy_vn
.v
[0] + copy_vn
.v
[1]);
5199 aarch64_set_vec_u64 (cpu
, vd
, 1, copy_vm
.v
[0] + copy_vm
.v
[1]);
5205 do_vec_UMOV (sim_cpu
*cpu
)
5208 instr[30] = 32-bit(0)/64-bit(1)
5209 instr[29,21] = 00 1110 000
5210 insrt[20,16] = size & index
5211 instr[15,10] = 0011 11
5212 instr[9,5] = V source
5213 instr[4,0] = R dest. */
5215 unsigned vs
= INSTR (9, 5);
5216 unsigned rd
= INSTR (4, 0);
5219 NYI_assert (29, 21, 0x070);
5220 NYI_assert (15, 10, 0x0F);
5224 /* Byte transfer. */
5225 index
= INSTR (20, 17);
5226 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
,
5227 aarch64_get_vec_u8 (cpu
, vs
, index
));
5229 else if (INSTR (17, 17))
5231 index
= INSTR (20, 18);
5232 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
,
5233 aarch64_get_vec_u16 (cpu
, vs
, index
));
5235 else if (INSTR (18, 18))
5237 index
= INSTR (20, 19);
5238 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
,
5239 aarch64_get_vec_u32 (cpu
, vs
, index
));
5243 if (INSTR (30, 30) != 1)
5246 index
= INSTR (20, 20);
5247 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
,
5248 aarch64_get_vec_u64 (cpu
, vs
, index
));
5253 do_vec_FABS (sim_cpu
*cpu
)
5256 instr[30] = half(0)/full(1)
5257 instr[29,23] = 00 1110 1
5258 instr[22] = float(0)/double(1)
5259 instr[21,16] = 10 0000
5260 instr[15,10] = 1111 10
5264 unsigned vn
= INSTR (9, 5);
5265 unsigned vd
= INSTR (4, 0);
5266 unsigned full
= INSTR (30, 30);
5269 NYI_assert (29, 23, 0x1D);
5270 NYI_assert (21, 10, 0x83E);
5277 for (i
= 0; i
< 2; i
++)
5278 aarch64_set_vec_double (cpu
, vd
, i
,
5279 fabs (aarch64_get_vec_double (cpu
, vn
, i
)));
5283 for (i
= 0; i
< (full
? 4 : 2); i
++)
5284 aarch64_set_vec_float (cpu
, vd
, i
,
5285 fabsf (aarch64_get_vec_float (cpu
, vn
, i
)));
5290 do_vec_FCVTZS (sim_cpu
*cpu
)
5293 instr[30] = half (0) / all (1)
5294 instr[29,23] = 00 1110 1
5295 instr[22] = single (0) / double (1)
5296 instr[21,10] = 10 0001 1011 10
5300 unsigned rn
= INSTR (9, 5);
5301 unsigned rd
= INSTR (4, 0);
5302 unsigned full
= INSTR (30, 30);
5305 NYI_assert (31, 31, 0);
5306 NYI_assert (29, 23, 0x1D);
5307 NYI_assert (21, 10, 0x86E);
5314 for (i
= 0; i
< 2; i
++)
5315 aarch64_set_vec_s64 (cpu
, rd
, i
,
5316 (int64_t) aarch64_get_vec_double (cpu
, rn
, i
));
5319 for (i
= 0; i
< (full
? 4 : 2); i
++)
5320 aarch64_set_vec_s32 (cpu
, rd
, i
,
5321 (int32_t) aarch64_get_vec_float (cpu
, rn
, i
));
5325 do_vec_op1 (sim_cpu
*cpu
)
5328 instr[30] = half/full
5329 instr[29,24] = 00 1110
5332 instr[15,10] = sub-opcode
5335 NYI_assert (29, 24, 0x0E);
5337 if (INSTR (21, 21) == 0)
5339 if (INSTR (23, 22) == 0)
5341 if (INSTR (30, 30) == 1
5342 && INSTR (17, 14) == 0
5343 && INSTR (12, 10) == 7)
5344 return do_vec_ins_2 (cpu
);
5346 switch (INSTR (15, 10))
5348 case 0x01: do_vec_DUP_vector_into_vector (cpu
); return;
5349 case 0x03: do_vec_DUP_scalar_into_vector (cpu
); return;
5350 case 0x07: do_vec_INS (cpu
); return;
5351 case 0x0A: do_vec_TRN (cpu
); return;
5354 if (INSTR (17, 16) == 0)
5356 do_vec_MOV_into_scalar (cpu
);
5365 do_vec_TBL (cpu
); return;
5369 do_vec_UZP (cpu
); return;
5373 do_vec_ZIP (cpu
); return;
5380 switch (INSTR (13, 10))
5382 case 0x6: do_vec_UZP (cpu
); return;
5383 case 0xE: do_vec_ZIP (cpu
); return;
5384 case 0xA: do_vec_TRN (cpu
); return;
5385 case 0xF: do_vec_UMOV (cpu
); return;
5390 switch (INSTR (15, 10))
5393 switch (INSTR (23, 21))
5395 case 1: do_vec_AND (cpu
); return;
5396 case 3: do_vec_BIC (cpu
); return;
5397 case 5: do_vec_ORR (cpu
); return;
5398 case 7: do_vec_ORN (cpu
); return;
5402 case 0x08: do_vec_sub_long (cpu
); return;
5403 case 0x0a: do_vec_XTN (cpu
); return;
5404 case 0x11: do_vec_SSHL (cpu
); return;
5405 case 0x19: do_vec_max (cpu
); return;
5406 case 0x1B: do_vec_min (cpu
); return;
5407 case 0x21: do_vec_add (cpu
); return;
5408 case 0x25: do_vec_MLA (cpu
); return;
5409 case 0x27: do_vec_mul (cpu
); return;
5410 case 0x2F: do_vec_ADDP (cpu
); return;
5411 case 0x30: do_vec_mull (cpu
); return;
5412 case 0x33: do_vec_FMLA (cpu
); return;
5413 case 0x35: do_vec_fadd (cpu
); return;
5416 switch (INSTR (20, 16))
5418 case 0x00: do_vec_ABS (cpu
); return;
5419 case 0x01: do_vec_FCVTZS (cpu
); return;
5420 case 0x11: do_vec_ADDV (cpu
); return;
5426 do_vec_Fminmax (cpu
); return;
5438 do_vec_compare (cpu
); return;
5441 do_vec_FABS (cpu
); return;
5449 do_vec_xtl (sim_cpu
*cpu
)
5452 instr[30,29] = SXTL (00), UXTL (01), SXTL2 (10), UXTL2 (11)
5453 instr[28,22] = 0 1111 00
5454 instr[21,16] = size & shift (USHLL, SSHLL, USHLL2, SSHLL2)
5455 instr[15,10] = 1010 01
5456 instr[9,5] = V source
5457 instr[4,0] = V dest. */
5459 unsigned vs
= INSTR (9, 5);
5460 unsigned vd
= INSTR (4, 0);
5461 unsigned i
, shift
, bias
= 0;
5463 NYI_assert (28, 22, 0x3C);
5464 NYI_assert (15, 10, 0x29);
5466 switch (INSTR (30, 29))
5468 case 2: /* SXTL2, SSHLL2. */
5470 case 0: /* SXTL, SSHLL. */
5475 shift
= INSTR (20, 16);
5476 /* Get the source values before setting the destination values
5477 in case the source and destination are the same. */
5478 val1
= aarch64_get_vec_s32 (cpu
, vs
, bias
) << shift
;
5479 val2
= aarch64_get_vec_s32 (cpu
, vs
, bias
+ 1) << shift
;
5480 aarch64_set_vec_s64 (cpu
, vd
, 0, val1
);
5481 aarch64_set_vec_s64 (cpu
, vd
, 1, val2
);
5483 else if (INSTR (20, 20))
5486 int32_t v1
,v2
,v3
,v4
;
5488 shift
= INSTR (19, 16);
5490 for (i
= 0; i
< 4; i
++)
5491 v
[i
] = aarch64_get_vec_s16 (cpu
, vs
, bias
+ i
) << shift
;
5492 for (i
= 0; i
< 4; i
++)
5493 aarch64_set_vec_s32 (cpu
, vd
, i
, v
[i
]);
5498 NYI_assert (19, 19, 1);
5500 shift
= INSTR (18, 16);
5502 for (i
= 0; i
< 8; i
++)
5503 v
[i
] = aarch64_get_vec_s8 (cpu
, vs
, i
+ bias
) << shift
;
5504 for (i
= 0; i
< 8; i
++)
5505 aarch64_set_vec_s16 (cpu
, vd
, i
, v
[i
]);
5509 case 3: /* UXTL2, USHLL2. */
5511 case 1: /* UXTL, USHLL. */
5515 shift
= INSTR (20, 16);
5516 v1
= aarch64_get_vec_u32 (cpu
, vs
, bias
) << shift
;
5517 v2
= aarch64_get_vec_u32 (cpu
, vs
, bias
+ 1) << shift
;
5518 aarch64_set_vec_u64 (cpu
, vd
, 0, v1
);
5519 aarch64_set_vec_u64 (cpu
, vd
, 1, v2
);
5521 else if (INSTR (20, 20))
5524 shift
= INSTR (19, 16);
5526 for (i
= 0; i
< 4; i
++)
5527 v
[i
] = aarch64_get_vec_u16 (cpu
, vs
, i
+ bias
) << shift
;
5528 for (i
= 0; i
< 4; i
++)
5529 aarch64_set_vec_u32 (cpu
, vd
, i
, v
[i
]);
5534 NYI_assert (19, 19, 1);
5536 shift
= INSTR (18, 16);
5538 for (i
= 0; i
< 8; i
++)
5539 v
[i
] = aarch64_get_vec_u8 (cpu
, vs
, i
+ bias
) << shift
;
5540 for (i
= 0; i
< 8; i
++)
5541 aarch64_set_vec_u16 (cpu
, vd
, i
, v
[i
]);
5548 do_vec_SHL (sim_cpu
*cpu
)
5551 instr [30] = half(0)/full(1)
5552 instr [29,23] = 001 1110
5553 instr [22,16] = size and shift amount
5554 instr [15,10] = 01 0101
5556 instr [4, 0] = Vd. */
5559 int full
= INSTR (30, 30);
5560 unsigned vs
= INSTR (9, 5);
5561 unsigned vd
= INSTR (4, 0);
5564 NYI_assert (29, 23, 0x1E);
5565 NYI_assert (15, 10, 0x15);
5569 shift
= INSTR (21, 16);
5574 for (i
= 0; i
< 2; i
++)
5576 uint64_t val
= aarch64_get_vec_u64 (cpu
, vs
, i
);
5577 aarch64_set_vec_u64 (cpu
, vd
, i
, val
<< shift
);
5585 shift
= INSTR (20, 16);
5587 for (i
= 0; i
< (full
? 4 : 2); i
++)
5589 uint32_t val
= aarch64_get_vec_u32 (cpu
, vs
, i
);
5590 aarch64_set_vec_u32 (cpu
, vd
, i
, val
<< shift
);
5598 shift
= INSTR (19, 16);
5600 for (i
= 0; i
< (full
? 8 : 4); i
++)
5602 uint16_t val
= aarch64_get_vec_u16 (cpu
, vs
, i
);
5603 aarch64_set_vec_u16 (cpu
, vd
, i
, val
<< shift
);
5609 if (INSTR (19, 19) == 0)
5612 shift
= INSTR (18, 16);
5614 for (i
= 0; i
< (full
? 16 : 8); i
++)
5616 uint8_t val
= aarch64_get_vec_u8 (cpu
, vs
, i
);
5617 aarch64_set_vec_u8 (cpu
, vd
, i
, val
<< shift
);
5622 do_vec_SSHR_USHR (sim_cpu
*cpu
)
5625 instr [30] = half(0)/full(1)
5626 instr [29] = signed(0)/unsigned(1)
5627 instr [28,23] = 0 1111 0
5628 instr [22,16] = size and shift amount
5629 instr [15,10] = 0000 01
5631 instr [4, 0] = Vd. */
5633 int full
= INSTR (30, 30);
5634 int sign
= ! INSTR (29, 29);
5635 unsigned shift
= INSTR (22, 16);
5636 unsigned vs
= INSTR (9, 5);
5637 unsigned vd
= INSTR (4, 0);
5640 NYI_assert (28, 23, 0x1E);
5641 NYI_assert (15, 10, 0x01);
5645 shift
= 128 - shift
;
5651 for (i
= 0; i
< 2; i
++)
5653 int64_t val
= aarch64_get_vec_s64 (cpu
, vs
, i
);
5654 aarch64_set_vec_s64 (cpu
, vd
, i
, val
>> shift
);
5657 for (i
= 0; i
< 2; i
++)
5659 uint64_t val
= aarch64_get_vec_u64 (cpu
, vs
, i
);
5660 aarch64_set_vec_u64 (cpu
, vd
, i
, val
>> shift
);
5671 for (i
= 0; i
< (full
? 4 : 2); i
++)
5673 int32_t val
= aarch64_get_vec_s32 (cpu
, vs
, i
);
5674 aarch64_set_vec_s32 (cpu
, vd
, i
, val
>> shift
);
5677 for (i
= 0; i
< (full
? 4 : 2); i
++)
5679 uint32_t val
= aarch64_get_vec_u32 (cpu
, vs
, i
);
5680 aarch64_set_vec_u32 (cpu
, vd
, i
, val
>> shift
);
5691 for (i
= 0; i
< (full
? 8 : 4); i
++)
5693 int16_t val
= aarch64_get_vec_s16 (cpu
, vs
, i
);
5694 aarch64_set_vec_s16 (cpu
, vd
, i
, val
>> shift
);
5697 for (i
= 0; i
< (full
? 8 : 4); i
++)
5699 uint16_t val
= aarch64_get_vec_u16 (cpu
, vs
, i
);
5700 aarch64_set_vec_u16 (cpu
, vd
, i
, val
>> shift
);
5706 if (INSTR (19, 19) == 0)
5712 for (i
= 0; i
< (full
? 16 : 8); i
++)
5714 int8_t val
= aarch64_get_vec_s8 (cpu
, vs
, i
);
5715 aarch64_set_vec_s8 (cpu
, vd
, i
, val
>> shift
);
5718 for (i
= 0; i
< (full
? 16 : 8); i
++)
5720 uint8_t val
= aarch64_get_vec_u8 (cpu
, vs
, i
);
5721 aarch64_set_vec_u8 (cpu
, vd
, i
, val
>> shift
);
5726 do_vec_MUL_by_element (sim_cpu
*cpu
)
5729 instr[30] = half/full
5730 instr[29,24] = 00 1111
5741 unsigned full
= INSTR (30, 30);
5742 unsigned L
= INSTR (21, 21);
5743 unsigned H
= INSTR (11, 11);
5744 unsigned vn
= INSTR (9, 5);
5745 unsigned vd
= INSTR (4, 0);
5746 unsigned size
= INSTR (23, 22);
5751 NYI_assert (29, 24, 0x0F);
5752 NYI_assert (15, 12, 0x8);
5753 NYI_assert (10, 10, 0);
5759 /* 16 bit products. */
5764 index
= (H
<< 2) | (L
<< 1) | INSTR (20, 20);
5765 vm
= INSTR (19, 16);
5766 element2
= aarch64_get_vec_u16 (cpu
, vm
, index
);
5768 for (e
= 0; e
< (full
? 8 : 4); e
++)
5770 element1
= aarch64_get_vec_u16 (cpu
, vn
, e
);
5771 product
= element1
* element2
;
5772 aarch64_set_vec_u16 (cpu
, vd
, e
, product
);
5779 /* 32 bit products. */
5784 index
= (H
<< 1) | L
;
5785 vm
= INSTR (20, 16);
5786 element2
= aarch64_get_vec_u32 (cpu
, vm
, index
);
5788 for (e
= 0; e
< (full
? 4 : 2); e
++)
5790 element1
= aarch64_get_vec_u32 (cpu
, vn
, e
);
5791 product
= element1
* element2
;
5792 aarch64_set_vec_u32 (cpu
, vd
, e
, product
);
5803 do_vec_op2 (sim_cpu
*cpu
)
5806 instr[30] = half/full
5807 instr[29,24] = 00 1111
5809 instr[22,16] = element size & index
5810 instr[15,10] = sub-opcode
5814 NYI_assert (29, 24, 0x0F);
5816 if (INSTR (23, 23) != 0)
5818 switch (INSTR (15, 10))
5821 case 0x22: do_vec_MUL_by_element (cpu
); return;
5827 switch (INSTR (15, 10))
5829 case 0x01: do_vec_SSHR_USHR (cpu
); return;
5830 case 0x15: do_vec_SHL (cpu
); return;
5832 case 0x22: do_vec_MUL_by_element (cpu
); return;
5833 case 0x29: do_vec_xtl (cpu
); return;
5840 do_vec_neg (sim_cpu
*cpu
)
5843 instr[30] = full(1)/half(0)
5844 instr[29,24] = 10 1110
5845 instr[23,22] = size: byte(00), half (01), word (10), long (11)
5846 instr[21,10] = 1000 0010 1110
5850 int full
= INSTR (30, 30);
5851 unsigned vs
= INSTR (9, 5);
5852 unsigned vd
= INSTR (4, 0);
5855 NYI_assert (29, 24, 0x2E);
5856 NYI_assert (21, 10, 0x82E);
5858 switch (INSTR (23, 22))
5861 for (i
= 0; i
< (full
? 16 : 8); i
++)
5862 aarch64_set_vec_s8 (cpu
, vd
, i
, - aarch64_get_vec_s8 (cpu
, vs
, i
));
5866 for (i
= 0; i
< (full
? 8 : 4); i
++)
5867 aarch64_set_vec_s16 (cpu
, vd
, i
, - aarch64_get_vec_s16 (cpu
, vs
, i
));
5871 for (i
= 0; i
< (full
? 4 : 2); i
++)
5872 aarch64_set_vec_s32 (cpu
, vd
, i
, - aarch64_get_vec_s32 (cpu
, vs
, i
));
5878 for (i
= 0; i
< 2; i
++)
5879 aarch64_set_vec_s64 (cpu
, vd
, i
, - aarch64_get_vec_s64 (cpu
, vs
, i
));
5885 do_vec_sqrt (sim_cpu
*cpu
)
5888 instr[30] = full(1)/half(0)
5889 instr[29,23] = 101 1101
5890 instr[22] = single(0)/double(1)
5891 instr[21,10] = 1000 0111 1110
5895 int full
= INSTR (30, 30);
5896 unsigned vs
= INSTR (9, 5);
5897 unsigned vd
= INSTR (4, 0);
5900 NYI_assert (29, 23, 0x5B);
5901 NYI_assert (21, 10, 0x87E);
5903 if (INSTR (22, 22) == 0)
5904 for (i
= 0; i
< (full
? 4 : 2); i
++)
5905 aarch64_set_vec_float (cpu
, vd
, i
,
5906 sqrtf (aarch64_get_vec_float (cpu
, vs
, i
)));
5908 for (i
= 0; i
< 2; i
++)
5909 aarch64_set_vec_double (cpu
, vd
, i
,
5910 sqrt (aarch64_get_vec_double (cpu
, vs
, i
)));
5914 do_vec_mls_indexed (sim_cpu
*cpu
)
5917 instr[30] = half(0)/full(1)
5918 instr[29,24] = 10 1111
5919 instr[23,22] = 16-bit(01)/32-bit(10)
5920 instr[21,20+11] = index (if 16-bit)
5921 instr[21+11] = index (if 32-bit)
5924 instr[11] = part of index
5929 int full
= INSTR (30, 30);
5930 unsigned vs
= INSTR (9, 5);
5931 unsigned vd
= INSTR (4, 0);
5932 unsigned vm
= INSTR (20, 16);
5935 NYI_assert (15, 12, 4);
5936 NYI_assert (10, 10, 0);
5938 switch (INSTR (23, 22))
5948 elem
= (INSTR (21, 20) << 1) | INSTR (11, 11);
5949 val
= aarch64_get_vec_u16 (cpu
, vm
, elem
);
5951 for (i
= 0; i
< (full
? 8 : 4); i
++)
5952 aarch64_set_vec_u32 (cpu
, vd
, i
,
5953 aarch64_get_vec_u32 (cpu
, vd
, i
) -
5954 (aarch64_get_vec_u32 (cpu
, vs
, i
) * val
));
5960 unsigned elem
= (INSTR (21, 21) << 1) | INSTR (11, 11);
5961 uint64_t val
= aarch64_get_vec_u32 (cpu
, vm
, elem
);
5963 for (i
= 0; i
< (full
? 4 : 2); i
++)
5964 aarch64_set_vec_u64 (cpu
, vd
, i
,
5965 aarch64_get_vec_u64 (cpu
, vd
, i
) -
5966 (aarch64_get_vec_u64 (cpu
, vs
, i
) * val
));
5978 do_vec_SUB (sim_cpu
*cpu
)
5981 instr [30] = half(0)/full(1)
5982 instr [29,24] = 10 1110
5983 instr [23,22] = size: byte(00, half(01), word (10), long (11)
5986 instr [15,10] = 10 0001
5988 instr [4, 0] = Vd. */
5990 unsigned full
= INSTR (30, 30);
5991 unsigned vm
= INSTR (20, 16);
5992 unsigned vn
= INSTR (9, 5);
5993 unsigned vd
= INSTR (4, 0);
5996 NYI_assert (29, 24, 0x2E);
5997 NYI_assert (21, 21, 1);
5998 NYI_assert (15, 10, 0x21);
6000 switch (INSTR (23, 22))
6003 for (i
= 0; i
< (full
? 16 : 8); i
++)
6004 aarch64_set_vec_s8 (cpu
, vd
, i
,
6005 aarch64_get_vec_s8 (cpu
, vn
, i
)
6006 - aarch64_get_vec_s8 (cpu
, vm
, i
));
6010 for (i
= 0; i
< (full
? 8 : 4); i
++)
6011 aarch64_set_vec_s16 (cpu
, vd
, i
,
6012 aarch64_get_vec_s16 (cpu
, vn
, i
)
6013 - aarch64_get_vec_s16 (cpu
, vm
, i
));
6017 for (i
= 0; i
< (full
? 4 : 2); i
++)
6018 aarch64_set_vec_s32 (cpu
, vd
, i
,
6019 aarch64_get_vec_s32 (cpu
, vn
, i
)
6020 - aarch64_get_vec_s32 (cpu
, vm
, i
));
6027 for (i
= 0; i
< 2; i
++)
6028 aarch64_set_vec_s64 (cpu
, vd
, i
,
6029 aarch64_get_vec_s64 (cpu
, vn
, i
)
6030 - aarch64_get_vec_s64 (cpu
, vm
, i
));
6036 do_vec_MLS (sim_cpu
*cpu
)
6039 instr [30] = half(0)/full(1)
6040 instr [29,24] = 10 1110
6041 instr [23,22] = size: byte(00, half(01), word (10)
6044 instr [15,10] = 10 0101
6046 instr [4, 0] = Vd. */
6048 unsigned full
= INSTR (30, 30);
6049 unsigned vm
= INSTR (20, 16);
6050 unsigned vn
= INSTR (9, 5);
6051 unsigned vd
= INSTR (4, 0);
6054 NYI_assert (29, 24, 0x2E);
6055 NYI_assert (21, 21, 1);
6056 NYI_assert (15, 10, 0x25);
6058 switch (INSTR (23, 22))
6061 for (i
= 0; i
< (full
? 16 : 8); i
++)
6062 aarch64_set_vec_u8 (cpu
, vd
, i
,
6063 (aarch64_get_vec_u8 (cpu
, vn
, i
)
6064 * aarch64_get_vec_u8 (cpu
, vm
, i
))
6065 - aarch64_get_vec_u8 (cpu
, vd
, i
));
6069 for (i
= 0; i
< (full
? 8 : 4); i
++)
6070 aarch64_set_vec_u16 (cpu
, vd
, i
,
6071 (aarch64_get_vec_u16 (cpu
, vn
, i
)
6072 * aarch64_get_vec_u16 (cpu
, vm
, i
))
6073 - aarch64_get_vec_u16 (cpu
, vd
, i
));
6077 for (i
= 0; i
< (full
? 4 : 2); i
++)
6078 aarch64_set_vec_u32 (cpu
, vd
, i
,
6079 (aarch64_get_vec_u32 (cpu
, vn
, i
)
6080 * aarch64_get_vec_u32 (cpu
, vm
, i
))
6081 - aarch64_get_vec_u32 (cpu
, vd
, i
));
6090 do_vec_FDIV (sim_cpu
*cpu
)
6093 instr [30] = half(0)/full(1)
6094 instr [29,23] = 10 1110 0
6095 instr [22] = float()/double(1)
6098 instr [15,10] = 1111 11
6100 instr [4, 0] = Vd. */
6102 unsigned full
= INSTR (30, 30);
6103 unsigned vm
= INSTR (20, 16);
6104 unsigned vn
= INSTR (9, 5);
6105 unsigned vd
= INSTR (4, 0);
6108 NYI_assert (29, 23, 0x5C);
6109 NYI_assert (21, 21, 1);
6110 NYI_assert (15, 10, 0x3F);
6117 for (i
= 0; i
< 2; i
++)
6118 aarch64_set_vec_double (cpu
, vd
, i
,
6119 aarch64_get_vec_double (cpu
, vn
, i
)
6120 / aarch64_get_vec_double (cpu
, vm
, i
));
6123 for (i
= 0; i
< (full
? 4 : 2); i
++)
6124 aarch64_set_vec_float (cpu
, vd
, i
,
6125 aarch64_get_vec_float (cpu
, vn
, i
)
6126 / aarch64_get_vec_float (cpu
, vm
, i
));
6130 do_vec_FMUL (sim_cpu
*cpu
)
6133 instr [30] = half(0)/full(1)
6134 instr [29,23] = 10 1110 0
6135 instr [22] = float(0)/double(1)
6138 instr [15,10] = 1101 11
6140 instr [4, 0] = Vd. */
6142 unsigned full
= INSTR (30, 30);
6143 unsigned vm
= INSTR (20, 16);
6144 unsigned vn
= INSTR (9, 5);
6145 unsigned vd
= INSTR (4, 0);
6148 NYI_assert (29, 23, 0x5C);
6149 NYI_assert (21, 21, 1);
6150 NYI_assert (15, 10, 0x37);
6157 for (i
= 0; i
< 2; i
++)
6158 aarch64_set_vec_double (cpu
, vd
, i
,
6159 aarch64_get_vec_double (cpu
, vn
, i
)
6160 * aarch64_get_vec_double (cpu
, vm
, i
));
6163 for (i
= 0; i
< (full
? 4 : 2); i
++)
6164 aarch64_set_vec_float (cpu
, vd
, i
,
6165 aarch64_get_vec_float (cpu
, vn
, i
)
6166 * aarch64_get_vec_float (cpu
, vm
, i
));
6170 do_vec_FADDP (sim_cpu
*cpu
)
6173 instr [30] = half(0)/full(1)
6174 instr [29,23] = 10 1110 0
6175 instr [22] = float(0)/double(1)
6178 instr [15,10] = 1101 01
6180 instr [4, 0] = Vd. */
6182 unsigned full
= INSTR (30, 30);
6183 unsigned vm
= INSTR (20, 16);
6184 unsigned vn
= INSTR (9, 5);
6185 unsigned vd
= INSTR (4, 0);
6187 NYI_assert (29, 23, 0x5C);
6188 NYI_assert (21, 21, 1);
6189 NYI_assert (15, 10, 0x35);
6193 /* Extract values before adding them incase vd == vn/vm. */
6194 double tmp1
= aarch64_get_vec_double (cpu
, vn
, 0);
6195 double tmp2
= aarch64_get_vec_double (cpu
, vn
, 1);
6196 double tmp3
= aarch64_get_vec_double (cpu
, vm
, 0);
6197 double tmp4
= aarch64_get_vec_double (cpu
, vm
, 1);
6202 aarch64_set_vec_double (cpu
, vd
, 0, tmp1
+ tmp2
);
6203 aarch64_set_vec_double (cpu
, vd
, 1, tmp3
+ tmp4
);
6207 /* Extract values before adding them incase vd == vn/vm. */
6208 float tmp1
= aarch64_get_vec_float (cpu
, vn
, 0);
6209 float tmp2
= aarch64_get_vec_float (cpu
, vn
, 1);
6210 float tmp5
= aarch64_get_vec_float (cpu
, vm
, 0);
6211 float tmp6
= aarch64_get_vec_float (cpu
, vm
, 1);
6215 float tmp3
= aarch64_get_vec_float (cpu
, vn
, 2);
6216 float tmp4
= aarch64_get_vec_float (cpu
, vn
, 3);
6217 float tmp7
= aarch64_get_vec_float (cpu
, vm
, 2);
6218 float tmp8
= aarch64_get_vec_float (cpu
, vm
, 3);
6220 aarch64_set_vec_float (cpu
, vd
, 0, tmp1
+ tmp2
);
6221 aarch64_set_vec_float (cpu
, vd
, 1, tmp3
+ tmp4
);
6222 aarch64_set_vec_float (cpu
, vd
, 2, tmp5
+ tmp6
);
6223 aarch64_set_vec_float (cpu
, vd
, 3, tmp7
+ tmp8
);
6227 aarch64_set_vec_float (cpu
, vd
, 0, tmp1
+ tmp2
);
6228 aarch64_set_vec_float (cpu
, vd
, 1, tmp5
+ tmp6
);
6234 do_vec_FSQRT (sim_cpu
*cpu
)
6237 instr[30] = half(0)/full(1)
6238 instr[29,23] = 10 1110 1
6239 instr[22] = single(0)/double(1)
6240 instr[21,10] = 10 0001 1111 10
6242 instr[4,0] = Vdest. */
6244 unsigned vn
= INSTR (9, 5);
6245 unsigned vd
= INSTR (4, 0);
6246 unsigned full
= INSTR (30, 30);
6249 NYI_assert (29, 23, 0x5D);
6250 NYI_assert (21, 10, 0x87E);
6257 for (i
= 0; i
< 2; i
++)
6258 aarch64_set_vec_double (cpu
, vd
, i
,
6259 sqrt (aarch64_get_vec_double (cpu
, vn
, i
)));
6263 for (i
= 0; i
< (full
? 4 : 2); i
++)
6264 aarch64_set_vec_float (cpu
, vd
, i
,
6265 sqrtf (aarch64_get_vec_float (cpu
, vn
, i
)));
6270 do_vec_FNEG (sim_cpu
*cpu
)
6273 instr[30] = half (0)/full (1)
6274 instr[29,23] = 10 1110 1
6275 instr[22] = single (0)/double (1)
6276 instr[21,10] = 10 0000 1111 10
6278 instr[4,0] = Vdest. */
6280 unsigned vn
= INSTR (9, 5);
6281 unsigned vd
= INSTR (4, 0);
6282 unsigned full
= INSTR (30, 30);
6285 NYI_assert (29, 23, 0x5D);
6286 NYI_assert (21, 10, 0x83E);
6293 for (i
= 0; i
< 2; i
++)
6294 aarch64_set_vec_double (cpu
, vd
, i
,
6295 - aarch64_get_vec_double (cpu
, vn
, i
));
6299 for (i
= 0; i
< (full
? 4 : 2); i
++)
6300 aarch64_set_vec_float (cpu
, vd
, i
,
6301 - aarch64_get_vec_float (cpu
, vn
, i
));
6306 do_vec_NOT (sim_cpu
*cpu
)
6309 instr[30] = half (0)/full (1)
6310 instr[29,10] = 10 1110 0010 0000 0101 10
6314 unsigned vn
= INSTR (9, 5);
6315 unsigned vd
= INSTR (4, 0);
6317 int full
= INSTR (30, 30);
6319 NYI_assert (29, 10, 0xB8816);
6321 for (i
= 0; i
< (full
? 16 : 8); i
++)
6322 aarch64_set_vec_u8 (cpu
, vd
, i
, ~ aarch64_get_vec_u8 (cpu
, vn
, i
));
6326 clz (uint64_t val
, unsigned size
)
6331 mask
<<= (size
- 1);
6346 do_vec_CLZ (sim_cpu
*cpu
)
6349 instr[30] = half (0)/full (1)
6350 instr[29,24] = 10 1110
6352 instr[21,10] = 10 0000 0100 10
6356 unsigned vn
= INSTR (9, 5);
6357 unsigned vd
= INSTR (4, 0);
6359 int full
= INSTR (30,30);
6361 NYI_assert (29, 24, 0x2E);
6362 NYI_assert (21, 10, 0x812);
6364 switch (INSTR (23, 22))
6367 for (i
= 0; i
< (full
? 16 : 8); i
++)
6368 aarch64_set_vec_u8 (cpu
, vd
, i
, clz (aarch64_get_vec_u8 (cpu
, vn
, i
), 8));
6371 for (i
= 0; i
< (full
? 8 : 4); i
++)
6372 aarch64_set_vec_u16 (cpu
, vd
, i
, clz (aarch64_get_vec_u16 (cpu
, vn
, i
), 16));
6375 for (i
= 0; i
< (full
? 4 : 2); i
++)
6376 aarch64_set_vec_u32 (cpu
, vd
, i
, clz (aarch64_get_vec_u32 (cpu
, vn
, i
), 32));
6381 aarch64_set_vec_u64 (cpu
, vd
, 0, clz (aarch64_get_vec_u64 (cpu
, vn
, 0), 64));
6382 aarch64_set_vec_u64 (cpu
, vd
, 1, clz (aarch64_get_vec_u64 (cpu
, vn
, 1), 64));
6388 do_vec_MOV_element (sim_cpu
*cpu
)
6390 /* instr[31,21] = 0110 1110 000
6391 instr[20,16] = size & dest index
6393 instr[14,11] = source index
6398 unsigned vs
= INSTR (9, 5);
6399 unsigned vd
= INSTR (4, 0);
6403 NYI_assert (31, 21, 0x370);
6404 NYI_assert (15, 15, 0);
6405 NYI_assert (10, 10, 1);
6410 src_index
= INSTR (14, 11);
6411 dst_index
= INSTR (20, 17);
6412 aarch64_set_vec_u8 (cpu
, vd
, dst_index
,
6413 aarch64_get_vec_u8 (cpu
, vs
, src_index
));
6415 else if (INSTR (17, 17))
6418 NYI_assert (11, 11, 0);
6419 src_index
= INSTR (14, 12);
6420 dst_index
= INSTR (20, 18);
6421 aarch64_set_vec_u16 (cpu
, vd
, dst_index
,
6422 aarch64_get_vec_u16 (cpu
, vs
, src_index
));
6424 else if (INSTR (18, 18))
6427 NYI_assert (12, 11, 0);
6428 src_index
= INSTR (14, 13);
6429 dst_index
= INSTR (20, 19);
6430 aarch64_set_vec_u32 (cpu
, vd
, dst_index
,
6431 aarch64_get_vec_u32 (cpu
, vs
, src_index
));
6435 NYI_assert (19, 19, 1);
6436 NYI_assert (13, 11, 0);
6437 src_index
= INSTR (14, 14);
6438 dst_index
= INSTR (20, 20);
6439 aarch64_set_vec_u64 (cpu
, vd
, dst_index
,
6440 aarch64_get_vec_u64 (cpu
, vs
, src_index
));
6445 dexAdvSIMD0 (sim_cpu
*cpu
)
6447 /* instr [28,25] = 0 111. */
6448 if ( INSTR (15, 10) == 0x07
6452 if (INSTR (31, 21) == 0x075
6453 || INSTR (31, 21) == 0x275)
6455 do_vec_MOV_whole_vector (cpu
);
6460 if (INSTR (29, 19) == 0x1E0)
6462 do_vec_MOV_immediate (cpu
);
6466 if (INSTR (29, 19) == 0x5E0)
6472 if (INSTR (29, 19) == 0x1C0
6473 || INSTR (29, 19) == 0x1C1)
6475 if (INSTR (15, 10) == 0x03)
6477 do_vec_DUP_scalar_into_vector (cpu
);
6482 switch (INSTR (29, 24))
6484 case 0x0E: do_vec_op1 (cpu
); return;
6485 case 0x0F: do_vec_op2 (cpu
); return;
6488 switch (INSTR (15, 10))
6490 case 0x01: do_vec_SSHR_USHR (cpu
); return;
6492 case 0x12: do_vec_mls_indexed (cpu
); return;
6493 case 0x29: do_vec_xtl (cpu
); return;
6499 if (INSTR (21, 21) == 1)
6501 switch (INSTR (15, 10))
6504 switch (INSTR (23, 22))
6506 case 0: do_vec_EOR (cpu
); return;
6507 case 1: do_vec_BSL (cpu
); return;
6509 case 3: do_vec_bit (cpu
); return;
6513 case 0x08: do_vec_sub_long (cpu
); return;
6514 case 0x11: do_vec_USHL (cpu
); return;
6515 case 0x12: do_vec_CLZ (cpu
); return;
6516 case 0x16: do_vec_NOT (cpu
); return;
6517 case 0x19: do_vec_max (cpu
); return;
6518 case 0x1B: do_vec_min (cpu
); return;
6519 case 0x21: do_vec_SUB (cpu
); return;
6520 case 0x25: do_vec_MLS (cpu
); return;
6521 case 0x31: do_vec_FminmaxNMP (cpu
); return;
6522 case 0x35: do_vec_FADDP (cpu
); return;
6523 case 0x37: do_vec_FMUL (cpu
); return;
6524 case 0x3F: do_vec_FDIV (cpu
); return;
6527 switch (INSTR (20, 16))
6529 case 0x00: do_vec_FNEG (cpu
); return;
6530 case 0x01: do_vec_FSQRT (cpu
); return;
6544 do_vec_compare (cpu
); return;
6551 if (INSTR (31, 21) == 0x370)
6553 do_vec_MOV_element (cpu
);
6557 switch (INSTR (21, 10))
6559 case 0x82E: do_vec_neg (cpu
); return;
6560 case 0x87E: do_vec_sqrt (cpu
); return;
6562 if (INSTR (15, 10) == 0x30)
6580 /* Float multiply add. */
6582 fmadds (sim_cpu
*cpu
)
6584 unsigned sa
= INSTR (14, 10);
6585 unsigned sm
= INSTR (20, 16);
6586 unsigned sn
= INSTR ( 9, 5);
6587 unsigned sd
= INSTR ( 4, 0);
6589 aarch64_set_FP_float (cpu
, sd
, aarch64_get_FP_float (cpu
, sa
)
6590 + aarch64_get_FP_float (cpu
, sn
)
6591 * aarch64_get_FP_float (cpu
, sm
));
6594 /* Double multiply add. */
6596 fmaddd (sim_cpu
*cpu
)
6598 unsigned sa
= INSTR (14, 10);
6599 unsigned sm
= INSTR (20, 16);
6600 unsigned sn
= INSTR ( 9, 5);
6601 unsigned sd
= INSTR ( 4, 0);
6603 aarch64_set_FP_double (cpu
, sd
, aarch64_get_FP_double (cpu
, sa
)
6604 + aarch64_get_FP_double (cpu
, sn
)
6605 * aarch64_get_FP_double (cpu
, sm
));
6608 /* Float multiply subtract. */
6610 fmsubs (sim_cpu
*cpu
)
6612 unsigned sa
= INSTR (14, 10);
6613 unsigned sm
= INSTR (20, 16);
6614 unsigned sn
= INSTR ( 9, 5);
6615 unsigned sd
= INSTR ( 4, 0);
6617 aarch64_set_FP_float (cpu
, sd
, aarch64_get_FP_float (cpu
, sa
)
6618 - aarch64_get_FP_float (cpu
, sn
)
6619 * aarch64_get_FP_float (cpu
, sm
));
6622 /* Double multiply subtract. */
6624 fmsubd (sim_cpu
*cpu
)
6626 unsigned sa
= INSTR (14, 10);
6627 unsigned sm
= INSTR (20, 16);
6628 unsigned sn
= INSTR ( 9, 5);
6629 unsigned sd
= INSTR ( 4, 0);
6631 aarch64_set_FP_double (cpu
, sd
, aarch64_get_FP_double (cpu
, sa
)
6632 - aarch64_get_FP_double (cpu
, sn
)
6633 * aarch64_get_FP_double (cpu
, sm
));
6636 /* Float negative multiply add. */
6638 fnmadds (sim_cpu
*cpu
)
6640 unsigned sa
= INSTR (14, 10);
6641 unsigned sm
= INSTR (20, 16);
6642 unsigned sn
= INSTR ( 9, 5);
6643 unsigned sd
= INSTR ( 4, 0);
6645 aarch64_set_FP_float (cpu
, sd
, - aarch64_get_FP_float (cpu
, sa
)
6646 + (- aarch64_get_FP_float (cpu
, sn
))
6647 * aarch64_get_FP_float (cpu
, sm
));
6650 /* Double negative multiply add. */
6652 fnmaddd (sim_cpu
*cpu
)
6654 unsigned sa
= INSTR (14, 10);
6655 unsigned sm
= INSTR (20, 16);
6656 unsigned sn
= INSTR ( 9, 5);
6657 unsigned sd
= INSTR ( 4, 0);
6659 aarch64_set_FP_double (cpu
, sd
, - aarch64_get_FP_double (cpu
, sa
)
6660 + (- aarch64_get_FP_double (cpu
, sn
))
6661 * aarch64_get_FP_double (cpu
, sm
));
6664 /* Float negative multiply subtract. */
6666 fnmsubs (sim_cpu
*cpu
)
6668 unsigned sa
= INSTR (14, 10);
6669 unsigned sm
= INSTR (20, 16);
6670 unsigned sn
= INSTR ( 9, 5);
6671 unsigned sd
= INSTR ( 4, 0);
6673 aarch64_set_FP_float (cpu
, sd
, - aarch64_get_FP_float (cpu
, sa
)
6674 + aarch64_get_FP_float (cpu
, sn
)
6675 * aarch64_get_FP_float (cpu
, sm
));
6678 /* Double negative multiply subtract. */
6680 fnmsubd (sim_cpu
*cpu
)
6682 unsigned sa
= INSTR (14, 10);
6683 unsigned sm
= INSTR (20, 16);
6684 unsigned sn
= INSTR ( 9, 5);
6685 unsigned sd
= INSTR ( 4, 0);
6687 aarch64_set_FP_double (cpu
, sd
, - aarch64_get_FP_double (cpu
, sa
)
6688 + aarch64_get_FP_double (cpu
, sn
)
6689 * aarch64_get_FP_double (cpu
, sm
));
6693 dexSimpleFPDataProc3Source (sim_cpu
*cpu
)
6695 /* instr[31] ==> M : 0 ==> OK, 1 ==> UNALLOC
6697 instr[29] ==> S : 0 ==> OK, 1 ==> UNALLOC
6700 instr[23,22] ==> type : 0 ==> single, 01 ==> double, 1x ==> UNALLOC
6701 instr[21] ==> o1 : 0 ==> unnegated, 1 ==> negated
6702 instr[15] ==> o2 : 0 ==> ADD, 1 ==> SUB */
6704 uint32_t M_S
= (INSTR (31, 31) << 1) | INSTR (29, 29);
6705 /* dispatch on combined type:o1:o2. */
6706 uint32_t dispatch
= (INSTR (23, 21) << 1) | INSTR (15, 15);
6713 case 0: fmadds (cpu
); return;
6714 case 1: fmsubs (cpu
); return;
6715 case 2: fnmadds (cpu
); return;
6716 case 3: fnmsubs (cpu
); return;
6717 case 4: fmaddd (cpu
); return;
6718 case 5: fmsubd (cpu
); return;
6719 case 6: fnmaddd (cpu
); return;
6720 case 7: fnmsubd (cpu
); return;
6722 /* type > 1 is currently unallocated. */
6728 dexSimpleFPFixedConvert (sim_cpu
*cpu
)
6734 dexSimpleFPCondCompare (sim_cpu
*cpu
)
6736 /* instr [31,23] = 0001 1110 0
6740 instr [15,12] = condition
6744 instr [3,0] = nzcv */
6746 unsigned rm
= INSTR (20, 16);
6747 unsigned rn
= INSTR (9, 5);
6749 NYI_assert (31, 23, 0x3C);
6750 NYI_assert (11, 10, 0x1);
6751 NYI_assert (4, 4, 0);
6753 if (! testConditionCode (cpu
, INSTR (15, 12)))
6755 aarch64_set_CPSR (cpu
, INSTR (3, 0));
6761 /* Double precision. */
6762 double val1
= aarch64_get_vec_double (cpu
, rn
, 0);
6763 double val2
= aarch64_get_vec_double (cpu
, rm
, 0);
6765 /* FIXME: Check for NaNs. */
6767 aarch64_set_CPSR (cpu
, (Z
| C
));
6768 else if (val1
< val2
)
6769 aarch64_set_CPSR (cpu
, N
);
6770 else /* val1 > val2 */
6771 aarch64_set_CPSR (cpu
, C
);
6775 /* Single precision. */
6776 float val1
= aarch64_get_vec_float (cpu
, rn
, 0);
6777 float val2
= aarch64_get_vec_float (cpu
, rm
, 0);
6779 /* FIXME: Check for NaNs. */
6781 aarch64_set_CPSR (cpu
, (Z
| C
));
6782 else if (val1
< val2
)
6783 aarch64_set_CPSR (cpu
, N
);
6784 else /* val1 > val2 */
6785 aarch64_set_CPSR (cpu
, C
);
6793 fadds (sim_cpu
*cpu
)
6795 unsigned sm
= INSTR (20, 16);
6796 unsigned sn
= INSTR ( 9, 5);
6797 unsigned sd
= INSTR ( 4, 0);
6799 aarch64_set_FP_float (cpu
, sd
, aarch64_get_FP_float (cpu
, sn
)
6800 + aarch64_get_FP_float (cpu
, sm
));
6805 faddd (sim_cpu
*cpu
)
6807 unsigned sm
= INSTR (20, 16);
6808 unsigned sn
= INSTR ( 9, 5);
6809 unsigned sd
= INSTR ( 4, 0);
6811 aarch64_set_FP_double (cpu
, sd
, aarch64_get_FP_double (cpu
, sn
)
6812 + aarch64_get_FP_double (cpu
, sm
));
6817 fdivs (sim_cpu
*cpu
)
6819 unsigned sm
= INSTR (20, 16);
6820 unsigned sn
= INSTR ( 9, 5);
6821 unsigned sd
= INSTR ( 4, 0);
6823 aarch64_set_FP_float (cpu
, sd
, aarch64_get_FP_float (cpu
, sn
)
6824 / aarch64_get_FP_float (cpu
, sm
));
6827 /* Double divide. */
6829 fdivd (sim_cpu
*cpu
)
6831 unsigned sm
= INSTR (20, 16);
6832 unsigned sn
= INSTR ( 9, 5);
6833 unsigned sd
= INSTR ( 4, 0);
6835 aarch64_set_FP_double (cpu
, sd
, aarch64_get_FP_double (cpu
, sn
)
6836 / aarch64_get_FP_double (cpu
, sm
));
6839 /* Float multiply. */
6841 fmuls (sim_cpu
*cpu
)
6843 unsigned sm
= INSTR (20, 16);
6844 unsigned sn
= INSTR ( 9, 5);
6845 unsigned sd
= INSTR ( 4, 0);
6847 aarch64_set_FP_float (cpu
, sd
, aarch64_get_FP_float (cpu
, sn
)
6848 * aarch64_get_FP_float (cpu
, sm
));
6851 /* Double multiply. */
6853 fmuld (sim_cpu
*cpu
)
6855 unsigned sm
= INSTR (20, 16);
6856 unsigned sn
= INSTR ( 9, 5);
6857 unsigned sd
= INSTR ( 4, 0);
6859 aarch64_set_FP_double (cpu
, sd
, aarch64_get_FP_double (cpu
, sn
)
6860 * aarch64_get_FP_double (cpu
, sm
));
6863 /* Float negate and multiply. */
6865 fnmuls (sim_cpu
*cpu
)
6867 unsigned sm
= INSTR (20, 16);
6868 unsigned sn
= INSTR ( 9, 5);
6869 unsigned sd
= INSTR ( 4, 0);
6871 aarch64_set_FP_float (cpu
, sd
, - (aarch64_get_FP_float (cpu
, sn
)
6872 * aarch64_get_FP_float (cpu
, sm
)));
6875 /* Double negate and multiply. */
6877 fnmuld (sim_cpu
*cpu
)
6879 unsigned sm
= INSTR (20, 16);
6880 unsigned sn
= INSTR ( 9, 5);
6881 unsigned sd
= INSTR ( 4, 0);
6883 aarch64_set_FP_double (cpu
, sd
, - (aarch64_get_FP_double (cpu
, sn
)
6884 * aarch64_get_FP_double (cpu
, sm
)));
6887 /* Float subtract. */
6889 fsubs (sim_cpu
*cpu
)
6891 unsigned sm
= INSTR (20, 16);
6892 unsigned sn
= INSTR ( 9, 5);
6893 unsigned sd
= INSTR ( 4, 0);
6895 aarch64_set_FP_float (cpu
, sd
, aarch64_get_FP_float (cpu
, sn
)
6896 - aarch64_get_FP_float (cpu
, sm
));
6899 /* Double subtract. */
6901 fsubd (sim_cpu
*cpu
)
6903 unsigned sm
= INSTR (20, 16);
6904 unsigned sn
= INSTR ( 9, 5);
6905 unsigned sd
= INSTR ( 4, 0);
6907 aarch64_set_FP_double (cpu
, sd
, aarch64_get_FP_double (cpu
, sn
)
6908 - aarch64_get_FP_double (cpu
, sm
));
6912 do_FMINNM (sim_cpu
*cpu
)
6914 /* instr[31,23] = 0 0011 1100
6915 instr[22] = float(0)/double(1)
6918 instr[15,10] = 01 1110
6922 unsigned sm
= INSTR (20, 16);
6923 unsigned sn
= INSTR ( 9, 5);
6924 unsigned sd
= INSTR ( 4, 0);
6926 NYI_assert (31, 23, 0x03C);
6927 NYI_assert (15, 10, 0x1E);
6930 aarch64_set_FP_double (cpu
, sd
,
6931 dminnm (aarch64_get_FP_double (cpu
, sn
),
6932 aarch64_get_FP_double (cpu
, sm
)));
6934 aarch64_set_FP_float (cpu
, sd
,
6935 fminnm (aarch64_get_FP_float (cpu
, sn
),
6936 aarch64_get_FP_float (cpu
, sm
)));
6940 do_FMAXNM (sim_cpu
*cpu
)
6942 /* instr[31,23] = 0 0011 1100
6943 instr[22] = float(0)/double(1)
6946 instr[15,10] = 01 1010
6950 unsigned sm
= INSTR (20, 16);
6951 unsigned sn
= INSTR ( 9, 5);
6952 unsigned sd
= INSTR ( 4, 0);
6954 NYI_assert (31, 23, 0x03C);
6955 NYI_assert (15, 10, 0x1A);
6958 aarch64_set_FP_double (cpu
, sd
,
6959 dmaxnm (aarch64_get_FP_double (cpu
, sn
),
6960 aarch64_get_FP_double (cpu
, sm
)));
6962 aarch64_set_FP_float (cpu
, sd
,
6963 fmaxnm (aarch64_get_FP_float (cpu
, sn
),
6964 aarch64_get_FP_float (cpu
, sm
)));
6968 dexSimpleFPDataProc2Source (sim_cpu
*cpu
)
6970 /* instr[31] ==> M : 0 ==> OK, 1 ==> UNALLOC
6972 instr[29] ==> S : 0 ==> OK, 1 ==> UNALLOC
6975 instr[23,22] ==> type : 0 ==> single, 01 ==> double, 1x ==> UNALLOC
6978 instr[15,12] ==> opcode : 0000 ==> FMUL, 0001 ==> FDIV
6979 0010 ==> FADD, 0011 ==> FSUB,
6980 0100 ==> FMAX, 0101 ==> FMIN
6981 0110 ==> FMAXNM, 0111 ==> FMINNM
6982 1000 ==> FNMUL, ow ==> UNALLOC
6987 uint32_t M_S
= (INSTR (31, 31) << 1) | INSTR (29, 29);
6988 uint32_t type
= INSTR (23, 22);
6989 /* Dispatch on opcode. */
6990 uint32_t dispatch
= INSTR (15, 12);
7001 case 0: fmuld (cpu
); return;
7002 case 1: fdivd (cpu
); return;
7003 case 2: faddd (cpu
); return;
7004 case 3: fsubd (cpu
); return;
7005 case 6: do_FMAXNM (cpu
); return;
7006 case 7: do_FMINNM (cpu
); return;
7007 case 8: fnmuld (cpu
); return;
7009 /* Have not yet implemented fmax and fmin. */
7017 else /* type == 0 => floats. */
7020 case 0: fmuls (cpu
); return;
7021 case 1: fdivs (cpu
); return;
7022 case 2: fadds (cpu
); return;
7023 case 3: fsubs (cpu
); return;
7024 case 6: do_FMAXNM (cpu
); return;
7025 case 7: do_FMINNM (cpu
); return;
7026 case 8: fnmuls (cpu
); return;
7038 dexSimpleFPCondSelect (sim_cpu
*cpu
)
7041 instr[31,23] = 0 0011 1100
7042 instr[22] = 0=>single 1=>double
7049 unsigned sm
= INSTR (20, 16);
7050 unsigned sn
= INSTR ( 9, 5);
7051 unsigned sd
= INSTR ( 4, 0);
7052 uint32_t set
= testConditionCode (cpu
, INSTR (15, 12));
7054 NYI_assert (31, 23, 0x03C);
7055 NYI_assert (11, 10, 0x3);
7058 aarch64_set_FP_double (cpu
, sd
, set
? sn
: sm
);
7060 aarch64_set_FP_float (cpu
, sd
, set
? sn
: sm
);
7063 /* Store 32 bit unscaled signed 9 bit. */
7065 fsturs (sim_cpu
*cpu
, int32_t offset
)
7067 unsigned int rn
= INSTR (9, 5);
7068 unsigned int st
= INSTR (4, 0);
7070 aarch64_set_mem_u32 (cpu
, aarch64_get_reg_u64 (cpu
, st
, 1) + offset
,
7071 aarch64_get_vec_u32 (cpu
, rn
, 0));
7074 /* Store 64 bit unscaled signed 9 bit. */
7076 fsturd (sim_cpu
*cpu
, int32_t offset
)
7078 unsigned int rn
= INSTR (9, 5);
7079 unsigned int st
= INSTR (4, 0);
7081 aarch64_set_mem_u64 (cpu
, aarch64_get_reg_u64 (cpu
, st
, 1) + offset
,
7082 aarch64_get_vec_u64 (cpu
, rn
, 0));
7085 /* Store 128 bit unscaled signed 9 bit. */
7087 fsturq (sim_cpu
*cpu
, int32_t offset
)
7089 unsigned int rn
= INSTR (9, 5);
7090 unsigned int st
= INSTR (4, 0);
7093 aarch64_get_FP_long_double (cpu
, rn
, & a
);
7094 aarch64_set_mem_long_double (cpu
,
7095 aarch64_get_reg_u64 (cpu
, st
, 1)
7099 /* TODO FP move register. */
7101 /* 32 bit fp to fp move register. */
7103 ffmovs (sim_cpu
*cpu
)
7105 unsigned int rn
= INSTR (9, 5);
7106 unsigned int st
= INSTR (4, 0);
7108 aarch64_set_FP_float (cpu
, st
, aarch64_get_FP_float (cpu
, rn
));
7111 /* 64 bit fp to fp move register. */
7113 ffmovd (sim_cpu
*cpu
)
7115 unsigned int rn
= INSTR (9, 5);
7116 unsigned int st
= INSTR (4, 0);
7118 aarch64_set_FP_double (cpu
, st
, aarch64_get_FP_double (cpu
, rn
));
7121 /* 32 bit GReg to Vec move register. */
7123 fgmovs (sim_cpu
*cpu
)
7125 unsigned int rn
= INSTR (9, 5);
7126 unsigned int st
= INSTR (4, 0);
7128 aarch64_set_vec_u32 (cpu
, st
, 0, aarch64_get_reg_u32 (cpu
, rn
, NO_SP
));
7131 /* 64 bit g to fp move register. */
7133 fgmovd (sim_cpu
*cpu
)
7135 unsigned int rn
= INSTR (9, 5);
7136 unsigned int st
= INSTR (4, 0);
7138 aarch64_set_vec_u64 (cpu
, st
, 0, aarch64_get_reg_u64 (cpu
, rn
, NO_SP
));
7141 /* 32 bit fp to g move register. */
7143 gfmovs (sim_cpu
*cpu
)
7145 unsigned int rn
= INSTR (9, 5);
7146 unsigned int st
= INSTR (4, 0);
7148 aarch64_set_reg_u64 (cpu
, st
, NO_SP
, aarch64_get_vec_u32 (cpu
, rn
, 0));
7151 /* 64 bit fp to g move register. */
7153 gfmovd (sim_cpu
*cpu
)
7155 unsigned int rn
= INSTR (9, 5);
7156 unsigned int st
= INSTR (4, 0);
7158 aarch64_set_reg_u64 (cpu
, st
, NO_SP
, aarch64_get_vec_u64 (cpu
, rn
, 0));
7161 /* FP move immediate
7163 These install an immediate 8 bit value in the target register
7164 where the 8 bits comprise 1 sign bit, 4 bits of fraction and a 3
7168 fmovs (sim_cpu
*cpu
)
7170 unsigned int sd
= INSTR (4, 0);
7171 uint32_t imm
= INSTR (20, 13);
7172 float f
= fp_immediate_for_encoding_32 (imm
);
7174 aarch64_set_FP_float (cpu
, sd
, f
);
7178 fmovd (sim_cpu
*cpu
)
7180 unsigned int sd
= INSTR (4, 0);
7181 uint32_t imm
= INSTR (20, 13);
7182 double d
= fp_immediate_for_encoding_64 (imm
);
7184 aarch64_set_FP_double (cpu
, sd
, d
);
7188 dexSimpleFPImmediate (sim_cpu
*cpu
)
7190 /* instr[31,23] == 00111100
7191 instr[22] == type : single(0)/double(1)
7193 instr[20,13] == imm8
7195 instr[9,5] == imm5 : 00000 ==> PK, ow ==> UNALLOC
7197 uint32_t imm5
= INSTR (9, 5);
7199 NYI_assert (31, 23, 0x3C);
7210 /* TODO specific decode and execute for group Load Store. */
7212 /* TODO FP load/store single register (unscaled offset). */
7214 /* TODO load 8 bit unscaled signed 9 bit. */
7215 /* TODO load 16 bit unscaled signed 9 bit. */
7217 /* Load 32 bit unscaled signed 9 bit. */
7219 fldurs (sim_cpu
*cpu
, int32_t offset
)
7221 unsigned int rn
= INSTR (9, 5);
7222 unsigned int st
= INSTR (4, 0);
7224 aarch64_set_vec_u32 (cpu
, st
, 0, aarch64_get_mem_u32
7225 (cpu
, aarch64_get_reg_u64 (cpu
, rn
, SP_OK
) + offset
));
7228 /* Load 64 bit unscaled signed 9 bit. */
7230 fldurd (sim_cpu
*cpu
, int32_t offset
)
7232 unsigned int rn
= INSTR (9, 5);
7233 unsigned int st
= INSTR (4, 0);
7235 aarch64_set_vec_u64 (cpu
, st
, 0, aarch64_get_mem_u64
7236 (cpu
, aarch64_get_reg_u64 (cpu
, rn
, SP_OK
) + offset
));
7239 /* Load 128 bit unscaled signed 9 bit. */
7241 fldurq (sim_cpu
*cpu
, int32_t offset
)
7243 unsigned int rn
= INSTR (9, 5);
7244 unsigned int st
= INSTR (4, 0);
7246 uint64_t addr
= aarch64_get_reg_u64 (cpu
, rn
, SP_OK
) + offset
;
7248 aarch64_get_mem_long_double (cpu
, addr
, & a
);
7249 aarch64_set_FP_long_double (cpu
, st
, a
);
7252 /* TODO store 8 bit unscaled signed 9 bit. */
7253 /* TODO store 16 bit unscaled signed 9 bit. */
7258 /* Float absolute value. */
7260 fabss (sim_cpu
*cpu
)
7262 unsigned sn
= INSTR (9, 5);
7263 unsigned sd
= INSTR (4, 0);
7264 float value
= aarch64_get_FP_float (cpu
, sn
);
7266 aarch64_set_FP_float (cpu
, sd
, fabsf (value
));
7269 /* Double absolute value. */
7271 fabcpu (sim_cpu
*cpu
)
7273 unsigned sn
= INSTR (9, 5);
7274 unsigned sd
= INSTR (4, 0);
7275 double value
= aarch64_get_FP_double (cpu
, sn
);
7277 aarch64_set_FP_double (cpu
, sd
, fabs (value
));
7280 /* Float negative value. */
7282 fnegs (sim_cpu
*cpu
)
7284 unsigned sn
= INSTR (9, 5);
7285 unsigned sd
= INSTR (4, 0);
7287 aarch64_set_FP_float (cpu
, sd
, - aarch64_get_FP_float (cpu
, sn
));
7290 /* Double negative value. */
7292 fnegd (sim_cpu
*cpu
)
7294 unsigned sn
= INSTR (9, 5);
7295 unsigned sd
= INSTR (4, 0);
7297 aarch64_set_FP_double (cpu
, sd
, - aarch64_get_FP_double (cpu
, sn
));
7300 /* Float square root. */
7302 fsqrts (sim_cpu
*cpu
)
7304 unsigned sn
= INSTR (9, 5);
7305 unsigned sd
= INSTR (4, 0);
7307 aarch64_set_FP_float (cpu
, sd
, sqrt (aarch64_get_FP_float (cpu
, sn
)));
7310 /* Double square root. */
7312 fsqrtd (sim_cpu
*cpu
)
7314 unsigned sn
= INSTR (9, 5);
7315 unsigned sd
= INSTR (4, 0);
7317 aarch64_set_FP_double (cpu
, sd
,
7318 sqrt (aarch64_get_FP_double (cpu
, sn
)));
7321 /* Convert double to float. */
7323 fcvtds (sim_cpu
*cpu
)
7325 unsigned sn
= INSTR (9, 5);
7326 unsigned sd
= INSTR (4, 0);
7328 aarch64_set_FP_float (cpu
, sd
, (float) aarch64_get_FP_double (cpu
, sn
));
7331 /* Convert float to double. */
7333 fcvtcpu (sim_cpu
*cpu
)
7335 unsigned sn
= INSTR (9, 5);
7336 unsigned sd
= INSTR (4, 0);
7338 aarch64_set_FP_double (cpu
, sd
, (double) aarch64_get_FP_float (cpu
, sn
));
7342 do_FRINT (sim_cpu
*cpu
)
7344 /* instr[31,23] = 0001 1110 0
7345 instr[22] = single(0)/double(1)
7347 instr[17,15] = rounding mode
7348 instr[14,10] = 10000
7350 instr[4,0] = dest */
7353 unsigned rs
= INSTR (9, 5);
7354 unsigned rd
= INSTR (4, 0);
7355 unsigned int rmode
= INSTR (17, 15);
7357 NYI_assert (31, 23, 0x03C);
7358 NYI_assert (21, 18, 0x9);
7359 NYI_assert (14, 10, 0x10);
7361 if (rmode
== 6 || rmode
== 7)
7362 /* FIXME: Add support for rmode == 6 exactness check. */
7363 rmode
= uimm (aarch64_get_FPSR (cpu
), 23, 22);
7367 double val
= aarch64_get_FP_double (cpu
, rs
);
7371 case 0: /* mode N: nearest or even. */
7373 double rval
= round (val
);
7375 if (val
- rval
== 0.5)
7377 if (((rval
/ 2.0) * 2.0) != rval
)
7381 aarch64_set_FP_double (cpu
, rd
, round (val
));
7385 case 1: /* mode P: towards +inf. */
7387 aarch64_set_FP_double (cpu
, rd
, trunc (val
));
7389 aarch64_set_FP_double (cpu
, rd
, round (val
));
7392 case 2: /* mode M: towards -inf. */
7394 aarch64_set_FP_double (cpu
, rd
, round (val
));
7396 aarch64_set_FP_double (cpu
, rd
, trunc (val
));
7399 case 3: /* mode Z: towards 0. */
7400 aarch64_set_FP_double (cpu
, rd
, trunc (val
));
7403 case 4: /* mode A: away from 0. */
7404 aarch64_set_FP_double (cpu
, rd
, round (val
));
7407 case 6: /* mode X: use FPCR with exactness check. */
7408 case 7: /* mode I: use FPCR mode. */
7416 val
= aarch64_get_FP_float (cpu
, rs
);
7420 case 0: /* mode N: nearest or even. */
7422 float rval
= roundf (val
);
7424 if (val
- rval
== 0.5)
7426 if (((rval
/ 2.0) * 2.0) != rval
)
7430 aarch64_set_FP_float (cpu
, rd
, rval
);
7434 case 1: /* mode P: towards +inf. */
7436 aarch64_set_FP_float (cpu
, rd
, truncf (val
));
7438 aarch64_set_FP_float (cpu
, rd
, roundf (val
));
7441 case 2: /* mode M: towards -inf. */
7443 aarch64_set_FP_float (cpu
, rd
, truncf (val
));
7445 aarch64_set_FP_float (cpu
, rd
, roundf (val
));
7448 case 3: /* mode Z: towards 0. */
7449 aarch64_set_FP_float (cpu
, rd
, truncf (val
));
7452 case 4: /* mode A: away from 0. */
7453 aarch64_set_FP_float (cpu
, rd
, roundf (val
));
7456 case 6: /* mode X: use FPCR with exactness check. */
7457 case 7: /* mode I: use FPCR mode. */
7465 /* Convert half to float. */
7467 do_FCVT_half_to_single (sim_cpu
*cpu
)
7469 unsigned rn
= INSTR (9, 5);
7470 unsigned rd
= INSTR (4, 0);
7472 NYI_assert (31, 10, 0x7B890);
7474 aarch64_set_FP_float (cpu
, rd
, (float) aarch64_get_FP_half (cpu
, rn
));
7477 /* Convert half to double. */
7479 do_FCVT_half_to_double (sim_cpu
*cpu
)
7481 unsigned rn
= INSTR (9, 5);
7482 unsigned rd
= INSTR (4, 0);
7484 NYI_assert (31, 10, 0x7B8B0);
7486 aarch64_set_FP_double (cpu
, rd
, (double) aarch64_get_FP_half (cpu
, rn
));
7490 do_FCVT_single_to_half (sim_cpu
*cpu
)
7492 unsigned rn
= INSTR (9, 5);
7493 unsigned rd
= INSTR (4, 0);
7495 NYI_assert (31, 10, 0x788F0);
7497 aarch64_set_FP_half (cpu
, rd
, aarch64_get_FP_float (cpu
, rn
));
7500 /* Convert double to half. */
7502 do_FCVT_double_to_half (sim_cpu
*cpu
)
7504 unsigned rn
= INSTR (9, 5);
7505 unsigned rd
= INSTR (4, 0);
7507 NYI_assert (31, 10, 0x798F0);
7509 aarch64_set_FP_half (cpu
, rd
, (float) aarch64_get_FP_double (cpu
, rn
));
7513 dexSimpleFPDataProc1Source (sim_cpu
*cpu
)
7515 /* instr[31] ==> M : 0 ==> OK, 1 ==> UNALLOC
7517 instr[29] ==> S : 0 ==> OK, 1 ==> UNALLOC
7520 instr[23,22] ==> type : 00 ==> source is single,
7521 01 ==> source is double
7523 11 ==> UNALLOC or source is half
7525 instr[20,15] ==> opcode : with type 00 or 01
7526 000000 ==> FMOV, 000001 ==> FABS,
7527 000010 ==> FNEG, 000011 ==> FSQRT,
7528 000100 ==> UNALLOC, 000101 ==> FCVT,(to single/double)
7529 000110 ==> UNALLOC, 000111 ==> FCVT (to half)
7530 001000 ==> FRINTN, 001001 ==> FRINTP,
7531 001010 ==> FRINTM, 001011 ==> FRINTZ,
7532 001100 ==> FRINTA, 001101 ==> UNALLOC
7533 001110 ==> FRINTX, 001111 ==> FRINTI
7535 000100 ==> FCVT (half-to-single)
7536 000101 ==> FCVT (half-to-double)
7537 instr[14,10] = 10000. */
7539 uint32_t M_S
= (INSTR (31, 31) << 1) | INSTR (29, 29);
7540 uint32_t type
= INSTR (23, 22);
7541 uint32_t opcode
= INSTR (20, 15);
7549 do_FCVT_half_to_single (cpu
);
7550 else if (opcode
== 5)
7551 do_FCVT_half_to_double (cpu
);
7603 case 8: /* FRINTN etc. */
7615 do_FCVT_double_to_half (cpu
);
7617 do_FCVT_single_to_half (cpu
);
7628 /* 32 bit signed int to float. */
7630 scvtf32 (sim_cpu
*cpu
)
7632 unsigned rn
= INSTR (9, 5);
7633 unsigned sd
= INSTR (4, 0);
7635 aarch64_set_FP_float
7636 (cpu
, sd
, (float) aarch64_get_reg_s32 (cpu
, rn
, NO_SP
));
7639 /* signed int to float. */
7641 scvtf (sim_cpu
*cpu
)
7643 unsigned rn
= INSTR (9, 5);
7644 unsigned sd
= INSTR (4, 0);
7646 aarch64_set_FP_float
7647 (cpu
, sd
, (float) aarch64_get_reg_s64 (cpu
, rn
, NO_SP
));
7650 /* 32 bit signed int to double. */
7652 scvtd32 (sim_cpu
*cpu
)
7654 unsigned rn
= INSTR (9, 5);
7655 unsigned sd
= INSTR (4, 0);
7657 aarch64_set_FP_double
7658 (cpu
, sd
, (double) aarch64_get_reg_s32 (cpu
, rn
, NO_SP
));
7661 /* signed int to double. */
7663 scvtd (sim_cpu
*cpu
)
7665 unsigned rn
= INSTR (9, 5);
7666 unsigned sd
= INSTR (4, 0);
7668 aarch64_set_FP_double
7669 (cpu
, sd
, (double) aarch64_get_reg_s64 (cpu
, rn
, NO_SP
));
7672 static const float FLOAT_INT_MAX
= (float) INT_MAX
;
7673 static const float FLOAT_INT_MIN
= (float) INT_MIN
;
7674 static const double DOUBLE_INT_MAX
= (double) INT_MAX
;
7675 static const double DOUBLE_INT_MIN
= (double) INT_MIN
;
7676 static const float FLOAT_LONG_MAX
= (float) LONG_MAX
;
7677 static const float FLOAT_LONG_MIN
= (float) LONG_MIN
;
7678 static const double DOUBLE_LONG_MAX
= (double) LONG_MAX
;
7679 static const double DOUBLE_LONG_MIN
= (double) LONG_MIN
;
7681 /* Check for FP exception conditions:
7684 Out of Range raises IO and IX and saturates value
7685 Denormal raises ID and IX and sets to zero. */
7686 #define RAISE_EXCEPTIONS(F, VALUE, FTYPE, ITYPE) \
7689 switch (fpclassify (F)) \
7693 aarch64_set_FPSR (cpu, IO); \
7695 VALUE = ITYPE##_MAX; \
7697 VALUE = ITYPE##_MIN; \
7701 if (F >= FTYPE##_##ITYPE##_MAX) \
7703 aarch64_set_FPSR_bits (cpu, IO | IX, IO | IX); \
7704 VALUE = ITYPE##_MAX; \
7706 else if (F <= FTYPE##_##ITYPE##_MIN) \
7708 aarch64_set_FPSR_bits (cpu, IO | IX, IO | IX); \
7709 VALUE = ITYPE##_MIN; \
7713 case FP_SUBNORMAL: \
7714 aarch64_set_FPSR_bits (cpu, IO | IX | ID, IX | ID); \
7726 /* 32 bit convert float to signed int truncate towards zero. */
7728 fcvtszs32 (sim_cpu
*cpu
)
7730 unsigned sn
= INSTR (9, 5);
7731 unsigned rd
= INSTR (4, 0);
7732 /* TODO : check that this rounds toward zero. */
7733 float f
= aarch64_get_FP_float (cpu
, sn
);
7734 int32_t value
= (int32_t) f
;
7736 RAISE_EXCEPTIONS (f
, value
, FLOAT
, INT
);
7738 /* Avoid sign extension to 64 bit. */
7739 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, (uint32_t) value
);
7742 /* 64 bit convert float to signed int truncate towards zero. */
7744 fcvtszs (sim_cpu
*cpu
)
7746 unsigned sn
= INSTR (9, 5);
7747 unsigned rd
= INSTR (4, 0);
7748 float f
= aarch64_get_FP_float (cpu
, sn
);
7749 int64_t value
= (int64_t) f
;
7751 RAISE_EXCEPTIONS (f
, value
, FLOAT
, LONG
);
7753 aarch64_set_reg_s64 (cpu
, rd
, NO_SP
, value
);
7756 /* 32 bit convert double to signed int truncate towards zero. */
7758 fcvtszd32 (sim_cpu
*cpu
)
7760 unsigned sn
= INSTR (9, 5);
7761 unsigned rd
= INSTR (4, 0);
7762 /* TODO : check that this rounds toward zero. */
7763 double d
= aarch64_get_FP_double (cpu
, sn
);
7764 int32_t value
= (int32_t) d
;
7766 RAISE_EXCEPTIONS (d
, value
, DOUBLE
, INT
);
7768 /* Avoid sign extension to 64 bit. */
7769 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, (uint32_t) value
);
7772 /* 64 bit convert double to signed int truncate towards zero. */
7774 fcvtszd (sim_cpu
*cpu
)
7776 unsigned sn
= INSTR (9, 5);
7777 unsigned rd
= INSTR (4, 0);
7778 /* TODO : check that this rounds toward zero. */
7779 double d
= aarch64_get_FP_double (cpu
, sn
);
7782 value
= (int64_t) d
;
7784 RAISE_EXCEPTIONS (d
, value
, DOUBLE
, LONG
);
7786 aarch64_set_reg_s64 (cpu
, rd
, NO_SP
, value
);
7790 do_fcvtzu (sim_cpu
*cpu
)
7792 /* instr[31] = size: 32-bit (0), 64-bit (1)
7793 instr[30,23] = 00111100
7794 instr[22] = type: single (0)/ double (1)
7795 instr[21] = enable (0)/disable(1) precision
7796 instr[20,16] = 11001
7797 instr[15,10] = precision
7801 unsigned rs
= INSTR (9, 5);
7802 unsigned rd
= INSTR (4, 0);
7804 NYI_assert (30, 23, 0x3C);
7805 NYI_assert (20, 16, 0x19);
7807 if (INSTR (21, 21) != 1)
7808 /* Convert to fixed point. */
7813 /* Convert to unsigned 64-bit integer. */
7816 double d
= aarch64_get_FP_double (cpu
, rs
);
7817 uint64_t value
= (uint64_t) d
;
7819 /* Do not raise an exception if we have reached ULONG_MAX. */
7820 if (value
!= (1UL << 63))
7821 RAISE_EXCEPTIONS (d
, value
, DOUBLE
, LONG
);
7823 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, value
);
7827 float f
= aarch64_get_FP_float (cpu
, rs
);
7828 uint64_t value
= (uint64_t) f
;
7830 /* Do not raise an exception if we have reached ULONG_MAX. */
7831 if (value
!= (1UL << 63))
7832 RAISE_EXCEPTIONS (f
, value
, FLOAT
, LONG
);
7834 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, value
);
7841 /* Convert to unsigned 32-bit integer. */
7844 double d
= aarch64_get_FP_double (cpu
, rs
);
7846 value
= (uint32_t) d
;
7847 /* Do not raise an exception if we have reached UINT_MAX. */
7848 if (value
!= (1UL << 31))
7849 RAISE_EXCEPTIONS (d
, value
, DOUBLE
, INT
);
7853 float f
= aarch64_get_FP_float (cpu
, rs
);
7855 value
= (uint32_t) f
;
7856 /* Do not raise an exception if we have reached UINT_MAX. */
7857 if (value
!= (1UL << 31))
7858 RAISE_EXCEPTIONS (f
, value
, FLOAT
, INT
);
7861 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, value
);
7866 do_UCVTF (sim_cpu
*cpu
)
7868 /* instr[31] = size: 32-bit (0), 64-bit (1)
7869 instr[30,23] = 001 1110 0
7870 instr[22] = type: single (0)/ double (1)
7871 instr[21] = enable (0)/disable(1) precision
7872 instr[20,16] = 0 0011
7873 instr[15,10] = precision
7877 unsigned rs
= INSTR (9, 5);
7878 unsigned rd
= INSTR (4, 0);
7880 NYI_assert (30, 23, 0x3C);
7881 NYI_assert (20, 16, 0x03);
7883 if (INSTR (21, 21) != 1)
7886 /* FIXME: Add exception raising. */
7889 uint64_t value
= aarch64_get_reg_u64 (cpu
, rs
, NO_SP
);
7892 aarch64_set_FP_double (cpu
, rd
, (double) value
);
7894 aarch64_set_FP_float (cpu
, rd
, (float) value
);
7898 uint32_t value
= aarch64_get_reg_u32 (cpu
, rs
, NO_SP
);
7901 aarch64_set_FP_double (cpu
, rd
, (double) value
);
7903 aarch64_set_FP_float (cpu
, rd
, (float) value
);
7908 float_vector_move (sim_cpu
*cpu
)
7910 /* instr[31,17] == 100 1111 0101 0111
7911 instr[16] ==> direction 0=> to GR, 1=> from GR
7913 instr[9,5] ==> source
7914 instr[4,0] ==> dest. */
7916 unsigned rn
= INSTR (9, 5);
7917 unsigned rd
= INSTR (4, 0);
7919 NYI_assert (31, 17, 0x4F57);
7921 if (INSTR (15, 10) != 0)
7925 aarch64_set_vec_u64 (cpu
, rd
, 1, aarch64_get_reg_u64 (cpu
, rn
, NO_SP
));
7927 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, aarch64_get_vec_u64 (cpu
, rn
, 1));
7931 dexSimpleFPIntegerConvert (sim_cpu
*cpu
)
7933 /* instr[31] = size : 0 ==> 32 bit, 1 ==> 64 bit
7935 instr[29] = S : 0 ==> OK, 1 ==> UNALLOC
7938 instr[23,22] = type : 00 ==> single, 01 ==> double, 1x ==> UNALLOC
7940 instr[20,19] = rmode
7941 instr[18,16] = opcode
7942 instr[15,10] = 10 0000 */
7944 uint32_t rmode_opcode
;
7950 if (INSTR (31, 17) == 0x4F57)
7952 float_vector_move (cpu
);
7956 size
= INSTR (31, 31);
7961 type
= INSTR (23, 22);
7965 rmode_opcode
= INSTR (20, 16);
7966 size_type
= (size
<< 1) | type
; /* 0==32f, 1==32d, 2==64f, 3==64d. */
7968 switch (rmode_opcode
)
7970 case 2: /* SCVTF. */
7973 case 0: scvtf32 (cpu
); return;
7974 case 1: scvtd32 (cpu
); return;
7975 case 2: scvtf (cpu
); return;
7976 case 3: scvtd (cpu
); return;
7979 case 6: /* FMOV GR, Vec. */
7982 case 0: gfmovs (cpu
); return;
7983 case 3: gfmovd (cpu
); return;
7984 default: HALT_UNALLOC
;
7987 case 7: /* FMOV vec, GR. */
7990 case 0: fgmovs (cpu
); return;
7991 case 3: fgmovd (cpu
); return;
7992 default: HALT_UNALLOC
;
7995 case 24: /* FCVTZS. */
7998 case 0: fcvtszs32 (cpu
); return;
7999 case 1: fcvtszd32 (cpu
); return;
8000 case 2: fcvtszs (cpu
); return;
8001 case 3: fcvtszd (cpu
); return;
8004 case 25: do_fcvtzu (cpu
); return;
8005 case 3: do_UCVTF (cpu
); return;
8007 case 0: /* FCVTNS. */
8008 case 1: /* FCVTNU. */
8009 case 4: /* FCVTAS. */
8010 case 5: /* FCVTAU. */
8011 case 8: /* FCVPTS. */
8012 case 9: /* FCVTPU. */
8013 case 16: /* FCVTMS. */
8014 case 17: /* FCVTMU. */
8021 set_flags_for_float_compare (sim_cpu
*cpu
, float fvalue1
, float fvalue2
)
8025 if (isnan (fvalue1
) || isnan (fvalue2
))
8029 float result
= fvalue1
- fvalue2
;
8033 else if (result
< 0)
8035 else /* (result > 0). */
8039 aarch64_set_CPSR (cpu
, flags
);
8043 fcmps (sim_cpu
*cpu
)
8045 unsigned sm
= INSTR (20, 16);
8046 unsigned sn
= INSTR ( 9, 5);
8048 float fvalue1
= aarch64_get_FP_float (cpu
, sn
);
8049 float fvalue2
= aarch64_get_FP_float (cpu
, sm
);
8051 set_flags_for_float_compare (cpu
, fvalue1
, fvalue2
);
8054 /* Float compare to zero -- Invalid Operation exception
8055 only on signaling NaNs. */
8057 fcmpzs (sim_cpu
*cpu
)
8059 unsigned sn
= INSTR ( 9, 5);
8060 float fvalue1
= aarch64_get_FP_float (cpu
, sn
);
8062 set_flags_for_float_compare (cpu
, fvalue1
, 0.0f
);
8065 /* Float compare -- Invalid Operation exception on all NaNs. */
8067 fcmpes (sim_cpu
*cpu
)
8069 unsigned sm
= INSTR (20, 16);
8070 unsigned sn
= INSTR ( 9, 5);
8072 float fvalue1
= aarch64_get_FP_float (cpu
, sn
);
8073 float fvalue2
= aarch64_get_FP_float (cpu
, sm
);
8075 set_flags_for_float_compare (cpu
, fvalue1
, fvalue2
);
8078 /* Float compare to zero -- Invalid Operation exception on all NaNs. */
8080 fcmpzes (sim_cpu
*cpu
)
8082 unsigned sn
= INSTR ( 9, 5);
8083 float fvalue1
= aarch64_get_FP_float (cpu
, sn
);
8085 set_flags_for_float_compare (cpu
, fvalue1
, 0.0f
);
8089 set_flags_for_double_compare (sim_cpu
*cpu
, double dval1
, double dval2
)
8093 if (isnan (dval1
) || isnan (dval2
))
8097 double result
= dval1
- dval2
;
8101 else if (result
< 0)
8103 else /* (result > 0). */
8107 aarch64_set_CPSR (cpu
, flags
);
8110 /* Double compare -- Invalid Operation exception only on signaling NaNs. */
8112 fcmpd (sim_cpu
*cpu
)
8114 unsigned sm
= INSTR (20, 16);
8115 unsigned sn
= INSTR ( 9, 5);
8117 double dvalue1
= aarch64_get_FP_double (cpu
, sn
);
8118 double dvalue2
= aarch64_get_FP_double (cpu
, sm
);
8120 set_flags_for_double_compare (cpu
, dvalue1
, dvalue2
);
8123 /* Double compare to zero -- Invalid Operation exception
8124 only on signaling NaNs. */
8126 fcmpzd (sim_cpu
*cpu
)
8128 unsigned sn
= INSTR ( 9, 5);
8129 double dvalue1
= aarch64_get_FP_double (cpu
, sn
);
8131 set_flags_for_double_compare (cpu
, dvalue1
, 0.0);
8134 /* Double compare -- Invalid Operation exception on all NaNs. */
8136 fcmped (sim_cpu
*cpu
)
8138 unsigned sm
= INSTR (20, 16);
8139 unsigned sn
= INSTR ( 9, 5);
8141 double dvalue1
= aarch64_get_FP_double (cpu
, sn
);
8142 double dvalue2
= aarch64_get_FP_double (cpu
, sm
);
8144 set_flags_for_double_compare (cpu
, dvalue1
, dvalue2
);
8147 /* Double compare to zero -- Invalid Operation exception on all NaNs. */
8149 fcmpzed (sim_cpu
*cpu
)
8151 unsigned sn
= INSTR ( 9, 5);
8152 double dvalue1
= aarch64_get_FP_double (cpu
, sn
);
8154 set_flags_for_double_compare (cpu
, dvalue1
, 0.0);
8158 dexSimpleFPCompare (sim_cpu
*cpu
)
8160 /* assert instr[28,25] == 1111
8161 instr[30:24:21:13,10] = 0011000
8162 instr[31] = M : 0 ==> OK, 1 ==> UNALLOC
8163 instr[29] ==> S : 0 ==> OK, 1 ==> UNALLOC
8164 instr[23,22] ==> type : 0 ==> single, 01 ==> double, 1x ==> UNALLOC
8165 instr[15,14] ==> op : 00 ==> OK, ow ==> UNALLOC
8166 instr[4,0] ==> opcode2 : 00000 ==> FCMP, 10000 ==> FCMPE,
8167 01000 ==> FCMPZ, 11000 ==> FCMPEZ,
8170 uint32_t M_S
= (INSTR (31, 31) << 1) | INSTR (29, 29);
8171 uint32_t type
= INSTR (23, 22);
8172 uint32_t op
= INSTR (15, 14);
8173 uint32_t op2_2_0
= INSTR (2, 0);
8187 /* dispatch on type and top 2 bits of opcode. */
8188 dispatch
= (type
<< 2) | INSTR (4, 3);
8192 case 0: fcmps (cpu
); return;
8193 case 1: fcmpzs (cpu
); return;
8194 case 2: fcmpes (cpu
); return;
8195 case 3: fcmpzes (cpu
); return;
8196 case 4: fcmpd (cpu
); return;
8197 case 5: fcmpzd (cpu
); return;
8198 case 6: fcmped (cpu
); return;
8199 case 7: fcmpzed (cpu
); return;
8204 do_scalar_FADDP (sim_cpu
*cpu
)
8206 /* instr [31,23] = 0111 1110 0
8207 instr [22] = single(0)/double(1)
8208 instr [21,10] = 11 0000 1101 10
8210 instr [4,0] = Fd. */
8212 unsigned Fn
= INSTR (9, 5);
8213 unsigned Fd
= INSTR (4, 0);
8215 NYI_assert (31, 23, 0x0FC);
8216 NYI_assert (21, 10, 0xC36);
8220 double val1
= aarch64_get_vec_double (cpu
, Fn
, 0);
8221 double val2
= aarch64_get_vec_double (cpu
, Fn
, 1);
8223 aarch64_set_FP_double (cpu
, Fd
, val1
+ val2
);
8227 float val1
= aarch64_get_vec_float (cpu
, Fn
, 0);
8228 float val2
= aarch64_get_vec_float (cpu
, Fn
, 1);
8230 aarch64_set_FP_float (cpu
, Fd
, val1
+ val2
);
8234 /* Floating point absolute difference. */
8237 do_scalar_FABD (sim_cpu
*cpu
)
8239 /* instr [31,23] = 0111 1110 1
8240 instr [22] = float(0)/double(1)
8243 instr [15,10] = 1101 01
8245 instr [4, 0] = Rd. */
8247 unsigned rm
= INSTR (20, 16);
8248 unsigned rn
= INSTR (9, 5);
8249 unsigned rd
= INSTR (4, 0);
8251 NYI_assert (31, 23, 0x0FD);
8252 NYI_assert (21, 21, 1);
8253 NYI_assert (15, 10, 0x35);
8256 aarch64_set_FP_double (cpu
, rd
,
8257 fabs (aarch64_get_FP_double (cpu
, rn
)
8258 - aarch64_get_FP_double (cpu
, rm
)));
8260 aarch64_set_FP_float (cpu
, rd
,
8261 fabsf (aarch64_get_FP_float (cpu
, rn
)
8262 - aarch64_get_FP_float (cpu
, rm
)));
8266 do_scalar_CMGT (sim_cpu
*cpu
)
8268 /* instr [31,21] = 0101 1110 111
8270 instr [15,10] = 00 1101
8272 instr [4, 0] = Rd. */
8274 unsigned rm
= INSTR (20, 16);
8275 unsigned rn
= INSTR (9, 5);
8276 unsigned rd
= INSTR (4, 0);
8278 NYI_assert (31, 21, 0x2F7);
8279 NYI_assert (15, 10, 0x0D);
8281 aarch64_set_vec_u64 (cpu
, rd
, 0,
8282 aarch64_get_vec_u64 (cpu
, rn
, 0) >
8283 aarch64_get_vec_u64 (cpu
, rm
, 0) ? -1L : 0L);
8287 do_scalar_USHR (sim_cpu
*cpu
)
8289 /* instr [31,23] = 0111 1111 0
8290 instr [22,16] = shift amount
8291 instr [15,10] = 0000 01
8293 instr [4, 0] = Rd. */
8295 unsigned amount
= 128 - INSTR (22, 16);
8296 unsigned rn
= INSTR (9, 5);
8297 unsigned rd
= INSTR (4, 0);
8299 NYI_assert (31, 23, 0x0FE);
8300 NYI_assert (15, 10, 0x01);
8302 aarch64_set_vec_u64 (cpu
, rd
, 0,
8303 aarch64_get_vec_u64 (cpu
, rn
, 0) >> amount
);
8307 do_scalar_SSHL (sim_cpu
*cpu
)
8309 /* instr [31,21] = 0101 1110 111
8311 instr [15,10] = 0100 01
8313 instr [4, 0] = Rd. */
8315 unsigned rm
= INSTR (20, 16);
8316 unsigned rn
= INSTR (9, 5);
8317 unsigned rd
= INSTR (4, 0);
8318 signed int shift
= aarch64_get_vec_s8 (cpu
, rm
, 0);
8320 NYI_assert (31, 21, 0x2F7);
8321 NYI_assert (15, 10, 0x11);
8324 aarch64_set_vec_s64 (cpu
, rd
, 0,
8325 aarch64_get_vec_s64 (cpu
, rn
, 0) << shift
);
8327 aarch64_set_vec_s64 (cpu
, rd
, 0,
8328 aarch64_get_vec_s64 (cpu
, rn
, 0) >> - shift
);
8332 do_scalar_shift (sim_cpu
*cpu
)
8334 /* instr [31,23] = 0101 1111 0
8335 instr [22,16] = shift amount
8336 instr [15,10] = 0101 01 [SHL]
8337 instr [15,10] = 0000 01 [SSHR]
8339 instr [4, 0] = Rd. */
8341 unsigned rn
= INSTR (9, 5);
8342 unsigned rd
= INSTR (4, 0);
8345 NYI_assert (31, 23, 0x0BE);
8347 if (INSTR (22, 22) == 0)
8350 switch (INSTR (15, 10))
8352 case 0x01: /* SSHR */
8353 amount
= 128 - INSTR (22, 16);
8354 aarch64_set_vec_s64 (cpu
, rd
, 0,
8355 aarch64_get_vec_s64 (cpu
, rn
, 0) >> amount
);
8357 case 0x15: /* SHL */
8358 amount
= INSTR (22, 16) - 64;
8359 aarch64_set_vec_u64 (cpu
, rd
, 0,
8360 aarch64_get_vec_u64 (cpu
, rn
, 0) << amount
);
8367 /* FCMEQ FCMGT FCMGE. */
8369 do_scalar_FCM (sim_cpu
*cpu
)
8371 /* instr [31,30] = 01
8373 instr [28,24] = 1 1110
8378 instr [15,12] = 1110
8382 instr [4, 0] = Rd. */
8384 unsigned rm
= INSTR (20, 16);
8385 unsigned rn
= INSTR (9, 5);
8386 unsigned rd
= INSTR (4, 0);
8387 unsigned EUac
= (INSTR (23, 23) << 2) | (INSTR (29, 29) << 1) | INSTR (11, 11);
8392 NYI_assert (31, 30, 1);
8393 NYI_assert (28, 24, 0x1E);
8394 NYI_assert (21, 21, 1);
8395 NYI_assert (15, 12, 0xE);
8396 NYI_assert (10, 10, 1);
8400 double val1
= aarch64_get_FP_double (cpu
, rn
);
8401 double val2
= aarch64_get_FP_double (cpu
, rm
);
8406 result
= val1
== val2
;
8414 result
= val1
>= val2
;
8422 result
= val1
> val2
;
8429 aarch64_set_vec_u32 (cpu
, rd
, 0, result
? -1 : 0);
8433 val1
= aarch64_get_FP_float (cpu
, rn
);
8434 val2
= aarch64_get_FP_float (cpu
, rm
);
8439 result
= val1
== val2
;
8443 val1
= fabsf (val1
);
8444 val2
= fabsf (val2
);
8447 result
= val1
>= val2
;
8451 val1
= fabsf (val1
);
8452 val2
= fabsf (val2
);
8455 result
= val1
> val2
;
8462 aarch64_set_vec_u32 (cpu
, rd
, 0, result
? -1 : 0);
8465 /* An alias of DUP. */
8467 do_scalar_MOV (sim_cpu
*cpu
)
8469 /* instr [31,21] = 0101 1110 000
8470 instr [20,16] = imm5
8471 instr [15,10] = 0000 01
8473 instr [4, 0] = Rd. */
8475 unsigned rn
= INSTR (9, 5);
8476 unsigned rd
= INSTR (4, 0);
8479 NYI_assert (31, 21, 0x2F0);
8480 NYI_assert (15, 10, 0x01);
8485 index
= INSTR (20, 17);
8487 (cpu
, rd
, 0, aarch64_get_vec_u8 (cpu
, rn
, index
));
8489 else if (INSTR (17, 17))
8492 index
= INSTR (20, 18);
8494 (cpu
, rd
, 0, aarch64_get_vec_u16 (cpu
, rn
, index
));
8496 else if (INSTR (18, 18))
8499 index
= INSTR (20, 19);
8501 (cpu
, rd
, 0, aarch64_get_vec_u32 (cpu
, rn
, index
));
8503 else if (INSTR (19, 19))
8506 index
= INSTR (20, 20);
8508 (cpu
, rd
, 0, aarch64_get_vec_u64 (cpu
, rn
, index
));
8515 do_scalar_NEG (sim_cpu
*cpu
)
8517 /* instr [31,10] = 0111 1110 1110 0000 1011 10
8519 instr [4, 0] = Rd. */
8521 unsigned rn
= INSTR (9, 5);
8522 unsigned rd
= INSTR (4, 0);
8524 NYI_assert (31, 10, 0x1FB82E);
8526 aarch64_set_vec_u64 (cpu
, rd
, 0, - aarch64_get_vec_u64 (cpu
, rn
, 0));
8530 do_scalar_USHL (sim_cpu
*cpu
)
8532 /* instr [31,21] = 0111 1110 111
8534 instr [15,10] = 0100 01
8536 instr [4, 0] = Rd. */
8538 unsigned rm
= INSTR (20, 16);
8539 unsigned rn
= INSTR (9, 5);
8540 unsigned rd
= INSTR (4, 0);
8541 signed int shift
= aarch64_get_vec_s8 (cpu
, rm
, 0);
8543 NYI_assert (31, 21, 0x3F7);
8544 NYI_assert (15, 10, 0x11);
8547 aarch64_set_vec_u64 (cpu
, rd
, 0, aarch64_get_vec_u64 (cpu
, rn
, 0) << shift
);
8549 aarch64_set_vec_u64 (cpu
, rd
, 0, aarch64_get_vec_u64 (cpu
, rn
, 0) >> - shift
);
8553 do_double_add (sim_cpu
*cpu
)
8555 /* instr [31,21] = 0101 1110 111
8557 instr [15,10] = 1000 01
8559 instr [4,0] = Fd. */
8566 NYI_assert (31, 21, 0x2F7);
8567 NYI_assert (15, 10, 0x21);
8571 Fn
= INSTR (20, 16);
8573 val1
= aarch64_get_FP_double (cpu
, Fm
);
8574 val2
= aarch64_get_FP_double (cpu
, Fn
);
8576 aarch64_set_FP_double (cpu
, Fd
, val1
+ val2
);
8580 do_scalar_UCVTF (sim_cpu
*cpu
)
8582 /* instr [31,23] = 0111 1110 0
8583 instr [22] = single(0)/double(1)
8584 instr [21,10] = 10 0001 1101 10
8586 instr [4,0] = rd. */
8588 unsigned rn
= INSTR (9, 5);
8589 unsigned rd
= INSTR (4, 0);
8591 NYI_assert (31, 23, 0x0FC);
8592 NYI_assert (21, 10, 0x876);
8596 uint64_t val
= aarch64_get_vec_u64 (cpu
, rn
, 0);
8598 aarch64_set_vec_double (cpu
, rd
, 0, (double) val
);
8602 uint32_t val
= aarch64_get_vec_u32 (cpu
, rn
, 0);
8604 aarch64_set_vec_float (cpu
, rd
, 0, (float) val
);
8609 do_scalar_vec (sim_cpu
*cpu
)
8611 /* instr [30] = 1. */
8612 /* instr [28,25] = 1111. */
8613 switch (INSTR (31, 23))
8616 switch (INSTR (15, 10))
8618 case 0x01: do_scalar_MOV (cpu
); return;
8619 case 0x39: do_scalar_FCM (cpu
); return;
8620 case 0x3B: do_scalar_FCM (cpu
); return;
8624 case 0xBE: do_scalar_shift (cpu
); return;
8627 switch (INSTR (15, 10))
8630 switch (INSTR (21, 16))
8632 case 0x30: do_scalar_FADDP (cpu
); return;
8633 case 0x21: do_scalar_UCVTF (cpu
); return;
8636 case 0x39: do_scalar_FCM (cpu
); return;
8637 case 0x3B: do_scalar_FCM (cpu
); return;
8642 switch (INSTR (15, 10))
8644 case 0x0D: do_scalar_CMGT (cpu
); return;
8645 case 0x11: do_scalar_USHL (cpu
); return;
8646 case 0x2E: do_scalar_NEG (cpu
); return;
8647 case 0x35: do_scalar_FABD (cpu
); return;
8648 case 0x39: do_scalar_FCM (cpu
); return;
8649 case 0x3B: do_scalar_FCM (cpu
); return;
8654 case 0xFE: do_scalar_USHR (cpu
); return;
8657 switch (INSTR (15, 10))
8659 case 0x21: do_double_add (cpu
); return;
8660 case 0x11: do_scalar_SSHL (cpu
); return;
8671 dexAdvSIMD1 (sim_cpu
*cpu
)
8673 /* instr [28,25] = 1 111. */
8675 /* We are currently only interested in the basic
8676 scalar fp routines which all have bit 30 = 0. */
8678 do_scalar_vec (cpu
);
8680 /* instr[24] is set for FP data processing 3-source and clear for
8681 all other basic scalar fp instruction groups. */
8682 else if (INSTR (24, 24))
8683 dexSimpleFPDataProc3Source (cpu
);
8685 /* instr[21] is clear for floating <-> fixed conversions and set for
8686 all other basic scalar fp instruction groups. */
8687 else if (!INSTR (21, 21))
8688 dexSimpleFPFixedConvert (cpu
);
8690 /* instr[11,10] : 01 ==> cond compare, 10 ==> Data Proc 2 Source
8691 11 ==> cond select, 00 ==> other. */
8693 switch (INSTR (11, 10))
8695 case 1: dexSimpleFPCondCompare (cpu
); return;
8696 case 2: dexSimpleFPDataProc2Source (cpu
); return;
8697 case 3: dexSimpleFPCondSelect (cpu
); return;
8700 /* Now an ordered cascade of tests.
8701 FP immediate has instr [12] == 1.
8702 FP compare has instr [13] == 1.
8703 FP Data Proc 1 Source has instr [14] == 1.
8704 FP floating <--> integer conversions has instr [15] == 0. */
8706 dexSimpleFPImmediate (cpu
);
8708 else if (INSTR (13, 13))
8709 dexSimpleFPCompare (cpu
);
8711 else if (INSTR (14, 14))
8712 dexSimpleFPDataProc1Source (cpu
);
8714 else if (!INSTR (15, 15))
8715 dexSimpleFPIntegerConvert (cpu
);
8718 /* If we get here then instr[15] == 1 which means UNALLOC. */
8723 /* PC relative addressing. */
8726 pcadr (sim_cpu
*cpu
)
8728 /* instr[31] = op : 0 ==> ADR, 1 ==> ADRP
8729 instr[30,29] = immlo
8730 instr[23,5] = immhi. */
8732 unsigned rd
= INSTR (4, 0);
8733 uint32_t isPage
= INSTR (31, 31);
8734 union { int64_t u64
; uint64_t s64
; } imm
;
8737 imm
.s64
= simm64 (aarch64_get_instr (cpu
), 23, 5);
8739 offset
= (offset
<< 2) | INSTR (30, 29);
8741 address
= aarch64_get_PC (cpu
);
8749 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, address
+ offset
);
8752 /* Specific decode and execute for group Data Processing Immediate. */
8755 dexPCRelAddressing (sim_cpu
*cpu
)
8757 /* assert instr[28,24] = 10000. */
8761 /* Immediate logical.
8762 The bimm32/64 argument is constructed by replicating a 2, 4, 8,
8763 16, 32 or 64 bit sequence pulled out at decode and possibly
8766 N.B. the output register (dest) can normally be Xn or SP
8767 the exception occurs for flag setting instructions which may
8768 only use Xn for the output (dest). The input register can
8771 /* 32 bit and immediate. */
8773 and32 (sim_cpu
*cpu
, uint32_t bimm
)
8775 unsigned rn
= INSTR (9, 5);
8776 unsigned rd
= INSTR (4, 0);
8778 aarch64_set_reg_u64 (cpu
, rd
, SP_OK
,
8779 aarch64_get_reg_u32 (cpu
, rn
, NO_SP
) & bimm
);
8782 /* 64 bit and immediate. */
8784 and64 (sim_cpu
*cpu
, uint64_t bimm
)
8786 unsigned rn
= INSTR (9, 5);
8787 unsigned rd
= INSTR (4, 0);
8789 aarch64_set_reg_u64 (cpu
, rd
, SP_OK
,
8790 aarch64_get_reg_u64 (cpu
, rn
, NO_SP
) & bimm
);
8793 /* 32 bit and immediate set flags. */
8795 ands32 (sim_cpu
*cpu
, uint32_t bimm
)
8797 unsigned rn
= INSTR (9, 5);
8798 unsigned rd
= INSTR (4, 0);
8800 uint32_t value1
= aarch64_get_reg_u32 (cpu
, rn
, NO_SP
);
8801 uint32_t value2
= bimm
;
8803 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, value1
& value2
);
8804 set_flags_for_binop32 (cpu
, value1
& value2
);
8807 /* 64 bit and immediate set flags. */
8809 ands64 (sim_cpu
*cpu
, uint64_t bimm
)
8811 unsigned rn
= INSTR (9, 5);
8812 unsigned rd
= INSTR (4, 0);
8814 uint64_t value1
= aarch64_get_reg_u64 (cpu
, rn
, NO_SP
);
8815 uint64_t value2
= bimm
;
8817 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, value1
& value2
);
8818 set_flags_for_binop64 (cpu
, value1
& value2
);
8821 /* 32 bit exclusive or immediate. */
8823 eor32 (sim_cpu
*cpu
, uint32_t bimm
)
8825 unsigned rn
= INSTR (9, 5);
8826 unsigned rd
= INSTR (4, 0);
8828 aarch64_set_reg_u64 (cpu
, rd
, SP_OK
,
8829 aarch64_get_reg_u32 (cpu
, rn
, NO_SP
) ^ bimm
);
8832 /* 64 bit exclusive or immediate. */
8834 eor64 (sim_cpu
*cpu
, uint64_t bimm
)
8836 unsigned rn
= INSTR (9, 5);
8837 unsigned rd
= INSTR (4, 0);
8839 aarch64_set_reg_u64 (cpu
, rd
, SP_OK
,
8840 aarch64_get_reg_u64 (cpu
, rn
, NO_SP
) ^ bimm
);
8843 /* 32 bit or immediate. */
8845 orr32 (sim_cpu
*cpu
, uint32_t bimm
)
8847 unsigned rn
= INSTR (9, 5);
8848 unsigned rd
= INSTR (4, 0);
8850 aarch64_set_reg_u64 (cpu
, rd
, SP_OK
,
8851 aarch64_get_reg_u32 (cpu
, rn
, NO_SP
) | bimm
);
8854 /* 64 bit or immediate. */
8856 orr64 (sim_cpu
*cpu
, uint64_t bimm
)
8858 unsigned rn
= INSTR (9, 5);
8859 unsigned rd
= INSTR (4, 0);
8861 aarch64_set_reg_u64 (cpu
, rd
, SP_OK
,
8862 aarch64_get_reg_u64 (cpu
, rn
, NO_SP
) | bimm
);
8865 /* Logical shifted register.
8866 These allow an optional LSL, ASR, LSR or ROR to the second source
8867 register with a count up to the register bit count.
8868 N.B register args may not be SP. */
8870 /* 32 bit AND shifted register. */
8872 and32_shift (sim_cpu
*cpu
, Shift shift
, uint32_t count
)
8874 unsigned rm
= INSTR (20, 16);
8875 unsigned rn
= INSTR (9, 5);
8876 unsigned rd
= INSTR (4, 0);
8879 (cpu
, rd
, NO_SP
, aarch64_get_reg_u32 (cpu
, rn
, NO_SP
)
8880 & shifted32 (aarch64_get_reg_u32 (cpu
, rm
, NO_SP
), shift
, count
));
8883 /* 64 bit AND shifted register. */
8885 and64_shift (sim_cpu
*cpu
, Shift shift
, uint32_t count
)
8887 unsigned rm
= INSTR (20, 16);
8888 unsigned rn
= INSTR (9, 5);
8889 unsigned rd
= INSTR (4, 0);
8892 (cpu
, rd
, NO_SP
, aarch64_get_reg_u64 (cpu
, rn
, NO_SP
)
8893 & shifted64 (aarch64_get_reg_u64 (cpu
, rm
, NO_SP
), shift
, count
));
8896 /* 32 bit AND shifted register setting flags. */
8898 ands32_shift (sim_cpu
*cpu
, Shift shift
, uint32_t count
)
8900 unsigned rm
= INSTR (20, 16);
8901 unsigned rn
= INSTR (9, 5);
8902 unsigned rd
= INSTR (4, 0);
8904 uint32_t value1
= aarch64_get_reg_u32 (cpu
, rn
, NO_SP
);
8905 uint32_t value2
= shifted32 (aarch64_get_reg_u32 (cpu
, rm
, NO_SP
),
8908 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, value1
& value2
);
8909 set_flags_for_binop32 (cpu
, value1
& value2
);
8912 /* 64 bit AND shifted register setting flags. */
8914 ands64_shift (sim_cpu
*cpu
, Shift shift
, uint32_t count
)
8916 unsigned rm
= INSTR (20, 16);
8917 unsigned rn
= INSTR (9, 5);
8918 unsigned rd
= INSTR (4, 0);
8920 uint64_t value1
= aarch64_get_reg_u64 (cpu
, rn
, NO_SP
);
8921 uint64_t value2
= shifted64 (aarch64_get_reg_u64 (cpu
, rm
, NO_SP
),
8924 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, value1
& value2
);
8925 set_flags_for_binop64 (cpu
, value1
& value2
);
8928 /* 32 bit BIC shifted register. */
8930 bic32_shift (sim_cpu
*cpu
, Shift shift
, uint32_t count
)
8932 unsigned rm
= INSTR (20, 16);
8933 unsigned rn
= INSTR (9, 5);
8934 unsigned rd
= INSTR (4, 0);
8937 (cpu
, rd
, NO_SP
, aarch64_get_reg_u32 (cpu
, rn
, NO_SP
)
8938 & ~ shifted32 (aarch64_get_reg_u32 (cpu
, rm
, NO_SP
), shift
, count
));
8941 /* 64 bit BIC shifted register. */
8943 bic64_shift (sim_cpu
*cpu
, Shift shift
, uint32_t count
)
8945 unsigned rm
= INSTR (20, 16);
8946 unsigned rn
= INSTR (9, 5);
8947 unsigned rd
= INSTR (4, 0);
8950 (cpu
, rd
, NO_SP
, aarch64_get_reg_u64 (cpu
, rn
, NO_SP
)
8951 & ~ shifted64 (aarch64_get_reg_u64 (cpu
, rm
, NO_SP
), shift
, count
));
8954 /* 32 bit BIC shifted register setting flags. */
8956 bics32_shift (sim_cpu
*cpu
, Shift shift
, uint32_t count
)
8958 unsigned rm
= INSTR (20, 16);
8959 unsigned rn
= INSTR (9, 5);
8960 unsigned rd
= INSTR (4, 0);
8962 uint32_t value1
= aarch64_get_reg_u32 (cpu
, rn
, NO_SP
);
8963 uint32_t value2
= ~ shifted32 (aarch64_get_reg_u32 (cpu
, rm
, NO_SP
),
8966 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, value1
& value2
);
8967 set_flags_for_binop32 (cpu
, value1
& value2
);
8970 /* 64 bit BIC shifted register setting flags. */
8972 bics64_shift (sim_cpu
*cpu
, Shift shift
, uint32_t count
)
8974 unsigned rm
= INSTR (20, 16);
8975 unsigned rn
= INSTR (9, 5);
8976 unsigned rd
= INSTR (4, 0);
8978 uint64_t value1
= aarch64_get_reg_u64 (cpu
, rn
, NO_SP
);
8979 uint64_t value2
= ~ shifted64 (aarch64_get_reg_u64 (cpu
, rm
, NO_SP
),
8982 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, value1
& value2
);
8983 set_flags_for_binop64 (cpu
, value1
& value2
);
8986 /* 32 bit EON shifted register. */
8988 eon32_shift (sim_cpu
*cpu
, Shift shift
, uint32_t count
)
8990 unsigned rm
= INSTR (20, 16);
8991 unsigned rn
= INSTR (9, 5);
8992 unsigned rd
= INSTR (4, 0);
8995 (cpu
, rd
, NO_SP
, aarch64_get_reg_u32 (cpu
, rn
, NO_SP
)
8996 ^ ~ shifted32 (aarch64_get_reg_u32 (cpu
, rm
, NO_SP
), shift
, count
));
8999 /* 64 bit EON shifted register. */
9001 eon64_shift (sim_cpu
*cpu
, Shift shift
, uint32_t count
)
9003 unsigned rm
= INSTR (20, 16);
9004 unsigned rn
= INSTR (9, 5);
9005 unsigned rd
= INSTR (4, 0);
9008 (cpu
, rd
, NO_SP
, aarch64_get_reg_u64 (cpu
, rn
, NO_SP
)
9009 ^ ~ shifted64 (aarch64_get_reg_u64 (cpu
, rm
, NO_SP
), shift
, count
));
9012 /* 32 bit EOR shifted register. */
9014 eor32_shift (sim_cpu
*cpu
, Shift shift
, uint32_t count
)
9016 unsigned rm
= INSTR (20, 16);
9017 unsigned rn
= INSTR (9, 5);
9018 unsigned rd
= INSTR (4, 0);
9021 (cpu
, rd
, NO_SP
, aarch64_get_reg_u32 (cpu
, rn
, NO_SP
)
9022 ^ shifted32 (aarch64_get_reg_u32 (cpu
, rm
, NO_SP
), shift
, count
));
9025 /* 64 bit EOR shifted register. */
9027 eor64_shift (sim_cpu
*cpu
, Shift shift
, uint32_t count
)
9029 unsigned rm
= INSTR (20, 16);
9030 unsigned rn
= INSTR (9, 5);
9031 unsigned rd
= INSTR (4, 0);
9034 (cpu
, rd
, NO_SP
, aarch64_get_reg_u64 (cpu
, rn
, NO_SP
)
9035 ^ shifted64 (aarch64_get_reg_u64 (cpu
, rm
, NO_SP
), shift
, count
));
9038 /* 32 bit ORR shifted register. */
9040 orr32_shift (sim_cpu
*cpu
, Shift shift
, uint32_t count
)
9042 unsigned rm
= INSTR (20, 16);
9043 unsigned rn
= INSTR (9, 5);
9044 unsigned rd
= INSTR (4, 0);
9047 (cpu
, rd
, NO_SP
, aarch64_get_reg_u32 (cpu
, rn
, NO_SP
)
9048 | shifted32 (aarch64_get_reg_u32 (cpu
, rm
, NO_SP
), shift
, count
));
9051 /* 64 bit ORR shifted register. */
9053 orr64_shift (sim_cpu
*cpu
, Shift shift
, uint32_t count
)
9055 unsigned rm
= INSTR (20, 16);
9056 unsigned rn
= INSTR (9, 5);
9057 unsigned rd
= INSTR (4, 0);
9060 (cpu
, rd
, NO_SP
, aarch64_get_reg_u64 (cpu
, rn
, NO_SP
)
9061 | shifted64 (aarch64_get_reg_u64 (cpu
, rm
, NO_SP
), shift
, count
));
9064 /* 32 bit ORN shifted register. */
9066 orn32_shift (sim_cpu
*cpu
, Shift shift
, uint32_t count
)
9068 unsigned rm
= INSTR (20, 16);
9069 unsigned rn
= INSTR (9, 5);
9070 unsigned rd
= INSTR (4, 0);
9073 (cpu
, rd
, NO_SP
, aarch64_get_reg_u32 (cpu
, rn
, NO_SP
)
9074 | ~ shifted32 (aarch64_get_reg_u32 (cpu
, rm
, NO_SP
), shift
, count
));
9077 /* 64 bit ORN shifted register. */
9079 orn64_shift (sim_cpu
*cpu
, Shift shift
, uint32_t count
)
9081 unsigned rm
= INSTR (20, 16);
9082 unsigned rn
= INSTR (9, 5);
9083 unsigned rd
= INSTR (4, 0);
9086 (cpu
, rd
, NO_SP
, aarch64_get_reg_u64 (cpu
, rn
, NO_SP
)
9087 | ~ shifted64 (aarch64_get_reg_u64 (cpu
, rm
, NO_SP
), shift
, count
));
9091 dexLogicalImmediate (sim_cpu
*cpu
)
9093 /* assert instr[28,23] = 1001000
9094 instr[31] = size : 0 ==> 32 bit, 1 ==> 64 bit
9095 instr[30,29] = op : 0 ==> AND, 1 ==> ORR, 2 ==> EOR, 3 ==> ANDS
9096 instr[22] = N : used to construct immediate mask
9102 /* 32 bit operations must have N = 0 or else we have an UNALLOC. */
9103 uint32_t size
= INSTR (31, 31);
9104 uint32_t N
= INSTR (22, 22);
9105 /* uint32_t immr = INSTR (21, 16);. */
9106 /* uint32_t imms = INSTR (15, 10);. */
9107 uint32_t index
= INSTR (22, 10);
9108 uint64_t bimm64
= LITable
[index
];
9109 uint32_t dispatch
= INSTR (30, 29);
9119 uint32_t bimm
= (uint32_t) bimm64
;
9123 case 0: and32 (cpu
, bimm
); return;
9124 case 1: orr32 (cpu
, bimm
); return;
9125 case 2: eor32 (cpu
, bimm
); return;
9126 case 3: ands32 (cpu
, bimm
); return;
9133 case 0: and64 (cpu
, bimm64
); return;
9134 case 1: orr64 (cpu
, bimm64
); return;
9135 case 2: eor64 (cpu
, bimm64
); return;
9136 case 3: ands64 (cpu
, bimm64
); return;
9143 The uimm argument is a 16 bit value to be inserted into the
9144 target register the pos argument locates the 16 bit word in the
9145 dest register i.e. it is in {0, 1} for 32 bit and {0, 1, 2,
9147 N.B register arg may not be SP so it should be.
9148 accessed using the setGZRegisterXXX accessors. */
9150 /* 32 bit move 16 bit immediate zero remaining shorts. */
9152 movz32 (sim_cpu
*cpu
, uint32_t val
, uint32_t pos
)
9154 unsigned rd
= INSTR (4, 0);
9156 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, val
<< (pos
* 16));
9159 /* 64 bit move 16 bit immediate zero remaining shorts. */
9161 movz64 (sim_cpu
*cpu
, uint32_t val
, uint32_t pos
)
9163 unsigned rd
= INSTR (4, 0);
9165 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, ((uint64_t) val
) << (pos
* 16));
9168 /* 32 bit move 16 bit immediate negated. */
9170 movn32 (sim_cpu
*cpu
, uint32_t val
, uint32_t pos
)
9172 unsigned rd
= INSTR (4, 0);
9174 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, ((val
<< (pos
* 16)) ^ 0xffffffffU
));
9177 /* 64 bit move 16 bit immediate negated. */
9179 movn64 (sim_cpu
*cpu
, uint32_t val
, uint32_t pos
)
9181 unsigned rd
= INSTR (4, 0);
9184 (cpu
, rd
, NO_SP
, ((((uint64_t) val
) << (pos
* 16))
9185 ^ 0xffffffffffffffffULL
));
9188 /* 32 bit move 16 bit immediate keep remaining shorts. */
9190 movk32 (sim_cpu
*cpu
, uint32_t val
, uint32_t pos
)
9192 unsigned rd
= INSTR (4, 0);
9193 uint32_t current
= aarch64_get_reg_u32 (cpu
, rd
, NO_SP
);
9194 uint32_t value
= val
<< (pos
* 16);
9195 uint32_t mask
= ~(0xffffU
<< (pos
* 16));
9197 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, (value
| (current
& mask
)));
9200 /* 64 bit move 16 it immediate keep remaining shorts. */
9202 movk64 (sim_cpu
*cpu
, uint32_t val
, uint32_t pos
)
9204 unsigned rd
= INSTR (4, 0);
9205 uint64_t current
= aarch64_get_reg_u64 (cpu
, rd
, NO_SP
);
9206 uint64_t value
= (uint64_t) val
<< (pos
* 16);
9207 uint64_t mask
= ~(0xffffULL
<< (pos
* 16));
9209 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, (value
| (current
& mask
)));
9213 dexMoveWideImmediate (sim_cpu
*cpu
)
9215 /* assert instr[28:23] = 100101
9216 instr[31] = size : 0 ==> 32 bit, 1 ==> 64 bit
9217 instr[30,29] = op : 0 ==> MOVN, 1 ==> UNALLOC, 2 ==> MOVZ, 3 ==> MOVK
9218 instr[22,21] = shift : 00 == LSL#0, 01 = LSL#16, 10 = LSL#32, 11 = LSL#48
9219 instr[20,5] = uimm16
9222 /* N.B. the (multiple of 16) shift is applied by the called routine,
9223 we just pass the multiplier. */
9226 uint32_t size
= INSTR (31, 31);
9227 uint32_t op
= INSTR (30, 29);
9228 uint32_t shift
= INSTR (22, 21);
9230 /* 32 bit can only shift 0 or 1 lot of 16.
9231 anything else is an unallocated instruction. */
9232 if (size
== 0 && (shift
> 1))
9238 imm
= INSTR (20, 5);
9243 movn32 (cpu
, imm
, shift
);
9245 movz32 (cpu
, imm
, shift
);
9247 movk32 (cpu
, imm
, shift
);
9252 movn64 (cpu
, imm
, shift
);
9254 movz64 (cpu
, imm
, shift
);
9256 movk64 (cpu
, imm
, shift
);
9260 /* Bitfield operations.
9261 These take a pair of bit positions r and s which are in {0..31}
9262 or {0..63} depending on the instruction word size.
9263 N.B register args may not be SP. */
9265 /* OK, we start with ubfm which just needs to pick
9266 some bits out of source zero the rest and write
9267 the result to dest. Just need two logical shifts. */
9269 /* 32 bit bitfield move, left and right of affected zeroed
9270 if r <= s Wd<s-r:0> = Wn<s:r> else Wd<32+s-r,32-r> = Wn<s:0>. */
9272 ubfm32 (sim_cpu
*cpu
, uint32_t r
, uint32_t s
)
9275 unsigned rn
= INSTR (9, 5);
9276 uint32_t value
= aarch64_get_reg_u32 (cpu
, rn
, NO_SP
);
9278 /* Pick either s+1-r or s+1 consecutive bits out of the original word. */
9281 /* 31:...:s:xxx:r:...:0 ==> 31:...:s-r:xxx:0.
9282 We want only bits s:xxx:r at the bottom of the word
9283 so we LSL bit s up to bit 31 i.e. by 31 - s
9284 and then we LSR to bring bit 31 down to bit s - r
9285 i.e. by 31 + r - s. */
9287 value
>>= 31 + r
- s
;
9291 /* 31:...:s:xxx:0 ==> 31:...:31-(r-1)+s:xxx:31-(r-1):...:0
9292 We want only bits s:xxx:0 starting at it 31-(r-1)
9293 so we LSL bit s up to bit 31 i.e. by 31 - s
9294 and then we LSL to bring bit 31 down to 31-(r-1)+s
9295 i.e. by r - (s + 1). */
9297 value
>>= r
- (s
+ 1);
9301 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, value
);
9304 /* 64 bit bitfield move, left and right of affected zeroed
9305 if r <= s Wd<s-r:0> = Wn<s:r> else Wd<64+s-r,64-r> = Wn<s:0>. */
9307 ubfm (sim_cpu
*cpu
, uint32_t r
, uint32_t s
)
9310 unsigned rn
= INSTR (9, 5);
9311 uint64_t value
= aarch64_get_reg_u64 (cpu
, rn
, NO_SP
);
9315 /* 63:...:s:xxx:r:...:0 ==> 63:...:s-r:xxx:0.
9316 We want only bits s:xxx:r at the bottom of the word.
9317 So we LSL bit s up to bit 63 i.e. by 63 - s
9318 and then we LSR to bring bit 63 down to bit s - r
9319 i.e. by 63 + r - s. */
9321 value
>>= 63 + r
- s
;
9325 /* 63:...:s:xxx:0 ==> 63:...:63-(r-1)+s:xxx:63-(r-1):...:0.
9326 We want only bits s:xxx:0 starting at it 63-(r-1).
9327 So we LSL bit s up to bit 63 i.e. by 63 - s
9328 and then we LSL to bring bit 63 down to 63-(r-1)+s
9329 i.e. by r - (s + 1). */
9331 value
>>= r
- (s
+ 1);
9335 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, value
);
9338 /* The signed versions need to insert sign bits
9339 on the left of the inserted bit field. so we do
9340 much the same as the unsigned version except we
9341 use an arithmetic shift right -- this just means
9342 we need to operate on signed values. */
9344 /* 32 bit bitfield move, left of affected sign-extended, right zeroed. */
9345 /* If r <= s Wd<s-r:0> = Wn<s:r> else Wd<32+s-r,32-r> = Wn<s:0>. */
9347 sbfm32 (sim_cpu
*cpu
, uint32_t r
, uint32_t s
)
9350 unsigned rn
= INSTR (9, 5);
9351 /* as per ubfm32 but use an ASR instead of an LSR. */
9352 int32_t value
= aarch64_get_reg_s32 (cpu
, rn
, NO_SP
);
9357 value
>>= 31 + r
- s
;
9362 value
>>= r
- (s
+ 1);
9366 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, (uint32_t) value
);
9369 /* 64 bit bitfield move, left of affected sign-extended, right zeroed. */
9370 /* If r <= s Wd<s-r:0> = Wn<s:r> else Wd<64+s-r,64-r> = Wn<s:0>. */
9372 sbfm (sim_cpu
*cpu
, uint32_t r
, uint32_t s
)
9375 unsigned rn
= INSTR (9, 5);
9376 /* acpu per ubfm but use an ASR instead of an LSR. */
9377 int64_t value
= aarch64_get_reg_s64 (cpu
, rn
, NO_SP
);
9382 value
>>= 63 + r
- s
;
9387 value
>>= r
- (s
+ 1);
9391 aarch64_set_reg_s64 (cpu
, rd
, NO_SP
, value
);
9394 /* Finally, these versions leave non-affected bits
9395 as is. so we need to generate the bits as per
9396 ubfm and also generate a mask to pick the
9397 bits from the original and computed values. */
9399 /* 32 bit bitfield move, non-affected bits left as is.
9400 If r <= s Wd<s-r:0> = Wn<s:r> else Wd<32+s-r,32-r> = Wn<s:0>. */
9402 bfm32 (sim_cpu
*cpu
, uint32_t r
, uint32_t s
)
9404 unsigned rn
= INSTR (9, 5);
9405 uint32_t value
= aarch64_get_reg_u32 (cpu
, rn
, NO_SP
);
9410 /* Pick either s+1-r or s+1 consecutive bits out of the original word. */
9413 /* 31:...:s:xxx:r:...:0 ==> 31:...:s-r:xxx:0.
9414 We want only bits s:xxx:r at the bottom of the word
9415 so we LSL bit s up to bit 31 i.e. by 31 - s
9416 and then we LSR to bring bit 31 down to bit s - r
9417 i.e. by 31 + r - s. */
9419 value
>>= 31 + r
- s
;
9420 /* the mask must include the same bits. */
9422 mask
>>= 31 + r
- s
;
9426 /* 31:...:s:xxx:0 ==> 31:...:31-(r-1)+s:xxx:31-(r-1):...:0.
9427 We want only bits s:xxx:0 starting at it 31-(r-1)
9428 so we LSL bit s up to bit 31 i.e. by 31 - s
9429 and then we LSL to bring bit 31 down to 31-(r-1)+s
9430 i.e. by r - (s + 1). */
9432 value
>>= r
- (s
+ 1);
9433 /* The mask must include the same bits. */
9435 mask
>>= r
- (s
+ 1);
9439 value2
= aarch64_get_reg_u32 (cpu
, rd
, NO_SP
);
9445 (cpu
, rd
, NO_SP
, (aarch64_get_reg_u32 (cpu
, rd
, NO_SP
) & ~mask
) | value
);
9448 /* 64 bit bitfield move, non-affected bits left as is.
9449 If r <= s Wd<s-r:0> = Wn<s:r> else Wd<64+s-r,64-r> = Wn<s:0>. */
9451 bfm (sim_cpu
*cpu
, uint32_t r
, uint32_t s
)
9454 unsigned rn
= INSTR (9, 5);
9455 uint64_t value
= aarch64_get_reg_u64 (cpu
, rn
, NO_SP
);
9456 uint64_t mask
= 0xffffffffffffffffULL
;
9460 /* 63:...:s:xxx:r:...:0 ==> 63:...:s-r:xxx:0.
9461 We want only bits s:xxx:r at the bottom of the word
9462 so we LSL bit s up to bit 63 i.e. by 63 - s
9463 and then we LSR to bring bit 63 down to bit s - r
9464 i.e. by 63 + r - s. */
9466 value
>>= 63 + r
- s
;
9467 /* The mask must include the same bits. */
9469 mask
>>= 63 + r
- s
;
9473 /* 63:...:s:xxx:0 ==> 63:...:63-(r-1)+s:xxx:63-(r-1):...:0
9474 We want only bits s:xxx:0 starting at it 63-(r-1)
9475 so we LSL bit s up to bit 63 i.e. by 63 - s
9476 and then we LSL to bring bit 63 down to 63-(r-1)+s
9477 i.e. by r - (s + 1). */
9479 value
>>= r
- (s
+ 1);
9480 /* The mask must include the same bits. */
9482 mask
>>= r
- (s
+ 1);
9487 (cpu
, rd
, NO_SP
, (aarch64_get_reg_u64 (cpu
, rd
, NO_SP
) & ~mask
) | value
);
9491 dexBitfieldImmediate (sim_cpu
*cpu
)
9493 /* assert instr[28:23] = 100110
9494 instr[31] = size : 0 ==> 32 bit, 1 ==> 64 bit
9495 instr[30,29] = op : 0 ==> SBFM, 1 ==> BFM, 2 ==> UBFM, 3 ==> UNALLOC
9496 instr[22] = N : must be 0 for 32 bit, 1 for 64 bit ow UNALLOC
9497 instr[21,16] = immr : 0xxxxx for 32 bit, xxxxxx for 64 bit
9498 instr[15,10] = imms : 0xxxxx for 32 bit, xxxxxx for 64 bit
9502 /* 32 bit operations must have N = 0 or else we have an UNALLOC. */
9505 uint32_t size
= INSTR (31, 31);
9506 uint32_t N
= INSTR (22, 22);
9507 /* 32 bit operations must have immr[5] = 0 and imms[5] = 0. */
9508 /* or else we have an UNALLOC. */
9509 uint32_t immr
= INSTR (21, 16);
9514 if (!size
&& uimm (immr
, 5, 5))
9517 imms
= INSTR (15, 10);
9518 if (!size
&& uimm (imms
, 5, 5))
9521 /* Switch on combined size and op. */
9522 dispatch
= INSTR (31, 29);
9525 case 0: sbfm32 (cpu
, immr
, imms
); return;
9526 case 1: bfm32 (cpu
, immr
, imms
); return;
9527 case 2: ubfm32 (cpu
, immr
, imms
); return;
9528 case 4: sbfm (cpu
, immr
, imms
); return;
9529 case 5: bfm (cpu
, immr
, imms
); return;
9530 case 6: ubfm (cpu
, immr
, imms
); return;
9531 default: HALT_UNALLOC
;
9536 do_EXTR_32 (sim_cpu
*cpu
)
9538 /* instr[31:21] = 00010011100
9540 instr[15,10] = imms : 0xxxxx for 32 bit
9543 unsigned rm
= INSTR (20, 16);
9544 unsigned imms
= INSTR (15, 10) & 31;
9545 unsigned rn
= INSTR ( 9, 5);
9546 unsigned rd
= INSTR ( 4, 0);
9550 val1
= aarch64_get_reg_u32 (cpu
, rm
, NO_SP
);
9552 val2
= aarch64_get_reg_u32 (cpu
, rn
, NO_SP
);
9553 val2
<<= (32 - imms
);
9555 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, val1
| val2
);
9559 do_EXTR_64 (sim_cpu
*cpu
)
9561 /* instr[31:21] = 10010011100
9566 unsigned rm
= INSTR (20, 16);
9567 unsigned imms
= INSTR (15, 10) & 63;
9568 unsigned rn
= INSTR ( 9, 5);
9569 unsigned rd
= INSTR ( 4, 0);
9572 val
= aarch64_get_reg_u64 (cpu
, rm
, NO_SP
);
9574 val
|= (aarch64_get_reg_u64 (cpu
, rn
, NO_SP
) << (64 - imms
));
9576 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, val
);
9580 dexExtractImmediate (sim_cpu
*cpu
)
9582 /* assert instr[28:23] = 100111
9583 instr[31] = size : 0 ==> 32 bit, 1 ==> 64 bit
9584 instr[30,29] = op21 : 0 ==> EXTR, 1,2,3 ==> UNALLOC
9585 instr[22] = N : must be 0 for 32 bit, 1 for 64 bit or UNALLOC
9586 instr[21] = op0 : must be 0 or UNALLOC
9588 instr[15,10] = imms : 0xxxxx for 32 bit, xxxxxx for 64 bit
9592 /* 32 bit operations must have N = 0 or else we have an UNALLOC. */
9593 /* 64 bit operations must have N = 1 or else we have an UNALLOC. */
9595 uint32_t size
= INSTR (31, 31);
9596 uint32_t N
= INSTR (22, 22);
9597 /* 32 bit operations must have imms[5] = 0
9598 or else we have an UNALLOC. */
9599 uint32_t imms
= INSTR (15, 10);
9604 if (!size
&& uimm (imms
, 5, 5))
9607 /* Switch on combined size and op. */
9608 dispatch
= INSTR (31, 29);
9613 else if (dispatch
== 4)
9616 else if (dispatch
== 1)
9623 dexDPImm (sim_cpu
*cpu
)
9625 /* uint32_t group = dispatchGroup (aarch64_get_instr (cpu));
9626 assert group == GROUP_DPIMM_1000 || grpoup == GROUP_DPIMM_1001
9627 bits [25,23] of a DPImm are the secondary dispatch vector. */
9628 uint32_t group2
= dispatchDPImm (aarch64_get_instr (cpu
));
9632 case DPIMM_PCADR_000
:
9633 case DPIMM_PCADR_001
:
9634 dexPCRelAddressing (cpu
);
9637 case DPIMM_ADDSUB_010
:
9638 case DPIMM_ADDSUB_011
:
9639 dexAddSubtractImmediate (cpu
);
9643 dexLogicalImmediate (cpu
);
9647 dexMoveWideImmediate (cpu
);
9650 case DPIMM_BITF_110
:
9651 dexBitfieldImmediate (cpu
);
9654 case DPIMM_EXTR_111
:
9655 dexExtractImmediate (cpu
);
9659 /* Should never reach here. */
9665 dexLoadUnscaledImmediate (sim_cpu
*cpu
)
9667 /* instr[29,24] == 111_00
9673 instr[20,12] = simm9
9674 instr[9,5] = rn may be SP. */
9675 /* unsigned rt = INSTR (4, 0); */
9676 uint32_t V
= INSTR (26, 26);
9677 uint32_t dispatch
= ((INSTR (31, 30) << 2) | INSTR (23, 22));
9678 int32_t imm
= simm32 (aarch64_get_instr (cpu
), 20, 12);
9682 /* GReg operations. */
9685 case 0: sturb (cpu
, imm
); return;
9686 case 1: ldurb32 (cpu
, imm
); return;
9687 case 2: ldursb64 (cpu
, imm
); return;
9688 case 3: ldursb32 (cpu
, imm
); return;
9689 case 4: sturh (cpu
, imm
); return;
9690 case 5: ldurh32 (cpu
, imm
); return;
9691 case 6: ldursh64 (cpu
, imm
); return;
9692 case 7: ldursh32 (cpu
, imm
); return;
9693 case 8: stur32 (cpu
, imm
); return;
9694 case 9: ldur32 (cpu
, imm
); return;
9695 case 10: ldursw (cpu
, imm
); return;
9696 case 12: stur64 (cpu
, imm
); return;
9697 case 13: ldur64 (cpu
, imm
); return;
9710 /* FReg operations. */
9713 case 2: fsturq (cpu
, imm
); return;
9714 case 3: fldurq (cpu
, imm
); return;
9715 case 8: fsturs (cpu
, imm
); return;
9716 case 9: fldurs (cpu
, imm
); return;
9717 case 12: fsturd (cpu
, imm
); return;
9718 case 13: fldurd (cpu
, imm
); return;
9720 case 0: /* STUR 8 bit FP. */
9721 case 1: /* LDUR 8 bit FP. */
9722 case 4: /* STUR 16 bit FP. */
9723 case 5: /* LDUR 8 bit FP. */
9737 /* N.B. A preliminary note regarding all the ldrs<x>32
9740 The signed value loaded by these instructions is cast to unsigned
9741 before being assigned to aarch64_get_reg_u64 (cpu, N) i.e. to the
9742 64 bit element of the GReg union. this performs a 32 bit sign extension
9743 (as required) but avoids 64 bit sign extension, thus ensuring that the
9744 top half of the register word is zero. this is what the spec demands
9745 when a 32 bit load occurs. */
9747 /* 32 bit load sign-extended byte scaled unsigned 12 bit. */
9749 ldrsb32_abs (sim_cpu
*cpu
, uint32_t offset
)
9751 unsigned int rn
= INSTR (9, 5);
9752 unsigned int rt
= INSTR (4, 0);
9754 /* The target register may not be SP but the source may be
9755 there is no scaling required for a byte load. */
9756 uint64_t address
= aarch64_get_reg_u64 (cpu
, rn
, SP_OK
) + offset
;
9757 aarch64_set_reg_u64 (cpu
, rt
, NO_SP
,
9758 (int64_t) aarch64_get_mem_s8 (cpu
, address
));
9761 /* 32 bit load sign-extended byte scaled or unscaled zero-
9762 or sign-extended 32-bit register offset. */
9764 ldrsb32_scale_ext (sim_cpu
*cpu
, Scaling scaling
, Extension extension
)
9766 unsigned int rm
= INSTR (20, 16);
9767 unsigned int rn
= INSTR (9, 5);
9768 unsigned int rt
= INSTR (4, 0);
9770 /* rn may reference SP, rm and rt must reference ZR. */
9772 uint64_t address
= aarch64_get_reg_u64 (cpu
, rn
, SP_OK
);
9773 int64_t displacement
= extend (aarch64_get_reg_u32 (cpu
, rm
, NO_SP
),
9776 /* There is no scaling required for a byte load. */
9778 (cpu
, rt
, NO_SP
, (int64_t) aarch64_get_mem_s8 (cpu
, address
9782 /* 32 bit load sign-extended byte unscaled signed 9 bit with
9783 pre- or post-writeback. */
9785 ldrsb32_wb (sim_cpu
*cpu
, int32_t offset
, WriteBack wb
)
9788 unsigned int rn
= INSTR (9, 5);
9789 unsigned int rt
= INSTR (4, 0);
9791 if (rn
== rt
&& wb
!= NoWriteBack
)
9794 address
= aarch64_get_reg_u64 (cpu
, rn
, SP_OK
);
9799 aarch64_set_reg_u64 (cpu
, rt
, NO_SP
,
9800 (int64_t) aarch64_get_mem_s8 (cpu
, address
));
9805 if (wb
!= NoWriteBack
)
9806 aarch64_set_reg_u64 (cpu
, rn
, NO_SP
, address
);
9809 /* 8 bit store scaled. */
9811 fstrb_abs (sim_cpu
*cpu
, uint32_t offset
)
9813 unsigned st
= INSTR (4, 0);
9814 unsigned rn
= INSTR (9, 5);
9816 aarch64_set_mem_u8 (cpu
,
9817 aarch64_get_reg_u64 (cpu
, rn
, SP_OK
) + offset
,
9818 aarch64_get_vec_u8 (cpu
, st
, 0));
9821 /* 8 bit store scaled or unscaled zero- or
9822 sign-extended 8-bit register offset. */
9824 fstrb_scale_ext (sim_cpu
*cpu
, Scaling scaling
, Extension extension
)
9826 unsigned rm
= INSTR (20, 16);
9827 unsigned rn
= INSTR (9, 5);
9828 unsigned st
= INSTR (4, 0);
9830 uint64_t address
= aarch64_get_reg_u64 (cpu
, rn
, SP_OK
);
9831 int64_t extended
= extend (aarch64_get_reg_u32 (cpu
, rm
, NO_SP
),
9833 uint64_t displacement
= scaling
== Scaled
? extended
: 0;
9836 (cpu
, address
+ displacement
, aarch64_get_vec_u8 (cpu
, st
, 0));
9839 /* 16 bit store scaled. */
9841 fstrh_abs (sim_cpu
*cpu
, uint32_t offset
)
9843 unsigned st
= INSTR (4, 0);
9844 unsigned rn
= INSTR (9, 5);
9848 aarch64_get_reg_u64 (cpu
, rn
, SP_OK
) + SCALE (offset
, 16),
9849 aarch64_get_vec_u16 (cpu
, st
, 0));
9852 /* 16 bit store scaled or unscaled zero-
9853 or sign-extended 16-bit register offset. */
9855 fstrh_scale_ext (sim_cpu
*cpu
, Scaling scaling
, Extension extension
)
9857 unsigned rm
= INSTR (20, 16);
9858 unsigned rn
= INSTR (9, 5);
9859 unsigned st
= INSTR (4, 0);
9861 uint64_t address
= aarch64_get_reg_u64 (cpu
, rn
, SP_OK
);
9862 int64_t extended
= extend (aarch64_get_reg_u32 (cpu
, rm
, NO_SP
),
9864 uint64_t displacement
= OPT_SCALE (extended
, 16, scaling
);
9867 (cpu
, address
+ displacement
, aarch64_get_vec_u16 (cpu
, st
, 0));
9870 /* 32 bit store scaled unsigned 12 bit. */
9872 fstrs_abs (sim_cpu
*cpu
, uint32_t offset
)
9874 unsigned st
= INSTR (4, 0);
9875 unsigned rn
= INSTR (9, 5);
9879 aarch64_get_reg_u64 (cpu
, rn
, SP_OK
) + SCALE (offset
, 32),
9880 aarch64_get_vec_u32 (cpu
, st
, 0));
9883 /* 32 bit store unscaled signed 9 bit with pre- or post-writeback. */
9885 fstrs_wb (sim_cpu
*cpu
, int32_t offset
, WriteBack wb
)
9887 unsigned rn
= INSTR (9, 5);
9888 unsigned st
= INSTR (4, 0);
9890 uint64_t address
= aarch64_get_reg_u64 (cpu
, rn
, SP_OK
);
9895 aarch64_set_mem_u32 (cpu
, address
, aarch64_get_vec_u32 (cpu
, st
, 0));
9900 if (wb
!= NoWriteBack
)
9901 aarch64_set_reg_u64 (cpu
, rn
, SP_OK
, address
);
9904 /* 32 bit store scaled or unscaled zero-
9905 or sign-extended 32-bit register offset. */
9907 fstrs_scale_ext (sim_cpu
*cpu
, Scaling scaling
, Extension extension
)
9909 unsigned rm
= INSTR (20, 16);
9910 unsigned rn
= INSTR (9, 5);
9911 unsigned st
= INSTR (4, 0);
9913 uint64_t address
= aarch64_get_reg_u64 (cpu
, rn
, SP_OK
);
9914 int64_t extended
= extend (aarch64_get_reg_u32 (cpu
, rm
, NO_SP
),
9916 uint64_t displacement
= OPT_SCALE (extended
, 32, scaling
);
9919 (cpu
, address
+ displacement
, aarch64_get_vec_u32 (cpu
, st
, 0));
9922 /* 64 bit store scaled unsigned 12 bit. */
9924 fstrd_abs (sim_cpu
*cpu
, uint32_t offset
)
9926 unsigned st
= INSTR (4, 0);
9927 unsigned rn
= INSTR (9, 5);
9931 aarch64_get_reg_u64 (cpu
, rn
, SP_OK
) + SCALE (offset
, 64),
9932 aarch64_get_vec_u64 (cpu
, st
, 0));
9935 /* 64 bit store unscaled signed 9 bit with pre- or post-writeback. */
9937 fstrd_wb (sim_cpu
*cpu
, int32_t offset
, WriteBack wb
)
9939 unsigned rn
= INSTR (9, 5);
9940 unsigned st
= INSTR (4, 0);
9942 uint64_t address
= aarch64_get_reg_u64 (cpu
, rn
, SP_OK
);
9947 aarch64_set_mem_u64 (cpu
, address
, aarch64_get_vec_u64 (cpu
, st
, 0));
9952 if (wb
!= NoWriteBack
)
9953 aarch64_set_reg_u64 (cpu
, rn
, SP_OK
, address
);
9956 /* 64 bit store scaled or unscaled zero-
9957 or sign-extended 32-bit register offset. */
9959 fstrd_scale_ext (sim_cpu
*cpu
, Scaling scaling
, Extension extension
)
9961 unsigned rm
= INSTR (20, 16);
9962 unsigned rn
= INSTR (9, 5);
9963 unsigned st
= INSTR (4, 0);
9965 uint64_t address
= aarch64_get_reg_u64 (cpu
, rn
, SP_OK
);
9966 int64_t extended
= extend (aarch64_get_reg_u32 (cpu
, rm
, NO_SP
),
9968 uint64_t displacement
= OPT_SCALE (extended
, 64, scaling
);
9971 (cpu
, address
+ displacement
, aarch64_get_vec_u64 (cpu
, st
, 0));
9974 /* 128 bit store scaled unsigned 12 bit. */
9976 fstrq_abs (sim_cpu
*cpu
, uint32_t offset
)
9979 unsigned st
= INSTR (4, 0);
9980 unsigned rn
= INSTR (9, 5);
9983 aarch64_get_FP_long_double (cpu
, st
, & a
);
9985 addr
= aarch64_get_reg_u64 (cpu
, rn
, SP_OK
) + SCALE (offset
, 128);
9986 aarch64_set_mem_long_double (cpu
, addr
, a
);
9989 /* 128 bit store unscaled signed 9 bit with pre- or post-writeback. */
9991 fstrq_wb (sim_cpu
*cpu
, int32_t offset
, WriteBack wb
)
9994 unsigned rn
= INSTR (9, 5);
9995 unsigned st
= INSTR (4, 0);
9996 uint64_t address
= aarch64_get_reg_u64 (cpu
, rn
, SP_OK
);
10001 aarch64_get_FP_long_double (cpu
, st
, & a
);
10002 aarch64_set_mem_long_double (cpu
, address
, a
);
10007 if (wb
!= NoWriteBack
)
10008 aarch64_set_reg_u64 (cpu
, rn
, SP_OK
, address
);
10011 /* 128 bit store scaled or unscaled zero-
10012 or sign-extended 32-bit register offset. */
10014 fstrq_scale_ext (sim_cpu
*cpu
, Scaling scaling
, Extension extension
)
10016 unsigned rm
= INSTR (20, 16);
10017 unsigned rn
= INSTR (9, 5);
10018 unsigned st
= INSTR (4, 0);
10020 uint64_t address
= aarch64_get_reg_u64 (cpu
, rn
, SP_OK
);
10021 int64_t extended
= extend (aarch64_get_reg_u32 (cpu
, rm
, NO_SP
),
10023 uint64_t displacement
= OPT_SCALE (extended
, 128, scaling
);
10027 aarch64_get_FP_long_double (cpu
, st
, & a
);
10028 aarch64_set_mem_long_double (cpu
, address
+ displacement
, a
);
10032 dexLoadImmediatePrePost (sim_cpu
*cpu
)
10034 /* instr[31,30] = size
10040 instr[20,12] = simm9
10041 instr[11] = wb : 0 ==> Post, 1 ==> Pre
10043 instr[9,5] = Rn may be SP.
10046 uint32_t V
= INSTR (26, 26);
10047 uint32_t dispatch
= ((INSTR (31, 30) << 2) | INSTR (23, 22));
10048 int32_t imm
= simm32 (aarch64_get_instr (cpu
), 20, 12);
10049 WriteBack wb
= INSTR (11, 11);
10053 /* GReg operations. */
10056 case 0: strb_wb (cpu
, imm
, wb
); return;
10057 case 1: ldrb32_wb (cpu
, imm
, wb
); return;
10058 case 2: ldrsb_wb (cpu
, imm
, wb
); return;
10059 case 3: ldrsb32_wb (cpu
, imm
, wb
); return;
10060 case 4: strh_wb (cpu
, imm
, wb
); return;
10061 case 5: ldrh32_wb (cpu
, imm
, wb
); return;
10062 case 6: ldrsh64_wb (cpu
, imm
, wb
); return;
10063 case 7: ldrsh32_wb (cpu
, imm
, wb
); return;
10064 case 8: str32_wb (cpu
, imm
, wb
); return;
10065 case 9: ldr32_wb (cpu
, imm
, wb
); return;
10066 case 10: ldrsw_wb (cpu
, imm
, wb
); return;
10067 case 12: str_wb (cpu
, imm
, wb
); return;
10068 case 13: ldr_wb (cpu
, imm
, wb
); return;
10078 /* FReg operations. */
10081 case 2: fstrq_wb (cpu
, imm
, wb
); return;
10082 case 3: fldrq_wb (cpu
, imm
, wb
); return;
10083 case 8: fstrs_wb (cpu
, imm
, wb
); return;
10084 case 9: fldrs_wb (cpu
, imm
, wb
); return;
10085 case 12: fstrd_wb (cpu
, imm
, wb
); return;
10086 case 13: fldrd_wb (cpu
, imm
, wb
); return;
10088 case 0: /* STUR 8 bit FP. */
10089 case 1: /* LDUR 8 bit FP. */
10090 case 4: /* STUR 16 bit FP. */
10091 case 5: /* LDUR 8 bit FP. */
10106 dexLoadRegisterOffset (sim_cpu
*cpu
)
10108 /* instr[31,30] = size
10115 instr[15,13] = option : 010 ==> UXTW, 011 ==> UXTX/LSL,
10116 110 ==> SXTW, 111 ==> SXTX,
10121 instr[4,0] = rt. */
10123 uint32_t V
= INSTR (26, 26);
10124 uint32_t dispatch
= ((INSTR (31, 30) << 2) | INSTR (23, 22));
10125 Scaling scale
= INSTR (12, 12);
10126 Extension extensionType
= INSTR (15, 13);
10128 /* Check for illegal extension types. */
10129 if (uimm (extensionType
, 1, 1) == 0)
10132 if (extensionType
== UXTX
|| extensionType
== SXTX
)
10133 extensionType
= NoExtension
;
10137 /* GReg operations. */
10140 case 0: strb_scale_ext (cpu
, scale
, extensionType
); return;
10141 case 1: ldrb32_scale_ext (cpu
, scale
, extensionType
); return;
10142 case 2: ldrsb_scale_ext (cpu
, scale
, extensionType
); return;
10143 case 3: ldrsb32_scale_ext (cpu
, scale
, extensionType
); return;
10144 case 4: strh_scale_ext (cpu
, scale
, extensionType
); return;
10145 case 5: ldrh32_scale_ext (cpu
, scale
, extensionType
); return;
10146 case 6: ldrsh_scale_ext (cpu
, scale
, extensionType
); return;
10147 case 7: ldrsh32_scale_ext (cpu
, scale
, extensionType
); return;
10148 case 8: str32_scale_ext (cpu
, scale
, extensionType
); return;
10149 case 9: ldr32_scale_ext (cpu
, scale
, extensionType
); return;
10150 case 10: ldrsw_scale_ext (cpu
, scale
, extensionType
); return;
10151 case 12: str_scale_ext (cpu
, scale
, extensionType
); return;
10152 case 13: ldr_scale_ext (cpu
, scale
, extensionType
); return;
10153 case 14: prfm_scale_ext (cpu
, scale
, extensionType
); return;
10162 /* FReg operations. */
10165 case 1: /* LDUR 8 bit FP. */
10167 case 3: fldrq_scale_ext (cpu
, scale
, extensionType
); return;
10168 case 5: /* LDUR 8 bit FP. */
10170 case 9: fldrs_scale_ext (cpu
, scale
, extensionType
); return;
10171 case 13: fldrd_scale_ext (cpu
, scale
, extensionType
); return;
10173 case 0: fstrb_scale_ext (cpu
, scale
, extensionType
); return;
10174 case 2: fstrq_scale_ext (cpu
, scale
, extensionType
); return;
10175 case 4: fstrh_scale_ext (cpu
, scale
, extensionType
); return;
10176 case 8: fstrs_scale_ext (cpu
, scale
, extensionType
); return;
10177 case 12: fstrd_scale_ext (cpu
, scale
, extensionType
); return;
10191 dexLoadUnsignedImmediate (sim_cpu
*cpu
)
10193 /* instr[29,24] == 111_01
10194 instr[31,30] = size
10197 instr[21,10] = uimm12 : unsigned immediate offset
10198 instr[9,5] = rn may be SP.
10199 instr[4,0] = rt. */
10201 uint32_t V
= INSTR (26,26);
10202 uint32_t dispatch
= ((INSTR (31, 30) << 2) | INSTR (23, 22));
10203 uint32_t imm
= INSTR (21, 10);
10207 /* GReg operations. */
10210 case 0: strb_abs (cpu
, imm
); return;
10211 case 1: ldrb32_abs (cpu
, imm
); return;
10212 case 2: ldrsb_abs (cpu
, imm
); return;
10213 case 3: ldrsb32_abs (cpu
, imm
); return;
10214 case 4: strh_abs (cpu
, imm
); return;
10215 case 5: ldrh32_abs (cpu
, imm
); return;
10216 case 6: ldrsh_abs (cpu
, imm
); return;
10217 case 7: ldrsh32_abs (cpu
, imm
); return;
10218 case 8: str32_abs (cpu
, imm
); return;
10219 case 9: ldr32_abs (cpu
, imm
); return;
10220 case 10: ldrsw_abs (cpu
, imm
); return;
10221 case 12: str_abs (cpu
, imm
); return;
10222 case 13: ldr_abs (cpu
, imm
); return;
10223 case 14: prfm_abs (cpu
, imm
); return;
10232 /* FReg operations. */
10235 case 0: fstrb_abs (cpu
, imm
); return;
10236 case 4: fstrh_abs (cpu
, imm
); return;
10237 case 8: fstrs_abs (cpu
, imm
); return;
10238 case 12: fstrd_abs (cpu
, imm
); return;
10239 case 2: fstrq_abs (cpu
, imm
); return;
10241 case 1: fldrb_abs (cpu
, imm
); return;
10242 case 5: fldrh_abs (cpu
, imm
); return;
10243 case 9: fldrs_abs (cpu
, imm
); return;
10244 case 13: fldrd_abs (cpu
, imm
); return;
10245 case 3: fldrq_abs (cpu
, imm
); return;
10259 dexLoadExclusive (sim_cpu
*cpu
)
10261 /* assert instr[29:24] = 001000;
10262 instr[31,30] = size
10263 instr[23] = 0 if exclusive
10264 instr[22] = L : 1 if load, 0 if store
10265 instr[21] = 1 if pair
10267 instr[15] = o0 : 1 if ordered
10270 instr[4.0] = Rt. */
10272 switch (INSTR (22, 21))
10274 case 2: ldxr (cpu
); return;
10275 case 0: stxr (cpu
); return;
10281 dexLoadOther (sim_cpu
*cpu
)
10285 /* instr[29,25] = 111_0
10286 instr[24] == 0 ==> dispatch, 1 ==> ldst reg unsigned immediate
10287 instr[21:11,10] is the secondary dispatch. */
10288 if (INSTR (24, 24))
10290 dexLoadUnsignedImmediate (cpu
);
10294 dispatch
= ((INSTR (21, 21) << 2) | INSTR (11, 10));
10297 case 0: dexLoadUnscaledImmediate (cpu
); return;
10298 case 1: dexLoadImmediatePrePost (cpu
); return;
10299 case 3: dexLoadImmediatePrePost (cpu
); return;
10300 case 6: dexLoadRegisterOffset (cpu
); return;
10312 store_pair_u32 (sim_cpu
*cpu
, int32_t offset
, WriteBack wb
)
10314 unsigned rn
= INSTR (14, 10);
10315 unsigned rd
= INSTR (9, 5);
10316 unsigned rm
= INSTR (4, 0);
10317 uint64_t address
= aarch64_get_reg_u64 (cpu
, rd
, SP_OK
);
10319 if ((rn
== rd
|| rm
== rd
) && wb
!= NoWriteBack
)
10320 HALT_UNALLOC
; /* ??? */
10327 aarch64_set_mem_u32 (cpu
, address
,
10328 aarch64_get_reg_u32 (cpu
, rm
, NO_SP
));
10329 aarch64_set_mem_u32 (cpu
, address
+ 4,
10330 aarch64_get_reg_u32 (cpu
, rn
, NO_SP
));
10335 if (wb
!= NoWriteBack
)
10336 aarch64_set_reg_u64 (cpu
, rd
, SP_OK
, address
);
10340 store_pair_u64 (sim_cpu
*cpu
, int32_t offset
, WriteBack wb
)
10342 unsigned rn
= INSTR (14, 10);
10343 unsigned rd
= INSTR (9, 5);
10344 unsigned rm
= INSTR (4, 0);
10345 uint64_t address
= aarch64_get_reg_u64 (cpu
, rd
, SP_OK
);
10347 if ((rn
== rd
|| rm
== rd
) && wb
!= NoWriteBack
)
10348 HALT_UNALLOC
; /* ??? */
10355 aarch64_set_mem_u64 (cpu
, address
,
10356 aarch64_get_reg_u64 (cpu
, rm
, NO_SP
));
10357 aarch64_set_mem_u64 (cpu
, address
+ 8,
10358 aarch64_get_reg_u64 (cpu
, rn
, NO_SP
));
10363 if (wb
!= NoWriteBack
)
10364 aarch64_set_reg_u64 (cpu
, rd
, SP_OK
, address
);
10368 load_pair_u32 (sim_cpu
*cpu
, int32_t offset
, WriteBack wb
)
10370 unsigned rn
= INSTR (14, 10);
10371 unsigned rd
= INSTR (9, 5);
10372 unsigned rm
= INSTR (4, 0);
10373 uint64_t address
= aarch64_get_reg_u64 (cpu
, rd
, SP_OK
);
10375 /* Treat this as unalloc to make sure we don't do it. */
10384 aarch64_set_reg_u64 (cpu
, rm
, SP_OK
, aarch64_get_mem_u32 (cpu
, address
));
10385 aarch64_set_reg_u64 (cpu
, rn
, SP_OK
, aarch64_get_mem_u32 (cpu
, address
+ 4));
10390 if (wb
!= NoWriteBack
)
10391 aarch64_set_reg_u64 (cpu
, rd
, SP_OK
, address
);
10395 load_pair_s32 (sim_cpu
*cpu
, int32_t offset
, WriteBack wb
)
10397 unsigned rn
= INSTR (14, 10);
10398 unsigned rd
= INSTR (9, 5);
10399 unsigned rm
= INSTR (4, 0);
10400 uint64_t address
= aarch64_get_reg_u64 (cpu
, rd
, SP_OK
);
10402 /* Treat this as unalloc to make sure we don't do it. */
10411 aarch64_set_reg_s64 (cpu
, rm
, SP_OK
, aarch64_get_mem_s32 (cpu
, address
));
10412 aarch64_set_reg_s64 (cpu
, rn
, SP_OK
, aarch64_get_mem_s32 (cpu
, address
+ 4));
10417 if (wb
!= NoWriteBack
)
10418 aarch64_set_reg_u64 (cpu
, rd
, SP_OK
, address
);
10422 load_pair_u64 (sim_cpu
*cpu
, int32_t offset
, WriteBack wb
)
10424 unsigned rn
= INSTR (14, 10);
10425 unsigned rd
= INSTR (9, 5);
10426 unsigned rm
= INSTR (4, 0);
10427 uint64_t address
= aarch64_get_reg_u64 (cpu
, rd
, SP_OK
);
10429 /* Treat this as unalloc to make sure we don't do it. */
10438 aarch64_set_reg_u64 (cpu
, rm
, SP_OK
, aarch64_get_mem_u64 (cpu
, address
));
10439 aarch64_set_reg_u64 (cpu
, rn
, SP_OK
, aarch64_get_mem_u64 (cpu
, address
+ 8));
10444 if (wb
!= NoWriteBack
)
10445 aarch64_set_reg_u64 (cpu
, rd
, SP_OK
, address
);
10449 dex_load_store_pair_gr (sim_cpu
*cpu
)
10451 /* instr[31,30] = size (10=> 64-bit, 01=> signed 32-bit, 00=> 32-bit)
10452 instr[29,25] = instruction encoding: 101_0
10453 instr[26] = V : 1 if fp 0 if gp
10454 instr[24,23] = addressing mode (10=> offset, 01=> post, 11=> pre)
10455 instr[22] = load/store (1=> load)
10456 instr[21,15] = signed, scaled, offset
10459 instr[ 4, 0] = Rm. */
10461 uint32_t dispatch
= ((INSTR (31, 30) << 3) | INSTR (24, 22));
10462 int32_t offset
= simm32 (aarch64_get_instr (cpu
), 21, 15);
10466 case 2: store_pair_u32 (cpu
, offset
, Post
); return;
10467 case 3: load_pair_u32 (cpu
, offset
, Post
); return;
10468 case 4: store_pair_u32 (cpu
, offset
, NoWriteBack
); return;
10469 case 5: load_pair_u32 (cpu
, offset
, NoWriteBack
); return;
10470 case 6: store_pair_u32 (cpu
, offset
, Pre
); return;
10471 case 7: load_pair_u32 (cpu
, offset
, Pre
); return;
10473 case 11: load_pair_s32 (cpu
, offset
, Post
); return;
10474 case 13: load_pair_s32 (cpu
, offset
, NoWriteBack
); return;
10475 case 15: load_pair_s32 (cpu
, offset
, Pre
); return;
10477 case 18: store_pair_u64 (cpu
, offset
, Post
); return;
10478 case 19: load_pair_u64 (cpu
, offset
, Post
); return;
10479 case 20: store_pair_u64 (cpu
, offset
, NoWriteBack
); return;
10480 case 21: load_pair_u64 (cpu
, offset
, NoWriteBack
); return;
10481 case 22: store_pair_u64 (cpu
, offset
, Pre
); return;
10482 case 23: load_pair_u64 (cpu
, offset
, Pre
); return;
10490 store_pair_float (sim_cpu
*cpu
, int32_t offset
, WriteBack wb
)
10492 unsigned rn
= INSTR (14, 10);
10493 unsigned rd
= INSTR (9, 5);
10494 unsigned rm
= INSTR (4, 0);
10495 uint64_t address
= aarch64_get_reg_u64 (cpu
, rd
, SP_OK
);
10502 aarch64_set_mem_u32 (cpu
, address
, aarch64_get_vec_u32 (cpu
, rm
, 0));
10503 aarch64_set_mem_u32 (cpu
, address
+ 4, aarch64_get_vec_u32 (cpu
, rn
, 0));
10508 if (wb
!= NoWriteBack
)
10509 aarch64_set_reg_u64 (cpu
, rd
, SP_OK
, address
);
10513 store_pair_double (sim_cpu
*cpu
, int32_t offset
, WriteBack wb
)
10515 unsigned rn
= INSTR (14, 10);
10516 unsigned rd
= INSTR (9, 5);
10517 unsigned rm
= INSTR (4, 0);
10518 uint64_t address
= aarch64_get_reg_u64 (cpu
, rd
, SP_OK
);
10525 aarch64_set_mem_u64 (cpu
, address
, aarch64_get_vec_u64 (cpu
, rm
, 0));
10526 aarch64_set_mem_u64 (cpu
, address
+ 8, aarch64_get_vec_u64 (cpu
, rn
, 0));
10531 if (wb
!= NoWriteBack
)
10532 aarch64_set_reg_u64 (cpu
, rd
, SP_OK
, address
);
10536 store_pair_long_double (sim_cpu
*cpu
, int32_t offset
, WriteBack wb
)
10539 unsigned rn
= INSTR (14, 10);
10540 unsigned rd
= INSTR (9, 5);
10541 unsigned rm
= INSTR (4, 0);
10542 uint64_t address
= aarch64_get_reg_u64 (cpu
, rd
, SP_OK
);
10549 aarch64_get_FP_long_double (cpu
, rm
, & a
);
10550 aarch64_set_mem_long_double (cpu
, address
, a
);
10551 aarch64_get_FP_long_double (cpu
, rn
, & a
);
10552 aarch64_set_mem_long_double (cpu
, address
+ 16, a
);
10557 if (wb
!= NoWriteBack
)
10558 aarch64_set_reg_u64 (cpu
, rd
, SP_OK
, address
);
10562 load_pair_float (sim_cpu
*cpu
, int32_t offset
, WriteBack wb
)
10564 unsigned rn
= INSTR (14, 10);
10565 unsigned rd
= INSTR (9, 5);
10566 unsigned rm
= INSTR (4, 0);
10567 uint64_t address
= aarch64_get_reg_u64 (cpu
, rd
, SP_OK
);
10577 aarch64_set_vec_u32 (cpu
, rm
, 0, aarch64_get_mem_u32 (cpu
, address
));
10578 aarch64_set_vec_u32 (cpu
, rn
, 0, aarch64_get_mem_u32 (cpu
, address
+ 4));
10583 if (wb
!= NoWriteBack
)
10584 aarch64_set_reg_u64 (cpu
, rd
, SP_OK
, address
);
10588 load_pair_double (sim_cpu
*cpu
, int32_t offset
, WriteBack wb
)
10590 unsigned rn
= INSTR (14, 10);
10591 unsigned rd
= INSTR (9, 5);
10592 unsigned rm
= INSTR (4, 0);
10593 uint64_t address
= aarch64_get_reg_u64 (cpu
, rd
, SP_OK
);
10603 aarch64_set_vec_u64 (cpu
, rm
, 0, aarch64_get_mem_u64 (cpu
, address
));
10604 aarch64_set_vec_u64 (cpu
, rn
, 0, aarch64_get_mem_u64 (cpu
, address
+ 8));
10609 if (wb
!= NoWriteBack
)
10610 aarch64_set_reg_u64 (cpu
, rd
, SP_OK
, address
);
10614 load_pair_long_double (sim_cpu
*cpu
, int32_t offset
, WriteBack wb
)
10617 unsigned rn
= INSTR (14, 10);
10618 unsigned rd
= INSTR (9, 5);
10619 unsigned rm
= INSTR (4, 0);
10620 uint64_t address
= aarch64_get_reg_u64 (cpu
, rd
, SP_OK
);
10630 aarch64_get_mem_long_double (cpu
, address
, & a
);
10631 aarch64_set_FP_long_double (cpu
, rm
, a
);
10632 aarch64_get_mem_long_double (cpu
, address
+ 16, & a
);
10633 aarch64_set_FP_long_double (cpu
, rn
, a
);
10638 if (wb
!= NoWriteBack
)
10639 aarch64_set_reg_u64 (cpu
, rd
, SP_OK
, address
);
10643 dex_load_store_pair_fp (sim_cpu
*cpu
)
10645 /* instr[31,30] = size (10=> 128-bit, 01=> 64-bit, 00=> 32-bit)
10646 instr[29,25] = instruction encoding
10647 instr[24,23] = addressing mode (10=> offset, 01=> post, 11=> pre)
10648 instr[22] = load/store (1=> load)
10649 instr[21,15] = signed, scaled, offset
10652 instr[ 4, 0] = Rm */
10654 uint32_t dispatch
= ((INSTR (31, 30) << 3) | INSTR (24, 22));
10655 int32_t offset
= simm32 (aarch64_get_instr (cpu
), 21, 15);
10659 case 2: store_pair_float (cpu
, offset
, Post
); return;
10660 case 3: load_pair_float (cpu
, offset
, Post
); return;
10661 case 4: store_pair_float (cpu
, offset
, NoWriteBack
); return;
10662 case 5: load_pair_float (cpu
, offset
, NoWriteBack
); return;
10663 case 6: store_pair_float (cpu
, offset
, Pre
); return;
10664 case 7: load_pair_float (cpu
, offset
, Pre
); return;
10666 case 10: store_pair_double (cpu
, offset
, Post
); return;
10667 case 11: load_pair_double (cpu
, offset
, Post
); return;
10668 case 12: store_pair_double (cpu
, offset
, NoWriteBack
); return;
10669 case 13: load_pair_double (cpu
, offset
, NoWriteBack
); return;
10670 case 14: store_pair_double (cpu
, offset
, Pre
); return;
10671 case 15: load_pair_double (cpu
, offset
, Pre
); return;
10673 case 18: store_pair_long_double (cpu
, offset
, Post
); return;
10674 case 19: load_pair_long_double (cpu
, offset
, Post
); return;
10675 case 20: store_pair_long_double (cpu
, offset
, NoWriteBack
); return;
10676 case 21: load_pair_long_double (cpu
, offset
, NoWriteBack
); return;
10677 case 22: store_pair_long_double (cpu
, offset
, Pre
); return;
10678 case 23: load_pair_long_double (cpu
, offset
, Pre
); return;
10685 static inline unsigned
10686 vec_reg (unsigned v
, unsigned o
)
10688 return (v
+ o
) & 0x3F;
10691 /* Load multiple N-element structures to N consecutive registers. */
10693 vec_load (sim_cpu
*cpu
, uint64_t address
, unsigned N
)
10695 int all
= INSTR (30, 30);
10696 unsigned size
= INSTR (11, 10);
10697 unsigned vd
= INSTR (4, 0);
10702 case 0: /* 8-bit operations. */
10704 for (i
= 0; i
< (16 * N
); i
++)
10705 aarch64_set_vec_u8 (cpu
, vec_reg (vd
, i
>> 4), i
& 15,
10706 aarch64_get_mem_u8 (cpu
, address
+ i
));
10708 for (i
= 0; i
< (8 * N
); i
++)
10709 aarch64_set_vec_u8 (cpu
, vec_reg (vd
, i
>> 3), i
& 7,
10710 aarch64_get_mem_u8 (cpu
, address
+ i
));
10713 case 1: /* 16-bit operations. */
10715 for (i
= 0; i
< (8 * N
); i
++)
10716 aarch64_set_vec_u16 (cpu
, vec_reg (vd
, i
>> 3), i
& 7,
10717 aarch64_get_mem_u16 (cpu
, address
+ i
* 2));
10719 for (i
= 0; i
< (4 * N
); i
++)
10720 aarch64_set_vec_u16 (cpu
, vec_reg (vd
, i
>> 2), i
& 3,
10721 aarch64_get_mem_u16 (cpu
, address
+ i
* 2));
10724 case 2: /* 32-bit operations. */
10726 for (i
= 0; i
< (4 * N
); i
++)
10727 aarch64_set_vec_u32 (cpu
, vec_reg (vd
, i
>> 2), i
& 3,
10728 aarch64_get_mem_u32 (cpu
, address
+ i
* 4));
10730 for (i
= 0; i
< (2 * N
); i
++)
10731 aarch64_set_vec_u32 (cpu
, vec_reg (vd
, i
>> 1), i
& 1,
10732 aarch64_get_mem_u32 (cpu
, address
+ i
* 4));
10735 case 3: /* 64-bit operations. */
10737 for (i
= 0; i
< (2 * N
); i
++)
10738 aarch64_set_vec_u64 (cpu
, vec_reg (vd
, i
>> 1), i
& 1,
10739 aarch64_get_mem_u64 (cpu
, address
+ i
* 8));
10741 for (i
= 0; i
< N
; i
++)
10742 aarch64_set_vec_u64 (cpu
, vec_reg (vd
, i
), 0,
10743 aarch64_get_mem_u64 (cpu
, address
+ i
* 8));
10748 /* LD4: load multiple 4-element to four consecutive registers. */
10750 LD4 (sim_cpu
*cpu
, uint64_t address
)
10752 vec_load (cpu
, address
, 4);
10755 /* LD3: load multiple 3-element structures to three consecutive registers. */
10757 LD3 (sim_cpu
*cpu
, uint64_t address
)
10759 vec_load (cpu
, address
, 3);
10762 /* LD2: load multiple 2-element structures to two consecutive registers. */
10764 LD2 (sim_cpu
*cpu
, uint64_t address
)
10766 vec_load (cpu
, address
, 2);
10769 /* Load multiple 1-element structures into one register. */
10771 LD1_1 (sim_cpu
*cpu
, uint64_t address
)
10773 int all
= INSTR (30, 30);
10774 unsigned size
= INSTR (11, 10);
10775 unsigned vd
= INSTR (4, 0);
10781 /* LD1 {Vd.16b}, addr, #16 */
10782 /* LD1 {Vd.8b}, addr, #8 */
10783 for (i
= 0; i
< (all
? 16 : 8); i
++)
10784 aarch64_set_vec_u8 (cpu
, vd
, i
,
10785 aarch64_get_mem_u8 (cpu
, address
+ i
));
10789 /* LD1 {Vd.8h}, addr, #16 */
10790 /* LD1 {Vd.4h}, addr, #8 */
10791 for (i
= 0; i
< (all
? 8 : 4); i
++)
10792 aarch64_set_vec_u16 (cpu
, vd
, i
,
10793 aarch64_get_mem_u16 (cpu
, address
+ i
* 2));
10797 /* LD1 {Vd.4s}, addr, #16 */
10798 /* LD1 {Vd.2s}, addr, #8 */
10799 for (i
= 0; i
< (all
? 4 : 2); i
++)
10800 aarch64_set_vec_u32 (cpu
, vd
, i
,
10801 aarch64_get_mem_u32 (cpu
, address
+ i
* 4));
10805 /* LD1 {Vd.2d}, addr, #16 */
10806 /* LD1 {Vd.1d}, addr, #8 */
10807 for (i
= 0; i
< (all
? 2 : 1); i
++)
10808 aarch64_set_vec_u64 (cpu
, vd
, i
,
10809 aarch64_get_mem_u64 (cpu
, address
+ i
* 8));
10814 /* Load multiple 1-element structures into two registers. */
10816 LD1_2 (sim_cpu
*cpu
, uint64_t address
)
10818 /* FIXME: This algorithm is *exactly* the same as the LD2 version.
10819 So why have two different instructions ? There must be something
10820 wrong somewhere. */
10821 vec_load (cpu
, address
, 2);
10824 /* Load multiple 1-element structures into three registers. */
10826 LD1_3 (sim_cpu
*cpu
, uint64_t address
)
10828 /* FIXME: This algorithm is *exactly* the same as the LD3 version.
10829 So why have two different instructions ? There must be something
10830 wrong somewhere. */
10831 vec_load (cpu
, address
, 3);
10834 /* Load multiple 1-element structures into four registers. */
10836 LD1_4 (sim_cpu
*cpu
, uint64_t address
)
10838 /* FIXME: This algorithm is *exactly* the same as the LD4 version.
10839 So why have two different instructions ? There must be something
10840 wrong somewhere. */
10841 vec_load (cpu
, address
, 4);
10844 /* Store multiple N-element structures to N consecutive registers. */
10846 vec_store (sim_cpu
*cpu
, uint64_t address
, unsigned N
)
10848 int all
= INSTR (30, 30);
10849 unsigned size
= INSTR (11, 10);
10850 unsigned vd
= INSTR (4, 0);
10855 case 0: /* 8-bit operations. */
10857 for (i
= 0; i
< (16 * N
); i
++)
10860 aarch64_get_vec_u8 (cpu
, vec_reg (vd
, i
>> 4), i
& 15));
10862 for (i
= 0; i
< (8 * N
); i
++)
10865 aarch64_get_vec_u8 (cpu
, vec_reg (vd
, i
>> 3), i
& 7));
10868 case 1: /* 16-bit operations. */
10870 for (i
= 0; i
< (8 * N
); i
++)
10871 aarch64_set_mem_u16
10872 (cpu
, address
+ i
* 2,
10873 aarch64_get_vec_u16 (cpu
, vec_reg (vd
, i
>> 3), i
& 7));
10875 for (i
= 0; i
< (4 * N
); i
++)
10876 aarch64_set_mem_u16
10877 (cpu
, address
+ i
* 2,
10878 aarch64_get_vec_u16 (cpu
, vec_reg (vd
, i
>> 2), i
& 3));
10881 case 2: /* 32-bit operations. */
10883 for (i
= 0; i
< (4 * N
); i
++)
10884 aarch64_set_mem_u32
10885 (cpu
, address
+ i
* 4,
10886 aarch64_get_vec_u32 (cpu
, vec_reg (vd
, i
>> 2), i
& 3));
10888 for (i
= 0; i
< (2 * N
); i
++)
10889 aarch64_set_mem_u32
10890 (cpu
, address
+ i
* 4,
10891 aarch64_get_vec_u32 (cpu
, vec_reg (vd
, i
>> 1), i
& 1));
10894 case 3: /* 64-bit operations. */
10896 for (i
= 0; i
< (2 * N
); i
++)
10897 aarch64_set_mem_u64
10898 (cpu
, address
+ i
* 8,
10899 aarch64_get_vec_u64 (cpu
, vec_reg (vd
, i
>> 1), i
& 1));
10901 for (i
= 0; i
< N
; i
++)
10902 aarch64_set_mem_u64
10903 (cpu
, address
+ i
* 8,
10904 aarch64_get_vec_u64 (cpu
, vec_reg (vd
, i
), 0));
10909 /* Store multiple 4-element structure to four consecutive registers. */
10911 ST4 (sim_cpu
*cpu
, uint64_t address
)
10913 vec_store (cpu
, address
, 4);
10916 /* Store multiple 3-element structures to three consecutive registers. */
10918 ST3 (sim_cpu
*cpu
, uint64_t address
)
10920 vec_store (cpu
, address
, 3);
10923 /* Store multiple 2-element structures to two consecutive registers. */
10925 ST2 (sim_cpu
*cpu
, uint64_t address
)
10927 vec_store (cpu
, address
, 2);
10930 /* Store multiple 1-element structures into one register. */
10932 ST1_1 (sim_cpu
*cpu
, uint64_t address
)
10934 int all
= INSTR (30, 30);
10935 unsigned size
= INSTR (11, 10);
10936 unsigned vd
= INSTR (4, 0);
10942 for (i
= 0; i
< (all
? 16 : 8); i
++)
10943 aarch64_set_mem_u8 (cpu
, address
+ i
,
10944 aarch64_get_vec_u8 (cpu
, vd
, i
));
10948 for (i
= 0; i
< (all
? 8 : 4); i
++)
10949 aarch64_set_mem_u16 (cpu
, address
+ i
* 2,
10950 aarch64_get_vec_u16 (cpu
, vd
, i
));
10954 for (i
= 0; i
< (all
? 4 : 2); i
++)
10955 aarch64_set_mem_u32 (cpu
, address
+ i
* 4,
10956 aarch64_get_vec_u32 (cpu
, vd
, i
));
10960 for (i
= 0; i
< (all
? 2 : 1); i
++)
10961 aarch64_set_mem_u64 (cpu
, address
+ i
* 8,
10962 aarch64_get_vec_u64 (cpu
, vd
, i
));
10967 /* Store multiple 1-element structures into two registers. */
10969 ST1_2 (sim_cpu
*cpu
, uint64_t address
)
10971 /* FIXME: This algorithm is *exactly* the same as the ST2 version.
10972 So why have two different instructions ? There must be
10973 something wrong somewhere. */
10974 vec_store (cpu
, address
, 2);
10977 /* Store multiple 1-element structures into three registers. */
10979 ST1_3 (sim_cpu
*cpu
, uint64_t address
)
10981 /* FIXME: This algorithm is *exactly* the same as the ST3 version.
10982 So why have two different instructions ? There must be
10983 something wrong somewhere. */
10984 vec_store (cpu
, address
, 3);
10987 /* Store multiple 1-element structures into four registers. */
10989 ST1_4 (sim_cpu
*cpu
, uint64_t address
)
10991 /* FIXME: This algorithm is *exactly* the same as the ST4 version.
10992 So why have two different instructions ? There must be
10993 something wrong somewhere. */
10994 vec_store (cpu
, address
, 4);
10998 do_vec_LDnR (sim_cpu
*cpu
, uint64_t address
)
11001 instr[30] = element selector 0=>half, 1=>all elements
11002 instr[29,24] = 00 1101
11003 instr[23] = 0=>simple, 1=>post
11005 instr[21] = width: LD1R-or-LD3R (0) / LD2R-or-LD4R (1)
11006 instr[20,16] = 0 0000 (simple), Vinc (reg-post-inc, no SP),
11007 11111 (immediate post inc)
11009 instr[13] = width: LD1R-or-LD2R (0) / LD3R-or-LD4R (1)
11011 instr[11,10] = element size 00=> byte(b), 01=> half(h),
11012 10=> word(s), 11=> double(d)
11013 instr[9,5] = address
11016 unsigned full
= INSTR (30, 30);
11017 unsigned vd
= INSTR (4, 0);
11018 unsigned size
= INSTR (11, 10);
11021 NYI_assert (29, 24, 0x0D);
11022 NYI_assert (22, 22, 1);
11023 NYI_assert (15, 14, 3);
11024 NYI_assert (12, 12, 0);
11026 switch ((INSTR (13, 13) << 1) | INSTR (21, 21))
11028 case 0: /* LD1R. */
11033 uint8_t val
= aarch64_get_mem_u8 (cpu
, address
);
11034 for (i
= 0; i
< (full
? 16 : 8); i
++)
11035 aarch64_set_vec_u8 (cpu
, vd
, i
, val
);
11041 uint16_t val
= aarch64_get_mem_u16 (cpu
, address
);
11042 for (i
= 0; i
< (full
? 8 : 4); i
++)
11043 aarch64_set_vec_u16 (cpu
, vd
, i
, val
);
11049 uint32_t val
= aarch64_get_mem_u32 (cpu
, address
);
11050 for (i
= 0; i
< (full
? 4 : 2); i
++)
11051 aarch64_set_vec_u32 (cpu
, vd
, i
, val
);
11057 uint64_t val
= aarch64_get_mem_u64 (cpu
, address
);
11058 for (i
= 0; i
< (full
? 2 : 1); i
++)
11059 aarch64_set_vec_u64 (cpu
, vd
, i
, val
);
11068 case 1: /* LD2R. */
11073 uint8_t val1
= aarch64_get_mem_u8 (cpu
, address
);
11074 uint8_t val2
= aarch64_get_mem_u8 (cpu
, address
+ 1);
11076 for (i
= 0; i
< (full
? 16 : 8); i
++)
11078 aarch64_set_vec_u8 (cpu
, vd
, 0, val1
);
11079 aarch64_set_vec_u8 (cpu
, vd
+ 1, 0, val2
);
11086 uint16_t val1
= aarch64_get_mem_u16 (cpu
, address
);
11087 uint16_t val2
= aarch64_get_mem_u16 (cpu
, address
+ 2);
11089 for (i
= 0; i
< (full
? 8 : 4); i
++)
11091 aarch64_set_vec_u16 (cpu
, vd
, 0, val1
);
11092 aarch64_set_vec_u16 (cpu
, vd
+ 1, 0, val2
);
11099 uint32_t val1
= aarch64_get_mem_u32 (cpu
, address
);
11100 uint32_t val2
= aarch64_get_mem_u32 (cpu
, address
+ 4);
11102 for (i
= 0; i
< (full
? 4 : 2); i
++)
11104 aarch64_set_vec_u32 (cpu
, vd
, 0, val1
);
11105 aarch64_set_vec_u32 (cpu
, vd
+ 1, 0, val2
);
11112 uint64_t val1
= aarch64_get_mem_u64 (cpu
, address
);
11113 uint64_t val2
= aarch64_get_mem_u64 (cpu
, address
+ 8);
11115 for (i
= 0; i
< (full
? 2 : 1); i
++)
11117 aarch64_set_vec_u64 (cpu
, vd
, 0, val1
);
11118 aarch64_set_vec_u64 (cpu
, vd
+ 1, 0, val2
);
11128 case 2: /* LD3R. */
11133 uint8_t val1
= aarch64_get_mem_u8 (cpu
, address
);
11134 uint8_t val2
= aarch64_get_mem_u8 (cpu
, address
+ 1);
11135 uint8_t val3
= aarch64_get_mem_u8 (cpu
, address
+ 2);
11137 for (i
= 0; i
< (full
? 16 : 8); i
++)
11139 aarch64_set_vec_u8 (cpu
, vd
, 0, val1
);
11140 aarch64_set_vec_u8 (cpu
, vd
+ 1, 0, val2
);
11141 aarch64_set_vec_u8 (cpu
, vd
+ 2, 0, val3
);
11148 uint32_t val1
= aarch64_get_mem_u16 (cpu
, address
);
11149 uint32_t val2
= aarch64_get_mem_u16 (cpu
, address
+ 2);
11150 uint32_t val3
= aarch64_get_mem_u16 (cpu
, address
+ 4);
11152 for (i
= 0; i
< (full
? 8 : 4); i
++)
11154 aarch64_set_vec_u16 (cpu
, vd
, 0, val1
);
11155 aarch64_set_vec_u16 (cpu
, vd
+ 1, 0, val2
);
11156 aarch64_set_vec_u16 (cpu
, vd
+ 2, 0, val3
);
11163 uint32_t val1
= aarch64_get_mem_u32 (cpu
, address
);
11164 uint32_t val2
= aarch64_get_mem_u32 (cpu
, address
+ 4);
11165 uint32_t val3
= aarch64_get_mem_u32 (cpu
, address
+ 8);
11167 for (i
= 0; i
< (full
? 4 : 2); i
++)
11169 aarch64_set_vec_u32 (cpu
, vd
, 0, val1
);
11170 aarch64_set_vec_u32 (cpu
, vd
+ 1, 0, val2
);
11171 aarch64_set_vec_u32 (cpu
, vd
+ 2, 0, val3
);
11178 uint64_t val1
= aarch64_get_mem_u64 (cpu
, address
);
11179 uint64_t val2
= aarch64_get_mem_u64 (cpu
, address
+ 8);
11180 uint64_t val3
= aarch64_get_mem_u64 (cpu
, address
+ 16);
11182 for (i
= 0; i
< (full
? 2 : 1); i
++)
11184 aarch64_set_vec_u64 (cpu
, vd
, 0, val1
);
11185 aarch64_set_vec_u64 (cpu
, vd
+ 1, 0, val2
);
11186 aarch64_set_vec_u64 (cpu
, vd
+ 2, 0, val3
);
11196 case 3: /* LD4R. */
11201 uint8_t val1
= aarch64_get_mem_u8 (cpu
, address
);
11202 uint8_t val2
= aarch64_get_mem_u8 (cpu
, address
+ 1);
11203 uint8_t val3
= aarch64_get_mem_u8 (cpu
, address
+ 2);
11204 uint8_t val4
= aarch64_get_mem_u8 (cpu
, address
+ 3);
11206 for (i
= 0; i
< (full
? 16 : 8); i
++)
11208 aarch64_set_vec_u8 (cpu
, vd
, 0, val1
);
11209 aarch64_set_vec_u8 (cpu
, vd
+ 1, 0, val2
);
11210 aarch64_set_vec_u8 (cpu
, vd
+ 2, 0, val3
);
11211 aarch64_set_vec_u8 (cpu
, vd
+ 3, 0, val4
);
11218 uint32_t val1
= aarch64_get_mem_u16 (cpu
, address
);
11219 uint32_t val2
= aarch64_get_mem_u16 (cpu
, address
+ 2);
11220 uint32_t val3
= aarch64_get_mem_u16 (cpu
, address
+ 4);
11221 uint32_t val4
= aarch64_get_mem_u16 (cpu
, address
+ 6);
11223 for (i
= 0; i
< (full
? 8 : 4); i
++)
11225 aarch64_set_vec_u16 (cpu
, vd
, 0, val1
);
11226 aarch64_set_vec_u16 (cpu
, vd
+ 1, 0, val2
);
11227 aarch64_set_vec_u16 (cpu
, vd
+ 2, 0, val3
);
11228 aarch64_set_vec_u16 (cpu
, vd
+ 3, 0, val4
);
11235 uint32_t val1
= aarch64_get_mem_u32 (cpu
, address
);
11236 uint32_t val2
= aarch64_get_mem_u32 (cpu
, address
+ 4);
11237 uint32_t val3
= aarch64_get_mem_u32 (cpu
, address
+ 8);
11238 uint32_t val4
= aarch64_get_mem_u32 (cpu
, address
+ 12);
11240 for (i
= 0; i
< (full
? 4 : 2); i
++)
11242 aarch64_set_vec_u32 (cpu
, vd
, 0, val1
);
11243 aarch64_set_vec_u32 (cpu
, vd
+ 1, 0, val2
);
11244 aarch64_set_vec_u32 (cpu
, vd
+ 2, 0, val3
);
11245 aarch64_set_vec_u32 (cpu
, vd
+ 3, 0, val4
);
11252 uint64_t val1
= aarch64_get_mem_u64 (cpu
, address
);
11253 uint64_t val2
= aarch64_get_mem_u64 (cpu
, address
+ 8);
11254 uint64_t val3
= aarch64_get_mem_u64 (cpu
, address
+ 16);
11255 uint64_t val4
= aarch64_get_mem_u64 (cpu
, address
+ 24);
11257 for (i
= 0; i
< (full
? 2 : 1); i
++)
11259 aarch64_set_vec_u64 (cpu
, vd
, 0, val1
);
11260 aarch64_set_vec_u64 (cpu
, vd
+ 1, 0, val2
);
11261 aarch64_set_vec_u64 (cpu
, vd
+ 2, 0, val3
);
11262 aarch64_set_vec_u64 (cpu
, vd
+ 3, 0, val4
);
11278 do_vec_load_store (sim_cpu
*cpu
)
11280 /* {LD|ST}<N> {Vd..Vd+N}, vaddr
11283 instr[30] = element selector 0=>half, 1=>all elements
11284 instr[29,25] = 00110
11286 instr[23] = 0=>simple, 1=>post
11287 instr[22] = 0=>store, 1=>load
11288 instr[21] = 0 (LDn) / small(0)-large(1) selector (LDnR)
11289 instr[20,16] = 00000 (simple), Vinc (reg-post-inc, no SP),
11290 11111 (immediate post inc)
11291 instr[15,12] = elements and destinations. eg for load:
11292 0000=>LD4 => load multiple 4-element to
11293 four consecutive registers
11294 0100=>LD3 => load multiple 3-element to
11295 three consecutive registers
11296 1000=>LD2 => load multiple 2-element to
11297 two consecutive registers
11298 0010=>LD1 => load multiple 1-element to
11299 four consecutive registers
11300 0110=>LD1 => load multiple 1-element to
11301 three consecutive registers
11302 1010=>LD1 => load multiple 1-element to
11303 two consecutive registers
11304 0111=>LD1 => load multiple 1-element to
11308 instr[11,10] = element size 00=> byte(b), 01=> half(h),
11309 10=> word(s), 11=> double(d)
11310 instr[9,5] = Vn, can be SP
11319 if (INSTR (31, 31) != 0 || INSTR (29, 25) != 0x06)
11322 type
= INSTR (15, 12);
11323 if (type
!= 0xE && type
!= 0xE && INSTR (21, 21) != 0)
11326 post
= INSTR (23, 23);
11327 load
= INSTR (22, 22);
11329 address
= aarch64_get_reg_u64 (cpu
, vn
, SP_OK
);
11333 unsigned vm
= INSTR (20, 16);
11337 unsigned sizeof_operation
;
11341 case 0: sizeof_operation
= 32; break;
11342 case 4: sizeof_operation
= 24; break;
11343 case 8: sizeof_operation
= 16; break;
11346 sizeof_operation
= INSTR (21, 21) ? 2 : 1;
11347 sizeof_operation
<<= INSTR (11, 10);
11351 sizeof_operation
= INSTR (21, 21) ? 8 : 4;
11352 sizeof_operation
<<= INSTR (11, 10);
11356 /* One register, immediate offset variant. */
11357 sizeof_operation
= 8;
11361 /* Two registers, immediate offset variant. */
11362 sizeof_operation
= 16;
11366 /* Three registers, immediate offset variant. */
11367 sizeof_operation
= 24;
11371 /* Four registers, immediate offset variant. */
11372 sizeof_operation
= 32;
11379 if (INSTR (30, 30))
11380 sizeof_operation
*= 2;
11382 aarch64_set_reg_u64 (cpu
, vn
, SP_OK
, address
+ sizeof_operation
);
11385 aarch64_set_reg_u64 (cpu
, vn
, SP_OK
,
11386 address
+ aarch64_get_reg_u64 (cpu
, vm
, NO_SP
));
11390 NYI_assert (20, 16, 0);
11397 case 0: LD4 (cpu
, address
); return;
11398 case 4: LD3 (cpu
, address
); return;
11399 case 8: LD2 (cpu
, address
); return;
11400 case 2: LD1_4 (cpu
, address
); return;
11401 case 6: LD1_3 (cpu
, address
); return;
11402 case 10: LD1_2 (cpu
, address
); return;
11403 case 7: LD1_1 (cpu
, address
); return;
11406 case 0xC: do_vec_LDnR (cpu
, address
); return;
11416 case 0: ST4 (cpu
, address
); return;
11417 case 4: ST3 (cpu
, address
); return;
11418 case 8: ST2 (cpu
, address
); return;
11419 case 2: ST1_4 (cpu
, address
); return;
11420 case 6: ST1_3 (cpu
, address
); return;
11421 case 10: ST1_2 (cpu
, address
); return;
11422 case 7: ST1_1 (cpu
, address
); return;
11429 dexLdSt (sim_cpu
*cpu
)
11431 /* uint32_t group = dispatchGroup (aarch64_get_instr (cpu));
11432 assert group == GROUP_LDST_0100 || group == GROUP_LDST_0110 ||
11433 group == GROUP_LDST_1100 || group == GROUP_LDST_1110
11434 bits [29,28:26] of a LS are the secondary dispatch vector. */
11435 uint32_t group2
= dispatchLS (aarch64_get_instr (cpu
));
11440 dexLoadExclusive (cpu
); return;
11444 dexLoadLiteral (cpu
); return;
11448 dexLoadOther (cpu
); return;
11450 case LS_ADVSIMD_001
:
11451 do_vec_load_store (cpu
); return;
11454 dex_load_store_pair_gr (cpu
); return;
11457 dex_load_store_pair_fp (cpu
); return;
11460 /* Should never reach here. */
11465 /* Specific decode and execute for group Data Processing Register. */
11468 dexLogicalShiftedRegister (sim_cpu
*cpu
)
11470 /* instr[31] = size : 0 ==> 32 bit, 1 ==> 64 bit
11472 instr[28:24] = 01010
11473 instr[23,22] = shift : 0 ==> LSL, 1 ==> LSR, 2 ==> ASR, 3 ==> ROR
11476 instr[15,10] = count : must be 0xxxxx for 32 bit
11480 uint32_t size
= INSTR (31, 31);
11481 Shift shiftType
= INSTR (23, 22);
11482 uint32_t count
= INSTR (15, 10);
11484 /* 32 bit operations must have count[5] = 0.
11485 or else we have an UNALLOC. */
11486 if (size
== 0 && uimm (count
, 5, 5))
11489 /* Dispatch on size:op:N. */
11490 switch ((INSTR (31, 29) << 1) | INSTR (21, 21))
11492 case 0: and32_shift (cpu
, shiftType
, count
); return;
11493 case 1: bic32_shift (cpu
, shiftType
, count
); return;
11494 case 2: orr32_shift (cpu
, shiftType
, count
); return;
11495 case 3: orn32_shift (cpu
, shiftType
, count
); return;
11496 case 4: eor32_shift (cpu
, shiftType
, count
); return;
11497 case 5: eon32_shift (cpu
, shiftType
, count
); return;
11498 case 6: ands32_shift (cpu
, shiftType
, count
); return;
11499 case 7: bics32_shift (cpu
, shiftType
, count
); return;
11500 case 8: and64_shift (cpu
, shiftType
, count
); return;
11501 case 9: bic64_shift (cpu
, shiftType
, count
); return;
11502 case 10:orr64_shift (cpu
, shiftType
, count
); return;
11503 case 11:orn64_shift (cpu
, shiftType
, count
); return;
11504 case 12:eor64_shift (cpu
, shiftType
, count
); return;
11505 case 13:eon64_shift (cpu
, shiftType
, count
); return;
11506 case 14:ands64_shift (cpu
, shiftType
, count
); return;
11507 case 15:bics64_shift (cpu
, shiftType
, count
); return;
11511 /* 32 bit conditional select. */
11513 csel32 (sim_cpu
*cpu
, CondCode cc
)
11515 unsigned rm
= INSTR (20, 16);
11516 unsigned rn
= INSTR (9, 5);
11517 unsigned rd
= INSTR (4, 0);
11519 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
,
11520 testConditionCode (cpu
, cc
)
11521 ? aarch64_get_reg_u32 (cpu
, rn
, NO_SP
)
11522 : aarch64_get_reg_u32 (cpu
, rm
, NO_SP
));
11525 /* 64 bit conditional select. */
11527 csel64 (sim_cpu
*cpu
, CondCode cc
)
11529 unsigned rm
= INSTR (20, 16);
11530 unsigned rn
= INSTR (9, 5);
11531 unsigned rd
= INSTR (4, 0);
11533 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
,
11534 testConditionCode (cpu
, cc
)
11535 ? aarch64_get_reg_u64 (cpu
, rn
, NO_SP
)
11536 : aarch64_get_reg_u64 (cpu
, rm
, NO_SP
));
11539 /* 32 bit conditional increment. */
11541 csinc32 (sim_cpu
*cpu
, CondCode cc
)
11543 unsigned rm
= INSTR (20, 16);
11544 unsigned rn
= INSTR (9, 5);
11545 unsigned rd
= INSTR (4, 0);
11547 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
,
11548 testConditionCode (cpu
, cc
)
11549 ? aarch64_get_reg_u32 (cpu
, rn
, NO_SP
)
11550 : aarch64_get_reg_u32 (cpu
, rm
, NO_SP
) + 1);
11553 /* 64 bit conditional increment. */
11555 csinc64 (sim_cpu
*cpu
, CondCode cc
)
11557 unsigned rm
= INSTR (20, 16);
11558 unsigned rn
= INSTR (9, 5);
11559 unsigned rd
= INSTR (4, 0);
11561 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
,
11562 testConditionCode (cpu
, cc
)
11563 ? aarch64_get_reg_u64 (cpu
, rn
, NO_SP
)
11564 : aarch64_get_reg_u64 (cpu
, rm
, NO_SP
) + 1);
11567 /* 32 bit conditional invert. */
11569 csinv32 (sim_cpu
*cpu
, CondCode cc
)
11571 unsigned rm
= INSTR (20, 16);
11572 unsigned rn
= INSTR (9, 5);
11573 unsigned rd
= INSTR (4, 0);
11575 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
,
11576 testConditionCode (cpu
, cc
)
11577 ? aarch64_get_reg_u32 (cpu
, rn
, NO_SP
)
11578 : ~ aarch64_get_reg_u32 (cpu
, rm
, NO_SP
));
11581 /* 64 bit conditional invert. */
11583 csinv64 (sim_cpu
*cpu
, CondCode cc
)
11585 unsigned rm
= INSTR (20, 16);
11586 unsigned rn
= INSTR (9, 5);
11587 unsigned rd
= INSTR (4, 0);
11589 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
,
11590 testConditionCode (cpu
, cc
)
11591 ? aarch64_get_reg_u64 (cpu
, rn
, NO_SP
)
11592 : ~ aarch64_get_reg_u64 (cpu
, rm
, NO_SP
));
11595 /* 32 bit conditional negate. */
11597 csneg32 (sim_cpu
*cpu
, CondCode cc
)
11599 unsigned rm
= INSTR (20, 16);
11600 unsigned rn
= INSTR (9, 5);
11601 unsigned rd
= INSTR (4, 0);
11603 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
,
11604 testConditionCode (cpu
, cc
)
11605 ? aarch64_get_reg_u32 (cpu
, rn
, NO_SP
)
11606 : - aarch64_get_reg_u32 (cpu
, rm
, NO_SP
));
11609 /* 64 bit conditional negate. */
11611 csneg64 (sim_cpu
*cpu
, CondCode cc
)
11613 unsigned rm
= INSTR (20, 16);
11614 unsigned rn
= INSTR (9, 5);
11615 unsigned rd
= INSTR (4, 0);
11617 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
,
11618 testConditionCode (cpu
, cc
)
11619 ? aarch64_get_reg_u64 (cpu
, rn
, NO_SP
)
11620 : - aarch64_get_reg_u64 (cpu
, rm
, NO_SP
));
11624 dexCondSelect (sim_cpu
*cpu
)
11626 /* instr[28,21] = 11011011
11627 instr[31] = size : 0 ==> 32 bit, 1 ==> 64 bit
11628 instr[30:11,10] = op : 000 ==> CSEL, 001 ==> CSINC,
11629 100 ==> CSINV, 101 ==> CSNEG,
11631 instr[29] = S : 0 ==> ok, 1 ==> UNALLOC
11632 instr[15,12] = cond
11633 instr[29] = S : 0 ==> ok, 1 ==> UNALLOC */
11635 CondCode cc
= INSTR (15, 12);
11636 uint32_t S
= INSTR (29, 29);
11637 uint32_t op2
= INSTR (11, 10);
11645 switch ((INSTR (31, 30) << 1) | op2
)
11647 case 0: csel32 (cpu
, cc
); return;
11648 case 1: csinc32 (cpu
, cc
); return;
11649 case 2: csinv32 (cpu
, cc
); return;
11650 case 3: csneg32 (cpu
, cc
); return;
11651 case 4: csel64 (cpu
, cc
); return;
11652 case 5: csinc64 (cpu
, cc
); return;
11653 case 6: csinv64 (cpu
, cc
); return;
11654 case 7: csneg64 (cpu
, cc
); return;
11658 /* Some helpers for counting leading 1 or 0 bits. */
11660 /* Counts the number of leading bits which are the same
11661 in a 32 bit value in the range 1 to 32. */
11663 leading32 (uint32_t value
)
11665 int32_t mask
= 0xffff0000;
11666 uint32_t count
= 16; /* Counts number of bits set in mask. */
11667 uint32_t lo
= 1; /* Lower bound for number of sign bits. */
11668 uint32_t hi
= 32; /* Upper bound for number of sign bits. */
11670 while (lo
+ 1 < hi
)
11672 int32_t test
= (value
& mask
);
11674 if (test
== 0 || test
== mask
)
11677 count
= (lo
+ hi
) / 2;
11678 mask
>>= (count
- lo
);
11683 count
= (lo
+ hi
) / 2;
11684 mask
<<= hi
- count
;
11693 test
= (value
& mask
);
11695 if (test
== 0 || test
== mask
)
11704 /* Counts the number of leading bits which are the same
11705 in a 64 bit value in the range 1 to 64. */
11707 leading64 (uint64_t value
)
11709 int64_t mask
= 0xffffffff00000000LL
;
11710 uint64_t count
= 32; /* Counts number of bits set in mask. */
11711 uint64_t lo
= 1; /* Lower bound for number of sign bits. */
11712 uint64_t hi
= 64; /* Upper bound for number of sign bits. */
11714 while (lo
+ 1 < hi
)
11716 int64_t test
= (value
& mask
);
11718 if (test
== 0 || test
== mask
)
11721 count
= (lo
+ hi
) / 2;
11722 mask
>>= (count
- lo
);
11727 count
= (lo
+ hi
) / 2;
11728 mask
<<= hi
- count
;
11737 test
= (value
& mask
);
11739 if (test
== 0 || test
== mask
)
11748 /* Bit operations. */
11749 /* N.B register args may not be SP. */
11751 /* 32 bit count leading sign bits. */
11753 cls32 (sim_cpu
*cpu
)
11755 unsigned rn
= INSTR (9, 5);
11756 unsigned rd
= INSTR (4, 0);
11758 /* N.B. the result needs to exclude the leading bit. */
11759 aarch64_set_reg_u64
11760 (cpu
, rd
, NO_SP
, leading32 (aarch64_get_reg_u32 (cpu
, rn
, NO_SP
)) - 1);
11763 /* 64 bit count leading sign bits. */
11765 cls64 (sim_cpu
*cpu
)
11767 unsigned rn
= INSTR (9, 5);
11768 unsigned rd
= INSTR (4, 0);
11770 /* N.B. the result needs to exclude the leading bit. */
11771 aarch64_set_reg_u64
11772 (cpu
, rd
, NO_SP
, leading64 (aarch64_get_reg_u64 (cpu
, rn
, NO_SP
)) - 1);
11775 /* 32 bit count leading zero bits. */
11777 clz32 (sim_cpu
*cpu
)
11779 unsigned rn
= INSTR (9, 5);
11780 unsigned rd
= INSTR (4, 0);
11781 uint32_t value
= aarch64_get_reg_u32 (cpu
, rn
, NO_SP
);
11783 /* if the sign (top) bit is set then the count is 0. */
11784 if (pick32 (value
, 31, 31))
11785 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, 0L);
11787 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, leading32 (value
));
11790 /* 64 bit count leading zero bits. */
11792 clz64 (sim_cpu
*cpu
)
11794 unsigned rn
= INSTR (9, 5);
11795 unsigned rd
= INSTR (4, 0);
11796 uint64_t value
= aarch64_get_reg_u64 (cpu
, rn
, NO_SP
);
11798 /* if the sign (top) bit is set then the count is 0. */
11799 if (pick64 (value
, 63, 63))
11800 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, 0L);
11802 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, leading64 (value
));
11805 /* 32 bit reverse bits. */
11807 rbit32 (sim_cpu
*cpu
)
11809 unsigned rn
= INSTR (9, 5);
11810 unsigned rd
= INSTR (4, 0);
11811 uint32_t value
= aarch64_get_reg_u32 (cpu
, rn
, NO_SP
);
11812 uint32_t result
= 0;
11815 for (i
= 0; i
< 32; i
++)
11818 result
|= (value
& 1);
11821 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, result
);
11824 /* 64 bit reverse bits. */
11826 rbit64 (sim_cpu
*cpu
)
11828 unsigned rn
= INSTR (9, 5);
11829 unsigned rd
= INSTR (4, 0);
11830 uint64_t value
= aarch64_get_reg_u64 (cpu
, rn
, NO_SP
);
11831 uint64_t result
= 0;
11834 for (i
= 0; i
< 64; i
++)
11837 result
|= (value
& 1UL);
11840 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, result
);
11843 /* 32 bit reverse bytes. */
11845 rev32 (sim_cpu
*cpu
)
11847 unsigned rn
= INSTR (9, 5);
11848 unsigned rd
= INSTR (4, 0);
11849 uint32_t value
= aarch64_get_reg_u32 (cpu
, rn
, NO_SP
);
11850 uint32_t result
= 0;
11853 for (i
= 0; i
< 4; i
++)
11856 result
|= (value
& 0xff);
11859 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, result
);
11862 /* 64 bit reverse bytes. */
11864 rev64 (sim_cpu
*cpu
)
11866 unsigned rn
= INSTR (9, 5);
11867 unsigned rd
= INSTR (4, 0);
11868 uint64_t value
= aarch64_get_reg_u64 (cpu
, rn
, NO_SP
);
11869 uint64_t result
= 0;
11872 for (i
= 0; i
< 8; i
++)
11875 result
|= (value
& 0xffULL
);
11878 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, result
);
11881 /* 32 bit reverse shorts. */
11882 /* N.B.this reverses the order of the bytes in each half word. */
11884 revh32 (sim_cpu
*cpu
)
11886 unsigned rn
= INSTR (9, 5);
11887 unsigned rd
= INSTR (4, 0);
11888 uint32_t value
= aarch64_get_reg_u32 (cpu
, rn
, NO_SP
);
11889 uint32_t result
= 0;
11892 for (i
= 0; i
< 2; i
++)
11895 result
|= (value
& 0x00ff00ff);
11898 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, result
);
11901 /* 64 bit reverse shorts. */
11902 /* N.B.this reverses the order of the bytes in each half word. */
11904 revh64 (sim_cpu
*cpu
)
11906 unsigned rn
= INSTR (9, 5);
11907 unsigned rd
= INSTR (4, 0);
11908 uint64_t value
= aarch64_get_reg_u64 (cpu
, rn
, NO_SP
);
11909 uint64_t result
= 0;
11912 for (i
= 0; i
< 2; i
++)
11915 result
|= (value
& 0x00ff00ff00ff00ffULL
);
11918 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, result
);
11922 dexDataProc1Source (sim_cpu
*cpu
)
11925 instr[28,21] = 111010110
11926 instr[31] = size : 0 ==> 32 bit, 1 ==> 64 bit
11927 instr[29] = S : 0 ==> ok, 1 ==> UNALLOC
11928 instr[20,16] = opcode2 : 00000 ==> ok, ow ==> UNALLOC
11929 instr[15,10] = opcode : 000000 ==> RBIT, 000001 ==> REV16,
11930 000010 ==> REV, 000011 ==> UNALLOC
11931 000100 ==> CLZ, 000101 ==> CLS
11933 instr[9,5] = rn : may not be SP
11934 instr[4,0] = rd : may not be SP. */
11936 uint32_t S
= INSTR (29, 29);
11937 uint32_t opcode2
= INSTR (20, 16);
11938 uint32_t opcode
= INSTR (15, 10);
11939 uint32_t dispatch
= ((INSTR (31, 31) << 3) | opcode
);
11952 case 0: rbit32 (cpu
); return;
11953 case 1: revh32 (cpu
); return;
11954 case 2: rev32 (cpu
); return;
11955 case 4: clz32 (cpu
); return;
11956 case 5: cls32 (cpu
); return;
11957 case 8: rbit64 (cpu
); return;
11958 case 9: revh64 (cpu
); return;
11959 case 10:rev32 (cpu
); return;
11960 case 11:rev64 (cpu
); return;
11961 case 12:clz64 (cpu
); return;
11962 case 13:cls64 (cpu
); return;
11963 default: HALT_UNALLOC
;
11968 Shifts by count supplied in register.
11969 N.B register args may not be SP.
11970 These all use the shifted auxiliary function for
11971 simplicity and clarity. Writing the actual shift
11972 inline would avoid a branch and so be faster but
11973 would also necessitate getting signs right. */
11975 /* 32 bit arithmetic shift right. */
11977 asrv32 (sim_cpu
*cpu
)
11979 unsigned rm
= INSTR (20, 16);
11980 unsigned rn
= INSTR (9, 5);
11981 unsigned rd
= INSTR (4, 0);
11983 aarch64_set_reg_u64
11985 shifted32 (aarch64_get_reg_u32 (cpu
, rn
, NO_SP
), ASR
,
11986 (aarch64_get_reg_u32 (cpu
, rm
, NO_SP
) & 0x1f)));
11989 /* 64 bit arithmetic shift right. */
11991 asrv64 (sim_cpu
*cpu
)
11993 unsigned rm
= INSTR (20, 16);
11994 unsigned rn
= INSTR (9, 5);
11995 unsigned rd
= INSTR (4, 0);
11997 aarch64_set_reg_u64
11999 shifted64 (aarch64_get_reg_u64 (cpu
, rn
, NO_SP
), ASR
,
12000 (aarch64_get_reg_u64 (cpu
, rm
, NO_SP
) & 0x3f)));
12003 /* 32 bit logical shift left. */
12005 lslv32 (sim_cpu
*cpu
)
12007 unsigned rm
= INSTR (20, 16);
12008 unsigned rn
= INSTR (9, 5);
12009 unsigned rd
= INSTR (4, 0);
12011 aarch64_set_reg_u64
12013 shifted32 (aarch64_get_reg_u32 (cpu
, rn
, NO_SP
), LSL
,
12014 (aarch64_get_reg_u32 (cpu
, rm
, NO_SP
) & 0x1f)));
12017 /* 64 bit arithmetic shift left. */
12019 lslv64 (sim_cpu
*cpu
)
12021 unsigned rm
= INSTR (20, 16);
12022 unsigned rn
= INSTR (9, 5);
12023 unsigned rd
= INSTR (4, 0);
12025 aarch64_set_reg_u64
12027 shifted64 (aarch64_get_reg_u64 (cpu
, rn
, NO_SP
), LSL
,
12028 (aarch64_get_reg_u64 (cpu
, rm
, NO_SP
) & 0x3f)));
12031 /* 32 bit logical shift right. */
12033 lsrv32 (sim_cpu
*cpu
)
12035 unsigned rm
= INSTR (20, 16);
12036 unsigned rn
= INSTR (9, 5);
12037 unsigned rd
= INSTR (4, 0);
12039 aarch64_set_reg_u64
12041 shifted32 (aarch64_get_reg_u32 (cpu
, rn
, NO_SP
), LSR
,
12042 (aarch64_get_reg_u32 (cpu
, rm
, NO_SP
) & 0x1f)));
12045 /* 64 bit logical shift right. */
12047 lsrv64 (sim_cpu
*cpu
)
12049 unsigned rm
= INSTR (20, 16);
12050 unsigned rn
= INSTR (9, 5);
12051 unsigned rd
= INSTR (4, 0);
12053 aarch64_set_reg_u64
12055 shifted64 (aarch64_get_reg_u64 (cpu
, rn
, NO_SP
), LSR
,
12056 (aarch64_get_reg_u64 (cpu
, rm
, NO_SP
) & 0x3f)));
12059 /* 32 bit rotate right. */
12061 rorv32 (sim_cpu
*cpu
)
12063 unsigned rm
= INSTR (20, 16);
12064 unsigned rn
= INSTR (9, 5);
12065 unsigned rd
= INSTR (4, 0);
12067 aarch64_set_reg_u64
12069 shifted32 (aarch64_get_reg_u32 (cpu
, rn
, NO_SP
), ROR
,
12070 (aarch64_get_reg_u32 (cpu
, rm
, NO_SP
) & 0x1f)));
12073 /* 64 bit rotate right. */
12075 rorv64 (sim_cpu
*cpu
)
12077 unsigned rm
= INSTR (20, 16);
12078 unsigned rn
= INSTR (9, 5);
12079 unsigned rd
= INSTR (4, 0);
12081 aarch64_set_reg_u64
12083 shifted64 (aarch64_get_reg_u64 (cpu
, rn
, NO_SP
), ROR
,
12084 (aarch64_get_reg_u64 (cpu
, rm
, NO_SP
) & 0x3f)));
12090 /* 32 bit signed divide. */
12092 cpuiv32 (sim_cpu
*cpu
)
12094 unsigned rm
= INSTR (20, 16);
12095 unsigned rn
= INSTR (9, 5);
12096 unsigned rd
= INSTR (4, 0);
12097 /* N.B. the pseudo-code does the divide using 64 bit data. */
12098 /* TODO : check that this rounds towards zero as required. */
12099 int64_t dividend
= aarch64_get_reg_s32 (cpu
, rn
, NO_SP
);
12100 int64_t divisor
= aarch64_get_reg_s32 (cpu
, rm
, NO_SP
);
12102 aarch64_set_reg_s64 (cpu
, rd
, NO_SP
,
12103 divisor
? ((int32_t) (dividend
/ divisor
)) : 0);
12106 /* 64 bit signed divide. */
12108 cpuiv64 (sim_cpu
*cpu
)
12110 unsigned rm
= INSTR (20, 16);
12111 unsigned rn
= INSTR (9, 5);
12112 unsigned rd
= INSTR (4, 0);
12114 /* TODO : check that this rounds towards zero as required. */
12115 int64_t divisor
= aarch64_get_reg_s64 (cpu
, rm
, NO_SP
);
12117 aarch64_set_reg_s64
12119 divisor
? (aarch64_get_reg_s64 (cpu
, rn
, NO_SP
) / divisor
) : 0);
12122 /* 32 bit unsigned divide. */
12124 udiv32 (sim_cpu
*cpu
)
12126 unsigned rm
= INSTR (20, 16);
12127 unsigned rn
= INSTR (9, 5);
12128 unsigned rd
= INSTR (4, 0);
12130 /* N.B. the pseudo-code does the divide using 64 bit data. */
12131 uint64_t dividend
= aarch64_get_reg_u32 (cpu
, rn
, NO_SP
);
12132 uint64_t divisor
= aarch64_get_reg_u32 (cpu
, rm
, NO_SP
);
12134 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
,
12135 divisor
? (uint32_t) (dividend
/ divisor
) : 0);
12138 /* 64 bit unsigned divide. */
12140 udiv64 (sim_cpu
*cpu
)
12142 unsigned rm
= INSTR (20, 16);
12143 unsigned rn
= INSTR (9, 5);
12144 unsigned rd
= INSTR (4, 0);
12146 /* TODO : check that this rounds towards zero as required. */
12147 uint64_t divisor
= aarch64_get_reg_u64 (cpu
, rm
, NO_SP
);
12149 aarch64_set_reg_u64
12151 divisor
? (aarch64_get_reg_u64 (cpu
, rn
, NO_SP
) / divisor
) : 0);
12155 dexDataProc2Source (sim_cpu
*cpu
)
12157 /* assert instr[30] == 0
12158 instr[28,21] == 11010110
12159 instr[31] = size : 0 ==> 32 bit, 1 ==> 64 bit
12160 instr[29] = S : 0 ==> ok, 1 ==> UNALLOC
12161 instr[15,10] = opcode : 000010 ==> UDIV, 000011 ==> CPUIV,
12162 001000 ==> LSLV, 001001 ==> LSRV
12163 001010 ==> ASRV, 001011 ==> RORV
12167 uint32_t S
= INSTR (29, 29);
12168 uint32_t opcode
= INSTR (15, 10);
12176 dispatch
= ( (INSTR (31, 31) << 3)
12177 | (uimm (opcode
, 3, 3) << 2)
12178 | uimm (opcode
, 1, 0));
12181 case 2: udiv32 (cpu
); return;
12182 case 3: cpuiv32 (cpu
); return;
12183 case 4: lslv32 (cpu
); return;
12184 case 5: lsrv32 (cpu
); return;
12185 case 6: asrv32 (cpu
); return;
12186 case 7: rorv32 (cpu
); return;
12187 case 10: udiv64 (cpu
); return;
12188 case 11: cpuiv64 (cpu
); return;
12189 case 12: lslv64 (cpu
); return;
12190 case 13: lsrv64 (cpu
); return;
12191 case 14: asrv64 (cpu
); return;
12192 case 15: rorv64 (cpu
); return;
12193 default: HALT_UNALLOC
;
12200 /* 32 bit multiply and add. */
12202 madd32 (sim_cpu
*cpu
)
12204 unsigned rm
= INSTR (20, 16);
12205 unsigned ra
= INSTR (14, 10);
12206 unsigned rn
= INSTR (9, 5);
12207 unsigned rd
= INSTR (4, 0);
12209 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
,
12210 aarch64_get_reg_u32 (cpu
, ra
, NO_SP
)
12211 + aarch64_get_reg_u32 (cpu
, rn
, NO_SP
)
12212 * aarch64_get_reg_u32 (cpu
, rm
, NO_SP
));
12215 /* 64 bit multiply and add. */
12217 madd64 (sim_cpu
*cpu
)
12219 unsigned rm
= INSTR (20, 16);
12220 unsigned ra
= INSTR (14, 10);
12221 unsigned rn
= INSTR (9, 5);
12222 unsigned rd
= INSTR (4, 0);
12224 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
,
12225 aarch64_get_reg_u64 (cpu
, ra
, NO_SP
)
12226 + aarch64_get_reg_u64 (cpu
, rn
, NO_SP
)
12227 * aarch64_get_reg_u64 (cpu
, rm
, NO_SP
));
12230 /* 32 bit multiply and sub. */
12232 msub32 (sim_cpu
*cpu
)
12234 unsigned rm
= INSTR (20, 16);
12235 unsigned ra
= INSTR (14, 10);
12236 unsigned rn
= INSTR (9, 5);
12237 unsigned rd
= INSTR (4, 0);
12239 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
,
12240 aarch64_get_reg_u32 (cpu
, ra
, NO_SP
)
12241 - aarch64_get_reg_u32 (cpu
, rn
, NO_SP
)
12242 * aarch64_get_reg_u32 (cpu
, rm
, NO_SP
));
12245 /* 64 bit multiply and sub. */
12247 msub64 (sim_cpu
*cpu
)
12249 unsigned rm
= INSTR (20, 16);
12250 unsigned ra
= INSTR (14, 10);
12251 unsigned rn
= INSTR (9, 5);
12252 unsigned rd
= INSTR (4, 0);
12254 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
,
12255 aarch64_get_reg_u64 (cpu
, ra
, NO_SP
)
12256 - aarch64_get_reg_u64 (cpu
, rn
, NO_SP
)
12257 * aarch64_get_reg_u64 (cpu
, rm
, NO_SP
));
12260 /* Signed multiply add long -- source, source2 : 32 bit, source3 : 64 bit. */
12262 smaddl (sim_cpu
*cpu
)
12264 unsigned rm
= INSTR (20, 16);
12265 unsigned ra
= INSTR (14, 10);
12266 unsigned rn
= INSTR (9, 5);
12267 unsigned rd
= INSTR (4, 0);
12269 /* N.B. we need to multiply the signed 32 bit values in rn, rm to
12270 obtain a 64 bit product. */
12271 aarch64_set_reg_s64
12273 aarch64_get_reg_s64 (cpu
, ra
, NO_SP
)
12274 + ((int64_t) aarch64_get_reg_s32 (cpu
, rn
, NO_SP
))
12275 * ((int64_t) aarch64_get_reg_s32 (cpu
, rm
, NO_SP
)));
12278 /* Signed multiply sub long -- source, source2 : 32 bit, source3 : 64 bit. */
12280 smsubl (sim_cpu
*cpu
)
12282 unsigned rm
= INSTR (20, 16);
12283 unsigned ra
= INSTR (14, 10);
12284 unsigned rn
= INSTR (9, 5);
12285 unsigned rd
= INSTR (4, 0);
12287 /* N.B. we need to multiply the signed 32 bit values in rn, rm to
12288 obtain a 64 bit product. */
12289 aarch64_set_reg_s64
12291 aarch64_get_reg_s64 (cpu
, ra
, NO_SP
)
12292 - ((int64_t) aarch64_get_reg_s32 (cpu
, rn
, NO_SP
))
12293 * ((int64_t) aarch64_get_reg_s32 (cpu
, rm
, NO_SP
)));
12296 /* Integer Multiply/Divide. */
12298 /* First some macros and a helper function. */
12299 /* Macros to test or access elements of 64 bit words. */
12301 /* Mask used to access lo 32 bits of 64 bit unsigned int. */
12302 #define LOW_WORD_MASK ((1ULL << 32) - 1)
12303 /* Return the lo 32 bit word of a 64 bit unsigned int as a 64 bit unsigned int. */
12304 #define lowWordToU64(_value_u64) ((_value_u64) & LOW_WORD_MASK)
12305 /* Return the hi 32 bit word of a 64 bit unsigned int as a 64 bit unsigned int. */
12306 #define highWordToU64(_value_u64) ((_value_u64) >> 32)
12308 /* Offset of sign bit in 64 bit signed integger. */
12309 #define SIGN_SHIFT_U64 63
12310 /* The sign bit itself -- also identifies the minimum negative int value. */
12311 #define SIGN_BIT_U64 (1UL << SIGN_SHIFT_U64)
12312 /* Return true if a 64 bit signed int presented as an unsigned int is the
12313 most negative value. */
12314 #define isMinimumU64(_value_u64) ((_value_u64) == SIGN_BIT_U64)
12315 /* Return true (non-zero) if a 64 bit signed int presented as an unsigned
12316 int has its sign bit set to false. */
12317 #define isSignSetU64(_value_u64) ((_value_u64) & SIGN_BIT_U64)
12318 /* Return 1L or -1L according to whether a 64 bit signed int presented as
12319 an unsigned int has its sign bit set or not. */
12320 #define signOfU64(_value_u64) (1L + (((value_u64) >> SIGN_SHIFT_U64) * -2L)
12321 /* Clear the sign bit of a 64 bit signed int presented as an unsigned int. */
12322 #define clearSignU64(_value_u64) ((_value_u64) &= ~SIGN_BIT_U64)
12324 /* Multiply two 64 bit ints and return.
12325 the hi 64 bits of the 128 bit product. */
12328 mul64hi (uint64_t value1
, uint64_t value2
)
12330 uint64_t resultmid1
;
12332 uint64_t value1_lo
= lowWordToU64 (value1
);
12333 uint64_t value1_hi
= highWordToU64 (value1
) ;
12334 uint64_t value2_lo
= lowWordToU64 (value2
);
12335 uint64_t value2_hi
= highWordToU64 (value2
);
12337 /* Cross-multiply and collect results. */
12339 uint64_t xproductlo
= value1_lo
* value2_lo
;
12340 uint64_t xproductmid1
= value1_lo
* value2_hi
;
12341 uint64_t xproductmid2
= value1_hi
* value2_lo
;
12342 uint64_t xproducthi
= value1_hi
* value2_hi
;
12343 uint64_t carry
= 0;
12344 /* Start accumulating 64 bit results. */
12345 /* Drop bottom half of lowest cross-product. */
12346 uint64_t resultmid
= xproductlo
>> 32;
12347 /* Add in middle products. */
12348 resultmid
= resultmid
+ xproductmid1
;
12350 /* Check for overflow. */
12351 if (resultmid
< xproductmid1
)
12352 /* Carry over 1 into top cross-product. */
12355 resultmid1
= resultmid
+ xproductmid2
;
12357 /* Check for overflow. */
12358 if (resultmid1
< xproductmid2
)
12359 /* Carry over 1 into top cross-product. */
12362 /* Drop lowest 32 bits of middle cross-product. */
12363 result
= resultmid1
>> 32;
12365 /* Add top cross-product plus and any carry. */
12366 result
+= xproducthi
+ carry
;
12371 /* Signed multiply high, source, source2 :
12372 64 bit, dest <-- high 64-bit of result. */
12374 smulh (sim_cpu
*cpu
)
12378 unsigned rm
= INSTR (20, 16);
12379 unsigned rn
= INSTR (9, 5);
12380 unsigned rd
= INSTR (4, 0);
12381 GReg ra
= INSTR (14, 10);
12382 int64_t value1
= aarch64_get_reg_u64 (cpu
, rn
, NO_SP
);
12383 int64_t value2
= aarch64_get_reg_u64 (cpu
, rm
, NO_SP
);
12386 int64_t signum
= 1;
12391 /* Convert to unsigned and use the unsigned mul64hi routine
12392 the fix the sign up afterwards. */
12413 uresult
= mul64hi (uvalue1
, uvalue2
);
12417 aarch64_set_reg_s64 (cpu
, rd
, NO_SP
, result
);
12420 /* Unsigned multiply add long -- source, source2 :
12421 32 bit, source3 : 64 bit. */
12423 umaddl (sim_cpu
*cpu
)
12425 unsigned rm
= INSTR (20, 16);
12426 unsigned ra
= INSTR (14, 10);
12427 unsigned rn
= INSTR (9, 5);
12428 unsigned rd
= INSTR (4, 0);
12430 /* N.B. we need to multiply the signed 32 bit values in rn, rm to
12431 obtain a 64 bit product. */
12432 aarch64_set_reg_u64
12434 aarch64_get_reg_u64 (cpu
, ra
, NO_SP
)
12435 + ((uint64_t) aarch64_get_reg_u32 (cpu
, rn
, NO_SP
))
12436 * ((uint64_t) aarch64_get_reg_u32 (cpu
, rm
, NO_SP
)));
12439 /* Unsigned multiply sub long -- source, source2 : 32 bit, source3 : 64 bit. */
12441 umsubl (sim_cpu
*cpu
)
12443 unsigned rm
= INSTR (20, 16);
12444 unsigned ra
= INSTR (14, 10);
12445 unsigned rn
= INSTR (9, 5);
12446 unsigned rd
= INSTR (4, 0);
12448 /* N.B. we need to multiply the signed 32 bit values in rn, rm to
12449 obtain a 64 bit product. */
12450 aarch64_set_reg_u64
12452 aarch64_get_reg_u64 (cpu
, ra
, NO_SP
)
12453 - ((uint64_t) aarch64_get_reg_u32 (cpu
, rn
, NO_SP
))
12454 * ((uint64_t) aarch64_get_reg_u32 (cpu
, rm
, NO_SP
)));
12457 /* Unsigned multiply high, source, source2 :
12458 64 bit, dest <-- high 64-bit of result. */
12460 umulh (sim_cpu
*cpu
)
12462 unsigned rm
= INSTR (20, 16);
12463 unsigned rn
= INSTR (9, 5);
12464 unsigned rd
= INSTR (4, 0);
12465 GReg ra
= INSTR (14, 10);
12470 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
,
12471 mul64hi (aarch64_get_reg_u64 (cpu
, rn
, NO_SP
),
12472 aarch64_get_reg_u64 (cpu
, rm
, NO_SP
)));
12476 dexDataProc3Source (sim_cpu
*cpu
)
12478 /* assert instr[28,24] == 11011. */
12479 /* instr[31] = size : 0 ==> 32 bit, 1 ==> 64 bit (for rd at least)
12480 instr[30,29] = op54 : 00 ==> ok, ow ==> UNALLOC
12481 instr[23,21] = op31 : 111 ==> UNALLOC, o2 ==> ok
12482 instr[15] = o0 : 0/1 ==> ok
12483 instr[23,21:15] ==> op : 0000 ==> MADD, 0001 ==> MSUB, (32/64 bit)
12484 0010 ==> SMADDL, 0011 ==> SMSUBL, (64 bit only)
12485 0100 ==> SMULH, (64 bit only)
12486 1010 ==> UMADDL, 1011 ==> UNSUBL, (64 bit only)
12487 1100 ==> UMULH (64 bit only)
12491 uint32_t size
= INSTR (31, 31);
12492 uint32_t op54
= INSTR (30, 29);
12493 uint32_t op31
= INSTR (23, 21);
12494 uint32_t o0
= INSTR (15, 15);
12511 dispatch
= (op31
<< 1) | o0
;
12515 case 0: madd64 (cpu
); return;
12516 case 1: msub64 (cpu
); return;
12517 case 2: smaddl (cpu
); return;
12518 case 3: smsubl (cpu
); return;
12519 case 4: smulh (cpu
); return;
12520 case 10: umaddl (cpu
); return;
12521 case 11: umsubl (cpu
); return;
12522 case 12: umulh (cpu
); return;
12523 default: HALT_UNALLOC
;
12528 dexDPReg (sim_cpu
*cpu
)
12530 /* uint32_t group = dispatchGroup (aarch64_get_instr (cpu));
12531 assert group == GROUP_DPREG_0101 || group == GROUP_DPREG_1101
12532 bits [28:24:21] of a DPReg are the secondary dispatch vector. */
12533 uint32_t group2
= dispatchDPReg (aarch64_get_instr (cpu
));
12537 case DPREG_LOG_000
:
12538 case DPREG_LOG_001
:
12539 dexLogicalShiftedRegister (cpu
); return;
12541 case DPREG_ADDSHF_010
:
12542 dexAddSubtractShiftedRegister (cpu
); return;
12544 case DPREG_ADDEXT_011
:
12545 dexAddSubtractExtendedRegister (cpu
); return;
12547 case DPREG_ADDCOND_100
:
12549 /* This set bundles a variety of different operations. */
12551 /* 1) add/sub w carry. */
12552 uint32_t mask1
= 0x1FE00000U
;
12553 uint32_t val1
= 0x1A000000U
;
12554 /* 2) cond compare register/immediate. */
12555 uint32_t mask2
= 0x1FE00000U
;
12556 uint32_t val2
= 0x1A400000U
;
12557 /* 3) cond select. */
12558 uint32_t mask3
= 0x1FE00000U
;
12559 uint32_t val3
= 0x1A800000U
;
12560 /* 4) data proc 1/2 source. */
12561 uint32_t mask4
= 0x1FE00000U
;
12562 uint32_t val4
= 0x1AC00000U
;
12564 if ((aarch64_get_instr (cpu
) & mask1
) == val1
)
12565 dexAddSubtractWithCarry (cpu
);
12567 else if ((aarch64_get_instr (cpu
) & mask2
) == val2
)
12570 else if ((aarch64_get_instr (cpu
) & mask3
) == val3
)
12571 dexCondSelect (cpu
);
12573 else if ((aarch64_get_instr (cpu
) & mask4
) == val4
)
12575 /* Bit 30 is clear for data proc 2 source
12576 and set for data proc 1 source. */
12577 if (aarch64_get_instr (cpu
) & (1U << 30))
12578 dexDataProc1Source (cpu
);
12580 dexDataProc2Source (cpu
);
12584 /* Should not reach here. */
12590 case DPREG_3SRC_110
:
12591 dexDataProc3Source (cpu
); return;
12593 case DPREG_UNALLOC_101
:
12596 case DPREG_3SRC_111
:
12597 dexDataProc3Source (cpu
); return;
12600 /* Should never reach here. */
12605 /* Unconditional Branch immediate.
12606 Offset is a PC-relative byte offset in the range +/- 128MiB.
12607 The offset is assumed to be raw from the decode i.e. the
12608 simulator is expected to scale them from word offsets to byte. */
12610 /* Unconditional branch. */
12612 buc (sim_cpu
*cpu
, int32_t offset
)
12614 aarch64_set_next_PC_by_offset (cpu
, offset
);
12617 static unsigned stack_depth
= 0;
12619 /* Unconditional branch and link -- writes return PC to LR. */
12621 bl (sim_cpu
*cpu
, int32_t offset
)
12623 aarch64_save_LR (cpu
);
12624 aarch64_set_next_PC_by_offset (cpu
, offset
);
12626 if (TRACE_BRANCH_P (cpu
))
12630 " %*scall %" PRIx64
" [%s]"
12631 " [args: %" PRIx64
" %" PRIx64
" %" PRIx64
"]",
12632 stack_depth
, " ", aarch64_get_next_PC (cpu
),
12633 aarch64_get_func (aarch64_get_next_PC (cpu
)),
12634 aarch64_get_reg_u64 (cpu
, 0, NO_SP
),
12635 aarch64_get_reg_u64 (cpu
, 1, NO_SP
),
12636 aarch64_get_reg_u64 (cpu
, 2, NO_SP
)
12641 /* Unconditional Branch register.
12642 Branch/return address is in source register. */
12644 /* Unconditional branch. */
12648 unsigned rn
= INSTR (9, 5);
12649 aarch64_set_next_PC (cpu
, aarch64_get_reg_u64 (cpu
, rn
, NO_SP
));
12652 /* Unconditional branch and link -- writes return PC to LR. */
12656 unsigned rn
= INSTR (9, 5);
12658 /* The pseudo code in the spec says we update LR before fetching.
12659 the value from the rn. */
12660 aarch64_save_LR (cpu
);
12661 aarch64_set_next_PC (cpu
, aarch64_get_reg_u64 (cpu
, rn
, NO_SP
));
12663 if (TRACE_BRANCH_P (cpu
))
12667 " %*scall %" PRIx64
" [%s]"
12668 " [args: %" PRIx64
" %" PRIx64
" %" PRIx64
"]",
12669 stack_depth
, " ", aarch64_get_next_PC (cpu
),
12670 aarch64_get_func (aarch64_get_next_PC (cpu
)),
12671 aarch64_get_reg_u64 (cpu
, 0, NO_SP
),
12672 aarch64_get_reg_u64 (cpu
, 1, NO_SP
),
12673 aarch64_get_reg_u64 (cpu
, 2, NO_SP
)
12678 /* Return -- assembler will default source to LR this is functionally
12679 equivalent to br but, presumably, unlike br it side effects the
12680 branch predictor. */
12684 unsigned rn
= INSTR (9, 5);
12685 aarch64_set_next_PC (cpu
, aarch64_get_reg_u64 (cpu
, rn
, NO_SP
));
12687 if (TRACE_BRANCH_P (cpu
))
12690 " %*sreturn [result: %" PRIx64
"]",
12691 stack_depth
, " ", aarch64_get_reg_u64 (cpu
, 0, NO_SP
));
12696 /* NOP -- we implement this and call it from the decode in case we
12697 want to intercept it later. */
12704 /* Data synchronization barrier. */
12711 /* Data memory barrier. */
12718 /* Instruction synchronization barrier. */
12726 dexBranchImmediate (sim_cpu
*cpu
)
12728 /* assert instr[30,26] == 00101
12729 instr[31] ==> 0 == B, 1 == BL
12730 instr[25,0] == imm26 branch offset counted in words. */
12732 uint32_t top
= INSTR (31, 31);
12733 /* We have a 26 byte signed word offset which we need to pass to the
12734 execute routine as a signed byte offset. */
12735 int32_t offset
= simm32 (aarch64_get_instr (cpu
), 25, 0) << 2;
12743 /* Control Flow. */
12745 /* Conditional branch
12747 Offset is a PC-relative byte offset in the range +/- 1MiB pos is
12748 a bit position in the range 0 .. 63
12750 cc is a CondCode enum value as pulled out of the decode
12752 N.B. any offset register (source) can only be Xn or Wn. */
12755 bcc (sim_cpu
*cpu
, int32_t offset
, CondCode cc
)
12757 /* the test returns TRUE if CC is met. */
12758 if (testConditionCode (cpu
, cc
))
12759 aarch64_set_next_PC_by_offset (cpu
, offset
);
12762 /* 32 bit branch on register non-zero. */
12764 cbnz32 (sim_cpu
*cpu
, int32_t offset
)
12766 unsigned rt
= INSTR (4, 0);
12768 if (aarch64_get_reg_u32 (cpu
, rt
, NO_SP
) != 0)
12769 aarch64_set_next_PC_by_offset (cpu
, offset
);
12772 /* 64 bit branch on register zero. */
12774 cbnz (sim_cpu
*cpu
, int32_t offset
)
12776 unsigned rt
= INSTR (4, 0);
12778 if (aarch64_get_reg_u64 (cpu
, rt
, NO_SP
) != 0)
12779 aarch64_set_next_PC_by_offset (cpu
, offset
);
12782 /* 32 bit branch on register non-zero. */
12784 cbz32 (sim_cpu
*cpu
, int32_t offset
)
12786 unsigned rt
= INSTR (4, 0);
12788 if (aarch64_get_reg_u32 (cpu
, rt
, NO_SP
) == 0)
12789 aarch64_set_next_PC_by_offset (cpu
, offset
);
12792 /* 64 bit branch on register zero. */
12794 cbz (sim_cpu
*cpu
, int32_t offset
)
12796 unsigned rt
= INSTR (4, 0);
12798 if (aarch64_get_reg_u64 (cpu
, rt
, NO_SP
) == 0)
12799 aarch64_set_next_PC_by_offset (cpu
, offset
);
12802 /* Branch on register bit test non-zero -- one size fits all. */
12804 tbnz (sim_cpu
*cpu
, uint32_t pos
, int32_t offset
)
12806 unsigned rt
= INSTR (4, 0);
12808 if (aarch64_get_reg_u64 (cpu
, rt
, NO_SP
) & (1 << pos
))
12809 aarch64_set_next_PC_by_offset (cpu
, offset
);
12812 /* branch on register bit test zero -- one size fits all. */
12814 tbz (sim_cpu
*cpu
, uint32_t pos
, int32_t offset
)
12816 unsigned rt
= INSTR (4, 0);
12818 if (!(aarch64_get_reg_u64 (cpu
, rt
, NO_SP
) & (1 << pos
)))
12819 aarch64_set_next_PC_by_offset (cpu
, offset
);
12823 dexCompareBranchImmediate (sim_cpu
*cpu
)
12825 /* instr[30,25] = 01 1010
12826 instr[31] = size : 0 ==> 32, 1 ==> 64
12827 instr[24] = op : 0 ==> CBZ, 1 ==> CBNZ
12828 instr[23,5] = simm19 branch offset counted in words
12831 uint32_t size
= INSTR (31, 31);
12832 uint32_t op
= INSTR (24, 24);
12833 int32_t offset
= simm32 (aarch64_get_instr (cpu
), 23, 5) << 2;
12838 cbz32 (cpu
, offset
);
12840 cbnz32 (cpu
, offset
);
12847 cbnz (cpu
, offset
);
12852 dexTestBranchImmediate (sim_cpu
*cpu
)
12854 /* instr[31] = b5 : bit 5 of test bit idx
12855 instr[30,25] = 01 1011
12856 instr[24] = op : 0 ==> TBZ, 1 == TBNZ
12857 instr[23,19] = b40 : bits 4 to 0 of test bit idx
12858 instr[18,5] = simm14 : signed offset counted in words
12859 instr[4,0] = uimm5 */
12861 uint32_t pos
= ((INSTR (31, 31) << 4) | INSTR (23, 19));
12862 int32_t offset
= simm32 (aarch64_get_instr (cpu
), 18, 5) << 2;
12864 NYI_assert (30, 25, 0x1b);
12866 if (INSTR (24, 24) == 0)
12867 tbz (cpu
, pos
, offset
);
12869 tbnz (cpu
, pos
, offset
);
12873 dexCondBranchImmediate (sim_cpu
*cpu
)
12875 /* instr[31,25] = 010 1010
12876 instr[24] = op1; op => 00 ==> B.cond
12877 instr[23,5] = simm19 : signed offset counted in words
12879 instr[3,0] = cond */
12882 uint32_t op
= ((INSTR (24, 24) << 1) | INSTR (4, 4));
12884 NYI_assert (31, 25, 0x2a);
12889 offset
= simm32 (aarch64_get_instr (cpu
), 23, 5) << 2;
12891 bcc (cpu
, offset
, INSTR (3, 0));
12895 dexBranchRegister (sim_cpu
*cpu
)
12897 /* instr[31,25] = 110 1011
12898 instr[24,21] = op : 0 ==> BR, 1 => BLR, 2 => RET, 3 => ERET, 4 => DRPS
12899 instr[20,16] = op2 : must be 11111
12900 instr[15,10] = op3 : must be 000000
12901 instr[4,0] = op2 : must be 11111. */
12903 uint32_t op
= INSTR (24, 21);
12904 uint32_t op2
= INSTR (20, 16);
12905 uint32_t op3
= INSTR (15, 10);
12906 uint32_t op4
= INSTR (4, 0);
12908 NYI_assert (31, 25, 0x6b);
12910 if (op2
!= 0x1F || op3
!= 0 || op4
!= 0)
12924 /* ERET and DRPS accept 0b11111 for rn = instr [4,0]. */
12925 /* anything else is unallocated. */
12926 uint32_t rn
= INSTR (4, 0);
12931 if (op
== 4 || op
== 5)
12938 /* FIXME: We should get the Angel SWI values from ../../libgloss/aarch64/svc.h
12939 but this may not be available. So instead we define the values we need
12941 #define AngelSVC_Reason_Open 0x01
12942 #define AngelSVC_Reason_Close 0x02
12943 #define AngelSVC_Reason_Write 0x05
12944 #define AngelSVC_Reason_Read 0x06
12945 #define AngelSVC_Reason_IsTTY 0x09
12946 #define AngelSVC_Reason_Seek 0x0A
12947 #define AngelSVC_Reason_FLen 0x0C
12948 #define AngelSVC_Reason_Remove 0x0E
12949 #define AngelSVC_Reason_Rename 0x0F
12950 #define AngelSVC_Reason_Clock 0x10
12951 #define AngelSVC_Reason_Time 0x11
12952 #define AngelSVC_Reason_System 0x12
12953 #define AngelSVC_Reason_Errno 0x13
12954 #define AngelSVC_Reason_GetCmdLine 0x15
12955 #define AngelSVC_Reason_HeapInfo 0x16
12956 #define AngelSVC_Reason_ReportException 0x18
12957 #define AngelSVC_Reason_Elapsed 0x30
12961 handle_halt (sim_cpu
*cpu
, uint32_t val
)
12963 uint64_t result
= 0;
12967 TRACE_SYSCALL (cpu
, " HLT [0x%x]", val
);
12968 sim_engine_halt (CPU_STATE (cpu
), cpu
, NULL
, aarch64_get_PC (cpu
),
12969 sim_stopped
, SIM_SIGTRAP
);
12972 /* We have encountered an Angel SVC call. See if we can process it. */
12973 switch (aarch64_get_reg_u32 (cpu
, 0, NO_SP
))
12975 case AngelSVC_Reason_HeapInfo
:
12977 /* Get the values. */
12978 uint64_t stack_top
= aarch64_get_stack_start (cpu
);
12979 uint64_t heap_base
= aarch64_get_heap_start (cpu
);
12981 /* Get the pointer */
12982 uint64_t ptr
= aarch64_get_reg_u64 (cpu
, 1, SP_OK
);
12983 ptr
= aarch64_get_mem_u64 (cpu
, ptr
);
12985 /* Fill in the memory block. */
12986 /* Start addr of heap. */
12987 aarch64_set_mem_u64 (cpu
, ptr
+ 0, heap_base
);
12988 /* End addr of heap. */
12989 aarch64_set_mem_u64 (cpu
, ptr
+ 8, stack_top
);
12990 /* Lowest stack addr. */
12991 aarch64_set_mem_u64 (cpu
, ptr
+ 16, heap_base
);
12992 /* Initial stack addr. */
12993 aarch64_set_mem_u64 (cpu
, ptr
+ 24, stack_top
);
12995 TRACE_SYSCALL (cpu
, " AngelSVC: Get Heap Info");
12999 case AngelSVC_Reason_Open
:
13001 /* Get the pointer */
13002 /* uint64_t ptr = aarch64_get_reg_u64 (cpu, 1, SP_OK);. */
13003 /* FIXME: For now we just assume that we will only be asked
13004 to open the standard file descriptors. */
13008 TRACE_SYSCALL (cpu
, " AngelSVC: Open file %d", fd
- 1);
13012 case AngelSVC_Reason_Close
:
13014 uint64_t fh
= aarch64_get_reg_u64 (cpu
, 1, SP_OK
);
13015 TRACE_SYSCALL (cpu
, " AngelSVC: Close file %d", (int) fh
);
13020 case AngelSVC_Reason_Errno
:
13022 TRACE_SYSCALL (cpu
, " AngelSVC: Get Errno");
13025 case AngelSVC_Reason_Clock
:
13027 #ifdef CLOCKS_PER_SEC
13028 (CLOCKS_PER_SEC
>= 100)
13029 ? (clock () / (CLOCKS_PER_SEC
/ 100))
13030 : ((clock () * 100) / CLOCKS_PER_SEC
)
13032 /* Presume unix... clock() returns microseconds. */
13036 TRACE_SYSCALL (cpu
, " AngelSVC: Get Clock");
13039 case AngelSVC_Reason_GetCmdLine
:
13041 /* Get the pointer */
13042 uint64_t ptr
= aarch64_get_reg_u64 (cpu
, 1, SP_OK
);
13043 ptr
= aarch64_get_mem_u64 (cpu
, ptr
);
13045 /* FIXME: No command line for now. */
13046 aarch64_set_mem_u64 (cpu
, ptr
, 0);
13047 TRACE_SYSCALL (cpu
, " AngelSVC: Get Command Line");
13051 case AngelSVC_Reason_IsTTY
:
13053 TRACE_SYSCALL (cpu
, " AngelSVC: IsTTY ?");
13056 case AngelSVC_Reason_Write
:
13058 /* Get the pointer */
13059 uint64_t ptr
= aarch64_get_reg_u64 (cpu
, 1, SP_OK
);
13060 /* Get the write control block. */
13061 uint64_t fd
= aarch64_get_mem_u64 (cpu
, ptr
);
13062 uint64_t buf
= aarch64_get_mem_u64 (cpu
, ptr
+ 8);
13063 uint64_t len
= aarch64_get_mem_u64 (cpu
, ptr
+ 16);
13065 TRACE_SYSCALL (cpu
, "write of %" PRIx64
" bytes from %"
13066 PRIx64
" on descriptor %" PRIx64
,
13071 TRACE_SYSCALL (cpu
,
13072 " AngelSVC: Write: Suspiciously long write: %ld",
13074 sim_engine_halt (CPU_STATE (cpu
), cpu
, NULL
, aarch64_get_PC (cpu
),
13075 sim_stopped
, SIM_SIGBUS
);
13079 printf ("%.*s", (int) len
, aarch64_get_mem_ptr (cpu
, buf
));
13083 TRACE (cpu
, 0, "\n");
13084 sim_io_eprintf (CPU_STATE (cpu
), "%.*s",
13085 (int) len
, aarch64_get_mem_ptr (cpu
, buf
));
13086 TRACE (cpu
, 0, "\n");
13090 TRACE_SYSCALL (cpu
,
13091 " AngelSVC: Write: Unexpected file handle: %d",
13093 sim_engine_halt (CPU_STATE (cpu
), cpu
, NULL
, aarch64_get_PC (cpu
),
13094 sim_stopped
, SIM_SIGABRT
);
13099 case AngelSVC_Reason_ReportException
:
13101 /* Get the pointer */
13102 uint64_t ptr
= aarch64_get_reg_u64 (cpu
, 1, SP_OK
);
13103 /*ptr = aarch64_get_mem_u64 (cpu, ptr);. */
13104 uint64_t type
= aarch64_get_mem_u64 (cpu
, ptr
);
13105 uint64_t state
= aarch64_get_mem_u64 (cpu
, ptr
+ 8);
13107 TRACE_SYSCALL (cpu
,
13108 "Angel Exception: type 0x%" PRIx64
" state %" PRIx64
,
13111 if (type
== 0x20026)
13112 sim_engine_halt (CPU_STATE (cpu
), cpu
, NULL
, aarch64_get_PC (cpu
),
13113 sim_exited
, state
);
13115 sim_engine_halt (CPU_STATE (cpu
), cpu
, NULL
, aarch64_get_PC (cpu
),
13116 sim_stopped
, SIM_SIGINT
);
13120 case AngelSVC_Reason_Read
:
13121 case AngelSVC_Reason_FLen
:
13122 case AngelSVC_Reason_Seek
:
13123 case AngelSVC_Reason_Remove
:
13124 case AngelSVC_Reason_Time
:
13125 case AngelSVC_Reason_System
:
13126 case AngelSVC_Reason_Rename
:
13127 case AngelSVC_Reason_Elapsed
:
13129 TRACE_SYSCALL (cpu
, " HLT [Unknown angel %x]",
13130 aarch64_get_reg_u32 (cpu
, 0, NO_SP
));
13131 sim_engine_halt (CPU_STATE (cpu
), cpu
, NULL
, aarch64_get_PC (cpu
),
13132 sim_stopped
, SIM_SIGTRAP
);
13135 aarch64_set_reg_u64 (cpu
, 0, NO_SP
, result
);
13139 dexExcpnGen (sim_cpu
*cpu
)
13141 /* instr[31:24] = 11010100
13142 instr[23,21] = opc : 000 ==> GEN EXCPN, 001 ==> BRK
13143 010 ==> HLT, 101 ==> DBG GEN EXCPN
13144 instr[20,5] = imm16
13145 instr[4,2] = opc2 000 ==> OK, ow ==> UNALLOC
13146 instr[1,0] = LL : discriminates opc */
13148 uint32_t opc
= INSTR (23, 21);
13149 uint32_t imm16
= INSTR (20, 5);
13150 uint32_t opc2
= INSTR (4, 2);
13153 NYI_assert (31, 24, 0xd4);
13160 /* We only implement HLT and BRK for now. */
13161 if (opc
== 1 && LL
== 0)
13163 TRACE_EVENTS (cpu
, " BRK [0x%x]", imm16
);
13164 sim_engine_halt (CPU_STATE (cpu
), cpu
, NULL
, aarch64_get_PC (cpu
),
13165 sim_exited
, aarch64_get_reg_s32 (cpu
, R0
, SP_OK
));
13168 if (opc
== 2 && LL
== 0)
13169 handle_halt (cpu
, imm16
);
13171 else if (opc
== 0 || opc
== 5)
13178 /* Stub for accessing system registers. */
13181 system_get (sim_cpu
*cpu
, unsigned op0
, unsigned op1
, unsigned crn
,
13182 unsigned crm
, unsigned op2
)
13184 if (crn
== 0 && op1
== 3 && crm
== 0 && op2
== 7)
13185 /* DCZID_EL0 - the Data Cache Zero ID register.
13186 We do not support DC ZVA at the moment, so
13187 we return a value with the disable bit set.
13188 We implement support for the DCZID register since
13189 it is used by the C library's memset function. */
13190 return ((uint64_t) 1) << 4;
13192 if (crn
== 0 && op1
== 3 && crm
== 0 && op2
== 1)
13193 /* Cache Type Register. */
13194 return 0x80008000UL
;
13196 if (crn
== 13 && op1
== 3 && crm
== 0 && op2
== 2)
13197 /* TPIDR_EL0 - thread pointer id. */
13198 return aarch64_get_thread_id (cpu
);
13200 if (op1
== 3 && crm
== 4 && op2
== 0)
13201 return aarch64_get_FPCR (cpu
);
13203 if (op1
== 3 && crm
== 4 && op2
== 1)
13204 return aarch64_get_FPSR (cpu
);
13206 else if (op1
== 3 && crm
== 2 && op2
== 0)
13207 return aarch64_get_CPSR (cpu
);
13213 system_set (sim_cpu
*cpu
, unsigned op0
, unsigned op1
, unsigned crn
,
13214 unsigned crm
, unsigned op2
, uint64_t val
)
13216 if (op1
== 3 && crm
== 4 && op2
== 0)
13217 aarch64_set_FPCR (cpu
, val
);
13219 else if (op1
== 3 && crm
== 4 && op2
== 1)
13220 aarch64_set_FPSR (cpu
, val
);
13222 else if (op1
== 3 && crm
== 2 && op2
== 0)
13223 aarch64_set_CPSR (cpu
, val
);
13230 do_mrs (sim_cpu
*cpu
)
13232 /* instr[31:20] = 1101 0101 0001 1
13239 unsigned sys_op0
= INSTR (19, 19) + 2;
13240 unsigned sys_op1
= INSTR (18, 16);
13241 unsigned sys_crn
= INSTR (15, 12);
13242 unsigned sys_crm
= INSTR (11, 8);
13243 unsigned sys_op2
= INSTR (7, 5);
13244 unsigned rt
= INSTR (4, 0);
13246 aarch64_set_reg_u64 (cpu
, rt
, NO_SP
,
13247 system_get (cpu
, sys_op0
, sys_op1
, sys_crn
, sys_crm
, sys_op2
));
13251 do_MSR_immediate (sim_cpu
*cpu
)
13253 /* instr[31:19] = 1101 0101 0000 0
13255 instr[15,12] = 0100
13258 instr[4,0] = 1 1111 */
13260 unsigned op1
= INSTR (18, 16);
13261 /*unsigned crm = INSTR (11, 8);*/
13262 unsigned op2
= INSTR (7, 5);
13264 NYI_assert (31, 19, 0x1AA0);
13265 NYI_assert (15, 12, 0x4);
13266 NYI_assert (4, 0, 0x1F);
13271 HALT_NYI
; /* set SPSel. */
13278 HALT_NYI
; /* set DAIFset. */
13280 HALT_NYI
; /* set DAIFclr. */
13289 do_MSR_reg (sim_cpu
*cpu
)
13291 /* instr[31:20] = 1101 0101 0001
13299 unsigned sys_op0
= INSTR (19, 19) + 2;
13300 unsigned sys_op1
= INSTR (18, 16);
13301 unsigned sys_crn
= INSTR (15, 12);
13302 unsigned sys_crm
= INSTR (11, 8);
13303 unsigned sys_op2
= INSTR (7, 5);
13304 unsigned rt
= INSTR (4, 0);
13306 NYI_assert (31, 20, 0xD51);
13308 system_set (cpu
, sys_op0
, sys_op1
, sys_crn
, sys_crm
, sys_op2
,
13309 aarch64_get_reg_u64 (cpu
, rt
, NO_SP
));
13313 do_SYS (sim_cpu
*cpu
)
13315 /* instr[31,19] = 1101 0101 0000 1
13321 NYI_assert (31, 19, 0x1AA1);
13323 /* FIXME: For now we just silently accept system ops. */
13327 dexSystem (sim_cpu
*cpu
)
13329 /* instr[31:22] = 1101 01010 0
13336 instr[4,0] = uimm5 */
13338 /* We are interested in HINT, DSB, DMB and ISB
13340 Hint #0 encodes NOOP (this is the only hint we care about)
13341 L == 0, op0 == 0, op1 = 011, CRn = 0010, Rt = 11111,
13342 CRm op2 != 0000 000 OR CRm op2 == 0000 000 || CRm op > 0000 101
13344 DSB, DMB, ISB are data store barrier, data memory barrier and
13345 instruction store barrier, respectively, where
13347 L == 0, op0 == 0, op1 = 011, CRn = 0011, Rt = 11111,
13348 op2 : DSB ==> 100, DMB ==> 101, ISB ==> 110
13349 CRm<3:2> ==> domain, CRm<1:0> ==> types,
13350 domain : 00 ==> OuterShareable, 01 ==> Nonshareable,
13351 10 ==> InerShareable, 11 ==> FullSystem
13352 types : 01 ==> Reads, 10 ==> Writes,
13353 11 ==> All, 00 ==> All (domain == FullSystem). */
13355 unsigned rt
= INSTR (4, 0);
13357 NYI_assert (31, 22, 0x354);
13359 switch (INSTR (21, 12))
13364 /* NOP has CRm != 0000 OR. */
13365 /* (CRm == 0000 AND (op2 == 000 OR op2 > 101)). */
13366 uint32_t crm
= INSTR (11, 8);
13367 uint32_t op2
= INSTR (7, 5);
13369 if (crm
!= 0 || (op2
== 0 || op2
> 5))
13371 /* Actually call nop method so we can reimplement it later. */
13380 uint32_t op2
= INSTR (7, 5);
13385 case 4: dsb (cpu
); return;
13386 case 5: dmb (cpu
); return;
13387 case 6: isb (cpu
); return;
13388 default: HALT_UNALLOC
;
13399 do_SYS (cpu
); /* DC is an alias of SYS. */
13403 if (INSTR (21, 20) == 0x1)
13405 else if (INSTR (21, 19) == 0 && INSTR (15, 12) == 0x4)
13406 do_MSR_immediate (cpu
);
13414 dexBr (sim_cpu
*cpu
)
13416 /* uint32_t group = dispatchGroup (aarch64_get_instr (cpu));
13417 assert group == GROUP_BREXSYS_1010 || group == GROUP_BREXSYS_1011
13418 bits [31,29] of a BrExSys are the secondary dispatch vector. */
13419 uint32_t group2
= dispatchBrExSys (aarch64_get_instr (cpu
));
13424 return dexBranchImmediate (cpu
);
13426 case BR_IMMCMP_001
:
13427 /* Compare has bit 25 clear while test has it set. */
13428 if (!INSTR (25, 25))
13429 dexCompareBranchImmediate (cpu
);
13431 dexTestBranchImmediate (cpu
);
13434 case BR_IMMCOND_010
:
13435 /* This is a conditional branch if bit 25 is clear otherwise
13437 if (!INSTR (25, 25))
13438 dexCondBranchImmediate (cpu
);
13443 case BR_UNALLOC_011
:
13447 dexBranchImmediate (cpu
);
13450 case BR_IMMCMP_101
:
13451 /* Compare has bit 25 clear while test has it set. */
13452 if (!INSTR (25, 25))
13453 dexCompareBranchImmediate (cpu
);
13455 dexTestBranchImmediate (cpu
);
13459 /* Unconditional branch reg has bit 25 set. */
13460 if (INSTR (25, 25))
13461 dexBranchRegister (cpu
);
13463 /* This includes both Excpn Gen, System and unalloc operations.
13464 We need to decode the Excpn Gen operation BRK so we can plant
13465 debugger entry points.
13466 Excpn Gen operations have instr [24] = 0.
13467 we need to decode at least one of the System operations NOP
13468 which is an alias for HINT #0.
13469 System operations have instr [24,22] = 100. */
13470 else if (INSTR (24, 24) == 0)
13473 else if (INSTR (24, 22) == 4)
13481 case BR_UNALLOC_111
:
13485 /* Should never reach here. */
13491 aarch64_decode_and_execute (sim_cpu
*cpu
, uint64_t pc
)
13493 /* We need to check if gdb wants an in here. */
13494 /* checkBreak (cpu);. */
13496 uint64_t group
= dispatchGroup (aarch64_get_instr (cpu
));
13500 case GROUP_PSEUDO_0000
: dexPseudo (cpu
); break;
13501 case GROUP_LDST_0100
: dexLdSt (cpu
); break;
13502 case GROUP_DPREG_0101
: dexDPReg (cpu
); break;
13503 case GROUP_LDST_0110
: dexLdSt (cpu
); break;
13504 case GROUP_ADVSIMD_0111
: dexAdvSIMD0 (cpu
); break;
13505 case GROUP_DPIMM_1000
: dexDPImm (cpu
); break;
13506 case GROUP_DPIMM_1001
: dexDPImm (cpu
); break;
13507 case GROUP_BREXSYS_1010
: dexBr (cpu
); break;
13508 case GROUP_BREXSYS_1011
: dexBr (cpu
); break;
13509 case GROUP_LDST_1100
: dexLdSt (cpu
); break;
13510 case GROUP_DPREG_1101
: dexDPReg (cpu
); break;
13511 case GROUP_LDST_1110
: dexLdSt (cpu
); break;
13512 case GROUP_ADVSIMD_1111
: dexAdvSIMD1 (cpu
); break;
13514 case GROUP_UNALLOC_0001
:
13515 case GROUP_UNALLOC_0010
:
13516 case GROUP_UNALLOC_0011
:
13520 /* Should never reach here. */
13526 aarch64_step (sim_cpu
*cpu
)
13528 uint64_t pc
= aarch64_get_PC (cpu
);
13530 if (pc
== TOP_LEVEL_RETURN_PC
)
13533 aarch64_set_next_PC (cpu
, pc
+ 4);
13534 aarch64_get_instr (cpu
) = aarch64_get_mem_u32 (cpu
, pc
);
13536 TRACE_INSN (cpu
, " pc = %" PRIx64
" instr = %08x", pc
,
13537 aarch64_get_instr (cpu
));
13538 TRACE_DISASM (cpu
, pc
);
13540 aarch64_decode_and_execute (cpu
, pc
);
13546 aarch64_run (SIM_DESC sd
)
13548 sim_cpu
*cpu
= STATE_CPU (sd
, 0);
13550 while (aarch64_step (cpu
))
13551 aarch64_update_PC (cpu
);
13553 sim_engine_halt (sd
, NULL
, NULL
, aarch64_get_PC (cpu
),
13554 sim_exited
, aarch64_get_reg_s32 (cpu
, R0
, SP_OK
));
13558 aarch64_init (sim_cpu
*cpu
, uint64_t pc
)
13560 uint64_t sp
= aarch64_get_stack_start (cpu
);
13562 /* Install SP, FP and PC and set LR to -20
13563 so we can detect a top-level return. */
13564 aarch64_set_reg_u64 (cpu
, SP
, SP_OK
, sp
);
13565 aarch64_set_reg_u64 (cpu
, FP
, SP_OK
, sp
);
13566 aarch64_set_reg_u64 (cpu
, LR
, SP_OK
, TOP_LEVEL_RETURN_PC
);
13567 aarch64_set_next_PC (cpu
, pc
);
13568 aarch64_update_PC (cpu
);
13569 aarch64_init_LIT_table ();