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);
3437 int full
= INSTR (30, 30);
3439 NYI_assert (29, 24, 0x0E);
3440 NYI_assert (21, 10, 0xC6E);
3442 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
3443 switch (INSTR (23, 22))
3446 for (i
= 0; i
< (full
? 16 : 8); i
++)
3447 val
+= aarch64_get_vec_u8 (cpu
, vm
, i
);
3448 aarch64_set_vec_u64 (cpu
, rd
, 0, val
);
3452 for (i
= 0; i
< (full
? 8 : 4); i
++)
3453 val
+= aarch64_get_vec_u16 (cpu
, vm
, i
);
3454 aarch64_set_vec_u64 (cpu
, rd
, 0, val
);
3460 for (i
= 0; i
< 4; i
++)
3461 val
+= aarch64_get_vec_u32 (cpu
, vm
, i
);
3462 aarch64_set_vec_u64 (cpu
, rd
, 0, val
);
3471 do_vec_ins_2 (sim_cpu
*cpu
)
3473 /* instr[31,21] = 01001110000
3474 instr[20,18] = size & element selector
3476 instr[13] = direction: to vec(0), from vec (1)
3482 unsigned vm
= INSTR (9, 5);
3483 unsigned vd
= INSTR (4, 0);
3485 NYI_assert (31, 21, 0x270);
3486 NYI_assert (17, 14, 0);
3487 NYI_assert (12, 10, 7);
3489 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
3490 if (INSTR (13, 13) == 1)
3492 if (INSTR (18, 18) == 1)
3495 elem
= INSTR (20, 19);
3496 aarch64_set_reg_u64 (cpu
, vd
, NO_SP
,
3497 aarch64_get_vec_u32 (cpu
, vm
, elem
));
3502 if (INSTR (19, 19) != 1)
3505 elem
= INSTR (20, 20);
3506 aarch64_set_reg_u64 (cpu
, vd
, NO_SP
,
3507 aarch64_get_vec_u64 (cpu
, vm
, elem
));
3512 if (INSTR (18, 18) == 1)
3515 elem
= INSTR (20, 19);
3516 aarch64_set_vec_u32 (cpu
, vd
, elem
,
3517 aarch64_get_reg_u32 (cpu
, vm
, NO_SP
));
3522 if (INSTR (19, 19) != 1)
3525 elem
= INSTR (20, 20);
3526 aarch64_set_vec_u64 (cpu
, vd
, elem
,
3527 aarch64_get_reg_u64 (cpu
, vm
, NO_SP
));
3532 #define DO_VEC_WIDENING_MUL(N, DST_TYPE, READ_TYPE, WRITE_TYPE) \
3535 DST_TYPE a[N], b[N]; \
3537 for (i = 0; i < (N); i++) \
3539 a[i] = aarch64_get_vec_##READ_TYPE (cpu, vn, i + bias); \
3540 b[i] = aarch64_get_vec_##READ_TYPE (cpu, vm, i + bias); \
3542 for (i = 0; i < (N); i++) \
3543 aarch64_set_vec_##WRITE_TYPE (cpu, vd, i, a[i] * b[i]); \
3548 do_vec_mull (sim_cpu
*cpu
)
3551 instr[30] = lower(0)/upper(1) selector
3552 instr[29] = signed(0)/unsigned(1)
3553 instr[28,24] = 0 1110
3554 instr[23,22] = size: 8-bit (00), 16-bit (01), 32-bit (10)
3557 instr[15,10] = 11 0000
3561 int unsign
= INSTR (29, 29);
3562 int bias
= INSTR (30, 30);
3563 unsigned vm
= INSTR (20, 16);
3564 unsigned vn
= INSTR ( 9, 5);
3565 unsigned vd
= INSTR ( 4, 0);
3568 NYI_assert (28, 24, 0x0E);
3569 NYI_assert (15, 10, 0x30);
3571 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
3572 /* NB: Read source values before writing results, in case
3573 the source and destination vectors are the same. */
3574 switch (INSTR (23, 22))
3580 DO_VEC_WIDENING_MUL (8, uint16_t, u8
, u16
);
3582 DO_VEC_WIDENING_MUL (8, int16_t, s8
, s16
);
3589 DO_VEC_WIDENING_MUL (4, uint32_t, u16
, u32
);
3591 DO_VEC_WIDENING_MUL (4, int32_t, s16
, s32
);
3598 DO_VEC_WIDENING_MUL (2, uint64_t, u32
, u64
);
3600 DO_VEC_WIDENING_MUL (2, int64_t, s32
, s64
);
3609 do_vec_fadd (sim_cpu
*cpu
)
3612 instr[30] = half(0)/full(1)
3613 instr[29,24] = 001110
3614 instr[23] = FADD(0)/FSUB(1)
3615 instr[22] = float (0)/double(1)
3618 instr[15,10] = 110101
3622 unsigned vm
= INSTR (20, 16);
3623 unsigned vn
= INSTR (9, 5);
3624 unsigned vd
= INSTR (4, 0);
3626 int full
= INSTR (30, 30);
3628 NYI_assert (29, 24, 0x0E);
3629 NYI_assert (21, 21, 1);
3630 NYI_assert (15, 10, 0x35);
3632 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
3640 for (i
= 0; i
< 2; i
++)
3641 aarch64_set_vec_double (cpu
, vd
, i
,
3642 aarch64_get_vec_double (cpu
, vn
, i
)
3643 - aarch64_get_vec_double (cpu
, vm
, i
));
3647 for (i
= 0; i
< (full
? 4 : 2); i
++)
3648 aarch64_set_vec_float (cpu
, vd
, i
,
3649 aarch64_get_vec_float (cpu
, vn
, i
)
3650 - aarch64_get_vec_float (cpu
, vm
, i
));
3660 for (i
= 0; i
< 2; i
++)
3661 aarch64_set_vec_double (cpu
, vd
, i
,
3662 aarch64_get_vec_double (cpu
, vm
, i
)
3663 + aarch64_get_vec_double (cpu
, vn
, i
));
3667 for (i
= 0; i
< (full
? 4 : 2); i
++)
3668 aarch64_set_vec_float (cpu
, vd
, i
,
3669 aarch64_get_vec_float (cpu
, vm
, i
)
3670 + aarch64_get_vec_float (cpu
, vn
, i
));
3676 do_vec_add (sim_cpu
*cpu
)
3679 instr[30] = full/half selector
3680 instr[29,24] = 001110
3681 instr[23,22] = size: 00=> 8-bit, 01=> 16-bit, 10=> 32-bit, 11=> 64-bit
3684 instr[15,10] = 100001
3688 unsigned vm
= INSTR (20, 16);
3689 unsigned vn
= INSTR (9, 5);
3690 unsigned vd
= INSTR (4, 0);
3692 int full
= INSTR (30, 30);
3694 NYI_assert (29, 24, 0x0E);
3695 NYI_assert (21, 21, 1);
3696 NYI_assert (15, 10, 0x21);
3698 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
3699 switch (INSTR (23, 22))
3702 for (i
= 0; i
< (full
? 16 : 8); i
++)
3703 aarch64_set_vec_u8 (cpu
, vd
, i
, aarch64_get_vec_u8 (cpu
, vn
, i
)
3704 + aarch64_get_vec_u8 (cpu
, vm
, i
));
3708 for (i
= 0; i
< (full
? 8 : 4); i
++)
3709 aarch64_set_vec_u16 (cpu
, vd
, i
, aarch64_get_vec_u16 (cpu
, vn
, i
)
3710 + aarch64_get_vec_u16 (cpu
, vm
, i
));
3714 for (i
= 0; i
< (full
? 4 : 2); i
++)
3715 aarch64_set_vec_u32 (cpu
, vd
, i
, aarch64_get_vec_u32 (cpu
, vn
, i
)
3716 + aarch64_get_vec_u32 (cpu
, vm
, i
));
3722 aarch64_set_vec_u64 (cpu
, vd
, 0, aarch64_get_vec_u64 (cpu
, vn
, 0)
3723 + aarch64_get_vec_u64 (cpu
, vm
, 0));
3724 aarch64_set_vec_u64 (cpu
, vd
, 1,
3725 aarch64_get_vec_u64 (cpu
, vn
, 1)
3726 + aarch64_get_vec_u64 (cpu
, vm
, 1));
3732 do_vec_mul (sim_cpu
*cpu
)
3735 instr[30] = full/half selector
3736 instr[29,24] = 00 1110
3737 instr[23,22] = size: 00=> 8-bit, 01=> 16-bit, 10=> 32-bit
3740 instr[15,10] = 10 0111
3744 unsigned vm
= INSTR (20, 16);
3745 unsigned vn
= INSTR (9, 5);
3746 unsigned vd
= INSTR (4, 0);
3748 int full
= INSTR (30, 30);
3751 NYI_assert (29, 24, 0x0E);
3752 NYI_assert (21, 21, 1);
3753 NYI_assert (15, 10, 0x27);
3755 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
3756 switch (INSTR (23, 22))
3759 DO_VEC_WIDENING_MUL (full
? 16 : 8, uint8_t, u8
, u8
);
3763 DO_VEC_WIDENING_MUL (full
? 8 : 4, uint16_t, u16
, u16
);
3767 DO_VEC_WIDENING_MUL (full
? 4 : 2, uint32_t, u32
, u32
);
3776 do_vec_MLA (sim_cpu
*cpu
)
3779 instr[30] = full/half selector
3780 instr[29,24] = 00 1110
3781 instr[23,22] = size: 00=> 8-bit, 01=> 16-bit, 10=> 32-bit
3784 instr[15,10] = 1001 01
3788 unsigned vm
= INSTR (20, 16);
3789 unsigned vn
= INSTR (9, 5);
3790 unsigned vd
= INSTR (4, 0);
3792 int full
= INSTR (30, 30);
3794 NYI_assert (29, 24, 0x0E);
3795 NYI_assert (21, 21, 1);
3796 NYI_assert (15, 10, 0x25);
3798 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
3799 switch (INSTR (23, 22))
3803 uint16_t a
[16], b
[16];
3805 for (i
= 0; i
< (full
? 16 : 8); i
++)
3807 a
[i
] = aarch64_get_vec_u8 (cpu
, vn
, i
);
3808 b
[i
] = aarch64_get_vec_u8 (cpu
, vm
, i
);
3811 for (i
= 0; i
< (full
? 16 : 8); i
++)
3813 uint16_t v
= aarch64_get_vec_u8 (cpu
, vd
, i
);
3815 aarch64_set_vec_u16 (cpu
, vd
, i
, v
+ (a
[i
] * b
[i
]));
3822 uint32_t a
[8], b
[8];
3824 for (i
= 0; i
< (full
? 8 : 4); i
++)
3826 a
[i
] = aarch64_get_vec_u16 (cpu
, vn
, i
);
3827 b
[i
] = aarch64_get_vec_u16 (cpu
, vm
, i
);
3830 for (i
= 0; i
< (full
? 8 : 4); i
++)
3832 uint32_t v
= aarch64_get_vec_u16 (cpu
, vd
, i
);
3834 aarch64_set_vec_u32 (cpu
, vd
, i
, v
+ (a
[i
] * b
[i
]));
3841 uint64_t a
[4], b
[4];
3843 for (i
= 0; i
< (full
? 4 : 2); i
++)
3845 a
[i
] = aarch64_get_vec_u32 (cpu
, vn
, i
);
3846 b
[i
] = aarch64_get_vec_u32 (cpu
, vm
, i
);
3849 for (i
= 0; i
< (full
? 4 : 2); i
++)
3851 uint64_t v
= aarch64_get_vec_u32 (cpu
, vd
, i
);
3853 aarch64_set_vec_u64 (cpu
, vd
, i
, v
+ (a
[i
] * b
[i
]));
3864 fmaxnm (float a
, float b
)
3869 return a
> b
? a
: b
;
3872 else if (! isnan (b
))
3878 fminnm (float a
, float b
)
3883 return a
< b
? a
: b
;
3886 else if (! isnan (b
))
3892 dmaxnm (double a
, double b
)
3897 return a
> b
? a
: b
;
3900 else if (! isnan (b
))
3906 dminnm (double a
, double b
)
3911 return a
< b
? a
: b
;
3914 else if (! isnan (b
))
3920 do_vec_FminmaxNMP (sim_cpu
*cpu
)
3923 instr [30] = half (0)/full (1)
3924 instr [29,24] = 10 1110
3925 instr [23] = max(0)/min(1)
3926 instr [22] = float (0)/double (1)
3929 instr [15,10] = 1100 01
3931 instr [4.0] = Vd. */
3933 unsigned vm
= INSTR (20, 16);
3934 unsigned vn
= INSTR (9, 5);
3935 unsigned vd
= INSTR (4, 0);
3936 int full
= INSTR (30, 30);
3938 NYI_assert (29, 24, 0x2E);
3939 NYI_assert (21, 21, 1);
3940 NYI_assert (15, 10, 0x31);
3942 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
3945 double (* fn
)(double, double) = INSTR (23, 23)
3950 aarch64_set_vec_double (cpu
, vd
, 0,
3951 fn (aarch64_get_vec_double (cpu
, vn
, 0),
3952 aarch64_get_vec_double (cpu
, vn
, 1)));
3953 aarch64_set_vec_double (cpu
, vd
, 0,
3954 fn (aarch64_get_vec_double (cpu
, vm
, 0),
3955 aarch64_get_vec_double (cpu
, vm
, 1)));
3959 float (* fn
)(float, float) = INSTR (23, 23)
3962 aarch64_set_vec_float (cpu
, vd
, 0,
3963 fn (aarch64_get_vec_float (cpu
, vn
, 0),
3964 aarch64_get_vec_float (cpu
, vn
, 1)));
3966 aarch64_set_vec_float (cpu
, vd
, 1,
3967 fn (aarch64_get_vec_float (cpu
, vn
, 2),
3968 aarch64_get_vec_float (cpu
, vn
, 3)));
3970 aarch64_set_vec_float (cpu
, vd
, (full
? 2 : 1),
3971 fn (aarch64_get_vec_float (cpu
, vm
, 0),
3972 aarch64_get_vec_float (cpu
, vm
, 1)));
3974 aarch64_set_vec_float (cpu
, vd
, 3,
3975 fn (aarch64_get_vec_float (cpu
, vm
, 2),
3976 aarch64_get_vec_float (cpu
, vm
, 3)));
3981 do_vec_AND (sim_cpu
*cpu
)
3984 instr[30] = half (0)/full (1)
3985 instr[29,21] = 001110001
3987 instr[15,10] = 000111
3991 unsigned vm
= INSTR (20, 16);
3992 unsigned vn
= INSTR (9, 5);
3993 unsigned vd
= INSTR (4, 0);
3995 int full
= INSTR (30, 30);
3997 NYI_assert (29, 21, 0x071);
3998 NYI_assert (15, 10, 0x07);
4000 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
4001 for (i
= 0; i
< (full
? 4 : 2); i
++)
4002 aarch64_set_vec_u32 (cpu
, vd
, i
,
4003 aarch64_get_vec_u32 (cpu
, vn
, i
)
4004 & aarch64_get_vec_u32 (cpu
, vm
, i
));
4008 do_vec_BSL (sim_cpu
*cpu
)
4011 instr[30] = half (0)/full (1)
4012 instr[29,21] = 101110011
4014 instr[15,10] = 000111
4018 unsigned vm
= INSTR (20, 16);
4019 unsigned vn
= INSTR (9, 5);
4020 unsigned vd
= INSTR (4, 0);
4022 int full
= INSTR (30, 30);
4024 NYI_assert (29, 21, 0x173);
4025 NYI_assert (15, 10, 0x07);
4027 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
4028 for (i
= 0; i
< (full
? 16 : 8); i
++)
4029 aarch64_set_vec_u8 (cpu
, vd
, i
,
4030 ( aarch64_get_vec_u8 (cpu
, vd
, i
)
4031 & aarch64_get_vec_u8 (cpu
, vn
, i
))
4032 | ((~ aarch64_get_vec_u8 (cpu
, vd
, i
))
4033 & aarch64_get_vec_u8 (cpu
, vm
, i
)));
4037 do_vec_EOR (sim_cpu
*cpu
)
4040 instr[30] = half (0)/full (1)
4041 instr[29,21] = 10 1110 001
4043 instr[15,10] = 000111
4047 unsigned vm
= INSTR (20, 16);
4048 unsigned vn
= INSTR (9, 5);
4049 unsigned vd
= INSTR (4, 0);
4051 int full
= INSTR (30, 30);
4053 NYI_assert (29, 21, 0x171);
4054 NYI_assert (15, 10, 0x07);
4056 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
4057 for (i
= 0; i
< (full
? 4 : 2); i
++)
4058 aarch64_set_vec_u32 (cpu
, vd
, i
,
4059 aarch64_get_vec_u32 (cpu
, vn
, i
)
4060 ^ aarch64_get_vec_u32 (cpu
, vm
, i
));
4064 do_vec_bit (sim_cpu
*cpu
)
4067 instr[30] = half (0)/full (1)
4068 instr[29,23] = 10 1110 1
4069 instr[22] = BIT (0) / BIF (1)
4072 instr[15,10] = 0001 11
4076 unsigned vm
= INSTR (20, 16);
4077 unsigned vn
= INSTR (9, 5);
4078 unsigned vd
= INSTR (4, 0);
4079 unsigned full
= INSTR (30, 30);
4080 unsigned test_false
= INSTR (22, 22);
4083 NYI_assert (29, 23, 0x5D);
4084 NYI_assert (21, 21, 1);
4085 NYI_assert (15, 10, 0x07);
4087 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
4090 for (i
= 0; i
< (full
? 16 : 8); i
++)
4091 if (aarch64_get_vec_u32 (cpu
, vn
, i
) == 0)
4092 aarch64_set_vec_u32 (cpu
, vd
, i
, aarch64_get_vec_u32 (cpu
, vm
, i
));
4096 for (i
= 0; i
< (full
? 16 : 8); i
++)
4097 if (aarch64_get_vec_u32 (cpu
, vn
, i
) != 0)
4098 aarch64_set_vec_u32 (cpu
, vd
, i
, aarch64_get_vec_u32 (cpu
, vm
, i
));
4103 do_vec_ORN (sim_cpu
*cpu
)
4106 instr[30] = half (0)/full (1)
4107 instr[29,21] = 00 1110 111
4109 instr[15,10] = 00 0111
4113 unsigned vm
= INSTR (20, 16);
4114 unsigned vn
= INSTR (9, 5);
4115 unsigned vd
= INSTR (4, 0);
4117 int full
= INSTR (30, 30);
4119 NYI_assert (29, 21, 0x077);
4120 NYI_assert (15, 10, 0x07);
4122 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
4123 for (i
= 0; i
< (full
? 16 : 8); i
++)
4124 aarch64_set_vec_u8 (cpu
, vd
, i
,
4125 aarch64_get_vec_u8 (cpu
, vn
, i
)
4126 | ~ aarch64_get_vec_u8 (cpu
, vm
, i
));
4130 do_vec_ORR (sim_cpu
*cpu
)
4133 instr[30] = half (0)/full (1)
4134 instr[29,21] = 00 1110 101
4136 instr[15,10] = 0001 11
4140 unsigned vm
= INSTR (20, 16);
4141 unsigned vn
= INSTR (9, 5);
4142 unsigned vd
= INSTR (4, 0);
4144 int full
= INSTR (30, 30);
4146 NYI_assert (29, 21, 0x075);
4147 NYI_assert (15, 10, 0x07);
4149 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
4150 for (i
= 0; i
< (full
? 16 : 8); i
++)
4151 aarch64_set_vec_u8 (cpu
, vd
, i
,
4152 aarch64_get_vec_u8 (cpu
, vn
, i
)
4153 | aarch64_get_vec_u8 (cpu
, vm
, i
));
4157 do_vec_BIC (sim_cpu
*cpu
)
4160 instr[30] = half (0)/full (1)
4161 instr[29,21] = 00 1110 011
4163 instr[15,10] = 00 0111
4167 unsigned vm
= INSTR (20, 16);
4168 unsigned vn
= INSTR (9, 5);
4169 unsigned vd
= INSTR (4, 0);
4171 int full
= INSTR (30, 30);
4173 NYI_assert (29, 21, 0x073);
4174 NYI_assert (15, 10, 0x07);
4176 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
4177 for (i
= 0; i
< (full
? 16 : 8); i
++)
4178 aarch64_set_vec_u8 (cpu
, vd
, i
,
4179 aarch64_get_vec_u8 (cpu
, vn
, i
)
4180 & ~ aarch64_get_vec_u8 (cpu
, vm
, i
));
4184 do_vec_XTN (sim_cpu
*cpu
)
4187 instr[30] = first part (0)/ second part (1)
4188 instr[29,24] = 00 1110
4189 instr[23,22] = size: byte(00), half(01), word (10)
4190 instr[21,10] = 1000 0100 1010
4194 unsigned vs
= INSTR (9, 5);
4195 unsigned vd
= INSTR (4, 0);
4196 unsigned bias
= INSTR (30, 30);
4199 NYI_assert (29, 24, 0x0E);
4200 NYI_assert (21, 10, 0x84A);
4202 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
4203 switch (INSTR (23, 22))
4206 for (i
= 0; i
< 8; i
++)
4207 aarch64_set_vec_u8 (cpu
, vd
, i
+ (bias
* 8),
4208 aarch64_get_vec_u16 (cpu
, vs
, i
));
4212 for (i
= 0; i
< 4; i
++)
4213 aarch64_set_vec_u16 (cpu
, vd
, i
+ (bias
* 4),
4214 aarch64_get_vec_u32 (cpu
, vs
, i
));
4218 for (i
= 0; i
< 2; i
++)
4219 aarch64_set_vec_u32 (cpu
, vd
, i
+ (bias
* 2),
4220 aarch64_get_vec_u64 (cpu
, vs
, i
));
4226 do_vec_maxv (sim_cpu
*cpu
)
4229 instr[30] = half(0)/full(1)
4230 instr[29] = signed (0)/unsigned(1)
4231 instr[28,24] = 0 1110
4232 instr[23,22] = size: byte(00), half(01), word (10)
4234 instr[20,17] = 1 000
4235 instr[16] = max(0)/min(1)
4236 instr[15,10] = 1010 10
4237 instr[9,5] = V source
4238 instr[4.0] = R dest. */
4240 unsigned vs
= INSTR (9, 5);
4241 unsigned rd
= INSTR (4, 0);
4242 unsigned full
= INSTR (30, 30);
4245 NYI_assert (28, 24, 0x0E);
4246 NYI_assert (21, 21, 1);
4247 NYI_assert (20, 17, 8);
4248 NYI_assert (15, 10, 0x2A);
4250 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
4251 switch ((INSTR (29, 29) << 1) | INSTR (16, 16))
4253 case 0: /* SMAXV. */
4256 switch (INSTR (23, 22))
4259 smax
= aarch64_get_vec_s8 (cpu
, vs
, 0);
4260 for (i
= 1; i
< (full
? 16 : 8); i
++)
4261 smax
= max (smax
, aarch64_get_vec_s8 (cpu
, vs
, i
));
4264 smax
= aarch64_get_vec_s16 (cpu
, vs
, 0);
4265 for (i
= 1; i
< (full
? 8 : 4); i
++)
4266 smax
= max (smax
, aarch64_get_vec_s16 (cpu
, vs
, i
));
4269 smax
= aarch64_get_vec_s32 (cpu
, vs
, 0);
4270 for (i
= 1; i
< (full
? 4 : 2); i
++)
4271 smax
= max (smax
, aarch64_get_vec_s32 (cpu
, vs
, i
));
4276 aarch64_set_reg_s64 (cpu
, rd
, NO_SP
, smax
);
4280 case 1: /* SMINV. */
4283 switch (INSTR (23, 22))
4286 smin
= aarch64_get_vec_s8 (cpu
, vs
, 0);
4287 for (i
= 1; i
< (full
? 16 : 8); i
++)
4288 smin
= min (smin
, aarch64_get_vec_s8 (cpu
, vs
, i
));
4291 smin
= aarch64_get_vec_s16 (cpu
, vs
, 0);
4292 for (i
= 1; i
< (full
? 8 : 4); i
++)
4293 smin
= min (smin
, aarch64_get_vec_s16 (cpu
, vs
, i
));
4296 smin
= aarch64_get_vec_s32 (cpu
, vs
, 0);
4297 for (i
= 1; i
< (full
? 4 : 2); i
++)
4298 smin
= min (smin
, aarch64_get_vec_s32 (cpu
, vs
, i
));
4304 aarch64_set_reg_s64 (cpu
, rd
, NO_SP
, smin
);
4308 case 2: /* UMAXV. */
4311 switch (INSTR (23, 22))
4314 umax
= aarch64_get_vec_u8 (cpu
, vs
, 0);
4315 for (i
= 1; i
< (full
? 16 : 8); i
++)
4316 umax
= max (umax
, aarch64_get_vec_u8 (cpu
, vs
, i
));
4319 umax
= aarch64_get_vec_u16 (cpu
, vs
, 0);
4320 for (i
= 1; i
< (full
? 8 : 4); i
++)
4321 umax
= max (umax
, aarch64_get_vec_u16 (cpu
, vs
, i
));
4324 umax
= aarch64_get_vec_u32 (cpu
, vs
, 0);
4325 for (i
= 1; i
< (full
? 4 : 2); i
++)
4326 umax
= max (umax
, aarch64_get_vec_u32 (cpu
, vs
, i
));
4332 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, umax
);
4336 case 3: /* UMINV. */
4339 switch (INSTR (23, 22))
4342 umin
= aarch64_get_vec_u8 (cpu
, vs
, 0);
4343 for (i
= 1; i
< (full
? 16 : 8); i
++)
4344 umin
= min (umin
, aarch64_get_vec_u8 (cpu
, vs
, i
));
4347 umin
= aarch64_get_vec_u16 (cpu
, vs
, 0);
4348 for (i
= 1; i
< (full
? 8 : 4); i
++)
4349 umin
= min (umin
, aarch64_get_vec_u16 (cpu
, vs
, i
));
4352 umin
= aarch64_get_vec_u32 (cpu
, vs
, 0);
4353 for (i
= 1; i
< (full
? 4 : 2); i
++)
4354 umin
= min (umin
, aarch64_get_vec_u32 (cpu
, vs
, i
));
4360 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, umin
);
4367 do_vec_fminmaxV (sim_cpu
*cpu
)
4369 /* instr[31,24] = 0110 1110
4370 instr[23] = max(0)/min(1)
4371 instr[22,14] = 011 0000 11
4372 instr[13,12] = nm(00)/normal(11)
4374 instr[9,5] = V source
4375 instr[4.0] = R dest. */
4377 unsigned vs
= INSTR (9, 5);
4378 unsigned rd
= INSTR (4, 0);
4380 float res
= aarch64_get_vec_float (cpu
, vs
, 0);
4382 NYI_assert (31, 24, 0x6E);
4383 NYI_assert (22, 14, 0x0C3);
4384 NYI_assert (11, 10, 2);
4386 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
4389 switch (INSTR (13, 12))
4391 case 0: /* FMNINNMV. */
4392 for (i
= 1; i
< 4; i
++)
4393 res
= fminnm (res
, aarch64_get_vec_float (cpu
, vs
, i
));
4396 case 3: /* FMINV. */
4397 for (i
= 1; i
< 4; i
++)
4398 res
= min (res
, aarch64_get_vec_float (cpu
, vs
, i
));
4407 switch (INSTR (13, 12))
4409 case 0: /* FMNAXNMV. */
4410 for (i
= 1; i
< 4; i
++)
4411 res
= fmaxnm (res
, aarch64_get_vec_float (cpu
, vs
, i
));
4414 case 3: /* FMAXV. */
4415 for (i
= 1; i
< 4; i
++)
4416 res
= max (res
, aarch64_get_vec_float (cpu
, vs
, i
));
4424 aarch64_set_FP_float (cpu
, rd
, res
);
4428 do_vec_Fminmax (sim_cpu
*cpu
)
4431 instr[30] = half(0)/full(1)
4432 instr[29,24] = 00 1110
4433 instr[23] = max(0)/min(1)
4434 instr[22] = float(0)/double(1)
4438 instr[13,12] = nm(00)/normal(11)
4443 unsigned vm
= INSTR (20, 16);
4444 unsigned vn
= INSTR (9, 5);
4445 unsigned vd
= INSTR (4, 0);
4446 unsigned full
= INSTR (30, 30);
4447 unsigned min
= INSTR (23, 23);
4450 NYI_assert (29, 24, 0x0E);
4451 NYI_assert (21, 21, 1);
4452 NYI_assert (15, 14, 3);
4453 NYI_assert (11, 10, 1);
4455 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
4458 double (* func
)(double, double);
4463 if (INSTR (13, 12) == 0)
4464 func
= min
? dminnm
: dmaxnm
;
4465 else if (INSTR (13, 12) == 3)
4466 func
= min
? fmin
: fmax
;
4470 for (i
= 0; i
< 2; i
++)
4471 aarch64_set_vec_double (cpu
, vd
, i
,
4472 func (aarch64_get_vec_double (cpu
, vn
, i
),
4473 aarch64_get_vec_double (cpu
, vm
, i
)));
4477 float (* func
)(float, float);
4479 if (INSTR (13, 12) == 0)
4480 func
= min
? fminnm
: fmaxnm
;
4481 else if (INSTR (13, 12) == 3)
4482 func
= min
? fminf
: fmaxf
;
4486 for (i
= 0; i
< (full
? 4 : 2); i
++)
4487 aarch64_set_vec_float (cpu
, vd
, i
,
4488 func (aarch64_get_vec_float (cpu
, vn
, i
),
4489 aarch64_get_vec_float (cpu
, vm
, i
)));
4494 do_vec_SCVTF (sim_cpu
*cpu
)
4498 instr[29,23] = 00 1110 0
4499 instr[22] = float(0)/double(1)
4500 instr[21,10] = 10 0001 1101 10
4504 unsigned vn
= INSTR (9, 5);
4505 unsigned vd
= INSTR (4, 0);
4506 unsigned full
= INSTR (30, 30);
4507 unsigned size
= INSTR (22, 22);
4510 NYI_assert (29, 23, 0x1C);
4511 NYI_assert (21, 10, 0x876);
4513 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
4519 for (i
= 0; i
< 2; i
++)
4521 double val
= (double) aarch64_get_vec_u64 (cpu
, vn
, i
);
4522 aarch64_set_vec_double (cpu
, vd
, i
, val
);
4527 for (i
= 0; i
< (full
? 4 : 2); i
++)
4529 float val
= (float) aarch64_get_vec_u32 (cpu
, vn
, i
);
4530 aarch64_set_vec_float (cpu
, vd
, i
, val
);
4535 #define VEC_CMP(SOURCE, CMP) \
4541 for (i = 0; i < (full ? 16 : 8); i++) \
4542 aarch64_set_vec_u8 (cpu, vd, i, \
4543 aarch64_get_vec_##SOURCE##8 (cpu, vn, i) \
4545 aarch64_get_vec_##SOURCE##8 (cpu, vm, i) \
4549 for (i = 0; i < (full ? 8 : 4); i++) \
4550 aarch64_set_vec_u16 (cpu, vd, i, \
4551 aarch64_get_vec_##SOURCE##16 (cpu, vn, i) \
4553 aarch64_get_vec_##SOURCE##16 (cpu, vm, i) \
4557 for (i = 0; i < (full ? 4 : 2); i++) \
4558 aarch64_set_vec_u32 (cpu, vd, i, \
4559 aarch64_get_vec_##SOURCE##32 (cpu, vn, i) \
4561 aarch64_get_vec_##SOURCE##32 (cpu, vm, i) \
4567 for (i = 0; i < 2; i++) \
4568 aarch64_set_vec_u64 (cpu, vd, i, \
4569 aarch64_get_vec_##SOURCE##64 (cpu, vn, i) \
4571 aarch64_get_vec_##SOURCE##64 (cpu, vm, i) \
4578 #define VEC_CMP0(SOURCE, CMP) \
4584 for (i = 0; i < (full ? 16 : 8); i++) \
4585 aarch64_set_vec_u8 (cpu, vd, i, \
4586 aarch64_get_vec_##SOURCE##8 (cpu, vn, i) \
4590 for (i = 0; i < (full ? 8 : 4); i++) \
4591 aarch64_set_vec_u16 (cpu, vd, i, \
4592 aarch64_get_vec_##SOURCE##16 (cpu, vn, i) \
4596 for (i = 0; i < (full ? 4 : 2); i++) \
4597 aarch64_set_vec_u32 (cpu, vd, i, \
4598 aarch64_get_vec_##SOURCE##32 (cpu, vn, i) \
4604 for (i = 0; i < 2; i++) \
4605 aarch64_set_vec_u64 (cpu, vd, i, \
4606 aarch64_get_vec_##SOURCE##64 (cpu, vn, i) \
4607 CMP 0 ? -1ULL : 0); \
4613 #define VEC_FCMP0(CMP) \
4618 if (INSTR (22, 22)) \
4622 for (i = 0; i < 2; i++) \
4623 aarch64_set_vec_u64 (cpu, vd, i, \
4624 aarch64_get_vec_double (cpu, vn, i) \
4625 CMP 0.0 ? -1 : 0); \
4629 for (i = 0; i < (full ? 4 : 2); i++) \
4630 aarch64_set_vec_u32 (cpu, vd, i, \
4631 aarch64_get_vec_float (cpu, vn, i) \
4632 CMP 0.0 ? -1 : 0); \
4638 #define VEC_FCMP(CMP) \
4641 if (INSTR (22, 22)) \
4645 for (i = 0; i < 2; i++) \
4646 aarch64_set_vec_u64 (cpu, vd, i, \
4647 aarch64_get_vec_double (cpu, vn, i) \
4649 aarch64_get_vec_double (cpu, vm, i) \
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) \
4658 aarch64_get_vec_float (cpu, vm, i) \
4666 do_vec_compare (sim_cpu
*cpu
)
4669 instr[30] = half(0)/full(1)
4670 instr[29] = part-of-comparison-type
4671 instr[28,24] = 0 1110
4672 instr[23,22] = size of integer compares: byte(00), half(01), word (10), long (11)
4673 type of float compares: single (-0) / double (-1)
4675 instr[20,16] = Vm or 00000 (compare vs 0)
4676 instr[15,10] = part-of-comparison-type
4680 int full
= INSTR (30, 30);
4681 int size
= INSTR (23, 22);
4682 unsigned vm
= INSTR (20, 16);
4683 unsigned vn
= INSTR (9, 5);
4684 unsigned vd
= INSTR (4, 0);
4687 NYI_assert (28, 24, 0x0E);
4688 NYI_assert (21, 21, 1);
4690 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
4693 || ((INSTR (11, 11) == 0
4694 && INSTR (10, 10) == 0)))
4696 /* A compare vs 0. */
4699 if (INSTR (15, 10) == 0x2A)
4701 else if (INSTR (15, 10) == 0x32
4702 || INSTR (15, 10) == 0x3E)
4703 do_vec_fminmaxV (cpu
);
4704 else if (INSTR (29, 23) == 0x1C
4705 && INSTR (21, 10) == 0x876)
4715 /* A floating point compare. */
4716 unsigned decode
= (INSTR (29, 29) << 5) | (INSTR (23, 23) << 4)
4719 NYI_assert (15, 15, 1);
4723 case /* 0b010010: GT#0 */ 0x12: VEC_FCMP0 (>);
4724 case /* 0b110010: GE#0 */ 0x32: VEC_FCMP0 (>=);
4725 case /* 0b010110: EQ#0 */ 0x16: VEC_FCMP0 (==);
4726 case /* 0b110110: LE#0 */ 0x36: VEC_FCMP0 (<=);
4727 case /* 0b011010: LT#0 */ 0x1A: VEC_FCMP0 (<);
4728 case /* 0b111001: GT */ 0x39: VEC_FCMP (>);
4729 case /* 0b101001: GE */ 0x29: VEC_FCMP (>=);
4730 case /* 0b001001: EQ */ 0x09: VEC_FCMP (==);
4738 unsigned decode
= (INSTR (29, 29) << 6) | INSTR (15, 10);
4742 case 0x0D: /* 0001101 GT */ VEC_CMP (s
, > );
4743 case 0x0F: /* 0001111 GE */ VEC_CMP (s
, >= );
4744 case 0x22: /* 0100010 GT #0 */ VEC_CMP0 (s
, > );
4745 case 0x23: /* 0100011 TST */ VEC_CMP (u
, & );
4746 case 0x26: /* 0100110 EQ #0 */ VEC_CMP0 (s
, == );
4747 case 0x2A: /* 0101010 LT #0 */ VEC_CMP0 (s
, < );
4748 case 0x4D: /* 1001101 HI */ VEC_CMP (u
, > );
4749 case 0x4F: /* 1001111 HS */ VEC_CMP (u
, >= );
4750 case 0x62: /* 1100010 GE #0 */ VEC_CMP0 (s
, >= );
4751 case 0x63: /* 1100011 EQ */ VEC_CMP (u
, == );
4752 case 0x66: /* 1100110 LE #0 */ VEC_CMP0 (s
, <= );
4762 do_vec_SSHL (sim_cpu
*cpu
)
4765 instr[30] = first part (0)/ second part (1)
4766 instr[29,24] = 00 1110
4767 instr[23,22] = size: byte(00), half(01), word (10), long (11)
4770 instr[15,10] = 0100 01
4774 unsigned full
= INSTR (30, 30);
4775 unsigned vm
= INSTR (20, 16);
4776 unsigned vn
= INSTR (9, 5);
4777 unsigned vd
= INSTR (4, 0);
4781 NYI_assert (29, 24, 0x0E);
4782 NYI_assert (21, 21, 1);
4783 NYI_assert (15, 10, 0x11);
4785 /* FIXME: What is a signed shift left in this context ?. */
4787 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
4788 switch (INSTR (23, 22))
4791 for (i
= 0; i
< (full
? 16 : 8); i
++)
4793 shift
= aarch64_get_vec_s8 (cpu
, vm
, i
);
4795 aarch64_set_vec_s8 (cpu
, vd
, i
, aarch64_get_vec_s8 (cpu
, vn
, i
)
4798 aarch64_set_vec_s8 (cpu
, vd
, i
, aarch64_get_vec_s8 (cpu
, vn
, i
)
4804 for (i
= 0; i
< (full
? 8 : 4); i
++)
4806 shift
= aarch64_get_vec_s8 (cpu
, vm
, i
* 2);
4808 aarch64_set_vec_s16 (cpu
, vd
, i
, aarch64_get_vec_s16 (cpu
, vn
, i
)
4811 aarch64_set_vec_s16 (cpu
, vd
, i
, aarch64_get_vec_s16 (cpu
, vn
, i
)
4817 for (i
= 0; i
< (full
? 4 : 2); i
++)
4819 shift
= aarch64_get_vec_s8 (cpu
, vm
, i
* 4);
4821 aarch64_set_vec_s32 (cpu
, vd
, i
, aarch64_get_vec_s32 (cpu
, vn
, i
)
4824 aarch64_set_vec_s32 (cpu
, vd
, i
, aarch64_get_vec_s32 (cpu
, vn
, i
)
4832 for (i
= 0; i
< 2; i
++)
4834 shift
= aarch64_get_vec_s8 (cpu
, vm
, i
* 8);
4836 aarch64_set_vec_s64 (cpu
, vd
, i
, aarch64_get_vec_s64 (cpu
, vn
, i
)
4839 aarch64_set_vec_s64 (cpu
, vd
, i
, aarch64_get_vec_s64 (cpu
, vn
, i
)
4847 do_vec_USHL (sim_cpu
*cpu
)
4850 instr[30] = first part (0)/ second part (1)
4851 instr[29,24] = 10 1110
4852 instr[23,22] = size: byte(00), half(01), word (10), long (11)
4855 instr[15,10] = 0100 01
4859 unsigned full
= INSTR (30, 30);
4860 unsigned vm
= INSTR (20, 16);
4861 unsigned vn
= INSTR (9, 5);
4862 unsigned vd
= INSTR (4, 0);
4866 NYI_assert (29, 24, 0x2E);
4867 NYI_assert (15, 10, 0x11);
4869 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
4870 switch (INSTR (23, 22))
4873 for (i
= 0; i
< (full
? 16 : 8); i
++)
4875 shift
= aarch64_get_vec_s8 (cpu
, vm
, i
);
4877 aarch64_set_vec_u8 (cpu
, vd
, i
, aarch64_get_vec_u8 (cpu
, vn
, i
)
4880 aarch64_set_vec_u8 (cpu
, vd
, i
, aarch64_get_vec_u8 (cpu
, vn
, i
)
4886 for (i
= 0; i
< (full
? 8 : 4); i
++)
4888 shift
= aarch64_get_vec_s8 (cpu
, vm
, i
* 2);
4890 aarch64_set_vec_u16 (cpu
, vd
, i
, aarch64_get_vec_u16 (cpu
, vn
, i
)
4893 aarch64_set_vec_u16 (cpu
, vd
, i
, aarch64_get_vec_u16 (cpu
, vn
, i
)
4899 for (i
= 0; i
< (full
? 4 : 2); i
++)
4901 shift
= aarch64_get_vec_s8 (cpu
, vm
, i
* 4);
4903 aarch64_set_vec_u32 (cpu
, vd
, i
, aarch64_get_vec_u32 (cpu
, vn
, i
)
4906 aarch64_set_vec_u32 (cpu
, vd
, i
, aarch64_get_vec_u32 (cpu
, vn
, i
)
4914 for (i
= 0; i
< 2; i
++)
4916 shift
= aarch64_get_vec_s8 (cpu
, vm
, i
* 8);
4918 aarch64_set_vec_u64 (cpu
, vd
, i
, aarch64_get_vec_u64 (cpu
, vn
, i
)
4921 aarch64_set_vec_u64 (cpu
, vd
, i
, aarch64_get_vec_u64 (cpu
, vn
, i
)
4929 do_vec_FMLA (sim_cpu
*cpu
)
4932 instr[30] = full/half selector
4933 instr[29,23] = 0011100
4934 instr[22] = size: 0=>float, 1=>double
4937 instr[15,10] = 1100 11
4941 unsigned vm
= INSTR (20, 16);
4942 unsigned vn
= INSTR (9, 5);
4943 unsigned vd
= INSTR (4, 0);
4945 int full
= INSTR (30, 30);
4947 NYI_assert (29, 23, 0x1C);
4948 NYI_assert (21, 21, 1);
4949 NYI_assert (15, 10, 0x33);
4951 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
4956 for (i
= 0; i
< 2; i
++)
4957 aarch64_set_vec_double (cpu
, vd
, i
,
4958 aarch64_get_vec_double (cpu
, vn
, i
) *
4959 aarch64_get_vec_double (cpu
, vm
, i
) +
4960 aarch64_get_vec_double (cpu
, vd
, i
));
4964 for (i
= 0; i
< (full
? 4 : 2); i
++)
4965 aarch64_set_vec_float (cpu
, vd
, i
,
4966 aarch64_get_vec_float (cpu
, vn
, i
) *
4967 aarch64_get_vec_float (cpu
, vm
, i
) +
4968 aarch64_get_vec_float (cpu
, vd
, i
));
4973 do_vec_max (sim_cpu
*cpu
)
4976 instr[30] = full/half selector
4977 instr[29] = SMAX (0) / UMAX (1)
4978 instr[28,24] = 0 1110
4979 instr[23,22] = size: 00=> 8-bit, 01=> 16-bit, 10=> 32-bit
4982 instr[15,10] = 0110 01
4986 unsigned vm
= INSTR (20, 16);
4987 unsigned vn
= INSTR (9, 5);
4988 unsigned vd
= INSTR (4, 0);
4990 int full
= INSTR (30, 30);
4992 NYI_assert (28, 24, 0x0E);
4993 NYI_assert (21, 21, 1);
4994 NYI_assert (15, 10, 0x19);
4996 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
4999 switch (INSTR (23, 22))
5002 for (i
= 0; i
< (full
? 16 : 8); i
++)
5003 aarch64_set_vec_u8 (cpu
, vd
, i
,
5004 aarch64_get_vec_u8 (cpu
, vn
, i
)
5005 > aarch64_get_vec_u8 (cpu
, vm
, i
)
5006 ? aarch64_get_vec_u8 (cpu
, vn
, i
)
5007 : aarch64_get_vec_u8 (cpu
, vm
, i
));
5011 for (i
= 0; i
< (full
? 8 : 4); i
++)
5012 aarch64_set_vec_u16 (cpu
, vd
, i
,
5013 aarch64_get_vec_u16 (cpu
, vn
, i
)
5014 > aarch64_get_vec_u16 (cpu
, vm
, i
)
5015 ? aarch64_get_vec_u16 (cpu
, vn
, i
)
5016 : aarch64_get_vec_u16 (cpu
, vm
, i
));
5020 for (i
= 0; i
< (full
? 4 : 2); i
++)
5021 aarch64_set_vec_u32 (cpu
, vd
, i
,
5022 aarch64_get_vec_u32 (cpu
, vn
, i
)
5023 > aarch64_get_vec_u32 (cpu
, vm
, i
)
5024 ? aarch64_get_vec_u32 (cpu
, vn
, i
)
5025 : aarch64_get_vec_u32 (cpu
, vm
, i
));
5034 switch (INSTR (23, 22))
5037 for (i
= 0; i
< (full
? 16 : 8); i
++)
5038 aarch64_set_vec_s8 (cpu
, vd
, i
,
5039 aarch64_get_vec_s8 (cpu
, vn
, i
)
5040 > aarch64_get_vec_s8 (cpu
, vm
, i
)
5041 ? aarch64_get_vec_s8 (cpu
, vn
, i
)
5042 : aarch64_get_vec_s8 (cpu
, vm
, i
));
5046 for (i
= 0; i
< (full
? 8 : 4); i
++)
5047 aarch64_set_vec_s16 (cpu
, vd
, i
,
5048 aarch64_get_vec_s16 (cpu
, vn
, i
)
5049 > aarch64_get_vec_s16 (cpu
, vm
, i
)
5050 ? aarch64_get_vec_s16 (cpu
, vn
, i
)
5051 : aarch64_get_vec_s16 (cpu
, vm
, i
));
5055 for (i
= 0; i
< (full
? 4 : 2); i
++)
5056 aarch64_set_vec_s32 (cpu
, vd
, i
,
5057 aarch64_get_vec_s32 (cpu
, vn
, i
)
5058 > aarch64_get_vec_s32 (cpu
, vm
, i
)
5059 ? aarch64_get_vec_s32 (cpu
, vn
, i
)
5060 : aarch64_get_vec_s32 (cpu
, vm
, i
));
5070 do_vec_min (sim_cpu
*cpu
)
5073 instr[30] = full/half selector
5074 instr[29] = SMIN (0) / UMIN (1)
5075 instr[28,24] = 0 1110
5076 instr[23,22] = size: 00=> 8-bit, 01=> 16-bit, 10=> 32-bit
5079 instr[15,10] = 0110 11
5083 unsigned vm
= INSTR (20, 16);
5084 unsigned vn
= INSTR (9, 5);
5085 unsigned vd
= INSTR (4, 0);
5087 int full
= INSTR (30, 30);
5089 NYI_assert (28, 24, 0x0E);
5090 NYI_assert (21, 21, 1);
5091 NYI_assert (15, 10, 0x1B);
5093 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
5096 switch (INSTR (23, 22))
5099 for (i
= 0; i
< (full
? 16 : 8); i
++)
5100 aarch64_set_vec_u8 (cpu
, vd
, i
,
5101 aarch64_get_vec_u8 (cpu
, vn
, i
)
5102 < aarch64_get_vec_u8 (cpu
, vm
, i
)
5103 ? aarch64_get_vec_u8 (cpu
, vn
, i
)
5104 : aarch64_get_vec_u8 (cpu
, vm
, i
));
5108 for (i
= 0; i
< (full
? 8 : 4); i
++)
5109 aarch64_set_vec_u16 (cpu
, vd
, i
,
5110 aarch64_get_vec_u16 (cpu
, vn
, i
)
5111 < aarch64_get_vec_u16 (cpu
, vm
, i
)
5112 ? aarch64_get_vec_u16 (cpu
, vn
, i
)
5113 : aarch64_get_vec_u16 (cpu
, vm
, i
));
5117 for (i
= 0; i
< (full
? 4 : 2); i
++)
5118 aarch64_set_vec_u32 (cpu
, vd
, i
,
5119 aarch64_get_vec_u32 (cpu
, vn
, i
)
5120 < aarch64_get_vec_u32 (cpu
, vm
, i
)
5121 ? aarch64_get_vec_u32 (cpu
, vn
, i
)
5122 : aarch64_get_vec_u32 (cpu
, vm
, i
));
5131 switch (INSTR (23, 22))
5134 for (i
= 0; i
< (full
? 16 : 8); i
++)
5135 aarch64_set_vec_s8 (cpu
, vd
, i
,
5136 aarch64_get_vec_s8 (cpu
, vn
, i
)
5137 < aarch64_get_vec_s8 (cpu
, vm
, i
)
5138 ? aarch64_get_vec_s8 (cpu
, vn
, i
)
5139 : aarch64_get_vec_s8 (cpu
, vm
, i
));
5143 for (i
= 0; i
< (full
? 8 : 4); i
++)
5144 aarch64_set_vec_s16 (cpu
, vd
, i
,
5145 aarch64_get_vec_s16 (cpu
, vn
, i
)
5146 < aarch64_get_vec_s16 (cpu
, vm
, i
)
5147 ? aarch64_get_vec_s16 (cpu
, vn
, i
)
5148 : aarch64_get_vec_s16 (cpu
, vm
, i
));
5152 for (i
= 0; i
< (full
? 4 : 2); i
++)
5153 aarch64_set_vec_s32 (cpu
, vd
, i
,
5154 aarch64_get_vec_s32 (cpu
, vn
, i
)
5155 < aarch64_get_vec_s32 (cpu
, vm
, i
)
5156 ? aarch64_get_vec_s32 (cpu
, vn
, i
)
5157 : aarch64_get_vec_s32 (cpu
, vm
, i
));
5167 do_vec_sub_long (sim_cpu
*cpu
)
5170 instr[30] = lower (0) / upper (1)
5171 instr[29] = signed (0) / unsigned (1)
5172 instr[28,24] = 0 1110
5173 instr[23,22] = size: bytes (00), half (01), word (10)
5176 instr[15,10] = 0010 00
5178 instr[4,0] = V dest. */
5180 unsigned size
= INSTR (23, 22);
5181 unsigned vm
= INSTR (20, 16);
5182 unsigned vn
= INSTR (9, 5);
5183 unsigned vd
= INSTR (4, 0);
5187 NYI_assert (28, 24, 0x0E);
5188 NYI_assert (21, 21, 1);
5189 NYI_assert (15, 10, 0x08);
5194 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
5195 switch (INSTR (30, 29))
5197 case 2: /* SSUBL2. */
5199 case 0: /* SSUBL. */
5204 for (i
= 0; i
< 8; i
++)
5205 aarch64_set_vec_s16 (cpu
, vd
, i
,
5206 aarch64_get_vec_s8 (cpu
, vn
, i
+ bias
)
5207 - aarch64_get_vec_s8 (cpu
, vm
, i
+ bias
));
5212 for (i
= 0; i
< 4; i
++)
5213 aarch64_set_vec_s32 (cpu
, vd
, i
,
5214 aarch64_get_vec_s16 (cpu
, vn
, i
+ bias
)
5215 - aarch64_get_vec_s16 (cpu
, vm
, i
+ bias
));
5219 for (i
= 0; i
< 2; i
++)
5220 aarch64_set_vec_s64 (cpu
, vd
, i
,
5221 aarch64_get_vec_s32 (cpu
, vn
, i
+ bias
)
5222 - aarch64_get_vec_s32 (cpu
, vm
, i
+ bias
));
5230 case 3: /* USUBL2. */
5232 case 1: /* USUBL. */
5237 for (i
= 0; i
< 8; i
++)
5238 aarch64_set_vec_u16 (cpu
, vd
, i
,
5239 aarch64_get_vec_u8 (cpu
, vn
, i
+ bias
)
5240 - aarch64_get_vec_u8 (cpu
, vm
, i
+ bias
));
5245 for (i
= 0; i
< 4; i
++)
5246 aarch64_set_vec_u32 (cpu
, vd
, i
,
5247 aarch64_get_vec_u16 (cpu
, vn
, i
+ bias
)
5248 - aarch64_get_vec_u16 (cpu
, vm
, i
+ bias
));
5252 for (i
= 0; i
< 2; i
++)
5253 aarch64_set_vec_u64 (cpu
, vd
, i
,
5254 aarch64_get_vec_u32 (cpu
, vn
, i
+ bias
)
5255 - aarch64_get_vec_u32 (cpu
, vm
, i
+ bias
));
5266 do_vec_ADDP (sim_cpu
*cpu
)
5269 instr[30] = half(0)/full(1)
5270 instr[29,24] = 00 1110
5271 instr[23,22] = size: bytes (00), half (01), word (10), long (11)
5274 instr[15,10] = 1011 11
5276 instr[4,0] = V dest. */
5280 unsigned full
= INSTR (30, 30);
5281 unsigned size
= INSTR (23, 22);
5282 unsigned vm
= INSTR (20, 16);
5283 unsigned vn
= INSTR (9, 5);
5284 unsigned vd
= INSTR (4, 0);
5287 NYI_assert (29, 24, 0x0E);
5288 NYI_assert (21, 21, 1);
5289 NYI_assert (15, 10, 0x2F);
5291 /* Make copies of the source registers in case vd == vn/vm. */
5292 copy_vn
= cpu
->fr
[vn
];
5293 copy_vm
= cpu
->fr
[vm
];
5295 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
5299 range
= full
? 8 : 4;
5300 for (i
= 0; i
< range
; i
++)
5302 aarch64_set_vec_u8 (cpu
, vd
, i
,
5303 copy_vn
.b
[i
* 2] + copy_vn
.b
[i
* 2 + 1]);
5304 aarch64_set_vec_u8 (cpu
, vd
, i
+ range
,
5305 copy_vm
.b
[i
* 2] + copy_vm
.b
[i
* 2 + 1]);
5310 range
= full
? 4 : 2;
5311 for (i
= 0; i
< range
; i
++)
5313 aarch64_set_vec_u16 (cpu
, vd
, i
,
5314 copy_vn
.h
[i
* 2] + copy_vn
.h
[i
* 2 + 1]);
5315 aarch64_set_vec_u16 (cpu
, vd
, i
+ range
,
5316 copy_vm
.h
[i
* 2] + copy_vm
.h
[i
* 2 + 1]);
5321 range
= full
? 2 : 1;
5322 for (i
= 0; i
< range
; i
++)
5324 aarch64_set_vec_u32 (cpu
, vd
, i
,
5325 copy_vn
.w
[i
* 2] + copy_vn
.w
[i
* 2 + 1]);
5326 aarch64_set_vec_u32 (cpu
, vd
, i
+ range
,
5327 copy_vm
.w
[i
* 2] + copy_vm
.w
[i
* 2 + 1]);
5334 aarch64_set_vec_u64 (cpu
, vd
, 0, copy_vn
.v
[0] + copy_vn
.v
[1]);
5335 aarch64_set_vec_u64 (cpu
, vd
, 1, copy_vm
.v
[0] + copy_vm
.v
[1]);
5341 do_vec_UMOV (sim_cpu
*cpu
)
5344 instr[30] = 32-bit(0)/64-bit(1)
5345 instr[29,21] = 00 1110 000
5346 insrt[20,16] = size & index
5347 instr[15,10] = 0011 11
5348 instr[9,5] = V source
5349 instr[4,0] = R dest. */
5351 unsigned vs
= INSTR (9, 5);
5352 unsigned rd
= INSTR (4, 0);
5355 NYI_assert (29, 21, 0x070);
5356 NYI_assert (15, 10, 0x0F);
5358 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
5361 /* Byte transfer. */
5362 index
= INSTR (20, 17);
5363 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
,
5364 aarch64_get_vec_u8 (cpu
, vs
, index
));
5366 else if (INSTR (17, 17))
5368 index
= INSTR (20, 18);
5369 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
,
5370 aarch64_get_vec_u16 (cpu
, vs
, index
));
5372 else if (INSTR (18, 18))
5374 index
= INSTR (20, 19);
5375 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
,
5376 aarch64_get_vec_u32 (cpu
, vs
, index
));
5380 if (INSTR (30, 30) != 1)
5383 index
= INSTR (20, 20);
5384 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
,
5385 aarch64_get_vec_u64 (cpu
, vs
, index
));
5390 do_vec_FABS (sim_cpu
*cpu
)
5393 instr[30] = half(0)/full(1)
5394 instr[29,23] = 00 1110 1
5395 instr[22] = float(0)/double(1)
5396 instr[21,16] = 10 0000
5397 instr[15,10] = 1111 10
5401 unsigned vn
= INSTR (9, 5);
5402 unsigned vd
= INSTR (4, 0);
5403 unsigned full
= INSTR (30, 30);
5406 NYI_assert (29, 23, 0x1D);
5407 NYI_assert (21, 10, 0x83E);
5409 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
5415 for (i
= 0; i
< 2; i
++)
5416 aarch64_set_vec_double (cpu
, vd
, i
,
5417 fabs (aarch64_get_vec_double (cpu
, vn
, i
)));
5421 for (i
= 0; i
< (full
? 4 : 2); i
++)
5422 aarch64_set_vec_float (cpu
, vd
, i
,
5423 fabsf (aarch64_get_vec_float (cpu
, vn
, i
)));
5428 do_vec_FCVTZS (sim_cpu
*cpu
)
5431 instr[30] = half (0) / all (1)
5432 instr[29,23] = 00 1110 1
5433 instr[22] = single (0) / double (1)
5434 instr[21,10] = 10 0001 1011 10
5438 unsigned rn
= INSTR (9, 5);
5439 unsigned rd
= INSTR (4, 0);
5440 unsigned full
= INSTR (30, 30);
5443 NYI_assert (31, 31, 0);
5444 NYI_assert (29, 23, 0x1D);
5445 NYI_assert (21, 10, 0x86E);
5447 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
5453 for (i
= 0; i
< 2; i
++)
5454 aarch64_set_vec_s64 (cpu
, rd
, i
,
5455 (int64_t) aarch64_get_vec_double (cpu
, rn
, i
));
5458 for (i
= 0; i
< (full
? 4 : 2); i
++)
5459 aarch64_set_vec_s32 (cpu
, rd
, i
,
5460 (int32_t) aarch64_get_vec_float (cpu
, rn
, i
));
5464 do_vec_REV64 (sim_cpu
*cpu
)
5467 instr[30] = full/half
5468 instr[29,24] = 00 1110
5470 instr[21,10] = 10 0000 0000 10
5474 unsigned rn
= INSTR (9, 5);
5475 unsigned rd
= INSTR (4, 0);
5476 unsigned size
= INSTR (23, 22);
5477 unsigned full
= INSTR (30, 30);
5481 NYI_assert (29, 24, 0x0E);
5482 NYI_assert (21, 10, 0x802);
5484 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
5488 for (i
= 0; i
< (full
? 16 : 8); i
++)
5489 val
.b
[i
^ 0x7] = aarch64_get_vec_u8 (cpu
, rn
, i
);
5493 for (i
= 0; i
< (full
? 8 : 4); i
++)
5494 val
.h
[i
^ 0x3] = aarch64_get_vec_u16 (cpu
, rn
, i
);
5498 for (i
= 0; i
< (full
? 4 : 2); i
++)
5499 val
.w
[i
^ 0x1] = aarch64_get_vec_u32 (cpu
, rn
, i
);
5506 aarch64_set_vec_u64 (cpu
, rd
, 0, val
.v
[0]);
5508 aarch64_set_vec_u64 (cpu
, rd
, 1, val
.v
[1]);
5512 do_vec_REV16 (sim_cpu
*cpu
)
5515 instr[30] = full/half
5516 instr[29,24] = 00 1110
5518 instr[21,10] = 10 0000 0001 10
5522 unsigned rn
= INSTR (9, 5);
5523 unsigned rd
= INSTR (4, 0);
5524 unsigned size
= INSTR (23, 22);
5525 unsigned full
= INSTR (30, 30);
5529 NYI_assert (29, 24, 0x0E);
5530 NYI_assert (21, 10, 0x806);
5532 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
5536 for (i
= 0; i
< (full
? 16 : 8); i
++)
5537 val
.b
[i
^ 0x1] = aarch64_get_vec_u8 (cpu
, rn
, i
);
5544 aarch64_set_vec_u64 (cpu
, rd
, 0, val
.v
[0]);
5546 aarch64_set_vec_u64 (cpu
, rd
, 1, val
.v
[1]);
5550 do_vec_op1 (sim_cpu
*cpu
)
5553 instr[30] = half/full
5554 instr[29,24] = 00 1110
5557 instr[15,10] = sub-opcode
5560 NYI_assert (29, 24, 0x0E);
5562 if (INSTR (21, 21) == 0)
5564 if (INSTR (23, 22) == 0)
5566 if (INSTR (30, 30) == 1
5567 && INSTR (17, 14) == 0
5568 && INSTR (12, 10) == 7)
5569 return do_vec_ins_2 (cpu
);
5571 switch (INSTR (15, 10))
5573 case 0x01: do_vec_DUP_vector_into_vector (cpu
); return;
5574 case 0x03: do_vec_DUP_scalar_into_vector (cpu
); return;
5575 case 0x07: do_vec_INS (cpu
); return;
5576 case 0x0A: do_vec_TRN (cpu
); return;
5579 if (INSTR (17, 16) == 0)
5581 do_vec_MOV_into_scalar (cpu
);
5590 do_vec_TBL (cpu
); return;
5594 do_vec_UZP (cpu
); return;
5598 do_vec_ZIP (cpu
); return;
5605 switch (INSTR (13, 10))
5607 case 0x6: do_vec_UZP (cpu
); return;
5608 case 0xE: do_vec_ZIP (cpu
); return;
5609 case 0xA: do_vec_TRN (cpu
); return;
5610 case 0xF: do_vec_UMOV (cpu
); return;
5615 switch (INSTR (15, 10))
5617 case 0x02: do_vec_REV64 (cpu
); return;
5618 case 0x06: do_vec_REV16 (cpu
); return;
5621 switch (INSTR (23, 21))
5623 case 1: do_vec_AND (cpu
); return;
5624 case 3: do_vec_BIC (cpu
); return;
5625 case 5: do_vec_ORR (cpu
); return;
5626 case 7: do_vec_ORN (cpu
); return;
5630 case 0x08: do_vec_sub_long (cpu
); return;
5631 case 0x0a: do_vec_XTN (cpu
); return;
5632 case 0x11: do_vec_SSHL (cpu
); return;
5633 case 0x19: do_vec_max (cpu
); return;
5634 case 0x1B: do_vec_min (cpu
); return;
5635 case 0x21: do_vec_add (cpu
); return;
5636 case 0x25: do_vec_MLA (cpu
); return;
5637 case 0x27: do_vec_mul (cpu
); return;
5638 case 0x2F: do_vec_ADDP (cpu
); return;
5639 case 0x30: do_vec_mull (cpu
); return;
5640 case 0x33: do_vec_FMLA (cpu
); return;
5641 case 0x35: do_vec_fadd (cpu
); return;
5644 switch (INSTR (20, 16))
5646 case 0x00: do_vec_ABS (cpu
); return;
5647 case 0x01: do_vec_FCVTZS (cpu
); return;
5648 case 0x11: do_vec_ADDV (cpu
); return;
5654 do_vec_Fminmax (cpu
); return;
5666 do_vec_compare (cpu
); return;
5669 do_vec_FABS (cpu
); return;
5677 do_vec_xtl (sim_cpu
*cpu
)
5680 instr[30,29] = SXTL (00), UXTL (01), SXTL2 (10), UXTL2 (11)
5681 instr[28,22] = 0 1111 00
5682 instr[21,16] = size & shift (USHLL, SSHLL, USHLL2, SSHLL2)
5683 instr[15,10] = 1010 01
5684 instr[9,5] = V source
5685 instr[4,0] = V dest. */
5687 unsigned vs
= INSTR (9, 5);
5688 unsigned vd
= INSTR (4, 0);
5689 unsigned i
, shift
, bias
= 0;
5691 NYI_assert (28, 22, 0x3C);
5692 NYI_assert (15, 10, 0x29);
5694 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
5695 switch (INSTR (30, 29))
5697 case 2: /* SXTL2, SSHLL2. */
5699 case 0: /* SXTL, SSHLL. */
5704 shift
= INSTR (20, 16);
5705 /* Get the source values before setting the destination values
5706 in case the source and destination are the same. */
5707 val1
= aarch64_get_vec_s32 (cpu
, vs
, bias
) << shift
;
5708 val2
= aarch64_get_vec_s32 (cpu
, vs
, bias
+ 1) << shift
;
5709 aarch64_set_vec_s64 (cpu
, vd
, 0, val1
);
5710 aarch64_set_vec_s64 (cpu
, vd
, 1, val2
);
5712 else if (INSTR (20, 20))
5715 int32_t v1
,v2
,v3
,v4
;
5717 shift
= INSTR (19, 16);
5719 for (i
= 0; i
< 4; i
++)
5720 v
[i
] = aarch64_get_vec_s16 (cpu
, vs
, bias
+ i
) << shift
;
5721 for (i
= 0; i
< 4; i
++)
5722 aarch64_set_vec_s32 (cpu
, vd
, i
, v
[i
]);
5727 NYI_assert (19, 19, 1);
5729 shift
= INSTR (18, 16);
5731 for (i
= 0; i
< 8; i
++)
5732 v
[i
] = aarch64_get_vec_s8 (cpu
, vs
, i
+ bias
) << shift
;
5733 for (i
= 0; i
< 8; i
++)
5734 aarch64_set_vec_s16 (cpu
, vd
, i
, v
[i
]);
5738 case 3: /* UXTL2, USHLL2. */
5740 case 1: /* UXTL, USHLL. */
5744 shift
= INSTR (20, 16);
5745 v1
= aarch64_get_vec_u32 (cpu
, vs
, bias
) << shift
;
5746 v2
= aarch64_get_vec_u32 (cpu
, vs
, bias
+ 1) << shift
;
5747 aarch64_set_vec_u64 (cpu
, vd
, 0, v1
);
5748 aarch64_set_vec_u64 (cpu
, vd
, 1, v2
);
5750 else if (INSTR (20, 20))
5753 shift
= INSTR (19, 16);
5755 for (i
= 0; i
< 4; i
++)
5756 v
[i
] = aarch64_get_vec_u16 (cpu
, vs
, i
+ bias
) << shift
;
5757 for (i
= 0; i
< 4; i
++)
5758 aarch64_set_vec_u32 (cpu
, vd
, i
, v
[i
]);
5763 NYI_assert (19, 19, 1);
5765 shift
= INSTR (18, 16);
5767 for (i
= 0; i
< 8; i
++)
5768 v
[i
] = aarch64_get_vec_u8 (cpu
, vs
, i
+ bias
) << shift
;
5769 for (i
= 0; i
< 8; i
++)
5770 aarch64_set_vec_u16 (cpu
, vd
, i
, v
[i
]);
5777 do_vec_SHL (sim_cpu
*cpu
)
5780 instr [30] = half(0)/full(1)
5781 instr [29,23] = 001 1110
5782 instr [22,16] = size and shift amount
5783 instr [15,10] = 01 0101
5785 instr [4, 0] = Vd. */
5788 int full
= INSTR (30, 30);
5789 unsigned vs
= INSTR (9, 5);
5790 unsigned vd
= INSTR (4, 0);
5793 NYI_assert (29, 23, 0x1E);
5794 NYI_assert (15, 10, 0x15);
5796 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
5799 shift
= INSTR (21, 16);
5804 for (i
= 0; i
< 2; i
++)
5806 uint64_t val
= aarch64_get_vec_u64 (cpu
, vs
, i
);
5807 aarch64_set_vec_u64 (cpu
, vd
, i
, val
<< shift
);
5815 shift
= INSTR (20, 16);
5817 for (i
= 0; i
< (full
? 4 : 2); i
++)
5819 uint32_t val
= aarch64_get_vec_u32 (cpu
, vs
, i
);
5820 aarch64_set_vec_u32 (cpu
, vd
, i
, val
<< shift
);
5828 shift
= INSTR (19, 16);
5830 for (i
= 0; i
< (full
? 8 : 4); i
++)
5832 uint16_t val
= aarch64_get_vec_u16 (cpu
, vs
, i
);
5833 aarch64_set_vec_u16 (cpu
, vd
, i
, val
<< shift
);
5839 if (INSTR (19, 19) == 0)
5842 shift
= INSTR (18, 16);
5844 for (i
= 0; i
< (full
? 16 : 8); i
++)
5846 uint8_t val
= aarch64_get_vec_u8 (cpu
, vs
, i
);
5847 aarch64_set_vec_u8 (cpu
, vd
, i
, val
<< shift
);
5852 do_vec_SSHR_USHR (sim_cpu
*cpu
)
5855 instr [30] = half(0)/full(1)
5856 instr [29] = signed(0)/unsigned(1)
5857 instr [28,23] = 0 1111 0
5858 instr [22,16] = size and shift amount
5859 instr [15,10] = 0000 01
5861 instr [4, 0] = Vd. */
5863 int full
= INSTR (30, 30);
5864 int sign
= ! INSTR (29, 29);
5865 unsigned shift
= INSTR (22, 16);
5866 unsigned vs
= INSTR (9, 5);
5867 unsigned vd
= INSTR (4, 0);
5870 NYI_assert (28, 23, 0x1E);
5871 NYI_assert (15, 10, 0x01);
5873 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
5876 shift
= 128 - shift
;
5882 for (i
= 0; i
< 2; i
++)
5884 int64_t val
= aarch64_get_vec_s64 (cpu
, vs
, i
);
5885 aarch64_set_vec_s64 (cpu
, vd
, i
, val
>> shift
);
5888 for (i
= 0; i
< 2; i
++)
5890 uint64_t val
= aarch64_get_vec_u64 (cpu
, vs
, i
);
5891 aarch64_set_vec_u64 (cpu
, vd
, i
, val
>> shift
);
5902 for (i
= 0; i
< (full
? 4 : 2); i
++)
5904 int32_t val
= aarch64_get_vec_s32 (cpu
, vs
, i
);
5905 aarch64_set_vec_s32 (cpu
, vd
, i
, val
>> shift
);
5908 for (i
= 0; i
< (full
? 4 : 2); i
++)
5910 uint32_t val
= aarch64_get_vec_u32 (cpu
, vs
, i
);
5911 aarch64_set_vec_u32 (cpu
, vd
, i
, val
>> shift
);
5922 for (i
= 0; i
< (full
? 8 : 4); i
++)
5924 int16_t val
= aarch64_get_vec_s16 (cpu
, vs
, i
);
5925 aarch64_set_vec_s16 (cpu
, vd
, i
, val
>> shift
);
5928 for (i
= 0; i
< (full
? 8 : 4); i
++)
5930 uint16_t val
= aarch64_get_vec_u16 (cpu
, vs
, i
);
5931 aarch64_set_vec_u16 (cpu
, vd
, i
, val
>> shift
);
5937 if (INSTR (19, 19) == 0)
5943 for (i
= 0; i
< (full
? 16 : 8); i
++)
5945 int8_t val
= aarch64_get_vec_s8 (cpu
, vs
, i
);
5946 aarch64_set_vec_s8 (cpu
, vd
, i
, val
>> shift
);
5949 for (i
= 0; i
< (full
? 16 : 8); i
++)
5951 uint8_t val
= aarch64_get_vec_u8 (cpu
, vs
, i
);
5952 aarch64_set_vec_u8 (cpu
, vd
, i
, val
>> shift
);
5957 do_vec_MUL_by_element (sim_cpu
*cpu
)
5960 instr[30] = half/full
5961 instr[29,24] = 00 1111
5972 unsigned full
= INSTR (30, 30);
5973 unsigned L
= INSTR (21, 21);
5974 unsigned H
= INSTR (11, 11);
5975 unsigned vn
= INSTR (9, 5);
5976 unsigned vd
= INSTR (4, 0);
5977 unsigned size
= INSTR (23, 22);
5982 NYI_assert (29, 24, 0x0F);
5983 NYI_assert (15, 12, 0x8);
5984 NYI_assert (10, 10, 0);
5986 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
5991 /* 16 bit products. */
5996 index
= (H
<< 2) | (L
<< 1) | INSTR (20, 20);
5997 vm
= INSTR (19, 16);
5998 element2
= aarch64_get_vec_u16 (cpu
, vm
, index
);
6000 for (e
= 0; e
< (full
? 8 : 4); e
++)
6002 element1
= aarch64_get_vec_u16 (cpu
, vn
, e
);
6003 product
= element1
* element2
;
6004 aarch64_set_vec_u16 (cpu
, vd
, e
, product
);
6011 /* 32 bit products. */
6016 index
= (H
<< 1) | L
;
6017 vm
= INSTR (20, 16);
6018 element2
= aarch64_get_vec_u32 (cpu
, vm
, index
);
6020 for (e
= 0; e
< (full
? 4 : 2); e
++)
6022 element1
= aarch64_get_vec_u32 (cpu
, vn
, e
);
6023 product
= element1
* element2
;
6024 aarch64_set_vec_u32 (cpu
, vd
, e
, product
);
6035 do_FMLA_by_element (sim_cpu
*cpu
)
6038 instr[30] = half/full
6039 instr[29,23] = 00 1111 1
6049 unsigned full
= INSTR (30, 30);
6050 unsigned size
= INSTR (22, 22);
6051 unsigned L
= INSTR (21, 21);
6052 unsigned vm
= INSTR (20, 16);
6053 unsigned H
= INSTR (11, 11);
6054 unsigned vn
= INSTR (9, 5);
6055 unsigned vd
= INSTR (4, 0);
6058 NYI_assert (29, 23, 0x1F);
6059 NYI_assert (15, 12, 0x1);
6060 NYI_assert (10, 10, 0);
6062 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
6065 double element1
, element2
;
6070 element2
= aarch64_get_vec_double (cpu
, vm
, H
);
6072 for (e
= 0; e
< 2; e
++)
6074 element1
= aarch64_get_vec_double (cpu
, vn
, e
);
6075 element1
*= element2
;
6076 element1
+= aarch64_get_vec_double (cpu
, vd
, e
);
6077 aarch64_set_vec_double (cpu
, vd
, e
, element1
);
6083 float element2
= aarch64_get_vec_float (cpu
, vm
, (H
<< 1) | L
);
6085 for (e
= 0; e
< (full
? 4 : 2); e
++)
6087 element1
= aarch64_get_vec_float (cpu
, vn
, e
);
6088 element1
*= element2
;
6089 element1
+= aarch64_get_vec_float (cpu
, vd
, e
);
6090 aarch64_set_vec_float (cpu
, vd
, e
, element1
);
6096 do_vec_op2 (sim_cpu
*cpu
)
6099 instr[30] = half/full
6100 instr[29,24] = 00 1111
6102 instr[22,16] = element size & index
6103 instr[15,10] = sub-opcode
6107 NYI_assert (29, 24, 0x0F);
6109 if (INSTR (23, 23) != 0)
6111 switch (INSTR (15, 10))
6115 do_FMLA_by_element (cpu
);
6120 do_vec_MUL_by_element (cpu
);
6129 switch (INSTR (15, 10))
6131 case 0x01: do_vec_SSHR_USHR (cpu
); return;
6132 case 0x15: do_vec_SHL (cpu
); return;
6134 case 0x22: do_vec_MUL_by_element (cpu
); return;
6135 case 0x29: do_vec_xtl (cpu
); return;
6142 do_vec_neg (sim_cpu
*cpu
)
6145 instr[30] = full(1)/half(0)
6146 instr[29,24] = 10 1110
6147 instr[23,22] = size: byte(00), half (01), word (10), long (11)
6148 instr[21,10] = 1000 0010 1110
6152 int full
= INSTR (30, 30);
6153 unsigned vs
= INSTR (9, 5);
6154 unsigned vd
= INSTR (4, 0);
6157 NYI_assert (29, 24, 0x2E);
6158 NYI_assert (21, 10, 0x82E);
6160 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
6161 switch (INSTR (23, 22))
6164 for (i
= 0; i
< (full
? 16 : 8); i
++)
6165 aarch64_set_vec_s8 (cpu
, vd
, i
, - aarch64_get_vec_s8 (cpu
, vs
, i
));
6169 for (i
= 0; i
< (full
? 8 : 4); i
++)
6170 aarch64_set_vec_s16 (cpu
, vd
, i
, - aarch64_get_vec_s16 (cpu
, vs
, i
));
6174 for (i
= 0; i
< (full
? 4 : 2); i
++)
6175 aarch64_set_vec_s32 (cpu
, vd
, i
, - aarch64_get_vec_s32 (cpu
, vs
, i
));
6181 for (i
= 0; i
< 2; i
++)
6182 aarch64_set_vec_s64 (cpu
, vd
, i
, - aarch64_get_vec_s64 (cpu
, vs
, i
));
6188 do_vec_sqrt (sim_cpu
*cpu
)
6191 instr[30] = full(1)/half(0)
6192 instr[29,23] = 101 1101
6193 instr[22] = single(0)/double(1)
6194 instr[21,10] = 1000 0111 1110
6198 int full
= INSTR (30, 30);
6199 unsigned vs
= INSTR (9, 5);
6200 unsigned vd
= INSTR (4, 0);
6203 NYI_assert (29, 23, 0x5B);
6204 NYI_assert (21, 10, 0x87E);
6206 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
6207 if (INSTR (22, 22) == 0)
6208 for (i
= 0; i
< (full
? 4 : 2); i
++)
6209 aarch64_set_vec_float (cpu
, vd
, i
,
6210 sqrtf (aarch64_get_vec_float (cpu
, vs
, i
)));
6212 for (i
= 0; i
< 2; i
++)
6213 aarch64_set_vec_double (cpu
, vd
, i
,
6214 sqrt (aarch64_get_vec_double (cpu
, vs
, i
)));
6218 do_vec_mls_indexed (sim_cpu
*cpu
)
6221 instr[30] = half(0)/full(1)
6222 instr[29,24] = 10 1111
6223 instr[23,22] = 16-bit(01)/32-bit(10)
6224 instr[21,20+11] = index (if 16-bit)
6225 instr[21+11] = index (if 32-bit)
6228 instr[11] = part of index
6233 int full
= INSTR (30, 30);
6234 unsigned vs
= INSTR (9, 5);
6235 unsigned vd
= INSTR (4, 0);
6236 unsigned vm
= INSTR (20, 16);
6239 NYI_assert (15, 12, 4);
6240 NYI_assert (10, 10, 0);
6242 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
6243 switch (INSTR (23, 22))
6253 elem
= (INSTR (21, 20) << 1) | INSTR (11, 11);
6254 val
= aarch64_get_vec_u16 (cpu
, vm
, elem
);
6256 for (i
= 0; i
< (full
? 8 : 4); i
++)
6257 aarch64_set_vec_u32 (cpu
, vd
, i
,
6258 aarch64_get_vec_u32 (cpu
, vd
, i
) -
6259 (aarch64_get_vec_u32 (cpu
, vs
, i
) * val
));
6265 unsigned elem
= (INSTR (21, 21) << 1) | INSTR (11, 11);
6266 uint64_t val
= aarch64_get_vec_u32 (cpu
, vm
, elem
);
6268 for (i
= 0; i
< (full
? 4 : 2); i
++)
6269 aarch64_set_vec_u64 (cpu
, vd
, i
,
6270 aarch64_get_vec_u64 (cpu
, vd
, i
) -
6271 (aarch64_get_vec_u64 (cpu
, vs
, i
) * val
));
6283 do_vec_SUB (sim_cpu
*cpu
)
6286 instr [30] = half(0)/full(1)
6287 instr [29,24] = 10 1110
6288 instr [23,22] = size: byte(00, half(01), word (10), long (11)
6291 instr [15,10] = 10 0001
6293 instr [4, 0] = Vd. */
6295 unsigned full
= INSTR (30, 30);
6296 unsigned vm
= INSTR (20, 16);
6297 unsigned vn
= INSTR (9, 5);
6298 unsigned vd
= INSTR (4, 0);
6301 NYI_assert (29, 24, 0x2E);
6302 NYI_assert (21, 21, 1);
6303 NYI_assert (15, 10, 0x21);
6305 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
6306 switch (INSTR (23, 22))
6309 for (i
= 0; i
< (full
? 16 : 8); i
++)
6310 aarch64_set_vec_s8 (cpu
, vd
, i
,
6311 aarch64_get_vec_s8 (cpu
, vn
, i
)
6312 - aarch64_get_vec_s8 (cpu
, vm
, i
));
6316 for (i
= 0; i
< (full
? 8 : 4); i
++)
6317 aarch64_set_vec_s16 (cpu
, vd
, i
,
6318 aarch64_get_vec_s16 (cpu
, vn
, i
)
6319 - aarch64_get_vec_s16 (cpu
, vm
, i
));
6323 for (i
= 0; i
< (full
? 4 : 2); i
++)
6324 aarch64_set_vec_s32 (cpu
, vd
, i
,
6325 aarch64_get_vec_s32 (cpu
, vn
, i
)
6326 - aarch64_get_vec_s32 (cpu
, vm
, i
));
6333 for (i
= 0; i
< 2; i
++)
6334 aarch64_set_vec_s64 (cpu
, vd
, i
,
6335 aarch64_get_vec_s64 (cpu
, vn
, i
)
6336 - aarch64_get_vec_s64 (cpu
, vm
, i
));
6342 do_vec_MLS (sim_cpu
*cpu
)
6345 instr [30] = half(0)/full(1)
6346 instr [29,24] = 10 1110
6347 instr [23,22] = size: byte(00, half(01), word (10)
6350 instr [15,10] = 10 0101
6352 instr [4, 0] = Vd. */
6354 unsigned full
= INSTR (30, 30);
6355 unsigned vm
= INSTR (20, 16);
6356 unsigned vn
= INSTR (9, 5);
6357 unsigned vd
= INSTR (4, 0);
6360 NYI_assert (29, 24, 0x2E);
6361 NYI_assert (21, 21, 1);
6362 NYI_assert (15, 10, 0x25);
6364 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
6365 switch (INSTR (23, 22))
6368 for (i
= 0; i
< (full
? 16 : 8); i
++)
6369 aarch64_set_vec_u8 (cpu
, vd
, i
,
6370 aarch64_get_vec_u8 (cpu
, vd
, i
)
6371 - (aarch64_get_vec_u8 (cpu
, vn
, i
)
6372 * aarch64_get_vec_u8 (cpu
, vm
, i
)));
6376 for (i
= 0; i
< (full
? 8 : 4); i
++)
6377 aarch64_set_vec_u16 (cpu
, vd
, i
,
6378 aarch64_get_vec_u16 (cpu
, vd
, i
)
6379 - (aarch64_get_vec_u16 (cpu
, vn
, i
)
6380 * aarch64_get_vec_u16 (cpu
, vm
, i
)));
6384 for (i
= 0; i
< (full
? 4 : 2); i
++)
6385 aarch64_set_vec_u32 (cpu
, vd
, i
,
6386 aarch64_get_vec_u32 (cpu
, vd
, i
)
6387 - (aarch64_get_vec_u32 (cpu
, vn
, i
)
6388 * aarch64_get_vec_u32 (cpu
, vm
, i
)));
6397 do_vec_FDIV (sim_cpu
*cpu
)
6400 instr [30] = half(0)/full(1)
6401 instr [29,23] = 10 1110 0
6402 instr [22] = float()/double(1)
6405 instr [15,10] = 1111 11
6407 instr [4, 0] = Vd. */
6409 unsigned full
= INSTR (30, 30);
6410 unsigned vm
= INSTR (20, 16);
6411 unsigned vn
= INSTR (9, 5);
6412 unsigned vd
= INSTR (4, 0);
6415 NYI_assert (29, 23, 0x5C);
6416 NYI_assert (21, 21, 1);
6417 NYI_assert (15, 10, 0x3F);
6419 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
6425 for (i
= 0; i
< 2; i
++)
6426 aarch64_set_vec_double (cpu
, vd
, i
,
6427 aarch64_get_vec_double (cpu
, vn
, i
)
6428 / aarch64_get_vec_double (cpu
, vm
, i
));
6431 for (i
= 0; i
< (full
? 4 : 2); i
++)
6432 aarch64_set_vec_float (cpu
, vd
, i
,
6433 aarch64_get_vec_float (cpu
, vn
, i
)
6434 / aarch64_get_vec_float (cpu
, vm
, i
));
6438 do_vec_FMUL (sim_cpu
*cpu
)
6441 instr [30] = half(0)/full(1)
6442 instr [29,23] = 10 1110 0
6443 instr [22] = float(0)/double(1)
6446 instr [15,10] = 1101 11
6448 instr [4, 0] = Vd. */
6450 unsigned full
= INSTR (30, 30);
6451 unsigned vm
= INSTR (20, 16);
6452 unsigned vn
= INSTR (9, 5);
6453 unsigned vd
= INSTR (4, 0);
6456 NYI_assert (29, 23, 0x5C);
6457 NYI_assert (21, 21, 1);
6458 NYI_assert (15, 10, 0x37);
6460 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
6466 for (i
= 0; i
< 2; i
++)
6467 aarch64_set_vec_double (cpu
, vd
, i
,
6468 aarch64_get_vec_double (cpu
, vn
, i
)
6469 * aarch64_get_vec_double (cpu
, vm
, i
));
6472 for (i
= 0; i
< (full
? 4 : 2); i
++)
6473 aarch64_set_vec_float (cpu
, vd
, i
,
6474 aarch64_get_vec_float (cpu
, vn
, i
)
6475 * aarch64_get_vec_float (cpu
, vm
, i
));
6479 do_vec_FADDP (sim_cpu
*cpu
)
6482 instr [30] = half(0)/full(1)
6483 instr [29,23] = 10 1110 0
6484 instr [22] = float(0)/double(1)
6487 instr [15,10] = 1101 01
6489 instr [4, 0] = Vd. */
6491 unsigned full
= INSTR (30, 30);
6492 unsigned vm
= INSTR (20, 16);
6493 unsigned vn
= INSTR (9, 5);
6494 unsigned vd
= INSTR (4, 0);
6496 NYI_assert (29, 23, 0x5C);
6497 NYI_assert (21, 21, 1);
6498 NYI_assert (15, 10, 0x35);
6500 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
6503 /* Extract values before adding them incase vd == vn/vm. */
6504 double tmp1
= aarch64_get_vec_double (cpu
, vn
, 0);
6505 double tmp2
= aarch64_get_vec_double (cpu
, vn
, 1);
6506 double tmp3
= aarch64_get_vec_double (cpu
, vm
, 0);
6507 double tmp4
= aarch64_get_vec_double (cpu
, vm
, 1);
6512 aarch64_set_vec_double (cpu
, vd
, 0, tmp1
+ tmp2
);
6513 aarch64_set_vec_double (cpu
, vd
, 1, tmp3
+ tmp4
);
6517 /* Extract values before adding them incase vd == vn/vm. */
6518 float tmp1
= aarch64_get_vec_float (cpu
, vn
, 0);
6519 float tmp2
= aarch64_get_vec_float (cpu
, vn
, 1);
6520 float tmp5
= aarch64_get_vec_float (cpu
, vm
, 0);
6521 float tmp6
= aarch64_get_vec_float (cpu
, vm
, 1);
6525 float tmp3
= aarch64_get_vec_float (cpu
, vn
, 2);
6526 float tmp4
= aarch64_get_vec_float (cpu
, vn
, 3);
6527 float tmp7
= aarch64_get_vec_float (cpu
, vm
, 2);
6528 float tmp8
= aarch64_get_vec_float (cpu
, vm
, 3);
6530 aarch64_set_vec_float (cpu
, vd
, 0, tmp1
+ tmp2
);
6531 aarch64_set_vec_float (cpu
, vd
, 1, tmp3
+ tmp4
);
6532 aarch64_set_vec_float (cpu
, vd
, 2, tmp5
+ tmp6
);
6533 aarch64_set_vec_float (cpu
, vd
, 3, tmp7
+ tmp8
);
6537 aarch64_set_vec_float (cpu
, vd
, 0, tmp1
+ tmp2
);
6538 aarch64_set_vec_float (cpu
, vd
, 1, tmp5
+ tmp6
);
6544 do_vec_FSQRT (sim_cpu
*cpu
)
6547 instr[30] = half(0)/full(1)
6548 instr[29,23] = 10 1110 1
6549 instr[22] = single(0)/double(1)
6550 instr[21,10] = 10 0001 1111 10
6552 instr[4,0] = Vdest. */
6554 unsigned vn
= INSTR (9, 5);
6555 unsigned vd
= INSTR (4, 0);
6556 unsigned full
= INSTR (30, 30);
6559 NYI_assert (29, 23, 0x5D);
6560 NYI_assert (21, 10, 0x87E);
6562 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
6568 for (i
= 0; i
< 2; i
++)
6569 aarch64_set_vec_double (cpu
, vd
, i
,
6570 sqrt (aarch64_get_vec_double (cpu
, vn
, i
)));
6574 for (i
= 0; i
< (full
? 4 : 2); i
++)
6575 aarch64_set_vec_float (cpu
, vd
, i
,
6576 sqrtf (aarch64_get_vec_float (cpu
, vn
, i
)));
6581 do_vec_FNEG (sim_cpu
*cpu
)
6584 instr[30] = half (0)/full (1)
6585 instr[29,23] = 10 1110 1
6586 instr[22] = single (0)/double (1)
6587 instr[21,10] = 10 0000 1111 10
6589 instr[4,0] = Vdest. */
6591 unsigned vn
= INSTR (9, 5);
6592 unsigned vd
= INSTR (4, 0);
6593 unsigned full
= INSTR (30, 30);
6596 NYI_assert (29, 23, 0x5D);
6597 NYI_assert (21, 10, 0x83E);
6599 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
6605 for (i
= 0; i
< 2; i
++)
6606 aarch64_set_vec_double (cpu
, vd
, i
,
6607 - aarch64_get_vec_double (cpu
, vn
, i
));
6611 for (i
= 0; i
< (full
? 4 : 2); i
++)
6612 aarch64_set_vec_float (cpu
, vd
, i
,
6613 - aarch64_get_vec_float (cpu
, vn
, i
));
6618 do_vec_NOT (sim_cpu
*cpu
)
6621 instr[30] = half (0)/full (1)
6622 instr[29,10] = 10 1110 0010 0000 0101 10
6626 unsigned vn
= INSTR (9, 5);
6627 unsigned vd
= INSTR (4, 0);
6629 int full
= INSTR (30, 30);
6631 NYI_assert (29, 10, 0xB8816);
6633 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
6634 for (i
= 0; i
< (full
? 16 : 8); i
++)
6635 aarch64_set_vec_u8 (cpu
, vd
, i
, ~ aarch64_get_vec_u8 (cpu
, vn
, i
));
6639 clz (uint64_t val
, unsigned size
)
6644 mask
<<= (size
- 1);
6659 do_vec_CLZ (sim_cpu
*cpu
)
6662 instr[30] = half (0)/full (1)
6663 instr[29,24] = 10 1110
6665 instr[21,10] = 10 0000 0100 10
6669 unsigned vn
= INSTR (9, 5);
6670 unsigned vd
= INSTR (4, 0);
6672 int full
= INSTR (30,30);
6674 NYI_assert (29, 24, 0x2E);
6675 NYI_assert (21, 10, 0x812);
6677 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
6678 switch (INSTR (23, 22))
6681 for (i
= 0; i
< (full
? 16 : 8); i
++)
6682 aarch64_set_vec_u8 (cpu
, vd
, i
, clz (aarch64_get_vec_u8 (cpu
, vn
, i
), 8));
6685 for (i
= 0; i
< (full
? 8 : 4); i
++)
6686 aarch64_set_vec_u16 (cpu
, vd
, i
, clz (aarch64_get_vec_u16 (cpu
, vn
, i
), 16));
6689 for (i
= 0; i
< (full
? 4 : 2); i
++)
6690 aarch64_set_vec_u32 (cpu
, vd
, i
, clz (aarch64_get_vec_u32 (cpu
, vn
, i
), 32));
6695 aarch64_set_vec_u64 (cpu
, vd
, 0, clz (aarch64_get_vec_u64 (cpu
, vn
, 0), 64));
6696 aarch64_set_vec_u64 (cpu
, vd
, 1, clz (aarch64_get_vec_u64 (cpu
, vn
, 1), 64));
6702 do_vec_MOV_element (sim_cpu
*cpu
)
6704 /* instr[31,21] = 0110 1110 000
6705 instr[20,16] = size & dest index
6707 instr[14,11] = source index
6712 unsigned vs
= INSTR (9, 5);
6713 unsigned vd
= INSTR (4, 0);
6717 NYI_assert (31, 21, 0x370);
6718 NYI_assert (15, 15, 0);
6719 NYI_assert (10, 10, 1);
6721 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
6725 src_index
= INSTR (14, 11);
6726 dst_index
= INSTR (20, 17);
6727 aarch64_set_vec_u8 (cpu
, vd
, dst_index
,
6728 aarch64_get_vec_u8 (cpu
, vs
, src_index
));
6730 else if (INSTR (17, 17))
6733 NYI_assert (11, 11, 0);
6734 src_index
= INSTR (14, 12);
6735 dst_index
= INSTR (20, 18);
6736 aarch64_set_vec_u16 (cpu
, vd
, dst_index
,
6737 aarch64_get_vec_u16 (cpu
, vs
, src_index
));
6739 else if (INSTR (18, 18))
6742 NYI_assert (12, 11, 0);
6743 src_index
= INSTR (14, 13);
6744 dst_index
= INSTR (20, 19);
6745 aarch64_set_vec_u32 (cpu
, vd
, dst_index
,
6746 aarch64_get_vec_u32 (cpu
, vs
, src_index
));
6750 NYI_assert (19, 19, 1);
6751 NYI_assert (13, 11, 0);
6752 src_index
= INSTR (14, 14);
6753 dst_index
= INSTR (20, 20);
6754 aarch64_set_vec_u64 (cpu
, vd
, dst_index
,
6755 aarch64_get_vec_u64 (cpu
, vs
, src_index
));
6760 do_vec_REV32 (sim_cpu
*cpu
)
6763 instr[30] = full/half
6764 instr[29,24] = 10 1110
6766 instr[21,10] = 10 0000 0000 10
6770 unsigned rn
= INSTR (9, 5);
6771 unsigned rd
= INSTR (4, 0);
6772 unsigned size
= INSTR (23, 22);
6773 unsigned full
= INSTR (30, 30);
6777 NYI_assert (29, 24, 0x2E);
6778 NYI_assert (21, 10, 0x802);
6780 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
6784 for (i
= 0; i
< (full
? 16 : 8); i
++)
6785 val
.b
[i
^ 0x3] = aarch64_get_vec_u8 (cpu
, rn
, i
);
6789 for (i
= 0; i
< (full
? 8 : 4); i
++)
6790 val
.h
[i
^ 0x1] = aarch64_get_vec_u16 (cpu
, rn
, i
);
6797 aarch64_set_vec_u64 (cpu
, rd
, 0, val
.v
[0]);
6799 aarch64_set_vec_u64 (cpu
, rd
, 1, val
.v
[1]);
6803 do_vec_EXT (sim_cpu
*cpu
)
6806 instr[30] = full/half
6807 instr[29,21] = 10 1110 000
6810 instr[14,11] = source index
6815 unsigned vm
= INSTR (20, 16);
6816 unsigned vn
= INSTR (9, 5);
6817 unsigned vd
= INSTR (4, 0);
6818 unsigned src_index
= INSTR (14, 11);
6819 unsigned full
= INSTR (30, 30);
6824 NYI_assert (31, 21, 0x370);
6825 NYI_assert (15, 15, 0);
6826 NYI_assert (10, 10, 0);
6828 if (!full
&& (src_index
& 0x8))
6833 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
6834 for (i
= src_index
; i
< (full
? 16 : 8); i
++)
6835 val
.b
[j
++] = aarch64_get_vec_u8 (cpu
, vn
, i
);
6836 for (i
= 0; i
< src_index
; i
++)
6837 val
.b
[j
++] = aarch64_get_vec_u8 (cpu
, vm
, i
);
6839 aarch64_set_vec_u64 (cpu
, vd
, 0, val
.v
[0]);
6841 aarch64_set_vec_u64 (cpu
, vd
, 1, val
.v
[1]);
6845 dexAdvSIMD0 (sim_cpu
*cpu
)
6847 /* instr [28,25] = 0 111. */
6848 if ( INSTR (15, 10) == 0x07
6852 if (INSTR (31, 21) == 0x075
6853 || INSTR (31, 21) == 0x275)
6855 do_vec_MOV_whole_vector (cpu
);
6860 if (INSTR (29, 19) == 0x1E0)
6862 do_vec_MOV_immediate (cpu
);
6866 if (INSTR (29, 19) == 0x5E0)
6872 if (INSTR (29, 19) == 0x1C0
6873 || INSTR (29, 19) == 0x1C1)
6875 if (INSTR (15, 10) == 0x03)
6877 do_vec_DUP_scalar_into_vector (cpu
);
6882 switch (INSTR (29, 24))
6884 case 0x0E: do_vec_op1 (cpu
); return;
6885 case 0x0F: do_vec_op2 (cpu
); return;
6888 if (INSTR (21, 21) == 1)
6890 switch (INSTR (15, 10))
6897 switch (INSTR (23, 22))
6899 case 0: do_vec_EOR (cpu
); return;
6900 case 1: do_vec_BSL (cpu
); return;
6902 case 3: do_vec_bit (cpu
); return;
6906 case 0x08: do_vec_sub_long (cpu
); return;
6907 case 0x11: do_vec_USHL (cpu
); return;
6908 case 0x12: do_vec_CLZ (cpu
); return;
6909 case 0x16: do_vec_NOT (cpu
); return;
6910 case 0x19: do_vec_max (cpu
); return;
6911 case 0x1B: do_vec_min (cpu
); return;
6912 case 0x21: do_vec_SUB (cpu
); return;
6913 case 0x25: do_vec_MLS (cpu
); return;
6914 case 0x31: do_vec_FminmaxNMP (cpu
); return;
6915 case 0x35: do_vec_FADDP (cpu
); return;
6916 case 0x37: do_vec_FMUL (cpu
); return;
6917 case 0x3F: do_vec_FDIV (cpu
); return;
6920 switch (INSTR (20, 16))
6922 case 0x00: do_vec_FNEG (cpu
); return;
6923 case 0x01: do_vec_FSQRT (cpu
); return;
6937 do_vec_compare (cpu
); return;
6944 if (INSTR (31, 21) == 0x370)
6947 do_vec_MOV_element (cpu
);
6953 switch (INSTR (21, 10))
6955 case 0x82E: do_vec_neg (cpu
); return;
6956 case 0x87E: do_vec_sqrt (cpu
); return;
6958 if (INSTR (15, 10) == 0x30)
6968 switch (INSTR (15, 10))
6970 case 0x01: do_vec_SSHR_USHR (cpu
); return;
6972 case 0x12: do_vec_mls_indexed (cpu
); return;
6973 case 0x29: do_vec_xtl (cpu
); return;
6987 /* Float multiply add. */
6989 fmadds (sim_cpu
*cpu
)
6991 unsigned sa
= INSTR (14, 10);
6992 unsigned sm
= INSTR (20, 16);
6993 unsigned sn
= INSTR ( 9, 5);
6994 unsigned sd
= INSTR ( 4, 0);
6996 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
6997 aarch64_set_FP_float (cpu
, sd
, aarch64_get_FP_float (cpu
, sa
)
6998 + aarch64_get_FP_float (cpu
, sn
)
6999 * aarch64_get_FP_float (cpu
, sm
));
7002 /* Double multiply add. */
7004 fmaddd (sim_cpu
*cpu
)
7006 unsigned sa
= INSTR (14, 10);
7007 unsigned sm
= INSTR (20, 16);
7008 unsigned sn
= INSTR ( 9, 5);
7009 unsigned sd
= INSTR ( 4, 0);
7011 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
7012 aarch64_set_FP_double (cpu
, sd
, aarch64_get_FP_double (cpu
, sa
)
7013 + aarch64_get_FP_double (cpu
, sn
)
7014 * aarch64_get_FP_double (cpu
, sm
));
7017 /* Float multiply subtract. */
7019 fmsubs (sim_cpu
*cpu
)
7021 unsigned sa
= INSTR (14, 10);
7022 unsigned sm
= INSTR (20, 16);
7023 unsigned sn
= INSTR ( 9, 5);
7024 unsigned sd
= INSTR ( 4, 0);
7026 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
7027 aarch64_set_FP_float (cpu
, sd
, aarch64_get_FP_float (cpu
, sa
)
7028 - aarch64_get_FP_float (cpu
, sn
)
7029 * aarch64_get_FP_float (cpu
, sm
));
7032 /* Double multiply subtract. */
7034 fmsubd (sim_cpu
*cpu
)
7036 unsigned sa
= INSTR (14, 10);
7037 unsigned sm
= INSTR (20, 16);
7038 unsigned sn
= INSTR ( 9, 5);
7039 unsigned sd
= INSTR ( 4, 0);
7041 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
7042 aarch64_set_FP_double (cpu
, sd
, aarch64_get_FP_double (cpu
, sa
)
7043 - aarch64_get_FP_double (cpu
, sn
)
7044 * aarch64_get_FP_double (cpu
, sm
));
7047 /* Float negative multiply add. */
7049 fnmadds (sim_cpu
*cpu
)
7051 unsigned sa
= INSTR (14, 10);
7052 unsigned sm
= INSTR (20, 16);
7053 unsigned sn
= INSTR ( 9, 5);
7054 unsigned sd
= INSTR ( 4, 0);
7056 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
7057 aarch64_set_FP_float (cpu
, sd
, - aarch64_get_FP_float (cpu
, sa
)
7058 + (- aarch64_get_FP_float (cpu
, sn
))
7059 * aarch64_get_FP_float (cpu
, sm
));
7062 /* Double negative multiply add. */
7064 fnmaddd (sim_cpu
*cpu
)
7066 unsigned sa
= INSTR (14, 10);
7067 unsigned sm
= INSTR (20, 16);
7068 unsigned sn
= INSTR ( 9, 5);
7069 unsigned sd
= INSTR ( 4, 0);
7071 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
7072 aarch64_set_FP_double (cpu
, sd
, - aarch64_get_FP_double (cpu
, sa
)
7073 + (- aarch64_get_FP_double (cpu
, sn
))
7074 * aarch64_get_FP_double (cpu
, sm
));
7077 /* Float negative multiply subtract. */
7079 fnmsubs (sim_cpu
*cpu
)
7081 unsigned sa
= INSTR (14, 10);
7082 unsigned sm
= INSTR (20, 16);
7083 unsigned sn
= INSTR ( 9, 5);
7084 unsigned sd
= INSTR ( 4, 0);
7086 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
7087 aarch64_set_FP_float (cpu
, sd
, - aarch64_get_FP_float (cpu
, sa
)
7088 + aarch64_get_FP_float (cpu
, sn
)
7089 * aarch64_get_FP_float (cpu
, sm
));
7092 /* Double negative multiply subtract. */
7094 fnmsubd (sim_cpu
*cpu
)
7096 unsigned sa
= INSTR (14, 10);
7097 unsigned sm
= INSTR (20, 16);
7098 unsigned sn
= INSTR ( 9, 5);
7099 unsigned sd
= INSTR ( 4, 0);
7101 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
7102 aarch64_set_FP_double (cpu
, sd
, - aarch64_get_FP_double (cpu
, sa
)
7103 + aarch64_get_FP_double (cpu
, sn
)
7104 * aarch64_get_FP_double (cpu
, sm
));
7108 dexSimpleFPDataProc3Source (sim_cpu
*cpu
)
7110 /* instr[31] ==> M : 0 ==> OK, 1 ==> UNALLOC
7112 instr[29] ==> S : 0 ==> OK, 1 ==> UNALLOC
7115 instr[23,22] ==> type : 0 ==> single, 01 ==> double, 1x ==> UNALLOC
7116 instr[21] ==> o1 : 0 ==> unnegated, 1 ==> negated
7117 instr[15] ==> o2 : 0 ==> ADD, 1 ==> SUB */
7119 uint32_t M_S
= (INSTR (31, 31) << 1) | INSTR (29, 29);
7120 /* dispatch on combined type:o1:o2. */
7121 uint32_t dispatch
= (INSTR (23, 21) << 1) | INSTR (15, 15);
7128 case 0: fmadds (cpu
); return;
7129 case 1: fmsubs (cpu
); return;
7130 case 2: fnmadds (cpu
); return;
7131 case 3: fnmsubs (cpu
); return;
7132 case 4: fmaddd (cpu
); return;
7133 case 5: fmsubd (cpu
); return;
7134 case 6: fnmaddd (cpu
); return;
7135 case 7: fnmsubd (cpu
); return;
7137 /* type > 1 is currently unallocated. */
7143 dexSimpleFPFixedConvert (sim_cpu
*cpu
)
7149 dexSimpleFPCondCompare (sim_cpu
*cpu
)
7151 /* instr [31,23] = 0001 1110 0
7155 instr [15,12] = condition
7159 instr [3,0] = nzcv */
7161 unsigned rm
= INSTR (20, 16);
7162 unsigned rn
= INSTR (9, 5);
7164 NYI_assert (31, 23, 0x3C);
7165 NYI_assert (11, 10, 0x1);
7166 NYI_assert (4, 4, 0);
7168 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
7169 if (! testConditionCode (cpu
, INSTR (15, 12)))
7171 aarch64_set_CPSR (cpu
, INSTR (3, 0));
7177 /* Double precision. */
7178 double val1
= aarch64_get_vec_double (cpu
, rn
, 0);
7179 double val2
= aarch64_get_vec_double (cpu
, rm
, 0);
7181 /* FIXME: Check for NaNs. */
7183 aarch64_set_CPSR (cpu
, (Z
| C
));
7184 else if (val1
< val2
)
7185 aarch64_set_CPSR (cpu
, N
);
7186 else /* val1 > val2 */
7187 aarch64_set_CPSR (cpu
, C
);
7191 /* Single precision. */
7192 float val1
= aarch64_get_vec_float (cpu
, rn
, 0);
7193 float val2
= aarch64_get_vec_float (cpu
, rm
, 0);
7195 /* FIXME: Check for NaNs. */
7197 aarch64_set_CPSR (cpu
, (Z
| C
));
7198 else if (val1
< val2
)
7199 aarch64_set_CPSR (cpu
, N
);
7200 else /* val1 > val2 */
7201 aarch64_set_CPSR (cpu
, C
);
7209 fadds (sim_cpu
*cpu
)
7211 unsigned sm
= INSTR (20, 16);
7212 unsigned sn
= INSTR ( 9, 5);
7213 unsigned sd
= INSTR ( 4, 0);
7215 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
7216 aarch64_set_FP_float (cpu
, sd
, aarch64_get_FP_float (cpu
, sn
)
7217 + aarch64_get_FP_float (cpu
, sm
));
7222 faddd (sim_cpu
*cpu
)
7224 unsigned sm
= INSTR (20, 16);
7225 unsigned sn
= INSTR ( 9, 5);
7226 unsigned sd
= INSTR ( 4, 0);
7228 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
7229 aarch64_set_FP_double (cpu
, sd
, aarch64_get_FP_double (cpu
, sn
)
7230 + aarch64_get_FP_double (cpu
, sm
));
7235 fdivs (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
));
7246 /* Double divide. */
7248 fdivd (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
));
7259 /* Float multiply. */
7261 fmuls (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 multiply. */
7274 fmuld (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 negate and multiply. */
7287 fnmuls (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 negate and multiply. */
7300 fnmuld (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 subtract. */
7313 fsubs (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 subtract. */
7326 fsubd (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
));
7338 do_FMINNM (sim_cpu
*cpu
)
7340 /* instr[31,23] = 0 0011 1100
7341 instr[22] = float(0)/double(1)
7344 instr[15,10] = 01 1110
7348 unsigned sm
= INSTR (20, 16);
7349 unsigned sn
= INSTR ( 9, 5);
7350 unsigned sd
= INSTR ( 4, 0);
7352 NYI_assert (31, 23, 0x03C);
7353 NYI_assert (15, 10, 0x1E);
7355 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
7357 aarch64_set_FP_double (cpu
, sd
,
7358 dminnm (aarch64_get_FP_double (cpu
, sn
),
7359 aarch64_get_FP_double (cpu
, sm
)));
7361 aarch64_set_FP_float (cpu
, sd
,
7362 fminnm (aarch64_get_FP_float (cpu
, sn
),
7363 aarch64_get_FP_float (cpu
, sm
)));
7367 do_FMAXNM (sim_cpu
*cpu
)
7369 /* instr[31,23] = 0 0011 1100
7370 instr[22] = float(0)/double(1)
7373 instr[15,10] = 01 1010
7377 unsigned sm
= INSTR (20, 16);
7378 unsigned sn
= INSTR ( 9, 5);
7379 unsigned sd
= INSTR ( 4, 0);
7381 NYI_assert (31, 23, 0x03C);
7382 NYI_assert (15, 10, 0x1A);
7384 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
7386 aarch64_set_FP_double (cpu
, sd
,
7387 dmaxnm (aarch64_get_FP_double (cpu
, sn
),
7388 aarch64_get_FP_double (cpu
, sm
)));
7390 aarch64_set_FP_float (cpu
, sd
,
7391 fmaxnm (aarch64_get_FP_float (cpu
, sn
),
7392 aarch64_get_FP_float (cpu
, sm
)));
7396 dexSimpleFPDataProc2Source (sim_cpu
*cpu
)
7398 /* instr[31] ==> M : 0 ==> OK, 1 ==> UNALLOC
7400 instr[29] ==> S : 0 ==> OK, 1 ==> UNALLOC
7403 instr[23,22] ==> type : 0 ==> single, 01 ==> double, 1x ==> UNALLOC
7406 instr[15,12] ==> opcode : 0000 ==> FMUL, 0001 ==> FDIV
7407 0010 ==> FADD, 0011 ==> FSUB,
7408 0100 ==> FMAX, 0101 ==> FMIN
7409 0110 ==> FMAXNM, 0111 ==> FMINNM
7410 1000 ==> FNMUL, ow ==> UNALLOC
7415 uint32_t M_S
= (INSTR (31, 31) << 1) | INSTR (29, 29);
7416 uint32_t type
= INSTR (23, 22);
7417 /* Dispatch on opcode. */
7418 uint32_t dispatch
= INSTR (15, 12);
7429 case 0: fmuld (cpu
); return;
7430 case 1: fdivd (cpu
); return;
7431 case 2: faddd (cpu
); return;
7432 case 3: fsubd (cpu
); return;
7433 case 6: do_FMAXNM (cpu
); return;
7434 case 7: do_FMINNM (cpu
); return;
7435 case 8: fnmuld (cpu
); return;
7437 /* Have not yet implemented fmax and fmin. */
7445 else /* type == 0 => floats. */
7448 case 0: fmuls (cpu
); return;
7449 case 1: fdivs (cpu
); return;
7450 case 2: fadds (cpu
); return;
7451 case 3: fsubs (cpu
); return;
7452 case 6: do_FMAXNM (cpu
); return;
7453 case 7: do_FMINNM (cpu
); return;
7454 case 8: fnmuls (cpu
); return;
7466 dexSimpleFPCondSelect (sim_cpu
*cpu
)
7469 instr[31,23] = 0 0011 1100
7470 instr[22] = 0=>single 1=>double
7477 unsigned sm
= INSTR (20, 16);
7478 unsigned sn
= INSTR ( 9, 5);
7479 unsigned sd
= INSTR ( 4, 0);
7480 uint32_t set
= testConditionCode (cpu
, INSTR (15, 12));
7482 NYI_assert (31, 23, 0x03C);
7483 NYI_assert (11, 10, 0x3);
7485 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
7487 aarch64_set_FP_double (cpu
, sd
, (set
? aarch64_get_FP_double (cpu
, sn
)
7488 : aarch64_get_FP_double (cpu
, sm
)));
7490 aarch64_set_FP_float (cpu
, sd
, (set
? aarch64_get_FP_float (cpu
, sn
)
7491 : aarch64_get_FP_float (cpu
, sm
)));
7494 /* Store 32 bit unscaled signed 9 bit. */
7496 fsturs (sim_cpu
*cpu
, int32_t offset
)
7498 unsigned int rn
= INSTR (9, 5);
7499 unsigned int st
= INSTR (4, 0);
7501 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
7502 aarch64_set_mem_u32 (cpu
, aarch64_get_reg_u64 (cpu
, rn
, 1) + offset
,
7503 aarch64_get_vec_u32 (cpu
, st
, 0));
7506 /* Store 64 bit unscaled signed 9 bit. */
7508 fsturd (sim_cpu
*cpu
, int32_t offset
)
7510 unsigned int rn
= INSTR (9, 5);
7511 unsigned int st
= INSTR (4, 0);
7513 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
7514 aarch64_set_mem_u64 (cpu
, aarch64_get_reg_u64 (cpu
, rn
, 1) + offset
,
7515 aarch64_get_vec_u64 (cpu
, st
, 0));
7518 /* Store 128 bit unscaled signed 9 bit. */
7520 fsturq (sim_cpu
*cpu
, int32_t offset
)
7522 unsigned int rn
= INSTR (9, 5);
7523 unsigned int st
= INSTR (4, 0);
7526 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
7527 aarch64_get_FP_long_double (cpu
, st
, & a
);
7528 aarch64_set_mem_long_double (cpu
,
7529 aarch64_get_reg_u64 (cpu
, rn
, 1)
7533 /* TODO FP move register. */
7535 /* 32 bit fp to fp move register. */
7537 ffmovs (sim_cpu
*cpu
)
7539 unsigned int rn
= INSTR (9, 5);
7540 unsigned int st
= INSTR (4, 0);
7542 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
7543 aarch64_set_FP_float (cpu
, st
, aarch64_get_FP_float (cpu
, rn
));
7546 /* 64 bit fp to fp move register. */
7548 ffmovd (sim_cpu
*cpu
)
7550 unsigned int rn
= INSTR (9, 5);
7551 unsigned int st
= INSTR (4, 0);
7553 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
7554 aarch64_set_FP_double (cpu
, st
, aarch64_get_FP_double (cpu
, rn
));
7557 /* 32 bit GReg to Vec move register. */
7559 fgmovs (sim_cpu
*cpu
)
7561 unsigned int rn
= INSTR (9, 5);
7562 unsigned int st
= INSTR (4, 0);
7564 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
7565 aarch64_set_vec_u32 (cpu
, st
, 0, aarch64_get_reg_u32 (cpu
, rn
, NO_SP
));
7568 /* 64 bit g to fp move register. */
7570 fgmovd (sim_cpu
*cpu
)
7572 unsigned int rn
= INSTR (9, 5);
7573 unsigned int st
= INSTR (4, 0);
7575 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
7576 aarch64_set_vec_u64 (cpu
, st
, 0, aarch64_get_reg_u64 (cpu
, rn
, NO_SP
));
7579 /* 32 bit fp to g move register. */
7581 gfmovs (sim_cpu
*cpu
)
7583 unsigned int rn
= INSTR (9, 5);
7584 unsigned int st
= INSTR (4, 0);
7586 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
7587 aarch64_set_reg_u64 (cpu
, st
, NO_SP
, aarch64_get_vec_u32 (cpu
, rn
, 0));
7590 /* 64 bit fp to g move register. */
7592 gfmovd (sim_cpu
*cpu
)
7594 unsigned int rn
= INSTR (9, 5);
7595 unsigned int st
= INSTR (4, 0);
7597 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
7598 aarch64_set_reg_u64 (cpu
, st
, NO_SP
, aarch64_get_vec_u64 (cpu
, rn
, 0));
7601 /* FP move immediate
7603 These install an immediate 8 bit value in the target register
7604 where the 8 bits comprise 1 sign bit, 4 bits of fraction and a 3
7608 fmovs (sim_cpu
*cpu
)
7610 unsigned int sd
= INSTR (4, 0);
7611 uint32_t imm
= INSTR (20, 13);
7612 float f
= fp_immediate_for_encoding_32 (imm
);
7614 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
7615 aarch64_set_FP_float (cpu
, sd
, f
);
7619 fmovd (sim_cpu
*cpu
)
7621 unsigned int sd
= INSTR (4, 0);
7622 uint32_t imm
= INSTR (20, 13);
7623 double d
= fp_immediate_for_encoding_64 (imm
);
7625 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
7626 aarch64_set_FP_double (cpu
, sd
, d
);
7630 dexSimpleFPImmediate (sim_cpu
*cpu
)
7632 /* instr[31,23] == 00111100
7633 instr[22] == type : single(0)/double(1)
7635 instr[20,13] == imm8
7637 instr[9,5] == imm5 : 00000 ==> PK, ow ==> UNALLOC
7639 uint32_t imm5
= INSTR (9, 5);
7641 NYI_assert (31, 23, 0x3C);
7652 /* TODO specific decode and execute for group Load Store. */
7654 /* TODO FP load/store single register (unscaled offset). */
7656 /* TODO load 8 bit unscaled signed 9 bit. */
7657 /* TODO load 16 bit unscaled signed 9 bit. */
7659 /* Load 32 bit unscaled signed 9 bit. */
7661 fldurs (sim_cpu
*cpu
, int32_t offset
)
7663 unsigned int rn
= INSTR (9, 5);
7664 unsigned int st
= INSTR (4, 0);
7666 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
7667 aarch64_set_vec_u32 (cpu
, st
, 0, aarch64_get_mem_u32
7668 (cpu
, aarch64_get_reg_u64 (cpu
, rn
, SP_OK
) + offset
));
7671 /* Load 64 bit unscaled signed 9 bit. */
7673 fldurd (sim_cpu
*cpu
, int32_t offset
)
7675 unsigned int rn
= INSTR (9, 5);
7676 unsigned int st
= INSTR (4, 0);
7678 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
7679 aarch64_set_vec_u64 (cpu
, st
, 0, aarch64_get_mem_u64
7680 (cpu
, aarch64_get_reg_u64 (cpu
, rn
, SP_OK
) + offset
));
7683 /* Load 128 bit unscaled signed 9 bit. */
7685 fldurq (sim_cpu
*cpu
, int32_t offset
)
7687 unsigned int rn
= INSTR (9, 5);
7688 unsigned int st
= INSTR (4, 0);
7690 uint64_t addr
= aarch64_get_reg_u64 (cpu
, rn
, SP_OK
) + offset
;
7692 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
7693 aarch64_get_mem_long_double (cpu
, addr
, & a
);
7694 aarch64_set_FP_long_double (cpu
, st
, a
);
7697 /* TODO store 8 bit unscaled signed 9 bit. */
7698 /* TODO store 16 bit unscaled signed 9 bit. */
7703 /* Float absolute value. */
7705 fabss (sim_cpu
*cpu
)
7707 unsigned sn
= INSTR (9, 5);
7708 unsigned sd
= INSTR (4, 0);
7709 float value
= aarch64_get_FP_float (cpu
, sn
);
7711 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
7712 aarch64_set_FP_float (cpu
, sd
, fabsf (value
));
7715 /* Double absolute value. */
7717 fabcpu (sim_cpu
*cpu
)
7719 unsigned sn
= INSTR (9, 5);
7720 unsigned sd
= INSTR (4, 0);
7721 double value
= aarch64_get_FP_double (cpu
, sn
);
7723 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
7724 aarch64_set_FP_double (cpu
, sd
, fabs (value
));
7727 /* Float negative value. */
7729 fnegs (sim_cpu
*cpu
)
7731 unsigned sn
= INSTR (9, 5);
7732 unsigned sd
= INSTR (4, 0);
7734 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
7735 aarch64_set_FP_float (cpu
, sd
, - aarch64_get_FP_float (cpu
, sn
));
7738 /* Double negative value. */
7740 fnegd (sim_cpu
*cpu
)
7742 unsigned sn
= INSTR (9, 5);
7743 unsigned sd
= INSTR (4, 0);
7745 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
7746 aarch64_set_FP_double (cpu
, sd
, - aarch64_get_FP_double (cpu
, sn
));
7749 /* Float square root. */
7751 fsqrts (sim_cpu
*cpu
)
7753 unsigned sn
= INSTR (9, 5);
7754 unsigned sd
= INSTR (4, 0);
7756 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
7757 aarch64_set_FP_float (cpu
, sd
, sqrtf (aarch64_get_FP_float (cpu
, sn
)));
7760 /* Double square root. */
7762 fsqrtd (sim_cpu
*cpu
)
7764 unsigned sn
= INSTR (9, 5);
7765 unsigned sd
= INSTR (4, 0);
7767 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
7768 aarch64_set_FP_double (cpu
, sd
,
7769 sqrt (aarch64_get_FP_double (cpu
, sn
)));
7772 /* Convert double to float. */
7774 fcvtds (sim_cpu
*cpu
)
7776 unsigned sn
= INSTR (9, 5);
7777 unsigned sd
= INSTR (4, 0);
7779 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
7780 aarch64_set_FP_float (cpu
, sd
, (float) aarch64_get_FP_double (cpu
, sn
));
7783 /* Convert float to double. */
7785 fcvtcpu (sim_cpu
*cpu
)
7787 unsigned sn
= INSTR (9, 5);
7788 unsigned sd
= INSTR (4, 0);
7790 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
7791 aarch64_set_FP_double (cpu
, sd
, (double) aarch64_get_FP_float (cpu
, sn
));
7795 do_FRINT (sim_cpu
*cpu
)
7797 /* instr[31,23] = 0001 1110 0
7798 instr[22] = single(0)/double(1)
7800 instr[17,15] = rounding mode
7801 instr[14,10] = 10000
7803 instr[4,0] = dest */
7806 unsigned rs
= INSTR (9, 5);
7807 unsigned rd
= INSTR (4, 0);
7808 unsigned int rmode
= INSTR (17, 15);
7810 NYI_assert (31, 23, 0x03C);
7811 NYI_assert (21, 18, 0x9);
7812 NYI_assert (14, 10, 0x10);
7814 if (rmode
== 6 || rmode
== 7)
7815 /* FIXME: Add support for rmode == 6 exactness check. */
7816 rmode
= uimm (aarch64_get_FPSR (cpu
), 23, 22);
7818 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
7821 double val
= aarch64_get_FP_double (cpu
, rs
);
7825 case 0: /* mode N: nearest or even. */
7827 double rval
= round (val
);
7829 if (val
- rval
== 0.5)
7831 if (((rval
/ 2.0) * 2.0) != rval
)
7835 aarch64_set_FP_double (cpu
, rd
, round (val
));
7839 case 1: /* mode P: towards +inf. */
7841 aarch64_set_FP_double (cpu
, rd
, trunc (val
));
7843 aarch64_set_FP_double (cpu
, rd
, round (val
));
7846 case 2: /* mode M: towards -inf. */
7848 aarch64_set_FP_double (cpu
, rd
, round (val
));
7850 aarch64_set_FP_double (cpu
, rd
, trunc (val
));
7853 case 3: /* mode Z: towards 0. */
7854 aarch64_set_FP_double (cpu
, rd
, trunc (val
));
7857 case 4: /* mode A: away from 0. */
7858 aarch64_set_FP_double (cpu
, rd
, round (val
));
7861 case 6: /* mode X: use FPCR with exactness check. */
7862 case 7: /* mode I: use FPCR mode. */
7870 val
= aarch64_get_FP_float (cpu
, rs
);
7874 case 0: /* mode N: nearest or even. */
7876 float rval
= roundf (val
);
7878 if (val
- rval
== 0.5)
7880 if (((rval
/ 2.0) * 2.0) != rval
)
7884 aarch64_set_FP_float (cpu
, rd
, rval
);
7888 case 1: /* mode P: towards +inf. */
7890 aarch64_set_FP_float (cpu
, rd
, truncf (val
));
7892 aarch64_set_FP_float (cpu
, rd
, roundf (val
));
7895 case 2: /* mode M: towards -inf. */
7897 aarch64_set_FP_float (cpu
, rd
, truncf (val
));
7899 aarch64_set_FP_float (cpu
, rd
, roundf (val
));
7902 case 3: /* mode Z: towards 0. */
7903 aarch64_set_FP_float (cpu
, rd
, truncf (val
));
7906 case 4: /* mode A: away from 0. */
7907 aarch64_set_FP_float (cpu
, rd
, roundf (val
));
7910 case 6: /* mode X: use FPCR with exactness check. */
7911 case 7: /* mode I: use FPCR mode. */
7919 /* Convert half to float. */
7921 do_FCVT_half_to_single (sim_cpu
*cpu
)
7923 unsigned rn
= INSTR (9, 5);
7924 unsigned rd
= INSTR (4, 0);
7926 NYI_assert (31, 10, 0x7B890);
7928 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
7929 aarch64_set_FP_float (cpu
, rd
, (float) aarch64_get_FP_half (cpu
, rn
));
7932 /* Convert half to double. */
7934 do_FCVT_half_to_double (sim_cpu
*cpu
)
7936 unsigned rn
= INSTR (9, 5);
7937 unsigned rd
= INSTR (4, 0);
7939 NYI_assert (31, 10, 0x7B8B0);
7941 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
7942 aarch64_set_FP_double (cpu
, rd
, (double) aarch64_get_FP_half (cpu
, rn
));
7946 do_FCVT_single_to_half (sim_cpu
*cpu
)
7948 unsigned rn
= INSTR (9, 5);
7949 unsigned rd
= INSTR (4, 0);
7951 NYI_assert (31, 10, 0x788F0);
7953 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
7954 aarch64_set_FP_half (cpu
, rd
, aarch64_get_FP_float (cpu
, rn
));
7957 /* Convert double to half. */
7959 do_FCVT_double_to_half (sim_cpu
*cpu
)
7961 unsigned rn
= INSTR (9, 5);
7962 unsigned rd
= INSTR (4, 0);
7964 NYI_assert (31, 10, 0x798F0);
7966 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
7967 aarch64_set_FP_half (cpu
, rd
, (float) aarch64_get_FP_double (cpu
, rn
));
7971 dexSimpleFPDataProc1Source (sim_cpu
*cpu
)
7973 /* instr[31] ==> M : 0 ==> OK, 1 ==> UNALLOC
7975 instr[29] ==> S : 0 ==> OK, 1 ==> UNALLOC
7978 instr[23,22] ==> type : 00 ==> source is single,
7979 01 ==> source is double
7981 11 ==> UNALLOC or source is half
7983 instr[20,15] ==> opcode : with type 00 or 01
7984 000000 ==> FMOV, 000001 ==> FABS,
7985 000010 ==> FNEG, 000011 ==> FSQRT,
7986 000100 ==> UNALLOC, 000101 ==> FCVT,(to single/double)
7987 000110 ==> UNALLOC, 000111 ==> FCVT (to half)
7988 001000 ==> FRINTN, 001001 ==> FRINTP,
7989 001010 ==> FRINTM, 001011 ==> FRINTZ,
7990 001100 ==> FRINTA, 001101 ==> UNALLOC
7991 001110 ==> FRINTX, 001111 ==> FRINTI
7993 000100 ==> FCVT (half-to-single)
7994 000101 ==> FCVT (half-to-double)
7995 instr[14,10] = 10000. */
7997 uint32_t M_S
= (INSTR (31, 31) << 1) | INSTR (29, 29);
7998 uint32_t type
= INSTR (23, 22);
7999 uint32_t opcode
= INSTR (20, 15);
8007 do_FCVT_half_to_single (cpu
);
8008 else if (opcode
== 5)
8009 do_FCVT_half_to_double (cpu
);
8061 case 8: /* FRINTN etc. */
8073 do_FCVT_double_to_half (cpu
);
8075 do_FCVT_single_to_half (cpu
);
8086 /* 32 bit signed int to float. */
8088 scvtf32 (sim_cpu
*cpu
)
8090 unsigned rn
= INSTR (9, 5);
8091 unsigned sd
= INSTR (4, 0);
8093 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
8094 aarch64_set_FP_float
8095 (cpu
, sd
, (float) aarch64_get_reg_s32 (cpu
, rn
, NO_SP
));
8098 /* signed int to float. */
8100 scvtf (sim_cpu
*cpu
)
8102 unsigned rn
= INSTR (9, 5);
8103 unsigned sd
= INSTR (4, 0);
8105 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
8106 aarch64_set_FP_float
8107 (cpu
, sd
, (float) aarch64_get_reg_s64 (cpu
, rn
, NO_SP
));
8110 /* 32 bit signed int to double. */
8112 scvtd32 (sim_cpu
*cpu
)
8114 unsigned rn
= INSTR (9, 5);
8115 unsigned sd
= INSTR (4, 0);
8117 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
8118 aarch64_set_FP_double
8119 (cpu
, sd
, (double) aarch64_get_reg_s32 (cpu
, rn
, NO_SP
));
8122 /* signed int to double. */
8124 scvtd (sim_cpu
*cpu
)
8126 unsigned rn
= INSTR (9, 5);
8127 unsigned sd
= INSTR (4, 0);
8129 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
8130 aarch64_set_FP_double
8131 (cpu
, sd
, (double) aarch64_get_reg_s64 (cpu
, rn
, NO_SP
));
8134 static const float FLOAT_INT_MAX
= (float) INT_MAX
;
8135 static const float FLOAT_INT_MIN
= (float) INT_MIN
;
8136 static const double DOUBLE_INT_MAX
= (double) INT_MAX
;
8137 static const double DOUBLE_INT_MIN
= (double) INT_MIN
;
8138 static const float FLOAT_LONG_MAX
= (float) LONG_MAX
;
8139 static const float FLOAT_LONG_MIN
= (float) LONG_MIN
;
8140 static const double DOUBLE_LONG_MAX
= (double) LONG_MAX
;
8141 static const double DOUBLE_LONG_MIN
= (double) LONG_MIN
;
8145 static const float FLOAT_UINT_MAX
= (float) UINT_MAX
;
8146 static const float FLOAT_UINT_MIN
= (float) UINT_MIN
;
8147 static const double DOUBLE_UINT_MAX
= (double) UINT_MAX
;
8148 static const double DOUBLE_UINT_MIN
= (double) UINT_MIN
;
8149 static const float FLOAT_ULONG_MAX
= (float) ULONG_MAX
;
8150 static const float FLOAT_ULONG_MIN
= (float) ULONG_MIN
;
8151 static const double DOUBLE_ULONG_MAX
= (double) ULONG_MAX
;
8152 static const double DOUBLE_ULONG_MIN
= (double) ULONG_MIN
;
8154 /* Check for FP exception conditions:
8157 Out of Range raises IO and IX and saturates value
8158 Denormal raises ID and IX and sets to zero. */
8159 #define RAISE_EXCEPTIONS(F, VALUE, FTYPE, ITYPE) \
8162 switch (fpclassify (F)) \
8166 aarch64_set_FPSR (cpu, IO); \
8168 VALUE = ITYPE##_MAX; \
8170 VALUE = ITYPE##_MIN; \
8174 if (F >= FTYPE##_##ITYPE##_MAX) \
8176 aarch64_set_FPSR_bits (cpu, IO | IX, IO | IX); \
8177 VALUE = ITYPE##_MAX; \
8179 else if (F <= FTYPE##_##ITYPE##_MIN) \
8181 aarch64_set_FPSR_bits (cpu, IO | IX, IO | IX); \
8182 VALUE = ITYPE##_MIN; \
8186 case FP_SUBNORMAL: \
8187 aarch64_set_FPSR_bits (cpu, IO | IX | ID, IX | ID); \
8199 /* 32 bit convert float to signed int truncate towards zero. */
8201 fcvtszs32 (sim_cpu
*cpu
)
8203 unsigned sn
= INSTR (9, 5);
8204 unsigned rd
= INSTR (4, 0);
8205 /* TODO : check that this rounds toward zero. */
8206 float f
= aarch64_get_FP_float (cpu
, sn
);
8207 int32_t value
= (int32_t) f
;
8209 RAISE_EXCEPTIONS (f
, value
, FLOAT
, INT
);
8211 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
8212 /* Avoid sign extension to 64 bit. */
8213 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, (uint32_t) value
);
8216 /* 64 bit convert float to signed int truncate towards zero. */
8218 fcvtszs (sim_cpu
*cpu
)
8220 unsigned sn
= INSTR (9, 5);
8221 unsigned rd
= INSTR (4, 0);
8222 float f
= aarch64_get_FP_float (cpu
, sn
);
8223 int64_t value
= (int64_t) f
;
8225 RAISE_EXCEPTIONS (f
, value
, FLOAT
, LONG
);
8227 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
8228 aarch64_set_reg_s64 (cpu
, rd
, NO_SP
, value
);
8231 /* 32 bit convert double to signed int truncate towards zero. */
8233 fcvtszd32 (sim_cpu
*cpu
)
8235 unsigned sn
= INSTR (9, 5);
8236 unsigned rd
= INSTR (4, 0);
8237 /* TODO : check that this rounds toward zero. */
8238 double d
= aarch64_get_FP_double (cpu
, sn
);
8239 int32_t value
= (int32_t) d
;
8241 RAISE_EXCEPTIONS (d
, value
, DOUBLE
, INT
);
8243 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
8244 /* Avoid sign extension to 64 bit. */
8245 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, (uint32_t) value
);
8248 /* 64 bit convert double to signed int truncate towards zero. */
8250 fcvtszd (sim_cpu
*cpu
)
8252 unsigned sn
= INSTR (9, 5);
8253 unsigned rd
= INSTR (4, 0);
8254 /* TODO : check that this rounds toward zero. */
8255 double d
= aarch64_get_FP_double (cpu
, sn
);
8258 value
= (int64_t) d
;
8260 RAISE_EXCEPTIONS (d
, value
, DOUBLE
, LONG
);
8262 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
8263 aarch64_set_reg_s64 (cpu
, rd
, NO_SP
, value
);
8267 do_fcvtzu (sim_cpu
*cpu
)
8269 /* instr[31] = size: 32-bit (0), 64-bit (1)
8270 instr[30,23] = 00111100
8271 instr[22] = type: single (0)/ double (1)
8272 instr[21] = enable (0)/disable(1) precision
8273 instr[20,16] = 11001
8274 instr[15,10] = precision
8278 unsigned rs
= INSTR (9, 5);
8279 unsigned rd
= INSTR (4, 0);
8281 NYI_assert (30, 23, 0x3C);
8282 NYI_assert (20, 16, 0x19);
8284 if (INSTR (21, 21) != 1)
8285 /* Convert to fixed point. */
8288 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
8291 /* Convert to unsigned 64-bit integer. */
8294 double d
= aarch64_get_FP_double (cpu
, rs
);
8295 uint64_t value
= (uint64_t) d
;
8297 /* Do not raise an exception if we have reached ULONG_MAX. */
8298 if (value
!= (1UL << 63))
8299 RAISE_EXCEPTIONS (d
, value
, DOUBLE
, ULONG
);
8301 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, value
);
8305 float f
= aarch64_get_FP_float (cpu
, rs
);
8306 uint64_t value
= (uint64_t) f
;
8308 /* Do not raise an exception if we have reached ULONG_MAX. */
8309 if (value
!= (1UL << 63))
8310 RAISE_EXCEPTIONS (f
, value
, FLOAT
, ULONG
);
8312 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, value
);
8319 /* Convert to unsigned 32-bit integer. */
8322 double d
= aarch64_get_FP_double (cpu
, rs
);
8324 value
= (uint32_t) d
;
8325 /* Do not raise an exception if we have reached UINT_MAX. */
8326 if (value
!= (1UL << 31))
8327 RAISE_EXCEPTIONS (d
, value
, DOUBLE
, UINT
);
8331 float f
= aarch64_get_FP_float (cpu
, rs
);
8333 value
= (uint32_t) f
;
8334 /* Do not raise an exception if we have reached UINT_MAX. */
8335 if (value
!= (1UL << 31))
8336 RAISE_EXCEPTIONS (f
, value
, FLOAT
, UINT
);
8339 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, value
);
8344 do_UCVTF (sim_cpu
*cpu
)
8346 /* instr[31] = size: 32-bit (0), 64-bit (1)
8347 instr[30,23] = 001 1110 0
8348 instr[22] = type: single (0)/ double (1)
8349 instr[21] = enable (0)/disable(1) precision
8350 instr[20,16] = 0 0011
8351 instr[15,10] = precision
8355 unsigned rs
= INSTR (9, 5);
8356 unsigned rd
= INSTR (4, 0);
8358 NYI_assert (30, 23, 0x3C);
8359 NYI_assert (20, 16, 0x03);
8361 if (INSTR (21, 21) != 1)
8364 /* FIXME: Add exception raising. */
8365 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
8368 uint64_t value
= aarch64_get_reg_u64 (cpu
, rs
, NO_SP
);
8371 aarch64_set_FP_double (cpu
, rd
, (double) value
);
8373 aarch64_set_FP_float (cpu
, rd
, (float) value
);
8377 uint32_t value
= aarch64_get_reg_u32 (cpu
, rs
, NO_SP
);
8380 aarch64_set_FP_double (cpu
, rd
, (double) value
);
8382 aarch64_set_FP_float (cpu
, rd
, (float) value
);
8387 float_vector_move (sim_cpu
*cpu
)
8389 /* instr[31,17] == 100 1111 0101 0111
8390 instr[16] ==> direction 0=> to GR, 1=> from GR
8392 instr[9,5] ==> source
8393 instr[4,0] ==> dest. */
8395 unsigned rn
= INSTR (9, 5);
8396 unsigned rd
= INSTR (4, 0);
8398 NYI_assert (31, 17, 0x4F57);
8400 if (INSTR (15, 10) != 0)
8403 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
8405 aarch64_set_vec_u64 (cpu
, rd
, 1, aarch64_get_reg_u64 (cpu
, rn
, NO_SP
));
8407 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, aarch64_get_vec_u64 (cpu
, rn
, 1));
8411 dexSimpleFPIntegerConvert (sim_cpu
*cpu
)
8413 /* instr[31] = size : 0 ==> 32 bit, 1 ==> 64 bit
8415 instr[29] = S : 0 ==> OK, 1 ==> UNALLOC
8418 instr[23,22] = type : 00 ==> single, 01 ==> double, 1x ==> UNALLOC
8420 instr[20,19] = rmode
8421 instr[18,16] = opcode
8422 instr[15,10] = 10 0000 */
8424 uint32_t rmode_opcode
;
8430 if (INSTR (31, 17) == 0x4F57)
8432 float_vector_move (cpu
);
8436 size
= INSTR (31, 31);
8441 type
= INSTR (23, 22);
8445 rmode_opcode
= INSTR (20, 16);
8446 size_type
= (size
<< 1) | type
; /* 0==32f, 1==32d, 2==64f, 3==64d. */
8448 switch (rmode_opcode
)
8450 case 2: /* SCVTF. */
8453 case 0: scvtf32 (cpu
); return;
8454 case 1: scvtd32 (cpu
); return;
8455 case 2: scvtf (cpu
); return;
8456 case 3: scvtd (cpu
); return;
8459 case 6: /* FMOV GR, Vec. */
8462 case 0: gfmovs (cpu
); return;
8463 case 3: gfmovd (cpu
); return;
8464 default: HALT_UNALLOC
;
8467 case 7: /* FMOV vec, GR. */
8470 case 0: fgmovs (cpu
); return;
8471 case 3: fgmovd (cpu
); return;
8472 default: HALT_UNALLOC
;
8475 case 24: /* FCVTZS. */
8478 case 0: fcvtszs32 (cpu
); return;
8479 case 1: fcvtszd32 (cpu
); return;
8480 case 2: fcvtszs (cpu
); return;
8481 case 3: fcvtszd (cpu
); return;
8484 case 25: do_fcvtzu (cpu
); return;
8485 case 3: do_UCVTF (cpu
); return;
8487 case 0: /* FCVTNS. */
8488 case 1: /* FCVTNU. */
8489 case 4: /* FCVTAS. */
8490 case 5: /* FCVTAU. */
8491 case 8: /* FCVPTS. */
8492 case 9: /* FCVTPU. */
8493 case 16: /* FCVTMS. */
8494 case 17: /* FCVTMU. */
8501 set_flags_for_float_compare (sim_cpu
*cpu
, float fvalue1
, float fvalue2
)
8505 /* FIXME: Add exception raising. */
8506 if (isnan (fvalue1
) || isnan (fvalue2
))
8508 else if (isinf (fvalue1
) && isinf (fvalue2
))
8510 /* Subtracting two infinities may give a NaN. We only need to compare
8511 the signs, which we can get from isinf. */
8512 int result
= isinf (fvalue1
) - isinf (fvalue2
);
8516 else if (result
< 0)
8518 else /* (result > 0). */
8523 float result
= fvalue1
- fvalue2
;
8527 else if (result
< 0)
8529 else /* (result > 0). */
8533 aarch64_set_CPSR (cpu
, flags
);
8537 fcmps (sim_cpu
*cpu
)
8539 unsigned sm
= INSTR (20, 16);
8540 unsigned sn
= INSTR ( 9, 5);
8542 float fvalue1
= aarch64_get_FP_float (cpu
, sn
);
8543 float fvalue2
= aarch64_get_FP_float (cpu
, sm
);
8545 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
8546 set_flags_for_float_compare (cpu
, fvalue1
, fvalue2
);
8549 /* Float compare to zero -- Invalid Operation exception
8550 only on signaling NaNs. */
8552 fcmpzs (sim_cpu
*cpu
)
8554 unsigned sn
= INSTR ( 9, 5);
8555 float fvalue1
= aarch64_get_FP_float (cpu
, sn
);
8557 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
8558 set_flags_for_float_compare (cpu
, fvalue1
, 0.0f
);
8561 /* Float compare -- Invalid Operation exception on all NaNs. */
8563 fcmpes (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 on all NaNs. */
8577 fcmpzes (sim_cpu
*cpu
)
8579 unsigned sn
= INSTR ( 9, 5);
8580 float fvalue1
= aarch64_get_FP_float (cpu
, sn
);
8582 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
8583 set_flags_for_float_compare (cpu
, fvalue1
, 0.0f
);
8587 set_flags_for_double_compare (sim_cpu
*cpu
, double dval1
, double dval2
)
8591 /* FIXME: Add exception raising. */
8592 if (isnan (dval1
) || isnan (dval2
))
8594 else if (isinf (dval1
) && isinf (dval2
))
8596 /* Subtracting two infinities may give a NaN. We only need to compare
8597 the signs, which we can get from isinf. */
8598 int result
= isinf (dval1
) - isinf (dval2
);
8602 else if (result
< 0)
8604 else /* (result > 0). */
8609 double result
= dval1
- dval2
;
8613 else if (result
< 0)
8615 else /* (result > 0). */
8619 aarch64_set_CPSR (cpu
, flags
);
8622 /* Double compare -- Invalid Operation exception only on signaling NaNs. */
8624 fcmpd (sim_cpu
*cpu
)
8626 unsigned sm
= INSTR (20, 16);
8627 unsigned sn
= INSTR ( 9, 5);
8629 double dvalue1
= aarch64_get_FP_double (cpu
, sn
);
8630 double dvalue2
= aarch64_get_FP_double (cpu
, sm
);
8632 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
8633 set_flags_for_double_compare (cpu
, dvalue1
, dvalue2
);
8636 /* Double compare to zero -- Invalid Operation exception
8637 only on signaling NaNs. */
8639 fcmpzd (sim_cpu
*cpu
)
8641 unsigned sn
= INSTR ( 9, 5);
8642 double dvalue1
= aarch64_get_FP_double (cpu
, sn
);
8644 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
8645 set_flags_for_double_compare (cpu
, dvalue1
, 0.0);
8648 /* Double compare -- Invalid Operation exception on all NaNs. */
8650 fcmped (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 on all NaNs. */
8664 fcmpzed (sim_cpu
*cpu
)
8666 unsigned sn
= INSTR ( 9, 5);
8667 double dvalue1
= aarch64_get_FP_double (cpu
, sn
);
8669 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
8670 set_flags_for_double_compare (cpu
, dvalue1
, 0.0);
8674 dexSimpleFPCompare (sim_cpu
*cpu
)
8676 /* assert instr[28,25] == 1111
8677 instr[30:24:21:13,10] = 0011000
8678 instr[31] = M : 0 ==> OK, 1 ==> UNALLOC
8679 instr[29] ==> S : 0 ==> OK, 1 ==> UNALLOC
8680 instr[23,22] ==> type : 0 ==> single, 01 ==> double, 1x ==> UNALLOC
8681 instr[15,14] ==> op : 00 ==> OK, ow ==> UNALLOC
8682 instr[4,0] ==> opcode2 : 00000 ==> FCMP, 10000 ==> FCMPE,
8683 01000 ==> FCMPZ, 11000 ==> FCMPEZ,
8686 uint32_t M_S
= (INSTR (31, 31) << 1) | INSTR (29, 29);
8687 uint32_t type
= INSTR (23, 22);
8688 uint32_t op
= INSTR (15, 14);
8689 uint32_t op2_2_0
= INSTR (2, 0);
8703 /* dispatch on type and top 2 bits of opcode. */
8704 dispatch
= (type
<< 2) | INSTR (4, 3);
8708 case 0: fcmps (cpu
); return;
8709 case 1: fcmpzs (cpu
); return;
8710 case 2: fcmpes (cpu
); return;
8711 case 3: fcmpzes (cpu
); return;
8712 case 4: fcmpd (cpu
); return;
8713 case 5: fcmpzd (cpu
); return;
8714 case 6: fcmped (cpu
); return;
8715 case 7: fcmpzed (cpu
); return;
8720 do_scalar_FADDP (sim_cpu
*cpu
)
8722 /* instr [31,23] = 0111 1110 0
8723 instr [22] = single(0)/double(1)
8724 instr [21,10] = 11 0000 1101 10
8726 instr [4,0] = Fd. */
8728 unsigned Fn
= INSTR (9, 5);
8729 unsigned Fd
= INSTR (4, 0);
8731 NYI_assert (31, 23, 0x0FC);
8732 NYI_assert (21, 10, 0xC36);
8734 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
8737 double val1
= aarch64_get_vec_double (cpu
, Fn
, 0);
8738 double val2
= aarch64_get_vec_double (cpu
, Fn
, 1);
8740 aarch64_set_FP_double (cpu
, Fd
, val1
+ val2
);
8744 float val1
= aarch64_get_vec_float (cpu
, Fn
, 0);
8745 float val2
= aarch64_get_vec_float (cpu
, Fn
, 1);
8747 aarch64_set_FP_float (cpu
, Fd
, val1
+ val2
);
8751 /* Floating point absolute difference. */
8754 do_scalar_FABD (sim_cpu
*cpu
)
8756 /* instr [31,23] = 0111 1110 1
8757 instr [22] = float(0)/double(1)
8760 instr [15,10] = 1101 01
8762 instr [4, 0] = Rd. */
8764 unsigned rm
= INSTR (20, 16);
8765 unsigned rn
= INSTR (9, 5);
8766 unsigned rd
= INSTR (4, 0);
8768 NYI_assert (31, 23, 0x0FD);
8769 NYI_assert (21, 21, 1);
8770 NYI_assert (15, 10, 0x35);
8772 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
8774 aarch64_set_FP_double (cpu
, rd
,
8775 fabs (aarch64_get_FP_double (cpu
, rn
)
8776 - aarch64_get_FP_double (cpu
, rm
)));
8778 aarch64_set_FP_float (cpu
, rd
,
8779 fabsf (aarch64_get_FP_float (cpu
, rn
)
8780 - aarch64_get_FP_float (cpu
, rm
)));
8784 do_scalar_CMGT (sim_cpu
*cpu
)
8786 /* instr [31,21] = 0101 1110 111
8788 instr [15,10] = 00 1101
8790 instr [4, 0] = Rd. */
8792 unsigned rm
= INSTR (20, 16);
8793 unsigned rn
= INSTR (9, 5);
8794 unsigned rd
= INSTR (4, 0);
8796 NYI_assert (31, 21, 0x2F7);
8797 NYI_assert (15, 10, 0x0D);
8799 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
8800 aarch64_set_vec_u64 (cpu
, rd
, 0,
8801 aarch64_get_vec_u64 (cpu
, rn
, 0) >
8802 aarch64_get_vec_u64 (cpu
, rm
, 0) ? -1L : 0L);
8806 do_scalar_USHR (sim_cpu
*cpu
)
8808 /* instr [31,23] = 0111 1111 0
8809 instr [22,16] = shift amount
8810 instr [15,10] = 0000 01
8812 instr [4, 0] = Rd. */
8814 unsigned amount
= 128 - INSTR (22, 16);
8815 unsigned rn
= INSTR (9, 5);
8816 unsigned rd
= INSTR (4, 0);
8818 NYI_assert (31, 23, 0x0FE);
8819 NYI_assert (15, 10, 0x01);
8821 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
8822 aarch64_set_vec_u64 (cpu
, rd
, 0,
8823 aarch64_get_vec_u64 (cpu
, rn
, 0) >> amount
);
8827 do_scalar_SSHL (sim_cpu
*cpu
)
8829 /* instr [31,21] = 0101 1110 111
8831 instr [15,10] = 0100 01
8833 instr [4, 0] = Rd. */
8835 unsigned rm
= INSTR (20, 16);
8836 unsigned rn
= INSTR (9, 5);
8837 unsigned rd
= INSTR (4, 0);
8838 signed int shift
= aarch64_get_vec_s8 (cpu
, rm
, 0);
8840 NYI_assert (31, 21, 0x2F7);
8841 NYI_assert (15, 10, 0x11);
8843 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
8845 aarch64_set_vec_s64 (cpu
, rd
, 0,
8846 aarch64_get_vec_s64 (cpu
, rn
, 0) << shift
);
8848 aarch64_set_vec_s64 (cpu
, rd
, 0,
8849 aarch64_get_vec_s64 (cpu
, rn
, 0) >> - shift
);
8853 do_scalar_shift (sim_cpu
*cpu
)
8855 /* instr [31,23] = 0101 1111 0
8856 instr [22,16] = shift amount
8857 instr [15,10] = 0101 01 [SHL]
8858 instr [15,10] = 0000 01 [SSHR]
8860 instr [4, 0] = Rd. */
8862 unsigned rn
= INSTR (9, 5);
8863 unsigned rd
= INSTR (4, 0);
8866 NYI_assert (31, 23, 0x0BE);
8868 if (INSTR (22, 22) == 0)
8871 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
8872 switch (INSTR (15, 10))
8874 case 0x01: /* SSHR */
8875 amount
= 128 - INSTR (22, 16);
8876 aarch64_set_vec_s64 (cpu
, rd
, 0,
8877 aarch64_get_vec_s64 (cpu
, rn
, 0) >> amount
);
8879 case 0x15: /* SHL */
8880 amount
= INSTR (22, 16) - 64;
8881 aarch64_set_vec_u64 (cpu
, rd
, 0,
8882 aarch64_get_vec_u64 (cpu
, rn
, 0) << amount
);
8889 /* FCMEQ FCMGT FCMGE. */
8891 do_scalar_FCM (sim_cpu
*cpu
)
8893 /* instr [31,30] = 01
8895 instr [28,24] = 1 1110
8900 instr [15,12] = 1110
8904 instr [4, 0] = Rd. */
8906 unsigned rm
= INSTR (20, 16);
8907 unsigned rn
= INSTR (9, 5);
8908 unsigned rd
= INSTR (4, 0);
8909 unsigned EUac
= (INSTR (23, 23) << 2) | (INSTR (29, 29) << 1) | INSTR (11, 11);
8914 NYI_assert (31, 30, 1);
8915 NYI_assert (28, 24, 0x1E);
8916 NYI_assert (21, 21, 1);
8917 NYI_assert (15, 12, 0xE);
8918 NYI_assert (10, 10, 1);
8920 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
8923 double val1
= aarch64_get_FP_double (cpu
, rn
);
8924 double val2
= aarch64_get_FP_double (cpu
, rm
);
8929 result
= val1
== val2
;
8937 result
= val1
>= val2
;
8945 result
= val1
> val2
;
8952 aarch64_set_vec_u32 (cpu
, rd
, 0, result
? -1 : 0);
8956 val1
= aarch64_get_FP_float (cpu
, rn
);
8957 val2
= aarch64_get_FP_float (cpu
, rm
);
8962 result
= val1
== val2
;
8966 val1
= fabsf (val1
);
8967 val2
= fabsf (val2
);
8970 result
= val1
>= val2
;
8974 val1
= fabsf (val1
);
8975 val2
= fabsf (val2
);
8978 result
= val1
> val2
;
8985 aarch64_set_vec_u32 (cpu
, rd
, 0, result
? -1 : 0);
8988 /* An alias of DUP. */
8990 do_scalar_MOV (sim_cpu
*cpu
)
8992 /* instr [31,21] = 0101 1110 000
8993 instr [20,16] = imm5
8994 instr [15,10] = 0000 01
8996 instr [4, 0] = Rd. */
8998 unsigned rn
= INSTR (9, 5);
8999 unsigned rd
= INSTR (4, 0);
9002 NYI_assert (31, 21, 0x2F0);
9003 NYI_assert (15, 10, 0x01);
9005 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
9009 index
= INSTR (20, 17);
9011 (cpu
, rd
, 0, aarch64_get_vec_u8 (cpu
, rn
, index
));
9013 else if (INSTR (17, 17))
9016 index
= INSTR (20, 18);
9018 (cpu
, rd
, 0, aarch64_get_vec_u16 (cpu
, rn
, index
));
9020 else if (INSTR (18, 18))
9023 index
= INSTR (20, 19);
9025 (cpu
, rd
, 0, aarch64_get_vec_u32 (cpu
, rn
, index
));
9027 else if (INSTR (19, 19))
9030 index
= INSTR (20, 20);
9032 (cpu
, rd
, 0, aarch64_get_vec_u64 (cpu
, rn
, index
));
9039 do_scalar_NEG (sim_cpu
*cpu
)
9041 /* instr [31,10] = 0111 1110 1110 0000 1011 10
9043 instr [4, 0] = Rd. */
9045 unsigned rn
= INSTR (9, 5);
9046 unsigned rd
= INSTR (4, 0);
9048 NYI_assert (31, 10, 0x1FB82E);
9050 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
9051 aarch64_set_vec_u64 (cpu
, rd
, 0, - aarch64_get_vec_u64 (cpu
, rn
, 0));
9055 do_scalar_USHL (sim_cpu
*cpu
)
9057 /* instr [31,21] = 0111 1110 111
9059 instr [15,10] = 0100 01
9061 instr [4, 0] = Rd. */
9063 unsigned rm
= INSTR (20, 16);
9064 unsigned rn
= INSTR (9, 5);
9065 unsigned rd
= INSTR (4, 0);
9066 signed int shift
= aarch64_get_vec_s8 (cpu
, rm
, 0);
9068 NYI_assert (31, 21, 0x3F7);
9069 NYI_assert (15, 10, 0x11);
9071 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
9073 aarch64_set_vec_u64 (cpu
, rd
, 0, aarch64_get_vec_u64 (cpu
, rn
, 0) << shift
);
9075 aarch64_set_vec_u64 (cpu
, rd
, 0, aarch64_get_vec_u64 (cpu
, rn
, 0) >> - shift
);
9079 do_double_add (sim_cpu
*cpu
)
9081 /* instr [31,21] = 0101 1110 111
9083 instr [15,10] = 1000 01
9085 instr [4,0] = Fd. */
9092 NYI_assert (31, 21, 0x2F7);
9093 NYI_assert (15, 10, 0x21);
9097 Fn
= INSTR (20, 16);
9099 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
9100 val1
= aarch64_get_FP_double (cpu
, Fm
);
9101 val2
= aarch64_get_FP_double (cpu
, Fn
);
9103 aarch64_set_FP_double (cpu
, Fd
, val1
+ val2
);
9107 do_scalar_UCVTF (sim_cpu
*cpu
)
9109 /* instr [31,23] = 0111 1110 0
9110 instr [22] = single(0)/double(1)
9111 instr [21,10] = 10 0001 1101 10
9113 instr [4,0] = rd. */
9115 unsigned rn
= INSTR (9, 5);
9116 unsigned rd
= INSTR (4, 0);
9118 NYI_assert (31, 23, 0x0FC);
9119 NYI_assert (21, 10, 0x876);
9121 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
9124 uint64_t val
= aarch64_get_vec_u64 (cpu
, rn
, 0);
9126 aarch64_set_vec_double (cpu
, rd
, 0, (double) val
);
9130 uint32_t val
= aarch64_get_vec_u32 (cpu
, rn
, 0);
9132 aarch64_set_vec_float (cpu
, rd
, 0, (float) val
);
9137 do_scalar_vec (sim_cpu
*cpu
)
9139 /* instr [30] = 1. */
9140 /* instr [28,25] = 1111. */
9141 switch (INSTR (31, 23))
9144 switch (INSTR (15, 10))
9146 case 0x01: do_scalar_MOV (cpu
); return;
9147 case 0x39: do_scalar_FCM (cpu
); return;
9148 case 0x3B: do_scalar_FCM (cpu
); return;
9152 case 0xBE: do_scalar_shift (cpu
); return;
9155 switch (INSTR (15, 10))
9158 switch (INSTR (21, 16))
9160 case 0x30: do_scalar_FADDP (cpu
); return;
9161 case 0x21: do_scalar_UCVTF (cpu
); return;
9164 case 0x39: do_scalar_FCM (cpu
); return;
9165 case 0x3B: do_scalar_FCM (cpu
); return;
9170 switch (INSTR (15, 10))
9172 case 0x0D: do_scalar_CMGT (cpu
); return;
9173 case 0x11: do_scalar_USHL (cpu
); return;
9174 case 0x2E: do_scalar_NEG (cpu
); return;
9175 case 0x35: do_scalar_FABD (cpu
); return;
9176 case 0x39: do_scalar_FCM (cpu
); return;
9177 case 0x3B: do_scalar_FCM (cpu
); return;
9182 case 0xFE: do_scalar_USHR (cpu
); return;
9185 switch (INSTR (15, 10))
9187 case 0x21: do_double_add (cpu
); return;
9188 case 0x11: do_scalar_SSHL (cpu
); return;
9199 dexAdvSIMD1 (sim_cpu
*cpu
)
9201 /* instr [28,25] = 1 111. */
9203 /* We are currently only interested in the basic
9204 scalar fp routines which all have bit 30 = 0. */
9206 do_scalar_vec (cpu
);
9208 /* instr[24] is set for FP data processing 3-source and clear for
9209 all other basic scalar fp instruction groups. */
9210 else if (INSTR (24, 24))
9211 dexSimpleFPDataProc3Source (cpu
);
9213 /* instr[21] is clear for floating <-> fixed conversions and set for
9214 all other basic scalar fp instruction groups. */
9215 else if (!INSTR (21, 21))
9216 dexSimpleFPFixedConvert (cpu
);
9218 /* instr[11,10] : 01 ==> cond compare, 10 ==> Data Proc 2 Source
9219 11 ==> cond select, 00 ==> other. */
9221 switch (INSTR (11, 10))
9223 case 1: dexSimpleFPCondCompare (cpu
); return;
9224 case 2: dexSimpleFPDataProc2Source (cpu
); return;
9225 case 3: dexSimpleFPCondSelect (cpu
); return;
9228 /* Now an ordered cascade of tests.
9229 FP immediate has instr [12] == 1.
9230 FP compare has instr [13] == 1.
9231 FP Data Proc 1 Source has instr [14] == 1.
9232 FP floating <--> integer conversions has instr [15] == 0. */
9234 dexSimpleFPImmediate (cpu
);
9236 else if (INSTR (13, 13))
9237 dexSimpleFPCompare (cpu
);
9239 else if (INSTR (14, 14))
9240 dexSimpleFPDataProc1Source (cpu
);
9242 else if (!INSTR (15, 15))
9243 dexSimpleFPIntegerConvert (cpu
);
9246 /* If we get here then instr[15] == 1 which means UNALLOC. */
9251 /* PC relative addressing. */
9254 pcadr (sim_cpu
*cpu
)
9256 /* instr[31] = op : 0 ==> ADR, 1 ==> ADRP
9257 instr[30,29] = immlo
9258 instr[23,5] = immhi. */
9260 unsigned rd
= INSTR (4, 0);
9261 uint32_t isPage
= INSTR (31, 31);
9262 union { int64_t u64
; uint64_t s64
; } imm
;
9265 imm
.s64
= simm64 (aarch64_get_instr (cpu
), 23, 5);
9267 offset
= (offset
<< 2) | INSTR (30, 29);
9269 address
= aarch64_get_PC (cpu
);
9277 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
9278 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, address
+ offset
);
9281 /* Specific decode and execute for group Data Processing Immediate. */
9284 dexPCRelAddressing (sim_cpu
*cpu
)
9286 /* assert instr[28,24] = 10000. */
9290 /* Immediate logical.
9291 The bimm32/64 argument is constructed by replicating a 2, 4, 8,
9292 16, 32 or 64 bit sequence pulled out at decode and possibly
9295 N.B. the output register (dest) can normally be Xn or SP
9296 the exception occurs for flag setting instructions which may
9297 only use Xn for the output (dest). The input register can
9300 /* 32 bit and immediate. */
9302 and32 (sim_cpu
*cpu
, uint32_t bimm
)
9304 unsigned rn
= INSTR (9, 5);
9305 unsigned rd
= INSTR (4, 0);
9307 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
9308 aarch64_set_reg_u64 (cpu
, rd
, SP_OK
,
9309 aarch64_get_reg_u32 (cpu
, rn
, NO_SP
) & bimm
);
9312 /* 64 bit and immediate. */
9314 and64 (sim_cpu
*cpu
, uint64_t bimm
)
9316 unsigned rn
= INSTR (9, 5);
9317 unsigned rd
= INSTR (4, 0);
9319 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
9320 aarch64_set_reg_u64 (cpu
, rd
, SP_OK
,
9321 aarch64_get_reg_u64 (cpu
, rn
, NO_SP
) & bimm
);
9324 /* 32 bit and immediate set flags. */
9326 ands32 (sim_cpu
*cpu
, uint32_t bimm
)
9328 unsigned rn
= INSTR (9, 5);
9329 unsigned rd
= INSTR (4, 0);
9331 uint32_t value1
= aarch64_get_reg_u32 (cpu
, rn
, NO_SP
);
9332 uint32_t value2
= bimm
;
9334 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
9335 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, value1
& value2
);
9336 set_flags_for_binop32 (cpu
, value1
& value2
);
9339 /* 64 bit and immediate set flags. */
9341 ands64 (sim_cpu
*cpu
, uint64_t bimm
)
9343 unsigned rn
= INSTR (9, 5);
9344 unsigned rd
= INSTR (4, 0);
9346 uint64_t value1
= aarch64_get_reg_u64 (cpu
, rn
, NO_SP
);
9347 uint64_t value2
= bimm
;
9349 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
9350 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, value1
& value2
);
9351 set_flags_for_binop64 (cpu
, value1
& value2
);
9354 /* 32 bit exclusive or immediate. */
9356 eor32 (sim_cpu
*cpu
, uint32_t bimm
)
9358 unsigned rn
= INSTR (9, 5);
9359 unsigned rd
= INSTR (4, 0);
9361 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
9362 aarch64_set_reg_u64 (cpu
, rd
, SP_OK
,
9363 aarch64_get_reg_u32 (cpu
, rn
, NO_SP
) ^ bimm
);
9366 /* 64 bit exclusive or immediate. */
9368 eor64 (sim_cpu
*cpu
, uint64_t bimm
)
9370 unsigned rn
= INSTR (9, 5);
9371 unsigned rd
= INSTR (4, 0);
9373 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
9374 aarch64_set_reg_u64 (cpu
, rd
, SP_OK
,
9375 aarch64_get_reg_u64 (cpu
, rn
, NO_SP
) ^ bimm
);
9378 /* 32 bit or immediate. */
9380 orr32 (sim_cpu
*cpu
, uint32_t bimm
)
9382 unsigned rn
= INSTR (9, 5);
9383 unsigned rd
= INSTR (4, 0);
9385 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
9386 aarch64_set_reg_u64 (cpu
, rd
, SP_OK
,
9387 aarch64_get_reg_u32 (cpu
, rn
, NO_SP
) | bimm
);
9390 /* 64 bit or immediate. */
9392 orr64 (sim_cpu
*cpu
, uint64_t bimm
)
9394 unsigned rn
= INSTR (9, 5);
9395 unsigned rd
= INSTR (4, 0);
9397 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
9398 aarch64_set_reg_u64 (cpu
, rd
, SP_OK
,
9399 aarch64_get_reg_u64 (cpu
, rn
, NO_SP
) | bimm
);
9402 /* Logical shifted register.
9403 These allow an optional LSL, ASR, LSR or ROR to the second source
9404 register with a count up to the register bit count.
9405 N.B register args may not be SP. */
9407 /* 32 bit AND shifted register. */
9409 and32_shift (sim_cpu
*cpu
, Shift shift
, uint32_t count
)
9411 unsigned rm
= INSTR (20, 16);
9412 unsigned rn
= INSTR (9, 5);
9413 unsigned rd
= INSTR (4, 0);
9415 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
9417 (cpu
, rd
, NO_SP
, aarch64_get_reg_u32 (cpu
, rn
, NO_SP
)
9418 & shifted32 (aarch64_get_reg_u32 (cpu
, rm
, NO_SP
), shift
, count
));
9421 /* 64 bit AND shifted register. */
9423 and64_shift (sim_cpu
*cpu
, Shift shift
, uint32_t count
)
9425 unsigned rm
= INSTR (20, 16);
9426 unsigned rn
= INSTR (9, 5);
9427 unsigned rd
= INSTR (4, 0);
9429 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
9431 (cpu
, rd
, NO_SP
, aarch64_get_reg_u64 (cpu
, rn
, NO_SP
)
9432 & shifted64 (aarch64_get_reg_u64 (cpu
, rm
, NO_SP
), shift
, count
));
9435 /* 32 bit AND shifted register setting flags. */
9437 ands32_shift (sim_cpu
*cpu
, Shift shift
, uint32_t count
)
9439 unsigned rm
= INSTR (20, 16);
9440 unsigned rn
= INSTR (9, 5);
9441 unsigned rd
= INSTR (4, 0);
9443 uint32_t value1
= aarch64_get_reg_u32 (cpu
, rn
, NO_SP
);
9444 uint32_t value2
= shifted32 (aarch64_get_reg_u32 (cpu
, rm
, NO_SP
),
9447 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
9448 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, value1
& value2
);
9449 set_flags_for_binop32 (cpu
, value1
& value2
);
9452 /* 64 bit AND shifted register setting flags. */
9454 ands64_shift (sim_cpu
*cpu
, Shift shift
, uint32_t count
)
9456 unsigned rm
= INSTR (20, 16);
9457 unsigned rn
= INSTR (9, 5);
9458 unsigned rd
= INSTR (4, 0);
9460 uint64_t value1
= aarch64_get_reg_u64 (cpu
, rn
, NO_SP
);
9461 uint64_t value2
= shifted64 (aarch64_get_reg_u64 (cpu
, rm
, NO_SP
),
9464 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
9465 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, value1
& value2
);
9466 set_flags_for_binop64 (cpu
, value1
& value2
);
9469 /* 32 bit BIC shifted register. */
9471 bic32_shift (sim_cpu
*cpu
, Shift shift
, uint32_t count
)
9473 unsigned rm
= INSTR (20, 16);
9474 unsigned rn
= INSTR (9, 5);
9475 unsigned rd
= INSTR (4, 0);
9477 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
9479 (cpu
, rd
, NO_SP
, aarch64_get_reg_u32 (cpu
, rn
, NO_SP
)
9480 & ~ shifted32 (aarch64_get_reg_u32 (cpu
, rm
, NO_SP
), shift
, count
));
9483 /* 64 bit BIC shifted register. */
9485 bic64_shift (sim_cpu
*cpu
, Shift shift
, uint32_t count
)
9487 unsigned rm
= INSTR (20, 16);
9488 unsigned rn
= INSTR (9, 5);
9489 unsigned rd
= INSTR (4, 0);
9491 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
9493 (cpu
, rd
, NO_SP
, aarch64_get_reg_u64 (cpu
, rn
, NO_SP
)
9494 & ~ shifted64 (aarch64_get_reg_u64 (cpu
, rm
, NO_SP
), shift
, count
));
9497 /* 32 bit BIC shifted register setting flags. */
9499 bics32_shift (sim_cpu
*cpu
, Shift shift
, uint32_t count
)
9501 unsigned rm
= INSTR (20, 16);
9502 unsigned rn
= INSTR (9, 5);
9503 unsigned rd
= INSTR (4, 0);
9505 uint32_t value1
= aarch64_get_reg_u32 (cpu
, rn
, NO_SP
);
9506 uint32_t value2
= ~ shifted32 (aarch64_get_reg_u32 (cpu
, rm
, NO_SP
),
9509 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
9510 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, value1
& value2
);
9511 set_flags_for_binop32 (cpu
, value1
& value2
);
9514 /* 64 bit BIC shifted register setting flags. */
9516 bics64_shift (sim_cpu
*cpu
, Shift shift
, uint32_t count
)
9518 unsigned rm
= INSTR (20, 16);
9519 unsigned rn
= INSTR (9, 5);
9520 unsigned rd
= INSTR (4, 0);
9522 uint64_t value1
= aarch64_get_reg_u64 (cpu
, rn
, NO_SP
);
9523 uint64_t value2
= ~ shifted64 (aarch64_get_reg_u64 (cpu
, rm
, NO_SP
),
9526 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
9527 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, value1
& value2
);
9528 set_flags_for_binop64 (cpu
, value1
& value2
);
9531 /* 32 bit EON shifted register. */
9533 eon32_shift (sim_cpu
*cpu
, Shift shift
, uint32_t count
)
9535 unsigned rm
= INSTR (20, 16);
9536 unsigned rn
= INSTR (9, 5);
9537 unsigned rd
= INSTR (4, 0);
9539 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
9541 (cpu
, rd
, NO_SP
, aarch64_get_reg_u32 (cpu
, rn
, NO_SP
)
9542 ^ ~ shifted32 (aarch64_get_reg_u32 (cpu
, rm
, NO_SP
), shift
, count
));
9545 /* 64 bit EON shifted register. */
9547 eon64_shift (sim_cpu
*cpu
, Shift shift
, uint32_t count
)
9549 unsigned rm
= INSTR (20, 16);
9550 unsigned rn
= INSTR (9, 5);
9551 unsigned rd
= INSTR (4, 0);
9553 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
9555 (cpu
, rd
, NO_SP
, aarch64_get_reg_u64 (cpu
, rn
, NO_SP
)
9556 ^ ~ shifted64 (aarch64_get_reg_u64 (cpu
, rm
, NO_SP
), shift
, count
));
9559 /* 32 bit EOR shifted register. */
9561 eor32_shift (sim_cpu
*cpu
, Shift shift
, uint32_t count
)
9563 unsigned rm
= INSTR (20, 16);
9564 unsigned rn
= INSTR (9, 5);
9565 unsigned rd
= INSTR (4, 0);
9567 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
9569 (cpu
, rd
, NO_SP
, aarch64_get_reg_u32 (cpu
, rn
, NO_SP
)
9570 ^ shifted32 (aarch64_get_reg_u32 (cpu
, rm
, NO_SP
), shift
, count
));
9573 /* 64 bit EOR shifted register. */
9575 eor64_shift (sim_cpu
*cpu
, Shift shift
, uint32_t count
)
9577 unsigned rm
= INSTR (20, 16);
9578 unsigned rn
= INSTR (9, 5);
9579 unsigned rd
= INSTR (4, 0);
9581 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
9583 (cpu
, rd
, NO_SP
, aarch64_get_reg_u64 (cpu
, rn
, NO_SP
)
9584 ^ shifted64 (aarch64_get_reg_u64 (cpu
, rm
, NO_SP
), shift
, count
));
9587 /* 32 bit ORR shifted register. */
9589 orr32_shift (sim_cpu
*cpu
, Shift shift
, uint32_t count
)
9591 unsigned rm
= INSTR (20, 16);
9592 unsigned rn
= INSTR (9, 5);
9593 unsigned rd
= INSTR (4, 0);
9595 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
9597 (cpu
, rd
, NO_SP
, aarch64_get_reg_u32 (cpu
, rn
, NO_SP
)
9598 | shifted32 (aarch64_get_reg_u32 (cpu
, rm
, NO_SP
), shift
, count
));
9601 /* 64 bit ORR shifted register. */
9603 orr64_shift (sim_cpu
*cpu
, Shift shift
, uint32_t count
)
9605 unsigned rm
= INSTR (20, 16);
9606 unsigned rn
= INSTR (9, 5);
9607 unsigned rd
= INSTR (4, 0);
9609 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
9611 (cpu
, rd
, NO_SP
, aarch64_get_reg_u64 (cpu
, rn
, NO_SP
)
9612 | shifted64 (aarch64_get_reg_u64 (cpu
, rm
, NO_SP
), shift
, count
));
9615 /* 32 bit ORN shifted register. */
9617 orn32_shift (sim_cpu
*cpu
, Shift shift
, uint32_t count
)
9619 unsigned rm
= INSTR (20, 16);
9620 unsigned rn
= INSTR (9, 5);
9621 unsigned rd
= INSTR (4, 0);
9623 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
9625 (cpu
, rd
, NO_SP
, aarch64_get_reg_u32 (cpu
, rn
, NO_SP
)
9626 | ~ shifted32 (aarch64_get_reg_u32 (cpu
, rm
, NO_SP
), shift
, count
));
9629 /* 64 bit ORN shifted register. */
9631 orn64_shift (sim_cpu
*cpu
, Shift shift
, uint32_t count
)
9633 unsigned rm
= INSTR (20, 16);
9634 unsigned rn
= INSTR (9, 5);
9635 unsigned rd
= INSTR (4, 0);
9637 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
9639 (cpu
, rd
, NO_SP
, aarch64_get_reg_u64 (cpu
, rn
, NO_SP
)
9640 | ~ shifted64 (aarch64_get_reg_u64 (cpu
, rm
, NO_SP
), shift
, count
));
9644 dexLogicalImmediate (sim_cpu
*cpu
)
9646 /* assert instr[28,23] = 1001000
9647 instr[31] = size : 0 ==> 32 bit, 1 ==> 64 bit
9648 instr[30,29] = op : 0 ==> AND, 1 ==> ORR, 2 ==> EOR, 3 ==> ANDS
9649 instr[22] = N : used to construct immediate mask
9655 /* 32 bit operations must have N = 0 or else we have an UNALLOC. */
9656 uint32_t size
= INSTR (31, 31);
9657 uint32_t N
= INSTR (22, 22);
9658 /* uint32_t immr = INSTR (21, 16);. */
9659 /* uint32_t imms = INSTR (15, 10);. */
9660 uint32_t index
= INSTR (22, 10);
9661 uint64_t bimm64
= LITable
[index
];
9662 uint32_t dispatch
= INSTR (30, 29);
9672 uint32_t bimm
= (uint32_t) bimm64
;
9676 case 0: and32 (cpu
, bimm
); return;
9677 case 1: orr32 (cpu
, bimm
); return;
9678 case 2: eor32 (cpu
, bimm
); return;
9679 case 3: ands32 (cpu
, bimm
); return;
9686 case 0: and64 (cpu
, bimm64
); return;
9687 case 1: orr64 (cpu
, bimm64
); return;
9688 case 2: eor64 (cpu
, bimm64
); return;
9689 case 3: ands64 (cpu
, bimm64
); return;
9696 The uimm argument is a 16 bit value to be inserted into the
9697 target register the pos argument locates the 16 bit word in the
9698 dest register i.e. it is in {0, 1} for 32 bit and {0, 1, 2,
9700 N.B register arg may not be SP so it should be.
9701 accessed using the setGZRegisterXXX accessors. */
9703 /* 32 bit move 16 bit immediate zero remaining shorts. */
9705 movz32 (sim_cpu
*cpu
, uint32_t val
, uint32_t pos
)
9707 unsigned rd
= INSTR (4, 0);
9709 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
9710 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, val
<< (pos
* 16));
9713 /* 64 bit move 16 bit immediate zero remaining shorts. */
9715 movz64 (sim_cpu
*cpu
, uint32_t val
, uint32_t pos
)
9717 unsigned rd
= INSTR (4, 0);
9719 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
9720 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, ((uint64_t) val
) << (pos
* 16));
9723 /* 32 bit move 16 bit immediate negated. */
9725 movn32 (sim_cpu
*cpu
, uint32_t val
, uint32_t pos
)
9727 unsigned rd
= INSTR (4, 0);
9729 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
9730 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, ((val
<< (pos
* 16)) ^ 0xffffffffU
));
9733 /* 64 bit move 16 bit immediate negated. */
9735 movn64 (sim_cpu
*cpu
, uint32_t val
, uint32_t pos
)
9737 unsigned rd
= INSTR (4, 0);
9739 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
9741 (cpu
, rd
, NO_SP
, ((((uint64_t) val
) << (pos
* 16))
9742 ^ 0xffffffffffffffffULL
));
9745 /* 32 bit move 16 bit immediate keep remaining shorts. */
9747 movk32 (sim_cpu
*cpu
, uint32_t val
, uint32_t pos
)
9749 unsigned rd
= INSTR (4, 0);
9750 uint32_t current
= aarch64_get_reg_u32 (cpu
, rd
, NO_SP
);
9751 uint32_t value
= val
<< (pos
* 16);
9752 uint32_t mask
= ~(0xffffU
<< (pos
* 16));
9754 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
9755 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, (value
| (current
& mask
)));
9758 /* 64 bit move 16 it immediate keep remaining shorts. */
9760 movk64 (sim_cpu
*cpu
, uint32_t val
, uint32_t pos
)
9762 unsigned rd
= INSTR (4, 0);
9763 uint64_t current
= aarch64_get_reg_u64 (cpu
, rd
, NO_SP
);
9764 uint64_t value
= (uint64_t) val
<< (pos
* 16);
9765 uint64_t mask
= ~(0xffffULL
<< (pos
* 16));
9767 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
9768 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, (value
| (current
& mask
)));
9772 dexMoveWideImmediate (sim_cpu
*cpu
)
9774 /* assert instr[28:23] = 100101
9775 instr[31] = size : 0 ==> 32 bit, 1 ==> 64 bit
9776 instr[30,29] = op : 0 ==> MOVN, 1 ==> UNALLOC, 2 ==> MOVZ, 3 ==> MOVK
9777 instr[22,21] = shift : 00 == LSL#0, 01 = LSL#16, 10 = LSL#32, 11 = LSL#48
9778 instr[20,5] = uimm16
9781 /* N.B. the (multiple of 16) shift is applied by the called routine,
9782 we just pass the multiplier. */
9785 uint32_t size
= INSTR (31, 31);
9786 uint32_t op
= INSTR (30, 29);
9787 uint32_t shift
= INSTR (22, 21);
9789 /* 32 bit can only shift 0 or 1 lot of 16.
9790 anything else is an unallocated instruction. */
9791 if (size
== 0 && (shift
> 1))
9797 imm
= INSTR (20, 5);
9802 movn32 (cpu
, imm
, shift
);
9804 movz32 (cpu
, imm
, shift
);
9806 movk32 (cpu
, imm
, shift
);
9811 movn64 (cpu
, imm
, shift
);
9813 movz64 (cpu
, imm
, shift
);
9815 movk64 (cpu
, imm
, shift
);
9819 /* Bitfield operations.
9820 These take a pair of bit positions r and s which are in {0..31}
9821 or {0..63} depending on the instruction word size.
9822 N.B register args may not be SP. */
9824 /* OK, we start with ubfm which just needs to pick
9825 some bits out of source zero the rest and write
9826 the result to dest. Just need two logical shifts. */
9828 /* 32 bit bitfield move, left and right of affected zeroed
9829 if r <= s Wd<s-r:0> = Wn<s:r> else Wd<32+s-r,32-r> = Wn<s:0>. */
9831 ubfm32 (sim_cpu
*cpu
, uint32_t r
, uint32_t s
)
9834 unsigned rn
= INSTR (9, 5);
9835 uint32_t value
= aarch64_get_reg_u32 (cpu
, rn
, NO_SP
);
9837 /* Pick either s+1-r or s+1 consecutive bits out of the original word. */
9840 /* 31:...:s:xxx:r:...:0 ==> 31:...:s-r:xxx:0.
9841 We want only bits s:xxx:r at the bottom of the word
9842 so we LSL bit s up to bit 31 i.e. by 31 - s
9843 and then we LSR to bring bit 31 down to bit s - r
9844 i.e. by 31 + r - s. */
9846 value
>>= 31 + r
- s
;
9850 /* 31:...:s:xxx:0 ==> 31:...:31-(r-1)+s:xxx:31-(r-1):...:0
9851 We want only bits s:xxx:0 starting at it 31-(r-1)
9852 so we LSL bit s up to bit 31 i.e. by 31 - s
9853 and then we LSL to bring bit 31 down to 31-(r-1)+s
9854 i.e. by r - (s + 1). */
9856 value
>>= r
- (s
+ 1);
9859 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
9861 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, value
);
9864 /* 64 bit bitfield move, left and right of affected zeroed
9865 if r <= s Wd<s-r:0> = Wn<s:r> else Wd<64+s-r,64-r> = Wn<s:0>. */
9867 ubfm (sim_cpu
*cpu
, uint32_t r
, uint32_t s
)
9870 unsigned rn
= INSTR (9, 5);
9871 uint64_t value
= aarch64_get_reg_u64 (cpu
, rn
, NO_SP
);
9875 /* 63:...:s:xxx:r:...:0 ==> 63:...:s-r:xxx:0.
9876 We want only bits s:xxx:r at the bottom of the word.
9877 So we LSL bit s up to bit 63 i.e. by 63 - s
9878 and then we LSR to bring bit 63 down to bit s - r
9879 i.e. by 63 + r - s. */
9881 value
>>= 63 + r
- s
;
9885 /* 63:...:s:xxx:0 ==> 63:...:63-(r-1)+s:xxx:63-(r-1):...:0.
9886 We want only bits s:xxx:0 starting at it 63-(r-1).
9887 So we LSL bit s up to bit 63 i.e. by 63 - s
9888 and then we LSL to bring bit 63 down to 63-(r-1)+s
9889 i.e. by r - (s + 1). */
9891 value
>>= r
- (s
+ 1);
9894 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
9896 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, value
);
9899 /* The signed versions need to insert sign bits
9900 on the left of the inserted bit field. so we do
9901 much the same as the unsigned version except we
9902 use an arithmetic shift right -- this just means
9903 we need to operate on signed values. */
9905 /* 32 bit bitfield move, left of affected sign-extended, right zeroed. */
9906 /* If r <= s Wd<s-r:0> = Wn<s:r> else Wd<32+s-r,32-r> = Wn<s:0>. */
9908 sbfm32 (sim_cpu
*cpu
, uint32_t r
, uint32_t s
)
9911 unsigned rn
= INSTR (9, 5);
9912 /* as per ubfm32 but use an ASR instead of an LSR. */
9913 int32_t value
= aarch64_get_reg_s32 (cpu
, rn
, NO_SP
);
9918 value
>>= 31 + r
- s
;
9923 value
>>= r
- (s
+ 1);
9926 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
9928 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, (uint32_t) value
);
9931 /* 64 bit bitfield move, left of affected sign-extended, right zeroed. */
9932 /* If r <= s Wd<s-r:0> = Wn<s:r> else Wd<64+s-r,64-r> = Wn<s:0>. */
9934 sbfm (sim_cpu
*cpu
, uint32_t r
, uint32_t s
)
9937 unsigned rn
= INSTR (9, 5);
9938 /* acpu per ubfm but use an ASR instead of an LSR. */
9939 int64_t value
= aarch64_get_reg_s64 (cpu
, rn
, NO_SP
);
9944 value
>>= 63 + r
- s
;
9949 value
>>= r
- (s
+ 1);
9952 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
9954 aarch64_set_reg_s64 (cpu
, rd
, NO_SP
, value
);
9957 /* Finally, these versions leave non-affected bits
9958 as is. so we need to generate the bits as per
9959 ubfm and also generate a mask to pick the
9960 bits from the original and computed values. */
9962 /* 32 bit bitfield move, non-affected bits left as is.
9963 If r <= s Wd<s-r:0> = Wn<s:r> else Wd<32+s-r,32-r> = Wn<s:0>. */
9965 bfm32 (sim_cpu
*cpu
, uint32_t r
, uint32_t s
)
9967 unsigned rn
= INSTR (9, 5);
9968 uint32_t value
= aarch64_get_reg_u32 (cpu
, rn
, NO_SP
);
9973 /* Pick either s+1-r or s+1 consecutive bits out of the original word. */
9976 /* 31:...:s:xxx:r:...:0 ==> 31:...:s-r:xxx:0.
9977 We want only bits s:xxx:r at the bottom of the word
9978 so we LSL bit s up to bit 31 i.e. by 31 - s
9979 and then we LSR to bring bit 31 down to bit s - r
9980 i.e. by 31 + r - s. */
9982 value
>>= 31 + r
- s
;
9983 /* the mask must include the same bits. */
9985 mask
>>= 31 + r
- s
;
9989 /* 31:...:s:xxx:0 ==> 31:...:31-(r-1)+s:xxx:31-(r-1):...:0.
9990 We want only bits s:xxx:0 starting at it 31-(r-1)
9991 so we LSL bit s up to bit 31 i.e. by 31 - s
9992 and then we LSL to bring bit 31 down to 31-(r-1)+s
9993 i.e. by r - (s + 1). */
9995 value
>>= r
- (s
+ 1);
9996 /* The mask must include the same bits. */
9998 mask
>>= r
- (s
+ 1);
10002 value2
= aarch64_get_reg_u32 (cpu
, rd
, NO_SP
);
10007 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
10008 aarch64_set_reg_u64
10009 (cpu
, rd
, NO_SP
, (aarch64_get_reg_u32 (cpu
, rd
, NO_SP
) & ~mask
) | value
);
10012 /* 64 bit bitfield move, non-affected bits left as is.
10013 If r <= s Wd<s-r:0> = Wn<s:r> else Wd<64+s-r,64-r> = Wn<s:0>. */
10015 bfm (sim_cpu
*cpu
, uint32_t r
, uint32_t s
)
10018 unsigned rn
= INSTR (9, 5);
10019 uint64_t value
= aarch64_get_reg_u64 (cpu
, rn
, NO_SP
);
10020 uint64_t mask
= 0xffffffffffffffffULL
;
10024 /* 63:...:s:xxx:r:...:0 ==> 63:...:s-r:xxx:0.
10025 We want only bits s:xxx:r at the bottom of the word
10026 so we LSL bit s up to bit 63 i.e. by 63 - s
10027 and then we LSR to bring bit 63 down to bit s - r
10028 i.e. by 63 + r - s. */
10030 value
>>= 63 + r
- s
;
10031 /* The mask must include the same bits. */
10033 mask
>>= 63 + r
- s
;
10037 /* 63:...:s:xxx:0 ==> 63:...:63-(r-1)+s:xxx:63-(r-1):...:0
10038 We want only bits s:xxx:0 starting at it 63-(r-1)
10039 so we LSL bit s up to bit 63 i.e. by 63 - s
10040 and then we LSL to bring bit 63 down to 63-(r-1)+s
10041 i.e. by r - (s + 1). */
10043 value
>>= r
- (s
+ 1);
10044 /* The mask must include the same bits. */
10046 mask
>>= r
- (s
+ 1);
10049 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
10051 aarch64_set_reg_u64
10052 (cpu
, rd
, NO_SP
, (aarch64_get_reg_u64 (cpu
, rd
, NO_SP
) & ~mask
) | value
);
10056 dexBitfieldImmediate (sim_cpu
*cpu
)
10058 /* assert instr[28:23] = 100110
10059 instr[31] = size : 0 ==> 32 bit, 1 ==> 64 bit
10060 instr[30,29] = op : 0 ==> SBFM, 1 ==> BFM, 2 ==> UBFM, 3 ==> UNALLOC
10061 instr[22] = N : must be 0 for 32 bit, 1 for 64 bit ow UNALLOC
10062 instr[21,16] = immr : 0xxxxx for 32 bit, xxxxxx for 64 bit
10063 instr[15,10] = imms : 0xxxxx for 32 bit, xxxxxx for 64 bit
10067 /* 32 bit operations must have N = 0 or else we have an UNALLOC. */
10070 uint32_t size
= INSTR (31, 31);
10071 uint32_t N
= INSTR (22, 22);
10072 /* 32 bit operations must have immr[5] = 0 and imms[5] = 0. */
10073 /* or else we have an UNALLOC. */
10074 uint32_t immr
= INSTR (21, 16);
10079 if (!size
&& uimm (immr
, 5, 5))
10082 imms
= INSTR (15, 10);
10083 if (!size
&& uimm (imms
, 5, 5))
10086 /* Switch on combined size and op. */
10087 dispatch
= INSTR (31, 29);
10090 case 0: sbfm32 (cpu
, immr
, imms
); return;
10091 case 1: bfm32 (cpu
, immr
, imms
); return;
10092 case 2: ubfm32 (cpu
, immr
, imms
); return;
10093 case 4: sbfm (cpu
, immr
, imms
); return;
10094 case 5: bfm (cpu
, immr
, imms
); return;
10095 case 6: ubfm (cpu
, immr
, imms
); return;
10096 default: HALT_UNALLOC
;
10101 do_EXTR_32 (sim_cpu
*cpu
)
10103 /* instr[31:21] = 00010011100
10105 instr[15,10] = imms : 0xxxxx for 32 bit
10108 unsigned rm
= INSTR (20, 16);
10109 unsigned imms
= INSTR (15, 10) & 31;
10110 unsigned rn
= INSTR ( 9, 5);
10111 unsigned rd
= INSTR ( 4, 0);
10115 val1
= aarch64_get_reg_u32 (cpu
, rm
, NO_SP
);
10117 val2
= aarch64_get_reg_u32 (cpu
, rn
, NO_SP
);
10118 val2
<<= (32 - imms
);
10120 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
10121 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, val1
| val2
);
10125 do_EXTR_64 (sim_cpu
*cpu
)
10127 /* instr[31:21] = 10010011100
10129 instr[15,10] = imms
10132 unsigned rm
= INSTR (20, 16);
10133 unsigned imms
= INSTR (15, 10) & 63;
10134 unsigned rn
= INSTR ( 9, 5);
10135 unsigned rd
= INSTR ( 4, 0);
10138 val
= aarch64_get_reg_u64 (cpu
, rm
, NO_SP
);
10140 val
|= (aarch64_get_reg_u64 (cpu
, rn
, NO_SP
) << (64 - imms
));
10142 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, val
);
10146 dexExtractImmediate (sim_cpu
*cpu
)
10148 /* assert instr[28:23] = 100111
10149 instr[31] = size : 0 ==> 32 bit, 1 ==> 64 bit
10150 instr[30,29] = op21 : 0 ==> EXTR, 1,2,3 ==> UNALLOC
10151 instr[22] = N : must be 0 for 32 bit, 1 for 64 bit or UNALLOC
10152 instr[21] = op0 : must be 0 or UNALLOC
10154 instr[15,10] = imms : 0xxxxx for 32 bit, xxxxxx for 64 bit
10158 /* 32 bit operations must have N = 0 or else we have an UNALLOC. */
10159 /* 64 bit operations must have N = 1 or else we have an UNALLOC. */
10161 uint32_t size
= INSTR (31, 31);
10162 uint32_t N
= INSTR (22, 22);
10163 /* 32 bit operations must have imms[5] = 0
10164 or else we have an UNALLOC. */
10165 uint32_t imms
= INSTR (15, 10);
10170 if (!size
&& uimm (imms
, 5, 5))
10173 /* Switch on combined size and op. */
10174 dispatch
= INSTR (31, 29);
10179 else if (dispatch
== 4)
10182 else if (dispatch
== 1)
10189 dexDPImm (sim_cpu
*cpu
)
10191 /* uint32_t group = dispatchGroup (aarch64_get_instr (cpu));
10192 assert group == GROUP_DPIMM_1000 || grpoup == GROUP_DPIMM_1001
10193 bits [25,23] of a DPImm are the secondary dispatch vector. */
10194 uint32_t group2
= dispatchDPImm (aarch64_get_instr (cpu
));
10198 case DPIMM_PCADR_000
:
10199 case DPIMM_PCADR_001
:
10200 dexPCRelAddressing (cpu
);
10203 case DPIMM_ADDSUB_010
:
10204 case DPIMM_ADDSUB_011
:
10205 dexAddSubtractImmediate (cpu
);
10208 case DPIMM_LOG_100
:
10209 dexLogicalImmediate (cpu
);
10212 case DPIMM_MOV_101
:
10213 dexMoveWideImmediate (cpu
);
10216 case DPIMM_BITF_110
:
10217 dexBitfieldImmediate (cpu
);
10220 case DPIMM_EXTR_111
:
10221 dexExtractImmediate (cpu
);
10225 /* Should never reach here. */
10231 dexLoadUnscaledImmediate (sim_cpu
*cpu
)
10233 /* instr[29,24] == 111_00
10236 instr[31,30] = size
10239 instr[20,12] = simm9
10240 instr[9,5] = rn may be SP. */
10241 /* unsigned rt = INSTR (4, 0); */
10242 uint32_t V
= INSTR (26, 26);
10243 uint32_t dispatch
= ((INSTR (31, 30) << 2) | INSTR (23, 22));
10244 int32_t imm
= simm32 (aarch64_get_instr (cpu
), 20, 12);
10248 /* GReg operations. */
10251 case 0: sturb (cpu
, imm
); return;
10252 case 1: ldurb32 (cpu
, imm
); return;
10253 case 2: ldursb64 (cpu
, imm
); return;
10254 case 3: ldursb32 (cpu
, imm
); return;
10255 case 4: sturh (cpu
, imm
); return;
10256 case 5: ldurh32 (cpu
, imm
); return;
10257 case 6: ldursh64 (cpu
, imm
); return;
10258 case 7: ldursh32 (cpu
, imm
); return;
10259 case 8: stur32 (cpu
, imm
); return;
10260 case 9: ldur32 (cpu
, imm
); return;
10261 case 10: ldursw (cpu
, imm
); return;
10262 case 12: stur64 (cpu
, imm
); return;
10263 case 13: ldur64 (cpu
, imm
); return;
10276 /* FReg operations. */
10279 case 2: fsturq (cpu
, imm
); return;
10280 case 3: fldurq (cpu
, imm
); return;
10281 case 8: fsturs (cpu
, imm
); return;
10282 case 9: fldurs (cpu
, imm
); return;
10283 case 12: fsturd (cpu
, imm
); return;
10284 case 13: fldurd (cpu
, imm
); return;
10286 case 0: /* STUR 8 bit FP. */
10287 case 1: /* LDUR 8 bit FP. */
10288 case 4: /* STUR 16 bit FP. */
10289 case 5: /* LDUR 8 bit FP. */
10303 /* N.B. A preliminary note regarding all the ldrs<x>32
10306 The signed value loaded by these instructions is cast to unsigned
10307 before being assigned to aarch64_get_reg_u64 (cpu, N) i.e. to the
10308 64 bit element of the GReg union. this performs a 32 bit sign extension
10309 (as required) but avoids 64 bit sign extension, thus ensuring that the
10310 top half of the register word is zero. this is what the spec demands
10311 when a 32 bit load occurs. */
10313 /* 32 bit load sign-extended byte scaled unsigned 12 bit. */
10315 ldrsb32_abs (sim_cpu
*cpu
, uint32_t offset
)
10317 unsigned int rn
= INSTR (9, 5);
10318 unsigned int rt
= INSTR (4, 0);
10320 /* The target register may not be SP but the source may be
10321 there is no scaling required for a byte load. */
10322 uint64_t address
= aarch64_get_reg_u64 (cpu
, rn
, SP_OK
) + offset
;
10323 aarch64_set_reg_u64 (cpu
, rt
, NO_SP
,
10324 (int64_t) aarch64_get_mem_s8 (cpu
, address
));
10327 /* 32 bit load sign-extended byte scaled or unscaled zero-
10328 or sign-extended 32-bit register offset. */
10330 ldrsb32_scale_ext (sim_cpu
*cpu
, Scaling scaling
, Extension extension
)
10332 unsigned int rm
= INSTR (20, 16);
10333 unsigned int rn
= INSTR (9, 5);
10334 unsigned int rt
= INSTR (4, 0);
10336 /* rn may reference SP, rm and rt must reference ZR. */
10338 uint64_t address
= aarch64_get_reg_u64 (cpu
, rn
, SP_OK
);
10339 int64_t displacement
= extend (aarch64_get_reg_u32 (cpu
, rm
, NO_SP
),
10342 /* There is no scaling required for a byte load. */
10343 aarch64_set_reg_u64
10344 (cpu
, rt
, NO_SP
, (int64_t) aarch64_get_mem_s8 (cpu
, address
10348 /* 32 bit load sign-extended byte unscaled signed 9 bit with
10349 pre- or post-writeback. */
10351 ldrsb32_wb (sim_cpu
*cpu
, int32_t offset
, WriteBack wb
)
10354 unsigned int rn
= INSTR (9, 5);
10355 unsigned int rt
= INSTR (4, 0);
10357 if (rn
== rt
&& wb
!= NoWriteBack
)
10360 address
= aarch64_get_reg_u64 (cpu
, rn
, SP_OK
);
10365 aarch64_set_reg_u64 (cpu
, rt
, NO_SP
,
10366 (int64_t) aarch64_get_mem_s8 (cpu
, address
));
10371 if (wb
!= NoWriteBack
)
10372 aarch64_set_reg_u64 (cpu
, rn
, NO_SP
, address
);
10375 /* 8 bit store scaled. */
10377 fstrb_abs (sim_cpu
*cpu
, uint32_t offset
)
10379 unsigned st
= INSTR (4, 0);
10380 unsigned rn
= INSTR (9, 5);
10382 aarch64_set_mem_u8 (cpu
,
10383 aarch64_get_reg_u64 (cpu
, rn
, SP_OK
) + offset
,
10384 aarch64_get_vec_u8 (cpu
, st
, 0));
10387 /* 8 bit store scaled or unscaled zero- or
10388 sign-extended 8-bit register offset. */
10390 fstrb_scale_ext (sim_cpu
*cpu
, Scaling scaling
, Extension extension
)
10392 unsigned rm
= INSTR (20, 16);
10393 unsigned rn
= INSTR (9, 5);
10394 unsigned st
= INSTR (4, 0);
10396 uint64_t address
= aarch64_get_reg_u64 (cpu
, rn
, SP_OK
);
10397 int64_t extended
= extend (aarch64_get_reg_u32 (cpu
, rm
, NO_SP
),
10399 uint64_t displacement
= scaling
== Scaled
? extended
: 0;
10402 (cpu
, address
+ displacement
, aarch64_get_vec_u8 (cpu
, st
, 0));
10405 /* 16 bit store scaled. */
10407 fstrh_abs (sim_cpu
*cpu
, uint32_t offset
)
10409 unsigned st
= INSTR (4, 0);
10410 unsigned rn
= INSTR (9, 5);
10412 aarch64_set_mem_u16
10414 aarch64_get_reg_u64 (cpu
, rn
, SP_OK
) + SCALE (offset
, 16),
10415 aarch64_get_vec_u16 (cpu
, st
, 0));
10418 /* 16 bit store scaled or unscaled zero-
10419 or sign-extended 16-bit register offset. */
10421 fstrh_scale_ext (sim_cpu
*cpu
, Scaling scaling
, Extension extension
)
10423 unsigned rm
= INSTR (20, 16);
10424 unsigned rn
= INSTR (9, 5);
10425 unsigned st
= INSTR (4, 0);
10427 uint64_t address
= aarch64_get_reg_u64 (cpu
, rn
, SP_OK
);
10428 int64_t extended
= extend (aarch64_get_reg_u32 (cpu
, rm
, NO_SP
),
10430 uint64_t displacement
= OPT_SCALE (extended
, 16, scaling
);
10432 aarch64_set_mem_u16
10433 (cpu
, address
+ displacement
, aarch64_get_vec_u16 (cpu
, st
, 0));
10436 /* 32 bit store scaled unsigned 12 bit. */
10438 fstrs_abs (sim_cpu
*cpu
, uint32_t offset
)
10440 unsigned st
= INSTR (4, 0);
10441 unsigned rn
= INSTR (9, 5);
10443 aarch64_set_mem_u32
10445 aarch64_get_reg_u64 (cpu
, rn
, SP_OK
) + SCALE (offset
, 32),
10446 aarch64_get_vec_u32 (cpu
, st
, 0));
10449 /* 32 bit store unscaled signed 9 bit with pre- or post-writeback. */
10451 fstrs_wb (sim_cpu
*cpu
, int32_t offset
, WriteBack wb
)
10453 unsigned rn
= INSTR (9, 5);
10454 unsigned st
= INSTR (4, 0);
10456 uint64_t address
= aarch64_get_reg_u64 (cpu
, rn
, SP_OK
);
10461 aarch64_set_mem_u32 (cpu
, address
, aarch64_get_vec_u32 (cpu
, st
, 0));
10466 if (wb
!= NoWriteBack
)
10467 aarch64_set_reg_u64 (cpu
, rn
, SP_OK
, address
);
10470 /* 32 bit store scaled or unscaled zero-
10471 or sign-extended 32-bit register offset. */
10473 fstrs_scale_ext (sim_cpu
*cpu
, Scaling scaling
, Extension extension
)
10475 unsigned rm
= INSTR (20, 16);
10476 unsigned rn
= INSTR (9, 5);
10477 unsigned st
= INSTR (4, 0);
10479 uint64_t address
= aarch64_get_reg_u64 (cpu
, rn
, SP_OK
);
10480 int64_t extended
= extend (aarch64_get_reg_u32 (cpu
, rm
, NO_SP
),
10482 uint64_t displacement
= OPT_SCALE (extended
, 32, scaling
);
10484 aarch64_set_mem_u32
10485 (cpu
, address
+ displacement
, aarch64_get_vec_u32 (cpu
, st
, 0));
10488 /* 64 bit store scaled unsigned 12 bit. */
10490 fstrd_abs (sim_cpu
*cpu
, uint32_t offset
)
10492 unsigned st
= INSTR (4, 0);
10493 unsigned rn
= INSTR (9, 5);
10495 aarch64_set_mem_u64
10497 aarch64_get_reg_u64 (cpu
, rn
, SP_OK
) + SCALE (offset
, 64),
10498 aarch64_get_vec_u64 (cpu
, st
, 0));
10501 /* 64 bit store unscaled signed 9 bit with pre- or post-writeback. */
10503 fstrd_wb (sim_cpu
*cpu
, int32_t offset
, WriteBack wb
)
10505 unsigned rn
= INSTR (9, 5);
10506 unsigned st
= INSTR (4, 0);
10508 uint64_t address
= aarch64_get_reg_u64 (cpu
, rn
, SP_OK
);
10513 aarch64_set_mem_u64 (cpu
, address
, aarch64_get_vec_u64 (cpu
, st
, 0));
10518 if (wb
!= NoWriteBack
)
10519 aarch64_set_reg_u64 (cpu
, rn
, SP_OK
, address
);
10522 /* 64 bit store scaled or unscaled zero-
10523 or sign-extended 32-bit register offset. */
10525 fstrd_scale_ext (sim_cpu
*cpu
, Scaling scaling
, Extension extension
)
10527 unsigned rm
= INSTR (20, 16);
10528 unsigned rn
= INSTR (9, 5);
10529 unsigned st
= INSTR (4, 0);
10531 uint64_t address
= aarch64_get_reg_u64 (cpu
, rn
, SP_OK
);
10532 int64_t extended
= extend (aarch64_get_reg_u32 (cpu
, rm
, NO_SP
),
10534 uint64_t displacement
= OPT_SCALE (extended
, 64, scaling
);
10536 aarch64_set_mem_u64
10537 (cpu
, address
+ displacement
, aarch64_get_vec_u64 (cpu
, st
, 0));
10540 /* 128 bit store scaled unsigned 12 bit. */
10542 fstrq_abs (sim_cpu
*cpu
, uint32_t offset
)
10545 unsigned st
= INSTR (4, 0);
10546 unsigned rn
= INSTR (9, 5);
10549 aarch64_get_FP_long_double (cpu
, st
, & a
);
10551 addr
= aarch64_get_reg_u64 (cpu
, rn
, SP_OK
) + SCALE (offset
, 128);
10552 aarch64_set_mem_long_double (cpu
, addr
, a
);
10555 /* 128 bit store unscaled signed 9 bit with pre- or post-writeback. */
10557 fstrq_wb (sim_cpu
*cpu
, int32_t offset
, WriteBack wb
)
10560 unsigned rn
= INSTR (9, 5);
10561 unsigned st
= INSTR (4, 0);
10562 uint64_t address
= aarch64_get_reg_u64 (cpu
, rn
, SP_OK
);
10567 aarch64_get_FP_long_double (cpu
, st
, & a
);
10568 aarch64_set_mem_long_double (cpu
, address
, a
);
10573 if (wb
!= NoWriteBack
)
10574 aarch64_set_reg_u64 (cpu
, rn
, SP_OK
, address
);
10577 /* 128 bit store scaled or unscaled zero-
10578 or sign-extended 32-bit register offset. */
10580 fstrq_scale_ext (sim_cpu
*cpu
, Scaling scaling
, Extension extension
)
10582 unsigned rm
= INSTR (20, 16);
10583 unsigned rn
= INSTR (9, 5);
10584 unsigned st
= INSTR (4, 0);
10586 uint64_t address
= aarch64_get_reg_u64 (cpu
, rn
, SP_OK
);
10587 int64_t extended
= extend (aarch64_get_reg_u32 (cpu
, rm
, NO_SP
),
10589 uint64_t displacement
= OPT_SCALE (extended
, 128, scaling
);
10593 aarch64_get_FP_long_double (cpu
, st
, & a
);
10594 aarch64_set_mem_long_double (cpu
, address
+ displacement
, a
);
10598 dexLoadImmediatePrePost (sim_cpu
*cpu
)
10600 /* instr[31,30] = size
10606 instr[20,12] = simm9
10607 instr[11] = wb : 0 ==> Post, 1 ==> Pre
10609 instr[9,5] = Rn may be SP.
10612 uint32_t V
= INSTR (26, 26);
10613 uint32_t dispatch
= ((INSTR (31, 30) << 2) | INSTR (23, 22));
10614 int32_t imm
= simm32 (aarch64_get_instr (cpu
), 20, 12);
10615 WriteBack wb
= INSTR (11, 11);
10619 /* GReg operations. */
10622 case 0: strb_wb (cpu
, imm
, wb
); return;
10623 case 1: ldrb32_wb (cpu
, imm
, wb
); return;
10624 case 2: ldrsb_wb (cpu
, imm
, wb
); return;
10625 case 3: ldrsb32_wb (cpu
, imm
, wb
); return;
10626 case 4: strh_wb (cpu
, imm
, wb
); return;
10627 case 5: ldrh32_wb (cpu
, imm
, wb
); return;
10628 case 6: ldrsh64_wb (cpu
, imm
, wb
); return;
10629 case 7: ldrsh32_wb (cpu
, imm
, wb
); return;
10630 case 8: str32_wb (cpu
, imm
, wb
); return;
10631 case 9: ldr32_wb (cpu
, imm
, wb
); return;
10632 case 10: ldrsw_wb (cpu
, imm
, wb
); return;
10633 case 12: str_wb (cpu
, imm
, wb
); return;
10634 case 13: ldr_wb (cpu
, imm
, wb
); return;
10644 /* FReg operations. */
10647 case 2: fstrq_wb (cpu
, imm
, wb
); return;
10648 case 3: fldrq_wb (cpu
, imm
, wb
); return;
10649 case 8: fstrs_wb (cpu
, imm
, wb
); return;
10650 case 9: fldrs_wb (cpu
, imm
, wb
); return;
10651 case 12: fstrd_wb (cpu
, imm
, wb
); return;
10652 case 13: fldrd_wb (cpu
, imm
, wb
); return;
10654 case 0: /* STUR 8 bit FP. */
10655 case 1: /* LDUR 8 bit FP. */
10656 case 4: /* STUR 16 bit FP. */
10657 case 5: /* LDUR 8 bit FP. */
10672 dexLoadRegisterOffset (sim_cpu
*cpu
)
10674 /* instr[31,30] = size
10681 instr[15,13] = option : 010 ==> UXTW, 011 ==> UXTX/LSL,
10682 110 ==> SXTW, 111 ==> SXTX,
10687 instr[4,0] = rt. */
10689 uint32_t V
= INSTR (26, 26);
10690 uint32_t dispatch
= ((INSTR (31, 30) << 2) | INSTR (23, 22));
10691 Scaling scale
= INSTR (12, 12);
10692 Extension extensionType
= INSTR (15, 13);
10694 /* Check for illegal extension types. */
10695 if (uimm (extensionType
, 1, 1) == 0)
10698 if (extensionType
== UXTX
|| extensionType
== SXTX
)
10699 extensionType
= NoExtension
;
10703 /* GReg operations. */
10706 case 0: strb_scale_ext (cpu
, scale
, extensionType
); return;
10707 case 1: ldrb32_scale_ext (cpu
, scale
, extensionType
); return;
10708 case 2: ldrsb_scale_ext (cpu
, scale
, extensionType
); return;
10709 case 3: ldrsb32_scale_ext (cpu
, scale
, extensionType
); return;
10710 case 4: strh_scale_ext (cpu
, scale
, extensionType
); return;
10711 case 5: ldrh32_scale_ext (cpu
, scale
, extensionType
); return;
10712 case 6: ldrsh_scale_ext (cpu
, scale
, extensionType
); return;
10713 case 7: ldrsh32_scale_ext (cpu
, scale
, extensionType
); return;
10714 case 8: str32_scale_ext (cpu
, scale
, extensionType
); return;
10715 case 9: ldr32_scale_ext (cpu
, scale
, extensionType
); return;
10716 case 10: ldrsw_scale_ext (cpu
, scale
, extensionType
); return;
10717 case 12: str_scale_ext (cpu
, scale
, extensionType
); return;
10718 case 13: ldr_scale_ext (cpu
, scale
, extensionType
); return;
10719 case 14: prfm_scale_ext (cpu
, scale
, extensionType
); return;
10728 /* FReg operations. */
10731 case 1: /* LDUR 8 bit FP. */
10733 case 3: fldrq_scale_ext (cpu
, scale
, extensionType
); return;
10734 case 5: /* LDUR 8 bit FP. */
10736 case 9: fldrs_scale_ext (cpu
, scale
, extensionType
); return;
10737 case 13: fldrd_scale_ext (cpu
, scale
, extensionType
); return;
10739 case 0: fstrb_scale_ext (cpu
, scale
, extensionType
); return;
10740 case 2: fstrq_scale_ext (cpu
, scale
, extensionType
); return;
10741 case 4: fstrh_scale_ext (cpu
, scale
, extensionType
); return;
10742 case 8: fstrs_scale_ext (cpu
, scale
, extensionType
); return;
10743 case 12: fstrd_scale_ext (cpu
, scale
, extensionType
); return;
10757 dexLoadUnsignedImmediate (sim_cpu
*cpu
)
10759 /* instr[29,24] == 111_01
10760 instr[31,30] = size
10763 instr[21,10] = uimm12 : unsigned immediate offset
10764 instr[9,5] = rn may be SP.
10765 instr[4,0] = rt. */
10767 uint32_t V
= INSTR (26,26);
10768 uint32_t dispatch
= ((INSTR (31, 30) << 2) | INSTR (23, 22));
10769 uint32_t imm
= INSTR (21, 10);
10773 /* GReg operations. */
10776 case 0: strb_abs (cpu
, imm
); return;
10777 case 1: ldrb32_abs (cpu
, imm
); return;
10778 case 2: ldrsb_abs (cpu
, imm
); return;
10779 case 3: ldrsb32_abs (cpu
, imm
); return;
10780 case 4: strh_abs (cpu
, imm
); return;
10781 case 5: ldrh32_abs (cpu
, imm
); return;
10782 case 6: ldrsh_abs (cpu
, imm
); return;
10783 case 7: ldrsh32_abs (cpu
, imm
); return;
10784 case 8: str32_abs (cpu
, imm
); return;
10785 case 9: ldr32_abs (cpu
, imm
); return;
10786 case 10: ldrsw_abs (cpu
, imm
); return;
10787 case 12: str_abs (cpu
, imm
); return;
10788 case 13: ldr_abs (cpu
, imm
); return;
10789 case 14: prfm_abs (cpu
, imm
); return;
10798 /* FReg operations. */
10801 case 0: fstrb_abs (cpu
, imm
); return;
10802 case 4: fstrh_abs (cpu
, imm
); return;
10803 case 8: fstrs_abs (cpu
, imm
); return;
10804 case 12: fstrd_abs (cpu
, imm
); return;
10805 case 2: fstrq_abs (cpu
, imm
); return;
10807 case 1: fldrb_abs (cpu
, imm
); return;
10808 case 5: fldrh_abs (cpu
, imm
); return;
10809 case 9: fldrs_abs (cpu
, imm
); return;
10810 case 13: fldrd_abs (cpu
, imm
); return;
10811 case 3: fldrq_abs (cpu
, imm
); return;
10825 dexLoadExclusive (sim_cpu
*cpu
)
10827 /* assert instr[29:24] = 001000;
10828 instr[31,30] = size
10829 instr[23] = 0 if exclusive
10830 instr[22] = L : 1 if load, 0 if store
10831 instr[21] = 1 if pair
10833 instr[15] = o0 : 1 if ordered
10836 instr[4.0] = Rt. */
10838 switch (INSTR (22, 21))
10840 case 2: ldxr (cpu
); return;
10841 case 0: stxr (cpu
); return;
10847 dexLoadOther (sim_cpu
*cpu
)
10851 /* instr[29,25] = 111_0
10852 instr[24] == 0 ==> dispatch, 1 ==> ldst reg unsigned immediate
10853 instr[21:11,10] is the secondary dispatch. */
10854 if (INSTR (24, 24))
10856 dexLoadUnsignedImmediate (cpu
);
10860 dispatch
= ((INSTR (21, 21) << 2) | INSTR (11, 10));
10863 case 0: dexLoadUnscaledImmediate (cpu
); return;
10864 case 1: dexLoadImmediatePrePost (cpu
); return;
10865 case 3: dexLoadImmediatePrePost (cpu
); return;
10866 case 6: dexLoadRegisterOffset (cpu
); return;
10878 store_pair_u32 (sim_cpu
*cpu
, int32_t offset
, WriteBack wb
)
10880 unsigned rn
= INSTR (14, 10);
10881 unsigned rd
= INSTR (9, 5);
10882 unsigned rm
= INSTR (4, 0);
10883 uint64_t address
= aarch64_get_reg_u64 (cpu
, rd
, SP_OK
);
10885 if ((rn
== rd
|| rm
== rd
) && wb
!= NoWriteBack
)
10886 HALT_UNALLOC
; /* ??? */
10893 aarch64_set_mem_u32 (cpu
, address
,
10894 aarch64_get_reg_u32 (cpu
, rm
, NO_SP
));
10895 aarch64_set_mem_u32 (cpu
, address
+ 4,
10896 aarch64_get_reg_u32 (cpu
, rn
, NO_SP
));
10901 if (wb
!= NoWriteBack
)
10902 aarch64_set_reg_u64 (cpu
, rd
, SP_OK
, address
);
10906 store_pair_u64 (sim_cpu
*cpu
, int32_t offset
, WriteBack wb
)
10908 unsigned rn
= INSTR (14, 10);
10909 unsigned rd
= INSTR (9, 5);
10910 unsigned rm
= INSTR (4, 0);
10911 uint64_t address
= aarch64_get_reg_u64 (cpu
, rd
, SP_OK
);
10913 if ((rn
== rd
|| rm
== rd
) && wb
!= NoWriteBack
)
10914 HALT_UNALLOC
; /* ??? */
10921 aarch64_set_mem_u64 (cpu
, address
,
10922 aarch64_get_reg_u64 (cpu
, rm
, NO_SP
));
10923 aarch64_set_mem_u64 (cpu
, address
+ 8,
10924 aarch64_get_reg_u64 (cpu
, rn
, NO_SP
));
10929 if (wb
!= NoWriteBack
)
10930 aarch64_set_reg_u64 (cpu
, rd
, SP_OK
, address
);
10934 load_pair_u32 (sim_cpu
*cpu
, int32_t offset
, WriteBack wb
)
10936 unsigned rn
= INSTR (14, 10);
10937 unsigned rd
= INSTR (9, 5);
10938 unsigned rm
= INSTR (4, 0);
10939 uint64_t address
= aarch64_get_reg_u64 (cpu
, rd
, SP_OK
);
10941 /* Treat this as unalloc to make sure we don't do it. */
10950 aarch64_set_reg_u64 (cpu
, rm
, SP_OK
, aarch64_get_mem_u32 (cpu
, address
));
10951 aarch64_set_reg_u64 (cpu
, rn
, SP_OK
, aarch64_get_mem_u32 (cpu
, address
+ 4));
10956 if (wb
!= NoWriteBack
)
10957 aarch64_set_reg_u64 (cpu
, rd
, SP_OK
, address
);
10961 load_pair_s32 (sim_cpu
*cpu
, int32_t offset
, WriteBack wb
)
10963 unsigned rn
= INSTR (14, 10);
10964 unsigned rd
= INSTR (9, 5);
10965 unsigned rm
= INSTR (4, 0);
10966 uint64_t address
= aarch64_get_reg_u64 (cpu
, rd
, SP_OK
);
10968 /* Treat this as unalloc to make sure we don't do it. */
10977 aarch64_set_reg_s64 (cpu
, rm
, SP_OK
, aarch64_get_mem_s32 (cpu
, address
));
10978 aarch64_set_reg_s64 (cpu
, rn
, SP_OK
, aarch64_get_mem_s32 (cpu
, address
+ 4));
10983 if (wb
!= NoWriteBack
)
10984 aarch64_set_reg_u64 (cpu
, rd
, SP_OK
, address
);
10988 load_pair_u64 (sim_cpu
*cpu
, int32_t offset
, WriteBack wb
)
10990 unsigned rn
= INSTR (14, 10);
10991 unsigned rd
= INSTR (9, 5);
10992 unsigned rm
= INSTR (4, 0);
10993 uint64_t address
= aarch64_get_reg_u64 (cpu
, rd
, SP_OK
);
10995 /* Treat this as unalloc to make sure we don't do it. */
11004 aarch64_set_reg_u64 (cpu
, rm
, SP_OK
, aarch64_get_mem_u64 (cpu
, address
));
11005 aarch64_set_reg_u64 (cpu
, rn
, SP_OK
, aarch64_get_mem_u64 (cpu
, address
+ 8));
11010 if (wb
!= NoWriteBack
)
11011 aarch64_set_reg_u64 (cpu
, rd
, SP_OK
, address
);
11015 dex_load_store_pair_gr (sim_cpu
*cpu
)
11017 /* instr[31,30] = size (10=> 64-bit, 01=> signed 32-bit, 00=> 32-bit)
11018 instr[29,25] = instruction encoding: 101_0
11019 instr[26] = V : 1 if fp 0 if gp
11020 instr[24,23] = addressing mode (10=> offset, 01=> post, 11=> pre)
11021 instr[22] = load/store (1=> load)
11022 instr[21,15] = signed, scaled, offset
11025 instr[ 4, 0] = Rm. */
11027 uint32_t dispatch
= ((INSTR (31, 30) << 3) | INSTR (24, 22));
11028 int32_t offset
= simm32 (aarch64_get_instr (cpu
), 21, 15);
11032 case 2: store_pair_u32 (cpu
, offset
, Post
); return;
11033 case 3: load_pair_u32 (cpu
, offset
, Post
); return;
11034 case 4: store_pair_u32 (cpu
, offset
, NoWriteBack
); return;
11035 case 5: load_pair_u32 (cpu
, offset
, NoWriteBack
); return;
11036 case 6: store_pair_u32 (cpu
, offset
, Pre
); return;
11037 case 7: load_pair_u32 (cpu
, offset
, Pre
); return;
11039 case 11: load_pair_s32 (cpu
, offset
, Post
); return;
11040 case 13: load_pair_s32 (cpu
, offset
, NoWriteBack
); return;
11041 case 15: load_pair_s32 (cpu
, offset
, Pre
); return;
11043 case 18: store_pair_u64 (cpu
, offset
, Post
); return;
11044 case 19: load_pair_u64 (cpu
, offset
, Post
); return;
11045 case 20: store_pair_u64 (cpu
, offset
, NoWriteBack
); return;
11046 case 21: load_pair_u64 (cpu
, offset
, NoWriteBack
); return;
11047 case 22: store_pair_u64 (cpu
, offset
, Pre
); return;
11048 case 23: load_pair_u64 (cpu
, offset
, Pre
); return;
11056 store_pair_float (sim_cpu
*cpu
, int32_t offset
, WriteBack wb
)
11058 unsigned rn
= INSTR (14, 10);
11059 unsigned rd
= INSTR (9, 5);
11060 unsigned rm
= INSTR (4, 0);
11061 uint64_t address
= aarch64_get_reg_u64 (cpu
, rd
, SP_OK
);
11068 aarch64_set_mem_u32 (cpu
, address
, aarch64_get_vec_u32 (cpu
, rm
, 0));
11069 aarch64_set_mem_u32 (cpu
, address
+ 4, aarch64_get_vec_u32 (cpu
, rn
, 0));
11074 if (wb
!= NoWriteBack
)
11075 aarch64_set_reg_u64 (cpu
, rd
, SP_OK
, address
);
11079 store_pair_double (sim_cpu
*cpu
, int32_t offset
, WriteBack wb
)
11081 unsigned rn
= INSTR (14, 10);
11082 unsigned rd
= INSTR (9, 5);
11083 unsigned rm
= INSTR (4, 0);
11084 uint64_t address
= aarch64_get_reg_u64 (cpu
, rd
, SP_OK
);
11091 aarch64_set_mem_u64 (cpu
, address
, aarch64_get_vec_u64 (cpu
, rm
, 0));
11092 aarch64_set_mem_u64 (cpu
, address
+ 8, aarch64_get_vec_u64 (cpu
, rn
, 0));
11097 if (wb
!= NoWriteBack
)
11098 aarch64_set_reg_u64 (cpu
, rd
, SP_OK
, address
);
11102 store_pair_long_double (sim_cpu
*cpu
, int32_t offset
, WriteBack wb
)
11105 unsigned rn
= INSTR (14, 10);
11106 unsigned rd
= INSTR (9, 5);
11107 unsigned rm
= INSTR (4, 0);
11108 uint64_t address
= aarch64_get_reg_u64 (cpu
, rd
, SP_OK
);
11115 aarch64_get_FP_long_double (cpu
, rm
, & a
);
11116 aarch64_set_mem_long_double (cpu
, address
, a
);
11117 aarch64_get_FP_long_double (cpu
, rn
, & a
);
11118 aarch64_set_mem_long_double (cpu
, address
+ 16, a
);
11123 if (wb
!= NoWriteBack
)
11124 aarch64_set_reg_u64 (cpu
, rd
, SP_OK
, address
);
11128 load_pair_float (sim_cpu
*cpu
, int32_t offset
, WriteBack wb
)
11130 unsigned rn
= INSTR (14, 10);
11131 unsigned rd
= INSTR (9, 5);
11132 unsigned rm
= INSTR (4, 0);
11133 uint64_t address
= aarch64_get_reg_u64 (cpu
, rd
, SP_OK
);
11143 aarch64_set_vec_u32 (cpu
, rm
, 0, aarch64_get_mem_u32 (cpu
, address
));
11144 aarch64_set_vec_u32 (cpu
, rn
, 0, aarch64_get_mem_u32 (cpu
, address
+ 4));
11149 if (wb
!= NoWriteBack
)
11150 aarch64_set_reg_u64 (cpu
, rd
, SP_OK
, address
);
11154 load_pair_double (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_u64 (cpu
, rm
, 0, aarch64_get_mem_u64 (cpu
, address
));
11170 aarch64_set_vec_u64 (cpu
, rn
, 0, aarch64_get_mem_u64 (cpu
, address
+ 8));
11175 if (wb
!= NoWriteBack
)
11176 aarch64_set_reg_u64 (cpu
, rd
, SP_OK
, address
);
11180 load_pair_long_double (sim_cpu
*cpu
, int32_t offset
, WriteBack wb
)
11183 unsigned rn
= INSTR (14, 10);
11184 unsigned rd
= INSTR (9, 5);
11185 unsigned rm
= INSTR (4, 0);
11186 uint64_t address
= aarch64_get_reg_u64 (cpu
, rd
, SP_OK
);
11196 aarch64_get_mem_long_double (cpu
, address
, & a
);
11197 aarch64_set_FP_long_double (cpu
, rm
, a
);
11198 aarch64_get_mem_long_double (cpu
, address
+ 16, & a
);
11199 aarch64_set_FP_long_double (cpu
, rn
, a
);
11204 if (wb
!= NoWriteBack
)
11205 aarch64_set_reg_u64 (cpu
, rd
, SP_OK
, address
);
11209 dex_load_store_pair_fp (sim_cpu
*cpu
)
11211 /* instr[31,30] = size (10=> 128-bit, 01=> 64-bit, 00=> 32-bit)
11212 instr[29,25] = instruction encoding
11213 instr[24,23] = addressing mode (10=> offset, 01=> post, 11=> pre)
11214 instr[22] = load/store (1=> load)
11215 instr[21,15] = signed, scaled, offset
11218 instr[ 4, 0] = Rm */
11220 uint32_t dispatch
= ((INSTR (31, 30) << 3) | INSTR (24, 22));
11221 int32_t offset
= simm32 (aarch64_get_instr (cpu
), 21, 15);
11225 case 2: store_pair_float (cpu
, offset
, Post
); return;
11226 case 3: load_pair_float (cpu
, offset
, Post
); return;
11227 case 4: store_pair_float (cpu
, offset
, NoWriteBack
); return;
11228 case 5: load_pair_float (cpu
, offset
, NoWriteBack
); return;
11229 case 6: store_pair_float (cpu
, offset
, Pre
); return;
11230 case 7: load_pair_float (cpu
, offset
, Pre
); return;
11232 case 10: store_pair_double (cpu
, offset
, Post
); return;
11233 case 11: load_pair_double (cpu
, offset
, Post
); return;
11234 case 12: store_pair_double (cpu
, offset
, NoWriteBack
); return;
11235 case 13: load_pair_double (cpu
, offset
, NoWriteBack
); return;
11236 case 14: store_pair_double (cpu
, offset
, Pre
); return;
11237 case 15: load_pair_double (cpu
, offset
, Pre
); return;
11239 case 18: store_pair_long_double (cpu
, offset
, Post
); return;
11240 case 19: load_pair_long_double (cpu
, offset
, Post
); return;
11241 case 20: store_pair_long_double (cpu
, offset
, NoWriteBack
); return;
11242 case 21: load_pair_long_double (cpu
, offset
, NoWriteBack
); return;
11243 case 22: store_pair_long_double (cpu
, offset
, Pre
); return;
11244 case 23: load_pair_long_double (cpu
, offset
, Pre
); return;
11251 static inline unsigned
11252 vec_reg (unsigned v
, unsigned o
)
11254 return (v
+ o
) & 0x3F;
11257 /* Load multiple N-element structures to N consecutive registers. */
11259 vec_load (sim_cpu
*cpu
, uint64_t address
, unsigned N
)
11261 int all
= INSTR (30, 30);
11262 unsigned size
= INSTR (11, 10);
11263 unsigned vd
= INSTR (4, 0);
11268 case 0: /* 8-bit operations. */
11270 for (i
= 0; i
< (16 * N
); i
++)
11271 aarch64_set_vec_u8 (cpu
, vec_reg (vd
, i
>> 4), i
& 15,
11272 aarch64_get_mem_u8 (cpu
, address
+ i
));
11274 for (i
= 0; i
< (8 * N
); i
++)
11275 aarch64_set_vec_u8 (cpu
, vec_reg (vd
, i
>> 3), i
& 7,
11276 aarch64_get_mem_u8 (cpu
, address
+ i
));
11279 case 1: /* 16-bit operations. */
11281 for (i
= 0; i
< (8 * N
); i
++)
11282 aarch64_set_vec_u16 (cpu
, vec_reg (vd
, i
>> 3), i
& 7,
11283 aarch64_get_mem_u16 (cpu
, address
+ i
* 2));
11285 for (i
= 0; i
< (4 * N
); i
++)
11286 aarch64_set_vec_u16 (cpu
, vec_reg (vd
, i
>> 2), i
& 3,
11287 aarch64_get_mem_u16 (cpu
, address
+ i
* 2));
11290 case 2: /* 32-bit operations. */
11292 for (i
= 0; i
< (4 * N
); i
++)
11293 aarch64_set_vec_u32 (cpu
, vec_reg (vd
, i
>> 2), i
& 3,
11294 aarch64_get_mem_u32 (cpu
, address
+ i
* 4));
11296 for (i
= 0; i
< (2 * N
); i
++)
11297 aarch64_set_vec_u32 (cpu
, vec_reg (vd
, i
>> 1), i
& 1,
11298 aarch64_get_mem_u32 (cpu
, address
+ i
* 4));
11301 case 3: /* 64-bit operations. */
11303 for (i
= 0; i
< (2 * N
); i
++)
11304 aarch64_set_vec_u64 (cpu
, vec_reg (vd
, i
>> 1), i
& 1,
11305 aarch64_get_mem_u64 (cpu
, address
+ i
* 8));
11307 for (i
= 0; i
< N
; i
++)
11308 aarch64_set_vec_u64 (cpu
, vec_reg (vd
, i
), 0,
11309 aarch64_get_mem_u64 (cpu
, address
+ i
* 8));
11314 /* LD4: load multiple 4-element to four consecutive registers. */
11316 LD4 (sim_cpu
*cpu
, uint64_t address
)
11318 vec_load (cpu
, address
, 4);
11321 /* LD3: load multiple 3-element structures to three consecutive registers. */
11323 LD3 (sim_cpu
*cpu
, uint64_t address
)
11325 vec_load (cpu
, address
, 3);
11328 /* LD2: load multiple 2-element structures to two consecutive registers. */
11330 LD2 (sim_cpu
*cpu
, uint64_t address
)
11332 vec_load (cpu
, address
, 2);
11335 /* Load multiple 1-element structures into one register. */
11337 LD1_1 (sim_cpu
*cpu
, uint64_t address
)
11339 int all
= INSTR (30, 30);
11340 unsigned size
= INSTR (11, 10);
11341 unsigned vd
= INSTR (4, 0);
11347 /* LD1 {Vd.16b}, addr, #16 */
11348 /* LD1 {Vd.8b}, addr, #8 */
11349 for (i
= 0; i
< (all
? 16 : 8); i
++)
11350 aarch64_set_vec_u8 (cpu
, vd
, i
,
11351 aarch64_get_mem_u8 (cpu
, address
+ i
));
11355 /* LD1 {Vd.8h}, addr, #16 */
11356 /* LD1 {Vd.4h}, addr, #8 */
11357 for (i
= 0; i
< (all
? 8 : 4); i
++)
11358 aarch64_set_vec_u16 (cpu
, vd
, i
,
11359 aarch64_get_mem_u16 (cpu
, address
+ i
* 2));
11363 /* LD1 {Vd.4s}, addr, #16 */
11364 /* LD1 {Vd.2s}, addr, #8 */
11365 for (i
= 0; i
< (all
? 4 : 2); i
++)
11366 aarch64_set_vec_u32 (cpu
, vd
, i
,
11367 aarch64_get_mem_u32 (cpu
, address
+ i
* 4));
11371 /* LD1 {Vd.2d}, addr, #16 */
11372 /* LD1 {Vd.1d}, addr, #8 */
11373 for (i
= 0; i
< (all
? 2 : 1); i
++)
11374 aarch64_set_vec_u64 (cpu
, vd
, i
,
11375 aarch64_get_mem_u64 (cpu
, address
+ i
* 8));
11380 /* Load multiple 1-element structures into two registers. */
11382 LD1_2 (sim_cpu
*cpu
, uint64_t address
)
11384 /* FIXME: This algorithm is *exactly* the same as the LD2 version.
11385 So why have two different instructions ? There must be something
11386 wrong somewhere. */
11387 vec_load (cpu
, address
, 2);
11390 /* Load multiple 1-element structures into three registers. */
11392 LD1_3 (sim_cpu
*cpu
, uint64_t address
)
11394 /* FIXME: This algorithm is *exactly* the same as the LD3 version.
11395 So why have two different instructions ? There must be something
11396 wrong somewhere. */
11397 vec_load (cpu
, address
, 3);
11400 /* Load multiple 1-element structures into four registers. */
11402 LD1_4 (sim_cpu
*cpu
, uint64_t address
)
11404 /* FIXME: This algorithm is *exactly* the same as the LD4 version.
11405 So why have two different instructions ? There must be something
11406 wrong somewhere. */
11407 vec_load (cpu
, address
, 4);
11410 /* Store multiple N-element structures to N consecutive registers. */
11412 vec_store (sim_cpu
*cpu
, uint64_t address
, unsigned N
)
11414 int all
= INSTR (30, 30);
11415 unsigned size
= INSTR (11, 10);
11416 unsigned vd
= INSTR (4, 0);
11421 case 0: /* 8-bit operations. */
11423 for (i
= 0; i
< (16 * N
); i
++)
11426 aarch64_get_vec_u8 (cpu
, vec_reg (vd
, i
>> 4), i
& 15));
11428 for (i
= 0; i
< (8 * N
); i
++)
11431 aarch64_get_vec_u8 (cpu
, vec_reg (vd
, i
>> 3), i
& 7));
11434 case 1: /* 16-bit operations. */
11436 for (i
= 0; i
< (8 * N
); i
++)
11437 aarch64_set_mem_u16
11438 (cpu
, address
+ i
* 2,
11439 aarch64_get_vec_u16 (cpu
, vec_reg (vd
, i
>> 3), i
& 7));
11441 for (i
= 0; i
< (4 * N
); i
++)
11442 aarch64_set_mem_u16
11443 (cpu
, address
+ i
* 2,
11444 aarch64_get_vec_u16 (cpu
, vec_reg (vd
, i
>> 2), i
& 3));
11447 case 2: /* 32-bit operations. */
11449 for (i
= 0; i
< (4 * N
); i
++)
11450 aarch64_set_mem_u32
11451 (cpu
, address
+ i
* 4,
11452 aarch64_get_vec_u32 (cpu
, vec_reg (vd
, i
>> 2), i
& 3));
11454 for (i
= 0; i
< (2 * N
); i
++)
11455 aarch64_set_mem_u32
11456 (cpu
, address
+ i
* 4,
11457 aarch64_get_vec_u32 (cpu
, vec_reg (vd
, i
>> 1), i
& 1));
11460 case 3: /* 64-bit operations. */
11462 for (i
= 0; i
< (2 * N
); i
++)
11463 aarch64_set_mem_u64
11464 (cpu
, address
+ i
* 8,
11465 aarch64_get_vec_u64 (cpu
, vec_reg (vd
, i
>> 1), i
& 1));
11467 for (i
= 0; i
< N
; i
++)
11468 aarch64_set_mem_u64
11469 (cpu
, address
+ i
* 8,
11470 aarch64_get_vec_u64 (cpu
, vec_reg (vd
, i
), 0));
11475 /* Store multiple 4-element structure to four consecutive registers. */
11477 ST4 (sim_cpu
*cpu
, uint64_t address
)
11479 vec_store (cpu
, address
, 4);
11482 /* Store multiple 3-element structures to three consecutive registers. */
11484 ST3 (sim_cpu
*cpu
, uint64_t address
)
11486 vec_store (cpu
, address
, 3);
11489 /* Store multiple 2-element structures to two consecutive registers. */
11491 ST2 (sim_cpu
*cpu
, uint64_t address
)
11493 vec_store (cpu
, address
, 2);
11496 /* Store multiple 1-element structures into one register. */
11498 ST1_1 (sim_cpu
*cpu
, uint64_t address
)
11500 int all
= INSTR (30, 30);
11501 unsigned size
= INSTR (11, 10);
11502 unsigned vd
= INSTR (4, 0);
11508 for (i
= 0; i
< (all
? 16 : 8); i
++)
11509 aarch64_set_mem_u8 (cpu
, address
+ i
,
11510 aarch64_get_vec_u8 (cpu
, vd
, i
));
11514 for (i
= 0; i
< (all
? 8 : 4); i
++)
11515 aarch64_set_mem_u16 (cpu
, address
+ i
* 2,
11516 aarch64_get_vec_u16 (cpu
, vd
, i
));
11520 for (i
= 0; i
< (all
? 4 : 2); i
++)
11521 aarch64_set_mem_u32 (cpu
, address
+ i
* 4,
11522 aarch64_get_vec_u32 (cpu
, vd
, i
));
11526 for (i
= 0; i
< (all
? 2 : 1); i
++)
11527 aarch64_set_mem_u64 (cpu
, address
+ i
* 8,
11528 aarch64_get_vec_u64 (cpu
, vd
, i
));
11533 /* Store multiple 1-element structures into two registers. */
11535 ST1_2 (sim_cpu
*cpu
, uint64_t address
)
11537 /* FIXME: This algorithm is *exactly* the same as the ST2 version.
11538 So why have two different instructions ? There must be
11539 something wrong somewhere. */
11540 vec_store (cpu
, address
, 2);
11543 /* Store multiple 1-element structures into three registers. */
11545 ST1_3 (sim_cpu
*cpu
, uint64_t address
)
11547 /* FIXME: This algorithm is *exactly* the same as the ST3 version.
11548 So why have two different instructions ? There must be
11549 something wrong somewhere. */
11550 vec_store (cpu
, address
, 3);
11553 /* Store multiple 1-element structures into four registers. */
11555 ST1_4 (sim_cpu
*cpu
, uint64_t address
)
11557 /* FIXME: This algorithm is *exactly* the same as the ST4 version.
11558 So why have two different instructions ? There must be
11559 something wrong somewhere. */
11560 vec_store (cpu
, address
, 4);
11564 do_vec_LDnR (sim_cpu
*cpu
, uint64_t address
)
11567 instr[30] = element selector 0=>half, 1=>all elements
11568 instr[29,24] = 00 1101
11569 instr[23] = 0=>simple, 1=>post
11571 instr[21] = width: LD1R-or-LD3R (0) / LD2R-or-LD4R (1)
11572 instr[20,16] = 0 0000 (simple), Vinc (reg-post-inc, no SP),
11573 11111 (immediate post inc)
11575 instr[13] = width: LD1R-or-LD2R (0) / LD3R-or-LD4R (1)
11577 instr[11,10] = element size 00=> byte(b), 01=> half(h),
11578 10=> word(s), 11=> double(d)
11579 instr[9,5] = address
11582 unsigned full
= INSTR (30, 30);
11583 unsigned vd
= INSTR (4, 0);
11584 unsigned size
= INSTR (11, 10);
11587 NYI_assert (29, 24, 0x0D);
11588 NYI_assert (22, 22, 1);
11589 NYI_assert (15, 14, 3);
11590 NYI_assert (12, 12, 0);
11592 switch ((INSTR (13, 13) << 1) | INSTR (21, 21))
11594 case 0: /* LD1R. */
11599 uint8_t val
= aarch64_get_mem_u8 (cpu
, address
);
11600 for (i
= 0; i
< (full
? 16 : 8); i
++)
11601 aarch64_set_vec_u8 (cpu
, vd
, i
, val
);
11607 uint16_t val
= aarch64_get_mem_u16 (cpu
, address
);
11608 for (i
= 0; i
< (full
? 8 : 4); i
++)
11609 aarch64_set_vec_u16 (cpu
, vd
, i
, val
);
11615 uint32_t val
= aarch64_get_mem_u32 (cpu
, address
);
11616 for (i
= 0; i
< (full
? 4 : 2); i
++)
11617 aarch64_set_vec_u32 (cpu
, vd
, i
, val
);
11623 uint64_t val
= aarch64_get_mem_u64 (cpu
, address
);
11624 for (i
= 0; i
< (full
? 2 : 1); i
++)
11625 aarch64_set_vec_u64 (cpu
, vd
, i
, val
);
11634 case 1: /* LD2R. */
11639 uint8_t val1
= aarch64_get_mem_u8 (cpu
, address
);
11640 uint8_t val2
= aarch64_get_mem_u8 (cpu
, address
+ 1);
11642 for (i
= 0; i
< (full
? 16 : 8); i
++)
11644 aarch64_set_vec_u8 (cpu
, vd
, 0, val1
);
11645 aarch64_set_vec_u8 (cpu
, vd
+ 1, 0, val2
);
11652 uint16_t val1
= aarch64_get_mem_u16 (cpu
, address
);
11653 uint16_t val2
= aarch64_get_mem_u16 (cpu
, address
+ 2);
11655 for (i
= 0; i
< (full
? 8 : 4); i
++)
11657 aarch64_set_vec_u16 (cpu
, vd
, 0, val1
);
11658 aarch64_set_vec_u16 (cpu
, vd
+ 1, 0, val2
);
11665 uint32_t val1
= aarch64_get_mem_u32 (cpu
, address
);
11666 uint32_t val2
= aarch64_get_mem_u32 (cpu
, address
+ 4);
11668 for (i
= 0; i
< (full
? 4 : 2); i
++)
11670 aarch64_set_vec_u32 (cpu
, vd
, 0, val1
);
11671 aarch64_set_vec_u32 (cpu
, vd
+ 1, 0, val2
);
11678 uint64_t val1
= aarch64_get_mem_u64 (cpu
, address
);
11679 uint64_t val2
= aarch64_get_mem_u64 (cpu
, address
+ 8);
11681 for (i
= 0; i
< (full
? 2 : 1); i
++)
11683 aarch64_set_vec_u64 (cpu
, vd
, 0, val1
);
11684 aarch64_set_vec_u64 (cpu
, vd
+ 1, 0, val2
);
11694 case 2: /* LD3R. */
11699 uint8_t val1
= aarch64_get_mem_u8 (cpu
, address
);
11700 uint8_t val2
= aarch64_get_mem_u8 (cpu
, address
+ 1);
11701 uint8_t val3
= aarch64_get_mem_u8 (cpu
, address
+ 2);
11703 for (i
= 0; i
< (full
? 16 : 8); i
++)
11705 aarch64_set_vec_u8 (cpu
, vd
, 0, val1
);
11706 aarch64_set_vec_u8 (cpu
, vd
+ 1, 0, val2
);
11707 aarch64_set_vec_u8 (cpu
, vd
+ 2, 0, val3
);
11714 uint32_t val1
= aarch64_get_mem_u16 (cpu
, address
);
11715 uint32_t val2
= aarch64_get_mem_u16 (cpu
, address
+ 2);
11716 uint32_t val3
= aarch64_get_mem_u16 (cpu
, address
+ 4);
11718 for (i
= 0; i
< (full
? 8 : 4); i
++)
11720 aarch64_set_vec_u16 (cpu
, vd
, 0, val1
);
11721 aarch64_set_vec_u16 (cpu
, vd
+ 1, 0, val2
);
11722 aarch64_set_vec_u16 (cpu
, vd
+ 2, 0, val3
);
11729 uint32_t val1
= aarch64_get_mem_u32 (cpu
, address
);
11730 uint32_t val2
= aarch64_get_mem_u32 (cpu
, address
+ 4);
11731 uint32_t val3
= aarch64_get_mem_u32 (cpu
, address
+ 8);
11733 for (i
= 0; i
< (full
? 4 : 2); i
++)
11735 aarch64_set_vec_u32 (cpu
, vd
, 0, val1
);
11736 aarch64_set_vec_u32 (cpu
, vd
+ 1, 0, val2
);
11737 aarch64_set_vec_u32 (cpu
, vd
+ 2, 0, val3
);
11744 uint64_t val1
= aarch64_get_mem_u64 (cpu
, address
);
11745 uint64_t val2
= aarch64_get_mem_u64 (cpu
, address
+ 8);
11746 uint64_t val3
= aarch64_get_mem_u64 (cpu
, address
+ 16);
11748 for (i
= 0; i
< (full
? 2 : 1); i
++)
11750 aarch64_set_vec_u64 (cpu
, vd
, 0, val1
);
11751 aarch64_set_vec_u64 (cpu
, vd
+ 1, 0, val2
);
11752 aarch64_set_vec_u64 (cpu
, vd
+ 2, 0, val3
);
11762 case 3: /* LD4R. */
11767 uint8_t val1
= aarch64_get_mem_u8 (cpu
, address
);
11768 uint8_t val2
= aarch64_get_mem_u8 (cpu
, address
+ 1);
11769 uint8_t val3
= aarch64_get_mem_u8 (cpu
, address
+ 2);
11770 uint8_t val4
= aarch64_get_mem_u8 (cpu
, address
+ 3);
11772 for (i
= 0; i
< (full
? 16 : 8); i
++)
11774 aarch64_set_vec_u8 (cpu
, vd
, 0, val1
);
11775 aarch64_set_vec_u8 (cpu
, vd
+ 1, 0, val2
);
11776 aarch64_set_vec_u8 (cpu
, vd
+ 2, 0, val3
);
11777 aarch64_set_vec_u8 (cpu
, vd
+ 3, 0, val4
);
11784 uint32_t val1
= aarch64_get_mem_u16 (cpu
, address
);
11785 uint32_t val2
= aarch64_get_mem_u16 (cpu
, address
+ 2);
11786 uint32_t val3
= aarch64_get_mem_u16 (cpu
, address
+ 4);
11787 uint32_t val4
= aarch64_get_mem_u16 (cpu
, address
+ 6);
11789 for (i
= 0; i
< (full
? 8 : 4); i
++)
11791 aarch64_set_vec_u16 (cpu
, vd
, 0, val1
);
11792 aarch64_set_vec_u16 (cpu
, vd
+ 1, 0, val2
);
11793 aarch64_set_vec_u16 (cpu
, vd
+ 2, 0, val3
);
11794 aarch64_set_vec_u16 (cpu
, vd
+ 3, 0, val4
);
11801 uint32_t val1
= aarch64_get_mem_u32 (cpu
, address
);
11802 uint32_t val2
= aarch64_get_mem_u32 (cpu
, address
+ 4);
11803 uint32_t val3
= aarch64_get_mem_u32 (cpu
, address
+ 8);
11804 uint32_t val4
= aarch64_get_mem_u32 (cpu
, address
+ 12);
11806 for (i
= 0; i
< (full
? 4 : 2); i
++)
11808 aarch64_set_vec_u32 (cpu
, vd
, 0, val1
);
11809 aarch64_set_vec_u32 (cpu
, vd
+ 1, 0, val2
);
11810 aarch64_set_vec_u32 (cpu
, vd
+ 2, 0, val3
);
11811 aarch64_set_vec_u32 (cpu
, vd
+ 3, 0, val4
);
11818 uint64_t val1
= aarch64_get_mem_u64 (cpu
, address
);
11819 uint64_t val2
= aarch64_get_mem_u64 (cpu
, address
+ 8);
11820 uint64_t val3
= aarch64_get_mem_u64 (cpu
, address
+ 16);
11821 uint64_t val4
= aarch64_get_mem_u64 (cpu
, address
+ 24);
11823 for (i
= 0; i
< (full
? 2 : 1); i
++)
11825 aarch64_set_vec_u64 (cpu
, vd
, 0, val1
);
11826 aarch64_set_vec_u64 (cpu
, vd
+ 1, 0, val2
);
11827 aarch64_set_vec_u64 (cpu
, vd
+ 2, 0, val3
);
11828 aarch64_set_vec_u64 (cpu
, vd
+ 3, 0, val4
);
11844 do_vec_load_store (sim_cpu
*cpu
)
11846 /* {LD|ST}<N> {Vd..Vd+N}, vaddr
11849 instr[30] = element selector 0=>half, 1=>all elements
11850 instr[29,25] = 00110
11852 instr[23] = 0=>simple, 1=>post
11853 instr[22] = 0=>store, 1=>load
11854 instr[21] = 0 (LDn) / small(0)-large(1) selector (LDnR)
11855 instr[20,16] = 00000 (simple), Vinc (reg-post-inc, no SP),
11856 11111 (immediate post inc)
11857 instr[15,12] = elements and destinations. eg for load:
11858 0000=>LD4 => load multiple 4-element to
11859 four consecutive registers
11860 0100=>LD3 => load multiple 3-element to
11861 three consecutive registers
11862 1000=>LD2 => load multiple 2-element to
11863 two consecutive registers
11864 0010=>LD1 => load multiple 1-element to
11865 four consecutive registers
11866 0110=>LD1 => load multiple 1-element to
11867 three consecutive registers
11868 1010=>LD1 => load multiple 1-element to
11869 two consecutive registers
11870 0111=>LD1 => load multiple 1-element to
11874 instr[11,10] = element size 00=> byte(b), 01=> half(h),
11875 10=> word(s), 11=> double(d)
11876 instr[9,5] = Vn, can be SP
11885 if (INSTR (31, 31) != 0 || INSTR (29, 25) != 0x06)
11888 type
= INSTR (15, 12);
11889 if (type
!= 0xE && type
!= 0xE && INSTR (21, 21) != 0)
11892 post
= INSTR (23, 23);
11893 load
= INSTR (22, 22);
11895 address
= aarch64_get_reg_u64 (cpu
, vn
, SP_OK
);
11899 unsigned vm
= INSTR (20, 16);
11903 unsigned sizeof_operation
;
11907 case 0: sizeof_operation
= 32; break;
11908 case 4: sizeof_operation
= 24; break;
11909 case 8: sizeof_operation
= 16; break;
11912 sizeof_operation
= INSTR (21, 21) ? 2 : 1;
11913 sizeof_operation
<<= INSTR (11, 10);
11917 sizeof_operation
= INSTR (21, 21) ? 8 : 4;
11918 sizeof_operation
<<= INSTR (11, 10);
11922 /* One register, immediate offset variant. */
11923 sizeof_operation
= 8;
11927 /* Two registers, immediate offset variant. */
11928 sizeof_operation
= 16;
11932 /* Three registers, immediate offset variant. */
11933 sizeof_operation
= 24;
11937 /* Four registers, immediate offset variant. */
11938 sizeof_operation
= 32;
11945 if (INSTR (30, 30))
11946 sizeof_operation
*= 2;
11948 aarch64_set_reg_u64 (cpu
, vn
, SP_OK
, address
+ sizeof_operation
);
11951 aarch64_set_reg_u64 (cpu
, vn
, SP_OK
,
11952 address
+ aarch64_get_reg_u64 (cpu
, vm
, NO_SP
));
11956 NYI_assert (20, 16, 0);
11963 case 0: LD4 (cpu
, address
); return;
11964 case 4: LD3 (cpu
, address
); return;
11965 case 8: LD2 (cpu
, address
); return;
11966 case 2: LD1_4 (cpu
, address
); return;
11967 case 6: LD1_3 (cpu
, address
); return;
11968 case 10: LD1_2 (cpu
, address
); return;
11969 case 7: LD1_1 (cpu
, address
); return;
11972 case 0xC: do_vec_LDnR (cpu
, address
); return;
11982 case 0: ST4 (cpu
, address
); return;
11983 case 4: ST3 (cpu
, address
); return;
11984 case 8: ST2 (cpu
, address
); return;
11985 case 2: ST1_4 (cpu
, address
); return;
11986 case 6: ST1_3 (cpu
, address
); return;
11987 case 10: ST1_2 (cpu
, address
); return;
11988 case 7: ST1_1 (cpu
, address
); return;
11995 dexLdSt (sim_cpu
*cpu
)
11997 /* uint32_t group = dispatchGroup (aarch64_get_instr (cpu));
11998 assert group == GROUP_LDST_0100 || group == GROUP_LDST_0110 ||
11999 group == GROUP_LDST_1100 || group == GROUP_LDST_1110
12000 bits [29,28:26] of a LS are the secondary dispatch vector. */
12001 uint32_t group2
= dispatchLS (aarch64_get_instr (cpu
));
12006 dexLoadExclusive (cpu
); return;
12010 dexLoadLiteral (cpu
); return;
12014 dexLoadOther (cpu
); return;
12016 case LS_ADVSIMD_001
:
12017 do_vec_load_store (cpu
); return;
12020 dex_load_store_pair_gr (cpu
); return;
12023 dex_load_store_pair_fp (cpu
); return;
12026 /* Should never reach here. */
12031 /* Specific decode and execute for group Data Processing Register. */
12034 dexLogicalShiftedRegister (sim_cpu
*cpu
)
12036 /* instr[31] = size : 0 ==> 32 bit, 1 ==> 64 bit
12038 instr[28:24] = 01010
12039 instr[23,22] = shift : 0 ==> LSL, 1 ==> LSR, 2 ==> ASR, 3 ==> ROR
12042 instr[15,10] = count : must be 0xxxxx for 32 bit
12046 uint32_t size
= INSTR (31, 31);
12047 Shift shiftType
= INSTR (23, 22);
12048 uint32_t count
= INSTR (15, 10);
12050 /* 32 bit operations must have count[5] = 0.
12051 or else we have an UNALLOC. */
12052 if (size
== 0 && uimm (count
, 5, 5))
12055 /* Dispatch on size:op:N. */
12056 switch ((INSTR (31, 29) << 1) | INSTR (21, 21))
12058 case 0: and32_shift (cpu
, shiftType
, count
); return;
12059 case 1: bic32_shift (cpu
, shiftType
, count
); return;
12060 case 2: orr32_shift (cpu
, shiftType
, count
); return;
12061 case 3: orn32_shift (cpu
, shiftType
, count
); return;
12062 case 4: eor32_shift (cpu
, shiftType
, count
); return;
12063 case 5: eon32_shift (cpu
, shiftType
, count
); return;
12064 case 6: ands32_shift (cpu
, shiftType
, count
); return;
12065 case 7: bics32_shift (cpu
, shiftType
, count
); return;
12066 case 8: and64_shift (cpu
, shiftType
, count
); return;
12067 case 9: bic64_shift (cpu
, shiftType
, count
); return;
12068 case 10:orr64_shift (cpu
, shiftType
, count
); return;
12069 case 11:orn64_shift (cpu
, shiftType
, count
); return;
12070 case 12:eor64_shift (cpu
, shiftType
, count
); return;
12071 case 13:eon64_shift (cpu
, shiftType
, count
); return;
12072 case 14:ands64_shift (cpu
, shiftType
, count
); return;
12073 case 15:bics64_shift (cpu
, shiftType
, count
); return;
12077 /* 32 bit conditional select. */
12079 csel32 (sim_cpu
*cpu
, CondCode cc
)
12081 unsigned rm
= INSTR (20, 16);
12082 unsigned rn
= INSTR (9, 5);
12083 unsigned rd
= INSTR (4, 0);
12085 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
,
12086 testConditionCode (cpu
, cc
)
12087 ? aarch64_get_reg_u32 (cpu
, rn
, NO_SP
)
12088 : aarch64_get_reg_u32 (cpu
, rm
, NO_SP
));
12091 /* 64 bit conditional select. */
12093 csel64 (sim_cpu
*cpu
, CondCode cc
)
12095 unsigned rm
= INSTR (20, 16);
12096 unsigned rn
= INSTR (9, 5);
12097 unsigned rd
= INSTR (4, 0);
12099 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
,
12100 testConditionCode (cpu
, cc
)
12101 ? aarch64_get_reg_u64 (cpu
, rn
, NO_SP
)
12102 : aarch64_get_reg_u64 (cpu
, rm
, NO_SP
));
12105 /* 32 bit conditional increment. */
12107 csinc32 (sim_cpu
*cpu
, CondCode cc
)
12109 unsigned rm
= INSTR (20, 16);
12110 unsigned rn
= INSTR (9, 5);
12111 unsigned rd
= INSTR (4, 0);
12113 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
,
12114 testConditionCode (cpu
, cc
)
12115 ? aarch64_get_reg_u32 (cpu
, rn
, NO_SP
)
12116 : aarch64_get_reg_u32 (cpu
, rm
, NO_SP
) + 1);
12119 /* 64 bit conditional increment. */
12121 csinc64 (sim_cpu
*cpu
, CondCode cc
)
12123 unsigned rm
= INSTR (20, 16);
12124 unsigned rn
= INSTR (9, 5);
12125 unsigned rd
= INSTR (4, 0);
12127 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
,
12128 testConditionCode (cpu
, cc
)
12129 ? aarch64_get_reg_u64 (cpu
, rn
, NO_SP
)
12130 : aarch64_get_reg_u64 (cpu
, rm
, NO_SP
) + 1);
12133 /* 32 bit conditional invert. */
12135 csinv32 (sim_cpu
*cpu
, CondCode cc
)
12137 unsigned rm
= INSTR (20, 16);
12138 unsigned rn
= INSTR (9, 5);
12139 unsigned rd
= INSTR (4, 0);
12141 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
,
12142 testConditionCode (cpu
, cc
)
12143 ? aarch64_get_reg_u32 (cpu
, rn
, NO_SP
)
12144 : ~ aarch64_get_reg_u32 (cpu
, rm
, NO_SP
));
12147 /* 64 bit conditional invert. */
12149 csinv64 (sim_cpu
*cpu
, CondCode cc
)
12151 unsigned rm
= INSTR (20, 16);
12152 unsigned rn
= INSTR (9, 5);
12153 unsigned rd
= INSTR (4, 0);
12155 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
,
12156 testConditionCode (cpu
, cc
)
12157 ? aarch64_get_reg_u64 (cpu
, rn
, NO_SP
)
12158 : ~ aarch64_get_reg_u64 (cpu
, rm
, NO_SP
));
12161 /* 32 bit conditional negate. */
12163 csneg32 (sim_cpu
*cpu
, CondCode cc
)
12165 unsigned rm
= INSTR (20, 16);
12166 unsigned rn
= INSTR (9, 5);
12167 unsigned rd
= INSTR (4, 0);
12169 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
,
12170 testConditionCode (cpu
, cc
)
12171 ? aarch64_get_reg_u32 (cpu
, rn
, NO_SP
)
12172 : - aarch64_get_reg_u32 (cpu
, rm
, NO_SP
));
12175 /* 64 bit conditional negate. */
12177 csneg64 (sim_cpu
*cpu
, CondCode cc
)
12179 unsigned rm
= INSTR (20, 16);
12180 unsigned rn
= INSTR (9, 5);
12181 unsigned rd
= INSTR (4, 0);
12183 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
,
12184 testConditionCode (cpu
, cc
)
12185 ? aarch64_get_reg_u64 (cpu
, rn
, NO_SP
)
12186 : - aarch64_get_reg_u64 (cpu
, rm
, NO_SP
));
12190 dexCondSelect (sim_cpu
*cpu
)
12192 /* instr[28,21] = 11011011
12193 instr[31] = size : 0 ==> 32 bit, 1 ==> 64 bit
12194 instr[30:11,10] = op : 000 ==> CSEL, 001 ==> CSINC,
12195 100 ==> CSINV, 101 ==> CSNEG,
12197 instr[29] = S : 0 ==> ok, 1 ==> UNALLOC
12198 instr[15,12] = cond
12199 instr[29] = S : 0 ==> ok, 1 ==> UNALLOC */
12201 CondCode cc
= INSTR (15, 12);
12202 uint32_t S
= INSTR (29, 29);
12203 uint32_t op2
= INSTR (11, 10);
12211 switch ((INSTR (31, 30) << 1) | op2
)
12213 case 0: csel32 (cpu
, cc
); return;
12214 case 1: csinc32 (cpu
, cc
); return;
12215 case 2: csinv32 (cpu
, cc
); return;
12216 case 3: csneg32 (cpu
, cc
); return;
12217 case 4: csel64 (cpu
, cc
); return;
12218 case 5: csinc64 (cpu
, cc
); return;
12219 case 6: csinv64 (cpu
, cc
); return;
12220 case 7: csneg64 (cpu
, cc
); return;
12224 /* Some helpers for counting leading 1 or 0 bits. */
12226 /* Counts the number of leading bits which are the same
12227 in a 32 bit value in the range 1 to 32. */
12229 leading32 (uint32_t value
)
12231 int32_t mask
= 0xffff0000;
12232 uint32_t count
= 16; /* Counts number of bits set in mask. */
12233 uint32_t lo
= 1; /* Lower bound for number of sign bits. */
12234 uint32_t hi
= 32; /* Upper bound for number of sign bits. */
12236 while (lo
+ 1 < hi
)
12238 int32_t test
= (value
& mask
);
12240 if (test
== 0 || test
== mask
)
12243 count
= (lo
+ hi
) / 2;
12244 mask
>>= (count
- lo
);
12249 count
= (lo
+ hi
) / 2;
12250 mask
<<= hi
- count
;
12259 test
= (value
& mask
);
12261 if (test
== 0 || test
== mask
)
12270 /* Counts the number of leading bits which are the same
12271 in a 64 bit value in the range 1 to 64. */
12273 leading64 (uint64_t value
)
12275 int64_t mask
= 0xffffffff00000000LL
;
12276 uint64_t count
= 32; /* Counts number of bits set in mask. */
12277 uint64_t lo
= 1; /* Lower bound for number of sign bits. */
12278 uint64_t hi
= 64; /* Upper bound for number of sign bits. */
12280 while (lo
+ 1 < hi
)
12282 int64_t test
= (value
& mask
);
12284 if (test
== 0 || test
== mask
)
12287 count
= (lo
+ hi
) / 2;
12288 mask
>>= (count
- lo
);
12293 count
= (lo
+ hi
) / 2;
12294 mask
<<= hi
- count
;
12303 test
= (value
& mask
);
12305 if (test
== 0 || test
== mask
)
12314 /* Bit operations. */
12315 /* N.B register args may not be SP. */
12317 /* 32 bit count leading sign bits. */
12319 cls32 (sim_cpu
*cpu
)
12321 unsigned rn
= INSTR (9, 5);
12322 unsigned rd
= INSTR (4, 0);
12324 /* N.B. the result needs to exclude the leading bit. */
12325 aarch64_set_reg_u64
12326 (cpu
, rd
, NO_SP
, leading32 (aarch64_get_reg_u32 (cpu
, rn
, NO_SP
)) - 1);
12329 /* 64 bit count leading sign bits. */
12331 cls64 (sim_cpu
*cpu
)
12333 unsigned rn
= INSTR (9, 5);
12334 unsigned rd
= INSTR (4, 0);
12336 /* N.B. the result needs to exclude the leading bit. */
12337 aarch64_set_reg_u64
12338 (cpu
, rd
, NO_SP
, leading64 (aarch64_get_reg_u64 (cpu
, rn
, NO_SP
)) - 1);
12341 /* 32 bit count leading zero bits. */
12343 clz32 (sim_cpu
*cpu
)
12345 unsigned rn
= INSTR (9, 5);
12346 unsigned rd
= INSTR (4, 0);
12347 uint32_t value
= aarch64_get_reg_u32 (cpu
, rn
, NO_SP
);
12349 /* if the sign (top) bit is set then the count is 0. */
12350 if (pick32 (value
, 31, 31))
12351 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, 0L);
12353 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, leading32 (value
));
12356 /* 64 bit count leading zero bits. */
12358 clz64 (sim_cpu
*cpu
)
12360 unsigned rn
= INSTR (9, 5);
12361 unsigned rd
= INSTR (4, 0);
12362 uint64_t value
= aarch64_get_reg_u64 (cpu
, rn
, NO_SP
);
12364 /* if the sign (top) bit is set then the count is 0. */
12365 if (pick64 (value
, 63, 63))
12366 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, 0L);
12368 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, leading64 (value
));
12371 /* 32 bit reverse bits. */
12373 rbit32 (sim_cpu
*cpu
)
12375 unsigned rn
= INSTR (9, 5);
12376 unsigned rd
= INSTR (4, 0);
12377 uint32_t value
= aarch64_get_reg_u32 (cpu
, rn
, NO_SP
);
12378 uint32_t result
= 0;
12381 for (i
= 0; i
< 32; i
++)
12384 result
|= (value
& 1);
12387 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, result
);
12390 /* 64 bit reverse bits. */
12392 rbit64 (sim_cpu
*cpu
)
12394 unsigned rn
= INSTR (9, 5);
12395 unsigned rd
= INSTR (4, 0);
12396 uint64_t value
= aarch64_get_reg_u64 (cpu
, rn
, NO_SP
);
12397 uint64_t result
= 0;
12400 for (i
= 0; i
< 64; i
++)
12403 result
|= (value
& 1UL);
12406 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, result
);
12409 /* 32 bit reverse bytes. */
12411 rev32 (sim_cpu
*cpu
)
12413 unsigned rn
= INSTR (9, 5);
12414 unsigned rd
= INSTR (4, 0);
12415 uint32_t value
= aarch64_get_reg_u32 (cpu
, rn
, NO_SP
);
12416 uint32_t result
= 0;
12419 for (i
= 0; i
< 4; i
++)
12422 result
|= (value
& 0xff);
12425 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, result
);
12428 /* 64 bit reverse bytes. */
12430 rev64 (sim_cpu
*cpu
)
12432 unsigned rn
= INSTR (9, 5);
12433 unsigned rd
= INSTR (4, 0);
12434 uint64_t value
= aarch64_get_reg_u64 (cpu
, rn
, NO_SP
);
12435 uint64_t result
= 0;
12438 for (i
= 0; i
< 8; i
++)
12441 result
|= (value
& 0xffULL
);
12444 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, result
);
12447 /* 32 bit reverse shorts. */
12448 /* N.B.this reverses the order of the bytes in each half word. */
12450 revh32 (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
< 2; i
++)
12461 result
|= (value
& 0x00ff00ff);
12464 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, result
);
12467 /* 64 bit reverse shorts. */
12468 /* N.B.this reverses the order of the bytes in each half word. */
12470 revh64 (sim_cpu
*cpu
)
12472 unsigned rn
= INSTR (9, 5);
12473 unsigned rd
= INSTR (4, 0);
12474 uint64_t value
= aarch64_get_reg_u64 (cpu
, rn
, NO_SP
);
12475 uint64_t result
= 0;
12478 for (i
= 0; i
< 2; i
++)
12481 result
|= (value
& 0x00ff00ff00ff00ffULL
);
12484 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, result
);
12488 dexDataProc1Source (sim_cpu
*cpu
)
12491 instr[28,21] = 111010110
12492 instr[31] = size : 0 ==> 32 bit, 1 ==> 64 bit
12493 instr[29] = S : 0 ==> ok, 1 ==> UNALLOC
12494 instr[20,16] = opcode2 : 00000 ==> ok, ow ==> UNALLOC
12495 instr[15,10] = opcode : 000000 ==> RBIT, 000001 ==> REV16,
12496 000010 ==> REV, 000011 ==> UNALLOC
12497 000100 ==> CLZ, 000101 ==> CLS
12499 instr[9,5] = rn : may not be SP
12500 instr[4,0] = rd : may not be SP. */
12502 uint32_t S
= INSTR (29, 29);
12503 uint32_t opcode2
= INSTR (20, 16);
12504 uint32_t opcode
= INSTR (15, 10);
12505 uint32_t dispatch
= ((INSTR (31, 31) << 3) | opcode
);
12518 case 0: rbit32 (cpu
); return;
12519 case 1: revh32 (cpu
); return;
12520 case 2: rev32 (cpu
); return;
12521 case 4: clz32 (cpu
); return;
12522 case 5: cls32 (cpu
); return;
12523 case 8: rbit64 (cpu
); return;
12524 case 9: revh64 (cpu
); return;
12525 case 10:rev32 (cpu
); return;
12526 case 11:rev64 (cpu
); return;
12527 case 12:clz64 (cpu
); return;
12528 case 13:cls64 (cpu
); return;
12529 default: HALT_UNALLOC
;
12534 Shifts by count supplied in register.
12535 N.B register args may not be SP.
12536 These all use the shifted auxiliary function for
12537 simplicity and clarity. Writing the actual shift
12538 inline would avoid a branch and so be faster but
12539 would also necessitate getting signs right. */
12541 /* 32 bit arithmetic shift right. */
12543 asrv32 (sim_cpu
*cpu
)
12545 unsigned rm
= INSTR (20, 16);
12546 unsigned rn
= INSTR (9, 5);
12547 unsigned rd
= INSTR (4, 0);
12549 aarch64_set_reg_u64
12551 shifted32 (aarch64_get_reg_u32 (cpu
, rn
, NO_SP
), ASR
,
12552 (aarch64_get_reg_u32 (cpu
, rm
, NO_SP
) & 0x1f)));
12555 /* 64 bit arithmetic shift right. */
12557 asrv64 (sim_cpu
*cpu
)
12559 unsigned rm
= INSTR (20, 16);
12560 unsigned rn
= INSTR (9, 5);
12561 unsigned rd
= INSTR (4, 0);
12563 aarch64_set_reg_u64
12565 shifted64 (aarch64_get_reg_u64 (cpu
, rn
, NO_SP
), ASR
,
12566 (aarch64_get_reg_u64 (cpu
, rm
, NO_SP
) & 0x3f)));
12569 /* 32 bit logical shift left. */
12571 lslv32 (sim_cpu
*cpu
)
12573 unsigned rm
= INSTR (20, 16);
12574 unsigned rn
= INSTR (9, 5);
12575 unsigned rd
= INSTR (4, 0);
12577 aarch64_set_reg_u64
12579 shifted32 (aarch64_get_reg_u32 (cpu
, rn
, NO_SP
), LSL
,
12580 (aarch64_get_reg_u32 (cpu
, rm
, NO_SP
) & 0x1f)));
12583 /* 64 bit arithmetic shift left. */
12585 lslv64 (sim_cpu
*cpu
)
12587 unsigned rm
= INSTR (20, 16);
12588 unsigned rn
= INSTR (9, 5);
12589 unsigned rd
= INSTR (4, 0);
12591 aarch64_set_reg_u64
12593 shifted64 (aarch64_get_reg_u64 (cpu
, rn
, NO_SP
), LSL
,
12594 (aarch64_get_reg_u64 (cpu
, rm
, NO_SP
) & 0x3f)));
12597 /* 32 bit logical shift right. */
12599 lsrv32 (sim_cpu
*cpu
)
12601 unsigned rm
= INSTR (20, 16);
12602 unsigned rn
= INSTR (9, 5);
12603 unsigned rd
= INSTR (4, 0);
12605 aarch64_set_reg_u64
12607 shifted32 (aarch64_get_reg_u32 (cpu
, rn
, NO_SP
), LSR
,
12608 (aarch64_get_reg_u32 (cpu
, rm
, NO_SP
) & 0x1f)));
12611 /* 64 bit logical shift right. */
12613 lsrv64 (sim_cpu
*cpu
)
12615 unsigned rm
= INSTR (20, 16);
12616 unsigned rn
= INSTR (9, 5);
12617 unsigned rd
= INSTR (4, 0);
12619 aarch64_set_reg_u64
12621 shifted64 (aarch64_get_reg_u64 (cpu
, rn
, NO_SP
), LSR
,
12622 (aarch64_get_reg_u64 (cpu
, rm
, NO_SP
) & 0x3f)));
12625 /* 32 bit rotate right. */
12627 rorv32 (sim_cpu
*cpu
)
12629 unsigned rm
= INSTR (20, 16);
12630 unsigned rn
= INSTR (9, 5);
12631 unsigned rd
= INSTR (4, 0);
12633 aarch64_set_reg_u64
12635 shifted32 (aarch64_get_reg_u32 (cpu
, rn
, NO_SP
), ROR
,
12636 (aarch64_get_reg_u32 (cpu
, rm
, NO_SP
) & 0x1f)));
12639 /* 64 bit rotate right. */
12641 rorv64 (sim_cpu
*cpu
)
12643 unsigned rm
= INSTR (20, 16);
12644 unsigned rn
= INSTR (9, 5);
12645 unsigned rd
= INSTR (4, 0);
12647 aarch64_set_reg_u64
12649 shifted64 (aarch64_get_reg_u64 (cpu
, rn
, NO_SP
), ROR
,
12650 (aarch64_get_reg_u64 (cpu
, rm
, NO_SP
) & 0x3f)));
12656 /* 32 bit signed divide. */
12658 cpuiv32 (sim_cpu
*cpu
)
12660 unsigned rm
= INSTR (20, 16);
12661 unsigned rn
= INSTR (9, 5);
12662 unsigned rd
= INSTR (4, 0);
12663 /* N.B. the pseudo-code does the divide using 64 bit data. */
12664 /* TODO : check that this rounds towards zero as required. */
12665 int64_t dividend
= aarch64_get_reg_s32 (cpu
, rn
, NO_SP
);
12666 int64_t divisor
= aarch64_get_reg_s32 (cpu
, rm
, NO_SP
);
12668 aarch64_set_reg_s64 (cpu
, rd
, NO_SP
,
12669 divisor
? ((int32_t) (dividend
/ divisor
)) : 0);
12672 /* 64 bit signed divide. */
12674 cpuiv64 (sim_cpu
*cpu
)
12676 unsigned rm
= INSTR (20, 16);
12677 unsigned rn
= INSTR (9, 5);
12678 unsigned rd
= INSTR (4, 0);
12680 /* TODO : check that this rounds towards zero as required. */
12681 int64_t divisor
= aarch64_get_reg_s64 (cpu
, rm
, NO_SP
);
12683 aarch64_set_reg_s64
12685 divisor
? (aarch64_get_reg_s64 (cpu
, rn
, NO_SP
) / divisor
) : 0);
12688 /* 32 bit unsigned divide. */
12690 udiv32 (sim_cpu
*cpu
)
12692 unsigned rm
= INSTR (20, 16);
12693 unsigned rn
= INSTR (9, 5);
12694 unsigned rd
= INSTR (4, 0);
12696 /* N.B. the pseudo-code does the divide using 64 bit data. */
12697 uint64_t dividend
= aarch64_get_reg_u32 (cpu
, rn
, NO_SP
);
12698 uint64_t divisor
= aarch64_get_reg_u32 (cpu
, rm
, NO_SP
);
12700 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
,
12701 divisor
? (uint32_t) (dividend
/ divisor
) : 0);
12704 /* 64 bit unsigned divide. */
12706 udiv64 (sim_cpu
*cpu
)
12708 unsigned rm
= INSTR (20, 16);
12709 unsigned rn
= INSTR (9, 5);
12710 unsigned rd
= INSTR (4, 0);
12712 /* TODO : check that this rounds towards zero as required. */
12713 uint64_t divisor
= aarch64_get_reg_u64 (cpu
, rm
, NO_SP
);
12715 aarch64_set_reg_u64
12717 divisor
? (aarch64_get_reg_u64 (cpu
, rn
, NO_SP
) / divisor
) : 0);
12721 dexDataProc2Source (sim_cpu
*cpu
)
12723 /* assert instr[30] == 0
12724 instr[28,21] == 11010110
12725 instr[31] = size : 0 ==> 32 bit, 1 ==> 64 bit
12726 instr[29] = S : 0 ==> ok, 1 ==> UNALLOC
12727 instr[15,10] = opcode : 000010 ==> UDIV, 000011 ==> CPUIV,
12728 001000 ==> LSLV, 001001 ==> LSRV
12729 001010 ==> ASRV, 001011 ==> RORV
12733 uint32_t S
= INSTR (29, 29);
12734 uint32_t opcode
= INSTR (15, 10);
12742 dispatch
= ( (INSTR (31, 31) << 3)
12743 | (uimm (opcode
, 3, 3) << 2)
12744 | uimm (opcode
, 1, 0));
12747 case 2: udiv32 (cpu
); return;
12748 case 3: cpuiv32 (cpu
); return;
12749 case 4: lslv32 (cpu
); return;
12750 case 5: lsrv32 (cpu
); return;
12751 case 6: asrv32 (cpu
); return;
12752 case 7: rorv32 (cpu
); return;
12753 case 10: udiv64 (cpu
); return;
12754 case 11: cpuiv64 (cpu
); return;
12755 case 12: lslv64 (cpu
); return;
12756 case 13: lsrv64 (cpu
); return;
12757 case 14: asrv64 (cpu
); return;
12758 case 15: rorv64 (cpu
); return;
12759 default: HALT_UNALLOC
;
12766 /* 32 bit multiply and add. */
12768 madd32 (sim_cpu
*cpu
)
12770 unsigned rm
= INSTR (20, 16);
12771 unsigned ra
= INSTR (14, 10);
12772 unsigned rn
= INSTR (9, 5);
12773 unsigned rd
= INSTR (4, 0);
12775 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
12776 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
,
12777 aarch64_get_reg_u32 (cpu
, ra
, NO_SP
)
12778 + aarch64_get_reg_u32 (cpu
, rn
, NO_SP
)
12779 * aarch64_get_reg_u32 (cpu
, rm
, NO_SP
));
12782 /* 64 bit multiply and add. */
12784 madd64 (sim_cpu
*cpu
)
12786 unsigned rm
= INSTR (20, 16);
12787 unsigned ra
= INSTR (14, 10);
12788 unsigned rn
= INSTR (9, 5);
12789 unsigned rd
= INSTR (4, 0);
12791 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
12792 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
,
12793 aarch64_get_reg_u64 (cpu
, ra
, NO_SP
)
12794 + (aarch64_get_reg_u64 (cpu
, rn
, NO_SP
)
12795 * aarch64_get_reg_u64 (cpu
, rm
, NO_SP
)));
12798 /* 32 bit multiply and sub. */
12800 msub32 (sim_cpu
*cpu
)
12802 unsigned rm
= INSTR (20, 16);
12803 unsigned ra
= INSTR (14, 10);
12804 unsigned rn
= INSTR (9, 5);
12805 unsigned rd
= INSTR (4, 0);
12807 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
12808 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
,
12809 aarch64_get_reg_u32 (cpu
, ra
, NO_SP
)
12810 - aarch64_get_reg_u32 (cpu
, rn
, NO_SP
)
12811 * aarch64_get_reg_u32 (cpu
, rm
, NO_SP
));
12814 /* 64 bit multiply and sub. */
12816 msub64 (sim_cpu
*cpu
)
12818 unsigned rm
= INSTR (20, 16);
12819 unsigned ra
= INSTR (14, 10);
12820 unsigned rn
= INSTR (9, 5);
12821 unsigned rd
= INSTR (4, 0);
12823 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
12824 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
,
12825 aarch64_get_reg_u64 (cpu
, ra
, NO_SP
)
12826 - aarch64_get_reg_u64 (cpu
, rn
, NO_SP
)
12827 * aarch64_get_reg_u64 (cpu
, rm
, NO_SP
));
12830 /* Signed multiply add long -- source, source2 : 32 bit, source3 : 64 bit. */
12832 smaddl (sim_cpu
*cpu
)
12834 unsigned rm
= INSTR (20, 16);
12835 unsigned ra
= INSTR (14, 10);
12836 unsigned rn
= INSTR (9, 5);
12837 unsigned rd
= INSTR (4, 0);
12839 /* N.B. we need to multiply the signed 32 bit values in rn, rm to
12840 obtain a 64 bit product. */
12841 aarch64_set_reg_s64
12843 aarch64_get_reg_s64 (cpu
, ra
, NO_SP
)
12844 + ((int64_t) aarch64_get_reg_s32 (cpu
, rn
, NO_SP
))
12845 * ((int64_t) aarch64_get_reg_s32 (cpu
, rm
, NO_SP
)));
12848 /* Signed multiply sub long -- source, source2 : 32 bit, source3 : 64 bit. */
12850 smsubl (sim_cpu
*cpu
)
12852 unsigned rm
= INSTR (20, 16);
12853 unsigned ra
= INSTR (14, 10);
12854 unsigned rn
= INSTR (9, 5);
12855 unsigned rd
= INSTR (4, 0);
12857 /* N.B. we need to multiply the signed 32 bit values in rn, rm to
12858 obtain a 64 bit product. */
12859 aarch64_set_reg_s64
12861 aarch64_get_reg_s64 (cpu
, ra
, NO_SP
)
12862 - ((int64_t) aarch64_get_reg_s32 (cpu
, rn
, NO_SP
))
12863 * ((int64_t) aarch64_get_reg_s32 (cpu
, rm
, NO_SP
)));
12866 /* Integer Multiply/Divide. */
12868 /* First some macros and a helper function. */
12869 /* Macros to test or access elements of 64 bit words. */
12871 /* Mask used to access lo 32 bits of 64 bit unsigned int. */
12872 #define LOW_WORD_MASK ((1ULL << 32) - 1)
12873 /* Return the lo 32 bit word of a 64 bit unsigned int as a 64 bit unsigned int. */
12874 #define lowWordToU64(_value_u64) ((_value_u64) & LOW_WORD_MASK)
12875 /* Return the hi 32 bit word of a 64 bit unsigned int as a 64 bit unsigned int. */
12876 #define highWordToU64(_value_u64) ((_value_u64) >> 32)
12878 /* Offset of sign bit in 64 bit signed integger. */
12879 #define SIGN_SHIFT_U64 63
12880 /* The sign bit itself -- also identifies the minimum negative int value. */
12881 #define SIGN_BIT_U64 (1UL << SIGN_SHIFT_U64)
12882 /* Return true if a 64 bit signed int presented as an unsigned int is the
12883 most negative value. */
12884 #define isMinimumU64(_value_u64) ((_value_u64) == SIGN_BIT_U64)
12885 /* Return true (non-zero) if a 64 bit signed int presented as an unsigned
12886 int has its sign bit set to false. */
12887 #define isSignSetU64(_value_u64) ((_value_u64) & SIGN_BIT_U64)
12888 /* Return 1L or -1L according to whether a 64 bit signed int presented as
12889 an unsigned int has its sign bit set or not. */
12890 #define signOfU64(_value_u64) (1L + (((value_u64) >> SIGN_SHIFT_U64) * -2L)
12891 /* Clear the sign bit of a 64 bit signed int presented as an unsigned int. */
12892 #define clearSignU64(_value_u64) ((_value_u64) &= ~SIGN_BIT_U64)
12894 /* Multiply two 64 bit ints and return.
12895 the hi 64 bits of the 128 bit product. */
12898 mul64hi (uint64_t value1
, uint64_t value2
)
12900 uint64_t resultmid1
;
12902 uint64_t value1_lo
= lowWordToU64 (value1
);
12903 uint64_t value1_hi
= highWordToU64 (value1
) ;
12904 uint64_t value2_lo
= lowWordToU64 (value2
);
12905 uint64_t value2_hi
= highWordToU64 (value2
);
12907 /* Cross-multiply and collect results. */
12908 uint64_t xproductlo
= value1_lo
* value2_lo
;
12909 uint64_t xproductmid1
= value1_lo
* value2_hi
;
12910 uint64_t xproductmid2
= value1_hi
* value2_lo
;
12911 uint64_t xproducthi
= value1_hi
* value2_hi
;
12912 uint64_t carry
= 0;
12913 /* Start accumulating 64 bit results. */
12914 /* Drop bottom half of lowest cross-product. */
12915 uint64_t resultmid
= xproductlo
>> 32;
12916 /* Add in middle products. */
12917 resultmid
= resultmid
+ xproductmid1
;
12919 /* Check for overflow. */
12920 if (resultmid
< xproductmid1
)
12921 /* Carry over 1 into top cross-product. */
12924 resultmid1
= resultmid
+ xproductmid2
;
12926 /* Check for overflow. */
12927 if (resultmid1
< xproductmid2
)
12928 /* Carry over 1 into top cross-product. */
12931 /* Drop lowest 32 bits of middle cross-product. */
12932 result
= resultmid1
>> 32;
12934 /* Add top cross-product plus and any carry. */
12935 result
+= xproducthi
+ carry
;
12940 /* Signed multiply high, source, source2 :
12941 64 bit, dest <-- high 64-bit of result. */
12943 smulh (sim_cpu
*cpu
)
12947 unsigned rm
= INSTR (20, 16);
12948 unsigned rn
= INSTR (9, 5);
12949 unsigned rd
= INSTR (4, 0);
12950 GReg ra
= INSTR (14, 10);
12951 int64_t value1
= aarch64_get_reg_u64 (cpu
, rn
, NO_SP
);
12952 int64_t value2
= aarch64_get_reg_u64 (cpu
, rm
, NO_SP
);
12955 int64_t signum
= 1;
12960 /* Convert to unsigned and use the unsigned mul64hi routine
12961 the fix the sign up afterwards. */
12982 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
12983 uresult
= mul64hi (uvalue1
, uvalue2
);
12987 aarch64_set_reg_s64 (cpu
, rd
, NO_SP
, result
);
12990 /* Unsigned multiply add long -- source, source2 :
12991 32 bit, source3 : 64 bit. */
12993 umaddl (sim_cpu
*cpu
)
12995 unsigned rm
= INSTR (20, 16);
12996 unsigned ra
= INSTR (14, 10);
12997 unsigned rn
= INSTR (9, 5);
12998 unsigned rd
= INSTR (4, 0);
13000 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
13001 /* N.B. we need to multiply the signed 32 bit values in rn, rm to
13002 obtain a 64 bit product. */
13003 aarch64_set_reg_u64
13005 aarch64_get_reg_u64 (cpu
, ra
, NO_SP
)
13006 + ((uint64_t) aarch64_get_reg_u32 (cpu
, rn
, NO_SP
))
13007 * ((uint64_t) aarch64_get_reg_u32 (cpu
, rm
, NO_SP
)));
13010 /* Unsigned multiply sub long -- source, source2 : 32 bit, source3 : 64 bit. */
13012 umsubl (sim_cpu
*cpu
)
13014 unsigned rm
= INSTR (20, 16);
13015 unsigned ra
= INSTR (14, 10);
13016 unsigned rn
= INSTR (9, 5);
13017 unsigned rd
= INSTR (4, 0);
13019 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
13020 /* N.B. we need to multiply the signed 32 bit values in rn, rm to
13021 obtain a 64 bit product. */
13022 aarch64_set_reg_u64
13024 aarch64_get_reg_u64 (cpu
, ra
, NO_SP
)
13025 - ((uint64_t) aarch64_get_reg_u32 (cpu
, rn
, NO_SP
))
13026 * ((uint64_t) aarch64_get_reg_u32 (cpu
, rm
, NO_SP
)));
13029 /* Unsigned multiply high, source, source2 :
13030 64 bit, dest <-- high 64-bit of result. */
13032 umulh (sim_cpu
*cpu
)
13034 unsigned rm
= INSTR (20, 16);
13035 unsigned rn
= INSTR (9, 5);
13036 unsigned rd
= INSTR (4, 0);
13037 GReg ra
= INSTR (14, 10);
13042 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
13043 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
,
13044 mul64hi (aarch64_get_reg_u64 (cpu
, rn
, NO_SP
),
13045 aarch64_get_reg_u64 (cpu
, rm
, NO_SP
)));
13049 dexDataProc3Source (sim_cpu
*cpu
)
13051 /* assert instr[28,24] == 11011. */
13052 /* instr[31] = size : 0 ==> 32 bit, 1 ==> 64 bit (for rd at least)
13053 instr[30,29] = op54 : 00 ==> ok, ow ==> UNALLOC
13054 instr[23,21] = op31 : 111 ==> UNALLOC, o2 ==> ok
13055 instr[15] = o0 : 0/1 ==> ok
13056 instr[23,21:15] ==> op : 0000 ==> MADD, 0001 ==> MSUB, (32/64 bit)
13057 0010 ==> SMADDL, 0011 ==> SMSUBL, (64 bit only)
13058 0100 ==> SMULH, (64 bit only)
13059 1010 ==> UMADDL, 1011 ==> UNSUBL, (64 bit only)
13060 1100 ==> UMULH (64 bit only)
13064 uint32_t size
= INSTR (31, 31);
13065 uint32_t op54
= INSTR (30, 29);
13066 uint32_t op31
= INSTR (23, 21);
13067 uint32_t o0
= INSTR (15, 15);
13084 dispatch
= (op31
<< 1) | o0
;
13088 case 0: madd64 (cpu
); return;
13089 case 1: msub64 (cpu
); return;
13090 case 2: smaddl (cpu
); return;
13091 case 3: smsubl (cpu
); return;
13092 case 4: smulh (cpu
); return;
13093 case 10: umaddl (cpu
); return;
13094 case 11: umsubl (cpu
); return;
13095 case 12: umulh (cpu
); return;
13096 default: HALT_UNALLOC
;
13101 dexDPReg (sim_cpu
*cpu
)
13103 /* uint32_t group = dispatchGroup (aarch64_get_instr (cpu));
13104 assert group == GROUP_DPREG_0101 || group == GROUP_DPREG_1101
13105 bits [28:24:21] of a DPReg are the secondary dispatch vector. */
13106 uint32_t group2
= dispatchDPReg (aarch64_get_instr (cpu
));
13110 case DPREG_LOG_000
:
13111 case DPREG_LOG_001
:
13112 dexLogicalShiftedRegister (cpu
); return;
13114 case DPREG_ADDSHF_010
:
13115 dexAddSubtractShiftedRegister (cpu
); return;
13117 case DPREG_ADDEXT_011
:
13118 dexAddSubtractExtendedRegister (cpu
); return;
13120 case DPREG_ADDCOND_100
:
13122 /* This set bundles a variety of different operations. */
13124 /* 1) add/sub w carry. */
13125 uint32_t mask1
= 0x1FE00000U
;
13126 uint32_t val1
= 0x1A000000U
;
13127 /* 2) cond compare register/immediate. */
13128 uint32_t mask2
= 0x1FE00000U
;
13129 uint32_t val2
= 0x1A400000U
;
13130 /* 3) cond select. */
13131 uint32_t mask3
= 0x1FE00000U
;
13132 uint32_t val3
= 0x1A800000U
;
13133 /* 4) data proc 1/2 source. */
13134 uint32_t mask4
= 0x1FE00000U
;
13135 uint32_t val4
= 0x1AC00000U
;
13137 if ((aarch64_get_instr (cpu
) & mask1
) == val1
)
13138 dexAddSubtractWithCarry (cpu
);
13140 else if ((aarch64_get_instr (cpu
) & mask2
) == val2
)
13143 else if ((aarch64_get_instr (cpu
) & mask3
) == val3
)
13144 dexCondSelect (cpu
);
13146 else if ((aarch64_get_instr (cpu
) & mask4
) == val4
)
13148 /* Bit 30 is clear for data proc 2 source
13149 and set for data proc 1 source. */
13150 if (aarch64_get_instr (cpu
) & (1U << 30))
13151 dexDataProc1Source (cpu
);
13153 dexDataProc2Source (cpu
);
13157 /* Should not reach here. */
13163 case DPREG_3SRC_110
:
13164 dexDataProc3Source (cpu
); return;
13166 case DPREG_UNALLOC_101
:
13169 case DPREG_3SRC_111
:
13170 dexDataProc3Source (cpu
); return;
13173 /* Should never reach here. */
13178 /* Unconditional Branch immediate.
13179 Offset is a PC-relative byte offset in the range +/- 128MiB.
13180 The offset is assumed to be raw from the decode i.e. the
13181 simulator is expected to scale them from word offsets to byte. */
13183 /* Unconditional branch. */
13185 buc (sim_cpu
*cpu
, int32_t offset
)
13187 aarch64_set_next_PC_by_offset (cpu
, offset
);
13190 static unsigned stack_depth
= 0;
13192 /* Unconditional branch and link -- writes return PC to LR. */
13194 bl (sim_cpu
*cpu
, int32_t offset
)
13196 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
13197 aarch64_save_LR (cpu
);
13198 aarch64_set_next_PC_by_offset (cpu
, offset
);
13200 if (TRACE_BRANCH_P (cpu
))
13204 " %*scall %" PRIx64
" [%s]"
13205 " [args: %" PRIx64
" %" PRIx64
" %" PRIx64
"]",
13206 stack_depth
, " ", aarch64_get_next_PC (cpu
),
13207 aarch64_get_func (CPU_STATE (cpu
),
13208 aarch64_get_next_PC (cpu
)),
13209 aarch64_get_reg_u64 (cpu
, 0, NO_SP
),
13210 aarch64_get_reg_u64 (cpu
, 1, NO_SP
),
13211 aarch64_get_reg_u64 (cpu
, 2, NO_SP
)
13216 /* Unconditional Branch register.
13217 Branch/return address is in source register. */
13219 /* Unconditional branch. */
13223 unsigned rn
= INSTR (9, 5);
13224 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
13225 aarch64_set_next_PC (cpu
, aarch64_get_reg_u64 (cpu
, rn
, NO_SP
));
13228 /* Unconditional branch and link -- writes return PC to LR. */
13232 unsigned rn
= INSTR (9, 5);
13234 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
13235 /* The pseudo code in the spec says we update LR before fetching.
13236 the value from the rn. */
13237 aarch64_save_LR (cpu
);
13238 aarch64_set_next_PC (cpu
, aarch64_get_reg_u64 (cpu
, rn
, NO_SP
));
13240 if (TRACE_BRANCH_P (cpu
))
13244 " %*scall %" PRIx64
" [%s]"
13245 " [args: %" PRIx64
" %" PRIx64
" %" PRIx64
"]",
13246 stack_depth
, " ", aarch64_get_next_PC (cpu
),
13247 aarch64_get_func (CPU_STATE (cpu
),
13248 aarch64_get_next_PC (cpu
)),
13249 aarch64_get_reg_u64 (cpu
, 0, NO_SP
),
13250 aarch64_get_reg_u64 (cpu
, 1, NO_SP
),
13251 aarch64_get_reg_u64 (cpu
, 2, NO_SP
)
13256 /* Return -- assembler will default source to LR this is functionally
13257 equivalent to br but, presumably, unlike br it side effects the
13258 branch predictor. */
13262 unsigned rn
= INSTR (9, 5);
13263 aarch64_set_next_PC (cpu
, aarch64_get_reg_u64 (cpu
, rn
, NO_SP
));
13265 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
13266 if (TRACE_BRANCH_P (cpu
))
13269 " %*sreturn [result: %" PRIx64
"]",
13270 stack_depth
, " ", aarch64_get_reg_u64 (cpu
, 0, NO_SP
));
13275 /* NOP -- we implement this and call it from the decode in case we
13276 want to intercept it later. */
13281 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
13284 /* Data synchronization barrier. */
13289 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
13292 /* Data memory barrier. */
13297 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
13300 /* Instruction synchronization barrier. */
13305 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
13309 dexBranchImmediate (sim_cpu
*cpu
)
13311 /* assert instr[30,26] == 00101
13312 instr[31] ==> 0 == B, 1 == BL
13313 instr[25,0] == imm26 branch offset counted in words. */
13315 uint32_t top
= INSTR (31, 31);
13316 /* We have a 26 byte signed word offset which we need to pass to the
13317 execute routine as a signed byte offset. */
13318 int32_t offset
= simm32 (aarch64_get_instr (cpu
), 25, 0) << 2;
13326 /* Control Flow. */
13328 /* Conditional branch
13330 Offset is a PC-relative byte offset in the range +/- 1MiB pos is
13331 a bit position in the range 0 .. 63
13333 cc is a CondCode enum value as pulled out of the decode
13335 N.B. any offset register (source) can only be Xn or Wn. */
13338 bcc (sim_cpu
*cpu
, int32_t offset
, CondCode cc
)
13340 /* The test returns TRUE if CC is met. */
13341 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
13342 if (testConditionCode (cpu
, cc
))
13343 aarch64_set_next_PC_by_offset (cpu
, offset
);
13346 /* 32 bit branch on register non-zero. */
13348 cbnz32 (sim_cpu
*cpu
, int32_t offset
)
13350 unsigned rt
= INSTR (4, 0);
13352 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
13353 if (aarch64_get_reg_u32 (cpu
, rt
, NO_SP
) != 0)
13354 aarch64_set_next_PC_by_offset (cpu
, offset
);
13357 /* 64 bit branch on register zero. */
13359 cbnz (sim_cpu
*cpu
, int32_t offset
)
13361 unsigned rt
= INSTR (4, 0);
13363 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
13364 if (aarch64_get_reg_u64 (cpu
, rt
, NO_SP
) != 0)
13365 aarch64_set_next_PC_by_offset (cpu
, offset
);
13368 /* 32 bit branch on register non-zero. */
13370 cbz32 (sim_cpu
*cpu
, int32_t offset
)
13372 unsigned rt
= INSTR (4, 0);
13374 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
13375 if (aarch64_get_reg_u32 (cpu
, rt
, NO_SP
) == 0)
13376 aarch64_set_next_PC_by_offset (cpu
, offset
);
13379 /* 64 bit branch on register zero. */
13381 cbz (sim_cpu
*cpu
, int32_t offset
)
13383 unsigned rt
= INSTR (4, 0);
13385 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
13386 if (aarch64_get_reg_u64 (cpu
, rt
, NO_SP
) == 0)
13387 aarch64_set_next_PC_by_offset (cpu
, offset
);
13390 /* Branch on register bit test non-zero -- one size fits all. */
13392 tbnz (sim_cpu
*cpu
, uint32_t pos
, int32_t offset
)
13394 unsigned rt
= INSTR (4, 0);
13396 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
13397 if (aarch64_get_reg_u64 (cpu
, rt
, NO_SP
) & (((uint64_t) 1) << pos
))
13398 aarch64_set_next_PC_by_offset (cpu
, offset
);
13401 /* Branch on register bit test zero -- one size fits all. */
13403 tbz (sim_cpu
*cpu
, uint32_t pos
, int32_t offset
)
13405 unsigned rt
= INSTR (4, 0);
13407 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
13408 if (!(aarch64_get_reg_u64 (cpu
, rt
, NO_SP
) & (((uint64_t) 1) << pos
)))
13409 aarch64_set_next_PC_by_offset (cpu
, offset
);
13413 dexCompareBranchImmediate (sim_cpu
*cpu
)
13415 /* instr[30,25] = 01 1010
13416 instr[31] = size : 0 ==> 32, 1 ==> 64
13417 instr[24] = op : 0 ==> CBZ, 1 ==> CBNZ
13418 instr[23,5] = simm19 branch offset counted in words
13421 uint32_t size
= INSTR (31, 31);
13422 uint32_t op
= INSTR (24, 24);
13423 int32_t offset
= simm32 (aarch64_get_instr (cpu
), 23, 5) << 2;
13428 cbz32 (cpu
, offset
);
13430 cbnz32 (cpu
, offset
);
13437 cbnz (cpu
, offset
);
13442 dexTestBranchImmediate (sim_cpu
*cpu
)
13444 /* instr[31] = b5 : bit 5 of test bit idx
13445 instr[30,25] = 01 1011
13446 instr[24] = op : 0 ==> TBZ, 1 == TBNZ
13447 instr[23,19] = b40 : bits 4 to 0 of test bit idx
13448 instr[18,5] = simm14 : signed offset counted in words
13449 instr[4,0] = uimm5 */
13451 uint32_t pos
= ((INSTR (31, 31) << 5) | INSTR (23, 19));
13452 int32_t offset
= simm32 (aarch64_get_instr (cpu
), 18, 5) << 2;
13454 NYI_assert (30, 25, 0x1b);
13456 if (INSTR (24, 24) == 0)
13457 tbz (cpu
, pos
, offset
);
13459 tbnz (cpu
, pos
, offset
);
13463 dexCondBranchImmediate (sim_cpu
*cpu
)
13465 /* instr[31,25] = 010 1010
13466 instr[24] = op1; op => 00 ==> B.cond
13467 instr[23,5] = simm19 : signed offset counted in words
13469 instr[3,0] = cond */
13472 uint32_t op
= ((INSTR (24, 24) << 1) | INSTR (4, 4));
13474 NYI_assert (31, 25, 0x2a);
13479 offset
= simm32 (aarch64_get_instr (cpu
), 23, 5) << 2;
13481 bcc (cpu
, offset
, INSTR (3, 0));
13485 dexBranchRegister (sim_cpu
*cpu
)
13487 /* instr[31,25] = 110 1011
13488 instr[24,21] = op : 0 ==> BR, 1 => BLR, 2 => RET, 3 => ERET, 4 => DRPS
13489 instr[20,16] = op2 : must be 11111
13490 instr[15,10] = op3 : must be 000000
13491 instr[4,0] = op2 : must be 11111. */
13493 uint32_t op
= INSTR (24, 21);
13494 uint32_t op2
= INSTR (20, 16);
13495 uint32_t op3
= INSTR (15, 10);
13496 uint32_t op4
= INSTR (4, 0);
13498 NYI_assert (31, 25, 0x6b);
13500 if (op2
!= 0x1F || op3
!= 0 || op4
!= 0)
13514 /* ERET and DRPS accept 0b11111 for rn = instr [4,0]. */
13515 /* anything else is unallocated. */
13516 uint32_t rn
= INSTR (4, 0);
13521 if (op
== 4 || op
== 5)
13528 /* FIXME: We should get the Angel SWI values from ../../libgloss/aarch64/svc.h
13529 but this may not be available. So instead we define the values we need
13531 #define AngelSVC_Reason_Open 0x01
13532 #define AngelSVC_Reason_Close 0x02
13533 #define AngelSVC_Reason_Write 0x05
13534 #define AngelSVC_Reason_Read 0x06
13535 #define AngelSVC_Reason_IsTTY 0x09
13536 #define AngelSVC_Reason_Seek 0x0A
13537 #define AngelSVC_Reason_FLen 0x0C
13538 #define AngelSVC_Reason_Remove 0x0E
13539 #define AngelSVC_Reason_Rename 0x0F
13540 #define AngelSVC_Reason_Clock 0x10
13541 #define AngelSVC_Reason_Time 0x11
13542 #define AngelSVC_Reason_System 0x12
13543 #define AngelSVC_Reason_Errno 0x13
13544 #define AngelSVC_Reason_GetCmdLine 0x15
13545 #define AngelSVC_Reason_HeapInfo 0x16
13546 #define AngelSVC_Reason_ReportException 0x18
13547 #define AngelSVC_Reason_Elapsed 0x30
13551 handle_halt (sim_cpu
*cpu
, uint32_t val
)
13553 uint64_t result
= 0;
13555 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
13558 TRACE_SYSCALL (cpu
, " HLT [0x%x]", val
);
13559 sim_engine_halt (CPU_STATE (cpu
), cpu
, NULL
, aarch64_get_PC (cpu
),
13560 sim_stopped
, SIM_SIGTRAP
);
13563 /* We have encountered an Angel SVC call. See if we can process it. */
13564 switch (aarch64_get_reg_u32 (cpu
, 0, NO_SP
))
13566 case AngelSVC_Reason_HeapInfo
:
13568 /* Get the values. */
13569 uint64_t stack_top
= aarch64_get_stack_start (cpu
);
13570 uint64_t heap_base
= aarch64_get_heap_start (cpu
);
13572 /* Get the pointer */
13573 uint64_t ptr
= aarch64_get_reg_u64 (cpu
, 1, SP_OK
);
13574 ptr
= aarch64_get_mem_u64 (cpu
, ptr
);
13576 /* Fill in the memory block. */
13577 /* Start addr of heap. */
13578 aarch64_set_mem_u64 (cpu
, ptr
+ 0, heap_base
);
13579 /* End addr of heap. */
13580 aarch64_set_mem_u64 (cpu
, ptr
+ 8, stack_top
);
13581 /* Lowest stack addr. */
13582 aarch64_set_mem_u64 (cpu
, ptr
+ 16, heap_base
);
13583 /* Initial stack addr. */
13584 aarch64_set_mem_u64 (cpu
, ptr
+ 24, stack_top
);
13586 TRACE_SYSCALL (cpu
, " AngelSVC: Get Heap Info");
13590 case AngelSVC_Reason_Open
:
13592 /* Get the pointer */
13593 /* uint64_t ptr = aarch64_get_reg_u64 (cpu, 1, SP_OK);. */
13594 /* FIXME: For now we just assume that we will only be asked
13595 to open the standard file descriptors. */
13599 TRACE_SYSCALL (cpu
, " AngelSVC: Open file %d", fd
- 1);
13603 case AngelSVC_Reason_Close
:
13605 uint64_t fh
= aarch64_get_reg_u64 (cpu
, 1, SP_OK
);
13606 TRACE_SYSCALL (cpu
, " AngelSVC: Close file %d", (int) fh
);
13611 case AngelSVC_Reason_Errno
:
13613 TRACE_SYSCALL (cpu
, " AngelSVC: Get Errno");
13616 case AngelSVC_Reason_Clock
:
13618 #ifdef CLOCKS_PER_SEC
13619 (CLOCKS_PER_SEC
>= 100)
13620 ? (clock () / (CLOCKS_PER_SEC
/ 100))
13621 : ((clock () * 100) / CLOCKS_PER_SEC
)
13623 /* Presume unix... clock() returns microseconds. */
13627 TRACE_SYSCALL (cpu
, " AngelSVC: Get Clock");
13630 case AngelSVC_Reason_GetCmdLine
:
13632 /* Get the pointer */
13633 uint64_t ptr
= aarch64_get_reg_u64 (cpu
, 1, SP_OK
);
13634 ptr
= aarch64_get_mem_u64 (cpu
, ptr
);
13636 /* FIXME: No command line for now. */
13637 aarch64_set_mem_u64 (cpu
, ptr
, 0);
13638 TRACE_SYSCALL (cpu
, " AngelSVC: Get Command Line");
13642 case AngelSVC_Reason_IsTTY
:
13644 TRACE_SYSCALL (cpu
, " AngelSVC: IsTTY ?");
13647 case AngelSVC_Reason_Write
:
13649 /* Get the pointer */
13650 uint64_t ptr
= aarch64_get_reg_u64 (cpu
, 1, SP_OK
);
13651 /* Get the write control block. */
13652 uint64_t fd
= aarch64_get_mem_u64 (cpu
, ptr
);
13653 uint64_t buf
= aarch64_get_mem_u64 (cpu
, ptr
+ 8);
13654 uint64_t len
= aarch64_get_mem_u64 (cpu
, ptr
+ 16);
13656 TRACE_SYSCALL (cpu
, "write of %" PRIx64
" bytes from %"
13657 PRIx64
" on descriptor %" PRIx64
,
13662 TRACE_SYSCALL (cpu
,
13663 " AngelSVC: Write: Suspiciously long write: %ld",
13665 sim_engine_halt (CPU_STATE (cpu
), cpu
, NULL
, aarch64_get_PC (cpu
),
13666 sim_stopped
, SIM_SIGBUS
);
13670 printf ("%.*s", (int) len
, aarch64_get_mem_ptr (cpu
, buf
));
13674 TRACE (cpu
, 0, "\n");
13675 sim_io_eprintf (CPU_STATE (cpu
), "%.*s",
13676 (int) len
, aarch64_get_mem_ptr (cpu
, buf
));
13677 TRACE (cpu
, 0, "\n");
13681 TRACE_SYSCALL (cpu
,
13682 " AngelSVC: Write: Unexpected file handle: %d",
13684 sim_engine_halt (CPU_STATE (cpu
), cpu
, NULL
, aarch64_get_PC (cpu
),
13685 sim_stopped
, SIM_SIGABRT
);
13690 case AngelSVC_Reason_ReportException
:
13692 /* Get the pointer */
13693 uint64_t ptr
= aarch64_get_reg_u64 (cpu
, 1, SP_OK
);
13694 /*ptr = aarch64_get_mem_u64 (cpu, ptr);. */
13695 uint64_t type
= aarch64_get_mem_u64 (cpu
, ptr
);
13696 uint64_t state
= aarch64_get_mem_u64 (cpu
, ptr
+ 8);
13698 TRACE_SYSCALL (cpu
,
13699 "Angel Exception: type 0x%" PRIx64
" state %" PRIx64
,
13702 if (type
== 0x20026)
13703 sim_engine_halt (CPU_STATE (cpu
), cpu
, NULL
, aarch64_get_PC (cpu
),
13704 sim_exited
, state
);
13706 sim_engine_halt (CPU_STATE (cpu
), cpu
, NULL
, aarch64_get_PC (cpu
),
13707 sim_stopped
, SIM_SIGINT
);
13711 case AngelSVC_Reason_Read
:
13712 case AngelSVC_Reason_FLen
:
13713 case AngelSVC_Reason_Seek
:
13714 case AngelSVC_Reason_Remove
:
13715 case AngelSVC_Reason_Time
:
13716 case AngelSVC_Reason_System
:
13717 case AngelSVC_Reason_Rename
:
13718 case AngelSVC_Reason_Elapsed
:
13720 TRACE_SYSCALL (cpu
, " HLT [Unknown angel %x]",
13721 aarch64_get_reg_u32 (cpu
, 0, NO_SP
));
13722 sim_engine_halt (CPU_STATE (cpu
), cpu
, NULL
, aarch64_get_PC (cpu
),
13723 sim_stopped
, SIM_SIGTRAP
);
13726 aarch64_set_reg_u64 (cpu
, 0, NO_SP
, result
);
13730 dexExcpnGen (sim_cpu
*cpu
)
13732 /* instr[31:24] = 11010100
13733 instr[23,21] = opc : 000 ==> GEN EXCPN, 001 ==> BRK
13734 010 ==> HLT, 101 ==> DBG GEN EXCPN
13735 instr[20,5] = imm16
13736 instr[4,2] = opc2 000 ==> OK, ow ==> UNALLOC
13737 instr[1,0] = LL : discriminates opc */
13739 uint32_t opc
= INSTR (23, 21);
13740 uint32_t imm16
= INSTR (20, 5);
13741 uint32_t opc2
= INSTR (4, 2);
13744 NYI_assert (31, 24, 0xd4);
13751 /* We only implement HLT and BRK for now. */
13752 if (opc
== 1 && LL
== 0)
13754 TRACE_EVENTS (cpu
, " BRK [0x%x]", imm16
);
13755 sim_engine_halt (CPU_STATE (cpu
), cpu
, NULL
, aarch64_get_PC (cpu
),
13756 sim_exited
, aarch64_get_reg_s32 (cpu
, R0
, SP_OK
));
13759 if (opc
== 2 && LL
== 0)
13760 handle_halt (cpu
, imm16
);
13762 else if (opc
== 0 || opc
== 5)
13769 /* Stub for accessing system registers. */
13772 system_get (sim_cpu
*cpu
, unsigned op0
, unsigned op1
, unsigned crn
,
13773 unsigned crm
, unsigned op2
)
13775 if (crn
== 0 && op1
== 3 && crm
== 0 && op2
== 7)
13776 /* DCZID_EL0 - the Data Cache Zero ID register.
13777 We do not support DC ZVA at the moment, so
13778 we return a value with the disable bit set.
13779 We implement support for the DCZID register since
13780 it is used by the C library's memset function. */
13781 return ((uint64_t) 1) << 4;
13783 if (crn
== 0 && op1
== 3 && crm
== 0 && op2
== 1)
13784 /* Cache Type Register. */
13785 return 0x80008000UL
;
13787 if (crn
== 13 && op1
== 3 && crm
== 0 && op2
== 2)
13788 /* TPIDR_EL0 - thread pointer id. */
13789 return aarch64_get_thread_id (cpu
);
13791 if (op1
== 3 && crm
== 4 && op2
== 0)
13792 return aarch64_get_FPCR (cpu
);
13794 if (op1
== 3 && crm
== 4 && op2
== 1)
13795 return aarch64_get_FPSR (cpu
);
13797 else if (op1
== 3 && crm
== 2 && op2
== 0)
13798 return aarch64_get_CPSR (cpu
);
13804 system_set (sim_cpu
*cpu
, unsigned op0
, unsigned op1
, unsigned crn
,
13805 unsigned crm
, unsigned op2
, uint64_t val
)
13807 if (op1
== 3 && crm
== 4 && op2
== 0)
13808 aarch64_set_FPCR (cpu
, val
);
13810 else if (op1
== 3 && crm
== 4 && op2
== 1)
13811 aarch64_set_FPSR (cpu
, val
);
13813 else if (op1
== 3 && crm
== 2 && op2
== 0)
13814 aarch64_set_CPSR (cpu
, val
);
13821 do_mrs (sim_cpu
*cpu
)
13823 /* instr[31:20] = 1101 0101 0001 1
13830 unsigned sys_op0
= INSTR (19, 19) + 2;
13831 unsigned sys_op1
= INSTR (18, 16);
13832 unsigned sys_crn
= INSTR (15, 12);
13833 unsigned sys_crm
= INSTR (11, 8);
13834 unsigned sys_op2
= INSTR (7, 5);
13835 unsigned rt
= INSTR (4, 0);
13837 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
13838 aarch64_set_reg_u64 (cpu
, rt
, NO_SP
,
13839 system_get (cpu
, sys_op0
, sys_op1
, sys_crn
, sys_crm
, sys_op2
));
13843 do_MSR_immediate (sim_cpu
*cpu
)
13845 /* instr[31:19] = 1101 0101 0000 0
13847 instr[15,12] = 0100
13850 instr[4,0] = 1 1111 */
13852 unsigned op1
= INSTR (18, 16);
13853 /*unsigned crm = INSTR (11, 8);*/
13854 unsigned op2
= INSTR (7, 5);
13856 NYI_assert (31, 19, 0x1AA0);
13857 NYI_assert (15, 12, 0x4);
13858 NYI_assert (4, 0, 0x1F);
13863 HALT_NYI
; /* set SPSel. */
13870 HALT_NYI
; /* set DAIFset. */
13872 HALT_NYI
; /* set DAIFclr. */
13881 do_MSR_reg (sim_cpu
*cpu
)
13883 /* instr[31:20] = 1101 0101 0001
13891 unsigned sys_op0
= INSTR (19, 19) + 2;
13892 unsigned sys_op1
= INSTR (18, 16);
13893 unsigned sys_crn
= INSTR (15, 12);
13894 unsigned sys_crm
= INSTR (11, 8);
13895 unsigned sys_op2
= INSTR (7, 5);
13896 unsigned rt
= INSTR (4, 0);
13898 NYI_assert (31, 20, 0xD51);
13900 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
13901 system_set (cpu
, sys_op0
, sys_op1
, sys_crn
, sys_crm
, sys_op2
,
13902 aarch64_get_reg_u64 (cpu
, rt
, NO_SP
));
13906 do_SYS (sim_cpu
*cpu
)
13908 /* instr[31,19] = 1101 0101 0000 1
13914 NYI_assert (31, 19, 0x1AA1);
13916 /* FIXME: For now we just silently accept system ops. */
13920 dexSystem (sim_cpu
*cpu
)
13922 /* instr[31:22] = 1101 01010 0
13929 instr[4,0] = uimm5 */
13931 /* We are interested in HINT, DSB, DMB and ISB
13933 Hint #0 encodes NOOP (this is the only hint we care about)
13934 L == 0, op0 == 0, op1 = 011, CRn = 0010, Rt = 11111,
13935 CRm op2 != 0000 000 OR CRm op2 == 0000 000 || CRm op > 0000 101
13937 DSB, DMB, ISB are data store barrier, data memory barrier and
13938 instruction store barrier, respectively, where
13940 L == 0, op0 == 0, op1 = 011, CRn = 0011, Rt = 11111,
13941 op2 : DSB ==> 100, DMB ==> 101, ISB ==> 110
13942 CRm<3:2> ==> domain, CRm<1:0> ==> types,
13943 domain : 00 ==> OuterShareable, 01 ==> Nonshareable,
13944 10 ==> InerShareable, 11 ==> FullSystem
13945 types : 01 ==> Reads, 10 ==> Writes,
13946 11 ==> All, 00 ==> All (domain == FullSystem). */
13948 unsigned rt
= INSTR (4, 0);
13950 NYI_assert (31, 22, 0x354);
13952 switch (INSTR (21, 12))
13957 /* NOP has CRm != 0000 OR. */
13958 /* (CRm == 0000 AND (op2 == 000 OR op2 > 101)). */
13959 uint32_t crm
= INSTR (11, 8);
13960 uint32_t op2
= INSTR (7, 5);
13962 if (crm
!= 0 || (op2
== 0 || op2
> 5))
13964 /* Actually call nop method so we can reimplement it later. */
13973 uint32_t op2
= INSTR (7, 5);
13978 case 4: dsb (cpu
); return;
13979 case 5: dmb (cpu
); return;
13980 case 6: isb (cpu
); return;
13981 default: HALT_UNALLOC
;
13992 do_SYS (cpu
); /* DC is an alias of SYS. */
13996 if (INSTR (21, 20) == 0x1)
13998 else if (INSTR (21, 19) == 0 && INSTR (15, 12) == 0x4)
13999 do_MSR_immediate (cpu
);
14007 dexBr (sim_cpu
*cpu
)
14009 /* uint32_t group = dispatchGroup (aarch64_get_instr (cpu));
14010 assert group == GROUP_BREXSYS_1010 || group == GROUP_BREXSYS_1011
14011 bits [31,29] of a BrExSys are the secondary dispatch vector. */
14012 uint32_t group2
= dispatchBrExSys (aarch64_get_instr (cpu
));
14017 return dexBranchImmediate (cpu
);
14019 case BR_IMMCMP_001
:
14020 /* Compare has bit 25 clear while test has it set. */
14021 if (!INSTR (25, 25))
14022 dexCompareBranchImmediate (cpu
);
14024 dexTestBranchImmediate (cpu
);
14027 case BR_IMMCOND_010
:
14028 /* This is a conditional branch if bit 25 is clear otherwise
14030 if (!INSTR (25, 25))
14031 dexCondBranchImmediate (cpu
);
14036 case BR_UNALLOC_011
:
14040 dexBranchImmediate (cpu
);
14043 case BR_IMMCMP_101
:
14044 /* Compare has bit 25 clear while test has it set. */
14045 if (!INSTR (25, 25))
14046 dexCompareBranchImmediate (cpu
);
14048 dexTestBranchImmediate (cpu
);
14052 /* Unconditional branch reg has bit 25 set. */
14053 if (INSTR (25, 25))
14054 dexBranchRegister (cpu
);
14056 /* This includes both Excpn Gen, System and unalloc operations.
14057 We need to decode the Excpn Gen operation BRK so we can plant
14058 debugger entry points.
14059 Excpn Gen operations have instr [24] = 0.
14060 we need to decode at least one of the System operations NOP
14061 which is an alias for HINT #0.
14062 System operations have instr [24,22] = 100. */
14063 else if (INSTR (24, 24) == 0)
14066 else if (INSTR (24, 22) == 4)
14074 case BR_UNALLOC_111
:
14078 /* Should never reach here. */
14084 aarch64_decode_and_execute (sim_cpu
*cpu
, uint64_t pc
)
14086 /* We need to check if gdb wants an in here. */
14087 /* checkBreak (cpu);. */
14089 uint64_t group
= dispatchGroup (aarch64_get_instr (cpu
));
14093 case GROUP_PSEUDO_0000
: dexPseudo (cpu
); break;
14094 case GROUP_LDST_0100
: dexLdSt (cpu
); break;
14095 case GROUP_DPREG_0101
: dexDPReg (cpu
); break;
14096 case GROUP_LDST_0110
: dexLdSt (cpu
); break;
14097 case GROUP_ADVSIMD_0111
: dexAdvSIMD0 (cpu
); break;
14098 case GROUP_DPIMM_1000
: dexDPImm (cpu
); break;
14099 case GROUP_DPIMM_1001
: dexDPImm (cpu
); break;
14100 case GROUP_BREXSYS_1010
: dexBr (cpu
); break;
14101 case GROUP_BREXSYS_1011
: dexBr (cpu
); break;
14102 case GROUP_LDST_1100
: dexLdSt (cpu
); break;
14103 case GROUP_DPREG_1101
: dexDPReg (cpu
); break;
14104 case GROUP_LDST_1110
: dexLdSt (cpu
); break;
14105 case GROUP_ADVSIMD_1111
: dexAdvSIMD1 (cpu
); break;
14107 case GROUP_UNALLOC_0001
:
14108 case GROUP_UNALLOC_0010
:
14109 case GROUP_UNALLOC_0011
:
14113 /* Should never reach here. */
14119 aarch64_step (sim_cpu
*cpu
)
14121 uint64_t pc
= aarch64_get_PC (cpu
);
14123 if (pc
== TOP_LEVEL_RETURN_PC
)
14126 aarch64_set_next_PC (cpu
, pc
+ 4);
14128 /* Code is always little-endian. */
14129 sim_core_read_buffer (CPU_STATE (cpu
), cpu
, read_map
,
14130 & aarch64_get_instr (cpu
), pc
, 4);
14131 aarch64_get_instr (cpu
) = endian_le2h_4 (aarch64_get_instr (cpu
));
14133 TRACE_INSN (cpu
, " pc = %" PRIx64
" instr = %08x", pc
,
14134 aarch64_get_instr (cpu
));
14135 TRACE_DISASM (cpu
, pc
);
14137 aarch64_decode_and_execute (cpu
, pc
);
14143 aarch64_run (SIM_DESC sd
)
14145 sim_cpu
*cpu
= STATE_CPU (sd
, 0);
14147 while (aarch64_step (cpu
))
14149 aarch64_update_PC (cpu
);
14151 if (sim_events_tick (sd
))
14152 sim_events_process (sd
);
14155 sim_engine_halt (sd
, cpu
, NULL
, aarch64_get_PC (cpu
),
14156 sim_exited
, aarch64_get_reg_s32 (cpu
, R0
, NO_SP
));
14160 aarch64_init (sim_cpu
*cpu
, uint64_t pc
)
14162 uint64_t sp
= aarch64_get_stack_start (cpu
);
14164 /* Install SP, FP and PC and set LR to -20
14165 so we can detect a top-level return. */
14166 aarch64_set_reg_u64 (cpu
, SP
, SP_OK
, sp
);
14167 aarch64_set_reg_u64 (cpu
, FP
, SP_OK
, sp
);
14168 aarch64_set_reg_u64 (cpu
, LR
, SP_OK
, TOP_LEVEL_RETURN_PC
);
14169 aarch64_set_next_PC (cpu
, pc
);
14170 aarch64_update_PC (cpu
);
14171 aarch64_init_LIT_table ();