1 /* simulator.c -- Interface for the AArch64 simulator.
3 Copyright (C) 2015-2017 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)) \
67 sim_io_eprintf (CPU_STATE (cpu), "SIM Error: Unimplemented instruction: %#08x\n", \
68 aarch64_get_instr (cpu)); \
69 sim_engine_halt (CPU_STATE (cpu), cpu, NULL, aarch64_get_PC (cpu),\
70 sim_stopped, SIM_SIGABRT); \
74 #define NYI_assert(HI, LO, EXPECTED) \
77 if (INSTR ((HI), (LO)) != (EXPECTED)) \
82 /* Helper functions used by expandLogicalImmediate. */
84 /* for i = 1, ... N result<i-1> = 1 other bits are zero */
85 static inline uint64_t
88 return (N
== 64 ? (uint64_t)-1UL : ((1UL << N
) - 1));
91 /* result<0> to val<N> */
92 static inline uint64_t
93 pickbit (uint64_t val
, int N
)
95 return pickbits64 (val
, N
, N
);
99 expand_logical_immediate (uint32_t S
, uint32_t R
, uint32_t N
)
105 /* The immediate value is S+1 bits to 1, left rotated by SIMDsize - R
106 (in other words, right rotated by R), then replicated. */
110 mask
= 0xffffffffffffffffull
;
116 case 0x00 ... 0x1f: /* 0xxxxx */ simd_size
= 32; break;
117 case 0x20 ... 0x2f: /* 10xxxx */ simd_size
= 16; S
&= 0xf; break;
118 case 0x30 ... 0x37: /* 110xxx */ simd_size
= 8; S
&= 0x7; break;
119 case 0x38 ... 0x3b: /* 1110xx */ simd_size
= 4; S
&= 0x3; break;
120 case 0x3c ... 0x3d: /* 11110x */ simd_size
= 2; S
&= 0x1; break;
123 mask
= (1ull << simd_size
) - 1;
124 /* Top bits are IGNORED. */
128 /* NOTE: if S = simd_size - 1 we get 0xf..f which is rejected. */
129 if (S
== simd_size
- 1)
132 /* S+1 consecutive bits to 1. */
133 /* NOTE: S can't be 63 due to detection above. */
134 imm
= (1ull << (S
+ 1)) - 1;
136 /* Rotate to the left by simd_size - R. */
138 imm
= ((imm
<< (simd_size
- R
)) & mask
) | (imm
>> R
);
140 /* Replicate the value according to SIMD size. */
143 case 2: imm
= (imm
<< 2) | imm
;
144 case 4: imm
= (imm
<< 4) | imm
;
145 case 8: imm
= (imm
<< 8) | imm
;
146 case 16: imm
= (imm
<< 16) | imm
;
147 case 32: imm
= (imm
<< 32) | imm
;
155 /* Instr[22,10] encodes N immr and imms. we want a lookup table
156 for each possible combination i.e. 13 bits worth of int entries. */
157 #define LI_TABLE_SIZE (1 << 13)
158 static uint64_t LITable
[LI_TABLE_SIZE
];
161 aarch64_init_LIT_table (void)
165 for (index
= 0; index
< LI_TABLE_SIZE
; index
++)
167 uint32_t N
= uimm (index
, 12, 12);
168 uint32_t immr
= uimm (index
, 11, 6);
169 uint32_t imms
= uimm (index
, 5, 0);
171 LITable
[index
] = expand_logical_immediate (imms
, immr
, N
);
176 dexNotify (sim_cpu
*cpu
)
178 /* instr[14,0] == type : 0 ==> method entry, 1 ==> method reentry
179 2 ==> exit Java, 3 ==> start next bytecode. */
180 uint32_t type
= INSTR (14, 0);
182 TRACE_EVENTS (cpu
, "Notify Insn encountered, type = 0x%x", type
);
187 /* aarch64_notifyMethodEntry (aarch64_get_reg_u64 (cpu, R23, 0),
188 aarch64_get_reg_u64 (cpu, R22, 0)); */
191 /* aarch64_notifyMethodReentry (aarch64_get_reg_u64 (cpu, R23, 0),
192 aarch64_get_reg_u64 (cpu, R22, 0)); */
195 /* aarch64_notifyMethodExit (); */
198 /* aarch64_notifyBCStart (aarch64_get_reg_u64 (cpu, R23, 0),
199 aarch64_get_reg_u64 (cpu, R22, 0)); */
204 /* secondary decode within top level groups */
207 dexPseudo (sim_cpu
*cpu
)
209 /* assert instr[28,27] = 00
211 We provide 2 pseudo instructions:
213 HALT stops execution of the simulator causing an immediate
214 return to the x86 code which entered it.
216 CALLOUT initiates recursive entry into x86 code. A register
217 argument holds the address of the x86 routine. Immediate
218 values in the instruction identify the number of general
219 purpose and floating point register arguments to be passed
220 and the type of any value to be returned. */
222 uint32_t PSEUDO_HALT
= 0xE0000000U
;
223 uint32_t PSEUDO_CALLOUT
= 0x00018000U
;
224 uint32_t PSEUDO_CALLOUTR
= 0x00018001U
;
225 uint32_t PSEUDO_NOTIFY
= 0x00014000U
;
228 if (aarch64_get_instr (cpu
) == PSEUDO_HALT
)
230 TRACE_EVENTS (cpu
, " Pseudo Halt Instruction");
231 sim_engine_halt (CPU_STATE (cpu
), cpu
, NULL
, aarch64_get_PC (cpu
),
232 sim_stopped
, SIM_SIGTRAP
);
235 dispatch
= INSTR (31, 15);
237 /* We do not handle callouts at the moment. */
238 if (dispatch
== PSEUDO_CALLOUT
|| dispatch
== PSEUDO_CALLOUTR
)
240 TRACE_EVENTS (cpu
, " Callout");
241 sim_engine_halt (CPU_STATE (cpu
), cpu
, NULL
, aarch64_get_PC (cpu
),
242 sim_stopped
, SIM_SIGABRT
);
245 else if (dispatch
== PSEUDO_NOTIFY
)
252 /* Load-store single register (unscaled offset)
253 These instructions employ a base register plus an unscaled signed
256 N.B. the base register (source) can be Xn or SP. all other
257 registers may not be SP. */
259 /* 32 bit load 32 bit unscaled signed 9 bit. */
261 ldur32 (sim_cpu
*cpu
, int32_t offset
)
263 unsigned rn
= INSTR (9, 5);
264 unsigned rt
= INSTR (4, 0);
266 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
267 aarch64_set_reg_u64 (cpu
, rt
, NO_SP
, aarch64_get_mem_u32
268 (cpu
, aarch64_get_reg_u64 (cpu
, rn
, SP_OK
)
272 /* 64 bit load 64 bit unscaled signed 9 bit. */
274 ldur64 (sim_cpu
*cpu
, int32_t offset
)
276 unsigned rn
= INSTR (9, 5);
277 unsigned rt
= INSTR (4, 0);
279 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
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 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
293 aarch64_set_reg_u64 (cpu
, rt
, NO_SP
, aarch64_get_mem_u8
294 (cpu
, aarch64_get_reg_u64 (cpu
, rn
, SP_OK
)
298 /* 32 bit load sign-extended byte unscaled signed 9 bit. */
300 ldursb32 (sim_cpu
*cpu
, int32_t offset
)
302 unsigned rn
= INSTR (9, 5);
303 unsigned rt
= INSTR (4, 0);
305 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
306 aarch64_set_reg_u64 (cpu
, rt
, NO_SP
, (uint32_t) aarch64_get_mem_s8
307 (cpu
, aarch64_get_reg_u64 (cpu
, rn
, SP_OK
)
311 /* 64 bit load sign-extended byte unscaled signed 9 bit. */
313 ldursb64 (sim_cpu
*cpu
, int32_t offset
)
315 unsigned rn
= INSTR (9, 5);
316 unsigned rt
= INSTR (4, 0);
318 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
319 aarch64_set_reg_s64 (cpu
, rt
, NO_SP
, aarch64_get_mem_s8
320 (cpu
, aarch64_get_reg_u64 (cpu
, rn
, SP_OK
)
324 /* 32 bit load zero-extended short unscaled signed 9 bit */
326 ldurh32 (sim_cpu
*cpu
, int32_t offset
)
328 unsigned rn
= INSTR (9, 5);
329 unsigned rd
= INSTR (4, 0);
331 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
332 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, aarch64_get_mem_u16
333 (cpu
, aarch64_get_reg_u64 (cpu
, rn
, SP_OK
)
337 /* 32 bit load sign-extended short unscaled signed 9 bit */
339 ldursh32 (sim_cpu
*cpu
, int32_t offset
)
341 unsigned rn
= INSTR (9, 5);
342 unsigned rd
= INSTR (4, 0);
344 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
345 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, (uint32_t) aarch64_get_mem_s16
346 (cpu
, aarch64_get_reg_u64 (cpu
, rn
, SP_OK
)
350 /* 64 bit load sign-extended short unscaled signed 9 bit */
352 ldursh64 (sim_cpu
*cpu
, int32_t offset
)
354 unsigned rn
= INSTR (9, 5);
355 unsigned rt
= INSTR (4, 0);
357 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
358 aarch64_set_reg_s64 (cpu
, rt
, NO_SP
, aarch64_get_mem_s16
359 (cpu
, aarch64_get_reg_u64 (cpu
, rn
, SP_OK
)
363 /* 64 bit load sign-extended word unscaled signed 9 bit */
365 ldursw (sim_cpu
*cpu
, int32_t offset
)
367 unsigned rn
= INSTR (9, 5);
368 unsigned rd
= INSTR (4, 0);
370 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
371 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, (uint32_t) aarch64_get_mem_s32
372 (cpu
, aarch64_get_reg_u64 (cpu
, rn
, SP_OK
)
376 /* N.B. with stores the value in source is written to the address
377 identified by source2 modified by offset. */
379 /* 32 bit store 32 bit unscaled signed 9 bit. */
381 stur32 (sim_cpu
*cpu
, int32_t offset
)
383 unsigned rn
= INSTR (9, 5);
384 unsigned rd
= INSTR (4, 0);
386 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
387 aarch64_set_mem_u32 (cpu
,
388 aarch64_get_reg_u64 (cpu
, rn
, SP_OK
) + offset
,
389 aarch64_get_reg_u32 (cpu
, rd
, NO_SP
));
392 /* 64 bit store 64 bit unscaled signed 9 bit */
394 stur64 (sim_cpu
*cpu
, int32_t offset
)
396 unsigned rn
= INSTR (9, 5);
397 unsigned rd
= INSTR (4, 0);
399 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
400 aarch64_set_mem_u64 (cpu
,
401 aarch64_get_reg_u64 (cpu
, rn
, SP_OK
) + offset
,
402 aarch64_get_reg_u64 (cpu
, rd
, NO_SP
));
405 /* 32 bit store byte unscaled signed 9 bit */
407 sturb (sim_cpu
*cpu
, int32_t offset
)
409 unsigned rn
= INSTR (9, 5);
410 unsigned rd
= INSTR (4, 0);
412 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
413 aarch64_set_mem_u8 (cpu
,
414 aarch64_get_reg_u64 (cpu
, rn
, SP_OK
) + offset
,
415 aarch64_get_reg_u8 (cpu
, rd
, NO_SP
));
418 /* 32 bit store short unscaled signed 9 bit */
420 sturh (sim_cpu
*cpu
, int32_t offset
)
422 unsigned rn
= INSTR (9, 5);
423 unsigned rd
= INSTR (4, 0);
425 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
426 aarch64_set_mem_u16 (cpu
,
427 aarch64_get_reg_u64 (cpu
, rn
, SP_OK
) + offset
,
428 aarch64_get_reg_u16 (cpu
, rd
, NO_SP
));
431 /* Load single register pc-relative label
432 Offset is a signed 19 bit immediate count in words
435 /* 32 bit pc-relative load */
437 ldr32_pcrel (sim_cpu
*cpu
, int32_t offset
)
439 unsigned rd
= INSTR (4, 0);
441 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
442 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
,
444 (cpu
, aarch64_get_PC (cpu
) + offset
* 4));
447 /* 64 bit pc-relative load */
449 ldr_pcrel (sim_cpu
*cpu
, int32_t offset
)
451 unsigned rd
= INSTR (4, 0);
453 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
454 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
,
456 (cpu
, aarch64_get_PC (cpu
) + offset
* 4));
459 /* sign extended 32 bit pc-relative load */
461 ldrsw_pcrel (sim_cpu
*cpu
, int32_t offset
)
463 unsigned rd
= INSTR (4, 0);
465 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
466 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
,
468 (cpu
, aarch64_get_PC (cpu
) + offset
* 4));
471 /* float pc-relative load */
473 fldrs_pcrel (sim_cpu
*cpu
, int32_t offset
)
475 unsigned int rd
= INSTR (4, 0);
477 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
478 aarch64_set_vec_u32 (cpu
, rd
, 0,
480 (cpu
, aarch64_get_PC (cpu
) + offset
* 4));
483 /* double pc-relative load */
485 fldrd_pcrel (sim_cpu
*cpu
, int32_t offset
)
487 unsigned int st
= INSTR (4, 0);
489 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
490 aarch64_set_vec_u64 (cpu
, st
, 0,
492 (cpu
, aarch64_get_PC (cpu
) + offset
* 4));
495 /* long double pc-relative load. */
497 fldrq_pcrel (sim_cpu
*cpu
, int32_t offset
)
499 unsigned int st
= INSTR (4, 0);
500 uint64_t addr
= aarch64_get_PC (cpu
) + offset
* 4;
503 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
504 aarch64_get_mem_long_double (cpu
, addr
, & a
);
505 aarch64_set_FP_long_double (cpu
, st
, a
);
508 /* This can be used to scale an offset by applying
509 the requisite shift. the second argument is either
512 #define SCALE(_offset, _elementSize) \
513 ((_offset) << ScaleShift ## _elementSize)
515 /* This can be used to optionally scale a register derived offset
516 by applying the requisite shift as indicated by the Scaling
517 argument. The second argument is either Byte, Short, Word
518 or Long. The third argument is either Scaled or Unscaled.
519 N.B. when _Scaling is Scaled the shift gets ANDed with
520 all 1s while when it is Unscaled it gets ANDed with 0. */
522 #define OPT_SCALE(_offset, _elementType, _Scaling) \
523 ((_offset) << (_Scaling ? ScaleShift ## _elementType : 0))
525 /* This can be used to zero or sign extend a 32 bit register derived
526 value to a 64 bit value. the first argument must be the value as
527 a uint32_t and the second must be either UXTW or SXTW. The result
528 is returned as an int64_t. */
530 static inline int64_t
531 extend (uint32_t value
, Extension extension
)
539 /* A branchless variant of this ought to be possible. */
540 if (extension
== UXTW
|| extension
== NoExtension
)
547 /* Scalar Floating Point
549 FP load/store single register (4 addressing modes)
551 N.B. the base register (source) can be the stack pointer.
552 The secondary source register (source2) can only be an Xn register. */
554 /* Load 32 bit unscaled signed 9 bit with pre- or post-writeback. */
556 fldrs_wb (sim_cpu
*cpu
, int32_t offset
, WriteBack wb
)
558 unsigned rn
= INSTR (9, 5);
559 unsigned st
= INSTR (4, 0);
560 uint64_t address
= aarch64_get_reg_u64 (cpu
, rn
, SP_OK
);
565 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
566 aarch64_set_vec_u32 (cpu
, st
, 0, aarch64_get_mem_u32 (cpu
, address
));
570 if (wb
!= NoWriteBack
)
571 aarch64_set_reg_u64 (cpu
, rn
, SP_OK
, address
);
574 /* Load 8 bit with unsigned 12 bit offset. */
576 fldrb_abs (sim_cpu
*cpu
, uint32_t offset
)
578 unsigned rd
= INSTR (4, 0);
579 unsigned rn
= INSTR (9, 5);
580 uint64_t addr
= aarch64_get_reg_u64 (cpu
, rn
, SP_OK
) + offset
;
582 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
583 aarch64_set_vec_u8 (cpu
, rd
, 0, aarch64_get_mem_u32 (cpu
, addr
));
586 /* Load 16 bit scaled unsigned 12 bit. */
588 fldrh_abs (sim_cpu
*cpu
, uint32_t offset
)
590 unsigned rd
= INSTR (4, 0);
591 unsigned rn
= INSTR (9, 5);
592 uint64_t addr
= aarch64_get_reg_u64 (cpu
, rn
, SP_OK
) + SCALE (offset
, 16);
594 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
595 aarch64_set_vec_u16 (cpu
, rd
, 0, aarch64_get_mem_u16 (cpu
, addr
));
598 /* Load 32 bit scaled unsigned 12 bit. */
600 fldrs_abs (sim_cpu
*cpu
, uint32_t offset
)
602 unsigned rd
= INSTR (4, 0);
603 unsigned rn
= INSTR (9, 5);
604 uint64_t addr
= aarch64_get_reg_u64 (cpu
, rn
, SP_OK
) + SCALE (offset
, 32);
606 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
607 aarch64_set_vec_u32 (cpu
, rd
, 0, aarch64_get_mem_u32 (cpu
, addr
));
610 /* Load 64 bit scaled unsigned 12 bit. */
612 fldrd_abs (sim_cpu
*cpu
, uint32_t offset
)
614 unsigned rd
= INSTR (4, 0);
615 unsigned rn
= INSTR (9, 5);
616 uint64_t addr
= aarch64_get_reg_u64 (cpu
, rn
, SP_OK
) + SCALE (offset
, 64);
618 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
619 aarch64_set_vec_u64 (cpu
, rd
, 0, aarch64_get_mem_u64 (cpu
, addr
));
622 /* Load 128 bit scaled unsigned 12 bit. */
624 fldrq_abs (sim_cpu
*cpu
, uint32_t offset
)
626 unsigned rd
= INSTR (4, 0);
627 unsigned rn
= INSTR (9, 5);
628 uint64_t addr
= aarch64_get_reg_u64 (cpu
, rn
, SP_OK
) + SCALE (offset
, 128);
630 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
631 aarch64_set_vec_u64 (cpu
, rd
, 0, aarch64_get_mem_u64 (cpu
, addr
));
632 aarch64_set_vec_u64 (cpu
, rd
, 1, aarch64_get_mem_u64 (cpu
, addr
+ 8));
635 /* Load 32 bit scaled or unscaled zero- or sign-extended
636 32-bit register offset. */
638 fldrs_scale_ext (sim_cpu
*cpu
, Scaling scaling
, Extension extension
)
640 unsigned rm
= INSTR (20, 16);
641 unsigned rn
= INSTR (9, 5);
642 unsigned st
= INSTR (4, 0);
643 uint64_t address
= aarch64_get_reg_u64 (cpu
, rn
, SP_OK
);
644 int64_t extended
= extend (aarch64_get_reg_u32 (cpu
, rm
, NO_SP
), extension
);
645 uint64_t displacement
= OPT_SCALE (extended
, 32, scaling
);
647 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
648 aarch64_set_vec_u32 (cpu
, st
, 0, aarch64_get_mem_u32
649 (cpu
, address
+ displacement
));
652 /* Load 64 bit unscaled signed 9 bit with pre- or post-writeback. */
654 fldrd_wb (sim_cpu
*cpu
, int32_t offset
, WriteBack wb
)
656 unsigned rn
= INSTR (9, 5);
657 unsigned st
= INSTR (4, 0);
658 uint64_t address
= aarch64_get_reg_u64 (cpu
, rn
, SP_OK
);
663 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
664 aarch64_set_vec_u64 (cpu
, st
, 0, aarch64_get_mem_u64 (cpu
, address
));
669 if (wb
!= NoWriteBack
)
670 aarch64_set_reg_u64 (cpu
, rn
, SP_OK
, address
);
673 /* Load 64 bit scaled or unscaled zero- or sign-extended 32-bit register offset. */
675 fldrd_scale_ext (sim_cpu
*cpu
, Scaling scaling
, Extension extension
)
677 unsigned rm
= INSTR (20, 16);
678 int64_t extended
= extend (aarch64_get_reg_u32 (cpu
, rm
, NO_SP
), extension
);
679 uint64_t displacement
= OPT_SCALE (extended
, 64, scaling
);
681 fldrd_wb (cpu
, displacement
, NoWriteBack
);
684 /* Load 128 bit unscaled signed 9 bit with pre- or post-writeback. */
686 fldrq_wb (sim_cpu
*cpu
, int32_t offset
, WriteBack wb
)
689 unsigned rn
= INSTR (9, 5);
690 unsigned st
= INSTR (4, 0);
691 uint64_t address
= aarch64_get_reg_u64 (cpu
, rn
, SP_OK
);
696 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
697 aarch64_get_mem_long_double (cpu
, address
, & a
);
698 aarch64_set_FP_long_double (cpu
, st
, a
);
703 if (wb
!= NoWriteBack
)
704 aarch64_set_reg_u64 (cpu
, rn
, SP_OK
, address
);
707 /* Load 128 bit scaled or unscaled zero- or sign-extended 32-bit register offset */
709 fldrq_scale_ext (sim_cpu
*cpu
, Scaling scaling
, Extension extension
)
711 unsigned rm
= INSTR (20, 16);
712 int64_t extended
= extend (aarch64_get_reg_u32 (cpu
, rm
, NO_SP
), extension
);
713 uint64_t displacement
= OPT_SCALE (extended
, 128, scaling
);
715 fldrq_wb (cpu
, displacement
, NoWriteBack
);
720 load-store single register
721 There are four addressing modes available here which all employ a
722 64 bit source (base) register.
724 N.B. the base register (source) can be the stack pointer.
725 The secondary source register (source2)can only be an Xn register.
727 Scaled, 12-bit, unsigned immediate offset, without pre- and
729 Unscaled, 9-bit, signed immediate offset with pre- or post-index
731 scaled or unscaled 64-bit register offset.
732 scaled or unscaled 32-bit extended register offset.
734 All offsets are assumed to be raw from the decode i.e. the
735 simulator is expected to adjust scaled offsets based on the
736 accessed data size with register or extended register offset
737 versions the same applies except that in the latter case the
738 operation may also require a sign extend.
740 A separate method is provided for each possible addressing mode. */
742 /* 32 bit load 32 bit scaled unsigned 12 bit */
744 ldr32_abs (sim_cpu
*cpu
, uint32_t offset
)
746 unsigned rn
= INSTR (9, 5);
747 unsigned rt
= INSTR (4, 0);
749 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
750 /* The target register may not be SP but the source may be. */
751 aarch64_set_reg_u64 (cpu
, rt
, NO_SP
, aarch64_get_mem_u32
752 (cpu
, aarch64_get_reg_u64 (cpu
, rn
, SP_OK
)
753 + SCALE (offset
, 32)));
756 /* 32 bit load 32 bit unscaled signed 9 bit with pre- or post-writeback. */
758 ldr32_wb (sim_cpu
*cpu
, int32_t offset
, WriteBack wb
)
760 unsigned rn
= INSTR (9, 5);
761 unsigned rt
= INSTR (4, 0);
764 if (rn
== rt
&& wb
!= NoWriteBack
)
767 address
= aarch64_get_reg_u64 (cpu
, rn
, SP_OK
);
772 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
773 aarch64_set_reg_u64 (cpu
, rt
, NO_SP
, aarch64_get_mem_u32 (cpu
, address
));
778 if (wb
!= NoWriteBack
)
779 aarch64_set_reg_u64 (cpu
, rn
, SP_OK
, address
);
782 /* 32 bit load 32 bit scaled or unscaled
783 zero- or sign-extended 32-bit register offset */
785 ldr32_scale_ext (sim_cpu
*cpu
, Scaling scaling
, Extension extension
)
787 unsigned rm
= INSTR (20, 16);
788 unsigned rn
= INSTR (9, 5);
789 unsigned rt
= INSTR (4, 0);
790 /* rn may reference SP, rm and rt must reference ZR */
792 uint64_t address
= aarch64_get_reg_u64 (cpu
, rn
, SP_OK
);
793 int64_t extended
= extend (aarch64_get_reg_u32 (cpu
, rm
, NO_SP
), extension
);
794 uint64_t displacement
= OPT_SCALE (extended
, 32, scaling
);
796 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
797 aarch64_set_reg_u64 (cpu
, rt
, NO_SP
,
798 aarch64_get_mem_u32 (cpu
, address
+ displacement
));
801 /* 64 bit load 64 bit scaled unsigned 12 bit */
803 ldr_abs (sim_cpu
*cpu
, uint32_t offset
)
805 unsigned rn
= INSTR (9, 5);
806 unsigned rt
= INSTR (4, 0);
808 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
809 /* The target register may not be SP but the source may be. */
810 aarch64_set_reg_u64 (cpu
, rt
, NO_SP
, aarch64_get_mem_u64
811 (cpu
, aarch64_get_reg_u64 (cpu
, rn
, SP_OK
)
812 + SCALE (offset
, 64)));
815 /* 64 bit load 64 bit unscaled signed 9 bit with pre- or post-writeback. */
817 ldr_wb (sim_cpu
*cpu
, int32_t offset
, WriteBack wb
)
819 unsigned rn
= INSTR (9, 5);
820 unsigned rt
= INSTR (4, 0);
823 if (rn
== rt
&& wb
!= NoWriteBack
)
826 address
= aarch64_get_reg_u64 (cpu
, rn
, SP_OK
);
831 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
832 aarch64_set_reg_u64 (cpu
, rt
, NO_SP
, aarch64_get_mem_u64 (cpu
, address
));
837 if (wb
!= NoWriteBack
)
838 aarch64_set_reg_u64 (cpu
, rn
, SP_OK
, address
);
841 /* 64 bit load 64 bit scaled or unscaled zero-
842 or sign-extended 32-bit register offset. */
844 ldr_scale_ext (sim_cpu
*cpu
, Scaling scaling
, Extension extension
)
846 unsigned rm
= INSTR (20, 16);
847 unsigned rn
= INSTR (9, 5);
848 unsigned rt
= INSTR (4, 0);
849 /* rn may reference SP, rm and rt must reference ZR */
851 uint64_t address
= aarch64_get_reg_u64 (cpu
, rn
, SP_OK
);
852 int64_t extended
= extend (aarch64_get_reg_u32 (cpu
, rm
, NO_SP
), extension
);
853 uint64_t displacement
= OPT_SCALE (extended
, 64, scaling
);
855 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
856 aarch64_set_reg_u64 (cpu
, rt
, NO_SP
,
857 aarch64_get_mem_u64 (cpu
, address
+ displacement
));
860 /* 32 bit load zero-extended byte scaled unsigned 12 bit. */
862 ldrb32_abs (sim_cpu
*cpu
, uint32_t offset
)
864 unsigned rn
= INSTR (9, 5);
865 unsigned rt
= INSTR (4, 0);
867 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
868 /* The target register may not be SP but the source may be
869 there is no scaling required for a byte load. */
870 aarch64_set_reg_u64 (cpu
, rt
, NO_SP
,
872 (cpu
, aarch64_get_reg_u64 (cpu
, rn
, SP_OK
) + offset
));
875 /* 32 bit load zero-extended byte unscaled signed 9 bit with pre- or post-writeback. */
877 ldrb32_wb (sim_cpu
*cpu
, int32_t offset
, WriteBack wb
)
879 unsigned rn
= INSTR (9, 5);
880 unsigned rt
= INSTR (4, 0);
883 if (rn
== rt
&& wb
!= NoWriteBack
)
886 address
= aarch64_get_reg_u64 (cpu
, rn
, SP_OK
);
891 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
892 aarch64_set_reg_u64 (cpu
, rt
, NO_SP
, aarch64_get_mem_u8 (cpu
, address
));
897 if (wb
!= NoWriteBack
)
898 aarch64_set_reg_u64 (cpu
, rn
, SP_OK
, address
);
901 /* 32 bit load zero-extended byte scaled or unscaled zero-
902 or sign-extended 32-bit register offset. */
904 ldrb32_scale_ext (sim_cpu
*cpu
, Scaling scaling
, Extension extension
)
906 unsigned rm
= INSTR (20, 16);
907 unsigned rn
= INSTR (9, 5);
908 unsigned rt
= INSTR (4, 0);
909 /* rn may reference SP, rm and rt must reference ZR */
911 uint64_t address
= aarch64_get_reg_u64 (cpu
, rn
, SP_OK
);
912 int64_t displacement
= extend (aarch64_get_reg_u32 (cpu
, rm
, NO_SP
),
915 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
916 /* There is no scaling required for a byte load. */
917 aarch64_set_reg_u64 (cpu
, rt
, NO_SP
,
918 aarch64_get_mem_u8 (cpu
, address
+ displacement
));
921 /* 64 bit load sign-extended byte unscaled signed 9 bit
922 with pre- or post-writeback. */
924 ldrsb_wb (sim_cpu
*cpu
, int32_t offset
, WriteBack wb
)
926 unsigned rn
= INSTR (9, 5);
927 unsigned rt
= INSTR (4, 0);
931 if (rn
== rt
&& wb
!= NoWriteBack
)
934 address
= aarch64_get_reg_u64 (cpu
, rn
, SP_OK
);
939 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
940 val
= aarch64_get_mem_s8 (cpu
, address
);
941 aarch64_set_reg_s64 (cpu
, rt
, NO_SP
, val
);
946 if (wb
!= NoWriteBack
)
947 aarch64_set_reg_u64 (cpu
, rn
, SP_OK
, address
);
950 /* 64 bit load sign-extended byte scaled unsigned 12 bit. */
952 ldrsb_abs (sim_cpu
*cpu
, uint32_t offset
)
954 ldrsb_wb (cpu
, offset
, NoWriteBack
);
957 /* 64 bit load sign-extended byte scaled or unscaled zero-
958 or sign-extended 32-bit register offset. */
960 ldrsb_scale_ext (sim_cpu
*cpu
, Scaling scaling
, Extension extension
)
962 unsigned rm
= INSTR (20, 16);
963 unsigned rn
= INSTR (9, 5);
964 unsigned rt
= INSTR (4, 0);
965 /* rn may reference SP, rm and rt must reference ZR */
967 uint64_t address
= aarch64_get_reg_u64 (cpu
, rn
, SP_OK
);
968 int64_t displacement
= extend (aarch64_get_reg_u32 (cpu
, rm
, NO_SP
),
970 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
971 /* There is no scaling required for a byte load. */
972 aarch64_set_reg_s64 (cpu
, rt
, NO_SP
,
973 aarch64_get_mem_s8 (cpu
, address
+ displacement
));
976 /* 32 bit load zero-extended short scaled unsigned 12 bit. */
978 ldrh32_abs (sim_cpu
*cpu
, uint32_t offset
)
980 unsigned rn
= INSTR (9, 5);
981 unsigned rt
= INSTR (4, 0);
984 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
985 /* The target register may not be SP but the source may be. */
986 val
= aarch64_get_mem_u16 (cpu
, aarch64_get_reg_u64 (cpu
, rn
, SP_OK
)
987 + SCALE (offset
, 16));
988 aarch64_set_reg_u32 (cpu
, rt
, NO_SP
, val
);
991 /* 32 bit load zero-extended short unscaled signed 9 bit
992 with pre- or post-writeback. */
994 ldrh32_wb (sim_cpu
*cpu
, int32_t offset
, WriteBack wb
)
996 unsigned rn
= INSTR (9, 5);
997 unsigned rt
= INSTR (4, 0);
1000 if (rn
== rt
&& wb
!= NoWriteBack
)
1003 address
= aarch64_get_reg_u64 (cpu
, rn
, SP_OK
);
1008 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
1009 aarch64_set_reg_u32 (cpu
, rt
, NO_SP
, aarch64_get_mem_u16 (cpu
, address
));
1014 if (wb
!= NoWriteBack
)
1015 aarch64_set_reg_u64 (cpu
, rn
, SP_OK
, address
);
1018 /* 32 bit load zero-extended short scaled or unscaled zero-
1019 or sign-extended 32-bit register offset. */
1021 ldrh32_scale_ext (sim_cpu
*cpu
, Scaling scaling
, Extension extension
)
1023 unsigned rm
= INSTR (20, 16);
1024 unsigned rn
= INSTR (9, 5);
1025 unsigned rt
= INSTR (4, 0);
1026 /* rn may reference SP, rm and rt must reference ZR */
1028 uint64_t address
= aarch64_get_reg_u64 (cpu
, rn
, SP_OK
);
1029 int64_t extended
= extend (aarch64_get_reg_u32 (cpu
, rm
, NO_SP
), extension
);
1030 uint64_t displacement
= OPT_SCALE (extended
, 16, scaling
);
1032 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
1033 aarch64_set_reg_u32 (cpu
, rt
, NO_SP
,
1034 aarch64_get_mem_u16 (cpu
, address
+ displacement
));
1037 /* 32 bit load sign-extended short scaled unsigned 12 bit. */
1039 ldrsh32_abs (sim_cpu
*cpu
, uint32_t offset
)
1041 unsigned rn
= INSTR (9, 5);
1042 unsigned rt
= INSTR (4, 0);
1045 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
1046 /* The target register may not be SP but the source may be. */
1047 val
= aarch64_get_mem_s16 (cpu
, aarch64_get_reg_u64 (cpu
, rn
, SP_OK
)
1048 + SCALE (offset
, 16));
1049 aarch64_set_reg_s32 (cpu
, rt
, NO_SP
, val
);
1052 /* 32 bit load sign-extended short unscaled signed 9 bit
1053 with pre- or post-writeback. */
1055 ldrsh32_wb (sim_cpu
*cpu
, int32_t offset
, WriteBack wb
)
1057 unsigned rn
= INSTR (9, 5);
1058 unsigned rt
= INSTR (4, 0);
1061 if (rn
== rt
&& wb
!= NoWriteBack
)
1064 address
= aarch64_get_reg_u64 (cpu
, rn
, SP_OK
);
1069 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
1070 aarch64_set_reg_s32 (cpu
, rt
, NO_SP
,
1071 (int32_t) aarch64_get_mem_s16 (cpu
, address
));
1076 if (wb
!= NoWriteBack
)
1077 aarch64_set_reg_u64 (cpu
, rn
, SP_OK
, address
);
1080 /* 32 bit load sign-extended short scaled or unscaled zero-
1081 or sign-extended 32-bit register offset. */
1083 ldrsh32_scale_ext (sim_cpu
*cpu
, Scaling scaling
, Extension extension
)
1085 unsigned rm
= INSTR (20, 16);
1086 unsigned rn
= INSTR (9, 5);
1087 unsigned rt
= INSTR (4, 0);
1088 /* rn may reference SP, rm and rt must reference ZR */
1090 uint64_t address
= aarch64_get_reg_u64 (cpu
, rn
, SP_OK
);
1091 int64_t extended
= extend (aarch64_get_reg_u32 (cpu
, rm
, NO_SP
), extension
);
1092 uint64_t displacement
= OPT_SCALE (extended
, 16, scaling
);
1094 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
1095 aarch64_set_reg_s32 (cpu
, rt
, NO_SP
,
1096 (int32_t) aarch64_get_mem_s16
1097 (cpu
, address
+ displacement
));
1100 /* 64 bit load sign-extended short scaled unsigned 12 bit. */
1102 ldrsh_abs (sim_cpu
*cpu
, uint32_t offset
)
1104 unsigned rn
= INSTR (9, 5);
1105 unsigned rt
= INSTR (4, 0);
1108 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
1109 /* The target register may not be SP but the source may be. */
1110 val
= aarch64_get_mem_s16 (cpu
, aarch64_get_reg_u64 (cpu
, rn
, SP_OK
)
1111 + SCALE (offset
, 16));
1112 aarch64_set_reg_s64 (cpu
, rt
, NO_SP
, val
);
1115 /* 64 bit load sign-extended short unscaled signed 9 bit
1116 with pre- or post-writeback. */
1118 ldrsh64_wb (sim_cpu
*cpu
, int32_t offset
, WriteBack wb
)
1120 unsigned rn
= INSTR (9, 5);
1121 unsigned rt
= INSTR (4, 0);
1125 if (rn
== rt
&& wb
!= NoWriteBack
)
1128 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
1129 address
= aarch64_get_reg_u64 (cpu
, rn
, SP_OK
);
1134 val
= aarch64_get_mem_s16 (cpu
, address
);
1135 aarch64_set_reg_s64 (cpu
, rt
, NO_SP
, val
);
1140 if (wb
!= NoWriteBack
)
1141 aarch64_set_reg_u64 (cpu
, rn
, SP_OK
, address
);
1144 /* 64 bit load sign-extended short scaled or unscaled zero-
1145 or sign-extended 32-bit register offset. */
1147 ldrsh_scale_ext (sim_cpu
*cpu
, Scaling scaling
, Extension extension
)
1149 unsigned rm
= INSTR (20, 16);
1150 unsigned rn
= INSTR (9, 5);
1151 unsigned rt
= INSTR (4, 0);
1153 /* rn may reference SP, rm and rt must reference ZR */
1155 uint64_t address
= aarch64_get_reg_u64 (cpu
, rn
, SP_OK
);
1156 int64_t extended
= extend (aarch64_get_reg_u32 (cpu
, rm
, NO_SP
), extension
);
1157 uint64_t displacement
= OPT_SCALE (extended
, 16, scaling
);
1160 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
1161 val
= aarch64_get_mem_s16 (cpu
, address
+ displacement
);
1162 aarch64_set_reg_s64 (cpu
, rt
, NO_SP
, val
);
1165 /* 64 bit load sign-extended 32 bit scaled unsigned 12 bit. */
1167 ldrsw_abs (sim_cpu
*cpu
, uint32_t offset
)
1169 unsigned rn
= INSTR (9, 5);
1170 unsigned rt
= INSTR (4, 0);
1173 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
1174 val
= aarch64_get_mem_s32 (cpu
, aarch64_get_reg_u64 (cpu
, rn
, SP_OK
)
1175 + SCALE (offset
, 32));
1176 /* The target register may not be SP but the source may be. */
1177 return aarch64_set_reg_s64 (cpu
, rt
, NO_SP
, val
);
1180 /* 64 bit load sign-extended 32 bit unscaled signed 9 bit
1181 with pre- or post-writeback. */
1183 ldrsw_wb (sim_cpu
*cpu
, int32_t offset
, WriteBack wb
)
1185 unsigned rn
= INSTR (9, 5);
1186 unsigned rt
= INSTR (4, 0);
1189 if (rn
== rt
&& wb
!= NoWriteBack
)
1192 address
= aarch64_get_reg_u64 (cpu
, rn
, SP_OK
);
1197 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
1198 aarch64_set_reg_s64 (cpu
, rt
, NO_SP
, aarch64_get_mem_s32 (cpu
, address
));
1203 if (wb
!= NoWriteBack
)
1204 aarch64_set_reg_u64 (cpu
, rn
, SP_OK
, address
);
1207 /* 64 bit load sign-extended 32 bit scaled or unscaled zero-
1208 or sign-extended 32-bit register offset. */
1210 ldrsw_scale_ext (sim_cpu
*cpu
, Scaling scaling
, Extension extension
)
1212 unsigned rm
= INSTR (20, 16);
1213 unsigned rn
= INSTR (9, 5);
1214 unsigned rt
= INSTR (4, 0);
1215 /* rn may reference SP, rm and rt must reference ZR */
1217 uint64_t address
= aarch64_get_reg_u64 (cpu
, rn
, SP_OK
);
1218 int64_t extended
= extend (aarch64_get_reg_u32 (cpu
, rm
, NO_SP
), extension
);
1219 uint64_t displacement
= OPT_SCALE (extended
, 32, scaling
);
1221 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
1222 aarch64_set_reg_s64 (cpu
, rt
, NO_SP
,
1223 aarch64_get_mem_s32 (cpu
, address
+ displacement
));
1226 /* N.B. with stores the value in source is written to the
1227 address identified by source2 modified by source3/offset. */
1229 /* 32 bit store scaled unsigned 12 bit. */
1231 str32_abs (sim_cpu
*cpu
, uint32_t offset
)
1233 unsigned rn
= INSTR (9, 5);
1234 unsigned rt
= INSTR (4, 0);
1236 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
1237 /* The target register may not be SP but the source may be. */
1238 aarch64_set_mem_u32 (cpu
, (aarch64_get_reg_u64 (cpu
, rn
, SP_OK
)
1239 + SCALE (offset
, 32)),
1240 aarch64_get_reg_u32 (cpu
, rt
, NO_SP
));
1243 /* 32 bit store unscaled signed 9 bit with pre- or post-writeback. */
1245 str32_wb (sim_cpu
*cpu
, int32_t offset
, WriteBack wb
)
1247 unsigned rn
= INSTR (9, 5);
1248 unsigned rt
= INSTR (4, 0);
1251 if (rn
== rt
&& wb
!= NoWriteBack
)
1254 address
= aarch64_get_reg_u64 (cpu
, rn
, SP_OK
);
1258 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
1259 aarch64_set_mem_u32 (cpu
, address
, aarch64_get_reg_u32 (cpu
, rt
, NO_SP
));
1264 if (wb
!= NoWriteBack
)
1265 aarch64_set_reg_u64 (cpu
, rn
, SP_OK
, address
);
1268 /* 32 bit store scaled or unscaled zero- or
1269 sign-extended 32-bit register offset. */
1271 str32_scale_ext (sim_cpu
*cpu
, Scaling scaling
, Extension extension
)
1273 unsigned rm
= INSTR (20, 16);
1274 unsigned rn
= INSTR (9, 5);
1275 unsigned rt
= INSTR (4, 0);
1277 uint64_t address
= aarch64_get_reg_u64 (cpu
, rn
, SP_OK
);
1278 int64_t extended
= extend (aarch64_get_reg_u32 (cpu
, rm
, NO_SP
), extension
);
1279 uint64_t displacement
= OPT_SCALE (extended
, 32, scaling
);
1281 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
1282 aarch64_set_mem_u32 (cpu
, address
+ displacement
,
1283 aarch64_get_reg_u64 (cpu
, rt
, NO_SP
));
1286 /* 64 bit store scaled unsigned 12 bit. */
1288 str_abs (sim_cpu
*cpu
, uint32_t offset
)
1290 unsigned rn
= INSTR (9, 5);
1291 unsigned rt
= INSTR (4, 0);
1293 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
1294 aarch64_set_mem_u64 (cpu
,
1295 aarch64_get_reg_u64 (cpu
, rn
, SP_OK
)
1296 + SCALE (offset
, 64),
1297 aarch64_get_reg_u64 (cpu
, rt
, NO_SP
));
1300 /* 64 bit store unscaled signed 9 bit with pre- or post-writeback. */
1302 str_wb (sim_cpu
*cpu
, int32_t offset
, WriteBack wb
)
1304 unsigned rn
= INSTR (9, 5);
1305 unsigned rt
= INSTR (4, 0);
1308 if (rn
== rt
&& wb
!= NoWriteBack
)
1311 address
= aarch64_get_reg_u64 (cpu
, rn
, SP_OK
);
1316 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
1317 aarch64_set_mem_u64 (cpu
, address
, aarch64_get_reg_u64 (cpu
, rt
, NO_SP
));
1322 if (wb
!= NoWriteBack
)
1323 aarch64_set_reg_u64 (cpu
, rn
, SP_OK
, address
);
1326 /* 64 bit store scaled or unscaled zero-
1327 or sign-extended 32-bit register offset. */
1329 str_scale_ext (sim_cpu
*cpu
, Scaling scaling
, Extension extension
)
1331 unsigned rm
= INSTR (20, 16);
1332 unsigned rn
= INSTR (9, 5);
1333 unsigned rt
= INSTR (4, 0);
1334 /* rn may reference SP, rm and rt must reference ZR */
1336 uint64_t address
= aarch64_get_reg_u64 (cpu
, rn
, SP_OK
);
1337 int64_t extended
= extend (aarch64_get_reg_u32 (cpu
, rm
, NO_SP
),
1339 uint64_t displacement
= OPT_SCALE (extended
, 64, scaling
);
1341 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
1342 aarch64_set_mem_u64 (cpu
, address
+ displacement
,
1343 aarch64_get_reg_u64 (cpu
, rt
, NO_SP
));
1346 /* 32 bit store byte scaled unsigned 12 bit. */
1348 strb_abs (sim_cpu
*cpu
, uint32_t offset
)
1350 unsigned rn
= INSTR (9, 5);
1351 unsigned rt
= INSTR (4, 0);
1353 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
1354 /* The target register may not be SP but the source may be.
1355 There is no scaling required for a byte load. */
1356 aarch64_set_mem_u8 (cpu
,
1357 aarch64_get_reg_u64 (cpu
, rn
, SP_OK
) + offset
,
1358 aarch64_get_reg_u8 (cpu
, rt
, NO_SP
));
1361 /* 32 bit store byte unscaled signed 9 bit with pre- or post-writeback. */
1363 strb_wb (sim_cpu
*cpu
, int32_t offset
, WriteBack wb
)
1365 unsigned rn
= INSTR (9, 5);
1366 unsigned rt
= INSTR (4, 0);
1369 if (rn
== rt
&& wb
!= NoWriteBack
)
1372 address
= aarch64_get_reg_u64 (cpu
, rn
, SP_OK
);
1377 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
1378 aarch64_set_mem_u8 (cpu
, address
, aarch64_get_reg_u8 (cpu
, rt
, NO_SP
));
1383 if (wb
!= NoWriteBack
)
1384 aarch64_set_reg_u64 (cpu
, rn
, SP_OK
, address
);
1387 /* 32 bit store byte scaled or unscaled zero-
1388 or sign-extended 32-bit register offset. */
1390 strb_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 displacement
= extend (aarch64_get_reg_u32 (cpu
, rm
, NO_SP
),
1401 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
1402 /* There is no scaling required for a byte load. */
1403 aarch64_set_mem_u8 (cpu
, address
+ displacement
,
1404 aarch64_get_reg_u8 (cpu
, rt
, NO_SP
));
1407 /* 32 bit store short scaled unsigned 12 bit. */
1409 strh_abs (sim_cpu
*cpu
, uint32_t offset
)
1411 unsigned rn
= INSTR (9, 5);
1412 unsigned rt
= INSTR (4, 0);
1414 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
1415 /* The target register may not be SP but the source may be. */
1416 aarch64_set_mem_u16 (cpu
, aarch64_get_reg_u64 (cpu
, rn
, SP_OK
)
1417 + SCALE (offset
, 16),
1418 aarch64_get_reg_u16 (cpu
, rt
, NO_SP
));
1421 /* 32 bit store short unscaled signed 9 bit with pre- or post-writeback. */
1423 strh_wb (sim_cpu
*cpu
, int32_t offset
, WriteBack wb
)
1425 unsigned rn
= INSTR (9, 5);
1426 unsigned rt
= INSTR (4, 0);
1429 if (rn
== rt
&& wb
!= NoWriteBack
)
1432 address
= aarch64_get_reg_u64 (cpu
, rn
, SP_OK
);
1437 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
1438 aarch64_set_mem_u16 (cpu
, address
, aarch64_get_reg_u16 (cpu
, rt
, NO_SP
));
1443 if (wb
!= NoWriteBack
)
1444 aarch64_set_reg_u64 (cpu
, rn
, SP_OK
, address
);
1447 /* 32 bit store short scaled or unscaled zero-
1448 or sign-extended 32-bit register offset. */
1450 strh_scale_ext (sim_cpu
*cpu
, Scaling scaling
, Extension extension
)
1452 unsigned rm
= INSTR (20, 16);
1453 unsigned rn
= INSTR (9, 5);
1454 unsigned rt
= INSTR (4, 0);
1455 /* rn may reference SP, rm and rt must reference ZR */
1457 uint64_t address
= aarch64_get_reg_u64 (cpu
, rn
, SP_OK
);
1458 int64_t extended
= extend (aarch64_get_reg_u32 (cpu
, rm
, NO_SP
), extension
);
1459 uint64_t displacement
= OPT_SCALE (extended
, 16, scaling
);
1461 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
1462 aarch64_set_mem_u16 (cpu
, address
+ displacement
,
1463 aarch64_get_reg_u16 (cpu
, rt
, NO_SP
));
1466 /* Prefetch unsigned 12 bit. */
1468 prfm_abs (sim_cpu
*cpu
, uint32_t offset
)
1470 /* instr[4,0] = prfop : 00000 ==> PLDL1KEEP, 00001 ==> PLDL1STRM,
1471 00010 ==> PLDL2KEEP, 00001 ==> PLDL2STRM,
1472 00100 ==> PLDL3KEEP, 00101 ==> PLDL3STRM,
1473 10000 ==> PSTL1KEEP, 10001 ==> PSTL1STRM,
1474 10010 ==> PSTL2KEEP, 10001 ==> PSTL2STRM,
1475 10100 ==> PSTL3KEEP, 10101 ==> PSTL3STRM,
1477 PrfOp prfop = prfop (instr, 4, 0);
1478 uint64_t address = aarch64_get_reg_u64 (cpu, rn, SP_OK)
1479 + SCALE (offset, 64). */
1481 /* TODO : implement prefetch of address. */
1484 /* Prefetch scaled or unscaled zero- or sign-extended 32-bit register offset. */
1486 prfm_scale_ext (sim_cpu
*cpu
, Scaling scaling
, Extension extension
)
1488 /* instr[4,0] = prfop : 00000 ==> PLDL1KEEP, 00001 ==> PLDL1STRM,
1489 00010 ==> PLDL2KEEP, 00001 ==> PLDL2STRM,
1490 00100 ==> PLDL3KEEP, 00101 ==> PLDL3STRM,
1491 10000 ==> PSTL1KEEP, 10001 ==> PSTL1STRM,
1492 10010 ==> PSTL2KEEP, 10001 ==> PSTL2STRM,
1493 10100 ==> PSTL3KEEP, 10101 ==> PSTL3STRM,
1495 rn may reference SP, rm may only reference ZR
1496 PrfOp prfop = prfop (instr, 4, 0);
1497 uint64_t base = aarch64_get_reg_u64 (cpu, rn, SP_OK);
1498 int64_t extended = extend (aarch64_get_reg_u32 (cpu, rm, NO_SP),
1500 uint64_t displacement = OPT_SCALE (extended, 64, scaling);
1501 uint64_t address = base + displacement. */
1503 /* TODO : implement prefetch of address */
1506 /* 64 bit pc-relative prefetch. */
1508 prfm_pcrel (sim_cpu
*cpu
, int32_t offset
)
1510 /* instr[4,0] = prfop : 00000 ==> PLDL1KEEP, 00001 ==> PLDL1STRM,
1511 00010 ==> PLDL2KEEP, 00001 ==> PLDL2STRM,
1512 00100 ==> PLDL3KEEP, 00101 ==> PLDL3STRM,
1513 10000 ==> PSTL1KEEP, 10001 ==> PSTL1STRM,
1514 10010 ==> PSTL2KEEP, 10001 ==> PSTL2STRM,
1515 10100 ==> PSTL3KEEP, 10101 ==> PSTL3STRM,
1517 PrfOp prfop = prfop (instr, 4, 0);
1518 uint64_t address = aarch64_get_PC (cpu) + offset. */
1520 /* TODO : implement this */
1523 /* Load-store exclusive. */
1528 unsigned rn
= INSTR (9, 5);
1529 unsigned rt
= INSTR (4, 0);
1530 uint64_t address
= aarch64_get_reg_u64 (cpu
, rn
, SP_OK
);
1531 int size
= INSTR (31, 30);
1532 /* int ordered = INSTR (15, 15); */
1533 /* int exclusive = ! INSTR (23, 23); */
1535 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
1539 aarch64_set_reg_u64 (cpu
, rt
, NO_SP
, aarch64_get_mem_u8 (cpu
, address
));
1542 aarch64_set_reg_u64 (cpu
, rt
, NO_SP
, aarch64_get_mem_u16 (cpu
, address
));
1545 aarch64_set_reg_u64 (cpu
, rt
, NO_SP
, aarch64_get_mem_u32 (cpu
, address
));
1548 aarch64_set_reg_u64 (cpu
, rt
, NO_SP
, aarch64_get_mem_u64 (cpu
, address
));
1556 unsigned rn
= INSTR (9, 5);
1557 unsigned rt
= INSTR (4, 0);
1558 unsigned rs
= INSTR (20, 16);
1559 uint64_t address
= aarch64_get_reg_u64 (cpu
, rn
, SP_OK
);
1560 int size
= INSTR (31, 30);
1561 uint64_t data
= aarch64_get_reg_u64 (cpu
, rt
, NO_SP
);
1565 case 0: aarch64_set_mem_u8 (cpu
, address
, data
); break;
1566 case 1: aarch64_set_mem_u16 (cpu
, address
, data
); break;
1567 case 2: aarch64_set_mem_u32 (cpu
, address
, data
); break;
1568 case 3: aarch64_set_mem_u64 (cpu
, address
, data
); break;
1571 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
1572 aarch64_set_reg_u64 (cpu
, rs
, NO_SP
, 0); /* Always exclusive... */
1576 dexLoadLiteral (sim_cpu
*cpu
)
1578 /* instr[29,27] == 011
1580 instr[31,30:26] = opc: 000 ==> LDRW, 001 ==> FLDRS
1581 010 ==> LDRX, 011 ==> FLDRD
1582 100 ==> LDRSW, 101 ==> FLDRQ
1583 110 ==> PRFM, 111 ==> UNALLOC
1584 instr[26] ==> V : 0 ==> GReg, 1 ==> FReg
1585 instr[23, 5] == simm19 */
1587 /* unsigned rt = INSTR (4, 0); */
1588 uint32_t dispatch
= (INSTR (31, 30) << 1) | INSTR (26, 26);
1589 int32_t imm
= simm32 (aarch64_get_instr (cpu
), 23, 5);
1593 case 0: ldr32_pcrel (cpu
, imm
); break;
1594 case 1: fldrs_pcrel (cpu
, imm
); break;
1595 case 2: ldr_pcrel (cpu
, imm
); break;
1596 case 3: fldrd_pcrel (cpu
, imm
); break;
1597 case 4: ldrsw_pcrel (cpu
, imm
); break;
1598 case 5: fldrq_pcrel (cpu
, imm
); break;
1599 case 6: prfm_pcrel (cpu
, imm
); break;
1606 /* Immediate arithmetic
1607 The aimm argument is a 12 bit unsigned value or a 12 bit unsigned
1608 value left shifted by 12 bits (done at decode).
1610 N.B. the register args (dest, source) can normally be Xn or SP.
1611 the exception occurs for flag setting instructions which may
1612 only use Xn for the output (dest). */
1614 /* 32 bit add immediate. */
1616 add32 (sim_cpu
*cpu
, uint32_t aimm
)
1618 unsigned rn
= INSTR (9, 5);
1619 unsigned rd
= INSTR (4, 0);
1621 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
1622 aarch64_set_reg_u64 (cpu
, rd
, SP_OK
,
1623 aarch64_get_reg_u32 (cpu
, rn
, SP_OK
) + aimm
);
1626 /* 64 bit add immediate. */
1628 add64 (sim_cpu
*cpu
, uint32_t aimm
)
1630 unsigned rn
= INSTR (9, 5);
1631 unsigned rd
= INSTR (4, 0);
1633 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
1634 aarch64_set_reg_u64 (cpu
, rd
, SP_OK
,
1635 aarch64_get_reg_u64 (cpu
, rn
, SP_OK
) + aimm
);
1639 set_flags_for_add32 (sim_cpu
*cpu
, int32_t value1
, int32_t value2
)
1641 int32_t result
= value1
+ value2
;
1642 int64_t sresult
= (int64_t) value1
+ (int64_t) value2
;
1643 uint64_t uresult
= (uint64_t)(uint32_t) value1
1644 + (uint64_t)(uint32_t) value2
;
1650 if (result
& (1 << 31))
1653 if (uresult
!= result
)
1656 if (sresult
!= result
)
1659 aarch64_set_CPSR (cpu
, flags
);
1662 #define NEG(a) (((a) & signbit) == signbit)
1663 #define POS(a) (((a) & signbit) == 0)
1666 set_flags_for_add64 (sim_cpu
*cpu
, uint64_t value1
, uint64_t value2
)
1668 uint64_t result
= value1
+ value2
;
1670 uint64_t signbit
= 1ULL << 63;
1678 if ( (NEG (value1
) && NEG (value2
))
1679 || (NEG (value1
) && POS (result
))
1680 || (NEG (value2
) && POS (result
)))
1683 if ( (NEG (value1
) && NEG (value2
) && POS (result
))
1684 || (POS (value1
) && POS (value2
) && NEG (result
)))
1687 aarch64_set_CPSR (cpu
, flags
);
1691 set_flags_for_sub32 (sim_cpu
*cpu
, uint32_t value1
, uint32_t value2
)
1693 uint32_t result
= value1
- value2
;
1695 uint32_t signbit
= 1U << 31;
1703 if ( (NEG (value1
) && POS (value2
))
1704 || (NEG (value1
) && POS (result
))
1705 || (POS (value2
) && POS (result
)))
1708 if ( (NEG (value1
) && POS (value2
) && POS (result
))
1709 || (POS (value1
) && NEG (value2
) && NEG (result
)))
1712 aarch64_set_CPSR (cpu
, flags
);
1716 set_flags_for_sub64 (sim_cpu
*cpu
, uint64_t value1
, uint64_t value2
)
1718 uint64_t result
= value1
- value2
;
1720 uint64_t signbit
= 1ULL << 63;
1728 if ( (NEG (value1
) && POS (value2
))
1729 || (NEG (value1
) && POS (result
))
1730 || (POS (value2
) && POS (result
)))
1733 if ( (NEG (value1
) && POS (value2
) && POS (result
))
1734 || (POS (value1
) && NEG (value2
) && NEG (result
)))
1737 aarch64_set_CPSR (cpu
, flags
);
1741 set_flags_for_binop32 (sim_cpu
*cpu
, uint32_t result
)
1750 if (result
& (1 << 31))
1755 aarch64_set_CPSR (cpu
, flags
);
1759 set_flags_for_binop64 (sim_cpu
*cpu
, uint64_t result
)
1768 if (result
& (1ULL << 63))
1773 aarch64_set_CPSR (cpu
, flags
);
1776 /* 32 bit add immediate set flags. */
1778 adds32 (sim_cpu
*cpu
, uint32_t aimm
)
1780 unsigned rn
= INSTR (9, 5);
1781 unsigned rd
= INSTR (4, 0);
1782 /* TODO : do we need to worry about signs here? */
1783 int32_t value1
= aarch64_get_reg_s32 (cpu
, rn
, SP_OK
);
1785 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
1786 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, value1
+ aimm
);
1787 set_flags_for_add32 (cpu
, value1
, aimm
);
1790 /* 64 bit add immediate set flags. */
1792 adds64 (sim_cpu
*cpu
, uint32_t aimm
)
1794 unsigned rn
= INSTR (9, 5);
1795 unsigned rd
= INSTR (4, 0);
1796 uint64_t value1
= aarch64_get_reg_u64 (cpu
, rn
, SP_OK
);
1797 uint64_t value2
= aimm
;
1799 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
1800 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, value1
+ value2
);
1801 set_flags_for_add64 (cpu
, value1
, value2
);
1804 /* 32 bit sub immediate. */
1806 sub32 (sim_cpu
*cpu
, uint32_t aimm
)
1808 unsigned rn
= INSTR (9, 5);
1809 unsigned rd
= INSTR (4, 0);
1811 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
1812 aarch64_set_reg_u64 (cpu
, rd
, SP_OK
,
1813 aarch64_get_reg_u32 (cpu
, rn
, SP_OK
) - aimm
);
1816 /* 64 bit sub immediate. */
1818 sub64 (sim_cpu
*cpu
, uint32_t aimm
)
1820 unsigned rn
= INSTR (9, 5);
1821 unsigned rd
= INSTR (4, 0);
1823 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
1824 aarch64_set_reg_u64 (cpu
, rd
, SP_OK
,
1825 aarch64_get_reg_u64 (cpu
, rn
, SP_OK
) - aimm
);
1828 /* 32 bit sub immediate set flags. */
1830 subs32 (sim_cpu
*cpu
, uint32_t aimm
)
1832 unsigned rn
= INSTR (9, 5);
1833 unsigned rd
= INSTR (4, 0);
1834 uint32_t value1
= aarch64_get_reg_u64 (cpu
, rn
, SP_OK
);
1835 uint32_t value2
= aimm
;
1837 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
1838 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, value1
- value2
);
1839 set_flags_for_sub32 (cpu
, value1
, value2
);
1842 /* 64 bit sub immediate set flags. */
1844 subs64 (sim_cpu
*cpu
, uint32_t aimm
)
1846 unsigned rn
= INSTR (9, 5);
1847 unsigned rd
= INSTR (4, 0);
1848 uint64_t value1
= aarch64_get_reg_u64 (cpu
, rn
, SP_OK
);
1849 uint32_t value2
= aimm
;
1851 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
1852 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, value1
- value2
);
1853 set_flags_for_sub64 (cpu
, value1
, value2
);
1856 /* Data Processing Register. */
1858 /* First two helpers to perform the shift operations. */
1860 static inline uint32_t
1861 shifted32 (uint32_t value
, Shift shift
, uint32_t count
)
1867 return (value
<< count
);
1869 return (value
>> count
);
1872 int32_t svalue
= value
;
1873 return (svalue
>> count
);
1877 uint32_t top
= value
>> count
;
1878 uint32_t bottom
= value
<< (32 - count
);
1879 return (bottom
| top
);
1884 static inline uint64_t
1885 shifted64 (uint64_t value
, Shift shift
, uint32_t count
)
1891 return (value
<< count
);
1893 return (value
>> count
);
1896 int64_t svalue
= value
;
1897 return (svalue
>> count
);
1901 uint64_t top
= value
>> count
;
1902 uint64_t bottom
= value
<< (64 - count
);
1903 return (bottom
| top
);
1908 /* Arithmetic shifted register.
1909 These allow an optional LSL, ASR or LSR to the second source
1910 register with a count up to the register bit count.
1912 N.B register args may not be SP. */
1914 /* 32 bit ADD shifted register. */
1916 add32_shift (sim_cpu
*cpu
, Shift shift
, uint32_t count
)
1918 unsigned rm
= INSTR (20, 16);
1919 unsigned rn
= INSTR (9, 5);
1920 unsigned rd
= INSTR (4, 0);
1922 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
1923 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
,
1924 aarch64_get_reg_u32 (cpu
, rn
, NO_SP
)
1925 + shifted32 (aarch64_get_reg_u32 (cpu
, rm
, NO_SP
),
1929 /* 64 bit ADD shifted register. */
1931 add64_shift (sim_cpu
*cpu
, Shift shift
, uint32_t count
)
1933 unsigned rm
= INSTR (20, 16);
1934 unsigned rn
= INSTR (9, 5);
1935 unsigned rd
= INSTR (4, 0);
1937 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
1938 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
,
1939 aarch64_get_reg_u64 (cpu
, rn
, NO_SP
)
1940 + shifted64 (aarch64_get_reg_u64 (cpu
, rm
, NO_SP
),
1944 /* 32 bit ADD shifted register setting flags. */
1946 adds32_shift (sim_cpu
*cpu
, Shift shift
, uint32_t count
)
1948 unsigned rm
= INSTR (20, 16);
1949 unsigned rn
= INSTR (9, 5);
1950 unsigned rd
= INSTR (4, 0);
1952 uint32_t value1
= aarch64_get_reg_u32 (cpu
, rn
, NO_SP
);
1953 uint32_t value2
= shifted32 (aarch64_get_reg_u32 (cpu
, rm
, NO_SP
),
1956 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
1957 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, value1
+ value2
);
1958 set_flags_for_add32 (cpu
, value1
, value2
);
1961 /* 64 bit ADD shifted register setting flags. */
1963 adds64_shift (sim_cpu
*cpu
, Shift shift
, uint32_t count
)
1965 unsigned rm
= INSTR (20, 16);
1966 unsigned rn
= INSTR (9, 5);
1967 unsigned rd
= INSTR (4, 0);
1969 uint64_t value1
= aarch64_get_reg_u64 (cpu
, rn
, NO_SP
);
1970 uint64_t value2
= shifted64 (aarch64_get_reg_u64 (cpu
, rm
, NO_SP
),
1973 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
1974 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, value1
+ value2
);
1975 set_flags_for_add64 (cpu
, value1
, value2
);
1978 /* 32 bit SUB shifted register. */
1980 sub32_shift (sim_cpu
*cpu
, Shift shift
, uint32_t count
)
1982 unsigned rm
= INSTR (20, 16);
1983 unsigned rn
= INSTR (9, 5);
1984 unsigned rd
= INSTR (4, 0);
1986 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
1987 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
,
1988 aarch64_get_reg_u32 (cpu
, rn
, NO_SP
)
1989 - shifted32 (aarch64_get_reg_u32 (cpu
, rm
, NO_SP
),
1993 /* 64 bit SUB shifted register. */
1995 sub64_shift (sim_cpu
*cpu
, Shift shift
, uint32_t count
)
1997 unsigned rm
= INSTR (20, 16);
1998 unsigned rn
= INSTR (9, 5);
1999 unsigned rd
= INSTR (4, 0);
2001 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
2002 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
,
2003 aarch64_get_reg_u64 (cpu
, rn
, NO_SP
)
2004 - shifted64 (aarch64_get_reg_u64 (cpu
, rm
, NO_SP
),
2008 /* 32 bit SUB shifted register setting flags. */
2010 subs32_shift (sim_cpu
*cpu
, Shift shift
, uint32_t count
)
2012 unsigned rm
= INSTR (20, 16);
2013 unsigned rn
= INSTR (9, 5);
2014 unsigned rd
= INSTR (4, 0);
2016 uint32_t value1
= aarch64_get_reg_u32 (cpu
, rn
, NO_SP
);
2017 uint32_t value2
= shifted32 (aarch64_get_reg_u32 (cpu
, rm
, NO_SP
),
2020 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
2021 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, value1
- value2
);
2022 set_flags_for_sub32 (cpu
, value1
, value2
);
2025 /* 64 bit SUB shifted register setting flags. */
2027 subs64_shift (sim_cpu
*cpu
, Shift shift
, uint32_t count
)
2029 unsigned rm
= INSTR (20, 16);
2030 unsigned rn
= INSTR (9, 5);
2031 unsigned rd
= INSTR (4, 0);
2033 uint64_t value1
= aarch64_get_reg_u64 (cpu
, rn
, NO_SP
);
2034 uint64_t value2
= shifted64 (aarch64_get_reg_u64 (cpu
, rm
, NO_SP
),
2037 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
2038 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, value1
- value2
);
2039 set_flags_for_sub64 (cpu
, value1
, value2
);
2042 /* First a couple more helpers to fetch the
2043 relevant source register element either
2044 sign or zero extended as required by the
2048 extreg32 (sim_cpu
*cpu
, unsigned int lo
, Extension extension
)
2052 case UXTB
: return aarch64_get_reg_u8 (cpu
, lo
, NO_SP
);
2053 case UXTH
: return aarch64_get_reg_u16 (cpu
, lo
, NO_SP
);
2054 case UXTW
: /* Fall through. */
2055 case UXTX
: return aarch64_get_reg_u32 (cpu
, lo
, NO_SP
);
2056 case SXTB
: return aarch64_get_reg_s8 (cpu
, lo
, NO_SP
);
2057 case SXTH
: return aarch64_get_reg_s16 (cpu
, lo
, NO_SP
);
2058 case SXTW
: /* Fall through. */
2059 case SXTX
: /* Fall through. */
2060 default: return aarch64_get_reg_s32 (cpu
, lo
, NO_SP
);
2065 extreg64 (sim_cpu
*cpu
, unsigned int lo
, Extension extension
)
2069 case UXTB
: return aarch64_get_reg_u8 (cpu
, lo
, NO_SP
);
2070 case UXTH
: return aarch64_get_reg_u16 (cpu
, lo
, NO_SP
);
2071 case UXTW
: return aarch64_get_reg_u32 (cpu
, lo
, NO_SP
);
2072 case UXTX
: return aarch64_get_reg_u64 (cpu
, lo
, NO_SP
);
2073 case SXTB
: return aarch64_get_reg_s8 (cpu
, lo
, NO_SP
);
2074 case SXTH
: return aarch64_get_reg_s16 (cpu
, lo
, NO_SP
);
2075 case SXTW
: return aarch64_get_reg_s32 (cpu
, lo
, NO_SP
);
2077 default: return aarch64_get_reg_s64 (cpu
, lo
, NO_SP
);
2081 /* Arithmetic extending register
2082 These allow an optional sign extension of some portion of the
2083 second source register followed by an optional left shift of
2084 between 1 and 4 bits (i.e. a shift of 0-4 bits???)
2086 N.B output (dest) and first input arg (source) may normally be Xn
2087 or SP. However, for flag setting operations dest can only be
2088 Xn. Second input registers are always Xn. */
2090 /* 32 bit ADD extending register. */
2092 add32_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 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
2099 aarch64_set_reg_u64 (cpu
, rd
, SP_OK
,
2100 aarch64_get_reg_u32 (cpu
, rn
, SP_OK
)
2101 + (extreg32 (cpu
, rm
, extension
) << shift
));
2104 /* 64 bit ADD extending register.
2105 N.B. This subsumes the case with 64 bit source2 and UXTX #n or LSL #0. */
2107 add64_ext (sim_cpu
*cpu
, Extension extension
, uint32_t shift
)
2109 unsigned rm
= INSTR (20, 16);
2110 unsigned rn
= INSTR (9, 5);
2111 unsigned rd
= INSTR (4, 0);
2113 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
2114 aarch64_set_reg_u64 (cpu
, rd
, SP_OK
,
2115 aarch64_get_reg_u64 (cpu
, rn
, SP_OK
)
2116 + (extreg64 (cpu
, rm
, extension
) << shift
));
2119 /* 32 bit ADD extending register setting flags. */
2121 adds32_ext (sim_cpu
*cpu
, Extension extension
, uint32_t shift
)
2123 unsigned rm
= INSTR (20, 16);
2124 unsigned rn
= INSTR (9, 5);
2125 unsigned rd
= INSTR (4, 0);
2127 uint32_t value1
= aarch64_get_reg_u32 (cpu
, rn
, SP_OK
);
2128 uint32_t value2
= extreg32 (cpu
, rm
, extension
) << shift
;
2130 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
2131 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, value1
+ value2
);
2132 set_flags_for_add32 (cpu
, value1
, value2
);
2135 /* 64 bit ADD extending register setting flags */
2136 /* N.B. this subsumes the case with 64 bit source2 and UXTX #n or LSL #0 */
2138 adds64_ext (sim_cpu
*cpu
, Extension extension
, uint32_t shift
)
2140 unsigned rm
= INSTR (20, 16);
2141 unsigned rn
= INSTR (9, 5);
2142 unsigned rd
= INSTR (4, 0);
2144 uint64_t value1
= aarch64_get_reg_u64 (cpu
, rn
, SP_OK
);
2145 uint64_t value2
= extreg64 (cpu
, rm
, extension
) << shift
;
2147 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
2148 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, value1
+ value2
);
2149 set_flags_for_add64 (cpu
, value1
, value2
);
2152 /* 32 bit SUB extending register. */
2154 sub32_ext (sim_cpu
*cpu
, Extension extension
, uint32_t shift
)
2156 unsigned rm
= INSTR (20, 16);
2157 unsigned rn
= INSTR (9, 5);
2158 unsigned rd
= INSTR (4, 0);
2160 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
2161 aarch64_set_reg_u64 (cpu
, rd
, SP_OK
,
2162 aarch64_get_reg_u32 (cpu
, rn
, SP_OK
)
2163 - (extreg32 (cpu
, rm
, extension
) << shift
));
2166 /* 64 bit SUB extending register. */
2167 /* N.B. this subsumes the case with 64 bit source2 and UXTX #n or LSL #0. */
2169 sub64_ext (sim_cpu
*cpu
, Extension extension
, uint32_t shift
)
2171 unsigned rm
= INSTR (20, 16);
2172 unsigned rn
= INSTR (9, 5);
2173 unsigned rd
= INSTR (4, 0);
2175 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
2176 aarch64_set_reg_u64 (cpu
, rd
, SP_OK
,
2177 aarch64_get_reg_u64 (cpu
, rn
, SP_OK
)
2178 - (extreg64 (cpu
, rm
, extension
) << shift
));
2181 /* 32 bit SUB extending register setting flags. */
2183 subs32_ext (sim_cpu
*cpu
, Extension extension
, uint32_t shift
)
2185 unsigned rm
= INSTR (20, 16);
2186 unsigned rn
= INSTR (9, 5);
2187 unsigned rd
= INSTR (4, 0);
2189 uint32_t value1
= aarch64_get_reg_u32 (cpu
, rn
, SP_OK
);
2190 uint32_t value2
= extreg32 (cpu
, rm
, extension
) << shift
;
2192 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
2193 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, value1
- value2
);
2194 set_flags_for_sub32 (cpu
, value1
, value2
);
2197 /* 64 bit SUB extending register setting flags */
2198 /* N.B. this subsumes the case with 64 bit source2 and UXTX #n or LSL #0 */
2200 subs64_ext (sim_cpu
*cpu
, Extension extension
, uint32_t shift
)
2202 unsigned rm
= INSTR (20, 16);
2203 unsigned rn
= INSTR (9, 5);
2204 unsigned rd
= INSTR (4, 0);
2206 uint64_t value1
= aarch64_get_reg_u64 (cpu
, rn
, SP_OK
);
2207 uint64_t value2
= extreg64 (cpu
, rm
, extension
) << shift
;
2209 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
2210 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, value1
- value2
);
2211 set_flags_for_sub64 (cpu
, value1
, value2
);
2215 dexAddSubtractImmediate (sim_cpu
*cpu
)
2217 /* instr[31] = size : 0 ==> 32 bit, 1 ==> 64 bit
2218 instr[30] = op : 0 ==> ADD, 1 ==> SUB
2219 instr[29] = set : 0 ==> no flags, 1 ==> set flags
2220 instr[28,24] = 10001
2221 instr[23,22] = shift : 00 == LSL#0, 01 = LSL#12 1x = UNALLOC
2222 instr[21,10] = uimm12
2226 /* N.B. the shift is applied at decode before calling the add/sub routine. */
2227 uint32_t shift
= INSTR (23, 22);
2228 uint32_t imm
= INSTR (21, 10);
2229 uint32_t dispatch
= INSTR (31, 29);
2231 NYI_assert (28, 24, 0x11);
2241 case 0: add32 (cpu
, imm
); break;
2242 case 1: adds32 (cpu
, imm
); break;
2243 case 2: sub32 (cpu
, imm
); break;
2244 case 3: subs32 (cpu
, imm
); break;
2245 case 4: add64 (cpu
, imm
); break;
2246 case 5: adds64 (cpu
, imm
); break;
2247 case 6: sub64 (cpu
, imm
); break;
2248 case 7: subs64 (cpu
, imm
); break;
2253 dexAddSubtractShiftedRegister (sim_cpu
*cpu
)
2255 /* instr[31] = size : 0 ==> 32 bit, 1 ==> 64 bit
2256 instr[30,29] = op : 00 ==> ADD, 01 ==> ADDS, 10 ==> SUB, 11 ==> SUBS
2257 instr[28,24] = 01011
2258 instr[23,22] = shift : 0 ==> LSL, 1 ==> LSR, 2 ==> ASR, 3 ==> UNALLOC
2261 instr[15,10] = count : must be 0xxxxx for 32 bit
2265 uint32_t size
= INSTR (31, 31);
2266 uint32_t count
= INSTR (15, 10);
2267 Shift shiftType
= INSTR (23, 22);
2269 NYI_assert (28, 24, 0x0B);
2270 NYI_assert (21, 21, 0);
2272 /* Shift encoded as ROR is unallocated. */
2273 if (shiftType
== ROR
)
2276 /* 32 bit operations must have count[5] = 0
2277 or else we have an UNALLOC. */
2278 if (size
== 0 && uimm (count
, 5, 5))
2281 /* Dispatch on size:op i.e instr [31,29]. */
2282 switch (INSTR (31, 29))
2284 case 0: add32_shift (cpu
, shiftType
, count
); break;
2285 case 1: adds32_shift (cpu
, shiftType
, count
); break;
2286 case 2: sub32_shift (cpu
, shiftType
, count
); break;
2287 case 3: subs32_shift (cpu
, shiftType
, count
); break;
2288 case 4: add64_shift (cpu
, shiftType
, count
); break;
2289 case 5: adds64_shift (cpu
, shiftType
, count
); break;
2290 case 6: sub64_shift (cpu
, shiftType
, count
); break;
2291 case 7: subs64_shift (cpu
, shiftType
, count
); break;
2296 dexAddSubtractExtendedRegister (sim_cpu
*cpu
)
2298 /* instr[31] = size : 0 ==> 32 bit, 1 ==> 64 bit
2299 instr[30] = op : 0 ==> ADD, 1 ==> SUB
2300 instr[29] = set? : 0 ==> no flags, 1 ==> set flags
2301 instr[28,24] = 01011
2302 instr[23,22] = opt : 0 ==> ok, 1,2,3 ==> UNALLOC
2305 instr[15,13] = option : 000 ==> UXTB, 001 ==> UXTH,
2306 000 ==> LSL|UXTW, 001 ==> UXTZ,
2307 000 ==> SXTB, 001 ==> SXTH,
2308 000 ==> SXTW, 001 ==> SXTX,
2309 instr[12,10] = shift : 0,1,2,3,4 ==> ok, 5,6,7 ==> UNALLOC
2313 Extension extensionType
= INSTR (15, 13);
2314 uint32_t shift
= INSTR (12, 10);
2316 NYI_assert (28, 24, 0x0B);
2317 NYI_assert (21, 21, 1);
2319 /* Shift may not exceed 4. */
2323 /* Dispatch on size:op:set?. */
2324 switch (INSTR (31, 29))
2326 case 0: add32_ext (cpu
, extensionType
, shift
); break;
2327 case 1: adds32_ext (cpu
, extensionType
, shift
); break;
2328 case 2: sub32_ext (cpu
, extensionType
, shift
); break;
2329 case 3: subs32_ext (cpu
, extensionType
, shift
); break;
2330 case 4: add64_ext (cpu
, extensionType
, shift
); break;
2331 case 5: adds64_ext (cpu
, extensionType
, shift
); break;
2332 case 6: sub64_ext (cpu
, extensionType
, shift
); break;
2333 case 7: subs64_ext (cpu
, extensionType
, shift
); break;
2337 /* Conditional data processing
2338 Condition register is implicit 3rd source. */
2340 /* 32 bit add with carry. */
2341 /* N.B register args may not be SP. */
2344 adc32 (sim_cpu
*cpu
)
2346 unsigned rm
= INSTR (20, 16);
2347 unsigned rn
= INSTR (9, 5);
2348 unsigned rd
= INSTR (4, 0);
2350 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
2351 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
,
2352 aarch64_get_reg_u32 (cpu
, rn
, NO_SP
)
2353 + aarch64_get_reg_u32 (cpu
, rm
, NO_SP
)
2357 /* 64 bit add with carry */
2359 adc64 (sim_cpu
*cpu
)
2361 unsigned rm
= INSTR (20, 16);
2362 unsigned rn
= INSTR (9, 5);
2363 unsigned rd
= INSTR (4, 0);
2365 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
2366 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
,
2367 aarch64_get_reg_u64 (cpu
, rn
, NO_SP
)
2368 + aarch64_get_reg_u64 (cpu
, rm
, NO_SP
)
2372 /* 32 bit add with carry setting flags. */
2374 adcs32 (sim_cpu
*cpu
)
2376 unsigned rm
= INSTR (20, 16);
2377 unsigned rn
= INSTR (9, 5);
2378 unsigned rd
= INSTR (4, 0);
2380 uint32_t value1
= aarch64_get_reg_u32 (cpu
, rn
, NO_SP
);
2381 uint32_t value2
= aarch64_get_reg_u32 (cpu
, rm
, NO_SP
);
2382 uint32_t carry
= IS_SET (C
);
2384 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
2385 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, value1
+ value2
+ carry
);
2386 set_flags_for_add32 (cpu
, value1
, value2
+ carry
);
2389 /* 64 bit add with carry setting flags. */
2391 adcs64 (sim_cpu
*cpu
)
2393 unsigned rm
= INSTR (20, 16);
2394 unsigned rn
= INSTR (9, 5);
2395 unsigned rd
= INSTR (4, 0);
2397 uint64_t value1
= aarch64_get_reg_u64 (cpu
, rn
, NO_SP
);
2398 uint64_t value2
= aarch64_get_reg_u64 (cpu
, rm
, NO_SP
);
2399 uint64_t carry
= IS_SET (C
);
2401 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
2402 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, value1
+ value2
+ carry
);
2403 set_flags_for_add64 (cpu
, value1
, value2
+ carry
);
2406 /* 32 bit sub with carry. */
2408 sbc32 (sim_cpu
*cpu
)
2410 unsigned rm
= INSTR (20, 16);
2411 unsigned rn
= INSTR (9, 5); /* ngc iff rn == 31. */
2412 unsigned rd
= INSTR (4, 0);
2414 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
2415 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
,
2416 aarch64_get_reg_u32 (cpu
, rn
, NO_SP
)
2417 - aarch64_get_reg_u32 (cpu
, rm
, NO_SP
)
2421 /* 64 bit sub with carry */
2423 sbc64 (sim_cpu
*cpu
)
2425 unsigned rm
= INSTR (20, 16);
2426 unsigned rn
= INSTR (9, 5);
2427 unsigned rd
= INSTR (4, 0);
2429 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
2430 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
,
2431 aarch64_get_reg_u64 (cpu
, rn
, NO_SP
)
2432 - aarch64_get_reg_u64 (cpu
, rm
, NO_SP
)
2436 /* 32 bit sub with carry setting flags */
2438 sbcs32 (sim_cpu
*cpu
)
2440 unsigned rm
= INSTR (20, 16);
2441 unsigned rn
= INSTR (9, 5);
2442 unsigned rd
= INSTR (4, 0);
2444 uint32_t value1
= aarch64_get_reg_u32 (cpu
, rn
, NO_SP
);
2445 uint32_t value2
= aarch64_get_reg_u32 (cpu
, rm
, NO_SP
);
2446 uint32_t carry
= IS_SET (C
);
2447 uint32_t result
= value1
- value2
+ 1 - carry
;
2449 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
2450 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, result
);
2451 set_flags_for_sub32 (cpu
, value1
, value2
+ 1 - carry
);
2454 /* 64 bit sub with carry setting flags */
2456 sbcs64 (sim_cpu
*cpu
)
2458 unsigned rm
= INSTR (20, 16);
2459 unsigned rn
= INSTR (9, 5);
2460 unsigned rd
= INSTR (4, 0);
2462 uint64_t value1
= aarch64_get_reg_u64 (cpu
, rn
, NO_SP
);
2463 uint64_t value2
= aarch64_get_reg_u64 (cpu
, rm
, NO_SP
);
2464 uint64_t carry
= IS_SET (C
);
2465 uint64_t result
= value1
- value2
+ 1 - carry
;
2467 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
2468 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, result
);
2469 set_flags_for_sub64 (cpu
, value1
, value2
+ 1 - carry
);
2473 dexAddSubtractWithCarry (sim_cpu
*cpu
)
2475 /* instr[31] = size : 0 ==> 32 bit, 1 ==> 64 bit
2476 instr[30] = op : 0 ==> ADC, 1 ==> SBC
2477 instr[29] = set? : 0 ==> no flags, 1 ==> set flags
2478 instr[28,21] = 1 1010 000
2480 instr[15,10] = op2 : 00000 ==> ok, ow ==> UNALLOC
2484 uint32_t op2
= INSTR (15, 10);
2486 NYI_assert (28, 21, 0xD0);
2491 /* Dispatch on size:op:set?. */
2492 switch (INSTR (31, 29))
2494 case 0: adc32 (cpu
); break;
2495 case 1: adcs32 (cpu
); break;
2496 case 2: sbc32 (cpu
); break;
2497 case 3: sbcs32 (cpu
); break;
2498 case 4: adc64 (cpu
); break;
2499 case 5: adcs64 (cpu
); break;
2500 case 6: sbc64 (cpu
); break;
2501 case 7: sbcs64 (cpu
); break;
2506 testConditionCode (sim_cpu
*cpu
, CondCode cc
)
2508 /* This should be reduceable to branchless logic
2509 by some careful testing of bits in CC followed
2510 by the requisite masking and combining of bits
2511 from the flag register.
2513 For now we do it with a switch. */
2518 case EQ
: res
= IS_SET (Z
); break;
2519 case NE
: res
= IS_CLEAR (Z
); break;
2520 case CS
: res
= IS_SET (C
); break;
2521 case CC
: res
= IS_CLEAR (C
); break;
2522 case MI
: res
= IS_SET (N
); break;
2523 case PL
: res
= IS_CLEAR (N
); break;
2524 case VS
: res
= IS_SET (V
); break;
2525 case VC
: res
= IS_CLEAR (V
); break;
2526 case HI
: res
= IS_SET (C
) && IS_CLEAR (Z
); break;
2527 case LS
: res
= IS_CLEAR (C
) || IS_SET (Z
); break;
2528 case GE
: res
= IS_SET (N
) == IS_SET (V
); break;
2529 case LT
: res
= IS_SET (N
) != IS_SET (V
); break;
2530 case GT
: res
= IS_CLEAR (Z
) && (IS_SET (N
) == IS_SET (V
)); break;
2531 case LE
: res
= IS_SET (Z
) || (IS_SET (N
) != IS_SET (V
)); break;
2542 CondCompare (sim_cpu
*cpu
) /* aka: ccmp and ccmn */
2544 /* instr[31] = size : 0 ==> 32 bit, 1 ==> 64 bit
2545 instr[30] = compare with positive (1) or negative value (0)
2546 instr[29,21] = 1 1101 0010
2547 instr[20,16] = Rm or const
2549 instr[11] = compare reg (0) or const (1)
2553 instr[3,0] = value for CPSR bits if the comparison does not take place. */
2558 NYI_assert (29, 21, 0x1d2);
2559 NYI_assert (10, 10, 0);
2560 NYI_assert (4, 4, 0);
2562 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
2563 if (! testConditionCode (cpu
, INSTR (15, 12)))
2565 aarch64_set_CPSR (cpu
, INSTR (3, 0));
2569 negate
= INSTR (30, 30) ? 1 : -1;
2570 rm
= INSTR (20, 16);
2576 set_flags_for_sub64 (cpu
, aarch64_get_reg_u64 (cpu
, rn
, SP_OK
),
2577 negate
* (uint64_t) rm
);
2579 set_flags_for_sub64 (cpu
, aarch64_get_reg_u64 (cpu
, rn
, SP_OK
),
2580 negate
* aarch64_get_reg_u64 (cpu
, rm
, SP_OK
));
2585 set_flags_for_sub32 (cpu
, aarch64_get_reg_u32 (cpu
, rn
, SP_OK
),
2588 set_flags_for_sub32 (cpu
, aarch64_get_reg_u32 (cpu
, rn
, SP_OK
),
2589 negate
* aarch64_get_reg_u32 (cpu
, rm
, SP_OK
));
2594 do_vec_MOV_whole_vector (sim_cpu
*cpu
)
2596 /* MOV Vd.T, Vs.T (alias for ORR Vd.T, Vn.T, Vm.T where Vn == Vm)
2599 instr[30] = half(0)/full(1)
2600 instr[29,21] = 001110101
2602 instr[15,10] = 000111
2606 unsigned vs
= INSTR (9, 5);
2607 unsigned vd
= INSTR (4, 0);
2609 NYI_assert (29, 21, 0x075);
2610 NYI_assert (15, 10, 0x07);
2612 if (INSTR (20, 16) != vs
)
2615 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
2617 aarch64_set_vec_u64 (cpu
, vd
, 1, aarch64_get_vec_u64 (cpu
, vs
, 1));
2619 aarch64_set_vec_u64 (cpu
, vd
, 0, aarch64_get_vec_u64 (cpu
, vs
, 0));
2623 do_vec_MOV_into_scalar (sim_cpu
*cpu
)
2626 instr[30] = word(0)/long(1)
2627 instr[29,21] = 00 1110 000
2628 instr[20,18] = element size and index
2629 instr[17,10] = 00 0011 11
2630 instr[9,5] = V source
2631 instr[4,0] = R dest */
2633 unsigned vs
= INSTR (9, 5);
2634 unsigned rd
= INSTR (4, 0);
2636 NYI_assert (29, 21, 0x070);
2637 NYI_assert (17, 10, 0x0F);
2639 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
2640 switch (INSTR (20, 18))
2643 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, aarch64_get_vec_u64 (cpu
, vs
, 0));
2647 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, aarch64_get_vec_u64 (cpu
, vs
, 1));
2654 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, aarch64_get_vec_u32
2655 (cpu
, vs
, INSTR (20, 19)));
2664 do_vec_INS (sim_cpu
*cpu
)
2666 /* instr[31,21] = 01001110000
2667 instr[20,16] = element size and index
2668 instr[15,10] = 000111
2669 instr[9,5] = W source
2670 instr[4,0] = V dest */
2673 unsigned rs
= INSTR (9, 5);
2674 unsigned vd
= INSTR (4, 0);
2676 NYI_assert (31, 21, 0x270);
2677 NYI_assert (15, 10, 0x07);
2679 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
2682 index
= INSTR (20, 17);
2683 aarch64_set_vec_u8 (cpu
, vd
, index
,
2684 aarch64_get_reg_u8 (cpu
, rs
, NO_SP
));
2686 else if (INSTR (17, 17))
2688 index
= INSTR (20, 18);
2689 aarch64_set_vec_u16 (cpu
, vd
, index
,
2690 aarch64_get_reg_u16 (cpu
, rs
, NO_SP
));
2692 else if (INSTR (18, 18))
2694 index
= INSTR (20, 19);
2695 aarch64_set_vec_u32 (cpu
, vd
, index
,
2696 aarch64_get_reg_u32 (cpu
, rs
, NO_SP
));
2698 else if (INSTR (19, 19))
2700 index
= INSTR (20, 20);
2701 aarch64_set_vec_u64 (cpu
, vd
, index
,
2702 aarch64_get_reg_u64 (cpu
, rs
, NO_SP
));
2709 do_vec_DUP_vector_into_vector (sim_cpu
*cpu
)
2712 instr[30] = half(0)/full(1)
2713 instr[29,21] = 00 1110 000
2714 instr[20,16] = element size and index
2715 instr[15,10] = 0000 01
2716 instr[9,5] = V source
2717 instr[4,0] = V dest. */
2719 unsigned full
= INSTR (30, 30);
2720 unsigned vs
= INSTR (9, 5);
2721 unsigned vd
= INSTR (4, 0);
2724 NYI_assert (29, 21, 0x070);
2725 NYI_assert (15, 10, 0x01);
2727 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
2730 index
= INSTR (20, 17);
2732 for (i
= 0; i
< (full
? 16 : 8); i
++)
2733 aarch64_set_vec_u8 (cpu
, vd
, i
, aarch64_get_vec_u8 (cpu
, vs
, index
));
2735 else if (INSTR (17, 17))
2737 index
= INSTR (20, 18);
2739 for (i
= 0; i
< (full
? 8 : 4); i
++)
2740 aarch64_set_vec_u16 (cpu
, vd
, i
, aarch64_get_vec_u16 (cpu
, vs
, index
));
2742 else if (INSTR (18, 18))
2744 index
= INSTR (20, 19);
2746 for (i
= 0; i
< (full
? 4 : 2); i
++)
2747 aarch64_set_vec_u32 (cpu
, vd
, i
, aarch64_get_vec_u32 (cpu
, vs
, index
));
2751 if (INSTR (19, 19) == 0)
2757 index
= INSTR (20, 20);
2759 for (i
= 0; i
< 2; i
++)
2760 aarch64_set_vec_u64 (cpu
, vd
, i
, aarch64_get_vec_u64 (cpu
, vs
, index
));
2765 do_vec_TBL (sim_cpu
*cpu
)
2768 instr[30] = half(0)/full(1)
2769 instr[29,21] = 00 1110 000
2772 instr[14,13] = vec length
2774 instr[9,5] = V start
2775 instr[4,0] = V dest */
2777 int full
= INSTR (30, 30);
2778 int len
= INSTR (14, 13) + 1;
2779 unsigned vm
= INSTR (20, 16);
2780 unsigned vn
= INSTR (9, 5);
2781 unsigned vd
= INSTR (4, 0);
2784 NYI_assert (29, 21, 0x070);
2785 NYI_assert (12, 10, 0);
2787 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
2788 for (i
= 0; i
< (full
? 16 : 8); i
++)
2790 unsigned int selector
= aarch64_get_vec_u8 (cpu
, vm
, i
);
2794 val
= aarch64_get_vec_u8 (cpu
, vn
, selector
);
2795 else if (selector
< 32)
2796 val
= len
< 2 ? 0 : aarch64_get_vec_u8 (cpu
, vn
+ 1, selector
- 16);
2797 else if (selector
< 48)
2798 val
= len
< 3 ? 0 : aarch64_get_vec_u8 (cpu
, vn
+ 2, selector
- 32);
2799 else if (selector
< 64)
2800 val
= len
< 4 ? 0 : aarch64_get_vec_u8 (cpu
, vn
+ 3, selector
- 48);
2804 aarch64_set_vec_u8 (cpu
, vd
, i
, val
);
2809 do_vec_TRN (sim_cpu
*cpu
)
2812 instr[30] = half(0)/full(1)
2813 instr[29,24] = 00 1110
2818 instr[14] = TRN1 (0) / TRN2 (1)
2820 instr[9,5] = V source
2821 instr[4,0] = V dest. */
2823 int full
= INSTR (30, 30);
2824 int second
= INSTR (14, 14);
2825 unsigned vm
= INSTR (20, 16);
2826 unsigned vn
= INSTR (9, 5);
2827 unsigned vd
= INSTR (4, 0);
2830 NYI_assert (29, 24, 0x0E);
2831 NYI_assert (13, 10, 0xA);
2833 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
2834 switch (INSTR (23, 22))
2837 for (i
= 0; i
< (full
? 8 : 4); i
++)
2841 aarch64_get_vec_u8 (cpu
, second
? vm
: vn
, i
* 2));
2843 (cpu
, vd
, 1 * 2 + 1,
2844 aarch64_get_vec_u8 (cpu
, second
? vn
: vm
, i
* 2 + 1));
2849 for (i
= 0; i
< (full
? 4 : 2); i
++)
2853 aarch64_get_vec_u16 (cpu
, second
? vm
: vn
, i
* 2));
2855 (cpu
, vd
, 1 * 2 + 1,
2856 aarch64_get_vec_u16 (cpu
, second
? vn
: vm
, i
* 2 + 1));
2862 (cpu
, vd
, 0, aarch64_get_vec_u32 (cpu
, second
? vm
: vn
, 0));
2864 (cpu
, vd
, 1, aarch64_get_vec_u32 (cpu
, second
? vn
: vm
, 1));
2866 (cpu
, vd
, 2, aarch64_get_vec_u32 (cpu
, second
? vm
: vn
, 2));
2868 (cpu
, vd
, 3, aarch64_get_vec_u32 (cpu
, second
? vn
: vm
, 3));
2875 aarch64_set_vec_u64 (cpu
, vd
, 0,
2876 aarch64_get_vec_u64 (cpu
, second
? vm
: vn
, 0));
2877 aarch64_set_vec_u64 (cpu
, vd
, 1,
2878 aarch64_get_vec_u64 (cpu
, second
? vn
: vm
, 1));
2884 do_vec_DUP_scalar_into_vector (sim_cpu
*cpu
)
2887 instr[30] = 0=> zero top 64-bits, 1=> duplicate into top 64-bits
2888 [must be 1 for 64-bit xfer]
2889 instr[29,20] = 00 1110 0000
2890 instr[19,16] = element size: 0001=> 8-bits, 0010=> 16-bits,
2891 0100=> 32-bits. 1000=>64-bits
2892 instr[15,10] = 0000 11
2893 instr[9,5] = W source
2894 instr[4,0] = V dest. */
2897 unsigned Vd
= INSTR (4, 0);
2898 unsigned Rs
= INSTR (9, 5);
2899 int both
= INSTR (30, 30);
2901 NYI_assert (29, 20, 0x0E0);
2902 NYI_assert (15, 10, 0x03);
2904 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
2905 switch (INSTR (19, 16))
2908 for (i
= 0; i
< (both
? 16 : 8); i
++)
2909 aarch64_set_vec_u8 (cpu
, Vd
, i
, aarch64_get_reg_u8 (cpu
, Rs
, NO_SP
));
2913 for (i
= 0; i
< (both
? 8 : 4); i
++)
2914 aarch64_set_vec_u16 (cpu
, Vd
, i
, aarch64_get_reg_u16 (cpu
, Rs
, NO_SP
));
2918 for (i
= 0; i
< (both
? 4 : 2); i
++)
2919 aarch64_set_vec_u32 (cpu
, Vd
, i
, aarch64_get_reg_u32 (cpu
, Rs
, NO_SP
));
2925 aarch64_set_vec_u64 (cpu
, Vd
, 0, aarch64_get_reg_u64 (cpu
, Rs
, NO_SP
));
2926 aarch64_set_vec_u64 (cpu
, Vd
, 1, aarch64_get_reg_u64 (cpu
, Rs
, NO_SP
));
2935 do_vec_UZP (sim_cpu
*cpu
)
2938 instr[30] = half(0)/full(1)
2939 instr[29,24] = 00 1110
2940 instr[23,22] = size: byte(00), half(01), word (10), long (11)
2944 instr[14] = lower (0) / upper (1)
2949 int full
= INSTR (30, 30);
2950 int upper
= INSTR (14, 14);
2952 unsigned vm
= INSTR (20, 16);
2953 unsigned vn
= INSTR (9, 5);
2954 unsigned vd
= INSTR (4, 0);
2956 uint64_t val_m1
= aarch64_get_vec_u64 (cpu
, vm
, 0);
2957 uint64_t val_m2
= aarch64_get_vec_u64 (cpu
, vm
, 1);
2958 uint64_t val_n1
= aarch64_get_vec_u64 (cpu
, vn
, 0);
2959 uint64_t val_n2
= aarch64_get_vec_u64 (cpu
, vn
, 1);
2964 uint64_t input2
= full
? val_n2
: val_m1
;
2966 NYI_assert (29, 24, 0x0E);
2967 NYI_assert (21, 21, 0);
2968 NYI_assert (15, 15, 0);
2969 NYI_assert (13, 10, 6);
2971 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
2972 switch (INSTR (23, 22))
2975 val1
= (val_n1
>> (upper
* 8)) & 0xFFULL
;
2976 val1
|= (val_n1
>> ((upper
* 8) + 8)) & 0xFF00ULL
;
2977 val1
|= (val_n1
>> ((upper
* 8) + 16)) & 0xFF0000ULL
;
2978 val1
|= (val_n1
>> ((upper
* 8) + 24)) & 0xFF000000ULL
;
2980 val1
|= (input2
<< (32 - (upper
* 8))) & 0xFF00000000ULL
;
2981 val1
|= (input2
<< (24 - (upper
* 8))) & 0xFF0000000000ULL
;
2982 val1
|= (input2
<< (16 - (upper
* 8))) & 0xFF000000000000ULL
;
2983 val1
|= (input2
<< (8 - (upper
* 8))) & 0xFF00000000000000ULL
;
2987 val2
= (val_m1
>> (upper
* 8)) & 0xFFULL
;
2988 val2
|= (val_m1
>> ((upper
* 8) + 8)) & 0xFF00ULL
;
2989 val2
|= (val_m1
>> ((upper
* 8) + 16)) & 0xFF0000ULL
;
2990 val2
|= (val_m1
>> ((upper
* 8) + 24)) & 0xFF000000ULL
;
2992 val2
|= (val_m2
<< (32 - (upper
* 8))) & 0xFF00000000ULL
;
2993 val2
|= (val_m2
<< (24 - (upper
* 8))) & 0xFF0000000000ULL
;
2994 val2
|= (val_m2
<< (16 - (upper
* 8))) & 0xFF000000000000ULL
;
2995 val2
|= (val_m2
<< (8 - (upper
* 8))) & 0xFF00000000000000ULL
;
3000 val1
= (val_n1
>> (upper
* 16)) & 0xFFFFULL
;
3001 val1
|= (val_n1
>> ((upper
* 16) + 16)) & 0xFFFF0000ULL
;
3003 val1
|= (input2
<< (32 - (upper
* 16))) & 0xFFFF00000000ULL
;;
3004 val1
|= (input2
<< (16 - (upper
* 16))) & 0xFFFF000000000000ULL
;
3008 val2
= (val_m1
>> (upper
* 16)) & 0xFFFFULL
;
3009 val2
|= (val_m1
>> ((upper
* 16) + 16)) & 0xFFFF0000ULL
;
3011 val2
|= (val_m2
<< (32 - (upper
* 16))) & 0xFFFF00000000ULL
;
3012 val2
|= (val_m2
<< (16 - (upper
* 16))) & 0xFFFF000000000000ULL
;
3017 val1
= (val_n1
>> (upper
* 32)) & 0xFFFFFFFF;
3018 val1
|= (input2
<< (32 - (upper
* 32))) & 0xFFFFFFFF00000000ULL
;
3022 val2
= (val_m1
>> (upper
* 32)) & 0xFFFFFFFF;
3023 val2
|= (val_m2
<< (32 - (upper
* 32))) & 0xFFFFFFFF00000000ULL
;
3031 val1
= upper
? val_n2
: val_n1
;
3032 val2
= upper
? val_m2
: val_m1
;
3036 aarch64_set_vec_u64 (cpu
, vd
, 0, val1
);
3038 aarch64_set_vec_u64 (cpu
, vd
, 1, val2
);
3042 do_vec_ZIP (sim_cpu
*cpu
)
3045 instr[30] = half(0)/full(1)
3046 instr[29,24] = 00 1110
3047 instr[23,22] = size: byte(00), hald(01), word (10), long (11)
3051 instr[14] = lower (0) / upper (1)
3056 int full
= INSTR (30, 30);
3057 int upper
= INSTR (14, 14);
3059 unsigned vm
= INSTR (20, 16);
3060 unsigned vn
= INSTR (9, 5);
3061 unsigned vd
= INSTR (4, 0);
3063 uint64_t val_m1
= aarch64_get_vec_u64 (cpu
, vm
, 0);
3064 uint64_t val_m2
= aarch64_get_vec_u64 (cpu
, vm
, 1);
3065 uint64_t val_n1
= aarch64_get_vec_u64 (cpu
, vn
, 0);
3066 uint64_t val_n2
= aarch64_get_vec_u64 (cpu
, vn
, 1);
3071 uint64_t input1
= upper
? val_n1
: val_m1
;
3072 uint64_t input2
= upper
? val_n2
: val_m2
;
3074 NYI_assert (29, 24, 0x0E);
3075 NYI_assert (21, 21, 0);
3076 NYI_assert (15, 15, 0);
3077 NYI_assert (13, 10, 0xE);
3079 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
3080 switch (INSTR (23, 23))
3084 ((input1
<< 0) & (0xFF << 0))
3085 | ((input2
<< 8) & (0xFF << 8))
3086 | ((input1
<< 8) & (0xFF << 16))
3087 | ((input2
<< 16) & (0xFF << 24))
3088 | ((input1
<< 16) & (0xFFULL
<< 32))
3089 | ((input2
<< 24) & (0xFFULL
<< 40))
3090 | ((input1
<< 24) & (0xFFULL
<< 48))
3091 | ((input2
<< 32) & (0xFFULL
<< 56));
3094 ((input1
>> 32) & (0xFF << 0))
3095 | ((input2
>> 24) & (0xFF << 8))
3096 | ((input1
>> 24) & (0xFF << 16))
3097 | ((input2
>> 16) & (0xFF << 24))
3098 | ((input1
>> 16) & (0xFFULL
<< 32))
3099 | ((input2
>> 8) & (0xFFULL
<< 40))
3100 | ((input1
>> 8) & (0xFFULL
<< 48))
3101 | ((input2
>> 0) & (0xFFULL
<< 56));
3106 ((input1
<< 0) & (0xFFFF << 0))
3107 | ((input2
<< 16) & (0xFFFF << 16))
3108 | ((input1
<< 16) & (0xFFFFULL
<< 32))
3109 | ((input2
<< 32) & (0xFFFFULL
<< 48));
3112 ((input1
>> 32) & (0xFFFF << 0))
3113 | ((input2
>> 16) & (0xFFFF << 16))
3114 | ((input1
>> 16) & (0xFFFFULL
<< 32))
3115 | ((input2
>> 0) & (0xFFFFULL
<< 48));
3119 val1
= (input1
& 0xFFFFFFFFULL
) | (input2
<< 32);
3120 val2
= (input2
& 0xFFFFFFFFULL
) | (input1
<< 32);
3129 aarch64_set_vec_u64 (cpu
, vd
, 0, val1
);
3131 aarch64_set_vec_u64 (cpu
, vd
, 1, val2
);
3134 /* Floating point immediates are encoded in 8 bits.
3135 fpimm[7] = sign bit.
3136 fpimm[6:4] = signed exponent.
3137 fpimm[3:0] = fraction (assuming leading 1).
3138 i.e. F = s * 1.f * 2^(e - b). */
3141 fp_immediate_for_encoding_32 (uint32_t imm8
)
3144 uint32_t s
, e
, f
, i
;
3146 s
= (imm8
>> 7) & 0x1;
3147 e
= (imm8
>> 4) & 0x7;
3150 /* The fp value is s * n/16 * 2r where n is 16+e. */
3151 u
= (16.0 + f
) / 16.0;
3153 /* N.B. exponent is signed. */
3158 for (i
= 0; i
<= epos
; i
++)
3165 for (i
= 0; i
< eneg
; i
++)
3176 fp_immediate_for_encoding_64 (uint32_t imm8
)
3179 uint32_t s
, e
, f
, i
;
3181 s
= (imm8
>> 7) & 0x1;
3182 e
= (imm8
>> 4) & 0x7;
3185 /* The fp value is s * n/16 * 2r where n is 16+e. */
3186 u
= (16.0 + f
) / 16.0;
3188 /* N.B. exponent is signed. */
3193 for (i
= 0; i
<= epos
; i
++)
3200 for (i
= 0; i
< eneg
; i
++)
3211 do_vec_MOV_immediate (sim_cpu
*cpu
)
3214 instr[30] = full/half selector
3215 instr[29,19] = 00111100000
3216 instr[18,16] = high 3 bits of uimm8
3217 instr[15,12] = size & shift:
3219 0010 => 32-bit + LSL#8
3220 0100 => 32-bit + LSL#16
3221 0110 => 32-bit + LSL#24
3222 1010 => 16-bit + LSL#8
3224 1101 => 32-bit + MSL#16
3225 1100 => 32-bit + MSL#8
3229 instr[9,5] = low 5-bits of uimm8
3232 int full
= INSTR (30, 30);
3233 unsigned vd
= INSTR (4, 0);
3234 unsigned val
= (INSTR (18, 16) << 5) | INSTR (9, 5);
3237 NYI_assert (29, 19, 0x1E0);
3238 NYI_assert (11, 10, 1);
3240 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
3241 switch (INSTR (15, 12))
3243 case 0x0: /* 32-bit, no shift. */
3244 case 0x2: /* 32-bit, shift by 8. */
3245 case 0x4: /* 32-bit, shift by 16. */
3246 case 0x6: /* 32-bit, shift by 24. */
3247 val
<<= (8 * INSTR (14, 13));
3248 for (i
= 0; i
< (full
? 4 : 2); i
++)
3249 aarch64_set_vec_u32 (cpu
, vd
, i
, val
);
3252 case 0xa: /* 16-bit, shift by 8. */
3255 case 0x8: /* 16-bit, no shift. */
3256 for (i
= 0; i
< (full
? 8 : 4); i
++)
3257 aarch64_set_vec_u16 (cpu
, vd
, i
, val
);
3260 case 0xd: /* 32-bit, mask shift by 16. */
3264 case 0xc: /* 32-bit, mask shift by 8. */
3267 for (i
= 0; i
< (full
? 4 : 2); i
++)
3268 aarch64_set_vec_u32 (cpu
, vd
, i
, val
);
3271 case 0xe: /* 8-bit, no shift. */
3272 for (i
= 0; i
< (full
? 16 : 8); i
++)
3273 aarch64_set_vec_u8 (cpu
, vd
, i
, val
);
3276 case 0xf: /* FMOV Vs.{2|4}S, #fpimm. */
3278 float u
= fp_immediate_for_encoding_32 (val
);
3279 for (i
= 0; i
< (full
? 4 : 2); i
++)
3280 aarch64_set_vec_float (cpu
, vd
, i
, u
);
3290 do_vec_MVNI (sim_cpu
*cpu
)
3293 instr[30] = full/half selector
3294 instr[29,19] = 10111100000
3295 instr[18,16] = high 3 bits of uimm8
3296 instr[15,12] = selector
3298 instr[9,5] = low 5-bits of uimm8
3301 int full
= INSTR (30, 30);
3302 unsigned vd
= INSTR (4, 0);
3303 unsigned val
= (INSTR (18, 16) << 5) | INSTR (9, 5);
3306 NYI_assert (29, 19, 0x5E0);
3307 NYI_assert (11, 10, 1);
3309 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
3310 switch (INSTR (15, 12))
3312 case 0x0: /* 32-bit, no shift. */
3313 case 0x2: /* 32-bit, shift by 8. */
3314 case 0x4: /* 32-bit, shift by 16. */
3315 case 0x6: /* 32-bit, shift by 24. */
3316 val
<<= (8 * INSTR (14, 13));
3318 for (i
= 0; i
< (full
? 4 : 2); i
++)
3319 aarch64_set_vec_u32 (cpu
, vd
, i
, val
);
3322 case 0xa: /* 16-bit, 8 bit shift. */
3324 case 0x8: /* 16-bit, no shift. */
3326 for (i
= 0; i
< (full
? 8 : 4); i
++)
3327 aarch64_set_vec_u16 (cpu
, vd
, i
, val
);
3330 case 0xd: /* 32-bit, mask shift by 16. */
3333 case 0xc: /* 32-bit, mask shift by 8. */
3337 for (i
= 0; i
< (full
? 4 : 2); i
++)
3338 aarch64_set_vec_u32 (cpu
, vd
, i
, val
);
3341 case 0xE: /* MOVI Dn, #mask64 */
3345 for (i
= 0; i
< 8; i
++)
3347 mask
|= (0xFFUL
<< (i
* 8));
3348 aarch64_set_vec_u64 (cpu
, vd
, 0, mask
);
3349 aarch64_set_vec_u64 (cpu
, vd
, 1, mask
);
3353 case 0xf: /* FMOV Vd.2D, #fpimm. */
3355 double u
= fp_immediate_for_encoding_64 (val
);
3360 aarch64_set_vec_double (cpu
, vd
, 0, u
);
3361 aarch64_set_vec_double (cpu
, vd
, 1, u
);
3370 #define ABS(A) ((A) < 0 ? - (A) : (A))
3373 do_vec_ABS (sim_cpu
*cpu
)
3376 instr[30] = half(0)/full(1)
3377 instr[29,24] = 00 1110
3378 instr[23,22] = size: 00=> 8-bit, 01=> 16-bit, 10=> 32-bit, 11=> 64-bit
3379 instr[21,10] = 10 0000 1011 10
3383 unsigned vn
= INSTR (9, 5);
3384 unsigned vd
= INSTR (4, 0);
3385 unsigned full
= INSTR (30, 30);
3388 NYI_assert (29, 24, 0x0E);
3389 NYI_assert (21, 10, 0x82E);
3391 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
3392 switch (INSTR (23, 22))
3395 for (i
= 0; i
< (full
? 16 : 8); i
++)
3396 aarch64_set_vec_s8 (cpu
, vd
, i
,
3397 ABS (aarch64_get_vec_s8 (cpu
, vn
, i
)));
3401 for (i
= 0; i
< (full
? 8 : 4); i
++)
3402 aarch64_set_vec_s16 (cpu
, vd
, i
,
3403 ABS (aarch64_get_vec_s16 (cpu
, vn
, i
)));
3407 for (i
= 0; i
< (full
? 4 : 2); i
++)
3408 aarch64_set_vec_s32 (cpu
, vd
, i
,
3409 ABS (aarch64_get_vec_s32 (cpu
, vn
, i
)));
3415 for (i
= 0; i
< 2; i
++)
3416 aarch64_set_vec_s64 (cpu
, vd
, i
,
3417 ABS (aarch64_get_vec_s64 (cpu
, vn
, i
)));
3423 do_vec_ADDV (sim_cpu
*cpu
)
3426 instr[30] = full/half selector
3427 instr[29,24] = 00 1110
3428 instr[23,22] = size: 00=> 8-bit, 01=> 16-bit, 10=> 32-bit, 11=> 64-bit
3429 instr[21,10] = 11 0001 1011 10
3433 unsigned vm
= INSTR (9, 5);
3434 unsigned rd
= INSTR (4, 0);
3436 int full
= INSTR (30, 30);
3438 NYI_assert (29, 24, 0x0E);
3439 NYI_assert (21, 10, 0xC6E);
3441 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
3442 switch (INSTR (23, 22))
3447 for (i
= 0; i
< (full
? 16 : 8); i
++)
3448 val
+= aarch64_get_vec_u8 (cpu
, vm
, i
);
3449 aarch64_set_vec_u64 (cpu
, rd
, 0, val
);
3456 for (i
= 0; i
< (full
? 8 : 4); i
++)
3457 val
+= aarch64_get_vec_u16 (cpu
, vm
, i
);
3458 aarch64_set_vec_u64 (cpu
, rd
, 0, val
);
3467 for (i
= 0; i
< 4; i
++)
3468 val
+= aarch64_get_vec_u32 (cpu
, vm
, i
);
3469 aarch64_set_vec_u64 (cpu
, rd
, 0, val
);
3479 do_vec_ins_2 (sim_cpu
*cpu
)
3481 /* instr[31,21] = 01001110000
3482 instr[20,18] = size & element selector
3484 instr[13] = direction: to vec(0), from vec (1)
3490 unsigned vm
= INSTR (9, 5);
3491 unsigned vd
= INSTR (4, 0);
3493 NYI_assert (31, 21, 0x270);
3494 NYI_assert (17, 14, 0);
3495 NYI_assert (12, 10, 7);
3497 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
3498 if (INSTR (13, 13) == 1)
3500 if (INSTR (18, 18) == 1)
3503 elem
= INSTR (20, 19);
3504 aarch64_set_reg_u64 (cpu
, vd
, NO_SP
,
3505 aarch64_get_vec_u32 (cpu
, vm
, elem
));
3510 if (INSTR (19, 19) != 1)
3513 elem
= INSTR (20, 20);
3514 aarch64_set_reg_u64 (cpu
, vd
, NO_SP
,
3515 aarch64_get_vec_u64 (cpu
, vm
, elem
));
3520 if (INSTR (18, 18) == 1)
3523 elem
= INSTR (20, 19);
3524 aarch64_set_vec_u32 (cpu
, vd
, elem
,
3525 aarch64_get_reg_u32 (cpu
, vm
, NO_SP
));
3530 if (INSTR (19, 19) != 1)
3533 elem
= INSTR (20, 20);
3534 aarch64_set_vec_u64 (cpu
, vd
, elem
,
3535 aarch64_get_reg_u64 (cpu
, vm
, NO_SP
));
3540 #define DO_VEC_WIDENING_MUL(N, DST_TYPE, READ_TYPE, WRITE_TYPE) \
3543 DST_TYPE a[N], b[N]; \
3545 for (i = 0; i < (N); i++) \
3547 a[i] = aarch64_get_vec_##READ_TYPE (cpu, vn, i + bias); \
3548 b[i] = aarch64_get_vec_##READ_TYPE (cpu, vm, i + bias); \
3550 for (i = 0; i < (N); i++) \
3551 aarch64_set_vec_##WRITE_TYPE (cpu, vd, i, a[i] * b[i]); \
3556 do_vec_mull (sim_cpu
*cpu
)
3559 instr[30] = lower(0)/upper(1) selector
3560 instr[29] = signed(0)/unsigned(1)
3561 instr[28,24] = 0 1110
3562 instr[23,22] = size: 8-bit (00), 16-bit (01), 32-bit (10)
3565 instr[15,10] = 11 0000
3569 int unsign
= INSTR (29, 29);
3570 int bias
= INSTR (30, 30);
3571 unsigned vm
= INSTR (20, 16);
3572 unsigned vn
= INSTR ( 9, 5);
3573 unsigned vd
= INSTR ( 4, 0);
3576 NYI_assert (28, 24, 0x0E);
3577 NYI_assert (15, 10, 0x30);
3579 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
3580 /* NB: Read source values before writing results, in case
3581 the source and destination vectors are the same. */
3582 switch (INSTR (23, 22))
3588 DO_VEC_WIDENING_MUL (8, uint16_t, u8
, u16
);
3590 DO_VEC_WIDENING_MUL (8, int16_t, s8
, s16
);
3597 DO_VEC_WIDENING_MUL (4, uint32_t, u16
, u32
);
3599 DO_VEC_WIDENING_MUL (4, int32_t, s16
, s32
);
3606 DO_VEC_WIDENING_MUL (2, uint64_t, u32
, u64
);
3608 DO_VEC_WIDENING_MUL (2, int64_t, s32
, s64
);
3617 do_vec_fadd (sim_cpu
*cpu
)
3620 instr[30] = half(0)/full(1)
3621 instr[29,24] = 001110
3622 instr[23] = FADD(0)/FSUB(1)
3623 instr[22] = float (0)/double(1)
3626 instr[15,10] = 110101
3630 unsigned vm
= INSTR (20, 16);
3631 unsigned vn
= INSTR (9, 5);
3632 unsigned vd
= INSTR (4, 0);
3634 int full
= INSTR (30, 30);
3636 NYI_assert (29, 24, 0x0E);
3637 NYI_assert (21, 21, 1);
3638 NYI_assert (15, 10, 0x35);
3640 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
3648 for (i
= 0; i
< 2; i
++)
3649 aarch64_set_vec_double (cpu
, vd
, i
,
3650 aarch64_get_vec_double (cpu
, vn
, i
)
3651 - aarch64_get_vec_double (cpu
, vm
, i
));
3655 for (i
= 0; i
< (full
? 4 : 2); i
++)
3656 aarch64_set_vec_float (cpu
, vd
, i
,
3657 aarch64_get_vec_float (cpu
, vn
, i
)
3658 - aarch64_get_vec_float (cpu
, vm
, i
));
3668 for (i
= 0; i
< 2; i
++)
3669 aarch64_set_vec_double (cpu
, vd
, i
,
3670 aarch64_get_vec_double (cpu
, vm
, i
)
3671 + aarch64_get_vec_double (cpu
, vn
, i
));
3675 for (i
= 0; i
< (full
? 4 : 2); i
++)
3676 aarch64_set_vec_float (cpu
, vd
, i
,
3677 aarch64_get_vec_float (cpu
, vm
, i
)
3678 + aarch64_get_vec_float (cpu
, vn
, i
));
3684 do_vec_add (sim_cpu
*cpu
)
3687 instr[30] = full/half selector
3688 instr[29,24] = 001110
3689 instr[23,22] = size: 00=> 8-bit, 01=> 16-bit, 10=> 32-bit, 11=> 64-bit
3692 instr[15,10] = 100001
3696 unsigned vm
= INSTR (20, 16);
3697 unsigned vn
= INSTR (9, 5);
3698 unsigned vd
= INSTR (4, 0);
3700 int full
= INSTR (30, 30);
3702 NYI_assert (29, 24, 0x0E);
3703 NYI_assert (21, 21, 1);
3704 NYI_assert (15, 10, 0x21);
3706 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
3707 switch (INSTR (23, 22))
3710 for (i
= 0; i
< (full
? 16 : 8); i
++)
3711 aarch64_set_vec_u8 (cpu
, vd
, i
, aarch64_get_vec_u8 (cpu
, vn
, i
)
3712 + aarch64_get_vec_u8 (cpu
, vm
, i
));
3716 for (i
= 0; i
< (full
? 8 : 4); i
++)
3717 aarch64_set_vec_u16 (cpu
, vd
, i
, aarch64_get_vec_u16 (cpu
, vn
, i
)
3718 + aarch64_get_vec_u16 (cpu
, vm
, i
));
3722 for (i
= 0; i
< (full
? 4 : 2); i
++)
3723 aarch64_set_vec_u32 (cpu
, vd
, i
, aarch64_get_vec_u32 (cpu
, vn
, i
)
3724 + aarch64_get_vec_u32 (cpu
, vm
, i
));
3730 aarch64_set_vec_u64 (cpu
, vd
, 0, aarch64_get_vec_u64 (cpu
, vn
, 0)
3731 + aarch64_get_vec_u64 (cpu
, vm
, 0));
3732 aarch64_set_vec_u64 (cpu
, vd
, 1,
3733 aarch64_get_vec_u64 (cpu
, vn
, 1)
3734 + aarch64_get_vec_u64 (cpu
, vm
, 1));
3740 do_vec_mul (sim_cpu
*cpu
)
3743 instr[30] = full/half selector
3744 instr[29,24] = 00 1110
3745 instr[23,22] = size: 00=> 8-bit, 01=> 16-bit, 10=> 32-bit
3748 instr[15,10] = 10 0111
3752 unsigned vm
= INSTR (20, 16);
3753 unsigned vn
= INSTR (9, 5);
3754 unsigned vd
= INSTR (4, 0);
3756 int full
= INSTR (30, 30);
3759 NYI_assert (29, 24, 0x0E);
3760 NYI_assert (21, 21, 1);
3761 NYI_assert (15, 10, 0x27);
3763 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
3764 switch (INSTR (23, 22))
3767 DO_VEC_WIDENING_MUL (full
? 16 : 8, uint8_t, u8
, u8
);
3771 DO_VEC_WIDENING_MUL (full
? 8 : 4, uint16_t, u16
, u16
);
3775 DO_VEC_WIDENING_MUL (full
? 4 : 2, uint32_t, u32
, u32
);
3784 do_vec_MLA (sim_cpu
*cpu
)
3787 instr[30] = full/half selector
3788 instr[29,24] = 00 1110
3789 instr[23,22] = size: 00=> 8-bit, 01=> 16-bit, 10=> 32-bit
3792 instr[15,10] = 1001 01
3796 unsigned vm
= INSTR (20, 16);
3797 unsigned vn
= INSTR (9, 5);
3798 unsigned vd
= INSTR (4, 0);
3800 int full
= INSTR (30, 30);
3802 NYI_assert (29, 24, 0x0E);
3803 NYI_assert (21, 21, 1);
3804 NYI_assert (15, 10, 0x25);
3806 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
3807 switch (INSTR (23, 22))
3810 for (i
= 0; i
< (full
? 16 : 8); i
++)
3811 aarch64_set_vec_u8 (cpu
, vd
, i
,
3812 aarch64_get_vec_u8 (cpu
, vd
, i
)
3813 + (aarch64_get_vec_u8 (cpu
, vn
, i
)
3814 * aarch64_get_vec_u8 (cpu
, vm
, i
)));
3818 for (i
= 0; i
< (full
? 8 : 4); i
++)
3819 aarch64_set_vec_u16 (cpu
, vd
, i
,
3820 aarch64_get_vec_u16 (cpu
, vd
, i
)
3821 + (aarch64_get_vec_u16 (cpu
, vn
, i
)
3822 * aarch64_get_vec_u16 (cpu
, vm
, i
)));
3826 for (i
= 0; i
< (full
? 4 : 2); i
++)
3827 aarch64_set_vec_u32 (cpu
, vd
, i
,
3828 aarch64_get_vec_u32 (cpu
, vd
, i
)
3829 + (aarch64_get_vec_u32 (cpu
, vn
, i
)
3830 * aarch64_get_vec_u32 (cpu
, vm
, i
)));
3839 fmaxnm (float a
, float b
)
3844 return a
> b
? a
: b
;
3847 else if (! isnan (b
))
3853 fminnm (float a
, float b
)
3858 return a
< b
? a
: b
;
3861 else if (! isnan (b
))
3867 dmaxnm (double a
, double b
)
3872 return a
> b
? a
: b
;
3875 else if (! isnan (b
))
3881 dminnm (double a
, double b
)
3886 return a
< b
? a
: b
;
3889 else if (! isnan (b
))
3895 do_vec_FminmaxNMP (sim_cpu
*cpu
)
3898 instr [30] = half (0)/full (1)
3899 instr [29,24] = 10 1110
3900 instr [23] = max(0)/min(1)
3901 instr [22] = float (0)/double (1)
3904 instr [15,10] = 1100 01
3906 instr [4.0] = Vd. */
3908 unsigned vm
= INSTR (20, 16);
3909 unsigned vn
= INSTR (9, 5);
3910 unsigned vd
= INSTR (4, 0);
3911 int full
= INSTR (30, 30);
3913 NYI_assert (29, 24, 0x2E);
3914 NYI_assert (21, 21, 1);
3915 NYI_assert (15, 10, 0x31);
3917 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
3920 double (* fn
)(double, double) = INSTR (23, 23)
3925 aarch64_set_vec_double (cpu
, vd
, 0,
3926 fn (aarch64_get_vec_double (cpu
, vn
, 0),
3927 aarch64_get_vec_double (cpu
, vn
, 1)));
3928 aarch64_set_vec_double (cpu
, vd
, 0,
3929 fn (aarch64_get_vec_double (cpu
, vm
, 0),
3930 aarch64_get_vec_double (cpu
, vm
, 1)));
3934 float (* fn
)(float, float) = INSTR (23, 23)
3937 aarch64_set_vec_float (cpu
, vd
, 0,
3938 fn (aarch64_get_vec_float (cpu
, vn
, 0),
3939 aarch64_get_vec_float (cpu
, vn
, 1)));
3941 aarch64_set_vec_float (cpu
, vd
, 1,
3942 fn (aarch64_get_vec_float (cpu
, vn
, 2),
3943 aarch64_get_vec_float (cpu
, vn
, 3)));
3945 aarch64_set_vec_float (cpu
, vd
, (full
? 2 : 1),
3946 fn (aarch64_get_vec_float (cpu
, vm
, 0),
3947 aarch64_get_vec_float (cpu
, vm
, 1)));
3949 aarch64_set_vec_float (cpu
, vd
, 3,
3950 fn (aarch64_get_vec_float (cpu
, vm
, 2),
3951 aarch64_get_vec_float (cpu
, vm
, 3)));
3956 do_vec_AND (sim_cpu
*cpu
)
3959 instr[30] = half (0)/full (1)
3960 instr[29,21] = 001110001
3962 instr[15,10] = 000111
3966 unsigned vm
= INSTR (20, 16);
3967 unsigned vn
= INSTR (9, 5);
3968 unsigned vd
= INSTR (4, 0);
3970 int full
= INSTR (30, 30);
3972 NYI_assert (29, 21, 0x071);
3973 NYI_assert (15, 10, 0x07);
3975 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
3976 for (i
= 0; i
< (full
? 4 : 2); i
++)
3977 aarch64_set_vec_u32 (cpu
, vd
, i
,
3978 aarch64_get_vec_u32 (cpu
, vn
, i
)
3979 & aarch64_get_vec_u32 (cpu
, vm
, i
));
3983 do_vec_BSL (sim_cpu
*cpu
)
3986 instr[30] = half (0)/full (1)
3987 instr[29,21] = 101110011
3989 instr[15,10] = 000111
3993 unsigned vm
= INSTR (20, 16);
3994 unsigned vn
= INSTR (9, 5);
3995 unsigned vd
= INSTR (4, 0);
3997 int full
= INSTR (30, 30);
3999 NYI_assert (29, 21, 0x173);
4000 NYI_assert (15, 10, 0x07);
4002 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
4003 for (i
= 0; i
< (full
? 16 : 8); i
++)
4004 aarch64_set_vec_u8 (cpu
, vd
, i
,
4005 ( aarch64_get_vec_u8 (cpu
, vd
, i
)
4006 & aarch64_get_vec_u8 (cpu
, vn
, i
))
4007 | ((~ aarch64_get_vec_u8 (cpu
, vd
, i
))
4008 & aarch64_get_vec_u8 (cpu
, vm
, i
)));
4012 do_vec_EOR (sim_cpu
*cpu
)
4015 instr[30] = half (0)/full (1)
4016 instr[29,21] = 10 1110 001
4018 instr[15,10] = 000111
4022 unsigned vm
= INSTR (20, 16);
4023 unsigned vn
= INSTR (9, 5);
4024 unsigned vd
= INSTR (4, 0);
4026 int full
= INSTR (30, 30);
4028 NYI_assert (29, 21, 0x171);
4029 NYI_assert (15, 10, 0x07);
4031 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
4032 for (i
= 0; i
< (full
? 4 : 2); i
++)
4033 aarch64_set_vec_u32 (cpu
, vd
, i
,
4034 aarch64_get_vec_u32 (cpu
, vn
, i
)
4035 ^ aarch64_get_vec_u32 (cpu
, vm
, i
));
4039 do_vec_bit (sim_cpu
*cpu
)
4042 instr[30] = half (0)/full (1)
4043 instr[29,23] = 10 1110 1
4044 instr[22] = BIT (0) / BIF (1)
4047 instr[15,10] = 0001 11
4051 unsigned vm
= INSTR (20, 16);
4052 unsigned vn
= INSTR (9, 5);
4053 unsigned vd
= INSTR (4, 0);
4054 unsigned full
= INSTR (30, 30);
4055 unsigned test_false
= INSTR (22, 22);
4058 NYI_assert (29, 23, 0x5D);
4059 NYI_assert (21, 21, 1);
4060 NYI_assert (15, 10, 0x07);
4062 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
4063 for (i
= 0; i
< (full
? 4 : 2); i
++)
4065 uint32_t vd_val
= aarch64_get_vec_u32 (cpu
, vd
, i
);
4066 uint32_t vn_val
= aarch64_get_vec_u32 (cpu
, vn
, i
);
4067 uint32_t vm_val
= aarch64_get_vec_u32 (cpu
, vm
, i
);
4069 aarch64_set_vec_u32 (cpu
, vd
, i
,
4070 (vd_val
& vm_val
) | (vn_val
& ~vm_val
));
4072 aarch64_set_vec_u32 (cpu
, vd
, i
,
4073 (vd_val
& ~vm_val
) | (vn_val
& vm_val
));
4078 do_vec_ORN (sim_cpu
*cpu
)
4081 instr[30] = half (0)/full (1)
4082 instr[29,21] = 00 1110 111
4084 instr[15,10] = 00 0111
4088 unsigned vm
= INSTR (20, 16);
4089 unsigned vn
= INSTR (9, 5);
4090 unsigned vd
= INSTR (4, 0);
4092 int full
= INSTR (30, 30);
4094 NYI_assert (29, 21, 0x077);
4095 NYI_assert (15, 10, 0x07);
4097 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
4098 for (i
= 0; i
< (full
? 16 : 8); i
++)
4099 aarch64_set_vec_u8 (cpu
, vd
, i
,
4100 aarch64_get_vec_u8 (cpu
, vn
, i
)
4101 | ~ aarch64_get_vec_u8 (cpu
, vm
, i
));
4105 do_vec_ORR (sim_cpu
*cpu
)
4108 instr[30] = half (0)/full (1)
4109 instr[29,21] = 00 1110 101
4111 instr[15,10] = 0001 11
4115 unsigned vm
= INSTR (20, 16);
4116 unsigned vn
= INSTR (9, 5);
4117 unsigned vd
= INSTR (4, 0);
4119 int full
= INSTR (30, 30);
4121 NYI_assert (29, 21, 0x075);
4122 NYI_assert (15, 10, 0x07);
4124 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
4125 for (i
= 0; i
< (full
? 16 : 8); i
++)
4126 aarch64_set_vec_u8 (cpu
, vd
, i
,
4127 aarch64_get_vec_u8 (cpu
, vn
, i
)
4128 | aarch64_get_vec_u8 (cpu
, vm
, i
));
4132 do_vec_BIC (sim_cpu
*cpu
)
4135 instr[30] = half (0)/full (1)
4136 instr[29,21] = 00 1110 011
4138 instr[15,10] = 00 0111
4142 unsigned vm
= INSTR (20, 16);
4143 unsigned vn
= INSTR (9, 5);
4144 unsigned vd
= INSTR (4, 0);
4146 int full
= INSTR (30, 30);
4148 NYI_assert (29, 21, 0x073);
4149 NYI_assert (15, 10, 0x07);
4151 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
4152 for (i
= 0; i
< (full
? 16 : 8); i
++)
4153 aarch64_set_vec_u8 (cpu
, vd
, i
,
4154 aarch64_get_vec_u8 (cpu
, vn
, i
)
4155 & ~ aarch64_get_vec_u8 (cpu
, vm
, i
));
4159 do_vec_XTN (sim_cpu
*cpu
)
4162 instr[30] = first part (0)/ second part (1)
4163 instr[29,24] = 00 1110
4164 instr[23,22] = size: byte(00), half(01), word (10)
4165 instr[21,10] = 1000 0100 1010
4169 unsigned vs
= INSTR (9, 5);
4170 unsigned vd
= INSTR (4, 0);
4171 unsigned bias
= INSTR (30, 30);
4174 NYI_assert (29, 24, 0x0E);
4175 NYI_assert (21, 10, 0x84A);
4177 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
4178 switch (INSTR (23, 22))
4181 for (i
= 0; i
< 8; i
++)
4182 aarch64_set_vec_u8 (cpu
, vd
, i
+ (bias
* 8),
4183 aarch64_get_vec_u16 (cpu
, vs
, i
));
4187 for (i
= 0; i
< 4; i
++)
4188 aarch64_set_vec_u16 (cpu
, vd
, i
+ (bias
* 4),
4189 aarch64_get_vec_u32 (cpu
, vs
, i
));
4193 for (i
= 0; i
< 2; i
++)
4194 aarch64_set_vec_u32 (cpu
, vd
, i
+ (bias
* 2),
4195 aarch64_get_vec_u64 (cpu
, vs
, i
));
4200 /* Return the number of bits set in the input value. */
4201 #if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4)
4202 # define popcount __builtin_popcount
4205 popcount (unsigned char x
)
4207 static const unsigned char popcnt
[16] =
4215 /* Only counts the low 8 bits of the input as that is all we need. */
4216 return popcnt
[x
% 16] + popcnt
[x
/ 16];
4221 do_vec_CNT (sim_cpu
*cpu
)
4224 instr[30] = half (0)/ full (1)
4225 instr[29,24] = 00 1110
4226 instr[23,22] = size: byte(00)
4227 instr[21,10] = 1000 0001 0110
4231 unsigned vs
= INSTR (9, 5);
4232 unsigned vd
= INSTR (4, 0);
4233 int full
= INSTR (30, 30);
4234 int size
= INSTR (23, 22);
4237 NYI_assert (29, 24, 0x0E);
4238 NYI_assert (21, 10, 0x816);
4243 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
4245 for (i
= 0; i
< (full
? 16 : 8); i
++)
4246 aarch64_set_vec_u8 (cpu
, vd
, i
,
4247 popcount (aarch64_get_vec_u8 (cpu
, vs
, i
)));
4251 do_vec_maxv (sim_cpu
*cpu
)
4254 instr[30] = half(0)/full(1)
4255 instr[29] = signed (0)/unsigned(1)
4256 instr[28,24] = 0 1110
4257 instr[23,22] = size: byte(00), half(01), word (10)
4259 instr[20,17] = 1 000
4260 instr[16] = max(0)/min(1)
4261 instr[15,10] = 1010 10
4262 instr[9,5] = V source
4263 instr[4.0] = R dest. */
4265 unsigned vs
= INSTR (9, 5);
4266 unsigned rd
= INSTR (4, 0);
4267 unsigned full
= INSTR (30, 30);
4270 NYI_assert (28, 24, 0x0E);
4271 NYI_assert (21, 21, 1);
4272 NYI_assert (20, 17, 8);
4273 NYI_assert (15, 10, 0x2A);
4275 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
4276 switch ((INSTR (29, 29) << 1) | INSTR (16, 16))
4278 case 0: /* SMAXV. */
4281 switch (INSTR (23, 22))
4284 smax
= aarch64_get_vec_s8 (cpu
, vs
, 0);
4285 for (i
= 1; i
< (full
? 16 : 8); i
++)
4286 smax
= max (smax
, aarch64_get_vec_s8 (cpu
, vs
, i
));
4289 smax
= aarch64_get_vec_s16 (cpu
, vs
, 0);
4290 for (i
= 1; i
< (full
? 8 : 4); i
++)
4291 smax
= max (smax
, aarch64_get_vec_s16 (cpu
, vs
, i
));
4294 smax
= aarch64_get_vec_s32 (cpu
, vs
, 0);
4295 for (i
= 1; i
< (full
? 4 : 2); i
++)
4296 smax
= max (smax
, aarch64_get_vec_s32 (cpu
, vs
, i
));
4301 aarch64_set_reg_s64 (cpu
, rd
, NO_SP
, smax
);
4305 case 1: /* SMINV. */
4308 switch (INSTR (23, 22))
4311 smin
= aarch64_get_vec_s8 (cpu
, vs
, 0);
4312 for (i
= 1; i
< (full
? 16 : 8); i
++)
4313 smin
= min (smin
, aarch64_get_vec_s8 (cpu
, vs
, i
));
4316 smin
= aarch64_get_vec_s16 (cpu
, vs
, 0);
4317 for (i
= 1; i
< (full
? 8 : 4); i
++)
4318 smin
= min (smin
, aarch64_get_vec_s16 (cpu
, vs
, i
));
4321 smin
= aarch64_get_vec_s32 (cpu
, vs
, 0);
4322 for (i
= 1; i
< (full
? 4 : 2); i
++)
4323 smin
= min (smin
, aarch64_get_vec_s32 (cpu
, vs
, i
));
4329 aarch64_set_reg_s64 (cpu
, rd
, NO_SP
, smin
);
4333 case 2: /* UMAXV. */
4336 switch (INSTR (23, 22))
4339 umax
= aarch64_get_vec_u8 (cpu
, vs
, 0);
4340 for (i
= 1; i
< (full
? 16 : 8); i
++)
4341 umax
= max (umax
, aarch64_get_vec_u8 (cpu
, vs
, i
));
4344 umax
= aarch64_get_vec_u16 (cpu
, vs
, 0);
4345 for (i
= 1; i
< (full
? 8 : 4); i
++)
4346 umax
= max (umax
, aarch64_get_vec_u16 (cpu
, vs
, i
));
4349 umax
= aarch64_get_vec_u32 (cpu
, vs
, 0);
4350 for (i
= 1; i
< (full
? 4 : 2); i
++)
4351 umax
= max (umax
, aarch64_get_vec_u32 (cpu
, vs
, i
));
4357 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, umax
);
4361 case 3: /* UMINV. */
4364 switch (INSTR (23, 22))
4367 umin
= aarch64_get_vec_u8 (cpu
, vs
, 0);
4368 for (i
= 1; i
< (full
? 16 : 8); i
++)
4369 umin
= min (umin
, aarch64_get_vec_u8 (cpu
, vs
, i
));
4372 umin
= aarch64_get_vec_u16 (cpu
, vs
, 0);
4373 for (i
= 1; i
< (full
? 8 : 4); i
++)
4374 umin
= min (umin
, aarch64_get_vec_u16 (cpu
, vs
, i
));
4377 umin
= aarch64_get_vec_u32 (cpu
, vs
, 0);
4378 for (i
= 1; i
< (full
? 4 : 2); i
++)
4379 umin
= min (umin
, aarch64_get_vec_u32 (cpu
, vs
, i
));
4385 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, umin
);
4392 do_vec_fminmaxV (sim_cpu
*cpu
)
4394 /* instr[31,24] = 0110 1110
4395 instr[23] = max(0)/min(1)
4396 instr[22,14] = 011 0000 11
4397 instr[13,12] = nm(00)/normal(11)
4399 instr[9,5] = V source
4400 instr[4.0] = R dest. */
4402 unsigned vs
= INSTR (9, 5);
4403 unsigned rd
= INSTR (4, 0);
4405 float res
= aarch64_get_vec_float (cpu
, vs
, 0);
4407 NYI_assert (31, 24, 0x6E);
4408 NYI_assert (22, 14, 0x0C3);
4409 NYI_assert (11, 10, 2);
4411 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
4414 switch (INSTR (13, 12))
4416 case 0: /* FMNINNMV. */
4417 for (i
= 1; i
< 4; i
++)
4418 res
= fminnm (res
, aarch64_get_vec_float (cpu
, vs
, i
));
4421 case 3: /* FMINV. */
4422 for (i
= 1; i
< 4; i
++)
4423 res
= min (res
, aarch64_get_vec_float (cpu
, vs
, i
));
4432 switch (INSTR (13, 12))
4434 case 0: /* FMNAXNMV. */
4435 for (i
= 1; i
< 4; i
++)
4436 res
= fmaxnm (res
, aarch64_get_vec_float (cpu
, vs
, i
));
4439 case 3: /* FMAXV. */
4440 for (i
= 1; i
< 4; i
++)
4441 res
= max (res
, aarch64_get_vec_float (cpu
, vs
, i
));
4449 aarch64_set_FP_float (cpu
, rd
, res
);
4453 do_vec_Fminmax (sim_cpu
*cpu
)
4456 instr[30] = half(0)/full(1)
4457 instr[29,24] = 00 1110
4458 instr[23] = max(0)/min(1)
4459 instr[22] = float(0)/double(1)
4463 instr[13,12] = nm(00)/normal(11)
4468 unsigned vm
= INSTR (20, 16);
4469 unsigned vn
= INSTR (9, 5);
4470 unsigned vd
= INSTR (4, 0);
4471 unsigned full
= INSTR (30, 30);
4472 unsigned min
= INSTR (23, 23);
4475 NYI_assert (29, 24, 0x0E);
4476 NYI_assert (21, 21, 1);
4477 NYI_assert (15, 14, 3);
4478 NYI_assert (11, 10, 1);
4480 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
4483 double (* func
)(double, double);
4488 if (INSTR (13, 12) == 0)
4489 func
= min
? dminnm
: dmaxnm
;
4490 else if (INSTR (13, 12) == 3)
4491 func
= min
? fmin
: fmax
;
4495 for (i
= 0; i
< 2; i
++)
4496 aarch64_set_vec_double (cpu
, vd
, i
,
4497 func (aarch64_get_vec_double (cpu
, vn
, i
),
4498 aarch64_get_vec_double (cpu
, vm
, i
)));
4502 float (* func
)(float, float);
4504 if (INSTR (13, 12) == 0)
4505 func
= min
? fminnm
: fmaxnm
;
4506 else if (INSTR (13, 12) == 3)
4507 func
= min
? fminf
: fmaxf
;
4511 for (i
= 0; i
< (full
? 4 : 2); i
++)
4512 aarch64_set_vec_float (cpu
, vd
, i
,
4513 func (aarch64_get_vec_float (cpu
, vn
, i
),
4514 aarch64_get_vec_float (cpu
, vm
, i
)));
4519 do_vec_SCVTF (sim_cpu
*cpu
)
4523 instr[29,23] = 00 1110 0
4524 instr[22] = float(0)/double(1)
4525 instr[21,10] = 10 0001 1101 10
4529 unsigned vn
= INSTR (9, 5);
4530 unsigned vd
= INSTR (4, 0);
4531 unsigned full
= INSTR (30, 30);
4532 unsigned size
= INSTR (22, 22);
4535 NYI_assert (29, 23, 0x1C);
4536 NYI_assert (21, 10, 0x876);
4538 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
4544 for (i
= 0; i
< 2; i
++)
4546 double val
= (double) aarch64_get_vec_u64 (cpu
, vn
, i
);
4547 aarch64_set_vec_double (cpu
, vd
, i
, val
);
4552 for (i
= 0; i
< (full
? 4 : 2); i
++)
4554 float val
= (float) aarch64_get_vec_u32 (cpu
, vn
, i
);
4555 aarch64_set_vec_float (cpu
, vd
, i
, val
);
4560 #define VEC_CMP(SOURCE, CMP) \
4566 for (i = 0; i < (full ? 16 : 8); i++) \
4567 aarch64_set_vec_u8 (cpu, vd, i, \
4568 aarch64_get_vec_##SOURCE##8 (cpu, vn, i) \
4570 aarch64_get_vec_##SOURCE##8 (cpu, vm, i) \
4574 for (i = 0; i < (full ? 8 : 4); i++) \
4575 aarch64_set_vec_u16 (cpu, vd, i, \
4576 aarch64_get_vec_##SOURCE##16 (cpu, vn, i) \
4578 aarch64_get_vec_##SOURCE##16 (cpu, vm, i) \
4582 for (i = 0; i < (full ? 4 : 2); i++) \
4583 aarch64_set_vec_u32 (cpu, vd, i, \
4584 aarch64_get_vec_##SOURCE##32 (cpu, vn, i) \
4586 aarch64_get_vec_##SOURCE##32 (cpu, vm, i) \
4592 for (i = 0; i < 2; i++) \
4593 aarch64_set_vec_u64 (cpu, vd, i, \
4594 aarch64_get_vec_##SOURCE##64 (cpu, vn, i) \
4596 aarch64_get_vec_##SOURCE##64 (cpu, vm, i) \
4603 #define VEC_CMP0(SOURCE, CMP) \
4609 for (i = 0; i < (full ? 16 : 8); i++) \
4610 aarch64_set_vec_u8 (cpu, vd, i, \
4611 aarch64_get_vec_##SOURCE##8 (cpu, vn, i) \
4615 for (i = 0; i < (full ? 8 : 4); i++) \
4616 aarch64_set_vec_u16 (cpu, vd, i, \
4617 aarch64_get_vec_##SOURCE##16 (cpu, vn, i) \
4621 for (i = 0; i < (full ? 4 : 2); i++) \
4622 aarch64_set_vec_u32 (cpu, vd, i, \
4623 aarch64_get_vec_##SOURCE##32 (cpu, vn, i) \
4629 for (i = 0; i < 2; i++) \
4630 aarch64_set_vec_u64 (cpu, vd, i, \
4631 aarch64_get_vec_##SOURCE##64 (cpu, vn, i) \
4632 CMP 0 ? -1ULL : 0); \
4638 #define VEC_FCMP0(CMP) \
4643 if (INSTR (22, 22)) \
4647 for (i = 0; i < 2; i++) \
4648 aarch64_set_vec_u64 (cpu, vd, i, \
4649 aarch64_get_vec_double (cpu, vn, i) \
4650 CMP 0.0 ? -1 : 0); \
4654 for (i = 0; i < (full ? 4 : 2); i++) \
4655 aarch64_set_vec_u32 (cpu, vd, i, \
4656 aarch64_get_vec_float (cpu, vn, i) \
4657 CMP 0.0 ? -1 : 0); \
4663 #define VEC_FCMP(CMP) \
4666 if (INSTR (22, 22)) \
4670 for (i = 0; i < 2; i++) \
4671 aarch64_set_vec_u64 (cpu, vd, i, \
4672 aarch64_get_vec_double (cpu, vn, i) \
4674 aarch64_get_vec_double (cpu, vm, i) \
4679 for (i = 0; i < (full ? 4 : 2); i++) \
4680 aarch64_set_vec_u32 (cpu, vd, i, \
4681 aarch64_get_vec_float (cpu, vn, i) \
4683 aarch64_get_vec_float (cpu, vm, i) \
4691 do_vec_compare (sim_cpu
*cpu
)
4694 instr[30] = half(0)/full(1)
4695 instr[29] = part-of-comparison-type
4696 instr[28,24] = 0 1110
4697 instr[23,22] = size of integer compares: byte(00), half(01), word (10), long (11)
4698 type of float compares: single (-0) / double (-1)
4700 instr[20,16] = Vm or 00000 (compare vs 0)
4701 instr[15,10] = part-of-comparison-type
4705 int full
= INSTR (30, 30);
4706 int size
= INSTR (23, 22);
4707 unsigned vm
= INSTR (20, 16);
4708 unsigned vn
= INSTR (9, 5);
4709 unsigned vd
= INSTR (4, 0);
4712 NYI_assert (28, 24, 0x0E);
4713 NYI_assert (21, 21, 1);
4715 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
4718 || ((INSTR (11, 11) == 0
4719 && INSTR (10, 10) == 0)))
4721 /* A compare vs 0. */
4724 if (INSTR (15, 10) == 0x2A)
4726 else if (INSTR (15, 10) == 0x32
4727 || INSTR (15, 10) == 0x3E)
4728 do_vec_fminmaxV (cpu
);
4729 else if (INSTR (29, 23) == 0x1C
4730 && INSTR (21, 10) == 0x876)
4740 /* A floating point compare. */
4741 unsigned decode
= (INSTR (29, 29) << 5) | (INSTR (23, 23) << 4)
4744 NYI_assert (15, 15, 1);
4748 case /* 0b010010: GT#0 */ 0x12: VEC_FCMP0 (>);
4749 case /* 0b110010: GE#0 */ 0x32: VEC_FCMP0 (>=);
4750 case /* 0b010110: EQ#0 */ 0x16: VEC_FCMP0 (==);
4751 case /* 0b110110: LE#0 */ 0x36: VEC_FCMP0 (<=);
4752 case /* 0b011010: LT#0 */ 0x1A: VEC_FCMP0 (<);
4753 case /* 0b111001: GT */ 0x39: VEC_FCMP (>);
4754 case /* 0b101001: GE */ 0x29: VEC_FCMP (>=);
4755 case /* 0b001001: EQ */ 0x09: VEC_FCMP (==);
4763 unsigned decode
= (INSTR (29, 29) << 6) | INSTR (15, 10);
4767 case 0x0D: /* 0001101 GT */ VEC_CMP (s
, > );
4768 case 0x0F: /* 0001111 GE */ VEC_CMP (s
, >= );
4769 case 0x22: /* 0100010 GT #0 */ VEC_CMP0 (s
, > );
4770 case 0x23: /* 0100011 TST */ VEC_CMP (u
, & );
4771 case 0x26: /* 0100110 EQ #0 */ VEC_CMP0 (s
, == );
4772 case 0x2A: /* 0101010 LT #0 */ VEC_CMP0 (s
, < );
4773 case 0x4D: /* 1001101 HI */ VEC_CMP (u
, > );
4774 case 0x4F: /* 1001111 HS */ VEC_CMP (u
, >= );
4775 case 0x62: /* 1100010 GE #0 */ VEC_CMP0 (s
, >= );
4776 case 0x63: /* 1100011 EQ */ VEC_CMP (u
, == );
4777 case 0x66: /* 1100110 LE #0 */ VEC_CMP0 (s
, <= );
4787 do_vec_SSHL (sim_cpu
*cpu
)
4790 instr[30] = first part (0)/ second part (1)
4791 instr[29,24] = 00 1110
4792 instr[23,22] = size: byte(00), half(01), word (10), long (11)
4795 instr[15,10] = 0100 01
4799 unsigned full
= INSTR (30, 30);
4800 unsigned vm
= INSTR (20, 16);
4801 unsigned vn
= INSTR (9, 5);
4802 unsigned vd
= INSTR (4, 0);
4806 NYI_assert (29, 24, 0x0E);
4807 NYI_assert (21, 21, 1);
4808 NYI_assert (15, 10, 0x11);
4810 /* FIXME: What is a signed shift left in this context ?. */
4812 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
4813 switch (INSTR (23, 22))
4816 for (i
= 0; i
< (full
? 16 : 8); i
++)
4818 shift
= aarch64_get_vec_s8 (cpu
, vm
, i
);
4820 aarch64_set_vec_s8 (cpu
, vd
, i
, aarch64_get_vec_s8 (cpu
, vn
, i
)
4823 aarch64_set_vec_s8 (cpu
, vd
, i
, aarch64_get_vec_s8 (cpu
, vn
, i
)
4829 for (i
= 0; i
< (full
? 8 : 4); i
++)
4831 shift
= aarch64_get_vec_s8 (cpu
, vm
, i
* 2);
4833 aarch64_set_vec_s16 (cpu
, vd
, i
, aarch64_get_vec_s16 (cpu
, vn
, i
)
4836 aarch64_set_vec_s16 (cpu
, vd
, i
, aarch64_get_vec_s16 (cpu
, vn
, i
)
4842 for (i
= 0; i
< (full
? 4 : 2); i
++)
4844 shift
= aarch64_get_vec_s8 (cpu
, vm
, i
* 4);
4846 aarch64_set_vec_s32 (cpu
, vd
, i
, aarch64_get_vec_s32 (cpu
, vn
, i
)
4849 aarch64_set_vec_s32 (cpu
, vd
, i
, aarch64_get_vec_s32 (cpu
, vn
, i
)
4857 for (i
= 0; i
< 2; i
++)
4859 shift
= aarch64_get_vec_s8 (cpu
, vm
, i
* 8);
4861 aarch64_set_vec_s64 (cpu
, vd
, i
, aarch64_get_vec_s64 (cpu
, vn
, i
)
4864 aarch64_set_vec_s64 (cpu
, vd
, i
, aarch64_get_vec_s64 (cpu
, vn
, i
)
4872 do_vec_USHL (sim_cpu
*cpu
)
4875 instr[30] = first part (0)/ second part (1)
4876 instr[29,24] = 10 1110
4877 instr[23,22] = size: byte(00), half(01), word (10), long (11)
4880 instr[15,10] = 0100 01
4884 unsigned full
= INSTR (30, 30);
4885 unsigned vm
= INSTR (20, 16);
4886 unsigned vn
= INSTR (9, 5);
4887 unsigned vd
= INSTR (4, 0);
4891 NYI_assert (29, 24, 0x2E);
4892 NYI_assert (15, 10, 0x11);
4894 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
4895 switch (INSTR (23, 22))
4898 for (i
= 0; i
< (full
? 16 : 8); i
++)
4900 shift
= aarch64_get_vec_s8 (cpu
, vm
, i
);
4902 aarch64_set_vec_u8 (cpu
, vd
, i
, aarch64_get_vec_u8 (cpu
, vn
, i
)
4905 aarch64_set_vec_u8 (cpu
, vd
, i
, aarch64_get_vec_u8 (cpu
, vn
, i
)
4911 for (i
= 0; i
< (full
? 8 : 4); i
++)
4913 shift
= aarch64_get_vec_s8 (cpu
, vm
, i
* 2);
4915 aarch64_set_vec_u16 (cpu
, vd
, i
, aarch64_get_vec_u16 (cpu
, vn
, i
)
4918 aarch64_set_vec_u16 (cpu
, vd
, i
, aarch64_get_vec_u16 (cpu
, vn
, i
)
4924 for (i
= 0; i
< (full
? 4 : 2); i
++)
4926 shift
= aarch64_get_vec_s8 (cpu
, vm
, i
* 4);
4928 aarch64_set_vec_u32 (cpu
, vd
, i
, aarch64_get_vec_u32 (cpu
, vn
, i
)
4931 aarch64_set_vec_u32 (cpu
, vd
, i
, aarch64_get_vec_u32 (cpu
, vn
, i
)
4939 for (i
= 0; i
< 2; i
++)
4941 shift
= aarch64_get_vec_s8 (cpu
, vm
, i
* 8);
4943 aarch64_set_vec_u64 (cpu
, vd
, i
, aarch64_get_vec_u64 (cpu
, vn
, i
)
4946 aarch64_set_vec_u64 (cpu
, vd
, i
, aarch64_get_vec_u64 (cpu
, vn
, i
)
4954 do_vec_FMLA (sim_cpu
*cpu
)
4957 instr[30] = full/half selector
4958 instr[29,23] = 0011100
4959 instr[22] = size: 0=>float, 1=>double
4962 instr[15,10] = 1100 11
4966 unsigned vm
= INSTR (20, 16);
4967 unsigned vn
= INSTR (9, 5);
4968 unsigned vd
= INSTR (4, 0);
4970 int full
= INSTR (30, 30);
4972 NYI_assert (29, 23, 0x1C);
4973 NYI_assert (21, 21, 1);
4974 NYI_assert (15, 10, 0x33);
4976 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
4981 for (i
= 0; i
< 2; i
++)
4982 aarch64_set_vec_double (cpu
, vd
, i
,
4983 aarch64_get_vec_double (cpu
, vn
, i
) *
4984 aarch64_get_vec_double (cpu
, vm
, i
) +
4985 aarch64_get_vec_double (cpu
, vd
, i
));
4989 for (i
= 0; i
< (full
? 4 : 2); i
++)
4990 aarch64_set_vec_float (cpu
, vd
, i
,
4991 aarch64_get_vec_float (cpu
, vn
, i
) *
4992 aarch64_get_vec_float (cpu
, vm
, i
) +
4993 aarch64_get_vec_float (cpu
, vd
, i
));
4998 do_vec_max (sim_cpu
*cpu
)
5001 instr[30] = full/half selector
5002 instr[29] = SMAX (0) / UMAX (1)
5003 instr[28,24] = 0 1110
5004 instr[23,22] = size: 00=> 8-bit, 01=> 16-bit, 10=> 32-bit
5007 instr[15,10] = 0110 01
5011 unsigned vm
= INSTR (20, 16);
5012 unsigned vn
= INSTR (9, 5);
5013 unsigned vd
= INSTR (4, 0);
5015 int full
= INSTR (30, 30);
5017 NYI_assert (28, 24, 0x0E);
5018 NYI_assert (21, 21, 1);
5019 NYI_assert (15, 10, 0x19);
5021 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
5024 switch (INSTR (23, 22))
5027 for (i
= 0; i
< (full
? 16 : 8); i
++)
5028 aarch64_set_vec_u8 (cpu
, vd
, i
,
5029 aarch64_get_vec_u8 (cpu
, vn
, i
)
5030 > aarch64_get_vec_u8 (cpu
, vm
, i
)
5031 ? aarch64_get_vec_u8 (cpu
, vn
, i
)
5032 : aarch64_get_vec_u8 (cpu
, vm
, i
));
5036 for (i
= 0; i
< (full
? 8 : 4); i
++)
5037 aarch64_set_vec_u16 (cpu
, vd
, i
,
5038 aarch64_get_vec_u16 (cpu
, vn
, i
)
5039 > aarch64_get_vec_u16 (cpu
, vm
, i
)
5040 ? aarch64_get_vec_u16 (cpu
, vn
, i
)
5041 : aarch64_get_vec_u16 (cpu
, vm
, i
));
5045 for (i
= 0; i
< (full
? 4 : 2); i
++)
5046 aarch64_set_vec_u32 (cpu
, vd
, i
,
5047 aarch64_get_vec_u32 (cpu
, vn
, i
)
5048 > aarch64_get_vec_u32 (cpu
, vm
, i
)
5049 ? aarch64_get_vec_u32 (cpu
, vn
, i
)
5050 : aarch64_get_vec_u32 (cpu
, vm
, i
));
5059 switch (INSTR (23, 22))
5062 for (i
= 0; i
< (full
? 16 : 8); i
++)
5063 aarch64_set_vec_s8 (cpu
, vd
, i
,
5064 aarch64_get_vec_s8 (cpu
, vn
, i
)
5065 > aarch64_get_vec_s8 (cpu
, vm
, i
)
5066 ? aarch64_get_vec_s8 (cpu
, vn
, i
)
5067 : aarch64_get_vec_s8 (cpu
, vm
, i
));
5071 for (i
= 0; i
< (full
? 8 : 4); i
++)
5072 aarch64_set_vec_s16 (cpu
, vd
, i
,
5073 aarch64_get_vec_s16 (cpu
, vn
, i
)
5074 > aarch64_get_vec_s16 (cpu
, vm
, i
)
5075 ? aarch64_get_vec_s16 (cpu
, vn
, i
)
5076 : aarch64_get_vec_s16 (cpu
, vm
, i
));
5080 for (i
= 0; i
< (full
? 4 : 2); i
++)
5081 aarch64_set_vec_s32 (cpu
, vd
, i
,
5082 aarch64_get_vec_s32 (cpu
, vn
, i
)
5083 > aarch64_get_vec_s32 (cpu
, vm
, i
)
5084 ? aarch64_get_vec_s32 (cpu
, vn
, i
)
5085 : aarch64_get_vec_s32 (cpu
, vm
, i
));
5095 do_vec_min (sim_cpu
*cpu
)
5098 instr[30] = full/half selector
5099 instr[29] = SMIN (0) / UMIN (1)
5100 instr[28,24] = 0 1110
5101 instr[23,22] = size: 00=> 8-bit, 01=> 16-bit, 10=> 32-bit
5104 instr[15,10] = 0110 11
5108 unsigned vm
= INSTR (20, 16);
5109 unsigned vn
= INSTR (9, 5);
5110 unsigned vd
= INSTR (4, 0);
5112 int full
= INSTR (30, 30);
5114 NYI_assert (28, 24, 0x0E);
5115 NYI_assert (21, 21, 1);
5116 NYI_assert (15, 10, 0x1B);
5118 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
5121 switch (INSTR (23, 22))
5124 for (i
= 0; i
< (full
? 16 : 8); i
++)
5125 aarch64_set_vec_u8 (cpu
, vd
, i
,
5126 aarch64_get_vec_u8 (cpu
, vn
, i
)
5127 < aarch64_get_vec_u8 (cpu
, vm
, i
)
5128 ? aarch64_get_vec_u8 (cpu
, vn
, i
)
5129 : aarch64_get_vec_u8 (cpu
, vm
, i
));
5133 for (i
= 0; i
< (full
? 8 : 4); i
++)
5134 aarch64_set_vec_u16 (cpu
, vd
, i
,
5135 aarch64_get_vec_u16 (cpu
, vn
, i
)
5136 < aarch64_get_vec_u16 (cpu
, vm
, i
)
5137 ? aarch64_get_vec_u16 (cpu
, vn
, i
)
5138 : aarch64_get_vec_u16 (cpu
, vm
, i
));
5142 for (i
= 0; i
< (full
? 4 : 2); i
++)
5143 aarch64_set_vec_u32 (cpu
, vd
, i
,
5144 aarch64_get_vec_u32 (cpu
, vn
, i
)
5145 < aarch64_get_vec_u32 (cpu
, vm
, i
)
5146 ? aarch64_get_vec_u32 (cpu
, vn
, i
)
5147 : aarch64_get_vec_u32 (cpu
, vm
, i
));
5156 switch (INSTR (23, 22))
5159 for (i
= 0; i
< (full
? 16 : 8); i
++)
5160 aarch64_set_vec_s8 (cpu
, vd
, i
,
5161 aarch64_get_vec_s8 (cpu
, vn
, i
)
5162 < aarch64_get_vec_s8 (cpu
, vm
, i
)
5163 ? aarch64_get_vec_s8 (cpu
, vn
, i
)
5164 : aarch64_get_vec_s8 (cpu
, vm
, i
));
5168 for (i
= 0; i
< (full
? 8 : 4); i
++)
5169 aarch64_set_vec_s16 (cpu
, vd
, i
,
5170 aarch64_get_vec_s16 (cpu
, vn
, i
)
5171 < aarch64_get_vec_s16 (cpu
, vm
, i
)
5172 ? aarch64_get_vec_s16 (cpu
, vn
, i
)
5173 : aarch64_get_vec_s16 (cpu
, vm
, i
));
5177 for (i
= 0; i
< (full
? 4 : 2); i
++)
5178 aarch64_set_vec_s32 (cpu
, vd
, i
,
5179 aarch64_get_vec_s32 (cpu
, vn
, i
)
5180 < aarch64_get_vec_s32 (cpu
, vm
, i
)
5181 ? aarch64_get_vec_s32 (cpu
, vn
, i
)
5182 : aarch64_get_vec_s32 (cpu
, vm
, i
));
5192 do_vec_sub_long (sim_cpu
*cpu
)
5195 instr[30] = lower (0) / upper (1)
5196 instr[29] = signed (0) / unsigned (1)
5197 instr[28,24] = 0 1110
5198 instr[23,22] = size: bytes (00), half (01), word (10)
5201 instr[15,10] = 0010 00
5203 instr[4,0] = V dest. */
5205 unsigned size
= INSTR (23, 22);
5206 unsigned vm
= INSTR (20, 16);
5207 unsigned vn
= INSTR (9, 5);
5208 unsigned vd
= INSTR (4, 0);
5212 NYI_assert (28, 24, 0x0E);
5213 NYI_assert (21, 21, 1);
5214 NYI_assert (15, 10, 0x08);
5219 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
5220 switch (INSTR (30, 29))
5222 case 2: /* SSUBL2. */
5224 case 0: /* SSUBL. */
5229 for (i
= 0; i
< 8; i
++)
5230 aarch64_set_vec_s16 (cpu
, vd
, i
,
5231 aarch64_get_vec_s8 (cpu
, vn
, i
+ bias
)
5232 - aarch64_get_vec_s8 (cpu
, vm
, i
+ bias
));
5237 for (i
= 0; i
< 4; i
++)
5238 aarch64_set_vec_s32 (cpu
, vd
, i
,
5239 aarch64_get_vec_s16 (cpu
, vn
, i
+ bias
)
5240 - aarch64_get_vec_s16 (cpu
, vm
, i
+ bias
));
5244 for (i
= 0; i
< 2; i
++)
5245 aarch64_set_vec_s64 (cpu
, vd
, i
,
5246 aarch64_get_vec_s32 (cpu
, vn
, i
+ bias
)
5247 - aarch64_get_vec_s32 (cpu
, vm
, i
+ bias
));
5255 case 3: /* USUBL2. */
5257 case 1: /* USUBL. */
5262 for (i
= 0; i
< 8; i
++)
5263 aarch64_set_vec_u16 (cpu
, vd
, i
,
5264 aarch64_get_vec_u8 (cpu
, vn
, i
+ bias
)
5265 - aarch64_get_vec_u8 (cpu
, vm
, i
+ bias
));
5270 for (i
= 0; i
< 4; i
++)
5271 aarch64_set_vec_u32 (cpu
, vd
, i
,
5272 aarch64_get_vec_u16 (cpu
, vn
, i
+ bias
)
5273 - aarch64_get_vec_u16 (cpu
, vm
, i
+ bias
));
5277 for (i
= 0; i
< 2; i
++)
5278 aarch64_set_vec_u64 (cpu
, vd
, i
,
5279 aarch64_get_vec_u32 (cpu
, vn
, i
+ bias
)
5280 - aarch64_get_vec_u32 (cpu
, vm
, i
+ bias
));
5291 do_vec_ADDP (sim_cpu
*cpu
)
5294 instr[30] = half(0)/full(1)
5295 instr[29,24] = 00 1110
5296 instr[23,22] = size: bytes (00), half (01), word (10), long (11)
5299 instr[15,10] = 1011 11
5301 instr[4,0] = V dest. */
5305 unsigned full
= INSTR (30, 30);
5306 unsigned size
= INSTR (23, 22);
5307 unsigned vm
= INSTR (20, 16);
5308 unsigned vn
= INSTR (9, 5);
5309 unsigned vd
= INSTR (4, 0);
5312 NYI_assert (29, 24, 0x0E);
5313 NYI_assert (21, 21, 1);
5314 NYI_assert (15, 10, 0x2F);
5316 /* Make copies of the source registers in case vd == vn/vm. */
5317 copy_vn
= cpu
->fr
[vn
];
5318 copy_vm
= cpu
->fr
[vm
];
5320 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
5324 range
= full
? 8 : 4;
5325 for (i
= 0; i
< range
; i
++)
5327 aarch64_set_vec_u8 (cpu
, vd
, i
,
5328 copy_vn
.b
[i
* 2] + copy_vn
.b
[i
* 2 + 1]);
5329 aarch64_set_vec_u8 (cpu
, vd
, i
+ range
,
5330 copy_vm
.b
[i
* 2] + copy_vm
.b
[i
* 2 + 1]);
5335 range
= full
? 4 : 2;
5336 for (i
= 0; i
< range
; i
++)
5338 aarch64_set_vec_u16 (cpu
, vd
, i
,
5339 copy_vn
.h
[i
* 2] + copy_vn
.h
[i
* 2 + 1]);
5340 aarch64_set_vec_u16 (cpu
, vd
, i
+ range
,
5341 copy_vm
.h
[i
* 2] + copy_vm
.h
[i
* 2 + 1]);
5346 range
= full
? 2 : 1;
5347 for (i
= 0; i
< range
; i
++)
5349 aarch64_set_vec_u32 (cpu
, vd
, i
,
5350 copy_vn
.w
[i
* 2] + copy_vn
.w
[i
* 2 + 1]);
5351 aarch64_set_vec_u32 (cpu
, vd
, i
+ range
,
5352 copy_vm
.w
[i
* 2] + copy_vm
.w
[i
* 2 + 1]);
5359 aarch64_set_vec_u64 (cpu
, vd
, 0, copy_vn
.v
[0] + copy_vn
.v
[1]);
5360 aarch64_set_vec_u64 (cpu
, vd
, 1, copy_vm
.v
[0] + copy_vm
.v
[1]);
5366 do_vec_UMOV (sim_cpu
*cpu
)
5369 instr[30] = 32-bit(0)/64-bit(1)
5370 instr[29,21] = 00 1110 000
5371 insrt[20,16] = size & index
5372 instr[15,10] = 0011 11
5373 instr[9,5] = V source
5374 instr[4,0] = R dest. */
5376 unsigned vs
= INSTR (9, 5);
5377 unsigned rd
= INSTR (4, 0);
5380 NYI_assert (29, 21, 0x070);
5381 NYI_assert (15, 10, 0x0F);
5383 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
5386 /* Byte transfer. */
5387 index
= INSTR (20, 17);
5388 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
,
5389 aarch64_get_vec_u8 (cpu
, vs
, index
));
5391 else if (INSTR (17, 17))
5393 index
= INSTR (20, 18);
5394 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
,
5395 aarch64_get_vec_u16 (cpu
, vs
, index
));
5397 else if (INSTR (18, 18))
5399 index
= INSTR (20, 19);
5400 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
,
5401 aarch64_get_vec_u32 (cpu
, vs
, index
));
5405 if (INSTR (30, 30) != 1)
5408 index
= INSTR (20, 20);
5409 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
,
5410 aarch64_get_vec_u64 (cpu
, vs
, index
));
5415 do_vec_FABS (sim_cpu
*cpu
)
5418 instr[30] = half(0)/full(1)
5419 instr[29,23] = 00 1110 1
5420 instr[22] = float(0)/double(1)
5421 instr[21,16] = 10 0000
5422 instr[15,10] = 1111 10
5426 unsigned vn
= INSTR (9, 5);
5427 unsigned vd
= INSTR (4, 0);
5428 unsigned full
= INSTR (30, 30);
5431 NYI_assert (29, 23, 0x1D);
5432 NYI_assert (21, 10, 0x83E);
5434 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
5440 for (i
= 0; i
< 2; i
++)
5441 aarch64_set_vec_double (cpu
, vd
, i
,
5442 fabs (aarch64_get_vec_double (cpu
, vn
, i
)));
5446 for (i
= 0; i
< (full
? 4 : 2); i
++)
5447 aarch64_set_vec_float (cpu
, vd
, i
,
5448 fabsf (aarch64_get_vec_float (cpu
, vn
, i
)));
5453 do_vec_FCVTZS (sim_cpu
*cpu
)
5456 instr[30] = half (0) / all (1)
5457 instr[29,23] = 00 1110 1
5458 instr[22] = single (0) / double (1)
5459 instr[21,10] = 10 0001 1011 10
5463 unsigned rn
= INSTR (9, 5);
5464 unsigned rd
= INSTR (4, 0);
5465 unsigned full
= INSTR (30, 30);
5468 NYI_assert (31, 31, 0);
5469 NYI_assert (29, 23, 0x1D);
5470 NYI_assert (21, 10, 0x86E);
5472 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
5478 for (i
= 0; i
< 2; i
++)
5479 aarch64_set_vec_s64 (cpu
, rd
, i
,
5480 (int64_t) aarch64_get_vec_double (cpu
, rn
, i
));
5483 for (i
= 0; i
< (full
? 4 : 2); i
++)
5484 aarch64_set_vec_s32 (cpu
, rd
, i
,
5485 (int32_t) aarch64_get_vec_float (cpu
, rn
, i
));
5489 do_vec_REV64 (sim_cpu
*cpu
)
5492 instr[30] = full/half
5493 instr[29,24] = 00 1110
5495 instr[21,10] = 10 0000 0000 10
5499 unsigned rn
= INSTR (9, 5);
5500 unsigned rd
= INSTR (4, 0);
5501 unsigned size
= INSTR (23, 22);
5502 unsigned full
= INSTR (30, 30);
5506 NYI_assert (29, 24, 0x0E);
5507 NYI_assert (21, 10, 0x802);
5509 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
5513 for (i
= 0; i
< (full
? 16 : 8); i
++)
5514 val
.b
[i
^ 0x7] = aarch64_get_vec_u8 (cpu
, rn
, i
);
5518 for (i
= 0; i
< (full
? 8 : 4); i
++)
5519 val
.h
[i
^ 0x3] = aarch64_get_vec_u16 (cpu
, rn
, i
);
5523 for (i
= 0; i
< (full
? 4 : 2); i
++)
5524 val
.w
[i
^ 0x1] = aarch64_get_vec_u32 (cpu
, rn
, i
);
5531 aarch64_set_vec_u64 (cpu
, rd
, 0, val
.v
[0]);
5533 aarch64_set_vec_u64 (cpu
, rd
, 1, val
.v
[1]);
5537 do_vec_REV16 (sim_cpu
*cpu
)
5540 instr[30] = full/half
5541 instr[29,24] = 00 1110
5543 instr[21,10] = 10 0000 0001 10
5547 unsigned rn
= INSTR (9, 5);
5548 unsigned rd
= INSTR (4, 0);
5549 unsigned size
= INSTR (23, 22);
5550 unsigned full
= INSTR (30, 30);
5554 NYI_assert (29, 24, 0x0E);
5555 NYI_assert (21, 10, 0x806);
5557 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
5561 for (i
= 0; i
< (full
? 16 : 8); i
++)
5562 val
.b
[i
^ 0x1] = aarch64_get_vec_u8 (cpu
, rn
, i
);
5569 aarch64_set_vec_u64 (cpu
, rd
, 0, val
.v
[0]);
5571 aarch64_set_vec_u64 (cpu
, rd
, 1, val
.v
[1]);
5575 do_vec_op1 (sim_cpu
*cpu
)
5578 instr[30] = half/full
5579 instr[29,24] = 00 1110
5582 instr[15,10] = sub-opcode
5585 NYI_assert (29, 24, 0x0E);
5587 if (INSTR (21, 21) == 0)
5589 if (INSTR (23, 22) == 0)
5591 if (INSTR (30, 30) == 1
5592 && INSTR (17, 14) == 0
5593 && INSTR (12, 10) == 7)
5594 return do_vec_ins_2 (cpu
);
5596 switch (INSTR (15, 10))
5598 case 0x01: do_vec_DUP_vector_into_vector (cpu
); return;
5599 case 0x03: do_vec_DUP_scalar_into_vector (cpu
); return;
5600 case 0x07: do_vec_INS (cpu
); return;
5601 case 0x0A: do_vec_TRN (cpu
); return;
5604 if (INSTR (17, 16) == 0)
5606 do_vec_MOV_into_scalar (cpu
);
5615 do_vec_TBL (cpu
); return;
5619 do_vec_UZP (cpu
); return;
5623 do_vec_ZIP (cpu
); return;
5630 switch (INSTR (13, 10))
5632 case 0x6: do_vec_UZP (cpu
); return;
5633 case 0xE: do_vec_ZIP (cpu
); return;
5634 case 0xA: do_vec_TRN (cpu
); return;
5635 case 0xF: do_vec_UMOV (cpu
); return;
5640 switch (INSTR (15, 10))
5642 case 0x02: do_vec_REV64 (cpu
); return;
5643 case 0x06: do_vec_REV16 (cpu
); return;
5646 switch (INSTR (23, 21))
5648 case 1: do_vec_AND (cpu
); return;
5649 case 3: do_vec_BIC (cpu
); return;
5650 case 5: do_vec_ORR (cpu
); return;
5651 case 7: do_vec_ORN (cpu
); return;
5655 case 0x08: do_vec_sub_long (cpu
); return;
5656 case 0x0a: do_vec_XTN (cpu
); return;
5657 case 0x11: do_vec_SSHL (cpu
); return;
5658 case 0x16: do_vec_CNT (cpu
); return;
5659 case 0x19: do_vec_max (cpu
); return;
5660 case 0x1B: do_vec_min (cpu
); return;
5661 case 0x21: do_vec_add (cpu
); return;
5662 case 0x25: do_vec_MLA (cpu
); return;
5663 case 0x27: do_vec_mul (cpu
); return;
5664 case 0x2F: do_vec_ADDP (cpu
); return;
5665 case 0x30: do_vec_mull (cpu
); return;
5666 case 0x33: do_vec_FMLA (cpu
); return;
5667 case 0x35: do_vec_fadd (cpu
); return;
5670 switch (INSTR (20, 16))
5672 case 0x00: do_vec_ABS (cpu
); return;
5673 case 0x01: do_vec_FCVTZS (cpu
); return;
5674 case 0x11: do_vec_ADDV (cpu
); return;
5680 do_vec_Fminmax (cpu
); return;
5692 do_vec_compare (cpu
); return;
5695 do_vec_FABS (cpu
); return;
5703 do_vec_xtl (sim_cpu
*cpu
)
5706 instr[30,29] = SXTL (00), UXTL (01), SXTL2 (10), UXTL2 (11)
5707 instr[28,22] = 0 1111 00
5708 instr[21,16] = size & shift (USHLL, SSHLL, USHLL2, SSHLL2)
5709 instr[15,10] = 1010 01
5710 instr[9,5] = V source
5711 instr[4,0] = V dest. */
5713 unsigned vs
= INSTR (9, 5);
5714 unsigned vd
= INSTR (4, 0);
5715 unsigned i
, shift
, bias
= 0;
5717 NYI_assert (28, 22, 0x3C);
5718 NYI_assert (15, 10, 0x29);
5720 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
5721 switch (INSTR (30, 29))
5723 case 2: /* SXTL2, SSHLL2. */
5725 case 0: /* SXTL, SSHLL. */
5730 shift
= INSTR (20, 16);
5731 /* Get the source values before setting the destination values
5732 in case the source and destination are the same. */
5733 val1
= aarch64_get_vec_s32 (cpu
, vs
, bias
) << shift
;
5734 val2
= aarch64_get_vec_s32 (cpu
, vs
, bias
+ 1) << shift
;
5735 aarch64_set_vec_s64 (cpu
, vd
, 0, val1
);
5736 aarch64_set_vec_s64 (cpu
, vd
, 1, val2
);
5738 else if (INSTR (20, 20))
5741 int32_t v1
,v2
,v3
,v4
;
5743 shift
= INSTR (19, 16);
5745 for (i
= 0; i
< 4; i
++)
5746 v
[i
] = aarch64_get_vec_s16 (cpu
, vs
, bias
+ i
) << shift
;
5747 for (i
= 0; i
< 4; i
++)
5748 aarch64_set_vec_s32 (cpu
, vd
, i
, v
[i
]);
5753 NYI_assert (19, 19, 1);
5755 shift
= INSTR (18, 16);
5757 for (i
= 0; i
< 8; i
++)
5758 v
[i
] = aarch64_get_vec_s8 (cpu
, vs
, i
+ bias
) << shift
;
5759 for (i
= 0; i
< 8; i
++)
5760 aarch64_set_vec_s16 (cpu
, vd
, i
, v
[i
]);
5764 case 3: /* UXTL2, USHLL2. */
5766 case 1: /* UXTL, USHLL. */
5770 shift
= INSTR (20, 16);
5771 v1
= aarch64_get_vec_u32 (cpu
, vs
, bias
) << shift
;
5772 v2
= aarch64_get_vec_u32 (cpu
, vs
, bias
+ 1) << shift
;
5773 aarch64_set_vec_u64 (cpu
, vd
, 0, v1
);
5774 aarch64_set_vec_u64 (cpu
, vd
, 1, v2
);
5776 else if (INSTR (20, 20))
5779 shift
= INSTR (19, 16);
5781 for (i
= 0; i
< 4; i
++)
5782 v
[i
] = aarch64_get_vec_u16 (cpu
, vs
, i
+ bias
) << shift
;
5783 for (i
= 0; i
< 4; i
++)
5784 aarch64_set_vec_u32 (cpu
, vd
, i
, v
[i
]);
5789 NYI_assert (19, 19, 1);
5791 shift
= INSTR (18, 16);
5793 for (i
= 0; i
< 8; i
++)
5794 v
[i
] = aarch64_get_vec_u8 (cpu
, vs
, i
+ bias
) << shift
;
5795 for (i
= 0; i
< 8; i
++)
5796 aarch64_set_vec_u16 (cpu
, vd
, i
, v
[i
]);
5803 do_vec_SHL (sim_cpu
*cpu
)
5806 instr [30] = half(0)/full(1)
5807 instr [29,23] = 001 1110
5808 instr [22,16] = size and shift amount
5809 instr [15,10] = 01 0101
5811 instr [4, 0] = Vd. */
5814 int full
= INSTR (30, 30);
5815 unsigned vs
= INSTR (9, 5);
5816 unsigned vd
= INSTR (4, 0);
5819 NYI_assert (29, 23, 0x1E);
5820 NYI_assert (15, 10, 0x15);
5822 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
5825 shift
= INSTR (21, 16);
5830 for (i
= 0; i
< 2; i
++)
5832 uint64_t val
= aarch64_get_vec_u64 (cpu
, vs
, i
);
5833 aarch64_set_vec_u64 (cpu
, vd
, i
, val
<< shift
);
5841 shift
= INSTR (20, 16);
5843 for (i
= 0; i
< (full
? 4 : 2); i
++)
5845 uint32_t val
= aarch64_get_vec_u32 (cpu
, vs
, i
);
5846 aarch64_set_vec_u32 (cpu
, vd
, i
, val
<< shift
);
5854 shift
= INSTR (19, 16);
5856 for (i
= 0; i
< (full
? 8 : 4); i
++)
5858 uint16_t val
= aarch64_get_vec_u16 (cpu
, vs
, i
);
5859 aarch64_set_vec_u16 (cpu
, vd
, i
, val
<< shift
);
5865 if (INSTR (19, 19) == 0)
5868 shift
= INSTR (18, 16);
5870 for (i
= 0; i
< (full
? 16 : 8); i
++)
5872 uint8_t val
= aarch64_get_vec_u8 (cpu
, vs
, i
);
5873 aarch64_set_vec_u8 (cpu
, vd
, i
, val
<< shift
);
5878 do_vec_SSHR_USHR (sim_cpu
*cpu
)
5881 instr [30] = half(0)/full(1)
5882 instr [29] = signed(0)/unsigned(1)
5883 instr [28,23] = 0 1111 0
5884 instr [22,16] = size and shift amount
5885 instr [15,10] = 0000 01
5887 instr [4, 0] = Vd. */
5889 int full
= INSTR (30, 30);
5890 int sign
= ! INSTR (29, 29);
5891 unsigned shift
= INSTR (22, 16);
5892 unsigned vs
= INSTR (9, 5);
5893 unsigned vd
= INSTR (4, 0);
5896 NYI_assert (28, 23, 0x1E);
5897 NYI_assert (15, 10, 0x01);
5899 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
5902 shift
= 128 - shift
;
5908 for (i
= 0; i
< 2; i
++)
5910 int64_t val
= aarch64_get_vec_s64 (cpu
, vs
, i
);
5911 aarch64_set_vec_s64 (cpu
, vd
, i
, val
>> shift
);
5914 for (i
= 0; i
< 2; i
++)
5916 uint64_t val
= aarch64_get_vec_u64 (cpu
, vs
, i
);
5917 aarch64_set_vec_u64 (cpu
, vd
, i
, val
>> shift
);
5928 for (i
= 0; i
< (full
? 4 : 2); i
++)
5930 int32_t val
= aarch64_get_vec_s32 (cpu
, vs
, i
);
5931 aarch64_set_vec_s32 (cpu
, vd
, i
, val
>> shift
);
5934 for (i
= 0; i
< (full
? 4 : 2); i
++)
5936 uint32_t val
= aarch64_get_vec_u32 (cpu
, vs
, i
);
5937 aarch64_set_vec_u32 (cpu
, vd
, i
, val
>> shift
);
5948 for (i
= 0; i
< (full
? 8 : 4); i
++)
5950 int16_t val
= aarch64_get_vec_s16 (cpu
, vs
, i
);
5951 aarch64_set_vec_s16 (cpu
, vd
, i
, val
>> shift
);
5954 for (i
= 0; i
< (full
? 8 : 4); i
++)
5956 uint16_t val
= aarch64_get_vec_u16 (cpu
, vs
, i
);
5957 aarch64_set_vec_u16 (cpu
, vd
, i
, val
>> shift
);
5963 if (INSTR (19, 19) == 0)
5969 for (i
= 0; i
< (full
? 16 : 8); i
++)
5971 int8_t val
= aarch64_get_vec_s8 (cpu
, vs
, i
);
5972 aarch64_set_vec_s8 (cpu
, vd
, i
, val
>> shift
);
5975 for (i
= 0; i
< (full
? 16 : 8); i
++)
5977 uint8_t val
= aarch64_get_vec_u8 (cpu
, vs
, i
);
5978 aarch64_set_vec_u8 (cpu
, vd
, i
, val
>> shift
);
5983 do_vec_MUL_by_element (sim_cpu
*cpu
)
5986 instr[30] = half/full
5987 instr[29,24] = 00 1111
5998 unsigned full
= INSTR (30, 30);
5999 unsigned L
= INSTR (21, 21);
6000 unsigned H
= INSTR (11, 11);
6001 unsigned vn
= INSTR (9, 5);
6002 unsigned vd
= INSTR (4, 0);
6003 unsigned size
= INSTR (23, 22);
6008 NYI_assert (29, 24, 0x0F);
6009 NYI_assert (15, 12, 0x8);
6010 NYI_assert (10, 10, 0);
6012 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
6017 /* 16 bit products. */
6022 index
= (H
<< 2) | (L
<< 1) | INSTR (20, 20);
6023 vm
= INSTR (19, 16);
6024 element2
= aarch64_get_vec_u16 (cpu
, vm
, index
);
6026 for (e
= 0; e
< (full
? 8 : 4); e
++)
6028 element1
= aarch64_get_vec_u16 (cpu
, vn
, e
);
6029 product
= element1
* element2
;
6030 aarch64_set_vec_u16 (cpu
, vd
, e
, product
);
6037 /* 32 bit products. */
6042 index
= (H
<< 1) | L
;
6043 vm
= INSTR (20, 16);
6044 element2
= aarch64_get_vec_u32 (cpu
, vm
, index
);
6046 for (e
= 0; e
< (full
? 4 : 2); e
++)
6048 element1
= aarch64_get_vec_u32 (cpu
, vn
, e
);
6049 product
= element1
* element2
;
6050 aarch64_set_vec_u32 (cpu
, vd
, e
, product
);
6061 do_FMLA_by_element (sim_cpu
*cpu
)
6064 instr[30] = half/full
6065 instr[29,23] = 00 1111 1
6075 unsigned full
= INSTR (30, 30);
6076 unsigned size
= INSTR (22, 22);
6077 unsigned L
= INSTR (21, 21);
6078 unsigned vm
= INSTR (20, 16);
6079 unsigned H
= INSTR (11, 11);
6080 unsigned vn
= INSTR (9, 5);
6081 unsigned vd
= INSTR (4, 0);
6084 NYI_assert (29, 23, 0x1F);
6085 NYI_assert (15, 12, 0x1);
6086 NYI_assert (10, 10, 0);
6088 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
6091 double element1
, element2
;
6096 element2
= aarch64_get_vec_double (cpu
, vm
, H
);
6098 for (e
= 0; e
< 2; e
++)
6100 element1
= aarch64_get_vec_double (cpu
, vn
, e
);
6101 element1
*= element2
;
6102 element1
+= aarch64_get_vec_double (cpu
, vd
, e
);
6103 aarch64_set_vec_double (cpu
, vd
, e
, element1
);
6109 float element2
= aarch64_get_vec_float (cpu
, vm
, (H
<< 1) | L
);
6111 for (e
= 0; e
< (full
? 4 : 2); e
++)
6113 element1
= aarch64_get_vec_float (cpu
, vn
, e
);
6114 element1
*= element2
;
6115 element1
+= aarch64_get_vec_float (cpu
, vd
, e
);
6116 aarch64_set_vec_float (cpu
, vd
, e
, element1
);
6122 do_vec_op2 (sim_cpu
*cpu
)
6125 instr[30] = half/full
6126 instr[29,24] = 00 1111
6128 instr[22,16] = element size & index
6129 instr[15,10] = sub-opcode
6133 NYI_assert (29, 24, 0x0F);
6135 if (INSTR (23, 23) != 0)
6137 switch (INSTR (15, 10))
6141 do_FMLA_by_element (cpu
);
6146 do_vec_MUL_by_element (cpu
);
6155 switch (INSTR (15, 10))
6157 case 0x01: do_vec_SSHR_USHR (cpu
); return;
6158 case 0x15: do_vec_SHL (cpu
); return;
6160 case 0x22: do_vec_MUL_by_element (cpu
); return;
6161 case 0x29: do_vec_xtl (cpu
); return;
6168 do_vec_neg (sim_cpu
*cpu
)
6171 instr[30] = full(1)/half(0)
6172 instr[29,24] = 10 1110
6173 instr[23,22] = size: byte(00), half (01), word (10), long (11)
6174 instr[21,10] = 1000 0010 1110
6178 int full
= INSTR (30, 30);
6179 unsigned vs
= INSTR (9, 5);
6180 unsigned vd
= INSTR (4, 0);
6183 NYI_assert (29, 24, 0x2E);
6184 NYI_assert (21, 10, 0x82E);
6186 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
6187 switch (INSTR (23, 22))
6190 for (i
= 0; i
< (full
? 16 : 8); i
++)
6191 aarch64_set_vec_s8 (cpu
, vd
, i
, - aarch64_get_vec_s8 (cpu
, vs
, i
));
6195 for (i
= 0; i
< (full
? 8 : 4); i
++)
6196 aarch64_set_vec_s16 (cpu
, vd
, i
, - aarch64_get_vec_s16 (cpu
, vs
, i
));
6200 for (i
= 0; i
< (full
? 4 : 2); i
++)
6201 aarch64_set_vec_s32 (cpu
, vd
, i
, - aarch64_get_vec_s32 (cpu
, vs
, i
));
6207 for (i
= 0; i
< 2; i
++)
6208 aarch64_set_vec_s64 (cpu
, vd
, i
, - aarch64_get_vec_s64 (cpu
, vs
, i
));
6214 do_vec_sqrt (sim_cpu
*cpu
)
6217 instr[30] = full(1)/half(0)
6218 instr[29,23] = 101 1101
6219 instr[22] = single(0)/double(1)
6220 instr[21,10] = 1000 0111 1110
6224 int full
= INSTR (30, 30);
6225 unsigned vs
= INSTR (9, 5);
6226 unsigned vd
= INSTR (4, 0);
6229 NYI_assert (29, 23, 0x5B);
6230 NYI_assert (21, 10, 0x87E);
6232 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
6233 if (INSTR (22, 22) == 0)
6234 for (i
= 0; i
< (full
? 4 : 2); i
++)
6235 aarch64_set_vec_float (cpu
, vd
, i
,
6236 sqrtf (aarch64_get_vec_float (cpu
, vs
, i
)));
6238 for (i
= 0; i
< 2; i
++)
6239 aarch64_set_vec_double (cpu
, vd
, i
,
6240 sqrt (aarch64_get_vec_double (cpu
, vs
, i
)));
6244 do_vec_mls_indexed (sim_cpu
*cpu
)
6247 instr[30] = half(0)/full(1)
6248 instr[29,24] = 10 1111
6249 instr[23,22] = 16-bit(01)/32-bit(10)
6250 instr[21,20+11] = index (if 16-bit)
6251 instr[21+11] = index (if 32-bit)
6254 instr[11] = part of index
6259 int full
= INSTR (30, 30);
6260 unsigned vs
= INSTR (9, 5);
6261 unsigned vd
= INSTR (4, 0);
6262 unsigned vm
= INSTR (20, 16);
6265 NYI_assert (15, 12, 4);
6266 NYI_assert (10, 10, 0);
6268 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
6269 switch (INSTR (23, 22))
6279 elem
= (INSTR (21, 20) << 1) | INSTR (11, 11);
6280 val
= aarch64_get_vec_u16 (cpu
, vm
, elem
);
6282 for (i
= 0; i
< (full
? 8 : 4); i
++)
6283 aarch64_set_vec_u32 (cpu
, vd
, i
,
6284 aarch64_get_vec_u32 (cpu
, vd
, i
) -
6285 (aarch64_get_vec_u32 (cpu
, vs
, i
) * val
));
6291 unsigned elem
= (INSTR (21, 21) << 1) | INSTR (11, 11);
6292 uint64_t val
= aarch64_get_vec_u32 (cpu
, vm
, elem
);
6294 for (i
= 0; i
< (full
? 4 : 2); i
++)
6295 aarch64_set_vec_u64 (cpu
, vd
, i
,
6296 aarch64_get_vec_u64 (cpu
, vd
, i
) -
6297 (aarch64_get_vec_u64 (cpu
, vs
, i
) * val
));
6309 do_vec_SUB (sim_cpu
*cpu
)
6312 instr [30] = half(0)/full(1)
6313 instr [29,24] = 10 1110
6314 instr [23,22] = size: byte(00, half(01), word (10), long (11)
6317 instr [15,10] = 10 0001
6319 instr [4, 0] = Vd. */
6321 unsigned full
= INSTR (30, 30);
6322 unsigned vm
= INSTR (20, 16);
6323 unsigned vn
= INSTR (9, 5);
6324 unsigned vd
= INSTR (4, 0);
6327 NYI_assert (29, 24, 0x2E);
6328 NYI_assert (21, 21, 1);
6329 NYI_assert (15, 10, 0x21);
6331 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
6332 switch (INSTR (23, 22))
6335 for (i
= 0; i
< (full
? 16 : 8); i
++)
6336 aarch64_set_vec_s8 (cpu
, vd
, i
,
6337 aarch64_get_vec_s8 (cpu
, vn
, i
)
6338 - aarch64_get_vec_s8 (cpu
, vm
, i
));
6342 for (i
= 0; i
< (full
? 8 : 4); i
++)
6343 aarch64_set_vec_s16 (cpu
, vd
, i
,
6344 aarch64_get_vec_s16 (cpu
, vn
, i
)
6345 - aarch64_get_vec_s16 (cpu
, vm
, i
));
6349 for (i
= 0; i
< (full
? 4 : 2); i
++)
6350 aarch64_set_vec_s32 (cpu
, vd
, i
,
6351 aarch64_get_vec_s32 (cpu
, vn
, i
)
6352 - aarch64_get_vec_s32 (cpu
, vm
, i
));
6359 for (i
= 0; i
< 2; i
++)
6360 aarch64_set_vec_s64 (cpu
, vd
, i
,
6361 aarch64_get_vec_s64 (cpu
, vn
, i
)
6362 - aarch64_get_vec_s64 (cpu
, vm
, i
));
6368 do_vec_MLS (sim_cpu
*cpu
)
6371 instr [30] = half(0)/full(1)
6372 instr [29,24] = 10 1110
6373 instr [23,22] = size: byte(00, half(01), word (10)
6376 instr [15,10] = 10 0101
6378 instr [4, 0] = Vd. */
6380 unsigned full
= INSTR (30, 30);
6381 unsigned vm
= INSTR (20, 16);
6382 unsigned vn
= INSTR (9, 5);
6383 unsigned vd
= INSTR (4, 0);
6386 NYI_assert (29, 24, 0x2E);
6387 NYI_assert (21, 21, 1);
6388 NYI_assert (15, 10, 0x25);
6390 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
6391 switch (INSTR (23, 22))
6394 for (i
= 0; i
< (full
? 16 : 8); i
++)
6395 aarch64_set_vec_u8 (cpu
, vd
, i
,
6396 aarch64_get_vec_u8 (cpu
, vd
, i
)
6397 - (aarch64_get_vec_u8 (cpu
, vn
, i
)
6398 * aarch64_get_vec_u8 (cpu
, vm
, i
)));
6402 for (i
= 0; i
< (full
? 8 : 4); i
++)
6403 aarch64_set_vec_u16 (cpu
, vd
, i
,
6404 aarch64_get_vec_u16 (cpu
, vd
, i
)
6405 - (aarch64_get_vec_u16 (cpu
, vn
, i
)
6406 * aarch64_get_vec_u16 (cpu
, vm
, i
)));
6410 for (i
= 0; i
< (full
? 4 : 2); i
++)
6411 aarch64_set_vec_u32 (cpu
, vd
, i
,
6412 aarch64_get_vec_u32 (cpu
, vd
, i
)
6413 - (aarch64_get_vec_u32 (cpu
, vn
, i
)
6414 * aarch64_get_vec_u32 (cpu
, vm
, i
)));
6423 do_vec_FDIV (sim_cpu
*cpu
)
6426 instr [30] = half(0)/full(1)
6427 instr [29,23] = 10 1110 0
6428 instr [22] = float()/double(1)
6431 instr [15,10] = 1111 11
6433 instr [4, 0] = Vd. */
6435 unsigned full
= INSTR (30, 30);
6436 unsigned vm
= INSTR (20, 16);
6437 unsigned vn
= INSTR (9, 5);
6438 unsigned vd
= INSTR (4, 0);
6441 NYI_assert (29, 23, 0x5C);
6442 NYI_assert (21, 21, 1);
6443 NYI_assert (15, 10, 0x3F);
6445 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
6451 for (i
= 0; i
< 2; i
++)
6452 aarch64_set_vec_double (cpu
, vd
, i
,
6453 aarch64_get_vec_double (cpu
, vn
, i
)
6454 / aarch64_get_vec_double (cpu
, vm
, i
));
6457 for (i
= 0; i
< (full
? 4 : 2); i
++)
6458 aarch64_set_vec_float (cpu
, vd
, i
,
6459 aarch64_get_vec_float (cpu
, vn
, i
)
6460 / aarch64_get_vec_float (cpu
, vm
, i
));
6464 do_vec_FMUL (sim_cpu
*cpu
)
6467 instr [30] = half(0)/full(1)
6468 instr [29,23] = 10 1110 0
6469 instr [22] = float(0)/double(1)
6472 instr [15,10] = 1101 11
6474 instr [4, 0] = Vd. */
6476 unsigned full
= INSTR (30, 30);
6477 unsigned vm
= INSTR (20, 16);
6478 unsigned vn
= INSTR (9, 5);
6479 unsigned vd
= INSTR (4, 0);
6482 NYI_assert (29, 23, 0x5C);
6483 NYI_assert (21, 21, 1);
6484 NYI_assert (15, 10, 0x37);
6486 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
6492 for (i
= 0; i
< 2; i
++)
6493 aarch64_set_vec_double (cpu
, vd
, i
,
6494 aarch64_get_vec_double (cpu
, vn
, i
)
6495 * aarch64_get_vec_double (cpu
, vm
, i
));
6498 for (i
= 0; i
< (full
? 4 : 2); i
++)
6499 aarch64_set_vec_float (cpu
, vd
, i
,
6500 aarch64_get_vec_float (cpu
, vn
, i
)
6501 * aarch64_get_vec_float (cpu
, vm
, i
));
6505 do_vec_FADDP (sim_cpu
*cpu
)
6508 instr [30] = half(0)/full(1)
6509 instr [29,23] = 10 1110 0
6510 instr [22] = float(0)/double(1)
6513 instr [15,10] = 1101 01
6515 instr [4, 0] = Vd. */
6517 unsigned full
= INSTR (30, 30);
6518 unsigned vm
= INSTR (20, 16);
6519 unsigned vn
= INSTR (9, 5);
6520 unsigned vd
= INSTR (4, 0);
6522 NYI_assert (29, 23, 0x5C);
6523 NYI_assert (21, 21, 1);
6524 NYI_assert (15, 10, 0x35);
6526 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
6529 /* Extract values before adding them incase vd == vn/vm. */
6530 double tmp1
= aarch64_get_vec_double (cpu
, vn
, 0);
6531 double tmp2
= aarch64_get_vec_double (cpu
, vn
, 1);
6532 double tmp3
= aarch64_get_vec_double (cpu
, vm
, 0);
6533 double tmp4
= aarch64_get_vec_double (cpu
, vm
, 1);
6538 aarch64_set_vec_double (cpu
, vd
, 0, tmp1
+ tmp2
);
6539 aarch64_set_vec_double (cpu
, vd
, 1, tmp3
+ tmp4
);
6543 /* Extract values before adding them incase vd == vn/vm. */
6544 float tmp1
= aarch64_get_vec_float (cpu
, vn
, 0);
6545 float tmp2
= aarch64_get_vec_float (cpu
, vn
, 1);
6546 float tmp5
= aarch64_get_vec_float (cpu
, vm
, 0);
6547 float tmp6
= aarch64_get_vec_float (cpu
, vm
, 1);
6551 float tmp3
= aarch64_get_vec_float (cpu
, vn
, 2);
6552 float tmp4
= aarch64_get_vec_float (cpu
, vn
, 3);
6553 float tmp7
= aarch64_get_vec_float (cpu
, vm
, 2);
6554 float tmp8
= aarch64_get_vec_float (cpu
, vm
, 3);
6556 aarch64_set_vec_float (cpu
, vd
, 0, tmp1
+ tmp2
);
6557 aarch64_set_vec_float (cpu
, vd
, 1, tmp3
+ tmp4
);
6558 aarch64_set_vec_float (cpu
, vd
, 2, tmp5
+ tmp6
);
6559 aarch64_set_vec_float (cpu
, vd
, 3, tmp7
+ tmp8
);
6563 aarch64_set_vec_float (cpu
, vd
, 0, tmp1
+ tmp2
);
6564 aarch64_set_vec_float (cpu
, vd
, 1, tmp5
+ tmp6
);
6570 do_vec_FSQRT (sim_cpu
*cpu
)
6573 instr[30] = half(0)/full(1)
6574 instr[29,23] = 10 1110 1
6575 instr[22] = single(0)/double(1)
6576 instr[21,10] = 10 0001 1111 10
6578 instr[4,0] = Vdest. */
6580 unsigned vn
= INSTR (9, 5);
6581 unsigned vd
= INSTR (4, 0);
6582 unsigned full
= INSTR (30, 30);
6585 NYI_assert (29, 23, 0x5D);
6586 NYI_assert (21, 10, 0x87E);
6588 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
6594 for (i
= 0; i
< 2; i
++)
6595 aarch64_set_vec_double (cpu
, vd
, i
,
6596 sqrt (aarch64_get_vec_double (cpu
, vn
, i
)));
6600 for (i
= 0; i
< (full
? 4 : 2); i
++)
6601 aarch64_set_vec_float (cpu
, vd
, i
,
6602 sqrtf (aarch64_get_vec_float (cpu
, vn
, i
)));
6607 do_vec_FNEG (sim_cpu
*cpu
)
6610 instr[30] = half (0)/full (1)
6611 instr[29,23] = 10 1110 1
6612 instr[22] = single (0)/double (1)
6613 instr[21,10] = 10 0000 1111 10
6615 instr[4,0] = Vdest. */
6617 unsigned vn
= INSTR (9, 5);
6618 unsigned vd
= INSTR (4, 0);
6619 unsigned full
= INSTR (30, 30);
6622 NYI_assert (29, 23, 0x5D);
6623 NYI_assert (21, 10, 0x83E);
6625 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
6631 for (i
= 0; i
< 2; i
++)
6632 aarch64_set_vec_double (cpu
, vd
, i
,
6633 - aarch64_get_vec_double (cpu
, vn
, i
));
6637 for (i
= 0; i
< (full
? 4 : 2); i
++)
6638 aarch64_set_vec_float (cpu
, vd
, i
,
6639 - aarch64_get_vec_float (cpu
, vn
, i
));
6644 do_vec_NOT (sim_cpu
*cpu
)
6647 instr[30] = half (0)/full (1)
6648 instr[29,10] = 10 1110 0010 0000 0101 10
6652 unsigned vn
= INSTR (9, 5);
6653 unsigned vd
= INSTR (4, 0);
6655 int full
= INSTR (30, 30);
6657 NYI_assert (29, 10, 0xB8816);
6659 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
6660 for (i
= 0; i
< (full
? 16 : 8); i
++)
6661 aarch64_set_vec_u8 (cpu
, vd
, i
, ~ aarch64_get_vec_u8 (cpu
, vn
, i
));
6665 clz (uint64_t val
, unsigned size
)
6670 mask
<<= (size
- 1);
6685 do_vec_CLZ (sim_cpu
*cpu
)
6688 instr[30] = half (0)/full (1)
6689 instr[29,24] = 10 1110
6691 instr[21,10] = 10 0000 0100 10
6695 unsigned vn
= INSTR (9, 5);
6696 unsigned vd
= INSTR (4, 0);
6698 int full
= INSTR (30,30);
6700 NYI_assert (29, 24, 0x2E);
6701 NYI_assert (21, 10, 0x812);
6703 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
6704 switch (INSTR (23, 22))
6707 for (i
= 0; i
< (full
? 16 : 8); i
++)
6708 aarch64_set_vec_u8 (cpu
, vd
, i
, clz (aarch64_get_vec_u8 (cpu
, vn
, i
), 8));
6711 for (i
= 0; i
< (full
? 8 : 4); i
++)
6712 aarch64_set_vec_u16 (cpu
, vd
, i
, clz (aarch64_get_vec_u16 (cpu
, vn
, i
), 16));
6715 for (i
= 0; i
< (full
? 4 : 2); i
++)
6716 aarch64_set_vec_u32 (cpu
, vd
, i
, clz (aarch64_get_vec_u32 (cpu
, vn
, i
), 32));
6721 aarch64_set_vec_u64 (cpu
, vd
, 0, clz (aarch64_get_vec_u64 (cpu
, vn
, 0), 64));
6722 aarch64_set_vec_u64 (cpu
, vd
, 1, clz (aarch64_get_vec_u64 (cpu
, vn
, 1), 64));
6728 do_vec_MOV_element (sim_cpu
*cpu
)
6730 /* instr[31,21] = 0110 1110 000
6731 instr[20,16] = size & dest index
6733 instr[14,11] = source index
6738 unsigned vs
= INSTR (9, 5);
6739 unsigned vd
= INSTR (4, 0);
6743 NYI_assert (31, 21, 0x370);
6744 NYI_assert (15, 15, 0);
6745 NYI_assert (10, 10, 1);
6747 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
6751 src_index
= INSTR (14, 11);
6752 dst_index
= INSTR (20, 17);
6753 aarch64_set_vec_u8 (cpu
, vd
, dst_index
,
6754 aarch64_get_vec_u8 (cpu
, vs
, src_index
));
6756 else if (INSTR (17, 17))
6759 NYI_assert (11, 11, 0);
6760 src_index
= INSTR (14, 12);
6761 dst_index
= INSTR (20, 18);
6762 aarch64_set_vec_u16 (cpu
, vd
, dst_index
,
6763 aarch64_get_vec_u16 (cpu
, vs
, src_index
));
6765 else if (INSTR (18, 18))
6768 NYI_assert (12, 11, 0);
6769 src_index
= INSTR (14, 13);
6770 dst_index
= INSTR (20, 19);
6771 aarch64_set_vec_u32 (cpu
, vd
, dst_index
,
6772 aarch64_get_vec_u32 (cpu
, vs
, src_index
));
6776 NYI_assert (19, 19, 1);
6777 NYI_assert (13, 11, 0);
6778 src_index
= INSTR (14, 14);
6779 dst_index
= INSTR (20, 20);
6780 aarch64_set_vec_u64 (cpu
, vd
, dst_index
,
6781 aarch64_get_vec_u64 (cpu
, vs
, src_index
));
6786 do_vec_REV32 (sim_cpu
*cpu
)
6789 instr[30] = full/half
6790 instr[29,24] = 10 1110
6792 instr[21,10] = 10 0000 0000 10
6796 unsigned rn
= INSTR (9, 5);
6797 unsigned rd
= INSTR (4, 0);
6798 unsigned size
= INSTR (23, 22);
6799 unsigned full
= INSTR (30, 30);
6803 NYI_assert (29, 24, 0x2E);
6804 NYI_assert (21, 10, 0x802);
6806 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
6810 for (i
= 0; i
< (full
? 16 : 8); i
++)
6811 val
.b
[i
^ 0x3] = aarch64_get_vec_u8 (cpu
, rn
, i
);
6815 for (i
= 0; i
< (full
? 8 : 4); i
++)
6816 val
.h
[i
^ 0x1] = aarch64_get_vec_u16 (cpu
, rn
, i
);
6823 aarch64_set_vec_u64 (cpu
, rd
, 0, val
.v
[0]);
6825 aarch64_set_vec_u64 (cpu
, rd
, 1, val
.v
[1]);
6829 do_vec_EXT (sim_cpu
*cpu
)
6832 instr[30] = full/half
6833 instr[29,21] = 10 1110 000
6836 instr[14,11] = source index
6841 unsigned vm
= INSTR (20, 16);
6842 unsigned vn
= INSTR (9, 5);
6843 unsigned vd
= INSTR (4, 0);
6844 unsigned src_index
= INSTR (14, 11);
6845 unsigned full
= INSTR (30, 30);
6850 NYI_assert (31, 21, 0x370);
6851 NYI_assert (15, 15, 0);
6852 NYI_assert (10, 10, 0);
6854 if (!full
&& (src_index
& 0x8))
6859 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
6860 for (i
= src_index
; i
< (full
? 16 : 8); i
++)
6861 val
.b
[j
++] = aarch64_get_vec_u8 (cpu
, vn
, i
);
6862 for (i
= 0; i
< src_index
; i
++)
6863 val
.b
[j
++] = aarch64_get_vec_u8 (cpu
, vm
, i
);
6865 aarch64_set_vec_u64 (cpu
, vd
, 0, val
.v
[0]);
6867 aarch64_set_vec_u64 (cpu
, vd
, 1, val
.v
[1]);
6871 dexAdvSIMD0 (sim_cpu
*cpu
)
6873 /* instr [28,25] = 0 111. */
6874 if ( INSTR (15, 10) == 0x07
6878 if (INSTR (31, 21) == 0x075
6879 || INSTR (31, 21) == 0x275)
6881 do_vec_MOV_whole_vector (cpu
);
6886 if (INSTR (29, 19) == 0x1E0)
6888 do_vec_MOV_immediate (cpu
);
6892 if (INSTR (29, 19) == 0x5E0)
6898 if (INSTR (29, 19) == 0x1C0
6899 || INSTR (29, 19) == 0x1C1)
6901 if (INSTR (15, 10) == 0x03)
6903 do_vec_DUP_scalar_into_vector (cpu
);
6908 switch (INSTR (29, 24))
6910 case 0x0E: do_vec_op1 (cpu
); return;
6911 case 0x0F: do_vec_op2 (cpu
); return;
6914 if (INSTR (21, 21) == 1)
6916 switch (INSTR (15, 10))
6923 switch (INSTR (23, 22))
6925 case 0: do_vec_EOR (cpu
); return;
6926 case 1: do_vec_BSL (cpu
); return;
6928 case 3: do_vec_bit (cpu
); return;
6932 case 0x08: do_vec_sub_long (cpu
); return;
6933 case 0x11: do_vec_USHL (cpu
); return;
6934 case 0x12: do_vec_CLZ (cpu
); return;
6935 case 0x16: do_vec_NOT (cpu
); return;
6936 case 0x19: do_vec_max (cpu
); return;
6937 case 0x1B: do_vec_min (cpu
); return;
6938 case 0x21: do_vec_SUB (cpu
); return;
6939 case 0x25: do_vec_MLS (cpu
); return;
6940 case 0x31: do_vec_FminmaxNMP (cpu
); return;
6941 case 0x35: do_vec_FADDP (cpu
); return;
6942 case 0x37: do_vec_FMUL (cpu
); return;
6943 case 0x3F: do_vec_FDIV (cpu
); return;
6946 switch (INSTR (20, 16))
6948 case 0x00: do_vec_FNEG (cpu
); return;
6949 case 0x01: do_vec_FSQRT (cpu
); return;
6963 do_vec_compare (cpu
); return;
6970 if (INSTR (31, 21) == 0x370)
6973 do_vec_MOV_element (cpu
);
6979 switch (INSTR (21, 10))
6981 case 0x82E: do_vec_neg (cpu
); return;
6982 case 0x87E: do_vec_sqrt (cpu
); return;
6984 if (INSTR (15, 10) == 0x30)
6994 switch (INSTR (15, 10))
6996 case 0x01: do_vec_SSHR_USHR (cpu
); return;
6998 case 0x12: do_vec_mls_indexed (cpu
); return;
6999 case 0x29: do_vec_xtl (cpu
); return;
7013 /* Float multiply add. */
7015 fmadds (sim_cpu
*cpu
)
7017 unsigned sa
= INSTR (14, 10);
7018 unsigned sm
= INSTR (20, 16);
7019 unsigned sn
= INSTR ( 9, 5);
7020 unsigned sd
= INSTR ( 4, 0);
7022 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
7023 aarch64_set_FP_float (cpu
, sd
, aarch64_get_FP_float (cpu
, sa
)
7024 + aarch64_get_FP_float (cpu
, sn
)
7025 * aarch64_get_FP_float (cpu
, sm
));
7028 /* Double multiply add. */
7030 fmaddd (sim_cpu
*cpu
)
7032 unsigned sa
= INSTR (14, 10);
7033 unsigned sm
= INSTR (20, 16);
7034 unsigned sn
= INSTR ( 9, 5);
7035 unsigned sd
= INSTR ( 4, 0);
7037 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
7038 aarch64_set_FP_double (cpu
, sd
, aarch64_get_FP_double (cpu
, sa
)
7039 + aarch64_get_FP_double (cpu
, sn
)
7040 * aarch64_get_FP_double (cpu
, sm
));
7043 /* Float multiply subtract. */
7045 fmsubs (sim_cpu
*cpu
)
7047 unsigned sa
= INSTR (14, 10);
7048 unsigned sm
= INSTR (20, 16);
7049 unsigned sn
= INSTR ( 9, 5);
7050 unsigned sd
= INSTR ( 4, 0);
7052 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
7053 aarch64_set_FP_float (cpu
, sd
, aarch64_get_FP_float (cpu
, sa
)
7054 - aarch64_get_FP_float (cpu
, sn
)
7055 * aarch64_get_FP_float (cpu
, sm
));
7058 /* Double multiply subtract. */
7060 fmsubd (sim_cpu
*cpu
)
7062 unsigned sa
= INSTR (14, 10);
7063 unsigned sm
= INSTR (20, 16);
7064 unsigned sn
= INSTR ( 9, 5);
7065 unsigned sd
= INSTR ( 4, 0);
7067 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
7068 aarch64_set_FP_double (cpu
, sd
, aarch64_get_FP_double (cpu
, sa
)
7069 - aarch64_get_FP_double (cpu
, sn
)
7070 * aarch64_get_FP_double (cpu
, sm
));
7073 /* Float negative multiply add. */
7075 fnmadds (sim_cpu
*cpu
)
7077 unsigned sa
= INSTR (14, 10);
7078 unsigned sm
= INSTR (20, 16);
7079 unsigned sn
= INSTR ( 9, 5);
7080 unsigned sd
= INSTR ( 4, 0);
7082 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
7083 aarch64_set_FP_float (cpu
, sd
, - aarch64_get_FP_float (cpu
, sa
)
7084 + (- aarch64_get_FP_float (cpu
, sn
))
7085 * aarch64_get_FP_float (cpu
, sm
));
7088 /* Double negative multiply add. */
7090 fnmaddd (sim_cpu
*cpu
)
7092 unsigned sa
= INSTR (14, 10);
7093 unsigned sm
= INSTR (20, 16);
7094 unsigned sn
= INSTR ( 9, 5);
7095 unsigned sd
= INSTR ( 4, 0);
7097 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
7098 aarch64_set_FP_double (cpu
, sd
, - aarch64_get_FP_double (cpu
, sa
)
7099 + (- aarch64_get_FP_double (cpu
, sn
))
7100 * aarch64_get_FP_double (cpu
, sm
));
7103 /* Float negative multiply subtract. */
7105 fnmsubs (sim_cpu
*cpu
)
7107 unsigned sa
= INSTR (14, 10);
7108 unsigned sm
= INSTR (20, 16);
7109 unsigned sn
= INSTR ( 9, 5);
7110 unsigned sd
= INSTR ( 4, 0);
7112 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
7113 aarch64_set_FP_float (cpu
, sd
, - aarch64_get_FP_float (cpu
, sa
)
7114 + aarch64_get_FP_float (cpu
, sn
)
7115 * aarch64_get_FP_float (cpu
, sm
));
7118 /* Double negative multiply subtract. */
7120 fnmsubd (sim_cpu
*cpu
)
7122 unsigned sa
= INSTR (14, 10);
7123 unsigned sm
= INSTR (20, 16);
7124 unsigned sn
= INSTR ( 9, 5);
7125 unsigned sd
= INSTR ( 4, 0);
7127 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
7128 aarch64_set_FP_double (cpu
, sd
, - aarch64_get_FP_double (cpu
, sa
)
7129 + aarch64_get_FP_double (cpu
, sn
)
7130 * aarch64_get_FP_double (cpu
, sm
));
7134 dexSimpleFPDataProc3Source (sim_cpu
*cpu
)
7136 /* instr[31] ==> M : 0 ==> OK, 1 ==> UNALLOC
7138 instr[29] ==> S : 0 ==> OK, 1 ==> UNALLOC
7141 instr[23,22] ==> type : 0 ==> single, 01 ==> double, 1x ==> UNALLOC
7142 instr[21] ==> o1 : 0 ==> unnegated, 1 ==> negated
7143 instr[15] ==> o2 : 0 ==> ADD, 1 ==> SUB */
7145 uint32_t M_S
= (INSTR (31, 31) << 1) | INSTR (29, 29);
7146 /* dispatch on combined type:o1:o2. */
7147 uint32_t dispatch
= (INSTR (23, 21) << 1) | INSTR (15, 15);
7154 case 0: fmadds (cpu
); return;
7155 case 1: fmsubs (cpu
); return;
7156 case 2: fnmadds (cpu
); return;
7157 case 3: fnmsubs (cpu
); return;
7158 case 4: fmaddd (cpu
); return;
7159 case 5: fmsubd (cpu
); return;
7160 case 6: fnmaddd (cpu
); return;
7161 case 7: fnmsubd (cpu
); return;
7163 /* type > 1 is currently unallocated. */
7169 dexSimpleFPFixedConvert (sim_cpu
*cpu
)
7175 dexSimpleFPCondCompare (sim_cpu
*cpu
)
7177 /* instr [31,23] = 0001 1110 0
7181 instr [15,12] = condition
7185 instr [3,0] = nzcv */
7187 unsigned rm
= INSTR (20, 16);
7188 unsigned rn
= INSTR (9, 5);
7190 NYI_assert (31, 23, 0x3C);
7191 NYI_assert (11, 10, 0x1);
7192 NYI_assert (4, 4, 0);
7194 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
7195 if (! testConditionCode (cpu
, INSTR (15, 12)))
7197 aarch64_set_CPSR (cpu
, INSTR (3, 0));
7203 /* Double precision. */
7204 double val1
= aarch64_get_vec_double (cpu
, rn
, 0);
7205 double val2
= aarch64_get_vec_double (cpu
, rm
, 0);
7207 /* FIXME: Check for NaNs. */
7209 aarch64_set_CPSR (cpu
, (Z
| C
));
7210 else if (val1
< val2
)
7211 aarch64_set_CPSR (cpu
, N
);
7212 else /* val1 > val2 */
7213 aarch64_set_CPSR (cpu
, C
);
7217 /* Single precision. */
7218 float val1
= aarch64_get_vec_float (cpu
, rn
, 0);
7219 float val2
= aarch64_get_vec_float (cpu
, rm
, 0);
7221 /* FIXME: Check for NaNs. */
7223 aarch64_set_CPSR (cpu
, (Z
| C
));
7224 else if (val1
< val2
)
7225 aarch64_set_CPSR (cpu
, N
);
7226 else /* val1 > val2 */
7227 aarch64_set_CPSR (cpu
, C
);
7235 fadds (sim_cpu
*cpu
)
7237 unsigned sm
= INSTR (20, 16);
7238 unsigned sn
= INSTR ( 9, 5);
7239 unsigned sd
= INSTR ( 4, 0);
7241 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
7242 aarch64_set_FP_float (cpu
, sd
, aarch64_get_FP_float (cpu
, sn
)
7243 + aarch64_get_FP_float (cpu
, sm
));
7248 faddd (sim_cpu
*cpu
)
7250 unsigned sm
= INSTR (20, 16);
7251 unsigned sn
= INSTR ( 9, 5);
7252 unsigned sd
= INSTR ( 4, 0);
7254 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
7255 aarch64_set_FP_double (cpu
, sd
, aarch64_get_FP_double (cpu
, sn
)
7256 + aarch64_get_FP_double (cpu
, sm
));
7261 fdivs (sim_cpu
*cpu
)
7263 unsigned sm
= INSTR (20, 16);
7264 unsigned sn
= INSTR ( 9, 5);
7265 unsigned sd
= INSTR ( 4, 0);
7267 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
7268 aarch64_set_FP_float (cpu
, sd
, aarch64_get_FP_float (cpu
, sn
)
7269 / aarch64_get_FP_float (cpu
, sm
));
7272 /* Double divide. */
7274 fdivd (sim_cpu
*cpu
)
7276 unsigned sm
= INSTR (20, 16);
7277 unsigned sn
= INSTR ( 9, 5);
7278 unsigned sd
= INSTR ( 4, 0);
7280 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
7281 aarch64_set_FP_double (cpu
, sd
, aarch64_get_FP_double (cpu
, sn
)
7282 / aarch64_get_FP_double (cpu
, sm
));
7285 /* Float multiply. */
7287 fmuls (sim_cpu
*cpu
)
7289 unsigned sm
= INSTR (20, 16);
7290 unsigned sn
= INSTR ( 9, 5);
7291 unsigned sd
= INSTR ( 4, 0);
7293 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
7294 aarch64_set_FP_float (cpu
, sd
, aarch64_get_FP_float (cpu
, sn
)
7295 * aarch64_get_FP_float (cpu
, sm
));
7298 /* Double multiply. */
7300 fmuld (sim_cpu
*cpu
)
7302 unsigned sm
= INSTR (20, 16);
7303 unsigned sn
= INSTR ( 9, 5);
7304 unsigned sd
= INSTR ( 4, 0);
7306 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
7307 aarch64_set_FP_double (cpu
, sd
, aarch64_get_FP_double (cpu
, sn
)
7308 * aarch64_get_FP_double (cpu
, sm
));
7311 /* Float negate and multiply. */
7313 fnmuls (sim_cpu
*cpu
)
7315 unsigned sm
= INSTR (20, 16);
7316 unsigned sn
= INSTR ( 9, 5);
7317 unsigned sd
= INSTR ( 4, 0);
7319 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
7320 aarch64_set_FP_float (cpu
, sd
, - (aarch64_get_FP_float (cpu
, sn
)
7321 * aarch64_get_FP_float (cpu
, sm
)));
7324 /* Double negate and multiply. */
7326 fnmuld (sim_cpu
*cpu
)
7328 unsigned sm
= INSTR (20, 16);
7329 unsigned sn
= INSTR ( 9, 5);
7330 unsigned sd
= INSTR ( 4, 0);
7332 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
7333 aarch64_set_FP_double (cpu
, sd
, - (aarch64_get_FP_double (cpu
, sn
)
7334 * aarch64_get_FP_double (cpu
, sm
)));
7337 /* Float subtract. */
7339 fsubs (sim_cpu
*cpu
)
7341 unsigned sm
= INSTR (20, 16);
7342 unsigned sn
= INSTR ( 9, 5);
7343 unsigned sd
= INSTR ( 4, 0);
7345 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
7346 aarch64_set_FP_float (cpu
, sd
, aarch64_get_FP_float (cpu
, sn
)
7347 - aarch64_get_FP_float (cpu
, sm
));
7350 /* Double subtract. */
7352 fsubd (sim_cpu
*cpu
)
7354 unsigned sm
= INSTR (20, 16);
7355 unsigned sn
= INSTR ( 9, 5);
7356 unsigned sd
= INSTR ( 4, 0);
7358 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
7359 aarch64_set_FP_double (cpu
, sd
, aarch64_get_FP_double (cpu
, sn
)
7360 - aarch64_get_FP_double (cpu
, sm
));
7364 do_FMINNM (sim_cpu
*cpu
)
7366 /* instr[31,23] = 0 0011 1100
7367 instr[22] = float(0)/double(1)
7370 instr[15,10] = 01 1110
7374 unsigned sm
= INSTR (20, 16);
7375 unsigned sn
= INSTR ( 9, 5);
7376 unsigned sd
= INSTR ( 4, 0);
7378 NYI_assert (31, 23, 0x03C);
7379 NYI_assert (15, 10, 0x1E);
7381 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
7383 aarch64_set_FP_double (cpu
, sd
,
7384 dminnm (aarch64_get_FP_double (cpu
, sn
),
7385 aarch64_get_FP_double (cpu
, sm
)));
7387 aarch64_set_FP_float (cpu
, sd
,
7388 fminnm (aarch64_get_FP_float (cpu
, sn
),
7389 aarch64_get_FP_float (cpu
, sm
)));
7393 do_FMAXNM (sim_cpu
*cpu
)
7395 /* instr[31,23] = 0 0011 1100
7396 instr[22] = float(0)/double(1)
7399 instr[15,10] = 01 1010
7403 unsigned sm
= INSTR (20, 16);
7404 unsigned sn
= INSTR ( 9, 5);
7405 unsigned sd
= INSTR ( 4, 0);
7407 NYI_assert (31, 23, 0x03C);
7408 NYI_assert (15, 10, 0x1A);
7410 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
7412 aarch64_set_FP_double (cpu
, sd
,
7413 dmaxnm (aarch64_get_FP_double (cpu
, sn
),
7414 aarch64_get_FP_double (cpu
, sm
)));
7416 aarch64_set_FP_float (cpu
, sd
,
7417 fmaxnm (aarch64_get_FP_float (cpu
, sn
),
7418 aarch64_get_FP_float (cpu
, sm
)));
7422 dexSimpleFPDataProc2Source (sim_cpu
*cpu
)
7424 /* instr[31] ==> M : 0 ==> OK, 1 ==> UNALLOC
7426 instr[29] ==> S : 0 ==> OK, 1 ==> UNALLOC
7429 instr[23,22] ==> type : 0 ==> single, 01 ==> double, 1x ==> UNALLOC
7432 instr[15,12] ==> opcode : 0000 ==> FMUL, 0001 ==> FDIV
7433 0010 ==> FADD, 0011 ==> FSUB,
7434 0100 ==> FMAX, 0101 ==> FMIN
7435 0110 ==> FMAXNM, 0111 ==> FMINNM
7436 1000 ==> FNMUL, ow ==> UNALLOC
7441 uint32_t M_S
= (INSTR (31, 31) << 1) | INSTR (29, 29);
7442 uint32_t type
= INSTR (23, 22);
7443 /* Dispatch on opcode. */
7444 uint32_t dispatch
= INSTR (15, 12);
7455 case 0: fmuld (cpu
); return;
7456 case 1: fdivd (cpu
); return;
7457 case 2: faddd (cpu
); return;
7458 case 3: fsubd (cpu
); return;
7459 case 6: do_FMAXNM (cpu
); return;
7460 case 7: do_FMINNM (cpu
); return;
7461 case 8: fnmuld (cpu
); return;
7463 /* Have not yet implemented fmax and fmin. */
7471 else /* type == 0 => floats. */
7474 case 0: fmuls (cpu
); return;
7475 case 1: fdivs (cpu
); return;
7476 case 2: fadds (cpu
); return;
7477 case 3: fsubs (cpu
); return;
7478 case 6: do_FMAXNM (cpu
); return;
7479 case 7: do_FMINNM (cpu
); return;
7480 case 8: fnmuls (cpu
); return;
7492 dexSimpleFPCondSelect (sim_cpu
*cpu
)
7495 instr[31,23] = 0 0011 1100
7496 instr[22] = 0=>single 1=>double
7503 unsigned sm
= INSTR (20, 16);
7504 unsigned sn
= INSTR ( 9, 5);
7505 unsigned sd
= INSTR ( 4, 0);
7506 uint32_t set
= testConditionCode (cpu
, INSTR (15, 12));
7508 NYI_assert (31, 23, 0x03C);
7509 NYI_assert (11, 10, 0x3);
7511 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
7513 aarch64_set_FP_double (cpu
, sd
, (set
? aarch64_get_FP_double (cpu
, sn
)
7514 : aarch64_get_FP_double (cpu
, sm
)));
7516 aarch64_set_FP_float (cpu
, sd
, (set
? aarch64_get_FP_float (cpu
, sn
)
7517 : aarch64_get_FP_float (cpu
, sm
)));
7520 /* Store 32 bit unscaled signed 9 bit. */
7522 fsturs (sim_cpu
*cpu
, int32_t offset
)
7524 unsigned int rn
= INSTR (9, 5);
7525 unsigned int st
= INSTR (4, 0);
7527 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
7528 aarch64_set_mem_u32 (cpu
, aarch64_get_reg_u64 (cpu
, rn
, 1) + offset
,
7529 aarch64_get_vec_u32 (cpu
, st
, 0));
7532 /* Store 64 bit unscaled signed 9 bit. */
7534 fsturd (sim_cpu
*cpu
, int32_t offset
)
7536 unsigned int rn
= INSTR (9, 5);
7537 unsigned int st
= INSTR (4, 0);
7539 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
7540 aarch64_set_mem_u64 (cpu
, aarch64_get_reg_u64 (cpu
, rn
, 1) + offset
,
7541 aarch64_get_vec_u64 (cpu
, st
, 0));
7544 /* Store 128 bit unscaled signed 9 bit. */
7546 fsturq (sim_cpu
*cpu
, int32_t offset
)
7548 unsigned int rn
= INSTR (9, 5);
7549 unsigned int st
= INSTR (4, 0);
7552 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
7553 aarch64_get_FP_long_double (cpu
, st
, & a
);
7554 aarch64_set_mem_long_double (cpu
,
7555 aarch64_get_reg_u64 (cpu
, rn
, 1)
7559 /* TODO FP move register. */
7561 /* 32 bit fp to fp move register. */
7563 ffmovs (sim_cpu
*cpu
)
7565 unsigned int rn
= INSTR (9, 5);
7566 unsigned int st
= INSTR (4, 0);
7568 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
7569 aarch64_set_FP_float (cpu
, st
, aarch64_get_FP_float (cpu
, rn
));
7572 /* 64 bit fp to fp move register. */
7574 ffmovd (sim_cpu
*cpu
)
7576 unsigned int rn
= INSTR (9, 5);
7577 unsigned int st
= INSTR (4, 0);
7579 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
7580 aarch64_set_FP_double (cpu
, st
, aarch64_get_FP_double (cpu
, rn
));
7583 /* 32 bit GReg to Vec move register. */
7585 fgmovs (sim_cpu
*cpu
)
7587 unsigned int rn
= INSTR (9, 5);
7588 unsigned int st
= INSTR (4, 0);
7590 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
7591 aarch64_set_vec_u32 (cpu
, st
, 0, aarch64_get_reg_u32 (cpu
, rn
, NO_SP
));
7594 /* 64 bit g to fp move register. */
7596 fgmovd (sim_cpu
*cpu
)
7598 unsigned int rn
= INSTR (9, 5);
7599 unsigned int st
= INSTR (4, 0);
7601 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
7602 aarch64_set_vec_u64 (cpu
, st
, 0, aarch64_get_reg_u64 (cpu
, rn
, NO_SP
));
7605 /* 32 bit fp to g move register. */
7607 gfmovs (sim_cpu
*cpu
)
7609 unsigned int rn
= INSTR (9, 5);
7610 unsigned int st
= INSTR (4, 0);
7612 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
7613 aarch64_set_reg_u64 (cpu
, st
, NO_SP
, aarch64_get_vec_u32 (cpu
, rn
, 0));
7616 /* 64 bit fp to g move register. */
7618 gfmovd (sim_cpu
*cpu
)
7620 unsigned int rn
= INSTR (9, 5);
7621 unsigned int st
= INSTR (4, 0);
7623 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
7624 aarch64_set_reg_u64 (cpu
, st
, NO_SP
, aarch64_get_vec_u64 (cpu
, rn
, 0));
7627 /* FP move immediate
7629 These install an immediate 8 bit value in the target register
7630 where the 8 bits comprise 1 sign bit, 4 bits of fraction and a 3
7634 fmovs (sim_cpu
*cpu
)
7636 unsigned int sd
= INSTR (4, 0);
7637 uint32_t imm
= INSTR (20, 13);
7638 float f
= fp_immediate_for_encoding_32 (imm
);
7640 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
7641 aarch64_set_FP_float (cpu
, sd
, f
);
7645 fmovd (sim_cpu
*cpu
)
7647 unsigned int sd
= INSTR (4, 0);
7648 uint32_t imm
= INSTR (20, 13);
7649 double d
= fp_immediate_for_encoding_64 (imm
);
7651 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
7652 aarch64_set_FP_double (cpu
, sd
, d
);
7656 dexSimpleFPImmediate (sim_cpu
*cpu
)
7658 /* instr[31,23] == 00111100
7659 instr[22] == type : single(0)/double(1)
7661 instr[20,13] == imm8
7663 instr[9,5] == imm5 : 00000 ==> PK, ow ==> UNALLOC
7665 uint32_t imm5
= INSTR (9, 5);
7667 NYI_assert (31, 23, 0x3C);
7678 /* TODO specific decode and execute for group Load Store. */
7680 /* TODO FP load/store single register (unscaled offset). */
7682 /* TODO load 8 bit unscaled signed 9 bit. */
7683 /* TODO load 16 bit unscaled signed 9 bit. */
7685 /* Load 32 bit unscaled signed 9 bit. */
7687 fldurs (sim_cpu
*cpu
, int32_t offset
)
7689 unsigned int rn
= INSTR (9, 5);
7690 unsigned int st
= INSTR (4, 0);
7692 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
7693 aarch64_set_vec_u32 (cpu
, st
, 0, aarch64_get_mem_u32
7694 (cpu
, aarch64_get_reg_u64 (cpu
, rn
, SP_OK
) + offset
));
7697 /* Load 64 bit unscaled signed 9 bit. */
7699 fldurd (sim_cpu
*cpu
, int32_t offset
)
7701 unsigned int rn
= INSTR (9, 5);
7702 unsigned int st
= INSTR (4, 0);
7704 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
7705 aarch64_set_vec_u64 (cpu
, st
, 0, aarch64_get_mem_u64
7706 (cpu
, aarch64_get_reg_u64 (cpu
, rn
, SP_OK
) + offset
));
7709 /* Load 128 bit unscaled signed 9 bit. */
7711 fldurq (sim_cpu
*cpu
, int32_t offset
)
7713 unsigned int rn
= INSTR (9, 5);
7714 unsigned int st
= INSTR (4, 0);
7716 uint64_t addr
= aarch64_get_reg_u64 (cpu
, rn
, SP_OK
) + offset
;
7718 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
7719 aarch64_get_mem_long_double (cpu
, addr
, & a
);
7720 aarch64_set_FP_long_double (cpu
, st
, a
);
7723 /* TODO store 8 bit unscaled signed 9 bit. */
7724 /* TODO store 16 bit unscaled signed 9 bit. */
7729 /* Float absolute value. */
7731 fabss (sim_cpu
*cpu
)
7733 unsigned sn
= INSTR (9, 5);
7734 unsigned sd
= INSTR (4, 0);
7735 float value
= aarch64_get_FP_float (cpu
, sn
);
7737 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
7738 aarch64_set_FP_float (cpu
, sd
, fabsf (value
));
7741 /* Double absolute value. */
7743 fabcpu (sim_cpu
*cpu
)
7745 unsigned sn
= INSTR (9, 5);
7746 unsigned sd
= INSTR (4, 0);
7747 double value
= aarch64_get_FP_double (cpu
, sn
);
7749 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
7750 aarch64_set_FP_double (cpu
, sd
, fabs (value
));
7753 /* Float negative value. */
7755 fnegs (sim_cpu
*cpu
)
7757 unsigned sn
= INSTR (9, 5);
7758 unsigned sd
= INSTR (4, 0);
7760 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
7761 aarch64_set_FP_float (cpu
, sd
, - aarch64_get_FP_float (cpu
, sn
));
7764 /* Double negative value. */
7766 fnegd (sim_cpu
*cpu
)
7768 unsigned sn
= INSTR (9, 5);
7769 unsigned sd
= INSTR (4, 0);
7771 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
7772 aarch64_set_FP_double (cpu
, sd
, - aarch64_get_FP_double (cpu
, sn
));
7775 /* Float square root. */
7777 fsqrts (sim_cpu
*cpu
)
7779 unsigned sn
= INSTR (9, 5);
7780 unsigned sd
= INSTR (4, 0);
7782 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
7783 aarch64_set_FP_float (cpu
, sd
, sqrtf (aarch64_get_FP_float (cpu
, sn
)));
7786 /* Double square root. */
7788 fsqrtd (sim_cpu
*cpu
)
7790 unsigned sn
= INSTR (9, 5);
7791 unsigned sd
= INSTR (4, 0);
7793 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
7794 aarch64_set_FP_double (cpu
, sd
,
7795 sqrt (aarch64_get_FP_double (cpu
, sn
)));
7798 /* Convert double to float. */
7800 fcvtds (sim_cpu
*cpu
)
7802 unsigned sn
= INSTR (9, 5);
7803 unsigned sd
= INSTR (4, 0);
7805 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
7806 aarch64_set_FP_float (cpu
, sd
, (float) aarch64_get_FP_double (cpu
, sn
));
7809 /* Convert float to double. */
7811 fcvtcpu (sim_cpu
*cpu
)
7813 unsigned sn
= INSTR (9, 5);
7814 unsigned sd
= INSTR (4, 0);
7816 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
7817 aarch64_set_FP_double (cpu
, sd
, (double) aarch64_get_FP_float (cpu
, sn
));
7821 do_FRINT (sim_cpu
*cpu
)
7823 /* instr[31,23] = 0001 1110 0
7824 instr[22] = single(0)/double(1)
7826 instr[17,15] = rounding mode
7827 instr[14,10] = 10000
7829 instr[4,0] = dest */
7832 unsigned rs
= INSTR (9, 5);
7833 unsigned rd
= INSTR (4, 0);
7834 unsigned int rmode
= INSTR (17, 15);
7836 NYI_assert (31, 23, 0x03C);
7837 NYI_assert (21, 18, 0x9);
7838 NYI_assert (14, 10, 0x10);
7840 if (rmode
== 6 || rmode
== 7)
7841 /* FIXME: Add support for rmode == 6 exactness check. */
7842 rmode
= uimm (aarch64_get_FPSR (cpu
), 23, 22);
7844 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
7847 double val
= aarch64_get_FP_double (cpu
, rs
);
7851 case 0: /* mode N: nearest or even. */
7853 double rval
= round (val
);
7855 if (val
- rval
== 0.5)
7857 if (((rval
/ 2.0) * 2.0) != rval
)
7861 aarch64_set_FP_double (cpu
, rd
, round (val
));
7865 case 1: /* mode P: towards +inf. */
7867 aarch64_set_FP_double (cpu
, rd
, trunc (val
));
7869 aarch64_set_FP_double (cpu
, rd
, round (val
));
7872 case 2: /* mode M: towards -inf. */
7874 aarch64_set_FP_double (cpu
, rd
, round (val
));
7876 aarch64_set_FP_double (cpu
, rd
, trunc (val
));
7879 case 3: /* mode Z: towards 0. */
7880 aarch64_set_FP_double (cpu
, rd
, trunc (val
));
7883 case 4: /* mode A: away from 0. */
7884 aarch64_set_FP_double (cpu
, rd
, round (val
));
7887 case 6: /* mode X: use FPCR with exactness check. */
7888 case 7: /* mode I: use FPCR mode. */
7896 val
= aarch64_get_FP_float (cpu
, rs
);
7900 case 0: /* mode N: nearest or even. */
7902 float rval
= roundf (val
);
7904 if (val
- rval
== 0.5)
7906 if (((rval
/ 2.0) * 2.0) != rval
)
7910 aarch64_set_FP_float (cpu
, rd
, rval
);
7914 case 1: /* mode P: towards +inf. */
7916 aarch64_set_FP_float (cpu
, rd
, truncf (val
));
7918 aarch64_set_FP_float (cpu
, rd
, roundf (val
));
7921 case 2: /* mode M: towards -inf. */
7923 aarch64_set_FP_float (cpu
, rd
, truncf (val
));
7925 aarch64_set_FP_float (cpu
, rd
, roundf (val
));
7928 case 3: /* mode Z: towards 0. */
7929 aarch64_set_FP_float (cpu
, rd
, truncf (val
));
7932 case 4: /* mode A: away from 0. */
7933 aarch64_set_FP_float (cpu
, rd
, roundf (val
));
7936 case 6: /* mode X: use FPCR with exactness check. */
7937 case 7: /* mode I: use FPCR mode. */
7945 /* Convert half to float. */
7947 do_FCVT_half_to_single (sim_cpu
*cpu
)
7949 unsigned rn
= INSTR (9, 5);
7950 unsigned rd
= INSTR (4, 0);
7952 NYI_assert (31, 10, 0x7B890);
7954 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
7955 aarch64_set_FP_float (cpu
, rd
, (float) aarch64_get_FP_half (cpu
, rn
));
7958 /* Convert half to double. */
7960 do_FCVT_half_to_double (sim_cpu
*cpu
)
7962 unsigned rn
= INSTR (9, 5);
7963 unsigned rd
= INSTR (4, 0);
7965 NYI_assert (31, 10, 0x7B8B0);
7967 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
7968 aarch64_set_FP_double (cpu
, rd
, (double) aarch64_get_FP_half (cpu
, rn
));
7972 do_FCVT_single_to_half (sim_cpu
*cpu
)
7974 unsigned rn
= INSTR (9, 5);
7975 unsigned rd
= INSTR (4, 0);
7977 NYI_assert (31, 10, 0x788F0);
7979 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
7980 aarch64_set_FP_half (cpu
, rd
, aarch64_get_FP_float (cpu
, rn
));
7983 /* Convert double to half. */
7985 do_FCVT_double_to_half (sim_cpu
*cpu
)
7987 unsigned rn
= INSTR (9, 5);
7988 unsigned rd
= INSTR (4, 0);
7990 NYI_assert (31, 10, 0x798F0);
7992 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
7993 aarch64_set_FP_half (cpu
, rd
, (float) aarch64_get_FP_double (cpu
, rn
));
7997 dexSimpleFPDataProc1Source (sim_cpu
*cpu
)
7999 /* instr[31] ==> M : 0 ==> OK, 1 ==> UNALLOC
8001 instr[29] ==> S : 0 ==> OK, 1 ==> UNALLOC
8004 instr[23,22] ==> type : 00 ==> source is single,
8005 01 ==> source is double
8007 11 ==> UNALLOC or source is half
8009 instr[20,15] ==> opcode : with type 00 or 01
8010 000000 ==> FMOV, 000001 ==> FABS,
8011 000010 ==> FNEG, 000011 ==> FSQRT,
8012 000100 ==> UNALLOC, 000101 ==> FCVT,(to single/double)
8013 000110 ==> UNALLOC, 000111 ==> FCVT (to half)
8014 001000 ==> FRINTN, 001001 ==> FRINTP,
8015 001010 ==> FRINTM, 001011 ==> FRINTZ,
8016 001100 ==> FRINTA, 001101 ==> UNALLOC
8017 001110 ==> FRINTX, 001111 ==> FRINTI
8019 000100 ==> FCVT (half-to-single)
8020 000101 ==> FCVT (half-to-double)
8021 instr[14,10] = 10000. */
8023 uint32_t M_S
= (INSTR (31, 31) << 1) | INSTR (29, 29);
8024 uint32_t type
= INSTR (23, 22);
8025 uint32_t opcode
= INSTR (20, 15);
8033 do_FCVT_half_to_single (cpu
);
8034 else if (opcode
== 5)
8035 do_FCVT_half_to_double (cpu
);
8087 case 8: /* FRINTN etc. */
8099 do_FCVT_double_to_half (cpu
);
8101 do_FCVT_single_to_half (cpu
);
8112 /* 32 bit signed int to float. */
8114 scvtf32 (sim_cpu
*cpu
)
8116 unsigned rn
= INSTR (9, 5);
8117 unsigned sd
= INSTR (4, 0);
8119 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
8120 aarch64_set_FP_float
8121 (cpu
, sd
, (float) aarch64_get_reg_s32 (cpu
, rn
, NO_SP
));
8124 /* signed int to float. */
8126 scvtf (sim_cpu
*cpu
)
8128 unsigned rn
= INSTR (9, 5);
8129 unsigned sd
= INSTR (4, 0);
8131 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
8132 aarch64_set_FP_float
8133 (cpu
, sd
, (float) aarch64_get_reg_s64 (cpu
, rn
, NO_SP
));
8136 /* 32 bit signed int to double. */
8138 scvtd32 (sim_cpu
*cpu
)
8140 unsigned rn
= INSTR (9, 5);
8141 unsigned sd
= INSTR (4, 0);
8143 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
8144 aarch64_set_FP_double
8145 (cpu
, sd
, (double) aarch64_get_reg_s32 (cpu
, rn
, NO_SP
));
8148 /* signed int to double. */
8150 scvtd (sim_cpu
*cpu
)
8152 unsigned rn
= INSTR (9, 5);
8153 unsigned sd
= INSTR (4, 0);
8155 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
8156 aarch64_set_FP_double
8157 (cpu
, sd
, (double) aarch64_get_reg_s64 (cpu
, rn
, NO_SP
));
8160 static const float FLOAT_INT_MAX
= (float) INT_MAX
;
8161 static const float FLOAT_INT_MIN
= (float) INT_MIN
;
8162 static const double DOUBLE_INT_MAX
= (double) INT_MAX
;
8163 static const double DOUBLE_INT_MIN
= (double) INT_MIN
;
8164 static const float FLOAT_LONG_MAX
= (float) LONG_MAX
;
8165 static const float FLOAT_LONG_MIN
= (float) LONG_MIN
;
8166 static const double DOUBLE_LONG_MAX
= (double) LONG_MAX
;
8167 static const double DOUBLE_LONG_MIN
= (double) LONG_MIN
;
8171 static const float FLOAT_UINT_MAX
= (float) UINT_MAX
;
8172 static const float FLOAT_UINT_MIN
= (float) UINT_MIN
;
8173 static const double DOUBLE_UINT_MAX
= (double) UINT_MAX
;
8174 static const double DOUBLE_UINT_MIN
= (double) UINT_MIN
;
8175 static const float FLOAT_ULONG_MAX
= (float) ULONG_MAX
;
8176 static const float FLOAT_ULONG_MIN
= (float) ULONG_MIN
;
8177 static const double DOUBLE_ULONG_MAX
= (double) ULONG_MAX
;
8178 static const double DOUBLE_ULONG_MIN
= (double) ULONG_MIN
;
8180 /* Check for FP exception conditions:
8183 Out of Range raises IO and IX and saturates value
8184 Denormal raises ID and IX and sets to zero. */
8185 #define RAISE_EXCEPTIONS(F, VALUE, FTYPE, ITYPE) \
8188 switch (fpclassify (F)) \
8192 aarch64_set_FPSR (cpu, IO); \
8194 VALUE = ITYPE##_MAX; \
8196 VALUE = ITYPE##_MIN; \
8200 if (F >= FTYPE##_##ITYPE##_MAX) \
8202 aarch64_set_FPSR_bits (cpu, IO | IX, IO | IX); \
8203 VALUE = ITYPE##_MAX; \
8205 else if (F <= FTYPE##_##ITYPE##_MIN) \
8207 aarch64_set_FPSR_bits (cpu, IO | IX, IO | IX); \
8208 VALUE = ITYPE##_MIN; \
8212 case FP_SUBNORMAL: \
8213 aarch64_set_FPSR_bits (cpu, IO | IX | ID, IX | ID); \
8225 /* 32 bit convert float to signed int truncate towards zero. */
8227 fcvtszs32 (sim_cpu
*cpu
)
8229 unsigned sn
= INSTR (9, 5);
8230 unsigned rd
= INSTR (4, 0);
8231 /* TODO : check that this rounds toward zero. */
8232 float f
= aarch64_get_FP_float (cpu
, sn
);
8233 int32_t value
= (int32_t) f
;
8235 RAISE_EXCEPTIONS (f
, value
, FLOAT
, INT
);
8237 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
8238 /* Avoid sign extension to 64 bit. */
8239 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, (uint32_t) value
);
8242 /* 64 bit convert float to signed int truncate towards zero. */
8244 fcvtszs (sim_cpu
*cpu
)
8246 unsigned sn
= INSTR (9, 5);
8247 unsigned rd
= INSTR (4, 0);
8248 float f
= aarch64_get_FP_float (cpu
, sn
);
8249 int64_t value
= (int64_t) f
;
8251 RAISE_EXCEPTIONS (f
, value
, FLOAT
, LONG
);
8253 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
8254 aarch64_set_reg_s64 (cpu
, rd
, NO_SP
, value
);
8257 /* 32 bit convert double to signed int truncate towards zero. */
8259 fcvtszd32 (sim_cpu
*cpu
)
8261 unsigned sn
= INSTR (9, 5);
8262 unsigned rd
= INSTR (4, 0);
8263 /* TODO : check that this rounds toward zero. */
8264 double d
= aarch64_get_FP_double (cpu
, sn
);
8265 int32_t value
= (int32_t) d
;
8267 RAISE_EXCEPTIONS (d
, value
, DOUBLE
, INT
);
8269 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
8270 /* Avoid sign extension to 64 bit. */
8271 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, (uint32_t) value
);
8274 /* 64 bit convert double to signed int truncate towards zero. */
8276 fcvtszd (sim_cpu
*cpu
)
8278 unsigned sn
= INSTR (9, 5);
8279 unsigned rd
= INSTR (4, 0);
8280 /* TODO : check that this rounds toward zero. */
8281 double d
= aarch64_get_FP_double (cpu
, sn
);
8284 value
= (int64_t) d
;
8286 RAISE_EXCEPTIONS (d
, value
, DOUBLE
, LONG
);
8288 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
8289 aarch64_set_reg_s64 (cpu
, rd
, NO_SP
, value
);
8293 do_fcvtzu (sim_cpu
*cpu
)
8295 /* instr[31] = size: 32-bit (0), 64-bit (1)
8296 instr[30,23] = 00111100
8297 instr[22] = type: single (0)/ double (1)
8298 instr[21] = enable (0)/disable(1) precision
8299 instr[20,16] = 11001
8300 instr[15,10] = precision
8304 unsigned rs
= INSTR (9, 5);
8305 unsigned rd
= INSTR (4, 0);
8307 NYI_assert (30, 23, 0x3C);
8308 NYI_assert (20, 16, 0x19);
8310 if (INSTR (21, 21) != 1)
8311 /* Convert to fixed point. */
8314 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
8317 /* Convert to unsigned 64-bit integer. */
8320 double d
= aarch64_get_FP_double (cpu
, rs
);
8321 uint64_t value
= (uint64_t) d
;
8323 /* Do not raise an exception if we have reached ULONG_MAX. */
8324 if (value
!= (1UL << 63))
8325 RAISE_EXCEPTIONS (d
, value
, DOUBLE
, ULONG
);
8327 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, value
);
8331 float f
= aarch64_get_FP_float (cpu
, rs
);
8332 uint64_t value
= (uint64_t) f
;
8334 /* Do not raise an exception if we have reached ULONG_MAX. */
8335 if (value
!= (1UL << 63))
8336 RAISE_EXCEPTIONS (f
, value
, FLOAT
, ULONG
);
8338 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, value
);
8345 /* Convert to unsigned 32-bit integer. */
8348 double d
= aarch64_get_FP_double (cpu
, rs
);
8350 value
= (uint32_t) d
;
8351 /* Do not raise an exception if we have reached UINT_MAX. */
8352 if (value
!= (1UL << 31))
8353 RAISE_EXCEPTIONS (d
, value
, DOUBLE
, UINT
);
8357 float f
= aarch64_get_FP_float (cpu
, rs
);
8359 value
= (uint32_t) f
;
8360 /* Do not raise an exception if we have reached UINT_MAX. */
8361 if (value
!= (1UL << 31))
8362 RAISE_EXCEPTIONS (f
, value
, FLOAT
, UINT
);
8365 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, value
);
8370 do_UCVTF (sim_cpu
*cpu
)
8372 /* instr[31] = size: 32-bit (0), 64-bit (1)
8373 instr[30,23] = 001 1110 0
8374 instr[22] = type: single (0)/ double (1)
8375 instr[21] = enable (0)/disable(1) precision
8376 instr[20,16] = 0 0011
8377 instr[15,10] = precision
8381 unsigned rs
= INSTR (9, 5);
8382 unsigned rd
= INSTR (4, 0);
8384 NYI_assert (30, 23, 0x3C);
8385 NYI_assert (20, 16, 0x03);
8387 if (INSTR (21, 21) != 1)
8390 /* FIXME: Add exception raising. */
8391 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
8394 uint64_t value
= aarch64_get_reg_u64 (cpu
, rs
, NO_SP
);
8397 aarch64_set_FP_double (cpu
, rd
, (double) value
);
8399 aarch64_set_FP_float (cpu
, rd
, (float) value
);
8403 uint32_t value
= aarch64_get_reg_u32 (cpu
, rs
, NO_SP
);
8406 aarch64_set_FP_double (cpu
, rd
, (double) value
);
8408 aarch64_set_FP_float (cpu
, rd
, (float) value
);
8413 float_vector_move (sim_cpu
*cpu
)
8415 /* instr[31,17] == 100 1111 0101 0111
8416 instr[16] ==> direction 0=> to GR, 1=> from GR
8418 instr[9,5] ==> source
8419 instr[4,0] ==> dest. */
8421 unsigned rn
= INSTR (9, 5);
8422 unsigned rd
= INSTR (4, 0);
8424 NYI_assert (31, 17, 0x4F57);
8426 if (INSTR (15, 10) != 0)
8429 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
8431 aarch64_set_vec_u64 (cpu
, rd
, 1, aarch64_get_reg_u64 (cpu
, rn
, NO_SP
));
8433 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, aarch64_get_vec_u64 (cpu
, rn
, 1));
8437 dexSimpleFPIntegerConvert (sim_cpu
*cpu
)
8439 /* instr[31] = size : 0 ==> 32 bit, 1 ==> 64 bit
8441 instr[29] = S : 0 ==> OK, 1 ==> UNALLOC
8444 instr[23,22] = type : 00 ==> single, 01 ==> double, 1x ==> UNALLOC
8446 instr[20,19] = rmode
8447 instr[18,16] = opcode
8448 instr[15,10] = 10 0000 */
8450 uint32_t rmode_opcode
;
8456 if (INSTR (31, 17) == 0x4F57)
8458 float_vector_move (cpu
);
8462 size
= INSTR (31, 31);
8467 type
= INSTR (23, 22);
8471 rmode_opcode
= INSTR (20, 16);
8472 size_type
= (size
<< 1) | type
; /* 0==32f, 1==32d, 2==64f, 3==64d. */
8474 switch (rmode_opcode
)
8476 case 2: /* SCVTF. */
8479 case 0: scvtf32 (cpu
); return;
8480 case 1: scvtd32 (cpu
); return;
8481 case 2: scvtf (cpu
); return;
8482 case 3: scvtd (cpu
); return;
8485 case 6: /* FMOV GR, Vec. */
8488 case 0: gfmovs (cpu
); return;
8489 case 3: gfmovd (cpu
); return;
8490 default: HALT_UNALLOC
;
8493 case 7: /* FMOV vec, GR. */
8496 case 0: fgmovs (cpu
); return;
8497 case 3: fgmovd (cpu
); return;
8498 default: HALT_UNALLOC
;
8501 case 24: /* FCVTZS. */
8504 case 0: fcvtszs32 (cpu
); return;
8505 case 1: fcvtszd32 (cpu
); return;
8506 case 2: fcvtszs (cpu
); return;
8507 case 3: fcvtszd (cpu
); return;
8510 case 25: do_fcvtzu (cpu
); return;
8511 case 3: do_UCVTF (cpu
); return;
8513 case 0: /* FCVTNS. */
8514 case 1: /* FCVTNU. */
8515 case 4: /* FCVTAS. */
8516 case 5: /* FCVTAU. */
8517 case 8: /* FCVPTS. */
8518 case 9: /* FCVTPU. */
8519 case 16: /* FCVTMS. */
8520 case 17: /* FCVTMU. */
8527 set_flags_for_float_compare (sim_cpu
*cpu
, float fvalue1
, float fvalue2
)
8531 /* FIXME: Add exception raising. */
8532 if (isnan (fvalue1
) || isnan (fvalue2
))
8534 else if (isinf (fvalue1
) && isinf (fvalue2
))
8536 /* Subtracting two infinities may give a NaN. We only need to compare
8537 the signs, which we can get from isinf. */
8538 int result
= isinf (fvalue1
) - isinf (fvalue2
);
8542 else if (result
< 0)
8544 else /* (result > 0). */
8549 float result
= fvalue1
- fvalue2
;
8553 else if (result
< 0)
8555 else /* (result > 0). */
8559 aarch64_set_CPSR (cpu
, flags
);
8563 fcmps (sim_cpu
*cpu
)
8565 unsigned sm
= INSTR (20, 16);
8566 unsigned sn
= INSTR ( 9, 5);
8568 float fvalue1
= aarch64_get_FP_float (cpu
, sn
);
8569 float fvalue2
= aarch64_get_FP_float (cpu
, sm
);
8571 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
8572 set_flags_for_float_compare (cpu
, fvalue1
, fvalue2
);
8575 /* Float compare to zero -- Invalid Operation exception
8576 only on signaling NaNs. */
8578 fcmpzs (sim_cpu
*cpu
)
8580 unsigned sn
= INSTR ( 9, 5);
8581 float fvalue1
= aarch64_get_FP_float (cpu
, sn
);
8583 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
8584 set_flags_for_float_compare (cpu
, fvalue1
, 0.0f
);
8587 /* Float compare -- Invalid Operation exception on all NaNs. */
8589 fcmpes (sim_cpu
*cpu
)
8591 unsigned sm
= INSTR (20, 16);
8592 unsigned sn
= INSTR ( 9, 5);
8594 float fvalue1
= aarch64_get_FP_float (cpu
, sn
);
8595 float fvalue2
= aarch64_get_FP_float (cpu
, sm
);
8597 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
8598 set_flags_for_float_compare (cpu
, fvalue1
, fvalue2
);
8601 /* Float compare to zero -- Invalid Operation exception on all NaNs. */
8603 fcmpzes (sim_cpu
*cpu
)
8605 unsigned sn
= INSTR ( 9, 5);
8606 float fvalue1
= aarch64_get_FP_float (cpu
, sn
);
8608 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
8609 set_flags_for_float_compare (cpu
, fvalue1
, 0.0f
);
8613 set_flags_for_double_compare (sim_cpu
*cpu
, double dval1
, double dval2
)
8617 /* FIXME: Add exception raising. */
8618 if (isnan (dval1
) || isnan (dval2
))
8620 else if (isinf (dval1
) && isinf (dval2
))
8622 /* Subtracting two infinities may give a NaN. We only need to compare
8623 the signs, which we can get from isinf. */
8624 int result
= isinf (dval1
) - isinf (dval2
);
8628 else if (result
< 0)
8630 else /* (result > 0). */
8635 double result
= dval1
- dval2
;
8639 else if (result
< 0)
8641 else /* (result > 0). */
8645 aarch64_set_CPSR (cpu
, flags
);
8648 /* Double compare -- Invalid Operation exception only on signaling NaNs. */
8650 fcmpd (sim_cpu
*cpu
)
8652 unsigned sm
= INSTR (20, 16);
8653 unsigned sn
= INSTR ( 9, 5);
8655 double dvalue1
= aarch64_get_FP_double (cpu
, sn
);
8656 double dvalue2
= aarch64_get_FP_double (cpu
, sm
);
8658 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
8659 set_flags_for_double_compare (cpu
, dvalue1
, dvalue2
);
8662 /* Double compare to zero -- Invalid Operation exception
8663 only on signaling NaNs. */
8665 fcmpzd (sim_cpu
*cpu
)
8667 unsigned sn
= INSTR ( 9, 5);
8668 double dvalue1
= aarch64_get_FP_double (cpu
, sn
);
8670 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
8671 set_flags_for_double_compare (cpu
, dvalue1
, 0.0);
8674 /* Double compare -- Invalid Operation exception on all NaNs. */
8676 fcmped (sim_cpu
*cpu
)
8678 unsigned sm
= INSTR (20, 16);
8679 unsigned sn
= INSTR ( 9, 5);
8681 double dvalue1
= aarch64_get_FP_double (cpu
, sn
);
8682 double dvalue2
= aarch64_get_FP_double (cpu
, sm
);
8684 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
8685 set_flags_for_double_compare (cpu
, dvalue1
, dvalue2
);
8688 /* Double compare to zero -- Invalid Operation exception on all NaNs. */
8690 fcmpzed (sim_cpu
*cpu
)
8692 unsigned sn
= INSTR ( 9, 5);
8693 double dvalue1
= aarch64_get_FP_double (cpu
, sn
);
8695 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
8696 set_flags_for_double_compare (cpu
, dvalue1
, 0.0);
8700 dexSimpleFPCompare (sim_cpu
*cpu
)
8702 /* assert instr[28,25] == 1111
8703 instr[30:24:21:13,10] = 0011000
8704 instr[31] = M : 0 ==> OK, 1 ==> UNALLOC
8705 instr[29] ==> S : 0 ==> OK, 1 ==> UNALLOC
8706 instr[23,22] ==> type : 0 ==> single, 01 ==> double, 1x ==> UNALLOC
8707 instr[15,14] ==> op : 00 ==> OK, ow ==> UNALLOC
8708 instr[4,0] ==> opcode2 : 00000 ==> FCMP, 10000 ==> FCMPE,
8709 01000 ==> FCMPZ, 11000 ==> FCMPEZ,
8712 uint32_t M_S
= (INSTR (31, 31) << 1) | INSTR (29, 29);
8713 uint32_t type
= INSTR (23, 22);
8714 uint32_t op
= INSTR (15, 14);
8715 uint32_t op2_2_0
= INSTR (2, 0);
8729 /* dispatch on type and top 2 bits of opcode. */
8730 dispatch
= (type
<< 2) | INSTR (4, 3);
8734 case 0: fcmps (cpu
); return;
8735 case 1: fcmpzs (cpu
); return;
8736 case 2: fcmpes (cpu
); return;
8737 case 3: fcmpzes (cpu
); return;
8738 case 4: fcmpd (cpu
); return;
8739 case 5: fcmpzd (cpu
); return;
8740 case 6: fcmped (cpu
); return;
8741 case 7: fcmpzed (cpu
); return;
8746 do_scalar_FADDP (sim_cpu
*cpu
)
8748 /* instr [31,23] = 0111 1110 0
8749 instr [22] = single(0)/double(1)
8750 instr [21,10] = 11 0000 1101 10
8752 instr [4,0] = Fd. */
8754 unsigned Fn
= INSTR (9, 5);
8755 unsigned Fd
= INSTR (4, 0);
8757 NYI_assert (31, 23, 0x0FC);
8758 NYI_assert (21, 10, 0xC36);
8760 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
8763 double val1
= aarch64_get_vec_double (cpu
, Fn
, 0);
8764 double val2
= aarch64_get_vec_double (cpu
, Fn
, 1);
8766 aarch64_set_FP_double (cpu
, Fd
, val1
+ val2
);
8770 float val1
= aarch64_get_vec_float (cpu
, Fn
, 0);
8771 float val2
= aarch64_get_vec_float (cpu
, Fn
, 1);
8773 aarch64_set_FP_float (cpu
, Fd
, val1
+ val2
);
8777 /* Floating point absolute difference. */
8780 do_scalar_FABD (sim_cpu
*cpu
)
8782 /* instr [31,23] = 0111 1110 1
8783 instr [22] = float(0)/double(1)
8786 instr [15,10] = 1101 01
8788 instr [4, 0] = Rd. */
8790 unsigned rm
= INSTR (20, 16);
8791 unsigned rn
= INSTR (9, 5);
8792 unsigned rd
= INSTR (4, 0);
8794 NYI_assert (31, 23, 0x0FD);
8795 NYI_assert (21, 21, 1);
8796 NYI_assert (15, 10, 0x35);
8798 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
8800 aarch64_set_FP_double (cpu
, rd
,
8801 fabs (aarch64_get_FP_double (cpu
, rn
)
8802 - aarch64_get_FP_double (cpu
, rm
)));
8804 aarch64_set_FP_float (cpu
, rd
,
8805 fabsf (aarch64_get_FP_float (cpu
, rn
)
8806 - aarch64_get_FP_float (cpu
, rm
)));
8810 do_scalar_CMGT (sim_cpu
*cpu
)
8812 /* instr [31,21] = 0101 1110 111
8814 instr [15,10] = 00 1101
8816 instr [4, 0] = Rd. */
8818 unsigned rm
= INSTR (20, 16);
8819 unsigned rn
= INSTR (9, 5);
8820 unsigned rd
= INSTR (4, 0);
8822 NYI_assert (31, 21, 0x2F7);
8823 NYI_assert (15, 10, 0x0D);
8825 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
8826 aarch64_set_vec_u64 (cpu
, rd
, 0,
8827 aarch64_get_vec_u64 (cpu
, rn
, 0) >
8828 aarch64_get_vec_u64 (cpu
, rm
, 0) ? -1L : 0L);
8832 do_scalar_USHR (sim_cpu
*cpu
)
8834 /* instr [31,23] = 0111 1111 0
8835 instr [22,16] = shift amount
8836 instr [15,10] = 0000 01
8838 instr [4, 0] = Rd. */
8840 unsigned amount
= 128 - INSTR (22, 16);
8841 unsigned rn
= INSTR (9, 5);
8842 unsigned rd
= INSTR (4, 0);
8844 NYI_assert (31, 23, 0x0FE);
8845 NYI_assert (15, 10, 0x01);
8847 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
8848 aarch64_set_vec_u64 (cpu
, rd
, 0,
8849 aarch64_get_vec_u64 (cpu
, rn
, 0) >> amount
);
8853 do_scalar_SSHL (sim_cpu
*cpu
)
8855 /* instr [31,21] = 0101 1110 111
8857 instr [15,10] = 0100 01
8859 instr [4, 0] = Rd. */
8861 unsigned rm
= INSTR (20, 16);
8862 unsigned rn
= INSTR (9, 5);
8863 unsigned rd
= INSTR (4, 0);
8864 signed int shift
= aarch64_get_vec_s8 (cpu
, rm
, 0);
8866 NYI_assert (31, 21, 0x2F7);
8867 NYI_assert (15, 10, 0x11);
8869 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
8871 aarch64_set_vec_s64 (cpu
, rd
, 0,
8872 aarch64_get_vec_s64 (cpu
, rn
, 0) << shift
);
8874 aarch64_set_vec_s64 (cpu
, rd
, 0,
8875 aarch64_get_vec_s64 (cpu
, rn
, 0) >> - shift
);
8879 do_scalar_shift (sim_cpu
*cpu
)
8881 /* instr [31,23] = 0101 1111 0
8882 instr [22,16] = shift amount
8883 instr [15,10] = 0101 01 [SHL]
8884 instr [15,10] = 0000 01 [SSHR]
8886 instr [4, 0] = Rd. */
8888 unsigned rn
= INSTR (9, 5);
8889 unsigned rd
= INSTR (4, 0);
8892 NYI_assert (31, 23, 0x0BE);
8894 if (INSTR (22, 22) == 0)
8897 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
8898 switch (INSTR (15, 10))
8900 case 0x01: /* SSHR */
8901 amount
= 128 - INSTR (22, 16);
8902 aarch64_set_vec_s64 (cpu
, rd
, 0,
8903 aarch64_get_vec_s64 (cpu
, rn
, 0) >> amount
);
8905 case 0x15: /* SHL */
8906 amount
= INSTR (22, 16) - 64;
8907 aarch64_set_vec_u64 (cpu
, rd
, 0,
8908 aarch64_get_vec_u64 (cpu
, rn
, 0) << amount
);
8915 /* FCMEQ FCMGT FCMGE. */
8917 do_scalar_FCM (sim_cpu
*cpu
)
8919 /* instr [31,30] = 01
8921 instr [28,24] = 1 1110
8926 instr [15,12] = 1110
8930 instr [4, 0] = Rd. */
8932 unsigned rm
= INSTR (20, 16);
8933 unsigned rn
= INSTR (9, 5);
8934 unsigned rd
= INSTR (4, 0);
8935 unsigned EUac
= (INSTR (23, 23) << 2) | (INSTR (29, 29) << 1) | INSTR (11, 11);
8940 NYI_assert (31, 30, 1);
8941 NYI_assert (28, 24, 0x1E);
8942 NYI_assert (21, 21, 1);
8943 NYI_assert (15, 12, 0xE);
8944 NYI_assert (10, 10, 1);
8946 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
8949 double val1
= aarch64_get_FP_double (cpu
, rn
);
8950 double val2
= aarch64_get_FP_double (cpu
, rm
);
8955 result
= val1
== val2
;
8963 result
= val1
>= val2
;
8971 result
= val1
> val2
;
8978 aarch64_set_vec_u32 (cpu
, rd
, 0, result
? -1 : 0);
8982 val1
= aarch64_get_FP_float (cpu
, rn
);
8983 val2
= aarch64_get_FP_float (cpu
, rm
);
8988 result
= val1
== val2
;
8992 val1
= fabsf (val1
);
8993 val2
= fabsf (val2
);
8996 result
= val1
>= val2
;
9000 val1
= fabsf (val1
);
9001 val2
= fabsf (val2
);
9004 result
= val1
> val2
;
9011 aarch64_set_vec_u32 (cpu
, rd
, 0, result
? -1 : 0);
9014 /* An alias of DUP. */
9016 do_scalar_MOV (sim_cpu
*cpu
)
9018 /* instr [31,21] = 0101 1110 000
9019 instr [20,16] = imm5
9020 instr [15,10] = 0000 01
9022 instr [4, 0] = Rd. */
9024 unsigned rn
= INSTR (9, 5);
9025 unsigned rd
= INSTR (4, 0);
9028 NYI_assert (31, 21, 0x2F0);
9029 NYI_assert (15, 10, 0x01);
9031 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
9035 index
= INSTR (20, 17);
9037 (cpu
, rd
, 0, aarch64_get_vec_u8 (cpu
, rn
, index
));
9039 else if (INSTR (17, 17))
9042 index
= INSTR (20, 18);
9044 (cpu
, rd
, 0, aarch64_get_vec_u16 (cpu
, rn
, index
));
9046 else if (INSTR (18, 18))
9049 index
= INSTR (20, 19);
9051 (cpu
, rd
, 0, aarch64_get_vec_u32 (cpu
, rn
, index
));
9053 else if (INSTR (19, 19))
9056 index
= INSTR (20, 20);
9058 (cpu
, rd
, 0, aarch64_get_vec_u64 (cpu
, rn
, index
));
9065 do_scalar_NEG (sim_cpu
*cpu
)
9067 /* instr [31,10] = 0111 1110 1110 0000 1011 10
9069 instr [4, 0] = Rd. */
9071 unsigned rn
= INSTR (9, 5);
9072 unsigned rd
= INSTR (4, 0);
9074 NYI_assert (31, 10, 0x1FB82E);
9076 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
9077 aarch64_set_vec_u64 (cpu
, rd
, 0, - aarch64_get_vec_u64 (cpu
, rn
, 0));
9081 do_scalar_USHL (sim_cpu
*cpu
)
9083 /* instr [31,21] = 0111 1110 111
9085 instr [15,10] = 0100 01
9087 instr [4, 0] = Rd. */
9089 unsigned rm
= INSTR (20, 16);
9090 unsigned rn
= INSTR (9, 5);
9091 unsigned rd
= INSTR (4, 0);
9092 signed int shift
= aarch64_get_vec_s8 (cpu
, rm
, 0);
9094 NYI_assert (31, 21, 0x3F7);
9095 NYI_assert (15, 10, 0x11);
9097 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
9099 aarch64_set_vec_u64 (cpu
, rd
, 0, aarch64_get_vec_u64 (cpu
, rn
, 0) << shift
);
9101 aarch64_set_vec_u64 (cpu
, rd
, 0, aarch64_get_vec_u64 (cpu
, rn
, 0) >> - shift
);
9105 do_double_add (sim_cpu
*cpu
)
9107 /* instr [31,21] = 0101 1110 111
9109 instr [15,10] = 1000 01
9111 instr [4,0] = Fd. */
9118 NYI_assert (31, 21, 0x2F7);
9119 NYI_assert (15, 10, 0x21);
9123 Fn
= INSTR (20, 16);
9125 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
9126 val1
= aarch64_get_FP_double (cpu
, Fm
);
9127 val2
= aarch64_get_FP_double (cpu
, Fn
);
9129 aarch64_set_FP_double (cpu
, Fd
, val1
+ val2
);
9133 do_scalar_UCVTF (sim_cpu
*cpu
)
9135 /* instr [31,23] = 0111 1110 0
9136 instr [22] = single(0)/double(1)
9137 instr [21,10] = 10 0001 1101 10
9139 instr [4,0] = rd. */
9141 unsigned rn
= INSTR (9, 5);
9142 unsigned rd
= INSTR (4, 0);
9144 NYI_assert (31, 23, 0x0FC);
9145 NYI_assert (21, 10, 0x876);
9147 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
9150 uint64_t val
= aarch64_get_vec_u64 (cpu
, rn
, 0);
9152 aarch64_set_vec_double (cpu
, rd
, 0, (double) val
);
9156 uint32_t val
= aarch64_get_vec_u32 (cpu
, rn
, 0);
9158 aarch64_set_vec_float (cpu
, rd
, 0, (float) val
);
9163 do_scalar_vec (sim_cpu
*cpu
)
9165 /* instr [30] = 1. */
9166 /* instr [28,25] = 1111. */
9167 switch (INSTR (31, 23))
9170 switch (INSTR (15, 10))
9172 case 0x01: do_scalar_MOV (cpu
); return;
9173 case 0x39: do_scalar_FCM (cpu
); return;
9174 case 0x3B: do_scalar_FCM (cpu
); return;
9178 case 0xBE: do_scalar_shift (cpu
); return;
9181 switch (INSTR (15, 10))
9184 switch (INSTR (21, 16))
9186 case 0x30: do_scalar_FADDP (cpu
); return;
9187 case 0x21: do_scalar_UCVTF (cpu
); return;
9190 case 0x39: do_scalar_FCM (cpu
); return;
9191 case 0x3B: do_scalar_FCM (cpu
); return;
9196 switch (INSTR (15, 10))
9198 case 0x0D: do_scalar_CMGT (cpu
); return;
9199 case 0x11: do_scalar_USHL (cpu
); return;
9200 case 0x2E: do_scalar_NEG (cpu
); return;
9201 case 0x35: do_scalar_FABD (cpu
); return;
9202 case 0x39: do_scalar_FCM (cpu
); return;
9203 case 0x3B: do_scalar_FCM (cpu
); return;
9208 case 0xFE: do_scalar_USHR (cpu
); return;
9211 switch (INSTR (15, 10))
9213 case 0x21: do_double_add (cpu
); return;
9214 case 0x11: do_scalar_SSHL (cpu
); return;
9225 dexAdvSIMD1 (sim_cpu
*cpu
)
9227 /* instr [28,25] = 1 111. */
9229 /* We are currently only interested in the basic
9230 scalar fp routines which all have bit 30 = 0. */
9232 do_scalar_vec (cpu
);
9234 /* instr[24] is set for FP data processing 3-source and clear for
9235 all other basic scalar fp instruction groups. */
9236 else if (INSTR (24, 24))
9237 dexSimpleFPDataProc3Source (cpu
);
9239 /* instr[21] is clear for floating <-> fixed conversions and set for
9240 all other basic scalar fp instruction groups. */
9241 else if (!INSTR (21, 21))
9242 dexSimpleFPFixedConvert (cpu
);
9244 /* instr[11,10] : 01 ==> cond compare, 10 ==> Data Proc 2 Source
9245 11 ==> cond select, 00 ==> other. */
9247 switch (INSTR (11, 10))
9249 case 1: dexSimpleFPCondCompare (cpu
); return;
9250 case 2: dexSimpleFPDataProc2Source (cpu
); return;
9251 case 3: dexSimpleFPCondSelect (cpu
); return;
9254 /* Now an ordered cascade of tests.
9255 FP immediate has instr [12] == 1.
9256 FP compare has instr [13] == 1.
9257 FP Data Proc 1 Source has instr [14] == 1.
9258 FP floating <--> integer conversions has instr [15] == 0. */
9260 dexSimpleFPImmediate (cpu
);
9262 else if (INSTR (13, 13))
9263 dexSimpleFPCompare (cpu
);
9265 else if (INSTR (14, 14))
9266 dexSimpleFPDataProc1Source (cpu
);
9268 else if (!INSTR (15, 15))
9269 dexSimpleFPIntegerConvert (cpu
);
9272 /* If we get here then instr[15] == 1 which means UNALLOC. */
9277 /* PC relative addressing. */
9280 pcadr (sim_cpu
*cpu
)
9282 /* instr[31] = op : 0 ==> ADR, 1 ==> ADRP
9283 instr[30,29] = immlo
9284 instr[23,5] = immhi. */
9286 unsigned rd
= INSTR (4, 0);
9287 uint32_t isPage
= INSTR (31, 31);
9288 union { int64_t u64
; uint64_t s64
; } imm
;
9291 imm
.s64
= simm64 (aarch64_get_instr (cpu
), 23, 5);
9293 offset
= (offset
<< 2) | INSTR (30, 29);
9295 address
= aarch64_get_PC (cpu
);
9303 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
9304 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, address
+ offset
);
9307 /* Specific decode and execute for group Data Processing Immediate. */
9310 dexPCRelAddressing (sim_cpu
*cpu
)
9312 /* assert instr[28,24] = 10000. */
9316 /* Immediate logical.
9317 The bimm32/64 argument is constructed by replicating a 2, 4, 8,
9318 16, 32 or 64 bit sequence pulled out at decode and possibly
9321 N.B. the output register (dest) can normally be Xn or SP
9322 the exception occurs for flag setting instructions which may
9323 only use Xn for the output (dest). The input register can
9326 /* 32 bit and immediate. */
9328 and32 (sim_cpu
*cpu
, uint32_t bimm
)
9330 unsigned rn
= INSTR (9, 5);
9331 unsigned rd
= INSTR (4, 0);
9333 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
9334 aarch64_set_reg_u64 (cpu
, rd
, SP_OK
,
9335 aarch64_get_reg_u32 (cpu
, rn
, NO_SP
) & bimm
);
9338 /* 64 bit and immediate. */
9340 and64 (sim_cpu
*cpu
, uint64_t bimm
)
9342 unsigned rn
= INSTR (9, 5);
9343 unsigned rd
= INSTR (4, 0);
9345 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
9346 aarch64_set_reg_u64 (cpu
, rd
, SP_OK
,
9347 aarch64_get_reg_u64 (cpu
, rn
, NO_SP
) & bimm
);
9350 /* 32 bit and immediate set flags. */
9352 ands32 (sim_cpu
*cpu
, uint32_t bimm
)
9354 unsigned rn
= INSTR (9, 5);
9355 unsigned rd
= INSTR (4, 0);
9357 uint32_t value1
= aarch64_get_reg_u32 (cpu
, rn
, NO_SP
);
9358 uint32_t value2
= bimm
;
9360 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
9361 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, value1
& value2
);
9362 set_flags_for_binop32 (cpu
, value1
& value2
);
9365 /* 64 bit and immediate set flags. */
9367 ands64 (sim_cpu
*cpu
, uint64_t bimm
)
9369 unsigned rn
= INSTR (9, 5);
9370 unsigned rd
= INSTR (4, 0);
9372 uint64_t value1
= aarch64_get_reg_u64 (cpu
, rn
, NO_SP
);
9373 uint64_t value2
= bimm
;
9375 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
9376 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, value1
& value2
);
9377 set_flags_for_binop64 (cpu
, value1
& value2
);
9380 /* 32 bit exclusive or immediate. */
9382 eor32 (sim_cpu
*cpu
, uint32_t bimm
)
9384 unsigned rn
= INSTR (9, 5);
9385 unsigned rd
= INSTR (4, 0);
9387 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
9388 aarch64_set_reg_u64 (cpu
, rd
, SP_OK
,
9389 aarch64_get_reg_u32 (cpu
, rn
, NO_SP
) ^ bimm
);
9392 /* 64 bit exclusive or immediate. */
9394 eor64 (sim_cpu
*cpu
, uint64_t bimm
)
9396 unsigned rn
= INSTR (9, 5);
9397 unsigned rd
= INSTR (4, 0);
9399 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
9400 aarch64_set_reg_u64 (cpu
, rd
, SP_OK
,
9401 aarch64_get_reg_u64 (cpu
, rn
, NO_SP
) ^ bimm
);
9404 /* 32 bit or immediate. */
9406 orr32 (sim_cpu
*cpu
, uint32_t bimm
)
9408 unsigned rn
= INSTR (9, 5);
9409 unsigned rd
= INSTR (4, 0);
9411 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
9412 aarch64_set_reg_u64 (cpu
, rd
, SP_OK
,
9413 aarch64_get_reg_u32 (cpu
, rn
, NO_SP
) | bimm
);
9416 /* 64 bit or immediate. */
9418 orr64 (sim_cpu
*cpu
, uint64_t bimm
)
9420 unsigned rn
= INSTR (9, 5);
9421 unsigned rd
= INSTR (4, 0);
9423 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
9424 aarch64_set_reg_u64 (cpu
, rd
, SP_OK
,
9425 aarch64_get_reg_u64 (cpu
, rn
, NO_SP
) | bimm
);
9428 /* Logical shifted register.
9429 These allow an optional LSL, ASR, LSR or ROR to the second source
9430 register with a count up to the register bit count.
9431 N.B register args may not be SP. */
9433 /* 32 bit AND shifted register. */
9435 and32_shift (sim_cpu
*cpu
, Shift shift
, uint32_t count
)
9437 unsigned rm
= INSTR (20, 16);
9438 unsigned rn
= INSTR (9, 5);
9439 unsigned rd
= INSTR (4, 0);
9441 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
9443 (cpu
, rd
, NO_SP
, aarch64_get_reg_u32 (cpu
, rn
, NO_SP
)
9444 & shifted32 (aarch64_get_reg_u32 (cpu
, rm
, NO_SP
), shift
, count
));
9447 /* 64 bit AND shifted register. */
9449 and64_shift (sim_cpu
*cpu
, Shift shift
, uint32_t count
)
9451 unsigned rm
= INSTR (20, 16);
9452 unsigned rn
= INSTR (9, 5);
9453 unsigned rd
= INSTR (4, 0);
9455 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
9457 (cpu
, rd
, NO_SP
, aarch64_get_reg_u64 (cpu
, rn
, NO_SP
)
9458 & shifted64 (aarch64_get_reg_u64 (cpu
, rm
, NO_SP
), shift
, count
));
9461 /* 32 bit AND shifted register setting flags. */
9463 ands32_shift (sim_cpu
*cpu
, Shift shift
, uint32_t count
)
9465 unsigned rm
= INSTR (20, 16);
9466 unsigned rn
= INSTR (9, 5);
9467 unsigned rd
= INSTR (4, 0);
9469 uint32_t value1
= aarch64_get_reg_u32 (cpu
, rn
, NO_SP
);
9470 uint32_t value2
= shifted32 (aarch64_get_reg_u32 (cpu
, rm
, NO_SP
),
9473 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
9474 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, value1
& value2
);
9475 set_flags_for_binop32 (cpu
, value1
& value2
);
9478 /* 64 bit AND shifted register setting flags. */
9480 ands64_shift (sim_cpu
*cpu
, Shift shift
, uint32_t count
)
9482 unsigned rm
= INSTR (20, 16);
9483 unsigned rn
= INSTR (9, 5);
9484 unsigned rd
= INSTR (4, 0);
9486 uint64_t value1
= aarch64_get_reg_u64 (cpu
, rn
, NO_SP
);
9487 uint64_t value2
= shifted64 (aarch64_get_reg_u64 (cpu
, rm
, NO_SP
),
9490 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
9491 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, value1
& value2
);
9492 set_flags_for_binop64 (cpu
, value1
& value2
);
9495 /* 32 bit BIC shifted register. */
9497 bic32_shift (sim_cpu
*cpu
, Shift shift
, uint32_t count
)
9499 unsigned rm
= INSTR (20, 16);
9500 unsigned rn
= INSTR (9, 5);
9501 unsigned rd
= INSTR (4, 0);
9503 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
9505 (cpu
, rd
, NO_SP
, aarch64_get_reg_u32 (cpu
, rn
, NO_SP
)
9506 & ~ shifted32 (aarch64_get_reg_u32 (cpu
, rm
, NO_SP
), shift
, count
));
9509 /* 64 bit BIC shifted register. */
9511 bic64_shift (sim_cpu
*cpu
, Shift shift
, uint32_t count
)
9513 unsigned rm
= INSTR (20, 16);
9514 unsigned rn
= INSTR (9, 5);
9515 unsigned rd
= INSTR (4, 0);
9517 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
9519 (cpu
, rd
, NO_SP
, aarch64_get_reg_u64 (cpu
, rn
, NO_SP
)
9520 & ~ shifted64 (aarch64_get_reg_u64 (cpu
, rm
, NO_SP
), shift
, count
));
9523 /* 32 bit BIC shifted register setting flags. */
9525 bics32_shift (sim_cpu
*cpu
, Shift shift
, uint32_t count
)
9527 unsigned rm
= INSTR (20, 16);
9528 unsigned rn
= INSTR (9, 5);
9529 unsigned rd
= INSTR (4, 0);
9531 uint32_t value1
= aarch64_get_reg_u32 (cpu
, rn
, NO_SP
);
9532 uint32_t value2
= ~ shifted32 (aarch64_get_reg_u32 (cpu
, rm
, NO_SP
),
9535 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
9536 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, value1
& value2
);
9537 set_flags_for_binop32 (cpu
, value1
& value2
);
9540 /* 64 bit BIC shifted register setting flags. */
9542 bics64_shift (sim_cpu
*cpu
, Shift shift
, uint32_t count
)
9544 unsigned rm
= INSTR (20, 16);
9545 unsigned rn
= INSTR (9, 5);
9546 unsigned rd
= INSTR (4, 0);
9548 uint64_t value1
= aarch64_get_reg_u64 (cpu
, rn
, NO_SP
);
9549 uint64_t value2
= ~ shifted64 (aarch64_get_reg_u64 (cpu
, rm
, NO_SP
),
9552 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
9553 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, value1
& value2
);
9554 set_flags_for_binop64 (cpu
, value1
& value2
);
9557 /* 32 bit EON shifted register. */
9559 eon32_shift (sim_cpu
*cpu
, Shift shift
, uint32_t count
)
9561 unsigned rm
= INSTR (20, 16);
9562 unsigned rn
= INSTR (9, 5);
9563 unsigned rd
= INSTR (4, 0);
9565 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
9567 (cpu
, rd
, NO_SP
, aarch64_get_reg_u32 (cpu
, rn
, NO_SP
)
9568 ^ ~ shifted32 (aarch64_get_reg_u32 (cpu
, rm
, NO_SP
), shift
, count
));
9571 /* 64 bit EON shifted register. */
9573 eon64_shift (sim_cpu
*cpu
, Shift shift
, uint32_t count
)
9575 unsigned rm
= INSTR (20, 16);
9576 unsigned rn
= INSTR (9, 5);
9577 unsigned rd
= INSTR (4, 0);
9579 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
9581 (cpu
, rd
, NO_SP
, aarch64_get_reg_u64 (cpu
, rn
, NO_SP
)
9582 ^ ~ shifted64 (aarch64_get_reg_u64 (cpu
, rm
, NO_SP
), shift
, count
));
9585 /* 32 bit EOR shifted register. */
9587 eor32_shift (sim_cpu
*cpu
, Shift shift
, uint32_t count
)
9589 unsigned rm
= INSTR (20, 16);
9590 unsigned rn
= INSTR (9, 5);
9591 unsigned rd
= INSTR (4, 0);
9593 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
9595 (cpu
, rd
, NO_SP
, aarch64_get_reg_u32 (cpu
, rn
, NO_SP
)
9596 ^ shifted32 (aarch64_get_reg_u32 (cpu
, rm
, NO_SP
), shift
, count
));
9599 /* 64 bit EOR shifted register. */
9601 eor64_shift (sim_cpu
*cpu
, Shift shift
, uint32_t count
)
9603 unsigned rm
= INSTR (20, 16);
9604 unsigned rn
= INSTR (9, 5);
9605 unsigned rd
= INSTR (4, 0);
9607 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
9609 (cpu
, rd
, NO_SP
, aarch64_get_reg_u64 (cpu
, rn
, NO_SP
)
9610 ^ shifted64 (aarch64_get_reg_u64 (cpu
, rm
, NO_SP
), shift
, count
));
9613 /* 32 bit ORR shifted register. */
9615 orr32_shift (sim_cpu
*cpu
, Shift shift
, uint32_t count
)
9617 unsigned rm
= INSTR (20, 16);
9618 unsigned rn
= INSTR (9, 5);
9619 unsigned rd
= INSTR (4, 0);
9621 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
9623 (cpu
, rd
, NO_SP
, aarch64_get_reg_u32 (cpu
, rn
, NO_SP
)
9624 | shifted32 (aarch64_get_reg_u32 (cpu
, rm
, NO_SP
), shift
, count
));
9627 /* 64 bit ORR shifted register. */
9629 orr64_shift (sim_cpu
*cpu
, Shift shift
, uint32_t count
)
9631 unsigned rm
= INSTR (20, 16);
9632 unsigned rn
= INSTR (9, 5);
9633 unsigned rd
= INSTR (4, 0);
9635 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
9637 (cpu
, rd
, NO_SP
, aarch64_get_reg_u64 (cpu
, rn
, NO_SP
)
9638 | shifted64 (aarch64_get_reg_u64 (cpu
, rm
, NO_SP
), shift
, count
));
9641 /* 32 bit ORN shifted register. */
9643 orn32_shift (sim_cpu
*cpu
, Shift shift
, uint32_t count
)
9645 unsigned rm
= INSTR (20, 16);
9646 unsigned rn
= INSTR (9, 5);
9647 unsigned rd
= INSTR (4, 0);
9649 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
9651 (cpu
, rd
, NO_SP
, aarch64_get_reg_u32 (cpu
, rn
, NO_SP
)
9652 | ~ shifted32 (aarch64_get_reg_u32 (cpu
, rm
, NO_SP
), shift
, count
));
9655 /* 64 bit ORN shifted register. */
9657 orn64_shift (sim_cpu
*cpu
, Shift shift
, uint32_t count
)
9659 unsigned rm
= INSTR (20, 16);
9660 unsigned rn
= INSTR (9, 5);
9661 unsigned rd
= INSTR (4, 0);
9663 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
9665 (cpu
, rd
, NO_SP
, aarch64_get_reg_u64 (cpu
, rn
, NO_SP
)
9666 | ~ shifted64 (aarch64_get_reg_u64 (cpu
, rm
, NO_SP
), shift
, count
));
9670 dexLogicalImmediate (sim_cpu
*cpu
)
9672 /* assert instr[28,23] = 1001000
9673 instr[31] = size : 0 ==> 32 bit, 1 ==> 64 bit
9674 instr[30,29] = op : 0 ==> AND, 1 ==> ORR, 2 ==> EOR, 3 ==> ANDS
9675 instr[22] = N : used to construct immediate mask
9681 /* 32 bit operations must have N = 0 or else we have an UNALLOC. */
9682 uint32_t size
= INSTR (31, 31);
9683 uint32_t N
= INSTR (22, 22);
9684 /* uint32_t immr = INSTR (21, 16);. */
9685 /* uint32_t imms = INSTR (15, 10);. */
9686 uint32_t index
= INSTR (22, 10);
9687 uint64_t bimm64
= LITable
[index
];
9688 uint32_t dispatch
= INSTR (30, 29);
9698 uint32_t bimm
= (uint32_t) bimm64
;
9702 case 0: and32 (cpu
, bimm
); return;
9703 case 1: orr32 (cpu
, bimm
); return;
9704 case 2: eor32 (cpu
, bimm
); return;
9705 case 3: ands32 (cpu
, bimm
); return;
9712 case 0: and64 (cpu
, bimm64
); return;
9713 case 1: orr64 (cpu
, bimm64
); return;
9714 case 2: eor64 (cpu
, bimm64
); return;
9715 case 3: ands64 (cpu
, bimm64
); return;
9722 The uimm argument is a 16 bit value to be inserted into the
9723 target register the pos argument locates the 16 bit word in the
9724 dest register i.e. it is in {0, 1} for 32 bit and {0, 1, 2,
9726 N.B register arg may not be SP so it should be.
9727 accessed using the setGZRegisterXXX accessors. */
9729 /* 32 bit move 16 bit immediate zero remaining shorts. */
9731 movz32 (sim_cpu
*cpu
, uint32_t val
, uint32_t pos
)
9733 unsigned rd
= INSTR (4, 0);
9735 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
9736 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, val
<< (pos
* 16));
9739 /* 64 bit move 16 bit immediate zero remaining shorts. */
9741 movz64 (sim_cpu
*cpu
, uint32_t val
, uint32_t pos
)
9743 unsigned rd
= INSTR (4, 0);
9745 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
9746 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, ((uint64_t) val
) << (pos
* 16));
9749 /* 32 bit move 16 bit immediate negated. */
9751 movn32 (sim_cpu
*cpu
, uint32_t val
, uint32_t pos
)
9753 unsigned rd
= INSTR (4, 0);
9755 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
9756 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, ((val
<< (pos
* 16)) ^ 0xffffffffU
));
9759 /* 64 bit move 16 bit immediate negated. */
9761 movn64 (sim_cpu
*cpu
, uint32_t val
, uint32_t pos
)
9763 unsigned rd
= INSTR (4, 0);
9765 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
9767 (cpu
, rd
, NO_SP
, ((((uint64_t) val
) << (pos
* 16))
9768 ^ 0xffffffffffffffffULL
));
9771 /* 32 bit move 16 bit immediate keep remaining shorts. */
9773 movk32 (sim_cpu
*cpu
, uint32_t val
, uint32_t pos
)
9775 unsigned rd
= INSTR (4, 0);
9776 uint32_t current
= aarch64_get_reg_u32 (cpu
, rd
, NO_SP
);
9777 uint32_t value
= val
<< (pos
* 16);
9778 uint32_t mask
= ~(0xffffU
<< (pos
* 16));
9780 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
9781 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, (value
| (current
& mask
)));
9784 /* 64 bit move 16 it immediate keep remaining shorts. */
9786 movk64 (sim_cpu
*cpu
, uint32_t val
, uint32_t pos
)
9788 unsigned rd
= INSTR (4, 0);
9789 uint64_t current
= aarch64_get_reg_u64 (cpu
, rd
, NO_SP
);
9790 uint64_t value
= (uint64_t) val
<< (pos
* 16);
9791 uint64_t mask
= ~(0xffffULL
<< (pos
* 16));
9793 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
9794 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, (value
| (current
& mask
)));
9798 dexMoveWideImmediate (sim_cpu
*cpu
)
9800 /* assert instr[28:23] = 100101
9801 instr[31] = size : 0 ==> 32 bit, 1 ==> 64 bit
9802 instr[30,29] = op : 0 ==> MOVN, 1 ==> UNALLOC, 2 ==> MOVZ, 3 ==> MOVK
9803 instr[22,21] = shift : 00 == LSL#0, 01 = LSL#16, 10 = LSL#32, 11 = LSL#48
9804 instr[20,5] = uimm16
9807 /* N.B. the (multiple of 16) shift is applied by the called routine,
9808 we just pass the multiplier. */
9811 uint32_t size
= INSTR (31, 31);
9812 uint32_t op
= INSTR (30, 29);
9813 uint32_t shift
= INSTR (22, 21);
9815 /* 32 bit can only shift 0 or 1 lot of 16.
9816 anything else is an unallocated instruction. */
9817 if (size
== 0 && (shift
> 1))
9823 imm
= INSTR (20, 5);
9828 movn32 (cpu
, imm
, shift
);
9830 movz32 (cpu
, imm
, shift
);
9832 movk32 (cpu
, imm
, shift
);
9837 movn64 (cpu
, imm
, shift
);
9839 movz64 (cpu
, imm
, shift
);
9841 movk64 (cpu
, imm
, shift
);
9845 /* Bitfield operations.
9846 These take a pair of bit positions r and s which are in {0..31}
9847 or {0..63} depending on the instruction word size.
9848 N.B register args may not be SP. */
9850 /* OK, we start with ubfm which just needs to pick
9851 some bits out of source zero the rest and write
9852 the result to dest. Just need two logical shifts. */
9854 /* 32 bit bitfield move, left and right of affected zeroed
9855 if r <= s Wd<s-r:0> = Wn<s:r> else Wd<32+s-r,32-r> = Wn<s:0>. */
9857 ubfm32 (sim_cpu
*cpu
, uint32_t r
, uint32_t s
)
9860 unsigned rn
= INSTR (9, 5);
9861 uint32_t value
= aarch64_get_reg_u32 (cpu
, rn
, NO_SP
);
9863 /* Pick either s+1-r or s+1 consecutive bits out of the original word. */
9866 /* 31:...:s:xxx:r:...:0 ==> 31:...:s-r:xxx:0.
9867 We want only bits s:xxx:r at the bottom of the word
9868 so we LSL bit s up to bit 31 i.e. by 31 - s
9869 and then we LSR to bring bit 31 down to bit s - r
9870 i.e. by 31 + r - s. */
9872 value
>>= 31 + r
- s
;
9876 /* 31:...:s:xxx:0 ==> 31:...:31-(r-1)+s:xxx:31-(r-1):...:0
9877 We want only bits s:xxx:0 starting at it 31-(r-1)
9878 so we LSL bit s up to bit 31 i.e. by 31 - s
9879 and then we LSL to bring bit 31 down to 31-(r-1)+s
9880 i.e. by r - (s + 1). */
9882 value
>>= r
- (s
+ 1);
9885 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
9887 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, value
);
9890 /* 64 bit bitfield move, left and right of affected zeroed
9891 if r <= s Wd<s-r:0> = Wn<s:r> else Wd<64+s-r,64-r> = Wn<s:0>. */
9893 ubfm (sim_cpu
*cpu
, uint32_t r
, uint32_t s
)
9896 unsigned rn
= INSTR (9, 5);
9897 uint64_t value
= aarch64_get_reg_u64 (cpu
, rn
, NO_SP
);
9901 /* 63:...:s:xxx:r:...:0 ==> 63:...:s-r:xxx:0.
9902 We want only bits s:xxx:r at the bottom of the word.
9903 So we LSL bit s up to bit 63 i.e. by 63 - s
9904 and then we LSR to bring bit 63 down to bit s - r
9905 i.e. by 63 + r - s. */
9907 value
>>= 63 + r
- s
;
9911 /* 63:...:s:xxx:0 ==> 63:...:63-(r-1)+s:xxx:63-(r-1):...:0.
9912 We want only bits s:xxx:0 starting at it 63-(r-1).
9913 So we LSL bit s up to bit 63 i.e. by 63 - s
9914 and then we LSL to bring bit 63 down to 63-(r-1)+s
9915 i.e. by r - (s + 1). */
9917 value
>>= r
- (s
+ 1);
9920 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
9922 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, value
);
9925 /* The signed versions need to insert sign bits
9926 on the left of the inserted bit field. so we do
9927 much the same as the unsigned version except we
9928 use an arithmetic shift right -- this just means
9929 we need to operate on signed values. */
9931 /* 32 bit bitfield move, left of affected sign-extended, right zeroed. */
9932 /* If r <= s Wd<s-r:0> = Wn<s:r> else Wd<32+s-r,32-r> = Wn<s:0>. */
9934 sbfm32 (sim_cpu
*cpu
, uint32_t r
, uint32_t s
)
9937 unsigned rn
= INSTR (9, 5);
9938 /* as per ubfm32 but use an ASR instead of an LSR. */
9939 int32_t value
= aarch64_get_reg_s32 (cpu
, rn
, NO_SP
);
9944 value
>>= 31 + r
- s
;
9949 value
>>= r
- (s
+ 1);
9952 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
9954 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, (uint32_t) value
);
9957 /* 64 bit bitfield move, left of affected sign-extended, right zeroed. */
9958 /* If r <= s Wd<s-r:0> = Wn<s:r> else Wd<64+s-r,64-r> = Wn<s:0>. */
9960 sbfm (sim_cpu
*cpu
, uint32_t r
, uint32_t s
)
9963 unsigned rn
= INSTR (9, 5);
9964 /* acpu per ubfm but use an ASR instead of an LSR. */
9965 int64_t value
= aarch64_get_reg_s64 (cpu
, rn
, NO_SP
);
9970 value
>>= 63 + r
- s
;
9975 value
>>= r
- (s
+ 1);
9978 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
9980 aarch64_set_reg_s64 (cpu
, rd
, NO_SP
, value
);
9983 /* Finally, these versions leave non-affected bits
9984 as is. so we need to generate the bits as per
9985 ubfm and also generate a mask to pick the
9986 bits from the original and computed values. */
9988 /* 32 bit bitfield move, non-affected bits left as is.
9989 If r <= s Wd<s-r:0> = Wn<s:r> else Wd<32+s-r,32-r> = Wn<s:0>. */
9991 bfm32 (sim_cpu
*cpu
, uint32_t r
, uint32_t s
)
9993 unsigned rn
= INSTR (9, 5);
9994 uint32_t value
= aarch64_get_reg_u32 (cpu
, rn
, NO_SP
);
9999 /* Pick either s+1-r or s+1 consecutive bits out of the original word. */
10002 /* 31:...:s:xxx:r:...:0 ==> 31:...:s-r:xxx:0.
10003 We want only bits s:xxx:r at the bottom of the word
10004 so we LSL bit s up to bit 31 i.e. by 31 - s
10005 and then we LSR to bring bit 31 down to bit s - r
10006 i.e. by 31 + r - s. */
10008 value
>>= 31 + r
- s
;
10009 /* the mask must include the same bits. */
10011 mask
>>= 31 + r
- s
;
10015 /* 31:...:s:xxx:0 ==> 31:...:31-(r-1)+s:xxx:31-(r-1):...:0.
10016 We want only bits s:xxx:0 starting at it 31-(r-1)
10017 so we LSL bit s up to bit 31 i.e. by 31 - s
10018 and then we LSL to bring bit 31 down to 31-(r-1)+s
10019 i.e. by r - (s + 1). */
10021 value
>>= r
- (s
+ 1);
10022 /* The mask must include the same bits. */
10024 mask
>>= r
- (s
+ 1);
10028 value2
= aarch64_get_reg_u32 (cpu
, rd
, NO_SP
);
10033 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
10034 aarch64_set_reg_u64
10035 (cpu
, rd
, NO_SP
, (aarch64_get_reg_u32 (cpu
, rd
, NO_SP
) & ~mask
) | value
);
10038 /* 64 bit bitfield move, non-affected bits left as is.
10039 If r <= s Wd<s-r:0> = Wn<s:r> else Wd<64+s-r,64-r> = Wn<s:0>. */
10041 bfm (sim_cpu
*cpu
, uint32_t r
, uint32_t s
)
10044 unsigned rn
= INSTR (9, 5);
10045 uint64_t value
= aarch64_get_reg_u64 (cpu
, rn
, NO_SP
);
10046 uint64_t mask
= 0xffffffffffffffffULL
;
10050 /* 63:...:s:xxx:r:...:0 ==> 63:...:s-r:xxx:0.
10051 We want only bits s:xxx:r at the bottom of the word
10052 so we LSL bit s up to bit 63 i.e. by 63 - s
10053 and then we LSR to bring bit 63 down to bit s - r
10054 i.e. by 63 + r - s. */
10056 value
>>= 63 + r
- s
;
10057 /* The mask must include the same bits. */
10059 mask
>>= 63 + r
- s
;
10063 /* 63:...:s:xxx:0 ==> 63:...:63-(r-1)+s:xxx:63-(r-1):...:0
10064 We want only bits s:xxx:0 starting at it 63-(r-1)
10065 so we LSL bit s up to bit 63 i.e. by 63 - s
10066 and then we LSL to bring bit 63 down to 63-(r-1)+s
10067 i.e. by r - (s + 1). */
10069 value
>>= r
- (s
+ 1);
10070 /* The mask must include the same bits. */
10072 mask
>>= r
- (s
+ 1);
10075 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
10077 aarch64_set_reg_u64
10078 (cpu
, rd
, NO_SP
, (aarch64_get_reg_u64 (cpu
, rd
, NO_SP
) & ~mask
) | value
);
10082 dexBitfieldImmediate (sim_cpu
*cpu
)
10084 /* assert instr[28:23] = 100110
10085 instr[31] = size : 0 ==> 32 bit, 1 ==> 64 bit
10086 instr[30,29] = op : 0 ==> SBFM, 1 ==> BFM, 2 ==> UBFM, 3 ==> UNALLOC
10087 instr[22] = N : must be 0 for 32 bit, 1 for 64 bit ow UNALLOC
10088 instr[21,16] = immr : 0xxxxx for 32 bit, xxxxxx for 64 bit
10089 instr[15,10] = imms : 0xxxxx for 32 bit, xxxxxx for 64 bit
10093 /* 32 bit operations must have N = 0 or else we have an UNALLOC. */
10096 uint32_t size
= INSTR (31, 31);
10097 uint32_t N
= INSTR (22, 22);
10098 /* 32 bit operations must have immr[5] = 0 and imms[5] = 0. */
10099 /* or else we have an UNALLOC. */
10100 uint32_t immr
= INSTR (21, 16);
10105 if (!size
&& uimm (immr
, 5, 5))
10108 imms
= INSTR (15, 10);
10109 if (!size
&& uimm (imms
, 5, 5))
10112 /* Switch on combined size and op. */
10113 dispatch
= INSTR (31, 29);
10116 case 0: sbfm32 (cpu
, immr
, imms
); return;
10117 case 1: bfm32 (cpu
, immr
, imms
); return;
10118 case 2: ubfm32 (cpu
, immr
, imms
); return;
10119 case 4: sbfm (cpu
, immr
, imms
); return;
10120 case 5: bfm (cpu
, immr
, imms
); return;
10121 case 6: ubfm (cpu
, immr
, imms
); return;
10122 default: HALT_UNALLOC
;
10127 do_EXTR_32 (sim_cpu
*cpu
)
10129 /* instr[31:21] = 00010011100
10131 instr[15,10] = imms : 0xxxxx for 32 bit
10134 unsigned rm
= INSTR (20, 16);
10135 unsigned imms
= INSTR (15, 10) & 31;
10136 unsigned rn
= INSTR ( 9, 5);
10137 unsigned rd
= INSTR ( 4, 0);
10141 val1
= aarch64_get_reg_u32 (cpu
, rm
, NO_SP
);
10143 val2
= aarch64_get_reg_u32 (cpu
, rn
, NO_SP
);
10144 val2
<<= (32 - imms
);
10146 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
10147 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, val1
| val2
);
10151 do_EXTR_64 (sim_cpu
*cpu
)
10153 /* instr[31:21] = 10010011100
10155 instr[15,10] = imms
10158 unsigned rm
= INSTR (20, 16);
10159 unsigned imms
= INSTR (15, 10) & 63;
10160 unsigned rn
= INSTR ( 9, 5);
10161 unsigned rd
= INSTR ( 4, 0);
10164 val
= aarch64_get_reg_u64 (cpu
, rm
, NO_SP
);
10166 val
|= (aarch64_get_reg_u64 (cpu
, rn
, NO_SP
) << (64 - imms
));
10168 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, val
);
10172 dexExtractImmediate (sim_cpu
*cpu
)
10174 /* assert instr[28:23] = 100111
10175 instr[31] = size : 0 ==> 32 bit, 1 ==> 64 bit
10176 instr[30,29] = op21 : 0 ==> EXTR, 1,2,3 ==> UNALLOC
10177 instr[22] = N : must be 0 for 32 bit, 1 for 64 bit or UNALLOC
10178 instr[21] = op0 : must be 0 or UNALLOC
10180 instr[15,10] = imms : 0xxxxx for 32 bit, xxxxxx for 64 bit
10184 /* 32 bit operations must have N = 0 or else we have an UNALLOC. */
10185 /* 64 bit operations must have N = 1 or else we have an UNALLOC. */
10187 uint32_t size
= INSTR (31, 31);
10188 uint32_t N
= INSTR (22, 22);
10189 /* 32 bit operations must have imms[5] = 0
10190 or else we have an UNALLOC. */
10191 uint32_t imms
= INSTR (15, 10);
10196 if (!size
&& uimm (imms
, 5, 5))
10199 /* Switch on combined size and op. */
10200 dispatch
= INSTR (31, 29);
10205 else if (dispatch
== 4)
10208 else if (dispatch
== 1)
10215 dexDPImm (sim_cpu
*cpu
)
10217 /* uint32_t group = dispatchGroup (aarch64_get_instr (cpu));
10218 assert group == GROUP_DPIMM_1000 || grpoup == GROUP_DPIMM_1001
10219 bits [25,23] of a DPImm are the secondary dispatch vector. */
10220 uint32_t group2
= dispatchDPImm (aarch64_get_instr (cpu
));
10224 case DPIMM_PCADR_000
:
10225 case DPIMM_PCADR_001
:
10226 dexPCRelAddressing (cpu
);
10229 case DPIMM_ADDSUB_010
:
10230 case DPIMM_ADDSUB_011
:
10231 dexAddSubtractImmediate (cpu
);
10234 case DPIMM_LOG_100
:
10235 dexLogicalImmediate (cpu
);
10238 case DPIMM_MOV_101
:
10239 dexMoveWideImmediate (cpu
);
10242 case DPIMM_BITF_110
:
10243 dexBitfieldImmediate (cpu
);
10246 case DPIMM_EXTR_111
:
10247 dexExtractImmediate (cpu
);
10251 /* Should never reach here. */
10257 dexLoadUnscaledImmediate (sim_cpu
*cpu
)
10259 /* instr[29,24] == 111_00
10262 instr[31,30] = size
10265 instr[20,12] = simm9
10266 instr[9,5] = rn may be SP. */
10267 /* unsigned rt = INSTR (4, 0); */
10268 uint32_t V
= INSTR (26, 26);
10269 uint32_t dispatch
= ((INSTR (31, 30) << 2) | INSTR (23, 22));
10270 int32_t imm
= simm32 (aarch64_get_instr (cpu
), 20, 12);
10274 /* GReg operations. */
10277 case 0: sturb (cpu
, imm
); return;
10278 case 1: ldurb32 (cpu
, imm
); return;
10279 case 2: ldursb64 (cpu
, imm
); return;
10280 case 3: ldursb32 (cpu
, imm
); return;
10281 case 4: sturh (cpu
, imm
); return;
10282 case 5: ldurh32 (cpu
, imm
); return;
10283 case 6: ldursh64 (cpu
, imm
); return;
10284 case 7: ldursh32 (cpu
, imm
); return;
10285 case 8: stur32 (cpu
, imm
); return;
10286 case 9: ldur32 (cpu
, imm
); return;
10287 case 10: ldursw (cpu
, imm
); return;
10288 case 12: stur64 (cpu
, imm
); return;
10289 case 13: ldur64 (cpu
, imm
); return;
10302 /* FReg operations. */
10305 case 2: fsturq (cpu
, imm
); return;
10306 case 3: fldurq (cpu
, imm
); return;
10307 case 8: fsturs (cpu
, imm
); return;
10308 case 9: fldurs (cpu
, imm
); return;
10309 case 12: fsturd (cpu
, imm
); return;
10310 case 13: fldurd (cpu
, imm
); return;
10312 case 0: /* STUR 8 bit FP. */
10313 case 1: /* LDUR 8 bit FP. */
10314 case 4: /* STUR 16 bit FP. */
10315 case 5: /* LDUR 8 bit FP. */
10329 /* N.B. A preliminary note regarding all the ldrs<x>32
10332 The signed value loaded by these instructions is cast to unsigned
10333 before being assigned to aarch64_get_reg_u64 (cpu, N) i.e. to the
10334 64 bit element of the GReg union. this performs a 32 bit sign extension
10335 (as required) but avoids 64 bit sign extension, thus ensuring that the
10336 top half of the register word is zero. this is what the spec demands
10337 when a 32 bit load occurs. */
10339 /* 32 bit load sign-extended byte scaled unsigned 12 bit. */
10341 ldrsb32_abs (sim_cpu
*cpu
, uint32_t offset
)
10343 unsigned int rn
= INSTR (9, 5);
10344 unsigned int rt
= INSTR (4, 0);
10346 /* The target register may not be SP but the source may be
10347 there is no scaling required for a byte load. */
10348 uint64_t address
= aarch64_get_reg_u64 (cpu
, rn
, SP_OK
) + offset
;
10349 aarch64_set_reg_u64 (cpu
, rt
, NO_SP
,
10350 (int64_t) aarch64_get_mem_s8 (cpu
, address
));
10353 /* 32 bit load sign-extended byte scaled or unscaled zero-
10354 or sign-extended 32-bit register offset. */
10356 ldrsb32_scale_ext (sim_cpu
*cpu
, Scaling scaling
, Extension extension
)
10358 unsigned int rm
= INSTR (20, 16);
10359 unsigned int rn
= INSTR (9, 5);
10360 unsigned int rt
= INSTR (4, 0);
10362 /* rn may reference SP, rm and rt must reference ZR. */
10364 uint64_t address
= aarch64_get_reg_u64 (cpu
, rn
, SP_OK
);
10365 int64_t displacement
= extend (aarch64_get_reg_u32 (cpu
, rm
, NO_SP
),
10368 /* There is no scaling required for a byte load. */
10369 aarch64_set_reg_u64
10370 (cpu
, rt
, NO_SP
, (int64_t) aarch64_get_mem_s8 (cpu
, address
10374 /* 32 bit load sign-extended byte unscaled signed 9 bit with
10375 pre- or post-writeback. */
10377 ldrsb32_wb (sim_cpu
*cpu
, int32_t offset
, WriteBack wb
)
10380 unsigned int rn
= INSTR (9, 5);
10381 unsigned int rt
= INSTR (4, 0);
10383 if (rn
== rt
&& wb
!= NoWriteBack
)
10386 address
= aarch64_get_reg_u64 (cpu
, rn
, SP_OK
);
10391 aarch64_set_reg_u64 (cpu
, rt
, NO_SP
,
10392 (int64_t) aarch64_get_mem_s8 (cpu
, address
));
10397 if (wb
!= NoWriteBack
)
10398 aarch64_set_reg_u64 (cpu
, rn
, NO_SP
, address
);
10401 /* 8 bit store scaled. */
10403 fstrb_abs (sim_cpu
*cpu
, uint32_t offset
)
10405 unsigned st
= INSTR (4, 0);
10406 unsigned rn
= INSTR (9, 5);
10408 aarch64_set_mem_u8 (cpu
,
10409 aarch64_get_reg_u64 (cpu
, rn
, SP_OK
) + offset
,
10410 aarch64_get_vec_u8 (cpu
, st
, 0));
10413 /* 8 bit store scaled or unscaled zero- or
10414 sign-extended 8-bit register offset. */
10416 fstrb_scale_ext (sim_cpu
*cpu
, Scaling scaling
, Extension extension
)
10418 unsigned rm
= INSTR (20, 16);
10419 unsigned rn
= INSTR (9, 5);
10420 unsigned st
= INSTR (4, 0);
10422 uint64_t address
= aarch64_get_reg_u64 (cpu
, rn
, SP_OK
);
10423 int64_t extended
= extend (aarch64_get_reg_u32 (cpu
, rm
, NO_SP
),
10425 uint64_t displacement
= scaling
== Scaled
? extended
: 0;
10428 (cpu
, address
+ displacement
, aarch64_get_vec_u8 (cpu
, st
, 0));
10431 /* 16 bit store scaled. */
10433 fstrh_abs (sim_cpu
*cpu
, uint32_t offset
)
10435 unsigned st
= INSTR (4, 0);
10436 unsigned rn
= INSTR (9, 5);
10438 aarch64_set_mem_u16
10440 aarch64_get_reg_u64 (cpu
, rn
, SP_OK
) + SCALE (offset
, 16),
10441 aarch64_get_vec_u16 (cpu
, st
, 0));
10444 /* 16 bit store scaled or unscaled zero-
10445 or sign-extended 16-bit register offset. */
10447 fstrh_scale_ext (sim_cpu
*cpu
, Scaling scaling
, Extension extension
)
10449 unsigned rm
= INSTR (20, 16);
10450 unsigned rn
= INSTR (9, 5);
10451 unsigned st
= INSTR (4, 0);
10453 uint64_t address
= aarch64_get_reg_u64 (cpu
, rn
, SP_OK
);
10454 int64_t extended
= extend (aarch64_get_reg_u32 (cpu
, rm
, NO_SP
),
10456 uint64_t displacement
= OPT_SCALE (extended
, 16, scaling
);
10458 aarch64_set_mem_u16
10459 (cpu
, address
+ displacement
, aarch64_get_vec_u16 (cpu
, st
, 0));
10462 /* 32 bit store scaled unsigned 12 bit. */
10464 fstrs_abs (sim_cpu
*cpu
, uint32_t offset
)
10466 unsigned st
= INSTR (4, 0);
10467 unsigned rn
= INSTR (9, 5);
10469 aarch64_set_mem_u32
10471 aarch64_get_reg_u64 (cpu
, rn
, SP_OK
) + SCALE (offset
, 32),
10472 aarch64_get_vec_u32 (cpu
, st
, 0));
10475 /* 32 bit store unscaled signed 9 bit with pre- or post-writeback. */
10477 fstrs_wb (sim_cpu
*cpu
, int32_t offset
, WriteBack wb
)
10479 unsigned rn
= INSTR (9, 5);
10480 unsigned st
= INSTR (4, 0);
10482 uint64_t address
= aarch64_get_reg_u64 (cpu
, rn
, SP_OK
);
10487 aarch64_set_mem_u32 (cpu
, address
, aarch64_get_vec_u32 (cpu
, st
, 0));
10492 if (wb
!= NoWriteBack
)
10493 aarch64_set_reg_u64 (cpu
, rn
, SP_OK
, address
);
10496 /* 32 bit store scaled or unscaled zero-
10497 or sign-extended 32-bit register offset. */
10499 fstrs_scale_ext (sim_cpu
*cpu
, Scaling scaling
, Extension extension
)
10501 unsigned rm
= INSTR (20, 16);
10502 unsigned rn
= INSTR (9, 5);
10503 unsigned st
= INSTR (4, 0);
10505 uint64_t address
= aarch64_get_reg_u64 (cpu
, rn
, SP_OK
);
10506 int64_t extended
= extend (aarch64_get_reg_u32 (cpu
, rm
, NO_SP
),
10508 uint64_t displacement
= OPT_SCALE (extended
, 32, scaling
);
10510 aarch64_set_mem_u32
10511 (cpu
, address
+ displacement
, aarch64_get_vec_u32 (cpu
, st
, 0));
10514 /* 64 bit store scaled unsigned 12 bit. */
10516 fstrd_abs (sim_cpu
*cpu
, uint32_t offset
)
10518 unsigned st
= INSTR (4, 0);
10519 unsigned rn
= INSTR (9, 5);
10521 aarch64_set_mem_u64
10523 aarch64_get_reg_u64 (cpu
, rn
, SP_OK
) + SCALE (offset
, 64),
10524 aarch64_get_vec_u64 (cpu
, st
, 0));
10527 /* 64 bit store unscaled signed 9 bit with pre- or post-writeback. */
10529 fstrd_wb (sim_cpu
*cpu
, int32_t offset
, WriteBack wb
)
10531 unsigned rn
= INSTR (9, 5);
10532 unsigned st
= INSTR (4, 0);
10534 uint64_t address
= aarch64_get_reg_u64 (cpu
, rn
, SP_OK
);
10539 aarch64_set_mem_u64 (cpu
, address
, aarch64_get_vec_u64 (cpu
, st
, 0));
10544 if (wb
!= NoWriteBack
)
10545 aarch64_set_reg_u64 (cpu
, rn
, SP_OK
, address
);
10548 /* 64 bit store scaled or unscaled zero-
10549 or sign-extended 32-bit register offset. */
10551 fstrd_scale_ext (sim_cpu
*cpu
, Scaling scaling
, Extension extension
)
10553 unsigned rm
= INSTR (20, 16);
10554 unsigned rn
= INSTR (9, 5);
10555 unsigned st
= INSTR (4, 0);
10557 uint64_t address
= aarch64_get_reg_u64 (cpu
, rn
, SP_OK
);
10558 int64_t extended
= extend (aarch64_get_reg_u32 (cpu
, rm
, NO_SP
),
10560 uint64_t displacement
= OPT_SCALE (extended
, 64, scaling
);
10562 aarch64_set_mem_u64
10563 (cpu
, address
+ displacement
, aarch64_get_vec_u64 (cpu
, st
, 0));
10566 /* 128 bit store scaled unsigned 12 bit. */
10568 fstrq_abs (sim_cpu
*cpu
, uint32_t offset
)
10571 unsigned st
= INSTR (4, 0);
10572 unsigned rn
= INSTR (9, 5);
10575 aarch64_get_FP_long_double (cpu
, st
, & a
);
10577 addr
= aarch64_get_reg_u64 (cpu
, rn
, SP_OK
) + SCALE (offset
, 128);
10578 aarch64_set_mem_long_double (cpu
, addr
, a
);
10581 /* 128 bit store unscaled signed 9 bit with pre- or post-writeback. */
10583 fstrq_wb (sim_cpu
*cpu
, int32_t offset
, WriteBack wb
)
10586 unsigned rn
= INSTR (9, 5);
10587 unsigned st
= INSTR (4, 0);
10588 uint64_t address
= aarch64_get_reg_u64 (cpu
, rn
, SP_OK
);
10593 aarch64_get_FP_long_double (cpu
, st
, & a
);
10594 aarch64_set_mem_long_double (cpu
, address
, a
);
10599 if (wb
!= NoWriteBack
)
10600 aarch64_set_reg_u64 (cpu
, rn
, SP_OK
, address
);
10603 /* 128 bit store scaled or unscaled zero-
10604 or sign-extended 32-bit register offset. */
10606 fstrq_scale_ext (sim_cpu
*cpu
, Scaling scaling
, Extension extension
)
10608 unsigned rm
= INSTR (20, 16);
10609 unsigned rn
= INSTR (9, 5);
10610 unsigned st
= INSTR (4, 0);
10612 uint64_t address
= aarch64_get_reg_u64 (cpu
, rn
, SP_OK
);
10613 int64_t extended
= extend (aarch64_get_reg_u32 (cpu
, rm
, NO_SP
),
10615 uint64_t displacement
= OPT_SCALE (extended
, 128, scaling
);
10619 aarch64_get_FP_long_double (cpu
, st
, & a
);
10620 aarch64_set_mem_long_double (cpu
, address
+ displacement
, a
);
10624 dexLoadImmediatePrePost (sim_cpu
*cpu
)
10626 /* instr[31,30] = size
10632 instr[20,12] = simm9
10633 instr[11] = wb : 0 ==> Post, 1 ==> Pre
10635 instr[9,5] = Rn may be SP.
10638 uint32_t V
= INSTR (26, 26);
10639 uint32_t dispatch
= ((INSTR (31, 30) << 2) | INSTR (23, 22));
10640 int32_t imm
= simm32 (aarch64_get_instr (cpu
), 20, 12);
10641 WriteBack wb
= INSTR (11, 11);
10645 /* GReg operations. */
10648 case 0: strb_wb (cpu
, imm
, wb
); return;
10649 case 1: ldrb32_wb (cpu
, imm
, wb
); return;
10650 case 2: ldrsb_wb (cpu
, imm
, wb
); return;
10651 case 3: ldrsb32_wb (cpu
, imm
, wb
); return;
10652 case 4: strh_wb (cpu
, imm
, wb
); return;
10653 case 5: ldrh32_wb (cpu
, imm
, wb
); return;
10654 case 6: ldrsh64_wb (cpu
, imm
, wb
); return;
10655 case 7: ldrsh32_wb (cpu
, imm
, wb
); return;
10656 case 8: str32_wb (cpu
, imm
, wb
); return;
10657 case 9: ldr32_wb (cpu
, imm
, wb
); return;
10658 case 10: ldrsw_wb (cpu
, imm
, wb
); return;
10659 case 12: str_wb (cpu
, imm
, wb
); return;
10660 case 13: ldr_wb (cpu
, imm
, wb
); return;
10670 /* FReg operations. */
10673 case 2: fstrq_wb (cpu
, imm
, wb
); return;
10674 case 3: fldrq_wb (cpu
, imm
, wb
); return;
10675 case 8: fstrs_wb (cpu
, imm
, wb
); return;
10676 case 9: fldrs_wb (cpu
, imm
, wb
); return;
10677 case 12: fstrd_wb (cpu
, imm
, wb
); return;
10678 case 13: fldrd_wb (cpu
, imm
, wb
); return;
10680 case 0: /* STUR 8 bit FP. */
10681 case 1: /* LDUR 8 bit FP. */
10682 case 4: /* STUR 16 bit FP. */
10683 case 5: /* LDUR 8 bit FP. */
10698 dexLoadRegisterOffset (sim_cpu
*cpu
)
10700 /* instr[31,30] = size
10707 instr[15,13] = option : 010 ==> UXTW, 011 ==> UXTX/LSL,
10708 110 ==> SXTW, 111 ==> SXTX,
10713 instr[4,0] = rt. */
10715 uint32_t V
= INSTR (26, 26);
10716 uint32_t dispatch
= ((INSTR (31, 30) << 2) | INSTR (23, 22));
10717 Scaling scale
= INSTR (12, 12);
10718 Extension extensionType
= INSTR (15, 13);
10720 /* Check for illegal extension types. */
10721 if (uimm (extensionType
, 1, 1) == 0)
10724 if (extensionType
== UXTX
|| extensionType
== SXTX
)
10725 extensionType
= NoExtension
;
10729 /* GReg operations. */
10732 case 0: strb_scale_ext (cpu
, scale
, extensionType
); return;
10733 case 1: ldrb32_scale_ext (cpu
, scale
, extensionType
); return;
10734 case 2: ldrsb_scale_ext (cpu
, scale
, extensionType
); return;
10735 case 3: ldrsb32_scale_ext (cpu
, scale
, extensionType
); return;
10736 case 4: strh_scale_ext (cpu
, scale
, extensionType
); return;
10737 case 5: ldrh32_scale_ext (cpu
, scale
, extensionType
); return;
10738 case 6: ldrsh_scale_ext (cpu
, scale
, extensionType
); return;
10739 case 7: ldrsh32_scale_ext (cpu
, scale
, extensionType
); return;
10740 case 8: str32_scale_ext (cpu
, scale
, extensionType
); return;
10741 case 9: ldr32_scale_ext (cpu
, scale
, extensionType
); return;
10742 case 10: ldrsw_scale_ext (cpu
, scale
, extensionType
); return;
10743 case 12: str_scale_ext (cpu
, scale
, extensionType
); return;
10744 case 13: ldr_scale_ext (cpu
, scale
, extensionType
); return;
10745 case 14: prfm_scale_ext (cpu
, scale
, extensionType
); return;
10754 /* FReg operations. */
10757 case 1: /* LDUR 8 bit FP. */
10759 case 3: fldrq_scale_ext (cpu
, scale
, extensionType
); return;
10760 case 5: /* LDUR 8 bit FP. */
10762 case 9: fldrs_scale_ext (cpu
, scale
, extensionType
); return;
10763 case 13: fldrd_scale_ext (cpu
, scale
, extensionType
); return;
10765 case 0: fstrb_scale_ext (cpu
, scale
, extensionType
); return;
10766 case 2: fstrq_scale_ext (cpu
, scale
, extensionType
); return;
10767 case 4: fstrh_scale_ext (cpu
, scale
, extensionType
); return;
10768 case 8: fstrs_scale_ext (cpu
, scale
, extensionType
); return;
10769 case 12: fstrd_scale_ext (cpu
, scale
, extensionType
); return;
10783 dexLoadUnsignedImmediate (sim_cpu
*cpu
)
10785 /* instr[29,24] == 111_01
10786 instr[31,30] = size
10789 instr[21,10] = uimm12 : unsigned immediate offset
10790 instr[9,5] = rn may be SP.
10791 instr[4,0] = rt. */
10793 uint32_t V
= INSTR (26,26);
10794 uint32_t dispatch
= ((INSTR (31, 30) << 2) | INSTR (23, 22));
10795 uint32_t imm
= INSTR (21, 10);
10799 /* GReg operations. */
10802 case 0: strb_abs (cpu
, imm
); return;
10803 case 1: ldrb32_abs (cpu
, imm
); return;
10804 case 2: ldrsb_abs (cpu
, imm
); return;
10805 case 3: ldrsb32_abs (cpu
, imm
); return;
10806 case 4: strh_abs (cpu
, imm
); return;
10807 case 5: ldrh32_abs (cpu
, imm
); return;
10808 case 6: ldrsh_abs (cpu
, imm
); return;
10809 case 7: ldrsh32_abs (cpu
, imm
); return;
10810 case 8: str32_abs (cpu
, imm
); return;
10811 case 9: ldr32_abs (cpu
, imm
); return;
10812 case 10: ldrsw_abs (cpu
, imm
); return;
10813 case 12: str_abs (cpu
, imm
); return;
10814 case 13: ldr_abs (cpu
, imm
); return;
10815 case 14: prfm_abs (cpu
, imm
); return;
10824 /* FReg operations. */
10827 case 0: fstrb_abs (cpu
, imm
); return;
10828 case 4: fstrh_abs (cpu
, imm
); return;
10829 case 8: fstrs_abs (cpu
, imm
); return;
10830 case 12: fstrd_abs (cpu
, imm
); return;
10831 case 2: fstrq_abs (cpu
, imm
); return;
10833 case 1: fldrb_abs (cpu
, imm
); return;
10834 case 5: fldrh_abs (cpu
, imm
); return;
10835 case 9: fldrs_abs (cpu
, imm
); return;
10836 case 13: fldrd_abs (cpu
, imm
); return;
10837 case 3: fldrq_abs (cpu
, imm
); return;
10851 dexLoadExclusive (sim_cpu
*cpu
)
10853 /* assert instr[29:24] = 001000;
10854 instr[31,30] = size
10855 instr[23] = 0 if exclusive
10856 instr[22] = L : 1 if load, 0 if store
10857 instr[21] = 1 if pair
10859 instr[15] = o0 : 1 if ordered
10862 instr[4.0] = Rt. */
10864 switch (INSTR (22, 21))
10866 case 2: ldxr (cpu
); return;
10867 case 0: stxr (cpu
); return;
10873 dexLoadOther (sim_cpu
*cpu
)
10877 /* instr[29,25] = 111_0
10878 instr[24] == 0 ==> dispatch, 1 ==> ldst reg unsigned immediate
10879 instr[21:11,10] is the secondary dispatch. */
10880 if (INSTR (24, 24))
10882 dexLoadUnsignedImmediate (cpu
);
10886 dispatch
= ((INSTR (21, 21) << 2) | INSTR (11, 10));
10889 case 0: dexLoadUnscaledImmediate (cpu
); return;
10890 case 1: dexLoadImmediatePrePost (cpu
); return;
10891 case 3: dexLoadImmediatePrePost (cpu
); return;
10892 case 6: dexLoadRegisterOffset (cpu
); return;
10904 store_pair_u32 (sim_cpu
*cpu
, int32_t offset
, WriteBack wb
)
10906 unsigned rn
= INSTR (14, 10);
10907 unsigned rd
= INSTR (9, 5);
10908 unsigned rm
= INSTR (4, 0);
10909 uint64_t address
= aarch64_get_reg_u64 (cpu
, rd
, SP_OK
);
10911 if ((rn
== rd
|| rm
== rd
) && wb
!= NoWriteBack
)
10912 HALT_UNALLOC
; /* ??? */
10919 aarch64_set_mem_u32 (cpu
, address
,
10920 aarch64_get_reg_u32 (cpu
, rm
, NO_SP
));
10921 aarch64_set_mem_u32 (cpu
, address
+ 4,
10922 aarch64_get_reg_u32 (cpu
, rn
, NO_SP
));
10927 if (wb
!= NoWriteBack
)
10928 aarch64_set_reg_u64 (cpu
, rd
, SP_OK
, address
);
10932 store_pair_u64 (sim_cpu
*cpu
, int32_t offset
, WriteBack wb
)
10934 unsigned rn
= INSTR (14, 10);
10935 unsigned rd
= INSTR (9, 5);
10936 unsigned rm
= INSTR (4, 0);
10937 uint64_t address
= aarch64_get_reg_u64 (cpu
, rd
, SP_OK
);
10939 if ((rn
== rd
|| rm
== rd
) && wb
!= NoWriteBack
)
10940 HALT_UNALLOC
; /* ??? */
10947 aarch64_set_mem_u64 (cpu
, address
,
10948 aarch64_get_reg_u64 (cpu
, rm
, NO_SP
));
10949 aarch64_set_mem_u64 (cpu
, address
+ 8,
10950 aarch64_get_reg_u64 (cpu
, rn
, NO_SP
));
10955 if (wb
!= NoWriteBack
)
10956 aarch64_set_reg_u64 (cpu
, rd
, SP_OK
, address
);
10960 load_pair_u32 (sim_cpu
*cpu
, int32_t offset
, WriteBack wb
)
10962 unsigned rn
= INSTR (14, 10);
10963 unsigned rd
= INSTR (9, 5);
10964 unsigned rm
= INSTR (4, 0);
10965 uint64_t address
= aarch64_get_reg_u64 (cpu
, rd
, SP_OK
);
10967 /* Treat this as unalloc to make sure we don't do it. */
10976 aarch64_set_reg_u64 (cpu
, rm
, SP_OK
, aarch64_get_mem_u32 (cpu
, address
));
10977 aarch64_set_reg_u64 (cpu
, rn
, SP_OK
, aarch64_get_mem_u32 (cpu
, address
+ 4));
10982 if (wb
!= NoWriteBack
)
10983 aarch64_set_reg_u64 (cpu
, rd
, SP_OK
, address
);
10987 load_pair_s32 (sim_cpu
*cpu
, int32_t offset
, WriteBack wb
)
10989 unsigned rn
= INSTR (14, 10);
10990 unsigned rd
= INSTR (9, 5);
10991 unsigned rm
= INSTR (4, 0);
10992 uint64_t address
= aarch64_get_reg_u64 (cpu
, rd
, SP_OK
);
10994 /* Treat this as unalloc to make sure we don't do it. */
11003 aarch64_set_reg_s64 (cpu
, rm
, SP_OK
, aarch64_get_mem_s32 (cpu
, address
));
11004 aarch64_set_reg_s64 (cpu
, rn
, SP_OK
, aarch64_get_mem_s32 (cpu
, address
+ 4));
11009 if (wb
!= NoWriteBack
)
11010 aarch64_set_reg_u64 (cpu
, rd
, SP_OK
, address
);
11014 load_pair_u64 (sim_cpu
*cpu
, int32_t offset
, WriteBack wb
)
11016 unsigned rn
= INSTR (14, 10);
11017 unsigned rd
= INSTR (9, 5);
11018 unsigned rm
= INSTR (4, 0);
11019 uint64_t address
= aarch64_get_reg_u64 (cpu
, rd
, SP_OK
);
11021 /* Treat this as unalloc to make sure we don't do it. */
11030 aarch64_set_reg_u64 (cpu
, rm
, SP_OK
, aarch64_get_mem_u64 (cpu
, address
));
11031 aarch64_set_reg_u64 (cpu
, rn
, SP_OK
, aarch64_get_mem_u64 (cpu
, address
+ 8));
11036 if (wb
!= NoWriteBack
)
11037 aarch64_set_reg_u64 (cpu
, rd
, SP_OK
, address
);
11041 dex_load_store_pair_gr (sim_cpu
*cpu
)
11043 /* instr[31,30] = size (10=> 64-bit, 01=> signed 32-bit, 00=> 32-bit)
11044 instr[29,25] = instruction encoding: 101_0
11045 instr[26] = V : 1 if fp 0 if gp
11046 instr[24,23] = addressing mode (10=> offset, 01=> post, 11=> pre)
11047 instr[22] = load/store (1=> load)
11048 instr[21,15] = signed, scaled, offset
11051 instr[ 4, 0] = Rm. */
11053 uint32_t dispatch
= ((INSTR (31, 30) << 3) | INSTR (24, 22));
11054 int32_t offset
= simm32 (aarch64_get_instr (cpu
), 21, 15);
11058 case 2: store_pair_u32 (cpu
, offset
, Post
); return;
11059 case 3: load_pair_u32 (cpu
, offset
, Post
); return;
11060 case 4: store_pair_u32 (cpu
, offset
, NoWriteBack
); return;
11061 case 5: load_pair_u32 (cpu
, offset
, NoWriteBack
); return;
11062 case 6: store_pair_u32 (cpu
, offset
, Pre
); return;
11063 case 7: load_pair_u32 (cpu
, offset
, Pre
); return;
11065 case 11: load_pair_s32 (cpu
, offset
, Post
); return;
11066 case 13: load_pair_s32 (cpu
, offset
, NoWriteBack
); return;
11067 case 15: load_pair_s32 (cpu
, offset
, Pre
); return;
11069 case 18: store_pair_u64 (cpu
, offset
, Post
); return;
11070 case 19: load_pair_u64 (cpu
, offset
, Post
); return;
11071 case 20: store_pair_u64 (cpu
, offset
, NoWriteBack
); return;
11072 case 21: load_pair_u64 (cpu
, offset
, NoWriteBack
); return;
11073 case 22: store_pair_u64 (cpu
, offset
, Pre
); return;
11074 case 23: load_pair_u64 (cpu
, offset
, Pre
); return;
11082 store_pair_float (sim_cpu
*cpu
, int32_t offset
, WriteBack wb
)
11084 unsigned rn
= INSTR (14, 10);
11085 unsigned rd
= INSTR (9, 5);
11086 unsigned rm
= INSTR (4, 0);
11087 uint64_t address
= aarch64_get_reg_u64 (cpu
, rd
, SP_OK
);
11094 aarch64_set_mem_u32 (cpu
, address
, aarch64_get_vec_u32 (cpu
, rm
, 0));
11095 aarch64_set_mem_u32 (cpu
, address
+ 4, aarch64_get_vec_u32 (cpu
, rn
, 0));
11100 if (wb
!= NoWriteBack
)
11101 aarch64_set_reg_u64 (cpu
, rd
, SP_OK
, address
);
11105 store_pair_double (sim_cpu
*cpu
, int32_t offset
, WriteBack wb
)
11107 unsigned rn
= INSTR (14, 10);
11108 unsigned rd
= INSTR (9, 5);
11109 unsigned rm
= INSTR (4, 0);
11110 uint64_t address
= aarch64_get_reg_u64 (cpu
, rd
, SP_OK
);
11117 aarch64_set_mem_u64 (cpu
, address
, aarch64_get_vec_u64 (cpu
, rm
, 0));
11118 aarch64_set_mem_u64 (cpu
, address
+ 8, aarch64_get_vec_u64 (cpu
, rn
, 0));
11123 if (wb
!= NoWriteBack
)
11124 aarch64_set_reg_u64 (cpu
, rd
, SP_OK
, address
);
11128 store_pair_long_double (sim_cpu
*cpu
, int32_t offset
, WriteBack wb
)
11131 unsigned rn
= INSTR (14, 10);
11132 unsigned rd
= INSTR (9, 5);
11133 unsigned rm
= INSTR (4, 0);
11134 uint64_t address
= aarch64_get_reg_u64 (cpu
, rd
, SP_OK
);
11141 aarch64_get_FP_long_double (cpu
, rm
, & a
);
11142 aarch64_set_mem_long_double (cpu
, address
, a
);
11143 aarch64_get_FP_long_double (cpu
, rn
, & a
);
11144 aarch64_set_mem_long_double (cpu
, address
+ 16, a
);
11149 if (wb
!= NoWriteBack
)
11150 aarch64_set_reg_u64 (cpu
, rd
, SP_OK
, address
);
11154 load_pair_float (sim_cpu
*cpu
, int32_t offset
, WriteBack wb
)
11156 unsigned rn
= INSTR (14, 10);
11157 unsigned rd
= INSTR (9, 5);
11158 unsigned rm
= INSTR (4, 0);
11159 uint64_t address
= aarch64_get_reg_u64 (cpu
, rd
, SP_OK
);
11169 aarch64_set_vec_u32 (cpu
, rm
, 0, aarch64_get_mem_u32 (cpu
, address
));
11170 aarch64_set_vec_u32 (cpu
, rn
, 0, aarch64_get_mem_u32 (cpu
, address
+ 4));
11175 if (wb
!= NoWriteBack
)
11176 aarch64_set_reg_u64 (cpu
, rd
, SP_OK
, address
);
11180 load_pair_double (sim_cpu
*cpu
, int32_t offset
, WriteBack wb
)
11182 unsigned rn
= INSTR (14, 10);
11183 unsigned rd
= INSTR (9, 5);
11184 unsigned rm
= INSTR (4, 0);
11185 uint64_t address
= aarch64_get_reg_u64 (cpu
, rd
, SP_OK
);
11195 aarch64_set_vec_u64 (cpu
, rm
, 0, aarch64_get_mem_u64 (cpu
, address
));
11196 aarch64_set_vec_u64 (cpu
, rn
, 0, aarch64_get_mem_u64 (cpu
, address
+ 8));
11201 if (wb
!= NoWriteBack
)
11202 aarch64_set_reg_u64 (cpu
, rd
, SP_OK
, address
);
11206 load_pair_long_double (sim_cpu
*cpu
, int32_t offset
, WriteBack wb
)
11209 unsigned rn
= INSTR (14, 10);
11210 unsigned rd
= INSTR (9, 5);
11211 unsigned rm
= INSTR (4, 0);
11212 uint64_t address
= aarch64_get_reg_u64 (cpu
, rd
, SP_OK
);
11222 aarch64_get_mem_long_double (cpu
, address
, & a
);
11223 aarch64_set_FP_long_double (cpu
, rm
, a
);
11224 aarch64_get_mem_long_double (cpu
, address
+ 16, & a
);
11225 aarch64_set_FP_long_double (cpu
, rn
, a
);
11230 if (wb
!= NoWriteBack
)
11231 aarch64_set_reg_u64 (cpu
, rd
, SP_OK
, address
);
11235 dex_load_store_pair_fp (sim_cpu
*cpu
)
11237 /* instr[31,30] = size (10=> 128-bit, 01=> 64-bit, 00=> 32-bit)
11238 instr[29,25] = instruction encoding
11239 instr[24,23] = addressing mode (10=> offset, 01=> post, 11=> pre)
11240 instr[22] = load/store (1=> load)
11241 instr[21,15] = signed, scaled, offset
11244 instr[ 4, 0] = Rm */
11246 uint32_t dispatch
= ((INSTR (31, 30) << 3) | INSTR (24, 22));
11247 int32_t offset
= simm32 (aarch64_get_instr (cpu
), 21, 15);
11251 case 2: store_pair_float (cpu
, offset
, Post
); return;
11252 case 3: load_pair_float (cpu
, offset
, Post
); return;
11253 case 4: store_pair_float (cpu
, offset
, NoWriteBack
); return;
11254 case 5: load_pair_float (cpu
, offset
, NoWriteBack
); return;
11255 case 6: store_pair_float (cpu
, offset
, Pre
); return;
11256 case 7: load_pair_float (cpu
, offset
, Pre
); return;
11258 case 10: store_pair_double (cpu
, offset
, Post
); return;
11259 case 11: load_pair_double (cpu
, offset
, Post
); return;
11260 case 12: store_pair_double (cpu
, offset
, NoWriteBack
); return;
11261 case 13: load_pair_double (cpu
, offset
, NoWriteBack
); return;
11262 case 14: store_pair_double (cpu
, offset
, Pre
); return;
11263 case 15: load_pair_double (cpu
, offset
, Pre
); return;
11265 case 18: store_pair_long_double (cpu
, offset
, Post
); return;
11266 case 19: load_pair_long_double (cpu
, offset
, Post
); return;
11267 case 20: store_pair_long_double (cpu
, offset
, NoWriteBack
); return;
11268 case 21: load_pair_long_double (cpu
, offset
, NoWriteBack
); return;
11269 case 22: store_pair_long_double (cpu
, offset
, Pre
); return;
11270 case 23: load_pair_long_double (cpu
, offset
, Pre
); return;
11277 static inline unsigned
11278 vec_reg (unsigned v
, unsigned o
)
11280 return (v
+ o
) & 0x3F;
11283 /* Load multiple N-element structures to N consecutive registers. */
11285 vec_load (sim_cpu
*cpu
, uint64_t address
, unsigned N
)
11287 int all
= INSTR (30, 30);
11288 unsigned size
= INSTR (11, 10);
11289 unsigned vd
= INSTR (4, 0);
11294 case 0: /* 8-bit operations. */
11296 for (i
= 0; i
< (16 * N
); i
++)
11297 aarch64_set_vec_u8 (cpu
, vec_reg (vd
, i
>> 4), i
& 15,
11298 aarch64_get_mem_u8 (cpu
, address
+ i
));
11300 for (i
= 0; i
< (8 * N
); i
++)
11301 aarch64_set_vec_u8 (cpu
, vec_reg (vd
, i
>> 3), i
& 7,
11302 aarch64_get_mem_u8 (cpu
, address
+ i
));
11305 case 1: /* 16-bit operations. */
11307 for (i
= 0; i
< (8 * N
); i
++)
11308 aarch64_set_vec_u16 (cpu
, vec_reg (vd
, i
>> 3), i
& 7,
11309 aarch64_get_mem_u16 (cpu
, address
+ i
* 2));
11311 for (i
= 0; i
< (4 * N
); i
++)
11312 aarch64_set_vec_u16 (cpu
, vec_reg (vd
, i
>> 2), i
& 3,
11313 aarch64_get_mem_u16 (cpu
, address
+ i
* 2));
11316 case 2: /* 32-bit operations. */
11318 for (i
= 0; i
< (4 * N
); i
++)
11319 aarch64_set_vec_u32 (cpu
, vec_reg (vd
, i
>> 2), i
& 3,
11320 aarch64_get_mem_u32 (cpu
, address
+ i
* 4));
11322 for (i
= 0; i
< (2 * N
); i
++)
11323 aarch64_set_vec_u32 (cpu
, vec_reg (vd
, i
>> 1), i
& 1,
11324 aarch64_get_mem_u32 (cpu
, address
+ i
* 4));
11327 case 3: /* 64-bit operations. */
11329 for (i
= 0; i
< (2 * N
); i
++)
11330 aarch64_set_vec_u64 (cpu
, vec_reg (vd
, i
>> 1), i
& 1,
11331 aarch64_get_mem_u64 (cpu
, address
+ i
* 8));
11333 for (i
= 0; i
< N
; i
++)
11334 aarch64_set_vec_u64 (cpu
, vec_reg (vd
, i
), 0,
11335 aarch64_get_mem_u64 (cpu
, address
+ i
* 8));
11340 /* LD4: load multiple 4-element to four consecutive registers. */
11342 LD4 (sim_cpu
*cpu
, uint64_t address
)
11344 vec_load (cpu
, address
, 4);
11347 /* LD3: load multiple 3-element structures to three consecutive registers. */
11349 LD3 (sim_cpu
*cpu
, uint64_t address
)
11351 vec_load (cpu
, address
, 3);
11354 /* LD2: load multiple 2-element structures to two consecutive registers. */
11356 LD2 (sim_cpu
*cpu
, uint64_t address
)
11358 vec_load (cpu
, address
, 2);
11361 /* Load multiple 1-element structures into one register. */
11363 LD1_1 (sim_cpu
*cpu
, uint64_t address
)
11365 int all
= INSTR (30, 30);
11366 unsigned size
= INSTR (11, 10);
11367 unsigned vd
= INSTR (4, 0);
11373 /* LD1 {Vd.16b}, addr, #16 */
11374 /* LD1 {Vd.8b}, addr, #8 */
11375 for (i
= 0; i
< (all
? 16 : 8); i
++)
11376 aarch64_set_vec_u8 (cpu
, vd
, i
,
11377 aarch64_get_mem_u8 (cpu
, address
+ i
));
11381 /* LD1 {Vd.8h}, addr, #16 */
11382 /* LD1 {Vd.4h}, addr, #8 */
11383 for (i
= 0; i
< (all
? 8 : 4); i
++)
11384 aarch64_set_vec_u16 (cpu
, vd
, i
,
11385 aarch64_get_mem_u16 (cpu
, address
+ i
* 2));
11389 /* LD1 {Vd.4s}, addr, #16 */
11390 /* LD1 {Vd.2s}, addr, #8 */
11391 for (i
= 0; i
< (all
? 4 : 2); i
++)
11392 aarch64_set_vec_u32 (cpu
, vd
, i
,
11393 aarch64_get_mem_u32 (cpu
, address
+ i
* 4));
11397 /* LD1 {Vd.2d}, addr, #16 */
11398 /* LD1 {Vd.1d}, addr, #8 */
11399 for (i
= 0; i
< (all
? 2 : 1); i
++)
11400 aarch64_set_vec_u64 (cpu
, vd
, i
,
11401 aarch64_get_mem_u64 (cpu
, address
+ i
* 8));
11406 /* Load multiple 1-element structures into two registers. */
11408 LD1_2 (sim_cpu
*cpu
, uint64_t address
)
11410 /* FIXME: This algorithm is *exactly* the same as the LD2 version.
11411 So why have two different instructions ? There must be something
11412 wrong somewhere. */
11413 vec_load (cpu
, address
, 2);
11416 /* Load multiple 1-element structures into three registers. */
11418 LD1_3 (sim_cpu
*cpu
, uint64_t address
)
11420 /* FIXME: This algorithm is *exactly* the same as the LD3 version.
11421 So why have two different instructions ? There must be something
11422 wrong somewhere. */
11423 vec_load (cpu
, address
, 3);
11426 /* Load multiple 1-element structures into four registers. */
11428 LD1_4 (sim_cpu
*cpu
, uint64_t address
)
11430 /* FIXME: This algorithm is *exactly* the same as the LD4 version.
11431 So why have two different instructions ? There must be something
11432 wrong somewhere. */
11433 vec_load (cpu
, address
, 4);
11436 /* Store multiple N-element structures to N consecutive registers. */
11438 vec_store (sim_cpu
*cpu
, uint64_t address
, unsigned N
)
11440 int all
= INSTR (30, 30);
11441 unsigned size
= INSTR (11, 10);
11442 unsigned vd
= INSTR (4, 0);
11447 case 0: /* 8-bit operations. */
11449 for (i
= 0; i
< (16 * N
); i
++)
11452 aarch64_get_vec_u8 (cpu
, vec_reg (vd
, i
>> 4), i
& 15));
11454 for (i
= 0; i
< (8 * N
); i
++)
11457 aarch64_get_vec_u8 (cpu
, vec_reg (vd
, i
>> 3), i
& 7));
11460 case 1: /* 16-bit operations. */
11462 for (i
= 0; i
< (8 * N
); i
++)
11463 aarch64_set_mem_u16
11464 (cpu
, address
+ i
* 2,
11465 aarch64_get_vec_u16 (cpu
, vec_reg (vd
, i
>> 3), i
& 7));
11467 for (i
= 0; i
< (4 * N
); i
++)
11468 aarch64_set_mem_u16
11469 (cpu
, address
+ i
* 2,
11470 aarch64_get_vec_u16 (cpu
, vec_reg (vd
, i
>> 2), i
& 3));
11473 case 2: /* 32-bit operations. */
11475 for (i
= 0; i
< (4 * N
); i
++)
11476 aarch64_set_mem_u32
11477 (cpu
, address
+ i
* 4,
11478 aarch64_get_vec_u32 (cpu
, vec_reg (vd
, i
>> 2), i
& 3));
11480 for (i
= 0; i
< (2 * N
); i
++)
11481 aarch64_set_mem_u32
11482 (cpu
, address
+ i
* 4,
11483 aarch64_get_vec_u32 (cpu
, vec_reg (vd
, i
>> 1), i
& 1));
11486 case 3: /* 64-bit operations. */
11488 for (i
= 0; i
< (2 * N
); i
++)
11489 aarch64_set_mem_u64
11490 (cpu
, address
+ i
* 8,
11491 aarch64_get_vec_u64 (cpu
, vec_reg (vd
, i
>> 1), i
& 1));
11493 for (i
= 0; i
< N
; i
++)
11494 aarch64_set_mem_u64
11495 (cpu
, address
+ i
* 8,
11496 aarch64_get_vec_u64 (cpu
, vec_reg (vd
, i
), 0));
11501 /* Store multiple 4-element structure to four consecutive registers. */
11503 ST4 (sim_cpu
*cpu
, uint64_t address
)
11505 vec_store (cpu
, address
, 4);
11508 /* Store multiple 3-element structures to three consecutive registers. */
11510 ST3 (sim_cpu
*cpu
, uint64_t address
)
11512 vec_store (cpu
, address
, 3);
11515 /* Store multiple 2-element structures to two consecutive registers. */
11517 ST2 (sim_cpu
*cpu
, uint64_t address
)
11519 vec_store (cpu
, address
, 2);
11522 /* Store multiple 1-element structures into one register. */
11524 ST1_1 (sim_cpu
*cpu
, uint64_t address
)
11526 int all
= INSTR (30, 30);
11527 unsigned size
= INSTR (11, 10);
11528 unsigned vd
= INSTR (4, 0);
11534 for (i
= 0; i
< (all
? 16 : 8); i
++)
11535 aarch64_set_mem_u8 (cpu
, address
+ i
,
11536 aarch64_get_vec_u8 (cpu
, vd
, i
));
11540 for (i
= 0; i
< (all
? 8 : 4); i
++)
11541 aarch64_set_mem_u16 (cpu
, address
+ i
* 2,
11542 aarch64_get_vec_u16 (cpu
, vd
, i
));
11546 for (i
= 0; i
< (all
? 4 : 2); i
++)
11547 aarch64_set_mem_u32 (cpu
, address
+ i
* 4,
11548 aarch64_get_vec_u32 (cpu
, vd
, i
));
11552 for (i
= 0; i
< (all
? 2 : 1); i
++)
11553 aarch64_set_mem_u64 (cpu
, address
+ i
* 8,
11554 aarch64_get_vec_u64 (cpu
, vd
, i
));
11559 /* Store multiple 1-element structures into two registers. */
11561 ST1_2 (sim_cpu
*cpu
, uint64_t address
)
11563 /* FIXME: This algorithm is *exactly* the same as the ST2 version.
11564 So why have two different instructions ? There must be
11565 something wrong somewhere. */
11566 vec_store (cpu
, address
, 2);
11569 /* Store multiple 1-element structures into three registers. */
11571 ST1_3 (sim_cpu
*cpu
, uint64_t address
)
11573 /* FIXME: This algorithm is *exactly* the same as the ST3 version.
11574 So why have two different instructions ? There must be
11575 something wrong somewhere. */
11576 vec_store (cpu
, address
, 3);
11579 /* Store multiple 1-element structures into four registers. */
11581 ST1_4 (sim_cpu
*cpu
, uint64_t address
)
11583 /* FIXME: This algorithm is *exactly* the same as the ST4 version.
11584 So why have two different instructions ? There must be
11585 something wrong somewhere. */
11586 vec_store (cpu
, address
, 4);
11589 #define LDn_STn_SINGLE_LANE_AND_SIZE() \
11592 switch (INSTR (15, 14)) \
11595 lane = (full << 3) | (s << 2) | size; \
11600 if ((size & 1) == 1) \
11602 lane = (full << 2) | (s << 1) | (size >> 1); \
11607 if ((size & 2) == 2) \
11610 if ((size & 1) == 0) \
11612 lane = (full << 1) | s; \
11630 /* Load single structure into one lane of N registers. */
11632 do_vec_LDn_single (sim_cpu
*cpu
, uint64_t address
)
11635 instr[30] = element selector 0=>half, 1=>all elements
11636 instr[29,24] = 00 1101
11637 instr[23] = 0=>simple, 1=>post
11639 instr[21] = width: LD1-or-LD3 (0) / LD2-or-LD4 (1)
11640 instr[20,16] = 0 0000 (simple), Vinc (reg-post-inc, no SP),
11641 11111 (immediate post inc)
11642 instr[15,13] = opcode
11643 instr[12] = S, used for lane number
11644 instr[11,10] = size, also used for lane number
11645 instr[9,5] = address
11648 unsigned full
= INSTR (30, 30);
11649 unsigned vd
= INSTR (4, 0);
11650 unsigned size
= INSTR (11, 10);
11651 unsigned s
= INSTR (12, 12);
11652 int nregs
= ((INSTR (13, 13) << 1) | INSTR (21, 21)) + 1;
11656 NYI_assert (29, 24, 0x0D);
11657 NYI_assert (22, 22, 1);
11659 /* Compute the lane number first (using size), and then compute size. */
11660 LDn_STn_SINGLE_LANE_AND_SIZE ();
11662 for (i
= 0; i
< nregs
; i
++)
11667 uint8_t val
= aarch64_get_mem_u8 (cpu
, address
+ i
);
11668 aarch64_set_vec_u8 (cpu
, vd
+ i
, lane
, val
);
11674 uint16_t val
= aarch64_get_mem_u16 (cpu
, address
+ (i
* 2));
11675 aarch64_set_vec_u16 (cpu
, vd
+ i
, lane
, val
);
11681 uint32_t val
= aarch64_get_mem_u32 (cpu
, address
+ (i
* 4));
11682 aarch64_set_vec_u32 (cpu
, vd
+ i
, lane
, val
);
11688 uint64_t val
= aarch64_get_mem_u64 (cpu
, address
+ (i
* 8));
11689 aarch64_set_vec_u64 (cpu
, vd
+ i
, lane
, val
);
11695 /* Store single structure from one lane from N registers. */
11697 do_vec_STn_single (sim_cpu
*cpu
, uint64_t address
)
11700 instr[30] = element selector 0=>half, 1=>all elements
11701 instr[29,24] = 00 1101
11702 instr[23] = 0=>simple, 1=>post
11704 instr[21] = width: LD1-or-LD3 (0) / LD2-or-LD4 (1)
11705 instr[20,16] = 0 0000 (simple), Vinc (reg-post-inc, no SP),
11706 11111 (immediate post inc)
11707 instr[15,13] = opcode
11708 instr[12] = S, used for lane number
11709 instr[11,10] = size, also used for lane number
11710 instr[9,5] = address
11713 unsigned full
= INSTR (30, 30);
11714 unsigned vd
= INSTR (4, 0);
11715 unsigned size
= INSTR (11, 10);
11716 unsigned s
= INSTR (12, 12);
11717 int nregs
= ((INSTR (13, 13) << 1) | INSTR (21, 21)) + 1;
11721 NYI_assert (29, 24, 0x0D);
11722 NYI_assert (22, 22, 0);
11724 /* Compute the lane number first (using size), and then compute size. */
11725 LDn_STn_SINGLE_LANE_AND_SIZE ();
11727 for (i
= 0; i
< nregs
; i
++)
11732 uint8_t val
= aarch64_get_vec_u8 (cpu
, vd
+ i
, lane
);
11733 aarch64_set_mem_u8 (cpu
, address
+ i
, val
);
11739 uint16_t val
= aarch64_get_vec_u16 (cpu
, vd
+ i
, lane
);
11740 aarch64_set_mem_u16 (cpu
, address
+ (i
* 2), val
);
11746 uint32_t val
= aarch64_get_vec_u32 (cpu
, vd
+ i
, lane
);
11747 aarch64_set_mem_u32 (cpu
, address
+ (i
* 4), val
);
11753 uint64_t val
= aarch64_get_vec_u64 (cpu
, vd
+ i
, lane
);
11754 aarch64_set_mem_u64 (cpu
, address
+ (i
* 8), val
);
11760 /* Load single structure into all lanes of N registers. */
11762 do_vec_LDnR (sim_cpu
*cpu
, uint64_t address
)
11765 instr[30] = element selector 0=>half, 1=>all elements
11766 instr[29,24] = 00 1101
11767 instr[23] = 0=>simple, 1=>post
11769 instr[21] = width: LD1R-or-LD3R (0) / LD2R-or-LD4R (1)
11770 instr[20,16] = 0 0000 (simple), Vinc (reg-post-inc, no SP),
11771 11111 (immediate post inc)
11773 instr[13] = width: LD1R-or-LD2R (0) / LD3R-or-LD4R (1)
11775 instr[11,10] = element size 00=> byte(b), 01=> half(h),
11776 10=> word(s), 11=> double(d)
11777 instr[9,5] = address
11780 unsigned full
= INSTR (30, 30);
11781 unsigned vd
= INSTR (4, 0);
11782 unsigned size
= INSTR (11, 10);
11783 int nregs
= ((INSTR (13, 13) << 1) | INSTR (21, 21)) + 1;
11786 NYI_assert (29, 24, 0x0D);
11787 NYI_assert (22, 22, 1);
11788 NYI_assert (15, 14, 3);
11789 NYI_assert (12, 12, 0);
11791 for (n
= 0; n
< nregs
; n
++)
11796 uint8_t val
= aarch64_get_mem_u8 (cpu
, address
+ n
);
11797 for (i
= 0; i
< (full
? 16 : 8); i
++)
11798 aarch64_set_vec_u8 (cpu
, vd
+ n
, i
, val
);
11804 uint16_t val
= aarch64_get_mem_u16 (cpu
, address
+ (n
* 2));
11805 for (i
= 0; i
< (full
? 8 : 4); i
++)
11806 aarch64_set_vec_u16 (cpu
, vd
+ n
, i
, val
);
11812 uint32_t val
= aarch64_get_mem_u32 (cpu
, address
+ (n
* 4));
11813 for (i
= 0; i
< (full
? 4 : 2); i
++)
11814 aarch64_set_vec_u32 (cpu
, vd
+ n
, i
, val
);
11820 uint64_t val
= aarch64_get_mem_u64 (cpu
, address
+ (n
* 8));
11821 for (i
= 0; i
< (full
? 2 : 1); i
++)
11822 aarch64_set_vec_u64 (cpu
, vd
+ n
, i
, val
);
11832 do_vec_load_store (sim_cpu
*cpu
)
11834 /* {LD|ST}<N> {Vd..Vd+N}, vaddr
11837 instr[30] = element selector 0=>half, 1=>all elements
11838 instr[29,25] = 00110
11839 instr[24] = 0=>multiple struct, 1=>single struct
11840 instr[23] = 0=>simple, 1=>post
11841 instr[22] = 0=>store, 1=>load
11842 instr[21] = 0 (LDn) / small(0)-large(1) selector (LDnR)
11843 instr[20,16] = 00000 (simple), Vinc (reg-post-inc, no SP),
11844 11111 (immediate post inc)
11845 instr[15,12] = elements and destinations. eg for load:
11846 0000=>LD4 => load multiple 4-element to
11847 four consecutive registers
11848 0100=>LD3 => load multiple 3-element to
11849 three consecutive registers
11850 1000=>LD2 => load multiple 2-element to
11851 two consecutive registers
11852 0010=>LD1 => load multiple 1-element to
11853 four consecutive registers
11854 0110=>LD1 => load multiple 1-element to
11855 three consecutive registers
11856 1010=>LD1 => load multiple 1-element to
11857 two consecutive registers
11858 0111=>LD1 => load multiple 1-element to
11862 instr[11,10] = element size 00=> byte(b), 01=> half(h),
11863 10=> word(s), 11=> double(d)
11864 instr[9,5] = Vn, can be SP
11874 if (INSTR (31, 31) != 0 || INSTR (29, 25) != 0x06)
11877 single
= INSTR (24, 24);
11878 post
= INSTR (23, 23);
11879 load
= INSTR (22, 22);
11880 type
= INSTR (15, 12);
11882 address
= aarch64_get_reg_u64 (cpu
, vn
, SP_OK
);
11884 if (! single
&& INSTR (21, 21) != 0)
11889 unsigned vm
= INSTR (20, 16);
11893 unsigned sizeof_operation
;
11897 if ((type
>= 0) && (type
<= 11))
11899 int nregs
= ((INSTR (13, 13) << 1) | INSTR (21, 21)) + 1;
11900 switch (INSTR (15, 14))
11903 sizeof_operation
= nregs
* 1;
11906 sizeof_operation
= nregs
* 2;
11909 if (INSTR (10, 10) == 0)
11910 sizeof_operation
= nregs
* 4;
11912 sizeof_operation
= nregs
* 8;
11918 else if (type
== 0xC)
11920 sizeof_operation
= INSTR (21, 21) ? 2 : 1;
11921 sizeof_operation
<<= INSTR (11, 10);
11923 else if (type
== 0xE)
11925 sizeof_operation
= INSTR (21, 21) ? 4 : 3;
11926 sizeof_operation
<<= INSTR (11, 10);
11935 case 0: sizeof_operation
= 32; break;
11936 case 4: sizeof_operation
= 24; break;
11937 case 8: sizeof_operation
= 16; break;
11940 /* One register, immediate offset variant. */
11941 sizeof_operation
= 8;
11945 /* Two registers, immediate offset variant. */
11946 sizeof_operation
= 16;
11950 /* Three registers, immediate offset variant. */
11951 sizeof_operation
= 24;
11955 /* Four registers, immediate offset variant. */
11956 sizeof_operation
= 32;
11963 if (INSTR (30, 30))
11964 sizeof_operation
*= 2;
11967 aarch64_set_reg_u64 (cpu
, vn
, SP_OK
, address
+ sizeof_operation
);
11970 aarch64_set_reg_u64 (cpu
, vn
, SP_OK
,
11971 address
+ aarch64_get_reg_u64 (cpu
, vm
, NO_SP
));
11975 NYI_assert (20, 16, 0);
11982 if ((type
>= 0) && (type
<= 11))
11983 do_vec_LDn_single (cpu
, address
);
11984 else if ((type
== 0xC) || (type
== 0xE))
11985 do_vec_LDnR (cpu
, address
);
11992 if ((type
>= 0) && (type
<= 11))
11994 do_vec_STn_single (cpu
, address
);
12005 case 0: LD4 (cpu
, address
); return;
12006 case 4: LD3 (cpu
, address
); return;
12007 case 8: LD2 (cpu
, address
); return;
12008 case 2: LD1_4 (cpu
, address
); return;
12009 case 6: LD1_3 (cpu
, address
); return;
12010 case 10: LD1_2 (cpu
, address
); return;
12011 case 7: LD1_1 (cpu
, address
); return;
12021 case 0: ST4 (cpu
, address
); return;
12022 case 4: ST3 (cpu
, address
); return;
12023 case 8: ST2 (cpu
, address
); return;
12024 case 2: ST1_4 (cpu
, address
); return;
12025 case 6: ST1_3 (cpu
, address
); return;
12026 case 10: ST1_2 (cpu
, address
); return;
12027 case 7: ST1_1 (cpu
, address
); return;
12034 dexLdSt (sim_cpu
*cpu
)
12036 /* uint32_t group = dispatchGroup (aarch64_get_instr (cpu));
12037 assert group == GROUP_LDST_0100 || group == GROUP_LDST_0110 ||
12038 group == GROUP_LDST_1100 || group == GROUP_LDST_1110
12039 bits [29,28:26] of a LS are the secondary dispatch vector. */
12040 uint32_t group2
= dispatchLS (aarch64_get_instr (cpu
));
12045 dexLoadExclusive (cpu
); return;
12049 dexLoadLiteral (cpu
); return;
12053 dexLoadOther (cpu
); return;
12055 case LS_ADVSIMD_001
:
12056 do_vec_load_store (cpu
); return;
12059 dex_load_store_pair_gr (cpu
); return;
12062 dex_load_store_pair_fp (cpu
); return;
12065 /* Should never reach here. */
12070 /* Specific decode and execute for group Data Processing Register. */
12073 dexLogicalShiftedRegister (sim_cpu
*cpu
)
12075 /* instr[31] = size : 0 ==> 32 bit, 1 ==> 64 bit
12077 instr[28:24] = 01010
12078 instr[23,22] = shift : 0 ==> LSL, 1 ==> LSR, 2 ==> ASR, 3 ==> ROR
12081 instr[15,10] = count : must be 0xxxxx for 32 bit
12085 uint32_t size
= INSTR (31, 31);
12086 Shift shiftType
= INSTR (23, 22);
12087 uint32_t count
= INSTR (15, 10);
12089 /* 32 bit operations must have count[5] = 0.
12090 or else we have an UNALLOC. */
12091 if (size
== 0 && uimm (count
, 5, 5))
12094 /* Dispatch on size:op:N. */
12095 switch ((INSTR (31, 29) << 1) | INSTR (21, 21))
12097 case 0: and32_shift (cpu
, shiftType
, count
); return;
12098 case 1: bic32_shift (cpu
, shiftType
, count
); return;
12099 case 2: orr32_shift (cpu
, shiftType
, count
); return;
12100 case 3: orn32_shift (cpu
, shiftType
, count
); return;
12101 case 4: eor32_shift (cpu
, shiftType
, count
); return;
12102 case 5: eon32_shift (cpu
, shiftType
, count
); return;
12103 case 6: ands32_shift (cpu
, shiftType
, count
); return;
12104 case 7: bics32_shift (cpu
, shiftType
, count
); return;
12105 case 8: and64_shift (cpu
, shiftType
, count
); return;
12106 case 9: bic64_shift (cpu
, shiftType
, count
); return;
12107 case 10:orr64_shift (cpu
, shiftType
, count
); return;
12108 case 11:orn64_shift (cpu
, shiftType
, count
); return;
12109 case 12:eor64_shift (cpu
, shiftType
, count
); return;
12110 case 13:eon64_shift (cpu
, shiftType
, count
); return;
12111 case 14:ands64_shift (cpu
, shiftType
, count
); return;
12112 case 15:bics64_shift (cpu
, shiftType
, count
); return;
12116 /* 32 bit conditional select. */
12118 csel32 (sim_cpu
*cpu
, CondCode cc
)
12120 unsigned rm
= INSTR (20, 16);
12121 unsigned rn
= INSTR (9, 5);
12122 unsigned rd
= INSTR (4, 0);
12124 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
,
12125 testConditionCode (cpu
, cc
)
12126 ? aarch64_get_reg_u32 (cpu
, rn
, NO_SP
)
12127 : aarch64_get_reg_u32 (cpu
, rm
, NO_SP
));
12130 /* 64 bit conditional select. */
12132 csel64 (sim_cpu
*cpu
, CondCode cc
)
12134 unsigned rm
= INSTR (20, 16);
12135 unsigned rn
= INSTR (9, 5);
12136 unsigned rd
= INSTR (4, 0);
12138 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
,
12139 testConditionCode (cpu
, cc
)
12140 ? aarch64_get_reg_u64 (cpu
, rn
, NO_SP
)
12141 : aarch64_get_reg_u64 (cpu
, rm
, NO_SP
));
12144 /* 32 bit conditional increment. */
12146 csinc32 (sim_cpu
*cpu
, CondCode cc
)
12148 unsigned rm
= INSTR (20, 16);
12149 unsigned rn
= INSTR (9, 5);
12150 unsigned rd
= INSTR (4, 0);
12152 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
,
12153 testConditionCode (cpu
, cc
)
12154 ? aarch64_get_reg_u32 (cpu
, rn
, NO_SP
)
12155 : aarch64_get_reg_u32 (cpu
, rm
, NO_SP
) + 1);
12158 /* 64 bit conditional increment. */
12160 csinc64 (sim_cpu
*cpu
, CondCode cc
)
12162 unsigned rm
= INSTR (20, 16);
12163 unsigned rn
= INSTR (9, 5);
12164 unsigned rd
= INSTR (4, 0);
12166 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
,
12167 testConditionCode (cpu
, cc
)
12168 ? aarch64_get_reg_u64 (cpu
, rn
, NO_SP
)
12169 : aarch64_get_reg_u64 (cpu
, rm
, NO_SP
) + 1);
12172 /* 32 bit conditional invert. */
12174 csinv32 (sim_cpu
*cpu
, CondCode cc
)
12176 unsigned rm
= INSTR (20, 16);
12177 unsigned rn
= INSTR (9, 5);
12178 unsigned rd
= INSTR (4, 0);
12180 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
,
12181 testConditionCode (cpu
, cc
)
12182 ? aarch64_get_reg_u32 (cpu
, rn
, NO_SP
)
12183 : ~ aarch64_get_reg_u32 (cpu
, rm
, NO_SP
));
12186 /* 64 bit conditional invert. */
12188 csinv64 (sim_cpu
*cpu
, CondCode cc
)
12190 unsigned rm
= INSTR (20, 16);
12191 unsigned rn
= INSTR (9, 5);
12192 unsigned rd
= INSTR (4, 0);
12194 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
,
12195 testConditionCode (cpu
, cc
)
12196 ? aarch64_get_reg_u64 (cpu
, rn
, NO_SP
)
12197 : ~ aarch64_get_reg_u64 (cpu
, rm
, NO_SP
));
12200 /* 32 bit conditional negate. */
12202 csneg32 (sim_cpu
*cpu
, CondCode cc
)
12204 unsigned rm
= INSTR (20, 16);
12205 unsigned rn
= INSTR (9, 5);
12206 unsigned rd
= INSTR (4, 0);
12208 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
,
12209 testConditionCode (cpu
, cc
)
12210 ? aarch64_get_reg_u32 (cpu
, rn
, NO_SP
)
12211 : - aarch64_get_reg_u32 (cpu
, rm
, NO_SP
));
12214 /* 64 bit conditional negate. */
12216 csneg64 (sim_cpu
*cpu
, CondCode cc
)
12218 unsigned rm
= INSTR (20, 16);
12219 unsigned rn
= INSTR (9, 5);
12220 unsigned rd
= INSTR (4, 0);
12222 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
,
12223 testConditionCode (cpu
, cc
)
12224 ? aarch64_get_reg_u64 (cpu
, rn
, NO_SP
)
12225 : - aarch64_get_reg_u64 (cpu
, rm
, NO_SP
));
12229 dexCondSelect (sim_cpu
*cpu
)
12231 /* instr[28,21] = 11011011
12232 instr[31] = size : 0 ==> 32 bit, 1 ==> 64 bit
12233 instr[30:11,10] = op : 000 ==> CSEL, 001 ==> CSINC,
12234 100 ==> CSINV, 101 ==> CSNEG,
12236 instr[29] = S : 0 ==> ok, 1 ==> UNALLOC
12237 instr[15,12] = cond
12238 instr[29] = S : 0 ==> ok, 1 ==> UNALLOC */
12240 CondCode cc
= INSTR (15, 12);
12241 uint32_t S
= INSTR (29, 29);
12242 uint32_t op2
= INSTR (11, 10);
12250 switch ((INSTR (31, 30) << 1) | op2
)
12252 case 0: csel32 (cpu
, cc
); return;
12253 case 1: csinc32 (cpu
, cc
); return;
12254 case 2: csinv32 (cpu
, cc
); return;
12255 case 3: csneg32 (cpu
, cc
); return;
12256 case 4: csel64 (cpu
, cc
); return;
12257 case 5: csinc64 (cpu
, cc
); return;
12258 case 6: csinv64 (cpu
, cc
); return;
12259 case 7: csneg64 (cpu
, cc
); return;
12263 /* Some helpers for counting leading 1 or 0 bits. */
12265 /* Counts the number of leading bits which are the same
12266 in a 32 bit value in the range 1 to 32. */
12268 leading32 (uint32_t value
)
12270 int32_t mask
= 0xffff0000;
12271 uint32_t count
= 16; /* Counts number of bits set in mask. */
12272 uint32_t lo
= 1; /* Lower bound for number of sign bits. */
12273 uint32_t hi
= 32; /* Upper bound for number of sign bits. */
12275 while (lo
+ 1 < hi
)
12277 int32_t test
= (value
& mask
);
12279 if (test
== 0 || test
== mask
)
12282 count
= (lo
+ hi
) / 2;
12283 mask
>>= (count
- lo
);
12288 count
= (lo
+ hi
) / 2;
12289 mask
<<= hi
- count
;
12298 test
= (value
& mask
);
12300 if (test
== 0 || test
== mask
)
12309 /* Counts the number of leading bits which are the same
12310 in a 64 bit value in the range 1 to 64. */
12312 leading64 (uint64_t value
)
12314 int64_t mask
= 0xffffffff00000000LL
;
12315 uint64_t count
= 32; /* Counts number of bits set in mask. */
12316 uint64_t lo
= 1; /* Lower bound for number of sign bits. */
12317 uint64_t hi
= 64; /* Upper bound for number of sign bits. */
12319 while (lo
+ 1 < hi
)
12321 int64_t test
= (value
& mask
);
12323 if (test
== 0 || test
== mask
)
12326 count
= (lo
+ hi
) / 2;
12327 mask
>>= (count
- lo
);
12332 count
= (lo
+ hi
) / 2;
12333 mask
<<= hi
- count
;
12342 test
= (value
& mask
);
12344 if (test
== 0 || test
== mask
)
12353 /* Bit operations. */
12354 /* N.B register args may not be SP. */
12356 /* 32 bit count leading sign bits. */
12358 cls32 (sim_cpu
*cpu
)
12360 unsigned rn
= INSTR (9, 5);
12361 unsigned rd
= INSTR (4, 0);
12363 /* N.B. the result needs to exclude the leading bit. */
12364 aarch64_set_reg_u64
12365 (cpu
, rd
, NO_SP
, leading32 (aarch64_get_reg_u32 (cpu
, rn
, NO_SP
)) - 1);
12368 /* 64 bit count leading sign bits. */
12370 cls64 (sim_cpu
*cpu
)
12372 unsigned rn
= INSTR (9, 5);
12373 unsigned rd
= INSTR (4, 0);
12375 /* N.B. the result needs to exclude the leading bit. */
12376 aarch64_set_reg_u64
12377 (cpu
, rd
, NO_SP
, leading64 (aarch64_get_reg_u64 (cpu
, rn
, NO_SP
)) - 1);
12380 /* 32 bit count leading zero bits. */
12382 clz32 (sim_cpu
*cpu
)
12384 unsigned rn
= INSTR (9, 5);
12385 unsigned rd
= INSTR (4, 0);
12386 uint32_t value
= aarch64_get_reg_u32 (cpu
, rn
, NO_SP
);
12388 /* if the sign (top) bit is set then the count is 0. */
12389 if (pick32 (value
, 31, 31))
12390 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, 0L);
12392 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, leading32 (value
));
12395 /* 64 bit count leading zero bits. */
12397 clz64 (sim_cpu
*cpu
)
12399 unsigned rn
= INSTR (9, 5);
12400 unsigned rd
= INSTR (4, 0);
12401 uint64_t value
= aarch64_get_reg_u64 (cpu
, rn
, NO_SP
);
12403 /* if the sign (top) bit is set then the count is 0. */
12404 if (pick64 (value
, 63, 63))
12405 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, 0L);
12407 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, leading64 (value
));
12410 /* 32 bit reverse bits. */
12412 rbit32 (sim_cpu
*cpu
)
12414 unsigned rn
= INSTR (9, 5);
12415 unsigned rd
= INSTR (4, 0);
12416 uint32_t value
= aarch64_get_reg_u32 (cpu
, rn
, NO_SP
);
12417 uint32_t result
= 0;
12420 for (i
= 0; i
< 32; i
++)
12423 result
|= (value
& 1);
12426 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, result
);
12429 /* 64 bit reverse bits. */
12431 rbit64 (sim_cpu
*cpu
)
12433 unsigned rn
= INSTR (9, 5);
12434 unsigned rd
= INSTR (4, 0);
12435 uint64_t value
= aarch64_get_reg_u64 (cpu
, rn
, NO_SP
);
12436 uint64_t result
= 0;
12439 for (i
= 0; i
< 64; i
++)
12442 result
|= (value
& 1UL);
12445 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, result
);
12448 /* 32 bit reverse bytes. */
12450 rev32 (sim_cpu
*cpu
)
12452 unsigned rn
= INSTR (9, 5);
12453 unsigned rd
= INSTR (4, 0);
12454 uint32_t value
= aarch64_get_reg_u32 (cpu
, rn
, NO_SP
);
12455 uint32_t result
= 0;
12458 for (i
= 0; i
< 4; i
++)
12461 result
|= (value
& 0xff);
12464 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, result
);
12467 /* 64 bit reverse bytes. */
12469 rev64 (sim_cpu
*cpu
)
12471 unsigned rn
= INSTR (9, 5);
12472 unsigned rd
= INSTR (4, 0);
12473 uint64_t value
= aarch64_get_reg_u64 (cpu
, rn
, NO_SP
);
12474 uint64_t result
= 0;
12477 for (i
= 0; i
< 8; i
++)
12480 result
|= (value
& 0xffULL
);
12483 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, result
);
12486 /* 32 bit reverse shorts. */
12487 /* N.B.this reverses the order of the bytes in each half word. */
12489 revh32 (sim_cpu
*cpu
)
12491 unsigned rn
= INSTR (9, 5);
12492 unsigned rd
= INSTR (4, 0);
12493 uint32_t value
= aarch64_get_reg_u32 (cpu
, rn
, NO_SP
);
12494 uint32_t result
= 0;
12497 for (i
= 0; i
< 2; i
++)
12500 result
|= (value
& 0x00ff00ff);
12503 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, result
);
12506 /* 64 bit reverse shorts. */
12507 /* N.B.this reverses the order of the bytes in each half word. */
12509 revh64 (sim_cpu
*cpu
)
12511 unsigned rn
= INSTR (9, 5);
12512 unsigned rd
= INSTR (4, 0);
12513 uint64_t value
= aarch64_get_reg_u64 (cpu
, rn
, NO_SP
);
12514 uint64_t result
= 0;
12517 for (i
= 0; i
< 2; i
++)
12520 result
|= (value
& 0x00ff00ff00ff00ffULL
);
12523 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, result
);
12527 dexDataProc1Source (sim_cpu
*cpu
)
12530 instr[28,21] = 111010110
12531 instr[31] = size : 0 ==> 32 bit, 1 ==> 64 bit
12532 instr[29] = S : 0 ==> ok, 1 ==> UNALLOC
12533 instr[20,16] = opcode2 : 00000 ==> ok, ow ==> UNALLOC
12534 instr[15,10] = opcode : 000000 ==> RBIT, 000001 ==> REV16,
12535 000010 ==> REV, 000011 ==> UNALLOC
12536 000100 ==> CLZ, 000101 ==> CLS
12538 instr[9,5] = rn : may not be SP
12539 instr[4,0] = rd : may not be SP. */
12541 uint32_t S
= INSTR (29, 29);
12542 uint32_t opcode2
= INSTR (20, 16);
12543 uint32_t opcode
= INSTR (15, 10);
12544 uint32_t dispatch
= ((INSTR (31, 31) << 3) | opcode
);
12557 case 0: rbit32 (cpu
); return;
12558 case 1: revh32 (cpu
); return;
12559 case 2: rev32 (cpu
); return;
12560 case 4: clz32 (cpu
); return;
12561 case 5: cls32 (cpu
); return;
12562 case 8: rbit64 (cpu
); return;
12563 case 9: revh64 (cpu
); return;
12564 case 10:rev32 (cpu
); return;
12565 case 11:rev64 (cpu
); return;
12566 case 12:clz64 (cpu
); return;
12567 case 13:cls64 (cpu
); return;
12568 default: HALT_UNALLOC
;
12573 Shifts by count supplied in register.
12574 N.B register args may not be SP.
12575 These all use the shifted auxiliary function for
12576 simplicity and clarity. Writing the actual shift
12577 inline would avoid a branch and so be faster but
12578 would also necessitate getting signs right. */
12580 /* 32 bit arithmetic shift right. */
12582 asrv32 (sim_cpu
*cpu
)
12584 unsigned rm
= INSTR (20, 16);
12585 unsigned rn
= INSTR (9, 5);
12586 unsigned rd
= INSTR (4, 0);
12588 aarch64_set_reg_u64
12590 shifted32 (aarch64_get_reg_u32 (cpu
, rn
, NO_SP
), ASR
,
12591 (aarch64_get_reg_u32 (cpu
, rm
, NO_SP
) & 0x1f)));
12594 /* 64 bit arithmetic shift right. */
12596 asrv64 (sim_cpu
*cpu
)
12598 unsigned rm
= INSTR (20, 16);
12599 unsigned rn
= INSTR (9, 5);
12600 unsigned rd
= INSTR (4, 0);
12602 aarch64_set_reg_u64
12604 shifted64 (aarch64_get_reg_u64 (cpu
, rn
, NO_SP
), ASR
,
12605 (aarch64_get_reg_u64 (cpu
, rm
, NO_SP
) & 0x3f)));
12608 /* 32 bit logical shift left. */
12610 lslv32 (sim_cpu
*cpu
)
12612 unsigned rm
= INSTR (20, 16);
12613 unsigned rn
= INSTR (9, 5);
12614 unsigned rd
= INSTR (4, 0);
12616 aarch64_set_reg_u64
12618 shifted32 (aarch64_get_reg_u32 (cpu
, rn
, NO_SP
), LSL
,
12619 (aarch64_get_reg_u32 (cpu
, rm
, NO_SP
) & 0x1f)));
12622 /* 64 bit arithmetic shift left. */
12624 lslv64 (sim_cpu
*cpu
)
12626 unsigned rm
= INSTR (20, 16);
12627 unsigned rn
= INSTR (9, 5);
12628 unsigned rd
= INSTR (4, 0);
12630 aarch64_set_reg_u64
12632 shifted64 (aarch64_get_reg_u64 (cpu
, rn
, NO_SP
), LSL
,
12633 (aarch64_get_reg_u64 (cpu
, rm
, NO_SP
) & 0x3f)));
12636 /* 32 bit logical shift right. */
12638 lsrv32 (sim_cpu
*cpu
)
12640 unsigned rm
= INSTR (20, 16);
12641 unsigned rn
= INSTR (9, 5);
12642 unsigned rd
= INSTR (4, 0);
12644 aarch64_set_reg_u64
12646 shifted32 (aarch64_get_reg_u32 (cpu
, rn
, NO_SP
), LSR
,
12647 (aarch64_get_reg_u32 (cpu
, rm
, NO_SP
) & 0x1f)));
12650 /* 64 bit logical shift right. */
12652 lsrv64 (sim_cpu
*cpu
)
12654 unsigned rm
= INSTR (20, 16);
12655 unsigned rn
= INSTR (9, 5);
12656 unsigned rd
= INSTR (4, 0);
12658 aarch64_set_reg_u64
12660 shifted64 (aarch64_get_reg_u64 (cpu
, rn
, NO_SP
), LSR
,
12661 (aarch64_get_reg_u64 (cpu
, rm
, NO_SP
) & 0x3f)));
12664 /* 32 bit rotate right. */
12666 rorv32 (sim_cpu
*cpu
)
12668 unsigned rm
= INSTR (20, 16);
12669 unsigned rn
= INSTR (9, 5);
12670 unsigned rd
= INSTR (4, 0);
12672 aarch64_set_reg_u64
12674 shifted32 (aarch64_get_reg_u32 (cpu
, rn
, NO_SP
), ROR
,
12675 (aarch64_get_reg_u32 (cpu
, rm
, NO_SP
) & 0x1f)));
12678 /* 64 bit rotate right. */
12680 rorv64 (sim_cpu
*cpu
)
12682 unsigned rm
= INSTR (20, 16);
12683 unsigned rn
= INSTR (9, 5);
12684 unsigned rd
= INSTR (4, 0);
12686 aarch64_set_reg_u64
12688 shifted64 (aarch64_get_reg_u64 (cpu
, rn
, NO_SP
), ROR
,
12689 (aarch64_get_reg_u64 (cpu
, rm
, NO_SP
) & 0x3f)));
12695 /* 32 bit signed divide. */
12697 cpuiv32 (sim_cpu
*cpu
)
12699 unsigned rm
= INSTR (20, 16);
12700 unsigned rn
= INSTR (9, 5);
12701 unsigned rd
= INSTR (4, 0);
12702 /* N.B. the pseudo-code does the divide using 64 bit data. */
12703 /* TODO : check that this rounds towards zero as required. */
12704 int64_t dividend
= aarch64_get_reg_s32 (cpu
, rn
, NO_SP
);
12705 int64_t divisor
= aarch64_get_reg_s32 (cpu
, rm
, NO_SP
);
12707 aarch64_set_reg_s64 (cpu
, rd
, NO_SP
,
12708 divisor
? ((int32_t) (dividend
/ divisor
)) : 0);
12711 /* 64 bit signed divide. */
12713 cpuiv64 (sim_cpu
*cpu
)
12715 unsigned rm
= INSTR (20, 16);
12716 unsigned rn
= INSTR (9, 5);
12717 unsigned rd
= INSTR (4, 0);
12719 /* TODO : check that this rounds towards zero as required. */
12720 int64_t divisor
= aarch64_get_reg_s64 (cpu
, rm
, NO_SP
);
12722 aarch64_set_reg_s64
12724 divisor
? (aarch64_get_reg_s64 (cpu
, rn
, NO_SP
) / divisor
) : 0);
12727 /* 32 bit unsigned divide. */
12729 udiv32 (sim_cpu
*cpu
)
12731 unsigned rm
= INSTR (20, 16);
12732 unsigned rn
= INSTR (9, 5);
12733 unsigned rd
= INSTR (4, 0);
12735 /* N.B. the pseudo-code does the divide using 64 bit data. */
12736 uint64_t dividend
= aarch64_get_reg_u32 (cpu
, rn
, NO_SP
);
12737 uint64_t divisor
= aarch64_get_reg_u32 (cpu
, rm
, NO_SP
);
12739 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
,
12740 divisor
? (uint32_t) (dividend
/ divisor
) : 0);
12743 /* 64 bit unsigned divide. */
12745 udiv64 (sim_cpu
*cpu
)
12747 unsigned rm
= INSTR (20, 16);
12748 unsigned rn
= INSTR (9, 5);
12749 unsigned rd
= INSTR (4, 0);
12751 /* TODO : check that this rounds towards zero as required. */
12752 uint64_t divisor
= aarch64_get_reg_u64 (cpu
, rm
, NO_SP
);
12754 aarch64_set_reg_u64
12756 divisor
? (aarch64_get_reg_u64 (cpu
, rn
, NO_SP
) / divisor
) : 0);
12760 dexDataProc2Source (sim_cpu
*cpu
)
12762 /* assert instr[30] == 0
12763 instr[28,21] == 11010110
12764 instr[31] = size : 0 ==> 32 bit, 1 ==> 64 bit
12765 instr[29] = S : 0 ==> ok, 1 ==> UNALLOC
12766 instr[15,10] = opcode : 000010 ==> UDIV, 000011 ==> CPUIV,
12767 001000 ==> LSLV, 001001 ==> LSRV
12768 001010 ==> ASRV, 001011 ==> RORV
12772 uint32_t S
= INSTR (29, 29);
12773 uint32_t opcode
= INSTR (15, 10);
12781 dispatch
= ( (INSTR (31, 31) << 3)
12782 | (uimm (opcode
, 3, 3) << 2)
12783 | uimm (opcode
, 1, 0));
12786 case 2: udiv32 (cpu
); return;
12787 case 3: cpuiv32 (cpu
); return;
12788 case 4: lslv32 (cpu
); return;
12789 case 5: lsrv32 (cpu
); return;
12790 case 6: asrv32 (cpu
); return;
12791 case 7: rorv32 (cpu
); return;
12792 case 10: udiv64 (cpu
); return;
12793 case 11: cpuiv64 (cpu
); return;
12794 case 12: lslv64 (cpu
); return;
12795 case 13: lsrv64 (cpu
); return;
12796 case 14: asrv64 (cpu
); return;
12797 case 15: rorv64 (cpu
); return;
12798 default: HALT_UNALLOC
;
12805 /* 32 bit multiply and add. */
12807 madd32 (sim_cpu
*cpu
)
12809 unsigned rm
= INSTR (20, 16);
12810 unsigned ra
= INSTR (14, 10);
12811 unsigned rn
= INSTR (9, 5);
12812 unsigned rd
= INSTR (4, 0);
12814 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
12815 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
,
12816 aarch64_get_reg_u32 (cpu
, ra
, NO_SP
)
12817 + aarch64_get_reg_u32 (cpu
, rn
, NO_SP
)
12818 * aarch64_get_reg_u32 (cpu
, rm
, NO_SP
));
12821 /* 64 bit multiply and add. */
12823 madd64 (sim_cpu
*cpu
)
12825 unsigned rm
= INSTR (20, 16);
12826 unsigned ra
= INSTR (14, 10);
12827 unsigned rn
= INSTR (9, 5);
12828 unsigned rd
= INSTR (4, 0);
12830 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
12831 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
,
12832 aarch64_get_reg_u64 (cpu
, ra
, NO_SP
)
12833 + (aarch64_get_reg_u64 (cpu
, rn
, NO_SP
)
12834 * aarch64_get_reg_u64 (cpu
, rm
, NO_SP
)));
12837 /* 32 bit multiply and sub. */
12839 msub32 (sim_cpu
*cpu
)
12841 unsigned rm
= INSTR (20, 16);
12842 unsigned ra
= INSTR (14, 10);
12843 unsigned rn
= INSTR (9, 5);
12844 unsigned rd
= INSTR (4, 0);
12846 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
12847 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
,
12848 aarch64_get_reg_u32 (cpu
, ra
, NO_SP
)
12849 - aarch64_get_reg_u32 (cpu
, rn
, NO_SP
)
12850 * aarch64_get_reg_u32 (cpu
, rm
, NO_SP
));
12853 /* 64 bit multiply and sub. */
12855 msub64 (sim_cpu
*cpu
)
12857 unsigned rm
= INSTR (20, 16);
12858 unsigned ra
= INSTR (14, 10);
12859 unsigned rn
= INSTR (9, 5);
12860 unsigned rd
= INSTR (4, 0);
12862 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
12863 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
,
12864 aarch64_get_reg_u64 (cpu
, ra
, NO_SP
)
12865 - aarch64_get_reg_u64 (cpu
, rn
, NO_SP
)
12866 * aarch64_get_reg_u64 (cpu
, rm
, NO_SP
));
12869 /* Signed multiply add long -- source, source2 : 32 bit, source3 : 64 bit. */
12871 smaddl (sim_cpu
*cpu
)
12873 unsigned rm
= INSTR (20, 16);
12874 unsigned ra
= INSTR (14, 10);
12875 unsigned rn
= INSTR (9, 5);
12876 unsigned rd
= INSTR (4, 0);
12878 /* N.B. we need to multiply the signed 32 bit values in rn, rm to
12879 obtain a 64 bit product. */
12880 aarch64_set_reg_s64
12882 aarch64_get_reg_s64 (cpu
, ra
, NO_SP
)
12883 + ((int64_t) aarch64_get_reg_s32 (cpu
, rn
, NO_SP
))
12884 * ((int64_t) aarch64_get_reg_s32 (cpu
, rm
, NO_SP
)));
12887 /* Signed multiply sub long -- source, source2 : 32 bit, source3 : 64 bit. */
12889 smsubl (sim_cpu
*cpu
)
12891 unsigned rm
= INSTR (20, 16);
12892 unsigned ra
= INSTR (14, 10);
12893 unsigned rn
= INSTR (9, 5);
12894 unsigned rd
= INSTR (4, 0);
12896 /* N.B. we need to multiply the signed 32 bit values in rn, rm to
12897 obtain a 64 bit product. */
12898 aarch64_set_reg_s64
12900 aarch64_get_reg_s64 (cpu
, ra
, NO_SP
)
12901 - ((int64_t) aarch64_get_reg_s32 (cpu
, rn
, NO_SP
))
12902 * ((int64_t) aarch64_get_reg_s32 (cpu
, rm
, NO_SP
)));
12905 /* Integer Multiply/Divide. */
12907 /* First some macros and a helper function. */
12908 /* Macros to test or access elements of 64 bit words. */
12910 /* Mask used to access lo 32 bits of 64 bit unsigned int. */
12911 #define LOW_WORD_MASK ((1ULL << 32) - 1)
12912 /* Return the lo 32 bit word of a 64 bit unsigned int as a 64 bit unsigned int. */
12913 #define lowWordToU64(_value_u64) ((_value_u64) & LOW_WORD_MASK)
12914 /* Return the hi 32 bit word of a 64 bit unsigned int as a 64 bit unsigned int. */
12915 #define highWordToU64(_value_u64) ((_value_u64) >> 32)
12917 /* Offset of sign bit in 64 bit signed integger. */
12918 #define SIGN_SHIFT_U64 63
12919 /* The sign bit itself -- also identifies the minimum negative int value. */
12920 #define SIGN_BIT_U64 (1UL << SIGN_SHIFT_U64)
12921 /* Return true if a 64 bit signed int presented as an unsigned int is the
12922 most negative value. */
12923 #define isMinimumU64(_value_u64) ((_value_u64) == SIGN_BIT_U64)
12924 /* Return true (non-zero) if a 64 bit signed int presented as an unsigned
12925 int has its sign bit set to false. */
12926 #define isSignSetU64(_value_u64) ((_value_u64) & SIGN_BIT_U64)
12927 /* Return 1L or -1L according to whether a 64 bit signed int presented as
12928 an unsigned int has its sign bit set or not. */
12929 #define signOfU64(_value_u64) (1L + (((value_u64) >> SIGN_SHIFT_U64) * -2L)
12930 /* Clear the sign bit of a 64 bit signed int presented as an unsigned int. */
12931 #define clearSignU64(_value_u64) ((_value_u64) &= ~SIGN_BIT_U64)
12933 /* Multiply two 64 bit ints and return.
12934 the hi 64 bits of the 128 bit product. */
12937 mul64hi (uint64_t value1
, uint64_t value2
)
12939 uint64_t resultmid1
;
12941 uint64_t value1_lo
= lowWordToU64 (value1
);
12942 uint64_t value1_hi
= highWordToU64 (value1
) ;
12943 uint64_t value2_lo
= lowWordToU64 (value2
);
12944 uint64_t value2_hi
= highWordToU64 (value2
);
12946 /* Cross-multiply and collect results. */
12947 uint64_t xproductlo
= value1_lo
* value2_lo
;
12948 uint64_t xproductmid1
= value1_lo
* value2_hi
;
12949 uint64_t xproductmid2
= value1_hi
* value2_lo
;
12950 uint64_t xproducthi
= value1_hi
* value2_hi
;
12951 uint64_t carry
= 0;
12952 /* Start accumulating 64 bit results. */
12953 /* Drop bottom half of lowest cross-product. */
12954 uint64_t resultmid
= xproductlo
>> 32;
12955 /* Add in middle products. */
12956 resultmid
= resultmid
+ xproductmid1
;
12958 /* Check for overflow. */
12959 if (resultmid
< xproductmid1
)
12960 /* Carry over 1 into top cross-product. */
12963 resultmid1
= resultmid
+ xproductmid2
;
12965 /* Check for overflow. */
12966 if (resultmid1
< xproductmid2
)
12967 /* Carry over 1 into top cross-product. */
12970 /* Drop lowest 32 bits of middle cross-product. */
12971 result
= resultmid1
>> 32;
12973 /* Add top cross-product plus and any carry. */
12974 result
+= xproducthi
+ carry
;
12979 /* Signed multiply high, source, source2 :
12980 64 bit, dest <-- high 64-bit of result. */
12982 smulh (sim_cpu
*cpu
)
12986 unsigned rm
= INSTR (20, 16);
12987 unsigned rn
= INSTR (9, 5);
12988 unsigned rd
= INSTR (4, 0);
12989 GReg ra
= INSTR (14, 10);
12990 int64_t value1
= aarch64_get_reg_u64 (cpu
, rn
, NO_SP
);
12991 int64_t value2
= aarch64_get_reg_u64 (cpu
, rm
, NO_SP
);
12994 int64_t signum
= 1;
12999 /* Convert to unsigned and use the unsigned mul64hi routine
13000 the fix the sign up afterwards. */
13021 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
13022 uresult
= mul64hi (uvalue1
, uvalue2
);
13026 aarch64_set_reg_s64 (cpu
, rd
, NO_SP
, result
);
13029 /* Unsigned multiply add long -- source, source2 :
13030 32 bit, source3 : 64 bit. */
13032 umaddl (sim_cpu
*cpu
)
13034 unsigned rm
= INSTR (20, 16);
13035 unsigned ra
= INSTR (14, 10);
13036 unsigned rn
= INSTR (9, 5);
13037 unsigned rd
= INSTR (4, 0);
13039 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
13040 /* N.B. we need to multiply the signed 32 bit values in rn, rm to
13041 obtain a 64 bit product. */
13042 aarch64_set_reg_u64
13044 aarch64_get_reg_u64 (cpu
, ra
, NO_SP
)
13045 + ((uint64_t) aarch64_get_reg_u32 (cpu
, rn
, NO_SP
))
13046 * ((uint64_t) aarch64_get_reg_u32 (cpu
, rm
, NO_SP
)));
13049 /* Unsigned multiply sub long -- source, source2 : 32 bit, source3 : 64 bit. */
13051 umsubl (sim_cpu
*cpu
)
13053 unsigned rm
= INSTR (20, 16);
13054 unsigned ra
= INSTR (14, 10);
13055 unsigned rn
= INSTR (9, 5);
13056 unsigned rd
= INSTR (4, 0);
13058 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
13059 /* N.B. we need to multiply the signed 32 bit values in rn, rm to
13060 obtain a 64 bit product. */
13061 aarch64_set_reg_u64
13063 aarch64_get_reg_u64 (cpu
, ra
, NO_SP
)
13064 - ((uint64_t) aarch64_get_reg_u32 (cpu
, rn
, NO_SP
))
13065 * ((uint64_t) aarch64_get_reg_u32 (cpu
, rm
, NO_SP
)));
13068 /* Unsigned multiply high, source, source2 :
13069 64 bit, dest <-- high 64-bit of result. */
13071 umulh (sim_cpu
*cpu
)
13073 unsigned rm
= INSTR (20, 16);
13074 unsigned rn
= INSTR (9, 5);
13075 unsigned rd
= INSTR (4, 0);
13076 GReg ra
= INSTR (14, 10);
13081 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
13082 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
,
13083 mul64hi (aarch64_get_reg_u64 (cpu
, rn
, NO_SP
),
13084 aarch64_get_reg_u64 (cpu
, rm
, NO_SP
)));
13088 dexDataProc3Source (sim_cpu
*cpu
)
13090 /* assert instr[28,24] == 11011. */
13091 /* instr[31] = size : 0 ==> 32 bit, 1 ==> 64 bit (for rd at least)
13092 instr[30,29] = op54 : 00 ==> ok, ow ==> UNALLOC
13093 instr[23,21] = op31 : 111 ==> UNALLOC, o2 ==> ok
13094 instr[15] = o0 : 0/1 ==> ok
13095 instr[23,21:15] ==> op : 0000 ==> MADD, 0001 ==> MSUB, (32/64 bit)
13096 0010 ==> SMADDL, 0011 ==> SMSUBL, (64 bit only)
13097 0100 ==> SMULH, (64 bit only)
13098 1010 ==> UMADDL, 1011 ==> UNSUBL, (64 bit only)
13099 1100 ==> UMULH (64 bit only)
13103 uint32_t size
= INSTR (31, 31);
13104 uint32_t op54
= INSTR (30, 29);
13105 uint32_t op31
= INSTR (23, 21);
13106 uint32_t o0
= INSTR (15, 15);
13123 dispatch
= (op31
<< 1) | o0
;
13127 case 0: madd64 (cpu
); return;
13128 case 1: msub64 (cpu
); return;
13129 case 2: smaddl (cpu
); return;
13130 case 3: smsubl (cpu
); return;
13131 case 4: smulh (cpu
); return;
13132 case 10: umaddl (cpu
); return;
13133 case 11: umsubl (cpu
); return;
13134 case 12: umulh (cpu
); return;
13135 default: HALT_UNALLOC
;
13140 dexDPReg (sim_cpu
*cpu
)
13142 /* uint32_t group = dispatchGroup (aarch64_get_instr (cpu));
13143 assert group == GROUP_DPREG_0101 || group == GROUP_DPREG_1101
13144 bits [28:24:21] of a DPReg are the secondary dispatch vector. */
13145 uint32_t group2
= dispatchDPReg (aarch64_get_instr (cpu
));
13149 case DPREG_LOG_000
:
13150 case DPREG_LOG_001
:
13151 dexLogicalShiftedRegister (cpu
); return;
13153 case DPREG_ADDSHF_010
:
13154 dexAddSubtractShiftedRegister (cpu
); return;
13156 case DPREG_ADDEXT_011
:
13157 dexAddSubtractExtendedRegister (cpu
); return;
13159 case DPREG_ADDCOND_100
:
13161 /* This set bundles a variety of different operations. */
13163 /* 1) add/sub w carry. */
13164 uint32_t mask1
= 0x1FE00000U
;
13165 uint32_t val1
= 0x1A000000U
;
13166 /* 2) cond compare register/immediate. */
13167 uint32_t mask2
= 0x1FE00000U
;
13168 uint32_t val2
= 0x1A400000U
;
13169 /* 3) cond select. */
13170 uint32_t mask3
= 0x1FE00000U
;
13171 uint32_t val3
= 0x1A800000U
;
13172 /* 4) data proc 1/2 source. */
13173 uint32_t mask4
= 0x1FE00000U
;
13174 uint32_t val4
= 0x1AC00000U
;
13176 if ((aarch64_get_instr (cpu
) & mask1
) == val1
)
13177 dexAddSubtractWithCarry (cpu
);
13179 else if ((aarch64_get_instr (cpu
) & mask2
) == val2
)
13182 else if ((aarch64_get_instr (cpu
) & mask3
) == val3
)
13183 dexCondSelect (cpu
);
13185 else if ((aarch64_get_instr (cpu
) & mask4
) == val4
)
13187 /* Bit 30 is clear for data proc 2 source
13188 and set for data proc 1 source. */
13189 if (aarch64_get_instr (cpu
) & (1U << 30))
13190 dexDataProc1Source (cpu
);
13192 dexDataProc2Source (cpu
);
13196 /* Should not reach here. */
13202 case DPREG_3SRC_110
:
13203 dexDataProc3Source (cpu
); return;
13205 case DPREG_UNALLOC_101
:
13208 case DPREG_3SRC_111
:
13209 dexDataProc3Source (cpu
); return;
13212 /* Should never reach here. */
13217 /* Unconditional Branch immediate.
13218 Offset is a PC-relative byte offset in the range +/- 128MiB.
13219 The offset is assumed to be raw from the decode i.e. the
13220 simulator is expected to scale them from word offsets to byte. */
13222 /* Unconditional branch. */
13224 buc (sim_cpu
*cpu
, int32_t offset
)
13226 aarch64_set_next_PC_by_offset (cpu
, offset
);
13229 static unsigned stack_depth
= 0;
13231 /* Unconditional branch and link -- writes return PC to LR. */
13233 bl (sim_cpu
*cpu
, int32_t offset
)
13235 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
13236 aarch64_save_LR (cpu
);
13237 aarch64_set_next_PC_by_offset (cpu
, offset
);
13239 if (TRACE_BRANCH_P (cpu
))
13243 " %*scall %" PRIx64
" [%s]"
13244 " [args: %" PRIx64
" %" PRIx64
" %" PRIx64
"]",
13245 stack_depth
, " ", aarch64_get_next_PC (cpu
),
13246 aarch64_get_func (CPU_STATE (cpu
),
13247 aarch64_get_next_PC (cpu
)),
13248 aarch64_get_reg_u64 (cpu
, 0, NO_SP
),
13249 aarch64_get_reg_u64 (cpu
, 1, NO_SP
),
13250 aarch64_get_reg_u64 (cpu
, 2, NO_SP
)
13255 /* Unconditional Branch register.
13256 Branch/return address is in source register. */
13258 /* Unconditional branch. */
13262 unsigned rn
= INSTR (9, 5);
13263 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
13264 aarch64_set_next_PC (cpu
, aarch64_get_reg_u64 (cpu
, rn
, NO_SP
));
13267 /* Unconditional branch and link -- writes return PC to LR. */
13271 unsigned rn
= INSTR (9, 5);
13273 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
13274 /* The pseudo code in the spec says we update LR before fetching.
13275 the value from the rn. */
13276 aarch64_save_LR (cpu
);
13277 aarch64_set_next_PC (cpu
, aarch64_get_reg_u64 (cpu
, rn
, NO_SP
));
13279 if (TRACE_BRANCH_P (cpu
))
13283 " %*scall %" PRIx64
" [%s]"
13284 " [args: %" PRIx64
" %" PRIx64
" %" PRIx64
"]",
13285 stack_depth
, " ", aarch64_get_next_PC (cpu
),
13286 aarch64_get_func (CPU_STATE (cpu
),
13287 aarch64_get_next_PC (cpu
)),
13288 aarch64_get_reg_u64 (cpu
, 0, NO_SP
),
13289 aarch64_get_reg_u64 (cpu
, 1, NO_SP
),
13290 aarch64_get_reg_u64 (cpu
, 2, NO_SP
)
13295 /* Return -- assembler will default source to LR this is functionally
13296 equivalent to br but, presumably, unlike br it side effects the
13297 branch predictor. */
13301 unsigned rn
= INSTR (9, 5);
13302 aarch64_set_next_PC (cpu
, aarch64_get_reg_u64 (cpu
, rn
, NO_SP
));
13304 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
13305 if (TRACE_BRANCH_P (cpu
))
13308 " %*sreturn [result: %" PRIx64
"]",
13309 stack_depth
, " ", aarch64_get_reg_u64 (cpu
, 0, NO_SP
));
13314 /* NOP -- we implement this and call it from the decode in case we
13315 want to intercept it later. */
13320 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
13323 /* Data synchronization barrier. */
13328 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
13331 /* Data memory barrier. */
13336 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
13339 /* Instruction synchronization barrier. */
13344 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
13348 dexBranchImmediate (sim_cpu
*cpu
)
13350 /* assert instr[30,26] == 00101
13351 instr[31] ==> 0 == B, 1 == BL
13352 instr[25,0] == imm26 branch offset counted in words. */
13354 uint32_t top
= INSTR (31, 31);
13355 /* We have a 26 byte signed word offset which we need to pass to the
13356 execute routine as a signed byte offset. */
13357 int32_t offset
= simm32 (aarch64_get_instr (cpu
), 25, 0) << 2;
13365 /* Control Flow. */
13367 /* Conditional branch
13369 Offset is a PC-relative byte offset in the range +/- 1MiB pos is
13370 a bit position in the range 0 .. 63
13372 cc is a CondCode enum value as pulled out of the decode
13374 N.B. any offset register (source) can only be Xn or Wn. */
13377 bcc (sim_cpu
*cpu
, int32_t offset
, CondCode cc
)
13379 /* The test returns TRUE if CC is met. */
13380 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
13381 if (testConditionCode (cpu
, cc
))
13382 aarch64_set_next_PC_by_offset (cpu
, offset
);
13385 /* 32 bit branch on register non-zero. */
13387 cbnz32 (sim_cpu
*cpu
, int32_t offset
)
13389 unsigned rt
= INSTR (4, 0);
13391 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
13392 if (aarch64_get_reg_u32 (cpu
, rt
, NO_SP
) != 0)
13393 aarch64_set_next_PC_by_offset (cpu
, offset
);
13396 /* 64 bit branch on register zero. */
13398 cbnz (sim_cpu
*cpu
, int32_t offset
)
13400 unsigned rt
= INSTR (4, 0);
13402 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
13403 if (aarch64_get_reg_u64 (cpu
, rt
, NO_SP
) != 0)
13404 aarch64_set_next_PC_by_offset (cpu
, offset
);
13407 /* 32 bit branch on register non-zero. */
13409 cbz32 (sim_cpu
*cpu
, int32_t offset
)
13411 unsigned rt
= INSTR (4, 0);
13413 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
13414 if (aarch64_get_reg_u32 (cpu
, rt
, NO_SP
) == 0)
13415 aarch64_set_next_PC_by_offset (cpu
, offset
);
13418 /* 64 bit branch on register zero. */
13420 cbz (sim_cpu
*cpu
, int32_t offset
)
13422 unsigned rt
= INSTR (4, 0);
13424 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
13425 if (aarch64_get_reg_u64 (cpu
, rt
, NO_SP
) == 0)
13426 aarch64_set_next_PC_by_offset (cpu
, offset
);
13429 /* Branch on register bit test non-zero -- one size fits all. */
13431 tbnz (sim_cpu
*cpu
, uint32_t pos
, int32_t offset
)
13433 unsigned rt
= INSTR (4, 0);
13435 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
13436 if (aarch64_get_reg_u64 (cpu
, rt
, NO_SP
) & (((uint64_t) 1) << pos
))
13437 aarch64_set_next_PC_by_offset (cpu
, offset
);
13440 /* Branch on register bit test zero -- one size fits all. */
13442 tbz (sim_cpu
*cpu
, uint32_t pos
, int32_t offset
)
13444 unsigned rt
= INSTR (4, 0);
13446 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
13447 if (!(aarch64_get_reg_u64 (cpu
, rt
, NO_SP
) & (((uint64_t) 1) << pos
)))
13448 aarch64_set_next_PC_by_offset (cpu
, offset
);
13452 dexCompareBranchImmediate (sim_cpu
*cpu
)
13454 /* instr[30,25] = 01 1010
13455 instr[31] = size : 0 ==> 32, 1 ==> 64
13456 instr[24] = op : 0 ==> CBZ, 1 ==> CBNZ
13457 instr[23,5] = simm19 branch offset counted in words
13460 uint32_t size
= INSTR (31, 31);
13461 uint32_t op
= INSTR (24, 24);
13462 int32_t offset
= simm32 (aarch64_get_instr (cpu
), 23, 5) << 2;
13467 cbz32 (cpu
, offset
);
13469 cbnz32 (cpu
, offset
);
13476 cbnz (cpu
, offset
);
13481 dexTestBranchImmediate (sim_cpu
*cpu
)
13483 /* instr[31] = b5 : bit 5 of test bit idx
13484 instr[30,25] = 01 1011
13485 instr[24] = op : 0 ==> TBZ, 1 == TBNZ
13486 instr[23,19] = b40 : bits 4 to 0 of test bit idx
13487 instr[18,5] = simm14 : signed offset counted in words
13488 instr[4,0] = uimm5 */
13490 uint32_t pos
= ((INSTR (31, 31) << 5) | INSTR (23, 19));
13491 int32_t offset
= simm32 (aarch64_get_instr (cpu
), 18, 5) << 2;
13493 NYI_assert (30, 25, 0x1b);
13495 if (INSTR (24, 24) == 0)
13496 tbz (cpu
, pos
, offset
);
13498 tbnz (cpu
, pos
, offset
);
13502 dexCondBranchImmediate (sim_cpu
*cpu
)
13504 /* instr[31,25] = 010 1010
13505 instr[24] = op1; op => 00 ==> B.cond
13506 instr[23,5] = simm19 : signed offset counted in words
13508 instr[3,0] = cond */
13511 uint32_t op
= ((INSTR (24, 24) << 1) | INSTR (4, 4));
13513 NYI_assert (31, 25, 0x2a);
13518 offset
= simm32 (aarch64_get_instr (cpu
), 23, 5) << 2;
13520 bcc (cpu
, offset
, INSTR (3, 0));
13524 dexBranchRegister (sim_cpu
*cpu
)
13526 /* instr[31,25] = 110 1011
13527 instr[24,21] = op : 0 ==> BR, 1 => BLR, 2 => RET, 3 => ERET, 4 => DRPS
13528 instr[20,16] = op2 : must be 11111
13529 instr[15,10] = op3 : must be 000000
13530 instr[4,0] = op2 : must be 11111. */
13532 uint32_t op
= INSTR (24, 21);
13533 uint32_t op2
= INSTR (20, 16);
13534 uint32_t op3
= INSTR (15, 10);
13535 uint32_t op4
= INSTR (4, 0);
13537 NYI_assert (31, 25, 0x6b);
13539 if (op2
!= 0x1F || op3
!= 0 || op4
!= 0)
13553 /* ERET and DRPS accept 0b11111 for rn = instr [4,0]. */
13554 /* anything else is unallocated. */
13555 uint32_t rn
= INSTR (4, 0);
13560 if (op
== 4 || op
== 5)
13567 /* FIXME: We should get the Angel SWI values from ../../libgloss/aarch64/svc.h
13568 but this may not be available. So instead we define the values we need
13570 #define AngelSVC_Reason_Open 0x01
13571 #define AngelSVC_Reason_Close 0x02
13572 #define AngelSVC_Reason_Write 0x05
13573 #define AngelSVC_Reason_Read 0x06
13574 #define AngelSVC_Reason_IsTTY 0x09
13575 #define AngelSVC_Reason_Seek 0x0A
13576 #define AngelSVC_Reason_FLen 0x0C
13577 #define AngelSVC_Reason_Remove 0x0E
13578 #define AngelSVC_Reason_Rename 0x0F
13579 #define AngelSVC_Reason_Clock 0x10
13580 #define AngelSVC_Reason_Time 0x11
13581 #define AngelSVC_Reason_System 0x12
13582 #define AngelSVC_Reason_Errno 0x13
13583 #define AngelSVC_Reason_GetCmdLine 0x15
13584 #define AngelSVC_Reason_HeapInfo 0x16
13585 #define AngelSVC_Reason_ReportException 0x18
13586 #define AngelSVC_Reason_Elapsed 0x30
13590 handle_halt (sim_cpu
*cpu
, uint32_t val
)
13592 uint64_t result
= 0;
13594 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
13597 TRACE_SYSCALL (cpu
, " HLT [0x%x]", val
);
13598 sim_engine_halt (CPU_STATE (cpu
), cpu
, NULL
, aarch64_get_PC (cpu
),
13599 sim_stopped
, SIM_SIGTRAP
);
13602 /* We have encountered an Angel SVC call. See if we can process it. */
13603 switch (aarch64_get_reg_u32 (cpu
, 0, NO_SP
))
13605 case AngelSVC_Reason_HeapInfo
:
13607 /* Get the values. */
13608 uint64_t stack_top
= aarch64_get_stack_start (cpu
);
13609 uint64_t heap_base
= aarch64_get_heap_start (cpu
);
13611 /* Get the pointer */
13612 uint64_t ptr
= aarch64_get_reg_u64 (cpu
, 1, SP_OK
);
13613 ptr
= aarch64_get_mem_u64 (cpu
, ptr
);
13615 /* Fill in the memory block. */
13616 /* Start addr of heap. */
13617 aarch64_set_mem_u64 (cpu
, ptr
+ 0, heap_base
);
13618 /* End addr of heap. */
13619 aarch64_set_mem_u64 (cpu
, ptr
+ 8, stack_top
);
13620 /* Lowest stack addr. */
13621 aarch64_set_mem_u64 (cpu
, ptr
+ 16, heap_base
);
13622 /* Initial stack addr. */
13623 aarch64_set_mem_u64 (cpu
, ptr
+ 24, stack_top
);
13625 TRACE_SYSCALL (cpu
, " AngelSVC: Get Heap Info");
13629 case AngelSVC_Reason_Open
:
13631 /* Get the pointer */
13632 /* uint64_t ptr = aarch64_get_reg_u64 (cpu, 1, SP_OK);. */
13633 /* FIXME: For now we just assume that we will only be asked
13634 to open the standard file descriptors. */
13638 TRACE_SYSCALL (cpu
, " AngelSVC: Open file %d", fd
- 1);
13642 case AngelSVC_Reason_Close
:
13644 uint64_t fh
= aarch64_get_reg_u64 (cpu
, 1, SP_OK
);
13645 TRACE_SYSCALL (cpu
, " AngelSVC: Close file %d", (int) fh
);
13650 case AngelSVC_Reason_Errno
:
13652 TRACE_SYSCALL (cpu
, " AngelSVC: Get Errno");
13655 case AngelSVC_Reason_Clock
:
13657 #ifdef CLOCKS_PER_SEC
13658 (CLOCKS_PER_SEC
>= 100)
13659 ? (clock () / (CLOCKS_PER_SEC
/ 100))
13660 : ((clock () * 100) / CLOCKS_PER_SEC
)
13662 /* Presume unix... clock() returns microseconds. */
13666 TRACE_SYSCALL (cpu
, " AngelSVC: Get Clock");
13669 case AngelSVC_Reason_GetCmdLine
:
13671 /* Get the pointer */
13672 uint64_t ptr
= aarch64_get_reg_u64 (cpu
, 1, SP_OK
);
13673 ptr
= aarch64_get_mem_u64 (cpu
, ptr
);
13675 /* FIXME: No command line for now. */
13676 aarch64_set_mem_u64 (cpu
, ptr
, 0);
13677 TRACE_SYSCALL (cpu
, " AngelSVC: Get Command Line");
13681 case AngelSVC_Reason_IsTTY
:
13683 TRACE_SYSCALL (cpu
, " AngelSVC: IsTTY ?");
13686 case AngelSVC_Reason_Write
:
13688 /* Get the pointer */
13689 uint64_t ptr
= aarch64_get_reg_u64 (cpu
, 1, SP_OK
);
13690 /* Get the write control block. */
13691 uint64_t fd
= aarch64_get_mem_u64 (cpu
, ptr
);
13692 uint64_t buf
= aarch64_get_mem_u64 (cpu
, ptr
+ 8);
13693 uint64_t len
= aarch64_get_mem_u64 (cpu
, ptr
+ 16);
13695 TRACE_SYSCALL (cpu
, "write of %" PRIx64
" bytes from %"
13696 PRIx64
" on descriptor %" PRIx64
,
13701 TRACE_SYSCALL (cpu
,
13702 " AngelSVC: Write: Suspiciously long write: %ld",
13704 sim_engine_halt (CPU_STATE (cpu
), cpu
, NULL
, aarch64_get_PC (cpu
),
13705 sim_stopped
, SIM_SIGBUS
);
13709 printf ("%.*s", (int) len
, aarch64_get_mem_ptr (cpu
, buf
));
13713 TRACE (cpu
, 0, "\n");
13714 sim_io_eprintf (CPU_STATE (cpu
), "%.*s",
13715 (int) len
, aarch64_get_mem_ptr (cpu
, buf
));
13716 TRACE (cpu
, 0, "\n");
13720 TRACE_SYSCALL (cpu
,
13721 " AngelSVC: Write: Unexpected file handle: %d",
13723 sim_engine_halt (CPU_STATE (cpu
), cpu
, NULL
, aarch64_get_PC (cpu
),
13724 sim_stopped
, SIM_SIGABRT
);
13729 case AngelSVC_Reason_ReportException
:
13731 /* Get the pointer */
13732 uint64_t ptr
= aarch64_get_reg_u64 (cpu
, 1, SP_OK
);
13733 /*ptr = aarch64_get_mem_u64 (cpu, ptr);. */
13734 uint64_t type
= aarch64_get_mem_u64 (cpu
, ptr
);
13735 uint64_t state
= aarch64_get_mem_u64 (cpu
, ptr
+ 8);
13737 TRACE_SYSCALL (cpu
,
13738 "Angel Exception: type 0x%" PRIx64
" state %" PRIx64
,
13741 if (type
== 0x20026)
13742 sim_engine_halt (CPU_STATE (cpu
), cpu
, NULL
, aarch64_get_PC (cpu
),
13743 sim_exited
, state
);
13745 sim_engine_halt (CPU_STATE (cpu
), cpu
, NULL
, aarch64_get_PC (cpu
),
13746 sim_stopped
, SIM_SIGINT
);
13750 case AngelSVC_Reason_Read
:
13751 case AngelSVC_Reason_FLen
:
13752 case AngelSVC_Reason_Seek
:
13753 case AngelSVC_Reason_Remove
:
13754 case AngelSVC_Reason_Time
:
13755 case AngelSVC_Reason_System
:
13756 case AngelSVC_Reason_Rename
:
13757 case AngelSVC_Reason_Elapsed
:
13759 TRACE_SYSCALL (cpu
, " HLT [Unknown angel %x]",
13760 aarch64_get_reg_u32 (cpu
, 0, NO_SP
));
13761 sim_engine_halt (CPU_STATE (cpu
), cpu
, NULL
, aarch64_get_PC (cpu
),
13762 sim_stopped
, SIM_SIGTRAP
);
13765 aarch64_set_reg_u64 (cpu
, 0, NO_SP
, result
);
13769 dexExcpnGen (sim_cpu
*cpu
)
13771 /* instr[31:24] = 11010100
13772 instr[23,21] = opc : 000 ==> GEN EXCPN, 001 ==> BRK
13773 010 ==> HLT, 101 ==> DBG GEN EXCPN
13774 instr[20,5] = imm16
13775 instr[4,2] = opc2 000 ==> OK, ow ==> UNALLOC
13776 instr[1,0] = LL : discriminates opc */
13778 uint32_t opc
= INSTR (23, 21);
13779 uint32_t imm16
= INSTR (20, 5);
13780 uint32_t opc2
= INSTR (4, 2);
13783 NYI_assert (31, 24, 0xd4);
13790 /* We only implement HLT and BRK for now. */
13791 if (opc
== 1 && LL
== 0)
13793 TRACE_EVENTS (cpu
, " BRK [0x%x]", imm16
);
13794 sim_engine_halt (CPU_STATE (cpu
), cpu
, NULL
, aarch64_get_PC (cpu
),
13795 sim_exited
, aarch64_get_reg_s32 (cpu
, R0
, SP_OK
));
13798 if (opc
== 2 && LL
== 0)
13799 handle_halt (cpu
, imm16
);
13801 else if (opc
== 0 || opc
== 5)
13808 /* Stub for accessing system registers. */
13811 system_get (sim_cpu
*cpu
, unsigned op0
, unsigned op1
, unsigned crn
,
13812 unsigned crm
, unsigned op2
)
13814 if (crn
== 0 && op1
== 3 && crm
== 0 && op2
== 7)
13815 /* DCZID_EL0 - the Data Cache Zero ID register.
13816 We do not support DC ZVA at the moment, so
13817 we return a value with the disable bit set.
13818 We implement support for the DCZID register since
13819 it is used by the C library's memset function. */
13820 return ((uint64_t) 1) << 4;
13822 if (crn
== 0 && op1
== 3 && crm
== 0 && op2
== 1)
13823 /* Cache Type Register. */
13824 return 0x80008000UL
;
13826 if (crn
== 13 && op1
== 3 && crm
== 0 && op2
== 2)
13827 /* TPIDR_EL0 - thread pointer id. */
13828 return aarch64_get_thread_id (cpu
);
13830 if (op1
== 3 && crm
== 4 && op2
== 0)
13831 return aarch64_get_FPCR (cpu
);
13833 if (op1
== 3 && crm
== 4 && op2
== 1)
13834 return aarch64_get_FPSR (cpu
);
13836 else if (op1
== 3 && crm
== 2 && op2
== 0)
13837 return aarch64_get_CPSR (cpu
);
13843 system_set (sim_cpu
*cpu
, unsigned op0
, unsigned op1
, unsigned crn
,
13844 unsigned crm
, unsigned op2
, uint64_t val
)
13846 if (op1
== 3 && crm
== 4 && op2
== 0)
13847 aarch64_set_FPCR (cpu
, val
);
13849 else if (op1
== 3 && crm
== 4 && op2
== 1)
13850 aarch64_set_FPSR (cpu
, val
);
13852 else if (op1
== 3 && crm
== 2 && op2
== 0)
13853 aarch64_set_CPSR (cpu
, val
);
13860 do_mrs (sim_cpu
*cpu
)
13862 /* instr[31:20] = 1101 0101 0001 1
13869 unsigned sys_op0
= INSTR (19, 19) + 2;
13870 unsigned sys_op1
= INSTR (18, 16);
13871 unsigned sys_crn
= INSTR (15, 12);
13872 unsigned sys_crm
= INSTR (11, 8);
13873 unsigned sys_op2
= INSTR (7, 5);
13874 unsigned rt
= INSTR (4, 0);
13876 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
13877 aarch64_set_reg_u64 (cpu
, rt
, NO_SP
,
13878 system_get (cpu
, sys_op0
, sys_op1
, sys_crn
, sys_crm
, sys_op2
));
13882 do_MSR_immediate (sim_cpu
*cpu
)
13884 /* instr[31:19] = 1101 0101 0000 0
13886 instr[15,12] = 0100
13889 instr[4,0] = 1 1111 */
13891 unsigned op1
= INSTR (18, 16);
13892 /*unsigned crm = INSTR (11, 8);*/
13893 unsigned op2
= INSTR (7, 5);
13895 NYI_assert (31, 19, 0x1AA0);
13896 NYI_assert (15, 12, 0x4);
13897 NYI_assert (4, 0, 0x1F);
13902 HALT_NYI
; /* set SPSel. */
13909 HALT_NYI
; /* set DAIFset. */
13911 HALT_NYI
; /* set DAIFclr. */
13920 do_MSR_reg (sim_cpu
*cpu
)
13922 /* instr[31:20] = 1101 0101 0001
13930 unsigned sys_op0
= INSTR (19, 19) + 2;
13931 unsigned sys_op1
= INSTR (18, 16);
13932 unsigned sys_crn
= INSTR (15, 12);
13933 unsigned sys_crm
= INSTR (11, 8);
13934 unsigned sys_op2
= INSTR (7, 5);
13935 unsigned rt
= INSTR (4, 0);
13937 NYI_assert (31, 20, 0xD51);
13939 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
13940 system_set (cpu
, sys_op0
, sys_op1
, sys_crn
, sys_crm
, sys_op2
,
13941 aarch64_get_reg_u64 (cpu
, rt
, NO_SP
));
13945 do_SYS (sim_cpu
*cpu
)
13947 /* instr[31,19] = 1101 0101 0000 1
13953 NYI_assert (31, 19, 0x1AA1);
13955 /* FIXME: For now we just silently accept system ops. */
13959 dexSystem (sim_cpu
*cpu
)
13961 /* instr[31:22] = 1101 01010 0
13968 instr[4,0] = uimm5 */
13970 /* We are interested in HINT, DSB, DMB and ISB
13972 Hint #0 encodes NOOP (this is the only hint we care about)
13973 L == 0, op0 == 0, op1 = 011, CRn = 0010, Rt = 11111,
13974 CRm op2 != 0000 000 OR CRm op2 == 0000 000 || CRm op > 0000 101
13976 DSB, DMB, ISB are data store barrier, data memory barrier and
13977 instruction store barrier, respectively, where
13979 L == 0, op0 == 0, op1 = 011, CRn = 0011, Rt = 11111,
13980 op2 : DSB ==> 100, DMB ==> 101, ISB ==> 110
13981 CRm<3:2> ==> domain, CRm<1:0> ==> types,
13982 domain : 00 ==> OuterShareable, 01 ==> Nonshareable,
13983 10 ==> InerShareable, 11 ==> FullSystem
13984 types : 01 ==> Reads, 10 ==> Writes,
13985 11 ==> All, 00 ==> All (domain == FullSystem). */
13987 unsigned rt
= INSTR (4, 0);
13989 NYI_assert (31, 22, 0x354);
13991 switch (INSTR (21, 12))
13996 /* NOP has CRm != 0000 OR. */
13997 /* (CRm == 0000 AND (op2 == 000 OR op2 > 101)). */
13998 uint32_t crm
= INSTR (11, 8);
13999 uint32_t op2
= INSTR (7, 5);
14001 if (crm
!= 0 || (op2
== 0 || op2
> 5))
14003 /* Actually call nop method so we can reimplement it later. */
14012 uint32_t op2
= INSTR (7, 5);
14017 case 4: dsb (cpu
); return;
14018 case 5: dmb (cpu
); return;
14019 case 6: isb (cpu
); return;
14020 default: HALT_UNALLOC
;
14031 do_SYS (cpu
); /* DC is an alias of SYS. */
14035 if (INSTR (21, 20) == 0x1)
14037 else if (INSTR (21, 19) == 0 && INSTR (15, 12) == 0x4)
14038 do_MSR_immediate (cpu
);
14046 dexBr (sim_cpu
*cpu
)
14048 /* uint32_t group = dispatchGroup (aarch64_get_instr (cpu));
14049 assert group == GROUP_BREXSYS_1010 || group == GROUP_BREXSYS_1011
14050 bits [31,29] of a BrExSys are the secondary dispatch vector. */
14051 uint32_t group2
= dispatchBrExSys (aarch64_get_instr (cpu
));
14056 return dexBranchImmediate (cpu
);
14058 case BR_IMMCMP_001
:
14059 /* Compare has bit 25 clear while test has it set. */
14060 if (!INSTR (25, 25))
14061 dexCompareBranchImmediate (cpu
);
14063 dexTestBranchImmediate (cpu
);
14066 case BR_IMMCOND_010
:
14067 /* This is a conditional branch if bit 25 is clear otherwise
14069 if (!INSTR (25, 25))
14070 dexCondBranchImmediate (cpu
);
14075 case BR_UNALLOC_011
:
14079 dexBranchImmediate (cpu
);
14082 case BR_IMMCMP_101
:
14083 /* Compare has bit 25 clear while test has it set. */
14084 if (!INSTR (25, 25))
14085 dexCompareBranchImmediate (cpu
);
14087 dexTestBranchImmediate (cpu
);
14091 /* Unconditional branch reg has bit 25 set. */
14092 if (INSTR (25, 25))
14093 dexBranchRegister (cpu
);
14095 /* This includes both Excpn Gen, System and unalloc operations.
14096 We need to decode the Excpn Gen operation BRK so we can plant
14097 debugger entry points.
14098 Excpn Gen operations have instr [24] = 0.
14099 we need to decode at least one of the System operations NOP
14100 which is an alias for HINT #0.
14101 System operations have instr [24,22] = 100. */
14102 else if (INSTR (24, 24) == 0)
14105 else if (INSTR (24, 22) == 4)
14113 case BR_UNALLOC_111
:
14117 /* Should never reach here. */
14123 aarch64_decode_and_execute (sim_cpu
*cpu
, uint64_t pc
)
14125 /* We need to check if gdb wants an in here. */
14126 /* checkBreak (cpu);. */
14128 uint64_t group
= dispatchGroup (aarch64_get_instr (cpu
));
14132 case GROUP_PSEUDO_0000
: dexPseudo (cpu
); break;
14133 case GROUP_LDST_0100
: dexLdSt (cpu
); break;
14134 case GROUP_DPREG_0101
: dexDPReg (cpu
); break;
14135 case GROUP_LDST_0110
: dexLdSt (cpu
); break;
14136 case GROUP_ADVSIMD_0111
: dexAdvSIMD0 (cpu
); break;
14137 case GROUP_DPIMM_1000
: dexDPImm (cpu
); break;
14138 case GROUP_DPIMM_1001
: dexDPImm (cpu
); break;
14139 case GROUP_BREXSYS_1010
: dexBr (cpu
); break;
14140 case GROUP_BREXSYS_1011
: dexBr (cpu
); break;
14141 case GROUP_LDST_1100
: dexLdSt (cpu
); break;
14142 case GROUP_DPREG_1101
: dexDPReg (cpu
); break;
14143 case GROUP_LDST_1110
: dexLdSt (cpu
); break;
14144 case GROUP_ADVSIMD_1111
: dexAdvSIMD1 (cpu
); break;
14146 case GROUP_UNALLOC_0001
:
14147 case GROUP_UNALLOC_0010
:
14148 case GROUP_UNALLOC_0011
:
14152 /* Should never reach here. */
14158 aarch64_step (sim_cpu
*cpu
)
14160 uint64_t pc
= aarch64_get_PC (cpu
);
14162 if (pc
== TOP_LEVEL_RETURN_PC
)
14165 aarch64_set_next_PC (cpu
, pc
+ 4);
14167 /* Code is always little-endian. */
14168 sim_core_read_buffer (CPU_STATE (cpu
), cpu
, read_map
,
14169 & aarch64_get_instr (cpu
), pc
, 4);
14170 aarch64_get_instr (cpu
) = endian_le2h_4 (aarch64_get_instr (cpu
));
14172 TRACE_INSN (cpu
, " pc = %" PRIx64
" instr = %08x", pc
,
14173 aarch64_get_instr (cpu
));
14174 TRACE_DISASM (cpu
, pc
);
14176 aarch64_decode_and_execute (cpu
, pc
);
14182 aarch64_run (SIM_DESC sd
)
14184 sim_cpu
*cpu
= STATE_CPU (sd
, 0);
14186 while (aarch64_step (cpu
))
14188 aarch64_update_PC (cpu
);
14190 if (sim_events_tick (sd
))
14191 sim_events_process (sd
);
14194 sim_engine_halt (sd
, cpu
, NULL
, aarch64_get_PC (cpu
),
14195 sim_exited
, aarch64_get_reg_s32 (cpu
, R0
, NO_SP
));
14199 aarch64_init (sim_cpu
*cpu
, uint64_t pc
)
14201 uint64_t sp
= aarch64_get_stack_start (cpu
);
14203 /* Install SP, FP and PC and set LR to -20
14204 so we can detect a top-level return. */
14205 aarch64_set_reg_u64 (cpu
, SP
, SP_OK
, sp
);
14206 aarch64_set_reg_u64 (cpu
, FP
, SP_OK
, sp
);
14207 aarch64_set_reg_u64 (cpu
, LR
, SP_OK
, TOP_LEVEL_RETURN_PC
);
14208 aarch64_set_next_PC (cpu
, pc
);
14209 aarch64_update_PC (cpu
);
14210 aarch64_init_LIT_table ();